From 7e46a78297adf42efa2b8254e160cb1aec5578a4 Mon Sep 17 00:00:00 2001 From: panxuefeng Date: Thu, 6 Nov 2025 11:29:11 +0800 Subject: [PATCH] upgrade LoongArch64 port to 11.0.29 --- download | 2 +- ...e80d0ab.patch => fips-11u-f93a863b56.patch | 234 +- java-11-openjdk.spec | 20 +- jdk11-LoongArch64.patch | 120827 +++++++++++++-- rh1750419-redhat_alt_java.patch | 27 +- 5 files changed, 105414 insertions(+), 15696 deletions(-) rename fips-11u-9087e80d0ab.patch => fips-11u-f93a863b56.patch (91%) diff --git a/download b/download index d40396a..c6ed1f9 100644 --- a/download +++ b/download @@ -1,2 +1,2 @@ -0fd1fc1d8f823d32a8dfe48e7ff9ff4d openjdk-jdk11u-jdk-11.0.17+8-4curve.tar.xz +0cb6c840210589a383f174ce0c52f13a openjdk-jdk11u-jdk-11.0.25+9.tar.xz 5d441d6217cc75372ca5a0943997cb24 tapsets-icedtea-6.0.0pre00-c848b93a8598.tar.xz diff --git a/fips-11u-9087e80d0ab.patch b/fips-11u-f93a863b56.patch similarity index 91% rename from fips-11u-9087e80d0ab.patch rename to fips-11u-f93a863b56.patch index a396fb8..3690cb8 100644 --- a/fips-11u-9087e80d0ab.patch +++ b/fips-11u-f93a863b56.patch @@ -1,5 +1,5 @@ diff --git a/make/autoconf/libraries.m4 b/make/autoconf/libraries.m4 -index a73c0f38181..80710886ed8 100644 +index 16e906bdc6..1a352e5a32 100644 --- a/make/autoconf/libraries.m4 +++ b/make/autoconf/libraries.m4 @@ -101,6 +101,7 @@ AC_DEFUN_ONCE([LIB_SETUP_LIBRARIES], @@ -74,10 +74,10 @@ index a73c0f38181..80710886ed8 100644 + AC_SUBST(USE_SYSCONF_NSS) +]) diff --git a/make/autoconf/spec.gmk.in b/make/autoconf/spec.gmk.in -index 0ae23b93167..a242acc1234 100644 +index 3787b12600..dab108a82b 100644 --- a/make/autoconf/spec.gmk.in +++ b/make/autoconf/spec.gmk.in -@@ -826,6 +826,10 @@ INSTALL_SYSCONFDIR=@sysconfdir@ +@@ -848,6 +848,10 @@ INSTALL_SYSCONFDIR=@sysconfdir@ # Libraries # @@ -89,10 +89,10 @@ index 0ae23b93167..a242acc1234 100644 LCMS_CFLAGS:=@LCMS_CFLAGS@ LCMS_LIBS:=@LCMS_LIBS@ diff --git a/make/lib/Lib-java.base.gmk b/make/lib/Lib-java.base.gmk -index a529768f39e..daf9c947172 100644 +index b40d3114b9..0d1d83cf3e 100644 --- a/make/lib/Lib-java.base.gmk +++ b/make/lib/Lib-java.base.gmk -@@ -178,6 +178,31 @@ ifeq ($(OPENJDK_TARGET_OS_TYPE), unix) +@@ -178,6 +178,31 @@ ifeq ($(call isTargetOsType, unix), true) endif endif @@ -125,7 +125,7 @@ index a529768f39e..daf9c947172 100644 # Create the symbols file for static builds. diff --git a/make/nb_native/nbproject/configurations.xml b/make/nb_native/nbproject/configurations.xml -index fb07d54c1f0..c5813e2b7aa 100644 +index fb07d54c1f..c5813e2b7a 100644 --- a/make/nb_native/nbproject/configurations.xml +++ b/make/nb_native/nbproject/configurations.xml @@ -2950,6 +2950,9 @@ @@ -151,7 +151,7 @@ index fb07d54c1f0..c5813e2b7aa 100644 ex="false" tool="3" diff --git a/make/scripts/compare_exceptions.sh.incl b/make/scripts/compare_exceptions.sh.incl -index 6327040964d..6b3780123b6 100644 +index 6327040964..6b3780123b 100644 --- a/make/scripts/compare_exceptions.sh.incl +++ b/make/scripts/compare_exceptions.sh.incl @@ -179,6 +179,7 @@ if [ "$OPENJDK_TARGET_OS" = "solaris" ] && [ "$OPENJDK_TARGET_CPU" = "x86_64" ]; @@ -172,7 +172,7 @@ index 6327040964d..6b3780123b6 100644 ./lib/libzip.so diff --git a/src/java.base/linux/native/libsystemconf/systemconf.c b/src/java.base/linux/native/libsystemconf/systemconf.c new file mode 100644 -index 00000000000..8dcb7d9073f +index 0000000000..8dcb7d9073 --- /dev/null +++ b/src/java.base/linux/native/libsystemconf/systemconf.c @@ -0,0 +1,224 @@ @@ -401,7 +401,7 @@ index 00000000000..8dcb7d9073f + } +} diff --git a/src/java.base/share/classes/java/security/Security.java b/src/java.base/share/classes/java/security/Security.java -index b36510a376b..ad5182e1e7c 100644 +index 5b9552058b..b46de49211 100644 --- a/src/java.base/share/classes/java/security/Security.java +++ b/src/java.base/share/classes/java/security/Security.java @@ -32,6 +32,7 @@ import java.net.URL; @@ -412,16 +412,17 @@ index b36510a376b..ad5182e1e7c 100644 import jdk.internal.misc.SharedSecrets; import jdk.internal.util.StaticProperty; import sun.security.util.Debug; -@@ -47,12 +48,20 @@ import sun.security.jca.*; +@@ -47,6 +48,9 @@ import sun.security.jca.*; * implementation-specific location, which is typically the properties file * {@code conf/security/java.security} in the Java installation directory. * + *

Additional default values of security properties are read from a + * system-specific location, if available.

+ * - * @author Benjamin Renaud - * @since 1.1 - */ + * @implNote If the properties file fails to load, the JDK implementation will + * throw an unspecified error when initializing the {@code Security} class. + * +@@ -56,6 +60,11 @@ import sun.security.jca.*; public final class Security { @@ -433,7 +434,7 @@ index b36510a376b..ad5182e1e7c 100644 /* Are we debugging? -- for developers */ private static final Debug sdebug = Debug.getInstance("properties"); -@@ -67,6 +76,19 @@ public final class Security { +@@ -70,6 +79,19 @@ public final class Security { } static { @@ -453,26 +454,19 @@ index b36510a376b..ad5182e1e7c 100644 // doPrivileged here because there are multiple // things in initialize that might require privs. // (the FileInputStream call and the File.exists call, -@@ -83,6 +105,7 @@ public final class Security { +@@ -85,6 +107,7 @@ public final class Security { + private static void initialize() { props = new Properties(); - boolean loadedProps = false; boolean overrideAll = false; + boolean systemSecPropsEnabled = false; // first load the system properties file // to determine the value of security.overridePropertiesFile -@@ -98,6 +121,7 @@ public final class Security { - if (sdebug != null) { - sdebug.println("reading security properties file: " + - propFile); -+ sdebug.println(props.toString()); - } - } catch (IOException e) { - if (sdebug != null) { -@@ -192,6 +216,61 @@ public final class Security { +@@ -105,9 +128,63 @@ public final class Security { } + loadProps(null, extraPropFile, overrideAll); } - ++ + boolean sysUseProps = Boolean.valueOf(System.getProperty(SYS_PROP_SWITCH, "false")); + boolean secUseProps = Boolean.valueOf(props.getProperty(SEC_PROP_SWITCH)); + if (sdebug != null) { @@ -492,9 +486,7 @@ index b36510a376b..ad5182e1e7c 100644 + } + } + -+ // FIPS support depends on the contents of java.security so -+ // ensure it has loaded first -+ if (loadedProps && systemSecPropsEnabled) { ++ if (systemSecPropsEnabled) { + boolean shouldEnable; + String sysProp = System.getProperty("com.redhat.fips"); + if (sysProp == null) { @@ -530,15 +522,19 @@ index b36510a376b..ad5182e1e7c 100644 + } } - /* +- private static boolean loadProps(File masterFile, String extraPropFile, boolean overrideAll) { ++ static boolean loadProps(File masterFile, String extraPropFile, boolean overrideAll) { + InputStream is = null; + try { + if (masterFile != null && masterFile.exists()) { diff --git a/src/java.base/share/classes/java/security/SystemConfigurator.java b/src/java.base/share/classes/java/security/SystemConfigurator.java new file mode 100644 -index 00000000000..90f6dd2ebc0 +index 0000000000..49bf17ea17 --- /dev/null +++ b/src/java.base/share/classes/java/security/SystemConfigurator.java -@@ -0,0 +1,248 @@ +@@ -0,0 +1,231 @@ +/* -+ * Copyright (c) 2019, 2021, Red Hat, Inc. ++ * Copyright (c) 2019, 2023, Red Hat, Inc. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * @@ -616,26 +612,9 @@ index 00000000000..90f6dd2ebc0 + * security.useSystemPropertiesFile is true. + */ + static boolean configureSysProps(Properties props) { -+ boolean systemSecPropsLoaded = false; -+ -+ try (BufferedInputStream bis = -+ new BufferedInputStream( -+ new FileInputStream(CRYPTO_POLICIES_JAVA_CONFIG))) { -+ props.load(bis); -+ systemSecPropsLoaded = true; -+ if (sdebug != null) { -+ sdebug.println("reading system security properties file " + -+ CRYPTO_POLICIES_JAVA_CONFIG); -+ sdebug.println(props.toString()); -+ } -+ } catch (IOException e) { -+ if (sdebug != null) { -+ sdebug.println("unable to load security properties from " + -+ CRYPTO_POLICIES_JAVA_CONFIG); -+ e.printStackTrace(); -+ } -+ } -+ return systemSecPropsLoaded; ++ // now load the system file, if it exists, so its values ++ // will win if they conflict with the earlier values ++ return Security.loadProps(null, CRYPTO_POLICIES_JAVA_CONFIG, false); + } + + /* @@ -787,7 +766,7 @@ index 00000000000..90f6dd2ebc0 +} diff --git a/src/java.base/share/classes/jdk/internal/misc/JavaSecuritySystemConfiguratorAccess.java b/src/java.base/share/classes/jdk/internal/misc/JavaSecuritySystemConfiguratorAccess.java new file mode 100644 -index 00000000000..21bc6d0b591 +index 0000000000..21bc6d0b59 --- /dev/null +++ b/src/java.base/share/classes/jdk/internal/misc/JavaSecuritySystemConfiguratorAccess.java @@ -0,0 +1,31 @@ @@ -823,7 +802,7 @@ index 00000000000..21bc6d0b591 + boolean isPlainKeySupportEnabled(); +} diff --git a/src/java.base/share/classes/jdk/internal/misc/SharedSecrets.java b/src/java.base/share/classes/jdk/internal/misc/SharedSecrets.java -index 688ec9f0915..8489b940c43 100644 +index 688ec9f091..8489b940c4 100644 --- a/src/java.base/share/classes/jdk/internal/misc/SharedSecrets.java +++ b/src/java.base/share/classes/jdk/internal/misc/SharedSecrets.java @@ -36,6 +36,7 @@ import java.io.FilePermission; @@ -859,7 +838,7 @@ index 688ec9f0915..8489b940c43 100644 + } } diff --git a/src/java.base/share/classes/module-info.java b/src/java.base/share/classes/module-info.java -index 5460efcf8c5..f08dc2fafc5 100644 +index 7351627db3..859591890d 100644 --- a/src/java.base/share/classes/module-info.java +++ b/src/java.base/share/classes/module-info.java @@ -182,6 +182,7 @@ module java.base { @@ -871,7 +850,7 @@ index 5460efcf8c5..f08dc2fafc5 100644 jdk.attach, jdk.charsets, diff --git a/src/java.base/share/classes/sun/security/ssl/KeyManagerFactoryImpl.java b/src/java.base/share/classes/sun/security/ssl/KeyManagerFactoryImpl.java -index ffee2c1603b..ff3d5e0e4ab 100644 +index ffee2c1603..ff3d5e0e4a 100644 --- a/src/java.base/share/classes/sun/security/ssl/KeyManagerFactoryImpl.java +++ b/src/java.base/share/classes/sun/security/ssl/KeyManagerFactoryImpl.java @@ -33,8 +33,13 @@ import java.security.KeyStore.*; @@ -910,7 +889,7 @@ index ffee2c1603b..ff3d5e0e4ab 100644 "FIPS mode: KeyStore must be " + "from provider " + SunJSSE.cryptoProvider.getName()); diff --git a/src/java.base/share/classes/sun/security/ssl/SSLContextImpl.java b/src/java.base/share/classes/sun/security/ssl/SSLContextImpl.java -index de7da5c3379..5c3813dda7b 100644 +index e06b2a588c..315a2ce370 100644 --- a/src/java.base/share/classes/sun/security/ssl/SSLContextImpl.java +++ b/src/java.base/share/classes/sun/security/ssl/SSLContextImpl.java @@ -31,6 +31,7 @@ import java.security.*; @@ -931,6 +910,14 @@ index de7da5c3379..5c3813dda7b 100644 - ProtocolVersion.TLS11, - ProtocolVersion.TLS10 - ); +- +- serverDefaultProtocols = getAvailableProtocols( +- new ProtocolVersion[] { +- ProtocolVersion.TLS13, +- ProtocolVersion.TLS12, +- ProtocolVersion.TLS11, +- ProtocolVersion.TLS10 +- }); + if (SharedSecrets.getJavaSecuritySystemConfiguratorAccess() + .isSystemFipsEnabled()) { + // RH1860986: TLSv1.3 key derivation not supported with @@ -940,14 +927,7 @@ index de7da5c3379..5c3813dda7b 100644 + ProtocolVersion.TLS11, + ProtocolVersion.TLS10 + ); - -- serverDefaultProtocols = getAvailableProtocols( -- new ProtocolVersion[] { -- ProtocolVersion.TLS13, -- ProtocolVersion.TLS12, -- ProtocolVersion.TLS11, -- ProtocolVersion.TLS10 -- }); ++ + serverDefaultProtocols = getAvailableProtocols( + new ProtocolVersion[] { + ProtocolVersion.TLS12, @@ -973,42 +953,68 @@ index de7da5c3379..5c3813dda7b 100644 } else { supportedProtocols = Arrays.asList( ProtocolVersion.TLS13, -@@ -620,6 +639,16 @@ public abstract class SSLContextImpl extends SSLContextSpi { - - static ProtocolVersion[] getSupportedProtocols() { - if (SunJSSE.isFIPS()) { -+ if (SharedSecrets.getJavaSecuritySystemConfiguratorAccess() -+ .isSystemFipsEnabled()) { -+ // RH1860986: TLSv1.3 key derivation not supported with -+ // the Security Providers available in system FIPS mode. -+ return new ProtocolVersion[] { -+ ProtocolVersion.TLS12, -+ ProtocolVersion.TLS11, -+ ProtocolVersion.TLS10 -+ }; -+ } - return new ProtocolVersion[] { - ProtocolVersion.TLS13, - ProtocolVersion.TLS12, -@@ -949,6 +978,16 @@ public abstract class SSLContextImpl extends SSLContextSpi { - - static ProtocolVersion[] getProtocols() { - if (SunJSSE.isFIPS()) { -+ if (SharedSecrets.getJavaSecuritySystemConfiguratorAccess() -+ .isSystemFipsEnabled()) { -+ // RH1860986: TLSv1.3 key derivation not supported with -+ // the Security Providers available in system FIPS mode. -+ return new ProtocolVersion[] { -+ ProtocolVersion.TLS12, -+ ProtocolVersion.TLS11, -+ ProtocolVersion.TLS10 -+ }; -+ } - return new ProtocolVersion[]{ - ProtocolVersion.TLS13, - ProtocolVersion.TLS12, +@@ -910,12 +929,23 @@ public abstract class SSLContextImpl extends SSLContextSpi { + if (client) { + // default client protocols + if (SunJSSE.isFIPS()) { +- candidates = new ProtocolVersion[] { +- ProtocolVersion.TLS13, +- ProtocolVersion.TLS12, +- ProtocolVersion.TLS11, +- ProtocolVersion.TLS10 +- }; ++ if (SharedSecrets.getJavaSecuritySystemConfiguratorAccess() ++ .isSystemFipsEnabled()) { ++ // RH1860986: TLSv1.3 key derivation not supported with ++ // the Security Providers available in system FIPS mode. ++ candidates = new ProtocolVersion[] { ++ ProtocolVersion.TLS12, ++ ProtocolVersion.TLS11, ++ ProtocolVersion.TLS10 ++ }; ++ } else { ++ candidates = new ProtocolVersion[] { ++ ProtocolVersion.TLS13, ++ ProtocolVersion.TLS12, ++ ProtocolVersion.TLS11, ++ ProtocolVersion.TLS10 ++ }; ++ } + } else { + candidates = new ProtocolVersion[] { + ProtocolVersion.TLS13, +@@ -927,12 +957,23 @@ public abstract class SSLContextImpl extends SSLContextSpi { + } else { + // default server protocols + if (SunJSSE.isFIPS()) { +- candidates = new ProtocolVersion[] { +- ProtocolVersion.TLS13, +- ProtocolVersion.TLS12, +- ProtocolVersion.TLS11, +- ProtocolVersion.TLS10 +- }; ++ if (SharedSecrets.getJavaSecuritySystemConfiguratorAccess() ++ .isSystemFipsEnabled()) { ++ // RH1860986: TLSv1.3 key derivation not supported with ++ // the Security Providers available in system FIPS mode. ++ candidates = new ProtocolVersion[] { ++ ProtocolVersion.TLS12, ++ ProtocolVersion.TLS11, ++ ProtocolVersion.TLS10 ++ }; ++ } else { ++ candidates = new ProtocolVersion[] { ++ ProtocolVersion.TLS13, ++ ProtocolVersion.TLS12, ++ ProtocolVersion.TLS11, ++ ProtocolVersion.TLS10 ++ }; ++ } + } else { + candidates = new ProtocolVersion[] { + ProtocolVersion.TLS13, diff --git a/src/java.base/share/classes/sun/security/ssl/SunJSSE.java b/src/java.base/share/classes/sun/security/ssl/SunJSSE.java -index c50ba93ecfc..de2a91a478c 100644 +index 2a2b5d7568..891796f19b 100644 --- a/src/java.base/share/classes/sun/security/ssl/SunJSSE.java +++ b/src/java.base/share/classes/sun/security/ssl/SunJSSE.java @@ -27,6 +27,8 @@ package sun.security.ssl; @@ -1019,7 +1025,7 @@ index c50ba93ecfc..de2a91a478c 100644 +import jdk.internal.misc.SharedSecrets; import sun.security.rsa.SunRsaSignEntries; import static sun.security.util.SecurityConstants.PROVIDER_VER; - import static sun.security.provider.SunEntries.createAliases; + import static sun.security.util.SecurityProviderConstants.*; @@ -195,8 +197,13 @@ public abstract class SunJSSE extends java.security.Provider { "sun.security.ssl.SSLContextImpl$TLS11Context", null, null); ps("SSLContext", "TLSv1.2", @@ -1035,12 +1041,12 @@ index c50ba93ecfc..de2a91a478c 100644 + } ps("SSLContext", "TLS", "sun.security.ssl.SSLContextImpl$TLSContext", - (isfips? null : createAliases("SSL")), null); + (isfips? null : List.of("SSL")), null); diff --git a/src/java.base/share/conf/security/java.security b/src/java.base/share/conf/security/java.security -index 097517926d1..474fe6f401f 100644 +index c0eed3f884..b03bd9f896 100644 --- a/src/java.base/share/conf/security/java.security +++ b/src/java.base/share/conf/security/java.security -@@ -85,6 +85,14 @@ security.provider.tbd=Apple +@@ -88,6 +88,14 @@ security.provider.tbd=Apple security.provider.tbd=SunPKCS11 #endif @@ -1055,7 +1061,7 @@ index 097517926d1..474fe6f401f 100644 # # A list of preferred providers for specific algorithms. These providers will # be searched for matching algorithms before the list of registered providers. -@@ -298,6 +306,11 @@ policy.ignoreIdentityScope=false +@@ -301,6 +309,11 @@ policy.ignoreIdentityScope=false # keystore.type=pkcs12 @@ -1067,7 +1073,7 @@ index 097517926d1..474fe6f401f 100644 # # Controls compatibility mode for JKS and PKCS12 keystore types. # -@@ -335,6 +348,13 @@ package.definition=sun.misc.,\ +@@ -338,6 +351,13 @@ package.definition=sun.misc.,\ # security.overridePropertiesFile=true @@ -1083,7 +1089,7 @@ index 097517926d1..474fe6f401f 100644 # the javax.net.ssl package. diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/FIPSKeyImporter.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/FIPSKeyImporter.java new file mode 100644 -index 00000000000..b848a1fd783 +index 0000000000..b848a1fd78 --- /dev/null +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/FIPSKeyImporter.java @@ -0,0 +1,290 @@ @@ -1378,7 +1384,7 @@ index 00000000000..b848a1fd783 + } +} diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SunPKCS11.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SunPKCS11.java -index 099caac605f..977e5332bd1 100644 +index ffbd671246..bdaad67e06 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SunPKCS11.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SunPKCS11.java @@ -26,6 +26,9 @@ @@ -1400,7 +1406,7 @@ index 099caac605f..977e5332bd1 100644 import sun.security.util.Debug; import sun.security.util.ResourcesMgr; import static sun.security.util.SecurityConstants.PROVIDER_VER; -@@ -60,6 +65,29 @@ import static sun.security.pkcs11.wrapper.PKCS11Constants.*; +@@ -61,6 +66,29 @@ import static sun.security.pkcs11.wrapper.PKCS11Constants.*; */ public final class SunPKCS11 extends AuthProvider { @@ -1430,7 +1436,7 @@ index 099caac605f..977e5332bd1 100644 private static final long serialVersionUID = -1354835039035306505L; static final Debug debug = Debug.getInstance("sunpkcs11"); -@@ -317,10 +345,15 @@ public final class SunPKCS11 extends AuthProvider { +@@ -318,10 +346,15 @@ public final class SunPKCS11 extends AuthProvider { // request multithreaded access first initArgs.flags = CKF_OS_LOCKING_OK; PKCS11 tmpPKCS11; @@ -1447,7 +1453,7 @@ index 099caac605f..977e5332bd1 100644 } catch (PKCS11Exception e) { if (debug != null) { debug.println("Multi-threaded initialization failed: " + e); -@@ -336,7 +369,7 @@ public final class SunPKCS11 extends AuthProvider { +@@ -337,7 +370,7 @@ public final class SunPKCS11 extends AuthProvider { initArgs.flags = 0; } tmpPKCS11 = PKCS11.getInstance(library, @@ -1456,7 +1462,7 @@ index 099caac605f..977e5332bd1 100644 } p11 = tmpPKCS11; -@@ -376,6 +409,24 @@ public final class SunPKCS11 extends AuthProvider { +@@ -377,6 +410,24 @@ public final class SunPKCS11 extends AuthProvider { if (nssModule != null) { nssModule.setProvider(this); } @@ -1482,7 +1488,7 @@ index 099caac605f..977e5332bd1 100644 if (config.getHandleStartupErrors() == Config.ERR_IGNORE_ALL) { throw new UnsupportedOperationException diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/PKCS11.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/PKCS11.java -index 04a369f453c..f033fe47593 100644 +index 04a369f453..f033fe4759 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/PKCS11.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/PKCS11.java @@ -49,6 +49,7 @@ package sun.security.pkcs11.wrapper; diff --git a/java-11-openjdk.spec b/java-11-openjdk.spec index 5c9004f..9c9c8e7 100644 --- a/java-11-openjdk.spec +++ b/java-11-openjdk.spec @@ -13,7 +13,7 @@ # Only produce a release build on x86_64: # $ rhpkg mockbuild --without slowdebug --without fastdebug -%global anolis_release 4 +%global anolis_release 1 # Enable fastdebug builds by default on relevant arches. %bcond_without fastdebug # Enable slowdebug builds by default on relevant arches. @@ -279,7 +279,7 @@ # New Version-String scheme-style defines %global featurever 11 %global interimver 0 -%global updatever 17 +%global updatever 29 %global patchver 0 # buildjdkver is usually same as %%{featurever}, # but in time of bootstrap of next jdk, it is featurever-1, @@ -297,14 +297,14 @@ # Define IcedTea version used for SystemTap tapsets and desktop file %global icedteaver 6.0.0pre00-c848b93a8598 # Define current Git revision for the FIPS support patches -%global fipsver 9087e80d0ab +%global fipsver f93a863b56 # Standard JPackage naming and versioning defines %global origin openjdk %global origin_nice OpenJDK %global top_level_dir_name %{origin} %global top_level_dir_name_backup %{top_level_dir_name}-backup -%global buildver 8 +%global buildver 7 %global rpmrelease 2 #%%global tagsuffix %%{nil} # Priority must be 8 digits in total; up to openjdk 1.8, we were using 18..... so when we moved to 11, we had to add another digit @@ -1215,7 +1215,7 @@ URL: http://openjdk.java.net/ # to regenerate source0 (jdk) run update_package.sh # update_package.sh contains hard-coded repos, revisions, tags, and projects to regenerate the source archives -Source0: openjdk-jdk%{featurever}u-%{vcstag}-4curve.tar.xz +Source0: openjdk-jdk11u-jdk-11.0.25+9.tar.xz # Use 'icedtea_sync.sh' to update the following # They are based on code contained in the IcedTea project (6.x). @@ -1417,6 +1417,8 @@ BuildRequires: libstdc++-static # when it is built in debug-only this package is just placeholder %{java_rpo %{nil}} +ExclusiveArch: loongarch64 + %description The %{origin_nice} %{featurever} runtime environment. @@ -1701,6 +1703,7 @@ if [ %{include_debug_build} -eq 0 -a %{include_normal_build} -eq 0 -a %{includ exit 14 fi %setup -q -c -n %{uniquesuffix ""} -T -a 0 +mv jdk-11.0.25+9 openjdk # https://bugzilla.redhat.com/show_bug.cgi?id=1189084 prioritylength=`expr length %{priority}` if [ $prioritylength -ne 8 ] ; then @@ -1725,9 +1728,11 @@ pushd %{top_level_dir_name} # nss.cfg PKCS11 support; must come last as it also alters java.security %patch1000 -p1 # tzdata updates targetted for 11.0.18 +%ifnarch loongarch64 %patch2001 -p1 %patch2002 -p1 %patch2003 -p1 +%endif %ifarch loongarch64 %patch3000 -p1 %endif @@ -1736,7 +1741,9 @@ popd # openjdk %patch600 %patch1003 +%ifnarch loongarch64 %patch8 +%endif # Extract systemtap tapsets %if %{with_systemtap} @@ -2552,6 +2559,9 @@ end %endif %changelog +* Thu Nov 06 2025 panxuefeng - 1:11.0.29.0.7-1 +- upgrade LoongArch64 port to 11.0.29 + * Thu Nov 09 2023 Leslie Zhai - 1:11.0.17.0.8-4 - Disable gdb diff --git a/jdk11-LoongArch64.patch b/jdk11-LoongArch64.patch index 00f5bb3..70a860f 100644 --- a/jdk11-LoongArch64.patch +++ b/jdk11-LoongArch64.patch @@ -1,7 +1,522 @@ -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/make/autoconf/hotspot.m4 jdk11u-ls/make/autoconf/hotspot.m4 ---- openjdk/make/autoconf/hotspot.m4 2022-10-12 23:00:01.000000000 +0800 -+++ jdk11u-ls/make/autoconf/hotspot.m4 2023-11-01 09:34:25.289945041 +0800 -@@ -34,6 +34,12 @@ +diff --git a/README.md b/README.md +index 399e7cc31..9a3eb23b9 100644 +--- a/README.md ++++ b/README.md +@@ -1,4 +1,11 @@ +-# Welcome to the JDK! ++# Welcome to OpenJDK 11 Updates! ++ ++The JDK 11 Updates project uses two GitHub repositories. ++Updates are continuously developed in the repository [jdk11u-dev](https://github.com/openjdk/jdk11u-dev). This is the repository usually targeted by contributors. ++The [jdk11u](https://github.com/openjdk/jdk11u) repository is used for rampdown of the update releases of jdk11u and only accepts critical changes that must make the next release during rampdown. (You probably do not want to target jdk11u). ++ ++For more OpenJDK 11 updates specific information such as timelines and contribution guidelines see the [project wiki page](https://wiki.openjdk.org/display/JDKUpdates/JDK11u). ++ + + For build instructions please see the + [online documentation](https://openjdk.java.net/groups/build/doc/building.html), +diff --git a/SECURITY.md b/SECURITY.md +new file mode 100644 +index 000000000..f4c5e7e67 +--- /dev/null ++++ b/SECURITY.md +@@ -0,0 +1,3 @@ ++# JDK Vulnerabilities ++ ++Please follow the process outlined in the [OpenJDK Vulnerability Policy](https://openjdk.org/groups/vulnerability/report) to disclose vulnerabilities in the JDK. +diff --git a/doc/building.html b/doc/building.html +index 81c8d30ef..13ee9b7b6 100644 +--- a/doc/building.html ++++ b/doc/building.html +@@ -175,26 +175,26 @@ + + + +- +- ++ ++ + + + + +- +- ++ ++ + + +- +- ++ ++ + + +- +- ++ ++ + + +- +- ++ ++ + + +
Operating systemVendor/version usedOperating systemVendor/version used
LinuxOracle Enterprise Linux 6.4 / 7.1 (using kernel 3.8.13)LinuxOracle Enterprise Linux 6.4 / 7.1 (using kernel 3.8.13)
SolarisSolaris 11.1 SRU 21.4.1 / 11.2 SRU 5.5SolarisSolaris 11.1 SRU 21.4.1 / 11.2 SRU 5.5
macOSMac OS X 10.9 (Mavericks) / 10.10 (Yosemite)macOSMac OS X 10.9 (Mavericks) / 10.10 (Yosemite)
WindowsWindows Server 2012 R2WindowsWindows Server 2012 R2
+@@ -296,7 +296,6 @@ + + + +-

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 doesn't fully support C99 so in practice shared code is limited to using C99 features that it does support.

+

gcc

+

The minimum accepted version of gcc is 4.8. Older versions will generate a warning by configure and are unlikely to work.

+

The JDK is currently known to be able to compile with at least version 7.4 of gcc.

+@@ -320,50 +319,50 @@ + + + +- +- ++ ++ + + + + +- +- ++ ++ + + +- +- ++ ++ + + +- +- ++ ++ + + +- +- ++ ++ + + +- +- ++ ++ + + +- +- ++ ++ + + +- +- ++ ++ + + +- +- ++ ++ + + +- +- ++ ++ + + +- +- ++ ++ + + +
PackageVersionPackageVersion
developer/solarisstudio-124/backend12.4-1.0.6.0developer/solarisstudio-124/backend12.4-1.0.6.0
developer/solarisstudio-124/c++12.4-1.0.10.0developer/solarisstudio-124/c++12.4-1.0.10.0
developer/solarisstudio-124/cc12.4-1.0.4.0developer/solarisstudio-124/cc12.4-1.0.4.0
developer/solarisstudio-124/library/c++-libs12.4-1.0.10.0developer/solarisstudio-124/library/c++-libs12.4-1.0.10.0
developer/solarisstudio-124/library/math-libs12.4-1.0.0.1developer/solarisstudio-124/library/math-libs12.4-1.0.0.1
developer/solarisstudio-124/library/studio-gccrt12.4-1.0.0.1developer/solarisstudio-124/library/studio-gccrt12.4-1.0.0.1
developer/solarisstudio-124/studio-common12.4-1.0.0.1developer/solarisstudio-124/studio-common12.4-1.0.0.1
developer/solarisstudio-124/studio-ja12.4-1.0.0.1developer/solarisstudio-124/studio-ja12.4-1.0.0.1
developer/solarisstudio-124/studio-legal12.4-1.0.0.1developer/solarisstudio-124/studio-legal12.4-1.0.0.1
developer/solarisstudio-124/studio-zhCN12.4-1.0.0.1developer/solarisstudio-124/studio-zhCN12.4-1.0.0.1
+@@ -747,103 +746,103 @@ ls build/linux-aarch64-normal-server-release/ + + + +- +- +- +- ++ ++ ++ ++ + + + + + +- +- +- +- ++ ++ ++ ++ + + + +- +- +- +- ++ ++ ++ ++ + + + +- +- +- +- ++ ++ ++ ++ + + + +- +- +- +- ++ ++ ++ ++ + + + +- +- +- +- ++ ++ ++ ++ + + + +- +- +- +- ++ ++ ++ ++ + + + +- +- +- +- ++ ++ ++ ++ + + + +- +- +- +- ++ ++ ++ ++ + + + +- +- +- +- ++ ++ ++ ++ + + + +- +- +- +- ++ ++ ++ ++ + + + +- +- +- +- ++ ++ ++ ++ + + + +- +- +- +- ++ ++ ++ ++ + + + +- +- +- +- ++ ++ ++ ++ + + + +diff --git a/doc/building.md b/doc/building.md +index 60d4d73a6..648be30b4 100644 +--- a/doc/building.md ++++ b/doc/building.md +@@ -151,12 +151,12 @@ This table lists the OS versions used by Oracle when building the JDK. Such + information is always subject to change, but this table is up to date at the + time of writing. + +- Operating system Vendor/version used +- ----------------- ------------------------------------------------------- +- Linux Oracle Enterprise Linux 6.4 / 7.1 (using kernel 3.8.13) +- Solaris Solaris 11.1 SRU 21.4.1 / 11.2 SRU 5.5 +- macOS Mac OS X 10.9 (Mavericks) / 10.10 (Yosemite) +- Windows Windows Server 2012 R2 ++| Operating system | Vendor/version used | ++| ----------------- | ------------------------------------------------------- | ++| Linux | Oracle Enterprise Linux 6.4 / 7.1 (using kernel 3.8.13) | ++| Solaris | Solaris 11.1 SRU 21.4.1 / 11.2 SRU 5.5 | ++| macOS | Mac OS X 10.9 (Mavericks) / 10.10 (Yosemite) | ++| Windows | Windows Server 2012 R2 | + + The double version numbers for Linux, Solaris and macOS is due to the hybrid + model used at Oracle, where header files and external libraries from an older +@@ -363,18 +363,18 @@ configure. + + The Solaris Studio installation should contain at least these packages: + +- Package Version +- -------------------------------------------------- ------------- +- developer/solarisstudio-124/backend 12.4-1.0.6.0 +- developer/solarisstudio-124/c++ 12.4-1.0.10.0 +- developer/solarisstudio-124/cc 12.4-1.0.4.0 +- developer/solarisstudio-124/library/c++-libs 12.4-1.0.10.0 +- developer/solarisstudio-124/library/math-libs 12.4-1.0.0.1 +- developer/solarisstudio-124/library/studio-gccrt 12.4-1.0.0.1 +- developer/solarisstudio-124/studio-common 12.4-1.0.0.1 +- developer/solarisstudio-124/studio-ja 12.4-1.0.0.1 +- developer/solarisstudio-124/studio-legal 12.4-1.0.0.1 +- developer/solarisstudio-124/studio-zhCN 12.4-1.0.0.1 ++| Package | Version | ++| -------------------------------------------------- | ------------- | ++| developer/solarisstudio-124/backend | 12.4-1.0.6.0 | ++| developer/solarisstudio-124/c++ | 12.4-1.0.10.0 | ++| developer/solarisstudio-124/cc | 12.4-1.0.4.0 | ++| developer/solarisstudio-124/library/c++-libs | 12.4-1.0.10.0 | ++| developer/solarisstudio-124/library/math-libs | 12.4-1.0.0.1 | ++| developer/solarisstudio-124/library/studio-gccrt | 12.4-1.0.0.1 | ++| developer/solarisstudio-124/studio-common | 12.4-1.0.0.1 | ++| developer/solarisstudio-124/studio-ja | 12.4-1.0.0.1 | ++| developer/solarisstudio-124/studio-legal | 12.4-1.0.0.1 | ++| developer/solarisstudio-124/studio-zhCN | 12.4-1.0.0.1 | + + Compiling with Solaris Studio can sometimes be finicky. This is the exact + version used by Oracle, which worked correctly at the time of writing: +@@ -965,14 +965,14 @@ https://sourceware.org/autobook/autobook/autobook_17.html). If no + targets are given, a native toolchain for the current platform will be + created. Currently, at least the following targets are known to work: + +- Supported devkit targets +- ------------------------ +- x86_64-linux-gnu +- aarch64-linux-gnu +- arm-linux-gnueabihf +- ppc64-linux-gnu +- ppc64le-linux-gnu +- s390x-linux-gnu ++| Supported devkit targets | ++| ------------------------ | ++| x86_64-linux-gnu | ++| aarch64-linux-gnu | ++| arm-linux-gnueabihf | ++| ppc64-linux-gnu | ++| ppc64le-linux-gnu | ++| s390x-linux-gnu | + + `BASE_OS` must be one of "OEL6" for Oracle Enterprise Linux 6 or + "Fedora" (if not specified "OEL6" will be the default). If the base OS +@@ -1199,21 +1199,21 @@ it might require a little nudge with: + + Architectures that are known to successfully cross-compile like this are: + +- Target Debian tree Debian arch `--openjdk-target=...` `--with-jvm-variants=...` +- ------------ ------------ ------------- ------------------------ -------------- +- x86 buster i386 i386-linux-gnu (all) +- arm buster armhf arm-linux-gnueabihf (all) +- aarch64 buster arm64 aarch64-linux-gnu (all) +- ppc64le buster ppc64el powerpc64le-linux-gnu (all) +- s390x buster s390x s390x-linux-gnu (all) +- mipsle buster mipsel mipsel-linux-gnu zero +- mips64le buster mips64el mips64el-linux-gnueabi64 zero +- armel buster arm arm-linux-gnueabi zero +- ppc sid powerpc powerpc-linux-gnu zero +- ppc64be sid ppc64 powerpc64-linux-gnu (all) +- m68k sid m68k m68k-linux-gnu zero +- alpha sid alpha alpha-linux-gnu zero +- sh4 sid sh4 sh4-linux-gnu zero ++| Target | Debian tree | Debian arch | `--openjdk-target=...` | `--with-jvm-variants=...` | ++| ------------ | ------------ | ------------- | ------------------------ | ------------------------- | ++| x86 | buster | i386 | i386-linux-gnu | (all) | ++| arm | buster | armhf | arm-linux-gnueabihf | (all) | ++| aarch64 | buster | arm64 | aarch64-linux-gnu | (all) | ++| ppc64le | buster | ppc64el | powerpc64le-linux-gnu | (all) | ++| s390x | buster | s390x | s390x-linux-gnu | (all) | ++| mipsle | buster | mipsel | mipsel-linux-gnu | zero | ++| mips64le | buster | mips64el | mips64el-linux-gnueabi64 | zero | ++| armel | buster | arm | arm-linux-gnueabi | zero | ++| ppc | sid | powerpc | powerpc-linux-gnu | zero | ++| ppc64be | sid | ppc64 | powerpc64-linux-gnu | (all) | ++| m68k | sid | m68k | m68k-linux-gnu | zero | ++| alpha | sid | alpha | alpha-linux-gnu | zero | ++| sh4 | sid | sh4 | sh4-linux-gnu | zero | + + ### Building for ARM/aarch64 + +diff --git a/make/CompileJavaModules.gmk b/make/CompileJavaModules.gmk +index 46fb9b421..c6d8b24fc 100644 +--- a/make/CompileJavaModules.gmk ++++ b/make/CompileJavaModules.gmk +@@ -430,6 +430,7 @@ jdk.internal.vm.ci_ADD_JAVAC_FLAGS += -parameters -Xlint:-exports -XDstringConca + + jdk.internal.vm.compiler_ADD_JAVAC_FLAGS += -parameters -XDstringConcat=inline \ + --add-exports jdk.internal.vm.ci/jdk.vm.ci.aarch64=jdk.internal.vm.compiler \ ++ --add-exports jdk.internal.vm.ci/jdk.vm.ci.loongarch64=jdk.internal.vm.compiler \ + --add-exports jdk.internal.vm.ci/jdk.vm.ci.amd64=jdk.internal.vm.compiler \ + --add-exports jdk.internal.vm.ci/jdk.vm.ci.code=jdk.internal.vm.compiler \ + --add-exports jdk.internal.vm.ci/jdk.vm.ci.code.site=jdk.internal.vm.compiler \ +@@ -437,6 +438,7 @@ jdk.internal.vm.compiler_ADD_JAVAC_FLAGS += -parameters -XDstringConcat=inline \ + --add-exports jdk.internal.vm.ci/jdk.vm.ci.common=jdk.internal.vm.compiler \ + --add-exports jdk.internal.vm.ci/jdk.vm.ci.hotspot=jdk.internal.vm.compiler \ + --add-exports jdk.internal.vm.ci/jdk.vm.ci.hotspot.aarch64=jdk.internal.vm.compiler \ ++ --add-exports jdk.internal.vm.ci/jdk.vm.ci.hotspot.loongarch64=jdk.internal.vm.compiler \ + --add-exports jdk.internal.vm.ci/jdk.vm.ci.hotspot.amd64=jdk.internal.vm.compiler \ + --add-exports jdk.internal.vm.ci/jdk.vm.ci.hotspot.sparc=jdk.internal.vm.compiler \ + --add-exports jdk.internal.vm.ci/jdk.vm.ci.meta=jdk.internal.vm.compiler \ +@@ -456,6 +458,7 @@ jdk.internal.vm.compiler_EXCLUDES += \ + org.graalvm.compiler.api.directives.test \ + org.graalvm.compiler.api.test \ + org.graalvm.compiler.asm.aarch64.test \ ++ org.graalvm.compiler.asm.loongarch64.test \ + org.graalvm.compiler.asm.amd64.test \ + org.graalvm.compiler.asm.sparc.test \ + org.graalvm.compiler.asm.test \ +diff --git a/make/RunTestsPrebuilt.gmk b/make/RunTestsPrebuilt.gmk +index 918140fb5..c33ecd767 100644 +--- a/make/RunTestsPrebuilt.gmk ++++ b/make/RunTestsPrebuilt.gmk +@@ -239,9 +239,9 @@ else ifeq ($(OPENJDK_TARGET_OS), solaris) + else ifeq ($(OPENJDK_TARGET_OS), windows) + NUM_CORES := $(NUMBER_OF_PROCESSORS) + MEMORY_SIZE := $(shell \ +- $(EXPR) `wmic computersystem get totalphysicalmemory -value \ +- | $(GREP) = | $(SED) 's/\\r//g' \ +- | $(CUT) -d "=" -f 2-` / 1024 / 1024 \ ++ $(EXPR) `powershell -Command \ ++ "(Get-CimInstance Win32_ComputerSystem).TotalPhysicalMemory" \ ++ | $(SED) 's/\\r//g' ` / 1024 / 1024 \ + ) + endif + ifeq ($(NUM_CORES), ) +diff --git a/make/autoconf/build-performance.m4 b/make/autoconf/build-performance.m4 +index 7892b4001..940c9eaac 100644 +--- a/make/autoconf/build-performance.m4 ++++ b/make/autoconf/build-performance.m4 +@@ -1,5 +1,5 @@ + # +-# Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved. ++# Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved. + # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + # + # This code is free software; you can redistribute it and/or modify it +@@ -84,7 +84,8 @@ AC_DEFUN([BPERF_CHECK_MEMORY_SIZE], + FOUND_MEM=yes + elif test "x$OPENJDK_BUILD_OS" = xwindows; then + # Windows, but without cygwin +- MEMORY_SIZE=`wmic computersystem get totalphysicalmemory -value | grep = | cut -d "=" -f 2-` ++ MEMORY_SIZE=`powershell -Command \ ++ "(Get-CimInstance Win32_ComputerSystem).TotalPhysicalMemory" | $SED 's/\\r//g' ` + MEMORY_SIZE=`expr $MEMORY_SIZE / 1024 / 1024` + FOUND_MEM=yes + fi +diff --git a/make/autoconf/flags-cflags.m4 b/make/autoconf/flags-cflags.m4 +index 8ea0b339c..8ead0e22d 100644 +--- a/make/autoconf/flags-cflags.m4 ++++ b/make/autoconf/flags-cflags.m4 +@@ -192,6 +192,12 @@ AC_DEFUN([FLAGS_SETUP_WARNINGS], + DISABLE_WARNING_PREFIX="-Wno-" + BUILD_CC_DISABLE_WARNING_PREFIX="-Wno-" + CFLAGS_WARNINGS_ARE_ERRORS="-Werror" ++ ++ WARNINGS_ENABLE_ALL="-Wall -Wextra -Wformat=2" ++ WARNINGS_ENABLE_ADDITIONAL_JVM="-Wpointer-arith -Wsign-compare -Wunused-function -Wundef -Wunused-value -Woverloaded-virtual -Wreturn-type" ++ ++ DISABLED_WARNINGS="unused-parameter unused" ++ + ;; + + clang) +@@ -200,7 +206,7 @@ AC_DEFUN([FLAGS_SETUP_WARNINGS], + CFLAGS_WARNINGS_ARE_ERRORS="-Werror" + + WARNINGS_ENABLE_ALL="-Wall -Wextra -Wformat=2" +- WARNINGS_ENABLE_ADDITIONAL_JVM="-Wpointer-arith -Wsign-compare -Wunused-function -Wundef -Wunused-value -Woverloaded-virtual -Wreorder" ++ WARNINGS_ENABLE_ADDITIONAL_JVM="-Wpointer-arith -Wsign-compare -Wunused-function -Wundef -Wunused-value -Woverloaded-virtual" + + DISABLED_WARNINGS="unused-parameter unused" + ;; +diff --git a/make/autoconf/hotspot.m4 b/make/autoconf/hotspot.m4 +index 9bb34363e..5d5380e07 100644 +--- a/make/autoconf/hotspot.m4 ++++ b/make/autoconf/hotspot.m4 +@@ -34,6 +34,12 @@ DEPRECATED_JVM_FEATURES="trace" # All valid JVM variants VALID_JVM_VARIANTS="server client minimal core zero custom" @@ -14,7 +529,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/make/autoconf/hotspot.m4 j ############################################################################### # Check if the specified JVM variant should be built. To be used in shell if # constructs, like this: -@@ -334,6 +340,26 @@ +@@ -340,6 +346,26 @@ AC_DEFUN_ONCE([HOTSPOT_SETUP_JVM_FEATURES], HOTSPOT_TARGET_CPU_ARCH=arm fi @@ -41,7 +556,15 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/make/autoconf/hotspot.m4 j # Verify that dependencies are met for explicitly set features. if HOTSPOT_CHECK_JVM_FEATURE(jvmti) && ! HOTSPOT_CHECK_JVM_FEATURE(services); then AC_MSG_ERROR([Specified JVM feature 'jvmti' requires feature 'services']) -@@ -418,10 +444,11 @@ +@@ -378,6 +404,7 @@ AC_DEFUN_ONCE([HOTSPOT_SETUP_JVM_FEATURES], + fi + else + DISABLED_JVM_FEATURES="$DISABLED_JVM_FEATURES shenandoahgc" ++ AC_MSG_RESULT([no, must be manually enabled --with-jvm-features=shenandoahgc]) + fi + + # Only enable ZGC on supported platforms +@@ -424,10 +451,11 @@ AC_DEFUN_ONCE([HOTSPOT_SETUP_JVM_FEATURES], JVM_FEATURES_jvmci="" INCLUDE_JVMCI="false" else @@ -55,9 +578,10 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/make/autoconf/hotspot.m4 j AC_MSG_RESULT([yes]) JVM_FEATURES_jvmci="jvmci" INCLUDE_JVMCI="true" -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/make/autoconf/platform.m4 jdk11u-ls/make/autoconf/platform.m4 ---- openjdk/make/autoconf/platform.m4 2022-10-12 23:00:01.000000000 +0800 -+++ jdk11u-ls/make/autoconf/platform.m4 2023-11-01 09:34:25.297945050 +0800 +diff --git a/make/autoconf/platform.m4 b/make/autoconf/platform.m4 +index 5d1d9efa3..815180ea9 100644 +--- a/make/autoconf/platform.m4 ++++ b/make/autoconf/platform.m4 @@ -23,6 +23,12 @@ # questions. # @@ -71,7 +595,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/make/autoconf/platform.m4 # Support macro for PLATFORM_EXTRACT_TARGET_AND_BUILD. # Converts autoconf style CPU name to OpenJDK style, into # VAR_CPU, VAR_CPU_ARCH, VAR_CPU_BITS and VAR_CPU_ENDIAN. -@@ -554,6 +560,12 @@ +@@ -554,6 +560,12 @@ AC_DEFUN([PLATFORM_SETUP_LEGACY_VARS_HELPER], HOTSPOT_$1_CPU_DEFINE=PPC64 elif test "x$OPENJDK_$1_CPU" = xppc64le; then HOTSPOT_$1_CPU_DEFINE=PPC64 @@ -84,77 +608,5125 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/make/autoconf/platform.m4 # The cpu defines below are for zero, we don't support them directly. elif test "x$OPENJDK_$1_CPU" = xsparc; then -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/make/CompileJavaModules.gmk jdk11u-ls/make/CompileJavaModules.gmk ---- openjdk/make/CompileJavaModules.gmk 2022-10-12 23:00:01.000000000 +0800 -+++ jdk11u-ls/make/CompileJavaModules.gmk 2023-11-01 09:34:25.261945010 +0800 -@@ -434,6 +434,7 @@ +diff --git a/make/autoconf/version-numbers b/make/autoconf/version-numbers +index fe5e0d985..c62a3bf46 100644 +--- a/make/autoconf/version-numbers ++++ b/make/autoconf/version-numbers +@@ -1,5 +1,5 @@ + # +-# Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved. ++# Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved. + # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + # + # This code is free software; you can redistribute it and/or modify it +@@ -28,12 +28,12 @@ - jdk.internal.vm.compiler_ADD_JAVAC_FLAGS += -parameters -XDstringConcat=inline \ - --add-exports jdk.internal.vm.ci/jdk.vm.ci.aarch64=jdk.internal.vm.compiler \ -+ --add-exports jdk.internal.vm.ci/jdk.vm.ci.loongarch64=jdk.internal.vm.compiler \ - --add-exports jdk.internal.vm.ci/jdk.vm.ci.amd64=jdk.internal.vm.compiler \ - --add-exports jdk.internal.vm.ci/jdk.vm.ci.code=jdk.internal.vm.compiler \ - --add-exports jdk.internal.vm.ci/jdk.vm.ci.code.site=jdk.internal.vm.compiler \ -@@ -441,6 +442,7 @@ - --add-exports jdk.internal.vm.ci/jdk.vm.ci.common=jdk.internal.vm.compiler \ - --add-exports jdk.internal.vm.ci/jdk.vm.ci.hotspot=jdk.internal.vm.compiler \ - --add-exports jdk.internal.vm.ci/jdk.vm.ci.hotspot.aarch64=jdk.internal.vm.compiler \ -+ --add-exports jdk.internal.vm.ci/jdk.vm.ci.hotspot.loongarch64=jdk.internal.vm.compiler \ - --add-exports jdk.internal.vm.ci/jdk.vm.ci.hotspot.amd64=jdk.internal.vm.compiler \ - --add-exports jdk.internal.vm.ci/jdk.vm.ci.hotspot.sparc=jdk.internal.vm.compiler \ - --add-exports jdk.internal.vm.ci/jdk.vm.ci.meta=jdk.internal.vm.compiler \ -@@ -460,6 +462,7 @@ - org.graalvm.compiler.api.directives.test \ - org.graalvm.compiler.api.test \ - org.graalvm.compiler.asm.aarch64.test \ -+ org.graalvm.compiler.asm.loongarch64.test \ - org.graalvm.compiler.asm.amd64.test \ - org.graalvm.compiler.asm.sparc.test \ - org.graalvm.compiler.asm.test \ -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/make/lib/Lib-jdk.crypto.ec.gmk jdk11u-ls/make/lib/Lib-jdk.crypto.ec.gmk ---- openjdk/make/lib/Lib-jdk.crypto.ec.gmk 2022-10-12 23:00:07.000000000 +0800 -+++ jdk11u-ls/make/lib/Lib-jdk.crypto.ec.gmk 2023-09-12 13:54:22.869571381 +0800 -@@ -43,7 +43,7 @@ - TOOLCHAIN := TOOLCHAIN_LINK_CXX, \ - OPTIMIZATION := LOW, \ - CFLAGS := $(BUILD_LIBSUNEC_CFLAGS_JDKLIB) \ -- -DMP_API_COMPATIBLE, \ -+ -DMP_API_COMPATIBLE -DNSS_ECC_MORE_THAN_SUITE_B, \ - CXXFLAGS := $(BUILD_LIBSUNEC_CXXFLAGS_JDKLIB), \ - DISABLED_WARNINGS_gcc := sign-compare implicit-fallthrough, \ - DISABLED_WARNINGS_microsoft := 4101 4244 4146 4018, \ -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/aarch64/c1_LIR_aarch64.cpp jdk11u-ls/src/hotspot/cpu/aarch64/c1_LIR_aarch64.cpp ---- openjdk/src/hotspot/cpu/aarch64/c1_LIR_aarch64.cpp 2022-10-12 23:00:01.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/aarch64/c1_LIR_aarch64.cpp 2023-09-12 13:54:22.977571517 +0800 -@@ -52,3 +52,24 @@ - "wrong type for addresses"); - } - #endif // PRODUCT -+ -+template -+void LIR_List::cmp_branch(LIR_Condition condition, LIR_Opr left, LIR_Opr right, BasicType type, T tgt, CodeEmitInfo* info) { -+ cmp(condition, left, right, info); -+ branch(condition, type, tgt); -+} -+ -+// Explicit instantiation for all supported types. -+template void LIR_List::cmp_branch(LIR_Condition, LIR_Opr, LIR_Opr, BasicType type, Label*, CodeEmitInfo*); -+template void LIR_List::cmp_branch(LIR_Condition, LIR_Opr, LIR_Opr, BasicType type, BlockBegin*, CodeEmitInfo*); -+template void LIR_List::cmp_branch(LIR_Condition, LIR_Opr, LIR_Opr, BasicType type, CodeStub*, CodeEmitInfo*); + DEFAULT_VERSION_FEATURE=11 + DEFAULT_VERSION_INTERIM=0 +-DEFAULT_VERSION_UPDATE=25 ++DEFAULT_VERSION_UPDATE=29 + DEFAULT_VERSION_PATCH=0 + DEFAULT_VERSION_EXTRA1=0 + DEFAULT_VERSION_EXTRA2=0 + DEFAULT_VERSION_EXTRA3=0 +-DEFAULT_VERSION_DATE=2024-10-15 ++DEFAULT_VERSION_DATE=2025-10-21 + DEFAULT_VERSION_CLASSFILE_MAJOR=55 # "`$EXPR $DEFAULT_VERSION_FEATURE + 44`" + DEFAULT_VERSION_CLASSFILE_MINOR=0 + DEFAULT_ACCEPTABLE_BOOT_VERSIONS="10 11" +diff --git a/make/common/MakeIO.gmk b/make/common/MakeIO.gmk +index 342e4f5c4..7cd6fa187 100644 +--- a/make/common/MakeIO.gmk ++++ b/make/common/MakeIO.gmk +@@ -257,7 +257,7 @@ ifeq ($(HAS_FILE_FUNCTION), true) + else + # Use printf to get consistent behavior on all platforms. + WriteFile = \ +- $(shell $(PRINTF) "%s" $(call ShellQuote, $1) > $2) ++ $(shell $(PRINTF) "%s\n" $(strip $(call ShellQuote, $1)) > $2) + endif + + # Param 1 - Text to write +@@ -268,5 +268,5 @@ ifeq ($(HAS_FILE_FUNCTION), true) + else + # Use printf to get consistent behavior on all platforms. + AppendFile = \ +- $(shell $(PRINTF) "%s" $(call ShellQuote, $1) >> $2) ++ $(shell $(PRINTF) "%s\n" $(strip $(call ShellQuote, $1)) >> $2) + endif +diff --git a/make/conf/github-actions.conf b/make/conf/github-actions.conf +index 419337a5c..0de85affe 100644 +--- a/make/conf/github-actions.conf ++++ b/make/conf/github-actions.conf +@@ -29,13 +29,13 @@ GTEST_VERSION=1.8.1 + JTREG_VERSION=7.3.1+1 + + LINUX_X64_BOOT_JDK_EXT=tar.gz +-LINUX_X64_BOOT_JDK_URL=https://github.com/adoptium/temurin11-binaries/releases/download/jdk-11.0.23%2B9/OpenJDK11U-jdk_x64_linux_hotspot_11.0.23_9.tar.gz +-LINUX_X64_BOOT_JDK_SHA256=23e47ea7a3015be3240f21185fd902adebdcf76530757c9b482c7eb5bd3417c2 +- +-WINDOWS_X64_BOOT_JDK_EXT=zip +-WINDOWS_X64_BOOT_JDK_URL=https://github.com/adoptium/temurin11-binaries/releases/download/jdk-11.0.23%2B9/OpenJDK11U-jdk_x64_windows_hotspot_11.0.23_9.zip +-WINDOWS_X64_BOOT_JDK_SHA256=d7a9f8ceee9a5785dcbbcbec20a07b1366efec59ba652ef7e03f6f7d10f52b85 ++LINUX_X64_BOOT_JDK_URL=https://github.com/adoptium/temurin11-binaries/releases/download/jdk-11.0.26%2B4/OpenJDK11U-jdk_x64_linux_hotspot_11.0.26_4.tar.gz ++LINUX_X64_BOOT_JDK_SHA256=7def4c5807b38ef1a7bb30a86572a795ca604127cc8d1f5b370abf23618104e6 + + MACOS_X64_BOOT_JDK_EXT=tar.gz +-MACOS_X64_BOOT_JDK_URL=https://github.com/adoptium/temurin11-binaries/releases/download/jdk-11.0.23%2B9/OpenJDK11U-jdk_x64_mac_hotspot_11.0.23_9.tar.gz +-MACOS_X64_BOOT_JDK_SHA256=4dbd21d9a0311d321f5886eda50c3086026ed61d02e1a85f7b8c2e9ad557bf03 ++MACOS_X64_BOOT_JDK_URL=https://github.com/adoptium/temurin11-binaries/releases/download/jdk-11.0.26%2B4/OpenJDK11U-jdk_x64_mac_hotspot_11.0.26_4.tar.gz ++MACOS_X64_BOOT_JDK_SHA256=b0142c2c85da43bb3565321164e8129b1166de5d6a43c88e567a92c39128c003 ++ ++WINDOWS_X64_BOOT_JDK_EXT=zip ++WINDOWS_X64_BOOT_JDK_URL=https://github.com/adoptium/temurin11-binaries/releases/download/jdk-11.0.26%2B4/OpenJDK11U-jdk_x64_windows_hotspot_11.0.26_4.zip ++WINDOWS_X64_BOOT_JDK_SHA256=a221ae370f609f00e5869c385f4853fecb622a99f8637b95c22ec66c04e15051 +diff --git a/make/data/cacerts/affirmtrustcommercialca b/make/data/cacerts/affirmtrustcommercialca +deleted file mode 100644 +index 5caddfd3a..000000000 +--- a/make/data/cacerts/affirmtrustcommercialca ++++ /dev/null +@@ -1,27 +0,0 @@ +-Owner: CN=AffirmTrust Commercial, O=AffirmTrust, C=US +-Issuer: CN=AffirmTrust Commercial, O=AffirmTrust, C=US +-Serial number: 7777062726a9b17c +-Valid from: Fri Jan 29 14:06:06 GMT 2010 until: Tue Dec 31 14:06:06 GMT 2030 +-Signature algorithm name: SHA256withRSA +-Subject Public Key Algorithm: 2048-bit RSA key +-Version: 3 +------BEGIN CERTIFICATE----- +-MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UE +-BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz +-dCBDb21tZXJjaWFsMB4XDTEwMDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDEL +-MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp +-cm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +-AQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6EqdbDuKP +-Hx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yr +-ba0F8PrVC8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPAL +-MeIrJmqbTFeurCA+ukV6BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1 +-yHp52UKqK39c/s4mT6NmgTWvRLpUHhwwMmWd5jyTXlBOeuM61G7MGvv50jeuJCqr +-VwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNVHQ4EFgQUnZPGU4teyq8/ +-nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ +-KoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYG +-XUPGhi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNj +-vbz4YYCanrHOQnDiqX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivt +-Z8SOyUOyXGsViQK8YvxO8rUzqrJv0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9g +-N53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0khsUlHRUe072o0EclNmsxZt9YC +-nlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8= +------END CERTIFICATE----- +diff --git a/make/data/cacerts/affirmtrustnetworkingca b/make/data/cacerts/affirmtrustnetworkingca +deleted file mode 100644 +index c773326d4..000000000 +--- a/make/data/cacerts/affirmtrustnetworkingca ++++ /dev/null +@@ -1,27 +0,0 @@ +-Owner: CN=AffirmTrust Networking, O=AffirmTrust, C=US +-Issuer: CN=AffirmTrust Networking, O=AffirmTrust, C=US +-Serial number: 7c4f04391cd4992d +-Valid from: Fri Jan 29 14:08:24 GMT 2010 until: Tue Dec 31 14:08:24 GMT 2030 +-Signature algorithm name: SHA1withRSA +-Subject Public Key Algorithm: 2048-bit RSA key +-Version: 3 +------BEGIN CERTIFICATE----- +-MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UE +-BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz +-dCBOZXR3b3JraW5nMB4XDTEwMDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDEL +-MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp +-cm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +-AQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SEHi3y +-YJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbua +-kCNrmreIdIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRL +-QESxG9fhwoXA3hA/Pe24/PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp +-6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gbh+0t+nvujArjqWaJGctB+d1ENmHP4ndG +-yH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNVHQ4EFgQUBx/S55zawm6i +-QLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ +-KoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfO +-tDIuUFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzu +-QY0x2+c06lkh1QF612S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZ +-Lgo/bNjR9eUJtGxUAArgFU2HdW23WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4u +-olu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9/ZFvgrG+CJPbFEfxojfHRZ48 +-x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s= +------END CERTIFICATE----- +diff --git a/make/data/cacerts/affirmtrustpremiumca b/make/data/cacerts/affirmtrustpremiumca +deleted file mode 100644 +index 275b495a2..000000000 +--- a/make/data/cacerts/affirmtrustpremiumca ++++ /dev/null +@@ -1,38 +0,0 @@ +-Owner: CN=AffirmTrust Premium, O=AffirmTrust, C=US +-Issuer: CN=AffirmTrust Premium, O=AffirmTrust, C=US +-Serial number: 6d8c1446b1a60aee +-Valid from: Fri Jan 29 14:10:36 GMT 2010 until: Mon Dec 31 14:10:36 GMT 2040 +-Signature algorithm name: SHA384withRSA +-Subject Public Key Algorithm: 4096-bit RSA key +-Version: 3 +------BEGIN CERTIFICATE----- +-MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UE +-BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVz +-dCBQcmVtaXVtMB4XDTEwMDEyOTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkG +-A1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1U +-cnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxBLf +-qV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtnBKAQ +-JG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ +-+jjeRFcV5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrS +-s8PhaJyJ+HoAVt70VZVs+7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5 +-HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmdGPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d7 +-70O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5Rp9EixAqnOEhss/n/fauG +-V+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NIS+LI+H+S +-qHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S +-5u046uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4Ia +-C1nEWTJ3s7xgaVY5/bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TX +-OwF0lkLgAOIua+rF7nKsu7/+6qqo+Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYE +-FJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/ +-BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByvMiPIs0laUZx2 +-KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg +-Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B +-8OWycvpEgjNC6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQ +-MKSOyARiqcTtNd56l+0OOF6SL5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc +-0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK+4w1IX2COPKpVJEZNZOUbWo6xbLQ +-u4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmVBtWVyuEklut89pMF +-u+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFgIxpH +-YoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8 +-GKa1qF60g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaO +-RtGdFNrHF+QFlozEJLUbzxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6e +-KeC2uAloGRwYQw== +------END CERTIFICATE----- +diff --git a/make/data/cacerts/affirmtrustpremiumeccca b/make/data/cacerts/affirmtrustpremiumeccca +deleted file mode 100644 +index d0fcc1e77..000000000 +--- a/make/data/cacerts/affirmtrustpremiumeccca ++++ /dev/null +@@ -1,20 +0,0 @@ +-Owner: CN=AffirmTrust Premium ECC, O=AffirmTrust, C=US +-Issuer: CN=AffirmTrust Premium ECC, O=AffirmTrust, C=US +-Serial number: 7497258ac73f7a54 +-Valid from: Fri Jan 29 14:20:24 GMT 2010 until: Mon Dec 31 14:20:24 GMT 2040 +-Signature algorithm name: SHA384withECDSA +-Subject Public Key Algorithm: 384-bit EC (secp384r1) key +-Version: 3 +------BEGIN CERTIFICATE----- +-MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMC +-VVMxFDASBgNVBAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQ +-cmVtaXVtIEVDQzAeFw0xMDAxMjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJ +-BgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1UcnVzdDEgMB4GA1UEAwwXQWZmaXJt +-VHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQNMF4bFZ0D +-0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQN8O9 +-ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0G +-A1UdDgQWBBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4G +-A1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/Vs +-aobgxCd05DhT1wV/GzTjxi+zygk8N53X57hG8f2h4nECMEJZh0PUUd+60wkyWs6I +-flc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKMeQ== +------END CERTIFICATE----- +diff --git a/make/data/cacerts/baltimorecybertrustca b/make/data/cacerts/baltimorecybertrustca +deleted file mode 100644 +index b3cf6547c..000000000 +--- a/make/data/cacerts/baltimorecybertrustca ++++ /dev/null +@@ -1,28 +0,0 @@ +-Owner: CN=Baltimore CyberTrust Root, OU=CyberTrust, O=Baltimore, C=IE +-Issuer: CN=Baltimore CyberTrust Root, OU=CyberTrust, O=Baltimore, C=IE +-Serial number: 20000b9 +-Valid from: Fri May 12 18:46:00 GMT 2000 until: Mon May 12 23:59:00 GMT 2025 +-Signature algorithm name: SHA1withRSA +-Subject Public Key Algorithm: 2048-bit RSA key +-Version: 3 +------BEGIN CERTIFICATE----- +-MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ +-RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD +-VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX +-DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y +-ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy +-VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr +-mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr +-IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK +-mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu +-XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy +-dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye +-jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1 +-BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3 +-DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92 +-9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx +-jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0 +-Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz +-ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS +-R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp +------END CERTIFICATE----- +diff --git a/make/data/cacerts/camerfirmachamberscommerceca b/make/data/cacerts/camerfirmachamberscommerceca +deleted file mode 100644 +index b92255f77..000000000 +--- a/make/data/cacerts/camerfirmachamberscommerceca ++++ /dev/null +@@ -1,35 +0,0 @@ +-Owner: CN=Chambers of Commerce Root, OU=http://www.chambersign.org, O=AC Camerfirma SA CIF A82743287, C=EU +-Issuer: CN=Chambers of Commerce Root, OU=http://www.chambersign.org, O=AC Camerfirma SA CIF A82743287, C=EU +-Serial number: 0 +-Valid from: Tue Sep 30 16:13:43 GMT 2003 until: Wed Sep 30 16:13:44 GMT 2037 +-Signature algorithm name: SHA1withRSA +-Subject Public Key Algorithm: 2048-bit RSA key +-Version: 3 +------BEGIN CERTIFICATE----- +-MIIEvTCCA6WgAwIBAgIBADANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJFVTEn +-MCUGA1UEChMeQUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQL +-ExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEiMCAGA1UEAxMZQ2hhbWJlcnMg +-b2YgQ29tbWVyY2UgUm9vdDAeFw0wMzA5MzAxNjEzNDNaFw0zNzA5MzAxNjEzNDRa +-MH8xCzAJBgNVBAYTAkVVMScwJQYDVQQKEx5BQyBDYW1lcmZpcm1hIFNBIENJRiBB +-ODI3NDMyODcxIzAhBgNVBAsTGmh0dHA6Ly93d3cuY2hhbWJlcnNpZ24ub3JnMSIw +-IAYDVQQDExlDaGFtYmVycyBvZiBDb21tZXJjZSBSb290MIIBIDANBgkqhkiG9w0B +-AQEFAAOCAQ0AMIIBCAKCAQEAtzZV5aVdGDDg2olUkfzIx1L4L1DZ77F1c2VHfRtb +-unXF/KGIJPov7coISjlUxFF6tdpg6jg8gbLL8bvZkSM/SAFwdakFKq0fcfPJVD0d +-BmpAPrMMhe5cG3nCYsS4No41XQEMIwRHNaqbYE6gZj3LJgqcQKH0XZi/caulAGgq +-7YN6D6IUtdQis4CwPAxaUWktWBiP7Zme8a7ileb2R6jWDA+wWFjbw2Y3npuRVDM3 +-0pQcakjJyfKl2qUMI/cjDpwyVV5xnIQFUZot/eZOKjRa3spAN2cMVCFVd9oKDMyX +-roDclDZK9D7ONhMeU+SsTjoF7Nuucpw4i9A5O4kKPnf+dQIBA6OCAUQwggFAMBIG +-A1UdEwEB/wQIMAYBAf8CAQwwPAYDVR0fBDUwMzAxoC+gLYYraHR0cDovL2NybC5j +-aGFtYmVyc2lnbi5vcmcvY2hhbWJlcnNyb290LmNybDAdBgNVHQ4EFgQU45T1sU3p +-26EpW1eLTXYGduHRooowDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIA +-BzAnBgNVHREEIDAegRxjaGFtYmVyc3Jvb3RAY2hhbWJlcnNpZ24ub3JnMCcGA1Ud +-EgQgMB6BHGNoYW1iZXJzcm9vdEBjaGFtYmVyc2lnbi5vcmcwWAYDVR0gBFEwTzBN +-BgsrBgEEAYGHLgoDATA+MDwGCCsGAQUFBwIBFjBodHRwOi8vY3BzLmNoYW1iZXJz +-aWduLm9yZy9jcHMvY2hhbWJlcnNyb290Lmh0bWwwDQYJKoZIhvcNAQEFBQADggEB +-AAxBl8IahsAifJ/7kPMa0QOx7xP5IV8EnNrJpY0nbJaHkb5BkAFyk+cefV/2icZd +-p0AJPaxJRUXcLo0waLIJuvvDL8y6C98/d3tGfToSJI6WjzwFCm/SlCgdbQzALogi +-1djPHRPH8EjX1wWnz8dHnjs8NMiAT9QUu/wNUPf6s+xCX6ndbcj0dc97wXImsQEc +-XCz9ek60AcUFV7nnPKoF2YjpB0ZBzu9Bga5Y34OirsrXdx/nADydb47kMgkdTXg0 +-eDQ8lJsm7U9xxhl6vSAiSFr+S30Dt+dYvsYyTnQeaN2oaFuzPu5ifdmA6Ap1erfu +-tGWaIZDgqtCYvDi1czyL+Nw= +------END CERTIFICATE----- +diff --git a/make/data/cacerts/camerfirmachambersignca b/make/data/cacerts/camerfirmachambersignca +deleted file mode 100644 +index 935eea9c2..000000000 +--- a/make/data/cacerts/camerfirmachambersignca ++++ /dev/null +@@ -1,48 +0,0 @@ +-Owner: CN=Global Chambersign Root - 2008, O=AC Camerfirma S.A., SERIALNUMBER=A82743287, L=Madrid (see current address at www.camerfirma.com/address), C=EU +-Issuer: CN=Global Chambersign Root - 2008, O=AC Camerfirma S.A., SERIALNUMBER=A82743287, L=Madrid (see current address at www.camerfirma.com/address), C=EU +-Serial number: c9cdd3e9d57d23ce +-Valid from: Fri Aug 01 12:31:40 GMT 2008 until: Sat Jul 31 12:31:40 GMT 2038 +-Signature algorithm name: SHA1withRSA +-Subject Public Key Algorithm: 4096-bit RSA key +-Version: 3 +------BEGIN CERTIFICATE----- +-MIIHSTCCBTGgAwIBAgIJAMnN0+nVfSPOMA0GCSqGSIb3DQEBBQUAMIGsMQswCQYD +-VQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0 +-IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3 +-MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAlBgNVBAMTHkdsb2JhbCBD +-aGFtYmVyc2lnbiBSb290IC0gMjAwODAeFw0wODA4MDExMjMxNDBaFw0zODA3MzEx +-MjMxNDBaMIGsMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3Vy +-cmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAG +-A1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAl +-BgNVBAMTHkdsb2JhbCBDaGFtYmVyc2lnbiBSb290IC0gMjAwODCCAiIwDQYJKoZI +-hvcNAQEBBQADggIPADCCAgoCggIBAMDfVtPkOpt2RbQT2//BthmLN0EYlVJH6xed +-KYiONWwGMi5HYvNJBL99RDaxccy9Wglz1dmFRP+RVyXfXjaOcNFccUMd2drvXNL7 +-G706tcuto8xEpw2uIRU/uXpbknXYpBI4iRmKt4DS4jJvVpyR1ogQC7N0ZJJ0YPP2 +-zxhPYLIj0Mc7zmFLmY/CDNBAspjcDahOo7kKrmCgrUVSY7pmvWjg+b4aqIG7HkF4 +-ddPB/gBVsIdU6CeQNR1MM62X/JcumIS/LMmjv9GYERTtY/jKmIhYF5ntRQOXfjyG +-HoiMvvKRhI9lNNgATH23MRdaKXoKGCQwoze1eqkBfSbW+Q6OWfH9GzO1KTsXO0G2 +-Id3UwD2ln58fQ1DJu7xsepeY7s2MH/ucUa6LcL0nn3HAa6x9kGbo1106DbDVwo3V +-yJ2dwW3Q0L9R5OP4wzg2rtandeavhENdk5IMagfeOx2YItaswTXbo6Al/3K1dh3e +-beksZixShNBFks4c5eUzHdwHU1SjqoI7mjcv3N2gZOnm3b2u/GSFHTynyQbehP9r +-6GsaPMWis0L7iwk+XwhSx2LE1AVxv8Rk5Pihg+g+EpuoHtQ2TS9x9o0o9oOpE9Jh +-wZG7SMA0j0GMS0zbaRL/UJScIINZc+18ofLx/d33SdNDWKBWY8o9PeU1VlnpDsog +-zCtLkykPAgMBAAGjggFqMIIBZjASBgNVHRMBAf8ECDAGAQH/AgEMMB0GA1UdDgQW +-BBS5CcqcHtvTbDprru1U8VuTBjUuXjCB4QYDVR0jBIHZMIHWgBS5CcqcHtvTbDpr +-ru1U8VuTBjUuXqGBsqSBrzCBrDELMAkGA1UEBhMCRVUxQzBBBgNVBAcTOk1hZHJp +-ZCAoc2VlIGN1cnJlbnQgYWRkcmVzcyBhdCB3d3cuY2FtZXJmaXJtYS5jb20vYWRk +-cmVzcykxEjAQBgNVBAUTCUE4Mjc0MzI4NzEbMBkGA1UEChMSQUMgQ2FtZXJmaXJt +-YSBTLkEuMScwJQYDVQQDEx5HbG9iYWwgQ2hhbWJlcnNpZ24gUm9vdCAtIDIwMDiC +-CQDJzdPp1X0jzjAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCow +-KAYIKwYBBQUHAgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZI +-hvcNAQEFBQADggIBAICIf3DekijZBZRG/5BXqfEv3xoNa/p8DhxJJHkn2EaqbylZ +-UohwEurdPfWbU1Rv4WCiqAm57OtZfMY18dwY6fFn5a+6ReAJ3spED8IXDneRRXoz +-X1+WLGiLwUePmJs9wOzL9dWCkoQ10b42OFZyMVtHLaoXpGNR6woBrX/sdZ7LoR/x +-fxKxueRkf2fWIyr0uDldmOghp+G9PUIadJpwr2hsUF1Jz//7Dl3mLEfXgTpZALVz +-a2Mg9jFFCDkO9HB+QHBaP9BrQql0PSgvAm11cpUJjUhjxsYjV5KTXjXBjfkK9yyd +-Yhz2rXzdpjEetrHHfoUm+qRqtdpjMNHvkzeyZi99Bffnt0uYlDXA2TopwZ2yUDMd +-SqlapskD7+3056huirRXhOukP9DuqqqHW2Pok+JrqNS4cnhrG+055F3Lm6qH1U9O +-AP7Zap88MQ8oAgF9mOinsKJknnn4SPIVqczmyETrP3iZ8ntxPjzxmKfFGBI/5rso +-M0LpRQp8bfKGeS/Fghl9CYl8slR2iK7ewfPM4W7bMdaTrpmg7yVqc5iJWzouE4ge +-v8CSlDQb4ye3ix5vQv/n6TebUB0tovkC7stYWDpxvGjjqsGvHCgfotwjZT+B6q6Z +-09gwzxMNTxXJhLynSC34MCN32EZLeW32jO06f2ARePTpm67VVMB0gNELQp/B +------END CERTIFICATE----- +diff --git a/make/data/cacerts/sectigocodesignroote46 b/make/data/cacerts/sectigocodesignroote46 +new file mode 100644 +index 000000000..7f13b28a4 +--- /dev/null ++++ b/make/data/cacerts/sectigocodesignroote46 +@@ -0,0 +1,21 @@ ++Owner: CN=Sectigo Public Code Signing Root E46, O=Sectigo Limited, C=GB ++Issuer: CN=Sectigo Public Code Signing Root E46, O=Sectigo Limited, C=GB ++Serial number: 50249ba2ef8ea6bf6c2c1f1a6385d4c3 ++Valid from: Mon Mar 22 00:00:00 GMT 2021 until: Wed Mar 21 23:59:59 GMT 2046 ++Signature algorithm name: SHA384withECDSA ++Subject Public Key Algorithm: 384-bit EC (secp384r1) key ++Version: 3 ++-----BEGIN CERTIFICATE----- ++MIICKDCCAa+gAwIBAgIQUCSbou+Opr9sLB8aY4XUwzAKBggqhkjOPQQDAzBWMQsw ++CQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMS0wKwYDVQQDEyRT ++ZWN0aWdvIFB1YmxpYyBDb2RlIFNpZ25pbmcgUm9vdCBFNDYwHhcNMjEwMzIyMDAw ++MDAwWhcNNDYwMzIxMjM1OTU5WjBWMQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2Vj ++dGlnbyBMaW1pdGVkMS0wKwYDVQQDEyRTZWN0aWdvIFB1YmxpYyBDb2RlIFNpZ25p ++bmcgUm9vdCBFNDYwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQIMoEDH487om+BR4zl ++e7m6wWmyW0nAKLkUWG8kM85Qm3PZO8FoOZx6Yc5c0iJHRKuAhanllayqrmZYhlan ++uIODzLTRDqlR+EtnOX+MubY5aDSPGUq6jiHrQrisVp0J3AejQjBAMB0GA1UdDgQW ++BBTPfSygkHqYHd22XoXC4NoVcdLlXjAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/ ++BAUwAwEB/zAKBggqhkjOPQQDAwNnADBkAjACd++zAerlV83j8HflRwwwlLmgchbs ++aGX/4g44dv/oG8KfzCVTRg6sZHMobtK0IqYCMGk5W6+oBFyZMtOebrSwXs8lGjll ++/zHz43Zy8DMXO+iiqzSEwWGneZ6KupkGGqfVKw== ++-----END CERTIFICATE----- +diff --git a/make/data/cacerts/sectigocodesignrootr46 b/make/data/cacerts/sectigocodesignrootr46 +new file mode 100644 +index 000000000..38270cb0c +--- /dev/null ++++ b/make/data/cacerts/sectigocodesignrootr46 +@@ -0,0 +1,39 @@ ++Owner: CN=Sectigo Public Code Signing Root R46, O=Sectigo Limited, C=GB ++Issuer: CN=Sectigo Public Code Signing Root R46, O=Sectigo Limited, C=GB ++Serial number: 4b2c3b01018bad2abc8c7b5b3eed9057 ++Valid from: Mon Mar 22 00:00:00 GMT 2021 until: Wed Mar 21 23:59:59 GMT 2046 ++Signature algorithm name: SHA384withRSA ++Subject Public Key Algorithm: 4096-bit RSA key ++Version: 3 ++-----BEGIN CERTIFICATE----- ++MIIFeDCCA2CgAwIBAgIQSyw7AQGLrSq8jHtbPu2QVzANBgkqhkiG9w0BAQwFADBW ++MQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMS0wKwYDVQQD ++EyRTZWN0aWdvIFB1YmxpYyBDb2RlIFNpZ25pbmcgUm9vdCBSNDYwHhcNMjEwMzIy ++MDAwMDAwWhcNNDYwMzIxMjM1OTU5WjBWMQswCQYDVQQGEwJHQjEYMBYGA1UEChMP ++U2VjdGlnbyBMaW1pdGVkMS0wKwYDVQQDEyRTZWN0aWdvIFB1YmxpYyBDb2RlIFNp ++Z25pbmcgUm9vdCBSNDYwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCN ++55QSIgQkdC7/FiMCkoq2rjaFrEfUI5ErPtx94jGgUW+shJHjUoq14pbe0IdjJImK ++/+8Skzt9u7aKvb0Ffyeba2XTpQxpsbxJOZrxbW6q5KCDJ9qaDStQ6Utbs7hkNqR+ ++Sj2pcaths3OzPAsM79szV+W+NDfjlxtd/R8SPYIDdub7P2bSlDFp+m2zNKzBenjc ++klDyZMeqLQSrw2rq4C+np9xu1+j/2iGrQL+57g2extmeme/G3h+pDHazJyCh1rr9 ++gOcB0u/rgimVcI3/uxXP/tEPNqIuTzKQdEZrRzUTdwUzT2MuuC3hv2WnBGsY2HH6 ++zAjybYmZELGt2z4s5KoYsMYHAXVn3m3pY2MeNn9pib6qRT5uWl+PoVvLnTCGMOgD ++s0DGDQ84zWeoU4j6uDBl+m/H5x2xg3RpPqzEaDux5mczmrYI4IAFSEDu9oJkRqj1 ++c7AGlfJsZZ+/VVscnFcax3hGfHCqlBuCF6yH6bbJDoEcQNYWFyn8XJwYK+pF9e+9 ++1WdPKF4F7pBMeufG9ND8+s0+MkYTIDaKBOq3qgdGnA2TOglmmVhcKaO5DKYwODzQ ++RjY1fJy67sPV+Qp2+n4FG0DKkjXp1XrRtX8ArqmQqsV/AZwQsRb8zG4Y3G9i/qZQ ++p7h7uJ0VP/4gDHXIIloTlRmQAOka1cKG8eOO7F/05QIDAQABo0IwQDAdBgNVHQ4E ++FgQUMuuSmv81lkgvKEBCcCA2kVwXheYwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB ++/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAHZlwuPXIkrXHYle/2lexhQCTXOm ++zc0oyrA36r+nySGqql/av/aDbNCA0QpcAKTL88w5D55BcYjVPOiKe4wXI/fKNHSR ++bAauUD8AWbImPDwXg1cDPi3RGj3UzwdUskMLUnKoiPXEF/Jv0Vil0WjkPZgIGO42 ++9EhImvpUcPCI1HAWMEJJ0Nk/dUtFcdiuorthDoiFUFe5uhErNikfjyBynlyeidGC ++2kWNapnahHFrM6UQu3nwl/Z0gaA/V8eGjDCMDjiVrgHGHqvcqB9vL9f/dh6uF3Nt ++5bl1s2EGqJUzwk5vsjfylb6FVBK5yL1iQnb3Kvz1NzEDJlf+0ebb8BYCcoOMCLOE ++rKnkB/ihiMQTWlBHVEKm7dBBNCyYsT6iNKEMXb2s9395p79tDFYyhRtLl7jhrOSk ++PHHxo+FOY9b0Rrr1CwjhYzztolkvCtQsayOinqFN7tESzRgzUO1Bbst/PUFgC2ML ++ePV170MVtzYLEK/cXBipmNk22R3YhLMGioLjexskp0LO7g8+VlwyfexL3lYrOzu6 +++XpY0FG2bNb2WKJSJHpEhqEcYD9J0/z6+YQcBcI0v+Lm8RkqmS9WVzWctfUHw0Yv ++3jg9GQ37o/HfE57nqXJYMa+96trX1m13MzOO9Kz9wb9Jh9JwBWd0Bqb2eEAtFgSR ++Dx/TFsS4ehcNJMmy ++-----END CERTIFICATE----- +diff --git a/make/data/cacerts/sectigotlsroote46 b/make/data/cacerts/sectigotlsroote46 +new file mode 100644 +index 000000000..60e0b83c9 +--- /dev/null ++++ b/make/data/cacerts/sectigotlsroote46 +@@ -0,0 +1,21 @@ ++Owner: CN=Sectigo Public Server Authentication Root E46, O=Sectigo Limited, C=GB ++Issuer: CN=Sectigo Public Server Authentication Root E46, O=Sectigo Limited, C=GB ++Serial number: 42f2ccda1b6937445f15fe752810b8f4 ++Valid from: Mon Mar 22 00:00:00 GMT 2021 until: Wed Mar 21 23:59:59 GMT 2046 ++Signature algorithm name: SHA384withECDSA ++Subject Public Key Algorithm: 384-bit EC (secp384r1) key ++Version: 3 ++-----BEGIN CERTIFICATE----- ++MIICOjCCAcGgAwIBAgIQQvLM2htpN0RfFf51KBC49DAKBggqhkjOPQQDAzBfMQsw ++CQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1T ++ZWN0aWdvIFB1YmxpYyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBFNDYwHhcN ++MjEwMzIyMDAwMDAwWhcNNDYwMzIxMjM1OTU5WjBfMQswCQYDVQQGEwJHQjEYMBYG ++A1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1TZWN0aWdvIFB1YmxpYyBT ++ZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBFNDYwdjAQBgcqhkjOPQIBBgUrgQQA ++IgNiAAR2+pmpbiDt+dd34wc7qNs9Xzjoq1WmVk/WSOrsfy2qw7LFeeyZYX8QeccC ++WvkEN/U0NSt3zn8gj1KjAIns1aeibVvjS5KToID1AZTc8GgHHs3u/iVStSBDHBv+ ++6xnOQ6OjQjBAMB0GA1UdDgQWBBTRItpMWfFLXyY4qp3W7usNw/upYTAOBgNVHQ8B ++Af8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNnADBkAjAn7qRa ++qCG76UeXlImldCBteU/IvZNeWBj7LRoAasm4PdCkT0RHlAFWovgzJQxC36oCMB3q ++4S6ILuH5px0CMk7yn2xVdOOurvulGu7t0vzCAxHrRVxgED1cf5kDW21USAGKcw== ++-----END CERTIFICATE----- +diff --git a/make/data/cacerts/sectigotlsrootr46 b/make/data/cacerts/sectigotlsrootr46 +new file mode 100644 +index 000000000..7ec1b263d +--- /dev/null ++++ b/make/data/cacerts/sectigotlsrootr46 +@@ -0,0 +1,39 @@ ++Owner: CN=Sectigo Public Server Authentication Root R46, O=Sectigo Limited, C=GB ++Issuer: CN=Sectigo Public Server Authentication Root R46, O=Sectigo Limited, C=GB ++Serial number: 758dfd8bae7c0700faa925a7e1c7ad14 ++Valid from: Mon Mar 22 00:00:00 GMT 2021 until: Wed Mar 21 23:59:59 GMT 2046 ++Signature algorithm name: SHA384withRSA ++Subject Public Key Algorithm: 4096-bit RSA key ++Version: 3 ++-----BEGIN CERTIFICATE----- ++MIIFijCCA3KgAwIBAgIQdY39i658BwD6qSWn4cetFDANBgkqhkiG9w0BAQwFADBf ++MQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQD ++Ey1TZWN0aWdvIFB1YmxpYyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBSNDYw ++HhcNMjEwMzIyMDAwMDAwWhcNNDYwMzIxMjM1OTU5WjBfMQswCQYDVQQGEwJHQjEY ++MBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1TZWN0aWdvIFB1Ymxp ++YyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBSNDYwggIiMA0GCSqGSIb3DQEB ++AQUAA4ICDwAwggIKAoICAQCTvtU2UnXYASOgHEdCSe5jtrch/cSV1UgrJnwUUxDa ++ef0rty2k1Cz66jLdScK5vQ9IPXtamFSvnl0xdE8H/FAh3aTPaE8bEmNtJZlMKpnz ++SDBh+oF8HqcIStw+KxwfGExxqjWMrfhu6DtK2eWUAtaJhBOqbchPM8xQljeSM9xf ++iOefVNlI8JhD1mb9nxc4Q8UBUQvX4yMPFF1bFOdLvt30yNoDN9HWOaEhUTCDsG3X ++ME6WW5HwcCSrv0WBZEMNvSE6Lzzpng3LILVCJ8zab5vuZDCQOc2TZYEhMbUjUDM3 ++IuM47fgxMMxF/mL50V0yeUKH32rMVhlATc6qu/m1dkmU8Sf4kaWD5QazYw6A3OAS ++VYCmO2a0OYctyPDQ0RTp5A1NDvZdV3LFOxxHVp3i1fuBYYzMTYCQNFu31xR13NgE ++SJ/AwSiItOkcyqex8Va3e0lMWeUgFaiEAin6OJRpmkkGj80feRQXEgyDet4fsZfu +++Zd4KKTIRJLpfSYFplhym3kT2BFfrsU4YjRosoYwjviQYZ4ybPUHNs2iTG7sijbt ++8uaZFURww3y8nDnAtOFr94MlI1fZEoDlSfB1D++N6xybVCi0ITz8fAr/73trdf+L ++HaAZBav6+CuBQug4urv7qv094PPK306Xlynt8xhW6aWWrL3DkJiy4Pmi1KZHQ3xt ++zwIDAQABo0IwQDAdBgNVHQ4EFgQUVnNYZJX5khqwEioEYnmhQBWIIUkwDgYDVR0P ++AQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAC9c ++mTz8Bl6MlC5w6tIyMY208FHVvArzZJ8HXtXBc2hkeqK5Duj5XYUtqDdFqij0lgVQ ++YKlJfp/imTYpE0RHap1VIDzYm/EDMrraQKFz6oOht0SmDpkBm+S8f74TlH7Kph52 ++gDY9hAaLMyZlbcp+nv4fjFg4exqDsQ+8FxG75gbMY/qB8oFM2gsQa6H61SilzwZA ++Fv97fRheORKkU55+MkIQpiGRqRxOF3yEvJ+M0ejf5lG5Nkc/kLnHvALcWxxPDkjB ++JYOcCj+esQMzEhonrPcibCTRAUH4WAP+JWgiH5paPHxsnnVI84HxZmduTILA7rpX ++DhjvLpr3Etiga+kFpaHpaPi8TD8SHkXoUsCjvxInebnMMTzD9joiFgOgyY9mpFui ++TdaBJQbpdqQACj7LzTWb4OE4y2BThihCQRxEV+ioratF4yUQvNs+ZUH7G6aXD+u5 ++dHn5HrwdVw1Hr8Mvn4dGp+smWg9WY7ViYG4A++MnESLn/pmPNPW56MORcr3Ywx65 ++LvKRRFHQV80MNNVIIb/bE/FmJUNS0nAiNs2fxBx1IK1jcmMGDw4nztJqDby1ORrp ++0XZ60Vzk50lJLVU3aPAaOpg+VBeHVOmmJ1CJeyAvP/+/oYtKR5j/K3tJPsMpRmAY ++QqszKbrAKbkTidOIijlBO8n9pu0f9GBj39ItVQGL ++-----END CERTIFICATE----- +diff --git a/make/data/currency/CurrencyData.properties b/make/data/currency/CurrencyData.properties +index 550662ec3..6e21fffde 100644 +--- a/make/data/currency/CurrencyData.properties ++++ b/make/data/currency/CurrencyData.properties +@@ -1,5 +1,5 @@ + # +-# Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. ++# Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + # + # This code is free software; you can redistribute it and/or modify it +@@ -32,7 +32,7 @@ formatVersion=3 + # Version of the currency code information in this class. + # It is a serial number that accompanies with each amendment. + +-dataVersion=177 ++dataVersion=180 + + # List of all valid ISO 4217 currency codes. + # To ensure compatibility, do not remove codes. +@@ -54,7 +54,7 @@ all=ADP020-AED784-AFA004-AFN971-ALL008-AMD051-ANG532-AOA973-ARS032-ATS040-AUD036 + 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-\ ++ UYU858-UZS860-VEB862-VED926-VEF937-VES928-VND704-VUV548-WST882-XAD396-XAF950-XAG961-XAU959-XBA955-\ + XBB956-XBC957-XBD958-XCD951-XCG532-XDR960-XFO000-XFU000-XOF952-XPD964-XPF953-\ + XPT962-XSU994-XTS963-XUA965-XXX999-YER886-YUM891-ZAR710-ZMK894-ZMW967-ZWD716-ZWG924-\ + ZWL932-ZWN942-ZWR935 +@@ -147,7 +147,7 @@ IO=USD + # BRUNEI DARUSSALAM + BN=BND + # BULGARIA +-BG=BGN ++BG=BGN;2025-12-31-22-00-00;EUR + # BURKINA FASO + BF=XOF + # BURUNDI +@@ -193,7 +193,7 @@ HR=EUR + # CUBA + CU=CUP + # Cura\u00e7ao +-CW=ANG;2025-04-01-04-00-00;XCG ++CW=XCG + # CYPRUS + CY=EUR + # CZECHIA +@@ -510,7 +510,7 @@ SR=SRD + # SVALBARD AND JAN MAYEN + SJ=NOK + # Sint Maarten (Dutch part) +-SX=ANG;2025-04-01-04-00-00;XCG ++SX=XCG + # ESWATINI + SZ=SZL + # SWEDEN +diff --git a/make/data/lsrdata/language-subtag-registry.txt b/make/data/lsrdata/language-subtag-registry.txt +index 3079d77ed..64c40f281 100644 +--- a/make/data/lsrdata/language-subtag-registry.txt ++++ b/make/data/lsrdata/language-subtag-registry.txt +@@ -1,4 +1,4 @@ +-File-Date: 2024-06-14 ++File-Date: 2025-05-15 + %% + Type: language + Subtag: aa +@@ -5950,6 +5950,7 @@ Added: 2009-07-29 + %% + Type: language + Subtag: bql ++Description: Karian + Description: Bilakura + Added: 2009-07-29 + %% +@@ -9083,6 +9084,7 @@ Scope: collection + %% + Type: language + Subtag: daz ++Description: Moi-Wadea + Description: Dao + Added: 2009-07-29 + %% +@@ -9290,6 +9292,8 @@ Type: language + Subtag: dek + Description: Dek + Added: 2009-07-29 ++Deprecated: 2024-12-12 ++Preferred-Value: sqm + %% + Type: language + Subtag: del +@@ -14082,6 +14086,12 @@ Added: 2009-07-29 + Macrolanguage: hmn + %% + Type: language ++Subtag: hnm ++Description: Hainanese ++Added: 2024-12-12 ++Macrolanguage: zh ++%% ++Type: language + Subtag: hnn + Description: Hanunoo + Added: 2009-07-29 +@@ -16421,6 +16431,7 @@ Added: 2009-07-29 + %% + Type: language + Subtag: kci ++Description: Ngyian + Description: Kamantan + Added: 2009-07-29 + %% +@@ -21081,6 +21092,12 @@ Description: Laua + Added: 2009-07-29 + %% + Type: language ++Subtag: luh ++Description: Leizhou Chinese ++Added: 2024-12-12 ++Macrolanguage: zh ++%% ++Type: language + Subtag: lui + Description: Luiseno + Added: 2005-10-16 +@@ -22850,6 +22867,8 @@ Added: 2009-07-29 + %% + Type: language + Subtag: mmi ++Description: Hember Avu ++Description: Amben + Description: Musar + Added: 2009-07-29 + %% +@@ -25197,8 +25216,9 @@ Added: 2009-07-29 + %% + Type: language + Subtag: new +-Description: Newari + Description: Nepal Bhasa ++Description: Newar ++Description: Newari + Added: 2005-10-16 + %% + Type: language +@@ -26641,6 +26661,8 @@ Type: language + Subtag: nte + Description: Nathembo + Added: 2009-07-29 ++Deprecated: 2024-12-12 ++Preferred-Value: eko + %% + Type: language + Subtag: ntg +@@ -27185,6 +27207,12 @@ Description: Oroch + Added: 2009-07-29 + %% + Type: language ++Subtag: oak ++Description: Noakhali ++Description: Noakhailla ++Added: 2025-05-14 ++%% ++Type: language + Subtag: oar + Description: Old Aramaic (up to 700 BCE) + Description: Ancient Aramaic (up to 700 BCE) +@@ -32147,6 +32175,12 @@ Description: Sajau Basap + Added: 2009-07-29 + %% + Type: language ++Subtag: sjc ++Description: Shaojiang Chinese ++Added: 2024-12-12 ++Macrolanguage: zh ++%% ++Type: language + Subtag: sjd + Description: Kildin Sami + Added: 2009-07-29 +@@ -41302,6 +41336,11 @@ Description: Aluo + Added: 2009-07-29 + %% + Type: language ++Subtag: ynb ++Description: Yamben ++Added: 2025-02-06 ++%% ++Type: language + Subtag: ynd + Description: Yandruwandha + Added: 2009-07-29 +@@ -43616,6 +43655,14 @@ Preferred-Value: hks + Prefix: sgn + %% + Type: extlang ++Subtag: hnm ++Description: Hainanese ++Added: 2024-12-12 ++Preferred-Value: hnm ++Prefix: zh ++Macrolanguage: zh ++%% ++Type: extlang + Subtag: hos + Description: Ho Chi Minh City Sign Language + Added: 2009-07-29 +@@ -43958,6 +44005,14 @@ Prefix: lv + Macrolanguage: lv + %% + Type: extlang ++Subtag: luh ++Description: Leizhou Chinese ++Added: 2024-12-12 ++Preferred-Value: luh ++Prefix: zh ++Macrolanguage: zh ++%% ++Type: extlang + Subtag: lvs + Description: Standard Latvian + Added: 2010-03-11 +@@ -44393,6 +44448,14 @@ Prefix: ar + Macrolanguage: ar + %% + Type: extlang ++Subtag: sjc ++Description: Shaojiang Chinese ++Added: 2024-12-12 ++Preferred-Value: sjc ++Prefix: zh ++Macrolanguage: zh ++%% ++Type: extlang + Subtag: slf + Description: Swiss-Italian Sign Language + Added: 2009-07-29 +@@ -44844,6 +44907,11 @@ Description: Bangla + Added: 2005-10-16 + %% + Type: script ++Subtag: Berf ++Description: Beria Erfe ++Added: 2025-02-06 ++%% ++Type: script + Subtag: Bhks + Description: Bhaiksuki + Added: 2015-07-24 +@@ -45132,6 +45200,12 @@ Description: Nyiakeng Puachue Hmong + Added: 2017-08-13 + %% + Type: script ++Subtag: Hntl ++Description: Han (Traditional variant) with Latin (alias for Hant + ++ Latn) ++Added: 2025-05-14 ++%% ++Type: script + Subtag: Hrkt + Description: Japanese syllabaries (alias for Hiragana + Katakana) + Added: 2005-10-16 +@@ -45636,6 +45710,12 @@ Description: Saurashtra + Added: 2006-07-21 + %% + Type: script ++Subtag: Seal ++Description: Seal ++Description: Small Seal ++Added: 2025-05-14 ++%% ++Type: script + Subtag: Sgnw + Description: SignWriting + Added: 2006-10-17 +@@ -47919,6 +47999,12 @@ Comments: Written standard developed by Romanilha in 1853 and used by + dóu Po, Escolo Gaston Febus, and others + %% + Type: variant ++Subtag: hanoi ++Description: The Hà Nội variant of Vietnamese ++Added: 2025-03-10 ++Prefix: vi ++%% ++Type: variant + Subtag: hepburn + Description: Hepburn romanization + Added: 2009-10-01 +@@ -47949,6 +48035,12 @@ Added: 2017-03-14 + Prefix: eo + %% + Type: variant ++Subtag: huett ++Description: The Huế (province Thừa Thiên) variant of Vietnamese ++Added: 2025-03-10 ++Prefix: vi ++%% ++Type: variant + Subtag: ijekavsk + Description: Serbian with Ijekavian pronunciation + Prefix: sr +@@ -47991,6 +48083,16 @@ Added: 2008-10-14 + Prefix: kw + %% + Type: variant ++Subtag: kleinsch ++Description: Kleinschmidt orthography ++Description: Allattaasitaamut ++Added: 2024-07-20 ++Prefix: kl ++Prefix: kl-tunumiit ++Comments: Orthography for Greenlandic designed by Samuel Kleinschmidt, ++ used from 1851 to 1973. ++%% ++Type: variant + Subtag: kociewie + Description: The Kociewie dialect of Polish + Added: 2014-11-27 +@@ -48014,6 +48116,13 @@ Prefix: sa + Comments: Preferred tag is cls + %% + Type: variant ++Subtag: leidentr ++Description: Ancient Egyptian in Leiden Unified Transliteration ++Added: 2025-02-06 ++Prefix: egy ++Comments: Recommended by the International Association of Egyptologists ++%% ++Type: variant + Subtag: lemosin + Description: Limousin + Added: 2018-04-22 +@@ -48058,6 +48167,19 @@ Comments: Russian orthography as established by the 1917/1918 + orthographic reforms + %% + Type: variant ++Subtag: mdcegyp ++Description: Ancient Egyptian hieroglyphs encoded in Manuel de Codage ++Added: 2025-02-06 ++Prefix: egy ++%% ++Type: variant ++Subtag: mdctrans ++Description: Ancient Egyptian transliteration encoded in Manuel de ++ Codage ++Added: 2025-02-06 ++Prefix: egy ++%% ++Type: variant + Subtag: metelko + Description: Slovene in Metelko alphabet + Added: 2012-06-27 +@@ -48245,6 +48367,12 @@ Prefix: rm + Comments: Supraregional Romansh written standard + %% + Type: variant ++Subtag: saigon ++Description: The Sài Gòn variant of Vietnamese ++Added: 2025-03-10 ++Prefix: vi ++%% ++Type: variant + Subtag: scotland + Description: Scottish Standard English + Added: 2007-08-31 +diff --git a/make/data/tzdata/VERSION b/make/data/tzdata/VERSION +index b138ed7fa..4bd54efbc 100644 +--- a/make/data/tzdata/VERSION ++++ b/make/data/tzdata/VERSION +@@ -21,4 +21,4 @@ + # or visit www.oracle.com if you need additional information or have any + # questions. + # +-tzdata2024a ++tzdata2025b +diff --git a/make/data/tzdata/africa b/make/data/tzdata/africa +index 72b188f07..8098f4bea 100644 +--- a/make/data/tzdata/africa ++++ b/make/data/tzdata/africa +@@ -126,17 +126,16 @@ Zone Africa/Algiers 0:12:12 - LMT 1891 Mar 16 + + # Cape Verde / Cabo Verde + # +-# From Paul Eggert (2018-02-16): +-# Shanks gives 1907 for the transition to +02. +-# For now, ignore that and follow the 1911-05-26 Portuguese decree +-# (see Europe/Lisbon). ++# From Tim Parenti (2024-07-01), per Paul Eggert (2018-02-16): ++# For timestamps before independence, see commentary for Europe/Lisbon. ++# Shanks gives 1907 instead for the transition to -02. + # + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone Atlantic/Cape_Verde -1:34:04 - LMT 1912 Jan 01 2:00u # Praia +- -2:00 - -02 1942 Sep +- -2:00 1:00 -01 1945 Oct 15 +- -2:00 - -02 1975 Nov 25 2:00 +- -1:00 - -01 ++ -2:00 - %z 1942 Sep ++ -2:00 1:00 %z 1945 Oct 15 ++ -2:00 - %z 1975 Nov 25 2:00 ++ -1:00 - %z + + # Chad + # Zone NAME STDOFF RULES FORMAT [UNTIL] +@@ -368,14 +367,12 @@ Zone Africa/Cairo 2:05:09 - LMT 1900 Oct + + # Guinea-Bissau + # +-# From Paul Eggert (2018-02-16): +-# Shanks gives 1911-05-26 for the transition to WAT, +-# evidently confusing the date of the Portuguese decree +-# (see Europe/Lisbon) with the date that it took effect. ++# From Tim Parenti (2024-07-01), per Paul Eggert (2018-02-16): ++# For timestamps before independence, see commentary for Europe/Lisbon. + # + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone Africa/Bissau -1:02:20 - LMT 1912 Jan 1 1:00u +- -1:00 - -01 1975 ++ -1:00 - %z 1975 + 0:00 - GMT + + # Comoros +@@ -440,10 +437,10 @@ Zone Africa/Bissau -1:02:20 - LMT 1912 Jan 1 1:00u + + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone Africa/Nairobi 2:27:16 - LMT 1908 May +- 2:30 - +0230 1928 Jun 30 24:00 ++ 2:30 - %z 1928 Jun 30 24:00 + 3:00 - EAT 1930 Jan 4 24:00 +- 2:30 - +0230 1936 Dec 31 24:00 +- 2:45 - +0245 1942 Jul 31 24:00 ++ 2:30 - %z 1936 Dec 31 24:00 ++ 2:45 - %z 1942 Jul 31 24:00 + 3:00 - EAT + + # Liberia +@@ -614,7 +611,7 @@ Rule Mauritius 2008 only - Oct lastSun 2:00 1:00 - + Rule Mauritius 2009 only - Mar lastSun 2:00 0 - + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone Indian/Mauritius 3:50:00 - LMT 1907 # Port Louis +- 4:00 Mauritius +04/+05 ++ 4:00 Mauritius %z + # Agalega Is, Rodriguez + # no information; probably like Indian/Mauritius + +@@ -1094,10 +1091,10 @@ Rule Morocco 2087 only - May 11 2:00 0 - + + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone Africa/Casablanca -0:30:20 - LMT 1913 Oct 26 +- 0:00 Morocco +00/+01 1984 Mar 16 +- 1:00 - +01 1986 +- 0:00 Morocco +00/+01 2018 Oct 28 3:00 +- 1:00 Morocco +01/+00 ++ 0:00 Morocco %z 1984 Mar 16 ++ 1:00 - %z 1986 ++ 0:00 Morocco %z 2018 Oct 28 3:00 ++ 1:00 Morocco %z + + # Western Sahara + # +@@ -1111,9 +1108,9 @@ Zone Africa/Casablanca -0:30:20 - LMT 1913 Oct 26 + # since most of it was then controlled by Morocco. + + Zone Africa/El_Aaiun -0:52:48 - LMT 1934 Jan # El Aaiún +- -1:00 - -01 1976 Apr 14 +- 0:00 Morocco +00/+01 2018 Oct 28 3:00 +- 1:00 Morocco +01/+00 ++ -1:00 - %z 1976 Apr 14 ++ 0:00 Morocco %z 2018 Oct 28 3:00 ++ 1:00 Morocco %z + + # Botswana + # Burundi +@@ -1124,13 +1121,27 @@ Zone Africa/El_Aaiun -0:52:48 - LMT 1934 Jan # El Aaiún + # Zambia + # Zimbabwe + # +-# Shanks gives 1903-03-01 for the transition to CAT. +-# Perhaps the 1911-05-26 Portuguese decree +-# https://dre.pt/pdf1sdip/1911/05/12500/23132313.pdf +-# merely made it official? ++# From Tim Parenti (2024-07-01): ++# For timestamps before Mozambique's independence, see commentary for ++# Europe/Lisbon. ++# ++# From Paul Eggert (2024-05-24): ++# The London Gazette, 1903-04-03, page 2245, says that ++# as of 1903-03-03 a time ball at the port of Lourenço Marques ++# (as Maputo was then called) was dropped daily at 13:00:00 LMT, ++# corresponding to 22:49:41.7 GMT, so local time was +02:10:18.3. ++# Conversely, the newspaper South Africa, 1909-02-09, page 321, ++# says the port had just installed an apparatus that communicated ++# "from the controlling clock in the new Observatory at Reuben Point ... ++# exact mean South African time, i.e., 30 deg., or 2 hours East of Greenwich". ++# Although Shanks gives 1903-03-01 for the transition to CAT, ++# evidently the port transitioned to CAT after 1903-03-03 but before ++# the Portuguese legal transition of 1912-01-01 (see Europe/Lisbon commentary). ++# For lack of better info, list 1909 as the transition date. + # + # Zone NAME STDOFF RULES FORMAT [UNTIL] +-Zone Africa/Maputo 2:10:20 - LMT 1903 Mar ++ #STDOFF 2:10:18.3 ++Zone Africa/Maputo 2:10:18 - LMT 1909 + 2:00 - CAT + + # Namibia +@@ -1195,7 +1206,7 @@ Rule Namibia 1995 2017 - Apr Sun>=1 2:00 -1:00 WAT + + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone Africa/Windhoek 1:08:24 - LMT 1892 Feb 8 +- 1:30 - +0130 1903 Mar ++ 1:30 - %z 1903 Mar + 2:00 - SAST 1942 Sep 20 2:00 + 2:00 1:00 SAST 1943 Mar 21 2:00 + 2:00 - SAST 1990 Mar 21 # independence +@@ -1283,7 +1294,7 @@ Zone Africa/Windhoek 1:08:24 - LMT 1892 Feb 8 + Zone Africa/Lagos 0:13:35 - LMT 1905 Jul 1 + 0:00 - GMT 1908 Jul 1 + 0:13:35 - LMT 1914 Jan 1 +- 0:30 - +0030 1919 Sep 1 ++ 0:30 - %z 1919 Sep 1 + 1:00 - WAT + + # São Tomé and Príncipe +diff --git a/make/data/tzdata/antarctica b/make/data/tzdata/antarctica +index fc7176cd0..87787d31c 100644 +--- a/make/data/tzdata/antarctica ++++ b/make/data/tzdata/antarctica +@@ -110,34 +110,34 @@ + + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone Antarctica/Casey 0 - -00 1969 +- 8:00 - +08 2009 Oct 18 2:00 +- 11:00 - +11 2010 Mar 5 2:00 +- 8:00 - +08 2011 Oct 28 2:00 +- 11:00 - +11 2012 Feb 21 17:00u +- 8:00 - +08 2016 Oct 22 +- 11:00 - +11 2018 Mar 11 4:00 +- 8:00 - +08 2018 Oct 7 4:00 +- 11:00 - +11 2019 Mar 17 3:00 +- 8:00 - +08 2019 Oct 4 3:00 +- 11:00 - +11 2020 Mar 8 3:00 +- 8:00 - +08 2020 Oct 4 0:01 +- 11:00 - +11 2021 Mar 14 0:00 +- 8:00 - +08 2021 Oct 3 0:01 +- 11:00 - +11 2022 Mar 13 0:00 +- 8:00 - +08 2022 Oct 2 0:01 +- 11:00 - +11 2023 Mar 9 3:00 +- 8:00 - +08 ++ 8:00 - %z 2009 Oct 18 2:00 ++ 11:00 - %z 2010 Mar 5 2:00 ++ 8:00 - %z 2011 Oct 28 2:00 ++ 11:00 - %z 2012 Feb 21 17:00u ++ 8:00 - %z 2016 Oct 22 ++ 11:00 - %z 2018 Mar 11 4:00 ++ 8:00 - %z 2018 Oct 7 4:00 ++ 11:00 - %z 2019 Mar 17 3:00 ++ 8:00 - %z 2019 Oct 4 3:00 ++ 11:00 - %z 2020 Mar 8 3:00 ++ 8:00 - %z 2020 Oct 4 0:01 ++ 11:00 - %z 2021 Mar 14 0:00 ++ 8:00 - %z 2021 Oct 3 0:01 ++ 11:00 - %z 2022 Mar 13 0:00 ++ 8:00 - %z 2022 Oct 2 0:01 ++ 11:00 - %z 2023 Mar 9 3:00 ++ 8:00 - %z + Zone Antarctica/Davis 0 - -00 1957 Jan 13 +- 7:00 - +07 1964 Nov ++ 7:00 - %z 1964 Nov + 0 - -00 1969 Feb +- 7:00 - +07 2009 Oct 18 2:00 +- 5:00 - +05 2010 Mar 10 20:00u +- 7:00 - +07 2011 Oct 28 2:00 +- 5:00 - +05 2012 Feb 21 20:00u +- 7:00 - +07 ++ 7:00 - %z 2009 Oct 18 2:00 ++ 5:00 - %z 2010 Mar 10 20:00u ++ 7:00 - %z 2011 Oct 28 2:00 ++ 5:00 - %z 2012 Feb 21 20:00u ++ 7:00 - %z + Zone Antarctica/Mawson 0 - -00 1954 Feb 13 +- 6:00 - +06 2009 Oct 18 2:00 +- 5:00 - +05 ++ 6:00 - %z 2009 Oct 18 2:00 ++ 5:00 - %z + # References: + # Casey Weather (1998-02-26) + # http://www.antdiv.gov.au/aad/exop/sfo/casey/casey_aws.html +@@ -197,6 +197,8 @@ Zone Antarctica/Mawson 0 - -00 1954 Feb 13 + + # France & Italy - year-round base + # Concordia, -750600+1232000, since 2005 ++# https://en.wikipedia.org/wiki/Concordia_Station ++# Can use Asia/Singapore, which it has agreed with since inception. + + # Germany - year-round base + # Neumayer III, -704080-0081602, since 2009 +@@ -313,10 +315,10 @@ Zone Antarctica/Troll 0 - -00 2005 Feb 12 + + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone Antarctica/Vostok 0 - -00 1957 Dec 16 +- 7:00 - +07 1994 Feb ++ 7:00 - %z 1994 Feb + 0 - -00 1994 Nov +- 7:00 - +07 2023 Dec 18 2:00 +- 5:00 - +05 ++ 7:00 - %z 2023 Dec 18 2:00 ++ 5:00 - %z + + # S Africa - year-round bases + # Marion Island, -4653+03752 +@@ -349,7 +351,7 @@ Zone Antarctica/Vostok 0 - -00 1957 Dec 16 + # + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone Antarctica/Rothera 0 - -00 1976 Dec 1 +- -3:00 - -03 ++ -3:00 - %z + + # Uruguay - year round base + # Artigas, King George Island, -621104-0585107 +diff --git a/make/data/tzdata/asia b/make/data/tzdata/asia +index 3a5429191..55b13134f 100644 +--- a/make/data/tzdata/asia ++++ b/make/data/tzdata/asia +@@ -106,8 +106,8 @@ Rule RussiaAsia 1996 2010 - Oct lastSun 2:00s 0 - + # Afghanistan + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone Asia/Kabul 4:36:48 - LMT 1890 +- 4:00 - +04 1945 +- 4:30 - +0430 ++ 4:00 - %z 1945 ++ 4:30 - %z + + # Armenia + # From Paul Eggert (2006-03-22): +@@ -139,12 +139,12 @@ Rule Armenia 2011 only - Mar lastSun 2:00s 1:00 - + Rule Armenia 2011 only - Oct lastSun 2:00s 0 - + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone Asia/Yerevan 2:58:00 - LMT 1924 May 2 +- 3:00 - +03 1957 Mar +- 4:00 RussiaAsia +04/+05 1991 Mar 31 2:00s +- 3:00 RussiaAsia +03/+04 1995 Sep 24 2:00s +- 4:00 - +04 1997 +- 4:00 RussiaAsia +04/+05 2011 +- 4:00 Armenia +04/+05 ++ 3:00 - %z 1957 Mar ++ 4:00 RussiaAsia %z 1991 Mar 31 2:00s ++ 3:00 RussiaAsia %z 1995 Sep 24 2:00s ++ 4:00 - %z 1997 ++ 4:00 RussiaAsia %z 2011 ++ 4:00 Armenia %z + + # Azerbaijan + +@@ -165,12 +165,12 @@ Rule Azer 1997 2015 - Mar lastSun 4:00 1:00 - + Rule Azer 1997 2015 - Oct lastSun 5:00 0 - + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone Asia/Baku 3:19:24 - LMT 1924 May 2 +- 3:00 - +03 1957 Mar +- 4:00 RussiaAsia +04/+05 1991 Mar 31 2:00s +- 3:00 RussiaAsia +03/+04 1992 Sep lastSun 2:00s +- 4:00 - +04 1996 +- 4:00 EUAsia +04/+05 1997 +- 4:00 Azer +04/+05 ++ 3:00 - %z 1957 Mar ++ 4:00 RussiaAsia %z 1991 Mar 31 2:00s ++ 3:00 RussiaAsia %z 1992 Sep lastSun 2:00s ++ 4:00 - %z 1996 ++ 4:00 EUAsia %z 1997 ++ 4:00 Azer %z + + # Bangladesh + # From Alexander Krivenyshev (2009-05-13): +@@ -251,17 +251,17 @@ Rule Dhaka 2009 only - Dec 31 24:00 0 - + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone Asia/Dhaka 6:01:40 - LMT 1890 + 5:53:20 - HMT 1941 Oct # Howrah Mean Time? +- 6:30 - +0630 1942 May 15 +- 5:30 - +0530 1942 Sep +- 6:30 - +0630 1951 Sep 30 +- 6:00 - +06 2009 +- 6:00 Dhaka +06/+07 ++ 6:30 - %z 1942 May 15 ++ 5:30 - %z 1942 Sep ++ 6:30 - %z 1951 Sep 30 ++ 6:00 - %z 2009 ++ 6:00 Dhaka %z + + # Bhutan + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone Asia/Thimphu 5:58:36 - LMT 1947 Aug 15 # or Thimbu +- 5:30 - +0530 1987 Oct +- 6:00 - +06 ++ 5:30 - %z 1987 Oct ++ 6:00 - %z + + # British Indian Ocean Territory + # Whitman and the 1995 CIA time zone map say 5:00, but the +@@ -271,8 +271,8 @@ Zone Asia/Thimphu 5:58:36 - LMT 1947 Aug 15 # or Thimbu + # then contained the Chagos Archipelago). + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone Indian/Chagos 4:49:40 - LMT 1907 +- 5:00 - +05 1996 +- 6:00 - +06 ++ 5:00 - %z 1996 ++ 6:00 - %z + + # Cocos (Keeling) Islands + # Myanmar (Burma) +@@ -288,9 +288,9 @@ Zone Indian/Chagos 4:49:40 - LMT 1907 + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone Asia/Yangon 6:24:47 - LMT 1880 # or Rangoon + 6:24:47 - RMT 1920 # Rangoon local time +- 6:30 - +0630 1942 May +- 9:00 - +09 1945 May 3 +- 6:30 - +0630 ++ 6:30 - %z 1942 May ++ 9:00 - %z 1945 May 3 ++ 6:30 - %z + + # China + +@@ -679,7 +679,7 @@ Zone Asia/Shanghai 8:05:43 - LMT 1901 + # Xinjiang time, used by many in western China; represented by Ürümqi / Ürümchi + # / Wulumuqi. (Please use Asia/Shanghai if you prefer Beijing time.) + Zone Asia/Urumqi 5:50:20 - LMT 1928 +- 6:00 - +06 ++ 6:00 - %z + + # Hong Kong + +@@ -1137,7 +1137,7 @@ Rule Macau 1979 only - Oct Sun>=16 03:30 0 S + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone Asia/Macau 7:34:10 - LMT 1904 Oct 30 + 8:00 - CST 1941 Dec 21 23:00 +- 9:00 Macau +09/+10 1945 Sep 30 24:00 ++ 9:00 Macau %z 1945 Sep 30 24:00 + 8:00 Macau C%sT + + +@@ -1180,7 +1180,7 @@ Zone Asia/Nicosia 2:13:28 - LMT 1921 Nov 14 + Zone Asia/Famagusta 2:15:48 - LMT 1921 Nov 14 + 2:00 Cyprus EE%sT 1998 Sep + 2:00 EUAsia EE%sT 2016 Sep 8 +- 3:00 - +03 2017 Oct 29 1:00u ++ 3:00 - %z 2017 Oct 29 1:00u + 2:00 EUAsia EE%sT + + # Georgia +@@ -1221,18 +1221,25 @@ Zone Asia/Famagusta 2:15:48 - LMT 1921 Nov 14 + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone Asia/Tbilisi 2:59:11 - LMT 1880 + 2:59:11 - TBMT 1924 May 2 # Tbilisi Mean Time +- 3:00 - +03 1957 Mar +- 4:00 RussiaAsia +04/+05 1991 Mar 31 2:00s +- 3:00 RussiaAsia +03/+04 1992 +- 3:00 E-EurAsia +03/+04 1994 Sep lastSun +- 4:00 E-EurAsia +04/+05 1996 Oct lastSun +- 4:00 1:00 +05 1997 Mar lastSun +- 4:00 E-EurAsia +04/+05 2004 Jun 27 +- 3:00 RussiaAsia +03/+04 2005 Mar lastSun 2:00 +- 4:00 - +04 ++ 3:00 - %z 1957 Mar ++ 4:00 RussiaAsia %z 1991 Mar 31 2:00s ++ 3:00 RussiaAsia %z 1992 ++ 3:00 E-EurAsia %z 1994 Sep lastSun ++ 4:00 E-EurAsia %z 1996 Oct lastSun ++ 4:00 1:00 %z 1997 Mar lastSun ++ 4:00 E-EurAsia %z 2004 Jun 27 ++ 3:00 RussiaAsia %z 2005 Mar lastSun 2:00 ++ 4:00 - %z + + # East Timor + ++# From Tim Parenti (2024-07-01): ++# The 1912-01-01 transition occurred at 00:00 new time, per the 1911-05-24 ++# Portuguese decree (see Europe/Lisbon). A provision in article 5(c) of the ++# decree prescribed that Timor "will keep counting time in harmony with ++# neighboring foreign colonies, [for] as long as they do not adopt the time ++# that belongs to them in [the Washington Convention] system." ++ + # See Indonesia for the 1945 transition. + + # From João Carrascalão, brother of the former governor of East Timor, in +@@ -1256,11 +1263,11 @@ Zone Asia/Tbilisi 2:59:11 - LMT 1880 + # midnight on Saturday, September 16. + + # Zone NAME STDOFF RULES FORMAT [UNTIL] +-Zone Asia/Dili 8:22:20 - LMT 1912 Jan 1 +- 8:00 - +08 1942 Feb 21 23:00 +- 9:00 - +09 1976 May 3 +- 8:00 - +08 2000 Sep 17 0:00 +- 9:00 - +09 ++Zone Asia/Dili 8:22:20 - LMT 1911 Dec 31 16:00u ++ 8:00 - %z 1942 Feb 21 23:00 ++ 9:00 - %z 1976 May 3 ++ 8:00 - %z 2000 Sep 17 0:00 ++ 9:00 - %z + + # India + +@@ -1326,9 +1333,9 @@ Zone Asia/Kolkata 5:53:28 - LMT 1854 Jun 28 # Kolkata + 5:53:20 - HMT 1870 # Howrah Mean Time? + 5:21:10 - MMT 1906 Jan 1 # Madras local time + 5:30 - IST 1941 Oct +- 5:30 1:00 +0630 1942 May 15 ++ 5:30 1:00 %z 1942 May 15 + 5:30 - IST 1942 Sep +- 5:30 1:00 +0630 1945 Oct 15 ++ 5:30 1:00 %z 1945 Oct 15 + 5:30 - IST + # Since 1970 the following are like Asia/Kolkata: + # Andaman Is +@@ -1380,33 +1387,33 @@ 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 16:40u # Batavia +- 7:20 - +0720 1932 Nov +- 7:30 - +0730 1942 Mar 23 +- 9:00 - +09 1945 Sep 23 +- 7:30 - +0730 1948 May +- 8:00 - +08 1950 May +- 7:30 - +0730 1964 ++ 7:20 - %z 1932 Nov ++ 7:30 - %z 1942 Mar 23 ++ 9:00 - %z 1945 Sep 23 ++ 7:30 - %z 1948 May ++ 8:00 - %z 1950 May ++ 7:30 - %z 1964 + 7:00 - WIB + # west and central Borneo + Zone Asia/Pontianak 7:17:20 - LMT 1908 May + 7:17:20 - PMT 1932 Nov # Pontianak MT +- 7:30 - +0730 1942 Jan 29 +- 9:00 - +09 1945 Sep 23 +- 7:30 - +0730 1948 May +- 8:00 - +08 1950 May +- 7:30 - +0730 1964 ++ 7:30 - %z 1942 Jan 29 ++ 9:00 - %z 1945 Sep 23 ++ 7:30 - %z 1948 May ++ 8:00 - %z 1950 May ++ 7:30 - %z 1964 + 8:00 - WITA 1988 Jan 1 + 7:00 - WIB + # Sulawesi, Lesser Sundas, east and south Borneo + Zone Asia/Makassar 7:57:36 - LMT 1920 + 7:57:36 - MMT 1932 Nov # Macassar MT +- 8:00 - +08 1942 Feb 9 +- 9:00 - +09 1945 Sep 23 ++ 8:00 - %z 1942 Feb 9 ++ 9:00 - %z 1945 Sep 23 + 8:00 - WITA + # Maluku Islands, West Papua, Papua + Zone Asia/Jayapura 9:22:48 - LMT 1932 Nov +- 9:00 - +09 1944 Sep 1 +- 9:30 - +0930 1964 ++ 9:00 - %z 1944 Sep 1 ++ 9:30 - %z 1964 + 9:00 - WIT + + # Iran +@@ -1516,6 +1523,16 @@ Zone Asia/Jayapura 9:22:48 - LMT 1932 Nov + # (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 (2025-03-18): ++# ... the exact time of Iran's transition from +0400 to +0330 ... was Friday ++# 1357/8/19 AP=1978-11-10. Here's a newspaper clip from the Ettela'at ++# newspaper, dated 1357/8/14 AP=1978-11-05, translated from Persian ++# (at https://w.wiki/DUEY): ++# Following the government's decision about returning the official time ++# to the previous status, the spokesperson for the Ministry of Energy ++# announced today: At the hour 24 of Friday 19th of Aban (=1978-11-10), ++# the country's time will be pulled back half an hour. ++# + # 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: +@@ -1642,9 +1659,9 @@ 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 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 ++ 3:30 Iran %z 1977 Oct 20 24:00 ++ 4:00 Iran %z 1978 Nov 10 24:00 ++ 3:30 Iran %z + + + # Iraq +@@ -1687,8 +1704,8 @@ Rule Iraq 1991 2007 - Oct 1 3:00s 0 - + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone Asia/Baghdad 2:57:40 - LMT 1890 + 2:57:36 - BMT 1918 # Baghdad Mean Time? +- 3:00 - +03 1982 May +- 3:00 Iraq +03/+04 ++ 3:00 - %z 1982 May ++ 3:00 Iraq %z + + + ############################################################################### +@@ -2285,7 +2302,7 @@ Rule Jordan 2022 only - Feb lastThu 24:00 1:00 S + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone Asia/Amman 2:23:44 - LMT 1931 + 2:00 Jordan EE%sT 2022 Oct 28 0:00s +- 3:00 - +03 ++ 3:00 - %z + + + # Kazakhstan +@@ -2496,88 +2513,88 @@ Zone Asia/Amman 2:23:44 - LMT 1931 + # Almaty (formerly Alma-Ata), representing most locations in Kazakhstan + # This includes Abai/Abay (ISO 3166-2 code KZ-10), Aqmola/Akmola (KZ-11), + # Almaty (KZ-19), Almaty city (KZ-75), Astana city (KZ-71), +-# East Kazkhstan (KZ-63), Jambyl/Zhambyl (KZ-31), Jetisu/Zhetysu (KZ-33), ++# East Kazakhstan (KZ-63), Jambyl/Zhambyl (KZ-31), Jetisu/Zhetysu (KZ-33), + # Karaganda (KZ-35), North Kazakhstan (KZ-59), Pavlodar (KZ-55), +-# Shyumkent city (KZ-79), Turkistan (KZ-61), and Ulytau (KZ-62). ++# Shymkent city (KZ-79), Turkistan (KZ-61), and Ulytau (KZ-62). + Zone Asia/Almaty 5:07:48 - LMT 1924 May 2 # or Alma-Ata +- 5:00 - +05 1930 Jun 21 +- 6:00 RussiaAsia +06/+07 1991 Mar 31 2:00s +- 5:00 RussiaAsia +05/+06 1992 Jan 19 2:00s +- 6:00 RussiaAsia +06/+07 2004 Oct 31 2:00s +- 6:00 - +06 2024 Mar 1 0:00 +- 5:00 - +05 ++ 5:00 - %z 1930 Jun 21 ++ 6:00 RussiaAsia %z 1991 Mar 31 2:00s ++ 5:00 RussiaAsia %z 1992 Jan 19 2:00s ++ 6:00 RussiaAsia %z 2004 Oct 31 2:00s ++ 6:00 - %z 2024 Mar 1 0:00 ++ 5:00 - %z + # Qyzylorda (aka Kyzylorda, Kizilorda, Kzyl-Orda, etc.) (KZ-43) + Zone Asia/Qyzylorda 4:21:52 - LMT 1924 May 2 +- 4:00 - +04 1930 Jun 21 +- 5:00 - +05 1981 Apr 1 +- 5:00 1:00 +06 1981 Oct 1 +- 6:00 - +06 1982 Apr 1 +- 5:00 RussiaAsia +05/+06 1991 Mar 31 2:00s +- 4:00 RussiaAsia +04/+05 1991 Sep 29 2:00s +- 5:00 RussiaAsia +05/+06 1992 Jan 19 2:00s +- 6:00 RussiaAsia +06/+07 1992 Mar 29 2:00s +- 5:00 RussiaAsia +05/+06 2004 Oct 31 2:00s +- 6:00 - +06 2018 Dec 21 0:00 +- 5:00 - +05 ++ 4:00 - %z 1930 Jun 21 ++ 5:00 - %z 1981 Apr 1 ++ 5:00 1:00 %z 1981 Oct 1 ++ 6:00 - %z 1982 Apr 1 ++ 5:00 RussiaAsia %z 1991 Mar 31 2:00s ++ 4:00 RussiaAsia %z 1991 Sep 29 2:00s ++ 5:00 RussiaAsia %z 1992 Jan 19 2:00s ++ 6:00 RussiaAsia %z 1992 Mar 29 2:00s ++ 5:00 RussiaAsia %z 2004 Oct 31 2:00s ++ 6:00 - %z 2018 Dec 21 0:00 ++ 5:00 - %z + # Qostanay (aka Kostanay, Kustanay) (KZ-39) + # The 1991/2 rules are unclear partly because of the 1997 Turgai + # reorganization. + Zone Asia/Qostanay 4:14:28 - LMT 1924 May 2 +- 4:00 - +04 1930 Jun 21 +- 5:00 - +05 1981 Apr 1 +- 5:00 1:00 +06 1981 Oct 1 +- 6:00 - +06 1982 Apr 1 +- 5:00 RussiaAsia +05/+06 1991 Mar 31 2:00s +- 4:00 RussiaAsia +04/+05 1992 Jan 19 2:00s +- 5:00 RussiaAsia +05/+06 2004 Oct 31 2:00s +- 6:00 - +06 2024 Mar 1 0:00 +- 5:00 - +05 ++ 4:00 - %z 1930 Jun 21 ++ 5:00 - %z 1981 Apr 1 ++ 5:00 1:00 %z 1981 Oct 1 ++ 6:00 - %z 1982 Apr 1 ++ 5:00 RussiaAsia %z 1991 Mar 31 2:00s ++ 4:00 RussiaAsia %z 1992 Jan 19 2:00s ++ 5:00 RussiaAsia %z 2004 Oct 31 2:00s ++ 6:00 - %z 2024 Mar 1 0:00 ++ 5:00 - %z + # Aqtöbe (aka Aktobe, formerly Aktyubinsk) (KZ-15) + Zone Asia/Aqtobe 3:48:40 - LMT 1924 May 2 +- 4:00 - +04 1930 Jun 21 +- 5:00 - +05 1981 Apr 1 +- 5:00 1:00 +06 1981 Oct 1 +- 6:00 - +06 1982 Apr 1 +- 5:00 RussiaAsia +05/+06 1991 Mar 31 2:00s +- 4:00 RussiaAsia +04/+05 1992 Jan 19 2:00s +- 5:00 RussiaAsia +05/+06 2004 Oct 31 2:00s +- 5:00 - +05 ++ 4:00 - %z 1930 Jun 21 ++ 5:00 - %z 1981 Apr 1 ++ 5:00 1:00 %z 1981 Oct 1 ++ 6:00 - %z 1982 Apr 1 ++ 5:00 RussiaAsia %z 1991 Mar 31 2:00s ++ 4:00 RussiaAsia %z 1992 Jan 19 2:00s ++ 5:00 RussiaAsia %z 2004 Oct 31 2:00s ++ 5:00 - %z + # Mangghystaū (KZ-47) + # Aqtau was not founded until 1963, but it represents an inhabited region, + # so include timestamps before 1963. + Zone Asia/Aqtau 3:21:04 - LMT 1924 May 2 +- 4:00 - +04 1930 Jun 21 +- 5:00 - +05 1981 Oct 1 +- 6:00 - +06 1982 Apr 1 +- 5:00 RussiaAsia +05/+06 1991 Mar 31 2:00s +- 4:00 RussiaAsia +04/+05 1992 Jan 19 2:00s +- 5:00 RussiaAsia +05/+06 1994 Sep 25 2:00s +- 4:00 RussiaAsia +04/+05 2004 Oct 31 2:00s +- 5:00 - +05 ++ 4:00 - %z 1930 Jun 21 ++ 5:00 - %z 1981 Oct 1 ++ 6:00 - %z 1982 Apr 1 ++ 5:00 RussiaAsia %z 1991 Mar 31 2:00s ++ 4:00 RussiaAsia %z 1992 Jan 19 2:00s ++ 5:00 RussiaAsia %z 1994 Sep 25 2:00s ++ 4:00 RussiaAsia %z 2004 Oct 31 2:00s ++ 5:00 - %z + # Atyraū (KZ-23) is like Mangghystaū except it switched from + # +04/+05 to +05/+06 in spring 1999, not fall 1994. + Zone Asia/Atyrau 3:27:44 - LMT 1924 May 2 +- 3:00 - +03 1930 Jun 21 +- 5:00 - +05 1981 Oct 1 +- 6:00 - +06 1982 Apr 1 +- 5:00 RussiaAsia +05/+06 1991 Mar 31 2:00s +- 4:00 RussiaAsia +04/+05 1992 Jan 19 2:00s +- 5:00 RussiaAsia +05/+06 1999 Mar 28 2:00s +- 4:00 RussiaAsia +04/+05 2004 Oct 31 2:00s +- 5:00 - +05 ++ 3:00 - %z 1930 Jun 21 ++ 5:00 - %z 1981 Oct 1 ++ 6:00 - %z 1982 Apr 1 ++ 5:00 RussiaAsia %z 1991 Mar 31 2:00s ++ 4:00 RussiaAsia %z 1992 Jan 19 2:00s ++ 5:00 RussiaAsia %z 1999 Mar 28 2:00s ++ 4:00 RussiaAsia %z 2004 Oct 31 2:00s ++ 5:00 - %z + # West Kazakhstan (KZ-27) + # From Paul Eggert (2016-03-18): + # The 1989 transition is from USSR act No. 227 (1989-03-14). + Zone Asia/Oral 3:25:24 - LMT 1924 May 2 # or Ural'sk +- 3:00 - +03 1930 Jun 21 +- 5:00 - +05 1981 Apr 1 +- 5:00 1:00 +06 1981 Oct 1 +- 6:00 - +06 1982 Apr 1 +- 5:00 RussiaAsia +05/+06 1989 Mar 26 2:00s +- 4:00 RussiaAsia +04/+05 1992 Jan 19 2:00s +- 5:00 RussiaAsia +05/+06 1992 Mar 29 2:00s +- 4:00 RussiaAsia +04/+05 2004 Oct 31 2:00s +- 5:00 - +05 ++ 3:00 - %z 1930 Jun 21 ++ 5:00 - %z 1981 Apr 1 ++ 5:00 1:00 %z 1981 Oct 1 ++ 6:00 - %z 1982 Apr 1 ++ 5:00 RussiaAsia %z 1989 Mar 26 2:00s ++ 4:00 RussiaAsia %z 1992 Jan 19 2:00s ++ 5:00 RussiaAsia %z 1992 Mar 29 2:00s ++ 4:00 RussiaAsia %z 2004 Oct 31 2:00s ++ 5:00 - %z + + # Kyrgyzstan (Kirgizstan) + # Transitions through 1991 are from Shanks & Pottenger. +@@ -2598,11 +2615,11 @@ Rule Kyrgyz 1997 2005 - Mar lastSun 2:30 1:00 - + Rule Kyrgyz 1997 2004 - Oct lastSun 2:30 0 - + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone Asia/Bishkek 4:58:24 - LMT 1924 May 2 +- 5:00 - +05 1930 Jun 21 +- 6:00 RussiaAsia +06/+07 1991 Mar 31 2:00s +- 5:00 RussiaAsia +05/+06 1991 Aug 31 2:00 +- 5:00 Kyrgyz +05/+06 2005 Aug 12 +- 6:00 - +06 ++ 5:00 - %z 1930 Jun 21 ++ 6:00 RussiaAsia %z 1991 Mar 31 2:00s ++ 5:00 RussiaAsia %z 1991 Aug 31 2:00 ++ 5:00 Kyrgyz %z 2005 Aug 12 ++ 6:00 - %z + + ############################################################################### + +@@ -2809,16 +2826,16 @@ Rule NBorneo 1935 1941 - Dec 14 0:00 0 - + # and 1982 transition dates are from Mok Ly Yng. + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone Asia/Kuching 7:21:20 - LMT 1926 Mar +- 7:30 - +0730 1933 +- 8:00 NBorneo +08/+0820 1942 Feb 16 +- 9:00 - +09 1945 Sep 12 +- 8:00 - +08 ++ 7:30 - %z 1933 ++ 8:00 NBorneo %z 1942 Feb 16 ++ 9:00 - %z 1945 Sep 12 ++ 8:00 - %z + + # 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 ++ 5:00 - %z + + # Mongolia + +@@ -2920,9 +2937,37 @@ Zone Indian/Maldives 4:54:00 - LMT 1880 # Malé + + # From Arthur David Olson (2008-05-19): + # Assume that Choibalsan is indeed offset by 8:00. +-# XXX--in the absence of better information, assume that transition +-# was at the start of 2008-03-31 (the day of Steffen Thorsen's report); +-# this is almost surely wrong. ++ ++# From Heitor David Pinto (2024-06-23): ++# Sources about time zones in Mongolia seem to list one of two conflicting ++# configurations. The first configuration, mentioned in a comment to the TZ ++# database in 1999, citing a Mongolian government website, lists the provinces ++# of Bayan-Ölgii, Khovd and Uvs in UTC+7, and the rest of the country in ++# UTC+8. The second configuration, mentioned in a comment to the database in ++# 2001, lists Bayan-Ölgii, Khovd, Uvs, Govi-Altai and Zavkhan in UTC+7, Dornod ++# and Sükhbaatar in UTC+9, and the rest of the country in UTC+8. ++# ++# The first configuration is still mentioned by several Mongolian travel ++# agencies: ++# https://www.adventurerider.mn/en/page/about_mongolia ++# http://www.naturetours.mn/nt/mongolia.php ++# https://www.newjuulchin.mn/web/content/7506?unique=fa24a0f6e96e022a3578ee5195ac879638c734ce ++# ++# It also matches these flight schedules in 2013: ++# http://web.archive.org/web/20130722023600/https://www.hunnuair.com/en/timetabled ++# The flight times imply that the airports of Uliastai (Zavkhan), Choibalsan ++# (Dornod) and Altai (Govi-Altai) are in the same time zone as Ulaanbaatar, ++# and Khovd is one hour behind.... ++# ++# The second configuration was mentioned by an official of the Mongolian ++# standards agency in an interview in 2014: https://ikon.mn/n/9v6 ++# And it's still listed by the Mongolian aviation agency: ++# https://ais.mn/files/aip/eAIP/2023-12-25/html/eSUP/ZM-eSUP-23-04-en-MN.html ++# ++# ... I believe that the first configuration is what is actually observed in ++# Mongolia and has been so all along, at least since 1999. The second ++# configuration closely matches the ideal time zone boundaries at 97.5° E and ++# 112.5° E but it doesn't seem to be used in practice. + + # From Ganbold Tsagaankhuu (2015-03-10): + # It seems like yesterday Mongolian Government meeting has concluded to use +@@ -2961,25 +3006,18 @@ Rule Mongol 2015 2016 - Sep lastSat 0:00 0 - + # Zone NAME STDOFF RULES FORMAT [UNTIL] + # Hovd, a.k.a. Chovd, Dund-Us, Dzhargalant, Khovd, Jirgalanta + Zone Asia/Hovd 6:06:36 - LMT 1905 Aug +- 6:00 - +06 1978 +- 7:00 Mongol +07/+08 ++ 6:00 - %z 1978 ++ 7:00 Mongol %z + # Ulaanbaatar, a.k.a. Ulan Bataar, Ulan Bator, Urga + Zone Asia/Ulaanbaatar 7:07:32 - LMT 1905 Aug +- 7:00 - +07 1978 +- 8:00 Mongol +08/+09 +-# Choibalsan, a.k.a. Bajan Tümen, Bajan Tumen, Chojbalsan, +-# Choybalsan, Sanbejse, Tchoibalsan +-Zone Asia/Choibalsan 7:38:00 - LMT 1905 Aug +- 7:00 - +07 1978 +- 8:00 - +08 1983 Apr +- 9:00 Mongol +09/+10 2008 Mar 31 +- 8:00 Mongol +08/+09 ++ 7:00 - %z 1978 ++ 8:00 Mongol %z + + # Nepal + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone Asia/Kathmandu 5:41:16 - LMT 1920 +- 5:30 - +0530 1986 +- 5:45 - +0545 ++ 5:30 - %z 1986 ++ 5:45 - %z + + # Pakistan + +@@ -3125,10 +3163,10 @@ Rule Pakistan 2009 only - Apr 15 0:00 1:00 S + + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone Asia/Karachi 4:28:12 - LMT 1907 +- 5:30 - +0530 1942 Sep +- 5:30 1:00 +0630 1945 Oct 15 +- 5:30 - +0530 1951 Sep 30 +- 5:00 - +05 1971 Mar 26 ++ 5:30 - %z 1942 Sep ++ 5:30 1:00 %z 1945 Oct 15 ++ 5:30 - %z 1951 Sep 30 ++ 5:00 - %z 1971 Mar 26 + 5:00 Pakistan PK%sT # Pakistan Time + + # Palestine +@@ -3660,30 +3698,79 @@ Zone Asia/Hebron 2:20:23 - LMT 1900 Oct + # be immediately followed by 1845-01-01; see R.H. van Gent's + # History of the International Date Line + # https://webspace.science.uu.nl/~gent0113/idl/idl_philippines.htm +-# The rest of the data entries are from Shanks & Pottenger. +- +-# From Jesper Nørgaard Welen (2006-04-26): +-# ... claims that Philippines had DST last time in 1990: +-# http://story.philippinetimes.com/p.x/ct/9/id/145be20cc6b121c0/cid/3e5bbccc730d258c/ +-# [a story dated 2006-04-25 by Cris Larano of Dow Jones Newswires, +-# but no details] +- +-# From Paul Eggert (2014-08-14): +-# The following source says DST may be instituted November-January and again +-# March-June, but this is not definite. It also says DST was last proclaimed +-# during the Ramos administration (1992-1998); but again, no details. +-# Carcamo D. PNoy urged to declare use of daylight saving time. +-# Philippine Star 2014-08-05 +-# http://www.philstar.com/headlines/2014/08/05/1354152/pnoy-urged-declare-use-daylight-saving-time +- +-# From Paul Goyette (2018-06-15): ++ ++# From P Chan (2021-05-10): ++# Here's a fairly comprehensive article in Japanese: ++# https://wiki.suikawiki.org/n/Philippine%20Time ++# (2021-05-16): ++# According to the references listed in the article, ++# the periods that the Philippines (Manila) observed DST or used +9 are: ++# ++# 1936-10-31 24:00 to 1937-01-15 24:00 ++# (Proclamation No. 104, Proclamation No. 126) ++# 1941-12-15 24:00 to 1945-11-30 24:00 ++# (Proclamation No. 789, Proclamation No. 20) ++# 1954-04-11 24:00 to 1954-06-04 24:00 ++# (Proclamation No. 13, Proclamation No. 33) ++# 1977-03-27 24:00 to 1977-09-21 24:00 ++# (Proclamation No. 1629, Proclamation No. 1641) ++# 1990-05-21 00:00 to 1990-07-28 24:00 ++# (National Emergency Memorandum Order No. 17, Executive Order No. 415) ++# ++# Proclamation No. 104 ... October 30, 1936 ++# https://www.officialgazette.gov.ph/1936/10/30/proclamation-no-104-s-1936/ ++# Proclamation No. 126 ... January 15, 1937 ++# https://www.officialgazette.gov.ph/1937/01/15/proclamation-no-126-s-1937/ ++# Proclamation No. 789 ... December 13, 1941 ++# https://www.officialgazette.gov.ph/1941/12/13/proclamation-no-789-s-1941/ ++# Proclamation No. 20 ... November 11, 1945 ++# https://www.officialgazette.gov.ph/1945/11/11/proclamation-no-20-s-1945/ ++# Proclamation No. 13 ... April 6, 1954 ++# https://www.officialgazette.gov.ph/1954/04/06/proclamation-no-13-s-1954/ ++# Proclamation No. 33 ... June 3, 1954 ++# https://www.officialgazette.gov.ph/1954/06/03/proclamation-no-33-s-1954/ ++# Proclamation No. 1629 ... March 25, 1977 ++# https://www.officialgazette.gov.ph/1977/03/25/proclamation-no-1629-s-1977/ ++# Proclamation No. 1641 ...May 26, 1977 ++# https://www.officialgazette.gov.ph/1977/05/26/proclamation-no-1641-s-1977/ ++# National Emergency Memorandum Order No. 17 ... May 2, 1990 ++# https://www.officialgazette.gov.ph/1990/05/02/national-emergency-memorandum-order-no-17-s-1990/ ++# Executive Order No. 415 ... July 20, 1990 ++# https://www.officialgazette.gov.ph/1990/07/20/executive-order-no-415-s-1990/ ++# ++# During WWII, Proclamation No. 789 fixed two periods of DST. The first period ++# was set to continue only until January 31, 1942. But Manila was occupied by ++# the Japanese earlier in the month.... ++# ++# For the date of the adoption of standard time, Shank[s] gives 1899-05-11. ++# The article is not able to state the basis of that. I guess it was based on ++# a US War Department Circular issued on that date. ++# https://books.google.com/books?id=JZ1PAAAAYAAJ&pg=RA3-PA8 ++# ++# However, according to other sources, standard time was adopted on ++# 1899-09-06. Also, the LMT was GMT+8:03:52 ++# https://books.google.com/books?id=MOYIAQAAIAAJ&pg=PA521 ++# https://books.google.com/books?id=lSnqqatpYikC&pg=PA21 ++# ++# From Paul Eggert (2024-09-05): ++# The penultimate URL in P Chan's email refers to page 521 of ++# Selga M, The Time Service in the Philippines. ++# Proc Pan-Pacific Science Congress. Vol. 1 (1923), 519-532. ++# It says, "The change from the meridian 120° 58' 04" to the 120th implied a ++# change of 3 min. 52s.26 in time; consequently on 6th September, 1899, ++# Manila Observatory gave the noon signal 3 min. 52s.26 later than before". ++# ++# Wikipedia says the US declared Manila liberated on March 4, 1945; ++# this doesn't affect clocks, just our time zone abbreviation and DST flag. ++ ++# From Paul Goyette (2018-06-15) with URLs updated by Guy Harris (2024-02-15): + # In the Philippines, there is a national law, Republic Act No. 10535 + # which declares the official time here as "Philippine Standard Time". + # The act [1] even specifies use of PST as the abbreviation, although + # the FAQ provided by PAGASA [2] uses the "acronym PhST to distinguish + # it from the Pacific Standard Time (PST)." +-# [1] http://www.officialgazette.gov.ph/2013/05/15/republic-act-no-10535/ +-# [2] https://www1.pagasa.dost.gov.ph/index.php/astronomy/philippine-standard-time#republic-act-10535 ++# [1] https://www.officialgazette.gov.ph/2013/05/15/republic-act-no-10535/ ++# [2] https://prsd.pagasa.dost.gov.ph/index.php/28-astronomy/302-philippine-standard-time + # + # From Paul Eggert (2018-06-19): + # I surveyed recent news reports, and my impression is that "PST" is +@@ -3692,32 +3779,34 @@ Zone Asia/Hebron 2:20:23 - LMT 1900 Oct + # influence of the sources. There is no current abbreviation for DST, + # so use "PDT", the usual American style. + +-# From P Chan (2021-05-10): +-# Here's a fairly comprehensive article in Japanese: +-# https://wiki.suikawiki.org/n/Philippine%20Time +-# From Paul Eggert (2021-05-10): +-# The info in the Japanese table has not been absorbed (yet) below. +- + # Rule NAME FROM TO - IN ON AT SAVE LETTER/S +-Rule Phil 1936 only - Nov 1 0:00 1:00 D +-Rule Phil 1937 only - Feb 1 0:00 0 S +-Rule Phil 1954 only - Apr 12 0:00 1:00 D +-Rule Phil 1954 only - Jul 1 0:00 0 S +-Rule Phil 1978 only - Mar 22 0:00 1:00 D +-Rule Phil 1978 only - Sep 21 0:00 0 S ++Rule Phil 1936 only - Oct 31 24:00 1:00 D ++Rule Phil 1937 only - Jan 15 24:00 0 S ++Rule Phil 1941 only - Dec 15 24:00 1:00 D ++# The following three rules were canceled by Japan: ++#Rule Phil 1942 only - Jan 31 24:00 0 S ++#Rule Phil 1942 only - Mar 1 0:00 1:00 D ++#Rule Phil 1942 only - Jun 30 24:00 0 S ++Rule Phil 1945 only - Nov 30 24:00 0 S ++Rule Phil 1954 only - Apr 11 24:00 1:00 D ++Rule Phil 1954 only - Jun 4 24:00 0 S ++Rule Phil 1977 only - Mar 27 24:00 1:00 D ++Rule Phil 1977 only - Sep 21 24:00 0 S ++Rule Phil 1990 only - May 21 0:00 1:00 D ++Rule Phil 1990 only - Jul 28 24:00 0 S + # Zone NAME STDOFF RULES FORMAT [UNTIL] +-Zone Asia/Manila -15:56:00 - LMT 1844 Dec 31 +- 8:04:00 - LMT 1899 May 11 +- 8:00 Phil P%sT 1942 May +- 9:00 - JST 1944 Nov ++Zone Asia/Manila -15:56:08 - LMT 1844 Dec 31 ++ 8:03:52 - LMT 1899 Sep 6 4:00u ++ 8:00 Phil P%sT 1942 Feb 11 24:00 ++ 9:00 - JST 1945 Mar 4 + 8:00 Phil P%sT + + # Bahrain + # Qatar + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone Asia/Qatar 3:26:08 - LMT 1920 # Al Dawhah / Doha +- 4:00 - +04 1972 Jun +- 3:00 - +03 ++ 4:00 - %z 1972 Jun ++ 3:00 - %z + + # Kuwait + # Saudi Arabia +@@ -3767,7 +3856,7 @@ Zone Asia/Qatar 3:26:08 - LMT 1920 # Al Dawhah / Doha + # + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone Asia/Riyadh 3:06:52 - LMT 1947 Mar 14 +- 3:00 - +03 ++ 3:00 - %z + + # Singapore + # taken from Mok Ly Yng (2003-10-30) +@@ -3775,13 +3864,13 @@ Zone Asia/Riyadh 3:06:52 - LMT 1947 Mar 14 + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone Asia/Singapore 6:55:25 - 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 1981 Dec 31 16:00u +- 8:00 - +08 ++ 7:00 - %z 1933 Jan 1 ++ 7:00 0:20 %z 1936 Jan 1 ++ 7:20 - %z 1941 Sep 1 ++ 7:30 - %z 1942 Feb 16 ++ 9:00 - %z 1945 Sep 12 ++ 7:30 - %z 1981 Dec 31 16:00u ++ 8:00 - %z + + # Spratly Is + # no information +@@ -3839,13 +3928,13 @@ Zone Asia/Singapore 6:55:25 - LMT 1901 Jan 1 + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone Asia/Colombo 5:19:24 - LMT 1880 + 5:19:32 - MMT 1906 # Moratuwa Mean Time +- 5:30 - +0530 1942 Jan 5 +- 5:30 0:30 +06 1942 Sep +- 5:30 1:00 +0630 1945 Oct 16 2:00 +- 5:30 - +0530 1996 May 25 0:00 +- 6:30 - +0630 1996 Oct 26 0:30 +- 6:00 - +06 2006 Apr 15 0:30 +- 5:30 - +0530 ++ 5:30 - %z 1942 Jan 5 ++ 5:30 0:30 %z 1942 Sep ++ 5:30 1:00 %z 1945 Oct 16 2:00 ++ 5:30 - %z 1996 May 25 0:00 ++ 6:30 - %z 1996 Oct 26 0:30 ++ 6:00 - %z 2006 Apr 15 0:30 ++ 5:30 - %z + + # Syria + # Rule NAME FROM TO - IN ON AT SAVE LETTER/S +@@ -4016,16 +4105,16 @@ Rule Syria 2009 2022 - Oct lastFri 0:00 0 - + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone Asia/Damascus 2:25:12 - LMT 1920 # Dimashq + 2:00 Syria EE%sT 2022 Oct 28 0:00 +- 3:00 - +03 ++ 3:00 - %z + + # Tajikistan + # From Shanks & Pottenger. + # Zone NAME STDOFF RULES FORMAT [UNTIL] + 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 +06 1991 Sep 9 2:00s +- 5:00 - +05 ++ 5:00 - %z 1930 Jun 21 ++ 6:00 RussiaAsia %z 1991 Mar 31 2:00s ++ 5:00 1:00 %z 1991 Sep 9 2:00s ++ 5:00 - %z + + # Cambodia + # Christmas I +@@ -4035,16 +4124,16 @@ Zone Asia/Dushanbe 4:35:12 - LMT 1924 May 2 + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone Asia/Bangkok 6:42:04 - LMT 1880 + 6:42:04 - BMT 1920 Apr # Bangkok Mean Time +- 7:00 - +07 ++ 7:00 - %z + + # Turkmenistan + # From Shanks & Pottenger. + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone Asia/Ashgabat 3:53:32 - LMT 1924 May 2 # or Ashkhabad +- 4:00 - +04 1930 Jun 21 +- 5:00 RussiaAsia +05/+06 1991 Mar 31 2:00 +- 4:00 RussiaAsia +04/+05 1992 Jan 19 2:00 +- 5:00 - +05 ++ 4:00 - %z 1930 Jun 21 ++ 5:00 RussiaAsia %z 1991 Mar 31 2:00 ++ 4:00 RussiaAsia %z 1992 Jan 19 2:00 ++ 5:00 - %z + + # Oman + # Réunion +@@ -4054,25 +4143,25 @@ Zone Asia/Ashgabat 3:53:32 - LMT 1924 May 2 # or Ashkhabad + # The Crozet Is also observe Réunion time; see the 'antarctica' file. + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone Asia/Dubai 3:41:12 - LMT 1920 +- 4:00 - +04 ++ 4:00 - %z + + # Uzbekistan + # Byalokoz 1919 says Uzbekistan was 4:27:53. + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone Asia/Samarkand 4:27:53 - LMT 1924 May 2 +- 4:00 - +04 1930 Jun 21 +- 5:00 - +05 1981 Apr 1 +- 5:00 1:00 +06 1981 Oct 1 +- 6:00 - +06 1982 Apr 1 +- 5:00 RussiaAsia +05/+06 1992 +- 5:00 - +05 ++ 4:00 - %z 1930 Jun 21 ++ 5:00 - %z 1981 Apr 1 ++ 5:00 1:00 %z 1981 Oct 1 ++ 6:00 - %z 1982 Apr 1 ++ 5:00 RussiaAsia %z 1992 ++ 5:00 - %z + # 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 +- 5:00 RussiaAsia +05/+06 1992 +- 5:00 - +05 ++ 5:00 - %z 1930 Jun 21 ++ 6:00 RussiaAsia %z 1991 Mar 31 2:00 ++ 5:00 RussiaAsia %z 1992 ++ 5:00 - %z + + # Vietnam (southern) + +@@ -4130,7 +4219,7 @@ Zone Asia/Tashkent 4:37:11 - LMT 1924 May 2 + # Võ Nguyên Giáp, Việt Nam Dân Quốc Công Báo, No. 1 (1945-09-29), page 13 + # http://baochi.nlv.gov.vn/baochi/cgi-bin/baochi?a=d&d=JwvzO19450929.2.5&dliv=none + # It says that on 1945-09-01 at 24:00, Vietnam moved back two hours, to +07. +-# It also mentions a 1945-03-29 decree (by a Japanese Goveror-General) ++# It also mentions a 1945-03-29 decree (by a Japanese Governor-General) + # to set the time zone to +09, but does not say whether that decree + # merely legalized an earlier change to +09. + # +@@ -4151,14 +4240,14 @@ Zone Asia/Tashkent 4:37:11 - LMT 1924 May 2 + #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 +- 9:00 - +09 1945 Sep 1 24:00 +- 7:00 - +07 1947 Apr 1 +- 8:00 - +08 1955 Jul 1 01:00 +- 7:00 - +07 1959 Dec 31 23:00 +- 8:00 - +08 1975 Jun 13 +- 7:00 - +07 ++ 7:00 - %z 1942 Dec 31 23:00 ++ 8:00 - %z 1945 Mar 14 23:00 ++ 9:00 - %z 1945 Sep 1 24:00 ++ 7:00 - %z 1947 Apr 1 ++ 8:00 - %z 1955 Jul 1 01:00 ++ 7:00 - %z 1959 Dec 31 23:00 ++ 8:00 - %z 1975 Jun 13 ++ 7:00 - %z + + # From Paul Eggert (2019-02-19): + # +diff --git a/make/data/tzdata/australasia b/make/data/tzdata/australasia +index 624735be6..d659d1fb4 100644 +--- a/make/data/tzdata/australasia ++++ b/make/data/tzdata/australasia +@@ -66,8 +66,8 @@ Zone Australia/Perth 7:43:24 - LMT 1895 Dec + 8:00 Aus AW%sT 1943 Jul + 8:00 AW AW%sT + Zone Australia/Eucla 8:35:28 - LMT 1895 Dec +- 8:45 Aus +0845/+0945 1943 Jul +- 8:45 AW +0845/+0945 ++ 8:45 Aus %z 1943 Jul ++ 8:45 AW %z + + # Queensland + # +@@ -232,8 +232,8 @@ Rule LH 2008 max - Apr Sun>=1 2:00 0 - + Rule LH 2008 max - Oct Sun>=1 2:00 0:30 - + Zone Australia/Lord_Howe 10:36:20 - LMT 1895 Feb + 10:00 - AEST 1981 Mar +- 10:30 LH +1030/+1130 1985 Jul +- 10:30 LH +1030/+11 ++ 10:30 LH %z 1985 Jul ++ 10:30 LH %z + + # Australian miscellany + # +@@ -439,16 +439,16 @@ Rule Fiji 2019 only - Nov Sun>=8 2:00 1:00 - + Rule Fiji 2020 only - Dec 20 2:00 1:00 - + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone Pacific/Fiji 11:55:44 - LMT 1915 Oct 26 # Suva +- 12:00 Fiji +12/+13 ++ 12:00 Fiji %z + + # French Polynesia + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone Pacific/Gambier -8:59:48 - LMT 1912 Oct 1 # Rikitea +- -9:00 - -09 ++ -9:00 - %z + Zone Pacific/Marquesas -9:18:00 - LMT 1912 Oct 1 +- -9:30 - -0930 ++ -9:30 - %z + Zone Pacific/Tahiti -9:58:16 - LMT 1912 Oct 1 # Papeete +- -10:00 - -10 ++ -10:00 - %z + # Clipperton (near North America) is administered from French Polynesia; + # it is uninhabited. + +@@ -491,7 +491,7 @@ Rule Guam 1977 only - Aug 28 2:00 0 S + Zone Pacific/Guam -14:21:00 - LMT 1844 Dec 31 + 9:39:00 - LMT 1901 # Agana + 10:00 - GST 1941 Dec 10 # Guam +- 9:00 - +09 1944 Jul 31 ++ 9:00 - %z 1944 Jul 31 + 10:00 Guam G%sT 2000 Dec 23 + 10:00 - ChST # Chamorro Standard Time + +@@ -503,30 +503,30 @@ Zone Pacific/Guam -14:21:00 - LMT 1844 Dec 31 + # Wallis & Futuna + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone Pacific/Tarawa 11:32:04 - LMT 1901 # Bairiki +- 12:00 - +12 ++ 12:00 - %z + + # Kiribati (except Gilbert Is) + # See Pacific/Tarawa for the Gilbert Is. + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone Pacific/Kanton 0 - -00 1937 Aug 31 +- -12:00 - -12 1979 Oct +- -11:00 - -11 1994 Dec 31 +- 13:00 - +13 ++ -12:00 - %z 1979 Oct ++ -11:00 - %z 1994 Dec 31 ++ 13:00 - %z + Zone Pacific/Kiritimati -10:29:20 - LMT 1901 +- -10:40 - -1040 1979 Oct +- -10:00 - -10 1994 Dec 31 +- 14:00 - +14 ++ -10:40 - %z 1979 Oct ++ -10:00 - %z 1994 Dec 31 ++ 14:00 - %z + + # Marshall Is + # See Pacific/Tarawa for most locations. + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone Pacific/Kwajalein 11:09:20 - LMT 1901 +- 11:00 - +11 1937 +- 10:00 - +10 1941 Apr 1 +- 9:00 - +09 1944 Feb 6 +- 11:00 - +11 1969 Oct +- -12:00 - -12 1993 Aug 20 24:00 +- 12:00 - +12 ++ 11:00 - %z 1937 ++ 10:00 - %z 1941 Apr 1 ++ 9:00 - %z 1944 Feb 6 ++ 11:00 - %z 1969 Oct ++ -12:00 - %z 1993 Aug 20 24:00 ++ 12:00 - %z + + # Micronesia + # For Chuuk and Yap see Pacific/Port_Moresby. +@@ -534,22 +534,22 @@ Zone Pacific/Kwajalein 11:09:20 - LMT 1901 + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone Pacific/Kosrae -13:08:04 - LMT 1844 Dec 31 + 10:51:56 - 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 1969 Oct +- 12:00 - +12 1999 +- 11:00 - +11 ++ 11:00 - %z 1914 Oct ++ 9:00 - %z 1919 Feb 1 ++ 11:00 - %z 1937 ++ 10:00 - %z 1941 Apr 1 ++ 9:00 - %z 1945 Aug ++ 11:00 - %z 1969 Oct ++ 12:00 - %z 1999 ++ 11:00 - %z + + # Nauru + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone Pacific/Nauru 11:07:40 - LMT 1921 Jan 15 # Uaobe +- 11:30 - +1130 1942 Aug 29 +- 9:00 - +09 1945 Sep 8 +- 11:30 - +1130 1979 Feb 10 2:00 +- 12:00 - +12 ++ 11:30 - %z 1942 Aug 29 ++ 9:00 - %z 1945 Sep 8 ++ 11:30 - %z 1979 Feb 10 2:00 ++ 12:00 - %z + + # New Caledonia + # Rule NAME FROM TO - IN ON AT SAVE LETTER/S +@@ -560,7 +560,7 @@ Rule NC 1996 only - Dec 1 2:00s 1:00 - + Rule NC 1997 only - Mar 2 2:00s 0 - + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone Pacific/Noumea 11:05:48 - LMT 1912 Jan 13 # Nouméa +- 11:00 NC +11/+12 ++ 11:00 NC %z + + + ############################################################################### +@@ -604,8 +604,8 @@ Zone Pacific/Auckland 11:39:04 - LMT 1868 Nov 2 + 12:00 NZ NZ%sT + + Zone Pacific/Chatham 12:13:48 - LMT 1868 Nov 2 +- 12:15 - +1215 1946 Jan 1 +- 12:45 Chatham +1245/+1345 ++ 12:15 - %z 1946 Jan 1 ++ 12:45 Chatham %z + + # Auckland Is + # uninhabited; Māori and Moriori, colonial settlers, pastoralists, sealers, +@@ -658,8 +658,8 @@ Rule Cook 1979 1990 - Oct lastSun 0:00 0:30 - + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone Pacific/Rarotonga 13:20:56 - LMT 1899 Dec 26 # Avarua + -10:39:04 - LMT 1952 Oct 16 +- -10:30 - -1030 1978 Nov 12 +- -10:00 Cook -10/-0930 ++ -10:30 - %z 1978 Nov 12 ++ -10:00 Cook %z + + ############################################################################### + +@@ -676,30 +676,30 @@ Zone Pacific/Rarotonga 13:20:56 - LMT 1899 Dec 26 # Avarua + + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone Pacific/Niue -11:19:40 - LMT 1952 Oct 16 # Alofi +- -11:20 - -1120 1964 Jul +- -11:00 - -11 ++ -11:20 - %z 1964 Jul ++ -11:00 - %z + + # Norfolk + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone Pacific/Norfolk 11:11:52 - LMT 1901 # Kingston +- 11:12 - +1112 1951 +- 11:30 - +1130 1974 Oct 27 02:00s +- 11:30 1:00 +1230 1975 Mar 2 02:00s +- 11:30 - +1130 2015 Oct 4 02:00s +- 11:00 - +11 2019 Jul +- 11:00 AN +11/+12 ++ 11:12 - %z 1951 ++ 11:30 - %z 1974 Oct 27 02:00s ++ 11:30 1:00 %z 1975 Mar 2 02:00s ++ 11:30 - %z 2015 Oct 4 02:00s ++ 11:00 - %z 2019 Jul ++ 11:00 AN %z + + # Palau (Belau) + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone Pacific/Palau -15:02:04 - LMT 1844 Dec 31 # Koror + 8:57:56 - LMT 1901 +- 9:00 - +09 ++ 9:00 - %z + + # Papua New Guinea + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone Pacific/Port_Moresby 9:48:40 - LMT 1880 + 9:48:32 - PMMT 1895 # Port Moresby Mean Time +- 10:00 - +10 ++ 10:00 - %z + # + # From Paul Eggert (2014-10-13): + # Base the Bougainville entry on the Arawa-Kieta region, which appears to have +@@ -720,16 +720,16 @@ Zone Pacific/Port_Moresby 9:48:40 - LMT 1880 + # + Zone Pacific/Bougainville 10:22:16 - LMT 1880 + 9:48:32 - PMMT 1895 +- 10:00 - +10 1942 Jul +- 9:00 - +09 1945 Aug 21 +- 10:00 - +10 2014 Dec 28 2:00 +- 11:00 - +11 ++ 10:00 - %z 1942 Jul ++ 9:00 - %z 1945 Aug 21 ++ 10:00 - %z 2014 Dec 28 2:00 ++ 11:00 - %z + + # Pitcairn + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone Pacific/Pitcairn -8:40:20 - LMT 1901 # Adamstown +- -8:30 - -0830 1998 Apr 27 0:00 +- -8:00 - -08 ++ -8:30 - %z 1998 Apr 27 0:00 ++ -8:00 - %z + + # American Samoa + # Midway +@@ -818,15 +818,15 @@ Rule WS 2012 2020 - Sep lastSun 3:00 1 - + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone Pacific/Apia 12:33:04 - LMT 1892 Jul 5 + -11:26:56 - LMT 1911 +- -11:30 - -1130 1950 +- -11:00 WS -11/-10 2011 Dec 29 24:00 +- 13:00 WS +13/+14 ++ -11:30 - %z 1950 ++ -11:00 WS %z 2011 Dec 29 24:00 ++ 13:00 WS %z + + # Solomon Is + # excludes Bougainville, for which see Papua New Guinea + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone Pacific/Guadalcanal 10:39:48 - LMT 1912 Oct 1 # Honiara +- 11:00 - +11 ++ 11:00 - %z + + # Tokelau + # +@@ -849,8 +849,8 @@ Zone Pacific/Guadalcanal 10:39:48 - LMT 1912 Oct 1 # Honiara + + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone Pacific/Fakaofo -11:24:56 - LMT 1901 +- -11:00 - -11 2011 Dec 30 +- 13:00 - +13 ++ -11:00 - %z 2011 Dec 30 ++ 13:00 - %z + + # Tonga + # Rule NAME FROM TO - IN ON AT SAVE LETTER/S +@@ -862,9 +862,9 @@ Rule Tonga 2016 only - Nov Sun>=1 2:00 1:00 - + Rule Tonga 2017 only - Jan Sun>=15 3:00 0 - + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone Pacific/Tongatapu 12:19:12 - LMT 1945 Sep 10 +- 12:20 - +1220 1961 +- 13:00 - +13 1999 +- 13:00 Tonga +13/+14 ++ 12:20 - %z 1961 ++ 13:00 - %z 1999 ++ 13:00 Tonga %z + + + # US minor outlying islands +@@ -953,7 +953,7 @@ Rule Vanuatu 1992 1993 - Jan Sat>=22 24:00 0 - + Rule Vanuatu 1992 only - Oct Sat>=22 24:00 1:00 - + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone Pacific/Efate 11:13:16 - LMT 1912 Jan 13 # Vila +- 11:00 Vanuatu +11/+12 ++ 11:00 Vanuatu %z + + ############################################################################### + +@@ -1262,10 +1262,10 @@ Zone Pacific/Efate 11:13:16 - LMT 1912 Jan 13 # Vila + # The 1992 ending date used in the rules is a best guess; + # it matches what was used in the past. + +-# The Australian Bureau of Meteorology FAQ +-# http://www.bom.gov.au/faq/faqgen.htm +-# (1999-09-27) writes that Giles Meteorological Station uses +-# South Australian time even though it's located in Western Australia. ++# From Christopher Hunt (2006-11-21), after an advance warning ++# from Jesper Nørgaard Welen (2006-11-01): ++# WA are trialing DST for three years. ++# http://www.parliament.wa.gov.au/parliament/bills.nsf/9A1B183144403DA54825721200088DF1/$File/Bill175-1B.pdf + + # From Paul Eggert (2018-04-01): + # The Guardian Express of Perth, Australia reported today that the +@@ -1277,54 +1277,10 @@ Zone Pacific/Efate 11:13:16 - LMT 1912 Jan 13 # Vila + # 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 +- +-# From Paul Eggert (2018-02-26): +-# I lack access to the following source for Queensland DST: +-# Pearce C. History of daylight saving time in Queensland. +-# Queensland Hist J. 2017 Aug;23(6):389-403 +-# https://search.informit.com.au/documentSummary;dn=994682348436426;res=IELHSS +- +-# From George Shepherd via Simon Woodhead via Robert Elz (1991-03-06): +-# # The state of QUEENSLAND.. [ Courtesy Qld. Dept Premier Econ&Trade Devel ] +-# # [ Dec 1990 ] +-# ... +-# Zone Australia/Queensland 10:00 AQ %sST +-# ... +-# Rule AQ 1971 only - Oct lastSun 2:00 1:00 D +-# Rule AQ 1972 only - Feb lastSun 3:00 0 E +-# Rule AQ 1989 max - Oct lastSun 2:00 1:00 D +-# Rule AQ 1990 max - Mar Sun>=1 3:00 0 E +- +-# From Bradley White (1989-12-24): +-# "Australia/Queensland" now observes daylight time (i.e. from +-# October 1989). +- +-# From Bradley White (1991-03-04): +-# A recent excerpt from an Australian newspaper... +-# ...Queensland...[has] agreed to end daylight saving +-# at 3am tomorrow (March 3)... +- +-# From John Mackin (1991-03-06): +-# I can certainly confirm for my part that Daylight Saving in NSW did in fact +-# end on Sunday, 3 March. I don't know at what hour, though. (It surprised +-# me.) +- +-# From Bradley White (1992-03-08): +-# ...there was recently a referendum in Queensland which resulted +-# in the experimental daylight saving system being abandoned. So, ... +-# ... +-# Rule QLD 1989 1991 - Oct lastSun 2:00 1:00 D +-# Rule QLD 1990 1992 - Mar Sun>=1 3:00 0 S +-# ... +- +-# From Arthur David Olson (1992-03-08): +-# The chosen rules the union of the 1971/1972 change and the 1989-1992 changes. +- +-# From Christopher Hunt (2006-11-21), after an advance warning +-# from Jesper Nørgaard Welen (2006-11-01): +-# WA are trialing DST for three years. +-# http://www.parliament.wa.gov.au/parliament/bills.nsf/9A1B183144403DA54825721200088DF1/$File/Bill175-1B.pdf ++# The Australian Bureau of Meteorology FAQ ++# http://www.bom.gov.au/faq/faqgen.htm ++# (1999-09-27) writes that Giles Meteorological Station uses ++# South Australian time even though it's located in Western Australia. + + # From Rives McDow (2002-04-09): + # The most interesting region I have found consists of three towns on the +@@ -1382,6 +1338,59 @@ Zone Pacific/Efate 11:13:16 - LMT 1912 Jan 13 # Vila + # For lack of better info, assume the tradition dates back to the + # introduction of standard time in 1895. + ++# From Stuart Bishop (2024-11-12): ++# An article discussing the in-use but technically unofficial timezones ++# in the Western Australian portion of the Nullarbor Plain. ++# https://www.abc.net.au/news/2024-11-22/outback-wa-properties-strange-time-zones/104542494 ++# From Paul Eggert (2024-11-12): ++# As the article says, the Eyre Bird Observatory and nearby sheep stations ++# can use Tokyo time. Other possibilities include Asia/Chita, Asia/Seoul, ++# and Asia/Jayapura. ++ ++# Queensland ++ ++# From Paul Eggert (2018-02-26): ++# I lack access to the following source for Queensland DST: ++# Pearce C. History of daylight saving time in Queensland. ++# Queensland Hist J. 2017 Aug;23(6):389-403 ++# https://search.informit.com.au/documentSummary;dn=994682348436426;res=IELHSS ++ ++# From George Shepherd via Simon Woodhead via Robert Elz (1991-03-06): ++# # The state of QUEENSLAND.. [ Courtesy Qld. Dept Premier Econ&Trade Devel ] ++# # [ Dec 1990 ] ++# ... ++# Zone Australia/Queensland 10:00 AQ %sST ++# ... ++# Rule AQ 1971 only - Oct lastSun 2:00 1:00 D ++# Rule AQ 1972 only - Feb lastSun 3:00 0 E ++# Rule AQ 1989 max - Oct lastSun 2:00 1:00 D ++# Rule AQ 1990 max - Mar Sun>=1 3:00 0 E ++ ++# From Bradley White (1989-12-24): ++# "Australia/Queensland" now observes daylight time (i.e. from ++# October 1989). ++ ++# From Bradley White (1991-03-04): ++# A recent excerpt from an Australian newspaper... ++# ...Queensland...[has] agreed to end daylight saving ++# at 3am tomorrow (March 3)... ++ ++# From John Mackin (1991-03-06): ++# I can certainly confirm for my part that Daylight Saving in NSW did in fact ++# end on Sunday, 3 March. I don't know at what hour, though. (It surprised ++# me.) ++ ++# From Bradley White (1992-03-08): ++# ...there was recently a referendum in Queensland which resulted ++# in the experimental daylight saving system being abandoned. So, ... ++# ... ++# Rule QLD 1989 1991 - Oct lastSun 2:00 1:00 D ++# Rule QLD 1990 1992 - Mar Sun>=1 3:00 0 S ++# ... ++ ++# From Arthur David Olson (1992-03-08): ++# The chosen rules the union of the 1971/1972 change and the 1989-1992 changes. + -+void LIR_List::cmp_branch(LIR_Condition condition, LIR_Opr left, LIR_Opr right, BasicType type, BlockBegin* block, BlockBegin* unordered) { -+ cmp(condition, left, right); -+ branch(condition, type, block, unordered); -+} + + # southeast Australia + # +diff --git a/make/data/tzdata/backward b/make/data/tzdata/backward +index 7ddc6cc3d..cda2ccc0c 100644 +--- a/make/data/tzdata/backward ++++ b/make/data/tzdata/backward +@@ -21,12 +21,13 @@ + # or visit www.oracle.com if you need additional information or have any + # questions. + # +-# tzdb links for backward compatibility ++# Links and zones for backward compatibility + + # This file is in the public domain, so clarified as of + # 2009-05-17 by Arthur David Olson. + + # This file provides links from old or merged timezone names to current ones. ++# It also provides a few zone entries for old naming conventions. + # Many names changed in 1993 and in 1995, 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 +@@ -67,6 +68,8 @@ Link America/Rio_Branco Brazil/Acre #= America/Porto_Acre + Link America/Noronha Brazil/DeNoronha + Link America/Sao_Paulo Brazil/East + Link America/Manaus Brazil/West ++Link Europe/Brussels CET ++Link America/Chicago CST6CDT + Link America/Halifax Canada/Atlantic + Link America/Winnipeg Canada/Central + # This line is commented out, as the name exceeded the 14-character limit +@@ -81,6 +84,9 @@ Link America/Whitehorse Canada/Yukon + Link America/Santiago Chile/Continental + Link Pacific/Easter Chile/EasterIsland + Link America/Havana Cuba ++Link Europe/Athens EET ++Link America/Panama EST ++Link America/New_York EST5EDT + Link Africa/Cairo Egypt + Link Europe/Dublin Eire + # Vanguard section, for most .zi parsers. +@@ -119,6 +125,9 @@ Link America/Jamaica Jamaica + Link Asia/Tokyo Japan + Link Pacific/Kwajalein Kwajalein + Link Africa/Tripoli Libya ++Link Europe/Brussels MET ++Link America/Phoenix MST ++Link America/Denver MST7MDT + Link America/Tijuana Mexico/BajaNorte + Link America/Mazatlan Mexico/BajaSur + Link America/Mexico_City Mexico/General +@@ -298,6 +307,7 @@ Link America/Denver America/Shiprock + Link America/Toronto America/Thunder_Bay + Link America/Edmonton America/Yellowknife + Link Pacific/Auckland Antarctica/South_Pole ++Link Asia/Ulaanbaatar Asia/Choibalsan + Link Asia/Shanghai Asia/Chongqing + Link Asia/Shanghai Asia/Harbin + Link Asia/Urumqi Asia/Kashgar +@@ -312,6 +322,7 @@ Link Europe/Kyiv Europe/Zaporozhye + Link Pacific/Kanton Pacific/Enderbury + Link Pacific/Honolulu Pacific/Johnston + Link Pacific/Port_Moresby Pacific/Yap ++Link Europe/Lisbon WET + + + # Alternate names for the same location +@@ -337,5 +348,7 @@ Link Europe/Kyiv Europe/Kiev + # Classically, Cyprus is in Asia; e.g. see Herodotus, Histories, I.72. + # However, for various reasons many users expect to find it under Europe. + Link Asia/Nicosia Europe/Nicosia ++Link Pacific/Honolulu HST ++Link America/Los_Angeles PST8PDT + Link Pacific/Guadalcanal Pacific/Ponape #= Pacific/Pohnpei + Link Pacific/Port_Moresby Pacific/Truk #= Pacific/Chuuk +diff --git a/make/data/tzdata/etcetera b/make/data/tzdata/etcetera +index 27147715e..41660b05d 100644 +--- a/make/data/tzdata/etcetera ++++ b/make/data/tzdata/etcetera +@@ -28,7 +28,7 @@ + + # These entries are for uses not otherwise covered by the tz database. + # Their main practical use is for platforms like Android that lack +-# support for POSIX.1-2017-style TZ strings. On such platforms these entries ++# support for POSIX proleptic TZ strings. On such platforms these entries + # can be useful if the timezone database is wrong or if a ship or + # aircraft at sea is not in a timezone. + +@@ -74,29 +74,33 @@ Link Etc/GMT GMT + # so we moved the names into the Etc subdirectory. + # Also, the time zone abbreviations are now compatible with %z. + +-Zone Etc/GMT-14 14 - +14 +-Zone Etc/GMT-13 13 - +13 +-Zone Etc/GMT-12 12 - +12 +-Zone Etc/GMT-11 11 - +11 +-Zone Etc/GMT-10 10 - +10 +-Zone Etc/GMT-9 9 - +09 +-Zone Etc/GMT-8 8 - +08 +-Zone Etc/GMT-7 7 - +07 +-Zone Etc/GMT-6 6 - +06 +-Zone Etc/GMT-5 5 - +05 +-Zone Etc/GMT-4 4 - +04 +-Zone Etc/GMT-3 3 - +03 +-Zone Etc/GMT-2 2 - +02 +-Zone Etc/GMT-1 1 - +01 +-Zone Etc/GMT+1 -1 - -01 +-Zone Etc/GMT+2 -2 - -02 +-Zone Etc/GMT+3 -3 - -03 +-Zone Etc/GMT+4 -4 - -04 +-Zone Etc/GMT+5 -5 - -05 +-Zone Etc/GMT+6 -6 - -06 +-Zone Etc/GMT+7 -7 - -07 +-Zone Etc/GMT+8 -8 - -08 +-Zone Etc/GMT+9 -9 - -09 +-Zone Etc/GMT+10 -10 - -10 +-Zone Etc/GMT+11 -11 - -11 +-Zone Etc/GMT+12 -12 - -12 ++# There is no "Etc/Unknown" entry, as CLDR says that "Etc/Unknown" ++# corresponds to an unknown or invalid time zone, and things would get ++# confusing if Etc/Unknown were made valid here. ++ ++Zone Etc/GMT-14 14 - %z ++Zone Etc/GMT-13 13 - %z ++Zone Etc/GMT-12 12 - %z ++Zone Etc/GMT-11 11 - %z ++Zone Etc/GMT-10 10 - %z ++Zone Etc/GMT-9 9 - %z ++Zone Etc/GMT-8 8 - %z ++Zone Etc/GMT-7 7 - %z ++Zone Etc/GMT-6 6 - %z ++Zone Etc/GMT-5 5 - %z ++Zone Etc/GMT-4 4 - %z ++Zone Etc/GMT-3 3 - %z ++Zone Etc/GMT-2 2 - %z ++Zone Etc/GMT-1 1 - %z ++Zone Etc/GMT+1 -1 - %z ++Zone Etc/GMT+2 -2 - %z ++Zone Etc/GMT+3 -3 - %z ++Zone Etc/GMT+4 -4 - %z ++Zone Etc/GMT+5 -5 - %z ++Zone Etc/GMT+6 -6 - %z ++Zone Etc/GMT+7 -7 - %z ++Zone Etc/GMT+8 -8 - %z ++Zone Etc/GMT+9 -9 - %z ++Zone Etc/GMT+10 -10 - %z ++Zone Etc/GMT+11 -11 - %z ++Zone Etc/GMT+12 -12 - %z +diff --git a/make/data/tzdata/europe b/make/data/tzdata/europe +index 18865f33b..7ba6c6796 100644 +--- a/make/data/tzdata/europe ++++ b/make/data/tzdata/europe +@@ -753,14 +753,6 @@ Rule Russia 1996 2010 - Oct lastSun 2:00s 0 - + # Take "abolishing daylight saving time" to mean that time is now considered + # to be standard. + +-# These are for backward compatibility with older versions. +- +-# Zone NAME STDOFF RULES FORMAT [UNTIL] +-Zone WET 0:00 EU WE%sT +-Zone CET 1:00 C-Eur CE%sT +-Zone MET 1:00 C-Eur ME%sT +-Zone EET 2:00 EU EE%sT +- + # Previous editions of this database used abbreviations like MET DST + # for Central European Summer Time, but this didn't agree with common usage. + +@@ -894,7 +886,7 @@ Zone Europe/Minsk 1:50:16 - LMT 1880 + 3:00 Russia MSK/MSD 1990 + 3:00 - MSK 1991 Mar 31 2:00s + 2:00 Russia EE%sT 2011 Mar 27 2:00s +- 3:00 - +03 ++ 3:00 - %z + + # Belgium + # Luxembourg +@@ -1178,7 +1170,7 @@ Zone Atlantic/Faroe -0:27:04 - LMT 1908 Jan 11 # Tórshavn + # However, Greenland will change to Daylight Saving Time again in 2024 + # and onwards. + +-# From a contributor who wishes to remain anonymous for now (2023-10-29): ++# From Jule Dabars (2023-10-29): + # https://www.dr.dk/nyheder/seneste/i-nat-skal-uret-stilles-en-time-tilbage-men-foerste-gang-sker-det-ikke-i-groenland + # with a link to that page: + # https://naalakkersuisut.gl/Nyheder/2023/10/2710_sommertid +@@ -1199,22 +1191,22 @@ Rule Thule 2007 max - Nov Sun>=1 2:00 0 S + # + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone America/Danmarkshavn -1:14:40 - LMT 1916 Jul 28 +- -3:00 - -03 1980 Apr 6 2:00 +- -3:00 EU -03/-02 1996 ++ -3:00 - %z 1980 Apr 6 2:00 ++ -3:00 EU %z 1996 + 0:00 - GMT + # + # Use the old name Scoresbysund, as the current name Ittoqqortoormiit + # exceeds tzdb's 14-letter limit and has no common English abbreviation. + Zone America/Scoresbysund -1:27:52 - LMT 1916 Jul 28 # Ittoqqortoormiit +- -2:00 - -02 1980 Apr 6 2:00 +- -2:00 C-Eur -02/-01 1981 Mar 29 +- -1:00 EU -01/+00 2024 Mar 31 +- -2:00 EU -02/-01 ++ -2:00 - %z 1980 Apr 6 2:00 ++ -2:00 C-Eur %z 1981 Mar 29 ++ -1:00 EU %z 2024 Mar 31 ++ -2:00 EU %z + Zone America/Nuuk -3:26:56 - LMT 1916 Jul 28 # Godthåb +- -3:00 - -03 1980 Apr 6 2:00 +- -3:00 EU -03/-02 2023 Mar 26 1:00u +- -2:00 - -02 2023 Oct 29 1:00u +- -2:00 EU -02/-01 ++ -3:00 - %z 1980 Apr 6 2:00 ++ -3:00 EU %z 2023 Mar 26 1:00u ++ -2:00 - %z 2023 Oct 29 1:00u ++ -2:00 EU %z + Zone America/Thule -4:35:08 - LMT 1916 Jul 28 # Pituffik + -4:00 Thule A%sT + +@@ -2086,10 +2078,39 @@ Zone Europe/Warsaw 1:24:00 - LMT 1880 + + # Portugal + +-# From Paul Eggert (2014-08-11), after a heads-up from Stephen Colebourne: +-# 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. ++# From Tim Parenti (2024-07-01), per Alois Treindl (2021-02-07) and Michael ++# Deckers (2021-02-10): ++# http://oal.ul.pt/documentos/2018/01/hl1911a2018.pdf/ ++# The Astronomical Observatory of Lisbon has published a list detailing the ++# historical transitions in legal time within continental Portugal. It ++# directly references many decrees and ordinances which are, in turn, ++# referenced below. They can be viewed in the public archives of the Diário da ++# República (until 1976-04-09 known as the Diário do Govêrno) at ++# https://dre.pt/ (in Portuguese). ++# ++# Most of the Rules below have been updated simply to match the Observatory's ++# listing for continental (mainland) Portugal. Although there are over 50 ++# referenced decrees and ordinances, only the handful with comments below have ++# been verified against the text, typically to provide additional confidence ++# wherever dates provided by Whitman and Shanks & Pottenger had disagreed. ++# See further below for the Azores and Madeira. ++ ++# From Tim Parenti (2024-07-01), per Paul Eggert (2014-08-11), after a ++# heads-up from Stephen Colebourne: ++# According to a 1911-05-24 Portuguese decree, Lisbon was at -0:36:44.68, but ++# switched to GMT on 1912-01-01 at 00:00. ++# https://dre.pt/dr/detalhe/decreto/593090 ++# https://dre.pt/application/conteudo/593090 ++# The decree made legal time throughout Portugal and her possessions ++# "subordinate to the Greenwich meridian, according to the principle adopted at ++# the Washington Convention in 1884" and eliminated the "difference of five ++# minutes between the internal and external clocks of railway stations". ++# ++# The decree was gazetted in the 1911-05-30 issue of Diário do Govêrno, and is ++# considered to be dated 1911-05-24 by that issue's summary; however, the text ++# of the decree itself is dated 1911-05-26. The Diário da República website ++# notes the discrepancy, but later laws and the Observatory all seem to refer ++# to this decree by the 1911-05-24 date. + # + # From Michael Deckers (2018-02-15): + # article 5 [of the 1911 decree; Deckers's translation] ...: +@@ -2097,37 +2118,62 @@ Zone Europe/Warsaw 1:24:00 - LMT 1880 + # according to the 2nd article, the civil day January 1, 1912 begins, + # all clocks therefore having to be advanced or set back correspondingly ... + +-# From Rui Pedro Salgueiro (1992-11-12): +-# Portugal has recently (September, 27) changed timezone +-# (from WET to MET or CET) to harmonize with EEC. +-# +-# Martin Bruckmann (1996-02-29) reports via Peter Ilieve +-# that Portugal is reverting to 0:00 by not moving its clocks this spring. +-# The new Prime Minister was fed up with getting up in the dark in the winter. +-# +-# From Paul Eggert (1996-11-12): +-# IATA SSIM (1991-09) reports several 1991-09 and 1992-09 transitions +-# at 02:00u, not 01:00u. Assume that these are typos. +-# IATA SSIM (1991/1992) reports that the Azores were at -1:00. +-# IATA SSIM (1993-02) says +0:00; later issues (through 1996-09) say -1:00. +-# Guess that the Azores changed to EU rules in 1992 (since that's when Portugal +-# harmonized with EU rules), and that they stayed +0:00 that winter. +-# + # Rule NAME FROM TO - IN ON AT SAVE LETTER/S +-# DSH writes that despite Decree 1,469 (1915), the change to the clocks was not +-# done every year, depending on what Spain did, because of railroad schedules. +-# Go with Shanks & Pottenger. ++# From Tim Parenti (2024-07-01), per Paul Eggert (1999-01-30): ++# DSH writes in their history that Decreto 1469 of 1915-03-30 established ++# summer time and that, "despite" this, the change to the clocks was not done ++# every year, depending on what Spain did, because of railroad schedules. ++# In fact, that decree had nothing to do with DST; rather, it regulated the ++# sending of time signals. But we do see linkage to Spain in the 1920s below. ++# https://dre.pt/dr/detalhe/decreto/1469-1915-285721 ++# https://dre.pt/application/conteudo/285721 ++# ++# According to the Observatory, standard time was first advanced by Decreto ++# 2433 of 1916-06-09 and restored by Decreto 2712 of 1916-10-28. While Whitman ++# gives 1916-10-31 for the latter transition, Shanks & Pottenger agrees more ++# closely with the decree, which stated that its provision "will start sixty ++# minutes after the end of 31 October, according to the current time," i.e., ++# 01:00 on 1 November. ++# https://dre.pt/dr/detalhe/decreto/2433-1916-267192 ++# https://dre.pt/application/conteudo/267192 ++# https://dre.pt/dr/detalhe/decreto/2712-1916-590937 ++# https://dre.pt/application/conteudo/590937 + Rule Port 1916 only - Jun 17 23:00 1:00 S +-# Whitman gives 1916 Oct 31; go with Shanks & Pottenger. + Rule Port 1916 only - Nov 1 1:00 0 - +-Rule Port 1917 only - Feb 28 23:00s 1:00 S +-Rule Port 1917 1921 - Oct 14 23:00s 0 - +-Rule Port 1918 only - Mar 1 23:00s 1:00 S +-Rule Port 1919 only - Feb 28 23:00s 1:00 S +-Rule Port 1920 only - Feb 29 23:00s 1:00 S +-Rule Port 1921 only - Feb 28 23:00s 1:00 S ++# From Tim Parenti (2024-07-01): ++# Article 7 of Decreto 2922 of 1916-12-30 stated that "the legal time will be ++# advanced by sixty minutes from 1 March to 31 October." Per Article 15, this ++# came into force from 1917-01-01. Just before the first fall back, Decreto ++# 3446 of 1917-10-11 changed the annual end date to 14 October. ++# https://dre.pt/dr/detalhe/decreto/2922-1916-261894 ++# https://dre.pt/application/conteudo/261894 ++# https://dre.pt/dr/detalhe/decreto/3446-1917-495161 ++# https://dre.pt/application/conteudo/495161 ++# This annual change was revoked by Decreto 8038 of 1922-02-18. ++# https://dre.pt/dr/detalhe/decreto/8038-1922-569751 ++# https://dre.pt/application/conteudo/569751 ++Rule Port 1917 1921 - Mar 1 0:00 1:00 S ++Rule Port 1917 1921 - Oct 14 24:00 0 - ++# From Tim Parenti (2024-07-01): ++# Decreto 9592 of 1924-04-14 noted that "France maintains the advance of legal ++# time in the summer and Spain has now adopted it for the first time" and ++# considered "that the absence of similar measures would cause serious ++# difficulties for international rail connections with consequent repercussions ++# on domestic service hours..." along with "inconvenient analogues...for postal ++# and telegraph services." Summer time would be in effect from 17 April to 4 ++# October, with the spring change explicitly specified by bringing clocks ++# forward from 16 April 23:00. ++# https://dre.pt/dr/detalhe/decreto/9592-1924-652133 ++# https://dre.pt/application/conteudo/652133 ++# ++# Decreto 10700, issued 1925-04-16, noted that Spain had not continued summer ++# time, declared that "the current legal hour prior to 17 April remains ++# unchanged from that day forward", and revoked legislation to the contrary, ++# just a day before summer time would have otherwise resumed. ++# https://dre.pt/dr/detalhe/decreto/10700-1925-437826 ++# https://dre.pt/application/conteudo/437826 + Rule Port 1924 only - Apr 16 23:00s 1:00 S +-Rule Port 1924 only - Oct 14 23:00s 0 - ++Rule Port 1924 only - Oct 4 23:00s 0 - + Rule Port 1926 only - Apr 17 23:00s 1:00 S + Rule Port 1926 1929 - Oct Sat>=1 23:00s 0 - + Rule Port 1927 only - Apr 9 23:00s 1:00 S +@@ -2139,6 +2185,8 @@ Rule Port 1931 1932 - Oct Sat>=1 23:00s 0 - + Rule Port 1932 only - Apr 2 23:00s 1:00 S + Rule Port 1934 only - Apr 7 23:00s 1:00 S + # Whitman gives 1934 Oct 5; go with Shanks & Pottenger. ++# Note: The 1935 law specified 10-06 00:00, not 10-05 24:00, but the following ++# is equivalent and more succinct. + Rule Port 1934 1938 - Oct Sat>=1 23:00s 0 - + # Shanks & Pottenger give 1935 Apr 30; go with Whitman. + Rule Port 1935 only - Mar 30 23:00s 1:00 S +@@ -2149,10 +2197,19 @@ Rule Port 1938 only - Mar 26 23:00s 1:00 S + Rule Port 1939 only - Apr 15 23:00s 1:00 S + # Whitman gives 1939 Oct 7; go with Shanks & Pottenger. + Rule Port 1939 only - Nov 18 23:00s 0 - ++# From Tim Parenti (2024-07-01): ++# Portaria 9465 of 1940-02-17 advanced clocks from Saturday 1940-02-24 23:00. ++# The clocks were restored by Portaria 9658, issued Monday 1940-10-07, ++# effective from 24:00 that very night, which agrees with Shanks & Pottenger; ++# Whitman gives Saturday 1940-10-05 instead. ++# https://dre.pt/dr/detalhe/portaria/9465-1940-189096 ++# https://dre.pt/application/conteudo/189096 ++# https://dre.pt/dr/detalhe/portaria/9658-1940-196729 ++# https://dre.pt/application/conteudo/196729 + Rule Port 1940 only - Feb 24 23:00s 1:00 S +-# Shanks & Pottenger give 1940 Oct 7; go with Whitman. +-Rule Port 1940 1941 - Oct 5 23:00s 0 - ++Rule Port 1940 only - Oct 7 23:00s 0 - + Rule Port 1941 only - Apr 5 23:00s 1:00 S ++Rule Port 1941 only - Oct 5 23:00s 0 - + Rule Port 1942 1945 - Mar Sat>=8 23:00s 1:00 S + Rule Port 1942 only - Apr 25 22:00s 2:00 M # Midsummer + Rule Port 1942 only - Aug 15 22:00s 1:00 S +@@ -2162,66 +2219,195 @@ Rule Port 1943 1945 - Aug Sat>=25 22:00s 1:00 S + Rule Port 1944 1945 - Apr Sat>=21 22:00s 2:00 M + Rule Port 1946 only - Apr Sat>=1 23:00s 1:00 S + Rule Port 1946 only - Oct Sat>=1 23:00s 0 - +-# Whitman says DST was not observed in 1950; go with Shanks & Pottenger. +-# Whitman gives Oct lastSun for 1952 on; go with Shanks & Pottenger. +-Rule Port 1947 1965 - Apr Sun>=1 2:00s 1:00 S ++# From Tim Parenti (2024-07-01), per Alois Treindl (2021-02-07): ++# The Astronomical Observatory of Lisbon cites Portaria 11767 of 1947-03-28 for ++# 1947 and Portaria 12286 of 1948-02-19 for 1948. ++# https://dre.pt/dr/detalhe/portaria/11767-1947-414787 ++# https://dre.pt/application/conteudo/414787 ++# https://dre.pt/dr/detalhe/portaria/12286-1948-152953 ++# https://dre.pt/application/conteudo/152953 ++# ++# Although the latter ordinance explicitly had the 1948-10-03 transition ++# scheduled for 02:00 rather than 03:00 as had been used in 1947, Decreto-Lei ++# 37048 of 1948-09-07 recognized "that it is advisable to definitely set...the ++# 'summer time' regime", and fixed the fall transition at 03:00 moving forward. ++# https://dre.pt/dr/detalhe/decreto-lei/37048-1948-373810 ++# https://dre.pt/application/conteudo/373810 ++# While the Observatory only cites this act for 1949-1965 and not for 1948, it ++# does not appear to have had any provision delaying its effect, so assume that ++# it overrode the prior ordinance for 1948-10-03. ++# ++# Whitman says DST was not observed in 1950 and gives Oct lastSun for 1952 on. ++# The Observatory, however, agrees with Shanks & Pottenger that 1950 was not an ++# exception and that Oct Sun>=1 was maintained through 1965. ++Rule Port 1947 1966 - Apr Sun>=1 2:00s 1:00 S + Rule Port 1947 1965 - Oct Sun>=1 2:00s 0 - +-Rule Port 1977 only - Mar 27 0:00s 1:00 S +-Rule Port 1977 only - Sep 25 0:00s 0 - +-Rule Port 1978 1979 - Apr Sun>=1 0:00s 1:00 S +-Rule Port 1978 only - Oct 1 0:00s 0 - +-Rule Port 1979 1982 - Sep lastSun 1:00s 0 - +-Rule Port 1980 only - Mar lastSun 0:00s 1:00 S +-Rule Port 1981 1982 - Mar lastSun 1:00s 1:00 S +-Rule Port 1983 only - Mar lastSun 2:00s 1:00 S ++# From Tim Parenti (2024-07-01): ++# Decreto-Lei 47233 of 1966-10-01 considered that the "duality" in time was ++# "the cause of serious disturbances" and noted that "the countries with which ++# we have the most frequent contacts...have already adopted" a solution ++# coinciding with the extant "summer time". It established that the former ++# "summer time" would apply year-round on the mainland and adjacent islands ++# with immediate effect, as the fall back would have otherwise occurred later ++# that evening. ++# https://dre.pt/dr/detalhe/decreto-lei/47233-1966-293729 ++# Model this by changing zones without changing clocks at the ++# previously-appointed fall back time. ++# ++# Decreto-Lei 309/76 of 1976-04-27 acknowledged that those international ++# contacts had returned to adopting seasonal times, and considered that the ++# year-round advancement "entails considerable sacrifices for the vast majority ++# of the working population during the winter months", including morning ++# visibility concerns for schoolchildren. It specified, beginning 1976-09-26 ++# 01:00, an annual return to UT+00 on the mainland from 00:00 UT on Sep lastSun ++# to 00:00 UT on Mar lastSun (unless the latter date fell on Easter, in which ++# case it was to be brought forward to the preceding Sunday). It also assigned ++# the Permanent Time Commission to study and propose revisions for the Azores ++# and Madeira, neither of which resumed DST until 1982 (as described further ++# below). ++# https://dre.pt/dr/detalhe/decreto-lei/309-1976-502063 ++Rule Port 1976 only - Sep lastSun 1:00 0 - ++Rule Port 1977 only - Mar lastSun 0:00s 1:00 S ++Rule Port 1977 only - Sep lastSun 0:00s 0 - ++# From Tim Parenti (2024-07-01): ++# Beginning in 1978, rather than triggering the Easter rule of the 1976 decree ++# (Easter fell on 1978-03-26), Article 5 was used instead, which allowed DST ++# dates to be changed by order of the Minister of Education and Scientific ++# Research, upon consultation with the Permanent Time Commission, "whenever ++# considered convenient." As such, a series of one-off ordinances were ++# promulgated for the mainland in 1978 through 1980, after which the 1976 ++# decree naturally came back into force from 1981. ++Rule Port 1978 1980 - Apr Sun>=1 1:00s 1:00 S ++Rule Port 1978 only - Oct 1 1:00s 0 - ++Rule Port 1979 1980 - Sep lastSun 1:00s 0 - ++Rule Port 1981 1986 - Mar lastSun 0:00s 1:00 S ++Rule Port 1981 1985 - Sep lastSun 0:00s 0 - ++# From Tim Parenti (2024-07-01): ++# Decreto-Lei 44-B/86 of 1986-03-07 switched mainland Portugal's transition ++# times from 0:00s to 1:00u to harmonize with the EEC from 1986-03-30. ++# https://dre.pt/dr/detalhe/decreto-lei/44-b-1986-628280 ++# (Transitions of 1:00s as previously reported and used by the W-Eur rules, ++# though equivalent, appear to have been fiction here.) Madeira continued to ++# use 0:00s for spring 1986 before joining with the mainland using 1:00u in the ++# fall; meanwhile, in the Azores the two were equivalent, so the law specifying ++# 0:00s wasn't touched until 1992. (See below for more on the islands.) ++# ++# From Rui Pedro Salgueiro (1992-11-12): ++# Portugal has recently (September, 27) changed timezone ++# (from WET to MET or CET) to harmonize with EEC. ++# ++# Martin Bruckmann (1996-02-29) reports via Peter Ilieve ++# that Portugal is reverting to 0:00 by not moving its clocks this spring. ++# The new Prime Minister was fed up with getting up in the dark in the winter. ++# ++# From Paul Eggert (1996-11-12): ++# IATA SSIM (1991-09) reports several 1991-09 and 1992-09 transitions ++# at 02:00u, not 01:00u. Assume that these are typos. + # + # 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 ++ 0:00 Port WE%sT 1966 Oct 2 2:00s + 1:00 - CET 1976 Sep 26 1:00 +- 0:00 Port WE%sT 1983 Sep 25 1:00s +- 0:00 W-Eur WE%sT 1992 Sep 27 1:00s ++ 0:00 Port WE%sT 1986 ++ 0:00 EU WE%sT 1992 Sep 27 1:00u + 1:00 EU CE%sT 1996 Mar 31 1:00u + 0:00 EU WE%sT ++ ++# From Tim Parenti (2024-07-01): ++# For the Azores and Madeira, legislation was followed from the laws currently ++# in force as listed at: ++# https://oal.ul.pt/hora-legal/legislacao/ ++# working backward through references of revocation and abrogation to ++# Decreto-Lei 47233 of 1966-10-01, the last time DST was abolished across the ++# mainland and its adjacent islands. Because of that reference, it is ++# therefore assumed that DST rules in the islands prior to 1966 were like that ++# of the mainland, though most legislation of the time didn't explicitly ++# specify DST practices for the islands. + 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 ++ -2:00 Port %z 1966 Oct 2 2:00s ++# From Tim Parenti (2024-07-01): ++# While Decreto-Lei 309/76 of 1976-04-27 reintroduced DST on the mainland by ++# falling back on 1976-09-26, it assigned the Permanent Time Commission to ++# study and propose revisions for the Azores and Madeira. Decreto Regional ++# 9/77/A of 1977-05-17 affirmed that "the legal time remained unchanged in the ++# Azores" at UT-1, and would remain there year-round. ++# https://dre.pt/dr/detalhe/decreto-regional/9-1977-252066 ++# ++# Decreto Regional 2/82/A, published 1982-03-02, adopted DST in the same ++# fashion as the mainland used at the time. ++# https://dre.pt/dr/detalhe/decreto-regional/2-1982-599965 ++# Though transitions in the Azores officially remained at 0:00s through 1992, ++# this was equivalent to the EU-style 1:00u adopted by the mainland in 1986, so ++# model it as such. ++ -1:00 - %z 1982 Mar 28 0:00s ++ -1:00 Port %z 1986 + # 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 +- -2:00 Port +00 1943 Aug 28 22:00s +- -2:00 Port -02/-01 1944 Apr 22 22:00s +- -2:00 Port +00 1944 Aug 26 22:00s +- -2:00 Port -02/-01 1945 Apr 21 22:00s +- -2:00 Port +00 1945 Aug 25 22:00s +- -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 ++# -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 ++# -2:00 Port +00 1943 Aug 28 22:00s ++# -2:00 Port -02/-01 1944 Apr 22 22:00s ++# -2:00 Port +00 1944 Aug 26 22:00s ++# -2:00 Port -02/-01 1945 Apr 21 22:00s ++# -2:00 Port +00 1945 Aug 25 22:00s ++# -2:00 Port -02/-01 1966 Oct 2 2:00s ++# -1:00 - -01 1982 Mar 28 0:00s ++# -1:00 Port -01/+00 1986 + # End of rearguard section. +- 0:00 EU WE%sT 1993 Mar 28 1:00u +- -1:00 EU -01/+00 ++# ++# From Paul Eggert (1996-11-12): ++# IATA SSIM (1991/1992) reports that the Azores were at -1:00. ++# IATA SSIM (1993-02) says +0:00; later issues (through 1996-09) say -1:00. ++# ++# From Tim Parenti (2024-07-01): ++# After mainland Portugal had shifted forward an hour from 1992-09-27, Decreto ++# Legislativo Regional 29/92/A of 1992-12-23 sought to "reduce the time ++# difference" by shifting the Azores forward as well from 1992-12-27. Just six ++# months later, this was revoked by Decreto Legislativo Regional 9/93/A, citing ++# "major changes in work habits and way of life." Though the revocation didn't ++# give a transition time, it was signed Wednesday 1993-06-16; assume it took ++# effect later that evening, and that an EU-style spring forward (to +01) was ++# still observed in the interim on 1993-03-28. ++# https://dre.pt/dr/detalhe/decreto-legislativo-regional/29-1992-621553 ++# https://dre.pt/dr/detalhe/decreto-legislativo-regional/9-1993-389633 ++ -1:00 EU %z 1992 Dec 27 1:00s ++ 0:00 EU WE%sT 1993 Jun 17 1:00u ++ -1:00 EU %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 ++ -1:00 Port %z 1966 Oct 2 2:00s + # 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 +- -1:00 Port +01 1943 Aug 28 22:00s +- -1:00 Port -01/+00 1944 Apr 22 22:00s +- -1:00 Port +01 1944 Aug 26 22:00s +- -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 ++# -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 ++# -1:00 Port +01 1943 Aug 28 22:00s ++# -1:00 Port -01/+00 1944 Apr 22 22:00s ++# -1:00 Port +01 1944 Aug 26 22:00s ++# -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 Oct 2 2:00s + # End of rearguard section. +- 0:00 Port WE%sT 1983 Sep 25 1:00s ++# ++# From Tim Parenti (2024-07-01): ++# Decreto Regional 5/82/M, published 1982-04-03, established DST transitions at ++# 0:00u, which for Madeira is equivalent to the mainland's rules (0:00s) at the ++# time. It came into effect the day following its publication, Sunday ++# 1982-04-04, thus resuming Madeira's DST practice about a week later than the ++# mainland and the Azores. ++# https://dre.pt/dr/detalhe/decreto-regional/5-1982-608273 ++# ++# Decreto Legislativo Regional 18/86/M, published 1986-10-01, adopted EU-style ++# rules (1:00u) and entered into immediate force after being signed on ++# 1986-07-31. ++# https://dre.pt/dr/detalhe/decreto-legislativo-regional/18-1986-221705 ++ 0:00 - WET 1982 Apr 4 ++ 0:00 Port WE%sT 1986 Jul 31 + 0:00 EU WE%sT + + # Romania +@@ -2433,7 +2619,7 @@ Zone Europe/Kaliningrad 1:22:00 - LMT 1893 Apr + 2:00 Poland EE%sT 1946 Apr 7 + 3:00 Russia MSK/MSD 1989 Mar 26 2:00s + 2:00 Russia EE%sT 2011 Mar 27 2:00s +- 3:00 - +03 2014 Oct 26 2:00s ++ 3:00 - %z 2014 Oct 26 2:00s + 2:00 - EET + + +@@ -2683,14 +2869,14 @@ Zone Europe/Simferopol 2:16:24 - LMT 1880 + # http://publication.pravo.gov.ru/Document/View/0001201602150056 + + Zone Europe/Astrakhan 3:12:12 - LMT 1924 May +- 3:00 - +03 1930 Jun 21 +- 4:00 Russia +04/+05 1989 Mar 26 2:00s +- 3:00 Russia +03/+04 1991 Mar 31 2:00s +- 4:00 - +04 1992 Mar 29 2:00s +- 3:00 Russia +03/+04 2011 Mar 27 2:00s +- 4:00 - +04 2014 Oct 26 2:00s +- 3:00 - +03 2016 Mar 27 2:00s +- 4:00 - +04 ++ 3:00 - %z 1930 Jun 21 ++ 4:00 Russia %z 1989 Mar 26 2:00s ++ 3:00 Russia %z 1991 Mar 31 2:00s ++ 4:00 - %z 1992 Mar 29 2:00s ++ 3:00 Russia %z 2011 Mar 27 2:00s ++ 4:00 - %z 2014 Oct 26 2:00s ++ 3:00 - %z 2016 Mar 27 2:00s ++ 4:00 - %z + + # From Paul Eggert (2016-11-11): + # Europe/Volgograd covers: +@@ -2720,15 +2906,15 @@ Zone Europe/Astrakhan 3:12:12 - LMT 1924 May + # http://publication.pravo.gov.ru/Document/View/0001202012220002 + + Zone Europe/Volgograd 2:57:40 - LMT 1920 Jan 3 +- 3:00 - +03 1930 Jun 21 +- 4:00 - +04 1961 Nov 11 +- 4:00 Russia +04/+05 1988 Mar 27 2:00s ++ 3:00 - %z 1930 Jun 21 ++ 4:00 - %z 1961 Nov 11 ++ 4:00 Russia %z 1988 Mar 27 2:00s + 3:00 Russia MSK/MSD 1991 Mar 31 2:00s +- 4:00 - +04 1992 Mar 29 2:00s ++ 4:00 - %z 1992 Mar 29 2:00s + 3:00 Russia MSK/MSD 2011 Mar 27 2:00s + 4:00 - MSK 2014 Oct 26 2:00s + 3:00 - MSK 2018 Oct 28 2:00s +- 4:00 - +04 2020 Dec 27 2:00s ++ 4:00 - %z 2020 Dec 27 2:00s + 3:00 - MSK + + # From Paul Eggert (2016-11-11): +@@ -2743,14 +2929,14 @@ Zone Europe/Volgograd 2:57:40 - LMT 1920 Jan 3 + # http://publication.pravo.gov.ru/Document/View/0001201611220031 + + Zone Europe/Saratov 3:04:18 - LMT 1919 Jul 1 0:00u +- 3:00 - +03 1930 Jun 21 +- 4:00 Russia +04/+05 1988 Mar 27 2:00s +- 3:00 Russia +03/+04 1991 Mar 31 2:00s +- 4:00 - +04 1992 Mar 29 2:00s +- 3:00 Russia +03/+04 2011 Mar 27 2:00s +- 4:00 - +04 2014 Oct 26 2:00s +- 3:00 - +03 2016 Dec 4 2:00s +- 4:00 - +04 ++ 3:00 - %z 1930 Jun 21 ++ 4:00 Russia %z 1988 Mar 27 2:00s ++ 3:00 Russia %z 1991 Mar 31 2:00s ++ 4:00 - %z 1992 Mar 29 2:00s ++ 3:00 Russia %z 2011 Mar 27 2:00s ++ 4:00 - %z 2014 Oct 26 2:00s ++ 3:00 - %z 2016 Dec 4 2:00s ++ 4:00 - %z + + # From Paul Eggert (2016-03-18): + # Europe/Kirov covers: +@@ -2758,10 +2944,10 @@ Zone Europe/Saratov 3:04:18 - LMT 1919 Jul 1 0:00u + # The 1989 transition is from USSR act No. 227 (1989-03-14). + # + Zone Europe/Kirov 3:18:48 - LMT 1919 Jul 1 0:00u +- 3:00 - +03 1930 Jun 21 +- 4:00 Russia +04/+05 1989 Mar 26 2:00s ++ 3:00 - %z 1930 Jun 21 ++ 4:00 Russia %z 1989 Mar 26 2:00s + 3:00 Russia MSK/MSD 1991 Mar 31 2:00s +- 4:00 - +04 1992 Mar 29 2:00s ++ 4:00 - %z 1992 Mar 29 2:00s + 3:00 Russia MSK/MSD 2011 Mar 27 2:00s + 4:00 - MSK 2014 Oct 26 2:00s + 3:00 - MSK +@@ -2776,15 +2962,15 @@ Zone Europe/Kirov 3:18:48 - LMT 1919 Jul 1 0:00u + # The 1989 transition is from USSR act No. 227 (1989-03-14). + + Zone Europe/Samara 3:20:20 - LMT 1919 Jul 1 0:00u +- 3:00 - +03 1930 Jun 21 +- 4:00 - +04 1935 Jan 27 +- 4:00 Russia +04/+05 1989 Mar 26 2:00s +- 3:00 Russia +03/+04 1991 Mar 31 2:00s +- 2:00 Russia +02/+03 1991 Sep 29 2:00s +- 3:00 - +03 1991 Oct 20 3:00 +- 4:00 Russia +04/+05 2010 Mar 28 2:00s +- 3:00 Russia +03/+04 2011 Mar 27 2:00s +- 4:00 - +04 ++ 3:00 - %z 1930 Jun 21 ++ 4:00 - %z 1935 Jan 27 ++ 4:00 Russia %z 1989 Mar 26 2:00s ++ 3:00 Russia %z 1991 Mar 31 2:00s ++ 2:00 Russia %z 1991 Sep 29 2:00s ++ 3:00 - %z 1991 Oct 20 3:00 ++ 4:00 Russia %z 2010 Mar 28 2:00s ++ 3:00 Russia %z 2011 Mar 27 2:00s ++ 4:00 - %z + + # From Paul Eggert (2016-03-18): + # Europe/Ulyanovsk covers: +@@ -2800,14 +2986,14 @@ Zone Europe/Samara 3:20:20 - LMT 1919 Jul 1 0:00u + # http://publication.pravo.gov.ru/Document/View/0001201603090051 + + Zone Europe/Ulyanovsk 3:13:36 - LMT 1919 Jul 1 0:00u +- 3:00 - +03 1930 Jun 21 +- 4:00 Russia +04/+05 1989 Mar 26 2:00s +- 3:00 Russia +03/+04 1991 Mar 31 2:00s +- 2:00 Russia +02/+03 1992 Jan 19 2:00s +- 3:00 Russia +03/+04 2011 Mar 27 2:00s +- 4:00 - +04 2014 Oct 26 2:00s +- 3:00 - +03 2016 Mar 27 2:00s +- 4:00 - +04 ++ 3:00 - %z 1930 Jun 21 ++ 4:00 Russia %z 1989 Mar 26 2:00s ++ 3:00 Russia %z 1991 Mar 31 2:00s ++ 2:00 Russia %z 1992 Jan 19 2:00s ++ 3:00 Russia %z 2011 Mar 27 2:00s ++ 4:00 - %z 2014 Oct 26 2:00s ++ 3:00 - %z 2016 Mar 27 2:00s ++ 4:00 - %z + + # From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2001-08-25): + # Asia/Yekaterinburg covers... +@@ -2832,12 +3018,12 @@ Zone Europe/Ulyanovsk 3:13:36 - LMT 1919 Jul 1 0:00u + #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 +- 5:00 Russia +05/+06 1991 Mar 31 2:00s +- 4:00 Russia +04/+05 1992 Jan 19 2:00s +- 5:00 Russia +05/+06 2011 Mar 27 2:00s +- 6:00 - +06 2014 Oct 26 2:00s +- 5:00 - +05 ++ 4:00 - %z 1930 Jun 21 ++ 5:00 Russia %z 1991 Mar 31 2:00s ++ 4:00 Russia %z 1992 Jan 19 2:00s ++ 5:00 Russia %z 2011 Mar 27 2:00s ++ 6:00 - %z 2014 Oct 26 2:00s ++ 5:00 - %z + + + # From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2001-08-25): +@@ -2847,12 +3033,12 @@ Zone Asia/Yekaterinburg 4:02:33 - LMT 1916 Jul 3 + # Byalokoz 1919 says Omsk was 4:53:30. + + Zone Asia/Omsk 4:53:30 - LMT 1919 Nov 14 +- 5:00 - +05 1930 Jun 21 +- 6:00 Russia +06/+07 1991 Mar 31 2:00s +- 5:00 Russia +05/+06 1992 Jan 19 2:00s +- 6:00 Russia +06/+07 2011 Mar 27 2:00s +- 7:00 - +07 2014 Oct 26 2:00s +- 6:00 - +06 ++ 5:00 - %z 1930 Jun 21 ++ 6:00 Russia %z 1991 Mar 31 2:00s ++ 5:00 Russia %z 1992 Jan 19 2:00s ++ 6:00 Russia %z 2011 Mar 27 2:00s ++ 7:00 - %z 2014 Oct 26 2:00s ++ 6:00 - %z + + # From Paul Eggert (2016-02-22): + # Asia/Barnaul covers: +@@ -2885,14 +3071,14 @@ Zone Asia/Omsk 4:53:30 - LMT 1919 Nov 14 + # http://publication.pravo.gov.ru/Document/View/0001201603090038 + + Zone Asia/Barnaul 5:35:00 - LMT 1919 Dec 10 +- 6:00 - +06 1930 Jun 21 +- 7:00 Russia +07/+08 1991 Mar 31 2:00s +- 6:00 Russia +06/+07 1992 Jan 19 2:00s +- 7:00 Russia +07/+08 1995 May 28 +- 6:00 Russia +06/+07 2011 Mar 27 2:00s +- 7:00 - +07 2014 Oct 26 2:00s +- 6:00 - +06 2016 Mar 27 2:00s +- 7:00 - +07 ++ 6:00 - %z 1930 Jun 21 ++ 7:00 Russia %z 1991 Mar 31 2:00s ++ 6:00 Russia %z 1992 Jan 19 2:00s ++ 7:00 Russia %z 1995 May 28 ++ 6:00 Russia %z 2011 Mar 27 2:00s ++ 7:00 - %z 2014 Oct 26 2:00s ++ 6:00 - %z 2016 Mar 27 2:00s ++ 7:00 - %z + + # From Paul Eggert (2016-03-18): + # Asia/Novosibirsk covers: +@@ -2906,14 +3092,14 @@ Zone Asia/Barnaul 5:35:00 - LMT 1919 Dec 10 + # http://publication.pravo.gov.ru/Document/View/0001201607040064 + + Zone Asia/Novosibirsk 5:31:40 - LMT 1919 Dec 14 6:00 +- 6:00 - +06 1930 Jun 21 +- 7:00 Russia +07/+08 1991 Mar 31 2:00s +- 6:00 Russia +06/+07 1992 Jan 19 2:00s +- 7:00 Russia +07/+08 1993 May 23 # say Shanks & P. +- 6:00 Russia +06/+07 2011 Mar 27 2:00s +- 7:00 - +07 2014 Oct 26 2:00s +- 6:00 - +06 2016 Jul 24 2:00s +- 7:00 - +07 ++ 6:00 - %z 1930 Jun 21 ++ 7:00 Russia %z 1991 Mar 31 2:00s ++ 6:00 Russia %z 1992 Jan 19 2:00s ++ 7:00 Russia %z 1993 May 23 # say Shanks & P. ++ 6:00 Russia %z 2011 Mar 27 2:00s ++ 7:00 - %z 2014 Oct 26 2:00s ++ 6:00 - %z 2016 Jul 24 2:00s ++ 7:00 - %z + + # From Paul Eggert (2016-03-18): + # Asia/Tomsk covers: +@@ -2958,14 +3144,14 @@ Zone Asia/Novosibirsk 5:31:40 - LMT 1919 Dec 14 6:00 + # http://publication.pravo.gov.ru/Document/View/0001201604260048 + + Zone Asia/Tomsk 5:39:51 - LMT 1919 Dec 22 +- 6:00 - +06 1930 Jun 21 +- 7:00 Russia +07/+08 1991 Mar 31 2:00s +- 6:00 Russia +06/+07 1992 Jan 19 2:00s +- 7:00 Russia +07/+08 2002 May 1 3:00 +- 6:00 Russia +06/+07 2011 Mar 27 2:00s +- 7:00 - +07 2014 Oct 26 2:00s +- 6:00 - +06 2016 May 29 2:00s +- 7:00 - +07 ++ 6:00 - %z 1930 Jun 21 ++ 7:00 Russia %z 1991 Mar 31 2:00s ++ 6:00 Russia %z 1992 Jan 19 2:00s ++ 7:00 Russia %z 2002 May 1 3:00 ++ 6:00 Russia %z 2011 Mar 27 2:00s ++ 7:00 - %z 2014 Oct 26 2:00s ++ 6:00 - %z 2016 May 29 2:00s ++ 7:00 - %z + + + # From Tim Parenti (2014-07-03): +@@ -2996,12 +3182,12 @@ Zone Asia/Tomsk 5:39:51 - LMT 1919 Dec 22 + # realigning itself with KRAT. + + Zone Asia/Novokuznetsk 5:48:48 - LMT 1924 May 1 +- 6:00 - +06 1930 Jun 21 +- 7:00 Russia +07/+08 1991 Mar 31 2:00s +- 6:00 Russia +06/+07 1992 Jan 19 2:00s +- 7:00 Russia +07/+08 2010 Mar 28 2:00s +- 6:00 Russia +06/+07 2011 Mar 27 2:00s +- 7:00 - +07 ++ 6:00 - %z 1930 Jun 21 ++ 7:00 Russia %z 1991 Mar 31 2:00s ++ 6:00 Russia %z 1992 Jan 19 2:00s ++ 7:00 Russia %z 2010 Mar 28 2:00s ++ 6:00 Russia %z 2011 Mar 27 2:00s ++ 7:00 - %z + + # From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2001-08-25): + # Asia/Krasnoyarsk covers... +@@ -3015,12 +3201,12 @@ Zone Asia/Novokuznetsk 5:48:48 - LMT 1924 May 1 + # Byalokoz 1919 says Krasnoyarsk was 6:11:26. + + Zone Asia/Krasnoyarsk 6:11:26 - LMT 1920 Jan 6 +- 6:00 - +06 1930 Jun 21 +- 7:00 Russia +07/+08 1991 Mar 31 2:00s +- 6:00 Russia +06/+07 1992 Jan 19 2:00s +- 7:00 Russia +07/+08 2011 Mar 27 2:00s +- 8:00 - +08 2014 Oct 26 2:00s +- 7:00 - +07 ++ 6:00 - %z 1930 Jun 21 ++ 7:00 Russia %z 1991 Mar 31 2:00s ++ 6:00 Russia %z 1992 Jan 19 2:00s ++ 7:00 Russia %z 2011 Mar 27 2:00s ++ 8:00 - %z 2014 Oct 26 2:00s ++ 7:00 - %z + + + # From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2001-08-25): +@@ -3037,12 +3223,12 @@ Zone Asia/Krasnoyarsk 6:11:26 - LMT 1920 Jan 6 + + Zone Asia/Irkutsk 6:57:05 - LMT 1880 + 6:57:05 - IMT 1920 Jan 25 # Irkutsk Mean Time +- 7:00 - +07 1930 Jun 21 +- 8:00 Russia +08/+09 1991 Mar 31 2:00s +- 7:00 Russia +07/+08 1992 Jan 19 2:00s +- 8:00 Russia +08/+09 2011 Mar 27 2:00s +- 9:00 - +09 2014 Oct 26 2:00s +- 8:00 - +08 ++ 7:00 - %z 1930 Jun 21 ++ 8:00 Russia %z 1991 Mar 31 2:00s ++ 7:00 Russia %z 1992 Jan 19 2:00s ++ 8:00 Russia %z 2011 Mar 27 2:00s ++ 9:00 - %z 2014 Oct 26 2:00s ++ 8:00 - %z + + + # From Tim Parenti (2014-07-06): +@@ -3059,13 +3245,13 @@ Zone Asia/Irkutsk 6:57:05 - LMT 1880 + # http://publication.pravo.gov.ru/Document/View/0001201512300107 + + Zone Asia/Chita 7:33:52 - LMT 1919 Dec 15 +- 8:00 - +08 1930 Jun 21 +- 9:00 Russia +09/+10 1991 Mar 31 2:00s +- 8:00 Russia +08/+09 1992 Jan 19 2:00s +- 9:00 Russia +09/+10 2011 Mar 27 2:00s +- 10:00 - +10 2014 Oct 26 2:00s +- 8:00 - +08 2016 Mar 27 2:00 +- 9:00 - +09 ++ 8:00 - %z 1930 Jun 21 ++ 9:00 Russia %z 1991 Mar 31 2:00s ++ 8:00 Russia %z 1992 Jan 19 2:00s ++ 9:00 Russia %z 2011 Mar 27 2:00s ++ 10:00 - %z 2014 Oct 26 2:00s ++ 8:00 - %z 2016 Mar 27 2:00 ++ 9:00 - %z + + + # From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2009-11-29): +@@ -3105,12 +3291,12 @@ Zone Asia/Chita 7:33:52 - LMT 1919 Dec 15 + # Byalokoz 1919 says Yakutsk was 8:38:58. + + Zone Asia/Yakutsk 8:38:58 - LMT 1919 Dec 15 +- 8:00 - +08 1930 Jun 21 +- 9:00 Russia +09/+10 1991 Mar 31 2:00s +- 8:00 Russia +08/+09 1992 Jan 19 2:00s +- 9:00 Russia +09/+10 2011 Mar 27 2:00s +- 10:00 - +10 2014 Oct 26 2:00s +- 9:00 - +09 ++ 8:00 - %z 1930 Jun 21 ++ 9:00 Russia %z 1991 Mar 31 2:00s ++ 8:00 Russia %z 1992 Jan 19 2:00s ++ 9:00 Russia %z 2011 Mar 27 2:00s ++ 10:00 - %z 2014 Oct 26 2:00s ++ 9:00 - %z + + + # From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2009-11-29): +@@ -3128,12 +3314,12 @@ Zone Asia/Yakutsk 8:38:58 - LMT 1919 Dec 15 + # Go with Byalokoz. + + Zone Asia/Vladivostok 8:47:31 - LMT 1922 Nov 15 +- 9:00 - +09 1930 Jun 21 +- 10:00 Russia +10/+11 1991 Mar 31 2:00s +- 9:00 Russia +09/+10 1992 Jan 19 2:00s +- 10:00 Russia +10/+11 2011 Mar 27 2:00s +- 11:00 - +11 2014 Oct 26 2:00s +- 10:00 - +10 ++ 9:00 - %z 1930 Jun 21 ++ 10:00 Russia %z 1991 Mar 31 2:00s ++ 9:00 Russia %z 1992 Jan 19 2:00s ++ 10:00 Russia %z 2011 Mar 27 2:00s ++ 11:00 - %z 2014 Oct 26 2:00s ++ 10:00 - %z + + + # From Tim Parenti (2014-07-03): +@@ -3151,14 +3337,14 @@ Zone Asia/Vladivostok 8:47:31 - LMT 1922 Nov 15 + # This transition is no doubt wrong, but we have no better info. + + Zone Asia/Khandyga 9:02:13 - LMT 1919 Dec 15 +- 8:00 - +08 1930 Jun 21 +- 9:00 Russia +09/+10 1991 Mar 31 2:00s +- 8:00 Russia +08/+09 1992 Jan 19 2:00s +- 9:00 Russia +09/+10 2004 +- 10:00 Russia +10/+11 2011 Mar 27 2:00s +- 11:00 - +11 2011 Sep 13 0:00s # Decree 725? +- 10:00 - +10 2014 Oct 26 2:00s +- 9:00 - +09 ++ 8:00 - %z 1930 Jun 21 ++ 9:00 Russia %z 1991 Mar 31 2:00s ++ 8:00 Russia %z 1992 Jan 19 2:00s ++ 9:00 Russia %z 2004 ++ 10:00 Russia %z 2011 Mar 27 2:00s ++ 11:00 - %z 2011 Sep 13 0:00s # Decree 725? ++ 10:00 - %z 2014 Oct 26 2:00s ++ 9:00 - %z + + + # From Tim Parenti (2014-07-03): +@@ -3174,14 +3360,14 @@ Zone Asia/Khandyga 9:02:13 - LMT 1919 Dec 15 + + # The Zone name should be Asia/Yuzhno-Sakhalinsk, but that's too long. + Zone Asia/Sakhalin 9:30:48 - LMT 1905 Aug 23 +- 9:00 - +09 1945 Aug 25 +- 11:00 Russia +11/+12 1991 Mar 31 2:00s # Sakhalin T +- 10:00 Russia +10/+11 1992 Jan 19 2:00s +- 11:00 Russia +11/+12 1997 Mar lastSun 2:00s +- 10:00 Russia +10/+11 2011 Mar 27 2:00s +- 11:00 - +11 2014 Oct 26 2:00s +- 10:00 - +10 2016 Mar 27 2:00s +- 11:00 - +11 ++ 9:00 - %z 1945 Aug 25 ++ 11:00 Russia %z 1991 Mar 31 2:00s # Sakhalin T ++ 10:00 Russia %z 1992 Jan 19 2:00s ++ 11:00 Russia %z 1997 Mar lastSun 2:00s ++ 10:00 Russia %z 2011 Mar 27 2:00s ++ 11:00 - %z 2014 Oct 26 2:00s ++ 10:00 - %z 2016 Mar 27 2:00s ++ 11:00 - %z + + + # From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2009-11-29): +@@ -3204,13 +3390,13 @@ Zone Asia/Sakhalin 9:30:48 - LMT 1905 Aug 23 + # http://publication.pravo.gov.ru/Document/View/0001201604050038 + + Zone Asia/Magadan 10:03:12 - LMT 1924 May 2 +- 10:00 - +10 1930 Jun 21 # Magadan Time +- 11:00 Russia +11/+12 1991 Mar 31 2:00s +- 10:00 Russia +10/+11 1992 Jan 19 2:00s +- 11:00 Russia +11/+12 2011 Mar 27 2:00s +- 12:00 - +12 2014 Oct 26 2:00s +- 10:00 - +10 2016 Apr 24 2:00s +- 11:00 - +11 ++ 10:00 - %z 1930 Jun 21 # Magadan Time ++ 11:00 Russia %z 1991 Mar 31 2:00s ++ 10:00 Russia %z 1992 Jan 19 2:00s ++ 11:00 Russia %z 2011 Mar 27 2:00s ++ 12:00 - %z 2014 Oct 26 2:00s ++ 10:00 - %z 2016 Apr 24 2:00s ++ 11:00 - %z + + + # From Tim Parenti (2014-07-06): +@@ -3255,12 +3441,12 @@ Zone Asia/Magadan 10:03:12 - LMT 1924 May 2 + # Go with Srednekolymsk. + + Zone Asia/Srednekolymsk 10:14:52 - LMT 1924 May 2 +- 10:00 - +10 1930 Jun 21 +- 11:00 Russia +11/+12 1991 Mar 31 2:00s +- 10:00 Russia +10/+11 1992 Jan 19 2:00s +- 11:00 Russia +11/+12 2011 Mar 27 2:00s +- 12:00 - +12 2014 Oct 26 2:00s +- 11:00 - +11 ++ 10:00 - %z 1930 Jun 21 ++ 11:00 Russia %z 1991 Mar 31 2:00s ++ 10:00 Russia %z 1992 Jan 19 2:00s ++ 11:00 Russia %z 2011 Mar 27 2:00s ++ 12:00 - %z 2014 Oct 26 2:00s ++ 11:00 - %z + + + # From Tim Parenti (2014-07-03): +@@ -3278,14 +3464,14 @@ Zone Asia/Srednekolymsk 10:14:52 - LMT 1924 May 2 + # UTC+12 since at least then, too. + + Zone Asia/Ust-Nera 9:32:54 - LMT 1919 Dec 15 +- 8:00 - +08 1930 Jun 21 +- 9:00 Russia +09/+10 1981 Apr 1 +- 11:00 Russia +11/+12 1991 Mar 31 2:00s +- 10:00 Russia +10/+11 1992 Jan 19 2:00s +- 11:00 Russia +11/+12 2011 Mar 27 2:00s +- 12:00 - +12 2011 Sep 13 0:00s # Decree 725? +- 11:00 - +11 2014 Oct 26 2:00s +- 10:00 - +10 ++ 8:00 - %z 1930 Jun 21 ++ 9:00 Russia %z 1981 Apr 1 ++ 11:00 Russia %z 1991 Mar 31 2:00s ++ 10:00 Russia %z 1992 Jan 19 2:00s ++ 11:00 Russia %z 2011 Mar 27 2:00s ++ 12:00 - %z 2011 Sep 13 0:00s # Decree 725? ++ 11:00 - %z 2014 Oct 26 2:00s ++ 10:00 - %z + + + # From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2001-08-25): +@@ -3298,12 +3484,12 @@ Zone Asia/Ust-Nera 9:32:54 - LMT 1919 Dec 15 + # The Zone name should be Asia/Petropavlovsk-Kamchatski or perhaps + # Asia/Petropavlovsk-Kamchatsky, but these are too long. + Zone Asia/Kamchatka 10:34:36 - LMT 1922 Nov 10 +- 11:00 - +11 1930 Jun 21 +- 12:00 Russia +12/+13 1991 Mar 31 2:00s +- 11:00 Russia +11/+12 1992 Jan 19 2:00s +- 12:00 Russia +12/+13 2010 Mar 28 2:00s +- 11:00 Russia +11/+12 2011 Mar 27 2:00s +- 12:00 - +12 ++ 11:00 - %z 1930 Jun 21 ++ 12:00 Russia %z 1991 Mar 31 2:00s ++ 11:00 Russia %z 1992 Jan 19 2:00s ++ 12:00 Russia %z 2010 Mar 28 2:00s ++ 11:00 Russia %z 2011 Mar 27 2:00s ++ 12:00 - %z + + + # From Tim Parenti (2014-07-03): +@@ -3311,13 +3497,13 @@ Zone Asia/Kamchatka 10:34:36 - LMT 1922 Nov 10 + # 87 RU-CHU Chukotka Autonomous Okrug + + Zone Asia/Anadyr 11:49:56 - LMT 1924 May 2 +- 12:00 - +12 1930 Jun 21 +- 13:00 Russia +13/+14 1982 Apr 1 0:00s +- 12:00 Russia +12/+13 1991 Mar 31 2:00s +- 11:00 Russia +11/+12 1992 Jan 19 2:00s +- 12:00 Russia +12/+13 2010 Mar 28 2:00s +- 11:00 Russia +11/+12 2011 Mar 27 2:00s +- 12:00 - +12 ++ 12:00 - %z 1930 Jun 21 ++ 13:00 Russia %z 1982 Apr 1 0:00s ++ 12:00 Russia %z 1991 Mar 31 2:00s ++ 11:00 Russia %z 1992 Jan 19 2:00s ++ 12:00 Russia %z 2010 Mar 28 2:00s ++ 11:00 Russia %z 2011 Mar 27 2:00s ++ 12:00 - %z + + # Bosnia & Herzegovina + # Croatia +@@ -3436,7 +3622,7 @@ Zone Africa/Ceuta -0:21:16 - LMT 1901 Jan 1 0:00u + 1:00 - CET 1986 + 1:00 EU CE%sT + Zone Atlantic/Canary -1:01:36 - LMT 1922 Mar # Las Palmas de Gran C. +- -1:00 - -01 1946 Sep 30 1:00 ++ -1:00 - %z 1946 Sep 30 1:00 + 0:00 - WET 1980 Apr 6 0:00s + 0:00 1:00 WEST 1980 Sep 28 1:00u + 0:00 EU WE%sT +@@ -3517,8 +3703,8 @@ Zone Atlantic/Canary -1:01:36 - LMT 1922 Mar # Las Palmas de Gran C. + # but if no one is present after 11 at night, could be postponed until one + # hour before the beginning of service. + +-# From Paul Eggert (2013-09-11): +-# Round BMT to the nearest even second, 0:29:46. ++# From Paul Eggert (2024-05-24): ++# Express BMT as 0:29:45.500, approximately the same precision 7° 26' 22.50". + # + # We can find no reliable source for Shanks's assertion that all of Switzerland + # except Geneva switched to Bern Mean Time at 00:00 on 1848-09-12. This book: +@@ -3557,6 +3743,7 @@ Rule Swiss 1941 1942 - May Mon>=1 1:00 1:00 S + Rule Swiss 1941 1942 - Oct Mon>=1 2:00 0 - + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone Europe/Zurich 0:34:08 - LMT 1853 Jul 16 # See above comment. ++ #STDOFF 0:29:45.500 + 0:29:46 - BMT 1894 Jun # Bern Mean Time + 1:00 Swiss CE%sT 1981 + 1:00 EU CE%sT +@@ -3754,7 +3941,7 @@ Rule Turkey 1996 2006 - Oct lastSun 1:00s 0 - + Zone Europe/Istanbul 1:55:52 - LMT 1880 + 1:56:56 - IMT 1910 Oct # Istanbul Mean Time? + 2:00 Turkey EE%sT 1978 Jun 29 +- 3:00 Turkey +03/+04 1984 Nov 1 2:00 ++ 3:00 Turkey %z 1984 Nov 1 2:00 + 2:00 Turkey EE%sT 2007 + 2:00 EU EE%sT 2011 Mar 27 1:00u + 2:00 - EET 2011 Mar 28 1:00u +@@ -3763,7 +3950,7 @@ Zone Europe/Istanbul 1:55:52 - LMT 1880 + 2:00 EU EE%sT 2015 Oct 25 1:00u + 2:00 1:00 EEST 2015 Nov 8 1:00u + 2:00 EU EE%sT 2016 Sep 7 +- 3:00 - +03 ++ 3:00 - %z + + # Ukraine + # +diff --git a/make/data/tzdata/factory b/make/data/tzdata/factory +index a05346a30..e5e7d88f5 100644 +--- a/make/data/tzdata/factory ++++ b/make/data/tzdata/factory +@@ -31,5 +31,15 @@ + # time zone abbreviation "-00", indicating that the actual time zone + # is unknown. + ++# TZ="Factory" was added to TZDB in 1989, and in 2016 its abbreviation ++# was changed to "-00" from a longish English-language error message. ++# Around 2010, CLDR added "Etc/Unknown" for use with TZDB, to stand ++# for an unknown or invalid time zone. These two notions differ: ++# TZ="Factory" is a valid timezone, so tzalloc("Factory") succeeds, whereas ++# TZ="Etc/Unknown" is invalid and tzalloc("Etc/Unknown") fails. ++# Also, a downstream distributor could modify Factory to be a ++# default timezone suitable for the devices it manufactures, ++# whereas that cannot happen for Etc/Unknown. ++ + # Zone NAME STDOFF RULES FORMAT + Zone Factory 0 - -00 +diff --git a/make/data/tzdata/leapseconds b/make/data/tzdata/leapseconds +index 8e7df3de9..042a32b05 100644 +--- a/make/data/tzdata/leapseconds ++++ b/make/data/tzdata/leapseconds +@@ -92,11 +92,11 @@ Leap 2016 Dec 31 23:59:60 + S + # 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 2024 Dec 28 00:00:00 ++#Expires 2025 Dec 28 00:00:00 + + # POSIX timestamps for the data in this file: +-#updated 1704708379 (2024-01-08 10:06:19 UTC) +-#expires 1735344000 (2024-12-28 00:00:00 UTC) ++#updated 1736208000 (2025-01-07 00:00:00 UTC) ++#expires 1766880000 (2025-12-28 00:00:00 UTC) + + # Updated through IERS Bulletin C (https://hpiers.obspm.fr/iers/bul/bulc/bulletinc.dat) +-# File expires on 28 December 2024 ++# File expires on 28 December 2025 +diff --git a/make/data/tzdata/northamerica b/make/data/tzdata/northamerica +index a8b2ef3f7..21f178ee8 100644 +--- a/make/data/tzdata/northamerica ++++ b/make/data/tzdata/northamerica +@@ -50,9 +50,12 @@ + # in New York City (1869-10). His 1870 proposal was based on Washington, DC, + # but in 1872-05 he moved the proposed origin to Greenwich. + +-# From Paul Eggert (2018-03-20): ++# From Paul Eggert (2024-11-18): + # Dowd's proposal left many details unresolved, such as where to draw +-# lines between time zones. The key individual who made time zones ++# lines between time zones. Sandford Fleming of the Canadian Pacific Railway ++# argued for Dowd's proposal in 1876, and Cleveland Abbe of the American ++# Meteorology Society published a report in 1879 recommending four US time ++# zones based on GMT. However, the key individual who made time zones + # work in the US was William Frederick Allen - railway engineer, + # managing editor of the Travelers' Guide, and secretary of the + # General Time Convention, a railway standardization group. Allen +@@ -208,26 +211,6 @@ Rule US 1987 2006 - Apr Sun>=1 2:00 1:00 D + Rule US 2007 max - Mar Sun>=8 2:00 1:00 D + Rule US 2007 max - Nov Sun>=1 2:00 0 S + +-# From Arthur David Olson, 2005-12-19 +-# We generate the files specified below to guard against old files with +-# obsolete information being left in the time zone binary directory. +-# We limit the list to names that have appeared in previous versions of +-# this time zone package. +-# We do these as separate Zones rather than as Links to avoid problems if +-# a particular place changes whether it observes DST. +-# We put these specifications here in the northamerica file both to +-# increase the chances that they'll actually get compiled and to +-# avoid the need to duplicate the US rules in another file. +- +-# Zone NAME STDOFF RULES FORMAT [UNTIL] +-Zone EST -5:00 - EST +-Zone MST -7:00 - MST +-Zone HST -10:00 - HST +-Zone EST5EDT -5:00 US E%sT +-Zone CST6CDT -6:00 US C%sT +-Zone MST7MDT -7:00 US M%sT +-Zone PST8PDT -8:00 US P%sT +- + # From U. S. Naval Observatory (1989-01-19): + # USA EASTERN 5 H BEHIND UTC NEW YORK, WASHINGTON + # USA EASTERN 4 H BEHIND UTC APR 3 - OCT 30 +@@ -1651,6 +1634,15 @@ Zone America/Moncton -4:19:08 - LMT 1883 Dec 9 + # For more on Orillia, see: Daubs K. Bold attempt at daylight saving + # time became a comic failure in Orillia. Toronto Star 2017-07-08. + # https://www.thestar.com/news/insight/2017/07/08/bold-attempt-at-daylight-saving-time-became-a-comic-failure-in-orillia.html ++# From Paul Eggert (2025-03-20): ++# Also see the 1912-06-17 front page of The Evening Sunbeam, ++# reproduced in: Richardson M. "Daylight saving was a confusing ++# time in Orillia" in the 2025-03-15 Orillia Matters. Richardson writes, ++# "The first Sunday after the switch was made, [DST proponent and ++# Orillia mayor William Sword] Frost walked into church an hour late. ++# This became a symbol of the downfall of daylight saving in Orillia." ++# The mayor became known as "Daylight Bill". ++# https://www.orilliamatters.com/local-news/column-daylight-saving-was-a-confusing-time-in-orillia-10377529 + + # From Mark Brader (2010-03-06): + # +@@ -2396,6 +2388,81 @@ Zone America/Dawson -9:17:40 - LMT 1900 Aug 20 + # the researchers who prepared the Decrees page failed to find some of + # the relevant documents. + ++# From Heitor David Pinto (2024-08-04): ++# In 1931, the decree implementing DST specified that it would take ++# effect on 30 April.... ++# https://www.dof.gob.mx/nota_to_imagen_fs.php?cod_diario=192270&pagina=2&seccion=1 ++# ++# In 1981, the decree changing Campeche, Yucatán and Quintana Roo to UTC-5 ++# specified that it would enter into force on 26 December 1981 at 2:00.... ++# https://www.dof.gob.mx/nota_to_imagen_fs.php?codnota=4705667&fecha=23/12/1981&cod_diario=202796 ++# ++# In 1982, the decree returning Campeche and Yucatán to UTC-6 specified that ++# it would enter into force on 2 November 1982 at 2:00.... ++# https://www.dof.gob.mx/nota_to_imagen_fs.php?cod_diario=205689&pagina=3&seccion=0 ++# ++# Quintana Roo changed to UTC-6 on 4 January 1983 at 0:00, and again ++# to UTC-5 on 26 October 1997 at 2:00.... ++# https://www.dof.gob.mx/nota_to_imagen_fs.php?codnota=4787355&fecha=28/12/1982&cod_diario=206112 ++# https://www.dof.gob.mx/nota_to_imagen_fs.php?cod_diario=209559&pagina=15&seccion=0 ++# ++# Durango, Coahuila, Nuevo León and Tamaulipas were set to UTC-7 on 1 January ++# 1922, and changed to UTC-6 on 10 June 1927. Then Durango, Coahuila and ++# Nuevo León (but not Tamaulipas) returned to UTC-7 on 15 November 1930, ++# observed DST in 1931, and changed again to UTC-6 on 1 April 1932.... ++# https://www.dof.gob.mx/nota_to_imagen_fs.php?codnota=4441846&fecha=29/12/1921&cod_diario=187468 ++# https://www.dof.gob.mx/nota_to_imagen_fs.php?codnota=4541520&fecha=09/06/1927&cod_diario=193920 ++# https://www.dof.gob.mx/nota_to_imagen_fs.php?codnota=4491963&fecha=15/11/1930&cod_diario=190835 ++# https://www.dof.gob.mx/nota_to_imagen_fs.php?codnota=4418437&fecha=21/01/1932&cod_diario=185588 ++# ++# ... the ... 10 June 1927 ... decree only said 10 June 1927, without ++# specifying a time, so I suppose that it should be considered at 0:00. ++# https://www.dof.gob.mx/nota_to_imagen_fs.php?codnota=4541520&fecha=09/06/1927&cod_diario=193920 ++# ++# In 1942, the decree changing Baja California, Baja California Sur, Sonora, ++# Sinaloa and Nayarit to UTC-7 was published on 24 April, but it said that it ++# would apply from 1 April, so it's unclear when the change actually ++# occurred. The database currently shows 24 April 1942. ++# https://www.dof.gob.mx/nota_to_imagen_fs.php?cod_diario=192203&pagina=2&seccion=1 ++# ++# Baja California Sur, Sonora, Sinaloa and Nayarit never used UTC-8. The ... ++# 14 January 1949 ... change [to UTC-8] only occurred in Baja California. ++# https://www.dof.gob.mx/nota_to_imagen_fs.php?codnota=4515613&fecha=13/01/1949&cod_diario=192309 ++# ++# In 1945, the decree changing Baja California to UTC-8 specified that it ++# would take effect on the third day from its publication. ++# It was published on 12 November, so it would take effect on 15 November.... ++# https://www.dof.gob.mx/nota_to_imagen_fs.php?codnota=4555049&fecha=12/11/1945&cod_diario=194763 ++# ++# In 1948, the decree changing Baja California to UTC-7 specified that it ++# would take effect on "this date". The decree was made on 13 March, ++# but published on 5 April, so it's unclear when the change actually occurred. ++# The database currently shows 5 April 1948. ++# https://www.dof.gob.mx/nota_to_imagen_fs.php?cod_diario=188624&pagina=2&seccion=0 ++# ++# In 1949, the decree changing Baja California to UTC-8 was published on 13 ++# January, but it said that it would apply from 1 January, so it's unclear when ++# the change actually occurred. The database currently shows 14 January 1949. ++# https://www.dof.gob.mx/nota_to_imagen_fs.php?codnota=4515613&fecha=13/01/1949&cod_diario=192309 ++# ++# Baja California also observed UTC-7 from 1 May to 24 September 1950, ++# from 29 April to 30 September 1951 at 2:00, ++# and from 27 April to 28 September 1952 at 2:00.... ++# https://www.dof.gob.mx/nota_to_imagen_fs.php?codnota=4600403&fecha=29/04/1950&cod_diario=197505 ++# https://www.dof.gob.mx/nota_to_imagen_fs.php?codnota=4623553&fecha=23/09/1950&cod_diario=198805 ++# https://www.dof.gob.mx/nota_to_imagen_fs.php?codnota=4469444&fecha=27/04/1951&cod_diario=189317 ++# https://www.dof.gob.mx/nota_to_imagen_fs.php?codnota=4533868&fecha=10/03/1952&cod_diario=193465 ++# ++# All changes in Baja California from 1948 to 1952 match those in California, ++# on the same dates or with a difference of one day. ++# So it may be easier to implement these changes as DST with rule CA ++# during this whole period. ++# ++# From Paul Eggert (2024-08-18): ++# For now, maintain the slightly-different history for Baja California, ++# as we have no information on whether 1948/1952 clocks in Tijuana followed ++# the decrees or followed San Diego. ++ + # From Alan Perry (1996-02-15): + # A guy from our Mexico subsidiary finally found the Presidential Decree + # outlining the timezone changes in Mexico. +@@ -2599,7 +2666,7 @@ Zone America/Dawson -9:17:40 - LMT 1900 Aug 20 + # http://puentelibre.mx/noticia/ciudad_juarez_cambio_horario_noviembre_2022/ + + # Rule NAME FROM TO - IN ON AT SAVE LETTER/S +-Rule Mexico 1931 only - May 1 23:00 1:00 D ++Rule Mexico 1931 only - Apr 30 0:00 1:00 D + Rule Mexico 1931 only - Oct 1 0:00 0 S + Rule Mexico 1939 only - Feb 5 0:00 1:00 D + Rule Mexico 1939 only - Jun 25 0:00 0 S +@@ -2618,14 +2685,16 @@ Rule Mexico 2002 2022 - Oct lastSun 2:00 0 S + # Zone NAME STDOFF RULES FORMAT [UNTIL] + # Quintana Roo; represented by Cancún + Zone America/Cancun -5:47:04 - LMT 1922 Jan 1 6:00u +- -6:00 - CST 1981 Dec 23 ++ -6:00 - CST 1981 Dec 26 2:00 ++ -5:00 - EST 1983 Jan 4 0:00 ++ -6:00 Mexico C%sT 1997 Oct 26 2:00 + -5:00 Mexico E%sT 1998 Aug 2 2:00 + -6:00 Mexico C%sT 2015 Feb 1 2:00 + -5:00 - EST + # Campeche, Yucatán; represented by Mérida + Zone America/Merida -5:58:28 - LMT 1922 Jan 1 6:00u +- -6:00 - CST 1981 Dec 23 +- -5:00 - EST 1982 Dec 2 ++ -6:00 - CST 1981 Dec 26 2:00 ++ -5:00 - EST 1982 Nov 2 2:00 + -6:00 Mexico C%sT + # Coahuila, Nuevo León, Tamaulipas (near US border) + # This includes the following municipios: +@@ -2642,12 +2711,15 @@ Zone America/Matamoros -6:30:00 - LMT 1922 Jan 1 6:00u + -6:00 US C%sT + # Durango; Coahuila, Nuevo León, Tamaulipas (away from US border) + Zone America/Monterrey -6:41:16 - LMT 1922 Jan 1 6:00u ++ -7:00 - MST 1927 Jun 10 ++ -6:00 - CST 1930 Nov 15 ++ -7:00 Mexico M%sT 1932 Apr 1 + -6:00 - CST 1988 + -6:00 US C%sT 1989 + -6:00 Mexico C%sT + # Central Mexico + Zone America/Mexico_City -6:36:36 - LMT 1922 Jan 1 7:00u +- -7:00 - MST 1927 Jun 10 23:00 ++ -7:00 - MST 1927 Jun 10 + -6:00 - CST 1930 Nov 15 + -7:00 Mexico M%sT 1932 Apr 1 + -6:00 Mexico C%sT 2001 Sep 30 2:00 +@@ -2658,7 +2730,7 @@ Zone America/Mexico_City -6:36:36 - LMT 1922 Jan 1 7:00u + # Práxedis G Guerrero. + # http://gaceta.diputados.gob.mx/PDF/65/2a022/nov/20221124-VII.pdf + Zone America/Ciudad_Juarez -7:05:56 - LMT 1922 Jan 1 7:00u +- -7:00 - MST 1927 Jun 10 23:00 ++ -7:00 - MST 1927 Jun 10 + -6:00 - CST 1930 Nov 15 + -7:00 Mexico M%sT 1932 Apr 1 + -6:00 - CST 1996 +@@ -2673,7 +2745,7 @@ Zone America/Ciudad_Juarez -7:05:56 - LMT 1922 Jan 1 7:00u + # Benavides. + # http://gaceta.diputados.gob.mx/PDF/65/2a022/nov/20221124-VII.pdf + Zone America/Ojinaga -6:57:40 - LMT 1922 Jan 1 7:00u +- -7:00 - MST 1927 Jun 10 23:00 ++ -7:00 - MST 1927 Jun 10 + -6:00 - CST 1930 Nov 15 + -7:00 Mexico M%sT 1932 Apr 1 + -6:00 - CST 1996 +@@ -2685,7 +2757,7 @@ Zone America/Ojinaga -6:57:40 - LMT 1922 Jan 1 7:00u + -6:00 US C%sT + # Chihuahua (away from US border) + Zone America/Chihuahua -7:04:20 - LMT 1922 Jan 1 7:00u +- -7:00 - MST 1927 Jun 10 23:00 ++ -7:00 - MST 1927 Jun 10 + -6:00 - CST 1930 Nov 15 + -7:00 Mexico M%sT 1932 Apr 1 + -6:00 - CST 1996 +@@ -2695,23 +2767,21 @@ Zone America/Chihuahua -7:04:20 - LMT 1922 Jan 1 7:00u + -6:00 - CST + # Sonora + Zone America/Hermosillo -7:23:52 - LMT 1922 Jan 1 7:00u +- -7:00 - MST 1927 Jun 10 23:00 ++ -7:00 - MST 1927 Jun 10 + -6:00 - CST 1930 Nov 15 + -7:00 Mexico M%sT 1932 Apr 1 + -6:00 - CST 1942 Apr 24 +- -7:00 - MST 1949 Jan 14 +- -8:00 - PST 1970 ++ -7:00 - MST 1996 + -7:00 Mexico M%sT 1999 + -7:00 - MST + + # Baja California Sur, Nayarit (except Bahía de Banderas), Sinaloa + Zone America/Mazatlan -7:05:40 - LMT 1922 Jan 1 7:00u +- -7:00 - MST 1927 Jun 10 23:00 ++ -7:00 - MST 1927 Jun 10 + -6:00 - CST 1930 Nov 15 + -7:00 Mexico M%sT 1932 Apr 1 + -6:00 - CST 1942 Apr 24 +- -7:00 - MST 1949 Jan 14 +- -8:00 - PST 1970 ++ -7:00 - MST 1970 + -7:00 Mexico M%sT + + # Bahía de Banderas +@@ -2744,27 +2814,32 @@ Zone America/Mazatlan -7:05:40 - LMT 1922 Jan 1 7:00u + # Use "Bahia_Banderas" to keep the name to fourteen characters. + + Zone America/Bahia_Banderas -7:01:00 - LMT 1922 Jan 1 7:00u +- -7:00 - MST 1927 Jun 10 23:00 ++ -7:00 - MST 1927 Jun 10 + -6:00 - CST 1930 Nov 15 + -7:00 Mexico M%sT 1932 Apr 1 + -6:00 - CST 1942 Apr 24 +- -7:00 - MST 1949 Jan 14 +- -8:00 - PST 1970 ++ -7:00 - MST 1970 + -7:00 Mexico M%sT 2010 Apr 4 2:00 + -6:00 Mexico C%sT + + # Baja California + Zone America/Tijuana -7:48:04 - LMT 1922 Jan 1 7:00u + -7:00 - MST 1924 +- -8:00 - PST 1927 Jun 10 23:00 ++ -8:00 - PST 1927 Jun 10 + -7:00 - MST 1930 Nov 15 + -8:00 - PST 1931 Apr 1 + -8:00 1:00 PDT 1931 Sep 30 + -8:00 - PST 1942 Apr 24 + -8:00 1:00 PWT 1945 Aug 14 23:00u +- -8:00 1:00 PPT 1945 Nov 12 # Peace ++ -8:00 1:00 PPT 1945 Nov 15 # Peace + -8:00 - PST 1948 Apr 5 + -8:00 1:00 PDT 1949 Jan 14 ++ -8:00 - PST 1950 May 1 ++ -8:00 1:00 PDT 1950 Sep 24 ++ -8:00 - PST 1951 Apr 29 2:00 ++ -8:00 1:00 PDT 1951 Sep 30 2:00 ++ -8:00 - PST 1952 Apr 27 2:00 ++ -8:00 1:00 PDT 1952 Sep 28 2:00 + -8:00 - PST 1954 + -8:00 CA P%sT 1961 + -8:00 - PST 1976 +@@ -3573,8 +3648,8 @@ Zone America/Puerto_Rico -4:24:25 - LMT 1899 Mar 28 12:00 # San Juan + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone America/Miquelon -3:44:40 - LMT 1911 Jun 15 # St Pierre + -4:00 - AST 1980 May +- -3:00 - -03 1987 +- -3:00 Canada -03/-02 ++ -3:00 - %z 1987 ++ -3:00 Canada %z + + # Turks and Caicos + # +diff --git a/make/data/tzdata/southamerica b/make/data/tzdata/southamerica +index d77acc088..06fee598b 100644 +--- a/make/data/tzdata/southamerica ++++ b/make/data/tzdata/southamerica +@@ -1,26 +1,3 @@ +-# +-# 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. +-# + # tzdb data for South America and environs + + # This file is in the public domain, so clarified as of +@@ -425,11 +402,11 @@ Rule Arg 2008 only - Oct Sun>=15 0:00 1:00 - + 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 +- -3:00 Arg -03/-02 1999 Oct 3 +- -4:00 Arg -04/-03 2000 Mar 3 +- -3:00 Arg -03/-02 ++ -4:00 - %z 1930 Dec ++ -4:00 Arg %z 1969 Oct 5 ++ -3:00 Arg %z 1999 Oct 3 ++ -4:00 Arg %z 2000 Mar 3 ++ -3:00 Arg %z + # + # Córdoba (CB), Santa Fe (SF), Entre Ríos (ER), Corrientes (CN), Misiones (MN), + # Chaco (CC), Formosa (FM), Santiago del Estero (SE) +@@ -444,120 +421,120 @@ Zone America/Argentina/Buenos_Aires -3:53:48 - LMT 1894 Oct 31 + #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 +- -4:00 Arg -04/-03 1969 Oct 5 +- -3:00 Arg -03/-02 1991 Mar 3 +- -4:00 - -04 1991 Oct 20 +- -3:00 Arg -03/-02 1999 Oct 3 +- -4:00 Arg -04/-03 2000 Mar 3 +- -3:00 Arg -03/-02 ++ -4:00 - %z 1930 Dec ++ -4:00 Arg %z 1969 Oct 5 ++ -3:00 Arg %z 1991 Mar 3 ++ -4:00 - %z 1991 Oct 20 ++ -3:00 Arg %z 1999 Oct 3 ++ -4:00 Arg %z 2000 Mar 3 ++ -3:00 Arg %z + # + # 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 +- -3:00 Arg -03/-02 1991 Mar 3 +- -4:00 - -04 1991 Oct 20 +- -3:00 Arg -03/-02 1999 Oct 3 +- -4:00 Arg -04/-03 2000 Mar 3 +- -3:00 Arg -03/-02 2008 Oct 18 +- -3:00 - -03 ++ -4:00 - %z 1930 Dec ++ -4:00 Arg %z 1969 Oct 5 ++ -3:00 Arg %z 1991 Mar 3 ++ -4:00 - %z 1991 Oct 20 ++ -3:00 Arg %z 1999 Oct 3 ++ -4:00 Arg %z 2000 Mar 3 ++ -3:00 Arg %z 2008 Oct 18 ++ -3:00 - %z + # + # 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 +- -3:00 Arg -03/-02 1991 Mar 3 +- -4:00 - -04 1991 Oct 20 +- -3:00 Arg -03/-02 1999 Oct 3 +- -4:00 Arg -04/-03 2000 Mar 3 +- -3:00 - -03 2004 Jun 1 +- -4:00 - -04 2004 Jun 13 +- -3:00 Arg -03/-02 ++ -4:00 - %z 1930 Dec ++ -4:00 Arg %z 1969 Oct 5 ++ -3:00 Arg %z 1991 Mar 3 ++ -4:00 - %z 1991 Oct 20 ++ -3:00 Arg %z 1999 Oct 3 ++ -4:00 Arg %z 2000 Mar 3 ++ -3:00 - %z 2004 Jun 1 ++ -4:00 - %z 2004 Jun 13 ++ -3:00 Arg %z + # + # 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 +- -3:00 Arg -03/-02 1991 Mar 1 +- -4:00 - -04 1991 May 7 +- -3:00 Arg -03/-02 1999 Oct 3 +- -4:00 Arg -04/-03 2000 Mar 3 +- -3:00 - -03 2004 Jun 1 +- -4:00 - -04 2004 Jun 20 +- -3:00 Arg -03/-02 2008 Oct 18 +- -3:00 - -03 ++ -4:00 - %z 1930 Dec ++ -4:00 Arg %z 1969 Oct 5 ++ -3:00 Arg %z 1991 Mar 1 ++ -4:00 - %z 1991 May 7 ++ -3:00 Arg %z 1999 Oct 3 ++ -4:00 Arg %z 2000 Mar 3 ++ -3:00 - %z 2004 Jun 1 ++ -4:00 - %z 2004 Jun 20 ++ -3:00 Arg %z 2008 Oct 18 ++ -3:00 - %z + # + # 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 +- -3:00 Arg -03/-02 1991 Mar 1 +- -4:00 - -04 1991 May 7 +- -3:00 Arg -03/-02 1999 Oct 3 +- -4:00 Arg -04/-03 2000 Mar 3 +- -3:00 - -03 2004 May 31 +- -4:00 - -04 2004 Jul 25 +- -3:00 Arg -03/-02 2008 Oct 18 +- -3:00 - -03 ++ -4:00 - %z 1930 Dec ++ -4:00 Arg %z 1969 Oct 5 ++ -3:00 Arg %z 1991 Mar 1 ++ -4:00 - %z 1991 May 7 ++ -3:00 Arg %z 1999 Oct 3 ++ -4:00 Arg %z 2000 Mar 3 ++ -3:00 - %z 2004 May 31 ++ -4:00 - %z 2004 Jul 25 ++ -3:00 Arg %z 2008 Oct 18 ++ -3:00 - %z + # + # 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 +- -3:00 Arg -03/-02 1990 Mar 4 +- -4:00 - -04 1990 Oct 28 +- -4:00 1:00 -03 1991 Mar 17 +- -4:00 - -04 1991 Oct 6 +- -3:00 1:00 -02 1992 +- -3:00 Arg -03/-02 1999 Oct 3 +- -4:00 Arg -04/-03 2000 Mar 3 +- -3:00 Arg -03/-02 2008 Oct 18 +- -3:00 - -03 ++ -4:00 - %z 1930 Dec ++ -4:00 Arg %z 1969 Oct 5 ++ -3:00 Arg %z 1990 Mar 4 ++ -4:00 - %z 1990 Oct 28 ++ -4:00 1:00 %z 1991 Mar 17 ++ -4:00 - %z 1991 Oct 6 ++ -3:00 1:00 %z 1992 ++ -3:00 Arg %z 1999 Oct 3 ++ -4:00 Arg %z 2000 Mar 3 ++ -3:00 Arg %z 2008 Oct 18 ++ -3:00 - %z + # + # 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 +- -3:00 Arg -03/-02 1991 Mar 3 +- -4:00 - -04 1991 Oct 20 +- -3:00 Arg -03/-02 1999 Oct 3 +- -4:00 Arg -04/-03 2000 Mar 3 +- -3:00 - -03 2004 Jun 1 +- -4:00 - -04 2004 Jun 20 +- -3:00 Arg -03/-02 2008 Oct 18 +- -3:00 - -03 ++ -4:00 - %z 1930 Dec ++ -4:00 Arg %z 1969 Oct 5 ++ -3:00 Arg %z 1991 Mar 3 ++ -4:00 - %z 1991 Oct 20 ++ -3:00 Arg %z 1999 Oct 3 ++ -4:00 Arg %z 2000 Mar 3 ++ -3:00 - %z 2004 Jun 1 ++ -4:00 - %z 2004 Jun 20 ++ -3:00 Arg %z 2008 Oct 18 ++ -3:00 - %z + # + # 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 +- -3:00 Arg -03/-02 1990 Mar 4 +- -4:00 - -04 1990 Oct 15 +- -4:00 1:00 -03 1991 Mar 1 +- -4:00 - -04 1991 Oct 15 +- -4:00 1:00 -03 1992 Mar 1 +- -4:00 - -04 1992 Oct 18 +- -3:00 Arg -03/-02 1999 Oct 3 +- -4:00 Arg -04/-03 2000 Mar 3 +- -3:00 - -03 2004 May 23 +- -4:00 - -04 2004 Sep 26 +- -3:00 Arg -03/-02 2008 Oct 18 +- -3:00 - -03 ++ -4:00 - %z 1930 Dec ++ -4:00 Arg %z 1969 Oct 5 ++ -3:00 Arg %z 1990 Mar 4 ++ -4:00 - %z 1990 Oct 15 ++ -4:00 1:00 %z 1991 Mar 1 ++ -4:00 - %z 1991 Oct 15 ++ -4:00 1:00 %z 1992 Mar 1 ++ -4:00 - %z 1992 Oct 18 ++ -3:00 Arg %z 1999 Oct 3 ++ -4:00 Arg %z 2000 Mar 3 ++ -3:00 - %z 2004 May 23 ++ -4:00 - %z 2004 Sep 26 ++ -3:00 Arg %z 2008 Oct 18 ++ -3:00 - %z + # + # San Luis (SL) + +@@ -567,53 +544,53 @@ 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 +- -3:00 Arg -03/-02 1990 +- -3:00 1:00 -02 1990 Mar 14 +- -4:00 - -04 1990 Oct 15 +- -4:00 1:00 -03 1991 Mar 1 +- -4:00 - -04 1991 Jun 1 +- -3:00 - -03 1999 Oct 3 +- -4:00 1:00 -03 2000 Mar 3 +- -3:00 - -03 2004 May 31 +- -4:00 - -04 2004 Jul 25 +- -3:00 Arg -03/-02 2008 Jan 21 +- -4:00 SanLuis -04/-03 2009 Oct 11 +- -3:00 - -03 ++ -4:00 - %z 1930 Dec ++ -4:00 Arg %z 1969 Oct 5 ++ -3:00 Arg %z 1990 ++ -3:00 1:00 %z 1990 Mar 14 ++ -4:00 - %z 1990 Oct 15 ++ -4:00 1:00 %z 1991 Mar 1 ++ -4:00 - %z 1991 Jun 1 ++ -3:00 - %z 1999 Oct 3 ++ -4:00 1:00 %z 2000 Mar 3 ++ -3:00 - %z 2004 May 31 ++ -4:00 - %z 2004 Jul 25 ++ -3:00 Arg %z 2008 Jan 21 ++ -4:00 SanLuis %z 2009 Oct 11 ++ -3:00 - %z + # + # 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 +- -3:00 Arg -03/-02 1999 Oct 3 +- -4:00 Arg -04/-03 2000 Mar 3 +- -3:00 - -03 2004 Jun 1 +- -4:00 - -04 2004 Jun 20 +- -3:00 Arg -03/-02 2008 Oct 18 +- -3:00 - -03 ++ -4:00 - %z 1930 Dec ++ -4:00 Arg %z 1969 Oct 5 ++ -3:00 Arg %z 1999 Oct 3 ++ -4:00 Arg %z 2000 Mar 3 ++ -3:00 - %z 2004 Jun 1 ++ -4:00 - %z 2004 Jun 20 ++ -3:00 Arg %z 2008 Oct 18 ++ -3:00 - %z + # + # 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 +- -3:00 Arg -03/-02 1999 Oct 3 +- -4:00 Arg -04/-03 2000 Mar 3 +- -3:00 - -03 2004 May 30 +- -4:00 - -04 2004 Jun 20 +- -3:00 Arg -03/-02 2008 Oct 18 +- -3:00 - -03 ++ -4:00 - %z 1930 Dec ++ -4:00 Arg %z 1969 Oct 5 ++ -3:00 Arg %z 1999 Oct 3 ++ -4:00 Arg %z 2000 Mar 3 ++ -3:00 - %z 2004 May 30 ++ -4:00 - %z 2004 Jun 20 ++ -3:00 Arg %z 2008 Oct 18 ++ -3:00 - %z + + # Bolivia + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone America/La_Paz -4:32:36 - LMT 1890 + -4:32:36 - CMT 1931 Oct 15 # Calamarca MT + -4:32:36 1:00 BST 1932 Mar 21 # Bolivia ST +- -4:00 - -04 ++ -4:00 - %z + + # Brazil + +@@ -984,12 +961,12 @@ Rule Brazil 2018 only - Nov Sun>=1 0:00 1:00 - + # + # Fernando de Noronha (administratively part of PE) + Zone America/Noronha -2:09:40 - LMT 1914 +- -2:00 Brazil -02/-01 1990 Sep 17 +- -2:00 - -02 1999 Sep 30 +- -2:00 Brazil -02/-01 2000 Oct 15 +- -2:00 - -02 2001 Sep 13 +- -2:00 Brazil -02/-01 2002 Oct 1 +- -2:00 - -02 ++ -2:00 Brazil %z 1990 Sep 17 ++ -2:00 - %z 1999 Sep 30 ++ -2:00 Brazil %z 2000 Oct 15 ++ -2:00 - %z 2001 Sep 13 ++ -2:00 Brazil %z 2002 Oct 1 ++ -2:00 - %z + # Other Atlantic islands have no permanent settlement. + # These include Trindade and Martim Vaz (administratively part of ES), + # Rocas Atoll (RN), and the St Peter and St Paul Archipelago (PE). +@@ -1002,119 +979,119 @@ Zone America/Noronha -2:09:40 - LMT 1914 + # In the north a very small part from the river Javary (now Jari I guess, + # the border with Amapá) to the Amazon, then to the Xingu. + Zone America/Belem -3:13:56 - LMT 1914 +- -3:00 Brazil -03/-02 1988 Sep 12 +- -3:00 - -03 ++ -3:00 Brazil %z 1988 Sep 12 ++ -3:00 - %z + # + # west Pará (PA) + # West Pará includes Altamira, Óbidos, Prainha, Oriximiná, and Santarém. + Zone America/Santarem -3:38:48 - LMT 1914 +- -4:00 Brazil -04/-03 1988 Sep 12 +- -4:00 - -04 2008 Jun 24 0:00 +- -3:00 - -03 ++ -4:00 Brazil %z 1988 Sep 12 ++ -4:00 - %z 2008 Jun 24 0:00 ++ -3:00 - %z + # + # Maranhão (MA), Piauí (PI), Ceará (CE), Rio Grande do Norte (RN), + # Paraíba (PB) + Zone America/Fortaleza -2:34:00 - LMT 1914 +- -3:00 Brazil -03/-02 1990 Sep 17 +- -3:00 - -03 1999 Sep 30 +- -3:00 Brazil -03/-02 2000 Oct 22 +- -3:00 - -03 2001 Sep 13 +- -3:00 Brazil -03/-02 2002 Oct 1 +- -3:00 - -03 ++ -3:00 Brazil %z 1990 Sep 17 ++ -3:00 - %z 1999 Sep 30 ++ -3:00 Brazil %z 2000 Oct 22 ++ -3:00 - %z 2001 Sep 13 ++ -3:00 Brazil %z 2002 Oct 1 ++ -3:00 - %z + # + # Pernambuco (PE) (except Atlantic islands) + Zone America/Recife -2:19:36 - LMT 1914 +- -3:00 Brazil -03/-02 1990 Sep 17 +- -3:00 - -03 1999 Sep 30 +- -3:00 Brazil -03/-02 2000 Oct 15 +- -3:00 - -03 2001 Sep 13 +- -3:00 Brazil -03/-02 2002 Oct 1 +- -3:00 - -03 ++ -3:00 Brazil %z 1990 Sep 17 ++ -3:00 - %z 1999 Sep 30 ++ -3:00 Brazil %z 2000 Oct 15 ++ -3:00 - %z 2001 Sep 13 ++ -3:00 Brazil %z 2002 Oct 1 ++ -3:00 - %z + # + # Tocantins (TO) + Zone America/Araguaina -3:12:48 - LMT 1914 +- -3:00 Brazil -03/-02 1990 Sep 17 +- -3:00 - -03 1995 Sep 14 +- -3:00 Brazil -03/-02 2003 Sep 24 +- -3:00 - -03 2012 Oct 21 +- -3:00 Brazil -03/-02 2013 Sep +- -3:00 - -03 ++ -3:00 Brazil %z 1990 Sep 17 ++ -3:00 - %z 1995 Sep 14 ++ -3:00 Brazil %z 2003 Sep 24 ++ -3:00 - %z 2012 Oct 21 ++ -3:00 Brazil %z 2013 Sep ++ -3:00 - %z + # + # Alagoas (AL), Sergipe (SE) + Zone America/Maceio -2:22:52 - LMT 1914 +- -3:00 Brazil -03/-02 1990 Sep 17 +- -3:00 - -03 1995 Oct 13 +- -3:00 Brazil -03/-02 1996 Sep 4 +- -3:00 - -03 1999 Sep 30 +- -3:00 Brazil -03/-02 2000 Oct 22 +- -3:00 - -03 2001 Sep 13 +- -3:00 Brazil -03/-02 2002 Oct 1 +- -3:00 - -03 ++ -3:00 Brazil %z 1990 Sep 17 ++ -3:00 - %z 1995 Oct 13 ++ -3:00 Brazil %z 1996 Sep 4 ++ -3:00 - %z 1999 Sep 30 ++ -3:00 Brazil %z 2000 Oct 22 ++ -3:00 - %z 2001 Sep 13 ++ -3:00 Brazil %z 2002 Oct 1 ++ -3:00 - %z + # + # Bahia (BA) + # There are too many Salvadors elsewhere, so use America/Bahia instead + # of America/Salvador. + Zone America/Bahia -2:34:04 - LMT 1914 +- -3:00 Brazil -03/-02 2003 Sep 24 +- -3:00 - -03 2011 Oct 16 +- -3:00 Brazil -03/-02 2012 Oct 21 +- -3:00 - -03 ++ -3:00 Brazil %z 2003 Sep 24 ++ -3:00 - %z 2011 Oct 16 ++ -3:00 Brazil %z 2012 Oct 21 ++ -3:00 - %z + # + # Goiás (GO), Distrito Federal (DF), Minas Gerais (MG), + # Espírito Santo (ES), Rio de Janeiro (RJ), São Paulo (SP), Paraná (PR), + # Santa Catarina (SC), Rio Grande do Sul (RS) + Zone America/Sao_Paulo -3:06:28 - LMT 1914 +- -3:00 Brazil -03/-02 1963 Oct 23 0:00 +- -3:00 1:00 -02 1964 +- -3:00 Brazil -03/-02 ++ -3:00 Brazil %z 1963 Oct 23 0:00 ++ -3:00 1:00 %z 1964 ++ -3:00 Brazil %z + # + # Mato Grosso do Sul (MS) + Zone America/Campo_Grande -3:38:28 - LMT 1914 +- -4:00 Brazil -04/-03 ++ -4:00 Brazil %z + # + # Mato Grosso (MT) + Zone America/Cuiaba -3:44:20 - LMT 1914 +- -4:00 Brazil -04/-03 2003 Sep 24 +- -4:00 - -04 2004 Oct 1 +- -4:00 Brazil -04/-03 ++ -4:00 Brazil %z 2003 Sep 24 ++ -4:00 - %z 2004 Oct 1 ++ -4:00 Brazil %z + # + # Rondônia (RO) + Zone America/Porto_Velho -4:15:36 - LMT 1914 +- -4:00 Brazil -04/-03 1988 Sep 12 +- -4:00 - -04 ++ -4:00 Brazil %z 1988 Sep 12 ++ -4:00 - %z + # + # Roraima (RR) + Zone America/Boa_Vista -4:02:40 - LMT 1914 +- -4:00 Brazil -04/-03 1988 Sep 12 +- -4:00 - -04 1999 Sep 30 +- -4:00 Brazil -04/-03 2000 Oct 15 +- -4:00 - -04 ++ -4:00 Brazil %z 1988 Sep 12 ++ -4:00 - %z 1999 Sep 30 ++ -4:00 Brazil %z 2000 Oct 15 ++ -4:00 - %z + # + # east Amazonas (AM): Boca do Acre, Jutaí, Manaus, Floriano Peixoto + # The great circle line from Tabatinga to Porto Acre divides + # east from west Amazonas. + Zone America/Manaus -4:00:04 - LMT 1914 +- -4:00 Brazil -04/-03 1988 Sep 12 +- -4:00 - -04 1993 Sep 28 +- -4:00 Brazil -04/-03 1994 Sep 22 +- -4:00 - -04 ++ -4:00 Brazil %z 1988 Sep 12 ++ -4:00 - %z 1993 Sep 28 ++ -4:00 Brazil %z 1994 Sep 22 ++ -4:00 - %z + # + # west Amazonas (AM): Atalaia do Norte, Boca do Maoco, Benjamin Constant, + # Eirunepé, Envira, Ipixuna + Zone America/Eirunepe -4:39:28 - LMT 1914 +- -5:00 Brazil -05/-04 1988 Sep 12 +- -5:00 - -05 1993 Sep 28 +- -5:00 Brazil -05/-04 1994 Sep 22 +- -5:00 - -05 2008 Jun 24 0:00 +- -4:00 - -04 2013 Nov 10 +- -5:00 - -05 ++ -5:00 Brazil %z 1988 Sep 12 ++ -5:00 - %z 1993 Sep 28 ++ -5:00 Brazil %z 1994 Sep 22 ++ -5:00 - %z 2008 Jun 24 0:00 ++ -4:00 - %z 2013 Nov 10 ++ -5:00 - %z + # + # Acre (AC) + Zone America/Rio_Branco -4:31:12 - LMT 1914 +- -5:00 Brazil -05/-04 1988 Sep 12 +- -5:00 - -05 2008 Jun 24 0:00 +- -4:00 - -04 2013 Nov 10 +- -5:00 - -05 ++ -5:00 Brazil %z 1988 Sep 12 ++ -5:00 - %z 2008 Jun 24 0:00 ++ -4:00 - %z 2013 Nov 10 ++ -5:00 - %z + + # Chile + +@@ -1269,35 +1246,45 @@ Zone America/Rio_Branco -4:31:12 - LMT 1914 + # dates to 2014. + # DST End: last Saturday of April 2014 (Sun 27 Apr 2014 03:00 UTC) + # DST Start: first Saturday of September 2014 (Sun 07 Sep 2014 04:00 UTC) +-# http://www.diariooficial.interior.gob.cl//media/2014/02/19/do-20140219.pdf ++# From Tim Parenti (2025-03-22): ++# Decreto 307 of 2014 of the Ministry of the Interior and Public Security, ++# promulgated 2014-01-30 and published 2014-02-19: ++# https://www.diariooficial.interior.gob.cl/media/2014/02/19/do-20140219.pdf#page=1 ++# https://www.bcn.cl/leychile/navegar?idNorma=1059557 + + # From Eduardo Romero Urra (2015-03-03): + # Today has been published officially that Chile will use the DST time + # permanently until March 25 of 2017 +-# http://www.diariooficial.interior.gob.cl/media/2015/03/03/1-large.jpg +-# +-# From Paul Eggert (2015-03-03): +-# For now, assume that the extension will persist indefinitely. ++# From Tim Parenti (2025-03-22): ++# Decreto 106 of 2015 of the Ministry of the Interior and Public Security, ++# promulgated 2015-01-27 and published 2015-03-03: ++# https://www.diariooficial.interior.gob.cl/media/2015/03/03/do-20150303.pdf#page=1 ++# https://www.bcn.cl/leychile/navegar?idNorma=1075157 + + # From Juan Correa (2016-03-18): +-# The decree regarding DST has been published in today's Official Gazette: +-# http://www.diariooficial.interior.gob.cl/versiones-anteriores/do/20160318/ +-# http://www.leychile.cl/Navegar?idNorma=1088502 ++# The decree regarding DST has been published in today's Official Gazette... + # It does consider the second Saturday of May and August as the dates + # for the transition; and it lists DST dates until 2019, but I think + # this scheme will stick. +-# + # From Paul Eggert (2016-03-18): +-# For now, assume the pattern holds for the indefinite future. + # The decree says transitions occur at 24:00; in practice this appears + # to mean 24:00 mainland time, not 24:00 local time, so that Easter + # Island is always two hours behind the mainland. ++# From Tim Parenti (2025-03-22): ++# Decreto 253 of 2016 of the Ministry of the Interior and Public Security, ++# promulgated 2016-03-16 and published 2016-03-18. ++# https://www.diariooficial.interior.gob.cl/media/2016/03/18/do-20160318.pdf#page=1 ++# https://www.bcn.cl/leychile/navegar?idNorma=1088502 + + # From Juan Correa (2016-12-04): + # Magallanes region ... will keep DST (UTC -3) all year round.... + # http://www.soychile.cl/Santiago/Sociedad/2016/12/04/433428/Bachelet-firmo-el-decreto-para-establecer-un-horario-unico-para-la-Region-de-Magallanes.aspx +-# From Deborah Goldsmith (2017-01-19): +-# http://www.diariooficial.interior.gob.cl/publicaciones/2017/01/17/41660/01/1169626.pdf ++# From Tim Parenti (2025-03-22), via Deborah Goldsmith (2017-01-19): ++# Decreto 1820 of 2016 of the Ministry of the Interior and Public Security, ++# promulgated 2016-12-02 and published 2017-01-17: ++# https://www.diariooficial.interior.gob.cl/publicaciones/2017/01/17/41660/01/1169626.pdf ++# https://www.bcn.cl/leychile/Navegar?idNorma=1099217 ++# Model this as a change to standard offset effective 2016-12-04. + + # From Juan Correa (2018-08-13): + # As of moments ago, the Ministry of Energy in Chile has announced the new +@@ -1316,13 +1303,20 @@ Zone America/Rio_Branco -4:31:12 - LMT 1914 + # https://twitter.com/MinEnergia/status/1029009354001973248 + # "We will keep the new time policy unchanged for at least the next 4 years." + # 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 Tim Parenti (2025-03-22), via Juan Correa (2019-02-04): ++# Decreto 1286 of 2018 of the Ministry of the Interior and Public Security, ++# promulgated 2018-09-21 and published 2018-11-23: ++# https://www.diariooficial.interior.gob.cl/publicaciones/2018/11/23/42212/01/1498738.pdf ++# https://www.bcn.cl/leychile/Navegar?idNorma=1125760 + + # 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 ++# Magallanes region to UTC -3 "indefinitely". ++# From Tim Parenti (2025-03-22): ++# Decreto 143 of 2022 of the Ministry of the Interior and Public Security, ++# promulgated 2022-03-29 and published 2022-03-31: + # https://www.diariooficial.interior.gob.cl/publicaciones/2022/03/31/43217-B/01/2108910.pdf ++# https://www.bcn.cl/leychile/Navegar?idNorma=1174342 + + # From Juan Correa (2022-08-09): + # the Internal Affairs Ministry (Ministerio del Interior) informed DST +@@ -1331,13 +1325,36 @@ Zone America/Rio_Branco -4:31:12 - LMT 1914 + # will keep UTC -3 "indefinitely"... This is because on September 4th + # we will have a voting whether to approve a new Constitution. + # +-# From Eduardo Romero Urra (2022-08-17): ++# From Tim Parenti (2025-03-22), via Eduardo Romero Urra (2022-08-17): ++# Decreto 224 of 2022 of the Ministry of the Interior and Public Security, ++# promulgated 2022-07-14 and published 2022-08-13: + # https://www.diariooficial.interior.gob.cl/publicaciones/2022/08/13/43327/01/2172567.pdf ++# https://www.bcn.cl/leychile/navegar?idNorma=1179983 + # + # From Paul Eggert (2022-08-17): + # Although the presidential decree stops at fall 2026, assume that + # similar DST rules will continue thereafter. + ++# From Paul Eggert (2025-01-15): ++# Diario Regional Aysén's Sebastián Martel reports that 94% of Aysén ++# citizens polled in November favored changing the rules from ++# -04/-03-with-DST to -03 all year... ++# https://www.diarioregionalaysen.cl/noticia/actualidad/2024/12/presentan-decision-que-gano-la-votacion-sobre-el-cambio-del-huso-horario-en-aysen ++# ++# From Yonathan Dossow (2025-03-20): ++# [T]oday we have more confirmation of the change. [Aysén] region will keep ++# UTC-3 all year... ++# https://www.cnnchile.com/pais/region-de-aysen-mantendra-horario-de-verano-todo-el-ano_20250320/ ++# https://www.latercera.com/nacional/noticia/tras-consulta-ciudadana-region-de-aysen-mantendra-el-horario-de-verano-durante-todo-el-ano/ ++# https://x.com/min_interior/status/1902692504270672098 ++# ++# From Tim Parenti (2025-03-22), via Eduardo Romero Urra (2025-03-20): ++# Decreto 93 of 2025 of the Ministry of the Interior and Public Security, ++# promulgated 2025-03-11 and published 2025-03-20: ++# https://www.diariooficial.interior.gob.cl/publicaciones/2025/03/20/44104/01/2624263.pdf ++# https://www.bcn.cl/leychile/Navegar?idNorma=1211955 ++# Model this as a change to standard offset effective 2025-03-20. ++ + # Rule NAME FROM TO - IN ON AT SAVE LETTER/S + Rule Chile 1927 1931 - Sep 1 0:00 1:00 - + Rule Chile 1928 1932 - Apr 1 0:00 0 - +@@ -1382,36 +1399,50 @@ Rule Chile 2023 max - Sep Sun>=2 4:00u 1:00 - + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone America/Santiago -4:42:45 - LMT 1890 + -4:42:45 - SMT 1910 Jan 10 # Santiago Mean Time +- -5:00 - -05 1916 Jul 1 ++ -5:00 - %z 1916 Jul 1 ++ -4:42:45 - SMT 1918 Sep 10 ++ -4:00 - %z 1919 Jul 1 ++ -4:42:45 - SMT 1927 Sep 1 ++ -5:00 Chile %z 1932 Sep 1 ++ -4:00 - %z 1942 Jun 1 ++ -5:00 - %z 1942 Aug 1 ++ -4:00 - %z 1946 Jul 14 24:00 ++ -4:00 1:00 %z 1946 Aug 28 24:00 # central CL ++ -5:00 1:00 %z 1947 Mar 31 24:00 ++ -5:00 - %z 1947 May 21 23:00 ++ -4:00 Chile %z ++Zone America/Coyhaique -4:48:16 - LMT 1890 ++ -4:42:45 - SMT 1910 Jan 10 ++ -5:00 - %z 1916 Jul 1 + -4:42:45 - SMT 1918 Sep 10 +- -4:00 - -04 1919 Jul 1 ++ -4:00 - %z 1919 Jul 1 + -4:42:45 - SMT 1927 Sep 1 +- -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 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 ++ -5:00 Chile %z 1932 Sep 1 ++ -4:00 - %z 1942 Jun 1 ++ -5:00 - %z 1942 Aug 1 ++ -4:00 - %z 1946 Aug 28 24:00 ++ -5:00 1:00 %z 1947 Mar 31 24:00 ++ -5:00 - %z 1947 May 21 23:00 ++ -4:00 Chile %z 2025 Mar 20 ++ -3:00 - %z + Zone America/Punta_Arenas -4:43:40 - LMT 1890 + -4:42:45 - SMT 1910 Jan 10 +- -5:00 - -05 1916 Jul 1 ++ -5:00 - %z 1916 Jul 1 + -4:42:45 - SMT 1918 Sep 10 +- -4:00 - -04 1919 Jul 1 ++ -4:00 - %z 1919 Jul 1 + -4:42:45 - SMT 1927 Sep 1 +- -5:00 Chile -05/-04 1932 Sep 1 +- -4:00 - -04 1942 Jun 1 +- -5:00 - -05 1942 Aug 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 ++ -5:00 Chile %z 1932 Sep 1 ++ -4:00 - %z 1942 Jun 1 ++ -5:00 - %z 1942 Aug 1 ++ -4:00 - %z 1946 Aug 28 24:00 ++ -5:00 1:00 %z 1947 Mar 31 24:00 ++ -5:00 - %z 1947 May 21 23:00 ++ -4:00 Chile %z 2016 Dec 4 ++ -3:00 - %z + Zone Pacific/Easter -7:17:28 - LMT 1890 + -7:17:28 - EMT 1932 Sep # Easter Mean Time +- -7:00 Chile -07/-06 1982 Mar 14 3:00u # Easter Time +- -6:00 Chile -06/-05 ++ -7:00 Chile %z 1982 Mar 14 3:00u # Easter Time ++ -6:00 Chile %z + # + # Salas y Gómez Island is uninhabited. + # Other Chilean locations, including Juan Fernández Is, Desventuradas Is, +@@ -1431,10 +1462,10 @@ Zone Pacific/Easter -7:17:28 - LMT 1890 + # + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone Antarctica/Palmer 0 - -00 1965 +- -4:00 Arg -04/-03 1969 Oct 5 +- -3:00 Arg -03/-02 1982 May +- -4:00 Chile -04/-03 2016 Dec 4 +- -3:00 - -03 ++ -4:00 Arg %z 1969 Oct 5 ++ -3:00 Arg %z 1982 May ++ -4:00 Chile %z 2016 Dec 4 ++ -3:00 - %z + + # Colombia + +@@ -1453,7 +1484,7 @@ Rule CO 1993 only - Feb 6 24:00 0 - + #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 ++ -5:00 CO %z + # Malpelo, Providencia, San Andres + # no information; probably like America/Bogota + +@@ -1484,10 +1515,10 @@ Rule Ecuador 1993 only - Feb 5 0:00 0 - + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone America/Guayaquil -5:19:20 - LMT 1890 + -5:14:00 - QMT 1931 # Quito Mean Time +- -5:00 Ecuador -05/-04 ++ -5:00 Ecuador %z + Zone Pacific/Galapagos -5:58:24 - LMT 1931 # Puerto Baquerizo Moreno +- -5:00 - -05 1986 +- -6:00 Ecuador -06/-05 ++ -5:00 - %z 1986 ++ -6:00 Ecuador %z + + # Falklands + +@@ -1587,10 +1618,10 @@ Rule Falk 2001 2010 - Sep Sun>=1 2:00 1:00 - + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone Atlantic/Stanley -3:51:24 - LMT 1890 + -3:51:24 - SMT 1912 Mar 12 # Stanley Mean Time +- -4:00 Falk -04/-03 1983 May +- -3:00 Falk -03/-02 1985 Sep 15 +- -4:00 Falk -04/-03 2010 Sep 5 2:00 +- -3:00 - -03 ++ -4:00 Falk %z 1983 May ++ -3:00 Falk %z 1985 Sep 15 ++ -4:00 Falk %z 2010 Sep 5 2:00 ++ -3:00 - %z + + # French Guiana + # For the 1911/1912 establishment of standard time in French possessions, see: +@@ -1598,8 +1629,8 @@ Zone Atlantic/Stanley -3:51:24 - LMT 1890 + # page 752, 18b. + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone America/Cayenne -3:29:20 - LMT 1911 Jul 1 +- -4:00 - -04 1967 Oct +- -3:00 - -03 ++ -4:00 - %z 1967 Oct ++ -3:00 - %z + + # Guyana + +@@ -1633,10 +1664,10 @@ Zone America/Cayenne -3:29:20 - LMT 1911 Jul 1 + + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone America/Guyana -3:52:39 - LMT 1911 Aug 1 # Georgetown +- -4:00 - -04 1915 Mar 1 +- -3:45 - -0345 1975 Aug 1 +- -3:00 - -03 1992 Mar 29 1:00 +- -4:00 - -04 ++ -4:00 - %z 1915 Mar 1 ++ -3:45 - %z 1975 Aug 1 ++ -3:00 - %z 1992 Mar 29 1:00 ++ -4:00 - %z + + # Paraguay + # +@@ -1710,7 +1741,7 @@ Rule Para 2005 2009 - Mar Sun>=8 0:00 0 - + # and that on the first Sunday of the month of October, it is to be set + # forward 60 minutes, in all the territory of the Paraguayan Republic. + # ... +-Rule Para 2010 max - Oct Sun>=1 0:00 1:00 - ++Rule Para 2010 2024 - Oct Sun>=1 0:00 1:00 - + Rule Para 2010 2012 - Apr Sun>=8 0:00 0 - + # + # From Steffen Thorsen (2013-03-07): +@@ -1729,14 +1760,35 @@ Rule Para 2010 2012 - Apr Sun>=8 0:00 0 - + # https://www.abc.com.py/politica/2023/07/12/promulgacion-el-cambio-de-hora-sera-por-ley/ + # From Carlos Raúl Perasso (2023-07-27): + # http://silpy.congreso.gov.py/descarga/ley-144138 +-Rule Para 2013 max - Mar Sun>=22 0:00 0 - ++Rule Para 2013 2024 - Mar Sun>=22 0:00 0 - ++# ++# From Heitor David Pinto (2024-09-24): ++# Today the Congress of Paraguay passed a bill to observe UTC-3 permanently.... ++# The text of the bill says that it would enter into force on the first ++# Sunday in October 2024, the same date currently scheduled to start DST.... ++# https://silpy.congreso.gov.py/web/expediente/132531 ++# (2024-10-14): ++# The president approved the law on 11 October 2024, ++# and it was officially published on 14 October 2024. ++# https://www.gacetaoficial.gov.py/index/detalle_publicacion/89723 ++# The text of the law says that it enters into force on the first ++# Sunday in October 2024 (6 October 2024). But the constitution ++# prohibits retroactive effect, and the civil code says that laws ++# enter into force on the day after their publication or on the day ++# that they specify, and it also says that they don't have retroactive ++# effect. So I think that the time change on 6 October 2024 should ++# still be considered as DST according to the previous law, and ++# permanently UTC-3 from 15 October 2024 according to the new law.... ++# https://www.constituteproject.org/constitution/Paraguay_2011 ++# https://www.oas.org/dil/esp/codigo_civil_paraguay.pdf + + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone America/Asuncion -3:50:40 - LMT 1890 + -3:50:40 - AMT 1931 Oct 10 # Asunción Mean Time +- -4:00 - -04 1972 Oct +- -3:00 - -03 1974 Apr +- -4:00 Para -04/-03 ++ -4:00 - %z 1972 Oct ++ -3:00 - %z 1974 Apr ++ -4:00 Para %z 2024 Oct 15 ++ -3:00 - %z + + # Peru + # +@@ -1763,12 +1815,12 @@ Rule Peru 1994 only - Apr 1 0:00 0 - + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone America/Lima -5:08:12 - LMT 1890 + -5:08:36 - LMT 1908 Jul 28 # Lima Mean Time? +- -5:00 Peru -05/-04 ++ -5:00 Peru %z + + # South Georgia + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone Atlantic/South_Georgia -2:26:08 - LMT 1890 # Grytviken +- -2:00 - -02 ++ -2:00 - %z + + # South Sandwich Is + # uninhabited; scientific personnel have wintered +@@ -1778,8 +1830,8 @@ Zone Atlantic/South_Georgia -2:26:08 - LMT 1890 # Grytviken + Zone America/Paramaribo -3:40:40 - LMT 1911 + -3:40:52 - PMT 1935 # Paramaribo Mean Time + -3:40:36 - PMT 1945 Oct # The capital moved? +- -3:30 - -0330 1984 Oct +- -3:00 - -03 ++ -3:30 - %z 1984 Oct ++ -3:00 - %z + + # Uruguay + # From Paul Eggert (1993-11-18): +@@ -1994,15 +2046,15 @@ Rule Uruguay 2006 2014 - Oct Sun>=1 2:00 1:00 - + # This Zone can be simplified once we assume zic %z. + Zone America/Montevideo -3:44:51 - LMT 1908 Jun 10 + -3:44:51 - MMT 1920 May 1 # Montevideo MT +- -4:00 - -04 1923 Oct 1 +- -3:30 Uruguay -0330/-03 1942 Dec 14 +- -3:00 Uruguay -03/-0230 1960 +- -3:00 Uruguay -03/-02 1968 +- -3:00 Uruguay -03/-0230 1970 +- -3:00 Uruguay -03/-02 1974 +- -3:00 Uruguay -03/-0130 1974 Mar 10 +- -3:00 Uruguay -03/-0230 1974 Dec 22 +- -3:00 Uruguay -03/-02 ++ -4:00 - %z 1923 Oct 1 ++ -3:30 Uruguay %z 1942 Dec 14 ++ -3:00 Uruguay %z 1960 ++ -3:00 Uruguay %z 1968 ++ -3:00 Uruguay %z 1970 ++ -3:00 Uruguay %z 1974 ++ -3:00 Uruguay %z 1974 Mar 10 ++ -3:00 Uruguay %z 1974 Dec 22 ++ -3:00 Uruguay %z + + # Venezuela + # +@@ -2036,7 +2088,7 @@ Zone America/Montevideo -3:44:51 - LMT 1908 Jun 10 + # Zone NAME STDOFF RULES FORMAT [UNTIL] + Zone America/Caracas -4:27:44 - LMT 1890 + -4:27:40 - CMT 1912 Feb 12 # Caracas Mean Time? +- -4:30 - -0430 1965 Jan 1 0:00 +- -4:00 - -04 2007 Dec 9 3:00 +- -4:30 - -0430 2016 May 1 2:30 +- -4:00 - -04 ++ -4:30 - %z 1965 Jan 1 0:00 ++ -4:00 - %z 2007 Dec 9 3:00 ++ -4:30 - %z 2016 May 1 2:30 ++ -4:00 - %z +diff --git a/make/data/tzdata/zone.tab b/make/data/tzdata/zone.tab +index 0a01e8777..c8fc60104 100644 +--- a/make/data/tzdata/zone.tab ++++ b/make/data/tzdata/zone.tab +@@ -162,7 +162,8 @@ CH +4723+00832 Europe/Zurich + CI +0519-00402 Africa/Abidjan + CK -2114-15946 Pacific/Rarotonga + CL -3327-07040 America/Santiago most of Chile +-CL -5309-07055 America/Punta_Arenas Region of Magallanes ++CL -4534-07204 America/Coyhaique Aysen Region ++CL -5309-07055 America/Punta_Arenas Magallanes Region + CL -2709-10926 Pacific/Easter Easter Island + CM +0403+00942 Africa/Douala + CN +3114+12128 Asia/Shanghai Beijing Time +@@ -287,8 +288,7 @@ MK +4159+02126 Europe/Skopje + ML +1239-00800 Africa/Bamako + MM +1647+09610 Asia/Yangon + MN +4755+10653 Asia/Ulaanbaatar most of Mongolia +-MN +4801+09139 Asia/Hovd Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan +-MN +4804+11430 Asia/Choibalsan Dornod, Sukhbaatar ++MN +4801+09139 Asia/Hovd Bayan-Olgii, Hovd, Uvs + MO +221150+1133230 Asia/Macau + MP +1512+14545 Pacific/Saipan + MQ +1436-06105 America/Martinique +@@ -334,7 +334,7 @@ PF -0900-13930 Pacific/Marquesas Marquesas Islands + PF -2308-13457 Pacific/Gambier Gambier Islands + PG -0930+14710 Pacific/Port_Moresby most of Papua New Guinea + PG -0613+15534 Pacific/Bougainville Bougainville +-PH +1435+12100 Asia/Manila ++PH +143512+1205804 Asia/Manila + PK +2452+06703 Asia/Karachi + PL +5215+02100 Europe/Warsaw + PM +4703-05620 America/Miquelon +diff --git a/make/hotspot/lib/JvmFlags.gmk b/make/hotspot/lib/JvmFlags.gmk +index 3246c8315..1a91eb007 100644 +--- a/make/hotspot/lib/JvmFlags.gmk ++++ b/make/hotspot/lib/JvmFlags.gmk +@@ -67,10 +67,12 @@ JVM_CFLAGS_TARGET_DEFINES += \ + # + + ifeq ($(DEBUG_LEVEL), release) ++ # release builds disable uses of assert macro from . ++ JVM_CFLAGS_DEBUGLEVEL := -DNDEBUG + # For hotspot, release builds differ internally between "optimized" and "product" + # in that "optimize" does not define PRODUCT. + ifneq ($(HOTSPOT_DEBUG_LEVEL), optimized) +- JVM_CFLAGS_DEBUGLEVEL := -DPRODUCT ++ JVM_CFLAGS_DEBUGLEVEL += -DPRODUCT + endif + else ifeq ($(DEBUG_LEVEL), fastdebug) + JVM_CFLAGS_DEBUGLEVEL := -DASSERT +diff --git a/make/jdk/src/classes/build/tools/tzdb/TzdbZoneRulesCompiler.java b/make/jdk/src/classes/build/tools/tzdb/TzdbZoneRulesCompiler.java +index 39aa5e35d..b7a97f50b 100644 +--- a/make/jdk/src/classes/build/tools/tzdb/TzdbZoneRulesCompiler.java ++++ b/make/jdk/src/classes/build/tools/tzdb/TzdbZoneRulesCompiler.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2012, 2024, 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 +@@ -273,7 +273,7 @@ public final class TzdbZoneRulesCompiler { + // link version-region-rules + out.writeShort(builtZones.size()); + for (Map.Entry entry : builtZones.entrySet()) { +- int regionIndex = Arrays.binarySearch(regionArray, entry.getKey()); ++ int regionIndex = findRegionIndex(regionArray, entry.getKey()); + int rulesIndex = rulesList.indexOf(entry.getValue()); + out.writeShort(regionIndex); + out.writeShort(rulesIndex); +@@ -281,8 +281,8 @@ public final class TzdbZoneRulesCompiler { + // alias-region + out.writeShort(links.size()); + for (Map.Entry entry : links.entrySet()) { +- int aliasIndex = Arrays.binarySearch(regionArray, entry.getKey()); +- int regionIndex = Arrays.binarySearch(regionArray, entry.getValue()); ++ int aliasIndex = findRegionIndex(regionArray, entry.getKey()); ++ int regionIndex = findRegionIndex(regionArray, entry.getValue()); + out.writeShort(aliasIndex); + out.writeShort(regionIndex); + } +@@ -294,6 +294,14 @@ public final class TzdbZoneRulesCompiler { + } + } + ++ private static int findRegionIndex(String[] regionArray, String region) { ++ int index = Arrays.binarySearch(regionArray, region); ++ if (index < 0) { ++ throw new IllegalArgumentException("Unknown region: " + region); ++ } ++ return index; ++ } + -+void LIR_List::cmp_cmove(LIR_Condition condition, LIR_Opr left, LIR_Opr right, LIR_Opr src1, LIR_Opr src2, LIR_Opr dst, BasicType type) { -+ cmp(condition, left, right); -+ cmove(condition, src1, src2, dst, type); -+} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp jdk11u-ls/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp ---- openjdk/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp 2022-10-12 23:00:01.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp 2023-09-12 13:54:22.977571517 +0800 -@@ -1123,7 +1123,9 @@ + /** Whether to output verbose messages. */ + private boolean verbose; + +diff --git a/make/jdk/src/classes/build/tools/tzdb/TzdbZoneRulesProvider.java b/make/jdk/src/classes/build/tools/tzdb/TzdbZoneRulesProvider.java +index f02537c30..72d2f647a 100644 +--- a/make/jdk/src/classes/build/tools/tzdb/TzdbZoneRulesProvider.java ++++ b/make/jdk/src/classes/build/tools/tzdb/TzdbZoneRulesProvider.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2014, 2024, 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 +@@ -163,7 +163,8 @@ class TzdbZoneRulesProvider { + } + continue; + } +- if (line.startsWith("Zone")) { // parse Zone line ++ int token0len = tokens.length > 0 ? tokens[0].length() : line.length(); ++ if (line.regionMatches(true, 0, "Zone", 0, token0len)) { // parse Zone line + String name = tokens[1]; + if (excludedZones.contains(name)){ + continue; +@@ -181,13 +182,13 @@ class TzdbZoneRulesProvider { + if (zLine.parse(tokens, 2)) { + openZone = null; + } +- } else if (line.startsWith("Rule")) { // parse Rule line ++ } else if (line.regionMatches(true, 0, "Rule", 0, token0len)) { // parse Rule line + String name = tokens[1]; + if (!rules.containsKey(name)) { + rules.put(name, new ArrayList(10)); + } + rules.get(name).add(new RuleLine().parse(tokens)); +- } else if (line.startsWith("Link")) { // parse link line ++ } else if (line.regionMatches(true, 0, "Link", 0, token0len)) { // parse link line + if (tokens.length >= 3) { + String realId = tokens[1]; + String aliasId = tokens[2]; +@@ -303,7 +304,7 @@ class TzdbZoneRulesProvider { + month = parseMonth(tokens[off++]); + if (off < tokens.length) { + String dayRule = tokens[off++]; +- if (dayRule.startsWith("last")) { ++ if (dayRule.regionMatches(true, 0, "last", 0, 4)) { + dayOfMonth = -1; + dayOfWeek = parseDayOfWeek(dayRule.substring(4)); + adjustForwards = false; +@@ -354,42 +355,45 @@ class TzdbZoneRulesProvider { + } + + int parseYear(String year, int defaultYear) { +- switch (year.toLowerCase()) { +- case "min": return 1900; +- case "max": return Year.MAX_VALUE; +- case "only": return defaultYear; +- } ++ int len = year.length(); ++ ++ if (year.regionMatches(true, 0, "minimum", 0, len)) return 1900; ++ if (year.regionMatches(true, 0, "maximum", 0, len)) return Year.MAX_VALUE; ++ if (year.regionMatches(true, 0, "only", 0, len)) return defaultYear; ++ + return Integer.parseInt(year); + } + + Month parseMonth(String mon) { +- switch (mon) { +- case "Jan": return Month.JANUARY; +- case "Feb": return Month.FEBRUARY; +- case "Mar": return Month.MARCH; +- case "Apr": return Month.APRIL; +- case "May": return Month.MAY; +- case "Jun": return Month.JUNE; +- case "Jul": return Month.JULY; +- case "Aug": return Month.AUGUST; +- case "Sep": return Month.SEPTEMBER; +- case "Oct": return Month.OCTOBER; +- case "Nov": return Month.NOVEMBER; +- case "Dec": return Month.DECEMBER; +- } ++ int len = mon.length(); ++ ++ if (mon.regionMatches(true, 0, "January", 0, len)) return Month.JANUARY; ++ if (mon.regionMatches(true, 0, "February", 0, len)) return Month.FEBRUARY; ++ if (mon.regionMatches(true, 0, "March", 0, len)) return Month.MARCH; ++ if (mon.regionMatches(true, 0, "April", 0, len)) return Month.APRIL; ++ if (mon.regionMatches(true, 0, "May", 0, len)) return Month.MAY; ++ if (mon.regionMatches(true, 0, "June", 0, len)) return Month.JUNE; ++ if (mon.regionMatches(true, 0, "July", 0, len)) return Month.JULY; ++ if (mon.regionMatches(true, 0, "August", 0, len)) return Month.AUGUST; ++ if (mon.regionMatches(true, 0, "September", 0, len)) return Month.SEPTEMBER; ++ if (mon.regionMatches(true, 0, "October", 0, len)) return Month.OCTOBER; ++ if (mon.regionMatches(true, 0, "November", 0, len)) return Month.NOVEMBER; ++ if (mon.regionMatches(true, 0, "December", 0, len)) return Month.DECEMBER; ++ + throw new IllegalArgumentException("Unknown month: " + mon); + } + + DayOfWeek parseDayOfWeek(String dow) { +- switch (dow) { +- case "Mon": return DayOfWeek.MONDAY; +- case "Tue": return DayOfWeek.TUESDAY; +- case "Wed": return DayOfWeek.WEDNESDAY; +- case "Thu": return DayOfWeek.THURSDAY; +- case "Fri": return DayOfWeek.FRIDAY; +- case "Sat": return DayOfWeek.SATURDAY; +- case "Sun": return DayOfWeek.SUNDAY; +- } ++ int len = dow.length(); ++ ++ if (dow.regionMatches(true, 0, "Monday", 0, len)) return DayOfWeek.MONDAY; ++ if (dow.regionMatches(true, 0, "Tuesday", 0, len)) return DayOfWeek.TUESDAY; ++ if (dow.regionMatches(true, 0, "Wednesday", 0, len)) return DayOfWeek.WEDNESDAY; ++ if (dow.regionMatches(true, 0, "Thursday", 0, len)) return DayOfWeek.THURSDAY; ++ if (dow.regionMatches(true, 0, "Friday", 0, len)) return DayOfWeek.FRIDAY; ++ if (dow.regionMatches(true, 0, "Saturday", 0, len)) return DayOfWeek.SATURDAY; ++ if (dow.regionMatches(true, 0, "Sunday", 0, len)) return DayOfWeek.SUNDAY; ++ + throw new IllegalArgumentException("Unknown day-of-week: " + dow); + } + +diff --git a/make/lib/Awt2dLibraries.gmk b/make/lib/Awt2dLibraries.gmk +index d50e5fa4c..f20f786c7 100644 +--- a/make/lib/Awt2dLibraries.gmk ++++ b/make/lib/Awt2dLibraries.gmk +@@ -388,7 +388,7 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBLCMS, \ + common/awt/debug \ + libawt/java2d, \ + HEADERS_FROM_SRC := $(LIBLCMS_HEADERS_FROM_SRC), \ +- DISABLED_WARNINGS_gcc := format-nonliteral type-limits misleading-indentation stringop-truncation, \ ++ DISABLED_WARNINGS_gcc := format-nonliteral misleading-indentation stringop-truncation, \ + DISABLED_WARNINGS_clang := tautological-compare, \ + DISABLED_WARNINGS_solstudio := E_STATEMENT_NOT_REACHED, \ + DISABLED_WARNINGS_microsoft := 4819, \ +@@ -556,7 +556,10 @@ else + HARFBUZZ_CFLAGS += -DHAVE_SOLARIS_ATOMIC_OPS + endif + # hb-ft.cc is not presently needed, and requires freetype 2.4.2 or later. +- LIBFONTMANAGER_EXCLUDE_FILES += libharfbuzz/hb-ft.cc ++ # hb-subset and hb-style APIs are not needed, excluded to cut on compilation time. ++ LIBFONTMANAGER_EXCLUDE_FILES += hb-ft.cc hb-subset-cff-common.cc \ ++ hb-subset-cff1.cc hb-subset-cff2.cc hb-subset-input.cc hb-subset-plan.cc \ ++ hb-subset.cc hb-subset-instancer-solver.cc gsubgpos-context.cc hb-style.cc + + # list of disabled warnings and the compilers for which it was specifically added. + # array-bounds -> GCC 12 on Alpine Linux +@@ -564,7 +567,7 @@ else + # range-loop-analysis -> clang on Xcode12 + + HARFBUZZ_DISABLED_WARNINGS_gcc := type-limits missing-field-initializers strict-aliasing \ +- array-bounds ++ array-bounds dangling-pointer + # noexcept-type required for GCC 7 builds. Not required for GCC 8+. + # expansion-to-defined required for GCC 9 builds. Not required for GCC 10+. + HARFBUZZ_DISABLED_WARNINGS_CXX_gcc := reorder delete-non-virtual-dtor strict-overflow \ +@@ -831,7 +834,8 @@ ifeq ($(ENABLE_HEADLESS_ONLY), false) + endif + + LIBSPLASHSCREEN_CFLAGS += -DSPLASHSCREEN -DPNG_NO_MMX_CODE \ +- -DPNG_ARM_NEON_OPT=0 -DPNG_ARM_NEON_IMPLEMENTATION=0 ++ -DPNG_ARM_NEON_OPT=0 -DPNG_ARM_NEON_IMPLEMENTATION=0 \ ++ -DPNG_LOONGARCH_LSX_OPT=0 + + ifeq ($(call isTargetOs, linux), true) + ifeq ($(call isTargetCpuArch, ppc), true) +@@ -887,9 +891,10 @@ ifeq ($(ENABLE_HEADLESS_ONLY), false) + $(GIFLIB_CFLAGS) $(LIBJPEG_CFLAGS) $(PNG_CFLAGS) $(LIBZ_CFLAGS), \ + EXTRA_HEADER_DIRS := $(LIBSPLASHSCREEN_HEADER_DIRS), \ + DISABLED_WARNINGS_gcc := sign-compare type-limits unused-result \ +- maybe-uninitialized shift-negative-value implicit-fallthrough, \ ++ maybe-uninitialized shift-negative-value implicit-fallthrough \ ++ unused-function, \ + DISABLED_WARNINGS_clang := incompatible-pointer-types deprecated-declarations \ +- $(LIBZ_DISABLED_WARNINGS_CLANG), \ ++ unused-function $(LIBZ_DISABLED_WARNINGS_CLANG), \ + DISABLED_WARNINGS_solstudio := E_NEWLINE_NOT_LAST E_DECLARATION_IN_CODE \ + E_STATEMENT_NOT_REACHED, \ + DISABLED_WARNINGS_microsoft := 4018 4244 4267, \ +diff --git a/make/lib/Lib-jdk.jdwp.agent.gmk b/make/lib/Lib-jdk.jdwp.agent.gmk +index f00f0760f..34fac90f5 100644 +--- a/make/lib/Lib-jdk.jdwp.agent.gmk ++++ b/make/lib/Lib-jdk.jdwp.agent.gmk +@@ -54,6 +54,7 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBJDWP, \ + NAME := jdwp, \ + OPTIMIZATION := LOW, \ + CFLAGS := $(CFLAGS_JDKLIB) -DJDWP_LOGGING, \ ++ DISABLED_WARNINGS_microsoft_debugInit.c := 5287, \ + EXTRA_HEADER_DIRS := \ + include \ + libjdwp/export, \ +diff --git a/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp +index fdd2c0ca3..318191233 100644 +--- a/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp ++++ b/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp +@@ -1123,7 +1123,9 @@ void LIR_Assembler::emit_opBranch(LIR_OpBranch* op) { } } @@ -165,7 +5737,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/aarch64/c1 void LIR_Assembler::emit_opConvert(LIR_OpConvert* op) { LIR_Opr src = op->in_opr(); -@@ -1663,6 +1665,10 @@ +@@ -1663,6 +1665,10 @@ void LIR_Assembler::cmove(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, L __ csel(result->as_register(), opr1->as_register(), opr2->as_register(), acond); } @@ -176,10 +5748,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/aarch64/c1 void LIR_Assembler::arith_op(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr dest, CodeEmitInfo* info, bool pop_fpu_stack) { assert(info == NULL, "should never be used, idiv/irem and ldiv/lrem not handled by this method"); -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/aarch64/c1_LIRGenerator_aarch64.cpp jdk11u-ls/src/hotspot/cpu/aarch64/c1_LIRGenerator_aarch64.cpp ---- openjdk/src/hotspot/cpu/aarch64/c1_LIRGenerator_aarch64.cpp 2022-10-12 23:00:01.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/aarch64/c1_LIRGenerator_aarch64.cpp 2023-11-01 09:34:25.457945227 +0800 -@@ -277,18 +277,29 @@ +diff --git a/src/hotspot/cpu/aarch64/c1_LIRGenerator_aarch64.cpp b/src/hotspot/cpu/aarch64/c1_LIRGenerator_aarch64.cpp +index 18b3ea147..f3398e191 100644 +--- a/src/hotspot/cpu/aarch64/c1_LIRGenerator_aarch64.cpp ++++ b/src/hotspot/cpu/aarch64/c1_LIRGenerator_aarch64.cpp +@@ -262,18 +262,29 @@ void LIRGenerator::increment_counter(LIR_Address* addr, int step) { __ store(reg, addr); } @@ -213,11 +5786,12 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/aarch64/c1 bool LIRGenerator::strength_reduce_multiply(LIR_Opr left, jint c, LIR_Opr result, LIR_Opr tmp) { -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/arm/c1_LIR_arm.cpp jdk11u-ls/src/hotspot/cpu/arm/c1_LIR_arm.cpp ---- openjdk/src/hotspot/cpu/arm/c1_LIR_arm.cpp 2022-10-12 23:00:01.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/arm/c1_LIR_arm.cpp 2023-09-12 13:54:23.041571597 +0800 -@@ -84,3 +84,24 @@ - #endif // AARCH64 +diff --git a/src/hotspot/cpu/aarch64/c1_LIR_aarch64.cpp b/src/hotspot/cpu/aarch64/c1_LIR_aarch64.cpp +index ce75dc552..74c4b7e55 100644 +--- a/src/hotspot/cpu/aarch64/c1_LIR_aarch64.cpp ++++ b/src/hotspot/cpu/aarch64/c1_LIR_aarch64.cpp +@@ -52,3 +52,24 @@ void LIR_Address::verify() const { + "wrong type for addresses"); } #endif // PRODUCT + @@ -241,10 +5815,24 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/arm/c1_LIR + cmp(condition, left, right); + cmove(condition, src1, src2, dst, type); +} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp jdk11u-ls/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp ---- openjdk/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp 2022-10-12 23:00:01.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp 2023-09-12 13:54:23.041571597 +0800 -@@ -1150,6 +1150,9 @@ +diff --git a/src/hotspot/cpu/aarch64/frame_aarch64.cpp b/src/hotspot/cpu/aarch64/frame_aarch64.cpp +index de369a1b6..e41a37b47 100644 +--- a/src/hotspot/cpu/aarch64/frame_aarch64.cpp ++++ b/src/hotspot/cpu/aarch64/frame_aarch64.cpp +@@ -84,7 +84,7 @@ bool frame::safe_for_sender(JavaThread *thread) { + // So unextended sp must be within the stack but we need not to check + // that unextended sp >= sp + +- bool unextended_sp_safe = (unextended_sp < thread->stack_base()); ++ bool unextended_sp_safe = (unextended_sp < thread->stack_base() && unextended_sp >= thread->stack_end()); + + if (!unextended_sp_safe) { + return false; +diff --git a/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp b/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp +index f0a7229aa..29db21f97 100644 +--- a/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp ++++ b/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp +@@ -1150,6 +1150,9 @@ void LIR_Assembler::emit_opBranch(LIR_OpBranch* op) { __ b(*(op->label()), acond); } @@ -254,7 +5842,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/arm/c1_LIR void LIR_Assembler::emit_opConvert(LIR_OpConvert* op) { LIR_Opr src = op->in_opr(); -@@ -3082,6 +3085,10 @@ +@@ -3082,6 +3085,10 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) { __ bind(*stub->continuation()); } @@ -265,10 +5853,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/arm/c1_LIR #ifdef ASSERT // emit run-time assertion void LIR_Assembler::emit_assert(LIR_OpAssert* op) { -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/arm/c1_LIRGenerator_arm.cpp jdk11u-ls/src/hotspot/cpu/arm/c1_LIRGenerator_arm.cpp ---- openjdk/src/hotspot/cpu/arm/c1_LIRGenerator_arm.cpp 2022-10-12 23:00:01.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/arm/c1_LIRGenerator_arm.cpp 2023-09-12 13:54:23.041571597 +0800 -@@ -423,18 +423,27 @@ +diff --git a/src/hotspot/cpu/arm/c1_LIRGenerator_arm.cpp b/src/hotspot/cpu/arm/c1_LIRGenerator_arm.cpp +index b05fc876f..b3c1afe69 100644 +--- a/src/hotspot/cpu/arm/c1_LIRGenerator_arm.cpp ++++ b/src/hotspot/cpu/arm/c1_LIRGenerator_arm.cpp +@@ -423,18 +423,27 @@ void LIRGenerator::increment_counter(LIR_Address* addr, int step) { __ move(temp, addr); } @@ -301,12 +5890,43 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/arm/c1_LIR bool LIRGenerator::strength_reduce_multiply(LIR_Opr left, jint c, LIR_Opr result, LIR_Opr tmp) { assert(left != result, "should be different registers"); -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/abstractInterpreter_loongarch.cpp jdk11u-ls/src/hotspot/cpu/loongarch/abstractInterpreter_loongarch.cpp ---- openjdk/src/hotspot/cpu/loongarch/abstractInterpreter_loongarch.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/abstractInterpreter_loongarch.cpp 2023-09-12 13:54:23.081571647 +0800 -@@ -0,0 +1,132 @@ -+/* -+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. +diff --git a/src/hotspot/cpu/arm/c1_LIR_arm.cpp b/src/hotspot/cpu/arm/c1_LIR_arm.cpp +index 806da3202..5305fe371 100644 +--- a/src/hotspot/cpu/arm/c1_LIR_arm.cpp ++++ b/src/hotspot/cpu/arm/c1_LIR_arm.cpp +@@ -84,3 +84,24 @@ void LIR_Address::verify() const { + #endif // AARCH64 + } + #endif // PRODUCT ++ ++template ++void LIR_List::cmp_branch(LIR_Condition condition, LIR_Opr left, LIR_Opr right, BasicType type, T tgt, CodeEmitInfo* info) { ++ cmp(condition, left, right, info); ++ branch(condition, type, tgt); ++} ++ ++// Explicit instantiation for all supported types. ++template void LIR_List::cmp_branch(LIR_Condition, LIR_Opr, LIR_Opr, BasicType type, Label*, CodeEmitInfo*); ++template void LIR_List::cmp_branch(LIR_Condition, LIR_Opr, LIR_Opr, BasicType type, BlockBegin*, CodeEmitInfo*); ++template void LIR_List::cmp_branch(LIR_Condition, LIR_Opr, LIR_Opr, BasicType type, CodeStub*, CodeEmitInfo*); ++ ++void LIR_List::cmp_branch(LIR_Condition condition, LIR_Opr left, LIR_Opr right, BasicType type, BlockBegin* block, BlockBegin* unordered) { ++ cmp(condition, left, right); ++ branch(condition, type, block, unordered); ++} ++ ++void LIR_List::cmp_cmove(LIR_Condition condition, LIR_Opr left, LIR_Opr right, LIR_Opr src1, LIR_Opr src2, LIR_Opr dst, BasicType type) { ++ cmp(condition, left, right); ++ cmove(condition, src1, src2, dst, type); ++} +diff --git a/src/hotspot/cpu/loongarch/abstractInterpreter_loongarch.cpp b/src/hotspot/cpu/loongarch/abstractInterpreter_loongarch.cpp +new file mode 100644 +index 000000000..0412b9953 +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/abstractInterpreter_loongarch.cpp +@@ -0,0 +1,132 @@ ++/* ++ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2021, Loongson Technology. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * @@ -437,10 +6057,12 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + *interpreter_frame->interpreter_frame_mirror_addr() = method->method_holder()->java_mirror(); +} + -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/assembler_loongarch.cpp jdk11u-ls/src/hotspot/cpu/loongarch/assembler_loongarch.cpp ---- openjdk/src/hotspot/cpu/loongarch/assembler_loongarch.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/assembler_loongarch.cpp 2023-11-01 09:34:25.477945249 +0800 -@@ -0,0 +1,850 @@ +diff --git a/src/hotspot/cpu/loongarch/assembler_loongarch.cpp b/src/hotspot/cpu/loongarch/assembler_loongarch.cpp +new file mode 100644 +index 000000000..e6e62ccca +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/assembler_loongarch.cpp +@@ -0,0 +1,849 @@ +/* + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2021, Loongson Technology. All rights reserved. @@ -852,7 +6474,6 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + ldx_w(dst, base, AT); + } + } -+//Disassembler::decode(pc()-32, pc(), tty); +} + +void Assembler::ld_wu(Register rd, Address src){ @@ -1291,10 +6912,12 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + } + } +} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/assembler_loongarch.hpp jdk11u-ls/src/hotspot/cpu/loongarch/assembler_loongarch.hpp ---- openjdk/src/hotspot/cpu/loongarch/assembler_loongarch.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/assembler_loongarch.hpp 2023-11-01 09:34:25.477945249 +0800 -@@ -0,0 +1,2804 @@ +diff --git a/src/hotspot/cpu/loongarch/assembler_loongarch.hpp b/src/hotspot/cpu/loongarch/assembler_loongarch.hpp +new file mode 100644 +index 000000000..a89b2cb56 +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/assembler_loongarch.hpp +@@ -0,0 +1,2827 @@ +/* + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2021, Loongson Technology. All rights reserved. @@ -2611,6 +8234,15 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + static int high6 (int x) { return high(x, 6); } + + ++ static ALWAYSINLINE void patch(address a, int length, uint32_t val) { ++ guarantee(val < (1ULL << length), "Field too big for insn"); ++ guarantee(length > 0, "length > 0"); ++ unsigned target = *(unsigned *)a; ++ target = (target >> length) << length; ++ target |= val; ++ *(unsigned *)a = target; ++ } ++ + protected: + // help methods for instruction ejection + @@ -2856,10 +8488,20 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + AbstractAssembler::flush(); + } + -+ inline void emit_int32(int); ++ inline void emit_int32(int x) { ++ AbstractAssembler::emit_int32(x); ++ } ++ + inline void emit_data(int x) { emit_int32(x); } -+ inline void emit_data(int, RelocationHolder const&); -+ inline void emit_data(int, relocInfo::relocType rtype); ++ inline void emit_data(int x, relocInfo::relocType rtype) { ++ relocate(rtype); ++ emit_int32(x); ++ } ++ ++ inline void emit_data(int x, RelocationHolder const& rspec) { ++ relocate(rspec); ++ emit_int32(x); ++ } + + + // Generic instructions @@ -3237,7 +8879,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + void dbar(int hint) { + assert(is_uimm(hint, 15), "not a unsigned 15-bit int"); + -+ if (os::is_ActiveCoresMP()) ++ if (UseActiveCoresMP) + andi(R0, R0, 0); + else + emit_int32(insn_I15(dbar_op, hint)); @@ -3314,18 +8956,25 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + void bceqz(ConditionalFlagRegister cj, Label& L) { bceqz(cj, target(L)); } + void bcnez(ConditionalFlagRegister cj, Label& L) { bcnez(cj, target(L)); } + -+ // Now Membar_mask_bits is 0,Need to fix it after LA6000 + typedef enum { -+ StoreStore = 0, -+ LoadStore = 0, -+ StoreLoad = 0, -+ LoadLoad = 0, -+ AnyAny = 0 ++ // hint[4] ++ Completion = 0, ++ Ordering = (1 << 4), ++ ++ // The bitwise-not of the below constants is corresponding to the hint. This is convenient for OR operation. ++ // hint[3:2] and hint[1:0] ++ LoadLoad = ((1 << 3) | (1 << 1)), ++ LoadStore = ((1 << 3) | (1 << 0)), ++ StoreLoad = ((1 << 2) | (1 << 1)), ++ StoreStore = ((1 << 2) | (1 << 0)), ++ AnyAny = ((3 << 2) | (3 << 0)), + } Membar_mask_bits; + + // Serializes memory and blows flags + void membar(Membar_mask_bits hint) { -+ dbar(hint); ++ assert((hint & (3 << 0)) != 0, "membar mask unsupported!"); ++ assert((hint & (3 << 2)) != 0, "membar mask unsupported!"); ++ dbar(Ordering | (~hint & 0xf)); + } + + // LSX and LASX @@ -4095,14 +9744,13 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + static address locate_next_instruction(address inst); +}; + -+ -+#include "assembler_loongarch.inline.hpp" -+ +#endif // CPU_LOONGARCH_ASSEMBLER_LOONGARCH_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/assembler_loongarch.inline.hpp jdk11u-ls/src/hotspot/cpu/loongarch/assembler_loongarch.inline.hpp ---- openjdk/src/hotspot/cpu/loongarch/assembler_loongarch.inline.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/assembler_loongarch.inline.hpp 2023-11-01 09:34:25.477945249 +0800 -@@ -0,0 +1,47 @@ +diff --git a/src/hotspot/cpu/loongarch/assembler_loongarch.inline.hpp b/src/hotspot/cpu/loongarch/assembler_loongarch.inline.hpp +new file mode 100644 +index 000000000..9ca0cd450 +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/assembler_loongarch.inline.hpp +@@ -0,0 +1,33 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, Loongson Technology. All rights reserved. @@ -4135,24 +9783,12 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ +#include "asm/codeBuffer.hpp" +#include "code/codeCache.hpp" + -+inline void Assembler::emit_int32(int x) { -+ AbstractAssembler::emit_int32(x); -+} -+ -+inline void Assembler::emit_data(int x, relocInfo::relocType rtype) { -+ relocate(rtype); -+ emit_int32(x); -+} -+ -+inline void Assembler::emit_data(int x, RelocationHolder const& rspec) { -+ relocate(rspec); -+ emit_int32(x); -+} -+ +#endif // CPU_LOONGARCH_ASSEMBLER_LOONGARCH_INLINE_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/bytes_loongarch.hpp jdk11u-ls/src/hotspot/cpu/loongarch/bytes_loongarch.hpp ---- openjdk/src/hotspot/cpu/loongarch/bytes_loongarch.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/bytes_loongarch.hpp 2023-09-12 13:54:23.081571647 +0800 +diff --git a/src/hotspot/cpu/loongarch/bytes_loongarch.hpp b/src/hotspot/cpu/loongarch/bytes_loongarch.hpp +new file mode 100644 +index 000000000..c15344eb3 +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/bytes_loongarch.hpp @@ -0,0 +1,73 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. @@ -4227,9 +9863,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ +#include OS_CPU_HEADER_INLINE(bytes) + +#endif // CPU_LOONGARCH_BYTES_LOONGARCH_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/c1_CodeStubs_loongarch_64.cpp jdk11u-ls/src/hotspot/cpu/loongarch/c1_CodeStubs_loongarch_64.cpp ---- openjdk/src/hotspot/cpu/loongarch/c1_CodeStubs_loongarch_64.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/c1_CodeStubs_loongarch_64.cpp 2023-09-12 13:54:23.081571647 +0800 +diff --git a/src/hotspot/cpu/loongarch/c1_CodeStubs_loongarch_64.cpp b/src/hotspot/cpu/loongarch/c1_CodeStubs_loongarch_64.cpp +new file mode 100644 +index 000000000..c0eeb6396 +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/c1_CodeStubs_loongarch_64.cpp @@ -0,0 +1,344 @@ +/* + * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. @@ -4575,9 +10213,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ +} + +#undef __ -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/c1_Defs_loongarch.hpp jdk11u-ls/src/hotspot/cpu/loongarch/c1_Defs_loongarch.hpp ---- openjdk/src/hotspot/cpu/loongarch/c1_Defs_loongarch.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/c1_Defs_loongarch.hpp 2023-09-12 13:54:23.081571647 +0800 +diff --git a/src/hotspot/cpu/loongarch/c1_Defs_loongarch.hpp b/src/hotspot/cpu/loongarch/c1_Defs_loongarch.hpp +new file mode 100644 +index 000000000..1140e4443 +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/c1_Defs_loongarch.hpp @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. @@ -4658,9 +10298,49 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ +}; + +#endif // CPU_LOONGARCH_C1_DEFS_LOONGARCH_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/c1_FpuStackSim_loongarch_64.cpp jdk11u-ls/src/hotspot/cpu/loongarch/c1_FpuStackSim_loongarch_64.cpp ---- openjdk/src/hotspot/cpu/loongarch/c1_FpuStackSim_loongarch_64.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/c1_FpuStackSim_loongarch_64.cpp 2023-09-12 13:54:23.081571647 +0800 +diff --git a/src/hotspot/cpu/loongarch/c1_FpuStackSim_loongarch.hpp b/src/hotspot/cpu/loongarch/c1_FpuStackSim_loongarch.hpp +new file mode 100644 +index 000000000..bd8578c72 +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/c1_FpuStackSim_loongarch.hpp +@@ -0,0 +1,32 @@ ++/* ++ * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2021, 2022, Loongson Technology. 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 CPU_LOONGARCH_C1_FPUSTACKSIM_LOONGARCH_HPP ++#define CPU_LOONGARCH_C1_FPUSTACKSIM_LOONGARCH_HPP ++ ++// No FPU stack on LoongArch ++class FpuStackSim; ++ ++#endif // CPU_LOONGARCH_C1_FPUSTACKSIM_LOONGARCH_HPP +diff --git a/src/hotspot/cpu/loongarch/c1_FpuStackSim_loongarch_64.cpp b/src/hotspot/cpu/loongarch/c1_FpuStackSim_loongarch_64.cpp +new file mode 100644 +index 000000000..1a89c437a +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/c1_FpuStackSim_loongarch_64.cpp @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved. @@ -4693,13 +10373,15 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + +// No FPU stack on LoongArch64 +#include "precompiled.hpp" -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/c1_FpuStackSim_loongarch.hpp jdk11u-ls/src/hotspot/cpu/loongarch/c1_FpuStackSim_loongarch.hpp ---- openjdk/src/hotspot/cpu/loongarch/c1_FpuStackSim_loongarch.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/c1_FpuStackSim_loongarch.hpp 2023-09-12 13:54:23.081571647 +0800 -@@ -0,0 +1,32 @@ +diff --git a/src/hotspot/cpu/loongarch/c1_FrameMap_loongarch.hpp b/src/hotspot/cpu/loongarch/c1_FrameMap_loongarch.hpp +new file mode 100644 +index 000000000..4f0cf0536 +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/c1_FrameMap_loongarch.hpp +@@ -0,0 +1,143 @@ +/* -+ * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2021, 2022, Loongson Technology. All rights reserved. ++ * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2021, Loongson Technology. 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 @@ -4722,16 +10404,129 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + * + */ + -+#ifndef CPU_LOONGARCH_C1_FPUSTACKSIM_LOONGARCH_HPP -+#define CPU_LOONGARCH_C1_FPUSTACKSIM_LOONGARCH_HPP ++#ifndef CPU_LOONGARCH_C1_FRAMEMAP_LOONGARCH_HPP ++#define CPU_LOONGARCH_C1_FRAMEMAP_LOONGARCH_HPP + -+// No FPU stack on LoongArch -+class FpuStackSim; ++// On LoongArch64 the frame looks as follows: ++// ++// +-----------------------------+---------+----------------------------------------+----------------+----------- ++// | size_arguments-nof_reg_args | 2 words | size_locals-size_arguments+numreg_args | _size_monitors | spilling . ++// +-----------------------------+---------+----------------------------------------+----------------+----------- + -+#endif // CPU_LOONGARCH_C1_FPUSTACKSIM_LOONGARCH_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/c1_FrameMap_loongarch_64.cpp jdk11u-ls/src/hotspot/cpu/loongarch/c1_FrameMap_loongarch_64.cpp ---- openjdk/src/hotspot/cpu/loongarch/c1_FrameMap_loongarch_64.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/c1_FrameMap_loongarch_64.cpp 2023-09-12 13:54:23.081571647 +0800 ++ public: ++ static const int pd_c_runtime_reserved_arg_size; ++ ++ enum { ++ first_available_sp_in_frame = 0, ++ frame_pad_in_bytes = 16, ++ nof_reg_args = 8 ++ }; ++ ++ public: ++ static LIR_Opr receiver_opr; ++ ++ static LIR_Opr r0_opr; ++ static LIR_Opr ra_opr; ++ static LIR_Opr tp_opr; ++ static LIR_Opr sp_opr; ++ static LIR_Opr a0_opr; ++ static LIR_Opr a1_opr; ++ static LIR_Opr a2_opr; ++ static LIR_Opr a3_opr; ++ static LIR_Opr a4_opr; ++ static LIR_Opr a5_opr; ++ static LIR_Opr a6_opr; ++ static LIR_Opr a7_opr; ++ static LIR_Opr t0_opr; ++ static LIR_Opr t1_opr; ++ static LIR_Opr t2_opr; ++ static LIR_Opr t3_opr; ++ static LIR_Opr t4_opr; ++ static LIR_Opr t5_opr; ++ static LIR_Opr t6_opr; ++ static LIR_Opr t7_opr; ++ static LIR_Opr t8_opr; ++ static LIR_Opr rx_opr; ++ static LIR_Opr fp_opr; ++ static LIR_Opr s0_opr; ++ static LIR_Opr s1_opr; ++ static LIR_Opr s2_opr; ++ static LIR_Opr s3_opr; ++ static LIR_Opr s4_opr; ++ static LIR_Opr s5_opr; ++ static LIR_Opr s6_opr; ++ static LIR_Opr s7_opr; ++ static LIR_Opr s8_opr; ++ ++ static LIR_Opr ra_oop_opr; ++ static LIR_Opr a0_oop_opr; ++ static LIR_Opr a1_oop_opr; ++ static LIR_Opr a2_oop_opr; ++ static LIR_Opr a3_oop_opr; ++ static LIR_Opr a4_oop_opr; ++ static LIR_Opr a5_oop_opr; ++ static LIR_Opr a6_oop_opr; ++ static LIR_Opr a7_oop_opr; ++ static LIR_Opr t0_oop_opr; ++ static LIR_Opr t1_oop_opr; ++ static LIR_Opr t2_oop_opr; ++ static LIR_Opr t3_oop_opr; ++ static LIR_Opr t4_oop_opr; ++ static LIR_Opr t5_oop_opr; ++ static LIR_Opr t6_oop_opr; ++ static LIR_Opr t7_oop_opr; ++ static LIR_Opr t8_oop_opr; ++ static LIR_Opr fp_oop_opr; ++ static LIR_Opr s0_oop_opr; ++ static LIR_Opr s1_oop_opr; ++ static LIR_Opr s2_oop_opr; ++ static LIR_Opr s3_oop_opr; ++ static LIR_Opr s4_oop_opr; ++ static LIR_Opr s5_oop_opr; ++ static LIR_Opr s6_oop_opr; ++ static LIR_Opr s7_oop_opr; ++ static LIR_Opr s8_oop_opr; ++ ++ static LIR_Opr scr1_opr; ++ static LIR_Opr scr2_opr; ++ static LIR_Opr scr1_long_opr; ++ static LIR_Opr scr2_long_opr; ++ ++ static LIR_Opr a0_metadata_opr; ++ static LIR_Opr a1_metadata_opr; ++ static LIR_Opr a2_metadata_opr; ++ static LIR_Opr a3_metadata_opr; ++ static LIR_Opr a4_metadata_opr; ++ static LIR_Opr a5_metadata_opr; ++ ++ static LIR_Opr long0_opr; ++ static LIR_Opr long1_opr; ++ static LIR_Opr fpu0_float_opr; ++ static LIR_Opr fpu0_double_opr; ++ ++ static LIR_Opr as_long_opr(Register r) { ++ return LIR_OprFact::double_cpu(cpu_reg2rnr(r), cpu_reg2rnr(r)); ++ } ++ static LIR_Opr as_pointer_opr(Register r) { ++ return LIR_OprFact::double_cpu(cpu_reg2rnr(r), cpu_reg2rnr(r)); ++ } ++ ++ // VMReg name for spilled physical FPU stack slot n ++ static VMReg fpu_regname (int n); ++ ++ static bool is_caller_save_register(LIR_Opr opr) { return true; } ++ static bool is_caller_save_register(Register r) { return true; } ++ ++ static int nof_caller_save_cpu_regs() { return pd_nof_caller_save_cpu_regs_frame_map; } ++ static int last_cpu_reg() { return pd_last_cpu_reg; } ++ static int last_byte_reg() { return pd_last_byte_reg; } ++ ++#endif // CPU_LOONGARCH_C1_FRAMEMAP_LOONGARCH_HPP +diff --git a/src/hotspot/cpu/loongarch/c1_FrameMap_loongarch_64.cpp b/src/hotspot/cpu/loongarch/c1_FrameMap_loongarch_64.cpp +new file mode 100644 +index 000000000..3b6089907 +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/c1_FrameMap_loongarch_64.cpp @@ -0,0 +1,354 @@ +/* + * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. @@ -5087,157 +10882,12 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ +bool FrameMap::validate_frame() { + return true; +} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/c1_FrameMap_loongarch.hpp jdk11u-ls/src/hotspot/cpu/loongarch/c1_FrameMap_loongarch.hpp ---- openjdk/src/hotspot/cpu/loongarch/c1_FrameMap_loongarch.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/c1_FrameMap_loongarch.hpp 2023-09-12 13:54:23.081571647 +0800 -@@ -0,0 +1,143 @@ -+/* -+ * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2021, Loongson Technology. 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 CPU_LOONGARCH_C1_FRAMEMAP_LOONGARCH_HPP -+#define CPU_LOONGARCH_C1_FRAMEMAP_LOONGARCH_HPP -+ -+// On LoongArch64 the frame looks as follows: -+// -+// +-----------------------------+---------+----------------------------------------+----------------+----------- -+// | size_arguments-nof_reg_args | 2 words | size_locals-size_arguments+numreg_args | _size_monitors | spilling . -+// +-----------------------------+---------+----------------------------------------+----------------+----------- -+ -+ public: -+ static const int pd_c_runtime_reserved_arg_size; -+ -+ enum { -+ first_available_sp_in_frame = 0, -+ frame_pad_in_bytes = 16, -+ nof_reg_args = 8 -+ }; -+ -+ public: -+ static LIR_Opr receiver_opr; -+ -+ static LIR_Opr r0_opr; -+ static LIR_Opr ra_opr; -+ static LIR_Opr tp_opr; -+ static LIR_Opr sp_opr; -+ static LIR_Opr a0_opr; -+ static LIR_Opr a1_opr; -+ static LIR_Opr a2_opr; -+ static LIR_Opr a3_opr; -+ static LIR_Opr a4_opr; -+ static LIR_Opr a5_opr; -+ static LIR_Opr a6_opr; -+ static LIR_Opr a7_opr; -+ static LIR_Opr t0_opr; -+ static LIR_Opr t1_opr; -+ static LIR_Opr t2_opr; -+ static LIR_Opr t3_opr; -+ static LIR_Opr t4_opr; -+ static LIR_Opr t5_opr; -+ static LIR_Opr t6_opr; -+ static LIR_Opr t7_opr; -+ static LIR_Opr t8_opr; -+ static LIR_Opr rx_opr; -+ static LIR_Opr fp_opr; -+ static LIR_Opr s0_opr; -+ static LIR_Opr s1_opr; -+ static LIR_Opr s2_opr; -+ static LIR_Opr s3_opr; -+ static LIR_Opr s4_opr; -+ static LIR_Opr s5_opr; -+ static LIR_Opr s6_opr; -+ static LIR_Opr s7_opr; -+ static LIR_Opr s8_opr; -+ -+ static LIR_Opr ra_oop_opr; -+ static LIR_Opr a0_oop_opr; -+ static LIR_Opr a1_oop_opr; -+ static LIR_Opr a2_oop_opr; -+ static LIR_Opr a3_oop_opr; -+ static LIR_Opr a4_oop_opr; -+ static LIR_Opr a5_oop_opr; -+ static LIR_Opr a6_oop_opr; -+ static LIR_Opr a7_oop_opr; -+ static LIR_Opr t0_oop_opr; -+ static LIR_Opr t1_oop_opr; -+ static LIR_Opr t2_oop_opr; -+ static LIR_Opr t3_oop_opr; -+ static LIR_Opr t4_oop_opr; -+ static LIR_Opr t5_oop_opr; -+ static LIR_Opr t6_oop_opr; -+ static LIR_Opr t7_oop_opr; -+ static LIR_Opr t8_oop_opr; -+ static LIR_Opr fp_oop_opr; -+ static LIR_Opr s0_oop_opr; -+ static LIR_Opr s1_oop_opr; -+ static LIR_Opr s2_oop_opr; -+ static LIR_Opr s3_oop_opr; -+ static LIR_Opr s4_oop_opr; -+ static LIR_Opr s5_oop_opr; -+ static LIR_Opr s6_oop_opr; -+ static LIR_Opr s7_oop_opr; -+ static LIR_Opr s8_oop_opr; -+ -+ static LIR_Opr scr1_opr; -+ static LIR_Opr scr2_opr; -+ static LIR_Opr scr1_long_opr; -+ static LIR_Opr scr2_long_opr; -+ -+ static LIR_Opr a0_metadata_opr; -+ static LIR_Opr a1_metadata_opr; -+ static LIR_Opr a2_metadata_opr; -+ static LIR_Opr a3_metadata_opr; -+ static LIR_Opr a4_metadata_opr; -+ static LIR_Opr a5_metadata_opr; -+ -+ static LIR_Opr long0_opr; -+ static LIR_Opr long1_opr; -+ static LIR_Opr fpu0_float_opr; -+ static LIR_Opr fpu0_double_opr; -+ -+ static LIR_Opr as_long_opr(Register r) { -+ return LIR_OprFact::double_cpu(cpu_reg2rnr(r), cpu_reg2rnr(r)); -+ } -+ static LIR_Opr as_pointer_opr(Register r) { -+ return LIR_OprFact::double_cpu(cpu_reg2rnr(r), cpu_reg2rnr(r)); -+ } -+ -+ // VMReg name for spilled physical FPU stack slot n -+ static VMReg fpu_regname (int n); -+ -+ static bool is_caller_save_register(LIR_Opr opr) { return true; } -+ static bool is_caller_save_register(Register r) { return true; } -+ -+ static int nof_caller_save_cpu_regs() { return pd_nof_caller_save_cpu_regs_frame_map; } -+ static int last_cpu_reg() { return pd_last_cpu_reg; } -+ static int last_byte_reg() { return pd_last_byte_reg; } -+ -+#endif // CPU_LOONGARCH_C1_FRAMEMAP_LOONGARCH_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/c1_globals_loongarch.hpp jdk11u-ls/src/hotspot/cpu/loongarch/c1_globals_loongarch.hpp ---- openjdk/src/hotspot/cpu/loongarch/c1_globals_loongarch.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/c1_globals_loongarch.hpp 2023-11-01 09:34:25.477945249 +0800 -@@ -0,0 +1,67 @@ +diff --git a/src/hotspot/cpu/loongarch/c1_LIRAssembler_loongarch.hpp b/src/hotspot/cpu/loongarch/c1_LIRAssembler_loongarch.hpp +new file mode 100644 +index 000000000..40d9408f1 +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/c1_LIRAssembler_loongarch.hpp +@@ -0,0 +1,83 @@ +/* + * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, Loongson Technology. All rights reserved. @@ -5263,162 +10913,69 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + * + */ + -+#ifndef CPU_LOONGARCH_C1_GLOBALS_LOONGARCH_HPP -+#define CPU_LOONGARCH_C1_GLOBALS_LOONGARCH_HPP ++#ifndef CPU_LOONGARCH_C1_LIRASSEMBLER_LOONGARCH_HPP ++#define CPU_LOONGARCH_C1_LIRASSEMBLER_LOONGARCH_HPP + -+#include "utilities/globalDefinitions.hpp" -+#include "utilities/macros.hpp" ++// ArrayCopyStub needs access to bailout ++friend class ArrayCopyStub; + -+// Sets the default values for platform dependent flags used by the client compiler. -+// (see c1_globals.hpp) ++ private: ++ int array_element_size(BasicType type) const; + -+#ifndef COMPILER2 -+define_pd_global(bool, BackgroundCompilation, true ); -+define_pd_global(bool, InlineIntrinsics, true ); -+define_pd_global(bool, PreferInterpreterNativeStubs, false); -+define_pd_global(bool, ProfileTraps, false); -+define_pd_global(bool, UseOnStackReplacement, true ); -+define_pd_global(bool, TieredCompilation, false); -+define_pd_global(intx, CompileThreshold, 1500 ); ++ void arith_fpu_implementation(LIR_Code code, int left_index, int right_index, ++ int dest_index, bool pop_fpu_stack); + -+define_pd_global(intx, OnStackReplacePercentage, 933 ); -+define_pd_global(intx, NewSizeThreadIncrease, 4*K ); -+define_pd_global(intx, InitialCodeCacheSize, 160*K); -+define_pd_global(intx, ReservedCodeCacheSize, 32*M ); -+define_pd_global(intx, NonProfiledCodeHeapSize, 13*M ); -+define_pd_global(intx, ProfiledCodeHeapSize, 14*M ); -+define_pd_global(intx, NonNMethodCodeHeapSize, 5*M ); -+define_pd_global(bool, ProfileInterpreter, false); -+define_pd_global(intx, CodeCacheExpansionSize, 32*K ); -+define_pd_global(uintx, CodeCacheMinBlockLength, 1); -+define_pd_global(uintx, CodeCacheMinimumUseSpace, 400*K); -+define_pd_global(bool, NeverActAsServerClassMachine, true ); -+define_pd_global(uint64_t,MaxRAM, 1ULL*G); -+define_pd_global(bool, CICompileOSR, true ); -+#endif // !COMPILER2 -+define_pd_global(bool, UseTypeProfile, false); -+define_pd_global(bool, RoundFPResults, true ); ++ // helper functions which checks for overflow and sets bailout if it ++ // occurs. Always returns a valid embeddable pointer but in the ++ // bailout case the pointer won't be to unique storage. ++ address float_constant(float f); ++ address double_constant(double d); + -+define_pd_global(bool, LIRFillDelaySlots, false); -+define_pd_global(bool, OptimizeSinglePrecision, true ); -+define_pd_global(bool, CSEArrayLength, false); -+define_pd_global(bool, TwoOperandLIRForm, false ); ++ address int_constant(jlong n); + -+#endif // CPU_LOONGARCH_C1_GLOBALS_LOONGARCH_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/c1_LinearScan_loongarch_64.cpp jdk11u-ls/src/hotspot/cpu/loongarch/c1_LinearScan_loongarch_64.cpp ---- openjdk/src/hotspot/cpu/loongarch/c1_LinearScan_loongarch_64.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/c1_LinearScan_loongarch_64.cpp 2023-09-12 13:54:23.081571647 +0800 -@@ -0,0 +1,33 @@ -+/* -+ * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. All rights reserved. -+ * Copyright (c) 2021, Loongson Technology. 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. -+ * -+ */ ++ bool is_literal_address(LIR_Address* addr); + -+#include "precompiled.hpp" -+#include "c1/c1_Instruction.hpp" -+#include "c1/c1_LinearScan.hpp" -+#include "utilities/bitMap.inline.hpp" ++ // Ensure we have a valid Address (base+offset) to a stack-slot. ++ Address stack_slot_address(int index, uint shift, int adjust = 0); + -+void LinearScan::allocate_fpu_stack() { -+ // No FPU stack on LoongArch64 -+} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/c1_LinearScan_loongarch.hpp jdk11u-ls/src/hotspot/cpu/loongarch/c1_LinearScan_loongarch.hpp ---- openjdk/src/hotspot/cpu/loongarch/c1_LinearScan_loongarch.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/c1_LinearScan_loongarch.hpp 2023-09-12 13:54:23.081571647 +0800 -@@ -0,0 +1,70 @@ -+/* -+ * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2021, Loongson Technology. 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. -+ * -+ */ ++ // Record the type of the receiver in ReceiverTypeData ++ void type_profile_helper(Register mdo, ciMethodData *md, ciProfileData *data, ++ Register recv, Label* update_done); ++ void add_debug_info_for_branch(address adr, CodeEmitInfo* info); + -+#ifndef CPU_LOONGARCH_C1_LINEARSCAN_LOONGARCH_HPP -+#define CPU_LOONGARCH_C1_LINEARSCAN_LOONGARCH_HPP ++ void casw(Register addr, Register newval, Register cmpval, bool sign); ++ void casl(Register addr, Register newval, Register cmpval); + -+inline bool LinearScan::is_processed_reg_num(int reg_num) { -+ return reg_num <= FrameMap::last_cpu_reg() || reg_num >= pd_nof_cpu_regs_frame_map; -+} ++ void poll_for_safepoint(relocInfo::relocType rtype, CodeEmitInfo* info = NULL); + -+inline int LinearScan::num_physical_regs(BasicType type) { -+ return 1; -+} ++ static const int max_tableswitches = 20; ++ struct tableswitch switches[max_tableswitches]; ++ int tableswitch_count; + -+inline bool LinearScan::requires_adjacent_regs(BasicType type) { -+ return false; -+} ++ void init() { tableswitch_count = 0; } + -+inline bool LinearScan::is_caller_save(int assigned_reg) { -+ assert(assigned_reg >= 0 && assigned_reg < nof_regs, "should call this only for registers"); -+ if (assigned_reg < pd_first_callee_saved_reg) -+ return true; -+ if (assigned_reg > pd_last_callee_saved_reg && assigned_reg < pd_first_callee_saved_fpu_reg) -+ return true; -+ if (assigned_reg > pd_last_callee_saved_fpu_reg && assigned_reg < pd_last_fpu_reg) -+ return true; -+ return false; -+} ++ void deoptimize_trap(CodeEmitInfo *info); + -+inline void LinearScan::pd_add_temps(LIR_Op* op) {} ++ enum { ++ // call stub: CompiledStaticCall::to_interp_stub_size() + ++ // CompiledStaticCall::to_trampoline_stub_size() ++ _call_stub_size = 13 * NativeInstruction::nop_instruction_size, ++ _call_aot_stub_size = 0, ++ _exception_handler_size = DEBUG_ONLY(1*K) NOT_DEBUG(175), ++ _deopt_handler_size = 7 * NativeInstruction::nop_instruction_size ++ }; + -+// Implementation of LinearScanWalker -+inline bool LinearScanWalker::pd_init_regs_for_alloc(Interval* cur) { -+ if (allocator()->gen()->is_vreg_flag_set(cur->reg_num(), LIRGenerator::callee_saved)) { -+ assert(cur->type() != T_FLOAT && cur->type() != T_DOUBLE, "cpu regs only"); -+ _first_reg = pd_first_callee_saved_reg; -+ _last_reg = pd_last_callee_saved_reg; -+ return true; -+ } else if (cur->type() == T_INT || cur->type() == T_LONG || cur->type() == T_OBJECT || -+ cur->type() == T_ADDRESS || cur->type() == T_METADATA) { -+ _first_reg = pd_first_cpu_reg; -+ _last_reg = pd_last_allocatable_cpu_reg; -+ return true; -+ } -+ return false; -+} ++public: ++ void store_parameter(Register r, int offset_from_sp_in_words); ++ void store_parameter(jint c, int offset_from_sp_in_words); ++ void store_parameter(jobject c, int offset_from_sp_in_words); + -+#endif // CPU_LOONGARCH_C1_LINEARSCAN_LOONGARCH_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/c1_LIRAssembler_loongarch_64.cpp jdk11u-ls/src/hotspot/cpu/loongarch/c1_LIRAssembler_loongarch_64.cpp ---- openjdk/src/hotspot/cpu/loongarch/c1_LIRAssembler_loongarch_64.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/c1_LIRAssembler_loongarch_64.cpp 2023-09-12 13:54:23.081571647 +0800 ++#endif // CPU_LOONGARCH_C1_LIRASSEMBLER_LOONGARCH_HPP +diff --git a/src/hotspot/cpu/loongarch/c1_LIRAssembler_loongarch_64.cpp b/src/hotspot/cpu/loongarch/c1_LIRAssembler_loongarch_64.cpp +new file mode 100644 +index 000000000..c989e25c3 +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/c1_LIRAssembler_loongarch_64.cpp @@ -0,0 +1,3387 @@ +/* + * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. @@ -8807,100 +14364,15 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ +} + +#undef __ -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/c1_LIRAssembler_loongarch.hpp jdk11u-ls/src/hotspot/cpu/loongarch/c1_LIRAssembler_loongarch.hpp ---- openjdk/src/hotspot/cpu/loongarch/c1_LIRAssembler_loongarch.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/c1_LIRAssembler_loongarch.hpp 2023-09-12 13:54:23.081571647 +0800 -@@ -0,0 +1,83 @@ -+/* -+ * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2021, Loongson Technology. 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 CPU_LOONGARCH_C1_LIRASSEMBLER_LOONGARCH_HPP -+#define CPU_LOONGARCH_C1_LIRASSEMBLER_LOONGARCH_HPP -+ -+// ArrayCopyStub needs access to bailout -+friend class ArrayCopyStub; -+ -+ private: -+ int array_element_size(BasicType type) const; -+ -+ void arith_fpu_implementation(LIR_Code code, int left_index, int right_index, -+ int dest_index, bool pop_fpu_stack); -+ -+ // helper functions which checks for overflow and sets bailout if it -+ // occurs. Always returns a valid embeddable pointer but in the -+ // bailout case the pointer won't be to unique storage. -+ address float_constant(float f); -+ address double_constant(double d); -+ -+ address int_constant(jlong n); -+ -+ bool is_literal_address(LIR_Address* addr); -+ -+ // Ensure we have a valid Address (base+offset) to a stack-slot. -+ Address stack_slot_address(int index, uint shift, int adjust = 0); -+ -+ // Record the type of the receiver in ReceiverTypeData -+ void type_profile_helper(Register mdo, ciMethodData *md, ciProfileData *data, -+ Register recv, Label* update_done); -+ void add_debug_info_for_branch(address adr, CodeEmitInfo* info); -+ -+ void casw(Register addr, Register newval, Register cmpval, bool sign); -+ void casl(Register addr, Register newval, Register cmpval); -+ -+ void poll_for_safepoint(relocInfo::relocType rtype, CodeEmitInfo* info = NULL); -+ -+ static const int max_tableswitches = 20; -+ struct tableswitch switches[max_tableswitches]; -+ int tableswitch_count; -+ -+ void init() { tableswitch_count = 0; } -+ -+ void deoptimize_trap(CodeEmitInfo *info); -+ -+ enum { -+ // call stub: CompiledStaticCall::to_interp_stub_size() + -+ // CompiledStaticCall::to_trampoline_stub_size() -+ _call_stub_size = 13 * NativeInstruction::nop_instruction_size, -+ _call_aot_stub_size = 0, -+ _exception_handler_size = DEBUG_ONLY(1*K) NOT_DEBUG(175), -+ _deopt_handler_size = 7 * NativeInstruction::nop_instruction_size -+ }; -+ -+public: -+ void store_parameter(Register r, int offset_from_sp_in_words); -+ void store_parameter(jint c, int offset_from_sp_in_words); -+ void store_parameter(jobject c, int offset_from_sp_in_words); -+ -+#endif // CPU_LOONGARCH_C1_LIRASSEMBLER_LOONGARCH_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/c1_LIRGenerator_loongarch_64.cpp jdk11u-ls/src/hotspot/cpu/loongarch/c1_LIRGenerator_loongarch_64.cpp ---- openjdk/src/hotspot/cpu/loongarch/c1_LIRGenerator_loongarch_64.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/c1_LIRGenerator_loongarch_64.cpp 2023-09-12 13:54:23.081571647 +0800 -@@ -0,0 +1,1396 @@ +diff --git a/src/hotspot/cpu/loongarch/c1_LIRGenerator_loongarch_64.cpp b/src/hotspot/cpu/loongarch/c1_LIRGenerator_loongarch_64.cpp +new file mode 100644 +index 000000000..6cb77f3fb +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/c1_LIRGenerator_loongarch_64.cpp +@@ -0,0 +1,1398 @@ +/* + * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2021, 2022, Loongson Technology. All rights reserved. ++ * Copyright (c) 2021, 2024, Loongson Technology. 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 @@ -9056,8 +14528,10 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + if (index->is_register()) { + // apply the shift and accumulate the displacement + if (shift > 0) { -+ LIR_Opr tmp = new_pointer_register(); -+ __ shift_left(index, shift, tmp); ++ // Use long register to avoid overflow when shifting large index values left. ++ LIR_Opr tmp = new_register(T_LONG); ++ __ convert(Bytecodes::_i2l, index, tmp); ++ __ shift_left(tmp, shift, tmp); + index = tmp; + } + if (large_disp != 0) { @@ -10294,9 +15768,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + } + __ volatile_load_mem_reg(address, result, info); +} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/c1_LIR_loongarch_64.cpp jdk11u-ls/src/hotspot/cpu/loongarch/c1_LIR_loongarch_64.cpp ---- openjdk/src/hotspot/cpu/loongarch/c1_LIR_loongarch_64.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/c1_LIR_loongarch_64.cpp 2023-09-12 13:54:23.081571647 +0800 +diff --git a/src/hotspot/cpu/loongarch/c1_LIR_loongarch_64.cpp b/src/hotspot/cpu/loongarch/c1_LIR_loongarch_64.cpp +new file mode 100644 +index 000000000..6bb15fbf1 +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/c1_LIR_loongarch_64.cpp @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. @@ -10373,10 +15849,127 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ +void LIR_List::cmp_cmove(LIR_Condition condition, LIR_Opr left, LIR_Opr right, LIR_Opr src1, LIR_Opr src2, LIR_Opr dst, BasicType type) { + append(new LIR_Op4(lir_cmp_cmove, condition, left, right, src1, src2, dst, type)); +} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/c1_MacroAssembler_loongarch_64.cpp jdk11u-ls/src/hotspot/cpu/loongarch/c1_MacroAssembler_loongarch_64.cpp ---- openjdk/src/hotspot/cpu/loongarch/c1_MacroAssembler_loongarch_64.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/c1_MacroAssembler_loongarch_64.cpp 2023-11-01 09:34:25.477945249 +0800 -@@ -0,0 +1,343 @@ +diff --git a/src/hotspot/cpu/loongarch/c1_LinearScan_loongarch.hpp b/src/hotspot/cpu/loongarch/c1_LinearScan_loongarch.hpp +new file mode 100644 +index 000000000..f15dacafe +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/c1_LinearScan_loongarch.hpp +@@ -0,0 +1,70 @@ ++/* ++ * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2021, Loongson Technology. 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 CPU_LOONGARCH_C1_LINEARSCAN_LOONGARCH_HPP ++#define CPU_LOONGARCH_C1_LINEARSCAN_LOONGARCH_HPP ++ ++inline bool LinearScan::is_processed_reg_num(int reg_num) { ++ return reg_num <= FrameMap::last_cpu_reg() || reg_num >= pd_nof_cpu_regs_frame_map; ++} ++ ++inline int LinearScan::num_physical_regs(BasicType type) { ++ return 1; ++} ++ ++inline bool LinearScan::requires_adjacent_regs(BasicType type) { ++ return false; ++} ++ ++inline bool LinearScan::is_caller_save(int assigned_reg) { ++ assert(assigned_reg >= 0 && assigned_reg < nof_regs, "should call this only for registers"); ++ if (assigned_reg < pd_first_callee_saved_reg) ++ return true; ++ if (assigned_reg > pd_last_callee_saved_reg && assigned_reg < pd_first_callee_saved_fpu_reg) ++ return true; ++ if (assigned_reg > pd_last_callee_saved_fpu_reg && assigned_reg < pd_last_fpu_reg) ++ return true; ++ return false; ++} ++ ++inline void LinearScan::pd_add_temps(LIR_Op* op) {} ++ ++// Implementation of LinearScanWalker ++inline bool LinearScanWalker::pd_init_regs_for_alloc(Interval* cur) { ++ if (allocator()->gen()->is_vreg_flag_set(cur->reg_num(), LIRGenerator::callee_saved)) { ++ assert(cur->type() != T_FLOAT && cur->type() != T_DOUBLE, "cpu regs only"); ++ _first_reg = pd_first_callee_saved_reg; ++ _last_reg = pd_last_callee_saved_reg; ++ return true; ++ } else if (cur->type() == T_INT || cur->type() == T_LONG || cur->type() == T_OBJECT || ++ cur->type() == T_ADDRESS || cur->type() == T_METADATA) { ++ _first_reg = pd_first_cpu_reg; ++ _last_reg = pd_last_allocatable_cpu_reg; ++ return true; ++ } ++ return false; ++} ++ ++#endif // CPU_LOONGARCH_C1_LINEARSCAN_LOONGARCH_HPP +diff --git a/src/hotspot/cpu/loongarch/c1_LinearScan_loongarch_64.cpp b/src/hotspot/cpu/loongarch/c1_LinearScan_loongarch_64.cpp +new file mode 100644 +index 000000000..219b2e367 +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/c1_LinearScan_loongarch_64.cpp +@@ -0,0 +1,33 @@ ++/* ++ * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. All rights reserved. ++ * Copyright (c) 2021, Loongson Technology. 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 "c1/c1_Instruction.hpp" ++#include "c1/c1_LinearScan.hpp" ++#include "utilities/bitMap.inline.hpp" ++ ++void LinearScan::allocate_fpu_stack() { ++ // No FPU stack on LoongArch64 ++} +diff --git a/src/hotspot/cpu/loongarch/c1_MacroAssembler_loongarch.hpp b/src/hotspot/cpu/loongarch/c1_MacroAssembler_loongarch.hpp +new file mode 100644 +index 000000000..38ff4c583 +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/c1_MacroAssembler_loongarch.hpp +@@ -0,0 +1,112 @@ +/* + * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, Loongson Technology. All rights reserved. @@ -10402,6 +15995,124 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + * + */ + ++#ifndef CPU_LOONGARCH_C1_MACROASSEMBLER_LOONGARCH_HPP ++#define CPU_LOONGARCH_C1_MACROASSEMBLER_LOONGARCH_HPP ++ ++using MacroAssembler::build_frame; ++using MacroAssembler::null_check; ++ ++// C1_MacroAssembler contains high-level macros for C1 ++ ++ private: ++ int _rsp_offset; // track rsp changes ++ // initialization ++ void pd_init() { _rsp_offset = 0; } ++ ++ public: ++ void try_allocate( ++ Register obj, // result: pointer to object after successful allocation ++ Register var_size_in_bytes, // object size in bytes if unknown at compile time; invalid otherwise ++ int con_size_in_bytes, // object size in bytes if known at compile time ++ Register t1, // temp register ++ Register t2, // temp register ++ Label& slow_case // continuation point if fast allocation fails ++ ); ++ ++ void initialize_header(Register obj, Register klass, Register len, Register t1, Register t2); ++ void initialize_body(Register obj, Register len_in_bytes, int hdr_size_in_bytes, Register t1, Register t2); ++ ++ // locking ++ // hdr : must be A0, contents destroyed ++ // obj : must point to the object to lock, contents preserved ++ // disp_hdr: must point to the displaced header location, contents preserved ++ // scratch : scratch register, contents destroyed ++ // returns code offset at which to add null check debug information ++ int lock_object (Register swap, Register obj, Register disp_hdr, Register scratch, Label& slow_case); ++ ++ // unlocking ++ // hdr : contents destroyed ++ // obj : must point to the object to lock, contents preserved ++ // disp_hdr: must be A0 & must point to the displaced header location, contents destroyed ++ void unlock_object(Register swap, Register obj, Register lock, Label& slow_case); ++ ++ void initialize_object( ++ Register obj, // result: pointer to object after successful allocation ++ Register klass, // object klass ++ Register var_size_in_bytes, // object size in bytes if unknown at compile time; invalid otherwise ++ int con_size_in_bytes, // object size in bytes if known at compile time ++ Register t1, // temp register ++ Register t2, // temp register ++ bool is_tlab_allocated // the object was allocated in a TLAB; relevant for the implementation of ZeroTLAB ++ ); ++ ++ // allocation of fixed-size objects ++ // (can also be used to allocate fixed-size arrays, by setting ++ // hdr_size correctly and storing the array length afterwards) ++ // obj : will contain pointer to allocated object ++ // t1, t2 : scratch registers - contents destroyed ++ // header_size: size of object header in words ++ // object_size: total size of object in words ++ // slow_case : exit to slow case implementation if fast allocation fails ++ void allocate_object(Register obj, Register t1, Register t2, int header_size, ++ int object_size, Register klass, Label& slow_case); ++ ++ enum { ++ max_array_allocation_length = 0x00FFFFFF ++ }; ++ ++ // allocation of arrays ++ // obj : will contain pointer to allocated object ++ // len : array length in number of elements ++ // t : scratch register - contents destroyed ++ // header_size: size of object header in words ++ // f : element scale factor ++ // slow_case : exit to slow case implementation if fast allocation fails ++ void allocate_array(Register obj, Register len, Register t, Register t2, int header_size, ++ int f, Register klass, Label& slow_case); ++ ++ int rsp_offset() const { return _rsp_offset; } ++ void set_rsp_offset(int n) { _rsp_offset = n; } ++ ++ void invalidate_registers(bool inv_a0, bool inv_s0, bool inv_a2, bool inv_a3, ++ bool inv_a4, bool inv_a5) PRODUCT_RETURN; ++ ++ // This platform only uses signal-based null checks. The Label is not needed. ++ void null_check(Register r, Label *Lnull = NULL) { MacroAssembler::null_check(r); } ++ ++ void load_parameter(int offset_in_words, Register reg); ++ ++#endif // CPU_LOONGARCH_C1_MACROASSEMBLER_LOONGARCH_HPP +diff --git a/src/hotspot/cpu/loongarch/c1_MacroAssembler_loongarch_64.cpp b/src/hotspot/cpu/loongarch/c1_MacroAssembler_loongarch_64.cpp +new file mode 100644 +index 000000000..17ff93a59 +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/c1_MacroAssembler_loongarch_64.cpp +@@ -0,0 +1,344 @@ ++/* ++ * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2021, 2022, Loongson Technology. 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 "c1/c1_MacroAssembler.hpp" +#include "c1/c1_Runtime1.hpp" @@ -10411,6 +16122,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ +#include "oops/arrayOop.hpp" +#include "oops/markOop.hpp" +#include "runtime/basicLock.hpp" ++#include "runtime/biasedLocking.hpp" +#include "runtime/os.hpp" +#include "runtime/sharedRuntime.hpp" +#include "runtime/stubRoutines.hpp" @@ -10720,125 +16432,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ +#endif +} +#endif // ifndef PRODUCT -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/c1_MacroAssembler_loongarch.hpp jdk11u-ls/src/hotspot/cpu/loongarch/c1_MacroAssembler_loongarch.hpp ---- openjdk/src/hotspot/cpu/loongarch/c1_MacroAssembler_loongarch.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/c1_MacroAssembler_loongarch.hpp 2023-09-12 13:54:23.081571647 +0800 -@@ -0,0 +1,112 @@ -+/* -+ * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2021, Loongson Technology. 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 CPU_LOONGARCH_C1_MACROASSEMBLER_LOONGARCH_HPP -+#define CPU_LOONGARCH_C1_MACROASSEMBLER_LOONGARCH_HPP -+ -+using MacroAssembler::build_frame; -+using MacroAssembler::null_check; -+ -+// C1_MacroAssembler contains high-level macros for C1 -+ -+ private: -+ int _rsp_offset; // track rsp changes -+ // initialization -+ void pd_init() { _rsp_offset = 0; } -+ -+ public: -+ void try_allocate( -+ Register obj, // result: pointer to object after successful allocation -+ Register var_size_in_bytes, // object size in bytes if unknown at compile time; invalid otherwise -+ int con_size_in_bytes, // object size in bytes if known at compile time -+ Register t1, // temp register -+ Register t2, // temp register -+ Label& slow_case // continuation point if fast allocation fails -+ ); -+ -+ void initialize_header(Register obj, Register klass, Register len, Register t1, Register t2); -+ void initialize_body(Register obj, Register len_in_bytes, int hdr_size_in_bytes, Register t1, Register t2); -+ -+ // locking -+ // hdr : must be A0, contents destroyed -+ // obj : must point to the object to lock, contents preserved -+ // disp_hdr: must point to the displaced header location, contents preserved -+ // scratch : scratch register, contents destroyed -+ // returns code offset at which to add null check debug information -+ int lock_object (Register swap, Register obj, Register disp_hdr, Register scratch, Label& slow_case); -+ -+ // unlocking -+ // hdr : contents destroyed -+ // obj : must point to the object to lock, contents preserved -+ // disp_hdr: must be A0 & must point to the displaced header location, contents destroyed -+ void unlock_object(Register swap, Register obj, Register lock, Label& slow_case); -+ -+ void initialize_object( -+ Register obj, // result: pointer to object after successful allocation -+ Register klass, // object klass -+ Register var_size_in_bytes, // object size in bytes if unknown at compile time; invalid otherwise -+ int con_size_in_bytes, // object size in bytes if known at compile time -+ Register t1, // temp register -+ Register t2, // temp register -+ bool is_tlab_allocated // the object was allocated in a TLAB; relevant for the implementation of ZeroTLAB -+ ); -+ -+ // allocation of fixed-size objects -+ // (can also be used to allocate fixed-size arrays, by setting -+ // hdr_size correctly and storing the array length afterwards) -+ // obj : will contain pointer to allocated object -+ // t1, t2 : scratch registers - contents destroyed -+ // header_size: size of object header in words -+ // object_size: total size of object in words -+ // slow_case : exit to slow case implementation if fast allocation fails -+ void allocate_object(Register obj, Register t1, Register t2, int header_size, -+ int object_size, Register klass, Label& slow_case); -+ -+ enum { -+ max_array_allocation_length = 0x00FFFFFF -+ }; -+ -+ // allocation of arrays -+ // obj : will contain pointer to allocated object -+ // len : array length in number of elements -+ // t : scratch register - contents destroyed -+ // header_size: size of object header in words -+ // f : element scale factor -+ // slow_case : exit to slow case implementation if fast allocation fails -+ void allocate_array(Register obj, Register len, Register t, Register t2, int header_size, -+ int f, Register klass, Label& slow_case); -+ -+ int rsp_offset() const { return _rsp_offset; } -+ void set_rsp_offset(int n) { _rsp_offset = n; } -+ -+ void invalidate_registers(bool inv_a0, bool inv_s0, bool inv_a2, bool inv_a3, -+ bool inv_a4, bool inv_a5) PRODUCT_RETURN; -+ -+ // This platform only uses signal-based null checks. The Label is not needed. -+ void null_check(Register r, Label *Lnull = NULL) { MacroAssembler::null_check(r); } -+ -+ void load_parameter(int offset_in_words, Register reg); -+ -+#endif // CPU_LOONGARCH_C1_MACROASSEMBLER_LOONGARCH_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/c1_Runtime1_loongarch_64.cpp jdk11u-ls/src/hotspot/cpu/loongarch/c1_Runtime1_loongarch_64.cpp ---- openjdk/src/hotspot/cpu/loongarch/c1_Runtime1_loongarch_64.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/c1_Runtime1_loongarch_64.cpp 2023-09-12 13:54:23.085571652 +0800 +diff --git a/src/hotspot/cpu/loongarch/c1_Runtime1_loongarch_64.cpp b/src/hotspot/cpu/loongarch/c1_Runtime1_loongarch_64.cpp +new file mode 100644 +index 000000000..aaa708f71 +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/c1_Runtime1_loongarch_64.cpp @@ -0,0 +1,1138 @@ +/* + * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. @@ -11978,9 +17576,88 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + Unimplemented(); + return 0; +} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/c2_globals_loongarch.hpp jdk11u-ls/src/hotspot/cpu/loongarch/c2_globals_loongarch.hpp ---- openjdk/src/hotspot/cpu/loongarch/c2_globals_loongarch.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/c2_globals_loongarch.hpp 2023-09-12 13:54:23.085571652 +0800 +diff --git a/src/hotspot/cpu/loongarch/c1_globals_loongarch.hpp b/src/hotspot/cpu/loongarch/c1_globals_loongarch.hpp +new file mode 100644 +index 000000000..164016e12 +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/c1_globals_loongarch.hpp +@@ -0,0 +1,71 @@ ++/* ++ * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2021, 2022, Loongson Technology. 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 CPU_LOONGARCH_C1_GLOBALS_LOONGARCH_HPP ++#define CPU_LOONGARCH_C1_GLOBALS_LOONGARCH_HPP ++ ++#include "utilities/globalDefinitions.hpp" ++#include "utilities/macros.hpp" ++ ++// Sets the default values for platform dependent flags used by the client compiler. ++// (see c1_globals.hpp) ++ ++#ifndef COMPILER2 ++define_pd_global(bool, BackgroundCompilation, true ); ++define_pd_global(bool, UseTLAB, true ); ++define_pd_global(bool, ResizeTLAB, true ); ++define_pd_global(bool, InlineIntrinsics, true ); ++define_pd_global(bool, PreferInterpreterNativeStubs, false); ++define_pd_global(bool, ProfileTraps, false); ++define_pd_global(bool, UseOnStackReplacement, true ); ++define_pd_global(bool, TieredCompilation, false); ++define_pd_global(intx, CompileThreshold, 1500 ); ++ ++define_pd_global(intx, OnStackReplacePercentage, 933 ); ++define_pd_global(intx, FreqInlineSize, 325 ); ++define_pd_global(intx, NewSizeThreadIncrease, 4*K ); ++define_pd_global(intx, InitialCodeCacheSize, 160*K); ++define_pd_global(intx, ReservedCodeCacheSize, 32*M ); ++define_pd_global(intx, NonProfiledCodeHeapSize, 13*M ); ++define_pd_global(intx, ProfiledCodeHeapSize, 14*M ); ++define_pd_global(intx, NonNMethodCodeHeapSize, 5*M ); ++define_pd_global(bool, ProfileInterpreter, false); ++define_pd_global(intx, CodeCacheExpansionSize, 32*K ); ++define_pd_global(uintx, CodeCacheMinBlockLength, 1); ++define_pd_global(uintx, CodeCacheMinimumUseSpace, 400*K); ++define_pd_global(uintx, MetaspaceSize, 12*M ); ++define_pd_global(bool, NeverActAsServerClassMachine, true ); ++define_pd_global(uint64_t,MaxRAM, 1ULL*G); ++define_pd_global(bool, CICompileOSR, true ); ++#endif // !COMPILER2 ++define_pd_global(bool, UseTypeProfile, false); ++define_pd_global(bool, RoundFPResults, true ); ++ ++define_pd_global(bool, LIRFillDelaySlots, false); ++define_pd_global(bool, OptimizeSinglePrecision, true ); ++define_pd_global(bool, CSEArrayLength, false); ++define_pd_global(bool, TwoOperandLIRForm, false ); ++ ++#endif // CPU_LOONGARCH_C1_GLOBALS_LOONGARCH_HPP +diff --git a/src/hotspot/cpu/loongarch/c2_globals_loongarch.hpp b/src/hotspot/cpu/loongarch/c2_globals_loongarch.hpp +new file mode 100644 +index 000000000..27a4ec522 +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/c2_globals_loongarch.hpp @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. @@ -12076,9 +17753,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ +define_pd_global(bool, NeverActAsServerClassMachine, false); + +#endif // CPU_LOONGARCH_C2_GLOBALS_LOONGARCH_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/c2_init_loongarch.cpp jdk11u-ls/src/hotspot/cpu/loongarch/c2_init_loongarch.cpp ---- openjdk/src/hotspot/cpu/loongarch/c2_init_loongarch.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/c2_init_loongarch.cpp 2023-09-12 13:54:23.085571652 +0800 +diff --git a/src/hotspot/cpu/loongarch/c2_init_loongarch.cpp b/src/hotspot/cpu/loongarch/c2_init_loongarch.cpp +new file mode 100644 +index 000000000..ec78b942d +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/c2_init_loongarch.cpp @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. @@ -12117,9 +17796,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + guarantee(CodeEntryAlignment >= InteriorEntryAlignment, "" ); + reg_mask_init(); +} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/codeBuffer_loongarch.hpp jdk11u-ls/src/hotspot/cpu/loongarch/codeBuffer_loongarch.hpp ---- openjdk/src/hotspot/cpu/loongarch/codeBuffer_loongarch.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/codeBuffer_loongarch.hpp 2023-09-12 13:54:23.085571652 +0800 +diff --git a/src/hotspot/cpu/loongarch/codeBuffer_loongarch.hpp b/src/hotspot/cpu/loongarch/codeBuffer_loongarch.hpp +new file mode 100644 +index 000000000..653d95806 +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/codeBuffer_loongarch.hpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. @@ -12156,13 +17837,15 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + void flush_bundle(bool start_new_bundle) {} + +#endif // CPU_LOONGARCH_CODEBUFFER_LOONGARCH_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/compiledIC_loongarch.cpp jdk11u-ls/src/hotspot/cpu/loongarch/compiledIC_loongarch.cpp ---- openjdk/src/hotspot/cpu/loongarch/compiledIC_loongarch.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/compiledIC_loongarch.cpp 2023-11-01 09:34:25.477945249 +0800 +diff --git a/src/hotspot/cpu/loongarch/compiledIC_loongarch.cpp b/src/hotspot/cpu/loongarch/compiledIC_loongarch.cpp +new file mode 100644 +index 000000000..d063d5d93 +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/compiledIC_loongarch.cpp @@ -0,0 +1,148 @@ +/* + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2021, Loongson Technology. All rights reserved. ++ * Copyright (c) 2015, 2022, Loongson Technology. 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 @@ -12209,7 +17892,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + // That's why we must use the macroassembler to generate a stub. + MacroAssembler _masm(&cbuf); + -+ address base = __ start_a_stub(Compile::MAX_stubs_size); ++ address base = __ start_a_stub(CompiledStaticCall::to_interp_stub_size()); + if (base == NULL) return NULL; // CodeBuffer::expand failed + // static stub relocation stores the instruction address of the call + @@ -12308,9 +17991,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ +} + +#endif // !PRODUCT -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/copy_loongarch.hpp jdk11u-ls/src/hotspot/cpu/loongarch/copy_loongarch.hpp ---- openjdk/src/hotspot/cpu/loongarch/copy_loongarch.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/copy_loongarch.hpp 2023-09-12 13:54:23.085571652 +0800 +diff --git a/src/hotspot/cpu/loongarch/copy_loongarch.hpp b/src/hotspot/cpu/loongarch/copy_loongarch.hpp +new file mode 100644 +index 000000000..54b847a73 +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/copy_loongarch.hpp @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. @@ -12389,9 +18074,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ +} + +#endif //CPU_LOONGARCH_COPY_LOONGARCH_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/depChecker_loongarch.cpp jdk11u-ls/src/hotspot/cpu/loongarch/depChecker_loongarch.cpp ---- openjdk/src/hotspot/cpu/loongarch/depChecker_loongarch.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/depChecker_loongarch.cpp 2023-09-12 13:54:23.085571652 +0800 +diff --git a/src/hotspot/cpu/loongarch/depChecker_loongarch.cpp b/src/hotspot/cpu/loongarch/depChecker_loongarch.cpp +new file mode 100644 +index 000000000..e4a92d103 +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/depChecker_loongarch.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. @@ -12423,9 +18110,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ +#include "depChecker_loongarch.hpp" + +// Nothing to do on LoongArch -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/depChecker_loongarch.hpp jdk11u-ls/src/hotspot/cpu/loongarch/depChecker_loongarch.hpp ---- openjdk/src/hotspot/cpu/loongarch/depChecker_loongarch.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/depChecker_loongarch.hpp 2023-09-12 13:54:23.085571652 +0800 +diff --git a/src/hotspot/cpu/loongarch/depChecker_loongarch.hpp b/src/hotspot/cpu/loongarch/depChecker_loongarch.hpp +new file mode 100644 +index 000000000..29c292a74 +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/depChecker_loongarch.hpp @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. @@ -12458,9 +18147,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ +// Nothing to do on LoongArch + +#endif // CPU_LOONGARCH_DEPCHECKER_LOONGARCH_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/disassembler_loongarch.hpp jdk11u-ls/src/hotspot/cpu/loongarch/disassembler_loongarch.hpp ---- openjdk/src/hotspot/cpu/loongarch/disassembler_loongarch.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/disassembler_loongarch.hpp 2023-09-12 13:54:23.085571652 +0800 +diff --git a/src/hotspot/cpu/loongarch/disassembler_loongarch.hpp b/src/hotspot/cpu/loongarch/disassembler_loongarch.hpp +new file mode 100644 +index 000000000..04359bc17 +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/disassembler_loongarch.hpp @@ -0,0 +1,37 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. @@ -12499,9 +18190,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + } + +#endif // CPU_LOONGARCH_DISASSEMBLER_LOONGARCH_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/frame_loongarch.cpp jdk11u-ls/src/hotspot/cpu/loongarch/frame_loongarch.cpp ---- openjdk/src/hotspot/cpu/loongarch/frame_loongarch.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/frame_loongarch.cpp 2023-11-01 09:34:25.481945254 +0800 +diff --git a/src/hotspot/cpu/loongarch/frame_loongarch.cpp b/src/hotspot/cpu/loongarch/frame_loongarch.cpp +new file mode 100644 +index 000000000..6f6d34e02 +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/frame_loongarch.cpp @@ -0,0 +1,690 @@ +/* + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. @@ -13048,7 +18741,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + + // first the method + -+ Method* m = *interpreter_frame_method_addr(); ++ Method* m = safe_interpreter_frame_method(); + + // validate the method we'd find in this potential sender + if (!Method::is_valid_method(m)) return false; @@ -13193,9 +18886,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + +void frame::pd_ps() {} +#endif -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/frame_loongarch.hpp jdk11u-ls/src/hotspot/cpu/loongarch/frame_loongarch.hpp ---- openjdk/src/hotspot/cpu/loongarch/frame_loongarch.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/frame_loongarch.hpp 2023-09-12 13:54:23.085571652 +0800 +diff --git a/src/hotspot/cpu/loongarch/frame_loongarch.hpp b/src/hotspot/cpu/loongarch/frame_loongarch.hpp +new file mode 100644 +index 000000000..b16389b3a +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/frame_loongarch.hpp @@ -0,0 +1,171 @@ +/* + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. @@ -13368,13 +19063,15 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + static jint interpreter_frame_expression_stack_direction() { return -1; } + +#endif // CPU_LOONGARCH_FRAME_LOONGARCH_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/frame_loongarch.inline.hpp jdk11u-ls/src/hotspot/cpu/loongarch/frame_loongarch.inline.hpp ---- openjdk/src/hotspot/cpu/loongarch/frame_loongarch.inline.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/frame_loongarch.inline.hpp 2023-11-01 09:34:25.481945254 +0800 -@@ -0,0 +1,246 @@ +diff --git a/src/hotspot/cpu/loongarch/frame_loongarch.inline.hpp b/src/hotspot/cpu/loongarch/frame_loongarch.inline.hpp +new file mode 100644 +index 000000000..1ddc038ee +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/frame_loongarch.inline.hpp +@@ -0,0 +1,252 @@ +/* + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2021, Loongson Technology. All rights reserved. ++ * Copyright (c) 2015, 2022, Loongson Technology. 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 @@ -13517,6 +19214,12 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + return (intptr_t*) *(intptr_t **)addr_at(native_frame_link_offset); +} + ++inline intptr_t* frame::link_or_null() const { ++ intptr_t** ptr = is_java_frame() ? (intptr_t **)addr_at(java_frame_link_offset) ++ : (intptr_t **)addr_at(native_frame_link_offset); ++ return os::is_readable_pointer(ptr) ? *ptr : NULL; ++} ++ +inline intptr_t* frame::unextended_sp() const { return _unextended_sp; } + +// Return address: @@ -13618,10 +19321,12 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ +} + +#endif // CPU_LOONGARCH_FRAME_LOONGARCH_INLINE_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/gc/g1/g1BarrierSetAssembler_loongarch.cpp jdk11u-ls/src/hotspot/cpu/loongarch/gc/g1/g1BarrierSetAssembler_loongarch.cpp ---- openjdk/src/hotspot/cpu/loongarch/gc/g1/g1BarrierSetAssembler_loongarch.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/gc/g1/g1BarrierSetAssembler_loongarch.cpp 2023-11-01 09:34:25.481945254 +0800 -@@ -0,0 +1,520 @@ +diff --git a/src/hotspot/cpu/loongarch/gc/g1/g1BarrierSetAssembler_loongarch.cpp b/src/hotspot/cpu/loongarch/gc/g1/g1BarrierSetAssembler_loongarch.cpp +new file mode 100644 +index 000000000..e1e4748c4 +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/gc/g1/g1BarrierSetAssembler_loongarch.cpp +@@ -0,0 +1,523 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, Loongson Technology. All rights reserved. @@ -13667,7 +19372,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ +#define __ masm-> + +void G1BarrierSetAssembler::gen_write_ref_array_pre_barrier(MacroAssembler* masm, DecoratorSet decorators, -+ Register addr, Register count) { ++ Register addr, Register count, RegSet saved_regs) { + bool dest_uninitialized = (decorators & IS_DEST_UNINITIALIZED) != 0; + + if (!dest_uninitialized) { @@ -13690,7 +19395,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + + __ beqz(AT, filtered); + -+ __ pushad(); // push registers ++ __ push(saved_regs); + if (count == A0) { + if (addr == A1) { + __ move(AT, A0); @@ -13709,15 +19414,15 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + } else { + __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_array_pre_oop_entry), 2); + } -+ __ popad(); ++ __ pop(saved_regs); + + __ bind(filtered); + } +} + +void G1BarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators, -+ Register addr, Register count, Register tmp) { -+ __ pushad(); // push registers (overkill) ++ Register addr, Register count, Register tmp, RegSet saved_regs) { ++ __ push(saved_regs); + if (count == A0) { + assert_different_registers(A1, addr); + __ move(A1, count); @@ -13728,7 +19433,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + __ move(A1, count); + } + __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_array_post_entry), 2); -+ __ popad(); ++ __ pop(saved_regs); +} + +void G1BarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, @@ -13743,6 +19448,8 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ +#ifndef OPT_THREAD + __ get_thread(thread); +#endif ++ // RA is live. It must be saved around calls. ++ __ enter(); // barrier may call runtime + // Generate the G1 pre-barrier code to log the value of + // the referent field in an SATB buffer. + g1_write_barrier_pre(masm /* masm */, @@ -13752,6 +19459,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + tmp1 /* tmp */, + true /* tosca_live */, + true /* expand_call */); ++ __ leave(); + } +} + @@ -14142,13 +19850,15 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ +#undef __ + +#endif // COMPILER1 -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/gc/g1/g1BarrierSetAssembler_loongarch.hpp jdk11u-ls/src/hotspot/cpu/loongarch/gc/g1/g1BarrierSetAssembler_loongarch.hpp ---- openjdk/src/hotspot/cpu/loongarch/gc/g1/g1BarrierSetAssembler_loongarch.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/gc/g1/g1BarrierSetAssembler_loongarch.hpp 2023-11-01 09:34:25.481945254 +0800 +diff --git a/src/hotspot/cpu/loongarch/gc/g1/g1BarrierSetAssembler_loongarch.hpp b/src/hotspot/cpu/loongarch/gc/g1/g1BarrierSetAssembler_loongarch.hpp +new file mode 100644 +index 000000000..745046ac0 +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/gc/g1/g1BarrierSetAssembler_loongarch.hpp @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2021, Loongson Technology. All rights reserved. ++ * Copyright (c) 2022, Loongson Technology. 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 @@ -14184,8 +19894,8 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + +class G1BarrierSetAssembler: public ModRefBarrierSetAssembler { + protected: -+ virtual void gen_write_ref_array_pre_barrier(MacroAssembler* masm, DecoratorSet decorators, Register addr, Register count); -+ virtual void gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators, Register addr, Register count, Register tmp); ++ virtual void gen_write_ref_array_pre_barrier(MacroAssembler* masm, DecoratorSet decorators, Register addr, Register count, RegSet saved_regs); ++ virtual void gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators, Register addr, Register count, Register tmp, RegSet saved_regs); + + void g1_write_barrier_pre(MacroAssembler* masm, + Register obj, @@ -14217,10 +19927,12 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ +}; + +#endif // CPU_LOONGARCH_GC_G1_G1BARRIERSETASSEMBLER_LOONGARCH_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/gc/shared/barrierSetAssembler_loongarch.cpp jdk11u-ls/src/hotspot/cpu/loongarch/gc/shared/barrierSetAssembler_loongarch.cpp ---- openjdk/src/hotspot/cpu/loongarch/gc/shared/barrierSetAssembler_loongarch.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/gc/shared/barrierSetAssembler_loongarch.cpp 2023-11-01 09:34:25.481945254 +0800 -@@ -0,0 +1,253 @@ +diff --git a/src/hotspot/cpu/loongarch/gc/shared/barrierSetAssembler_loongarch.cpp b/src/hotspot/cpu/loongarch/gc/shared/barrierSetAssembler_loongarch.cpp +new file mode 100644 +index 000000000..a890cd3f6 +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/gc/shared/barrierSetAssembler_loongarch.cpp +@@ -0,0 +1,255 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2022, Loongson Technology. All rights reserved. @@ -14257,6 +19969,8 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + +void BarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, + Register dst, Address src, Register tmp1, Register tmp_thread) { ++ // RA is live. It must be saved around calls. ++ + bool in_heap = (decorators & IN_HEAP) != 0; + bool in_native = (decorators & IN_NATIVE) != 0; + bool is_not_null = (decorators & IS_NOT_NULL) != 0; @@ -14474,13 +20188,15 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + __ addi_d(t1, t1, con_size_in_bytes); + __ st_ptr(t1, Address(TREG, in_bytes(JavaThread::allocated_bytes_offset()))); +} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/gc/shared/barrierSetAssembler_loongarch.hpp jdk11u-ls/src/hotspot/cpu/loongarch/gc/shared/barrierSetAssembler_loongarch.hpp ---- openjdk/src/hotspot/cpu/loongarch/gc/shared/barrierSetAssembler_loongarch.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/gc/shared/barrierSetAssembler_loongarch.hpp 2023-11-01 09:34:25.481945254 +0800 +diff --git a/src/hotspot/cpu/loongarch/gc/shared/barrierSetAssembler_loongarch.hpp b/src/hotspot/cpu/loongarch/gc/shared/barrierSetAssembler_loongarch.hpp +new file mode 100644 +index 000000000..a7ebbfaab +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/gc/shared/barrierSetAssembler_loongarch.hpp @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2018, 2021, Loongson Technology. All rights reserved. ++ * Copyright (c) 2018, 2022, Loongson Technology. 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 @@ -14522,9 +20238,9 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + +public: + virtual void arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop, -+ Register dst, Register count, Register scratch = NOREG) {} ++ Register dst, Register count, RegSet saved_regs) {} + virtual void arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop, -+ Register dst, Register count, Register scratch = NOREG) {} ++ Register dst, Register count, Register scratch, RegSet saved_regs) {} + + virtual void load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, + Register dst, Address src, Register tmp1, Register tmp_thread); @@ -14566,13 +20282,15 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ +}; + +#endif // CPU_LOONGARCH_GC_SHARED_BARRIERSETASSEMBLER_LOONGARCH_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/gc/shared/cardTableBarrierSetAssembler_loongarch.cpp jdk11u-ls/src/hotspot/cpu/loongarch/gc/shared/cardTableBarrierSetAssembler_loongarch.cpp ---- openjdk/src/hotspot/cpu/loongarch/gc/shared/cardTableBarrierSetAssembler_loongarch.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/gc/shared/cardTableBarrierSetAssembler_loongarch.cpp 2023-11-01 09:34:25.481945254 +0800 -@@ -0,0 +1,141 @@ +diff --git a/src/hotspot/cpu/loongarch/gc/shared/cardTableBarrierSetAssembler_loongarch.cpp b/src/hotspot/cpu/loongarch/gc/shared/cardTableBarrierSetAssembler_loongarch.cpp +new file mode 100644 +index 000000000..d09e9a75a +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/gc/shared/cardTableBarrierSetAssembler_loongarch.cpp +@@ -0,0 +1,140 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2018, Loongson Technology. All rights reserved. ++ * Copyright (c) 2018, 2023, Loongson Technology. 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 @@ -14617,7 +20335,8 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ +#define TIMES_OOP (UseCompressedOops ? Address::times_4 : Address::times_8) + +void CardTableBarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators, -+ Register addr, Register count, Register tmp) { ++ Register addr, Register count, Register tmp, ++ RegSet saved_regs) { + BarrierSet *bs = BarrierSet::barrier_set(); + CardTableBarrierSet* ctbs = barrier_set_cast(bs); + CardTable* ct = ctbs->card_table(); @@ -14630,7 +20349,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + + __ beq(count, R0, L_done); // zero count - nothing to do + -+ if (UseConcMarkSweepGC) __ membar(__ StoreStore); ++ if (ct->scanned_concurrently()) __ membar(__ StoreStore); + + __ li(tmp, disp); + @@ -14673,8 +20392,6 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + + jbyte dirty = CardTable::dirty_card_val(); + if (UseCondCardMark) { -+ Untested("Untested"); -+ __ warn("store_check Untested"); + Label L_already_dirty; + __ membar(__ StoreLoad); + __ ld_b(AT, tmp, 0); @@ -14684,7 +20401,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + __ bind(L_already_dirty); + } else { + if (ct->scanned_concurrently()) { -+ __ membar(Assembler::StoreLoad); ++ __ membar(Assembler::StoreStore); + } + __ st_b(R0, tmp, 0); + } @@ -14711,13 +20428,15 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + } + } +} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/gc/shared/cardTableBarrierSetAssembler_loongarch.hpp jdk11u-ls/src/hotspot/cpu/loongarch/gc/shared/cardTableBarrierSetAssembler_loongarch.hpp ---- openjdk/src/hotspot/cpu/loongarch/gc/shared/cardTableBarrierSetAssembler_loongarch.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/gc/shared/cardTableBarrierSetAssembler_loongarch.hpp 2023-11-01 09:34:25.481945254 +0800 -@@ -0,0 +1,42 @@ +diff --git a/src/hotspot/cpu/loongarch/gc/shared/cardTableBarrierSetAssembler_loongarch.hpp b/src/hotspot/cpu/loongarch/gc/shared/cardTableBarrierSetAssembler_loongarch.hpp +new file mode 100644 +index 000000000..b37c2ba0b +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/gc/shared/cardTableBarrierSetAssembler_loongarch.hpp +@@ -0,0 +1,44 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2018, 2021, Loongson Technology. All rights reserved. ++ * Copyright (c) 2018, 2022, Loongson Technology. 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 @@ -14750,20 +20469,24 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ +protected: + void store_check(MacroAssembler* masm, Register obj, Address dst); + -+ virtual void gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators, Register addr, Register count, Register tmp); ++ virtual void gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators, ++ Register addr, Register count, Register tmp, ++ RegSet saved_regs); + + virtual void oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, + Address dst, Register val, Register tmp1, Register tmp2); +}; + +#endif // CPU_LOONGARCH_GC_SHARED_CARDTABLEBARRIERSETASSEMBLER_LOONGARCH_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/gc/shared/modRefBarrierSetAssembler_loongarch.cpp jdk11u-ls/src/hotspot/cpu/loongarch/gc/shared/modRefBarrierSetAssembler_loongarch.cpp ---- openjdk/src/hotspot/cpu/loongarch/gc/shared/modRefBarrierSetAssembler_loongarch.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/gc/shared/modRefBarrierSetAssembler_loongarch.cpp 2023-11-01 09:34:25.481945254 +0800 +diff --git a/src/hotspot/cpu/loongarch/gc/shared/modRefBarrierSetAssembler_loongarch.cpp b/src/hotspot/cpu/loongarch/gc/shared/modRefBarrierSetAssembler_loongarch.cpp +new file mode 100644 +index 000000000..14c41ea79 +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/gc/shared/modRefBarrierSetAssembler_loongarch.cpp @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2018, 2021, Loongson Technology. All rights reserved. ++ * Copyright (c) 2018, 2022, Loongson Technology. 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 @@ -14793,16 +20516,16 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ +#define __ masm-> + +void ModRefBarrierSetAssembler::arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop, -+ Register dst, Register count, Register scratch) { ++ Register dst, Register count, RegSet saved_regs) { + if (is_oop) { -+ gen_write_ref_array_pre_barrier(masm, decorators, dst, count); ++ gen_write_ref_array_pre_barrier(masm, decorators, dst, count, saved_regs); + } +} + +void ModRefBarrierSetAssembler::arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop, -+ Register dst, Register count, Register scratch) { ++ Register dst, Register count, Register scratch, RegSet saved_regs) { + if (is_oop) { -+ gen_write_ref_array_post_barrier(masm, decorators, dst, count, scratch); ++ gen_write_ref_array_post_barrier(masm, decorators, dst, count, scratch, saved_regs); + } +} + @@ -14814,13 +20537,15 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + BarrierSetAssembler::store_at(masm, decorators, type, dst, val, tmp1, tmp2); + } +} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/gc/shared/modRefBarrierSetAssembler_loongarch.hpp jdk11u-ls/src/hotspot/cpu/loongarch/gc/shared/modRefBarrierSetAssembler_loongarch.hpp ---- openjdk/src/hotspot/cpu/loongarch/gc/shared/modRefBarrierSetAssembler_loongarch.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/gc/shared/modRefBarrierSetAssembler_loongarch.hpp 2023-11-01 09:34:25.481945254 +0800 +diff --git a/src/hotspot/cpu/loongarch/gc/shared/modRefBarrierSetAssembler_loongarch.hpp b/src/hotspot/cpu/loongarch/gc/shared/modRefBarrierSetAssembler_loongarch.hpp +new file mode 100644 +index 000000000..8043220ef +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/gc/shared/modRefBarrierSetAssembler_loongarch.hpp @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2018, 2021, Loongson Technology. All rights reserved. ++ * Copyright (c) 2018, 2022, Loongson Technology. 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 @@ -14856,25 +20581,27 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ +class ModRefBarrierSetAssembler: public BarrierSetAssembler { +protected: + virtual void gen_write_ref_array_pre_barrier(MacroAssembler* masm, DecoratorSet decorators, -+ Register addr, Register count) {} ++ Register addr, Register count, RegSet saved_regs) {} + virtual void gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators, -+ Register addr, Register count, Register tmp) {} ++ Register addr, Register count, Register tmp, RegSet saved_regs) {} + virtual void oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, + Address dst, Register val, Register tmp1, Register tmp2) = 0; +public: + virtual void arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop, -+ Register dst, Register count, Register scratch = NOREG); ++ Register dst, Register count, RegSet saved_regs); + virtual void arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop, -+ Register dst, Register count, Register scratch = NOREG); ++ Register dst, Register count, Register scratch, RegSet saved_regs); + + virtual void store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, + Address dst, Register val, Register tmp1, Register tmp2); +}; + +#endif // CPU_LOONGARCH_GC_SHARED_MODREFBARRIERSETASSEMBLER_LOONGARCH_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/globalDefinitions_loongarch.hpp jdk11u-ls/src/hotspot/cpu/loongarch/globalDefinitions_loongarch.hpp ---- openjdk/src/hotspot/cpu/loongarch/globalDefinitions_loongarch.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/globalDefinitions_loongarch.hpp 2023-09-12 13:54:23.085571652 +0800 +diff --git a/src/hotspot/cpu/loongarch/globalDefinitions_loongarch.hpp b/src/hotspot/cpu/loongarch/globalDefinitions_loongarch.hpp +new file mode 100644 +index 000000000..dc21d001c +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/globalDefinitions_loongarch.hpp @@ -0,0 +1,53 @@ +/* + * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. @@ -14929,9 +20656,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ +#define THREAD_LOCAL_POLL + +#endif // CPU_LOONGARCH_GLOBALDEFINITIONS_LOONGARCH_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/globals_loongarch.hpp jdk11u-ls/src/hotspot/cpu/loongarch/globals_loongarch.hpp ---- openjdk/src/hotspot/cpu/loongarch/globals_loongarch.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/globals_loongarch.hpp 2023-09-12 13:54:23.085571652 +0800 +diff --git a/src/hotspot/cpu/loongarch/globals_loongarch.hpp b/src/hotspot/cpu/loongarch/globals_loongarch.hpp +new file mode 100644 +index 000000000..e6b758b55 +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/globals_loongarch.hpp @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. @@ -15042,100 +20771,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + "Eliminate barriers for single active cpu") + +#endif // CPU_LOONGARCH_GLOBALS_LOONGARCH_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/icache_loongarch.cpp jdk11u-ls/src/hotspot/cpu/loongarch/icache_loongarch.cpp ---- openjdk/src/hotspot/cpu/loongarch/icache_loongarch.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/icache_loongarch.cpp 2023-09-12 13:54:23.085571652 +0800 -@@ -0,0 +1,42 @@ -+/* -+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2021, Loongson Technology. 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 "asm/macroAssembler.hpp" -+#include "runtime/icache.hpp" -+ -+void ICacheStubGenerator::generate_icache_flush(ICache::flush_icache_stub_t* flush_icache_stub) -+{ -+#define __ _masm-> -+ StubCodeMark mark(this, "ICache", "flush_icache_stub"); -+ address start = __ pc(); -+ -+ __ ibar(0); -+ __ ori(V0, A2, 0); -+ __ jr(RA); -+ -+ *flush_icache_stub = (ICache::flush_icache_stub_t)start; -+#undef __ -+} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/icache_loongarch.hpp jdk11u-ls/src/hotspot/cpu/loongarch/icache_loongarch.hpp ---- openjdk/src/hotspot/cpu/loongarch/icache_loongarch.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/icache_loongarch.hpp 2023-09-12 13:54:23.085571652 +0800 -@@ -0,0 +1,41 @@ -+/* -+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2022, Loongson Technology. 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 CPU_LOONGARCH_ICACHE_LOONGARCH_HPP -+#define CPU_LOONGARCH_ICACHE_LOONGARCH_HPP -+ -+// Interface for updating the instruction cache. Whenever the VM modifies -+// code, part of the processor instruction cache potentially has to be flushed. -+ -+class ICache : public AbstractICache { -+ public: -+ enum { -+ stub_size = 3 * BytesPerInstWord, // Size of the icache flush stub in bytes -+ line_size = 32, // flush instruction affects a dword -+ log2_line_size = 5 // log2(line_size) -+ }; -+}; -+ -+#endif // CPU_LOONGARCH_ICACHE_LOONGARCH_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/icBuffer_loongarch.cpp jdk11u-ls/src/hotspot/cpu/loongarch/icBuffer_loongarch.cpp ---- openjdk/src/hotspot/cpu/loongarch/icBuffer_loongarch.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/icBuffer_loongarch.cpp 2023-09-12 13:54:23.085571652 +0800 +diff --git a/src/hotspot/cpu/loongarch/icBuffer_loongarch.cpp b/src/hotspot/cpu/loongarch/icBuffer_loongarch.cpp +new file mode 100644 +index 000000000..7b9769482 +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/icBuffer_loongarch.cpp @@ -0,0 +1,92 @@ +/* + * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. @@ -15229,10 +20869,107 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + void* o= (void*)move->data(); + return o; +} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/interp_masm_loongarch_64.cpp jdk11u-ls/src/hotspot/cpu/loongarch/interp_masm_loongarch_64.cpp ---- openjdk/src/hotspot/cpu/loongarch/interp_masm_loongarch_64.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/interp_masm_loongarch_64.cpp 2023-11-01 09:34:25.481945254 +0800 -@@ -0,0 +1,2042 @@ +diff --git a/src/hotspot/cpu/loongarch/icache_loongarch.cpp b/src/hotspot/cpu/loongarch/icache_loongarch.cpp +new file mode 100644 +index 000000000..1ae7e5376 +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/icache_loongarch.cpp +@@ -0,0 +1,42 @@ ++/* ++ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2015, 2021, Loongson Technology. 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 "asm/macroAssembler.hpp" ++#include "runtime/icache.hpp" ++ ++void ICacheStubGenerator::generate_icache_flush(ICache::flush_icache_stub_t* flush_icache_stub) ++{ ++#define __ _masm-> ++ StubCodeMark mark(this, "ICache", "flush_icache_stub"); ++ address start = __ pc(); ++ ++ __ ibar(0); ++ __ ori(V0, A2, 0); ++ __ jr(RA); ++ ++ *flush_icache_stub = (ICache::flush_icache_stub_t)start; ++#undef __ ++} +diff --git a/src/hotspot/cpu/loongarch/icache_loongarch.hpp b/src/hotspot/cpu/loongarch/icache_loongarch.hpp +new file mode 100644 +index 000000000..3a180549f +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/icache_loongarch.hpp +@@ -0,0 +1,41 @@ ++/* ++ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2015, 2022, Loongson Technology. 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 CPU_LOONGARCH_ICACHE_LOONGARCH_HPP ++#define CPU_LOONGARCH_ICACHE_LOONGARCH_HPP ++ ++// Interface for updating the instruction cache. Whenever the VM modifies ++// code, part of the processor instruction cache potentially has to be flushed. ++ ++class ICache : public AbstractICache { ++ public: ++ enum { ++ stub_size = 3 * BytesPerInstWord, // Size of the icache flush stub in bytes ++ line_size = 32, // flush instruction affects a dword ++ log2_line_size = 5 // log2(line_size) ++ }; ++}; ++ ++#endif // CPU_LOONGARCH_ICACHE_LOONGARCH_HPP +diff --git a/src/hotspot/cpu/loongarch/interp_masm_loongarch.hpp b/src/hotspot/cpu/loongarch/interp_masm_loongarch.hpp +new file mode 100644 +index 000000000..53a06ba7f +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/interp_masm_loongarch.hpp +@@ -0,0 +1,281 @@ +/* + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2021, Loongson Technology. All rights reserved. @@ -15258,6 +20995,293 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + * + */ + ++#ifndef CPU_LOONGARCH_INTERP_MASM_LOONGARCH_64_HPP ++#define CPU_LOONGARCH_INTERP_MASM_LOONGARCH_64_HPP ++ ++#include "asm/assembler.hpp" ++#include "asm/macroAssembler.hpp" ++#include "asm/macroAssembler.inline.hpp" ++#include "interpreter/invocationCounter.hpp" ++#include "runtime/frame.hpp" ++ ++// This file specializes the assember with interpreter-specific macros ++ ++typedef ByteSize (*OffsetFunction)(uint); ++ ++class InterpreterMacroAssembler: public MacroAssembler { ++#ifndef CC_INTERP ++ private: ++ ++ Register _locals_register; // register that contains the pointer to the locals ++ Register _bcp_register; // register that contains the bcp ++ ++ protected: ++ // Interpreter specific version of call_VM_base ++ virtual void call_VM_leaf_base(address entry_point, ++ int number_of_arguments); ++ ++ virtual void call_VM_base(Register oop_result, ++ Register java_thread, ++ Register last_java_sp, ++ address entry_point, ++ int number_of_arguments, ++ bool check_exceptions); ++ ++ // base routine for all dispatches ++ void dispatch_base(TosState state, address* table, bool verifyoop = true, bool generate_poll = false); ++#endif // CC_INTERP ++ ++ public: ++ void jump_to_entry(address entry); ++ // narrow int return value ++ void narrow(Register result); ++ ++ InterpreterMacroAssembler(CodeBuffer* code) : MacroAssembler(code), _locals_register(LVP), _bcp_register(BCP) {} ++ ++ void get_2_byte_integer_at_bcp(Register reg, Register tmp, int offset); ++ void get_4_byte_integer_at_bcp(Register reg, int offset); ++ ++ virtual void check_and_handle_popframe(Register java_thread); ++ virtual void check_and_handle_earlyret(Register java_thread); ++ ++ void load_earlyret_value(TosState state); ++ ++#ifdef CC_INTERP ++ void save_bcp() { /* not needed in c++ interpreter and harmless */ } ++ void restore_bcp() { /* not needed in c++ interpreter and harmless */ } ++ ++ // Helpers for runtime call arguments/results ++ void get_method(Register reg); ++ ++#else ++ ++ // Interpreter-specific registers ++ void save_bcp() { ++ st_d(BCP, FP, frame::interpreter_frame_bcp_offset * wordSize); ++ } ++ ++ void restore_bcp() { ++ ld_d(BCP, FP, frame::interpreter_frame_bcp_offset * wordSize); ++ } ++ ++ void restore_locals() { ++ ld_d(LVP, FP, frame::interpreter_frame_locals_offset * wordSize); ++ } ++ ++ // Helpers for runtime call arguments/results ++ void get_method(Register reg) { ++ ld_d(reg, FP, frame::interpreter_frame_method_offset * wordSize); ++ } ++ ++ void get_const(Register reg){ ++ get_method(reg); ++ ld_d(reg, reg, in_bytes(Method::const_offset())); ++ } ++ ++ void get_constant_pool(Register reg) { ++ get_const(reg); ++ ld_d(reg, reg, in_bytes(ConstMethod::constants_offset())); ++ } ++ ++ void get_constant_pool_cache(Register reg) { ++ get_constant_pool(reg); ++ ld_d(reg, reg, ConstantPool::cache_offset_in_bytes()); ++ } ++ ++ void get_cpool_and_tags(Register cpool, Register tags) { ++ get_constant_pool(cpool); ++ ld_d(tags, cpool, ConstantPool::tags_offset_in_bytes()); ++ } ++ ++ void get_unsigned_2_byte_index_at_bcp(Register reg, int bcp_offset); ++ void get_cache_and_index_at_bcp(Register cache, Register index, int bcp_offset, size_t index_size = sizeof(u2)); ++ void get_cache_and_index_and_bytecode_at_bcp(Register cache, Register index, Register bytecode, int byte_no, int bcp_offset, size_t index_size = sizeof(u2)); ++ void get_cache_entry_pointer_at_bcp(Register cache, Register tmp, int bcp_offset, size_t index_size = sizeof(u2)); ++ void get_cache_index_at_bcp(Register index, int bcp_offset, size_t index_size = sizeof(u2)); ++ void get_method_counters(Register method, Register mcs, Label& skip); ++ ++ // load cpool->resolved_references(index); ++ void load_resolved_reference_at_index(Register result, Register index, Register tmp); ++ ++ // load cpool->resolved_klass_at(index) ++ void load_resolved_klass_at_index(Register cpool, // the constant pool (corrupted on return) ++ Register index, // the constant pool index (corrupted on return) ++ Register klass); // contains the Klass on return ++ ++ void pop_ptr( Register r = FSR); ++ void pop_i( Register r = FSR); ++ void pop_l( Register r = FSR); ++ void pop_f(FloatRegister r = FSF); ++ void pop_d(FloatRegister r = FSF); ++ ++ void push_ptr( Register r = FSR); ++ void push_i( Register r = FSR); ++ void push_l( Register r = FSR); ++ void push_f(FloatRegister r = FSF); ++ void push_d(FloatRegister r = FSF); ++ ++ void pop(Register r ) { ((MacroAssembler*)this)->pop(r); } ++ ++ void push(Register r ) { ((MacroAssembler*)this)->push(r); } ++ ++ void pop(TosState state); // transition vtos -> state ++ void push(TosState state); // transition state -> vtos ++ ++ void empty_expression_stack() { ++ ld_d(SP, FP, frame::interpreter_frame_monitor_block_top_offset * wordSize); ++ // NULL last_sp until next java call ++ st_d(R0, FP, frame::interpreter_frame_last_sp_offset * wordSize); ++ } ++ ++ // Super call_VM calls - correspond to MacroAssembler::call_VM(_leaf) calls ++ void load_ptr(int n, Register val); ++ void store_ptr(int n, Register val); ++ ++ // Generate a subtype check: branch to ok_is_subtype if sub_klass is ++ // a subtype of super_klass. ++ //void gen_subtype_check( Register sub_klass, Label &ok_is_subtype ); ++ void gen_subtype_check( Register Rsup_klass, Register sub_klass, Label &ok_is_subtype ); ++ ++ // Dispatching ++ void dispatch_prolog(TosState state, int step = 0); ++ void dispatch_epilog(TosState state, int step = 0); ++ void dispatch_only(TosState state, bool generate_poll = false); ++ void dispatch_only_normal(TosState state); ++ void dispatch_only_noverify(TosState state); ++ void dispatch_next(TosState state, int step = 0, bool generate_poll = false); ++ void dispatch_via (TosState state, address* table); ++ ++ // jump to an invoked target ++ void prepare_to_jump_from_interpreted(); ++ void jump_from_interpreted(Register method, Register temp); ++ ++ ++ // Returning from interpreted functions ++ // ++ // Removes the current activation (incl. unlocking of monitors) ++ // and sets up the return address. This code is also used for ++ // exception unwindwing. In that case, we do not want to throw ++ // IllegalMonitorStateExceptions, since that might get us into an ++ // infinite rethrow exception loop. ++ // Additionally this code is used for popFrame and earlyReturn. ++ // In popFrame case we want to skip throwing an exception, ++ // installing an exception, and notifying jvmdi. ++ // In earlyReturn case we only want to skip throwing an exception ++ // and installing an exception. ++ void remove_activation(TosState state, Register ret_addr, ++ bool throw_monitor_exception = true, ++ bool install_monitor_exception = true, ++ bool notify_jvmdi = true); ++#endif // CC_INTERP ++ ++ // Object locking ++ void lock_object (Register lock_reg); ++ void unlock_object(Register lock_reg); ++ ++#ifndef CC_INTERP ++ ++ // Interpreter profiling operations ++ void set_method_data_pointer_for_bcp(); ++ void test_method_data_pointer(Register mdp, Label& zero_continue); ++ void verify_method_data_pointer(); ++ ++ void set_mdp_data_at(Register mdp_in, int constant, Register value); ++ void increment_mdp_data_at(Address data, bool decrement = false); ++ void increment_mdp_data_at(Register mdp_in, int constant, ++ bool decrement = false); ++ void increment_mdp_data_at(Register mdp_in, Register reg, int constant, ++ bool decrement = false); ++ void increment_mask_and_jump(Address counter_addr, ++ int increment, int mask, ++ Register scratch, bool preloaded, ++ Condition cond, Label* where); ++ void set_mdp_flag_at(Register mdp_in, int flag_constant); ++ void test_mdp_data_at(Register mdp_in, int offset, Register value, ++ Register test_value_out, ++ Label& not_equal_continue); ++ ++ void record_klass_in_profile(Register receiver, Register mdp, ++ Register reg2, bool is_virtual_call); ++ void record_klass_in_profile_helper(Register receiver, Register mdp, ++ Register reg2, int start_row, ++ Label& done, bool is_virtual_call); ++ ++ void record_item_in_profile_helper(Register item, Register mdp, ++ Register reg2, int start_row, Label& done, int total_rows, ++ OffsetFunction item_offset_fn, OffsetFunction item_count_offset_fn, ++ int non_profiled_offset); ++ void update_mdp_by_offset(Register mdp_in, int offset_of_offset); ++ void update_mdp_by_offset(Register mdp_in, Register reg, int offset_of_disp); ++ void update_mdp_by_constant(Register mdp_in, int constant); ++ void update_mdp_for_ret(Register return_bci); ++ ++ void profile_taken_branch(Register mdp, Register bumped_count); ++ void profile_not_taken_branch(Register mdp); ++ void profile_call(Register mdp); ++ void profile_final_call(Register mdp); ++ void profile_virtual_call(Register receiver, Register mdp, ++ Register scratch2, ++ bool receiver_can_be_null = false); ++ void profile_called_method(Register method, Register mdp, Register reg2) NOT_JVMCI_RETURN; ++ void profile_ret(Register return_bci, Register mdp); ++ void profile_null_seen(Register mdp); ++ void profile_typecheck(Register mdp, Register klass, Register scratch); ++ void profile_typecheck_failed(Register mdp); ++ void profile_switch_default(Register mdp); ++ void profile_switch_case(Register index_in_scratch, Register mdp, ++ Register scratch2); ++ ++ // Debugging ++ // only if +VerifyOops && state == atos ++ void verify_oop(Register reg, TosState state = atos); ++ // only if +VerifyFPU && (state == ftos || state == dtos) ++ void verify_FPU(int stack_depth, TosState state = ftos); ++ ++ void profile_obj_type(Register obj, const Address& mdo_addr); ++ void profile_arguments_type(Register mdp, Register callee, Register tmp, bool is_virtual); ++ void profile_return_type(Register mdp, Register ret, Register tmp); ++ void profile_parameters_type(Register mdp, Register tmp1, Register tmp2); ++#endif // !CC_INTERP ++ ++ typedef enum { NotifyJVMTI, SkipNotifyJVMTI } NotifyMethodExitMode; ++ ++ // support for jvmti/dtrace ++ void notify_method_entry(); ++ void notify_method_exit(TosState state, NotifyMethodExitMode mode); ++}; ++ ++#endif // CPU_LOONGARCH_INTERP_MASM_LOONGARCH_64_HPP +diff --git a/src/hotspot/cpu/loongarch/interp_masm_loongarch_64.cpp b/src/hotspot/cpu/loongarch/interp_masm_loongarch_64.cpp +new file mode 100644 +index 000000000..c533a5765 +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/interp_masm_loongarch_64.cpp +@@ -0,0 +1,2043 @@ ++/* ++ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2015, 2022, Loongson Technology. 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 "gc/shared/barrierSet.hpp" +#include "gc/shared/barrierSetAssembler.hpp" @@ -15272,6 +21296,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ +#include "prims/jvmtiThreadState.hpp" +#include "runtime/basicLock.hpp" +#include "runtime/biasedLocking.hpp" ++#include "runtime/frame.inline.hpp" +#include "runtime/safepointMechanism.hpp" +#include "runtime/sharedRuntime.hpp" +#include "runtime/thread.inline.hpp" @@ -17275,13 +23300,15 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + unimplemented(); + } +} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/interp_masm_loongarch.hpp jdk11u-ls/src/hotspot/cpu/loongarch/interp_masm_loongarch.hpp ---- openjdk/src/hotspot/cpu/loongarch/interp_masm_loongarch.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/interp_masm_loongarch.hpp 2023-09-12 13:54:23.085571652 +0800 -@@ -0,0 +1,281 @@ +diff --git a/src/hotspot/cpu/loongarch/interpreterRT_loongarch.hpp b/src/hotspot/cpu/loongarch/interpreterRT_loongarch.hpp +new file mode 100644 +index 000000000..d53d951a1 +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/interpreterRT_loongarch.hpp +@@ -0,0 +1,62 @@ +/* -+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2021, Loongson Technology. All rights reserved. ++ * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2015, 2022, Loongson Technology. 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 @@ -17304,266 +23331,49 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + * + */ + -+#ifndef CPU_LOONGARCH_INTERP_MASM_LOONGARCH_64_HPP -+#define CPU_LOONGARCH_INTERP_MASM_LOONGARCH_64_HPP -+ -+#include "asm/assembler.hpp" -+#include "asm/macroAssembler.hpp" -+#include "asm/macroAssembler.inline.hpp" -+#include "interpreter/invocationCounter.hpp" -+#include "runtime/frame.hpp" ++#ifndef CPU_LOONGARCH_INTERPRETERRT_LOONGARCH_HPP ++#define CPU_LOONGARCH_INTERPRETERRT_LOONGARCH_HPP + -+// This file specializes the assember with interpreter-specific macros ++// This is included in the middle of class Interpreter. ++// Do not include files here. + -+typedef ByteSize (*OffsetFunction)(uint); ++// native method calls + -+class InterpreterMacroAssembler: public MacroAssembler { -+#ifndef CC_INTERP ++class SignatureHandlerGenerator: public NativeSignatureIterator { + private: ++ MacroAssembler* _masm; ++ unsigned int _num_fp_args; ++ unsigned int _num_int_args; ++ int _stack_offset; + -+ Register _locals_register; // register that contains the pointer to the locals -+ Register _bcp_register; // register that contains the bcp -+ -+ protected: -+ // Interpreter specific version of call_VM_base -+ virtual void call_VM_leaf_base(address entry_point, -+ int number_of_arguments); -+ -+ virtual void call_VM_base(Register oop_result, -+ Register java_thread, -+ Register last_java_sp, -+ address entry_point, -+ int number_of_arguments, -+ bool check_exceptions); -+ -+ // base routine for all dispatches -+ void dispatch_base(TosState state, address* table, bool verifyoop = true, bool generate_poll = false); -+#endif // CC_INTERP ++ void move(int from_offset, int to_offset); ++ void box(int from_offset, int to_offset); ++ void pass_int(); ++ void pass_long(); ++ void pass_object(); ++ void pass_float(); ++ void pass_double(); + + public: -+ void jump_to_entry(address entry); -+ // narrow int return value -+ void narrow(Register result); -+ -+ InterpreterMacroAssembler(CodeBuffer* code) : MacroAssembler(code), _locals_register(LVP), _bcp_register(BCP) {} -+ -+ void get_2_byte_integer_at_bcp(Register reg, Register tmp, int offset); -+ void get_4_byte_integer_at_bcp(Register reg, int offset); -+ -+ virtual void check_and_handle_popframe(Register java_thread); -+ virtual void check_and_handle_earlyret(Register java_thread); -+ -+ void load_earlyret_value(TosState state); -+ -+#ifdef CC_INTERP -+ void save_bcp() { /* not needed in c++ interpreter and harmless */ } -+ void restore_bcp() { /* not needed in c++ interpreter and harmless */ } -+ -+ // Helpers for runtime call arguments/results -+ void get_method(Register reg); -+ -+#else -+ -+ // Interpreter-specific registers -+ void save_bcp() { -+ st_d(BCP, FP, frame::interpreter_frame_bcp_offset * wordSize); -+ } -+ -+ void restore_bcp() { -+ ld_d(BCP, FP, frame::interpreter_frame_bcp_offset * wordSize); -+ } -+ -+ void restore_locals() { -+ ld_d(LVP, FP, frame::interpreter_frame_locals_offset * wordSize); -+ } -+ -+ // Helpers for runtime call arguments/results -+ void get_method(Register reg) { -+ ld_d(reg, FP, frame::interpreter_frame_method_offset * wordSize); -+ } -+ -+ void get_const(Register reg){ -+ get_method(reg); -+ ld_d(reg, reg, in_bytes(Method::const_offset())); -+ } -+ -+ void get_constant_pool(Register reg) { -+ get_const(reg); -+ ld_d(reg, reg, in_bytes(ConstMethod::constants_offset())); -+ } -+ -+ void get_constant_pool_cache(Register reg) { -+ get_constant_pool(reg); -+ ld_d(reg, reg, ConstantPool::cache_offset_in_bytes()); -+ } -+ -+ void get_cpool_and_tags(Register cpool, Register tags) { -+ get_constant_pool(cpool); -+ ld_d(tags, cpool, ConstantPool::tags_offset_in_bytes()); -+ } -+ -+ void get_unsigned_2_byte_index_at_bcp(Register reg, int bcp_offset); -+ void get_cache_and_index_at_bcp(Register cache, Register index, int bcp_offset, size_t index_size = sizeof(u2)); -+ void get_cache_and_index_and_bytecode_at_bcp(Register cache, Register index, Register bytecode, int byte_no, int bcp_offset, size_t index_size = sizeof(u2)); -+ void get_cache_entry_pointer_at_bcp(Register cache, Register tmp, int bcp_offset, size_t index_size = sizeof(u2)); -+ void get_cache_index_at_bcp(Register index, int bcp_offset, size_t index_size = sizeof(u2)); -+ void get_method_counters(Register method, Register mcs, Label& skip); -+ -+ // load cpool->resolved_references(index); -+ void load_resolved_reference_at_index(Register result, Register index, Register tmp); -+ -+ // load cpool->resolved_klass_at(index) -+ void load_resolved_klass_at_index(Register cpool, // the constant pool (corrupted on return) -+ Register index, // the constant pool index (corrupted on return) -+ Register klass); // contains the Klass on return -+ -+ void pop_ptr( Register r = FSR); -+ void pop_i( Register r = FSR); -+ void pop_l( Register r = FSR); -+ void pop_f(FloatRegister r = FSF); -+ void pop_d(FloatRegister r = FSF); -+ -+ void push_ptr( Register r = FSR); -+ void push_i( Register r = FSR); -+ void push_l( Register r = FSR); -+ void push_f(FloatRegister r = FSF); -+ void push_d(FloatRegister r = FSF); -+ -+ void pop(Register r ) { ((MacroAssembler*)this)->pop(r); } -+ -+ void push(Register r ) { ((MacroAssembler*)this)->push(r); } -+ -+ void pop(TosState state); // transition vtos -> state -+ void push(TosState state); // transition state -> vtos -+ -+ void empty_expression_stack() { -+ ld_d(SP, FP, frame::interpreter_frame_monitor_block_top_offset * wordSize); -+ // NULL last_sp until next java call -+ st_d(R0, FP, frame::interpreter_frame_last_sp_offset * wordSize); -+ } -+ -+ // Super call_VM calls - correspond to MacroAssembler::call_VM(_leaf) calls -+ void load_ptr(int n, Register val); -+ void store_ptr(int n, Register val); -+ -+ // Generate a subtype check: branch to ok_is_subtype if sub_klass is -+ // a subtype of super_klass. -+ //void gen_subtype_check( Register sub_klass, Label &ok_is_subtype ); -+ void gen_subtype_check( Register Rsup_klass, Register sub_klass, Label &ok_is_subtype ); -+ -+ // Dispatching -+ void dispatch_prolog(TosState state, int step = 0); -+ void dispatch_epilog(TosState state, int step = 0); -+ void dispatch_only(TosState state, bool generate_poll = false); -+ void dispatch_only_normal(TosState state); -+ void dispatch_only_noverify(TosState state); -+ void dispatch_next(TosState state, int step = 0, bool generate_poll = false); -+ void dispatch_via (TosState state, address* table); -+ -+ // jump to an invoked target -+ void prepare_to_jump_from_interpreted(); -+ void jump_from_interpreted(Register method, Register temp); -+ -+ -+ // Returning from interpreted functions -+ // -+ // Removes the current activation (incl. unlocking of monitors) -+ // and sets up the return address. This code is also used for -+ // exception unwindwing. In that case, we do not want to throw -+ // IllegalMonitorStateExceptions, since that might get us into an -+ // infinite rethrow exception loop. -+ // Additionally this code is used for popFrame and earlyReturn. -+ // In popFrame case we want to skip throwing an exception, -+ // installing an exception, and notifying jvmdi. -+ // In earlyReturn case we only want to skip throwing an exception -+ // and installing an exception. -+ void remove_activation(TosState state, Register ret_addr, -+ bool throw_monitor_exception = true, -+ bool install_monitor_exception = true, -+ bool notify_jvmdi = true); -+#endif // CC_INTERP -+ -+ // Object locking -+ void lock_object (Register lock_reg); -+ void unlock_object(Register lock_reg); -+ -+#ifndef CC_INTERP -+ -+ // Interpreter profiling operations -+ void set_method_data_pointer_for_bcp(); -+ void test_method_data_pointer(Register mdp, Label& zero_continue); -+ void verify_method_data_pointer(); -+ -+ void set_mdp_data_at(Register mdp_in, int constant, Register value); -+ void increment_mdp_data_at(Address data, bool decrement = false); -+ void increment_mdp_data_at(Register mdp_in, int constant, -+ bool decrement = false); -+ void increment_mdp_data_at(Register mdp_in, Register reg, int constant, -+ bool decrement = false); -+ void increment_mask_and_jump(Address counter_addr, -+ int increment, int mask, -+ Register scratch, bool preloaded, -+ Condition cond, Label* where); -+ void set_mdp_flag_at(Register mdp_in, int flag_constant); -+ void test_mdp_data_at(Register mdp_in, int offset, Register value, -+ Register test_value_out, -+ Label& not_equal_continue); -+ -+ void record_klass_in_profile(Register receiver, Register mdp, -+ Register reg2, bool is_virtual_call); -+ void record_klass_in_profile_helper(Register receiver, Register mdp, -+ Register reg2, int start_row, -+ Label& done, bool is_virtual_call); -+ -+ void record_item_in_profile_helper(Register item, Register mdp, -+ Register reg2, int start_row, Label& done, int total_rows, -+ OffsetFunction item_offset_fn, OffsetFunction item_count_offset_fn, -+ int non_profiled_offset); -+ void update_mdp_by_offset(Register mdp_in, int offset_of_offset); -+ void update_mdp_by_offset(Register mdp_in, Register reg, int offset_of_disp); -+ void update_mdp_by_constant(Register mdp_in, int constant); -+ void update_mdp_for_ret(Register return_bci); -+ -+ void profile_taken_branch(Register mdp, Register bumped_count); -+ void profile_not_taken_branch(Register mdp); -+ void profile_call(Register mdp); -+ void profile_final_call(Register mdp); -+ void profile_virtual_call(Register receiver, Register mdp, -+ Register scratch2, -+ bool receiver_can_be_null = false); -+ void profile_called_method(Register method, Register mdp, Register reg2) NOT_JVMCI_RETURN; -+ void profile_ret(Register return_bci, Register mdp); -+ void profile_null_seen(Register mdp); -+ void profile_typecheck(Register mdp, Register klass, Register scratch); -+ void profile_typecheck_failed(Register mdp); -+ void profile_switch_default(Register mdp); -+ void profile_switch_case(Register index_in_scratch, Register mdp, -+ Register scratch2); -+ -+ // Debugging -+ // only if +VerifyOops && state == atos -+ void verify_oop(Register reg, TosState state = atos); -+ // only if +VerifyFPU && (state == ftos || state == dtos) -+ void verify_FPU(int stack_depth, TosState state = ftos); -+ -+ void profile_obj_type(Register obj, const Address& mdo_addr); -+ void profile_arguments_type(Register mdp, Register callee, Register tmp, bool is_virtual); -+ void profile_return_type(Register mdp, Register ret, Register tmp); -+ void profile_parameters_type(Register mdp, Register tmp1, Register tmp2); -+#endif // !CC_INTERP ++ // Creation ++ SignatureHandlerGenerator(const methodHandle& method, CodeBuffer* buffer); + -+ typedef enum { NotifyJVMTI, SkipNotifyJVMTI } NotifyMethodExitMode; ++ // Code generation ++ void generate(uint64_t fingerprint); + -+ // support for jvmti/dtrace -+ void notify_method_entry(); -+ void notify_method_exit(TosState state, NotifyMethodExitMode mode); ++ // Code generation support ++ static Register from(); ++ static Register to(); ++ static Register temp(); +}; + -+#endif // CPU_LOONGARCH_INTERP_MASM_LOONGARCH_64_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/interpreterRT_loongarch_64.cpp jdk11u-ls/src/hotspot/cpu/loongarch/interpreterRT_loongarch_64.cpp ---- openjdk/src/hotspot/cpu/loongarch/interpreterRT_loongarch_64.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/interpreterRT_loongarch_64.cpp 2023-11-01 09:34:25.485945258 +0800 -@@ -0,0 +1,266 @@ ++#endif // CPU_LOONGARCH_INTERPRETERRT_LOONGARCH_HPP +diff --git a/src/hotspot/cpu/loongarch/interpreterRT_loongarch_64.cpp b/src/hotspot/cpu/loongarch/interpreterRT_loongarch_64.cpp +new file mode 100644 +index 000000000..e2f31997b +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/interpreterRT_loongarch_64.cpp +@@ -0,0 +1,273 @@ +/* + * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2018, Loongson Technology. All rights reserved. @@ -17614,6 +23424,13 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ +#define T8 RT8 + +// Implementation of SignatureHandlerGenerator ++InterpreterRuntime::SignatureHandlerGenerator::SignatureHandlerGenerator( ++ const methodHandle& method, CodeBuffer* buffer) : NativeSignatureIterator(method) { ++ _masm = new MacroAssembler(buffer); ++ _num_int_args = (method->is_static() ? 1 : 0); ++ _num_fp_args = 0; ++ _stack_offset = 0; ++} + +void InterpreterRuntime::SignatureHandlerGenerator::move(int from_offset, int to_offset) { + __ ld_d(temp(), from(), Interpreter::local_offset_in_bytes(from_offset)); @@ -17830,79 +23647,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + // return result handler + return Interpreter::result_handler(m->result_type()); +IRT_END -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/interpreterRT_loongarch.hpp jdk11u-ls/src/hotspot/cpu/loongarch/interpreterRT_loongarch.hpp ---- openjdk/src/hotspot/cpu/loongarch/interpreterRT_loongarch.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/interpreterRT_loongarch.hpp 2023-11-01 09:34:25.485945258 +0800 -@@ -0,0 +1,66 @@ -+/* -+ * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2022, Loongson Technology. 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 CPU_LOONGARCH_INTERPRETERRT_LOONGARCH_HPP -+#define CPU_LOONGARCH_INTERPRETERRT_LOONGARCH_HPP -+ -+#include "memory/allocation.hpp" -+ -+// native method calls -+ -+class SignatureHandlerGenerator: public NativeSignatureIterator { -+ private: -+ MacroAssembler* _masm; -+ unsigned int _num_fp_args; -+ unsigned int _num_int_args; -+ int _stack_offset; -+ -+ void move(int from_offset, int to_offset); -+ void box(int from_offset, int to_offset); -+ void pass_int(); -+ void pass_long(); -+ void pass_object(); -+ void pass_float(); -+ void pass_double(); -+ -+ public: -+ // Creation -+ SignatureHandlerGenerator(methodHandle method, CodeBuffer* buffer) : NativeSignatureIterator(method) { -+ _masm = new MacroAssembler(buffer); -+ _num_int_args = (method->is_static() ? 1 : 0); -+ _num_fp_args = 0; -+ _stack_offset = 0; -+ } -+ -+ // Code generation -+ void generate(uint64_t fingerprint); -+ -+ // Code generation support -+ static Register from(); -+ static Register to(); -+ static Register temp(); -+}; -+ -+#endif // CPU_LOONGARCH_INTERPRETERRT_LOONGARCH_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/javaFrameAnchor_loongarch.hpp jdk11u-ls/src/hotspot/cpu/loongarch/javaFrameAnchor_loongarch.hpp ---- openjdk/src/hotspot/cpu/loongarch/javaFrameAnchor_loongarch.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/javaFrameAnchor_loongarch.hpp 2023-09-12 13:54:23.085571652 +0800 +diff --git a/src/hotspot/cpu/loongarch/javaFrameAnchor_loongarch.hpp b/src/hotspot/cpu/loongarch/javaFrameAnchor_loongarch.hpp +new file mode 100644 +index 000000000..6814fa44a +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/javaFrameAnchor_loongarch.hpp @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. @@ -17991,10 +23740,12 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + void set_last_Java_fp(intptr_t* fp) { _last_Java_fp = fp; } + +#endif // CPU_LOONGARCH_JAVAFRAMEANCHOR_LOONGARCH_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/jniFastGetField_loongarch_64.cpp jdk11u-ls/src/hotspot/cpu/loongarch/jniFastGetField_loongarch_64.cpp ---- openjdk/src/hotspot/cpu/loongarch/jniFastGetField_loongarch_64.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/jniFastGetField_loongarch_64.cpp 2023-11-01 09:34:25.485945258 +0800 -@@ -0,0 +1,165 @@ +diff --git a/src/hotspot/cpu/loongarch/jniFastGetField_loongarch_64.cpp b/src/hotspot/cpu/loongarch/jniFastGetField_loongarch_64.cpp +new file mode 100644 +index 000000000..dbcdb7a6a +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/jniFastGetField_loongarch_64.cpp +@@ -0,0 +1,166 @@ +/* + * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2021, Loongson Technology. All rights reserved. @@ -18022,6 +23773,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + +#include "precompiled.hpp" +#include "asm/macroAssembler.hpp" ++#include "code/codeBlob.hpp" +#include "gc/shared/barrierSet.hpp" +#include "gc/shared/barrierSetAssembler.hpp" +#include "memory/resourceArea.hpp" @@ -18160,9 +23912,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ +address JNI_FastGetField::generate_fast_get_double_field() { + return generate_fast_get_int_field0(T_DOUBLE); +} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/jniTypes_loongarch.hpp jdk11u-ls/src/hotspot/cpu/loongarch/jniTypes_loongarch.hpp ---- openjdk/src/hotspot/cpu/loongarch/jniTypes_loongarch.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/jniTypes_loongarch.hpp 2023-09-12 13:54:23.085571652 +0800 +diff --git a/src/hotspot/cpu/loongarch/jniTypes_loongarch.hpp b/src/hotspot/cpu/loongarch/jniTypes_loongarch.hpp +new file mode 100644 +index 000000000..b281f8637 +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/jniTypes_loongarch.hpp @@ -0,0 +1,144 @@ +/* + * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. @@ -18308,9 +24062,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ +}; + +#endif // CPU_LOONGARCH_JNITYPES_LOONGARCH_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/jvmciCodeInstaller_loongarch.cpp jdk11u-ls/src/hotspot/cpu/loongarch/jvmciCodeInstaller_loongarch.cpp ---- openjdk/src/hotspot/cpu/loongarch/jvmciCodeInstaller_loongarch.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/jvmciCodeInstaller_loongarch.cpp 2023-09-12 13:54:23.085571652 +0800 +diff --git a/src/hotspot/cpu/loongarch/jvmciCodeInstaller_loongarch.cpp b/src/hotspot/cpu/loongarch/jvmciCodeInstaller_loongarch.cpp +new file mode 100644 +index 000000000..ea481c7fa +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/jvmciCodeInstaller_loongarch.cpp @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. @@ -18511,13 +24267,46 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ +bool CodeInstaller::is_general_purpose_reg(VMReg hotspotRegister) { + return !hotspotRegister->is_FloatRegister(); +} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/loongarch_64.ad jdk11u-ls/src/hotspot/cpu/loongarch/loongarch_64.ad ---- openjdk/src/hotspot/cpu/loongarch/loongarch_64.ad 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/loongarch_64.ad 2023-11-01 09:34:25.485945258 +0800 -@@ -0,0 +1,13906 @@ +diff --git a/src/hotspot/cpu/loongarch/loongarch.ad b/src/hotspot/cpu/loongarch/loongarch.ad +new file mode 100644 +index 000000000..80dff0c76 +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/loongarch.ad +@@ -0,0 +1,25 @@ ++// ++// Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. ++// Copyright (c) 2015, 2021, Loongson Technology. 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. ++// ++// ++ +diff --git a/src/hotspot/cpu/loongarch/loongarch_64.ad b/src/hotspot/cpu/loongarch/loongarch_64.ad +new file mode 100644 +index 000000000..c10f0b70c +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/loongarch_64.ad +@@ -0,0 +1,13928 @@ +// +// Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. -+// Copyright (c) 2015, 2022, Loongson Technology. All rights reserved. ++// Copyright (c) 2015, 2023, Loongson Technology. 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 @@ -24955,6 +30744,17 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + ins_pipe(empty); +%} + ++instruct same_addr_load_fence() %{ ++ match(SameAddrLoadFence); ++ ins_cost(400); ++ ++ format %{ "MEMBAR @ same_addr_load_fence" %} ++ ins_encode %{ ++ __ dbar(0x700); ++ %} ++ ins_pipe(pipe_slow); ++%} ++ +//----------Move Instructions-------------------------------------------------- +instruct castX2P(mRegP dst, mRegL src) %{ + match(Set dst (CastX2P src)); @@ -28578,14 +34378,25 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ +%} + +// Store CMS card-mark Immediate 0 ++instruct storeImmCM_order(memory mem, immI_0 zero) %{ ++ match(Set mem (StoreCM mem zero)); ++ predicate(UseConcMarkSweepGC && !UseCondCardMark); ++ ins_cost(100); ++ format %{ "StoreCM MEMBAR storestore\n\t" ++ "st_b $mem, zero\t! card-mark imm0" %} ++ ins_encode %{ ++ __ membar(__ StoreStore); ++ __ loadstore_enc(R0, $mem$$base, $mem$$index, $mem$$scale, $mem$$disp, MacroAssembler::STORE_BYTE); ++ %} ++ ins_pipe( ialu_storeI ); ++%} ++ +instruct storeImmCM(memory mem, immI_0 zero) %{ + match(Set mem (StoreCM mem zero)); + + ins_cost(150); -+ format %{ "StoreCM MEMBAR loadstore\n\t" -+ "st_b $mem, zero\t! CMS card-mark imm0" %} ++ format %{ "st_b $mem, zero\t! card-mark imm0" %} + ins_encode %{ -+ __ membar(__ StoreStore); + __ loadstore_enc(R0, $mem$$base, $mem$$index, $mem$$scale, $mem$$disp, MacroAssembler::STORE_BYTE); + %} + ins_pipe( ialu_storeI ); @@ -32421,42 +38232,15 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ +// These must follow all instruction definitions as they use the names +// defined in the instructions definitions. + -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/loongarch.ad jdk11u-ls/src/hotspot/cpu/loongarch/loongarch.ad ---- openjdk/src/hotspot/cpu/loongarch/loongarch.ad 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/loongarch.ad 2023-09-12 13:54:23.089571657 +0800 -@@ -0,0 +1,25 @@ -+// -+// Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. -+// Copyright (c) 2015, 2021, Loongson Technology. 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. -+// -+// -+ -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/macroAssembler_loongarch.cpp jdk11u-ls/src/hotspot/cpu/loongarch/macroAssembler_loongarch.cpp ---- openjdk/src/hotspot/cpu/loongarch/macroAssembler_loongarch.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/macroAssembler_loongarch.cpp 2023-11-01 09:34:25.485945258 +0800 -@@ -0,0 +1,4521 @@ +diff --git a/src/hotspot/cpu/loongarch/macroAssembler_loongarch.cpp b/src/hotspot/cpu/loongarch/macroAssembler_loongarch.cpp +new file mode 100644 +index 000000000..9720fd176 +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/macroAssembler_loongarch.cpp +@@ -0,0 +1,4567 @@ +/* + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2017, 2022, Loongson Technology. All rights reserved. ++ * Copyright (c) 2017, 2023, Loongson Technology. 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 @@ -32491,6 +38275,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ +#include "interpreter/interpreter.hpp" +#include "memory/resourceArea.hpp" +#include "memory/universe.hpp" ++#include "nativeInst_loongarch.hpp" +#include "prims/methodHandles.hpp" +#include "runtime/biasedLocking.hpp" +#include "runtime/interfaceSupport.inline.hpp" @@ -32504,6 +38289,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + +#ifdef COMPILER2 +#include "opto/compile.hpp" ++#include "opto/intrinsicnode.hpp" +#endif + +#define T0 RT0 @@ -34280,7 +40066,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + + bind(fail); + if (barrier) -+ membar(LoadLoad); ++ dbar(0x700); + if (retold && oldval != R0) + move(oldval, resflag); + move(resflag, R0); @@ -34303,7 +40089,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + + bind(neq); + if (barrier) -+ membar(LoadLoad); ++ dbar(0x700); + if (retold && oldval != R0) + move(oldval, tmp); + if (fail) @@ -34328,7 +40114,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + + bind(fail); + if (barrier) -+ membar(LoadLoad); ++ dbar(0x700); + if (retold && oldval != R0) + move(oldval, resflag); + move(resflag, R0); @@ -34353,7 +40139,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + + bind(neq); + if (barrier) -+ membar(LoadLoad); ++ dbar(0x700); + if (retold && oldval != R0) + move(oldval, tmp); + if (fail) @@ -34372,6 +40158,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + guarantee(0, "LA not implemented yet"); +} + ++#ifdef COMPILER2 +// Fast_Lock and Fast_Unlock used by C2 + +// Because the transitions from emitted code to the runtime @@ -34730,7 +40517,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + move(AT, R0); + bnez(scrReg, DONE_SET); + -+ membar(Assembler::Membar_mask_bits(LoadLoad|LoadStore)); ++ membar(Assembler::Membar_mask_bits(LoadStore|StoreStore)); + st_d(R0, Address(tmpReg, ObjectMonitor::owner_offset_in_bytes() - 2)); + li(resReg, 1); + b(DONE); @@ -34752,6 +40539,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + if (EmitSync & 32768) { nop() ; } + } +} ++#endif // COMPILER2 + +void MacroAssembler::align(int modulus) { + while (offset() % modulus != 0) nop(); @@ -34853,6 +40641,38 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + addi_d(SP, SP, 16); +} + ++void MacroAssembler::push(unsigned int bitset) { ++ unsigned char regs[31]; ++ int count = 0; ++ ++ bitset >>= 1; ++ for (int reg = 1; reg < 31; reg++) { ++ if (1 & bitset) ++ regs[count++] = reg; ++ bitset >>= 1; ++ } ++ ++ addi_d(SP, SP, -align_up(count, 2) * wordSize); ++ for (int i = 0; i < count; i ++) ++ st_d(as_Register(regs[i]), SP, i * wordSize); ++} ++ ++void MacroAssembler::pop(unsigned int bitset) { ++ unsigned char regs[31]; ++ int count = 0; ++ ++ bitset >>= 1; ++ for (int reg = 1; reg < 31; reg++) { ++ if (1 & bitset) ++ regs[count++] = reg; ++ bitset >>= 1; ++ } ++ ++ for (int i = 0; i < count; i ++) ++ ld_d(as_Register(regs[i]), SP, i * wordSize); ++ addi_d(SP, SP, align_up(count, 2) * wordSize); ++} ++ +// for UseCompressedOops Option +void MacroAssembler::load_klass(Register dst, Register src) { + if(UseCompressedClassPointers){ @@ -35571,6 +41391,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + ld_d(method_result, AT, base + vtableEntry::method_offset_in_bytes()); +} + ++#ifdef COMPILER2 +// Compare strings, used for char[] and byte[]. +void MacroAssembler::string_compare(Register str1, Register str2, + Register cnt1, Register cnt2, Register result, @@ -35663,6 +41484,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + + bind(True); +} ++#endif // COMPILER2 + +void MacroAssembler::load_byte_map_base(Register reg) { + jbyte *byte_map_base = @@ -36449,6 +42271,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + } +} + ++#ifdef COMPILER2 +void MacroAssembler::reduce_ins_v(FloatRegister vec1, FloatRegister vec2, FloatRegister vec3, BasicType type, int opcode) { + switch (type) { + case T_BYTE: @@ -36654,6 +42477,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + ShouldNotReachHere(); + } +} ++#endif // COMPILER2 + +/** + * Emits code to update CRC-32 with a byte value according to constants in table @@ -36803,6 +42627,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + bind(L_exit); +} + ++#ifdef COMPILER2 +void MacroAssembler::cmp_branch_short(int flag, Register op1, Register op2, Label& L, bool is_signed) { + + switch(flag) { @@ -36890,16 +42715,21 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + Unimplemented(); + } +} ++#endif // COMPILER2 + +void MacroAssembler::membar(Membar_mask_bits hint){ + address prev = pc() - NativeInstruction::sync_instruction_size; + address last = code()->last_insn(); + if (last != NULL && ((NativeInstruction*)last)->is_sync() && prev == last) { + code()->set_last_insn(NULL); ++ NativeMembar *membar = (NativeMembar*)prev; ++ // merged membar ++ // e.g. LoadLoad and LoadLoad|LoadStore to LoadLoad|LoadStore ++ membar->set_hint(membar->get_hint() & (~hint & 0xF)); + block_comment("merged membar"); + } else { + code()->set_last_insn(pc()); -+ dbar(hint); ++ Assembler::membar(hint); + } +} + @@ -36975,10 +42805,12 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + bind(L_end); +} + -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/macroAssembler_loongarch.hpp jdk11u-ls/src/hotspot/cpu/loongarch/macroAssembler_loongarch.hpp ---- openjdk/src/hotspot/cpu/loongarch/macroAssembler_loongarch.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/macroAssembler_loongarch.hpp 2023-11-01 09:34:25.489945263 +0800 -@@ -0,0 +1,814 @@ +diff --git a/src/hotspot/cpu/loongarch/macroAssembler_loongarch.hpp b/src/hotspot/cpu/loongarch/macroAssembler_loongarch.hpp +new file mode 100644 +index 000000000..1f9655754 +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/macroAssembler_loongarch.hpp +@@ -0,0 +1,825 @@ +/* + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, Loongson Technology. All rights reserved. @@ -37564,6 +43396,8 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + void popad(); + void pushad_except_v0(); + void popad_except_v0(); ++ void push(RegSet regs) { if (regs.bits()) push(regs.bits()); } ++ void pop(RegSet regs) { if (regs.bits()) pop(regs.bits()); } + + void li(Register rd, jlong value); + void li(Register rd, address addr) { li(rd, (long)addr); } @@ -37599,6 +43433,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + //FIXME + void empty_FPU_stack(){/*need implemented*/}; + ++#ifdef COMPILER2 + // Compare strings. + void string_compare(Register str1, Register str2, + Register cnt1, Register cnt2, Register result, @@ -37608,6 +43443,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + void arrays_equals(Register str1, Register str2, + Register cnt, Register tmp1, Register tmp2, Register result, + bool is_char); ++#endif + + // method handles (JSR 292) + Address argument_address(RegisterOrConstant arg_slot, int extra_slot_offset = 0); @@ -37726,10 +43562,15 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + loadstore_t(reg, base, index, scale, disp, type); + } + ++#ifdef COMPILER2 + void reduce(Register dst, Register src, FloatRegister vsrc, FloatRegister tmp1, FloatRegister tmp2, BasicType type, int opcode, int vector_size); + void reduce(FloatRegister dst, FloatRegister src, FloatRegister vsrc, FloatRegister tmp, BasicType type, int opcode, int vector_size); ++#endif + +private: ++ void push(unsigned int bitset); ++ void pop(unsigned int bitset); ++ + template + void loadstore_t(T reg, int base, int index, int scale, int disp, int type) { + if (index != 0) { @@ -37744,9 +43585,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + void loadstore(FloatRegister reg, Register base, int disp, int type); + void loadstore(FloatRegister reg, Register base, Register disp, int type); + ++#ifdef COMPILER2 + void reduce_ins_v(FloatRegister vec1, FloatRegister vec2, FloatRegister vec3, BasicType type, int opcode); + void reduce_ins_r(Register reg1, Register reg2, Register reg3, BasicType type, int opcode); + void reduce_ins_f(FloatRegister reg1, FloatRegister reg2, FloatRegister reg3, BasicType type, int opcode); ++#endif + void generate_kernel_sin(FloatRegister x, bool iyIsOne, address dsin_coef); + void generate_kernel_cos(FloatRegister x, address dcos_coef); + void generate__ieee754_rem_pio2(address npio2_hw, address two_over_pi, address pio2); @@ -37793,9 +43636,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ +}; + +#endif // CPU_LOONGARCH_MACROASSEMBLER_LOONGARCH_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/macroAssembler_loongarch.inline.hpp jdk11u-ls/src/hotspot/cpu/loongarch/macroAssembler_loongarch.inline.hpp ---- openjdk/src/hotspot/cpu/loongarch/macroAssembler_loongarch.inline.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/macroAssembler_loongarch.inline.hpp 2023-09-12 13:54:23.089571657 +0800 +diff --git a/src/hotspot/cpu/loongarch/macroAssembler_loongarch.inline.hpp b/src/hotspot/cpu/loongarch/macroAssembler_loongarch.inline.hpp +new file mode 100644 +index 000000000..49302590c +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/macroAssembler_loongarch.inline.hpp @@ -0,0 +1,34 @@ +/* + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. @@ -37831,13 +43676,15 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ +#include "code/codeCache.hpp" + +#endif // CPU_LOONGARCH_MACROASSEMBLER_LOONGARCH_INLINE_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/macroAssembler_loongarch_trig.cpp jdk11u-ls/src/hotspot/cpu/loongarch/macroAssembler_loongarch_trig.cpp ---- openjdk/src/hotspot/cpu/loongarch/macroAssembler_loongarch_trig.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/macroAssembler_loongarch_trig.cpp 2023-09-12 13:54:23.089571657 +0800 -@@ -0,0 +1,1625 @@ +diff --git a/src/hotspot/cpu/loongarch/macroAssembler_loongarch_trig.cpp b/src/hotspot/cpu/loongarch/macroAssembler_loongarch_trig.cpp +new file mode 100644 +index 000000000..6e27a6974 +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/macroAssembler_loongarch_trig.cpp +@@ -0,0 +1,1626 @@ +/* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, Cavium. All rights reserved. (By BELLSOFT) -+ * Copyright (c) 2022, Loongson Technology. All rights reserved. ++ * Copyright (c) 2022, 2024, Loongson Technology. 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 @@ -38736,7 +44583,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + b(Q_DONE); + bind(JX_IS_0); + if (UseLASX) { -+ xvfmul_d(v28, v18, v6); // f[0,1] * x[0] ++ xvfmul_d(v28, v18, v6); // f[0,3] * x[0] + fmul_d(v30, v19, v6); // f[4] * x[0] + } else { + vfmul_d(v28, v18, v6); // f[0,1] * x[0] @@ -38965,6 +44812,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + st_w(tmp2, SCR2, 0); + addi_w(SCR1, SCR1, 24); + addi_w(jz, jz, 1); ++ alsl_d(SCR2, jz, iqBase, 2 - 1); + st_w(tmp3, SCR2, 0); // iq[jz] = (int) fw + b(Z_ZERO_CHECK_DONE); + bind(Z_IS_LESS_THAN_TWO24B); @@ -39460,13 +45308,15 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + bind(DONE); + jr(RA); +} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/methodHandles_loongarch.cpp jdk11u-ls/src/hotspot/cpu/loongarch/methodHandles_loongarch.cpp ---- openjdk/src/hotspot/cpu/loongarch/methodHandles_loongarch.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/methodHandles_loongarch.cpp 2023-11-01 09:34:25.489945263 +0800 -@@ -0,0 +1,562 @@ +diff --git a/src/hotspot/cpu/loongarch/methodHandles_loongarch.cpp b/src/hotspot/cpu/loongarch/methodHandles_loongarch.cpp +new file mode 100644 +index 000000000..e517dcd41 +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/methodHandles_loongarch.cpp +@@ -0,0 +1,564 @@ +/* + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2021, Loongson Technology. All rights reserved. ++ * Copyright (c) 2015, 2022, Loongson Technology. 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 @@ -39496,6 +45346,8 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ +#include "interpreter/interpreterRuntime.hpp" +#include "memory/allocation.inline.hpp" +#include "prims/methodHandles.hpp" ++#include "runtime/frame.inline.hpp" ++#include "utilities/preserveException.hpp" + +#define __ _masm-> + @@ -40026,9 +45878,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ +void MethodHandles::trace_method_handle(MacroAssembler* _masm, const char* adaptername) { +} +#endif //PRODUCT -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/methodHandles_loongarch.hpp jdk11u-ls/src/hotspot/cpu/loongarch/methodHandles_loongarch.hpp ---- openjdk/src/hotspot/cpu/loongarch/methodHandles_loongarch.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/methodHandles_loongarch.hpp 2023-09-12 13:54:23.089571657 +0800 +diff --git a/src/hotspot/cpu/loongarch/methodHandles_loongarch.hpp b/src/hotspot/cpu/loongarch/methodHandles_loongarch.hpp +new file mode 100644 +index 000000000..f84337424 +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/methodHandles_loongarch.hpp @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. @@ -40092,10 +45946,12 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + // Should be in sharedRuntime, not here. + return R3; + } -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/nativeInst_loongarch.cpp jdk11u-ls/src/hotspot/cpu/loongarch/nativeInst_loongarch.cpp ---- openjdk/src/hotspot/cpu/loongarch/nativeInst_loongarch.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/nativeInst_loongarch.cpp 2023-11-01 09:34:25.489945263 +0800 -@@ -0,0 +1,505 @@ +diff --git a/src/hotspot/cpu/loongarch/nativeInst_loongarch.cpp b/src/hotspot/cpu/loongarch/nativeInst_loongarch.cpp +new file mode 100644 +index 000000000..9234befae +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/nativeInst_loongarch.cpp +@@ -0,0 +1,511 @@ +/* + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2021, Loongson Technology. All rights reserved. @@ -40133,6 +45989,10 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ +#include "runtime/stubRoutines.hpp" +#include "utilities/ostream.hpp" + ++#ifndef PRODUCT ++#include "compiler/disassembler.hpp" ++#endif ++ +#include + +#define T0 RT0 @@ -40434,7 +46294,9 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + return Assembler::simm12((int_at(0) >> 10) & 0xfff); + } + -+ //Disassembler::decode(addr_at(0), addr_at(0) + 16, tty); ++#ifndef PRODUCT ++ Disassembler::decode(addr_at(0), addr_at(0) + 16, tty); ++#endif + fatal("not a mov reg, imm52"); + return 0; // unreachable +} @@ -40601,10 +46463,12 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + return Assembler::high(insn_word(), 10) == Assembler::ld_w_op && + Assembler::low(insn_word(), 5) == AT->encoding(); +} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/nativeInst_loongarch.hpp jdk11u-ls/src/hotspot/cpu/loongarch/nativeInst_loongarch.hpp ---- openjdk/src/hotspot/cpu/loongarch/nativeInst_loongarch.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/nativeInst_loongarch.hpp 2023-11-01 09:34:25.489945263 +0800 -@@ -0,0 +1,521 @@ +diff --git a/src/hotspot/cpu/loongarch/nativeInst_loongarch.hpp b/src/hotspot/cpu/loongarch/nativeInst_loongarch.hpp +new file mode 100644 +index 000000000..a6e9d4dd3 +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/nativeInst_loongarch.hpp +@@ -0,0 +1,528 @@ +/* + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2021, Loongson Technology. All rights reserved. @@ -41125,10 +46989,72 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + assert(ni->is_NativeCallTrampolineStub_at(), "no call trampoline found"); + return (NativeCallTrampolineStub*)addr; +} ++ ++class NativeMembar : public NativeInstruction { ++public: ++ unsigned int get_hint() { return Assembler::low(insn_word(), 4); } ++ void set_hint(int hint) { Assembler::patch(addr_at(0), 4, hint); } ++}; ++ +#endif // CPU_LOONGARCH_NATIVEINST_LOONGARCH_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/register_definitions_loongarch.cpp jdk11u-ls/src/hotspot/cpu/loongarch/register_definitions_loongarch.cpp ---- openjdk/src/hotspot/cpu/loongarch/register_definitions_loongarch.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/register_definitions_loongarch.cpp 2023-09-12 13:54:23.089571657 +0800 +diff --git a/src/hotspot/cpu/loongarch/registerMap_loongarch.hpp b/src/hotspot/cpu/loongarch/registerMap_loongarch.hpp +new file mode 100644 +index 000000000..e9f0fc280 +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/registerMap_loongarch.hpp +@@ -0,0 +1,47 @@ ++/* ++ * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2015, 2016, Loongson Technology. 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 CPU_LOONGARCH_REGISTERMAP_LOONGARCH_HPP ++#define CPU_LOONGARCH_REGISTERMAP_LOONGARCH_HPP ++ ++// machine-dependent implemention for register maps ++ friend class frame; ++ ++ private: ++#ifndef CORE ++ // This is the hook for finding a register in an "well-known" location, ++ // such as a register block of a predetermined format. ++ // Since there is none, we just return NULL. ++ // See registerMap_sparc.hpp for an example of grabbing registers ++ // from register save areas of a standard layout. ++ address pd_location(VMReg reg) const {return NULL;} ++#endif ++ ++ // no PD state to clear or copy: ++ void pd_clear() {} ++ void pd_initialize() {} ++ void pd_initialize_from(const RegisterMap* map) {} ++ ++#endif // CPU_LOONGARCH_REGISTERMAP_LOONGARCH_HPP +diff --git a/src/hotspot/cpu/loongarch/register_definitions_loongarch.cpp b/src/hotspot/cpu/loongarch/register_definitions_loongarch.cpp +new file mode 100644 +index 000000000..58f40b747 +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/register_definitions_loongarch.cpp @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. @@ -41233,9 +47159,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ +REGISTER_DEFINITION(FloatRegister, f29); +REGISTER_DEFINITION(FloatRegister, f30); +REGISTER_DEFINITION(FloatRegister, f31); -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/register_loongarch.cpp jdk11u-ls/src/hotspot/cpu/loongarch/register_loongarch.cpp ---- openjdk/src/hotspot/cpu/loongarch/register_loongarch.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/register_loongarch.cpp 2023-09-12 13:54:23.089571657 +0800 +diff --git a/src/hotspot/cpu/loongarch/register_loongarch.cpp b/src/hotspot/cpu/loongarch/register_loongarch.cpp +new file mode 100644 +index 000000000..54d90167a +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/register_loongarch.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. @@ -41296,13 +47224,15 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + }; + return is_valid() ? names[encoding()] : "fccnoreg"; +} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/register_loongarch.hpp jdk11u-ls/src/hotspot/cpu/loongarch/register_loongarch.hpp ---- openjdk/src/hotspot/cpu/loongarch/register_loongarch.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/register_loongarch.hpp 2023-11-01 09:34:25.489945263 +0800 -@@ -0,0 +1,428 @@ +diff --git a/src/hotspot/cpu/loongarch/register_loongarch.hpp b/src/hotspot/cpu/loongarch/register_loongarch.hpp +new file mode 100644 +index 000000000..da876a508 +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/register_loongarch.hpp +@@ -0,0 +1,495 @@ +/* + * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2021, Loongson Technology. All rights reserved. ++ * Copyright (c) 2015, 2022, Loongson Technology. 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 @@ -41727,65 +47657,83 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + static const int max_fpr; +}; + -+#endif //CPU_LOONGARCH_REGISTER_LOONGARCH_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/registerMap_loongarch.hpp jdk11u-ls/src/hotspot/cpu/loongarch/registerMap_loongarch.hpp ---- openjdk/src/hotspot/cpu/loongarch/registerMap_loongarch.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/registerMap_loongarch.hpp 2023-09-12 13:54:23.089571657 +0800 -@@ -0,0 +1,47 @@ -+/* -+ * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2016, Loongson Technology. 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. -+ * -+ */ ++// A set of registers ++template ++class AbstractRegSet { ++ uint32_t _bitset; + -+#ifndef CPU_LOONGARCH_REGISTERMAP_LOONGARCH_HPP -+#define CPU_LOONGARCH_REGISTERMAP_LOONGARCH_HPP ++ AbstractRegSet(uint32_t bitset) : _bitset(bitset) { } + -+// machine-dependent implemention for register maps -+ friend class frame; ++public: + -+ private: -+#ifndef CORE -+ // This is the hook for finding a register in an "well-known" location, -+ // such as a register block of a predetermined format. -+ // Since there is none, we just return NULL. -+ // See registerMap_sparc.hpp for an example of grabbing registers -+ // from register save areas of a standard layout. -+ address pd_location(VMReg reg) const {return NULL;} -+#endif ++ AbstractRegSet() : _bitset(0) { } + -+ // no PD state to clear or copy: -+ void pd_clear() {} -+ void pd_initialize() {} -+ void pd_initialize_from(const RegisterMap* map) {} ++ AbstractRegSet(RegImpl r1) : _bitset(1 << r1->encoding()) { } + -+#endif // CPU_LOONGARCH_REGISTERMAP_LOONGARCH_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/relocInfo_loongarch.cpp jdk11u-ls/src/hotspot/cpu/loongarch/relocInfo_loongarch.cpp ---- openjdk/src/hotspot/cpu/loongarch/relocInfo_loongarch.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/relocInfo_loongarch.cpp 2023-11-01 09:34:25.489945263 +0800 -@@ -0,0 +1,130 @@ ++ AbstractRegSet operator+(const AbstractRegSet aSet) const { ++ AbstractRegSet result(_bitset | aSet._bitset); ++ return result; ++ } ++ ++ AbstractRegSet operator-(const AbstractRegSet aSet) const { ++ AbstractRegSet result(_bitset & ~aSet._bitset); ++ return result; ++ } ++ ++ AbstractRegSet &operator+=(const AbstractRegSet aSet) { ++ *this = *this + aSet; ++ return *this; ++ } ++ ++ AbstractRegSet &operator-=(const AbstractRegSet aSet) { ++ *this = *this - aSet; ++ return *this; ++ } ++ ++ static AbstractRegSet of(RegImpl r1) { ++ return AbstractRegSet(r1); ++ } ++ ++ static AbstractRegSet of(RegImpl r1, RegImpl r2) { ++ return of(r1) + r2; ++ } ++ ++ static AbstractRegSet of(RegImpl r1, RegImpl r2, RegImpl r3) { ++ return of(r1, r2) + r3; ++ } ++ ++ static AbstractRegSet of(RegImpl r1, RegImpl r2, RegImpl r3, RegImpl r4) { ++ return of(r1, r2, r3) + r4; ++ } ++ ++ static AbstractRegSet of(RegImpl r1, RegImpl r2, RegImpl r3, RegImpl r4, RegImpl r5) { ++ return of(r1, r2, r3, r4) + r5; ++ } ++ ++ static AbstractRegSet range(RegImpl start, RegImpl end) { ++ uint32_t bits = ~0; ++ bits <<= start->encoding(); ++ bits <<= 31 - end->encoding(); ++ bits >>= 31 - end->encoding(); ++ ++ return AbstractRegSet(bits); ++ } ++ ++ uint32_t bits() const { return _bitset; } ++}; ++ ++typedef AbstractRegSet RegSet; ++ ++#endif //CPU_LOONGARCH_REGISTER_LOONGARCH_HPP +diff --git a/src/hotspot/cpu/loongarch/relocInfo_loongarch.cpp b/src/hotspot/cpu/loongarch/relocInfo_loongarch.cpp +new file mode 100644 +index 000000000..1caba4369 +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/relocInfo_loongarch.cpp +@@ -0,0 +1,132 @@ +/* + * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2021, Loongson Technology. All rights reserved. ++ * Copyright (c) 2015, 2022, Loongson Technology. 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 @@ -41811,9 +47759,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ +#include "precompiled.hpp" +#include "asm/macroAssembler.hpp" +#include "code/relocInfo.hpp" ++#include "compiler/disassembler.hpp" +#include "nativeInst_loongarch.hpp" +#include "oops/compressedOops.inline.hpp" +#include "oops/oop.hpp" ++#include "oops/klass.inline.hpp" +#include "runtime/safepoint.hpp" + + @@ -41913,9 +47863,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + +void metadata_Relocation::pd_fix_value(address x) { +} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/relocInfo_loongarch.hpp jdk11u-ls/src/hotspot/cpu/loongarch/relocInfo_loongarch.hpp ---- openjdk/src/hotspot/cpu/loongarch/relocInfo_loongarch.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/relocInfo_loongarch.hpp 2023-09-12 13:54:23.089571657 +0800 +diff --git a/src/hotspot/cpu/loongarch/relocInfo_loongarch.hpp b/src/hotspot/cpu/loongarch/relocInfo_loongarch.hpp +new file mode 100644 +index 000000000..c85ca4963 +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/relocInfo_loongarch.hpp @@ -0,0 +1,44 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. @@ -41961,9 +47913,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + static bool mustIterateImmediateOopsInCode() { return false; } + +#endif // CPU_LOONGARCH_RELOCINFO_LOONGARCH_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/runtime_loongarch_64.cpp jdk11u-ls/src/hotspot/cpu/loongarch/runtime_loongarch_64.cpp ---- openjdk/src/hotspot/cpu/loongarch/runtime_loongarch_64.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/runtime_loongarch_64.cpp 2023-09-12 13:54:23.089571657 +0800 +diff --git a/src/hotspot/cpu/loongarch/runtime_loongarch_64.cpp b/src/hotspot/cpu/loongarch/runtime_loongarch_64.cpp +new file mode 100644 +index 000000000..334c783b3 +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/runtime_loongarch_64.cpp @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. @@ -42156,13 +48110,15 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + masm->flush(); + _exception_blob = ExceptionBlob::create(&buffer, oop_maps, framesize); +} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/sharedRuntime_loongarch_64.cpp jdk11u-ls/src/hotspot/cpu/loongarch/sharedRuntime_loongarch_64.cpp ---- openjdk/src/hotspot/cpu/loongarch/sharedRuntime_loongarch_64.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/sharedRuntime_loongarch_64.cpp 2023-11-01 09:34:25.489945263 +0800 -@@ -0,0 +1,3620 @@ +diff --git a/src/hotspot/cpu/loongarch/sharedRuntime_loongarch_64.cpp b/src/hotspot/cpu/loongarch/sharedRuntime_loongarch_64.cpp +new file mode 100644 +index 000000000..bc91ee005 +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/sharedRuntime_loongarch_64.cpp +@@ -0,0 +1,3621 @@ +/* + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2021, Loongson Technology. All rights reserved. ++ * Copyright (c) 2015, 2022, Loongson Technology. 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 @@ -42192,6 +48148,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ +#include "code/icBuffer.hpp" +#include "code/vtableStubs.hpp" +#include "interpreter/interpreter.hpp" ++#include "nativeInst_loongarch.hpp" +#include "oops/compiledICHolder.hpp" +#include "runtime/sharedRuntime.hpp" +#include "runtime/vframeArray.hpp" @@ -42474,9 +48431,9 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ +} + +// Is vector's size (in bytes) bigger than a size saved by default? -+// 16 bytes XMM registers are saved by default using fxsave/fxrstor instructions. ++// 8 bytes registers are saved by default using fld/fst instructions. +bool SharedRuntime::is_wide_vector(int size) { -+ return size > 16; ++ return size > 8; +} + +size_t SharedRuntime::trampoline_size() { @@ -45780,10 +51737,12 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ +} + +extern "C" int SpinPause() {return 0;} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/stubGenerator_loongarch_64.cpp jdk11u-ls/src/hotspot/cpu/loongarch/stubGenerator_loongarch_64.cpp ---- openjdk/src/hotspot/cpu/loongarch/stubGenerator_loongarch_64.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/stubGenerator_loongarch_64.cpp 2023-11-01 09:34:25.489945263 +0800 -@@ -0,0 +1,4825 @@ +diff --git a/src/hotspot/cpu/loongarch/stubGenerator_loongarch_64.cpp b/src/hotspot/cpu/loongarch/stubGenerator_loongarch_64.cpp +new file mode 100644 +index 000000000..7f73863b2 +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/stubGenerator_loongarch_64.cpp +@@ -0,0 +1,4804 @@ +/* + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, Loongson Technology. All rights reserved. @@ -46493,8 +52452,8 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + + // disjoint large copy + void generate_disjoint_large_copy(Label &entry, const char *name) { -+ StubCodeMark mark(this, "StubRoutines", name); + __ align(CodeEntryAlignment); ++ StubCodeMark mark(this, "StubRoutines", name); + + Label loop, le32, le16, le8, lt8; + @@ -46574,8 +52533,8 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + + // disjoint large copy lsx + void generate_disjoint_large_copy_lsx(Label &entry, const char *name) { -+ StubCodeMark mark(this, "StubRoutines", name); + __ align(CodeEntryAlignment); ++ StubCodeMark mark(this, "StubRoutines", name); + + Label loop, le64, le32, le16, lt16; + @@ -46656,8 +52615,8 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + + // disjoint large copy lasx + void generate_disjoint_large_copy_lasx(Label &entry, const char *name) { -+ StubCodeMark mark(this, "StubRoutines", name); + __ align(CodeEntryAlignment); ++ StubCodeMark mark(this, "StubRoutines", name); + + Label loop, le128, le64, le32, lt32; + @@ -46738,8 +52697,8 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + + // conjoint large copy + void generate_conjoint_large_copy(Label &entry, const char *name) { -+ StubCodeMark mark(this, "StubRoutines", name); + __ align(CodeEntryAlignment); ++ StubCodeMark mark(this, "StubRoutines", name); + + Label loop, le32, le16, le8, lt8; + @@ -46816,8 +52775,8 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + + // conjoint large copy lsx + void generate_conjoint_large_copy_lsx(Label &entry, const char *name) { -+ StubCodeMark mark(this, "StubRoutines", name); + __ align(CodeEntryAlignment); ++ StubCodeMark mark(this, "StubRoutines", name); + + Label loop, le64, le32, le16, lt16; + @@ -46895,8 +52854,8 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + + // conjoint large copy lasx + void generate_conjoint_large_copy_lasx(Label &entry, const char *name) { -+ StubCodeMark mark(this, "StubRoutines", name); + __ align(CodeEntryAlignment); ++ StubCodeMark mark(this, "StubRoutines", name); + + Label loop, le128, le64, le32, lt32; + @@ -46974,8 +52933,8 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + + // Byte small copy: less than { int:9, lsx:17, lasx:33 } elements. + void generate_byte_small_copy(Label &entry, const char *name) { -+ StubCodeMark mark(this, "StubRoutines", name); + __ align(CodeEntryAlignment); ++ StubCodeMark mark(this, "StubRoutines", name); + + Label L; + __ bind(entry); @@ -47340,8 +53299,8 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + // + address generate_disjoint_byte_copy(bool aligned, Label &small, Label &large, + Label &large_aligned, const char * name) { -+ StubCodeMark mark(this, "StubRoutines", name); + __ align(CodeEntryAlignment); ++ StubCodeMark mark(this, "StubRoutines", name); + address start = __ pc(); + + if (UseLASX) @@ -47380,8 +53339,8 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + // + address generate_conjoint_byte_copy(bool aligned, Label &small, Label &large, + Label &large_aligned, const char *name) { -+ StubCodeMark mark(this, "StubRoutines", name); + __ align(CodeEntryAlignment); ++ StubCodeMark mark(this, "StubRoutines", name); + address start = __ pc(); + + array_overlap_test(StubRoutines::jbyte_disjoint_arraycopy(), 0); @@ -47407,8 +53366,8 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + + // Short small copy: less than { int:9, lsx:9, lasx:17 } elements. + void generate_short_small_copy(Label &entry, const char *name) { -+ StubCodeMark mark(this, "StubRoutines", name); + __ align(CodeEntryAlignment); ++ StubCodeMark mark(this, "StubRoutines", name); + + Label L; + __ bind(entry); @@ -47619,8 +53578,8 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + // + address generate_disjoint_short_copy(bool aligned, Label &small, Label &large, + Label &large_aligned, const char * name) { -+ StubCodeMark mark(this, "StubRoutines", name); + __ align(CodeEntryAlignment); ++ StubCodeMark mark(this, "StubRoutines", name); + address start = __ pc(); + + if (UseLASX) @@ -47659,8 +53618,8 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + // + address generate_conjoint_short_copy(bool aligned, Label &small, Label &large, + Label &large_aligned, const char *name) { -+ StubCodeMark mark(this, "StubRoutines", name); + __ align(CodeEntryAlignment); ++ StubCodeMark mark(this, "StubRoutines", name); + address start = __ pc(); + + array_overlap_test(StubRoutines::jshort_disjoint_arraycopy(), 1); @@ -47686,8 +53645,8 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + + // Int small copy: less than { int:7, lsx:7, lasx:9 } elements. + void generate_int_small_copy(Label &entry, const char *name) { -+ StubCodeMark mark(this, "StubRoutines", name); + __ align(CodeEntryAlignment); ++ StubCodeMark mark(this, "StubRoutines", name); + + Label L; + __ bind(entry); @@ -47848,7 +53807,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + __ st_d(RA, SP, 0 * wordSize); + + bs = BarrierSet::barrier_set()->barrier_set_assembler(); -+ bs->arraycopy_prologue(_masm, decorators, is_oop, A1, A2); ++ bs->arraycopy_prologue(_masm, decorators, is_oop, A1, A2, RegSet()); + + __ ld_d(A2, SP, 3 * wordSize); + __ ld_d(A1, SP, 2 * wordSize); @@ -47892,7 +53851,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + __ ld_d(A2, SP, 3 * wordSize); + __ ld_d(A1, SP, 2 * wordSize); + -+ bs->arraycopy_epilogue(_masm, decorators, is_oop, A1, A2, T1); ++ bs->arraycopy_epilogue(_masm, decorators, is_oop, A1, A2, T1, RegSet()); + + __ ld_d(RA, SP, 0 * wordSize); + __ addi_d(SP, SP, 4 * wordSize); @@ -47923,8 +53882,8 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + address generate_disjoint_int_oop_copy(bool aligned, bool is_oop, Label &small, + Label &large, Label &large_aligned, const char *name, + int small_limit, bool dest_uninitialized = false) { -+ StubCodeMark mark(this, "StubRoutines", name); + __ align(CodeEntryAlignment); ++ StubCodeMark mark(this, "StubRoutines", name); + address start = __ pc(); + + gen_maybe_oop_copy(is_oop, true, aligned, small, large, large_aligned, @@ -47951,8 +53910,8 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + address generate_conjoint_int_oop_copy(bool aligned, bool is_oop, Label &small, + Label &large, Label &large_aligned, const char *name, + int small_limit, bool dest_uninitialized = false) { -+ StubCodeMark mark(this, "StubRoutines", name); + __ align(CodeEntryAlignment); ++ StubCodeMark mark(this, "StubRoutines", name); + address start = __ pc(); + + if (is_oop) { @@ -47969,8 +53928,8 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + + // Long small copy: less than { int:4, lsx:4, lasx:5 } elements. + void generate_long_small_copy(Label &entry, const char *name) { -+ StubCodeMark mark(this, "StubRoutines", name); + __ align(CodeEntryAlignment); ++ StubCodeMark mark(this, "StubRoutines", name); + + Label L; + __ bind(entry); @@ -48073,8 +54032,8 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + address generate_disjoint_long_oop_copy(bool aligned, bool is_oop, Label &small, + Label &large, Label &large_aligned, const char *name, + int small_limit, bool dest_uninitialized = false) { -+ StubCodeMark mark(this, "StubRoutines", name); + __ align(CodeEntryAlignment); ++ StubCodeMark mark(this, "StubRoutines", name); + address start = __ pc(); + + gen_maybe_oop_copy(is_oop, true, aligned, small, large, large_aligned, @@ -48101,8 +54060,8 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + address generate_conjoint_long_oop_copy(bool aligned, bool is_oop, Label &small, + Label &large, Label &large_aligned, const char *name, + int small_limit, bool dest_uninitialized = false) { -+ StubCodeMark mark(this, "StubRoutines", name); + __ align(CodeEntryAlignment); ++ StubCodeMark mark(this, "StubRoutines", name); + address start = __ pc(); + + if (is_oop) { @@ -48163,6 +54122,9 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + const Register ckoff = A3; // super_check_offset + const Register ckval = A4; // super_klass + ++ RegSet wb_pre_saved_regs = RegSet::range(A0, A4); ++ RegSet wb_post_saved_regs = RegSet::of(count); ++ + // Registers used as temps (S0, S1, S2, S3 are save-on-entry) + const Register copied_oop = S0; // actual oop copied + const Register count_save = S1; // orig elementscount @@ -48194,12 +54156,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + // Empty array: Nothing to do. + __ beqz(count, L_done); + -+ __ addi_d(SP, SP, -6 * wordSize); -+ __ st_d(S0, SP, 0 * wordSize); -+ __ st_d(S1, SP, 1 * wordSize); -+ __ st_d(S2, SP, 2 * wordSize); -+ __ st_d(S3, SP, 3 * wordSize); -+ __ st_d(S4, SP, 4 * wordSize); ++ __ push(RegSet::of(S0, S1, S2, S3, RA)); + +#ifdef ASSERT + __ block_comment("assert consistent ckoff/ckval"); @@ -48220,20 +54177,8 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + decorators |= IS_DEST_UNINITIALIZED; + } + -+ __ move(S0, A0); -+ __ move(S1, A1); -+ __ move(S2, A2); -+ __ move(S3, A3); -+ __ move(S4, A4); -+ + BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler(); -+ bs->arraycopy_prologue(_masm, decorators, is_oop, to, count); -+ -+ __ move(A0, S0); -+ __ move(A1, S1); -+ __ move(A2, S2); -+ __ move(A3, S3); -+ __ move(A4, S4); ++ bs->arraycopy_prologue(_masm, decorators, is_oop, to, count, wb_pre_saved_regs); + + // save the original count + __ move(count_save, count); @@ -48278,19 +54223,10 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + + __ bind(L_do_card_marks); + -+ __ move(S0, count); -+ -+ bs->arraycopy_epilogue(_masm, decorators, is_oop, start_to, count_save, tmp2); -+ -+ __ move(count, S0); ++ bs->arraycopy_epilogue(_masm, decorators, is_oop, start_to, count_save, tmp2, wb_post_saved_regs); + + __ bind(L_done_pop); -+ __ ld_d(S0, SP, 0 * wordSize); -+ __ ld_d(S1, SP, 1 * wordSize); -+ __ ld_d(S2, SP, 2 * wordSize); -+ __ ld_d(S3, SP, 3 * wordSize); -+ __ ld_d(S4, SP, 4 * wordSize); -+ __ addi_d(SP, SP, 6 * wordSize); ++ __ pop(RegSet::of(S0, S1, S2, S3, RA)); + +#ifndef PRODUCT + __ li(SCR2, (address)&SharedRuntime::_checkcast_array_copy_ctr); @@ -50546,10 +56482,6 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + generate_arraycopy_stubs(); +#endif + -+ if (UseMulAddIntrinsic) { -+ StubRoutines::_mulAdd = generate_mulAdd(); -+ } -+ + if (UseLSX && vmIntrinsics::is_intrinsic_available(vmIntrinsics::_dsin)) { + StubRoutines::_dsin = generate_dsin_dcos(/* isCos = */ false); + } @@ -50566,6 +56498,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + &StubRoutines::_safefetchN_fault_pc, + &StubRoutines::_safefetchN_continuation_pc); + ++#ifdef COMPILER2 ++ if (UseMulAddIntrinsic) { ++ StubRoutines::_mulAdd = generate_mulAdd(); ++ } ++ + if (UseMontgomeryMultiplyIntrinsic) { + StubCodeMark mark(this, "StubRoutines", "montgomeryMultiply"); + MontgomeryMultiplyGenerator g(_masm, false /* squaring */); @@ -50579,6 +56516,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + // because it's faster for the sizes of modulus we care about. + StubRoutines::_montgomerySquare = g.generate_multiply(); + } ++#endif + + if (UseAESIntrinsics) { + StubRoutines::_aescrypt_encryptBlock = generate_aescrypt_encryptBlock(false); @@ -50609,9 +56547,84 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ +void StubGenerator_generate(CodeBuffer* code, bool all) { + StubGenerator g(code, all); +} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/stubRoutines_loongarch_64.cpp jdk11u-ls/src/hotspot/cpu/loongarch/stubRoutines_loongarch_64.cpp ---- openjdk/src/hotspot/cpu/loongarch/stubRoutines_loongarch_64.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/stubRoutines_loongarch_64.cpp 2023-09-12 13:54:23.093571662 +0800 +diff --git a/src/hotspot/cpu/loongarch/stubRoutines_loongarch.hpp b/src/hotspot/cpu/loongarch/stubRoutines_loongarch.hpp +new file mode 100644 +index 000000000..0ab07e1e9 +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/stubRoutines_loongarch.hpp +@@ -0,0 +1,67 @@ ++/* ++ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2015, 2022, Loongson Technology. 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 CPU_LOONGARCH_STUBROUTINES_LOONGARCH_64_HPP ++#define CPU_LOONGARCH_STUBROUTINES_LOONGARCH_64_HPP ++ ++// This file holds the platform specific parts of the StubRoutines ++// definition. See stubRoutines.hpp for a description on how to ++// extend it. ++ ++static bool returns_to_call_stub(address return_pc){ ++ return return_pc == _call_stub_return_address||return_pc == la::get_call_stub_compiled_return(); ++} ++ ++enum platform_dependent_constants { ++ code_size1 = 20000, // simply increase if too small (assembler will crash if too small) ++ code_size2 = 60000 // simply increase if too small (assembler will crash if too small) ++}; ++ ++class la { ++ friend class StubGenerator; ++ friend class VMStructs; ++ private: ++ // If we call compiled code directly from the call stub we will ++ // need to adjust the return back to the call stub to a specialized ++ // piece of code that can handle compiled results and cleaning the fpu ++ // stack. The variable holds that location. ++ static address _call_stub_compiled_return; ++ static juint _crc_table[]; ++ // begin trigonometric tables block. See comments in .cpp file ++ static juint _npio2_hw[]; ++ static jdouble _two_over_pi[]; ++ static jdouble _pio2[]; ++ static jdouble _dsin_coef[]; ++ static jdouble _dcos_coef[]; ++ // end trigonometric tables block ++ ++public: ++ // Call back points for traps in compiled code ++ static address get_call_stub_compiled_return() { return _call_stub_compiled_return; } ++ static void set_call_stub_compiled_return(address ret){ _call_stub_compiled_return = ret; } ++ ++}; ++ ++#endif // CPU_LOONGARCH_STUBROUTINES_LOONGARCH_64_HPP +diff --git a/src/hotspot/cpu/loongarch/stubRoutines_loongarch_64.cpp b/src/hotspot/cpu/loongarch/stubRoutines_loongarch_64.cpp +new file mode 100644 +index 000000000..1a6ea3bcd +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/stubRoutines_loongarch_64.cpp @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. @@ -50791,81 +56804,12 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + 2.73370053816464559624e-44, // 0x36E3822280000000 + 2.16741683877804819444e-51, // 0x3569F31D00000000 +}; -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/stubRoutines_loongarch.hpp jdk11u-ls/src/hotspot/cpu/loongarch/stubRoutines_loongarch.hpp ---- openjdk/src/hotspot/cpu/loongarch/stubRoutines_loongarch.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/stubRoutines_loongarch.hpp 2023-09-12 13:54:23.093571662 +0800 -@@ -0,0 +1,67 @@ -+/* -+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2022, Loongson Technology. 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 CPU_LOONGARCH_STUBROUTINES_LOONGARCH_64_HPP -+#define CPU_LOONGARCH_STUBROUTINES_LOONGARCH_64_HPP -+ -+// This file holds the platform specific parts of the StubRoutines -+// definition. See stubRoutines.hpp for a description on how to -+// extend it. -+ -+static bool returns_to_call_stub(address return_pc){ -+ return return_pc == _call_stub_return_address||return_pc == la::get_call_stub_compiled_return(); -+} -+ -+enum platform_dependent_constants { -+ code_size1 = 20000, // simply increase if too small (assembler will crash if too small) -+ code_size2 = 60000 // simply increase if too small (assembler will crash if too small) -+}; -+ -+class la { -+ friend class StubGenerator; -+ friend class VMStructs; -+ private: -+ // If we call compiled code directly from the call stub we will -+ // need to adjust the return back to the call stub to a specialized -+ // piece of code that can handle compiled results and cleaning the fpu -+ // stack. The variable holds that location. -+ static address _call_stub_compiled_return; -+ static juint _crc_table[]; -+ // begin trigonometric tables block. See comments in .cpp file -+ static juint _npio2_hw[]; -+ static jdouble _two_over_pi[]; -+ static jdouble _pio2[]; -+ static jdouble _dsin_coef[]; -+ static jdouble _dcos_coef[]; -+ // end trigonometric tables block -+ -+public: -+ // Call back points for traps in compiled code -+ static address get_call_stub_compiled_return() { return _call_stub_compiled_return; } -+ static void set_call_stub_compiled_return(address ret){ _call_stub_compiled_return = ret; } -+ -+}; -+ -+#endif // CPU_LOONGARCH_STUBROUTINES_LOONGARCH_64_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/templateInterpreterGenerator_loongarch.cpp jdk11u-ls/src/hotspot/cpu/loongarch/templateInterpreterGenerator_loongarch.cpp ---- openjdk/src/hotspot/cpu/loongarch/templateInterpreterGenerator_loongarch.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/templateInterpreterGenerator_loongarch.cpp 2023-11-01 09:34:25.489945263 +0800 -@@ -0,0 +1,2223 @@ +diff --git a/src/hotspot/cpu/loongarch/templateInterpreterGenerator_loongarch.cpp b/src/hotspot/cpu/loongarch/templateInterpreterGenerator_loongarch.cpp +new file mode 100644 +index 000000000..be1d28d4b +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/templateInterpreterGenerator_loongarch.cpp +@@ -0,0 +1,2269 @@ +/* + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, Loongson Technology. All rights reserved. @@ -50893,9 +56837,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + +#include "precompiled.hpp" +#include "asm/macroAssembler.hpp" ++#include "gc/shared/barrierSetAssembler.hpp" +#include "interpreter/bytecodeHistogram.hpp" +#include "interpreter/interpreter.hpp" +#include "interpreter/interpreterRuntime.hpp" ++#include "interpreter/interp_masm.hpp" +#include "interpreter/templateInterpreterGenerator.hpp" +#include "interpreter/templateTable.hpp" +#include "oops/arrayOop.hpp" @@ -51875,10 +57821,54 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + +// Method entry for java.lang.ref.Reference.get. +address TemplateInterpreterGenerator::generate_Reference_get_entry(void) { ++ // Code: _aload_0, _getfield, _areturn ++ // parameter size = 1 ++ // ++ // The code that gets generated by this routine is split into 2 parts: ++ // 1. The "intrinsified" code for G1 (or any SATB based GC), ++ // 2. The slow path - which is an expansion of the regular method entry. ++ // ++ // Notes:- ++ // * In the G1 code we do not check whether we need to block for ++ // a safepoint. If G1 is enabled then we must execute the specialized ++ // code for Reference.get (except when the Reference object is null) ++ // so that we can log the value in the referent field with an SATB ++ // update buffer. ++ // If the code for the getfield template is modified so that the ++ // G1 pre-barrier code is executed when the current method is ++ // Reference.get() then going through the normal method entry ++ // will be fine. ++ // * The G1 code can, however, check the receiver object (the instance ++ // of java.lang.Reference) and jump to the slow path if null. If the ++ // Reference object is null then we obviously cannot fetch the referent ++ // and so we don't need to call the G1 pre-barrier. Thus we can use the ++ // regular method entry code to generate the NPE. ++ // ++ // This code is based on generate_accessor_entry. ++ // ++ // Rmethod: Method* ++ // Rsender: senderSP must preserve for slow path, set SP to it on fast path ++ // RA is live. It must be saved around calls. + + address entry = __ pc(); ++ ++ const int referent_offset = java_lang_ref_Reference::referent_offset; ++ + Label slow_path; -+ __ b(slow_path); ++ const Register local_0 = A0; ++ // Check if local 0 != NULL ++ // If the receiver is null then it is OK to jump to the slow path. ++ __ ld_d(local_0, Address(SP, 0)); ++ __ beqz(local_0, slow_path); ++ ++ // Load the value of the referent field. ++ const Address field_address(local_0, referent_offset); ++ BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler(); ++ bs->load_at(_masm, IN_HEAP | ON_WEAK_OOP_REF, T_OBJECT, local_0, field_address, /*tmp1*/ T4, /*tmp2*/ noreg); ++ ++ // areturn ++ __ move(SP, Rsender); ++ __ jr(RA); + + // generate a vanilla interpreter entry as the slow path + __ bind(slow_path); @@ -53089,13 +59079,64 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + __ bind(L); +} +#endif // !PRODUCT -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/templateTable_loongarch_64.cpp jdk11u-ls/src/hotspot/cpu/loongarch/templateTable_loongarch_64.cpp ---- openjdk/src/hotspot/cpu/loongarch/templateTable_loongarch_64.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/templateTable_loongarch_64.cpp 2023-11-01 09:34:25.489945263 +0800 -@@ -0,0 +1,4145 @@ +diff --git a/src/hotspot/cpu/loongarch/templateTable_loongarch.hpp b/src/hotspot/cpu/loongarch/templateTable_loongarch.hpp +new file mode 100644 +index 000000000..ddb38faf4 +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/templateTable_loongarch.hpp +@@ -0,0 +1,43 @@ ++/* ++ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2015, 2022, Loongson Technology. 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 CPU_LOONGARCH_TEMPLATETABLE_LOONGARCH_64_HPP ++#define CPU_LOONGARCH_TEMPLATETABLE_LOONGARCH_64_HPP ++ ++ static void prepare_invoke(int byte_no, ++ Register method, // linked method (or i-klass) ++ Register index = noreg, // itable index, MethodType, etc. ++ Register recv = noreg, // if caller wants to see it ++ Register flags = noreg // if caller wants to test it ++ ); ++ static void invokevirtual_helper(Register index, Register recv, ++ Register flags); ++ static void volatile_barrier(); ++ ++ // Helpers ++ static void index_check(Register array, Register index); ++ static void index_check_without_pop(Register array, Register index); ++ ++#endif // CPU_LOONGARCH_TEMPLATETABLE_LOONGARCH_64_HPP +diff --git a/src/hotspot/cpu/loongarch/templateTable_loongarch_64.cpp b/src/hotspot/cpu/loongarch/templateTable_loongarch_64.cpp +new file mode 100644 +index 000000000..673032218 +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/templateTable_loongarch_64.cpp +@@ -0,0 +1,4113 @@ +/* + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2021, Loongson Technology. All rights reserved. ++ * Copyright (c) 2015, 2022, Loongson Technology. 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 @@ -53122,12 +59163,14 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ +#include "asm/macroAssembler.hpp" +#include "interpreter/interpreter.hpp" +#include "interpreter/interpreterRuntime.hpp" ++#include "interpreter/interp_masm.hpp" +#include "interpreter/templateTable.hpp" +#include "memory/universe.hpp" +#include "oops/methodData.hpp" +#include "oops/objArrayKlass.hpp" +#include "oops/oop.inline.hpp" +#include "prims/methodHandles.hpp" ++#include "runtime/frame.inline.hpp" +#include "runtime/sharedRuntime.hpp" +#include "runtime/stubRoutines.hpp" +#include "runtime/synchronizer.hpp" @@ -55335,38 +61378,6 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + __ jr(T4); +} + -+// ---------------------------------------------------------------------------- -+// Volatile variables demand their effects be made known to all CPU's -+// in order. Store buffers on most chips allow reads & writes to -+// reorder; the JMM's ReadAfterWrite.java test fails in -Xint mode -+// without some kind of memory barrier (i.e., it's not sufficient that -+// the interpreter does not reorder volatile references, the hardware -+// also must not reorder them). -+// -+// According to the new Java Memory Model (JMM): -+// (1) All volatiles are serialized wrt to each other. ALSO reads & -+// writes act as aquire & release, so: -+// (2) A read cannot let unrelated NON-volatile memory refs that -+// happen after the read float up to before the read. It's OK for -+// non-volatile memory refs that happen before the volatile read to -+// float down below it. -+// (3) Similar a volatile write cannot let unrelated NON-volatile -+// memory refs that happen BEFORE the write float down to after the -+// write. It's OK for non-volatile memory refs that happen after the -+// volatile write to float up before it. -+// -+// We only put in barriers around volatile refs (they are expensive), -+// not _between_ memory refs (that would require us to track the -+// flavor of the previous memory refs). Requirements (2) and (3) -+// require some barriers before volatile stores and after volatile -+// loads. These nearly cover requirement (1) but miss the -+// volatile-store-volatile-load case. This final case is placed after -+// volatile-stores although it could just as well go before -+// volatile-loads. -+void TemplateTable::volatile_barrier() { -+ if(os::is_MP()) __ membar(__ StoreLoad); -+} -+ +// we dont shift left 2 bits in get_cache_and_index_at_bcp +// for we always need shift the index we use it. the ConstantPoolCacheEntry +// is 16-byte long, index is the index in @@ -55562,7 +61573,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + + Label notVolatile; + __ beq(scratch, R0, notVolatile); -+ volatile_barrier(); ++ __ membar(MacroAssembler::AnyAny); + __ bind(notVolatile); + } + @@ -55708,7 +61719,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + { + Label notVolatile; + __ beq(scratch, R0, notVolatile); -+ volatile_barrier(); ++ __ membar(Assembler::Membar_mask_bits(__ LoadLoad | __ LoadStore)); + __ bind(notVolatile); + } +} @@ -55824,7 +61835,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + + Label notVolatile; + __ beq(scratch, R0, notVolatile); -+ volatile_barrier(); ++ __ membar(Assembler::Membar_mask_bits(__ StoreStore | __ LoadStore)); + __ bind(notVolatile); + } + @@ -55996,7 +62007,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + { + Label notVolatile; + __ beq(scratch, R0, notVolatile); -+ volatile_barrier(); ++ __ membar(Assembler::Membar_mask_bits(__ StoreLoad | __ StoreStore)); + __ bind(notVolatile); + } +} @@ -56105,7 +62116,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + + Label notVolatile; + __ beq(scratch, R0, notVolatile); -+ volatile_barrier(); ++ __ membar(Assembler::Membar_mask_bits(__ StoreStore | __ LoadStore)); + __ bind(notVolatile); + } + @@ -56154,7 +62165,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + { + Label notVolatile; + __ beq(scratch, R0, notVolatile); -+ volatile_barrier(); ++ __ membar(Assembler::Membar_mask_bits(__ StoreLoad | __ StoreStore)); + __ bind(notVolatile); + } +} @@ -56205,7 +62216,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + + Label notVolatile; + __ beq(scratch, R0, notVolatile); -+ volatile_barrier(); ++ __ membar(MacroAssembler::AnyAny); + __ bind(notVolatile); + } + @@ -56249,7 +62260,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + { + Label notVolatile; + __ beq(scratch, R0, notVolatile); -+ volatile_barrier(); ++ __ membar(Assembler::Membar_mask_bits(__ LoadLoad | __ LoadStore)); + __ bind(notVolatile); + } +} @@ -56279,7 +62290,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + + Label notVolatile; + __ beq(scratch, R0, notVolatile); -+ volatile_barrier(); ++ __ membar(MacroAssembler::AnyAny); + __ bind(notVolatile); + } + @@ -56304,7 +62315,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + { + Label notVolatile; + __ beq(scratch, R0, notVolatile); -+ volatile_barrier(); ++ __ membar(Assembler::Membar_mask_bits(__ LoadLoad | __ LoadStore)); + __ bind(notVolatile); + } +} @@ -56636,7 +62647,6 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + + __ bind(no_such_method); + // throw exception -+ __ pop(Rmethod); // pop return address (pushed by prepare_invoke) + __ restore_bcp(); + __ restore_locals(); + // Pass arguments for generating a verbose error message. @@ -56650,7 +62660,6 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + + __ bind(no_such_interface); + // throw exception -+ __ pop(Rmethod); // pop return address (pushed by prepare_invoke) + __ restore_bcp(); + __ restore_locals(); + // Pass arguments for generating a verbose error message. @@ -57238,12 +63247,14 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + __ membar(__ AnyAny);//no membar here for aarch64 +} +#endif // !CC_INTERP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/templateTable_loongarch.hpp jdk11u-ls/src/hotspot/cpu/loongarch/templateTable_loongarch.hpp ---- openjdk/src/hotspot/cpu/loongarch/templateTable_loongarch.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/templateTable_loongarch.hpp 2023-09-12 13:54:23.093571662 +0800 -@@ -0,0 +1,43 @@ +diff --git a/src/hotspot/cpu/loongarch/vmStructs_loongarch.hpp b/src/hotspot/cpu/loongarch/vmStructs_loongarch.hpp +new file mode 100644 +index 000000000..5b9f7b789 +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/vmStructs_loongarch.hpp +@@ -0,0 +1,61 @@ +/* -+ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, Loongson Technology. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * @@ -57267,88 +63278,51 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + * + */ + -+#ifndef CPU_LOONGARCH_TEMPLATETABLE_LOONGARCH_64_HPP -+#define CPU_LOONGARCH_TEMPLATETABLE_LOONGARCH_64_HPP ++#ifndef CPU_LOONGARCH_VMSTRUCTS_LOONGARCH_HPP ++#define CPU_LOONGARCH_VMSTRUCTS_LOONGARCH_HPP + -+ static void prepare_invoke(int byte_no, -+ Register method, // linked method (or i-klass) -+ Register index = noreg, // itable index, MethodType, etc. -+ Register recv = noreg, // if caller wants to see it -+ Register flags = noreg // if caller wants to test it -+ ); -+ static void invokevirtual_helper(Register index, Register recv, -+ Register flags); -+ static void volatile_barrier(); ++// These are the CPU-specific fields, types and integer ++// constants required by the Serviceability Agent. This file is ++// referenced by vmStructs.cpp. + -+ // Helpers -+ static void index_check(Register array, Register index); -+ static void index_check_without_pop(Register array, Register index); ++#define VM_STRUCTS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) \ ++ volatile_nonstatic_field(JavaFrameAnchor, _last_Java_fp, intptr_t*) \ ++ \ + -+#endif // CPU_LOONGARCH_TEMPLATETABLE_LOONGARCH_64_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/vmreg_loongarch.cpp jdk11u-ls/src/hotspot/cpu/loongarch/vmreg_loongarch.cpp ---- openjdk/src/hotspot/cpu/loongarch/vmreg_loongarch.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/vmreg_loongarch.cpp 2023-09-12 13:54:23.093571662 +0800 -@@ -0,0 +1,53 @@ -+/* -+ * Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2022, Loongson Technology. 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. -+ * -+ */ ++ /* NOTE that we do not use the last_entry() macro here; it is used */ ++ /* in vmStructs__.hpp's VM_STRUCTS_OS_CPU macro (and must */ ++ /* be present there) */ + -+#include "precompiled.hpp" -+#include "asm/assembler.hpp" -+#include "code/vmreg.hpp" + ++#define VM_TYPES_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) \ ++ ++ /* NOTE that we do not use the last_entry() macro here; it is used */ ++ /* in vmStructs__.hpp's VM_TYPES_OS_CPU macro (and must */ ++ /* be present there) */ + + -+void VMRegImpl::set_regName() { -+ Register reg = ::as_Register(0); -+ int i; -+ for (i = 0; i < ConcreteRegisterImpl::max_gpr ; ) { -+ for (int j = 0 ; j < RegisterImpl::max_slots_per_register ; j++) { -+ regName[i++] = reg->name(); -+ } -+ reg = reg->successor(); -+ } ++#define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) \ + -+ FloatRegister freg = ::as_FloatRegister(0); -+ for ( ; i < ConcreteRegisterImpl::max_fpr ; ) { -+ for (int j = 0 ; j < FloatRegisterImpl::max_slots_per_register ; j++) { -+ regName[i++] = freg->name(); -+ } -+ freg = freg->successor(); -+ } ++ /* NOTE that we do not use the last_entry() macro here; it is used */ ++ /* in vmStructs__.hpp's VM_INT_CONSTANTS_OS_CPU macro (and must */ ++ /* be present there) */ + -+ for ( ; i < ConcreteRegisterImpl::number_of_registers ; i ++ ) { -+ regName[i] = "NON-GPR-FPR"; -+ } -+} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/vmreg_loongarch.hpp jdk11u-ls/src/hotspot/cpu/loongarch/vmreg_loongarch.hpp ---- openjdk/src/hotspot/cpu/loongarch/vmreg_loongarch.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/vmreg_loongarch.hpp 2023-09-12 13:54:23.093571662 +0800 -@@ -0,0 +1,58 @@ ++#define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) \ ++ ++ /* NOTE that we do not use the last_entry() macro here; it is used */ ++ /* in vmStructs__.hpp's VM_LONG_CONSTANTS_OS_CPU macro (and must */ ++ /* be present there) */ ++ ++#endif // CPU_LOONGARCH_VMSTRUCTS_LOONGARCH_HPP +diff --git a/src/hotspot/cpu/loongarch/vm_version_ext_loongarch.cpp b/src/hotspot/cpu/loongarch/vm_version_ext_loongarch.cpp +new file mode 100644 +index 000000000..eb8f075c7 +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/vm_version_ext_loongarch.cpp +@@ -0,0 +1,85 @@ +/* -+ * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2022, Loongson Technology. All rights reserved. ++ * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2018, Loongson Technology. 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 @@ -57371,89 +63345,75 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + * + */ + -+#ifndef CPU_LOONGARCH_VMREG_LOONGARCH_HPP -+#define CPU_LOONGARCH_VMREG_LOONGARCH_HPP ++#include "memory/allocation.inline.hpp" ++#include "runtime/os.inline.hpp" ++#include "vm_version_ext_loongarch.hpp" + -+inline bool is_Register() { -+ return (unsigned int) value() < (unsigned int) ConcreteRegisterImpl::max_gpr; -+} ++// VM_Version_Ext statics ++int VM_Version_Ext::_no_of_threads = 0; ++int VM_Version_Ext::_no_of_cores = 0; ++int VM_Version_Ext::_no_of_sockets = 0; ++bool VM_Version_Ext::_initialized = false; ++char VM_Version_Ext::_cpu_name[CPU_TYPE_DESC_BUF_SIZE] = {0}; ++char VM_Version_Ext::_cpu_desc[CPU_DETAILED_DESC_BUF_SIZE] = {0}; + -+inline Register as_Register() { -+ assert( is_Register(), "must be"); -+ return ::as_Register(value() / RegisterImpl::max_slots_per_register); -+} ++void VM_Version_Ext::initialize_cpu_information(void) { ++ // do nothing if cpu info has been initialized ++ if (_initialized) { ++ return; ++ } + -+inline bool is_FloatRegister() { -+ return value() >= ConcreteRegisterImpl::max_gpr && value() < ConcreteRegisterImpl::max_fpr; ++ _no_of_cores = os::processor_count(); ++ _no_of_threads = _no_of_cores; ++ _no_of_sockets = _no_of_cores; ++ snprintf(_cpu_name, CPU_TYPE_DESC_BUF_SIZE - 1, "LoongArch"); ++ snprintf(_cpu_desc, CPU_DETAILED_DESC_BUF_SIZE, "LoongArch %s", cpu_features()); ++ _initialized = true; +} + -+inline FloatRegister as_FloatRegister() { -+ assert( is_FloatRegister() && is_even(value()), "must be" ); -+ return ::as_FloatRegister((value() - ConcreteRegisterImpl::max_gpr) / -+ FloatRegisterImpl::max_slots_per_register); ++int VM_Version_Ext::number_of_threads(void) { ++ initialize_cpu_information(); ++ return _no_of_threads; +} + -+inline bool is_concrete() { -+ assert(is_reg(), "must be"); -+ if (is_FloatRegister()) { -+ int base = value() - ConcreteRegisterImpl::max_gpr; -+ return base % FloatRegisterImpl::max_slots_per_register == 0; -+ } else { -+ return is_even(value()); -+ } ++int VM_Version_Ext::number_of_cores(void) { ++ initialize_cpu_information(); ++ return _no_of_cores; +} + -+#endif // CPU_LOONGARCH_VMREG_LOONGARCH_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/vmreg_loongarch.inline.hpp jdk11u-ls/src/hotspot/cpu/loongarch/vmreg_loongarch.inline.hpp ---- openjdk/src/hotspot/cpu/loongarch/vmreg_loongarch.inline.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/vmreg_loongarch.inline.hpp 2023-09-12 13:54:23.093571662 +0800 -@@ -0,0 +1,39 @@ -+/* -+ * Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2022, Loongson Technology. 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 CPU_LOONGARCH_VMREG_LOONGARCH_INLINE_HPP -+#define CPU_LOONGARCH_VMREG_LOONGARCH_INLINE_HPP -+ -+inline VMReg RegisterImpl::as_VMReg() { -+ if( this==noreg ) return VMRegImpl::Bad(); -+ return VMRegImpl::as_VMReg(encoding() * RegisterImpl::max_slots_per_register); ++int VM_Version_Ext::number_of_sockets(void) { ++ initialize_cpu_information(); ++ return _no_of_sockets; +} + -+inline VMReg FloatRegisterImpl::as_VMReg() { -+ return VMRegImpl::as_VMReg((encoding() * FloatRegisterImpl::max_slots_per_register) + -+ ConcreteRegisterImpl::max_gpr); ++const char* VM_Version_Ext::cpu_name(void) { ++ initialize_cpu_information(); ++ char* tmp = NEW_C_HEAP_ARRAY_RETURN_NULL(char, CPU_TYPE_DESC_BUF_SIZE, mtTracing); ++ if (NULL == tmp) { ++ return NULL; ++ } ++ strncpy(tmp, _cpu_name, CPU_TYPE_DESC_BUF_SIZE); ++ return tmp; +} + -+#endif // CPU_LOONGARCH_VMREG_LOONGARCH_INLINE_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/vmStructs_loongarch.hpp jdk11u-ls/src/hotspot/cpu/loongarch/vmStructs_loongarch.hpp ---- openjdk/src/hotspot/cpu/loongarch/vmStructs_loongarch.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/vmStructs_loongarch.hpp 2023-09-12 13:54:23.093571662 +0800 -@@ -0,0 +1,61 @@ ++const char* VM_Version_Ext::cpu_description(void) { ++ initialize_cpu_information(); ++ char* tmp = NEW_C_HEAP_ARRAY_RETURN_NULL(char, CPU_DETAILED_DESC_BUF_SIZE, mtTracing); ++ if (NULL == tmp) { ++ return NULL; ++ } ++ strncpy(tmp, _cpu_desc, CPU_DETAILED_DESC_BUF_SIZE); ++ return tmp; ++} +diff --git a/src/hotspot/cpu/loongarch/vm_version_ext_loongarch.hpp b/src/hotspot/cpu/loongarch/vm_version_ext_loongarch.hpp +new file mode 100644 +index 000000000..1a9312313 +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/vm_version_ext_loongarch.hpp +@@ -0,0 +1,54 @@ +/* -+ * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2022, Loongson Technology. All rights reserved. ++ * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2018, 2022, Loongson Technology. 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 @@ -57476,196 +63436,44 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + * + */ + -+#ifndef CPU_LOONGARCH_VMSTRUCTS_LOONGARCH_HPP -+#define CPU_LOONGARCH_VMSTRUCTS_LOONGARCH_HPP -+ -+// These are the CPU-specific fields, types and integer -+// constants required by the Serviceability Agent. This file is -+// referenced by vmStructs.cpp. -+ -+#define VM_STRUCTS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) \ -+ volatile_nonstatic_field(JavaFrameAnchor, _last_Java_fp, intptr_t*) \ -+ \ -+ -+ /* NOTE that we do not use the last_entry() macro here; it is used */ -+ /* in vmStructs__.hpp's VM_STRUCTS_OS_CPU macro (and must */ -+ /* be present there) */ -+ -+ -+#define VM_TYPES_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) \ -+ -+ /* NOTE that we do not use the last_entry() macro here; it is used */ -+ /* in vmStructs__.hpp's VM_TYPES_OS_CPU macro (and must */ -+ /* be present there) */ ++#ifndef CPU_LOONGARCH_VM_VERSION_EXT_LOONGARCH_HPP ++#define CPU_LOONGARCH_VM_VERSION_EXT_LOONGARCH_HPP + ++#include "runtime/vm_version.hpp" ++#include "utilities/macros.hpp" + -+#define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) \ ++class VM_Version_Ext : public VM_Version { ++ private: ++ static const size_t CPU_TYPE_DESC_BUF_SIZE = 256; ++ static const size_t CPU_DETAILED_DESC_BUF_SIZE = 4096; + -+ /* NOTE that we do not use the last_entry() macro here; it is used */ -+ /* in vmStructs__.hpp's VM_INT_CONSTANTS_OS_CPU macro (and must */ -+ /* be present there) */ ++ static int _no_of_threads; ++ static int _no_of_cores; ++ static int _no_of_sockets; ++ static bool _initialized; ++ static char _cpu_name[CPU_TYPE_DESC_BUF_SIZE]; ++ static char _cpu_desc[CPU_DETAILED_DESC_BUF_SIZE]; + -+#define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) \ ++ public: ++ static int number_of_threads(void); ++ static int number_of_cores(void); ++ static int number_of_sockets(void); + -+ /* NOTE that we do not use the last_entry() macro here; it is used */ -+ /* in vmStructs__.hpp's VM_LONG_CONSTANTS_OS_CPU macro (and must */ -+ /* be present there) */ ++ static const char* cpu_name(void); ++ static const char* cpu_description(void); ++ static void initialize_cpu_information(void); ++}; + -+#endif // CPU_LOONGARCH_VMSTRUCTS_LOONGARCH_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/vm_version_ext_loongarch.cpp jdk11u-ls/src/hotspot/cpu/loongarch/vm_version_ext_loongarch.cpp ---- openjdk/src/hotspot/cpu/loongarch/vm_version_ext_loongarch.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/vm_version_ext_loongarch.cpp 2023-09-12 13:54:23.093571662 +0800 -@@ -0,0 +1,85 @@ ++#endif // CPU_LOONGARCH_VM_VERSION_EXT_LOONGARCH_HPP +diff --git a/src/hotspot/cpu/loongarch/vm_version_loongarch.cpp b/src/hotspot/cpu/loongarch/vm_version_loongarch.cpp +new file mode 100644 +index 000000000..58808deec +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/vm_version_loongarch.cpp +@@ -0,0 +1,410 @@ +/* -+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2018, Loongson Technology. 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 "memory/allocation.inline.hpp" -+#include "runtime/os.inline.hpp" -+#include "vm_version_ext_loongarch.hpp" -+ -+// VM_Version_Ext statics -+int VM_Version_Ext::_no_of_threads = 0; -+int VM_Version_Ext::_no_of_cores = 0; -+int VM_Version_Ext::_no_of_sockets = 0; -+bool VM_Version_Ext::_initialized = false; -+char VM_Version_Ext::_cpu_name[CPU_TYPE_DESC_BUF_SIZE] = {0}; -+char VM_Version_Ext::_cpu_desc[CPU_DETAILED_DESC_BUF_SIZE] = {0}; -+ -+void VM_Version_Ext::initialize_cpu_information(void) { -+ // do nothing if cpu info has been initialized -+ if (_initialized) { -+ return; -+ } -+ -+ _no_of_cores = os::processor_count(); -+ _no_of_threads = _no_of_cores; -+ _no_of_sockets = _no_of_cores; -+ snprintf(_cpu_name, CPU_TYPE_DESC_BUF_SIZE - 1, "LoongArch"); -+ snprintf(_cpu_desc, CPU_DETAILED_DESC_BUF_SIZE, "LoongArch %s", cpu_features()); -+ _initialized = true; -+} -+ -+int VM_Version_Ext::number_of_threads(void) { -+ initialize_cpu_information(); -+ return _no_of_threads; -+} -+ -+int VM_Version_Ext::number_of_cores(void) { -+ initialize_cpu_information(); -+ return _no_of_cores; -+} -+ -+int VM_Version_Ext::number_of_sockets(void) { -+ initialize_cpu_information(); -+ return _no_of_sockets; -+} -+ -+const char* VM_Version_Ext::cpu_name(void) { -+ initialize_cpu_information(); -+ char* tmp = NEW_C_HEAP_ARRAY_RETURN_NULL(char, CPU_TYPE_DESC_BUF_SIZE, mtTracing); -+ if (NULL == tmp) { -+ return NULL; -+ } -+ strncpy(tmp, _cpu_name, CPU_TYPE_DESC_BUF_SIZE); -+ return tmp; -+} -+ -+const char* VM_Version_Ext::cpu_description(void) { -+ initialize_cpu_information(); -+ char* tmp = NEW_C_HEAP_ARRAY_RETURN_NULL(char, CPU_DETAILED_DESC_BUF_SIZE, mtTracing); -+ if (NULL == tmp) { -+ return NULL; -+ } -+ strncpy(tmp, _cpu_desc, CPU_DETAILED_DESC_BUF_SIZE); -+ return tmp; -+} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/vm_version_ext_loongarch.hpp jdk11u-ls/src/hotspot/cpu/loongarch/vm_version_ext_loongarch.hpp ---- openjdk/src/hotspot/cpu/loongarch/vm_version_ext_loongarch.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/vm_version_ext_loongarch.hpp 2023-09-12 13:54:23.093571662 +0800 -@@ -0,0 +1,54 @@ -+/* -+ * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2018, 2022, Loongson Technology. 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 CPU_LOONGARCH_VM_VERSION_EXT_LOONGARCH_HPP -+#define CPU_LOONGARCH_VM_VERSION_EXT_LOONGARCH_HPP -+ -+#include "runtime/vm_version.hpp" -+#include "utilities/macros.hpp" -+ -+class VM_Version_Ext : public VM_Version { -+ private: -+ static const size_t CPU_TYPE_DESC_BUF_SIZE = 256; -+ static const size_t CPU_DETAILED_DESC_BUF_SIZE = 4096; -+ -+ static int _no_of_threads; -+ static int _no_of_cores; -+ static int _no_of_sockets; -+ static bool _initialized; -+ static char _cpu_name[CPU_TYPE_DESC_BUF_SIZE]; -+ static char _cpu_desc[CPU_DETAILED_DESC_BUF_SIZE]; -+ -+ public: -+ static int number_of_threads(void); -+ static int number_of_cores(void); -+ static int number_of_sockets(void); -+ -+ static const char* cpu_name(void); -+ static const char* cpu_description(void); -+ static void initialize_cpu_information(void); -+}; -+ -+#endif // CPU_LOONGARCH_VM_VERSION_EXT_LOONGARCH_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/vm_version_loongarch.cpp jdk11u-ls/src/hotspot/cpu/loongarch/vm_version_loongarch.cpp ---- openjdk/src/hotspot/cpu/loongarch/vm_version_loongarch.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/vm_version_loongarch.cpp 2023-11-01 09:34:25.493945267 +0800 -@@ -0,0 +1,412 @@ -+/* -+ * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2021, Loongson Technology. All rights reserved. ++ * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2015, 2021, Loongson Technology. 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 @@ -57695,13 +63503,13 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ +#include "runtime/java.hpp" +#include "runtime/stubCodeGenerator.hpp" +#include "runtime/vm_version.hpp" ++#include "os_linux.hpp" +#ifdef TARGET_OS_FAMILY_linux +# include "os_linux.inline.hpp" +#endif + +#define T5 RT5 + -+int VM_Version::_cpuFeatures; +const char* VM_Version::_features_str = ""; +VM_Version::CpuidInfo VM_Version::_cpuid_info = { 0, }; +bool VM_Version::_cpu_info_is_initialized = false; @@ -57795,27 +63603,9 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + } else if (_cpuid_info.cpucfg_info_id1.bits.ARCH == 0b10 ) { + result |= CPU_LA64; + } -+ if (_cpuid_info.cpucfg_info_id1.bits.UAL != 0) -+ result |= CPU_UAL; + + if (_cpuid_info.cpucfg_info_id2.bits.FP_CFG != 0) + result |= CPU_FP; -+ if (_cpuid_info.cpucfg_info_id2.bits.LSX != 0) -+ result |= CPU_LSX; -+ if (_cpuid_info.cpucfg_info_id2.bits.LASX != 0) -+ result |= CPU_LASX; -+ if (_cpuid_info.cpucfg_info_id2.bits.COMPLEX != 0) -+ result |= CPU_COMPLEX; -+ if (_cpuid_info.cpucfg_info_id2.bits.CRYPTO != 0) -+ result |= CPU_CRYPTO; -+ if (_cpuid_info.cpucfg_info_id2.bits.LBT_X86 != 0) -+ result |= CPU_LBT_X86; -+ if (_cpuid_info.cpucfg_info_id2.bits.LBT_ARM != 0) -+ result |= CPU_LBT_ARM; -+ if (_cpuid_info.cpucfg_info_id2.bits.LBT_MIPS != 0) -+ result |= CPU_LBT_MIPS; -+ if (_cpuid_info.cpucfg_info_id2.bits.LAM != 0) -+ result |= CPU_LAM; + + if (_cpuid_info.cpucfg_info_id3.bits.CCDMA != 0) + result |= CPU_CCDMA; @@ -57835,18 +63625,20 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + + clean_cpuFeatures(); + ++ get_os_cpu_info(); ++ + get_cpu_info_stub(&_cpuid_info); -+ _cpuFeatures = get_feature_flags_by_cpucfg(); ++ _features |= get_feature_flags_by_cpucfg(); + + _supports_cx8 = true; + + if (UseG1GC && FLAG_IS_DEFAULT(MaxGCPauseMillis)) { -+ FLAG_SET_CMDLINE(uintx, MaxGCPauseMillis, 650); ++ FLAG_SET_DEFAULT(MaxGCPauseMillis, 150); + } + + if (supports_lsx()) { + if (FLAG_IS_DEFAULT(UseLSX)) { -+ //FLAG_SET_DEFAULT(UseLSX, true); ++ FLAG_SET_DEFAULT(UseLSX, true); + } + } else if (UseLSX) { + warning("LSX instructions are not available on this CPU"); @@ -57855,7 +63647,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + + if (supports_lasx()) { + if (FLAG_IS_DEFAULT(UseLASX)) { -+ //FLAG_SET_DEFAULT(UseLASX, true); ++ FLAG_SET_DEFAULT(UseLASX, true); + } + } else if (UseLASX) { + warning("LASX instructions are not available on this CPU"); @@ -58033,6 +63825,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + } + } + ++#ifdef COMPILER2 + if (FLAG_IS_DEFAULT(UseMulAddIntrinsic)) { + FLAG_SET_DEFAULT(UseMulAddIntrinsic, true); + } @@ -58043,6 +63836,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + if (FLAG_IS_DEFAULT(UseMontgomerySquareIntrinsic)) { + UseMontgomerySquareIntrinsic = true; + } ++#endif + + // This machine allows unaligned memory accesses + if (FLAG_IS_DEFAULT(UseUnalignedAccesses)) { @@ -58057,6 +63851,18 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + FLAG_SET_DEFAULT(UseCopySignIntrinsic, true); + } + ++ if (UseActiveCoresMP) { ++ if (os::Linux::sched_active_processor_count() != 1) { ++ if (!FLAG_IS_DEFAULT(UseActiveCoresMP)) ++ warning("UseActiveCoresMP disabled because active processors are more than one."); ++ FLAG_SET_DEFAULT(UseActiveCoresMP, false); ++ } ++ } else { // !UseActiveCoresMP ++ if (FLAG_IS_DEFAULT(UseActiveCoresMP) && !os::is_MP()) { ++ FLAG_SET_DEFAULT(UseActiveCoresMP, true); ++ } ++ } ++ + UNSUPPORTED_OPTION(CriticalJNINatives); +} + @@ -58075,13 +63881,15 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + + get_processor_features(); +} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/vm_version_loongarch.hpp jdk11u-ls/src/hotspot/cpu/loongarch/vm_version_loongarch.hpp ---- openjdk/src/hotspot/cpu/loongarch/vm_version_loongarch.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/vm_version_loongarch.hpp 2023-11-01 09:34:25.493945267 +0800 +diff --git a/src/hotspot/cpu/loongarch/vm_version_loongarch.hpp b/src/hotspot/cpu/loongarch/vm_version_loongarch.hpp +new file mode 100644 +index 000000000..00b8e608a +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/vm_version_loongarch.hpp @@ -0,0 +1,292 @@ +/* + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2021, Loongson Technology. All rights reserved. ++ * Copyright (c) 2015, 2023, Loongson Technology. 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 @@ -58279,30 +64087,30 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ +protected: + + enum { -+ CPU_LA32 = (1 << 1), -+ CPU_LA64 = (1 << 2), -+ CPU_LLEXC = (1 << 3), -+ CPU_SCDLY = (1 << 4), -+ CPU_LLDBAR = (1 << 5), -+ CPU_LBT_X86 = (1 << 6), -+ CPU_LBT_ARM = (1 << 7), -+ CPU_LBT_MIPS = (1 << 8), -+ CPU_CCDMA = (1 << 9), -+ CPU_COMPLEX = (1 << 10), -+ CPU_FP = (1 << 11), -+ CPU_CRYPTO = (1 << 14), -+ CPU_LSX = (1 << 15), -+ CPU_LASX = (1 << 17), -+ CPU_LAM = (1 << 21), -+ CPU_LLSYNC = (1 << 23), -+ CPU_TGTSYNC = (1 << 24), -+ CPU_ULSYNC = (1 << 25), -+ CPU_UAL = (1 << 26), ++ CPU_LAM = (1 << 1), ++ CPU_UAL = (1 << 2), ++ CPU_LSX = (1 << 4), ++ CPU_LASX = (1 << 5), ++ CPU_COMPLEX = (1 << 7), ++ CPU_CRYPTO = (1 << 8), ++ CPU_LBT_X86 = (1 << 10), ++ CPU_LBT_ARM = (1 << 11), ++ CPU_LBT_MIPS = (1 << 12), ++ // flags above must follow Linux HWCAP ++ CPU_LA32 = (1 << 13), ++ CPU_LA64 = (1 << 14), ++ CPU_FP = (1 << 15), ++ CPU_LLEXC = (1 << 16), ++ CPU_SCDLY = (1 << 17), ++ CPU_LLDBAR = (1 << 18), ++ CPU_CCDMA = (1 << 19), ++ CPU_LLSYNC = (1 << 20), ++ CPU_TGTSYNC = (1 << 21), ++ CPU_ULSYNC = (1 << 22), + + //////////////////////add some other feature here////////////////// + } cpuFeatureFlags; + -+ static int _cpuFeatures; + static const char* _features_str; + static bool _cpu_info_is_initialized; + @@ -58325,8 +64133,8 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + static CpuidInfo _cpuid_info; + + static uint32_t get_feature_flags_by_cpucfg(); -+ static int get_feature_flags_by_cpuinfo(int features); + static void get_processor_features(); ++ static void get_os_cpu_info(); + +public: + // Offsets for cpuid asm stub @@ -58343,26 +64151,26 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + static ByteSize Loongson_Cpucfg_id13_offset() { return byte_offset_of(CpuidInfo, cpucfg_info_id13); } + static ByteSize Loongson_Cpucfg_id14_offset() { return byte_offset_of(CpuidInfo, cpucfg_info_id14); } + -+ static void clean_cpuFeatures() { _cpuFeatures = 0; } ++ static void clean_cpuFeatures() { _features = 0; } + + // Initialization + static void initialize(); + + static bool cpu_info_is_initialized() { return _cpu_info_is_initialized; } + -+ static bool is_la32() { return _cpuFeatures & CPU_LA32; } -+ static bool is_la64() { return _cpuFeatures & CPU_LA64; } -+ static bool supports_crypto() { return _cpuFeatures & CPU_CRYPTO; } -+ static bool supports_lsx() { return _cpuFeatures & CPU_LSX; } -+ static bool supports_lasx() { return _cpuFeatures & CPU_LASX; } -+ static bool supports_lam() { return _cpuFeatures & CPU_LAM; } -+ static bool supports_llexc() { return _cpuFeatures & CPU_LLEXC; } -+ static bool supports_scdly() { return _cpuFeatures & CPU_SCDLY; } -+ static bool supports_lldbar() { return _cpuFeatures & CPU_LLDBAR; } -+ static bool supports_ual() { return _cpuFeatures & CPU_UAL; } -+ static bool supports_lbt_x86() { return _cpuFeatures & CPU_LBT_X86; } -+ static bool supports_lbt_arm() { return _cpuFeatures & CPU_LBT_ARM; } -+ static bool supports_lbt_mips() { return _cpuFeatures & CPU_LBT_MIPS; } ++ static bool is_la32() { return _features & CPU_LA32; } ++ static bool is_la64() { return _features & CPU_LA64; } ++ static bool supports_crypto() { return _features & CPU_CRYPTO; } ++ static bool supports_lsx() { return _features & CPU_LSX; } ++ static bool supports_lasx() { return _features & CPU_LASX; } ++ static bool supports_lam() { return _features & CPU_LAM; } ++ static bool supports_llexc() { return _features & CPU_LLEXC; } ++ static bool supports_scdly() { return _features & CPU_SCDLY; } ++ static bool supports_lldbar() { return _features & CPU_LLDBAR; } ++ static bool supports_ual() { return _features & CPU_UAL; } ++ static bool supports_lbt_x86() { return _features & CPU_LBT_X86; } ++ static bool supports_lbt_arm() { return _features & CPU_LBT_ARM; } ++ static bool supports_lbt_mips() { return _features & CPU_LBT_MIPS; } + static bool needs_llsync() { return !supports_lldbar(); } + static bool needs_tgtsync() { return 1; } + static bool needs_ulsync() { return 1; } @@ -58371,9 +64179,179 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ +}; + +#endif // CPU_LOONGARCH_VM_VERSION_LOONGARCH_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/vtableStubs_loongarch_64.cpp jdk11u-ls/src/hotspot/cpu/loongarch/vtableStubs_loongarch_64.cpp ---- openjdk/src/hotspot/cpu/loongarch/vtableStubs_loongarch_64.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/loongarch/vtableStubs_loongarch_64.cpp 2023-09-12 13:54:23.093571662 +0800 +diff --git a/src/hotspot/cpu/loongarch/vmreg_loongarch.cpp b/src/hotspot/cpu/loongarch/vmreg_loongarch.cpp +new file mode 100644 +index 000000000..43caba518 +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/vmreg_loongarch.cpp +@@ -0,0 +1,53 @@ ++/* ++ * Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2015, 2022, Loongson Technology. 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 "asm/assembler.hpp" ++#include "code/vmreg.hpp" ++ ++ ++ ++void VMRegImpl::set_regName() { ++ Register reg = ::as_Register(0); ++ int i; ++ for (i = 0; i < ConcreteRegisterImpl::max_gpr ; ) { ++ for (int j = 0 ; j < RegisterImpl::max_slots_per_register ; j++) { ++ regName[i++] = reg->name(); ++ } ++ reg = reg->successor(); ++ } ++ ++ FloatRegister freg = ::as_FloatRegister(0); ++ for ( ; i < ConcreteRegisterImpl::max_fpr ; ) { ++ for (int j = 0 ; j < FloatRegisterImpl::max_slots_per_register ; j++) { ++ regName[i++] = freg->name(); ++ } ++ freg = freg->successor(); ++ } ++ ++ for ( ; i < ConcreteRegisterImpl::number_of_registers ; i ++ ) { ++ regName[i] = "NON-GPR-FPR"; ++ } ++} +diff --git a/src/hotspot/cpu/loongarch/vmreg_loongarch.hpp b/src/hotspot/cpu/loongarch/vmreg_loongarch.hpp +new file mode 100644 +index 000000000..819eaff0b +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/vmreg_loongarch.hpp +@@ -0,0 +1,58 @@ ++/* ++ * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2015, 2022, Loongson Technology. 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 CPU_LOONGARCH_VMREG_LOONGARCH_HPP ++#define CPU_LOONGARCH_VMREG_LOONGARCH_HPP ++ ++inline bool is_Register() { ++ return (unsigned int) value() < (unsigned int) ConcreteRegisterImpl::max_gpr; ++} ++ ++inline Register as_Register() { ++ assert( is_Register(), "must be"); ++ return ::as_Register(value() / RegisterImpl::max_slots_per_register); ++} ++ ++inline bool is_FloatRegister() { ++ return value() >= ConcreteRegisterImpl::max_gpr && value() < ConcreteRegisterImpl::max_fpr; ++} ++ ++inline FloatRegister as_FloatRegister() { ++ assert( is_FloatRegister() && is_even(value()), "must be" ); ++ return ::as_FloatRegister((value() - ConcreteRegisterImpl::max_gpr) / ++ FloatRegisterImpl::max_slots_per_register); ++} ++ ++inline bool is_concrete() { ++ assert(is_reg(), "must be"); ++ if (is_FloatRegister()) { ++ int base = value() - ConcreteRegisterImpl::max_gpr; ++ return base % FloatRegisterImpl::max_slots_per_register == 0; ++ } else { ++ return is_even(value()); ++ } ++} ++ ++#endif // CPU_LOONGARCH_VMREG_LOONGARCH_HPP +diff --git a/src/hotspot/cpu/loongarch/vmreg_loongarch.inline.hpp b/src/hotspot/cpu/loongarch/vmreg_loongarch.inline.hpp +new file mode 100644 +index 000000000..edb78e36d +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/vmreg_loongarch.inline.hpp +@@ -0,0 +1,39 @@ ++/* ++ * Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2015, 2022, Loongson Technology. 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 CPU_LOONGARCH_VMREG_LOONGARCH_INLINE_HPP ++#define CPU_LOONGARCH_VMREG_LOONGARCH_INLINE_HPP ++ ++inline VMReg RegisterImpl::as_VMReg() { ++ if( this==noreg ) return VMRegImpl::Bad(); ++ return VMRegImpl::as_VMReg(encoding() * RegisterImpl::max_slots_per_register); ++} ++ ++inline VMReg FloatRegisterImpl::as_VMReg() { ++ return VMRegImpl::as_VMReg((encoding() * FloatRegisterImpl::max_slots_per_register) + ++ ConcreteRegisterImpl::max_gpr); ++} ++ ++#endif // CPU_LOONGARCH_VMREG_LOONGARCH_INLINE_HPP +diff --git a/src/hotspot/cpu/loongarch/vtableStubs_loongarch_64.cpp b/src/hotspot/cpu/loongarch/vtableStubs_loongarch_64.cpp +new file mode 100644 +index 000000000..2c4b60653 +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/vtableStubs_loongarch_64.cpp @@ -0,0 +1,322 @@ +/* + * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. @@ -58697,9 +64675,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/loongarch/ + const unsigned int icache_line_size = wordSize; + return icache_line_size; +} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/abstractInterpreter_mips.cpp jdk11u-ls/src/hotspot/cpu/mips/abstractInterpreter_mips.cpp ---- openjdk/src/hotspot/cpu/mips/abstractInterpreter_mips.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/abstractInterpreter_mips.cpp 2023-09-12 13:54:23.097571667 +0800 +diff --git a/src/hotspot/cpu/mips/abstractInterpreter_mips.cpp b/src/hotspot/cpu/mips/abstractInterpreter_mips.cpp +new file mode 100644 +index 000000000..73f021c9b +--- /dev/null ++++ b/src/hotspot/cpu/mips/abstractInterpreter_mips.cpp @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. @@ -58833,10 +64813,12 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/abstr + *interpreter_frame->interpreter_frame_mirror_addr() = method->method_holder()->java_mirror(); +} + -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/assembler_mips.cpp jdk11u-ls/src/hotspot/cpu/mips/assembler_mips.cpp ---- openjdk/src/hotspot/cpu/mips/assembler_mips.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/assembler_mips.cpp 2023-11-01 09:34:25.493945267 +0800 -@@ -0,0 +1,733 @@ +diff --git a/src/hotspot/cpu/mips/assembler_mips.cpp b/src/hotspot/cpu/mips/assembler_mips.cpp +new file mode 100644 +index 000000000..c8c7a5d4d +--- /dev/null ++++ b/src/hotspot/cpu/mips/assembler_mips.cpp +@@ -0,0 +1,759 @@ +/* + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, Loongson Technology. All rights reserved. @@ -58876,6 +64858,9 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/assem +#include "runtime/sharedRuntime.hpp" +#include "runtime/stubRoutines.hpp" +#include "utilities/macros.hpp" ++#ifndef PRODUCT ++#include "compiler/disassembler.hpp" ++#endif + +#ifdef PRODUCT +#define BLOCK_COMMENT(str) /* nothing */ @@ -59570,10 +65555,35 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/assem + emit_long((jal_op<<26) | dest); + has_delay_slot(); +} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/assembler_mips.hpp jdk11u-ls/src/hotspot/cpu/mips/assembler_mips.hpp ---- openjdk/src/hotspot/cpu/mips/assembler_mips.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/assembler_mips.hpp 2023-11-01 09:34:25.493945267 +0800 -@@ -0,0 +1,1802 @@ ++ ++void Assembler::emit_long(int x) { // shadows AbstractAssembler::emit_long ++ check_delay(); ++ AbstractAssembler::emit_int32(x); ++} ++ ++inline void Assembler::emit_data(int x) { emit_long(x); } ++inline void Assembler::emit_data(int x, relocInfo::relocType rtype) { ++ relocate(rtype); ++ emit_long(x); ++} ++ ++inline void Assembler::emit_data(int x, RelocationHolder const& rspec) { ++ relocate(rspec); ++ emit_long(x); ++} ++ ++inline void Assembler::check_delay() { ++#ifdef CHECK_DELAY ++ guarantee(delay_state != at_delay_slot, "must say delayed() when filling delay slot"); ++ delay_state = no_delay; ++#endif ++} +diff --git a/src/hotspot/cpu/mips/assembler_mips.hpp b/src/hotspot/cpu/mips/assembler_mips.hpp +new file mode 100644 +index 000000000..116f906e1 +--- /dev/null ++++ b/src/hotspot/cpu/mips/assembler_mips.hpp +@@ -0,0 +1,1789 @@ +/* + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, Loongson Technology. All rights reserved. @@ -60242,13 +66252,6 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/assem + gssdbbp_op = 0x38 + }; + -+ enum gscam_ops { -+ campv_op = 0x0, -+ campi_op = 0x1, -+ camwi_op = 0x2, -+ ramri_op = 0x3 -+ }; -+ + static const char* special2_name[]; + + // special3 family, the opcode is in low 6 bits. @@ -60273,8 +66276,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/assem + re2_op = 0x16, //MIPS DSP, re2_ops + sh2_op = 0x17, //MIPS DSP + ar3_op = 0x18, //MIPS DSP -+ bshfl_op = 0x20, //seb, seh -+ rdhwr_op = 0x3b ++ bshfl_op = 0x20 //seb, seh + }; + + // re1_ops @@ -60521,8 +66523,6 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/assem +#endif + } + -+ inline bool is_load_op(int); -+ inline void check_load_and_patch(int); +protected: + // Delay slot helpers + // cti is called when emitting control-transfer instruction, @@ -60553,11 +66553,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/assem + AbstractAssembler::flush(); + } + -+ inline void emit_long(int); // shadows AbstractAssembler::emit_long -+ inline void emit_data(int x) { emit_long(x); } -+ inline void emit_data(int, RelocationHolder const&); -+ inline void emit_data(int, relocInfo::relocType rtype); -+ inline void check_delay(); ++ void emit_long(int); // shadows AbstractAssembler::emit_long ++ void emit_data(int); ++ void emit_data(int, RelocationHolder const&); ++ void emit_data(int, relocInfo::relocType rtype); ++ void check_delay(); + + + // Generic instructions @@ -60798,7 +66798,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/assem + void swr (Register rt, Register base, int off) { emit_long(insn_ORRI(swr_op, (int)base->encoding(), (int)rt->encoding(), off)); } + void synci(Register base, int off) { emit_long(insn_ORRI(regimm_op, (int)base->encoding(), synci_op, off)); } + void sync () { -+ if (os::is_ActiveCoresMP()) ++ if (UseActiveCoresMP) + emit_long(0); + else + emit_long(sync_op); @@ -61372,14 +67372,13 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/assem + static address locate_next_instruction(address inst); +}; + -+ -+#include "assembler_mips.inline.hpp" -+ +#endif // CPU_MIPS_VM_ASSEMBLER_MIPS_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/assembler_mips.inline.hpp jdk11u-ls/src/hotspot/cpu/mips/assembler_mips.inline.hpp ---- openjdk/src/hotspot/cpu/mips/assembler_mips.inline.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/assembler_mips.inline.hpp 2023-11-01 09:34:25.493945267 +0800 -@@ -0,0 +1,227 @@ +diff --git a/src/hotspot/cpu/mips/assembler_mips.inline.hpp b/src/hotspot/cpu/mips/assembler_mips.inline.hpp +new file mode 100644 +index 000000000..f35a06fc4 +--- /dev/null ++++ b/src/hotspot/cpu/mips/assembler_mips.inline.hpp +@@ -0,0 +1,33 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2018, Loongson Technology. All rights reserved. @@ -61411,394 +67410,204 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/assem +#include "asm/assembler.inline.hpp" +#include "asm/codeBuffer.hpp" +#include "code/codeCache.hpp" -+#ifndef PRODUCT -+#include "compiler/disassembler.hpp" -+#endif + ++#endif // CPU_MIPS_VM_ASSEMBLER_MIPS_INLINE_HPP +diff --git a/src/hotspot/cpu/mips/bytes_mips.hpp b/src/hotspot/cpu/mips/bytes_mips.hpp +new file mode 100644 +index 000000000..4172db219 +--- /dev/null ++++ b/src/hotspot/cpu/mips/bytes_mips.hpp +@@ -0,0 +1,181 @@ ++/* ++ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2015, 2019, Loongson Technology. 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 CPU_MIPS_VM_BYTES_MIPS_HPP ++#define CPU_MIPS_VM_BYTES_MIPS_HPP + -+inline void Assembler::check_delay() { -+# ifdef CHECK_DELAY -+ guarantee(delay_state != at_delay_slot, "must say delayed() when filling delay slot"); -+ delay_state = no_delay; -+# endif -+} ++#include "memory/allocation.hpp" + -+inline void Assembler::emit_long(int x) { -+ check_delay(); -+ AbstractAssembler::emit_int32(x); -+ if (PatchContinuousLoad) -+ check_load_and_patch(x); -+} ++class Bytes: AllStatic { ++ public: ++ // Returns true if the byte ordering used by Java is different from the native byte ordering ++ // of the underlying machine. For example, this is true for Intel x86, but false for Solaris ++ // on Sparc. ++ // we use mipsel, so return true ++ static inline bool is_Java_byte_ordering_different(){ return true; } + -+inline void Assembler::emit_data(int x, relocInfo::relocType rtype) { -+ relocate(rtype); -+ emit_long(x); -+} + -+inline void Assembler::emit_data(int x, RelocationHolder const& rspec) { -+ relocate(rspec); -+ emit_long(x); -+} ++ // Efficient reading and writing of unaligned unsigned data in platform-specific byte ordering ++ // (no special code is needed since x86 CPUs can access unaligned data) ++ static inline u2 get_native_u2(address p) { ++ if ((intptr_t)p & 0x1) { ++ return ((u2)p[1] << 8) | (u2)p[0]; ++ } else { ++ return *(u2*)p; ++ } ++ } + -+// Check If an Instruction Is a Load Instruction -+ -+// All load instructions includes: -+// 1. FIRST OPS -+// LDL, LDR, LB, LH, LWL, LW, LBU, LHU, LWR, LWU, LD, LWC1, PREF, LDC1 -+// 2. SPECIAL OPS -+// MOVF, MOVT -+// 3. COP0 OPS -+// MFC0, DMFC0, MFGC0, DMFGC0 -+// 4. COP1 OPS -+// MFC1, DMFC1, CFC1, MFHC1, MTC1, DMTC1, CTC1, MTHC1, MOVZ.FMT, MOVN.FMT -+// 5. COP1X OPS -+// LWXC1, LDXC1, LUXC1, PREFX -+// 6. SPECIAL2 OPs -+// CAMPV, CAMPI, RAMRI -+// 7. SPECIAL3 OPS -+// LWX, LHX, LBUX, LDX, RDHWR -+// 8. LWC2 OPS -+// GSLWLC1, GSLWRC1, GSLDLC1, GSLDRC1, GSLBLE, GSLBGT, -+// GSLHLE, GSLHGT, GSLWLE, GSLWGT, GSLDLE, GSLDGT, -+// LWDIR, LWPTE, LDDIR, LDPTE -+// GSLWLEC1, GSLWGTC1, GSLDLEC1, GSLDGTC1 -+// 9. LDC2 OPS -+// ALL LDC2 OPS(GSLBX, GSLHX, GSLWX, GSLDX, GSLWXC1, GSLDXC1) -+ -+#define SPECIAL_MOVCI_OP_MASK 0b1111110000000100000011111111111 -+inline bool Assembler::is_load_op(int x) { -+ assert(PatchContinuousLoad, "just checking"); -+ int ins = x; -+ int op = (ins >> 26) & 0x3f; -+ switch (op) { -+ //first_ops: ldl, ldr, lb, lh, lwl, lw, lbu, lhu, lwr, lwu, ld, lwc1, pref, ldc1, ldc2_ops -+ case ldl_op: -+ case ldr_op: -+ case lb_op: -+ case lh_op: -+ case lwl_op: -+ case lw_op: -+ case lbu_op: -+ case lhu_op: -+ case lwr_op: -+ case lwu_op: -+ case ld_op: -+ case lwc1_op: -+ case pref_op: -+ case ldc1_op: -+ //ldc2_ops: gslbx, gslhx, gslwx, gsldx, gslwxc1, gsldxc1 -+ case gs_ldc2_op: -+ return true; -+ //special_ops: movf, movt -+ case special_op: -+ if ((ins & SPECIAL_MOVCI_OP_MASK) == movci_op) -+ return true; -+ else -+ return false; -+ //cop0_ops: mfc0, dmfc0, mfgc0, dmfgc0 -+ case cop0_op: -+ switch ((ins >> 21) & 0x1f) { -+ case mfc0_op: -+ case dmfc0_op: -+ return true; -+ case mxgc0_op: -+ if ((ins >> 9 & 1) == 0) -+ return true; -+ default: -+ return false; -+ } -+ //cop1_ops: mfc1, dmfc1, cfc1, mfhc1, mtc1, dmtc1, ctc1, mthc1, movz.fmt, movn.fmt -+ case cop1_op: -+ switch ((ins >> 21) & 0x1f) { -+ case cfc1_op: -+ case mfhc1_op: -+ case mtc1_op: -+ case dmtc1_op: -+ case ctc1_op: -+ case mthc1_op: -+ return true; -+ case single_fmt: -+ case double_fmt: -+ case ps_fmt: -+ if ((ins & 0x3f == movz_f_op) || (ins & 0x3f == movn_f_op)) -+ return true; -+ default: -+ return false; -+ } -+ //cop1x_ops: lwxc1, ldxc1, luxc1, prefx -+ case cop1x_op: -+ switch (ins & 0x3f) { -+ case lwxc1_op: -+ case ldxc1_op: -+ case luxc1_op: -+ case prefx_op: -+ return true; -+ default: -+ return false; -+ } -+ //special2_ops: campv, campi, ramri -+ case special2_op: -+ switch (ins & 0xff) { -+ case campv_op << 6 | gscam_op: -+ case campi_op << 6 | gscam_op: -+ case ramri_op << 6 | gscam_op: -+ return true; -+ default: -+ return false; -+ } -+ //special3_ops: lwx, lhx, lbux, ldx, rdhwr -+ case special3_op: -+ switch (ins & 0x3f) { -+ case lxx_op: -+ case rdhwr_op: -+ return true; -+ default: -+ return false; -+ } -+ //lwc2_ops: gslwlc1, gslwrc1, gsldlc1, gsldrc1, gslble, gslbgt, gslhle, gslhgt, gslwle, gslwgt, -+ // gsldle, gsldgt, gslwlec1, gslwgtc1, gsldlec1, gsldgtc1 -+ case gs_lwc2_op: -+ if ((ins >> 5 & 1) == 0) //gslq, gslqc1 are excluded. -+ return true; -+ else -+ return false; -+ default: -+ return false; ++ static inline u4 get_native_u4(address p) { ++ if ((intptr_t)p & 3) { ++ u4 res; ++ __asm__ __volatile__ ( ++ " .set push\n" ++ " .set mips64\n" ++ " .set noreorder\n" ++ ++ " lwr %[res], 0(%[addr]) \n" ++ " lwl %[res], 3(%[addr]) \n" ++ ++ " .set pop" ++ : [res] "=&r" (res) ++ : [addr] "r" (p) ++ : "memory" ++ ); ++ return res; ++ } else { ++ return *(u4*)p; ++ } + } -+ return false; -+} + -+#define MAX_LOADS_INSTRUCTION_SEQUENCE_LEN 3 -+inline void Assembler::check_load_and_patch(int x) { -+ int load_count = 0; -+ assert(PatchContinuousLoad, "just checking"); -+ if (is_load_op(x)) { -+ load_count = code()->get_continuous_load_instuctions_count(); -+ code()->set_continuous_load_instuctions_count(++load_count); -+ if (load_count >= MAX_LOADS_INSTRUCTION_SEQUENCE_LEN) { -+ assert(load_count == MAX_LOADS_INSTRUCTION_SEQUENCE_LEN, "load_count should not be greater than MAX_LOADS_INSTRUCTION_SEQUENCE_LEN"); -+#ifndef PRODUCT -+#include "compiler/disassembler.hpp" -+ if (code()->get_continuous_load_instuctions_count() != MAX_LOADS_INSTRUCTION_SEQUENCE_LEN) -+ tty->print_cr("get_continuous_load_instuctions_count() returns %d, which should be %d", code()->get_continuous_load_instuctions_count(), MAX_LOADS_INSTRUCTION_SEQUENCE_LEN); -+ if (TracePatchContinuousLoad && PatchContinuousLoad) { -+ tty->print_cr("found %d consecutive loads, separated by a nop, pc: %p", load_count, pc()); -+ int i; -+ for (i = -MAX_LOADS_INSTRUCTION_SEQUENCE_LEN; i <= 0; i++) -+ tty->print_cr("loads %d(" INTPTR_FORMAT "-" INTPTR_FORMAT "): ", i, p2i(pc()+(i*4)), p2i(pc()+(i*4)+4)); -+ Disassembler::decode(pc()+(i*4), pc()+(i*4)+4, tty); -+ tty->print_cr(" -> nop"); -+ Disassembler::decode((address)&x, (address)&x+4, tty); -+ } -+#endif -+ nop(); /*do a patch here, consecutive loads separated by a nop*/ -+ code()->set_continuous_load_instuctions_count(0); ++ static inline u8 get_native_u8(address p) { ++ u8 res; ++ u8 temp = 0; ++ // u4 tp;//tmp register ++ __asm__ __volatile__ ( ++ " .set push\n" ++ " .set mips64\n" ++ " .set noreorder\n" ++ " .set noat\n" ++ " andi $1,%[addr],0x7 \n" ++ " beqz $1,1f \n" ++ " nop \n" ++ " ldr %[temp], 0(%[addr]) \n" ++ " ldl %[temp], 7(%[addr]) \n" ++ " b 2f \n" ++ " nop \n" ++ " 1:\t ld %[temp],0(%[addr]) \n" ++ " 2:\t sd %[temp], %[res] \n" ++ ++ " .set at\n" ++ " .set pop\n" ++ : [addr]"=r"(p), [temp]"=r" (temp) ++ : "[addr]"(p), "[temp]" (temp), [res]"m" (*(volatile jint*)&res) ++ : "memory" ++ ); ++ ++ return res; ++ } ++ ++ //use mips unaligned load instructions ++ static inline void put_native_u2(address p, u2 x) { ++ if((intptr_t)p & 0x1) { ++ p[0] = (u_char)(x); ++ p[1] = (u_char)(x>>8); ++ } else { ++ *(u2*)p = x; + } -+ } else { -+ code()->set_continuous_load_instuctions_count(0); + } -+#ifndef PRODUCT -+ load_count = code()->get_continuous_load_instuctions_count(); -+ if (load_count >= MAX_LOADS_INSTRUCTION_SEQUENCE_LEN) -+ tty->print_cr("wrong load_count: %d", load_count); -+ assert(load_count < MAX_LOADS_INSTRUCTION_SEQUENCE_LEN, "just checking"); -+#endif -+} + -+#endif // CPU_MIPS_VM_ASSEMBLER_MIPS_INLINE_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/bytes_mips.hpp jdk11u-ls/src/hotspot/cpu/mips/bytes_mips.hpp ---- openjdk/src/hotspot/cpu/mips/bytes_mips.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/bytes_mips.hpp 2023-09-12 13:54:23.097571667 +0800 -@@ -0,0 +1,181 @@ ++ static inline void put_native_u4(address p, u4 x) { ++ // refer to sparc implementation. ++ // Note that sparc is big-endian, while mips is little-endian ++ switch ( intptr_t(p) & 3 ) { ++ case 0: *(u4*)p = x; ++ break; ++ ++ case 2: ((u2*)p)[1] = x >> 16; ++ ((u2*)p)[0] = x; ++ break; ++ ++ default: ((u1*)p)[3] = x >> 24; ++ ((u1*)p)[2] = x >> 16; ++ ((u1*)p)[1] = x >> 8; ++ ((u1*)p)[0] = x; ++ break; ++ } ++ } ++ ++ static inline void put_native_u8(address p, u8 x) { ++ // refer to sparc implementation. ++ // Note that sparc is big-endian, while mips is little-endian ++ switch ( intptr_t(p) & 7 ) { ++ case 0: *(u8*)p = x; ++ break; ++ ++ case 4: ((u4*)p)[1] = x >> 32; ++ ((u4*)p)[0] = x; ++ break; ++ ++ case 2: ((u2*)p)[3] = x >> 48; ++ ((u2*)p)[2] = x >> 32; ++ ((u2*)p)[1] = x >> 16; ++ ((u2*)p)[0] = x; ++ break; ++ ++ default: ((u1*)p)[7] = x >> 56; ++ ((u1*)p)[6] = x >> 48; ++ ((u1*)p)[5] = x >> 40; ++ ((u1*)p)[4] = x >> 32; ++ ((u1*)p)[3] = x >> 24; ++ ((u1*)p)[2] = x >> 16; ++ ((u1*)p)[1] = x >> 8; ++ ((u1*)p)[0] = x; ++ } ++ } ++ ++ ++ // Efficient reading and writing of unaligned unsigned data in Java ++ // byte ordering (i.e. big-endian ordering). Byte-order reversal is ++ // needed since MIPS64EL CPUs use little-endian format. ++ static inline u2 get_Java_u2(address p) { return swap_u2(get_native_u2(p)); } ++ static inline u4 get_Java_u4(address p) { return swap_u4(get_native_u4(p)); } ++ static inline u8 get_Java_u8(address p) { return swap_u8(get_native_u8(p)); } ++ ++ static inline void put_Java_u2(address p, u2 x) { put_native_u2(p, swap_u2(x)); } ++ static inline void put_Java_u4(address p, u4 x) { put_native_u4(p, swap_u4(x)); } ++ static inline void put_Java_u8(address p, u8 x) { put_native_u8(p, swap_u8(x)); } ++ ++ ++ // Efficient swapping of byte ordering ++ static inline u2 swap_u2(u2 x); // compiler-dependent implementation ++ static inline u4 swap_u4(u4 x); // compiler-dependent implementation ++ static inline u8 swap_u8(u8 x); ++}; ++ ++ ++// The following header contains the implementations of swap_u2, swap_u4, and swap_u8[_base] ++#include OS_CPU_HEADER_INLINE(bytes) ++ ++#endif // CPU_MIPS_VM_BYTES_MIPS_HPP +diff --git a/src/hotspot/cpu/mips/c2_globals_mips.hpp b/src/hotspot/cpu/mips/c2_globals_mips.hpp +new file mode 100644 +index 000000000..ef11827ab +--- /dev/null ++++ b/src/hotspot/cpu/mips/c2_globals_mips.hpp +@@ -0,0 +1,95 @@ +/* -+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2019, Loongson Technology. 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 CPU_MIPS_VM_BYTES_MIPS_HPP -+#define CPU_MIPS_VM_BYTES_MIPS_HPP -+ -+#include "memory/allocation.hpp" -+ -+class Bytes: AllStatic { -+ public: -+ // Returns true if the byte ordering used by Java is different from the native byte ordering -+ // of the underlying machine. For example, this is true for Intel x86, but false for Solaris -+ // on Sparc. -+ // we use mipsel, so return true -+ static inline bool is_Java_byte_ordering_different(){ return true; } -+ -+ -+ // Efficient reading and writing of unaligned unsigned data in platform-specific byte ordering -+ // (no special code is needed since x86 CPUs can access unaligned data) -+ static inline u2 get_native_u2(address p) { -+ if ((intptr_t)p & 0x1) { -+ return ((u2)p[1] << 8) | (u2)p[0]; -+ } else { -+ return *(u2*)p; -+ } -+ } -+ -+ static inline u4 get_native_u4(address p) { -+ if ((intptr_t)p & 3) { -+ u4 res; -+ __asm__ __volatile__ ( -+ " .set push\n" -+ " .set mips64\n" -+ " .set noreorder\n" -+ -+ " lwr %[res], 0(%[addr]) \n" -+ " lwl %[res], 3(%[addr]) \n" -+ -+ " .set pop" -+ : [res] "=&r" (res) -+ : [addr] "r" (p) -+ : "memory" -+ ); -+ return res; -+ } else { -+ return *(u4*)p; -+ } -+ } -+ -+ static inline u8 get_native_u8(address p) { -+ u8 res; -+ u8 temp = 0; -+ // u4 tp;//tmp register -+ __asm__ __volatile__ ( -+ " .set push\n" -+ " .set mips64\n" -+ " .set noreorder\n" -+ " .set noat\n" -+ " andi $1,%[addr],0x7 \n" -+ " beqz $1,1f \n" -+ " nop \n" -+ " ldr %[temp], 0(%[addr]) \n" -+ " ldl %[temp], 7(%[addr]) \n" -+ " b 2f \n" -+ " nop \n" -+ " 1:\t ld %[temp],0(%[addr]) \n" -+ " 2:\t sd %[temp], %[res] \n" -+ -+ " .set at\n" -+ " .set pop\n" -+ : [addr]"=r"(p), [temp]"=r" (temp) -+ : "[addr]"(p), "[temp]" (temp), [res]"m" (*(volatile jint*)&res) -+ : "memory" -+ ); -+ -+ return res; -+ } -+ -+ //use mips unaligned load instructions -+ static inline void put_native_u2(address p, u2 x) { -+ if((intptr_t)p & 0x1) { -+ p[0] = (u_char)(x); -+ p[1] = (u_char)(x>>8); -+ } else { -+ *(u2*)p = x; -+ } -+ } -+ -+ static inline void put_native_u4(address p, u4 x) { -+ // refer to sparc implementation. -+ // Note that sparc is big-endian, while mips is little-endian -+ switch ( intptr_t(p) & 3 ) { -+ case 0: *(u4*)p = x; -+ break; -+ -+ case 2: ((u2*)p)[1] = x >> 16; -+ ((u2*)p)[0] = x; -+ break; -+ -+ default: ((u1*)p)[3] = x >> 24; -+ ((u1*)p)[2] = x >> 16; -+ ((u1*)p)[1] = x >> 8; -+ ((u1*)p)[0] = x; -+ break; -+ } -+ } -+ -+ static inline void put_native_u8(address p, u8 x) { -+ // refer to sparc implementation. -+ // Note that sparc is big-endian, while mips is little-endian -+ switch ( intptr_t(p) & 7 ) { -+ case 0: *(u8*)p = x; -+ break; -+ -+ case 4: ((u4*)p)[1] = x >> 32; -+ ((u4*)p)[0] = x; -+ break; -+ -+ case 2: ((u2*)p)[3] = x >> 48; -+ ((u2*)p)[2] = x >> 32; -+ ((u2*)p)[1] = x >> 16; -+ ((u2*)p)[0] = x; -+ break; -+ -+ default: ((u1*)p)[7] = x >> 56; -+ ((u1*)p)[6] = x >> 48; -+ ((u1*)p)[5] = x >> 40; -+ ((u1*)p)[4] = x >> 32; -+ ((u1*)p)[3] = x >> 24; -+ ((u1*)p)[2] = x >> 16; -+ ((u1*)p)[1] = x >> 8; -+ ((u1*)p)[0] = x; -+ } -+ } -+ -+ -+ // Efficient reading and writing of unaligned unsigned data in Java -+ // byte ordering (i.e. big-endian ordering). Byte-order reversal is -+ // needed since MIPS64EL CPUs use little-endian format. -+ static inline u2 get_Java_u2(address p) { return swap_u2(get_native_u2(p)); } -+ static inline u4 get_Java_u4(address p) { return swap_u4(get_native_u4(p)); } -+ static inline u8 get_Java_u8(address p) { return swap_u8(get_native_u8(p)); } -+ -+ static inline void put_Java_u2(address p, u2 x) { put_native_u2(p, swap_u2(x)); } -+ static inline void put_Java_u4(address p, u4 x) { put_native_u4(p, swap_u4(x)); } -+ static inline void put_Java_u8(address p, u8 x) { put_native_u8(p, swap_u8(x)); } -+ -+ -+ // Efficient swapping of byte ordering -+ static inline u2 swap_u2(u2 x); // compiler-dependent implementation -+ static inline u4 swap_u4(u4 x); // compiler-dependent implementation -+ static inline u8 swap_u8(u8 x); -+}; -+ -+ -+// The following header contains the implementations of swap_u2, swap_u4, and swap_u8[_base] -+#include OS_CPU_HEADER_INLINE(bytes) -+ -+#endif // CPU_MIPS_VM_BYTES_MIPS_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/c2_globals_mips.hpp jdk11u-ls/src/hotspot/cpu/mips/c2_globals_mips.hpp ---- openjdk/src/hotspot/cpu/mips/c2_globals_mips.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/c2_globals_mips.hpp 2023-09-12 13:54:23.097571667 +0800 -@@ -0,0 +1,95 @@ -+/* -+ * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2022, Loongson Technology. All rights reserved. ++ * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2015, 2022, Loongson Technology. 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 @@ -61891,9 +67700,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/c2_gl +define_pd_global(bool, NeverActAsServerClassMachine, false); + +#endif // CPU_MIPS_VM_C2_GLOBALS_MIPS_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/c2_init_mips.cpp jdk11u-ls/src/hotspot/cpu/mips/c2_init_mips.cpp ---- openjdk/src/hotspot/cpu/mips/c2_init_mips.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/c2_init_mips.cpp 2023-09-12 13:54:23.097571667 +0800 +diff --git a/src/hotspot/cpu/mips/c2_init_mips.cpp b/src/hotspot/cpu/mips/c2_init_mips.cpp +new file mode 100644 +index 000000000..e6d5815f4 +--- /dev/null ++++ b/src/hotspot/cpu/mips/c2_init_mips.cpp @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. @@ -61929,10 +67740,12 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/c2_in +void Compile::pd_compiler2_init() { + guarantee(CodeEntryAlignment >= InteriorEntryAlignment, "" ); +} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/codeBuffer_mips.hpp jdk11u-ls/src/hotspot/cpu/mips/codeBuffer_mips.hpp ---- openjdk/src/hotspot/cpu/mips/codeBuffer_mips.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/codeBuffer_mips.hpp 2023-09-12 13:54:23.097571667 +0800 -@@ -0,0 +1,38 @@ +diff --git a/src/hotspot/cpu/mips/codeBuffer_mips.hpp b/src/hotspot/cpu/mips/codeBuffer_mips.hpp +new file mode 100644 +index 000000000..3cc191006 +--- /dev/null ++++ b/src/hotspot/cpu/mips/codeBuffer_mips.hpp +@@ -0,0 +1,35 @@ +/* + * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2018, Loongson Technology. All rights reserved. @@ -61963,17 +67776,16 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/codeB + +private: + void pd_initialize() {} -+ int _continuous_load_instuctions_count; + +public: + void flush_bundle(bool start_new_bundle) {} -+ int get_continuous_load_instuctions_count() const { return _continuous_load_instuctions_count; } -+ int set_continuous_load_instuctions_count(int x) { return _continuous_load_instuctions_count = x; } + +#endif // CPU_MIPS_VM_CODEBUFFER_MIPS_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/compiledIC_mips.cpp jdk11u-ls/src/hotspot/cpu/mips/compiledIC_mips.cpp ---- openjdk/src/hotspot/cpu/mips/compiledIC_mips.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/compiledIC_mips.cpp 2023-09-12 13:54:23.097571667 +0800 +diff --git a/src/hotspot/cpu/mips/compiledIC_mips.cpp b/src/hotspot/cpu/mips/compiledIC_mips.cpp +new file mode 100644 +index 000000000..068ca4799 +--- /dev/null ++++ b/src/hotspot/cpu/mips/compiledIC_mips.cpp @@ -0,0 +1,151 @@ +/* + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. @@ -62126,9 +67938,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/compi +} + +#endif // !PRODUCT -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/copy_mips.hpp jdk11u-ls/src/hotspot/cpu/mips/copy_mips.hpp ---- openjdk/src/hotspot/cpu/mips/copy_mips.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/copy_mips.hpp 2023-09-12 13:54:23.097571667 +0800 +diff --git a/src/hotspot/cpu/mips/copy_mips.hpp b/src/hotspot/cpu/mips/copy_mips.hpp +new file mode 100644 +index 000000000..dcc77adfe +--- /dev/null ++++ b/src/hotspot/cpu/mips/copy_mips.hpp @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. @@ -62207,9 +68021,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/copy_ +} + +#endif //CPU_MIPS_VM_COPY_MIPS_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/depChecker_mips.cpp jdk11u-ls/src/hotspot/cpu/mips/depChecker_mips.cpp ---- openjdk/src/hotspot/cpu/mips/depChecker_mips.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/depChecker_mips.cpp 2023-09-12 13:54:23.097571667 +0800 +diff --git a/src/hotspot/cpu/mips/depChecker_mips.cpp b/src/hotspot/cpu/mips/depChecker_mips.cpp +new file mode 100644 +index 000000000..756ccb68f +--- /dev/null ++++ b/src/hotspot/cpu/mips/depChecker_mips.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. @@ -62241,9 +68057,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/depCh +#include "depChecker_mips.hpp" + +// Nothing to do on mips -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/depChecker_mips.hpp jdk11u-ls/src/hotspot/cpu/mips/depChecker_mips.hpp ---- openjdk/src/hotspot/cpu/mips/depChecker_mips.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/depChecker_mips.hpp 2023-09-12 13:54:23.097571667 +0800 +diff --git a/src/hotspot/cpu/mips/depChecker_mips.hpp b/src/hotspot/cpu/mips/depChecker_mips.hpp +new file mode 100644 +index 000000000..11e52b4e8 +--- /dev/null ++++ b/src/hotspot/cpu/mips/depChecker_mips.hpp @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. @@ -62276,9 +68094,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/depCh +// Nothing to do on MIPS + +#endif // CPU_MIPS_VM_DEPCHECKER_MIPS_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/disassembler_mips.hpp jdk11u-ls/src/hotspot/cpu/mips/disassembler_mips.hpp ---- openjdk/src/hotspot/cpu/mips/disassembler_mips.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/disassembler_mips.hpp 2023-09-12 13:54:23.097571667 +0800 +diff --git a/src/hotspot/cpu/mips/disassembler_mips.hpp b/src/hotspot/cpu/mips/disassembler_mips.hpp +new file mode 100644 +index 000000000..c5f3a8888 +--- /dev/null ++++ b/src/hotspot/cpu/mips/disassembler_mips.hpp @@ -0,0 +1,37 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. @@ -62317,9 +68137,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/disas + } + +#endif // CPU_MIPS_VM_DISASSEMBLER_MIPS_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/frame_mips.cpp jdk11u-ls/src/hotspot/cpu/mips/frame_mips.cpp ---- openjdk/src/hotspot/cpu/mips/frame_mips.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/frame_mips.cpp 2023-09-12 13:54:23.097571667 +0800 +diff --git a/src/hotspot/cpu/mips/frame_mips.cpp b/src/hotspot/cpu/mips/frame_mips.cpp +new file mode 100644 +index 000000000..d49bd6290 +--- /dev/null ++++ b/src/hotspot/cpu/mips/frame_mips.cpp @@ -0,0 +1,690 @@ +/* + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. @@ -63011,9 +68833,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/frame + +void frame::pd_ps() {} +#endif -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/frame_mips.hpp jdk11u-ls/src/hotspot/cpu/mips/frame_mips.hpp ---- openjdk/src/hotspot/cpu/mips/frame_mips.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/frame_mips.hpp 2023-09-12 13:54:23.097571667 +0800 +diff --git a/src/hotspot/cpu/mips/frame_mips.hpp b/src/hotspot/cpu/mips/frame_mips.hpp +new file mode 100644 +index 000000000..bdbfa8aaa +--- /dev/null ++++ b/src/hotspot/cpu/mips/frame_mips.hpp @@ -0,0 +1,215 @@ +/* + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. @@ -63230,13 +69054,15 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/frame + static jint interpreter_frame_expression_stack_direction() { return -1; } + +#endif // CPU_MIPS_VM_FRAME_MIPS_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/frame_mips.inline.hpp jdk11u-ls/src/hotspot/cpu/mips/frame_mips.inline.hpp ---- openjdk/src/hotspot/cpu/mips/frame_mips.inline.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/frame_mips.inline.hpp 2023-11-01 09:34:25.493945267 +0800 -@@ -0,0 +1,233 @@ +diff --git a/src/hotspot/cpu/mips/frame_mips.inline.hpp b/src/hotspot/cpu/mips/frame_mips.inline.hpp +new file mode 100644 +index 000000000..c408f01d6 +--- /dev/null ++++ b/src/hotspot/cpu/mips/frame_mips.inline.hpp +@@ -0,0 +1,238 @@ +/* + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2018, Loongson Technology. All rights reserved. ++ * Copyright (c) 2015, 2022, Loongson Technology. 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 @@ -63371,9 +69197,14 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/frame +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() 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; } + @@ -63467,9 +69298,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/frame +} + +#endif // CPU_MIPS_VM_FRAME_MIPS_INLINE_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/gc/g1/g1BarrierSetAssembler_mips.cpp jdk11u-ls/src/hotspot/cpu/mips/gc/g1/g1BarrierSetAssembler_mips.cpp ---- openjdk/src/hotspot/cpu/mips/gc/g1/g1BarrierSetAssembler_mips.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/gc/g1/g1BarrierSetAssembler_mips.cpp 2023-09-12 13:54:23.097571667 +0800 +diff --git a/src/hotspot/cpu/mips/gc/g1/g1BarrierSetAssembler_mips.cpp b/src/hotspot/cpu/mips/gc/g1/g1BarrierSetAssembler_mips.cpp +new file mode 100644 +index 000000000..179f7703c +--- /dev/null ++++ b/src/hotspot/cpu/mips/gc/g1/g1BarrierSetAssembler_mips.cpp @@ -0,0 +1,364 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. @@ -63835,9 +69668,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/gc/g1 + } + } +} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/gc/g1/g1BarrierSetAssembler_mips.hpp jdk11u-ls/src/hotspot/cpu/mips/gc/g1/g1BarrierSetAssembler_mips.hpp ---- openjdk/src/hotspot/cpu/mips/gc/g1/g1BarrierSetAssembler_mips.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/gc/g1/g1BarrierSetAssembler_mips.hpp 2023-09-12 13:54:23.097571667 +0800 +diff --git a/src/hotspot/cpu/mips/gc/g1/g1BarrierSetAssembler_mips.hpp b/src/hotspot/cpu/mips/gc/g1/g1BarrierSetAssembler_mips.hpp +new file mode 100644 +index 000000000..ec5c243c3 +--- /dev/null ++++ b/src/hotspot/cpu/mips/gc/g1/g1BarrierSetAssembler_mips.hpp @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. @@ -63910,9 +69745,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/gc/g1 +}; + +#endif // CPU_MIPS_GC_G1_G1BARRIERSETASSEMBLER_MIPS_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/gc/shared/barrierSetAssembler_mips.cpp jdk11u-ls/src/hotspot/cpu/mips/gc/shared/barrierSetAssembler_mips.cpp ---- openjdk/src/hotspot/cpu/mips/gc/shared/barrierSetAssembler_mips.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/gc/shared/barrierSetAssembler_mips.cpp 2023-09-12 13:54:23.097571667 +0800 +diff --git a/src/hotspot/cpu/mips/gc/shared/barrierSetAssembler_mips.cpp b/src/hotspot/cpu/mips/gc/shared/barrierSetAssembler_mips.cpp +new file mode 100644 +index 000000000..071debdc3 +--- /dev/null ++++ b/src/hotspot/cpu/mips/gc/shared/barrierSetAssembler_mips.cpp @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. @@ -64108,9 +69945,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/gc/sh + Register t1) { + Unimplemented(); +} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/gc/shared/barrierSetAssembler_mips.hpp jdk11u-ls/src/hotspot/cpu/mips/gc/shared/barrierSetAssembler_mips.hpp ---- openjdk/src/hotspot/cpu/mips/gc/shared/barrierSetAssembler_mips.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/gc/shared/barrierSetAssembler_mips.hpp 2023-09-12 13:54:23.097571667 +0800 +diff --git a/src/hotspot/cpu/mips/gc/shared/barrierSetAssembler_mips.hpp b/src/hotspot/cpu/mips/gc/shared/barrierSetAssembler_mips.hpp +new file mode 100644 +index 000000000..b97ecbcca +--- /dev/null ++++ b/src/hotspot/cpu/mips/gc/shared/barrierSetAssembler_mips.hpp @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. @@ -64195,13 +70034,15 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/gc/sh +}; + +#endif // CPU_MIPS_GC_SHARED_BARRIERSETASSEMBLER_MIPS_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/gc/shared/cardTableBarrierSetAssembler_mips.cpp jdk11u-ls/src/hotspot/cpu/mips/gc/shared/cardTableBarrierSetAssembler_mips.cpp ---- openjdk/src/hotspot/cpu/mips/gc/shared/cardTableBarrierSetAssembler_mips.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/gc/shared/cardTableBarrierSetAssembler_mips.cpp 2023-11-01 09:34:25.493945267 +0800 -@@ -0,0 +1,149 @@ +diff --git a/src/hotspot/cpu/mips/gc/shared/cardTableBarrierSetAssembler_mips.cpp b/src/hotspot/cpu/mips/gc/shared/cardTableBarrierSetAssembler_mips.cpp +new file mode 100644 +index 000000000..f33165334 +--- /dev/null ++++ b/src/hotspot/cpu/mips/gc/shared/cardTableBarrierSetAssembler_mips.cpp +@@ -0,0 +1,147 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2018, 2022, Loongson Technology. All rights reserved. ++ * Copyright (c) 2018, 2023, Loongson Technology. 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 @@ -64260,7 +70101,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/gc/sh + __ beq(count, R0, L_done); // zero count - nothing to do + __ delayed()->nop(); + -+ if (UseConcMarkSweepGC) __ sync(); ++ if (ct->scanned_concurrently()) __ membar(Assembler::StoreStore); + + __ set64(tmp, disp); + @@ -64309,8 +70150,6 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/gc/sh + + jbyte dirty = CardTable::dirty_card_val(); + if (UseCondCardMark) { -+ Untested("Untested"); -+ __ warn("store_check Untested"); + Label L_already_dirty; + __ membar(Assembler::StoreLoad); + __ lb(AT, tmp, 0); @@ -64321,7 +70160,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/gc/sh + __ bind(L_already_dirty); + } else { + if (ct->scanned_concurrently()) { -+ __ membar(Assembler::StoreLoad); ++ __ membar(Assembler::StoreStore); + } + __ sb(R0, tmp, 0); + } @@ -64348,9 +70187,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/gc/sh + } + } +} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/gc/shared/cardTableBarrierSetAssembler_mips.hpp jdk11u-ls/src/hotspot/cpu/mips/gc/shared/cardTableBarrierSetAssembler_mips.hpp ---- openjdk/src/hotspot/cpu/mips/gc/shared/cardTableBarrierSetAssembler_mips.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/gc/shared/cardTableBarrierSetAssembler_mips.hpp 2023-09-12 13:54:23.097571667 +0800 +diff --git a/src/hotspot/cpu/mips/gc/shared/cardTableBarrierSetAssembler_mips.hpp b/src/hotspot/cpu/mips/gc/shared/cardTableBarrierSetAssembler_mips.hpp +new file mode 100644 +index 000000000..49c2a0ea8 +--- /dev/null ++++ b/src/hotspot/cpu/mips/gc/shared/cardTableBarrierSetAssembler_mips.hpp @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. @@ -64394,9 +70235,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/gc/sh +}; + +#endif // CPU_MIPS_GC_SHARED_CARDTABLEBARRIERSETASSEMBLER_MIPS_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/gc/shared/modRefBarrierSetAssembler_mips.cpp jdk11u-ls/src/hotspot/cpu/mips/gc/shared/modRefBarrierSetAssembler_mips.cpp ---- openjdk/src/hotspot/cpu/mips/gc/shared/modRefBarrierSetAssembler_mips.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/gc/shared/modRefBarrierSetAssembler_mips.cpp 2023-09-12 13:54:23.097571667 +0800 +diff --git a/src/hotspot/cpu/mips/gc/shared/modRefBarrierSetAssembler_mips.cpp b/src/hotspot/cpu/mips/gc/shared/modRefBarrierSetAssembler_mips.cpp +new file mode 100644 +index 000000000..765259e62 +--- /dev/null ++++ b/src/hotspot/cpu/mips/gc/shared/modRefBarrierSetAssembler_mips.cpp @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. @@ -64451,9 +70294,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/gc/sh + BarrierSetAssembler::store_at(masm, decorators, type, dst, val, tmp1, tmp2); + } +} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/gc/shared/modRefBarrierSetAssembler_mips.hpp jdk11u-ls/src/hotspot/cpu/mips/gc/shared/modRefBarrierSetAssembler_mips.hpp ---- openjdk/src/hotspot/cpu/mips/gc/shared/modRefBarrierSetAssembler_mips.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/gc/shared/modRefBarrierSetAssembler_mips.hpp 2023-09-12 13:54:23.097571667 +0800 +diff --git a/src/hotspot/cpu/mips/gc/shared/modRefBarrierSetAssembler_mips.hpp b/src/hotspot/cpu/mips/gc/shared/modRefBarrierSetAssembler_mips.hpp +new file mode 100644 +index 000000000..5320a4c0a +--- /dev/null ++++ b/src/hotspot/cpu/mips/gc/shared/modRefBarrierSetAssembler_mips.hpp @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. @@ -64509,9 +70354,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/gc/sh +}; + +#endif // CPU_MIPS_GC_SHARED_MODREFBARRIERSETASSEMBLER_MIPS_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/globalDefinitions_mips.hpp jdk11u-ls/src/hotspot/cpu/mips/globalDefinitions_mips.hpp ---- openjdk/src/hotspot/cpu/mips/globalDefinitions_mips.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/globalDefinitions_mips.hpp 2023-09-12 13:54:23.097571667 +0800 +diff --git a/src/hotspot/cpu/mips/globalDefinitions_mips.hpp b/src/hotspot/cpu/mips/globalDefinitions_mips.hpp +new file mode 100644 +index 000000000..abf8141e8 +--- /dev/null ++++ b/src/hotspot/cpu/mips/globalDefinitions_mips.hpp @@ -0,0 +1,45 @@ +/* + * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. @@ -64558,10 +70405,12 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/globa +#define THREAD_LOCAL_POLL + +#endif // CPU_MIPS_VM_GLOBALDEFINITIONS_MIPS_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/globals_mips.hpp jdk11u-ls/src/hotspot/cpu/mips/globals_mips.hpp ---- openjdk/src/hotspot/cpu/mips/globals_mips.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/globals_mips.hpp 2023-09-12 13:54:23.097571667 +0800 -@@ -0,0 +1,143 @@ +diff --git a/src/hotspot/cpu/mips/globals_mips.hpp b/src/hotspot/cpu/mips/globals_mips.hpp +new file mode 100644 +index 000000000..3bcad005d +--- /dev/null ++++ b/src/hotspot/cpu/mips/globals_mips.hpp +@@ -0,0 +1,137 @@ +/* + * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, Loongson Technology. All rights reserved. @@ -64669,12 +70518,6 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/globa + product(bool, UseLEXT3, false, \ + "Use LoongISA general EXTensions 3") \ + \ -+ product(bool, PatchContinuousLoad, true, \ -+ "Patch continuous loads with nop") \ -+ \ -+ notproduct(bool, TracePatchContinuousLoad, false, \ -+ "Trace patch of continuous loads") \ -+ \ + product(bool, UseCodeCacheAllocOpt, true, \ + "Allocate code cache within 32-bit memory address space") \ + \ @@ -64705,13 +70548,15 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/globa + "Eliminate barriers for single active cpu") + +#endif // CPU_MIPS_VM_GLOBALS_MIPS_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/icache_mips.cpp jdk11u-ls/src/hotspot/cpu/mips/icache_mips.cpp ---- openjdk/src/hotspot/cpu/mips/icache_mips.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/icache_mips.cpp 2023-09-12 13:54:23.097571667 +0800 -@@ -0,0 +1,41 @@ +diff --git a/src/hotspot/cpu/mips/icBuffer_mips.cpp b/src/hotspot/cpu/mips/icBuffer_mips.cpp +new file mode 100644 +index 000000000..6586c6396 +--- /dev/null ++++ b/src/hotspot/cpu/mips/icBuffer_mips.cpp +@@ -0,0 +1,88 @@ +/* -+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2021, Loongson Technology. All rights reserved. ++ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2015, 2022, Loongson Technology. 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 @@ -64736,23 +70581,119 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/icach + +#include "precompiled.hpp" +#include "asm/macroAssembler.hpp" -+#include "runtime/icache.hpp" ++#include "asm/macroAssembler.inline.hpp" ++#include "code/icBuffer.hpp" ++#include "gc/shared/collectedHeap.inline.hpp" ++#include "interpreter/bytecodes.hpp" ++#include "memory/resourceArea.hpp" ++#include "nativeInst_mips.hpp" ++#include "oops/oop.inline.hpp" + -+void ICacheStubGenerator::generate_icache_flush(ICache::flush_icache_stub_t* flush_icache_stub) -+{ -+#define __ _masm-> -+ StubCodeMark mark(this, "ICache", "flush_icache_stub"); -+ address start = __ pc(); ++#define T0 RT0 ++#define T1 RT1 ++#define T2 RT2 ++#define T3 RT3 ++#define T8 RT8 ++#define T9 RT9 + -+ __ jr_hb(RA); -+ __ delayed()->ori(V0, A2, 0); ++int InlineCacheBuffer::ic_stub_code_size() { ++ return NativeMovConstReg::instruction_size + ++ NativeGeneralJump::instruction_size + ++ 1; ++ // so that code_end can be set in CodeBuffer ++ // 64bit 15 = 6 + 8 bytes + 1 byte ++ // 32bit 7 = 2 + 4 bytes + 1 byte ++} + -+ *flush_icache_stub = (ICache::flush_icache_stub_t)start; ++ ++// we use T1 as cached oop(klass) now. this is the target of virtual call, ++// when reach here, the receiver in T0 ++// refer to shareRuntime_mips.cpp,gen_i2c2i_adapters ++void InlineCacheBuffer::assemble_ic_buffer_code(address code_begin, void* cached_value, address entry_point) { ++ ResourceMark rm; ++ CodeBuffer code(code_begin, ic_stub_code_size()); ++ MacroAssembler* masm = new MacroAssembler(&code); ++ // note: even though the code contains an embedded oop, we do not need reloc info ++ // because ++ // (1) the oop is old (i.e., doesn't matter for scavenges) ++ // (2) these ICStubs are removed *before* a GC happens, so the roots disappear ++// assert(cached_oop == NULL || cached_oop->is_perm(), "must be perm oop"); ++#define __ masm-> ++ __ patchable_set48(T1, (long)cached_value); ++ ++ __ patchable_jump(entry_point); ++ __ flush(); +#undef __ +} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/icache_mips.hpp jdk11u-ls/src/hotspot/cpu/mips/icache_mips.hpp ---- openjdk/src/hotspot/cpu/mips/icache_mips.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/icache_mips.hpp 2023-09-12 13:54:23.097571667 +0800 ++ ++ ++address InlineCacheBuffer::ic_buffer_entry_point(address code_begin) { ++ NativeMovConstReg* move = nativeMovConstReg_at(code_begin); // creation also verifies the object ++ NativeGeneralJump* jump = nativeGeneralJump_at(move->next_instruction_address()); ++ return jump->jump_destination(); ++} ++ ++ ++void* InlineCacheBuffer::ic_buffer_cached_value(address code_begin) { ++ // creation also verifies the object ++ NativeMovConstReg* move = nativeMovConstReg_at(code_begin); ++ // Verifies the jump ++ NativeGeneralJump* jump = nativeGeneralJump_at(move->next_instruction_address()); ++ void* o= (void*)move->data(); ++ return o; ++} +diff --git a/src/hotspot/cpu/mips/icache_mips.cpp b/src/hotspot/cpu/mips/icache_mips.cpp +new file mode 100644 +index 000000000..e84e37358 +--- /dev/null ++++ b/src/hotspot/cpu/mips/icache_mips.cpp +@@ -0,0 +1,41 @@ ++/* ++ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2015, 2021, Loongson Technology. 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 "asm/macroAssembler.hpp" ++#include "runtime/icache.hpp" ++ ++void ICacheStubGenerator::generate_icache_flush(ICache::flush_icache_stub_t* flush_icache_stub) ++{ ++#define __ _masm-> ++ StubCodeMark mark(this, "ICache", "flush_icache_stub"); ++ address start = __ pc(); ++ ++ __ jr_hb(RA); ++ __ delayed()->ori(V0, A2, 0); ++ ++ *flush_icache_stub = (ICache::flush_icache_stub_t)start; ++#undef __ ++} +diff --git a/src/hotspot/cpu/mips/icache_mips.hpp b/src/hotspot/cpu/mips/icache_mips.hpp +new file mode 100644 +index 000000000..f90dee6ee +--- /dev/null ++++ b/src/hotspot/cpu/mips/icache_mips.hpp @@ -0,0 +1,41 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. @@ -64795,13 +70736,15 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/icach +}; + +#endif // CPU_MIPS_VM_ICACHE_MIPS_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/icBuffer_mips.cpp jdk11u-ls/src/hotspot/cpu/mips/icBuffer_mips.cpp ---- openjdk/src/hotspot/cpu/mips/icBuffer_mips.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/icBuffer_mips.cpp 2023-09-12 13:54:23.097571667 +0800 -@@ -0,0 +1,88 @@ +diff --git a/src/hotspot/cpu/mips/interp_masm_mips.hpp b/src/hotspot/cpu/mips/interp_masm_mips.hpp +new file mode 100644 +index 000000000..e526e39d5 +--- /dev/null ++++ b/src/hotspot/cpu/mips/interp_masm_mips.hpp +@@ -0,0 +1,276 @@ +/* -+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2022, Loongson Technology. All rights reserved. ++ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2015, 2020, Loongson Technology. 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 @@ -64824,73 +70767,263 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/icBuf + * + */ + -+#include "precompiled.hpp" ++#ifndef CPU_MIPS_VM_INTERP_MASM_MIPS_64_HPP ++#define CPU_MIPS_VM_INTERP_MASM_MIPS_64_HPP ++ ++#include "asm/assembler.hpp" +#include "asm/macroAssembler.hpp" +#include "asm/macroAssembler.inline.hpp" -+#include "code/icBuffer.hpp" -+#include "gc/shared/collectedHeap.inline.hpp" -+#include "interpreter/bytecodes.hpp" -+#include "memory/resourceArea.hpp" -+#include "nativeInst_mips.hpp" -+#include "oops/oop.inline.hpp" ++#include "interpreter/invocationCounter.hpp" ++#include "runtime/frame.hpp" + -+#define T0 RT0 -+#define T1 RT1 -+#define T2 RT2 -+#define T3 RT3 -+#define T8 RT8 -+#define T9 RT9 ++// This file specializes the assember with interpreter-specific macros + -+int InlineCacheBuffer::ic_stub_code_size() { -+ return NativeMovConstReg::instruction_size + -+ NativeGeneralJump::instruction_size + -+ 1; -+ // so that code_end can be set in CodeBuffer -+ // 64bit 15 = 6 + 8 bytes + 1 byte -+ // 32bit 7 = 2 + 4 bytes + 1 byte -+} + ++class InterpreterMacroAssembler: public MacroAssembler { ++#ifndef CC_INTERP ++ private: + -+// we use T1 as cached oop(klass) now. this is the target of virtual call, -+// when reach here, the receiver in T0 -+// refer to shareRuntime_mips.cpp,gen_i2c2i_adapters -+void InlineCacheBuffer::assemble_ic_buffer_code(address code_begin, void* cached_value, address entry_point) { -+ ResourceMark rm; -+ CodeBuffer code(code_begin, ic_stub_code_size()); -+ MacroAssembler* masm = new MacroAssembler(&code); -+ // note: even though the code contains an embedded oop, we do not need reloc info -+ // because -+ // (1) the oop is old (i.e., doesn't matter for scavenges) -+ // (2) these ICStubs are removed *before* a GC happens, so the roots disappear -+// assert(cached_oop == NULL || cached_oop->is_perm(), "must be perm oop"); -+#define __ masm-> -+ __ patchable_set48(T1, (long)cached_value); ++ Register _locals_register; // register that contains the pointer to the locals ++ Register _bcp_register; // register that contains the bcp + -+ __ patchable_jump(entry_point); -+ __ flush(); -+#undef __ -+} ++ protected: ++ // Interpreter specific version of call_VM_base ++ virtual void call_VM_leaf_base(address entry_point, ++ int number_of_arguments); + ++ virtual void call_VM_base(Register oop_result, ++ Register java_thread, ++ Register last_java_sp, ++ address entry_point, ++ int number_of_arguments, ++ bool check_exceptions); + -+address InlineCacheBuffer::ic_buffer_entry_point(address code_begin) { -+ NativeMovConstReg* move = nativeMovConstReg_at(code_begin); // creation also verifies the object -+ NativeGeneralJump* jump = nativeGeneralJump_at(move->next_instruction_address()); -+ return jump->jump_destination(); -+} ++ // base routine for all dispatches ++ void dispatch_base(TosState state, address* table, bool verifyoop = true, bool generate_poll = false); ++#endif // CC_INTERP + ++ public: ++ void jump_to_entry(address entry); ++ // narrow int return value ++ void narrow(Register result); + -+void* InlineCacheBuffer::ic_buffer_cached_value(address code_begin) { -+ // creation also verifies the object -+ NativeMovConstReg* move = nativeMovConstReg_at(code_begin); -+ // Verifies the jump -+ NativeGeneralJump* jump = nativeGeneralJump_at(move->next_instruction_address()); -+ void* o= (void*)move->data(); -+ return o; -+} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/interp_masm_mips_64.cpp jdk11u-ls/src/hotspot/cpu/mips/interp_masm_mips_64.cpp ---- openjdk/src/hotspot/cpu/mips/interp_masm_mips_64.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/interp_masm_mips_64.cpp 2023-11-01 09:34:25.493945267 +0800 -@@ -0,0 +1,2125 @@ ++ InterpreterMacroAssembler(CodeBuffer* code) : MacroAssembler(code), _locals_register(LVP), _bcp_register(BCP) {} ++ ++ void get_2_byte_integer_at_bcp(Register reg, Register tmp, int offset); ++ void get_4_byte_integer_at_bcp(Register reg, Register tmp, int offset); ++ ++ virtual void check_and_handle_popframe(Register java_thread); ++ virtual void check_and_handle_earlyret(Register java_thread); ++ ++ void load_earlyret_value(TosState state); ++ ++#ifdef CC_INTERP ++ void save_bcp() { /* not needed in c++ interpreter and harmless */ } ++ void restore_bcp() { /* not needed in c++ interpreter and harmless */ } ++ ++ // Helpers for runtime call arguments/results ++ void get_method(Register reg); ++ ++#else ++ ++ // Interpreter-specific registers ++ void save_bcp() { ++ sd(BCP, FP, frame::interpreter_frame_bcp_offset * wordSize); ++ } ++ ++ void restore_bcp() { ++ ld(BCP, FP, frame::interpreter_frame_bcp_offset * wordSize); ++ } ++ ++ void restore_locals() { ++ ld(LVP, FP, frame::interpreter_frame_locals_offset * wordSize); ++ } ++ ++ // Helpers for runtime call arguments/results ++ void get_method(Register reg) { ++ ld(reg, FP, frame::interpreter_frame_method_offset * wordSize); ++ } ++ ++ void get_const(Register reg){ ++ get_method(reg); ++ ld(reg, reg, in_bytes(Method::const_offset())); ++ } ++ ++ void get_constant_pool(Register reg) { ++ get_const(reg); ++ ld(reg, reg, in_bytes(ConstMethod::constants_offset())); ++ } ++ ++ void get_constant_pool_cache(Register reg) { ++ get_constant_pool(reg); ++ ld(reg, reg, ConstantPool::cache_offset_in_bytes()); ++ } ++ ++ void get_cpool_and_tags(Register cpool, Register tags) { ++ get_constant_pool(cpool); ++ ld(tags, cpool, ConstantPool::tags_offset_in_bytes()); ++ } ++ ++ void get_unsigned_2_byte_index_at_bcp(Register reg, int bcp_offset); ++ void get_cache_and_index_at_bcp(Register cache, Register index, int bcp_offset, size_t index_size = sizeof(u2)); ++ void get_cache_and_index_and_bytecode_at_bcp(Register cache, Register index, Register bytecode, int byte_no, int bcp_offset, size_t index_size = sizeof(u2)); ++ void get_cache_entry_pointer_at_bcp(Register cache, Register tmp, int bcp_offset, size_t index_size = sizeof(u2)); ++ void get_cache_index_at_bcp(Register index, int bcp_offset, size_t index_size = sizeof(u2)); ++ void get_method_counters(Register method, Register mcs, Label& skip); ++ ++ // load cpool->resolved_references(index); ++ void load_resolved_reference_at_index(Register result, Register index, Register tmp); ++ ++ // load cpool->resolved_klass_at(index) ++ void load_resolved_klass_at_index(Register cpool, // the constant pool (corrupted on return) ++ Register index, // the constant pool index (corrupted on return) ++ Register klass); // contains the Klass on return ++ ++ void pop_ptr( Register r = FSR); ++ void pop_i( Register r = FSR); ++ void pop_l( Register r = FSR); ++ void pop_f(FloatRegister r = FSF); ++ void pop_d(FloatRegister r = FSF); ++ ++ void push_ptr( Register r = FSR); ++ void push_i( Register r = FSR); ++ void push_l( Register r = FSR); ++ void push_f(FloatRegister r = FSF); ++ void push_d(FloatRegister r = FSF); ++ ++ void pop(Register r ) { ((MacroAssembler*)this)->pop(r); } ++ ++ void push(Register r ) { ((MacroAssembler*)this)->push(r); } ++ ++ void pop(TosState state); // transition vtos -> state ++ void push(TosState state); // transition state -> vtos ++ ++ void empty_expression_stack() { ++ ld(SP, FP, frame::interpreter_frame_monitor_block_top_offset * wordSize); ++ // NULL last_sp until next java call ++ sd(R0, FP, frame::interpreter_frame_last_sp_offset * wordSize); ++ } ++ ++ // Super call_VM calls - correspond to MacroAssembler::call_VM(_leaf) calls ++ void load_ptr(int n, Register val); ++ void store_ptr(int n, Register val); ++ ++ // Generate a subtype check: branch to ok_is_subtype if sub_klass is ++ // a subtype of super_klass. ++ //void gen_subtype_check( Register sub_klass, Label &ok_is_subtype ); ++ void gen_subtype_check( Register Rsup_klass, Register sub_klass, Label &ok_is_subtype ); ++ ++ // Dispatching ++ void dispatch_prolog(TosState state, int step = 0); ++ void dispatch_epilog(TosState state, int step = 0); ++ void dispatch_only(TosState state, bool generate_poll = false); ++ void dispatch_only_normal(TosState state); ++ void dispatch_only_noverify(TosState state); ++ void dispatch_next(TosState state, int step = 0, bool generate_poll = false); ++ void dispatch_via (TosState state, address* table); ++ ++ // jump to an invoked target ++ void prepare_to_jump_from_interpreted(); ++ void jump_from_interpreted(Register method, Register temp); ++ ++ ++ // Returning from interpreted functions ++ // ++ // Removes the current activation (incl. unlocking of monitors) ++ // and sets up the return address. This code is also used for ++ // exception unwindwing. In that case, we do not want to throw ++ // IllegalMonitorStateExceptions, since that might get us into an ++ // infinite rethrow exception loop. ++ // Additionally this code is used for popFrame and earlyReturn. ++ // In popFrame case we want to skip throwing an exception, ++ // installing an exception, and notifying jvmdi. ++ // In earlyReturn case we only want to skip throwing an exception ++ // and installing an exception. ++ void remove_activation(TosState state, Register ret_addr, ++ bool throw_monitor_exception = true, ++ bool install_monitor_exception = true, ++ bool notify_jvmdi = true); ++#endif // CC_INTERP ++ ++ // Object locking ++ void lock_object (Register lock_reg); ++ void unlock_object(Register lock_reg); ++ ++#ifndef CC_INTERP ++ ++ // Interpreter profiling operations ++ void set_method_data_pointer_for_bcp(); ++ void test_method_data_pointer(Register mdp, Label& zero_continue); ++ void verify_method_data_pointer(); ++ ++ void set_mdp_data_at(Register mdp_in, int constant, Register value); ++ void increment_mdp_data_at(Address data, bool decrement = false); ++ void increment_mdp_data_at(Register mdp_in, int constant, ++ bool decrement = false); ++ void increment_mdp_data_at(Register mdp_in, Register reg, int constant, ++ bool decrement = false); ++ void increment_mask_and_jump(Address counter_addr, ++ int increment, int mask, ++ Register scratch, bool preloaded, ++ Condition cond, Label* where); ++ void set_mdp_flag_at(Register mdp_in, int flag_constant); ++ void test_mdp_data_at(Register mdp_in, int offset, Register value, ++ Register test_value_out, ++ Label& not_equal_continue); ++ ++ void record_klass_in_profile(Register receiver, Register mdp, ++ Register reg2, bool is_virtual_call); ++ void record_klass_in_profile_helper(Register receiver, Register mdp, ++ Register reg2, int start_row, ++ Label& done, bool is_virtual_call); ++ ++ void update_mdp_by_offset(Register mdp_in, int offset_of_offset); ++ void update_mdp_by_offset(Register mdp_in, Register reg, int offset_of_disp); ++ void update_mdp_by_constant(Register mdp_in, int constant); ++ void update_mdp_for_ret(Register return_bci); ++ ++ void profile_taken_branch(Register mdp, Register bumped_count); ++ void profile_not_taken_branch(Register mdp); ++ void profile_call(Register mdp); ++ void profile_final_call(Register mdp); ++ void profile_virtual_call(Register receiver, Register mdp, ++ Register scratch2, ++ bool receiver_can_be_null = false); ++ void profile_called_method(Register method, Register mdp, Register reg2) NOT_JVMCI_RETURN; ++ void profile_ret(Register return_bci, Register mdp); ++ void profile_null_seen(Register mdp); ++ void profile_typecheck(Register mdp, Register klass, Register scratch); ++ void profile_typecheck_failed(Register mdp); ++ void profile_switch_default(Register mdp); ++ void profile_switch_case(Register index_in_scratch, Register mdp, ++ Register scratch2); ++ ++ // Debugging ++ // only if +VerifyOops && state == atos ++ void verify_oop(Register reg, TosState state = atos); ++ // only if +VerifyFPU && (state == ftos || state == dtos) ++ void verify_FPU(int stack_depth, TosState state = ftos); ++ ++ void profile_obj_type(Register obj, const Address& mdo_addr); ++ void profile_arguments_type(Register mdp, Register callee, Register tmp, bool is_virtual); ++ void profile_return_type(Register mdp, Register ret, Register tmp); ++ void profile_parameters_type(Register mdp, Register tmp1, Register tmp2); ++#endif // !CC_INTERP ++ ++ typedef enum { NotifyJVMTI, SkipNotifyJVMTI } NotifyMethodExitMode; ++ ++ // support for jvmti/dtrace ++ void notify_method_entry(); ++ void notify_method_exit(TosState state, NotifyMethodExitMode mode); ++}; ++ ++#endif // CPU_MIPS_VM_INTERP_MASM_MIPS_64_HPP +diff --git a/src/hotspot/cpu/mips/interp_masm_mips_64.cpp b/src/hotspot/cpu/mips/interp_masm_mips_64.cpp +new file mode 100644 +index 000000000..eb35bb063 +--- /dev/null ++++ b/src/hotspot/cpu/mips/interp_masm_mips_64.cpp +@@ -0,0 +1,2126 @@ +/* + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, Loongson Technology. All rights reserved. @@ -64930,6 +71063,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/inter +#include "prims/jvmtiThreadState.hpp" +#include "runtime/basicLock.hpp" +#include "runtime/biasedLocking.hpp" ++#include "runtime/frame.inline.hpp" +#include "runtime/safepointMechanism.hpp" +#include "runtime/sharedRuntime.hpp" +#include "runtime/thread.inline.hpp" @@ -67016,13 +73150,15 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/inter + unimplemented(); + } +} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/interp_masm_mips.hpp jdk11u-ls/src/hotspot/cpu/mips/interp_masm_mips.hpp ---- openjdk/src/hotspot/cpu/mips/interp_masm_mips.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/interp_masm_mips.hpp 2023-09-12 13:54:23.097571667 +0800 -@@ -0,0 +1,276 @@ +diff --git a/src/hotspot/cpu/mips/interpreterRT_mips.hpp b/src/hotspot/cpu/mips/interpreterRT_mips.hpp +new file mode 100644 +index 000000000..054138ea4 +--- /dev/null ++++ b/src/hotspot/cpu/mips/interpreterRT_mips.hpp +@@ -0,0 +1,60 @@ +/* -+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2020, Loongson Technology. All rights reserved. ++ * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2015, 2022, Loongson Technology. 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 @@ -67045,261 +73181,47 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/inter + * + */ + -+#ifndef CPU_MIPS_VM_INTERP_MASM_MIPS_64_HPP -+#define CPU_MIPS_VM_INTERP_MASM_MIPS_64_HPP -+ -+#include "asm/assembler.hpp" -+#include "asm/macroAssembler.hpp" -+#include "asm/macroAssembler.inline.hpp" -+#include "interpreter/invocationCounter.hpp" -+#include "runtime/frame.hpp" ++#ifndef CPU_MIPS_VM_INTERPRETERRT_MIPS_HPP ++#define CPU_MIPS_VM_INTERPRETERRT_MIPS_HPP + -+// This file specializes the assember with interpreter-specific macros ++// This is included in the middle of class Interpreter. ++// Do not include files here. + ++// native method calls + -+class InterpreterMacroAssembler: public MacroAssembler { -+#ifndef CC_INTERP ++class SignatureHandlerGenerator: public NativeSignatureIterator { + private: ++ MacroAssembler* _masm; + -+ Register _locals_register; // register that contains the pointer to the locals -+ Register _bcp_register; // register that contains the bcp -+ -+ protected: -+ // Interpreter specific version of call_VM_base -+ virtual void call_VM_leaf_base(address entry_point, -+ int number_of_arguments); -+ -+ virtual void call_VM_base(Register oop_result, -+ Register java_thread, -+ Register last_java_sp, -+ address entry_point, -+ int number_of_arguments, -+ bool check_exceptions); ++ void move(int from_offset, int to_offset); + -+ // base routine for all dispatches -+ void dispatch_base(TosState state, address* table, bool verifyoop = true, bool generate_poll = false); -+#endif // CC_INTERP ++ void box(int from_offset, int to_offset); ++ void pass_int(); ++ void pass_long(); ++ void pass_object(); ++ void pass_float(); ++ void pass_double(); + + public: -+ void jump_to_entry(address entry); -+ // narrow int return value -+ void narrow(Register result); -+ -+ InterpreterMacroAssembler(CodeBuffer* code) : MacroAssembler(code), _locals_register(LVP), _bcp_register(BCP) {} -+ -+ void get_2_byte_integer_at_bcp(Register reg, Register tmp, int offset); -+ void get_4_byte_integer_at_bcp(Register reg, Register tmp, int offset); -+ -+ virtual void check_and_handle_popframe(Register java_thread); -+ virtual void check_and_handle_earlyret(Register java_thread); -+ -+ void load_earlyret_value(TosState state); -+ -+#ifdef CC_INTERP -+ void save_bcp() { /* not needed in c++ interpreter and harmless */ } -+ void restore_bcp() { /* not needed in c++ interpreter and harmless */ } -+ -+ // Helpers for runtime call arguments/results -+ void get_method(Register reg); -+ -+#else -+ -+ // Interpreter-specific registers -+ void save_bcp() { -+ sd(BCP, FP, frame::interpreter_frame_bcp_offset * wordSize); -+ } -+ -+ void restore_bcp() { -+ ld(BCP, FP, frame::interpreter_frame_bcp_offset * wordSize); -+ } -+ -+ void restore_locals() { -+ ld(LVP, FP, frame::interpreter_frame_locals_offset * wordSize); -+ } -+ -+ // Helpers for runtime call arguments/results -+ void get_method(Register reg) { -+ ld(reg, FP, frame::interpreter_frame_method_offset * wordSize); -+ } -+ -+ void get_const(Register reg){ -+ get_method(reg); -+ ld(reg, reg, in_bytes(Method::const_offset())); -+ } -+ -+ void get_constant_pool(Register reg) { -+ get_const(reg); -+ ld(reg, reg, in_bytes(ConstMethod::constants_offset())); -+ } -+ -+ void get_constant_pool_cache(Register reg) { -+ get_constant_pool(reg); -+ ld(reg, reg, ConstantPool::cache_offset_in_bytes()); -+ } -+ -+ void get_cpool_and_tags(Register cpool, Register tags) { -+ get_constant_pool(cpool); -+ ld(tags, cpool, ConstantPool::tags_offset_in_bytes()); -+ } -+ -+ void get_unsigned_2_byte_index_at_bcp(Register reg, int bcp_offset); -+ void get_cache_and_index_at_bcp(Register cache, Register index, int bcp_offset, size_t index_size = sizeof(u2)); -+ void get_cache_and_index_and_bytecode_at_bcp(Register cache, Register index, Register bytecode, int byte_no, int bcp_offset, size_t index_size = sizeof(u2)); -+ void get_cache_entry_pointer_at_bcp(Register cache, Register tmp, int bcp_offset, size_t index_size = sizeof(u2)); -+ void get_cache_index_at_bcp(Register index, int bcp_offset, size_t index_size = sizeof(u2)); -+ void get_method_counters(Register method, Register mcs, Label& skip); -+ -+ // load cpool->resolved_references(index); -+ void load_resolved_reference_at_index(Register result, Register index, Register tmp); -+ -+ // load cpool->resolved_klass_at(index) -+ void load_resolved_klass_at_index(Register cpool, // the constant pool (corrupted on return) -+ Register index, // the constant pool index (corrupted on return) -+ Register klass); // contains the Klass on return -+ -+ void pop_ptr( Register r = FSR); -+ void pop_i( Register r = FSR); -+ void pop_l( Register r = FSR); -+ void pop_f(FloatRegister r = FSF); -+ void pop_d(FloatRegister r = FSF); -+ -+ void push_ptr( Register r = FSR); -+ void push_i( Register r = FSR); -+ void push_l( Register r = FSR); -+ void push_f(FloatRegister r = FSF); -+ void push_d(FloatRegister r = FSF); -+ -+ void pop(Register r ) { ((MacroAssembler*)this)->pop(r); } -+ -+ void push(Register r ) { ((MacroAssembler*)this)->push(r); } -+ -+ void pop(TosState state); // transition vtos -> state -+ void push(TosState state); // transition state -> vtos -+ -+ void empty_expression_stack() { -+ ld(SP, FP, frame::interpreter_frame_monitor_block_top_offset * wordSize); -+ // NULL last_sp until next java call -+ sd(R0, FP, frame::interpreter_frame_last_sp_offset * wordSize); -+ } -+ -+ // Super call_VM calls - correspond to MacroAssembler::call_VM(_leaf) calls -+ void load_ptr(int n, Register val); -+ void store_ptr(int n, Register val); -+ -+ // Generate a subtype check: branch to ok_is_subtype if sub_klass is -+ // a subtype of super_klass. -+ //void gen_subtype_check( Register sub_klass, Label &ok_is_subtype ); -+ void gen_subtype_check( Register Rsup_klass, Register sub_klass, Label &ok_is_subtype ); -+ -+ // Dispatching -+ void dispatch_prolog(TosState state, int step = 0); -+ void dispatch_epilog(TosState state, int step = 0); -+ void dispatch_only(TosState state, bool generate_poll = false); -+ void dispatch_only_normal(TosState state); -+ void dispatch_only_noverify(TosState state); -+ void dispatch_next(TosState state, int step = 0, bool generate_poll = false); -+ void dispatch_via (TosState state, address* table); -+ -+ // jump to an invoked target -+ void prepare_to_jump_from_interpreted(); -+ void jump_from_interpreted(Register method, Register temp); -+ -+ -+ // Returning from interpreted functions -+ // -+ // Removes the current activation (incl. unlocking of monitors) -+ // and sets up the return address. This code is also used for -+ // exception unwindwing. In that case, we do not want to throw -+ // IllegalMonitorStateExceptions, since that might get us into an -+ // infinite rethrow exception loop. -+ // Additionally this code is used for popFrame and earlyReturn. -+ // In popFrame case we want to skip throwing an exception, -+ // installing an exception, and notifying jvmdi. -+ // In earlyReturn case we only want to skip throwing an exception -+ // and installing an exception. -+ void remove_activation(TosState state, Register ret_addr, -+ bool throw_monitor_exception = true, -+ bool install_monitor_exception = true, -+ bool notify_jvmdi = true); -+#endif // CC_INTERP -+ -+ // Object locking -+ void lock_object (Register lock_reg); -+ void unlock_object(Register lock_reg); -+ -+#ifndef CC_INTERP -+ -+ // Interpreter profiling operations -+ void set_method_data_pointer_for_bcp(); -+ void test_method_data_pointer(Register mdp, Label& zero_continue); -+ void verify_method_data_pointer(); -+ -+ void set_mdp_data_at(Register mdp_in, int constant, Register value); -+ void increment_mdp_data_at(Address data, bool decrement = false); -+ void increment_mdp_data_at(Register mdp_in, int constant, -+ bool decrement = false); -+ void increment_mdp_data_at(Register mdp_in, Register reg, int constant, -+ bool decrement = false); -+ void increment_mask_and_jump(Address counter_addr, -+ int increment, int mask, -+ Register scratch, bool preloaded, -+ Condition cond, Label* where); -+ void set_mdp_flag_at(Register mdp_in, int flag_constant); -+ void test_mdp_data_at(Register mdp_in, int offset, Register value, -+ Register test_value_out, -+ Label& not_equal_continue); -+ -+ void record_klass_in_profile(Register receiver, Register mdp, -+ Register reg2, bool is_virtual_call); -+ void record_klass_in_profile_helper(Register receiver, Register mdp, -+ Register reg2, int start_row, -+ Label& done, bool is_virtual_call); -+ -+ void update_mdp_by_offset(Register mdp_in, int offset_of_offset); -+ void update_mdp_by_offset(Register mdp_in, Register reg, int offset_of_disp); -+ void update_mdp_by_constant(Register mdp_in, int constant); -+ void update_mdp_for_ret(Register return_bci); -+ -+ void profile_taken_branch(Register mdp, Register bumped_count); -+ void profile_not_taken_branch(Register mdp); -+ void profile_call(Register mdp); -+ void profile_final_call(Register mdp); -+ void profile_virtual_call(Register receiver, Register mdp, -+ Register scratch2, -+ bool receiver_can_be_null = false); -+ void profile_called_method(Register method, Register mdp, Register reg2) NOT_JVMCI_RETURN; -+ void profile_ret(Register return_bci, Register mdp); -+ void profile_null_seen(Register mdp); -+ void profile_typecheck(Register mdp, Register klass, Register scratch); -+ void profile_typecheck_failed(Register mdp); -+ void profile_switch_default(Register mdp); -+ void profile_switch_case(Register index_in_scratch, Register mdp, -+ Register scratch2); -+ -+ // Debugging -+ // only if +VerifyOops && state == atos -+ void verify_oop(Register reg, TosState state = atos); -+ // only if +VerifyFPU && (state == ftos || state == dtos) -+ void verify_FPU(int stack_depth, TosState state = ftos); -+ -+ void profile_obj_type(Register obj, const Address& mdo_addr); -+ void profile_arguments_type(Register mdp, Register callee, Register tmp, bool is_virtual); -+ void profile_return_type(Register mdp, Register ret, Register tmp); -+ void profile_parameters_type(Register mdp, Register tmp1, Register tmp2); -+#endif // !CC_INTERP ++ // Creation ++ SignatureHandlerGenerator(const methodHandle& method, CodeBuffer* buffer); + -+ typedef enum { NotifyJVMTI, SkipNotifyJVMTI } NotifyMethodExitMode; ++ // Code generation ++ void generate(uint64_t fingerprint); + -+ // support for jvmti/dtrace -+ void notify_method_entry(); -+ void notify_method_exit(TosState state, NotifyMethodExitMode mode); ++ // Code generation support ++ static Register from(); ++ static Register to(); ++ static Register temp(); +}; + -+#endif // CPU_MIPS_VM_INTERP_MASM_MIPS_64_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/interpreterRT_mips_64.cpp jdk11u-ls/src/hotspot/cpu/mips/interpreterRT_mips_64.cpp ---- openjdk/src/hotspot/cpu/mips/interpreterRT_mips_64.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/interpreterRT_mips_64.cpp 2023-11-01 09:34:25.493945267 +0800 -@@ -0,0 +1,247 @@ ++#endif // CPU_MIPS_VM_INTERPRETERRT_MIPS_HPP +diff --git a/src/hotspot/cpu/mips/interpreterRT_mips_64.cpp b/src/hotspot/cpu/mips/interpreterRT_mips_64.cpp +new file mode 100644 +index 000000000..e655b2a1a +--- /dev/null ++++ b/src/hotspot/cpu/mips/interpreterRT_mips_64.cpp +@@ -0,0 +1,252 @@ +/* + * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, Loongson Technology. All rights reserved. @@ -67326,6 +73248,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/inter + */ + +#include "precompiled.hpp" ++#include "interpreter/interp_masm.hpp" +#include "interpreter/interpreter.hpp" +#include "interpreter/interpreterRuntime.hpp" +#include "memory/allocation.inline.hpp" @@ -67347,6 +73270,10 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/inter +#define T9 RT9 + +// Implementation of SignatureHandlerGenerator ++InterpreterRuntime::SignatureHandlerGenerator::SignatureHandlerGenerator( ++ const methodHandle& method, CodeBuffer* buffer) : NativeSignatureIterator(method) { ++ _masm = new MacroAssembler(buffer); ++} + +void InterpreterRuntime::SignatureHandlerGenerator::move(int from_offset, int to_offset) { + __ ld(temp(), from(), Interpreter::local_offset_in_bytes(from_offset)); @@ -67547,74 +73474,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/inter + // return result handler + return Interpreter::result_handler(m->result_type()); +IRT_END -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/interpreterRT_mips.hpp jdk11u-ls/src/hotspot/cpu/mips/interpreterRT_mips.hpp ---- openjdk/src/hotspot/cpu/mips/interpreterRT_mips.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/interpreterRT_mips.hpp 2023-11-01 09:34:25.493945267 +0800 -@@ -0,0 +1,61 @@ -+/* -+ * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2022, Loongson Technology. 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 CPU_MIPS_VM_INTERPRETERRT_MIPS_HPP -+#define CPU_MIPS_VM_INTERPRETERRT_MIPS_HPP -+ -+#include "memory/allocation.hpp" -+ -+// native method calls -+ -+class SignatureHandlerGenerator: public NativeSignatureIterator { -+ private: -+ MacroAssembler* _masm; -+ -+ void move(int from_offset, int to_offset); -+ -+ void box(int from_offset, int to_offset); -+ void pass_int(); -+ void pass_long(); -+ void pass_object(); -+ void pass_float(); -+ void pass_double(); -+ -+ public: -+ // Creation -+ SignatureHandlerGenerator(methodHandle method, CodeBuffer* buffer) : NativeSignatureIterator(method) { -+ _masm = new MacroAssembler(buffer); -+ } -+ -+ // Code generation -+ void generate(uint64_t fingerprint); -+ -+ // Code generation support -+ static Register from(); -+ static Register to(); -+ static Register temp(); -+}; -+ -+#endif // CPU_MIPS_VM_INTERPRETERRT_MIPS_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/javaFrameAnchor_mips.hpp jdk11u-ls/src/hotspot/cpu/mips/javaFrameAnchor_mips.hpp ---- openjdk/src/hotspot/cpu/mips/javaFrameAnchor_mips.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/javaFrameAnchor_mips.hpp 2023-09-12 13:54:23.101571672 +0800 +diff --git a/src/hotspot/cpu/mips/javaFrameAnchor_mips.hpp b/src/hotspot/cpu/mips/javaFrameAnchor_mips.hpp +new file mode 100644 +index 000000000..dccdf6a01 +--- /dev/null ++++ b/src/hotspot/cpu/mips/javaFrameAnchor_mips.hpp @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. @@ -67703,10 +73567,12 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/javaF + void set_last_Java_fp(intptr_t* fp) { _last_Java_fp = fp; } + +#endif // CPU_MIPS_VM_JAVAFRAMEANCHOR_MIPS_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/jniFastGetField_mips_64.cpp jdk11u-ls/src/hotspot/cpu/mips/jniFastGetField_mips_64.cpp ---- openjdk/src/hotspot/cpu/mips/jniFastGetField_mips_64.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/jniFastGetField_mips_64.cpp 2023-11-01 09:34:25.493945267 +0800 -@@ -0,0 +1,166 @@ +diff --git a/src/hotspot/cpu/mips/jniFastGetField_mips_64.cpp b/src/hotspot/cpu/mips/jniFastGetField_mips_64.cpp +new file mode 100644 +index 000000000..bba5b7eee +--- /dev/null ++++ b/src/hotspot/cpu/mips/jniFastGetField_mips_64.cpp +@@ -0,0 +1,167 @@ +/* + * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2021, Loongson Technology. All rights reserved. @@ -67734,6 +73600,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/jniFa + +#include "precompiled.hpp" +#include "asm/macroAssembler.hpp" ++#include "code/codeBlob.hpp" +#include "gc/shared/barrierSet.hpp" +#include "gc/shared/barrierSetAssembler.hpp" +#include "memory/resourceArea.hpp" @@ -67873,9 +73740,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/jniFa +address JNI_FastGetField::generate_fast_get_double_field() { + return generate_fast_get_int_field0(T_DOUBLE); +} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/jniTypes_mips.hpp jdk11u-ls/src/hotspot/cpu/mips/jniTypes_mips.hpp ---- openjdk/src/hotspot/cpu/mips/jniTypes_mips.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/jniTypes_mips.hpp 2023-09-12 13:54:23.101571672 +0800 +diff --git a/src/hotspot/cpu/mips/jniTypes_mips.hpp b/src/hotspot/cpu/mips/jniTypes_mips.hpp +new file mode 100644 +index 000000000..e93237ffd +--- /dev/null ++++ b/src/hotspot/cpu/mips/jniTypes_mips.hpp @@ -0,0 +1,144 @@ +/* + * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. @@ -68021,10 +73890,12 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/jniTy +}; + +#endif // CPU_MIPS_VM_JNITYPES_MIPS_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/macroAssembler_mips.cpp jdk11u-ls/src/hotspot/cpu/mips/macroAssembler_mips.cpp ---- openjdk/src/hotspot/cpu/mips/macroAssembler_mips.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/macroAssembler_mips.cpp 2023-11-01 09:34:25.497945271 +0800 -@@ -0,0 +1,4249 @@ +diff --git a/src/hotspot/cpu/mips/macroAssembler_mips.cpp b/src/hotspot/cpu/mips/macroAssembler_mips.cpp +new file mode 100644 +index 000000000..cc868cae5 +--- /dev/null ++++ b/src/hotspot/cpu/mips/macroAssembler_mips.cpp +@@ -0,0 +1,4257 @@ +/* + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2022, Loongson Technology. All rights reserved. @@ -68074,6 +73945,10 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/macro +#include "runtime/stubRoutines.hpp" +#include "utilities/macros.hpp" + ++#ifdef COMPILER2 ++#include "opto/intrinsicnode.hpp" ++#endif ++ +#define T0 RT0 +#define T1 RT1 +#define T2 RT2 @@ -70232,6 +76107,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/macro + sub_d(fd, fs, tmp); +} + ++#ifdef COMPILER2 +// Fast_Lock and Fast_Unlock used by C2 + +// Because the transitions from emitted code to the runtime @@ -70616,6 +76492,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/macro + if (EmitSync & 32768) { nop() ; } + } +} ++#endif // COMPILER2 + +void MacroAssembler::align(int modulus) { + while (offset() % modulus != 0) nop(); @@ -71703,6 +77580,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/macro + return code_offset; +} + ++#ifdef COMPILER2 +// Compare strings, used for char[] and byte[]. +void MacroAssembler::string_compare(Register str1, Register str2, + Register cnt1, Register cnt2, Register result, @@ -71789,6 +77667,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/macro + + bind(True); +} ++#endif // COMPILER2 + +void MacroAssembler::load_for_type_by_register(FloatRegister dst_reg, Register tmp_reg, int disp, BasicType type) { + switch (type) { @@ -72274,10 +78153,12 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/macro + ShouldNotReachHere(); + } +} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/macroAssembler_mips.hpp jdk11u-ls/src/hotspot/cpu/mips/macroAssembler_mips.hpp ---- openjdk/src/hotspot/cpu/mips/macroAssembler_mips.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/macroAssembler_mips.hpp 2023-11-01 09:34:25.497945271 +0800 -@@ -0,0 +1,816 @@ +diff --git a/src/hotspot/cpu/mips/macroAssembler_mips.hpp b/src/hotspot/cpu/mips/macroAssembler_mips.hpp +new file mode 100644 +index 000000000..55ec29e91 +--- /dev/null ++++ b/src/hotspot/cpu/mips/macroAssembler_mips.hpp +@@ -0,0 +1,818 @@ +/* + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, Loongson Technology. All rights reserved. @@ -72920,6 +78801,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/macro + //FIXME + void empty_FPU_stack(){/*need implemented*/}; + ++#ifdef COMPILER2 + // Compare strings. + void string_compare(Register str1, Register str2, + Register cnt1, Register cnt2, Register result, @@ -72929,6 +78811,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/macro + void arrays_equals(Register str1, Register str2, + Register cnt, Register tmp, Register result, + bool is_char); ++#endif + + // method handles (JSR 292) + Address argument_address(RegisterOrConstant arg_slot, int extra_slot_offset = 0); @@ -73094,9 +78977,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/macro + + +#endif // CPU_MIPS_VM_MACROASSEMBLER_MIPS_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/macroAssembler_mips.inline.hpp jdk11u-ls/src/hotspot/cpu/mips/macroAssembler_mips.inline.hpp ---- openjdk/src/hotspot/cpu/mips/macroAssembler_mips.inline.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/macroAssembler_mips.inline.hpp 2023-09-12 13:54:23.101571672 +0800 +diff --git a/src/hotspot/cpu/mips/macroAssembler_mips.inline.hpp b/src/hotspot/cpu/mips/macroAssembler_mips.inline.hpp +new file mode 100644 +index 000000000..92c05fb72 +--- /dev/null ++++ b/src/hotspot/cpu/mips/macroAssembler_mips.inline.hpp @@ -0,0 +1,34 @@ +/* + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. @@ -73132,10 +79017,12 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/macro +#include "code/codeCache.hpp" + +#endif // CPU_MIPS_VM_MACROASSEMBLER_MIPS_INLINE_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/methodHandles_mips.cpp jdk11u-ls/src/hotspot/cpu/mips/methodHandles_mips.cpp ---- openjdk/src/hotspot/cpu/mips/methodHandles_mips.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/methodHandles_mips.cpp 2023-11-01 09:34:25.497945271 +0800 -@@ -0,0 +1,574 @@ +diff --git a/src/hotspot/cpu/mips/methodHandles_mips.cpp b/src/hotspot/cpu/mips/methodHandles_mips.cpp +new file mode 100644 +index 000000000..e9788ac52 +--- /dev/null ++++ b/src/hotspot/cpu/mips/methodHandles_mips.cpp +@@ -0,0 +1,576 @@ +/* + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, Loongson Technology. All rights reserved. @@ -73168,6 +79055,8 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/metho +#include "interpreter/interpreterRuntime.hpp" +#include "memory/allocation.inline.hpp" +#include "prims/methodHandles.hpp" ++#include "runtime/frame.inline.hpp" ++#include "utilities/preserveException.hpp" + +#define __ _masm-> + @@ -73710,9 +79599,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/metho +void MethodHandles::trace_method_handle(MacroAssembler* _masm, const char* adaptername) { +} +#endif //PRODUCT -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/methodHandles_mips.hpp jdk11u-ls/src/hotspot/cpu/mips/methodHandles_mips.hpp ---- openjdk/src/hotspot/cpu/mips/methodHandles_mips.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/methodHandles_mips.hpp 2023-09-12 13:54:23.101571672 +0800 +diff --git a/src/hotspot/cpu/mips/methodHandles_mips.hpp b/src/hotspot/cpu/mips/methodHandles_mips.hpp +new file mode 100644 +index 000000000..03b65fc8e +--- /dev/null ++++ b/src/hotspot/cpu/mips/methodHandles_mips.hpp @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. @@ -73776,9 +79667,42 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/metho + // Should be in sharedRuntime, not here. + return I29; + } -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/mips_64.ad jdk11u-ls/src/hotspot/cpu/mips/mips_64.ad ---- openjdk/src/hotspot/cpu/mips/mips_64.ad 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/mips_64.ad 2023-09-12 13:54:23.101571672 +0800 +diff --git a/src/hotspot/cpu/mips/mips.ad b/src/hotspot/cpu/mips/mips.ad +new file mode 100644 +index 000000000..3563bbe0e +--- /dev/null ++++ b/src/hotspot/cpu/mips/mips.ad +@@ -0,0 +1,25 @@ ++// ++// Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. ++// Copyright (c) 2015, 2016, Loongson Technology. 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. ++// ++// ++ +diff --git a/src/hotspot/cpu/mips/mips_64.ad b/src/hotspot/cpu/mips/mips_64.ad +new file mode 100644 +index 000000000..b4acbd83f +--- /dev/null ++++ b/src/hotspot/cpu/mips/mips_64.ad @@ -0,0 +1,12243 @@ +// +// Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. @@ -86023,39 +91947,12 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/mips_ +// These must follow all instruction definitions as they use the names +// defined in the instructions definitions. + -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/mips.ad jdk11u-ls/src/hotspot/cpu/mips/mips.ad ---- openjdk/src/hotspot/cpu/mips/mips.ad 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/mips.ad 2023-09-12 13:54:23.101571672 +0800 -@@ -0,0 +1,25 @@ -+// -+// Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. -+// Copyright (c) 2015, 2016, Loongson Technology. 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. -+// -+// -+ -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/nativeInst_mips.cpp jdk11u-ls/src/hotspot/cpu/mips/nativeInst_mips.cpp ---- openjdk/src/hotspot/cpu/mips/nativeInst_mips.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/nativeInst_mips.cpp 2023-11-01 09:34:25.497945271 +0800 -@@ -0,0 +1,1820 @@ +diff --git a/src/hotspot/cpu/mips/nativeInst_mips.cpp b/src/hotspot/cpu/mips/nativeInst_mips.cpp +new file mode 100644 +index 000000000..96a147eaa +--- /dev/null ++++ b/src/hotspot/cpu/mips/nativeInst_mips.cpp +@@ -0,0 +1,1821 @@ +/* + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, Loongson Technology. All rights reserved. @@ -86084,6 +91981,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/nativ +#include "precompiled.hpp" +#include "asm/macroAssembler.hpp" +#include "compiler/disassembler.hpp" ++#include "code/codeCache.hpp" +#include "code/compiledIC.hpp" +#include "memory/resourceArea.hpp" +#include "nativeInst_mips.hpp" @@ -87876,10 +93774,12 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/nativ + // we check the safepoint instruction like the this. + return is_op(Assembler::lw_op) && is_rt(AT); +} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/nativeInst_mips.hpp jdk11u-ls/src/hotspot/cpu/mips/nativeInst_mips.hpp ---- openjdk/src/hotspot/cpu/mips/nativeInst_mips.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/nativeInst_mips.hpp 2023-11-01 09:34:25.497945271 +0800 -@@ -0,0 +1,733 @@ +diff --git a/src/hotspot/cpu/mips/nativeInst_mips.hpp b/src/hotspot/cpu/mips/nativeInst_mips.hpp +new file mode 100644 +index 000000000..fb4f99c9c +--- /dev/null ++++ b/src/hotspot/cpu/mips/nativeInst_mips.hpp +@@ -0,0 +1,734 @@ +/* + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, Loongson Technology. All rights reserved. @@ -87909,6 +93809,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/nativ +#define CPU_MIPS_VM_NATIVEINST_MIPS_HPP + +#include "asm/assembler.hpp" ++#include "asm/macroAssembler.hpp" +#include "runtime/icache.hpp" +#include "runtime/os.hpp" +#include "runtime/safepointMechanism.hpp" @@ -88613,9 +94514,64 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/nativ + return (NativeCallTrampolineStub*)addr; +} +#endif // CPU_MIPS_VM_NATIVEINST_MIPS_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/register_definitions_mips.cpp jdk11u-ls/src/hotspot/cpu/mips/register_definitions_mips.cpp ---- openjdk/src/hotspot/cpu/mips/register_definitions_mips.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/register_definitions_mips.cpp 2023-09-12 13:54:23.101571672 +0800 +diff --git a/src/hotspot/cpu/mips/registerMap_mips.hpp b/src/hotspot/cpu/mips/registerMap_mips.hpp +new file mode 100644 +index 000000000..7f800eb10 +--- /dev/null ++++ b/src/hotspot/cpu/mips/registerMap_mips.hpp +@@ -0,0 +1,47 @@ ++/* ++ * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2015, 2016, Loongson Technology. 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 CPU_MIPS_VM_REGISTERMAP_MIPS_HPP ++#define CPU_MIPS_VM_REGISTERMAP_MIPS_HPP ++ ++// machine-dependent implemention for register maps ++ friend class frame; ++ ++ private: ++#ifndef CORE ++ // This is the hook for finding a register in an "well-known" location, ++ // such as a register block of a predetermined format. ++ // Since there is none, we just return NULL. ++ // See registerMap_sparc.hpp for an example of grabbing registers ++ // from register save areas of a standard layout. ++ address pd_location(VMReg reg) const {return NULL;} ++#endif ++ ++ // no PD state to clear or copy: ++ void pd_clear() {} ++ void pd_initialize() {} ++ void pd_initialize_from(const RegisterMap* map) {} ++ ++#endif // CPU_MIPS_VM_REGISTERMAP_MIPS_HPP +diff --git a/src/hotspot/cpu/mips/register_definitions_mips.cpp b/src/hotspot/cpu/mips/register_definitions_mips.cpp +new file mode 100644 +index 000000000..4af253183 +--- /dev/null ++++ b/src/hotspot/cpu/mips/register_definitions_mips.cpp @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. @@ -88720,60 +94676,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/regis +REGISTER_DEFINITION(FloatRegister, f29); +REGISTER_DEFINITION(FloatRegister, f30); +REGISTER_DEFINITION(FloatRegister, f31); -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/registerMap_mips.hpp jdk11u-ls/src/hotspot/cpu/mips/registerMap_mips.hpp ---- openjdk/src/hotspot/cpu/mips/registerMap_mips.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/registerMap_mips.hpp 2023-09-12 13:54:23.101571672 +0800 -@@ -0,0 +1,47 @@ -+/* -+ * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2016, Loongson Technology. 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 CPU_MIPS_VM_REGISTERMAP_MIPS_HPP -+#define CPU_MIPS_VM_REGISTERMAP_MIPS_HPP -+ -+// machine-dependent implemention for register maps -+ friend class frame; -+ -+ private: -+#ifndef CORE -+ // This is the hook for finding a register in an "well-known" location, -+ // such as a register block of a predetermined format. -+ // Since there is none, we just return NULL. -+ // See registerMap_sparc.hpp for an example of grabbing registers -+ // from register save areas of a standard layout. -+ address pd_location(VMReg reg) const {return NULL;} -+#endif -+ -+ // no PD state to clear or copy: -+ void pd_clear() {} -+ void pd_initialize() {} -+ void pd_initialize_from(const RegisterMap* map) {} -+ -+#endif // CPU_MIPS_VM_REGISTERMAP_MIPS_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/register_mips.cpp jdk11u-ls/src/hotspot/cpu/mips/register_mips.cpp ---- openjdk/src/hotspot/cpu/mips/register_mips.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/register_mips.cpp 2023-09-12 13:54:23.101571672 +0800 +diff --git a/src/hotspot/cpu/mips/register_mips.cpp b/src/hotspot/cpu/mips/register_mips.cpp +new file mode 100644 +index 000000000..4a9b22bfe +--- /dev/null ++++ b/src/hotspot/cpu/mips/register_mips.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. @@ -88827,9 +94734,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/regis + return is_valid() ? names[encoding()] : "fnoreg"; +} + -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/register_mips.hpp jdk11u-ls/src/hotspot/cpu/mips/register_mips.hpp ---- openjdk/src/hotspot/cpu/mips/register_mips.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/register_mips.hpp 2023-09-12 13:54:23.101571672 +0800 +diff --git a/src/hotspot/cpu/mips/register_mips.hpp b/src/hotspot/cpu/mips/register_mips.hpp +new file mode 100644 +index 000000000..ea216fbcb +--- /dev/null ++++ b/src/hotspot/cpu/mips/register_mips.hpp @@ -0,0 +1,341 @@ +/* + * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. @@ -89172,10 +95081,12 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/regis +}; + +#endif //CPU_MIPS_VM_REGISTER_MIPS_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/relocInfo_mips.cpp jdk11u-ls/src/hotspot/cpu/mips/relocInfo_mips.cpp ---- openjdk/src/hotspot/cpu/mips/relocInfo_mips.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/relocInfo_mips.cpp 2023-11-01 09:34:25.497945271 +0800 -@@ -0,0 +1,158 @@ +diff --git a/src/hotspot/cpu/mips/relocInfo_mips.cpp b/src/hotspot/cpu/mips/relocInfo_mips.cpp +new file mode 100644 +index 000000000..ff8028032 +--- /dev/null ++++ b/src/hotspot/cpu/mips/relocInfo_mips.cpp +@@ -0,0 +1,160 @@ +/* + * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, Loongson Technology. All rights reserved. @@ -89204,9 +95115,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/reloc +#include "precompiled.hpp" +#include "asm/macroAssembler.hpp" +#include "code/relocInfo.hpp" ++#include "compiler/disassembler.hpp" +#include "nativeInst_mips.hpp" +#include "oops/compressedOops.inline.hpp" +#include "oops/oop.hpp" ++#include "oops/oop.inline.hpp" +#include "runtime/safepoint.hpp" + + @@ -89334,9 +95247,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/reloc + +void metadata_Relocation::pd_fix_value(address x) { +} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/relocInfo_mips.hpp jdk11u-ls/src/hotspot/cpu/mips/relocInfo_mips.hpp ---- openjdk/src/hotspot/cpu/mips/relocInfo_mips.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/relocInfo_mips.hpp 2023-09-12 13:54:23.101571672 +0800 +diff --git a/src/hotspot/cpu/mips/relocInfo_mips.hpp b/src/hotspot/cpu/mips/relocInfo_mips.hpp +new file mode 100644 +index 000000000..1e1e170fd +--- /dev/null ++++ b/src/hotspot/cpu/mips/relocInfo_mips.hpp @@ -0,0 +1,44 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. @@ -89382,9 +95297,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/reloc + static bool mustIterateImmediateOopsInCode() { return false; } + +#endif // CPU_MIPS_VM_RELOCINFO_MIPS_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/runtime_mips_64.cpp jdk11u-ls/src/hotspot/cpu/mips/runtime_mips_64.cpp ---- openjdk/src/hotspot/cpu/mips/runtime_mips_64.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/runtime_mips_64.cpp 2023-09-12 13:54:23.101571672 +0800 +diff --git a/src/hotspot/cpu/mips/runtime_mips_64.cpp b/src/hotspot/cpu/mips/runtime_mips_64.cpp +new file mode 100644 +index 000000000..2a0488cd0 +--- /dev/null ++++ b/src/hotspot/cpu/mips/runtime_mips_64.cpp @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. @@ -89584,10 +95501,12 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/runti + + _exception_blob = ExceptionBlob::create(&buffer, oop_maps, framesize); +} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/sharedRuntime_mips_64.cpp jdk11u-ls/src/hotspot/cpu/mips/sharedRuntime_mips_64.cpp ---- openjdk/src/hotspot/cpu/mips/sharedRuntime_mips_64.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/sharedRuntime_mips_64.cpp 2023-11-01 09:34:25.497945271 +0800 -@@ -0,0 +1,3877 @@ +diff --git a/src/hotspot/cpu/mips/sharedRuntime_mips_64.cpp b/src/hotspot/cpu/mips/sharedRuntime_mips_64.cpp +new file mode 100644 +index 000000000..4a9791d4c +--- /dev/null ++++ b/src/hotspot/cpu/mips/sharedRuntime_mips_64.cpp +@@ -0,0 +1,3879 @@ +/* + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, Loongson Technology. All rights reserved. @@ -89618,9 +95537,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/share +#include "asm/macroAssembler.inline.hpp" +#include "code/debugInfoRec.hpp" +#include "code/icBuffer.hpp" ++#include "code/nativeInst.hpp" +#include "code/vtableStubs.hpp" +#include "interpreter/interpreter.hpp" +#include "oops/compiledICHolder.hpp" ++#include "oops/klass.inline.hpp" +#include "runtime/sharedRuntime.hpp" +#include "runtime/vframeArray.hpp" +#include "vmreg_mips.inline.hpp" @@ -93465,10 +99386,12 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/share + + reverse_words(m, (unsigned long *)m_ints, longwords); +} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/stubGenerator_mips_64.cpp jdk11u-ls/src/hotspot/cpu/mips/stubGenerator_mips_64.cpp ---- openjdk/src/hotspot/cpu/mips/stubGenerator_mips_64.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/stubGenerator_mips_64.cpp 2023-11-01 09:34:25.497945271 +0800 -@@ -0,0 +1,2160 @@ +diff --git a/src/hotspot/cpu/mips/stubGenerator_mips_64.cpp b/src/hotspot/cpu/mips/stubGenerator_mips_64.cpp +new file mode 100644 +index 000000000..9fe2bc837 +--- /dev/null ++++ b/src/hotspot/cpu/mips/stubGenerator_mips_64.cpp +@@ -0,0 +1,2162 @@ +/* + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, Loongson Technology. All rights reserved. @@ -95606,6 +101529,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/stubG + &StubRoutines::_safefetchN_fault_pc, + &StubRoutines::_safefetchN_continuation_pc); + ++#ifdef COMPILER2 + if (UseMontgomeryMultiplyIntrinsic) { + StubRoutines::_montgomeryMultiply + = CAST_FROM_FN_PTR(address, SharedRuntime::montgomery_multiply); @@ -95614,6 +101538,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/stubG + StubRoutines::_montgomerySquare + = CAST_FROM_FN_PTR(address, SharedRuntime::montgomery_square); + } ++#endif + } + + public: @@ -95629,48 +101554,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/stubG +void StubGenerator_generate(CodeBuffer* code, bool all) { + StubGenerator g(code, all); +} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/stubRoutines_mips_64.cpp jdk11u-ls/src/hotspot/cpu/mips/stubRoutines_mips_64.cpp ---- openjdk/src/hotspot/cpu/mips/stubRoutines_mips_64.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/stubRoutines_mips_64.cpp 2023-09-12 13:54:23.105571678 +0800 -@@ -0,0 +1,35 @@ -+/* -+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2021, Loongson Technology. 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/deoptimization.hpp" -+#include "runtime/frame.inline.hpp" -+#include "runtime/stubRoutines.hpp" -+#include "runtime/thread.inline.hpp" -+ -+// a description of how to extend it, see the stubRoutines.hpp file. -+ -+//find the last fp value -+address StubRoutines::gs2::_call_stub_compiled_return = NULL; -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/stubRoutines_mips.hpp jdk11u-ls/src/hotspot/cpu/mips/stubRoutines_mips.hpp ---- openjdk/src/hotspot/cpu/mips/stubRoutines_mips.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/stubRoutines_mips.hpp 2023-09-12 13:54:23.101571672 +0800 +diff --git a/src/hotspot/cpu/mips/stubRoutines_mips.hpp b/src/hotspot/cpu/mips/stubRoutines_mips.hpp +new file mode 100644 +index 000000000..920c08844 +--- /dev/null ++++ b/src/hotspot/cpu/mips/stubRoutines_mips.hpp @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. @@ -95731,10 +101619,53 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/stubR +}; + +#endif // CPU_MIPS_VM_STUBROUTINES_MIPS_64_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/templateInterpreterGenerator_mips.cpp jdk11u-ls/src/hotspot/cpu/mips/templateInterpreterGenerator_mips.cpp ---- openjdk/src/hotspot/cpu/mips/templateInterpreterGenerator_mips.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/templateInterpreterGenerator_mips.cpp 2023-11-01 09:34:25.501945276 +0800 -@@ -0,0 +1,2148 @@ +diff --git a/src/hotspot/cpu/mips/stubRoutines_mips_64.cpp b/src/hotspot/cpu/mips/stubRoutines_mips_64.cpp +new file mode 100644 +index 000000000..358d580d5 +--- /dev/null ++++ b/src/hotspot/cpu/mips/stubRoutines_mips_64.cpp +@@ -0,0 +1,35 @@ ++/* ++ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2015, 2021, Loongson Technology. 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/deoptimization.hpp" ++#include "runtime/frame.inline.hpp" ++#include "runtime/stubRoutines.hpp" ++#include "runtime/thread.inline.hpp" ++ ++// a description of how to extend it, see the stubRoutines.hpp file. ++ ++//find the last fp value ++address StubRoutines::gs2::_call_stub_compiled_return = NULL; +diff --git a/src/hotspot/cpu/mips/templateInterpreterGenerator_mips.cpp b/src/hotspot/cpu/mips/templateInterpreterGenerator_mips.cpp +new file mode 100644 +index 000000000..19e2f29c5 +--- /dev/null ++++ b/src/hotspot/cpu/mips/templateInterpreterGenerator_mips.cpp +@@ -0,0 +1,2149 @@ +/* + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, Loongson Technology. All rights reserved. @@ -95763,6 +101694,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/templ +#include "precompiled.hpp" +#include "asm/macroAssembler.hpp" +#include "interpreter/bytecodeHistogram.hpp" ++#include "interpreter/interp_masm.hpp" +#include "interpreter/interpreter.hpp" +#include "interpreter/interpreterRuntime.hpp" +#include "interpreter/templateInterpreterGenerator.hpp" @@ -97883,10 +103815,61 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/templ + __ bind(L); +} +#endif // !PRODUCT -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/templateTable_mips_64.cpp jdk11u-ls/src/hotspot/cpu/mips/templateTable_mips_64.cpp ---- openjdk/src/hotspot/cpu/mips/templateTable_mips_64.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/templateTable_mips_64.cpp 2023-11-01 09:34:25.501945276 +0800 -@@ -0,0 +1,4685 @@ +diff --git a/src/hotspot/cpu/mips/templateTable_mips.hpp b/src/hotspot/cpu/mips/templateTable_mips.hpp +new file mode 100644 +index 000000000..46a88aba2 +--- /dev/null ++++ b/src/hotspot/cpu/mips/templateTable_mips.hpp +@@ -0,0 +1,43 @@ ++/* ++ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2015, 2018, Loongson Technology. 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 CPU_MIPS_VM_TEMPLATETABLE_MIPS_64_HPP ++#define CPU_MIPS_VM_TEMPLATETABLE_MIPS_64_HPP ++ ++ static void prepare_invoke(int byte_no, ++ Register method, // linked method (or i-klass) ++ Register index = noreg, // itable index, MethodType, etc. ++ Register recv = noreg, // if caller wants to see it ++ Register flags = noreg // if caller wants to test it ++ ); ++ static void invokevirtual_helper(Register index, Register recv, ++ Register flags); ++ static void volatile_barrier(); ++ ++ // Helpers ++ static void index_check(Register array, Register index); ++ static void index_check_without_pop(Register array, Register index); ++ ++#endif // CPU_MIPS_VM_TEMPLATETABLE_MIPS_64_HPP +diff --git a/src/hotspot/cpu/mips/templateTable_mips_64.cpp b/src/hotspot/cpu/mips/templateTable_mips_64.cpp +new file mode 100644 +index 000000000..526548383 +--- /dev/null ++++ b/src/hotspot/cpu/mips/templateTable_mips_64.cpp +@@ -0,0 +1,4688 @@ +/* + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, Loongson Technology. All rights reserved. @@ -97916,12 +103899,14 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/templ +#include "asm/macroAssembler.hpp" +#include "interpreter/interpreter.hpp" +#include "interpreter/interpreterRuntime.hpp" ++#include "interpreter/interp_masm.hpp" +#include "interpreter/templateTable.hpp" +#include "memory/universe.hpp" +#include "oops/methodData.hpp" +#include "oops/objArrayKlass.hpp" +#include "oops/oop.inline.hpp" +#include "prims/methodHandles.hpp" ++#include "runtime/frame.inline.hpp" +#include "runtime/sharedRuntime.hpp" +#include "runtime/stubRoutines.hpp" +#include "runtime/synchronizer.hpp" @@ -101338,6 +107323,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/templ + case Bytecodes::_fast_dputfield: __ pop_d(); break; + case Bytecodes::_fast_fputfield: __ pop_f(); break; + case Bytecodes::_fast_lputfield: __ pop_l(FSR); break; ++ default: break; + } + __ bind(L2); + } @@ -102572,13 +108558,15 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/templ + __ sync(); +} +#endif // !CC_INTERP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/templateTable_mips.hpp jdk11u-ls/src/hotspot/cpu/mips/templateTable_mips.hpp ---- openjdk/src/hotspot/cpu/mips/templateTable_mips.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/templateTable_mips.hpp 2023-09-12 13:54:23.105571678 +0800 -@@ -0,0 +1,43 @@ +diff --git a/src/hotspot/cpu/mips/vmStructs_mips.hpp b/src/hotspot/cpu/mips/vmStructs_mips.hpp +new file mode 100644 +index 000000000..693991435 +--- /dev/null ++++ b/src/hotspot/cpu/mips/vmStructs_mips.hpp +@@ -0,0 +1,68 @@ +/* -+ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2018, Loongson Technology. All rights reserved. ++ * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2015, 2016, Loongson Technology. 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 @@ -102601,86 +108589,58 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/templ + * + */ + -+#ifndef CPU_MIPS_VM_TEMPLATETABLE_MIPS_64_HPP -+#define CPU_MIPS_VM_TEMPLATETABLE_MIPS_64_HPP ++#ifndef CPU_MIPS_VM_VMSTRUCTS_MIPS_HPP ++#define CPU_MIPS_VM_VMSTRUCTS_MIPS_HPP + -+ static void prepare_invoke(int byte_no, -+ Register method, // linked method (or i-klass) -+ Register index = noreg, // itable index, MethodType, etc. -+ Register recv = noreg, // if caller wants to see it -+ Register flags = noreg // if caller wants to test it -+ ); -+ static void invokevirtual_helper(Register index, Register recv, -+ Register flags); -+ static void volatile_barrier(); ++// These are the CPU-specific fields, types and integer ++// constants required by the Serviceability Agent. This file is ++// referenced by vmStructs.cpp. + -+ // Helpers -+ static void index_check(Register array, Register index); -+ static void index_check_without_pop(Register array, Register index); ++#define VM_STRUCTS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) \ ++ \ ++ /******************************/ \ ++ /* JavaCallWrapper */ \ ++ /******************************/ \ ++ /******************************/ \ ++ /* JavaFrameAnchor */ \ ++ /******************************/ \ ++ volatile_nonstatic_field(JavaFrameAnchor, _last_Java_fp, intptr_t*) \ ++ \ + -+#endif // CPU_MIPS_VM_TEMPLATETABLE_MIPS_64_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/vmreg_mips.cpp jdk11u-ls/src/hotspot/cpu/mips/vmreg_mips.cpp ---- openjdk/src/hotspot/cpu/mips/vmreg_mips.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/vmreg_mips.cpp 2023-09-12 13:54:23.105571678 +0800 -@@ -0,0 +1,51 @@ -+/* -+ * Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2022, Loongson Technology. 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. -+ * -+ */ ++ /* NOTE that we do not use the last_entry() macro here; it is used */ ++ /* in vmStructs__.hpp's VM_STRUCTS_OS_CPU macro (and must */ ++ /* be present there) */ + -+#include "precompiled.hpp" -+#include "asm/assembler.hpp" -+#include "code/vmreg.hpp" + ++#define VM_TYPES_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) \ + ++ /* NOTE that we do not use the last_entry() macro here; it is used */ ++ /* in vmStructs__.hpp's VM_TYPES_OS_CPU macro (and must */ ++ /* be present there) */ + -+void VMRegImpl::set_regName() { -+ Register reg = ::as_Register(0); -+ int i; -+ for (i = 0; i < ConcreteRegisterImpl::max_gpr ; ) { -+ regName[i++] = reg->name(); -+ regName[i++] = reg->name(); -+ reg = reg->successor(); -+ } + -+ FloatRegister freg = ::as_FloatRegister(0); -+ for ( ; i < ConcreteRegisterImpl::max_fpr ; ) { -+ regName[i++] = freg->name(); -+ regName[i++] = freg->name(); -+ freg = freg->successor(); -+ } ++#define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) \ + -+ for ( ; i < ConcreteRegisterImpl::number_of_registers ; i ++ ) { -+ regName[i] = "NON-GPR-FPR"; -+ } -+} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/vmreg_mips.hpp jdk11u-ls/src/hotspot/cpu/mips/vmreg_mips.hpp ---- openjdk/src/hotspot/cpu/mips/vmreg_mips.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/vmreg_mips.hpp 2023-09-12 13:54:23.105571678 +0800 -@@ -0,0 +1,56 @@ ++ /* NOTE that we do not use the last_entry() macro here; it is used */ ++ /* in vmStructs__.hpp's VM_INT_CONSTANTS_OS_CPU macro (and must */ ++ /* be present there) */ ++ ++#define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) \ ++ ++ /* NOTE that we do not use the last_entry() macro here; it is used */ ++ /* in vmStructs__.hpp's VM_LONG_CONSTANTS_OS_CPU macro (and must */ ++ /* be present there) */ ++ ++#endif // CPU_MIPS_VM_VMSTRUCTS_MIPS_HPP +diff --git a/src/hotspot/cpu/mips/vm_version_ext_mips.cpp b/src/hotspot/cpu/mips/vm_version_ext_mips.cpp +new file mode 100644 +index 000000000..ac2a43edc +--- /dev/null ++++ b/src/hotspot/cpu/mips/vm_version_ext_mips.cpp +@@ -0,0 +1,90 @@ +/* -+ * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2022, Loongson Technology. All rights reserved. ++ * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2018, Loongson Technology. 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 @@ -102703,86 +108663,80 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/vmreg + * + */ + -+#ifndef CPU_MIPS_VM_VMREG_MIPS_HPP -+#define CPU_MIPS_VM_VMREG_MIPS_HPP ++#include "memory/allocation.inline.hpp" ++#include "runtime/os.inline.hpp" ++#include "vm_version_ext_mips.hpp" + -+inline Register as_Register() { -+ assert( is_Register(), "must be"); -+ return ::as_Register(value() >> 1); -+} ++// VM_Version_Ext statics ++int VM_Version_Ext::_no_of_threads = 0; ++int VM_Version_Ext::_no_of_cores = 0; ++int VM_Version_Ext::_no_of_sockets = 0; ++bool VM_Version_Ext::_initialized = false; ++char VM_Version_Ext::_cpu_name[CPU_TYPE_DESC_BUF_SIZE] = {0}; ++char VM_Version_Ext::_cpu_desc[CPU_DETAILED_DESC_BUF_SIZE] = {0}; + -+inline FloatRegister as_FloatRegister() { -+ assert( is_FloatRegister(), "must be" ); -+ assert( is_even(value()), "must be" ); -+ return ::as_FloatRegister((value() - ConcreteRegisterImpl::max_gpr) >> 1); -+} ++void VM_Version_Ext::initialize_cpu_information(void) { ++ // do nothing if cpu info has been initialized ++ if (_initialized) { ++ return; ++ } + -+inline bool is_Register() { -+ return (unsigned int) value() < (unsigned int) ConcreteRegisterImpl::max_gpr; ++ _no_of_cores = os::processor_count(); ++ _no_of_threads = _no_of_cores; ++ _no_of_sockets = _no_of_cores; ++ if (is_loongson()) { ++ snprintf(_cpu_name, CPU_TYPE_DESC_BUF_SIZE - 1, "Loongson MIPS"); ++ snprintf(_cpu_desc, CPU_DETAILED_DESC_BUF_SIZE, "Loongson MIPS %s", cpu_features()); ++ } else { ++ snprintf(_cpu_name, CPU_TYPE_DESC_BUF_SIZE - 1, "MIPS"); ++ snprintf(_cpu_desc, CPU_DETAILED_DESC_BUF_SIZE, "MIPS %s", cpu_features()); ++ } ++ _initialized = true; +} + -+inline bool is_FloatRegister() { -+ return value() >= ConcreteRegisterImpl::max_gpr && value() < ConcreteRegisterImpl::max_fpr; ++int VM_Version_Ext::number_of_threads(void) { ++ initialize_cpu_information(); ++ return _no_of_threads; +} + -+inline bool is_concrete() { -+ assert(is_reg(), "must be"); -+ if(is_Register()) return true; -+ if(is_FloatRegister()) return true; -+ assert(false, "what register?"); -+ return false; ++int VM_Version_Ext::number_of_cores(void) { ++ initialize_cpu_information(); ++ return _no_of_cores; +} + -+#endif // CPU_MIPS_VM_VMREG_MIPS_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/vmreg_mips.inline.hpp jdk11u-ls/src/hotspot/cpu/mips/vmreg_mips.inline.hpp ---- openjdk/src/hotspot/cpu/mips/vmreg_mips.inline.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/vmreg_mips.inline.hpp 2023-09-12 13:54:23.105571678 +0800 -@@ -0,0 +1,38 @@ -+/* -+ * Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2022, Loongson Technology. 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 CPU_MIPS_VM_VMREG_MIPS_INLINE_HPP -+#define CPU_MIPS_VM_VMREG_MIPS_INLINE_HPP -+ -+inline VMReg RegisterImpl::as_VMReg() { -+ if( this==noreg ) return VMRegImpl::Bad(); -+ return VMRegImpl::as_VMReg(encoding() << 1 ); ++int VM_Version_Ext::number_of_sockets(void) { ++ initialize_cpu_information(); ++ return _no_of_sockets; +} + -+inline VMReg FloatRegisterImpl::as_VMReg() { -+ return VMRegImpl::as_VMReg((encoding() << 1) + ConcreteRegisterImpl::max_gpr); ++const char* VM_Version_Ext::cpu_name(void) { ++ initialize_cpu_information(); ++ char* tmp = NEW_C_HEAP_ARRAY_RETURN_NULL(char, CPU_TYPE_DESC_BUF_SIZE, mtTracing); ++ if (NULL == tmp) { ++ return NULL; ++ } ++ strncpy(tmp, _cpu_name, CPU_TYPE_DESC_BUF_SIZE); ++ return tmp; +} + -+#endif // CPU_MIPS_VM_VMREG_MIPS_INLINE_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/vmStructs_mips.hpp jdk11u-ls/src/hotspot/cpu/mips/vmStructs_mips.hpp ---- openjdk/src/hotspot/cpu/mips/vmStructs_mips.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/vmStructs_mips.hpp 2023-09-12 13:54:23.105571678 +0800 -@@ -0,0 +1,68 @@ ++const char* VM_Version_Ext::cpu_description(void) { ++ initialize_cpu_information(); ++ char* tmp = NEW_C_HEAP_ARRAY_RETURN_NULL(char, CPU_DETAILED_DESC_BUF_SIZE, mtTracing); ++ if (NULL == tmp) { ++ return NULL; ++ } ++ strncpy(tmp, _cpu_desc, CPU_DETAILED_DESC_BUF_SIZE); ++ return tmp; ++} +diff --git a/src/hotspot/cpu/mips/vm_version_ext_mips.hpp b/src/hotspot/cpu/mips/vm_version_ext_mips.hpp +new file mode 100644 +index 000000000..ffdcff067 +--- /dev/null ++++ b/src/hotspot/cpu/mips/vm_version_ext_mips.hpp +@@ -0,0 +1,54 @@ +/* -+ * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2016, Loongson Technology. All rights reserved. ++ * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2018, 2019, Loongson Technology. 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 @@ -102805,208 +108759,44 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/vmStr + * + */ + -+#ifndef CPU_MIPS_VM_VMSTRUCTS_MIPS_HPP -+#define CPU_MIPS_VM_VMSTRUCTS_MIPS_HPP -+ -+// These are the CPU-specific fields, types and integer -+// constants required by the Serviceability Agent. This file is -+// referenced by vmStructs.cpp. -+ -+#define VM_STRUCTS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) \ -+ \ -+ /******************************/ \ -+ /* JavaCallWrapper */ \ -+ /******************************/ \ -+ /******************************/ \ -+ /* JavaFrameAnchor */ \ -+ /******************************/ \ -+ volatile_nonstatic_field(JavaFrameAnchor, _last_Java_fp, intptr_t*) \ -+ \ -+ -+ /* NOTE that we do not use the last_entry() macro here; it is used */ -+ /* in vmStructs__.hpp's VM_STRUCTS_OS_CPU macro (and must */ -+ /* be present there) */ -+ -+ -+#define VM_TYPES_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) \ -+ -+ /* NOTE that we do not use the last_entry() macro here; it is used */ -+ /* in vmStructs__.hpp's VM_TYPES_OS_CPU macro (and must */ -+ /* be present there) */ ++#ifndef CPU_MIPS_VM_VM_VERSION_EXT_MIPS_HPP ++#define CPU_MIPS_VM_VM_VERSION_EXT_MIPS_HPP + ++#include "runtime/vm_version.hpp" ++#include "utilities/macros.hpp" + -+#define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) \ ++class VM_Version_Ext : public VM_Version { ++ private: ++ static const size_t CPU_TYPE_DESC_BUF_SIZE = 256; ++ static const size_t CPU_DETAILED_DESC_BUF_SIZE = 4096; + -+ /* NOTE that we do not use the last_entry() macro here; it is used */ -+ /* in vmStructs__.hpp's VM_INT_CONSTANTS_OS_CPU macro (and must */ -+ /* be present there) */ ++ static int _no_of_threads; ++ static int _no_of_cores; ++ static int _no_of_sockets; ++ static bool _initialized; ++ static char _cpu_name[CPU_TYPE_DESC_BUF_SIZE]; ++ static char _cpu_desc[CPU_DETAILED_DESC_BUF_SIZE]; + -+#define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) \ ++ public: ++ static int number_of_threads(void); ++ static int number_of_cores(void); ++ static int number_of_sockets(void); + -+ /* NOTE that we do not use the last_entry() macro here; it is used */ -+ /* in vmStructs__.hpp's VM_LONG_CONSTANTS_OS_CPU macro (and must */ -+ /* be present there) */ ++ static const char* cpu_name(void); ++ static const char* cpu_description(void); ++ static void initialize_cpu_information(void); ++}; + -+#endif // CPU_MIPS_VM_VMSTRUCTS_MIPS_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/vm_version_ext_mips.cpp jdk11u-ls/src/hotspot/cpu/mips/vm_version_ext_mips.cpp ---- openjdk/src/hotspot/cpu/mips/vm_version_ext_mips.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/vm_version_ext_mips.cpp 2023-09-12 13:54:23.105571678 +0800 -@@ -0,0 +1,90 @@ ++#endif // CPU_MIPS_VM_VM_VERSION_EXT_MIPS_HPP +diff --git a/src/hotspot/cpu/mips/vm_version_mips.cpp b/src/hotspot/cpu/mips/vm_version_mips.cpp +new file mode 100644 +index 000000000..275ebc4a7 +--- /dev/null ++++ b/src/hotspot/cpu/mips/vm_version_mips.cpp +@@ -0,0 +1,527 @@ +/* -+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2018, Loongson Technology. 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 "memory/allocation.inline.hpp" -+#include "runtime/os.inline.hpp" -+#include "vm_version_ext_mips.hpp" -+ -+// VM_Version_Ext statics -+int VM_Version_Ext::_no_of_threads = 0; -+int VM_Version_Ext::_no_of_cores = 0; -+int VM_Version_Ext::_no_of_sockets = 0; -+bool VM_Version_Ext::_initialized = false; -+char VM_Version_Ext::_cpu_name[CPU_TYPE_DESC_BUF_SIZE] = {0}; -+char VM_Version_Ext::_cpu_desc[CPU_DETAILED_DESC_BUF_SIZE] = {0}; -+ -+void VM_Version_Ext::initialize_cpu_information(void) { -+ // do nothing if cpu info has been initialized -+ if (_initialized) { -+ return; -+ } -+ -+ _no_of_cores = os::processor_count(); -+ _no_of_threads = _no_of_cores; -+ _no_of_sockets = _no_of_cores; -+ if (is_loongson()) { -+ snprintf(_cpu_name, CPU_TYPE_DESC_BUF_SIZE - 1, "Loongson MIPS"); -+ snprintf(_cpu_desc, CPU_DETAILED_DESC_BUF_SIZE, "Loongson MIPS %s", cpu_features()); -+ } else { -+ snprintf(_cpu_name, CPU_TYPE_DESC_BUF_SIZE - 1, "MIPS"); -+ snprintf(_cpu_desc, CPU_DETAILED_DESC_BUF_SIZE, "MIPS %s", cpu_features()); -+ } -+ _initialized = true; -+} -+ -+int VM_Version_Ext::number_of_threads(void) { -+ initialize_cpu_information(); -+ return _no_of_threads; -+} -+ -+int VM_Version_Ext::number_of_cores(void) { -+ initialize_cpu_information(); -+ return _no_of_cores; -+} -+ -+int VM_Version_Ext::number_of_sockets(void) { -+ initialize_cpu_information(); -+ return _no_of_sockets; -+} -+ -+const char* VM_Version_Ext::cpu_name(void) { -+ initialize_cpu_information(); -+ char* tmp = NEW_C_HEAP_ARRAY_RETURN_NULL(char, CPU_TYPE_DESC_BUF_SIZE, mtTracing); -+ if (NULL == tmp) { -+ return NULL; -+ } -+ strncpy(tmp, _cpu_name, CPU_TYPE_DESC_BUF_SIZE); -+ return tmp; -+} -+ -+const char* VM_Version_Ext::cpu_description(void) { -+ initialize_cpu_information(); -+ char* tmp = NEW_C_HEAP_ARRAY_RETURN_NULL(char, CPU_DETAILED_DESC_BUF_SIZE, mtTracing); -+ if (NULL == tmp) { -+ return NULL; -+ } -+ strncpy(tmp, _cpu_desc, CPU_DETAILED_DESC_BUF_SIZE); -+ return tmp; -+} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/vm_version_ext_mips.hpp jdk11u-ls/src/hotspot/cpu/mips/vm_version_ext_mips.hpp ---- openjdk/src/hotspot/cpu/mips/vm_version_ext_mips.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/vm_version_ext_mips.hpp 2023-09-12 13:54:23.105571678 +0800 -@@ -0,0 +1,54 @@ -+/* -+ * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2018, 2019, Loongson Technology. 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 CPU_MIPS_VM_VM_VERSION_EXT_MIPS_HPP -+#define CPU_MIPS_VM_VM_VERSION_EXT_MIPS_HPP -+ -+#include "runtime/vm_version.hpp" -+#include "utilities/macros.hpp" -+ -+class VM_Version_Ext : public VM_Version { -+ private: -+ static const size_t CPU_TYPE_DESC_BUF_SIZE = 256; -+ static const size_t CPU_DETAILED_DESC_BUF_SIZE = 4096; -+ -+ static int _no_of_threads; -+ static int _no_of_cores; -+ static int _no_of_sockets; -+ static bool _initialized; -+ static char _cpu_name[CPU_TYPE_DESC_BUF_SIZE]; -+ static char _cpu_desc[CPU_DETAILED_DESC_BUF_SIZE]; -+ -+ public: -+ static int number_of_threads(void); -+ static int number_of_cores(void); -+ static int number_of_sockets(void); -+ -+ static const char* cpu_name(void); -+ static const char* cpu_description(void); -+ static void initialize_cpu_information(void); -+}; -+ -+#endif // CPU_MIPS_VM_VM_VERSION_EXT_MIPS_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/vm_version_mips.cpp jdk11u-ls/src/hotspot/cpu/mips/vm_version_mips.cpp ---- openjdk/src/hotspot/cpu/mips/vm_version_mips.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/vm_version_mips.cpp 2023-11-01 09:34:25.501945276 +0800 -@@ -0,0 +1,520 @@ -+/* -+ * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2021, Loongson Technology. All rights reserved. ++ * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2015, 2022, Loongson Technology. 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 @@ -103374,12 +109164,6 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/vm_ve + FLAG_SET_DEFAULT(UseLEXT3, false); + } + -+ if (is_gs264() || is_gs464() || supports_cpucfg()) { -+ if (FLAG_IS_DEFAULT(PatchContinuousLoad)) { -+ FLAG_SET_DEFAULT(PatchContinuousLoad, false); -+ } -+ } -+ + if (UseLEXT2) { + if (FLAG_IS_DEFAULT(UseCountTrailingZerosInstructionMIPS64)) { + FLAG_SET_DEFAULT(UseCountTrailingZerosInstructionMIPS64, 1); @@ -103495,17 +109279,30 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/vm_ve + } + } + ++#ifdef COMPILER2 + if (FLAG_IS_DEFAULT(UseMontgomeryMultiplyIntrinsic)) { + UseMontgomeryMultiplyIntrinsic = true; + } + if (FLAG_IS_DEFAULT(UseMontgomerySquareIntrinsic)) { + UseMontgomerySquareIntrinsic = true; + } ++#endif + + if (FLAG_IS_DEFAULT(UseFMA)) { + FLAG_SET_DEFAULT(UseFMA, true); + } + ++ if (UseActiveCoresMP) { ++ if (os::Linux::sched_active_processor_count() != 1) { ++ if (!FLAG_IS_DEFAULT(UseActiveCoresMP)) ++ warning("UseActiveCoresMP disabled because active processors are more than one."); ++ FLAG_SET_DEFAULT(UseActiveCoresMP, false); ++ } ++ } else { ++ if (!os::is_MP()) ++ FLAG_SET_DEFAULT(UseActiveCoresMP, true); ++ } ++ + UNSUPPORTED_OPTION(CriticalJNINatives); +} + @@ -103524,13 +109321,15 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/vm_ve + + get_processor_features(); +} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/vm_version_mips.hpp jdk11u-ls/src/hotspot/cpu/mips/vm_version_mips.hpp ---- openjdk/src/hotspot/cpu/mips/vm_version_mips.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/vm_version_mips.hpp 2023-11-01 09:34:25.501945276 +0800 +diff --git a/src/hotspot/cpu/mips/vm_version_mips.hpp b/src/hotspot/cpu/mips/vm_version_mips.hpp +new file mode 100644 +index 000000000..733a0af29 +--- /dev/null ++++ b/src/hotspot/cpu/mips/vm_version_mips.hpp @@ -0,0 +1,221 @@ +/* + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2019, Loongson Technology. All rights reserved. ++ * Copyright (c) 2015, 2022, Loongson Technology. 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 @@ -103566,7 +109365,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/vm_ve + union Loongson_Cpucfg_Id1 { + uint32_t value; + struct { -+ uint32_t FP : 1, ++ uint32_t FP_CFG : 1, + FPREV : 3, + MMI : 1, + MSA1 : 1, @@ -103749,13 +109548,178 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/vm_ve +}; + +#endif // CPU_MIPS_VM_VM_VERSION_MIPS_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/vtableStubs_mips_64.cpp jdk11u-ls/src/hotspot/cpu/mips/vtableStubs_mips_64.cpp ---- openjdk/src/hotspot/cpu/mips/vtableStubs_mips_64.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/mips/vtableStubs_mips_64.cpp 2023-11-01 09:34:25.501945276 +0800 -@@ -0,0 +1,339 @@ +diff --git a/src/hotspot/cpu/mips/vmreg_mips.cpp b/src/hotspot/cpu/mips/vmreg_mips.cpp +new file mode 100644 +index 000000000..86bd74d43 +--- /dev/null ++++ b/src/hotspot/cpu/mips/vmreg_mips.cpp +@@ -0,0 +1,51 @@ ++/* ++ * Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2015, 2022, Loongson Technology. 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 "asm/assembler.hpp" ++#include "code/vmreg.hpp" ++ ++ ++ ++void VMRegImpl::set_regName() { ++ Register reg = ::as_Register(0); ++ int i; ++ for (i = 0; i < ConcreteRegisterImpl::max_gpr ; ) { ++ regName[i++] = reg->name(); ++ regName[i++] = reg->name(); ++ reg = reg->successor(); ++ } ++ ++ FloatRegister freg = ::as_FloatRegister(0); ++ for ( ; i < ConcreteRegisterImpl::max_fpr ; ) { ++ regName[i++] = freg->name(); ++ regName[i++] = freg->name(); ++ freg = freg->successor(); ++ } ++ ++ for ( ; i < ConcreteRegisterImpl::number_of_registers ; i ++ ) { ++ regName[i] = "NON-GPR-FPR"; ++ } ++} +diff --git a/src/hotspot/cpu/mips/vmreg_mips.hpp b/src/hotspot/cpu/mips/vmreg_mips.hpp +new file mode 100644 +index 000000000..8ccc8c513 +--- /dev/null ++++ b/src/hotspot/cpu/mips/vmreg_mips.hpp +@@ -0,0 +1,56 @@ ++/* ++ * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2015, 2022, Loongson Technology. 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 CPU_MIPS_VM_VMREG_MIPS_HPP ++#define CPU_MIPS_VM_VMREG_MIPS_HPP ++ ++inline Register as_Register() { ++ assert( is_Register(), "must be"); ++ return ::as_Register(value() >> 1); ++} ++ ++inline FloatRegister as_FloatRegister() { ++ assert( is_FloatRegister(), "must be" ); ++ assert( is_even(value()), "must be" ); ++ return ::as_FloatRegister((value() - ConcreteRegisterImpl::max_gpr) >> 1); ++} ++ ++inline bool is_Register() { ++ return (unsigned int) value() < (unsigned int) ConcreteRegisterImpl::max_gpr; ++} ++ ++inline bool is_FloatRegister() { ++ return value() >= ConcreteRegisterImpl::max_gpr && value() < ConcreteRegisterImpl::max_fpr; ++} ++ ++inline bool is_concrete() { ++ assert(is_reg(), "must be"); ++ if(is_Register()) return true; ++ if(is_FloatRegister()) return true; ++ assert(false, "what register?"); ++ return false; ++} ++ ++#endif // CPU_MIPS_VM_VMREG_MIPS_HPP +diff --git a/src/hotspot/cpu/mips/vmreg_mips.inline.hpp b/src/hotspot/cpu/mips/vmreg_mips.inline.hpp +new file mode 100644 +index 000000000..12ad7361a +--- /dev/null ++++ b/src/hotspot/cpu/mips/vmreg_mips.inline.hpp +@@ -0,0 +1,38 @@ ++/* ++ * Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2015, 2022, Loongson Technology. 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 CPU_MIPS_VM_VMREG_MIPS_INLINE_HPP ++#define CPU_MIPS_VM_VMREG_MIPS_INLINE_HPP ++ ++inline VMReg RegisterImpl::as_VMReg() { ++ if( this==noreg ) return VMRegImpl::Bad(); ++ return VMRegImpl::as_VMReg(encoding() << 1 ); ++} ++ ++inline VMReg FloatRegisterImpl::as_VMReg() { ++ return VMRegImpl::as_VMReg((encoding() << 1) + ConcreteRegisterImpl::max_gpr); ++} ++ ++#endif // CPU_MIPS_VM_VMREG_MIPS_INLINE_HPP +diff --git a/src/hotspot/cpu/mips/vtableStubs_mips_64.cpp b/src/hotspot/cpu/mips/vtableStubs_mips_64.cpp +new file mode 100644 +index 000000000..75c23e808 +--- /dev/null ++++ b/src/hotspot/cpu/mips/vtableStubs_mips_64.cpp +@@ -0,0 +1,340 @@ +/* + * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2021, Loongson Technology. All rights reserved. ++ * Copyright (c) 2015, 2022, Loongson Technology. 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 @@ -103784,6 +109748,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/vtabl +#include "interp_masm_mips.hpp" +#include "memory/resourceArea.hpp" +#include "oops/compiledICHolder.hpp" ++#include "oops/klass.inline.hpp" +#include "oops/klassVtable.hpp" +#include "runtime/sharedRuntime.hpp" +#include "vmreg_mips.inline.hpp" @@ -104092,10 +110057,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/mips/vtabl + const unsigned int icache_line_size = wordSize; + return icache_line_size; +} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp jdk11u-ls/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp ---- openjdk/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp 2022-10-12 23:00:01.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp 2023-09-12 13:54:23.109571683 +0800 -@@ -488,6 +488,9 @@ +diff --git a/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp b/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp +index 243cde8d7..124efbfb1 100644 +--- a/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp ++++ b/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp +@@ -488,6 +488,9 @@ void LIR_Assembler::emit_opBranch(LIR_OpBranch* op) { } } @@ -104105,7 +110071,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/ppc/c1_LIR void LIR_Assembler::emit_opConvert(LIR_OpConvert* op) { Bytecodes::Code code = op->bytecode(); -@@ -1608,6 +1611,10 @@ +@@ -1608,6 +1611,10 @@ void LIR_Assembler::cmove(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, L __ bind(skip); } @@ -104116,10 +110082,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/ppc/c1_LIR void LIR_Assembler::arith_op(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr dest, CodeEmitInfo* info, bool pop_fpu_stack) { -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/ppc/c1_LIRGenerator_ppc.cpp jdk11u-ls/src/hotspot/cpu/ppc/c1_LIRGenerator_ppc.cpp ---- openjdk/src/hotspot/cpu/ppc/c1_LIRGenerator_ppc.cpp 2022-10-12 23:00:01.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/ppc/c1_LIRGenerator_ppc.cpp 2023-09-12 13:54:23.109571683 +0800 -@@ -273,21 +273,29 @@ +diff --git a/src/hotspot/cpu/ppc/c1_LIRGenerator_ppc.cpp b/src/hotspot/cpu/ppc/c1_LIRGenerator_ppc.cpp +index 8bb8c441b..32384c649 100644 +--- a/src/hotspot/cpu/ppc/c1_LIRGenerator_ppc.cpp ++++ b/src/hotspot/cpu/ppc/c1_LIRGenerator_ppc.cpp +@@ -275,21 +275,29 @@ void LIRGenerator::increment_counter(LIR_Address* addr, int step) { __ move(temp, addr); } @@ -104155,10 +110122,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/ppc/c1_LIR bool LIRGenerator::strength_reduce_multiply(LIR_Opr left, jint c, LIR_Opr result, LIR_Opr tmp) { assert(left != result, "should be different registers"); -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/ppc/c1_LIR_ppc.cpp jdk11u-ls/src/hotspot/cpu/ppc/c1_LIR_ppc.cpp ---- openjdk/src/hotspot/cpu/ppc/c1_LIR_ppc.cpp 2022-10-12 23:00:01.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/ppc/c1_LIR_ppc.cpp 2023-09-12 13:54:23.109571683 +0800 -@@ -62,3 +62,24 @@ +diff --git a/src/hotspot/cpu/ppc/c1_LIR_ppc.cpp b/src/hotspot/cpu/ppc/c1_LIR_ppc.cpp +index ef9b0833d..c6b25bf10 100644 +--- a/src/hotspot/cpu/ppc/c1_LIR_ppc.cpp ++++ b/src/hotspot/cpu/ppc/c1_LIR_ppc.cpp +@@ -62,3 +62,24 @@ void LIR_Address::verify() const { #endif } #endif // PRODUCT @@ -104183,10 +110151,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/ppc/c1_LIR + cmp(condition, left, right); + cmove(condition, src1, src2, dst, type); +} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp jdk11u-ls/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp ---- openjdk/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp 2022-10-12 23:00:01.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp 2023-09-12 13:54:23.137571718 +0800 -@@ -379,6 +379,9 @@ +diff --git a/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp b/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp +index 897be2209..0c27cc20f 100644 +--- a/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp ++++ b/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp +@@ -379,6 +379,9 @@ void LIR_Assembler::emit_opBranch(LIR_OpBranch* op) { } } @@ -104196,7 +110165,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/s390/c1_LI void LIR_Assembler::emit_opConvert(LIR_OpConvert* op) { LIR_Opr src = op->in_opr(); -@@ -1503,6 +1506,10 @@ +@@ -1503,6 +1506,10 @@ void LIR_Assembler::cmove(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, L } } @@ -104207,10 +110176,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/s390/c1_LI void LIR_Assembler::arith_op(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr dest, CodeEmitInfo* info, bool pop_fpu_stack) { assert(info == NULL, "should never be used, idiv/irem and ldiv/lrem not handled by this method"); -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/s390/c1_LIRGenerator_s390.cpp jdk11u-ls/src/hotspot/cpu/s390/c1_LIRGenerator_s390.cpp ---- openjdk/src/hotspot/cpu/s390/c1_LIRGenerator_s390.cpp 2022-10-12 23:00:01.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/s390/c1_LIRGenerator_s390.cpp 2023-09-12 13:54:23.137571718 +0800 -@@ -213,16 +213,29 @@ +diff --git a/src/hotspot/cpu/s390/c1_LIRGenerator_s390.cpp b/src/hotspot/cpu/s390/c1_LIRGenerator_s390.cpp +index 86eb2fe88..114aacaad 100644 +--- a/src/hotspot/cpu/s390/c1_LIRGenerator_s390.cpp ++++ b/src/hotspot/cpu/s390/c1_LIRGenerator_s390.cpp +@@ -215,16 +215,29 @@ void LIRGenerator::increment_counter(LIR_Address* addr, int step) { __ add((LIR_Opr)addr, LIR_OprFact::intConst(step), (LIR_Opr)addr); } @@ -104243,10 +110213,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/s390/c1_LI bool LIRGenerator::strength_reduce_multiply(LIR_Opr left, jint c, LIR_Opr result, LIR_Opr tmp) { if (tmp->is_valid()) { if (is_power_of_2(c + 1)) { -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/s390/c1_LIR_s390.cpp jdk11u-ls/src/hotspot/cpu/s390/c1_LIR_s390.cpp ---- openjdk/src/hotspot/cpu/s390/c1_LIR_s390.cpp 2022-10-12 23:00:01.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/s390/c1_LIR_s390.cpp 2023-09-12 13:54:23.137571718 +0800 -@@ -56,3 +56,23 @@ +diff --git a/src/hotspot/cpu/s390/c1_LIR_s390.cpp b/src/hotspot/cpu/s390/c1_LIR_s390.cpp +index 9507ca085..2116e9af2 100644 +--- a/src/hotspot/cpu/s390/c1_LIR_s390.cpp ++++ b/src/hotspot/cpu/s390/c1_LIR_s390.cpp +@@ -56,3 +56,23 @@ void LIR_Address::verify() const { } #endif // PRODUCT @@ -104270,10 +110241,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/s390/c1_LI + cmp(condition, left, right); + cmove(condition, src1, src2, dst, type); +} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/sparc/c1_LIRAssembler_sparc.cpp jdk11u-ls/src/hotspot/cpu/sparc/c1_LIRAssembler_sparc.cpp ---- openjdk/src/hotspot/cpu/sparc/c1_LIRAssembler_sparc.cpp 2022-10-12 23:00:01.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/sparc/c1_LIRAssembler_sparc.cpp 2023-09-12 13:54:23.173571763 +0800 -@@ -599,6 +599,9 @@ +diff --git a/src/hotspot/cpu/sparc/c1_LIRAssembler_sparc.cpp b/src/hotspot/cpu/sparc/c1_LIRAssembler_sparc.cpp +index e503159eb..2e5609fec 100644 +--- a/src/hotspot/cpu/sparc/c1_LIRAssembler_sparc.cpp ++++ b/src/hotspot/cpu/sparc/c1_LIRAssembler_sparc.cpp +@@ -599,6 +599,9 @@ void LIR_Assembler::emit_opBranch(LIR_OpBranch* op) { // The peephole pass fills the delay slot } @@ -104283,7 +110255,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/sparc/c1_L void LIR_Assembler::emit_opConvert(LIR_OpConvert* op) { Bytecodes::Code code = op->bytecode(); -@@ -1638,6 +1641,9 @@ +@@ -1638,6 +1641,9 @@ void LIR_Assembler::cmove(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, L __ bind(skip); } @@ -104293,10 +110265,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/sparc/c1_L void LIR_Assembler::arith_op(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr dest, CodeEmitInfo* info, bool pop_fpu_stack) { assert(info == NULL, "unused on this code path"); -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/sparc/c1_LIRGenerator_sparc.cpp jdk11u-ls/src/hotspot/cpu/sparc/c1_LIRGenerator_sparc.cpp ---- openjdk/src/hotspot/cpu/sparc/c1_LIRGenerator_sparc.cpp 2022-10-12 23:00:01.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/sparc/c1_LIRGenerator_sparc.cpp 2023-09-12 13:54:23.173571763 +0800 -@@ -267,19 +267,29 @@ +diff --git a/src/hotspot/cpu/sparc/c1_LIRGenerator_sparc.cpp b/src/hotspot/cpu/sparc/c1_LIRGenerator_sparc.cpp +index b324a3dbd..0b7cb52dc 100644 +--- a/src/hotspot/cpu/sparc/c1_LIRGenerator_sparc.cpp ++++ b/src/hotspot/cpu/sparc/c1_LIRGenerator_sparc.cpp +@@ -269,19 +269,29 @@ void LIRGenerator::increment_counter(LIR_Address* addr, int step) { __ move(temp, addr); } @@ -104330,10 +110303,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/sparc/c1_L bool LIRGenerator::strength_reduce_multiply(LIR_Opr left, int c, LIR_Opr result, LIR_Opr tmp) { assert(left != result, "should be different registers"); -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/sparc/c1_LIR_sparc.cpp jdk11u-ls/src/hotspot/cpu/sparc/c1_LIR_sparc.cpp ---- openjdk/src/hotspot/cpu/sparc/c1_LIR_sparc.cpp 2022-10-12 23:00:01.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/sparc/c1_LIR_sparc.cpp 2023-09-12 13:54:23.173571763 +0800 -@@ -54,3 +54,24 @@ +diff --git a/src/hotspot/cpu/sparc/c1_LIR_sparc.cpp b/src/hotspot/cpu/sparc/c1_LIR_sparc.cpp +index c21d2c1d9..9cebb387e 100644 +--- a/src/hotspot/cpu/sparc/c1_LIR_sparc.cpp ++++ b/src/hotspot/cpu/sparc/c1_LIR_sparc.cpp +@@ -54,3 +54,24 @@ void LIR_Address::verify() const { "wrong type for addresses"); } #endif // PRODUCT @@ -104358,10 +110332,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/sparc/c1_L + cmp(condition, left, right); + cmove(condition, src1, src2, dst, type); +} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp jdk11u-ls/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp ---- openjdk/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp 2022-10-12 23:00:01.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp 2023-09-12 13:54:23.189571783 +0800 -@@ -1442,6 +1442,10 @@ +diff --git a/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp b/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp +index cee3140f4..7b76eb0b9 100644 +--- a/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp ++++ b/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp +@@ -1442,6 +1442,10 @@ void LIR_Assembler::emit_opBranch(LIR_OpBranch* op) { } } @@ -104372,7 +110347,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/x86/c1_LIR void LIR_Assembler::emit_opConvert(LIR_OpConvert* op) { LIR_Opr src = op->in_opr(); LIR_Opr dest = op->result_opr(); -@@ -2030,6 +2034,9 @@ +@@ -2030,6 +2034,9 @@ void LIR_Assembler::cmove(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, L } } @@ -104382,10 +110357,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/x86/c1_LIR void LIR_Assembler::arith_op(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr dest, CodeEmitInfo* info, bool pop_fpu_stack) { assert(info == NULL, "should never be used, idiv/irem and ldiv/lrem not handled by this method"); -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp jdk11u-ls/src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp ---- openjdk/src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp 2022-10-12 23:00:01.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp 2023-09-12 13:54:23.189571783 +0800 -@@ -255,15 +255,27 @@ +diff --git a/src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp b/src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp +index 905708a9f..1c6774e1d 100644 +--- a/src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp ++++ b/src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp +@@ -255,15 +255,27 @@ void LIRGenerator::increment_counter(LIR_Address* addr, int step) { __ add((LIR_Opr)addr, LIR_OprFact::intConst(step), (LIR_Opr)addr); } @@ -104415,10 +110391,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/x86/c1_LIR bool LIRGenerator::strength_reduce_multiply(LIR_Opr left, jint c, LIR_Opr result, LIR_Opr tmp) { if (tmp->is_valid() && c > 0 && c < max_jint) { -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/x86/c1_LIR_x86.cpp jdk11u-ls/src/hotspot/cpu/x86/c1_LIR_x86.cpp ---- openjdk/src/hotspot/cpu/x86/c1_LIR_x86.cpp 2022-10-12 23:00:01.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/x86/c1_LIR_x86.cpp 2023-09-12 13:54:23.189571783 +0800 -@@ -72,3 +72,24 @@ +diff --git a/src/hotspot/cpu/x86/c1_LIR_x86.cpp b/src/hotspot/cpu/x86/c1_LIR_x86.cpp +index 92277ee06..20e283e30 100644 +--- a/src/hotspot/cpu/x86/c1_LIR_x86.cpp ++++ b/src/hotspot/cpu/x86/c1_LIR_x86.cpp +@@ -72,3 +72,24 @@ void LIR_Address::verify() const { #endif } #endif // PRODUCT @@ -104443,10 +110420,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/x86/c1_LIR + cmp(condition, left, right); + cmove(condition, src1, src2, dst, type); +} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp jdk11u-ls/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp ---- openjdk/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp 2022-10-12 23:00:01.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp 2023-09-12 13:54:23.201571798 +0800 -@@ -263,7 +263,8 @@ +diff --git a/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp b/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp +index 95d7e5150..8d7b623ee 100644 +--- a/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp ++++ b/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp +@@ -263,7 +263,8 @@ void ZBarrierSetAssembler::try_resolve_jobject_in_native(MacroAssembler* masm, #define __ ce->masm()-> void ZBarrierSetAssembler::generate_c1_load_barrier_test(LIR_Assembler* ce, @@ -104456,10 +110434,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/x86/gc/z/z __ testptr(ref->as_register(), address_bad_mask_from_thread(r15_thread)); } -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.hpp jdk11u-ls/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.hpp ---- openjdk/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.hpp 2022-10-12 23:00:01.000000000 +0800 -+++ jdk11u-ls/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.hpp 2023-09-12 13:54:23.201571798 +0800 -@@ -77,7 +77,8 @@ +diff --git a/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.hpp b/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.hpp +index 3687754e7..791e4ed43 100644 +--- a/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.hpp ++++ b/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.hpp +@@ -77,7 +77,8 @@ public: #ifdef COMPILER1 void generate_c1_load_barrier_test(LIR_Assembler* ce, @@ -104469,23 +110448,53 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/cpu/x86/gc/z/z void generate_c1_load_barrier_stub(LIR_Assembler* ce, ZLoadBarrierStubC1* stub) const; -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os/linux/os_linux.cpp jdk11u-ls/src/hotspot/os/linux/os_linux.cpp ---- openjdk/src/hotspot/os/linux/os_linux.cpp 2022-10-12 23:00:01.000000000 +0800 -+++ jdk11u-ls/src/hotspot/os/linux/os_linux.cpp 2023-11-01 09:34:25.565945347 +0800 +diff --git a/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp b/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp +index e62dcf4f7..e380319e7 100644 +--- a/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp ++++ b/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp +@@ -225,9 +225,9 @@ void CgroupV1Subsystem::print_version_specific_info(outputStream* st) { + jlong kmem_limit = kernel_memory_limit_in_bytes(); + jlong kmem_max_usage = kernel_memory_max_usage_in_bytes(); + ++ OSContainer::print_container_helper(st, kmem_limit, "kernel_memory_limit_in_bytes"); + OSContainer::print_container_helper(st, kmem_usage, "kernel_memory_usage_in_bytes"); +- OSContainer::print_container_helper(st, kmem_limit, "kernel_memory_max_usage_in_bytes"); +- OSContainer::print_container_helper(st, kmem_max_usage, "kernel_memory_limit_in_bytes"); ++ OSContainer::print_container_helper(st, kmem_max_usage, "kernel_memory_max_usage_in_bytes"); + } + + char * CgroupV1Subsystem::cpu_cpuset_cpus() { +diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp +index 2842a11f9..cd80fba8a 100644 +--- a/src/hotspot/os/linux/os_linux.cpp ++++ b/src/hotspot/os/linux/os_linux.cpp @@ -23,6 +23,12 @@ * */ +/* -+ * This file has been modified by Loongson Technology in 2021. These -+ * modifications are Copyright (c) 2021 Loongson Technology, and are made ++ * This file has been modified by Loongson Technology in 2023. These ++ * modifications are Copyright (c) 2021, 2023 Loongson Technology, and are made + * available on the same license terms set forth above. + */ + // no precompiled headers #include "jvm.h" #include "classfile/classLoader.hpp" -@@ -3967,6 +3973,8 @@ +@@ -2458,6 +2464,12 @@ bool os::Linux::query_process_memory_info(os::Linux::meminfo_t* info) { + return false; + } + ++int os::Linux::sched_active_processor_count() { ++ if (OSContainer::is_containerized()) ++ return OSContainer::active_processor_count(); ++ return os::Linux::active_processor_count(); ++} ++ + #ifdef __GLIBC__ + // For Glibc, print a one-liner with the malloc tunables. + // Most important and popular is MALLOC_ARENA_MAX, but we are +@@ -4060,6 +4072,8 @@ size_t os::Linux::find_large_page_size() { IA64_ONLY(256 * M) PPC_ONLY(4 * M) S390_ONLY(1 * M) @@ -104494,9 +110503,53 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os/linux/os_li SPARC_ONLY(4 * M); #endif // ZERO -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os_cpu/linux_loongarch/assembler_linux_loongarch.cpp jdk11u-ls/src/hotspot/os_cpu/linux_loongarch/assembler_linux_loongarch.cpp ---- openjdk/src/hotspot/os_cpu/linux_loongarch/assembler_linux_loongarch.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/os_cpu/linux_loongarch/assembler_linux_loongarch.cpp 2023-09-12 13:54:23.349571984 +0800 +diff --git a/src/hotspot/os/linux/os_linux.hpp b/src/hotspot/os/linux/os_linux.hpp +index 3172de605..d630c0887 100644 +--- a/src/hotspot/os/linux/os_linux.hpp ++++ b/src/hotspot/os/linux/os_linux.hpp +@@ -22,6 +22,12 @@ + * + */ + ++/* ++ * This file has been modified by Loongson Technology in 2023. These ++ * modifications are Copyright (c) 2023, Loongson Technology, and are made ++ * available on the same license terms set forth above. ++ */ ++ + #ifndef OS_LINUX_VM_OS_LINUX_HPP + #define OS_LINUX_VM_OS_LINUX_HPP + +@@ -251,6 +257,8 @@ class Linux { + + // none present + ++ static int sched_active_processor_count(); ++ + private: + static void expand_stack_to(address bottom); + +diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp +index 3646d5092..d3fcc7970 100644 +--- a/src/hotspot/os/windows/os_windows.cpp ++++ b/src/hotspot/os/windows/os_windows.cpp +@@ -1741,7 +1741,10 @@ void os::win32::print_windows_version(outputStream* st) { + // - 2016 GA 10/2016 build: 14393 + // - 2019 GA 11/2018 build: 17763 + // - 2022 GA 08/2021 build: 20348 +- if (build_number > 20347) { ++ // - 2025 Preview build : 26040 ++ if (build_number > 26039) { ++ st->print("Server 2025"); ++ } else if (build_number > 20347) { + st->print("Server 2022"); + } else if (build_number > 17762) { + st->print("Server 2019"); +diff --git a/src/hotspot/os_cpu/linux_loongarch/assembler_linux_loongarch.cpp b/src/hotspot/os_cpu/linux_loongarch/assembler_linux_loongarch.cpp +new file mode 100644 +index 000000000..30719a034 +--- /dev/null ++++ b/src/hotspot/os_cpu/linux_loongarch/assembler_linux_loongarch.cpp @@ -0,0 +1,24 @@ +/* + * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. @@ -104522,13 +110575,15 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os_cpu/linux_l + * questions. + * + */ -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os_cpu/linux_loongarch/atomic_linux_loongarch.hpp jdk11u-ls/src/hotspot/os_cpu/linux_loongarch/atomic_linux_loongarch.hpp ---- openjdk/src/hotspot/os_cpu/linux_loongarch/atomic_linux_loongarch.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/os_cpu/linux_loongarch/atomic_linux_loongarch.hpp 2023-11-01 09:34:25.597945382 +0800 +diff --git a/src/hotspot/os_cpu/linux_loongarch/atomic_linux_loongarch.hpp b/src/hotspot/os_cpu/linux_loongarch/atomic_linux_loongarch.hpp +new file mode 100644 +index 000000000..8403e7838 +--- /dev/null ++++ b/src/hotspot/os_cpu/linux_loongarch/atomic_linux_loongarch.hpp @@ -0,0 +1,160 @@ +/* + * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2021, Loongson Technology. All rights reserved. ++ * Copyright (c) 2015, 2023, Loongson Technology. 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 @@ -104647,7 +110702,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os_cpu/linux_l + " sc.w %[__cmp], %[__dest] \n\t" + " beqz %[__cmp], 1b \n\t" + "2: \n\t" -+ " dbar 0 \n\t" ++ " dbar 0x700 \n\t" + + : [__prev] "=&r" (__prev), [__cmp] "=&r" (__cmp) + : [__dest] "ZC" (*(volatile jint*)dest), [__old] "r" (compare_value), [__new] "r" (exchange_value) @@ -104675,7 +110730,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os_cpu/linux_l + " sc.d %[__cmp], %[__dest] \n\t" + " beqz %[__cmp], 1b \n\t" + "2: \n\t" -+ " dbar 0 \n\t" ++ " dbar 0x700 \n\t" + + : [__prev] "=&r" (__prev), [__cmp] "=&r" (__cmp) + : [__dest] "ZC" (*(volatile jlong*)dest), [__old] "r" (compare_value), [__new] "r" (exchange_value) @@ -104686,9 +110741,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os_cpu/linux_l + + +#endif // OS_CPU_LINUX_LOONGARCH_ATOMIC_LINUX_LOONGARCH_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os_cpu/linux_loongarch/bytes_linux_loongarch.inline.hpp jdk11u-ls/src/hotspot/os_cpu/linux_loongarch/bytes_linux_loongarch.inline.hpp ---- openjdk/src/hotspot/os_cpu/linux_loongarch/bytes_linux_loongarch.inline.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/os_cpu/linux_loongarch/bytes_linux_loongarch.inline.hpp 2023-09-12 13:54:23.349571984 +0800 +diff --git a/src/hotspot/os_cpu/linux_loongarch/bytes_linux_loongarch.inline.hpp b/src/hotspot/os_cpu/linux_loongarch/bytes_linux_loongarch.inline.hpp +new file mode 100644 +index 000000000..c9f675bac +--- /dev/null ++++ b/src/hotspot/os_cpu/linux_loongarch/bytes_linux_loongarch.inline.hpp @@ -0,0 +1,37 @@ +/* + * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. @@ -104727,9 +110784,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os_cpu/linux_l +inline u8 Bytes::swap_u8(u8 x) { return bswap_64(x); } + +#endif // OS_CPU_LINUX_LOONGARCH_BYTES_LINUX_LOONGARCH_INLINE_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os_cpu/linux_loongarch/copy_linux_loongarch.inline.hpp jdk11u-ls/src/hotspot/os_cpu/linux_loongarch/copy_linux_loongarch.inline.hpp ---- openjdk/src/hotspot/os_cpu/linux_loongarch/copy_linux_loongarch.inline.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/os_cpu/linux_loongarch/copy_linux_loongarch.inline.hpp 2023-09-12 13:54:23.349571984 +0800 +diff --git a/src/hotspot/os_cpu/linux_loongarch/copy_linux_loongarch.inline.hpp b/src/hotspot/os_cpu/linux_loongarch/copy_linux_loongarch.inline.hpp +new file mode 100644 +index 000000000..826c1fe39 +--- /dev/null ++++ b/src/hotspot/os_cpu/linux_loongarch/copy_linux_loongarch.inline.hpp @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. @@ -104856,9 +110915,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os_cpu/linux_l +} + +#endif // OS_CPU_LINUX_LOONGARCH_COPY_LINUX_LOONGARCH_INLINE_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os_cpu/linux_loongarch/globals_linux_loongarch.hpp jdk11u-ls/src/hotspot/os_cpu/linux_loongarch/globals_linux_loongarch.hpp ---- openjdk/src/hotspot/os_cpu/linux_loongarch/globals_linux_loongarch.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/os_cpu/linux_loongarch/globals_linux_loongarch.hpp 2023-09-12 13:54:23.349571984 +0800 +diff --git a/src/hotspot/os_cpu/linux_loongarch/globals_linux_loongarch.hpp b/src/hotspot/os_cpu/linux_loongarch/globals_linux_loongarch.hpp +new file mode 100644 +index 000000000..0b5247aa0 +--- /dev/null ++++ b/src/hotspot/os_cpu/linux_loongarch/globals_linux_loongarch.hpp @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. @@ -104903,42 +110964,37 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os_cpu/linux_l +define_pd_global(uintx,HeapBaseMinAddress, 2*G); + +#endif // OS_CPU_LINUX_LOONGARCH_GLOBALS_LINUX_LOONGARCH_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os_cpu/linux_loongarch/linux_loongarch.s jdk11u-ls/src/hotspot/os_cpu/linux_loongarch/linux_loongarch.s ---- openjdk/src/hotspot/os_cpu/linux_loongarch/linux_loongarch.s 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/os_cpu/linux_loongarch/linux_loongarch.s 2023-09-12 13:54:23.349571984 +0800 -@@ -0,0 +1,25 @@ -+# +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_anonclassloader_inMemoryCompilation_keep_class/TEST.properties b/src/hotspot/os_cpu/linux_loongarch/linux_loongarch.s +similarity index 87% +rename from test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_anonclassloader_inMemoryCompilation_keep_class/TEST.properties +rename to src/hotspot/os_cpu/linux_loongarch/linux_loongarch.s +index 04b22a107..ebd73af0c 100644 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_anonclassloader_inMemoryCompilation_keep_class/TEST.properties ++++ b/src/hotspot/os_cpu/linux_loongarch/linux_loongarch.s +@@ -1,5 +1,6 @@ + # +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2015, 2021, Loongson Technology. 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. -+# + # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + # + # This code is free software; you can redistribute it and/or modify it +@@ -20,4 +21,5 @@ + # or visit www.oracle.com if you need additional information or have any + # questions. + # +-exclusiveAccess.dirs=. + + -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os_cpu/linux_loongarch/orderAccess_linux_loongarch.hpp jdk11u-ls/src/hotspot/os_cpu/linux_loongarch/orderAccess_linux_loongarch.hpp ---- openjdk/src/hotspot/os_cpu/linux_loongarch/orderAccess_linux_loongarch.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/os_cpu/linux_loongarch/orderAccess_linux_loongarch.hpp 2023-11-01 09:34:25.597945382 +0800 -@@ -0,0 +1,51 @@ +diff --git a/src/hotspot/os_cpu/linux_loongarch/orderAccess_linux_loongarch.hpp b/src/hotspot/os_cpu/linux_loongarch/orderAccess_linux_loongarch.hpp +new file mode 100644 +index 000000000..3eee09371 +--- /dev/null ++++ b/src/hotspot/os_cpu/linux_loongarch/orderAccess_linux_loongarch.hpp +@@ -0,0 +1,50 @@ +/* + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2022, Loongson Technology. All rights reserved. ++ * Copyright (c) 2015, 2023, Loongson Technology. 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 @@ -104964,36 +111020,37 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os_cpu/linux_l +#ifndef OS_CPU_LINUX_LOONGARCH_ORDERACCESS_LINUX_LOONGARCH_HPP +#define OS_CPU_LINUX_LOONGARCH_ORDERACCESS_LINUX_LOONGARCH_HPP + ++#include "runtime/globals.hpp" +#include "runtime/os.hpp" + +// Included in orderAccess.hpp header file. + +// Implementation of class OrderAccess. -+#define inlasm_sync() if (os::is_ActiveCoresMP()) \ -+ __asm__ __volatile__ ("nop" : : : "memory"); \ -+ else \ -+ __asm__ __volatile__ ("dbar 0" : : : "memory"); ++#define inlasm_sync(v) if (!UseActiveCoresMP) \ ++ __asm__ __volatile__ ("dbar %0" : :"K"(v) : "memory"); + -+inline void OrderAccess::loadload() { inlasm_sync(); } -+inline void OrderAccess::storestore() { inlasm_sync(); } -+inline void OrderAccess::loadstore() { inlasm_sync(); } -+inline void OrderAccess::storeload() { inlasm_sync(); } ++inline void OrderAccess::loadload() { inlasm_sync(0x15); } ++inline void OrderAccess::storestore() { inlasm_sync(0x1a); } ++inline void OrderAccess::loadstore() { inlasm_sync(0x16); } ++inline void OrderAccess::storeload() { inlasm_sync(0x19); } + -+inline void OrderAccess::acquire() { inlasm_sync(); } -+inline void OrderAccess::release() { inlasm_sync(); } -+inline void OrderAccess::fence() { inlasm_sync(); } ++inline void OrderAccess::acquire() { inlasm_sync(0x14); } ++inline void OrderAccess::release() { inlasm_sync(0x12); } ++inline void OrderAccess::fence() { inlasm_sync(0x10); } + + +#undef inlasm_sync + +#endif // OS_CPU_LINUX_LOONGARCH_ORDERACCESS_LINUX_LOONGARCH_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os_cpu/linux_loongarch/os_linux_loongarch.cpp jdk11u-ls/src/hotspot/os_cpu/linux_loongarch/os_linux_loongarch.cpp ---- openjdk/src/hotspot/os_cpu/linux_loongarch/os_linux_loongarch.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/os_cpu/linux_loongarch/os_linux_loongarch.cpp 2023-11-01 09:34:25.597945382 +0800 -@@ -0,0 +1,710 @@ +diff --git a/src/hotspot/os_cpu/linux_loongarch/os_linux_loongarch.cpp b/src/hotspot/os_cpu/linux_loongarch/os_linux_loongarch.cpp +new file mode 100644 +index 000000000..9662dfdf7 +--- /dev/null ++++ b/src/hotspot/os_cpu/linux_loongarch/os_linux_loongarch.cpp +@@ -0,0 +1,706 @@ +/* + * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2018, Loongson Technology. All rights reserved. ++ * Copyright (c) 2015, 2023, Loongson Technology. 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 @@ -105383,7 +111440,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os_cpu/linux_l +#endif + + // Handle signal from NativeJump::patch_verified_entry(). -+ if (sig == SIGILL & nativeInstruction_at(pc)->is_sigill_zombie_not_entrant()) { ++ if (sig == SIGILL && nativeInstruction_at(pc)->is_sigill_zombie_not_entrant()) { +#ifdef PRINT_SIGNAL_HANDLE + tty->print_cr("verified entry = %lx, sig=%d", nativeInstruction_at(pc), sig); +#endif @@ -105697,14 +111754,12 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os_cpu/linux_l + // LA does not require the additional stack bang. + return 0; +} -+ -+bool os::is_ActiveCoresMP() { -+ return UseActiveCoresMP && _initial_active_processor_count == 1; -+} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os_cpu/linux_loongarch/os_linux_loongarch.hpp jdk11u-ls/src/hotspot/os_cpu/linux_loongarch/os_linux_loongarch.hpp ---- openjdk/src/hotspot/os_cpu/linux_loongarch/os_linux_loongarch.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/os_cpu/linux_loongarch/os_linux_loongarch.hpp 2023-09-12 13:54:23.349571984 +0800 -@@ -0,0 +1,38 @@ +diff --git a/src/hotspot/os_cpu/linux_loongarch/os_linux_loongarch.hpp b/src/hotspot/os_cpu/linux_loongarch/os_linux_loongarch.hpp +new file mode 100644 +index 000000000..f2f46ce1b +--- /dev/null ++++ b/src/hotspot/os_cpu/linux_loongarch/os_linux_loongarch.hpp +@@ -0,0 +1,36 @@ +/* + * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, Loongson Technology. All rights reserved. @@ -105740,12 +111795,12 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os_cpu/linux_l + // Note: Currently only used in 64 bit Windows implementations + static bool register_code_area(char *low, char *high) { return true; } + -+ static bool is_ActiveCoresMP(); -+ +#endif // OS_CPU_LINUX_LOONGARCH_OS_LINUX_LOONGARCH_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os_cpu/linux_loongarch/prefetch_linux_loongarch.inline.hpp jdk11u-ls/src/hotspot/os_cpu/linux_loongarch/prefetch_linux_loongarch.inline.hpp ---- openjdk/src/hotspot/os_cpu/linux_loongarch/prefetch_linux_loongarch.inline.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/os_cpu/linux_loongarch/prefetch_linux_loongarch.inline.hpp 2023-09-12 13:54:23.349571984 +0800 +diff --git a/src/hotspot/os_cpu/linux_loongarch/prefetch_linux_loongarch.inline.hpp b/src/hotspot/os_cpu/linux_loongarch/prefetch_linux_loongarch.inline.hpp +new file mode 100644 +index 000000000..cf3a59638 +--- /dev/null ++++ b/src/hotspot/os_cpu/linux_loongarch/prefetch_linux_loongarch.inline.hpp @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. @@ -105803,13 +111858,15 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os_cpu/linux_l +} + +#endif // OS_CPU_LINUX_LOONGARCH_PREFETCH_LINUX_LOONGARCH_INLINE_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os_cpu/linux_loongarch/thread_linux_loongarch.cpp jdk11u-ls/src/hotspot/os_cpu/linux_loongarch/thread_linux_loongarch.cpp ---- openjdk/src/hotspot/os_cpu/linux_loongarch/thread_linux_loongarch.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/os_cpu/linux_loongarch/thread_linux_loongarch.cpp 2023-11-01 09:34:25.597945382 +0800 -@@ -0,0 +1,106 @@ +diff --git a/src/hotspot/os_cpu/linux_loongarch/thread_linux_loongarch.cpp b/src/hotspot/os_cpu/linux_loongarch/thread_linux_loongarch.cpp +new file mode 100644 +index 000000000..a1a9f181b +--- /dev/null ++++ b/src/hotspot/os_cpu/linux_loongarch/thread_linux_loongarch.cpp +@@ -0,0 +1,116 @@ +/* + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2021, Loongson Technology. All rights reserved. ++ * Copyright (c) 2015, 2022, Loongson Technology. 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 @@ -105843,6 +111900,16 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os_cpu/linux_l + _anchor.clear(); +} + ++frame JavaThread::pd_last_frame() { ++ assert(has_last_Java_frame(), "must have last_Java_sp() when suspended"); ++ if (_anchor.last_Java_pc() != NULL) { ++ return frame(_anchor.last_Java_sp(), _anchor.last_Java_fp(), _anchor.last_Java_pc()); ++ } else { ++ // This will pick up pc from sp ++ return frame(_anchor.last_Java_sp(), _anchor.last_Java_fp()); ++ } ++} ++ +// For Forte Analyzer AsyncGetCallTrace profiling support - thread is +// currently interrupted by SIGPROF +bool JavaThread::pd_get_top_frame_for_signal_handler(frame* fr_addr, @@ -105891,7 +111958,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os_cpu/linux_l + + frame ret_frame(ret_sp, ret_fp, addr.pc()); + if (!ret_frame.safe_for_sender(jt)) { -+#if COMPILER2 ++#ifdef COMPILER2 + // C2 and JVMCI use ebp as a general register see if NULL fp helps + frame ret_frame2(ret_sp, NULL, addr.pc()); + if (!ret_frame2.safe_for_sender(jt)) { @@ -105913,13 +111980,15 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os_cpu/linux_l +} + +void JavaThread::cache_global_variables() { } -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os_cpu/linux_loongarch/thread_linux_loongarch.hpp jdk11u-ls/src/hotspot/os_cpu/linux_loongarch/thread_linux_loongarch.hpp ---- openjdk/src/hotspot/os_cpu/linux_loongarch/thread_linux_loongarch.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/os_cpu/linux_loongarch/thread_linux_loongarch.hpp 2023-11-01 09:34:25.597945382 +0800 -@@ -0,0 +1,74 @@ +diff --git a/src/hotspot/os_cpu/linux_loongarch/thread_linux_loongarch.hpp b/src/hotspot/os_cpu/linux_loongarch/thread_linux_loongarch.hpp +new file mode 100644 +index 000000000..a3ac28ebd +--- /dev/null ++++ b/src/hotspot/os_cpu/linux_loongarch/thread_linux_loongarch.hpp +@@ -0,0 +1,66 @@ +/* + * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2021, Loongson Technology. All rights reserved. ++ * Copyright (c) 2015, 2022, Loongson Technology. 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 @@ -105948,15 +112017,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os_cpu/linux_l + private: + void pd_initialize(); + -+ frame pd_last_frame() { -+ assert(has_last_Java_frame(), "must have last_Java_sp() when suspended"); -+ if (_anchor.last_Java_pc() != NULL) { -+ return frame(_anchor.last_Java_sp(), _anchor.last_Java_fp(), _anchor.last_Java_pc()); -+ } else { -+ // This will pick up pc from sp -+ return frame(_anchor.last_Java_sp(), _anchor.last_Java_fp()); -+ } -+ } ++ frame pd_last_frame(); + + public: + // Mutators are highly dangerous.... @@ -105991,9 +112052,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os_cpu/linux_l + static void disable_register_stack_guard() {} + +#endif // OS_CPU_LINUX_LOONGARCH_VM_THREAD_LINUX_LOONGARCH_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os_cpu/linux_loongarch/vmStructs_linux_loongarch.hpp jdk11u-ls/src/hotspot/os_cpu/linux_loongarch/vmStructs_linux_loongarch.hpp ---- openjdk/src/hotspot/os_cpu/linux_loongarch/vmStructs_linux_loongarch.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/os_cpu/linux_loongarch/vmStructs_linux_loongarch.hpp 2023-09-12 13:54:23.349571984 +0800 +diff --git a/src/hotspot/os_cpu/linux_loongarch/vmStructs_linux_loongarch.hpp b/src/hotspot/os_cpu/linux_loongarch/vmStructs_linux_loongarch.hpp +new file mode 100644 +index 000000000..a39cb79bb +--- /dev/null ++++ b/src/hotspot/os_cpu/linux_loongarch/vmStructs_linux_loongarch.hpp @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. @@ -106050,41 +112113,15 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os_cpu/linux_l +#define VM_LONG_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) + +#endif // OS_CPU_LINUX_LOONGARCH_VMSTRUCTS_LINUX_LOONGARCH_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os_cpu/linux_mips/assembler_linux_mips.cpp jdk11u-ls/src/hotspot/os_cpu/linux_mips/assembler_linux_mips.cpp ---- openjdk/src/hotspot/os_cpu/linux_mips/assembler_linux_mips.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/os_cpu/linux_mips/assembler_linux_mips.cpp 2023-09-12 13:54:23.349571984 +0800 -@@ -0,0 +1,24 @@ +diff --git a/src/hotspot/os_cpu/linux_loongarch/vm_version_linux_loongarch.cpp b/src/hotspot/os_cpu/linux_loongarch/vm_version_linux_loongarch.cpp +new file mode 100644 +index 000000000..edc148ef9 +--- /dev/null ++++ b/src/hotspot/os_cpu/linux_loongarch/vm_version_linux_loongarch.cpp +@@ -0,0 +1,93 @@ +/* -+ * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2021, Loongson Technology. 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. -+ * -+ */ -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os_cpu/linux_mips/atomic_linux_mips.hpp jdk11u-ls/src/hotspot/os_cpu/linux_mips/atomic_linux_mips.hpp ---- openjdk/src/hotspot/os_cpu/linux_mips/atomic_linux_mips.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/os_cpu/linux_mips/atomic_linux_mips.hpp 2023-09-12 13:54:23.349571984 +0800 -@@ -0,0 +1,191 @@ -+/* -+ * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2022, Loongson Technology. All rights reserved. ++ * Copyright (c) 2006, 2021, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2015, 2023, Loongson Technology. 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 @@ -106107,179 +112144,83 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os_cpu/linux_m + * + */ + -+#ifndef OS_CPU_LINUX_MIPS_VM_ATOMIC_LINUX_MIPS_HPP -+#define OS_CPU_LINUX_MIPS_VM_ATOMIC_LINUX_MIPS_HPP -+ ++#include "precompiled.hpp" ++#include "runtime/os.hpp" +#include "runtime/vm_version.hpp" + -+// Implementation of class atomic -+ -+template -+struct Atomic::PlatformAdd -+ : Atomic::AddAndFetch > -+{ -+ template -+ D add_and_fetch(I add_value, D volatile* dest, atomic_memory_order order) const { -+ //Unimplemented(); -+ return __sync_add_and_fetch(dest, add_value); -+ } -+}; -+ -+template<> -+template -+inline T Atomic::PlatformXchg<4>::operator()(T exchange_value, -+ T volatile* dest, -+ atomic_memory_order order) const { -+ T __ret, __tmp; -+ -+ STATIC_ASSERT(4 == sizeof(T)); -+ __asm__ __volatile__ ( -+ " .set push\n\t" -+ " .set mips64\n\t" -+ " .set noreorder\n\t" -+ -+ "1: sync\n\t" -+ " ll %[__ret], %[__dest] \n\t" -+ " move %[__tmp], %[__val] \n\t" -+ " sc %[__tmp], %[__dest] \n\t" -+ " beqz %[__tmp], 1b \n\t" -+ " nop \n\t" ++#include ++#include + -+ " .set pop\n\t" -+ -+ : [__ret] "=&r" (__ret), [__tmp] "=&r" (__tmp) -+ : [__dest] "m" (*(volatile jint*)dest), [__val] "r" (exchange_value) -+ : "memory" -+ ); -+ -+ return __ret; -+} -+ -+template<> -+template -+inline T Atomic::PlatformXchg<8>::operator()(T exchange_value, -+ T volatile* dest, -+ atomic_memory_order order) const { -+ STATIC_ASSERT(8 == sizeof(T)); -+ T __ret; -+ jlong __tmp; -+ __asm__ __volatile__ ( -+ " .set push\n\t" -+ " .set mips64\n\t" -+ " .set noreorder\n\t" -+ -+ "1: sync\n\t" -+ " lld %[__ret], %[__dest] \n\t" -+ " move %[__tmp], %[__val] \n\t" -+ " scd %[__tmp], %[__dest] \n\t" -+ " beqz %[__tmp], 1b \n\t" -+ " nop \n\t" -+ -+ " .set pop\n\t" -+ -+ : [__ret] "=&r" (__ret), [__tmp] "=&r" (__tmp) -+ : [__dest] "m" (*(volatile intptr_t*)dest), [__val] "r" (exchange_value) -+ : "memory" -+ ); -+ return __ret; -+} -+ -+#if 0 -+template<> -+template -+inline T Atomic::PlatformCmpxchg<1>::operator()(T exchange_value, -+ T volatile* dest, -+ T compare_value, -+ atomic_memory_order order) const { -+ STATIC_ASSERT(1 == sizeof(T)); -+} ++#ifndef HWCAP_LOONGARCH_LAM ++#define HWCAP_LOONGARCH_LAM (1 << 1) ++#endif + -+#else -+// No direct support for cmpxchg of bytes; emulate using int. -+template<> -+struct Atomic::PlatformCmpxchg<1> : Atomic::CmpxchgByteUsingInt {}; ++#ifndef HWCAP_LOONGARCH_UAL ++#define HWCAP_LOONGARCH_UAL (1 << 2) +#endif + -+template<> -+template -+inline T Atomic::PlatformCmpxchg<4>::operator()(T exchange_value, -+ T volatile* dest, -+ T compare_value, -+ atomic_memory_order order) const { -+ STATIC_ASSERT(4 == sizeof(T)); -+ T __prev; -+ jint __cmp; ++#ifndef HWCAP_LOONGARCH_LSX ++#define HWCAP_LOONGARCH_LSX (1 << 4) ++#endif + -+ __asm__ __volatile__ ( -+ " .set push\n\t" -+ " .set mips64\n\t" -+ " .set noreorder\n\t" ++#ifndef HWCAP_LOONGARCH_LASX ++#define HWCAP_LOONGARCH_LASX (1 << 5) ++#endif + -+ "1:sync \n\t" -+ " ll %[__prev], %[__dest] \n\t" -+ " bne %[__prev], %[__old], 2f \n\t" -+ " move %[__cmp], $0 \n\t" -+ " move %[__cmp], %[__new] \n\t" -+ " sc %[__cmp], %[__dest] \n\t" -+ " beqz %[__cmp], 1b \n\t" -+ " nop \n\t" -+ "2: \n\t" -+ " sync \n\t" ++#ifndef HWCAP_LOONGARCH_COMPLEX ++#define HWCAP_LOONGARCH_COMPLEX (1 << 7) ++#endif + -+ " .set pop\n\t" ++#ifndef HWCAP_LOONGARCH_CRYPTO ++#define HWCAP_LOONGARCH_CRYPTO (1 << 8) ++#endif + -+ : [__prev] "=&r" (__prev), [__cmp] "=&r" (__cmp) -+ : [__dest] "m" (*(volatile jint*)dest), [__old] "r" (compare_value), [__new] "r" (exchange_value) -+ : "memory" -+ ); ++#ifndef HWCAP_LOONGARCH_LBT_X86 ++#define HWCAP_LOONGARCH_LBT_X86 (1 << 10) ++#endif + -+ return __prev; -+} ++#ifndef HWCAP_LOONGARCH_LBT_ARM ++#define HWCAP_LOONGARCH_LBT_ARM (1 << 11) ++#endif + -+template<> -+template -+inline T Atomic::PlatformCmpxchg<8>::operator()(T exchange_value, -+ T volatile* dest, -+ T compare_value, -+ atomic_memory_order order) const { -+ STATIC_ASSERT(8 == sizeof(T)); -+ T __prev; -+ jlong __cmp; ++#ifndef HWCAP_LOONGARCH_LBT_MIPS ++#define HWCAP_LOONGARCH_LBT_MIPS (1 << 12) ++#endif + -+ __asm__ __volatile__ ( -+ " .set push\n\t" -+ " .set mips64\n\t" -+ " .set noreorder\n\t" ++void VM_Version::get_os_cpu_info() { + -+ "1:sync \n\t" -+ " lld %[__prev], %[__dest] \n\t" -+ " bne %[__prev], %[__old], 2f \n\t" -+ " move %[__cmp], $0 \n\t" -+ " move %[__cmp], %[__new] \n\t" -+ " scd %[__cmp], %[__dest] \n\t" -+ " beqz %[__cmp], 1b \n\t" -+ " nop \n\t" -+ "2: \n\t" -+ " sync \n\t" ++ uint64_t auxv = getauxval(AT_HWCAP); + -+ " .set pop\n\t" ++ STATIC_ASSERT(CPU_LAM == HWCAP_LOONGARCH_LAM); ++ STATIC_ASSERT(CPU_UAL == HWCAP_LOONGARCH_UAL); ++ STATIC_ASSERT(CPU_LSX == HWCAP_LOONGARCH_LSX); ++ STATIC_ASSERT(CPU_LASX == HWCAP_LOONGARCH_LASX); ++ STATIC_ASSERT(CPU_COMPLEX == HWCAP_LOONGARCH_COMPLEX); ++ STATIC_ASSERT(CPU_CRYPTO == HWCAP_LOONGARCH_CRYPTO); ++ STATIC_ASSERT(CPU_LBT_X86 == HWCAP_LOONGARCH_LBT_X86); ++ STATIC_ASSERT(CPU_LBT_ARM == HWCAP_LOONGARCH_LBT_ARM); ++ STATIC_ASSERT(CPU_LBT_MIPS == HWCAP_LOONGARCH_LBT_MIPS); + -+ : [__prev] "=&r" (__prev), [__cmp] "=&r" (__cmp) -+ : [__dest] "m" (*(volatile jlong*)dest), [__old] "r" (compare_value), [__new] "r" (exchange_value) -+ : "memory" -+ ); -+ return __prev; ++ _features = auxv & ( ++ HWCAP_LOONGARCH_LAM | ++ HWCAP_LOONGARCH_UAL | ++ HWCAP_LOONGARCH_LSX | ++ HWCAP_LOONGARCH_LASX | ++ HWCAP_LOONGARCH_COMPLEX | ++ HWCAP_LOONGARCH_CRYPTO | ++ HWCAP_LOONGARCH_LBT_X86 | ++ HWCAP_LOONGARCH_LBT_ARM | ++ HWCAP_LOONGARCH_LBT_MIPS); +} -+ -+ -+#endif // OS_CPU_LINUX_MIPS_VM_ATOMIC_LINUX_MIPS_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os_cpu/linux_mips/bytes_linux_mips.inline.hpp jdk11u-ls/src/hotspot/os_cpu/linux_mips/bytes_linux_mips.inline.hpp ---- openjdk/src/hotspot/os_cpu/linux_mips/bytes_linux_mips.inline.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/os_cpu/linux_mips/bytes_linux_mips.inline.hpp 2023-09-12 13:54:23.349571984 +0800 -@@ -0,0 +1,37 @@ +diff --git a/src/hotspot/os_cpu/linux_mips/assembler_linux_mips.cpp b/src/hotspot/os_cpu/linux_mips/assembler_linux_mips.cpp +new file mode 100644 +index 000000000..30719a034 +--- /dev/null ++++ b/src/hotspot/os_cpu/linux_mips/assembler_linux_mips.cpp +@@ -0,0 +1,24 @@ +/* + * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2016, Loongson Technology. All rights reserved. ++ * Copyright (c) 2015, 2021, Loongson Technology. 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 @@ -106301,26 +112242,255 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os_cpu/linux_m + * questions. + * + */ -+ -+#ifndef OS_CPU_LINUX_MIPS_VM_BYTES_LINUX_MIPS_INLINE_HPP -+#define OS_CPU_LINUX_MIPS_VM_BYTES_LINUX_MIPS_INLINE_HPP -+ -+#include -+ -+// Efficient swapping of data bytes from Java byte -+// ordering to native byte ordering and vice versa. -+inline u2 Bytes::swap_u2(u2 x) { return bswap_16(x); } -+inline u4 Bytes::swap_u4(u4 x) { return bswap_32(x); } -+inline u8 Bytes::swap_u8(u8 x) { return bswap_64(x); } -+ -+#endif // OS_CPU_LINUX_MIPS_VM_BYTES_LINUX_MIPS_INLINE_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os_cpu/linux_mips/copy_linux_mips.inline.hpp jdk11u-ls/src/hotspot/os_cpu/linux_mips/copy_linux_mips.inline.hpp ---- openjdk/src/hotspot/os_cpu/linux_mips/copy_linux_mips.inline.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/os_cpu/linux_mips/copy_linux_mips.inline.hpp 2023-09-12 13:54:23.349571984 +0800 -@@ -0,0 +1,125 @@ +diff --git a/src/hotspot/os_cpu/linux_mips/atomic_linux_mips.hpp b/src/hotspot/os_cpu/linux_mips/atomic_linux_mips.hpp +new file mode 100644 +index 000000000..cd7cecad6 +--- /dev/null ++++ b/src/hotspot/os_cpu/linux_mips/atomic_linux_mips.hpp +@@ -0,0 +1,191 @@ +/* -+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2016, Loongson Technology. All rights reserved. ++ * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2015, 2022, Loongson Technology. 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 OS_CPU_LINUX_MIPS_VM_ATOMIC_LINUX_MIPS_HPP ++#define OS_CPU_LINUX_MIPS_VM_ATOMIC_LINUX_MIPS_HPP ++ ++#include "runtime/vm_version.hpp" ++ ++// Implementation of class atomic ++ ++template ++struct Atomic::PlatformAdd ++ : Atomic::AddAndFetch > ++{ ++ template ++ D add_and_fetch(I add_value, D volatile* dest, atomic_memory_order order) const { ++ //Unimplemented(); ++ return __sync_add_and_fetch(dest, add_value); ++ } ++}; ++ ++template<> ++template ++inline T Atomic::PlatformXchg<4>::operator()(T exchange_value, ++ T volatile* dest, ++ atomic_memory_order order) const { ++ T __ret, __tmp; ++ ++ STATIC_ASSERT(4 == sizeof(T)); ++ __asm__ __volatile__ ( ++ " .set push\n\t" ++ " .set mips64\n\t" ++ " .set noreorder\n\t" ++ ++ "1: sync\n\t" ++ " ll %[__ret], %[__dest] \n\t" ++ " move %[__tmp], %[__val] \n\t" ++ " sc %[__tmp], %[__dest] \n\t" ++ " beqz %[__tmp], 1b \n\t" ++ " nop \n\t" ++ ++ " .set pop\n\t" ++ ++ : [__ret] "=&r" (__ret), [__tmp] "=&r" (__tmp) ++ : [__dest] "m" (*(volatile jint*)dest), [__val] "r" (exchange_value) ++ : "memory" ++ ); ++ ++ return __ret; ++} ++ ++template<> ++template ++inline T Atomic::PlatformXchg<8>::operator()(T exchange_value, ++ T volatile* dest, ++ atomic_memory_order order) const { ++ STATIC_ASSERT(8 == sizeof(T)); ++ T __ret; ++ jlong __tmp; ++ __asm__ __volatile__ ( ++ " .set push\n\t" ++ " .set mips64\n\t" ++ " .set noreorder\n\t" ++ ++ "1: sync\n\t" ++ " lld %[__ret], %[__dest] \n\t" ++ " move %[__tmp], %[__val] \n\t" ++ " scd %[__tmp], %[__dest] \n\t" ++ " beqz %[__tmp], 1b \n\t" ++ " nop \n\t" ++ ++ " .set pop\n\t" ++ ++ : [__ret] "=&r" (__ret), [__tmp] "=&r" (__tmp) ++ : [__dest] "m" (*(volatile intptr_t*)dest), [__val] "r" (exchange_value) ++ : "memory" ++ ); ++ return __ret; ++} ++ ++#if 0 ++template<> ++template ++inline T Atomic::PlatformCmpxchg<1>::operator()(T exchange_value, ++ T volatile* dest, ++ T compare_value, ++ atomic_memory_order order) const { ++ STATIC_ASSERT(1 == sizeof(T)); ++} ++ ++#else ++// No direct support for cmpxchg of bytes; emulate using int. ++template<> ++struct Atomic::PlatformCmpxchg<1> : Atomic::CmpxchgByteUsingInt {}; ++#endif ++ ++template<> ++template ++inline T Atomic::PlatformCmpxchg<4>::operator()(T exchange_value, ++ T volatile* dest, ++ T compare_value, ++ atomic_memory_order order) const { ++ STATIC_ASSERT(4 == sizeof(T)); ++ T __prev; ++ jint __cmp; ++ ++ __asm__ __volatile__ ( ++ " .set push\n\t" ++ " .set mips64\n\t" ++ " .set noreorder\n\t" ++ ++ "1:sync \n\t" ++ " ll %[__prev], %[__dest] \n\t" ++ " bne %[__prev], %[__old], 2f \n\t" ++ " move %[__cmp], $0 \n\t" ++ " move %[__cmp], %[__new] \n\t" ++ " sc %[__cmp], %[__dest] \n\t" ++ " beqz %[__cmp], 1b \n\t" ++ " nop \n\t" ++ "2: \n\t" ++ " sync \n\t" ++ ++ " .set pop\n\t" ++ ++ : [__prev] "=&r" (__prev), [__cmp] "=&r" (__cmp) ++ : [__dest] "m" (*(volatile jint*)dest), [__old] "r" (compare_value), [__new] "r" (exchange_value) ++ : "memory" ++ ); ++ ++ return __prev; ++} ++ ++template<> ++template ++inline T Atomic::PlatformCmpxchg<8>::operator()(T exchange_value, ++ T volatile* dest, ++ T compare_value, ++ atomic_memory_order order) const { ++ STATIC_ASSERT(8 == sizeof(T)); ++ T __prev; ++ jlong __cmp; ++ ++ __asm__ __volatile__ ( ++ " .set push\n\t" ++ " .set mips64\n\t" ++ " .set noreorder\n\t" ++ ++ "1:sync \n\t" ++ " lld %[__prev], %[__dest] \n\t" ++ " bne %[__prev], %[__old], 2f \n\t" ++ " move %[__cmp], $0 \n\t" ++ " move %[__cmp], %[__new] \n\t" ++ " scd %[__cmp], %[__dest] \n\t" ++ " beqz %[__cmp], 1b \n\t" ++ " nop \n\t" ++ "2: \n\t" ++ " sync \n\t" ++ ++ " .set pop\n\t" ++ ++ : [__prev] "=&r" (__prev), [__cmp] "=&r" (__cmp) ++ : [__dest] "m" (*(volatile jlong*)dest), [__old] "r" (compare_value), [__new] "r" (exchange_value) ++ : "memory" ++ ); ++ return __prev; ++} ++ ++ ++#endif // OS_CPU_LINUX_MIPS_VM_ATOMIC_LINUX_MIPS_HPP +diff --git a/src/hotspot/os_cpu/linux_mips/bytes_linux_mips.inline.hpp b/src/hotspot/os_cpu/linux_mips/bytes_linux_mips.inline.hpp +new file mode 100644 +index 000000000..5b5cd10aa +--- /dev/null ++++ b/src/hotspot/os_cpu/linux_mips/bytes_linux_mips.inline.hpp +@@ -0,0 +1,37 @@ ++/* ++ * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2015, 2016, Loongson Technology. 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 OS_CPU_LINUX_MIPS_VM_BYTES_LINUX_MIPS_INLINE_HPP ++#define OS_CPU_LINUX_MIPS_VM_BYTES_LINUX_MIPS_INLINE_HPP ++ ++#include ++ ++// Efficient swapping of data bytes from Java byte ++// ordering to native byte ordering and vice versa. ++inline u2 Bytes::swap_u2(u2 x) { return bswap_16(x); } ++inline u4 Bytes::swap_u4(u4 x) { return bswap_32(x); } ++inline u8 Bytes::swap_u8(u8 x) { return bswap_64(x); } ++ ++#endif // OS_CPU_LINUX_MIPS_VM_BYTES_LINUX_MIPS_INLINE_HPP +diff --git a/src/hotspot/os_cpu/linux_mips/copy_linux_mips.inline.hpp b/src/hotspot/os_cpu/linux_mips/copy_linux_mips.inline.hpp +new file mode 100644 +index 000000000..3fd6ef7b3 +--- /dev/null ++++ b/src/hotspot/os_cpu/linux_mips/copy_linux_mips.inline.hpp +@@ -0,0 +1,125 @@ ++/* ++ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2015, 2016, Loongson Technology. 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 @@ -106443,9 +112613,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os_cpu/linux_m +} + +#endif // OS_CPU_LINUX_MIPS_VM_COPY_LINUX_MIPS_INLINE_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os_cpu/linux_mips/globals_linux_mips.hpp jdk11u-ls/src/hotspot/os_cpu/linux_mips/globals_linux_mips.hpp ---- openjdk/src/hotspot/os_cpu/linux_mips/globals_linux_mips.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/os_cpu/linux_mips/globals_linux_mips.hpp 2023-09-12 13:54:23.353571989 +0800 +diff --git a/src/hotspot/os_cpu/linux_mips/globals_linux_mips.hpp b/src/hotspot/os_cpu/linux_mips/globals_linux_mips.hpp +new file mode 100644 +index 000000000..f1599ac5f +--- /dev/null ++++ b/src/hotspot/os_cpu/linux_mips/globals_linux_mips.hpp @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. @@ -106498,39 +112670,34 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os_cpu/linux_m +define_pd_global(uintx,HeapBaseMinAddress, 2*G); + +#endif // OS_CPU_LINUX_MIPS_VM_GLOBALS_LINUX_MIPS_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os_cpu/linux_mips/linux_mips.s jdk11u-ls/src/hotspot/os_cpu/linux_mips/linux_mips.s ---- openjdk/src/hotspot/os_cpu/linux_mips/linux_mips.s 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/os_cpu/linux_mips/linux_mips.s 2023-09-12 13:54:23.353571989 +0800 -@@ -0,0 +1,25 @@ -+# +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_anonclassloader_inMemoryCompilation_keep_obj/TEST.properties b/src/hotspot/os_cpu/linux_mips/linux_mips.s +similarity index 87% +rename from test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_anonclassloader_inMemoryCompilation_keep_obj/TEST.properties +rename to src/hotspot/os_cpu/linux_mips/linux_mips.s +index 04b22a107..36c8d810c 100644 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_anonclassloader_inMemoryCompilation_keep_obj/TEST.properties ++++ b/src/hotspot/os_cpu/linux_mips/linux_mips.s +@@ -1,5 +1,6 @@ + # +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2015, 2018, Loongson Technology. 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. -+# + # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + # + # This code is free software; you can redistribute it and/or modify it +@@ -20,4 +21,5 @@ + # or visit www.oracle.com if you need additional information or have any + # questions. + # +-exclusiveAccess.dirs=. + + -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os_cpu/linux_mips/orderAccess_linux_mips.hpp jdk11u-ls/src/hotspot/os_cpu/linux_mips/orderAccess_linux_mips.hpp ---- openjdk/src/hotspot/os_cpu/linux_mips/orderAccess_linux_mips.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/os_cpu/linux_mips/orderAccess_linux_mips.hpp 2023-09-12 13:54:23.353571989 +0800 -@@ -0,0 +1,51 @@ +diff --git a/src/hotspot/os_cpu/linux_mips/orderAccess_linux_mips.hpp b/src/hotspot/os_cpu/linux_mips/orderAccess_linux_mips.hpp +new file mode 100644 +index 000000000..b1b959a80 +--- /dev/null ++++ b/src/hotspot/os_cpu/linux_mips/orderAccess_linux_mips.hpp +@@ -0,0 +1,50 @@ +/* + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, Loongson Technology. All rights reserved. @@ -106559,14 +112726,13 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os_cpu/linux_m +#ifndef OS_CPU_LINUX_MIPS_VM_ORDERACCESS_LINUX_MIPS_HPP +#define OS_CPU_LINUX_MIPS_VM_ORDERACCESS_LINUX_MIPS_HPP + ++#include "runtime/globals.hpp" +#include "runtime/os.hpp" + +// Included in orderAccess.hpp header file. + +// Implementation of class OrderAccess. -+#define inlasm_sync() if (os::is_ActiveCoresMP()) \ -+ __asm__ __volatile__ ("nop" : : : "memory"); \ -+ else \ ++#define inlasm_sync() if (!UseActiveCoresMP) \ + __asm__ __volatile__ ("sync" : : : "memory"); + +inline void OrderAccess::loadload() { inlasm_sync(); } @@ -106582,13 +112748,15 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os_cpu/linux_m +#undef inlasm_sync + +#endif // OS_CPU_LINUX_MIPS_VM_ORDERACCESS_LINUX_MIPS_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os_cpu/linux_mips/os_linux_mips.cpp jdk11u-ls/src/hotspot/os_cpu/linux_mips/os_linux_mips.cpp ---- openjdk/src/hotspot/os_cpu/linux_mips/os_linux_mips.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/os_cpu/linux_mips/os_linux_mips.cpp 2023-11-01 09:34:25.597945382 +0800 -@@ -0,0 +1,1020 @@ +diff --git a/src/hotspot/os_cpu/linux_mips/os_linux_mips.cpp b/src/hotspot/os_cpu/linux_mips/os_linux_mips.cpp +new file mode 100644 +index 000000000..beeabe571 +--- /dev/null ++++ b/src/hotspot/os_cpu/linux_mips/os_linux_mips.cpp +@@ -0,0 +1,1016 @@ +/* + * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2022, Loongson Technology. All rights reserved. ++ * Copyright (c) 2015, 2023, Loongson Technology. 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 @@ -107009,7 +113177,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os_cpu/linux_m +#endif + + // Handle signal from NativeJump::patch_verified_entry(). -+ if (sig == SIGILL & nativeInstruction_at(pc)->is_sigill_zombie_not_entrant()) { ++ if (sig == SIGILL && nativeInstruction_at(pc)->is_sigill_zombie_not_entrant()) { +#ifdef PRINT_SIGNAL_HANDLE + tty->print_cr("verified entry = %lx, sig=%d", nativeInstruction_at(pc), sig); +#endif @@ -107602,14 +113770,12 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os_cpu/linux_m + // MIPS does not require the additional stack bang. + return 0; +} -+ -+bool os::is_ActiveCoresMP() { -+ return UseActiveCoresMP && _initial_active_processor_count == 1; -+} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os_cpu/linux_mips/os_linux_mips.hpp jdk11u-ls/src/hotspot/os_cpu/linux_mips/os_linux_mips.hpp ---- openjdk/src/hotspot/os_cpu/linux_mips/os_linux_mips.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/os_cpu/linux_mips/os_linux_mips.hpp 2023-09-12 13:54:23.353571989 +0800 -@@ -0,0 +1,39 @@ +diff --git a/src/hotspot/os_cpu/linux_mips/os_linux_mips.hpp b/src/hotspot/os_cpu/linux_mips/os_linux_mips.hpp +new file mode 100644 +index 000000000..98131ac78 +--- /dev/null ++++ b/src/hotspot/os_cpu/linux_mips/os_linux_mips.hpp +@@ -0,0 +1,37 @@ +/* + * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, Loongson Technology. All rights reserved. @@ -107646,12 +113812,12 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os_cpu/linux_m + // Note: Currently only used in 64 bit Windows implementations + static bool register_code_area(char *low, char *high) { return true; } + -+ static bool is_ActiveCoresMP(); -+ +#endif // OS_CPU_LINUX_MIPS_VM_OS_LINUX_MIPS_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os_cpu/linux_mips/prefetch_linux_mips.inline.hpp jdk11u-ls/src/hotspot/os_cpu/linux_mips/prefetch_linux_mips.inline.hpp ---- openjdk/src/hotspot/os_cpu/linux_mips/prefetch_linux_mips.inline.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/os_cpu/linux_mips/prefetch_linux_mips.inline.hpp 2023-09-12 13:54:23.353571989 +0800 +diff --git a/src/hotspot/os_cpu/linux_mips/prefetch_linux_mips.inline.hpp b/src/hotspot/os_cpu/linux_mips/prefetch_linux_mips.inline.hpp +new file mode 100644 +index 000000000..93490345f +--- /dev/null ++++ b/src/hotspot/os_cpu/linux_mips/prefetch_linux_mips.inline.hpp @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. @@ -107711,13 +113877,15 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os_cpu/linux_m +} + +#endif // OS_CPU_LINUX_MIPS_VM_PREFETCH_LINUX_MIPS_INLINE_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os_cpu/linux_mips/thread_linux_mips.cpp jdk11u-ls/src/hotspot/os_cpu/linux_mips/thread_linux_mips.cpp ---- openjdk/src/hotspot/os_cpu/linux_mips/thread_linux_mips.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/os_cpu/linux_mips/thread_linux_mips.cpp 2023-11-01 09:34:25.597945382 +0800 -@@ -0,0 +1,106 @@ +diff --git a/src/hotspot/os_cpu/linux_mips/thread_linux_mips.cpp b/src/hotspot/os_cpu/linux_mips/thread_linux_mips.cpp +new file mode 100644 +index 000000000..dbe8efe16 +--- /dev/null ++++ b/src/hotspot/os_cpu/linux_mips/thread_linux_mips.cpp +@@ -0,0 +1,117 @@ +/* + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2021, Loongson Technology. All rights reserved. ++ * Copyright (c) 2015, 2022, Loongson Technology. 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 @@ -107741,6 +113909,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os_cpu/linux_m + */ + +#include "precompiled.hpp" ++#include "compiler/compileBroker.hpp" +#include "memory/metaspaceShared.hpp" +#include "runtime/frame.inline.hpp" +#include "runtime/thread.inline.hpp" @@ -107751,6 +113920,16 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os_cpu/linux_m + _anchor.clear(); +} + ++frame JavaThread::pd_last_frame() { ++ assert(has_last_Java_frame(), "must have last_Java_sp() when suspended"); ++ if (_anchor.last_Java_pc() != NULL) { ++ return frame(_anchor.last_Java_sp(), _anchor.last_Java_fp(), _anchor.last_Java_pc()); ++ } else { ++ // This will pick up pc from sp ++ return frame(_anchor.last_Java_sp(), _anchor.last_Java_fp()); ++ } ++} ++ +// For Forte Analyzer AsyncGetCallTrace profiling support - thread is +// currently interrupted by SIGPROF +bool JavaThread::pd_get_top_frame_for_signal_handler(frame* fr_addr, @@ -107799,7 +113978,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os_cpu/linux_m + + frame ret_frame(ret_sp, ret_fp, addr.pc()); + if (!ret_frame.safe_for_sender(jt)) { -+#if COMPILER2 ++#ifdef COMPILER2 + // C2 and JVMCI use ebp as a general register see if NULL fp helps + frame ret_frame2(ret_sp, NULL, addr.pc()); + if (!ret_frame2.safe_for_sender(jt)) { @@ -107821,13 +114000,15 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os_cpu/linux_m +} + +void JavaThread::cache_global_variables() { } -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os_cpu/linux_mips/thread_linux_mips.hpp jdk11u-ls/src/hotspot/os_cpu/linux_mips/thread_linux_mips.hpp ---- openjdk/src/hotspot/os_cpu/linux_mips/thread_linux_mips.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/os_cpu/linux_mips/thread_linux_mips.hpp 2023-11-01 09:34:25.597945382 +0800 -@@ -0,0 +1,74 @@ +diff --git a/src/hotspot/os_cpu/linux_mips/thread_linux_mips.hpp b/src/hotspot/os_cpu/linux_mips/thread_linux_mips.hpp +new file mode 100644 +index 000000000..8b8dbe219 +--- /dev/null ++++ b/src/hotspot/os_cpu/linux_mips/thread_linux_mips.hpp +@@ -0,0 +1,66 @@ +/* + * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2021, Loongson Technology. All rights reserved. ++ * Copyright (c) 2015, 2022, Loongson Technology. 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 @@ -107856,15 +114037,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os_cpu/linux_m + private: + void pd_initialize(); + -+ frame pd_last_frame() { -+ assert(has_last_Java_frame(), "must have last_Java_sp() when suspended"); -+ if (_anchor.last_Java_pc() != NULL) { -+ return frame(_anchor.last_Java_sp(), _anchor.last_Java_fp(), _anchor.last_Java_pc()); -+ } else { -+ // This will pick up pc from sp -+ return frame(_anchor.last_Java_sp(), _anchor.last_Java_fp()); -+ } -+ } ++ frame pd_last_frame(); + + public: + // Mutators are highly dangerous.... @@ -107899,9 +114072,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os_cpu/linux_m + static void disable_register_stack_guard() {} + +#endif // OS_CPU_LINUX_MIPS_VM_THREAD_LINUX_MIPS_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os_cpu/linux_mips/vmStructs_linux_mips.hpp jdk11u-ls/src/hotspot/os_cpu/linux_mips/vmStructs_linux_mips.hpp ---- openjdk/src/hotspot/os_cpu/linux_mips/vmStructs_linux_mips.hpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/os_cpu/linux_mips/vmStructs_linux_mips.hpp 2023-09-12 13:54:23.353571989 +0800 +diff --git a/src/hotspot/os_cpu/linux_mips/vmStructs_linux_mips.hpp b/src/hotspot/os_cpu/linux_mips/vmStructs_linux_mips.hpp +new file mode 100644 +index 000000000..b7454bf04 +--- /dev/null ++++ b/src/hotspot/os_cpu/linux_mips/vmStructs_linux_mips.hpp @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. @@ -107958,9 +114133,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os_cpu/linux_m +#define VM_LONG_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) + +#endif // OS_CPU_LINUX_MIPS_VM_VMSTRUCTS_LINUX_MIPS_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os_cpu/linux_mips/vm_version_linux_mips.cpp jdk11u-ls/src/hotspot/os_cpu/linux_mips/vm_version_linux_mips.cpp ---- openjdk/src/hotspot/os_cpu/linux_mips/vm_version_linux_mips.cpp 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/hotspot/os_cpu/linux_mips/vm_version_linux_mips.cpp 2023-09-12 13:54:23.353571989 +0800 +diff --git a/src/hotspot/os_cpu/linux_mips/vm_version_linux_mips.cpp b/src/hotspot/os_cpu/linux_mips/vm_version_linux_mips.cpp +new file mode 100644 +index 000000000..93e4bea04 +--- /dev/null ++++ b/src/hotspot/os_cpu/linux_mips/vm_version_linux_mips.cpp @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. @@ -107990,242 +114167,228 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os_cpu/linux_m +#include "precompiled.hpp" +#include "runtime/os.hpp" +#include "runtime/vm_version.hpp" -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/os_cpu/linux_x86/gc/z/zGlobals_linux_x86.hpp jdk11u-ls/src/hotspot/os_cpu/linux_x86/gc/z/zGlobals_linux_x86.hpp ---- openjdk/src/hotspot/os_cpu/linux_x86/gc/z/zGlobals_linux_x86.hpp 2022-10-12 23:00:01.000000000 +0800 -+++ jdk11u-ls/src/hotspot/os_cpu/linux_x86/gc/z/zGlobals_linux_x86.hpp 2023-09-12 13:54:23.353571989 +0800 -@@ -85,4 +85,6 @@ +diff --git a/src/hotspot/os_cpu/linux_x86/gc/z/zGlobals_linux_x86.hpp b/src/hotspot/os_cpu/linux_x86/gc/z/zGlobals_linux_x86.hpp +index 2b0fa83c1..270e0bc18 100644 +--- a/src/hotspot/os_cpu/linux_x86/gc/z/zGlobals_linux_x86.hpp ++++ b/src/hotspot/os_cpu/linux_x86/gc/z/zGlobals_linux_x86.hpp +@@ -85,4 +85,6 @@ const uintptr_t ZPlatformAddressSpaceSize = ((uintptr_t)1 << ZPlatformAddres const size_t ZPlatformCacheLineSize = 64; +const bool ZPlatformLoadBarrierTestResultInRegister = false; + #endif // OS_CPU_LINUX_X86_ZGLOBALS_LINUX_X86_HPP -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/asm/codeBuffer.cpp jdk11u-ls/src/hotspot/share/asm/codeBuffer.cpp ---- openjdk/src/hotspot/share/asm/codeBuffer.cpp 2022-10-12 23:00:01.000000000 +0800 -+++ jdk11u-ls/src/hotspot/share/asm/codeBuffer.cpp 2023-11-01 09:34:25.601945387 +0800 -@@ -351,6 +351,9 @@ - assert(rtype == relocInfo::none || - rtype == relocInfo::runtime_call_type || - rtype == relocInfo::internal_word_type|| -+#ifdef MIPS -+ rtype == relocInfo::internal_pc_type || -+#endif - rtype == relocInfo::section_word_type || - rtype == relocInfo::external_word_type, - "code needs relocation information"); -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/asm/codeBuffer.hpp jdk11u-ls/src/hotspot/share/asm/codeBuffer.hpp ---- openjdk/src/hotspot/share/asm/codeBuffer.hpp 2022-10-12 23:00:01.000000000 +0800 -+++ jdk11u-ls/src/hotspot/share/asm/codeBuffer.hpp 2023-09-12 13:54:23.389572035 +0800 -@@ -403,6 +403,9 @@ - #if INCLUDE_AOT - _immutable_PIC = false; - #endif -+#if defined(MIPS) && !defined(ZERO) -+ _continuous_load_instuctions_count = 0; -+#endif - } - - void initialize(address code_start, csize_t code_size) { -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/c1/c1_Compiler.cpp jdk11u-ls/src/hotspot/share/c1/c1_Compiler.cpp ---- openjdk/src/hotspot/share/c1/c1_Compiler.cpp 2022-10-12 23:00:01.000000000 +0800 -+++ jdk11u-ls/src/hotspot/share/c1/c1_Compiler.cpp 2023-09-12 13:54:23.397572045 +0800 -@@ -44,6 +44,12 @@ - #include "utilities/bitMap.inline.hpp" - #include "utilities/macros.hpp" +diff --git a/src/hotspot/share/adlc/formssel.cpp b/src/hotspot/share/adlc/formssel.cpp +index f810fde76..90f733cdf 100644 +--- a/src/hotspot/share/adlc/formssel.cpp ++++ b/src/hotspot/share/adlc/formssel.cpp +@@ -22,6 +22,12 @@ + * + */ +/* -+ * This file has been modified by Loongson Technology in 2022, These -+ * modifications are Copyright (c) 2022, Loongson Technology, and are made ++ * This file has been modified by Loongson Technology in 2023, These ++ * modifications are Copyright (c) 2023, Loongson Technology, and are made + * available on the same license terms set forth above. + */ + + // FORMS.CPP - Definitions for ADL Parser Forms Classes + #include "adlc.hpp" - Compiler::Compiler() : AbstractCompiler(compiler_c1) { +@@ -4109,6 +4115,7 @@ bool MatchRule::is_ideal_membar() const { + !strcmp(_opType,"MemBarVolatile") || + !strcmp(_opType,"MemBarCPUOrder") || + !strcmp(_opType,"MemBarStoreStore") || ++ !strcmp(_opType,"SameAddrLoadFence" ) || + !strcmp(_opType,"OnSpinWait"); } -@@ -211,7 +217,7 @@ - case vmIntrinsics::_updateCRC32: - case vmIntrinsics::_updateBytesCRC32: - case vmIntrinsics::_updateByteBufferCRC32: --#if defined(SPARC) || defined(S390) || defined(PPC64) || defined(AARCH64) -+#if defined(SPARC) || defined(S390) || defined(PPC64) || defined(AARCH64) || defined(LOONGARCH64) - case vmIntrinsics::_updateBytesCRC32C: - case vmIntrinsics::_updateDirectByteBufferCRC32C: - #endif -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/c1/c1_LinearScan.cpp jdk11u-ls/src/hotspot/share/c1/c1_LinearScan.cpp ---- openjdk/src/hotspot/share/c1/c1_LinearScan.cpp 2022-10-12 23:00:01.000000000 +0800 -+++ jdk11u-ls/src/hotspot/share/c1/c1_LinearScan.cpp 2023-11-01 09:34:25.621945409 +0800 -@@ -35,6 +35,12 @@ - #include "runtime/timerTrace.hpp" - #include "utilities/bitMap.inline.hpp" + +diff --git a/src/hotspot/share/asm/codeBuffer.cpp b/src/hotspot/share/asm/codeBuffer.cpp +index 4912f8805..5e07e27d3 100644 +--- a/src/hotspot/share/asm/codeBuffer.cpp ++++ b/src/hotspot/share/asm/codeBuffer.cpp +@@ -22,6 +22,12 @@ + * + */ +/* -+ * This file has been modified by Loongson Technology in 2022, These -+ * modifications are Copyright (c) 2022, Loongson Technology, and are made ++ * This file has been modified by Loongson Technology in 2023. These ++ * modifications are Copyright (c) 2018, 2023, Loongson Technology, and are made + * available on the same license terms set forth above. + */ + - #ifndef PRODUCT + #include "precompiled.hpp" + #include "asm/codeBuffer.hpp" + #include "compiler/disassembler.hpp" +@@ -351,6 +357,7 @@ void CodeSection::relocate(address at, RelocationHolder const& spec, int format) + assert(rtype == relocInfo::none || + rtype == relocInfo::runtime_call_type || + rtype == relocInfo::internal_word_type|| ++ NOT_ZERO(MIPS64_ONLY(rtype == relocInfo::internal_pc_type ||)) + rtype == relocInfo::section_word_type || + rtype == relocInfo::external_word_type, + "code needs relocation information"); +@@ -1046,10 +1053,11 @@ class CodeString: public CHeapObj { + friend class CodeStrings; + const char * _string; + CodeString* _next; ++ CodeString* _prev; + intptr_t _offset; - static LinearScanStatistic _stat_before_alloc; -@@ -1258,6 +1264,23 @@ - } - break; - } -+ case lir_cmp_cmove: { -+ assert(op->as_Op4() != NULL, "lir_cmp_cmove must be LIR_Op4"); -+ LIR_Op4* cmove = (LIR_Op4*)op; -+ -+ LIR_Opr move_from = cmove->in_opr3(); -+ LIR_Opr move_to = cmove->result_opr(); -+ -+ if (move_to->is_register() && move_from->is_register()) { -+ Interval* from = interval_at(reg_num(move_from)); -+ Interval* to = interval_at(reg_num(move_to)); -+ if (from != NULL && to != NULL) { -+ to->set_register_hint(from); -+ TRACE_LINEAR_SCAN(4, tty->print_cr("operation at op_id %d: added hint from interval %d to %d", cmove->id(), from->reg_num(), to->reg_num())); -+ } -+ } -+ break; -+ } - default: - break; + ~CodeString() { +- assert(_next == NULL, "wrong interface for freeing list"); ++ assert(_next == NULL && _prev == NULL, "wrong interface for freeing list"); + os::free((void*)_string); } -@@ -3342,7 +3365,9 @@ - check_live = (move->patch_code() == lir_patch_none); - } - LIR_OpBranch* branch = op->as_OpBranch(); -- if (branch != NULL && branch->stub() != NULL && branch->stub()->is_exception_throw_stub()) { -+ LIR_OpCmpBranch* cmp_branch = op->as_OpCmpBranch(); -+ if ((branch != NULL && branch->stub() != NULL && branch->stub()->is_exception_throw_stub()) || -+ (cmp_branch != NULL && cmp_branch->stub() != NULL && cmp_branch->stub()->is_exception_throw_stub())) { - // Don't bother checking the stub in this case since the - // exception stub will never return to normal control flow. - check_live = false; -@@ -6198,6 +6223,16 @@ - if (branch->ublock() == target_from) { - branch->change_ublock(target_to); - } -+ } else if (op->code() == lir_cmp_branch || op->code() == lir_cmp_float_branch) { -+ assert(op->as_OpCmpBranch() != NULL, "branch must be of type LIR_OpCmpBranch"); -+ LIR_OpCmpBranch* branch = (LIR_OpCmpBranch*)op; -+ -+ if (branch->block() == target_from) { -+ branch->change_block(target_to); -+ } -+ if (branch->ublock() == target_from) { -+ branch->change_ublock(target_to); -+ } - } + +@@ -1057,7 +1065,7 @@ class CodeString: public CHeapObj { + + public: + CodeString(const char * string, intptr_t offset = -1) +- : _next(NULL), _offset(offset) { ++ : _next(NULL), _prev(NULL), _offset(offset) { + _string = os::strdup(string, mtCode); } - } -@@ -6320,6 +6355,20 @@ - } - } - } -+ } else if (prev_op->code() == lir_cmp_branch || prev_op->code() == lir_cmp_float_branch) { -+ assert(prev_op->as_OpCmpBranch() != NULL, "branch must be of type LIR_OpCmpBranch"); -+ LIR_OpCmpBranch* prev_branch = (LIR_OpCmpBranch*)prev_op; -+ -+ if (prev_branch->stub() == NULL) { -+ if (prev_branch->block() == code->at(i + 1) && prev_branch->info() == NULL) { -+ TRACE_LINEAR_SCAN(3, tty->print_cr("Negating conditional branch and deleting unconditional branch at end of block B%d", block->block_id())); -+ -+ // eliminate a conditional branch to the immediate successor -+ prev_branch->change_block(last_branch->block()); -+ prev_branch->negate_cond(); -+ instructions->trunc_to(instructions->length() - 1); -+ } -+ } - } - } - } -@@ -6395,6 +6444,13 @@ - assert(op_branch->block() == NULL || code->find(op_branch->block()) != -1, "branch target not valid"); - assert(op_branch->ublock() == NULL || code->find(op_branch->ublock()) != -1, "branch target not valid"); - } -+ -+ LIR_OpCmpBranch* op_cmp_branch = instructions->at(j)->as_OpCmpBranch(); -+ -+ if (op_cmp_branch != NULL) { -+ assert(op_cmp_branch->block() == NULL || code->find(op_cmp_branch->block()) != -1, "branch target not valid"); -+ assert(op_cmp_branch->ublock() == NULL || code->find(op_cmp_branch->ublock()) != -1, "branch target not valid"); -+ } - } - for (j = 0; j < block->number_of_sux() - 1; j++) { -@@ -6639,6 +6695,24 @@ - break; - } +@@ -1065,7 +1073,12 @@ class CodeString: public CHeapObj { + intptr_t offset() const { assert(_offset >= 0, "offset for non comment?"); return _offset; } + CodeString* next() const { return _next; } -+ case lir_cmp_branch: -+ case lir_cmp_float_branch: { -+ LIR_OpCmpBranch* branch = op->as_OpCmpBranch(); -+ if (branch->block() == NULL) { -+ inc_counter(counter_stub_branch); -+ } else { -+ inc_counter(counter_cond_branch); -+ } -+ inc_counter(counter_cmp); -+ break; -+ } -+ -+ case lir_cmp_cmove: { -+ inc_counter(counter_misc_inst); -+ inc_counter(counter_cmp); -+ break; -+ } -+ - case lir_neg: - case lir_add: - case lir_sub: -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/c1/c1_LIRAssembler.cpp jdk11u-ls/src/hotspot/share/c1/c1_LIRAssembler.cpp ---- openjdk/src/hotspot/share/c1/c1_LIRAssembler.cpp 2022-10-12 23:00:01.000000000 +0800 -+++ jdk11u-ls/src/hotspot/share/c1/c1_LIRAssembler.cpp 2023-09-12 13:54:23.413572065 +0800 -@@ -777,6 +777,18 @@ - } +- void set_next(CodeString* next) { _next = next; } ++ void set_next(CodeString* next) { ++ _next = next; ++ if (next != NULL) { ++ next->_prev = this; ++ } ++ } + CodeString* first_comment() { + if (is_comment()) { +@@ -1093,12 +1106,9 @@ CodeString* CodeStrings::find(intptr_t offset) const { -+void LIR_Assembler::emit_op4(LIR_Op4* op) { -+ switch (op->code()) { -+ case lir_cmp_cmove: -+ cmp_cmove(op->condition(), op->in_opr1(), op->in_opr2(), op->in_opr3(), op->in_opr4(), op->result_opr(), op->type()); -+ break; -+ -+ default: -+ Unimplemented(); -+ break; + // Convenience for add_comment. + CodeString* CodeStrings::find_last(intptr_t offset) const { +- CodeString* a = find(offset); +- if (a != NULL) { +- CodeString* c = NULL; +- while (((c = a->next_comment()) != NULL) && (c->offset() == offset)) { +- a = c; +- } ++ CodeString* a = _strings_last; ++ while (a != NULL && !(a->is_comment() && a->offset() == offset)) { ++ a = a->_prev; + } + return a; + } +@@ -1117,12 +1127,16 @@ void CodeStrings::add_comment(intptr_t offset, const char * comment) { + c->set_next(_strings); + _strings = c; + } ++ if (c->next() == NULL) { ++ _strings_last = c; + } -+} -+ - void LIR_Assembler::build_frame() { - _masm->build_frame(initial_frame_size_in_bytes(), bang_size_in_bytes()); } -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/c1/c1_LIRAssembler.hpp jdk11u-ls/src/hotspot/share/c1/c1_LIRAssembler.hpp ---- openjdk/src/hotspot/share/c1/c1_LIRAssembler.hpp 2022-10-12 23:00:01.000000000 +0800 -+++ jdk11u-ls/src/hotspot/share/c1/c1_LIRAssembler.hpp 2023-09-12 13:54:23.417572070 +0800 -@@ -190,7 +190,9 @@ - void emit_op1(LIR_Op1* op); - void emit_op2(LIR_Op2* op); - void emit_op3(LIR_Op3* op); -+ void emit_op4(LIR_Op4* op); - void emit_opBranch(LIR_OpBranch* op); -+ void emit_opCmpBranch(LIR_OpCmpBranch* op); - void emit_opLabel(LIR_OpLabel* op); - void emit_arraycopy(LIR_OpArrayCopy* op); - void emit_updatecrc32(LIR_OpUpdateCRC32* op); -@@ -223,6 +225,7 @@ - void comp_mem_op(LIR_Opr src, LIR_Opr result, BasicType type, CodeEmitInfo* info); // info set for null exceptions - void comp_fl2i(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr result, LIR_Op2* op); - void cmove(LIR_Condition code, LIR_Opr left, LIR_Opr right, LIR_Opr result, BasicType type); -+ void cmp_cmove(LIR_Condition code, LIR_Opr left, LIR_Opr right, LIR_Opr src1, LIR_Opr src2, LIR_Opr result, BasicType type); - void call( LIR_OpJavaCall* op, relocInfo::relocType rtype); - void ic_call( LIR_OpJavaCall* op); -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/c1/c1_LIR.cpp jdk11u-ls/src/hotspot/share/c1/c1_LIR.cpp ---- openjdk/src/hotspot/share/c1/c1_LIR.cpp 2022-10-12 23:00:01.000000000 +0800 -+++ jdk11u-ls/src/hotspot/share/c1/c1_LIR.cpp 2023-11-01 09:34:25.613945400 +0800 -@@ -250,6 +250,18 @@ + void CodeStrings::assign(CodeStrings& other) { + other.check_valid(); + assert(is_null(), "Cannot assign onto non-empty CodeStrings"); + _strings = other._strings; ++ _strings_last = other._strings_last; + #ifdef ASSERT + _defunct = false; + #endif +@@ -1138,8 +1152,11 @@ void CodeStrings::copy(CodeStrings& other) { + assert(is_null(), "Cannot copy onto non-empty CodeStrings"); + CodeString* n = other._strings; + CodeString** ps = &_strings; ++ CodeString* prev = NULL; + while (n != NULL) { + *ps = new CodeString(n->string(),n->offset()); ++ (*ps)->_prev = prev; ++ prev = *ps; + ps = &((*ps)->_next); + n = n->next(); + } +@@ -1168,6 +1185,10 @@ void CodeStrings::free() { + // unlink the node from the list saving a pointer to the next + CodeString* p = n->next(); + n->set_next(NULL); ++ if (p != NULL) { ++ assert(p->_prev == n, "missing prev link"); ++ p->_prev = NULL; ++ } + delete n; + n = p; + } +@@ -1178,6 +1199,9 @@ const char* CodeStrings::add_string(const char * string) { + check_valid(); + CodeString* s = new CodeString(string); + s->set_next(_strings); ++ if (_strings == NULL) { ++ _strings_last = s; ++ } + _strings = s; + assert(s->string() != NULL, "should have a string"); + return s->string(); +diff --git a/src/hotspot/share/asm/codeBuffer.hpp b/src/hotspot/share/asm/codeBuffer.hpp +index 2f6b2ed4f..01c78fd9a 100644 +--- a/src/hotspot/share/asm/codeBuffer.hpp ++++ b/src/hotspot/share/asm/codeBuffer.hpp +@@ -249,6 +249,7 @@ class CodeStrings { + private: + #ifndef PRODUCT + CodeString* _strings; ++ CodeString* _strings_last; + #ifdef ASSERT + // Becomes true after copy-out, forbids further use. + bool _defunct; // Zero bit pattern is "valid", see memset call in decode_env::decode_env +@@ -262,6 +263,7 @@ private: + void set_null_and_invalidate() { + #ifndef PRODUCT + _strings = NULL; ++ _strings_last = NULL; + #ifdef ASSERT + _defunct = true; + #endif +@@ -272,6 +274,7 @@ public: + CodeStrings() { + #ifndef PRODUCT + _strings = NULL; ++ _strings_last = NULL; + #ifdef ASSERT + _defunct = false; + #endif +diff --git a/src/hotspot/share/c1/c1_Compiler.cpp b/src/hotspot/share/c1/c1_Compiler.cpp +index aff12954b..4999aac57 100644 +--- a/src/hotspot/share/c1/c1_Compiler.cpp ++++ b/src/hotspot/share/c1/c1_Compiler.cpp +@@ -22,6 +22,12 @@ + * + */ + ++/* ++ * This file has been modified by Loongson Technology in 2025, These ++ * modifications are Copyright (c) 2022, 2025, Loongson Technology, and are made ++ * available on the same license terms set forth above. ++ */ ++ + #include "precompiled.hpp" + #include "c1/c1_Compilation.hpp" + #include "c1/c1_Compiler.hpp" +@@ -211,7 +217,7 @@ bool Compiler::is_intrinsic_supported(const methodHandle& method) { + case vmIntrinsics::_updateCRC32: + case vmIntrinsics::_updateBytesCRC32: + case vmIntrinsics::_updateByteBufferCRC32: +-#if defined(SPARC) || defined(S390) || defined(PPC64) || defined(AARCH64) ++#if defined(SPARC) || defined(S390) || defined(PPC64) || defined(AARCH64) || defined(LOONGARCH64) + case vmIntrinsics::_updateBytesCRC32C: + case vmIntrinsics::_updateDirectByteBufferCRC32C: + #endif +diff --git a/src/hotspot/share/c1/c1_LIR.cpp b/src/hotspot/share/c1/c1_LIR.cpp +index e30d39f73..7461b7449 100644 +--- a/src/hotspot/share/c1/c1_LIR.cpp ++++ b/src/hotspot/share/c1/c1_LIR.cpp +@@ -250,6 +250,18 @@ void LIR_Op2::verify() const { #endif } @@ -108244,7 +114407,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/c1/c1_LI LIR_OpBranch::LIR_OpBranch(LIR_Condition cond, BasicType type, BlockBegin* block) : LIR_Op(lir_branch, LIR_OprFact::illegalOpr, (CodeEmitInfo*)NULL) -@@ -308,6 +320,56 @@ +@@ -308,6 +320,56 @@ void LIR_OpBranch::negate_cond() { } @@ -108301,7 +114464,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/c1/c1_LI LIR_OpTypeCheck::LIR_OpTypeCheck(LIR_Code code, LIR_Opr result, LIR_Opr object, ciKlass* klass, LIR_Opr tmp1, LIR_Opr tmp2, LIR_Opr tmp3, bool fast_check, CodeEmitInfo* info_for_exception, CodeEmitInfo* info_for_patch, -@@ -509,10 +571,7 @@ +@@ -509,10 +571,7 @@ void LIR_OpVisitState::visit(LIR_Op* op) { assert(opConvert->_info == NULL, "must be"); if (opConvert->_opr->is_valid()) do_input(opConvert->_opr); if (opConvert->_result->is_valid()) do_output(opConvert->_result); @@ -108313,7 +114476,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/c1/c1_LI do_stub(opConvert->_stub); break; -@@ -611,6 +670,25 @@ +@@ -611,6 +670,25 @@ void LIR_OpVisitState::visit(LIR_Op* op) { break; } @@ -108339,7 +114502,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/c1/c1_LI // special handling for cmove: right input operand must not be equal // to the result operand, otherwise the backend fails case lir_cmove: -@@ -711,6 +789,29 @@ +@@ -711,6 +789,29 @@ void LIR_OpVisitState::visit(LIR_Op* op) { break; } @@ -108369,7 +114532,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/c1/c1_LI // LIR_OpJavaCall case lir_static_call: case lir_optvirtual_call: -@@ -1028,6 +1129,13 @@ +@@ -1028,6 +1129,13 @@ void LIR_Op2::emit_code(LIR_Assembler* masm) { masm->emit_op2(this); } @@ -108383,7 +114546,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/c1/c1_LI void LIR_OpAllocArray::emit_code(LIR_Assembler* masm) { masm->emit_alloc_array(this); masm->append_code_stub(stub()); -@@ -1048,6 +1156,10 @@ +@@ -1048,6 +1156,10 @@ void LIR_Op3::emit_code(LIR_Assembler* masm) { masm->emit_op3(this); } @@ -108394,7 +114557,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/c1/c1_LI void LIR_OpLock::emit_code(LIR_Assembler* masm) { masm->emit_lock(this); if (stub()) { -@@ -1424,8 +1536,7 @@ +@@ -1424,8 +1536,7 @@ void LIR_List::null_check(LIR_Opr opr, CodeEmitInfo* info, bool deoptimize_on_nu if (deoptimize_on_null) { // Emit an explicit null check and deoptimize if opr is null CodeStub* deopt = new DeoptimizeStub(info, Deoptimization::Reason_null_check, Deoptimization::Action_none); @@ -108404,7 +114567,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/c1/c1_LI } else { // Emit an implicit null check append(new LIR_Op1(lir_null_check, opr, info)); -@@ -1680,6 +1791,8 @@ +@@ -1680,6 +1791,8 @@ const char * LIR_Op::name() const { case lir_cmp_l2i: s = "cmp_l2i"; break; case lir_ucmp_fd2i: s = "ucomp_fd2i"; break; case lir_cmp_fd2i: s = "comp_fd2i"; break; @@ -108413,7 +114576,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/c1/c1_LI case lir_cmove: s = "cmove"; break; case lir_add: s = "add"; break; case lir_sub: s = "sub"; break; -@@ -1705,6 +1818,8 @@ +@@ -1705,6 +1818,8 @@ const char * LIR_Op::name() const { case lir_irem: s = "irem"; break; case lir_fmad: s = "fmad"; break; case lir_fmaf: s = "fmaf"; break; @@ -108422,7 +114585,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/c1/c1_LI // LIR_OpJavaCall case lir_static_call: s = "static"; break; case lir_optvirtual_call: s = "optvirtual"; break; -@@ -1856,6 +1971,26 @@ +@@ -1856,6 +1971,26 @@ void LIR_OpBranch::print_instr(outputStream* out) const { } } @@ -108449,7 +114612,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/c1/c1_LI void LIR_Op::print_condition(outputStream* out, LIR_Condition cond) { switch(cond) { case lir_cond_equal: out->print("[EQ]"); break; -@@ -1876,12 +2011,7 @@ +@@ -1876,12 +2011,9 @@ void LIR_OpConvert::print_instr(outputStream* out) const { print_bytecode(out, bytecode()); in_opr()->print(out); out->print(" "); result_opr()->print(out); out->print(" "); @@ -108457,17 +114620,17 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/c1/c1_LI - if(tmp1()->is_valid()) { - tmp1()->print(out); out->print(" "); - tmp2()->print(out); out->print(" "); -- } ++ if(tmp()->is_valid()) { ++ tmp()->print(out); out->print(" "); + } -#endif -+ if(tmp()->is_valid()) tmp()->print(out); out->print(" "); } void LIR_OpConvert::print_bytecode(outputStream* out, Bytecodes::Code code) { -@@ -1978,6 +2108,19 @@ - result_opr()->print(out); +@@ -1979,6 +2111,19 @@ void LIR_Op3::print_instr(outputStream* out) const { } -+ + +// LIR_Op4 +void LIR_Op4::print_instr(outputStream* out) const { + if (code() == lir_cmp_cmove) { @@ -108480,32 +114643,321 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/c1/c1_LI + result_opr()->print(out); +} + - ++ void LIR_OpLock::print_instr(outputStream* out) const { hdr_opr()->print(out); out->print(" "); -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/c1/c1_LIRGenerator.cpp jdk11u-ls/src/hotspot/share/c1/c1_LIRGenerator.cpp ---- openjdk/src/hotspot/share/c1/c1_LIRGenerator.cpp 2022-10-12 23:00:01.000000000 +0800 -+++ jdk11u-ls/src/hotspot/share/c1/c1_LIRGenerator.cpp 2023-09-12 13:54:23.417572070 +0800 -@@ -479,13 +479,11 @@ + obj_opr()->print(out); out->print(" "); +diff --git a/src/hotspot/share/c1/c1_LIR.hpp b/src/hotspot/share/c1/c1_LIR.hpp +index 3234ca018..1f46e44c7 100644 +--- a/src/hotspot/share/c1/c1_LIR.hpp ++++ b/src/hotspot/share/c1/c1_LIR.hpp +@@ -864,9 +864,11 @@ class LIR_OpConvert; + class LIR_OpAllocObj; + class LIR_OpRoundFP; + class LIR_Op2; ++class LIR_OpCmpBranch; + class LIR_OpDelay; + class LIR_Op3; + class LIR_OpAllocArray; ++class LIR_Op4; + class LIR_OpCall; + class LIR_OpJavaCall; + class LIR_OpRTCall; +@@ -933,6 +935,8 @@ enum LIR_Code { + , lir_cmp_l2i + , lir_ucmp_fd2i + , lir_cmp_fd2i ++ , lir_cmp_branch ++ , lir_cmp_float_branch + , lir_cmove + , lir_add + , lir_sub +@@ -964,6 +968,9 @@ enum LIR_Code { + , lir_fmad + , lir_fmaf + , end_op3 ++ , begin_op4 ++ , lir_cmp_cmove ++ , end_op4 + , begin_opJavaCall + , lir_static_call + , lir_optvirtual_call +@@ -1128,12 +1135,14 @@ class LIR_Op: public CompilationResourceObj { + virtual LIR_OpAllocObj* as_OpAllocObj() { return NULL; } + virtual LIR_OpRoundFP* as_OpRoundFP() { return NULL; } + virtual LIR_OpBranch* as_OpBranch() { return NULL; } ++ virtual LIR_OpCmpBranch* as_OpCmpBranch() { return NULL; } + virtual LIR_OpRTCall* as_OpRTCall() { return NULL; } + virtual LIR_OpConvert* as_OpConvert() { return NULL; } + virtual LIR_Op0* as_Op0() { return NULL; } + virtual LIR_Op1* as_Op1() { return NULL; } + virtual LIR_Op2* as_Op2() { return NULL; } + virtual LIR_Op3* as_Op3() { return NULL; } ++ virtual LIR_Op4* as_Op4() { return NULL; } + virtual LIR_OpArrayCopy* as_OpArrayCopy() { return NULL; } + virtual LIR_OpUpdateCRC32* as_OpUpdateCRC32() { return NULL; } + virtual LIR_OpTypeCheck* as_OpTypeCheck() { return NULL; } +@@ -1463,15 +1472,18 @@ class LIR_OpConvert: public LIR_Op1 { + private: + Bytecodes::Code _bytecode; + ConversionStub* _stub; ++ LIR_Opr _tmp; + + public: +- LIR_OpConvert(Bytecodes::Code code, LIR_Opr opr, LIR_Opr result, ConversionStub* stub) ++ LIR_OpConvert(Bytecodes::Code code, LIR_Opr opr, LIR_Opr result, ConversionStub* stub, LIR_Opr tmp) + : LIR_Op1(lir_convert, opr, result) + , _stub(stub) +- , _bytecode(code) {} ++ , _bytecode(code) ++ , _tmp(tmp) {} + + Bytecodes::Code bytecode() const { return _bytecode; } + ConversionStub* stub() const { return _stub; } ++ LIR_Opr tmp() const { return _tmp; } + + virtual void emit_code(LIR_Assembler* masm); + virtual LIR_OpConvert* as_OpConvert() { return this; } +@@ -1626,7 +1638,7 @@ class LIR_Op2: public LIR_Op { + , _tmp3(LIR_OprFact::illegalOpr) + , _tmp4(LIR_OprFact::illegalOpr) + , _tmp5(LIR_OprFact::illegalOpr) { +- assert(code == lir_cmp || code == lir_assert, "code check"); ++ assert(code == lir_cmp || code == lir_cmp_branch || code == lir_cmp_float_branch || code == lir_assert, "code check"); + } + + LIR_Op2(LIR_Code code, LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr result, BasicType type) +@@ -1658,7 +1670,7 @@ class LIR_Op2: public LIR_Op { + , _tmp3(LIR_OprFact::illegalOpr) + , _tmp4(LIR_OprFact::illegalOpr) + , _tmp5(LIR_OprFact::illegalOpr) { +- assert(code != lir_cmp && is_in_range(code, begin_op2, end_op2), "code check"); ++ assert((code != lir_cmp && code != lir_cmp_branch && code != lir_cmp_float_branch) && is_in_range(code, begin_op2, end_op2), "code check"); + } + + LIR_Op2(LIR_Code code, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr result, LIR_Opr tmp1, LIR_Opr tmp2 = LIR_OprFact::illegalOpr, +@@ -1674,7 +1686,7 @@ class LIR_Op2: public LIR_Op { + , _tmp3(tmp3) + , _tmp4(tmp4) + , _tmp5(tmp5) { +- assert(code != lir_cmp && is_in_range(code, begin_op2, end_op2), "code check"); ++ assert((code != lir_cmp && code != lir_cmp_branch && code != lir_cmp_float_branch) && is_in_range(code, begin_op2, end_op2), "code check"); + } + + LIR_Opr in_opr1() const { return _opr1; } +@@ -1686,10 +1698,12 @@ class LIR_Op2: public LIR_Op { + LIR_Opr tmp4_opr() const { return _tmp4; } + LIR_Opr tmp5_opr() const { return _tmp5; } + LIR_Condition condition() const { +- assert(code() == lir_cmp || code() == lir_cmove || code() == lir_assert, "only valid for cmp and cmove and assert"); return _condition; ++ assert(code() == lir_cmp || code() == lir_cmp_branch || code() == lir_cmp_float_branch || code() == lir_cmove || code() == lir_assert, "only valid for cmp and cmove and assert"); ++ return _condition; + } + void set_condition(LIR_Condition condition) { +- assert(code() == lir_cmp || code() == lir_cmove, "only valid for cmp and cmove"); _condition = condition; ++ assert(code() == lir_cmp || code() == lir_cmp_branch || code() == lir_cmp_float_branch || code() == lir_cmove, "only valid for cmp and cmove"); ++ _condition = condition; + } + + void set_fpu_stack_size(int size) { _fpu_stack_size = size; } +@@ -1703,6 +1717,43 @@ class LIR_Op2: public LIR_Op { + virtual void print_instr(outputStream* out) const PRODUCT_RETURN; + }; + ++class LIR_OpCmpBranch: public LIR_Op2 { ++ friend class LIR_OpVisitState; ++ ++ private: ++ Label* _label; ++ BlockBegin* _block; // if this is a branch to a block, this is the block ++ BlockBegin* _ublock; // if this is a float-branch, this is the unorderd block ++ CodeStub* _stub; // if this is a branch to a stub, this is the stub ++ ++ public: ++ LIR_OpCmpBranch(LIR_Condition cond, LIR_Opr left, LIR_Opr right, Label* lbl, CodeEmitInfo* info = NULL) ++ : LIR_Op2(lir_cmp_branch, cond, left, right, info) ++ , _label(lbl) ++ , _block(NULL) ++ , _ublock(NULL) ++ , _stub(NULL) { } ++ ++ LIR_OpCmpBranch(LIR_Condition cond, LIR_Opr left, LIR_Opr right, CodeStub* stub, CodeEmitInfo* info = NULL); ++ LIR_OpCmpBranch(LIR_Condition cond, LIR_Opr left, LIR_Opr right, BlockBegin* block, CodeEmitInfo* info = NULL); ++ ++ // for unordered comparisons ++ LIR_OpCmpBranch(LIR_Condition cond, LIR_Opr left, LIR_Opr right, BlockBegin* block, BlockBegin* ublock, CodeEmitInfo* info = NULL); ++ ++ Label* label() const { return _label; } ++ BlockBegin* block() const { return _block; } ++ BlockBegin* ublock() const { return _ublock; } ++ CodeStub* stub() const { return _stub; } ++ ++ void change_block(BlockBegin* b); ++ void change_ublock(BlockBegin* b); ++ void negate_cond(); ++ ++ virtual void emit_code(LIR_Assembler* masm); ++ virtual LIR_OpCmpBranch* as_OpCmpBranch() { return this; } ++ virtual void print_instr(outputStream* out) const PRODUCT_RETURN; ++}; ++ + class LIR_OpAllocArray : public LIR_Op { + friend class LIR_OpVisitState; + +@@ -1767,6 +1818,48 @@ class LIR_Op3: public LIR_Op { + }; + + ++class LIR_Op4: public LIR_Op { ++ friend class LIR_OpVisitState; ++ ++ private: ++ LIR_Opr _opr1; ++ LIR_Opr _opr2; ++ LIR_Opr _opr3; ++ LIR_Opr _opr4; ++ BasicType _type; ++ LIR_Condition _condition; ++ ++ void verify() const; ++ ++ public: ++ LIR_Op4(LIR_Code code, LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr opr3, LIR_Opr opr4, LIR_Opr result, BasicType type) ++ : LIR_Op(code, result, NULL) ++ , _opr1(opr1) ++ , _opr2(opr2) ++ , _opr3(opr3) ++ , _opr4(opr4) ++ , _type(type) ++ , _condition(condition) { ++ assert(is_in_range(code, begin_op4, end_op4), "code check"); ++ assert(type != T_ILLEGAL, "cmove should have type"); ++ } ++ LIR_Opr in_opr1() const { return _opr1; } ++ LIR_Opr in_opr2() const { return _opr2; } ++ LIR_Opr in_opr3() const { return _opr3; } ++ LIR_Opr in_opr4() const { return _opr4; } ++ BasicType type() const { return _type; } ++ LIR_Condition condition() const { ++ assert(code() == lir_cmp_cmove, "only valid for cmp cmove"); return _condition; ++ } ++ void set_condition(LIR_Condition condition) { ++ assert(code() == lir_cmp_cmove, "only valid for cmp cmove"); _condition = condition; ++ } ++ ++ virtual void emit_code(LIR_Assembler* masm); ++ virtual LIR_Op4* as_Op4() { return this; } ++ virtual void print_instr(outputStream* out) const PRODUCT_RETURN; ++}; ++ + //-------------------------------- + class LabelObj: public CompilationResourceObj { + private: +@@ -2115,7 +2208,9 @@ class LIR_List: public CompilationResourceObj { + + void safepoint(LIR_Opr tmp, CodeEmitInfo* info) { append(new LIR_Op1(lir_safepoint, tmp, info)); } + +- void convert(Bytecodes::Code code, LIR_Opr left, LIR_Opr dst, ConversionStub* stub = NULL/*, bool is_32bit = false*/) { append(new LIR_OpConvert(code, left, dst, stub)); } ++ void convert(Bytecodes::Code code, LIR_Opr left, LIR_Opr dst, ConversionStub* stub = NULL, LIR_Opr tmp = LIR_OprFact::illegalOpr) { ++ append(new LIR_OpConvert(code, left, dst, stub, tmp)); ++ } + + void logical_and (LIR_Opr left, LIR_Opr right, LIR_Opr dst) { append(new LIR_Op2(lir_logic_and, left, right, dst)); } + void logical_or (LIR_Opr left, LIR_Opr right, LIR_Opr dst) { append(new LIR_Op2(lir_logic_or, left, right, dst)); } +@@ -2146,6 +2241,15 @@ class LIR_List: public CompilationResourceObj { + cmp(condition, left, LIR_OprFact::intConst(right), info); + } + ++ // machine dependent ++ template ++ void cmp_branch(LIR_Condition condition, LIR_Opr left, LIR_Opr right, BasicType type, T tgt, CodeEmitInfo* info = NULL); ++ template ++ void cmp_branch(LIR_Condition condition, LIR_Opr left, int right, BasicType type, T tgt, CodeEmitInfo* info = NULL) { ++ cmp_branch(condition, left, LIR_OprFact::intConst(right), type, tgt, info); ++ } ++ void cmp_branch(LIR_Condition condition, LIR_Opr left, LIR_Opr right, BasicType type, BlockBegin* block, BlockBegin* unordered); ++ + void cmp_mem_int(LIR_Condition condition, LIR_Opr base, int disp, int c, CodeEmitInfo* info); + void cmp_reg_mem(LIR_Condition condition, LIR_Opr reg, LIR_Address* addr, CodeEmitInfo* info); + +@@ -2153,6 +2257,9 @@ class LIR_List: public CompilationResourceObj { + append(new LIR_Op2(lir_cmove, condition, src1, src2, dst, type)); + } + ++ // machine dependent ++ void cmp_cmove(LIR_Condition condition, LIR_Opr left, LIR_Opr right, LIR_Opr src1, LIR_Opr src2, LIR_Opr dst, BasicType type); ++ + void cas_long(LIR_Opr addr, LIR_Opr cmp_value, LIR_Opr new_value, + LIR_Opr t1, LIR_Opr t2, LIR_Opr result = LIR_OprFact::illegalOpr); + void cas_obj(LIR_Opr addr, LIR_Opr cmp_value, LIR_Opr new_value, +diff --git a/src/hotspot/share/c1/c1_LIRAssembler.cpp b/src/hotspot/share/c1/c1_LIRAssembler.cpp +index 160483d5f..bec297ebd 100644 +--- a/src/hotspot/share/c1/c1_LIRAssembler.cpp ++++ b/src/hotspot/share/c1/c1_LIRAssembler.cpp +@@ -777,6 +777,18 @@ void LIR_Assembler::emit_op2(LIR_Op2* op) { + } + + ++void LIR_Assembler::emit_op4(LIR_Op4* op) { ++ switch (op->code()) { ++ case lir_cmp_cmove: ++ cmp_cmove(op->condition(), op->in_opr1(), op->in_opr2(), op->in_opr3(), op->in_opr4(), op->result_opr(), op->type()); ++ break; ++ ++ default: ++ Unimplemented(); ++ break; ++ } ++} ++ + void LIR_Assembler::build_frame() { + _masm->build_frame(initial_frame_size_in_bytes(), bang_size_in_bytes()); + } +diff --git a/src/hotspot/share/c1/c1_LIRAssembler.hpp b/src/hotspot/share/c1/c1_LIRAssembler.hpp +index 44a5bcbe5..114b155f9 100644 +--- a/src/hotspot/share/c1/c1_LIRAssembler.hpp ++++ b/src/hotspot/share/c1/c1_LIRAssembler.hpp +@@ -190,7 +190,9 @@ class LIR_Assembler: public CompilationResourceObj { + void emit_op1(LIR_Op1* op); + void emit_op2(LIR_Op2* op); + void emit_op3(LIR_Op3* op); ++ void emit_op4(LIR_Op4* op); + void emit_opBranch(LIR_OpBranch* op); ++ void emit_opCmpBranch(LIR_OpCmpBranch* op); + void emit_opLabel(LIR_OpLabel* op); + void emit_arraycopy(LIR_OpArrayCopy* op); + void emit_updatecrc32(LIR_OpUpdateCRC32* op); +@@ -223,6 +225,7 @@ class LIR_Assembler: public CompilationResourceObj { + void comp_mem_op(LIR_Opr src, LIR_Opr result, BasicType type, CodeEmitInfo* info); // info set for null exceptions + void comp_fl2i(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr result, LIR_Op2* op); + void cmove(LIR_Condition code, LIR_Opr left, LIR_Opr right, LIR_Opr result, BasicType type); ++ void cmp_cmove(LIR_Condition code, LIR_Opr left, LIR_Opr right, LIR_Opr src1, LIR_Opr src2, LIR_Opr result, BasicType type); + + void call( LIR_OpJavaCall* op, relocInfo::relocType rtype); + void ic_call( LIR_OpJavaCall* op); +diff --git a/src/hotspot/share/c1/c1_LIRGenerator.cpp b/src/hotspot/share/c1/c1_LIRGenerator.cpp +index 88f6d3069..1d5a6668e 100644 +--- a/src/hotspot/share/c1/c1_LIRGenerator.cpp ++++ b/src/hotspot/share/c1/c1_LIRGenerator.cpp +@@ -480,13 +480,11 @@ void LIRGenerator::array_range_check(LIR_Opr array, LIR_Opr index, CodeEmitInfo* null_check_info, CodeEmitInfo* range_check_info) { CodeStub* stub = new RangeCheckStub(range_check_info, index, array); if (index->is_constant()) { - cmp_mem_int(lir_cond_belowEqual, array, arrayOopDesc::length_offset_in_bytes(), - index->as_jint(), null_check_info); - __ branch(lir_cond_belowEqual, T_INT, stub); // forward branch -- } else { ++ cmp_mem_int_branch(lir_cond_belowEqual, array, arrayOopDesc::length_offset_in_bytes(), ++ index->as_jint(), stub, null_check_info); // forward branch + } else { - cmp_reg_mem(lir_cond_aboveEqual, index, array, - arrayOopDesc::length_offset_in_bytes(), T_INT, null_check_info); - __ branch(lir_cond_aboveEqual, T_INT, stub); // forward branch -+ cmp_mem_int_branch(lir_cond_belowEqual, array, arrayOopDesc::length_offset_in_bytes(), -+ index->as_jint(), stub, null_check_info); // forward branch -+ } else { + cmp_reg_mem_branch(lir_cond_aboveEqual, index, array, arrayOopDesc::length_offset_in_bytes(), + T_INT, stub, null_check_info); // forward branch } } -@@ -493,12 +491,11 @@ +@@ -494,12 +492,11 @@ void LIRGenerator::array_range_check(LIR_Opr array, LIR_Opr index, void LIRGenerator::nio_range_check(LIR_Opr buffer, LIR_Opr index, LIR_Opr result, CodeEmitInfo* info) { CodeStub* stub = new RangeCheckStub(info, index); if (index->is_constant()) { @@ -108522,7 +114974,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/c1/c1_LI } __ move(index, result); } -@@ -934,7 +931,7 @@ +@@ -935,7 +932,7 @@ LIR_Opr LIRGenerator::force_to_spill(LIR_Opr value, BasicType t) { return tmp; } @@ -108531,7 +114983,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/c1/c1_LI if (if_instr->should_profile()) { ciMethod* method = if_instr->profiled_method(); assert(method != NULL, "method should be set if branch is profiled"); -@@ -955,10 +952,17 @@ +@@ -956,10 +953,17 @@ void LIRGenerator::profile_branch(If* if_instr, If::Condition cond) { __ metadata2reg(md->constant_encoding(), md_reg); LIR_Opr data_offset_reg = new_pointer_register(); @@ -108553,7 +115005,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/c1/c1_LI // MDO cells are intptr_t, so the data_reg width is arch-dependent. LIR_Opr data_reg = new_pointer_register(); -@@ -1315,8 +1319,8 @@ +@@ -1316,8 +1320,8 @@ void LIRGenerator::do_isPrimitive(Intrinsic* x) { } __ move(new LIR_Address(rcvr.result(), java_lang_Class::klass_offset_in_bytes(), T_ADDRESS), temp, info); @@ -108564,7 +115016,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/c1/c1_LI } -@@ -1598,8 +1602,8 @@ +@@ -1599,8 +1603,8 @@ void LIRGenerator::do_StoreIndexed(StoreIndexed* x) { if (GenerateRangeChecks && needs_range_check) { if (use_length) { @@ -108575,7 +115027,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/c1/c1_LI } else { array_range_check(array.result(), index.result(), null_check_info, range_check_info); // range_check also does the null check -@@ -1777,12 +1781,9 @@ +@@ -1778,12 +1782,9 @@ void LIRGenerator::do_NIOCheckIndex(Intrinsic* x) { CodeEmitInfo* info = state_for(x); CodeStub* stub = new RangeCheckStub(info, index.result()); if (index.result()->is_constant()) { @@ -108590,7 +115042,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/c1/c1_LI } __ move(index.result(), result); } else { -@@ -1860,8 +1861,8 @@ +@@ -1861,8 +1862,8 @@ void LIRGenerator::do_LoadIndexed(LoadIndexed* x) { } else if (use_length) { // TODO: use a (modified) version of array_range_check that does not require a // constant length to be loaded to a register @@ -108601,7 +115053,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/c1/c1_LI } else { array_range_check(array.result(), index.result(), null_check_info, range_check_info); // The range check performs the null check, so clear it out for the load -@@ -2234,19 +2235,14 @@ +@@ -2235,19 +2236,14 @@ void LIRGenerator::do_SwitchRanges(SwitchRangeArray* x, LIR_Opr value, BlockBegi int high_key = one_range->high_key(); BlockBegin* dest = one_range->sux(); if (low_key == high_key) { @@ -108626,7 +115078,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/c1/c1_LI __ branch_destination(L->label()); } } -@@ -2346,12 +2342,11 @@ +@@ -2347,12 +2343,11 @@ void LIRGenerator::do_TableSwitch(TableSwitch* x) { __ move(LIR_OprFact::intptrConst(default_count_offset), data_offset_reg); for (int i = 0; i < len; i++) { int count_offset = md->byte_offset_of_slot(data, MultiBranchData::case_count_offset(i)); @@ -108643,7 +115095,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/c1/c1_LI } LIR_Opr data_reg = new_pointer_register(); -@@ -2365,8 +2360,7 @@ +@@ -2366,8 +2361,7 @@ void LIRGenerator::do_TableSwitch(TableSwitch* x) { do_SwitchRanges(create_lookup_ranges(x), value, x->default_sux()); } else { for (int i = 0; i < len; i++) { @@ -108653,7 +115105,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/c1/c1_LI } __ jump(x->default_sux()); } -@@ -2404,12 +2398,11 @@ +@@ -2405,12 +2399,11 @@ void LIRGenerator::do_LookupSwitch(LookupSwitch* x) { __ move(LIR_OprFact::intptrConst(default_count_offset), data_offset_reg); for (int i = 0; i < len; i++) { int count_offset = md->byte_offset_of_slot(data, MultiBranchData::case_count_offset(i)); @@ -108670,7 +115122,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/c1/c1_LI } LIR_Opr data_reg = new_pointer_register(); -@@ -2424,8 +2417,7 @@ +@@ -2425,8 +2418,7 @@ void LIRGenerator::do_LookupSwitch(LookupSwitch* x) { } else { int len = x->length(); for (int i = 0; i < len; i++) { @@ -108680,7 +115132,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/c1/c1_LI } __ jump(x->default_sux()); } -@@ -2935,8 +2927,8 @@ +@@ -2936,8 +2928,8 @@ void LIRGenerator::do_IfOp(IfOp* x) { f_val.dont_load_item(); LIR_Opr reg = rlock_result(x); @@ -108691,7 +115143,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/c1/c1_LI } #ifdef JFR_HAVE_INTRINSICS -@@ -2980,8 +2972,7 @@ +@@ -2981,8 +2973,7 @@ void LIRGenerator::do_getEventWriter(Intrinsic* x) { __ move(LIR_OprFact::oopConst(NULL), result); LIR_Opr jobj = new_register(T_METADATA); __ move_wide(jobj_addr, jobj); @@ -108701,7 +115153,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/c1/c1_LI access_load(IN_NATIVE, T_OBJECT, LIR_OprFact::address(new LIR_Address(jobj, T_OBJECT)), result); -@@ -3286,21 +3277,24 @@ +@@ -3287,21 +3278,24 @@ void LIRGenerator::do_ProfileInvoke(ProfileInvoke* x) { void LIRGenerator::increment_backedge_counter_conditionally(LIR_Condition cond, LIR_Opr left, LIR_Opr right, CodeEmitInfo* info, int left_bci, int right_bci, int bci) { if (compilation()->count_backedges()) { @@ -108732,7 +115184,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/c1/c1_LI increment_backedge_counter(info, step, bci); } } -@@ -3339,8 +3333,7 @@ +@@ -3340,8 +3334,7 @@ void LIRGenerator::decrement_age(CodeEmitInfo* info) { // DeoptimizeStub will reexecute from the current state in code info. CodeStub* deopt = new DeoptimizeStub(info, Deoptimization::Reason_tenured, Deoptimization::Action_make_not_entrant); @@ -108742,7 +115194,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/c1/c1_LI } } -@@ -3386,8 +3379,7 @@ +@@ -3387,8 +3380,7 @@ void LIRGenerator::increment_event_counter_impl(CodeEmitInfo* info, int freq = frequency << InvocationCounter::count_shift; if (freq == 0) { if (!step->is_constant()) { @@ -108752,7 +115204,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/c1/c1_LI } else { __ branch(lir_cond_always, T_ILLEGAL, overflow); } -@@ -3395,12 +3387,11 @@ +@@ -3396,12 +3388,11 @@ void LIRGenerator::increment_event_counter_impl(CodeEmitInfo* info, LIR_Opr mask = load_immediate(freq, T_INT); if (!step->is_constant()) { // If step is 0, make sure the overflow check below always fails @@ -108768,7 +115220,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/c1/c1_LI } __ branch_destination(overflow->continuation()); } -@@ -3513,8 +3504,7 @@ +@@ -3514,8 +3505,7 @@ void LIRGenerator::do_RangeCheckPredicate(RangeCheckPredicate *x) { CodeEmitInfo *info = state_for(x, x->state()); CodeStub* stub = new PredicateFailedStub(info); @@ -108778,7 +115230,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/c1/c1_LI } } -@@ -3661,8 +3651,8 @@ +@@ -3662,8 +3652,8 @@ LIR_Opr LIRGenerator::mask_boolean(LIR_Opr array, LIR_Opr value, CodeEmitInfo*& __ move(new LIR_Address(klass, in_bytes(Klass::layout_helper_offset()), T_INT), layout); int diffbit = Klass::layout_helper_boolean_diffbit(); __ logical_and(layout, LIR_OprFact::intConst(diffbit), layout); @@ -108789,10 +115241,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/c1/c1_LI value = value_fixed; return value; } -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/c1/c1_LIRGenerator.hpp jdk11u-ls/src/hotspot/share/c1/c1_LIRGenerator.hpp ---- openjdk/src/hotspot/share/c1/c1_LIRGenerator.hpp 2022-10-12 23:00:01.000000000 +0800 -+++ jdk11u-ls/src/hotspot/share/c1/c1_LIRGenerator.hpp 2023-09-12 13:54:23.417572070 +0800 -@@ -363,8 +363,10 @@ +diff --git a/src/hotspot/share/c1/c1_LIRGenerator.hpp b/src/hotspot/share/c1/c1_LIRGenerator.hpp +index 3ad325d75..f377b2785 100644 +--- a/src/hotspot/share/c1/c1_LIRGenerator.hpp ++++ b/src/hotspot/share/c1/c1_LIRGenerator.hpp +@@ -363,8 +363,10 @@ class LIRGenerator: public InstructionVisitor, public BlockClosure { void new_instance (LIR_Opr dst, ciInstanceKlass* klass, bool is_unresolved, LIR_Opr scratch1, LIR_Opr scratch2, LIR_Opr scratch3, LIR_Opr scratch4, LIR_Opr klass_reg, CodeEmitInfo* info); // machine dependent @@ -108805,7 +115258,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/c1/c1_LI void arraycopy_helper(Intrinsic* x, int* flags, ciArrayKlass** expected_type); -@@ -391,7 +393,7 @@ +@@ -391,7 +393,7 @@ class LIRGenerator: public InstructionVisitor, public BlockClosure { LIR_Opr safepoint_poll_register(); @@ -108814,251 +115267,330 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/c1/c1_LI void increment_event_counter_impl(CodeEmitInfo* info, ciMethod *method, LIR_Opr step, int frequency, int bci, bool backedge, bool notify); -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/c1/c1_LIR.hpp jdk11u-ls/src/hotspot/share/c1/c1_LIR.hpp ---- openjdk/src/hotspot/share/c1/c1_LIR.hpp 2022-10-12 23:00:01.000000000 +0800 -+++ jdk11u-ls/src/hotspot/share/c1/c1_LIR.hpp 2023-09-12 13:54:23.413572065 +0800 -@@ -864,9 +864,11 @@ - class LIR_OpAllocObj; - class LIR_OpRoundFP; - class LIR_Op2; -+class LIR_OpCmpBranch; - class LIR_OpDelay; - class LIR_Op3; - class LIR_OpAllocArray; -+class LIR_Op4; - class LIR_OpCall; - class LIR_OpJavaCall; - class LIR_OpRTCall; -@@ -933,6 +935,8 @@ - , lir_cmp_l2i - , lir_ucmp_fd2i - , lir_cmp_fd2i -+ , lir_cmp_branch -+ , lir_cmp_float_branch - , lir_cmove - , lir_add - , lir_sub -@@ -964,6 +968,9 @@ - , lir_fmad - , lir_fmaf - , end_op3 -+ , begin_op4 -+ , lir_cmp_cmove -+ , end_op4 - , begin_opJavaCall - , lir_static_call - , lir_optvirtual_call -@@ -1128,12 +1135,14 @@ - virtual LIR_OpAllocObj* as_OpAllocObj() { return NULL; } - virtual LIR_OpRoundFP* as_OpRoundFP() { return NULL; } - virtual LIR_OpBranch* as_OpBranch() { return NULL; } -+ virtual LIR_OpCmpBranch* as_OpCmpBranch() { return NULL; } - virtual LIR_OpRTCall* as_OpRTCall() { return NULL; } - virtual LIR_OpConvert* as_OpConvert() { return NULL; } - virtual LIR_Op0* as_Op0() { return NULL; } - virtual LIR_Op1* as_Op1() { return NULL; } - virtual LIR_Op2* as_Op2() { return NULL; } - virtual LIR_Op3* as_Op3() { return NULL; } -+ virtual LIR_Op4* as_Op4() { return NULL; } - virtual LIR_OpArrayCopy* as_OpArrayCopy() { return NULL; } - virtual LIR_OpUpdateCRC32* as_OpUpdateCRC32() { return NULL; } - virtual LIR_OpTypeCheck* as_OpTypeCheck() { return NULL; } -@@ -1463,15 +1472,18 @@ - private: - Bytecodes::Code _bytecode; - ConversionStub* _stub; -+ LIR_Opr _tmp; - - public: -- LIR_OpConvert(Bytecodes::Code code, LIR_Opr opr, LIR_Opr result, ConversionStub* stub) -+ LIR_OpConvert(Bytecodes::Code code, LIR_Opr opr, LIR_Opr result, ConversionStub* stub, LIR_Opr tmp) - : LIR_Op1(lir_convert, opr, result) - , _stub(stub) -- , _bytecode(code) {} -+ , _bytecode(code) -+ , _tmp(tmp) {} - - Bytecodes::Code bytecode() const { return _bytecode; } - ConversionStub* stub() const { return _stub; } -+ LIR_Opr tmp() const { return _tmp; } - - virtual void emit_code(LIR_Assembler* masm); - virtual LIR_OpConvert* as_OpConvert() { return this; } -@@ -1626,7 +1638,7 @@ - , _tmp3(LIR_OprFact::illegalOpr) - , _tmp4(LIR_OprFact::illegalOpr) - , _tmp5(LIR_OprFact::illegalOpr) { -- assert(code == lir_cmp || code == lir_assert, "code check"); -+ assert(code == lir_cmp || code == lir_cmp_branch || code == lir_cmp_float_branch || code == lir_assert, "code check"); - } - - LIR_Op2(LIR_Code code, LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr result, BasicType type) -@@ -1658,7 +1670,7 @@ - , _tmp3(LIR_OprFact::illegalOpr) - , _tmp4(LIR_OprFact::illegalOpr) - , _tmp5(LIR_OprFact::illegalOpr) { -- assert(code != lir_cmp && is_in_range(code, begin_op2, end_op2), "code check"); -+ assert((code != lir_cmp && code != lir_cmp_branch && code != lir_cmp_float_branch) && is_in_range(code, begin_op2, end_op2), "code check"); - } - - LIR_Op2(LIR_Code code, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr result, LIR_Opr tmp1, LIR_Opr tmp2 = LIR_OprFact::illegalOpr, -@@ -1674,7 +1686,7 @@ - , _tmp3(tmp3) - , _tmp4(tmp4) - , _tmp5(tmp5) { -- assert(code != lir_cmp && is_in_range(code, begin_op2, end_op2), "code check"); -+ assert((code != lir_cmp && code != lir_cmp_branch && code != lir_cmp_float_branch) && is_in_range(code, begin_op2, end_op2), "code check"); - } - - LIR_Opr in_opr1() const { return _opr1; } -@@ -1686,10 +1698,12 @@ - LIR_Opr tmp4_opr() const { return _tmp4; } - LIR_Opr tmp5_opr() const { return _tmp5; } - LIR_Condition condition() const { -- assert(code() == lir_cmp || code() == lir_cmove || code() == lir_assert, "only valid for cmp and cmove and assert"); return _condition; -+ assert(code() == lir_cmp || code() == lir_cmp_branch || code() == lir_cmp_float_branch || code() == lir_cmove || code() == lir_assert, "only valid for cmp and cmove and assert"); -+ return _condition; - } - void set_condition(LIR_Condition condition) { -- assert(code() == lir_cmp || code() == lir_cmove, "only valid for cmp and cmove"); _condition = condition; -+ assert(code() == lir_cmp || code() == lir_cmp_branch || code() == lir_cmp_float_branch || code() == lir_cmove, "only valid for cmp and cmove"); -+ _condition = condition; - } - - void set_fpu_stack_size(int size) { _fpu_stack_size = size; } -@@ -1703,6 +1717,43 @@ - virtual void print_instr(outputStream* out) const PRODUCT_RETURN; - }; +diff --git a/src/hotspot/share/c1/c1_LinearScan.cpp b/src/hotspot/share/c1/c1_LinearScan.cpp +index acc969ac9..c16d0c255 100644 +--- a/src/hotspot/share/c1/c1_LinearScan.cpp ++++ b/src/hotspot/share/c1/c1_LinearScan.cpp +@@ -22,6 +22,12 @@ + * + */ -+class LIR_OpCmpBranch: public LIR_Op2 { -+ friend class LIR_OpVisitState; ++/* ++ * This file has been modified by Loongson Technology in 2025, These ++ * modifications are Copyright (c) 2022, 2025, Loongson Technology, and are made ++ * available on the same license terms set forth above. ++ */ + -+ private: -+ Label* _label; -+ BlockBegin* _block; // if this is a branch to a block, this is the block -+ BlockBegin* _ublock; // if this is a float-branch, this is the unorderd block -+ CodeStub* _stub; // if this is a branch to a stub, this is the stub + #include "precompiled.hpp" + #include "c1/c1_CFGPrinter.hpp" + #include "c1/c1_CodeStubs.hpp" +@@ -1258,6 +1264,23 @@ void LinearScan::add_register_hints(LIR_Op* op) { + } + break; + } ++ case lir_cmp_cmove: { ++ assert(op->as_Op4() != NULL, "lir_cmp_cmove must be LIR_Op4"); ++ LIR_Op4* cmove = (LIR_Op4*)op; + -+ public: -+ LIR_OpCmpBranch(LIR_Condition cond, LIR_Opr left, LIR_Opr right, Label* lbl, CodeEmitInfo* info = NULL) -+ : LIR_Op2(lir_cmp_branch, cond, left, right, info) -+ , _label(lbl) -+ , _block(NULL) -+ , _ublock(NULL) -+ , _stub(NULL) { } ++ LIR_Opr move_from = cmove->in_opr3(); ++ LIR_Opr move_to = cmove->result_opr(); + -+ LIR_OpCmpBranch(LIR_Condition cond, LIR_Opr left, LIR_Opr right, CodeStub* stub, CodeEmitInfo* info = NULL); -+ LIR_OpCmpBranch(LIR_Condition cond, LIR_Opr left, LIR_Opr right, BlockBegin* block, CodeEmitInfo* info = NULL); ++ if (move_to->is_register() && move_from->is_register()) { ++ Interval* from = interval_at(reg_num(move_from)); ++ Interval* to = interval_at(reg_num(move_to)); ++ if (from != NULL && to != NULL) { ++ to->set_register_hint(from); ++ TRACE_LINEAR_SCAN(4, tty->print_cr("operation at op_id %d: added hint from interval %d to %d", cmove->id(), from->reg_num(), to->reg_num())); ++ } ++ } ++ break; ++ } + default: + break; + } +@@ -3350,7 +3373,9 @@ void LinearScan::verify_no_oops_in_fixed_intervals() { + check_live = (move->patch_code() == lir_patch_none); + } + LIR_OpBranch* branch = op->as_OpBranch(); +- if (branch != NULL && branch->stub() != NULL && branch->stub()->is_exception_throw_stub()) { ++ LIR_OpCmpBranch* cmp_branch = op->as_OpCmpBranch(); ++ if ((branch != NULL && branch->stub() != NULL && branch->stub()->is_exception_throw_stub()) || ++ (cmp_branch != NULL && cmp_branch->stub() != NULL && cmp_branch->stub()->is_exception_throw_stub())) { + // Don't bother checking the stub in this case since the + // exception stub will never return to normal control flow. + check_live = false; +@@ -6200,6 +6225,16 @@ void ControlFlowOptimizer::substitute_branch_target(BlockBegin* block, BlockBegi + assert(op->as_OpBranch() != NULL, "branch must be of type LIR_OpBranch"); + LIR_OpBranch* branch = (LIR_OpBranch*)op; + ++ if (branch->block() == target_from) { ++ branch->change_block(target_to); ++ } ++ if (branch->ublock() == target_from) { ++ branch->change_ublock(target_to); ++ } ++ } else if (op->code() == lir_cmp_branch || op->code() == lir_cmp_float_branch) { ++ assert(op->as_OpCmpBranch() != NULL, "branch must be of type LIR_OpCmpBranch"); ++ LIR_OpCmpBranch* branch = (LIR_OpCmpBranch*)op; + -+ // for unordered comparisons -+ LIR_OpCmpBranch(LIR_Condition cond, LIR_Opr left, LIR_Opr right, BlockBegin* block, BlockBegin* ublock, CodeEmitInfo* info = NULL); + if (branch->block() == target_from) { + branch->change_block(target_to); + } +@@ -6328,6 +6363,20 @@ void ControlFlowOptimizer::delete_unnecessary_jumps(BlockList* code) { + } + } + } ++ } else if (prev_op->code() == lir_cmp_branch || prev_op->code() == lir_cmp_float_branch) { ++ assert(prev_op->as_OpCmpBranch() != NULL, "branch must be of type LIR_OpCmpBranch"); ++ LIR_OpCmpBranch* prev_branch = (LIR_OpCmpBranch*)prev_op; + -+ Label* label() const { return _label; } -+ BlockBegin* block() const { return _block; } -+ BlockBegin* ublock() const { return _ublock; } -+ CodeStub* stub() const { return _stub; } ++ if (prev_branch->stub() == NULL) { ++ if (prev_branch->block() == code->at(i + 1) && prev_branch->info() == NULL) { ++ TRACE_LINEAR_SCAN(3, tty->print_cr("Negating conditional branch and deleting unconditional branch at end of block B%d", block->block_id())); + -+ void change_block(BlockBegin* b); -+ void change_ublock(BlockBegin* b); -+ void negate_cond(); ++ // eliminate a conditional branch to the immediate successor ++ prev_branch->change_block(last_branch->block()); ++ prev_branch->negate_cond(); ++ instructions->trunc_to(instructions->length() - 1); ++ } ++ } + } + } + } +@@ -6403,6 +6452,13 @@ void ControlFlowOptimizer::verify(BlockList* code) { + assert(op_branch->block() == NULL || code->find(op_branch->block()) != -1, "branch target not valid"); + assert(op_branch->ublock() == NULL || code->find(op_branch->ublock()) != -1, "branch target not valid"); + } + -+ virtual void emit_code(LIR_Assembler* masm); -+ virtual LIR_OpCmpBranch* as_OpCmpBranch() { return this; } -+ virtual void print_instr(outputStream* out) const PRODUCT_RETURN; -+}; ++ LIR_OpCmpBranch* op_cmp_branch = instructions->at(j)->as_OpCmpBranch(); + - class LIR_OpAllocArray : public LIR_Op { - friend class LIR_OpVisitState; - -@@ -1767,6 +1818,48 @@ - }; ++ if (op_cmp_branch != NULL) { ++ assert(op_cmp_branch->block() == NULL || code->find(op_cmp_branch->block()) != -1, "branch target not valid"); ++ assert(op_cmp_branch->ublock() == NULL || code->find(op_cmp_branch->ublock()) != -1, "branch target not valid"); ++ } + } + for (j = 0; j < block->number_of_sux() - 1; j++) { +@@ -6647,6 +6703,24 @@ void LinearScanStatistic::collect(LinearScan* allocator) { + break; + } -+class LIR_Op4: public LIR_Op { -+ friend class LIR_OpVisitState; -+ -+ private: -+ LIR_Opr _opr1; -+ LIR_Opr _opr2; -+ LIR_Opr _opr3; -+ LIR_Opr _opr4; -+ BasicType _type; -+ LIR_Condition _condition; ++ case lir_cmp_branch: ++ case lir_cmp_float_branch: { ++ LIR_OpCmpBranch* branch = op->as_OpCmpBranch(); ++ if (branch->block() == NULL) { ++ inc_counter(counter_stub_branch); ++ } else { ++ inc_counter(counter_cond_branch); ++ } ++ inc_counter(counter_cmp); ++ break; ++ } + -+ void verify() const; ++ case lir_cmp_cmove: { ++ inc_counter(counter_misc_inst); ++ inc_counter(counter_cmp); ++ break; ++ } + -+ public: -+ LIR_Op4(LIR_Code code, LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr opr3, LIR_Opr opr4, LIR_Opr result, BasicType type) -+ : LIR_Op(code, result, NULL) -+ , _opr1(opr1) -+ , _opr2(opr2) -+ , _opr3(opr3) -+ , _opr4(opr4) -+ , _type(type) -+ , _condition(condition) { -+ assert(is_in_range(code, begin_op4, end_op4), "code check"); -+ assert(type != T_ILLEGAL, "cmove should have type"); -+ } -+ LIR_Opr in_opr1() const { return _opr1; } -+ LIR_Opr in_opr2() const { return _opr2; } -+ LIR_Opr in_opr3() const { return _opr3; } -+ LIR_Opr in_opr4() const { return _opr4; } -+ BasicType type() const { return _type; } -+ LIR_Condition condition() const { -+ assert(code() == lir_cmp_cmove, "only valid for cmp cmove"); return _condition; -+ } -+ void set_condition(LIR_Condition condition) { -+ assert(code() == lir_cmp_cmove, "only valid for cmp cmove"); _condition = condition; + case lir_neg: + case lir_add: + case lir_sub: +diff --git a/src/hotspot/share/classfile/classLoaderData.cpp b/src/hotspot/share/classfile/classLoaderData.cpp +index 37bd9d8ee..45c938c89 100644 +--- a/src/hotspot/share/classfile/classLoaderData.cpp ++++ b/src/hotspot/share/classfile/classLoaderData.cpp +@@ -614,6 +614,21 @@ void ClassLoaderData::unload() { + // after erroneous classes are released. + classes_do(InstanceKlass::notify_unload_class); + ++ // Method::clear_jmethod_ids only sets the jmethod_ids to NULL without ++ // releasing the memory for related JNIMethodBlocks and JNIMethodBlockNodes. ++ // This is done intentionally because native code (e.g. JVMTI agent) holding ++ // jmethod_ids may access them after the associated classes and class loader ++ // are unloaded. The Java Native Interface Specification says "method ID ++ // does not prevent the VM from unloading the class from which the ID has ++ // been derived. After the class is unloaded, the method or field ID becomes ++ // invalid". In real world usages, the native code may rely on jmethod_ids ++ // being NULL after class unloading. Hence, it is unsafe to free the memory ++ // from the VM side without knowing when native code is going to stop using ++ // them. ++ if (_jmethod_ids != NULL) { ++ Method::clear_jmethod_ids(this); + } + -+ virtual void emit_code(LIR_Assembler* masm); -+ virtual LIR_Op4* as_Op4() { return this; } -+ virtual void print_instr(outputStream* out) const PRODUCT_RETURN; -+}; -+ - //-------------------------------- - class LabelObj: public CompilationResourceObj { - private: -@@ -2115,7 +2208,9 @@ + // Clean up global class iterator for compiler + static_klass_iterator.adjust_saved_class(this); + } +@@ -749,15 +764,6 @@ ClassLoaderData::~ClassLoaderData() { + _metaspace = NULL; + delete m; + } +- // Clear all the JNI handles for methods +- // These aren't deallocated and are going to look like a leak, but that's +- // needed because we can't really get rid of jmethodIDs because we don't +- // know when native code is going to stop using them. The spec says that +- // they're "invalid" but existing programs likely rely on their being +- // NULL after class unloading. +- if (_jmethod_ids != NULL) { +- Method::clear_jmethod_ids(this); +- } + // Delete lock + delete _metaspace_lock; - void safepoint(LIR_Opr tmp, CodeEmitInfo* info) { append(new LIR_Op1(lir_safepoint, tmp, info)); } +diff --git a/src/hotspot/share/classfile/classLoaderData.hpp b/src/hotspot/share/classfile/classLoaderData.hpp +index aa6b25c0b..730feeef8 100644 +--- a/src/hotspot/share/classfile/classLoaderData.hpp ++++ b/src/hotspot/share/classfile/classLoaderData.hpp +@@ -293,7 +293,7 @@ class ClassLoaderData : public CHeapObj { + bool keep_alive() const { return _keep_alive > 0; } -- void convert(Bytecodes::Code code, LIR_Opr left, LIR_Opr dst, ConversionStub* stub = NULL/*, bool is_32bit = false*/) { append(new LIR_OpConvert(code, left, dst, stub)); } -+ void convert(Bytecodes::Code code, LIR_Opr left, LIR_Opr dst, ConversionStub* stub = NULL, LIR_Opr tmp = LIR_OprFact::illegalOpr) { -+ append(new LIR_OpConvert(code, left, dst, stub, tmp)); + oop holder_phantom() const; +- void classes_do(void f(Klass*)); ++ void classes_do(void f(Klass* const)); + void loaded_classes_do(KlassClosure* klass_closure); + void classes_do(void f(InstanceKlass*)); + void methods_do(void f(Method*)); +diff --git a/src/hotspot/share/classfile/stackMapTable.cpp b/src/hotspot/share/classfile/stackMapTable.cpp +index 7c9a2a156..518626f86 100644 +--- a/src/hotspot/share/classfile/stackMapTable.cpp ++++ b/src/hotspot/share/classfile/stackMapTable.cpp +@@ -122,8 +122,16 @@ bool StackMapTable::match_stackmap( + } + + void StackMapTable::check_jump_target( +- StackMapFrame* frame, int32_t target, TRAPS) const { ++ StackMapFrame* frame, int bci, int offset, TRAPS) const { + ErrorContext ctx; ++ // Jump targets must be within the method and the method size is limited. See JVMS 4.11 ++ int min_offset = -1 * max_method_code_size; ++ if (offset < min_offset || offset > max_method_code_size) { ++ frame->verifier()->verify_error(ErrorContext::bad_stackmap(bci, frame), ++ "Illegal target of jump or branch (bci %d + offset %d)", bci, offset); ++ return; + } ++ int target = bci + offset; + bool match = match_stackmap( + frame, target, true, false, &ctx, CHECK_VERIFY(frame->verifier())); + if (!match || (target < 0 || target >= _code_length)) { +diff --git a/src/hotspot/share/classfile/stackMapTable.hpp b/src/hotspot/share/classfile/stackMapTable.hpp +index 2a0bffcb0..5c31db7c4 100644 +--- a/src/hotspot/share/classfile/stackMapTable.hpp ++++ b/src/hotspot/share/classfile/stackMapTable.hpp +@@ -69,7 +69,7 @@ class StackMapTable : public StackObj { - void logical_and (LIR_Opr left, LIR_Opr right, LIR_Opr dst) { append(new LIR_Op2(lir_logic_and, left, right, dst)); } - void logical_or (LIR_Opr left, LIR_Opr right, LIR_Opr dst) { append(new LIR_Op2(lir_logic_or, left, right, dst)); } -@@ -2146,6 +2241,15 @@ - cmp(condition, left, LIR_OprFact::intConst(right), info); - } + // Check jump instructions. Make sure there are no uninitialized + // instances on backward branch. +- void check_jump_target(StackMapFrame* frame, int32_t target, TRAPS) const; ++ void check_jump_target(StackMapFrame* frame, int bci, int offset, TRAPS) const; -+ // machine dependent -+ template -+ void cmp_branch(LIR_Condition condition, LIR_Opr left, LIR_Opr right, BasicType type, T tgt, CodeEmitInfo* info = NULL); -+ template -+ void cmp_branch(LIR_Condition condition, LIR_Opr left, int right, BasicType type, T tgt, CodeEmitInfo* info = NULL) { -+ cmp_branch(condition, left, LIR_OprFact::intConst(right), type, tgt, info); -+ } -+ void cmp_branch(LIR_Condition condition, LIR_Opr left, LIR_Opr right, BasicType type, BlockBegin* block, BlockBegin* unordered); -+ - void cmp_mem_int(LIR_Condition condition, LIR_Opr base, int disp, int c, CodeEmitInfo* info); - void cmp_reg_mem(LIR_Condition condition, LIR_Opr reg, LIR_Address* addr, CodeEmitInfo* info); + // The following methods are only used inside this class. -@@ -2153,6 +2257,9 @@ - append(new LIR_Op2(lir_cmove, condition, src1, src2, dst, type)); +diff --git a/src/hotspot/share/classfile/verifier.cpp b/src/hotspot/share/classfile/verifier.cpp +index 70edfa9ef..2cb67387b 100644 +--- a/src/hotspot/share/classfile/verifier.cpp ++++ b/src/hotspot/share/classfile/verifier.cpp +@@ -717,7 +717,6 @@ void ClassVerifier::verify_method(const methodHandle& m, TRAPS) { + // Merge with the next instruction + { + u2 index; +- int target; + VerificationType type, type2; + VerificationType atype; + +@@ -1534,9 +1533,8 @@ void ClassVerifier::verify_method(const methodHandle& m, TRAPS) { + case Bytecodes::_ifle: + current_frame.pop_stack( + VerificationType::integer_type(), CHECK_VERIFY(this)); +- target = bcs.dest(); + stackmap_table.check_jump_target( +- ¤t_frame, target, CHECK_VERIFY(this)); ++ ¤t_frame, bcs.bci(), bcs.get_offset_s2(), CHECK_VERIFY(this)); + no_control_flow = false; break; + case Bytecodes::_if_acmpeq : + case Bytecodes::_if_acmpne : +@@ -1547,19 +1545,16 @@ void ClassVerifier::verify_method(const methodHandle& m, TRAPS) { + case Bytecodes::_ifnonnull : + current_frame.pop_stack( + VerificationType::reference_check(), CHECK_VERIFY(this)); +- target = bcs.dest(); + stackmap_table.check_jump_target +- (¤t_frame, target, CHECK_VERIFY(this)); ++ (¤t_frame, bcs.bci(), bcs.get_offset_s2(), CHECK_VERIFY(this)); + no_control_flow = false; break; + case Bytecodes::_goto : +- target = bcs.dest(); + stackmap_table.check_jump_target( +- ¤t_frame, target, CHECK_VERIFY(this)); ++ ¤t_frame, bcs.bci(), bcs.get_offset_s2(), CHECK_VERIFY(this)); + no_control_flow = true; break; + case Bytecodes::_goto_w : +- target = bcs.dest_w(); + stackmap_table.check_jump_target( +- ¤t_frame, target, CHECK_VERIFY(this)); ++ ¤t_frame, bcs.bci(), bcs.get_offset_s4(), CHECK_VERIFY(this)); + no_control_flow = true; break; + case Bytecodes::_tableswitch : + case Bytecodes::_lookupswitch : +@@ -2208,15 +2203,14 @@ void ClassVerifier::verify_switch( + } + } } +- int target = bci + default_offset; +- stackmap_table->check_jump_target(current_frame, target, CHECK_VERIFY(this)); ++ stackmap_table->check_jump_target(current_frame, bci, default_offset, CHECK_VERIFY(this)); + for (int i = 0; i < keys; i++) { + // Because check_jump_target() may safepoint, the bytecode could have + // moved, which means 'aligned_bcp' is no good and needs to be recalculated. + aligned_bcp = align_up(bcs->bcp() + 1, jintSize); +- target = bci + (jint)Bytes::get_Java_u4(aligned_bcp+(3+i*delta)*jintSize); ++ int offset = (jint)Bytes::get_Java_u4(aligned_bcp+(3+i*delta)*jintSize); + stackmap_table->check_jump_target( +- current_frame, target, CHECK_VERIFY(this)); ++ current_frame, bci, offset, CHECK_VERIFY(this)); + } + NOT_PRODUCT(aligned_bcp = NULL); // no longer valid at this point + } +@@ -2479,8 +2473,13 @@ bool ClassVerifier::ends_in_athrow(u4 start_bc_offset) { + break; -+ // machine dependent -+ void cmp_cmove(LIR_Condition condition, LIR_Opr left, LIR_Opr right, LIR_Opr src1, LIR_Opr src2, LIR_Opr dst, BasicType type); -+ - void cas_long(LIR_Opr addr, LIR_Opr cmp_value, LIR_Opr new_value, - LIR_Opr t1, LIR_Opr t2, LIR_Opr result = LIR_OprFact::illegalOpr); - void cas_obj(LIR_Opr addr, LIR_Opr cmp_value, LIR_Opr new_value, -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/code/nmethod.cpp jdk11u-ls/src/hotspot/share/code/nmethod.cpp ---- openjdk/src/hotspot/share/code/nmethod.cpp 2022-10-12 23:00:01.000000000 +0800 -+++ jdk11u-ls/src/hotspot/share/code/nmethod.cpp 2023-09-12 13:54:23.485572155 +0800 + case Bytecodes::_goto: +- case Bytecodes::_goto_w: +- target = (opcode == Bytecodes::_goto ? bcs.dest() : bcs.dest_w()); ++ case Bytecodes::_goto_w: { ++ int offset = (opcode == Bytecodes::_goto ? bcs.get_offset_s2() : bcs.get_offset_s4()); ++ int min_offset = -1 * max_method_code_size; ++ // Check offset for overflow ++ if (offset < min_offset || offset > max_method_code_size) return false; ++ ++ target = bci + offset; + if (visited_branches->contains(bci)) { + if (bci_stack->is_empty()) { + if (handler_stack->is_empty()) { +@@ -2501,6 +2500,7 @@ bool ClassVerifier::ends_in_athrow(u4 start_bc_offset) { + visited_branches->append(bci); + } + break; ++ } + + // Check that all switch alternatives end in 'athrow' bytecodes. Since it + // is difficult to determine where each switch alternative ends, parse +@@ -2537,7 +2537,10 @@ bool ClassVerifier::ends_in_athrow(u4 start_bc_offset) { + + // Push the switch alternatives onto the stack. + for (int i = 0; i < keys; i++) { +- u4 target = bci + (jint)Bytes::get_Java_u4(aligned_bcp+(3+i*delta)*jintSize); ++ int min_offset = -1 * max_method_code_size; ++ int offset = (jint)Bytes::get_Java_u4(aligned_bcp+(3+i*delta)*jintSize); ++ if (offset < min_offset || offset > max_method_code_size) return false; ++ u4 target = bci + offset; + if (target > code_length) return false; + bci_stack->push(target); + } +diff --git a/src/hotspot/share/code/nmethod.cpp b/src/hotspot/share/code/nmethod.cpp +index 6bc63116b..41c0a0ea3 100644 +--- a/src/hotspot/share/code/nmethod.cpp ++++ b/src/hotspot/share/code/nmethod.cpp @@ -22,6 +22,12 @@ * */ @@ -109072,7 +115604,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/code/nme #include "precompiled.hpp" #include "jvm.h" #include "code/codeCache.hpp" -@@ -2155,7 +2161,8 @@ +@@ -2159,7 +2165,8 @@ void nmethod::verify_scopes() { //verify_interrupt_point(iter.addr()); break; case relocInfo::runtime_call_type: @@ -109082,7 +115614,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/code/nme address destination = iter.reloc()->value(); // Right now there is no way to find out which entries support // an interrupt point. It would be nice if we had this -@@ -2392,7 +2399,8 @@ +@@ -2396,7 +2403,8 @@ const char* nmethod::reloc_string_for(u_char* begin, u_char* end) { return st.as_string(); } case relocInfo::runtime_call_type: @@ -109092,10 +115624,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/code/nme stringStream st; st.print("runtime_call"); CallRelocation* r = (CallRelocation*)iter.reloc(); -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/code/relocInfo.cpp jdk11u-ls/src/hotspot/share/code/relocInfo.cpp ---- openjdk/src/hotspot/share/code/relocInfo.cpp 2022-10-12 23:00:01.000000000 +0800 -+++ jdk11u-ls/src/hotspot/share/code/relocInfo.cpp 2023-09-12 13:54:23.489572160 +0800 -@@ -433,6 +433,7 @@ +diff --git a/src/hotspot/share/code/relocInfo.cpp b/src/hotspot/share/code/relocInfo.cpp +index a20de8dde..c6f49cf7d 100644 +--- a/src/hotspot/share/code/relocInfo.cpp ++++ b/src/hotspot/share/code/relocInfo.cpp +@@ -433,6 +433,7 @@ void virtual_call_Relocation::unpack_data() { _cached_value = x0==0? NULL: address_from_scaled_offset(x0, point); } @@ -109103,7 +115636,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/code/rel void runtime_call_w_cp_Relocation::pack_data_to(CodeSection * dest) { short* p = pack_1_int_to((short *)dest->locs_end(), (jint)(_offset >> 2)); dest->set_locs_end((relocInfo*) p); -@@ -441,6 +442,7 @@ +@@ -441,6 +442,7 @@ void runtime_call_w_cp_Relocation::pack_data_to(CodeSection * dest) { void runtime_call_w_cp_Relocation::unpack_data() { _offset = unpack_1_int() << 2; } @@ -109111,7 +115644,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/code/rel void static_stub_Relocation::pack_data_to(CodeSection* dest) { short* p = (short*) dest->locs_end(); -@@ -910,7 +912,7 @@ +@@ -910,7 +912,7 @@ void RelocIterator::print_current() { break; } case relocInfo::runtime_call_type: @@ -109120,10 +115653,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/code/rel { CallRelocation* r = (CallRelocation*) reloc(); tty->print(" | [destination=" INTPTR_FORMAT "]", p2i(r->destination())); -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/code/relocInfo.hpp jdk11u-ls/src/hotspot/share/code/relocInfo.hpp ---- openjdk/src/hotspot/share/code/relocInfo.hpp 2022-10-12 23:00:01.000000000 +0800 -+++ jdk11u-ls/src/hotspot/share/code/relocInfo.hpp 2023-09-12 13:54:23.489572160 +0800 -@@ -269,7 +269,11 @@ +diff --git a/src/hotspot/share/code/relocInfo.hpp b/src/hotspot/share/code/relocInfo.hpp +index 57931a1a6..fb56fd3ab 100644 +--- a/src/hotspot/share/code/relocInfo.hpp ++++ b/src/hotspot/share/code/relocInfo.hpp +@@ -269,7 +269,11 @@ class relocInfo { poll_return_type = 11, // polling instruction for safepoints at return metadata_type = 12, // metadata that used to be oops trampoline_stub_type = 13, // stub-entry for trampoline @@ -109135,7 +115669,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/code/rel data_prefix_tag = 15, // tag for a prefix (carries data arguments) type_mask = 15 // A mask which selects only the above values }; -@@ -304,13 +308,13 @@ +@@ -304,13 +308,13 @@ class relocInfo { visitor(static_call) \ visitor(static_stub) \ visitor(runtime_call) \ @@ -109151,7 +115685,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/code/rel public: -@@ -1174,6 +1178,15 @@ +@@ -1174,6 +1178,15 @@ class runtime_call_Relocation : public CallRelocation { }; @@ -109167,7 +115701,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/code/rel class runtime_call_w_cp_Relocation : public CallRelocation { relocInfo::relocType type() { return relocInfo::runtime_call_w_cp_type; } -@@ -1202,6 +1215,7 @@ +@@ -1202,6 +1215,7 @@ class runtime_call_w_cp_Relocation : public CallRelocation { void pack_data_to(CodeSection * dest); void unpack_data(); }; @@ -109175,9 +115709,10 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/code/rel // Trampoline Relocations. // A trampoline allows to encode a small branch in the code, even if there -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/code/vtableStubs.cpp jdk11u-ls/src/hotspot/share/code/vtableStubs.cpp ---- openjdk/src/hotspot/share/code/vtableStubs.cpp 2022-10-12 23:00:01.000000000 +0800 -+++ jdk11u-ls/src/hotspot/share/code/vtableStubs.cpp 2023-09-12 13:54:23.489572160 +0800 +diff --git a/src/hotspot/share/code/vtableStubs.cpp b/src/hotspot/share/code/vtableStubs.cpp +index 3c986f40f..23d07f050 100644 +--- a/src/hotspot/share/code/vtableStubs.cpp ++++ b/src/hotspot/share/code/vtableStubs.cpp @@ -22,6 +22,12 @@ * */ @@ -109191,7 +115726,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/code/vta #include "precompiled.hpp" #include "code/vtableStubs.hpp" #include "compiler/compileBroker.hpp" -@@ -98,7 +104,11 @@ +@@ -98,7 +104,11 @@ int VtableStubs::_itab_stub_size = 0; #if defined(PRODUCT) // These values are good for the PRODUCT case (no tracing). @@ -109203,7 +115738,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/code/vta static const int first_itableStub_size = 256; #else // These values are good for the non-PRODUCT case (when tracing can be switched on). -@@ -109,6 +119,7 @@ +@@ -109,6 +119,7 @@ int VtableStubs::_itab_stub_size = 0; // vtable itable // aarch64: 460 324 // arm: ? ? @@ -109211,10 +115746,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/code/vta // ppc (linux, BE): 404 288 // ppc (linux, LE): 356 276 // ppc (AIX): 416 296 -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/gc/g1/c1/g1BarrierSetC1.cpp jdk11u-ls/src/hotspot/share/gc/g1/c1/g1BarrierSetC1.cpp ---- openjdk/src/hotspot/share/gc/g1/c1/g1BarrierSetC1.cpp 2022-10-12 23:00:01.000000000 +0800 -+++ jdk11u-ls/src/hotspot/share/gc/g1/c1/g1BarrierSetC1.cpp 2023-09-12 13:54:23.521572201 +0800 -@@ -74,7 +74,6 @@ +diff --git a/src/hotspot/share/gc/g1/c1/g1BarrierSetC1.cpp b/src/hotspot/share/gc/g1/c1/g1BarrierSetC1.cpp +index 4289e5e5c..9502463bd 100644 +--- a/src/hotspot/share/gc/g1/c1/g1BarrierSetC1.cpp ++++ b/src/hotspot/share/gc/g1/c1/g1BarrierSetC1.cpp +@@ -74,7 +74,6 @@ void G1BarrierSetC1::pre_barrier(LIRAccess& access, LIR_Opr addr_opr, // Read the marking-in-progress flag. LIR_Opr flag_val = gen->new_register(T_INT); __ load(mark_active_flag_addr, flag_val); @@ -109222,7 +115758,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/gc/g1/c1 LIR_PatchCode pre_val_patch_code = lir_patch_none; -@@ -103,7 +102,7 @@ +@@ -103,7 +102,7 @@ void G1BarrierSetC1::pre_barrier(LIRAccess& access, LIR_Opr addr_opr, slow = new G1PreBarrierStub(pre_val); } @@ -109231,7 +115767,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/gc/g1/c1 __ branch_destination(slow->continuation()); } -@@ -168,10 +167,9 @@ +@@ -168,10 +167,9 @@ void G1BarrierSetC1::post_barrier(LIRAccess& access, LIR_OprDesc* addr, LIR_OprD } assert(new_val->is_register(), "must be a register at this point"); @@ -109244,10 +115780,73 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/gc/g1/c1 __ branch_destination(slow->continuation()); } -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/gc/parallel/psPromotionManager.inline.hpp jdk11u-ls/src/hotspot/share/gc/parallel/psPromotionManager.inline.hpp ---- openjdk/src/hotspot/share/gc/parallel/psPromotionManager.inline.hpp 2022-10-12 23:00:01.000000000 +0800 -+++ jdk11u-ls/src/hotspot/share/gc/parallel/psPromotionManager.inline.hpp 2023-09-12 13:54:23.577572271 +0800 -@@ -51,8 +51,9 @@ +diff --git a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp +index b9c0627a3..1ed5470ec 100644 +--- a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp ++++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp +@@ -22,6 +22,12 @@ + * + */ + ++/* ++ * This file has been modified by Loongson Technology in 2025, These ++ * modifications are Copyright (c) 2025, Loongson Technology, and are made ++ * available on the same license terms set forth above. ++ */ ++ + #include "precompiled.hpp" + #include "classfile/metadataOnStackMark.hpp" + #include "classfile/symbolTable.hpp" +@@ -2764,6 +2770,9 @@ void G1CMTask::do_marking_step(double time_target_ms, + // Since we've done everything else, we can now totally drain the + // local queue and global stack. + drain_local_queue(false); ++ // Load of _age._fields._top in drain_local_queue must not pass ++ // the load of _age._fields._top in assert _task_queue->size(). ++ LOONGARCH64_ONLY(DEBUG_ONLY(OrderAccess::loadload();)) + drain_global_stack(false); + + // Attempt at work stealing from other task's queues. +@@ -2783,6 +2792,9 @@ void G1CMTask::do_marking_step(double time_target_ms, + // And since we're towards the end, let's totally drain the + // local queue and global stack. + drain_local_queue(false); ++ // Load of _age._fields._top in drain_local_queue must not pass ++ // the load of _age._fields._top in assert _task_queue->size(). ++ LOONGARCH64_ONLY(DEBUG_ONLY(OrderAccess::loadload();)) + drain_global_stack(false); + } else { + break; +diff --git a/src/hotspot/share/gc/g1/g1FullGCMarker.inline.hpp b/src/hotspot/share/gc/g1/g1FullGCMarker.inline.hpp +index 98a2fe7f1..b43a44106 100644 +--- a/src/hotspot/share/gc/g1/g1FullGCMarker.inline.hpp ++++ b/src/hotspot/share/gc/g1/g1FullGCMarker.inline.hpp +@@ -22,6 +22,12 @@ + * + */ + ++/* ++ * This file has been modified by Loongson Technology in 2022. These ++ * modifications are Copyright (c) 2022, Loongson Technology, and are made ++ * available on the same license terms set forth above. ++ */ ++ + #ifndef SHARE_VM_GC_G1_G1MARKSTACK_INLINE_HPP + #define SHARE_VM_GC_G1_G1MARKSTACK_INLINE_HPP + +@@ -71,6 +77,7 @@ template inline void G1FullGCMarker::mark_and_push(T* p) { + _oop_stack.push(obj); + assert(_bitmap->is_marked(obj), "Must be marked now - map self"); + } else { ++ DEBUG_ONLY(OrderAccess::loadload()); + assert(_bitmap->is_marked(obj) || G1ArchiveAllocator::is_closed_archive_object(obj), + "Must be marked by other or closed archive object"); + } +diff --git a/src/hotspot/share/gc/parallel/psPromotionManager.inline.hpp b/src/hotspot/share/gc/parallel/psPromotionManager.inline.hpp +index 1ef900783..b30456429 100644 +--- a/src/hotspot/share/gc/parallel/psPromotionManager.inline.hpp ++++ b/src/hotspot/share/gc/parallel/psPromotionManager.inline.hpp +@@ -51,8 +51,9 @@ template inline void PSPromotionManager::claim_or_forward_internal_depth(T* p) { if (p != NULL) { // XXX: error if p != NULL here oop o = RawAccess::oop_load(p); @@ -109259,7 +115858,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/gc/paral // Card mark if (PSScavenge::is_obj_in_young(o)) { PSScavenge::card_table()->inline_write_ref_field_gc(p, o); -@@ -282,13 +283,17 @@ +@@ -282,13 +283,17 @@ inline void PSPromotionManager::copy_and_push_safe_barrier(T* p) { assert(should_scavenge(p, true), "revisiting object?"); oop o = RawAccess::oop_load(p); @@ -109281,10 +115880,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/gc/paral log_develop_trace(gc, scavenge)("{%s %s " PTR_FORMAT " -> " PTR_FORMAT " (%d)}", "forwarding", new_obj->klass()->internal_name(), p2i((void *)o), p2i((void *)new_obj), new_obj->size()); -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/gc/parallel/psScavenge.inline.hpp jdk11u-ls/src/hotspot/share/gc/parallel/psScavenge.inline.hpp ---- openjdk/src/hotspot/share/gc/parallel/psScavenge.inline.hpp 2022-10-12 23:00:01.000000000 +0800 -+++ jdk11u-ls/src/hotspot/share/gc/parallel/psScavenge.inline.hpp 2023-09-12 13:54:23.577572271 +0800 -@@ -104,8 +104,9 @@ +diff --git a/src/hotspot/share/gc/parallel/psScavenge.inline.hpp b/src/hotspot/share/gc/parallel/psScavenge.inline.hpp +index 0c58fd4b3..415990ff5 100644 +--- a/src/hotspot/share/gc/parallel/psScavenge.inline.hpp ++++ b/src/hotspot/share/gc/parallel/psScavenge.inline.hpp +@@ -104,8 +104,9 @@ class PSScavengeFromCLDClosure: public OopClosure { oop o = *p; oop new_obj; @@ -109296,10 +115896,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/gc/paral } else { new_obj = _pm->copy_to_survivor_space(o); } -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/gc/shared/c1/barrierSetC1.cpp jdk11u-ls/src/hotspot/share/gc/shared/c1/barrierSetC1.cpp ---- openjdk/src/hotspot/share/gc/shared/c1/barrierSetC1.cpp 2022-10-12 23:00:01.000000000 +0800 -+++ jdk11u-ls/src/hotspot/share/gc/shared/c1/barrierSetC1.cpp 2023-09-12 13:54:23.585572281 +0800 -@@ -192,8 +192,7 @@ +diff --git a/src/hotspot/share/gc/shared/c1/barrierSetC1.cpp b/src/hotspot/share/gc/shared/c1/barrierSetC1.cpp +index 5241322a9..0ddabb4da 100644 +--- a/src/hotspot/share/gc/shared/c1/barrierSetC1.cpp ++++ b/src/hotspot/share/gc/shared/c1/barrierSetC1.cpp +@@ -192,8 +192,7 @@ void BarrierSetC1::load_at_resolved(LIRAccess& access, LIR_Opr result) { /* Normalize boolean value returned by unsafe operation, i.e., value != 0 ? value = true : value false. */ if (mask_boolean) { LabelObj* equalZeroLabel = new LabelObj(); @@ -109309,7 +115910,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/gc/share __ move(LIR_OprFact::intConst(1), result); __ branch_destination(equalZeroLabel->label()); } -@@ -320,14 +319,12 @@ +@@ -320,14 +319,12 @@ void BarrierSetC1::generate_referent_check(LIRAccess& access, LabelObj* cont) { referent_off = gen->new_register(T_LONG); __ move(LIR_OprFact::longConst(java_lang_ref_Reference::referent_offset), referent_off); } @@ -109326,7 +115927,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/gc/share } LIR_Opr src_klass = gen->new_register(T_METADATA); if (gen_type_check) { -@@ -337,8 +334,7 @@ +@@ -337,8 +334,7 @@ void BarrierSetC1::generate_referent_check(LIRAccess& access, LabelObj* cont) { LIR_Address* reference_type_addr = new LIR_Address(src_klass, in_bytes(InstanceKlass::reference_type_offset()), T_BYTE); LIR_Opr reference_type = gen->new_register(T_INT); __ move(reference_type_addr, reference_type); @@ -109336,10 +115937,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/gc/share } } } -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/gc/shared/c1/cardTableBarrierSetC1.cpp jdk11u-ls/src/hotspot/share/gc/shared/c1/cardTableBarrierSetC1.cpp ---- openjdk/src/hotspot/share/gc/shared/c1/cardTableBarrierSetC1.cpp 2022-10-12 23:00:01.000000000 +0800 -+++ jdk11u-ls/src/hotspot/share/gc/shared/c1/cardTableBarrierSetC1.cpp 2023-09-12 13:54:23.585572281 +0800 -@@ -89,8 +89,7 @@ +diff --git a/src/hotspot/share/gc/shared/c1/cardTableBarrierSetC1.cpp b/src/hotspot/share/gc/shared/c1/cardTableBarrierSetC1.cpp +index 84815adea..57e29f129 100644 +--- a/src/hotspot/share/gc/shared/c1/cardTableBarrierSetC1.cpp ++++ b/src/hotspot/share/gc/shared/c1/cardTableBarrierSetC1.cpp +@@ -89,8 +89,7 @@ void CardTableBarrierSetC1::post_barrier(LIRAccess& access, LIR_OprDesc* addr, L __ move(card_addr, cur_value); LabelObj* L_already_dirty = new LabelObj(); @@ -109349,10 +115951,51 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/gc/share __ move(dirty, card_addr); __ branch_destination(L_already_dirty->label()); } else { -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/gc/shenandoah/c1/shenandoahBarrierSetC1.cpp jdk11u-ls/src/hotspot/share/gc/shenandoah/c1/shenandoahBarrierSetC1.cpp ---- openjdk/src/hotspot/share/gc/shenandoah/c1/shenandoahBarrierSetC1.cpp 2022-10-12 23:00:01.000000000 +0800 -+++ jdk11u-ls/src/hotspot/share/gc/shenandoah/c1/shenandoahBarrierSetC1.cpp 2023-09-12 13:54:23.609572311 +0800 -@@ -73,7 +73,6 @@ +diff --git a/src/hotspot/share/gc/shared/c2/barrierSetC2.cpp b/src/hotspot/share/gc/shared/c2/barrierSetC2.cpp +index 545275644..62adf9971 100644 +--- a/src/hotspot/share/gc/shared/c2/barrierSetC2.cpp ++++ b/src/hotspot/share/gc/shared/c2/barrierSetC2.cpp +@@ -22,6 +22,12 @@ + * + */ + ++/* ++ * This file has been modified by Loongson Technology in 2023, These ++ * modifications are Copyright (c) 2023, Loongson Technology, and are made ++ * available on the same license terms set forth above. ++ */ ++ + #include "precompiled.hpp" + #include "gc/shared/c2/barrierSetC2.hpp" + #include "opto/arraycopynode.hpp" +@@ -197,6 +203,8 @@ public: + + bool is_volatile = (decorators & MO_SEQ_CST) != 0; + bool is_acquire = (decorators & MO_ACQUIRE) != 0; ++ bool is_relaxed = (decorators & MO_RELAXED) != 0; ++ bool is_unsafe = (decorators & C2_UNSAFE_ACCESS) != 0; + + // If reference is volatile, prevent following volatiles ops from + // floating up before the volatile access. +@@ -227,6 +235,13 @@ public: + assert(_leading_membar == NULL || support_IRIW_for_not_multiple_copy_atomic_cpu, "no leading membar expected"); + Node* mb = kit->insert_mem_bar(Op_MemBarAcquire, n); + mb->as_MemBar()->set_trailing_load(); ++ } else if (is_relaxed && is_unsafe) { ++#ifdef LOONGARCH64 ++ assert(kit != NULL, "unsupported at optimization time"); ++ Node* n = _access.raw_access(); ++ Node* mb = kit->insert_mem_bar(Op_SameAddrLoadFence, n); ++ mb->as_MemBar()->set_trailing_load(); ++#endif + } + } + } +diff --git a/src/hotspot/share/gc/shenandoah/c1/shenandoahBarrierSetC1.cpp b/src/hotspot/share/gc/shenandoah/c1/shenandoahBarrierSetC1.cpp +index f51d18648..506f0301f 100644 +--- a/src/hotspot/share/gc/shenandoah/c1/shenandoahBarrierSetC1.cpp ++++ b/src/hotspot/share/gc/shenandoah/c1/shenandoahBarrierSetC1.cpp +@@ -73,7 +73,6 @@ void ShenandoahBarrierSetC1::pre_barrier(LIRGenerator* gen, CodeEmitInfo* info, // Read the marking-in-progress flag. LIR_Opr flag_val = gen->new_register(T_INT); __ load(mark_active_flag_addr, flag_val); @@ -109360,7 +116003,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/gc/shena LIR_PatchCode pre_val_patch_code = lir_patch_none; -@@ -101,7 +100,7 @@ +@@ -101,7 +100,7 @@ void ShenandoahBarrierSetC1::pre_barrier(LIRGenerator* gen, CodeEmitInfo* info, slow = new ShenandoahPreBarrierStub(pre_val); } @@ -109369,7 +116012,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/gc/shena __ branch_destination(slow->continuation()); } -@@ -144,10 +143,9 @@ +@@ -144,10 +143,9 @@ LIR_Opr ShenandoahBarrierSetC1::load_reference_barrier_impl(LIRGenerator* gen, L __ logical_and(flag_val, mask_reg, masked_flag); flag_val = masked_flag; } @@ -109381,10 +116024,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/gc/shena __ branch_destination(slow->continuation()); return result; -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/gc/z/c1/zBarrierSetC1.cpp jdk11u-ls/src/hotspot/share/gc/z/c1/zBarrierSetC1.cpp ---- openjdk/src/hotspot/share/gc/z/c1/zBarrierSetC1.cpp 2022-10-12 23:00:01.000000000 +0800 -+++ jdk11u-ls/src/hotspot/share/gc/z/c1/zBarrierSetC1.cpp 2023-09-12 13:54:23.629572336 +0800 -@@ -105,15 +105,20 @@ +diff --git a/src/hotspot/share/gc/z/c1/zBarrierSetC1.cpp b/src/hotspot/share/gc/z/c1/zBarrierSetC1.cpp +index 9f8ce7424..3c1862d82 100644 +--- a/src/hotspot/share/gc/z/c1/zBarrierSetC1.cpp ++++ b/src/hotspot/share/gc/z/c1/zBarrierSetC1.cpp +@@ -105,15 +105,20 @@ public: virtual void visit(LIR_OpVisitState* state) { state->do_input(_opr); @@ -109406,7 +116050,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/gc/z/c1/ } #ifndef PRODUCT -@@ -149,13 +154,21 @@ +@@ -149,13 +154,21 @@ address ZBarrierSetC1::load_barrier_on_oop_field_preloaded_runtime_stub(Decorato #endif void ZBarrierSetC1::load_barrier(LIRAccess& access, LIR_Opr result) const { @@ -109430,9 +116074,40 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/gc/z/c1/ __ branch_destination(stub->continuation()); } -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/interpreter/interpreterRuntime.cpp jdk11u-ls/src/hotspot/share/interpreter/interpreterRuntime.cpp ---- openjdk/src/hotspot/share/interpreter/interpreterRuntime.cpp 2022-10-12 23:00:01.000000000 +0800 -+++ jdk11u-ls/src/hotspot/share/interpreter/interpreterRuntime.cpp 2023-11-01 09:34:25.709945506 +0800 +diff --git a/src/hotspot/share/interpreter/bytecodeStream.hpp b/src/hotspot/share/interpreter/bytecodeStream.hpp +index ae1f86a50..1fa1accff 100644 +--- a/src/hotspot/share/interpreter/bytecodeStream.hpp ++++ b/src/hotspot/share/interpreter/bytecodeStream.hpp +@@ -100,8 +100,23 @@ class BaseBytecodeStream: StackObj { + void set_next_bci(int bci) { assert(0 <= bci && bci <= method()->code_size(), "illegal bci"); _next_bci = bci; } + + // Bytecode-specific attributes +- int dest() const { return bci() + bytecode().get_offset_s2(raw_code()); } +- int dest_w() const { return bci() + bytecode().get_offset_s4(raw_code()); } ++ int get_offset_s2() const { return bytecode().get_offset_s2(raw_code()); } ++ int get_offset_s4() const { return bytecode().get_offset_s4(raw_code()); } ++ ++ // These methods are not safe to use before or during verification as they may ++ // have large offsets and cause overflows ++ int dest() const { ++ int min_offset = -1 * max_method_code_size; ++ int offset = bytecode().get_offset_s2(raw_code()); ++ guarantee(offset >= min_offset && offset <= max_method_code_size, "must be"); ++ return bci() + offset; ++ } ++ int dest_w() const { ++ int min_offset = -1 * max_method_code_size; ++ int offset = bytecode().get_offset_s4(raw_code()); ++ guarantee(offset >= min_offset && offset <= max_method_code_size, "must be"); ++ return bci() + offset; ++ } + + // One-byte indices. + int get_index_u1() const { assert_raw_index_size(1); return *(jubyte*)(bcp()+1); } +diff --git a/src/hotspot/share/interpreter/interpreterRuntime.cpp b/src/hotspot/share/interpreter/interpreterRuntime.cpp +index 648315913..f40e304f9 100644 +--- a/src/hotspot/share/interpreter/interpreterRuntime.cpp ++++ b/src/hotspot/share/interpreter/interpreterRuntime.cpp @@ -22,6 +22,12 @@ * */ @@ -109446,7 +116121,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/interpre #include "precompiled.hpp" #include "classfile/javaClasses.inline.hpp" #include "classfile/systemDictionary.hpp" -@@ -1506,7 +1512,7 @@ +@@ -1497,7 +1503,7 @@ IRT_ENTRY(void, InterpreterRuntime::prepare_native_call(JavaThread* thread, Meth // preparing the same method will be sure to see non-null entry & mirror. IRT_END @@ -109455,9 +116130,10 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/interpre IRT_LEAF(void, InterpreterRuntime::popframe_move_outgoing_args(JavaThread* thread, void* src_address, void* dest_address)) if (src_address == dest_address) { return; -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/interpreter/interpreterRuntime.hpp jdk11u-ls/src/hotspot/share/interpreter/interpreterRuntime.hpp ---- openjdk/src/hotspot/share/interpreter/interpreterRuntime.hpp 2022-10-12 23:00:01.000000000 +0800 -+++ jdk11u-ls/src/hotspot/share/interpreter/interpreterRuntime.hpp 2023-09-12 13:54:23.657572372 +0800 +diff --git a/src/hotspot/share/interpreter/interpreterRuntime.hpp b/src/hotspot/share/interpreter/interpreterRuntime.hpp +index 87e84c893..3043fa634 100644 +--- a/src/hotspot/share/interpreter/interpreterRuntime.hpp ++++ b/src/hotspot/share/interpreter/interpreterRuntime.hpp @@ -22,6 +22,12 @@ * */ @@ -109471,7 +116147,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/interpre #ifndef SHARE_VM_INTERPRETER_INTERPRETERRUNTIME_HPP #define SHARE_VM_INTERPRETER_INTERPRETERRUNTIME_HPP -@@ -146,7 +152,7 @@ +@@ -146,7 +152,7 @@ class InterpreterRuntime: AllStatic { Method* method, intptr_t* from, intptr_t* to); @@ -109480,9 +116156,10 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/interpre // Popframe support (only needed on x86, AMD64 and ARM) static void popframe_move_outgoing_args(JavaThread* thread, void* src_address, void* dest_address); #endif -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/interpreter/templateInterpreterGenerator.hpp jdk11u-ls/src/hotspot/share/interpreter/templateInterpreterGenerator.hpp ---- openjdk/src/hotspot/share/interpreter/templateInterpreterGenerator.hpp 2022-10-12 23:00:01.000000000 +0800 -+++ jdk11u-ls/src/hotspot/share/interpreter/templateInterpreterGenerator.hpp 2023-09-12 13:54:23.661572377 +0800 +diff --git a/src/hotspot/share/interpreter/templateInterpreterGenerator.hpp b/src/hotspot/share/interpreter/templateInterpreterGenerator.hpp +index 965f6b0d1..07942993c 100644 +--- a/src/hotspot/share/interpreter/templateInterpreterGenerator.hpp ++++ b/src/hotspot/share/interpreter/templateInterpreterGenerator.hpp @@ -22,6 +22,12 @@ * */ @@ -109496,7 +116173,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/interpre #ifndef SHARE_VM_INTERPRETER_TEMPLATEINTERPRETERGENERATOR_HPP #define SHARE_VM_INTERPRETER_TEMPLATEINTERPRETERGENERATOR_HPP -@@ -114,9 +120,9 @@ +@@ -114,9 +120,9 @@ class TemplateInterpreterGenerator: public AbstractInterpreterGenerator { void restore_native_result(void); #endif // SPARC @@ -109508,9 +116185,10 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/interpre #ifdef PPC void lock_method(Register Rflags, Register Rscratch1, Register Rscratch2, bool flags_preloaded=false); -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/jfr/utilities/jfrBigEndian.hpp jdk11u-ls/src/hotspot/share/jfr/utilities/jfrBigEndian.hpp ---- openjdk/src/hotspot/share/jfr/utilities/jfrBigEndian.hpp 2022-10-12 23:00:01.000000000 +0800 -+++ jdk11u-ls/src/hotspot/share/jfr/utilities/jfrBigEndian.hpp 2023-09-12 13:54:23.741572477 +0800 +diff --git a/src/hotspot/share/jfr/utilities/jfrBigEndian.hpp b/src/hotspot/share/jfr/utilities/jfrBigEndian.hpp +index e01a242a5..0661f3b9d 100644 +--- a/src/hotspot/share/jfr/utilities/jfrBigEndian.hpp ++++ b/src/hotspot/share/jfr/utilities/jfrBigEndian.hpp @@ -22,6 +22,12 @@ * */ @@ -109524,7 +116202,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/jfr/util #ifndef SHARE_VM_JFR_UTILITIES_JFRBIGENDIAN_HPP #define SHARE_VM_JFR_UTILITIES_JFRBIGENDIAN_HPP -@@ -102,7 +108,7 @@ +@@ -102,7 +108,7 @@ inline T JfrBigEndian::read_unaligned(const address location) { inline bool JfrBigEndian::platform_supports_unaligned_reads(void) { #if defined(IA32) || defined(AMD64) || defined(PPC) || defined(S390) return true; @@ -109533,9 +116211,10 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/jfr/util return false; #else #warning "Unconfigured platform" -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/jvmci/vmStructs_jvmci.cpp jdk11u-ls/src/hotspot/share/jvmci/vmStructs_jvmci.cpp ---- openjdk/src/hotspot/share/jvmci/vmStructs_jvmci.cpp 2022-10-12 23:00:01.000000000 +0800 -+++ jdk11u-ls/src/hotspot/share/jvmci/vmStructs_jvmci.cpp 2023-09-12 13:54:23.753572492 +0800 +diff --git a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp +index 892706333..b5bb5c288 100644 +--- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp ++++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp @@ -22,6 +22,12 @@ * */ @@ -109549,11 +116228,10 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/jvmci/vm #include "precompiled.hpp" #include "code/codeBlob.hpp" #include "compiler/abstractCompiler.hpp" -@@ -714,6 +720,35 @@ - +@@ -715,6 +721,35 @@ #endif -+ + +#ifdef LOONGARCH64 + +#define VM_STRUCTS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) \ @@ -109582,13 +116260,15 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/jvmci/vm + +#endif + - ++ #ifdef X86 -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/memory/metaspace.cpp jdk11u-ls/src/hotspot/share/memory/metaspace.cpp ---- openjdk/src/hotspot/share/memory/metaspace.cpp 2022-10-12 23:00:01.000000000 +0800 -+++ jdk11u-ls/src/hotspot/share/memory/metaspace.cpp 2023-11-01 09:34:25.729945529 +0800 -@@ -1082,12 +1082,12 @@ + #define VM_STRUCTS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) \ +diff --git a/src/hotspot/share/memory/metaspace.cpp b/src/hotspot/share/memory/metaspace.cpp +index c3a884faf..103789d9b 100644 +--- a/src/hotspot/share/memory/metaspace.cpp ++++ b/src/hotspot/share/memory/metaspace.cpp +@@ -1083,12 +1083,12 @@ void Metaspace::allocate_metaspace_compressed_klass_ptrs(char* requested_addr, a // Don't use large pages for the class space. bool large_pages = false; @@ -109603,7 +116283,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/memory/m ReservedSpace metaspace_rs; -@@ -1113,7 +1113,8 @@ +@@ -1114,7 +1114,8 @@ void Metaspace::allocate_metaspace_compressed_klass_ptrs(char* requested_addr, a // below 32g to get a zerobased CCS. For simplicity we reuse the search // strategy for AARCH64. @@ -109613,7 +116293,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/memory/m for (char *a = align_up(requested_addr, increment); a < (char*)(1024*G); a += increment) { -@@ -1144,7 +1145,7 @@ +@@ -1145,7 +1146,7 @@ void Metaspace::allocate_metaspace_compressed_klass_ptrs(char* requested_addr, a } } @@ -109622,10 +116302,178 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/memory/m if (!metaspace_rs.is_reserved()) { #if INCLUDE_CDS -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/opto/compile.hpp jdk11u-ls/src/hotspot/share/opto/compile.hpp ---- openjdk/src/hotspot/share/opto/compile.hpp 2022-10-12 23:00:01.000000000 +0800 -+++ jdk11u-ls/src/hotspot/share/opto/compile.hpp 2023-09-12 13:54:23.813572568 +0800 -@@ -1204,7 +1204,7 @@ +diff --git a/src/hotspot/share/oops/method.cpp b/src/hotspot/share/oops/method.cpp +index 9fa79d448..16b2c8b97 100644 +--- a/src/hotspot/share/oops/method.cpp ++++ b/src/hotspot/share/oops/method.cpp +@@ -2191,10 +2191,15 @@ bool Method::is_method_id(jmethodID mid) { + Method* Method::checked_resolve_jmethod_id(jmethodID mid) { + if (mid == NULL) return NULL; + Method* o = resolve_jmethod_id(mid); +- if (o == NULL || o == JNIMethodBlock::_free_method || !((Metadata*)o)->is_method()) { ++ if (o == NULL || o == JNIMethodBlock::_free_method) { + return NULL; + } +- return o; ++ // Method should otherwise be valid. Assert for testing. ++ assert(is_valid_method(o), "should be valid jmethodid"); ++ // If the method's class holder object is unreferenced, but not yet marked as ++ // unloaded, we need to return NULL here too because after a safepoint, its memory ++ // will be reclaimed. ++ return o->method_holder()->is_loader_alive() ? o : NULL; + }; + + void Method::set_on_stack(const bool value) { +diff --git a/src/hotspot/share/oops/oop.inline.hpp b/src/hotspot/share/oops/oop.inline.hpp +index 6c631f545..986510672 100644 +--- a/src/hotspot/share/oops/oop.inline.hpp ++++ b/src/hotspot/share/oops/oop.inline.hpp +@@ -22,6 +22,12 @@ + * + */ + ++/* ++ * This file has been modified by Loongson Technology in 2022. These ++ * modifications are Copyright (c) 2022, Loongson Technology, and are made ++ * available on the same license terms set forth above. ++ */ ++ + #ifndef SHARE_VM_OOPS_OOP_INLINE_HPP + #define SHARE_VM_OOPS_OOP_INLINE_HPP + +@@ -389,7 +395,7 @@ oop oopDesc::forward_to_atomic(oop p, atomic_memory_order order) { + // forwarding pointer. + oldMark = curMark; + } +- return forwardee(); ++ return (oop)oldMark->decode_pointer(); + } + + // Note that the forwardee is not the same thing as the displaced_mark. +diff --git a/src/hotspot/share/opto/addnode.cpp b/src/hotspot/share/opto/addnode.cpp +index bdde4fe8d..240c1aac4 100644 +--- a/src/hotspot/share/opto/addnode.cpp ++++ b/src/hotspot/share/opto/addnode.cpp +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -941,6 +941,14 @@ static bool can_overflow(const TypeInt* t, jint c) { + (c > 0 && (java_add(t_hi, c) < t_hi))); + } + ++// Check if addition of a long with type 't' and a constant 'c' can overflow. ++static bool can_overflow(const TypeLong* t, jlong c) { ++ jlong t_lo = t->_lo; ++ jlong t_hi = t->_hi; ++ return ((c < 0 && (java_add(t_lo, c) > t_lo)) || ++ (c > 0 && (java_add(t_hi, c) < t_hi))); ++} ++ + //============================================================================= + //------------------------------Idealize--------------------------------------- + // MINs show up in range-check loop limit calculations. Look for +@@ -1062,6 +1070,31 @@ const Type *MinINode::add_ring( const Type *t0, const Type *t1 ) const { + // + // Note: we assume that SubL was already replaced by an AddL, and that the stride + // has its sign flipped: SubL(limit, stride) -> AddL(limit, -stride). ++// ++// Proof MaxL collapsed version equivalent to original (MinL version similar): ++// is_sub_con ensures that con1, con2 ∈ [min_int, 0[ ++// ++// Original: ++// - AddL2 underflow => x + con2 ∈ ]max_long - min_int, max_long], ALWAYS BAILOUT as x + con1 + con2 surely fails can_overflow (*) ++// - AddL2 no underflow => x + con2 ∈ [min_long, max_long] ++// - MaxL2 clamp => min_int ++// - AddL1 underflow: NOT POSSIBLE: cannot underflow since min_int + con1 ∈ [2 * min_int, min_int] always > min_long ++// - AddL1 no underflow => min_int + con1 ∈ [2 * min_int, min_int] ++// - MaxL1 clamp => min_int (RESULT 1) ++// - MaxL1 no clamp: NOT POSSIBLE: min_int + con1 ∈ [2 * min_int, min_int] always <= min_int, so clamp always taken ++// - MaxL2 no clamp => x + con2 ∈ [min_int, max_long] ++// - AddL1 underflow: NOT POSSIBLE: cannot underflow since x + con2 + con1 ∈ [2 * min_int, max_long] always > min_long ++// - AddL1 no underflow => x + con2 + con1 ∈ [2 * min_int, max_long] ++// - MaxL1 clamp => min_int (RESULT 2) ++// - MaxL1 no clamp => x + con2 + con1 ∈ ]min_int, max_long] (RESULT 3) ++// ++// Collapsed: ++// - AddL2 (cannot underflow) => con2 + con1 ∈ [2 * min_int, 0] ++// - AddL1 underflow: NOT POSSIBLE: would have bailed out at can_overflow (*) ++// - AddL1 no underflow => x + con2 + con1 ∈ [min_long, max_long] ++// - MaxL clamp => min_int (RESULT 1 and RESULT 2) ++// - MaxL no clamp => x + con2 + con1 ∈ ]min_int, max_long] (RESULT 3) ++// + static bool is_clamp(PhaseGVN* phase, Node* n, Node* c) { + // Check that the two clamps have the correct values. + jlong clamp = (n->Opcode() == Op_MaxL) ? min_jint : max_jint; +@@ -1093,6 +1126,10 @@ Node* fold_subI_no_underflow_pattern(Node* n, PhaseGVN* phase) { + Node* x = add2->in(1); + Node* con2 = add2->in(2); + if (is_sub_con(phase, n, con2)) { ++ // Collapsed graph not equivalent if potential over/underflow -> bailing out (*) ++ if (can_overflow(phase->type(x)->is_long(), con1->get_long() + con2->get_long())) { ++ return NULL; ++ } + Node* new_con = phase->transform(new AddLNode(con1, con2)); + Node* new_sub = phase->transform(new AddLNode(x, new_con)); + n->set_req_X(1, new_sub, phase); +diff --git a/src/hotspot/share/opto/classes.hpp b/src/hotspot/share/opto/classes.hpp +index 7a9bd9111..b46e9bcf5 100644 +--- a/src/hotspot/share/opto/classes.hpp ++++ b/src/hotspot/share/opto/classes.hpp +@@ -22,6 +22,12 @@ + * + */ + ++/* ++ * This file has been modified by Loongson Technology in 2023, These ++ * modifications are Copyright (c) 2023, Loongson Technology, and are made ++ * available on the same license terms set forth above. ++ */ ++ + #include "utilities/macros.hpp" + + // The giant table of Node classes. +@@ -217,6 +223,7 @@ macro(StoreFence) + macro(MemBarReleaseLock) + macro(MemBarVolatile) + macro(MemBarStoreStore) ++macro(SameAddrLoadFence) + macro(MergeMem) + macro(MinD) + macro(MinF) +diff --git a/src/hotspot/share/opto/compile.cpp b/src/hotspot/share/opto/compile.cpp +index da06b4740..510438d67 100644 +--- a/src/hotspot/share/opto/compile.cpp ++++ b/src/hotspot/share/opto/compile.cpp +@@ -22,6 +22,12 @@ + * + */ + ++/* ++ * This file has been modified by Loongson Technology in 2023, These ++ * modifications are Copyright (c) 2023, Loongson Technology, and are made ++ * available on the same license terms set forth above. ++ */ ++ + #include "precompiled.hpp" + #include "asm/macroAssembler.hpp" + #include "asm/macroAssembler.inline.hpp" +@@ -3448,6 +3454,7 @@ void Compile::final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc) { + n->set_req(MemBarNode::Precedent, top()); + } + break; ++ case Op_SameAddrLoadFence: + case Op_MemBarAcquire: { + if (n->as_MemBar()->trailing_load() && n->req() > MemBarNode::Precedent) { + // At parse time, the trailing MemBarAcquire for a volatile load +diff --git a/src/hotspot/share/opto/compile.hpp b/src/hotspot/share/opto/compile.hpp +index 569fbc6d6..c1f1b82ff 100644 +--- a/src/hotspot/share/opto/compile.hpp ++++ b/src/hotspot/share/opto/compile.hpp +@@ -1204,7 +1204,7 @@ class Compile : public Phase { bool in_scratch_emit_size() const { return _in_scratch_emit_size; } enum ScratchBufferBlob { @@ -109634,9 +116482,81 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/opto/com MAX_inst_size = 2048, #else MAX_inst_size = 1024, -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/opto/output.cpp jdk11u-ls/src/hotspot/share/opto/output.cpp ---- openjdk/src/hotspot/share/opto/output.cpp 2022-10-12 23:00:01.000000000 +0800 -+++ jdk11u-ls/src/hotspot/share/opto/output.cpp 2023-09-12 13:54:23.877572648 +0800 +diff --git a/src/hotspot/share/opto/memnode.cpp b/src/hotspot/share/opto/memnode.cpp +index e194386b5..d5e6dd71a 100644 +--- a/src/hotspot/share/opto/memnode.cpp ++++ b/src/hotspot/share/opto/memnode.cpp +@@ -22,6 +22,12 @@ + * + */ + ++/* ++ * This file has been modified by Loongson Technology in 2023, These ++ * modifications are Copyright (c) 2023, Loongson Technology, and are made ++ * available on the same license terms set forth above. ++ */ ++ + #include "precompiled.hpp" + #include "classfile/systemDictionary.hpp" + #include "compiler/compileLog.hpp" +@@ -3190,6 +3196,7 @@ MemBarNode* MemBarNode::make(Compile* C, int opcode, int atp, Node* pn) { + case Op_MemBarReleaseLock: return new MemBarReleaseLockNode(C, atp, pn); + case Op_MemBarVolatile: return new MemBarVolatileNode(C, atp, pn); + case Op_MemBarCPUOrder: return new MemBarCPUOrderNode(C, atp, pn); ++ case Op_SameAddrLoadFence: return new SameAddrLoadFenceNode(C, atp, pn); + case Op_OnSpinWait: return new OnSpinWaitNode(C, atp, pn); + case Op_Initialize: return new InitializeNode(C, atp, pn); + case Op_MemBarStoreStore: return new MemBarStoreStoreNode(C, atp, pn); +diff --git a/src/hotspot/share/opto/memnode.hpp b/src/hotspot/share/opto/memnode.hpp +index e4676977e..bf1efbf83 100644 +--- a/src/hotspot/share/opto/memnode.hpp ++++ b/src/hotspot/share/opto/memnode.hpp +@@ -22,6 +22,12 @@ + * + */ + ++/* ++ * This file has been modified by Loongson Technology in 2023, These ++ * modifications are Copyright (c) 2023, Loongson Technology, and are made ++ * available on the same license terms set forth above. ++ */ ++ + #ifndef SHARE_VM_OPTO_MEMNODE_HPP + #define SHARE_VM_OPTO_MEMNODE_HPP + +@@ -1293,6 +1299,14 @@ public: + virtual uint ideal_reg() const { return 0; } // not matched in the AD file + }; + ++// Used to prevent LoadLoad reorder for same address. ++class SameAddrLoadFenceNode: public MemBarNode { ++public: ++ SameAddrLoadFenceNode(Compile* C, int alias_idx, Node* precedent) ++ : MemBarNode(C, alias_idx, precedent) {} ++ virtual int Opcode() const; ++}; ++ + class OnSpinWaitNode: public MemBarNode { + public: + OnSpinWaitNode(Compile* C, int alias_idx, Node* precedent) +diff --git a/src/hotspot/share/opto/node.hpp b/src/hotspot/share/opto/node.hpp +index 0c0b9bf69..d7ccf70bf 100644 +--- a/src/hotspot/share/opto/node.hpp ++++ b/src/hotspot/share/opto/node.hpp +@@ -1455,8 +1455,8 @@ Node* Node::last_out(DUIterator_Last& i) const { + class SimpleDUIterator : public StackObj { + private: + Node* node; +- DUIterator_Fast i; + DUIterator_Fast imax; ++ DUIterator_Fast i; + public: + SimpleDUIterator(Node* n): node(n), i(n->fast_outs(imax)) {} + bool has_next() { return i < imax; } +diff --git a/src/hotspot/share/opto/output.cpp b/src/hotspot/share/opto/output.cpp +index b6540e06a..52d1fc9fb 100644 +--- a/src/hotspot/share/opto/output.cpp ++++ b/src/hotspot/share/opto/output.cpp @@ -22,6 +22,12 @@ * */ @@ -109650,7 +116570,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/opto/out #include "precompiled.hpp" #include "asm/assembler.inline.hpp" #include "asm/macroAssembler.inline.hpp" -@@ -731,6 +737,27 @@ +@@ -731,6 +737,27 @@ void Compile::Process_OopMap_Node(MachNode *mach, int current_offset) { // Add the safepoint in the DebugInfoRecorder if( !mach->is_MachCall() ) { mcall = NULL; @@ -109678,7 +116598,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/opto/out debug_info()->add_safepoint(safepoint_pc_offset, sfn->_oop_map); } else { mcall = mach->as_MachCall(); -@@ -1393,6 +1420,31 @@ +@@ -1393,6 +1420,22 @@ void Compile::fill_buffer(CodeBuffer* cb, uint* blk_starts) { DEBUG_ONLY(uint instr_offset = cb->insts_size()); n->emit(*cb, _regalloc); current_offset = cb->insts_size(); @@ -109695,50 +116615,131 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/opto/out + adjust += 4; + inst = (NativeInstruction*) (cb->insts()->end() - 8); + } -+#ifdef MIPS64 -+ if (PatchContinuousLoad) { -+ // if PatchContinuousLoad is true, a nop may be inserted after a load instruction and -+ // the adjust would be 2 instructions. -+ if (inst->is_nop()) { -+ adjust += 4; -+ } -+ } -+#endif + previous_offset = current_offset - adjust; + } +#endif // Above we only verified that there is enough space in the instruction section. // However, the instruction may emit stubs that cause code buffer expansion. -@@ -1402,7 +1454,9 @@ - } +diff --git a/src/hotspot/share/opto/subnode.cpp b/src/hotspot/share/opto/subnode.cpp +index e3fc12de6..51fe60945 100644 +--- a/src/hotspot/share/opto/subnode.cpp ++++ b/src/hotspot/share/opto/subnode.cpp +@@ -1489,44 +1489,86 @@ Node *BoolNode::Ideal(PhaseGVN *phase, bool can_reshape) { + return new BoolNode( ncmp, _test.negate() ); + } - #ifdef ASSERT -- uint n_size = n->size(_regalloc); -+ // adjust: one node may be inserted one and only one nop. -+ int adjust = MIPS64_ONLY(PatchContinuousLoad ? block->number_of_nodes() * 4 :) 0; -+ uint n_size = n->size(regalloc()) + adjust; - if (n_size < (current_offset-instr_offset)) { - MachNode* mach = n->as_Mach(); - n->dump(); -@@ -1488,7 +1542,13 @@ - } - // Verify that the distance for generated before forward - // short branches is still valid. -- guarantee((int)(blk_starts[i+1] - blk_starts[i]) >= (current_offset - blk_offset), "shouldn't increase block size"); -+ // adjust: one node may be inserted one and only one nop. -+ int adjust = MIPS64_ONLY(PatchContinuousLoad ? block->number_of_nodes() * 4 :) 0; -+#ifndef PRODUCT -+ if ((int)(blk_starts[i+1] - blk_starts[i] + adjust) < (current_offset - blk_offset)) -+ tty->print_cr("%s:%d blk_starts[i+1]:%d, blk_starts[i]:%d, adjust: %d, current_offset:%d, blk_offset:%d", __func__, __LINE__, blk_starts[i+1], blk_starts[i], adjust, current_offset, blk_offset); -+#endif -+ guarantee((int)(blk_starts[i+1] - blk_starts[i] + adjust) >= (current_offset - blk_offset), "shouldn't increase block size"); +- // Change ((x & m) u<= m) or ((m & x) u<= m) to always true +- // Same with ((x & m) u< m+1) and ((m & x) u< m+1) ++ // We use the following Lemmas/insights for the following two transformations (1) and (2): ++ // x & y <=u y, for any x and y (Lemma 1, masking always results in a smaller unsigned number) ++ // y Opcode() == Op_AddI && + cmp2->in(2)->find_int_con(0) == 1) { +- bound = cmp2->in(1); ++ // (1b) "(x & m) in(1); ++ const TypeInt* rhs_m_type = phase->type(rhs_m)->isa_int(); ++ if (rhs_m_type->_lo > -1 || rhs_m_type->_hi < -1) { ++ // Exclude any case where m == -1 is possible. ++ m = rhs_m; ++ } + } +- if (cmp1->in(2) == bound || cmp1->in(1) == bound) { ++ if (cmp1->in(2) == m || cmp1->in(1) == m) { + return ConINode::make(1); + } + } - // Save new block start offset - blk_starts[i] = blk_offset; -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/opto/type.cpp jdk11u-ls/src/hotspot/share/opto/type.cpp ---- openjdk/src/hotspot/share/opto/type.cpp 2022-10-12 23:00:01.000000000 +0800 -+++ jdk11u-ls/src/hotspot/share/opto/type.cpp 2023-11-01 09:34:25.781945586 +0800 +- // Change ((x & (m - 1)) u< m) into (m > 0) +- // This is the off-by-one variant of the above ++ // (2) Change ((x & (m - 1)) u 0) ++ // This is the off-by-one variant of the above. ++ // ++ // We now prove that this replacement is correct. This is the same as proving ++ // "m >u 0" if and only if "x & (m - 1) u 0 <=> x & (m - 1) m >u 0": ++ // We prove this by contradiction: ++ // Assume m <=u 0 which is equivalent to m == 0: ++ // and thus ++ // x & (m - 1) u 0 => x & (m - 1) u 0, no underflow of "m - 1" ++ // ++ // ++ // Note that the signed version of "m > 0": ++ // m > 0 <=> x & (m - 1) 0 ++ // is false which is a contradiction. + if (cop == Op_CmpU && + _test._test == BoolTest::lt && + cmp1_op == Op_AndI) { +- Node* l = cmp1->in(1); +- Node* r = cmp1->in(2); +- for (int repeat = 0; repeat < 2; repeat++) { +- bool match = r->Opcode() == Op_AddI && r->in(2)->find_int_con(0) == -1 && +- r->in(1) == cmp2; +- if (match) { +- // arraylength known to be non-negative, so a (arraylength != 0) is sufficient, +- // but to be compatible with the array range check pattern, use (arraylength u> 0) +- Node* ncmp = cmp2->Opcode() == Op_LoadRange +- ? phase->transform(new CmpUNode(cmp2, phase->intcon(0))) +- : phase->transform(new CmpINode(cmp2, phase->intcon(0))); +- return new BoolNode(ncmp, BoolTest::gt); +- } else { +- // commute and try again +- l = cmp1->in(2); +- r = cmp1->in(1); ++ Node* m = cmp2; // RHS: m ++ for (int add_idx = 1; add_idx <= 2; add_idx++) { // LHS: "(m + (-1)) & x" or "x & (m + (-1))"? ++ Node* maybe_m_minus_1 = cmp1->in(add_idx); ++ if (maybe_m_minus_1->Opcode() == Op_AddI && ++ maybe_m_minus_1->in(2)->find_int_con(0) == -1 && ++ maybe_m_minus_1->in(1) == m) { ++ Node* m_cmpu_0 = phase->transform(new CmpUNode(m, phase->intcon(0))); ++ return new BoolNode(m_cmpu_0, BoolTest::gt); + } + } + } +diff --git a/src/hotspot/share/opto/type.cpp b/src/hotspot/share/opto/type.cpp +index 7d767c47c..23ec34e5e 100644 +--- a/src/hotspot/share/opto/type.cpp ++++ b/src/hotspot/share/opto/type.cpp @@ -22,6 +22,12 @@ * */ @@ -109752,7 +116753,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/opto/typ #include "precompiled.hpp" #include "ci/ciMethodData.hpp" #include "ci/ciTypeFlow.hpp" -@@ -78,6 +84,12 @@ +@@ -78,6 +84,12 @@ const Type::TypeInfo Type::_type_info[Type::lastype] = { { Bad, T_ILLEGAL, "vectorx:", false, 0, relocInfo::none }, // VectorX { Bad, T_ILLEGAL, "vectory:", false, 0, relocInfo::none }, // VectorY { Bad, T_ILLEGAL, "vectorz:", false, 0, relocInfo::none }, // VectorZ @@ -109765,35 +116766,113 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/opto/typ #else // all other { Bad, T_ILLEGAL, "vectors:", false, Op_VecS, relocInfo::none }, // VectorS { Bad, T_ILLEGAL, "vectord:", false, Op_VecD, relocInfo::none }, // VectorD -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/runtime/os.cpp jdk11u-ls/src/hotspot/share/runtime/os.cpp ---- openjdk/src/hotspot/share/runtime/os.cpp 2022-10-12 23:00:01.000000000 +0800 -+++ jdk11u-ls/src/hotspot/share/runtime/os.cpp 2023-11-01 09:34:25.821945631 +0800 +diff --git a/src/hotspot/share/prims/jvmtiExport.cpp b/src/hotspot/share/prims/jvmtiExport.cpp +index 5ed8c00e3..1d9cb9bd9 100644 +--- a/src/hotspot/share/prims/jvmtiExport.cpp ++++ b/src/hotspot/share/prims/jvmtiExport.cpp +@@ -2284,13 +2284,17 @@ void JvmtiExport::post_dynamic_code_generated_while_holding_locks(const char* na + address code_begin, address code_end) + { + // register the stub with the current dynamic code event collector +- JvmtiThreadState* state = JvmtiThreadState::state_for(JavaThread::current()); +- // state can only be NULL if the current thread is exiting which +- // should not happen since we're trying to post an event +- guarantee(state != NULL, "attempt to register stub via an exiting thread"); +- JvmtiDynamicCodeEventCollector* collector = state->get_dynamic_code_event_collector(); +- guarantee(collector != NULL, "attempt to register stub without event collector"); +- collector->register_stub(name, code_begin, code_end); ++ // Cannot take safepoint here so do not use state_for to get ++ // jvmti thread state. ++ // The collector and/or state might be NULL if JvmtiDynamicCodeEventCollector ++ // has been initialized while JVMTI_EVENT_DYNAMIC_CODE_GENERATED was disabled. ++ JvmtiThreadState* state = JavaThread::current()->jvmti_thread_state(); ++ if (state != NULL) { ++ JvmtiDynamicCodeEventCollector *collector = state->get_dynamic_code_event_collector(); ++ if (collector != NULL) { ++ collector->register_stub(name, code_begin, code_end); ++ } ++ } + } + + // Collect all the vm internally allocated objects which are visible to java world +diff --git a/src/hotspot/share/runtime/java.cpp b/src/hotspot/share/runtime/java.cpp +index 84123b29e..77fbacf2d 100644 +--- a/src/hotspot/share/runtime/java.cpp ++++ b/src/hotspot/share/runtime/java.cpp +@@ -68,6 +68,7 @@ + #include "runtime/thread.inline.hpp" + #include "runtime/timer.hpp" + #include "runtime/vmOperations.hpp" ++#include "runtime/vmThread.hpp" + #include "services/memTracker.hpp" + #include "utilities/dtrace.hpp" + #include "utilities/globalDefinitions.hpp" +diff --git a/src/hotspot/share/runtime/objectMonitor.cpp b/src/hotspot/share/runtime/objectMonitor.cpp +index ce23aafa8..d3dfb74d5 100644 +--- a/src/hotspot/share/runtime/objectMonitor.cpp ++++ b/src/hotspot/share/runtime/objectMonitor.cpp @@ -22,6 +22,12 @@ * */ +/* -+ * This file has been modified by Loongson Technology in 2021, These -+ * modifications are Copyright (c) 2019, 2021, Loongson Technology, and are made ++ * This file has been modified by Loongson Technology in 2023, These ++ * modifications are Copyright (c) 2023, Loongson Technology, and are made ++ * available on the same license terms set forth above. ++ */ ++ + #include "precompiled.hpp" + #include "classfile/vmSymbols.hpp" + #include "jfr/jfrEvents.hpp" +@@ -308,6 +314,9 @@ void ObjectMonitor::enter(TRAPS) { + } + + assert(_owner != Self, "invariant"); ++ // Thread _succ != current assertion load reording before Thread if (_succ == current) _succ = nullptr. ++ // But expect order is firstly if (_succ == current) _succ = nullptr then _succ != current assertion. ++ DEBUG_ONLY(LOONGARCH64_ONLY(__asm__ __volatile__ ("dbar 0x700\n");)MIPS64_ONLY(OrderAccess::loadload();)) + assert(_succ != Self, "invariant"); + assert(Self->is_Java_thread(), "invariant"); + JavaThread * jt = (JavaThread *) Self; +@@ -469,6 +478,7 @@ void ObjectMonitor::EnterI(TRAPS) { + } + + // The Spin failed -- Enqueue and park the thread ... ++ DEBUG_ONLY(LOONGARCH64_ONLY(__asm__ __volatile__ ("dbar 0x700\n");)MIPS64_ONLY(OrderAccess::loadload();)) + assert(_succ != Self, "invariant"); + assert(_owner != Self, "invariant"); + assert(_Responsible != Self, "invariant"); +diff --git a/src/hotspot/share/runtime/os.cpp b/src/hotspot/share/runtime/os.cpp +index 1c540bb62..0e44240d4 100644 +--- a/src/hotspot/share/runtime/os.cpp ++++ b/src/hotspot/share/runtime/os.cpp +@@ -22,6 +22,12 @@ + * + */ + ++/* ++ * This file has been modified by Loongson Technology in 2022, These ++ * modifications are Copyright (c) 2019, 2022, Loongson Technology, and are made + * available on the same license terms set forth above. + */ + #include "precompiled.hpp" #include "jvm.h" #include "classfile/classLoader.hpp" -@@ -1242,7 +1248,8 @@ +@@ -1242,7 +1248,8 @@ bool os::is_first_C_frame(frame* fr) { + 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 || + // The check for old_fp and ufp is harmful on LoongArch and MIPS due to their special ABIs. -+ if (old_fp == 0 || old_fp == (uintptr_t)-1 NOT_LOONGARCH64_AND_MIPS64(|| old_fp == ufp)) return true; ++ if (old_fp == 0 || old_fp == (uintptr_t)-1 NOT_LOONGARCH64_AND_MIPS64(|| 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 -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/runtime/sharedRuntimeTrig.cpp jdk11u-ls/src/hotspot/share/runtime/sharedRuntimeTrig.cpp ---- openjdk/src/hotspot/share/runtime/sharedRuntimeTrig.cpp 2022-10-12 23:00:01.000000000 +0800 -+++ jdk11u-ls/src/hotspot/share/runtime/sharedRuntimeTrig.cpp 2023-09-12 13:54:23.985572784 +0800 +diff --git a/src/hotspot/share/runtime/sharedRuntimeTrig.cpp b/src/hotspot/share/runtime/sharedRuntimeTrig.cpp +index e086f794c..f48019577 100644 +--- a/src/hotspot/share/runtime/sharedRuntimeTrig.cpp ++++ b/src/hotspot/share/runtime/sharedRuntimeTrig.cpp @@ -22,6 +22,13 @@ * */ @@ -109808,7 +116887,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/runtime/ #include "precompiled.hpp" #include "jni.h" #include "runtime/interfaceSupport.inline.hpp" -@@ -512,6 +519,14 @@ +@@ -512,6 +519,14 @@ static int __ieee754_rem_pio2(double x, double *y) { * sin(x) = x + (S1*x + (x *(r-y/2)+y)) */ @@ -109823,10 +116902,36 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/runtime/ static const double S1 = -1.66666666666666324348e-01, /* 0xBFC55555, 0x55555549 */ S2 = 8.33333333332248946124e-03, /* 0x3F811111, 0x1110F8A6 */ -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/utilities/globalDefinitions.hpp jdk11u-ls/src/hotspot/share/utilities/globalDefinitions.hpp ---- openjdk/src/hotspot/share/utilities/globalDefinitions.hpp 2022-10-12 23:00:01.000000000 +0800 -+++ jdk11u-ls/src/hotspot/share/utilities/globalDefinitions.hpp 2023-09-12 13:54:24.025572834 +0800 -@@ -1161,6 +1161,15 @@ +diff --git a/src/hotspot/share/runtime/vmStructs.cpp b/src/hotspot/share/runtime/vmStructs.cpp +index adce6da6a..db099a298 100644 +--- a/src/hotspot/share/runtime/vmStructs.cpp ++++ b/src/hotspot/share/runtime/vmStructs.cpp +@@ -22,6 +22,12 @@ + * + */ + ++/* ++ * This file has been modified by Loongson Technology in 2023, These ++ * modifications are Copyright (c) 2023, Loongson Technology, and are made ++ * available on the same license terms set forth above. ++ */ ++ + #include "precompiled.hpp" + #include "ci/ciField.hpp" + #include "ci/ciInstance.hpp" +@@ -1642,6 +1648,7 @@ typedef PaddedEnd PaddedObjectMonitor; + declare_c2_type(StoreFenceNode, MemBarNode) \ + declare_c2_type(MemBarVolatileNode, MemBarNode) \ + declare_c2_type(MemBarCPUOrderNode, MemBarNode) \ ++ declare_c2_type(SameAddrLoadFenceNode, MemBarNode) \ + declare_c2_type(OnSpinWaitNode, MemBarNode) \ + declare_c2_type(InitializeNode, MemBarNode) \ + declare_c2_type(ThreadLocalNode, Node) \ +diff --git a/src/hotspot/share/utilities/globalDefinitions.hpp b/src/hotspot/share/utilities/globalDefinitions.hpp +index c758fc574..a8c4638f6 100644 +--- a/src/hotspot/share/utilities/globalDefinitions.hpp ++++ b/src/hotspot/share/utilities/globalDefinitions.hpp +@@ -1161,6 +1161,15 @@ inline int exact_log2_long(jlong x) { return log2_long(x); } @@ -109842,9 +116947,10 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/utilitie inline bool is_odd (intx x) { return x & 1; } inline bool is_even(intx x) { return !is_odd(x); } -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/utilities/macros.hpp jdk11u-ls/src/hotspot/share/utilities/macros.hpp ---- openjdk/src/hotspot/share/utilities/macros.hpp 2022-10-12 23:00:01.000000000 +0800 -+++ jdk11u-ls/src/hotspot/share/utilities/macros.hpp 2023-09-12 13:54:24.025572834 +0800 +diff --git a/src/hotspot/share/utilities/macros.hpp b/src/hotspot/share/utilities/macros.hpp +index 6605ab367..5a2be6ef1 100644 +--- a/src/hotspot/share/utilities/macros.hpp ++++ b/src/hotspot/share/utilities/macros.hpp @@ -22,6 +22,12 @@ * */ @@ -109858,7 +116964,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/utilitie #ifndef SHARE_VM_UTILITIES_MACROS_HPP #define SHARE_VM_UTILITIES_MACROS_HPP -@@ -531,6 +537,38 @@ +@@ -535,6 +541,38 @@ #define NOT_SPARC(code) code #endif @@ -109897,7 +117003,7 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/utilitie #if defined(PPC32) || defined(PPC64) #ifndef PPC #define PPC -@@ -623,16 +661,34 @@ +@@ -627,16 +665,34 @@ // OS_CPU_HEADER(vmStructs) --> vmStructs_linux_sparc.hpp // // basename.hpp / basename.inline.hpp @@ -109932,6157 +117038,66240 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/hotspot/share/utilitie // basename.hpp / basename.inline.hpp #define COMPILER_HEADER(basename) XSTR(COMPILER_HEADER_STEM(basename).hpp) #define COMPILER_HEADER_INLINE(basename) XSTR(COMPILER_HEADER_STEM(basename).inline.hpp) -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/java.base/share/classes/sun/security/ssl/NamedGroup.java jdk11u-ls/src/java.base/share/classes/sun/security/ssl/NamedGroup.java ---- openjdk/src/java.base/share/classes/sun/security/ssl/NamedGroup.java 2022-10-12 23:00:07.000000000 +0800 -+++ jdk11u-ls/src/java.base/share/classes/sun/security/ssl/NamedGroup.java 2023-09-12 13:54:24.533573473 +0800 -@@ -49,7 +49,114 @@ - // Elliptic Curves (RFC 4492) - // - // See sun.security.util.CurveDB for the OIDs -+ // NIST K-163 -+ -+ SECT163_K1(0x0001, "sect163k1", true, -+ NamedGroupSpec.NAMED_GROUP_ECDHE, -+ ProtocolVersion.PROTOCOLS_TO_12, -+ CurveDB.lookup("sect163k1")), -+ SECT163_R1(0x0002, "sect163r1", false, -+ NamedGroupSpec.NAMED_GROUP_ECDHE, -+ ProtocolVersion.PROTOCOLS_TO_12, -+ CurveDB.lookup("sect163r1")), -+ -+ // NIST B-163 -+ SECT163_R2(0x0003, "sect163r2", true, -+ NamedGroupSpec.NAMED_GROUP_ECDHE, -+ ProtocolVersion.PROTOCOLS_TO_12, -+ CurveDB.lookup("sect163r2")), -+ SECT193_R1(0x0004, "sect193r1", false, -+ NamedGroupSpec.NAMED_GROUP_ECDHE, -+ ProtocolVersion.PROTOCOLS_TO_12, -+ CurveDB.lookup("sect193r1")), -+ SECT193_R2(0x0005, "sect193r2", false, -+ NamedGroupSpec.NAMED_GROUP_ECDHE, -+ ProtocolVersion.PROTOCOLS_TO_12, -+ CurveDB.lookup("sect193r2")), -+ -+ // NIST K-233 -+ SECT233_K1(0x0006, "sect233k1", true, -+ NamedGroupSpec.NAMED_GROUP_ECDHE, -+ ProtocolVersion.PROTOCOLS_TO_12, -+ CurveDB.lookup("sect233k1")), -+ -+ // NIST B-233 -+ SECT233_R1(0x0007, "sect233r1", true, -+ NamedGroupSpec.NAMED_GROUP_ECDHE, -+ ProtocolVersion.PROTOCOLS_TO_12, -+ CurveDB.lookup("sect233r1")), -+ SECT239_K1(0x0008, "sect239k1", false, -+ NamedGroupSpec.NAMED_GROUP_ECDHE, -+ ProtocolVersion.PROTOCOLS_TO_12, -+ CurveDB.lookup("sect239k1")), -+ -+ // NIST K-283 -+ SECT283_K1(0x0009, "sect283k1", true, -+ NamedGroupSpec.NAMED_GROUP_ECDHE, -+ ProtocolVersion.PROTOCOLS_TO_12, -+ CurveDB.lookup("sect283k1")), -+ -+ // NIST B-283 -+ SECT283_R1(0x000A, "sect283r1", true, -+ NamedGroupSpec.NAMED_GROUP_ECDHE, -+ ProtocolVersion.PROTOCOLS_TO_12, -+ CurveDB.lookup("sect283r1")), -+ -+ // NIST K-409 -+ SECT409_K1(0x000B, "sect409k1", true, -+ NamedGroupSpec.NAMED_GROUP_ECDHE, -+ ProtocolVersion.PROTOCOLS_TO_12, -+ CurveDB.lookup("sect409k1")), -+ -+ // NIST B-409 -+ SECT409_R1(0x000C, "sect409r1", true, -+ NamedGroupSpec.NAMED_GROUP_ECDHE, -+ ProtocolVersion.PROTOCOLS_TO_12, -+ CurveDB.lookup("sect409r1")), -+ -+ // NIST K-571 -+ SECT571_K1(0x000D, "sect571k1", true, -+ NamedGroupSpec.NAMED_GROUP_ECDHE, -+ ProtocolVersion.PROTOCOLS_TO_12, -+ CurveDB.lookup("sect571k1")), -+ -+ // NIST B-571 -+ SECT571_R1(0x000E, "sect571r1", true, -+ NamedGroupSpec.NAMED_GROUP_ECDHE, -+ ProtocolVersion.PROTOCOLS_TO_12, -+ CurveDB.lookup("sect571r1")), -+ SECP160_K1(0x000F, "secp160k1", false, -+ NamedGroupSpec.NAMED_GROUP_ECDHE, -+ ProtocolVersion.PROTOCOLS_TO_12, -+ CurveDB.lookup("secp160k1")), -+ SECP160_R1(0x0010, "secp160r1", false, -+ NamedGroupSpec.NAMED_GROUP_ECDHE, -+ ProtocolVersion.PROTOCOLS_TO_12, -+ CurveDB.lookup("secp160r1")), -+ SECP160_R2(0x0011, "secp160r2", false, -+ NamedGroupSpec.NAMED_GROUP_ECDHE, -+ ProtocolVersion.PROTOCOLS_TO_12, -+ CurveDB.lookup("secp160r2")), -+ SECP192_K1(0x0012, "secp192k1", false, -+ NamedGroupSpec.NAMED_GROUP_ECDHE, -+ ProtocolVersion.PROTOCOLS_TO_12, -+ CurveDB.lookup("secp192k1")), -+ -+ // NIST P-192 -+ SECP192_R1(0x0013, "secp192r1", true, -+ NamedGroupSpec.NAMED_GROUP_ECDHE, -+ ProtocolVersion.PROTOCOLS_TO_12, -+ CurveDB.lookup("secp192r1")), -+ SECP224_K1(0x0014, "secp224k1", false, -+ NamedGroupSpec.NAMED_GROUP_ECDHE, -+ ProtocolVersion.PROTOCOLS_TO_12, -+ CurveDB.lookup("secp224k1")), -+ - // NIST P-224 -+ SECP224_R1(0x0015, "secp224r1", true, -+ NamedGroupSpec.NAMED_GROUP_ECDHE, -+ ProtocolVersion.PROTOCOLS_TO_12, -+ CurveDB.lookup("secp224r1")), - SECP256_K1(0x0016, "secp256k1", false, - NamedGroupSpec.NAMED_GROUP_ECDHE, - ProtocolVersion.PROTOCOLS_TO_12, -@@ -104,7 +211,19 @@ - FFDHE_8192(0x0104, "ffdhe8192", true, - NamedGroupSpec.NAMED_GROUP_FFDHE, - ProtocolVersion.PROTOCOLS_TO_13, -- PredefinedDHParameterSpecs.ffdheParams.get(8192)); -+ PredefinedDHParameterSpecs.ffdheParams.get(8192)), -+ -+ // Elliptic Curves (RFC 4492) -+ // -+ // arbitrary prime and characteristic-2 curves -+ ARBITRARY_PRIME(0xFF01, "arbitrary_explicit_prime_curves", false, -+ NamedGroupSpec.NAMED_GROUP_ARBITRARY, -+ ProtocolVersion.PROTOCOLS_TO_12, -+ null), -+ ARBITRARY_CHAR2(0xFF02, "arbitrary_explicit_char2_curves", false, -+ NamedGroupSpec.NAMED_GROUP_ARBITRARY, -+ ProtocolVersion.PROTOCOLS_TO_12, -+ null); - - final int id; // hash + signature - final String name; // literal name -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/java.base/share/classes/sun/security/util/CurveDB.java jdk11u-ls/src/java.base/share/classes/sun/security/util/CurveDB.java ---- openjdk/src/java.base/share/classes/sun/security/util/CurveDB.java 2022-10-12 23:00:07.000000000 +0800 -+++ jdk11u-ls/src/java.base/share/classes/sun/security/util/CurveDB.java 2023-11-01 09:34:25.977945804 +0800 -@@ -176,6 +176,105 @@ - Pattern nameSplitPattern = Holder.nameSplitPattern; - - /* SEC2 prime curves */ -+ add("secp112r1", "1.3.132.0.6", P, -+ "DB7C2ABF62E35E668076BEAD208B", -+ "DB7C2ABF62E35E668076BEAD2088", -+ "659EF8BA043916EEDE8911702B22", -+ "09487239995A5EE76B55F9C2F098", -+ "A89CE5AF8724C0A23E0E0FF77500", -+ "DB7C2ABF62E35E7628DFAC6561C5", -+ 1, nameSplitPattern); -+ -+ add("secp112r2", "1.3.132.0.7", P, -+ "DB7C2ABF62E35E668076BEAD208B", -+ "6127C24C05F38A0AAAF65C0EF02C", -+ "51DEF1815DB5ED74FCC34C85D709", -+ "4BA30AB5E892B4E1649DD0928643", -+ "adcd46f5882e3747def36e956e97", -+ "36DF0AAFD8B8D7597CA10520D04B", -+ 4, nameSplitPattern); -+ -+ add("secp128r1", "1.3.132.0.28", P, -+ "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF", -+ "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFC", -+ "E87579C11079F43DD824993C2CEE5ED3", -+ "161FF7528B899B2D0C28607CA52C5B86", -+ "CF5AC8395BAFEB13C02DA292DDED7A83", -+ "FFFFFFFE0000000075A30D1B9038A115", -+ 1, nameSplitPattern); -+ -+ add("secp128r2", "1.3.132.0.29", P, -+ "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF", -+ "D6031998D1B3BBFEBF59CC9BBFF9AEE1", -+ "5EEEFCA380D02919DC2C6558BB6D8A5D", -+ "7B6AA5D85E572983E6FB32A7CDEBC140", -+ "27B6916A894D3AEE7106FE805FC34B44", -+ "3FFFFFFF7FFFFFFFBE0024720613B5A3", -+ 4, nameSplitPattern); -+ -+ add("secp160k1", "1.3.132.0.9", P, -+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73", -+ "0000000000000000000000000000000000000000", -+ "0000000000000000000000000000000000000007", -+ "3B4C382CE37AA192A4019E763036F4F5DD4D7EBB", -+ "938CF935318FDCED6BC28286531733C3F03C4FEE", -+ "0100000000000000000001B8FA16DFAB9ACA16B6B3", -+ 1, nameSplitPattern); -+ -+ add("secp160r1", "1.3.132.0.8", P, -+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF", -+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC", -+ "1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45", -+ "4A96B5688EF573284664698968C38BB913CBFC82", -+ "23A628553168947D59DCC912042351377AC5FB32", -+ "0100000000000000000001F4C8F927AED3CA752257", -+ 1, nameSplitPattern); -+ -+ add("secp160r2", "1.3.132.0.30", P, -+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73", -+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC70", -+ "B4E134D3FB59EB8BAB57274904664D5AF50388BA", -+ "52DCB034293A117E1F4FF11B30F7199D3144CE6D", -+ "FEAFFEF2E331F296E071FA0DF9982CFEA7D43F2E", -+ "0100000000000000000000351EE786A818F3A1A16B", -+ 1, nameSplitPattern); -+ -+ add("secp192k1", "1.3.132.0.31", P, -+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37", -+ "000000000000000000000000000000000000000000000000", -+ "000000000000000000000000000000000000000000000003", -+ "DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D", -+ "9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D", -+ "FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D", -+ 1, nameSplitPattern); -+ -+ add("secp192r1 [NIST P-192, X9.62 prime192v1]", "1.2.840.10045.3.1.1", PD, -+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", -+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC", -+ "64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1", -+ "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012", -+ "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811", -+ "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831", -+ 1, nameSplitPattern); -+ -+ add("secp224k1", "1.3.132.0.32", P, -+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFE56D", -+ "00000000000000000000000000000000000000000000000000000000", -+ "00000000000000000000000000000000000000000000000000000005", -+ "A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C", -+ "7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5", -+ "010000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7", -+ 1, nameSplitPattern); -+ -+ add("secp224r1 [NIST P-224]", "1.3.132.0.33", PD, -+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001", -+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE", -+ "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4", -+ "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21", -+ "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34", -+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D", -+ 1, nameSplitPattern); -+ - add("secp256k1", "1.3.132.0.10", P, - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", - "0000000000000000000000000000000000000000000000000000000000000000", -@@ -212,6 +311,435 @@ - "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409", - 1, nameSplitPattern); - -+ /* ANSI X9.62 prime curves */ -+ add("X9.62 prime192v2", "1.2.840.10045.3.1.2", P, -+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", -+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC", -+ "CC22D6DFB95C6B25E49C0D6364A4E5980C393AA21668D953", -+ "EEA2BAE7E1497842F2DE7769CFE9C989C072AD696F48034A", -+ "6574D11D69B6EC7A672BB82A083DF2F2B0847DE970B2DE15", -+ "FFFFFFFFFFFFFFFFFFFFFFFE5FB1A724DC80418648D8DD31", -+ 1, nameSplitPattern); -+ -+ add("X9.62 prime192v3", "1.2.840.10045.3.1.3", P, -+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", -+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC", -+ "22123DC2395A05CAA7423DAECCC94760A7D462256BD56916", -+ "7D29778100C65A1DA1783716588DCE2B8B4AEE8E228F1896", -+ "38A90F22637337334B49DCB66A6DC8F9978ACA7648A943B0", -+ "FFFFFFFFFFFFFFFFFFFFFFFF7A62D031C83F4294F640EC13", -+ 1, nameSplitPattern); -+ -+ add("X9.62 prime239v1", "1.2.840.10045.3.1.4", P, -+ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF", -+ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC", -+ "6B016C3BDCF18941D0D654921475CA71A9DB2FB27D1D37796185C2942C0A", -+ "0FFA963CDCA8816CCC33B8642BEDF905C3D358573D3F27FBBD3B3CB9AAAF", -+ "7DEBE8E4E90A5DAE6E4054CA530BA04654B36818CE226B39FCCB7B02F1AE", -+ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFF9E5E9A9F5D9071FBD1522688909D0B", -+ 1, nameSplitPattern); -+ -+ add("X9.62 prime239v2", "1.2.840.10045.3.1.5", P, -+ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF", -+ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC", -+ "617FAB6832576CBBFED50D99F0249C3FEE58B94BA0038C7AE84C8C832F2C", -+ "38AF09D98727705120C921BB5E9E26296A3CDCF2F35757A0EAFD87B830E7", -+ "5B0125E4DBEA0EC7206DA0FC01D9B081329FB555DE6EF460237DFF8BE4BA", -+ "7FFFFFFFFFFFFFFFFFFFFFFF800000CFA7E8594377D414C03821BC582063", -+ 1, nameSplitPattern); -+ -+ add("X9.62 prime239v3", "1.2.840.10045.3.1.6", P, -+ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF", -+ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC", -+ "255705FA2A306654B1F4CB03D6A750A30C250102D4988717D9BA15AB6D3E", -+ "6768AE8E18BB92CFCF005C949AA2C6D94853D0E660BBF854B1C9505FE95A", -+ "1607E6898F390C06BC1D552BAD226F3B6FCFE48B6E818499AF18E3ED6CF3", -+ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFF975DEB41B3A6057C3C432146526551", -+ 1, nameSplitPattern); -+ -+ /* SEC2 binary curves */ -+ add("sect113r1", "1.3.132.0.4", B, -+ "020000000000000000000000000201", -+ "003088250CA6E7C7FE649CE85820F7", -+ "00E8BEE4D3E2260744188BE0E9C723", -+ "009D73616F35F4AB1407D73562C10F", -+ "00A52830277958EE84D1315ED31886", -+ "0100000000000000D9CCEC8A39E56F", -+ 2, nameSplitPattern); -+ -+ add("sect113r2", "1.3.132.0.5", B, -+ "020000000000000000000000000201", -+ "00689918DBEC7E5A0DD6DFC0AA55C7", -+ "0095E9A9EC9B297BD4BF36E059184F", -+ "01A57A6A7B26CA5EF52FCDB8164797", -+ "00B3ADC94ED1FE674C06E695BABA1D", -+ "010000000000000108789B2496AF93", -+ 2, nameSplitPattern); -+ -+ add("sect131r1", "1.3.132.0.22", B, -+ "080000000000000000000000000000010D", -+ "07A11B09A76B562144418FF3FF8C2570B8", -+ "0217C05610884B63B9C6C7291678F9D341", -+ "0081BAF91FDF9833C40F9C181343638399", -+ "078C6E7EA38C001F73C8134B1B4EF9E150", -+ "0400000000000000023123953A9464B54D", -+ 2, nameSplitPattern); -+ -+ add("sect131r2", "1.3.132.0.23", B, -+ "080000000000000000000000000000010D", -+ "03E5A88919D7CAFCBF415F07C2176573B2", -+ "04B8266A46C55657AC734CE38F018F2192", -+ "0356DCD8F2F95031AD652D23951BB366A8", -+ "0648F06D867940A5366D9E265DE9EB240F", -+ "0400000000000000016954A233049BA98F", -+ 2, nameSplitPattern); -+ -+ add("sect163k1 [NIST K-163]", "1.3.132.0.1", BD, -+ "0800000000000000000000000000000000000000C9", -+ "000000000000000000000000000000000000000001", -+ "000000000000000000000000000000000000000001", -+ "02FE13C0537BBC11ACAA07D793DE4E6D5E5C94EEE8", -+ "0289070FB05D38FF58321F2E800536D538CCDAA3D9", -+ "04000000000000000000020108A2E0CC0D99F8A5EF", -+ 2, nameSplitPattern); -+ -+ add("sect163r1", "1.3.132.0.2", B, -+ "0800000000000000000000000000000000000000C9", -+ "07B6882CAAEFA84F9554FF8428BD88E246D2782AE2", -+ "0713612DCDDCB40AAB946BDA29CA91F73AF958AFD9", -+ "0369979697AB43897789566789567F787A7876A654", -+ "00435EDB42EFAFB2989D51FEFCE3C80988F41FF883", -+ "03FFFFFFFFFFFFFFFFFFFF48AAB689C29CA710279B", -+ 2, nameSplitPattern); -+ -+ add("sect163r2 [NIST B-163]", "1.3.132.0.15", BD, -+ "0800000000000000000000000000000000000000C9", -+ "000000000000000000000000000000000000000001", -+ "020A601907B8C953CA1481EB10512F78744A3205FD", -+ "03F0EBA16286A2D57EA0991168D4994637E8343E36", -+ "00D51FBC6C71A0094FA2CDD545B11C5C0C797324F1", -+ "040000000000000000000292FE77E70C12A4234C33", -+ 2, nameSplitPattern); -+ -+ add("sect193r1", "1.3.132.0.24", B, -+ "02000000000000000000000000000000000000000000008001", -+ "0017858FEB7A98975169E171F77B4087DE098AC8A911DF7B01", -+ "00FDFB49BFE6C3A89FACADAA7A1E5BBC7CC1C2E5D831478814", -+ "01F481BC5F0FF84A74AD6CDF6FDEF4BF6179625372D8C0C5E1", -+ "0025E399F2903712CCF3EA9E3A1AD17FB0B3201B6AF7CE1B05", -+ "01000000000000000000000000C7F34A778F443ACC920EBA49", -+ 2, nameSplitPattern); -+ -+ add("sect193r2", "1.3.132.0.25", B, -+ "02000000000000000000000000000000000000000000008001", -+ "0163F35A5137C2CE3EA6ED8667190B0BC43ECD69977702709B", -+ "00C9BB9E8927D4D64C377E2AB2856A5B16E3EFB7F61D4316AE", -+ "00D9B67D192E0367C803F39E1A7E82CA14A651350AAE617E8F", -+ "01CE94335607C304AC29E7DEFBD9CA01F596F927224CDECF6C", -+ "010000000000000000000000015AAB561B005413CCD4EE99D5", -+ 2, nameSplitPattern); -+ -+ add("sect233k1 [NIST K-233]", "1.3.132.0.26", BD, -+ "020000000000000000000000000000000000000004000000000000000001", -+ "000000000000000000000000000000000000000000000000000000000000", -+ "000000000000000000000000000000000000000000000000000000000001", -+ "017232BA853A7E731AF129F22FF4149563A419C26BF50A4C9D6EEFAD6126", -+ "01DB537DECE819B7F70F555A67C427A8CD9BF18AEB9B56E0C11056FAE6A3", -+ "008000000000000000000000000000069D5BB915BCD46EFB1AD5F173ABDF", -+ 4, nameSplitPattern); -+ -+ add("sect233r1 [NIST B-233]", "1.3.132.0.27", B, -+ "020000000000000000000000000000000000000004000000000000000001", -+ "000000000000000000000000000000000000000000000000000000000001", -+ "0066647EDE6C332C7F8C0923BB58213B333B20E9CE4281FE115F7D8F90AD", -+ "00FAC9DFCBAC8313BB2139F1BB755FEF65BC391F8B36F8F8EB7371FD558B", -+ "01006A08A41903350678E58528BEBF8A0BEFF867A7CA36716F7E01F81052", -+ "01000000000000000000000000000013E974E72F8A6922031D2603CFE0D7", -+ 2, nameSplitPattern); -+ -+ add("sect239k1", "1.3.132.0.3", B, -+ "800000000000000000004000000000000000000000000000000000000001", -+ "000000000000000000000000000000000000000000000000000000000000", -+ "000000000000000000000000000000000000000000000000000000000001", -+ "29A0B6A887A983E9730988A68727A8B2D126C44CC2CC7B2A6555193035DC", -+ "76310804F12E549BDB011C103089E73510ACB275FC312A5DC6B76553F0CA", -+ "2000000000000000000000000000005A79FEC67CB6E91F1C1DA800E478A5", -+ 4, nameSplitPattern); -+ -+ add("sect283k1 [NIST K-283]", "1.3.132.0.16", BD, -+ "0800000000000000000000000000000000000000000000000000000000000000000010A1", -+ "000000000000000000000000000000000000000000000000000000000000000000000000", -+ "000000000000000000000000000000000000000000000000000000000000000000000001", -+ "0503213F78CA44883F1A3B8162F188E553CD265F23C1567A16876913B0C2AC2458492836", -+ "01CCDA380F1C9E318D90F95D07E5426FE87E45C0E8184698E45962364E34116177DD2259", -+ "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE9AE2ED07577265DFF7F94451E061E163C61", -+ 4, nameSplitPattern); -+ -+ add("sect283r1 [NIST B-283]", "1.3.132.0.17", B, -+ "0800000000000000000000000000000000000000000000000000000000000000000010A1", -+ "000000000000000000000000000000000000000000000000000000000000000000000001", -+ "027B680AC8B8596DA5A4AF8A19A0303FCA97FD7645309FA2A581485AF6263E313B79A2F5", -+ "05F939258DB7DD90E1934F8C70B0DFEC2EED25B8557EAC9C80E2E198F8CDBECD86B12053", -+ "03676854FE24141CB98FE6D4B20D02B4516FF702350EDDB0826779C813F0DF45BE8112F4", -+ "03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF90399660FC938A90165B042A7CEFADB307", -+ 2, nameSplitPattern); -+ -+ add("sect409k1 [NIST K-409]", "1.3.132.0.36", BD, -+ "02000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001", -+ "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", -+ "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", -+ "0060F05F658F49C1AD3AB1890F7184210EFD0987E307C84C27ACCFB8F9F67CC2C460189EB5AAAA62EE222EB1B35540CFE9023746", -+ "01E369050B7C4E42ACBA1DACBF04299C3460782F918EA427E6325165E9EA10E3DA5F6C42E9C55215AA9CA27A5863EC48D8E0286B", -+ "007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE5F83B2D4EA20400EC4557D5ED3E3E7CA5B4B5C83B8E01E5FCF", -+ 4, nameSplitPattern); -+ -+ add("sect409r1 [NIST B-409]", "1.3.132.0.37", B, -+ "02000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001", -+ "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", -+ "0021A5C2C8EE9FEB5C4B9A753B7B476B7FD6422EF1F3DD674761FA99D6AC27C8A9A197B272822F6CD57A55AA4F50AE317B13545F", -+ "015D4860D088DDB3496B0C6064756260441CDE4AF1771D4DB01FFE5B34E59703DC255A868A1180515603AEAB60794E54BB7996A7", -+ "0061B1CFAB6BE5F32BBFA78324ED106A7636B9C5A7BD198D0158AA4F5488D08F38514F1FDF4B4F40D2181B3681C364BA0273C706", -+ "010000000000000000000000000000000000000000000000000001E2AAD6A612F33307BE5FA47C3C9E052F838164CD37D9A21173", -+ 2, nameSplitPattern); -+ -+ add("sect571k1 [NIST K-571]", "1.3.132.0.38", BD, -+ "080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425", -+ "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", -+ "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", -+ "026EB7A859923FBC82189631F8103FE4AC9CA2970012D5D46024804801841CA44370958493B205E647DA304DB4CEB08CBBD1BA39494776FB988B47174DCA88C7E2945283A01C8972", -+ "0349DC807F4FBF374F4AEADE3BCA95314DD58CEC9F307A54FFC61EFC006D8A2C9D4979C0AC44AEA74FBEBBB9F772AEDCB620B01A7BA7AF1B320430C8591984F601CD4C143EF1C7A3", -+ "020000000000000000000000000000000000000000000000000000000000000000000000131850E1F19A63E4B391A8DB917F4138B630D84BE5D639381E91DEB45CFE778F637C1001", -+ 4, nameSplitPattern); -+ -+ add("sect571r1 [NIST B-571]", "1.3.132.0.39", B, -+ "080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425", -+ "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", -+ "02F40E7E2221F295DE297117B7F3D62F5C6A97FFCB8CEFF1CD6BA8CE4A9A18AD84FFABBD8EFA59332BE7AD6756A66E294AFD185A78FF12AA520E4DE739BACA0C7FFEFF7F2955727A", -+ "0303001D34B856296C16C0D40D3CD7750A93D1D2955FA80AA5F40FC8DB7B2ABDBDE53950F4C0D293CDD711A35B67FB1499AE60038614F1394ABFA3B4C850D927E1E7769C8EEC2D19", -+ "037BF27342DA639B6DCCFFFEB73D69D78C6C27A6009CBBCA1980F8533921E8A684423E43BAB08A576291AF8F461BB2A8B3531D2F0485C19B16E2F1516E23DD3C1A4827AF1B8AC15B", -+ "03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE661CE18FF55987308059B186823851EC7DD9CA1161DE93D5174D66E8382E9BB2FE84E47", -+ 2, nameSplitPattern); -+ -+ /* ANSI X9.62 binary curves */ -+ add("X9.62 c2tnb191v1", "1.2.840.10045.3.0.5", B, -+ "800000000000000000000000000000000000000000000201", -+ "2866537B676752636A68F56554E12640276B649EF7526267", -+ "2E45EF571F00786F67B0081B9495A3D95462F5DE0AA185EC", -+ "36B3DAF8A23206F9C4F299D7B21A9C369137F2C84AE1AA0D", -+ "765BE73433B3F95E332932E70EA245CA2418EA0EF98018FB", -+ "40000000000000000000000004A20E90C39067C893BBB9A5", -+ 2, nameSplitPattern); -+ -+ add("X9.62 c2tnb191v2", "1.2.840.10045.3.0.6", B, -+ "800000000000000000000000000000000000000000000201", -+ "401028774D7777C7B7666D1366EA432071274F89FF01E718", -+ "0620048D28BCBD03B6249C99182B7C8CD19700C362C46A01", -+ "3809B2B7CC1B28CC5A87926AAD83FD28789E81E2C9E3BF10", -+ "17434386626D14F3DBF01760D9213A3E1CF37AEC437D668A", -+ "20000000000000000000000050508CB89F652824E06B8173", -+ 4, nameSplitPattern); -+ -+ add("X9.62 c2tnb191v3", "1.2.840.10045.3.0.7", B, -+ "800000000000000000000000000000000000000000000201", -+ "6C01074756099122221056911C77D77E77A777E7E7E77FCB", -+ "71FE1AF926CF847989EFEF8DB459F66394D90F32AD3F15E8", -+ "375D4CE24FDE434489DE8746E71786015009E66E38A926DD", -+ "545A39176196575D985999366E6AD34CE0A77CD7127B06BE", -+ "155555555555555555555555610C0B196812BFB6288A3EA3", -+ 6, nameSplitPattern); -+ -+ add("X9.62 c2tnb239v1", "1.2.840.10045.3.0.11", B, -+ "800000000000000000000000000000000000000000000000001000000001", -+ "32010857077C5431123A46B808906756F543423E8D27877578125778AC76", -+ "790408F2EEDAF392B012EDEFB3392F30F4327C0CA3F31FC383C422AA8C16", -+ "57927098FA932E7C0A96D3FD5B706EF7E5F5C156E16B7E7C86038552E91D", -+ "61D8EE5077C33FECF6F1A16B268DE469C3C7744EA9A971649FC7A9616305", -+ "2000000000000000000000000000000F4D42FFE1492A4993F1CAD666E447", -+ 4, nameSplitPattern); -+ -+ add("X9.62 c2tnb239v2", "1.2.840.10045.3.0.12", B, -+ "800000000000000000000000000000000000000000000000001000000001", -+ "4230017757A767FAE42398569B746325D45313AF0766266479B75654E65F", -+ "5037EA654196CFF0CD82B2C14A2FCF2E3FF8775285B545722F03EACDB74B", -+ "28F9D04E900069C8DC47A08534FE76D2B900B7D7EF31F5709F200C4CA205", -+ "5667334C45AFF3B5A03BAD9DD75E2C71A99362567D5453F7FA6E227EC833", -+ "1555555555555555555555555555553C6F2885259C31E3FCDF154624522D", -+ 6, nameSplitPattern); -+ -+ add("X9.62 c2tnb239v3", "1.2.840.10045.3.0.13", B, -+ "800000000000000000000000000000000000000000000000001000000001", -+ "01238774666A67766D6676F778E676B66999176666E687666D8766C66A9F", -+ "6A941977BA9F6A435199ACFC51067ED587F519C5ECB541B8E44111DE1D40", -+ "70F6E9D04D289C4E89913CE3530BFDE903977D42B146D539BF1BDE4E9C92", -+ "2E5A0EAF6E5E1305B9004DCE5C0ED7FE59A35608F33837C816D80B79F461", -+ "0CCCCCCCCCCCCCCCCCCCCCCCCCCCCCAC4912D2D9DF903EF9888B8A0E4CFF", -+ 0xA, nameSplitPattern); -+ -+ add("X9.62 c2tnb359v1", "1.2.840.10045.3.0.18", B, -+ "800000000000000000000000000000000000000000000000000000000000000000000000100000000000000001", -+ "5667676A654B20754F356EA92017D946567C46675556F19556A04616B567D223A5E05656FB549016A96656A557", -+ "2472E2D0197C49363F1FE7F5B6DB075D52B6947D135D8CA445805D39BC345626089687742B6329E70680231988", -+ "3C258EF3047767E7EDE0F1FDAA79DAEE3841366A132E163ACED4ED2401DF9C6BDCDE98E8E707C07A2239B1B097", -+ "53D7E08529547048121E9C95F3791DD804963948F34FAE7BF44EA82365DC7868FE57E4AE2DE211305A407104BD", -+ "01AF286BCA1AF286BCA1AF286BCA1AF286BCA1AF286BC9FB8F6B85C556892C20A7EB964FE7719E74F490758D3B", -+ 0x4C, nameSplitPattern); -+ -+ add("X9.62 c2tnb431r1", "1.2.840.10045.3.0.20", B, -+ "800000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000001", -+ "1A827EF00DD6FC0E234CAF046C6A5D8A85395B236CC4AD2CF32A0CADBDC9DDF620B0EB9906D0957F6C6FEACD615468DF104DE296CD8F", -+ "10D9B4A3D9047D8B154359ABFB1B7F5485B04CEB868237DDC9DEDA982A679A5A919B626D4E50A8DD731B107A9962381FB5D807BF2618", -+ "120FC05D3C67A99DE161D2F4092622FECA701BE4F50F4758714E8A87BBF2A658EF8C21E7C5EFE965361F6C2999C0C247B0DBD70CE6B7", -+ "20D0AF8903A96F8D5FA2C255745D3C451B302C9346D9B7E485E7BCE41F6B591F3E8F6ADDCBB0BC4C2F947A7DE1A89B625D6A598B3760", -+ "0340340340340340340340340340340340340340340340340340340323C313FAB50589703B5EC68D3587FEC60D161CC149C1AD4A91", -+ 0x2760, nameSplitPattern); -+ -+ /* ANSI X9.62 binary curves from the 1998 standard but forbidden -+ * in the 2005 version of the standard. -+ * We don't register them but leave them here for the time being in -+ * case we need to support them after all. -+ */ +diff --git a/src/hotspot/share/utilities/vmassert_reinstall.hpp b/src/hotspot/share/utilities/vmassert_reinstall.hpp +new file mode 100644 +index 000000000..32d31ac0c +--- /dev/null ++++ b/src/hotspot/share/utilities/vmassert_reinstall.hpp +@@ -0,0 +1,36 @@ +/* -+ add("X9.62 c2pnb163v1", "1.2.840.10045.3.0.1", B, -+ "080000000000000000000000000000000000000107", -+ "072546B5435234A422E0789675F432C89435DE5242", -+ "00C9517D06D5240D3CFF38C74B20B6CD4D6F9DD4D9", -+ "07AF69989546103D79329FCC3D74880F33BBE803CB", -+ "01EC23211B5966ADEA1D3F87F7EA5848AEF0B7CA9F", -+ "0400000000000000000001E60FC8821CC74DAEAFC1", -+ 2, nameSplitPattern); -+ -+ add("X9.62 c2pnb163v2", "1.2.840.10045.3.0.2", B, -+ "080000000000000000000000000000000000000107", -+ "0108B39E77C4B108BED981ED0E890E117C511CF072", -+ "0667ACEB38AF4E488C407433FFAE4F1C811638DF20", -+ "0024266E4EB5106D0A964D92C4860E2671DB9B6CC5", -+ "079F684DDF6684C5CD258B3890021B2386DFD19FC5", -+ "03FFFFFFFFFFFFFFFFFFFDF64DE1151ADBB78F10A7", -+ 2, nameSplitPattern); -+ -+ add("X9.62 c2pnb163v3", "1.2.840.10045.3.0.3", B, -+ "080000000000000000000000000000000000000107", -+ "07A526C63D3E25A256A007699F5447E32AE456B50E", -+ "03F7061798EB99E238FD6F1BF95B48FEEB4854252B", -+ "02F9F87B7C574D0BDECF8A22E6524775F98CDEBDCB", -+ "05B935590C155E17EA48EB3FF3718B893DF59A05D0", -+ "03FFFFFFFFFFFFFFFFFFFE1AEE140F110AFF961309", -+ 2, nameSplitPattern); -+ -+ add("X9.62 c2pnb176w1", "1.2.840.10045.3.0.4", B, -+ "0100000000000000000000000000000000080000000007", -+ "E4E6DB2995065C407D9D39B8D0967B96704BA8E9C90B", -+ "5DDA470ABE6414DE8EC133AE28E9BBD7FCEC0AE0FFF2", -+ "8D16C2866798B600F9F08BB4A8E860F3298CE04A5798", -+ "6FA4539C2DADDDD6BAB5167D61B436E1D92BB16A562C", -+ "00010092537397ECA4F6145799D62B0A19CE06FE26AD", -+ 0xFF6E, nameSplitPattern); -+ -+ add("X9.62 c2pnb208w1", "1.2.840.10045.3.0.10", B, -+ "010000000000000000000000000000000800000000000000000007", -+ "0000000000000000000000000000000000000000000000000000", -+ "C8619ED45A62E6212E1160349E2BFA844439FAFC2A3FD1638F9E", -+ "89FDFBE4ABE193DF9559ECF07AC0CE78554E2784EB8C1ED1A57A", -+ "0F55B51A06E78E9AC38A035FF520D8B01781BEB1A6BB08617DE3", -+ "000101BAF95C9723C57B6C21DA2EFF2D5ED588BDD5717E212F9D", -+ 0xFE48, nameSplitPattern); -+ -+ add("X9.62 c2pnb272w1", "1.2.840.10045.3.0.16", B, -+ "010000000000000000000000000000000000000000000000000000010000000000000B", -+ "91A091F03B5FBA4AB2CCF49C4EDD220FB028712D42BE752B2C40094DBACDB586FB20", -+ "7167EFC92BB2E3CE7C8AAAFF34E12A9C557003D7C73A6FAF003F99F6CC8482E540F7", -+ "6108BABB2CEEBCF787058A056CBE0CFE622D7723A289E08A07AE13EF0D10D171DD8D", -+ "10C7695716851EEF6BA7F6872E6142FBD241B830FF5EFCACECCAB05E02005DDE9D23", -+ "000100FAF51354E0E39E4892DF6E319C72C8161603FA45AA7B998A167B8F1E629521", -+ 0xFF06, nameSplitPattern); -+ -+ add("X9.62 c2pnb304w1", "1.2.840.10045.3.0.17", B, -+ "010000000000000000000000000000000000000000000000000000000000000000000000000807", -+ "FD0D693149A118F651E6DCE6802085377E5F882D1B510B44160074C1288078365A0396C8E681", -+ "BDDB97E555A50A908E43B01C798EA5DAA6788F1EA2794EFCF57166B8C14039601E55827340BE", -+ "197B07845E9BE2D96ADB0F5F3C7F2CFFBD7A3EB8B6FEC35C7FD67F26DDF6285A644F740A2614", -+ "E19FBEB76E0DA171517ECF401B50289BF014103288527A9B416A105E80260B549FDC1B92C03B", -+ "000101D556572AABAC800101D556572AABAC8001022D5C91DD173F8FB561DA6899164443051D", -+ 0xFE2E, nameSplitPattern); -+ -+ add("X9.62 c2pnb368w1", "1.2.840.10045.3.0.19", B, -+ "0100000000000000000000000000000000000000000000000000000000000000000000002000000000000000000007", -+ "E0D2EE25095206F5E2A4F9ED229F1F256E79A0E2B455970D8D0D865BD94778C576D62F0AB7519CCD2A1A906AE30D", -+ "FC1217D4320A90452C760A58EDCD30C8DD069B3C34453837A34ED50CB54917E1C2112D84D164F444F8F74786046A", -+ "1085E2755381DCCCE3C1557AFA10C2F0C0C2825646C5B34A394CBCFA8BC16B22E7E789E927BE216F02E1FB136A5F", -+ "7B3EB1BDDCBA62D5D8B2059B525797FC73822C59059C623A45FF3843CEE8F87CD1855ADAA81E2A0750B80FDA2310", -+ "00010090512DA9AF72B08349D98A5DD4C7B0532ECA51CE03E2D10F3B7AC579BD87E909AE40A6F131E9CFCE5BD967", -+ 0xFF70, nameSplitPattern); -+*/ -+ -+ /* -+ * Brainpool curves (RFC 5639) -+ * (Twisted curves are not included) -+ */ ++ * 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. ++ * ++ */ + -+ add("brainpoolP160r1", "1.3.36.3.3.2.8.1.1.1", P, -+ "E95E4A5F737059DC60DFC7AD95B3D8139515620F", -+ "340E7BE2A280EB74E2BE61BADA745D97E8F7C300", -+ "1E589A8595423412134FAA2DBDEC95C8D8675E58", -+ "BED5AF16EA3F6A4F62938C4631EB5AF7BDBCDBC3", -+ "1667CB477A1A8EC338F94741669C976316DA6321", -+ "E95E4A5F737059DC60DF5991D45029409E60FC09", -+ 1, nameSplitPattern); -+ -+ add("brainpoolP192r1", "1.3.36.3.3.2.8.1.1.3", P, -+ "C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86297", -+ "6A91174076B1E0E19C39C031FE8685C1CAE040E5C69A28EF", -+ "469A28EF7C28CCA3DC721D044F4496BCCA7EF4146FBF25C9", -+ "C0A0647EAAB6A48753B033C56CB0F0900A2F5C4853375FD6", -+ "14B690866ABD5BB88B5F4828C1490002E6773FA2FA299B8F", -+ "C302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1", -+ 1, nameSplitPattern); -+ -+ add("brainpoolP224r1", "1.3.36.3.3.2.8.1.1.5", P, -+ "D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF", -+ "68A5E62CA9CE6C1C299803A6C1530B514E182AD8B0042A59CAD29F43", -+ "2580F63CCFE44138870713B1A92369E33E2135D266DBB372386C400B", -+ "0D9029AD2C7E5CF4340823B2A87DC68C9E4CE3174C1E6EFDEE12C07D", -+ "58AA56F772C0726F24C6B89E4ECDAC24354B9E99CAA3F6D3761402CD", -+ "D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F", -+ 1, nameSplitPattern); -+ -+ add("brainpoolP256r1", "1.3.36.3.3.2.8.1.1.7", P, -+ "A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377", -+ "7D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9", -+ "26DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B6", -+ "8BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262", -+ "547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997", -+ "A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7", -+ 1, nameSplitPattern); -+ -+ add("brainpoolP320r1", "1.3.36.3.3.2.8.1.1.9", P, -+ "D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E27", -+ "3EE30B568FBAB0F883CCEBD46D3F3BB8A2A73513F5EB79DA66190EB085FFA9F492F375A97D860EB4", -+ "520883949DFDBC42D3AD198640688A6FE13F41349554B49ACC31DCCD884539816F5EB4AC8FB1F1A6", -+ "43BD7E9AFB53D8B85289BCC48EE5BFE6F20137D10A087EB6E7871E2A10A599C710AF8D0D39E20611", -+ "14FDD05545EC1CC8AB4093247F77275E0743FFED117182EAA9C77877AAAC6AC7D35245D1692E8EE1", -+ "D35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D482EC7EE8658E98691555B44C59311", -+ 1, nameSplitPattern); -+ -+ add("brainpoolP384r1", "1.3.36.3.3.2.8.1.1.11", P, -+ "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53", -+ "7BC382C63D8C150C3C72080ACE05AFA0C2BEA28E4FB22787139165EFBA91F90F8AA5814A503AD4EB04A8C7DD22CE2826", -+ "04A8C7DD22CE28268B39B55416F0447C2FB77DE107DCD2A62E880EA53EEB62D57CB4390295DBC9943AB78696FA504C11", -+ "1D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10E8E826E03436D646AAEF87B2E247D4AF1E", -+ "8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129280E4646217791811142820341263C5315", -+ "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565", -+ 1, nameSplitPattern); -+ -+ add("brainpoolP512r1", "1.3.36.3.3.2.8.1.1.13", P, -+ "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3", -+ "7830A3318B603B89E2327145AC234CC594CBDD8D3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CA", -+ "3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CADC083E67984050B75EBAE5DD2809BD638016F723", -+ "81AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D0098EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F822", -+ "7DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F8111B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892", -+ "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069", -+ 1, nameSplitPattern); -+ - specCollection = Collections.unmodifiableCollection(oidMap.values()); - } - } -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/java.base/share/conf/security/java.security jdk11u-ls/src/java.base/share/conf/security/java.security ---- openjdk/src/java.base/share/conf/security/java.security 2022-10-12 23:00:07.000000000 +0800 -+++ jdk11u-ls/src/java.base/share/conf/security/java.security 2023-11-01 09:34:26.009945839 +0800 -@@ -505,7 +505,16 @@ - # in the jdk.[tls|certpath|jar].disabledAlgorithms properties. To include this - # list in any of the disabledAlgorithms properties, add the property name as - # an entry. --jdk.disabled.namedCurves = secp256k1 -+jdk.disabled.namedCurves = secp112r1, secp112r2, secp128r1, secp128r2, \ -+ secp160k1, secp160r1, secp160r2, secp192k1, secp192r1, secp224k1, \ -+ secp224r1, secp256k1, sect113r1, sect113r2, sect131r1, sect131r2, \ -+ sect163k1, sect163r1, sect163r2, sect193r1, sect193r2, sect233k1, \ -+ sect233r1, sect239k1, sect283k1, sect283r1, sect409k1, sect409r1, \ -+ sect571k1, sect571r1, X9.62 c2tnb191v1, X9.62 c2tnb191v2, \ -+ X9.62 c2tnb191v3, X9.62 c2tnb239v1, X9.62 c2tnb239v2, X9.62 c2tnb239v3, \ -+ X9.62 c2tnb359v1, X9.62 c2tnb431r1, X9.62 prime192v2, X9.62 prime192v3, \ -+ X9.62 prime239v1, X9.62 prime239v2, X9.62 prime239v3, brainpoolP256r1, \ -+ brainpoolP320r1, brainpoolP384r1, brainpoolP512r1 - - # - # Algorithm restrictions for certification path (CertPath) processing -@@ -743,7 +752,7 @@ - # - # Example: - # jdk.tls.disabledAlgorithms=MD5, SSLv3, DSA, RSA keySize < 2048, \ --# rsa_pkcs1_sha1 -+# rsa_pkcs1_sha1, secp224r1 - jdk.tls.disabledAlgorithms=SSLv3, TLSv1, TLSv1.1, RC4, DES, MD5withRSA, \ - DH keySize < 1024, EC keySize < 224, 3DES_EDE_CBC, anon, NULL, \ - include jdk.disabled.namedCurves -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c jdk11u-ls/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c ---- openjdk/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c 2022-10-12 23:00:02.000000000 +0800 -+++ jdk11u-ls/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c 2023-09-12 13:54:24.761573760 +0800 -@@ -612,7 +612,15 @@ - JNU_ThrowInternalError(env, "should not reach here"); - return; - } ++// Intentionally no #include guard. May be included multiple times for effect. + -+#ifdef __mips__ -+ // __NR_newfstatat is incorrect on Loongnix -+ // workaround it using glibc's fstatat64 -+ RESTARTABLE(fstatat64((int)dfd, path, &buf, (int)flag), err); -+#else - RESTARTABLE((*my_fstatat64_func)((int)dfd, path, &buf, (int)flag), err); -+#endif ++// See vmassert_uninstall.hpp for usage. + - if (err == -1) { - throwUnixException(env, errno); - } else { -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/ECDSAUtils.java jdk11u-ls/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/ECDSAUtils.java ---- openjdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/ECDSAUtils.java 2022-10-12 23:00:07.000000000 +0800 -+++ jdk11u-ls/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/ECDSAUtils.java 2023-09-12 13:54:25.881575168 +0800 -@@ -171,6 +171,149 @@ - static { - ecCurveDefinitions.add( - new ECCurveDefinition( -+ "secp112r1", -+ "1.3.132.0.6", -+ "db7c2abf62e35e668076bead208b", -+ "db7c2abf62e35e668076bead2088", -+ "659ef8ba043916eede8911702b22", -+ "09487239995a5ee76b55f9c2f098", -+ "a89ce5af8724c0a23e0e0ff77500", -+ "db7c2abf62e35e7628dfac6561c5", -+ 1) -+ ); ++// Remove possible stdlib assert macro (or any others, for that matter). ++#undef assert + -+ ecCurveDefinitions.add( -+ new ECCurveDefinition( -+ "secp112r2", -+ "1.3.132.0.7", -+ "db7c2abf62e35e668076bead208b", -+ "6127c24c05f38a0aaaf65c0ef02c", -+ "51def1815db5ed74fcc34c85d709", -+ "4ba30ab5e892b4e1649dd0928643", -+ "adcd46f5882e3747def36e956e97", -+ "36df0aafd8b8d7597ca10520d04b", -+ 4) -+ ); ++// Reinstall HotSpot's assert macro, if previously defined. ++#ifdef vmassert ++#define assert(p, ...) vmassert(p, __VA_ARGS__) ++#endif + -+ ecCurveDefinitions.add( -+ new ECCurveDefinition( -+ "secp128r1", -+ "1.3.132.0.28", -+ "fffffffdffffffffffffffffffffffff", -+ "fffffffdfffffffffffffffffffffffc", -+ "e87579c11079f43dd824993c2cee5ed3", -+ "161ff7528b899b2d0c28607ca52c5b86", -+ "cf5ac8395bafeb13c02da292dded7a83", -+ "fffffffe0000000075a30d1b9038a115", -+ 1) -+ ); -+ -+ ecCurveDefinitions.add( -+ new ECCurveDefinition( -+ "secp128r2", -+ "1.3.132.0.29", -+ "fffffffdffffffffffffffffffffffff", -+ "d6031998d1b3bbfebf59cc9bbff9aee1", -+ "5eeefca380d02919dc2c6558bb6d8a5d", -+ "7b6aa5d85e572983e6fb32a7cdebc140", -+ "27b6916a894d3aee7106fe805fc34b44", -+ "3fffffff7fffffffbe0024720613b5a3", -+ 4) -+ ); -+ -+ ecCurveDefinitions.add( -+ new ECCurveDefinition( -+ "secp160k1", -+ "1.3.132.0.9", -+ "fffffffffffffffffffffffffffffffeffffac73", -+ "0000000000000000000000000000000000000000", -+ "0000000000000000000000000000000000000007", -+ "3b4c382ce37aa192a4019e763036f4f5dd4d7ebb", -+ "938cf935318fdced6bc28286531733c3f03c4fee", -+ "0100000000000000000001b8fa16dfab9aca16b6b3", -+ 1) -+ ); -+ -+ ecCurveDefinitions.add( -+ new ECCurveDefinition( -+ "secp160r1", -+ "1.3.132.0.8", -+ "ffffffffffffffffffffffffffffffff7fffffff", -+ "ffffffffffffffffffffffffffffffff7ffffffc", -+ "1c97befc54bd7a8b65acf89f81d4d4adc565fa45", -+ "4a96b5688ef573284664698968c38bb913cbfc82", -+ "23a628553168947d59dcc912042351377ac5fb32", -+ "0100000000000000000001f4c8f927aed3ca752257", -+ 1) -+ ); -+ -+ ecCurveDefinitions.add( -+ new ECCurveDefinition( -+ "secp160r2", -+ "1.3.132.0.30", -+ "fffffffffffffffffffffffffffffffeffffac73", -+ "fffffffffffffffffffffffffffffffeffffac70", -+ "b4e134d3fb59eb8bab57274904664d5af50388ba", -+ "52dcb034293a117e1f4ff11b30f7199d3144ce6d", -+ "feaffef2e331f296e071fa0df9982cfea7d43f2e", -+ "0100000000000000000000351ee786a818f3a1a16b", -+ 1) -+ ); -+ -+ ecCurveDefinitions.add( -+ new ECCurveDefinition( -+ "secp192k1", -+ "1.3.132.0.31", -+ "fffffffffffffffffffffffffffffffffffffffeffffee37", -+ "000000000000000000000000000000000000000000000000", -+ "000000000000000000000000000000000000000000000003", -+ "db4ff10ec057e9ae26b07d0280b7f4341da5d1b1eae06c7d", -+ "9b2f2f6d9c5628a7844163d015be86344082aa88d95e2f9d", -+ "fffffffffffffffffffffffe26f2fc170f69466a74defd8d", -+ 1) -+ ); -+ -+ ecCurveDefinitions.add( -+ new ECCurveDefinition( -+ "secp192r1 [NIST P-192, X9.62 prime192v1]", -+ "1.2.840.10045.3.1.1", -+ "fffffffffffffffffffffffffffffffeffffffffffffffff", -+ "fffffffffffffffffffffffffffffffefffffffffffffffc", -+ "64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1", -+ "188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", -+ "07192b95ffc8da78631011ed6b24cdd573f977a11e794811", -+ "ffffffffffffffffffffffff99def836146bc9b1b4d22831", -+ 1) -+ ); -+ -+ ecCurveDefinitions.add( -+ new ECCurveDefinition( -+ "secp224k1", -+ "1.3.132.0.32", -+ "fffffffffffffffffffffffffffffffffffffffffffffffeffffe56d", -+ "00000000000000000000000000000000000000000000000000000000", -+ "00000000000000000000000000000000000000000000000000000005", -+ "a1455b334df099df30fc28a169a467e9e47075a90f7e650eb6b7a45c", -+ "7e089fed7fba344282cafbd6f7e319f7c0b0bd59e2ca4bdb556d61a5", -+ "010000000000000000000000000001dce8d2ec6184caf0a971769fb1f7", -+ 1) -+ ); -+ -+ ecCurveDefinitions.add( -+ new ECCurveDefinition( -+ "secp224r1 [NIST P-224]", -+ "1.3.132.0.33", -+ "ffffffffffffffffffffffffffffffff000000000000000000000001", -+ "fffffffffffffffffffffffffffffffefffffffffffffffffffffffe", -+ "b4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4", -+ "b70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21", -+ "bd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34", -+ "ffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d", -+ 1) -+ ); -+ -+ ecCurveDefinitions.add( -+ new ECCurveDefinition( - "secp256k1", - "1.3.132.0.10", - "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", -@@ -220,6 +363,409 @@ - "01fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409", - 1) - ); -+ -+ ecCurveDefinitions.add( -+ new ECCurveDefinition( -+ "X9.62 prime192v2", -+ "1.2.840.10045.3.1.2", -+ "fffffffffffffffffffffffffffffffeffffffffffffffff", -+ "fffffffffffffffffffffffffffffffefffffffffffffffc", -+ "cc22d6dfb95c6b25e49c0d6364a4e5980c393aa21668d953", -+ "eea2bae7e1497842f2de7769cfe9c989c072ad696f48034a", -+ "6574d11d69b6ec7a672bb82a083df2f2b0847de970b2de15", -+ "fffffffffffffffffffffffe5fb1a724dc80418648d8dd31", -+ 1) -+ ); -+ -+ ecCurveDefinitions.add( -+ new ECCurveDefinition( -+ "X9.62 prime192v3", -+ "1.2.840.10045.3.1.3", -+ "fffffffffffffffffffffffffffffffeffffffffffffffff", -+ "fffffffffffffffffffffffffffffffefffffffffffffffc", -+ "22123dc2395a05caa7423daeccc94760a7d462256bd56916", -+ "7d29778100c65a1da1783716588dce2b8b4aee8e228f1896", -+ "38a90f22637337334b49dcb66a6dc8f9978aca7648a943b0", -+ "ffffffffffffffffffffffff7a62d031c83f4294f640ec13", -+ 1) -+ ); -+ -+ ecCurveDefinitions.add( -+ new ECCurveDefinition( -+ "X9.62 prime239v1", -+ "1.2.840.10045.3.1.4", -+ "7fffffffffffffffffffffff7fffffffffff8000000000007fffffffffff", -+ "7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", -+ "6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", -+ "0ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf", -+ "7debe8e4e90a5dae6e4054ca530ba04654b36818ce226b39fccb7b02f1ae", -+ "7fffffffffffffffffffffff7fffff9e5e9a9f5d9071fbd1522688909d0b", -+ 1) -+ ); -+ -+ ecCurveDefinitions.add( -+ new ECCurveDefinition( -+ "X9.62 prime239v2", -+ "1.2.840.10045.3.1.5", -+ "7fffffffffffffffffffffff7fffffffffff8000000000007fffffffffff", -+ "7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", -+ "617fab6832576cbbfed50d99f0249c3fee58b94ba0038c7ae84c8c832f2c", -+ "38af09d98727705120c921bb5e9e26296a3cdcf2f35757a0eafd87b830e7", -+ "5b0125e4dbea0ec7206da0fc01d9b081329fb555de6ef460237dff8be4ba", -+ "7fffffffffffffffffffffff800000cfa7e8594377d414c03821bc582063", -+ 1) -+ ); -+ -+ ecCurveDefinitions.add( -+ new ECCurveDefinition( -+ "X9.62 prime239v3", -+ "1.2.840.10045.3.1.6", -+ "7fffffffffffffffffffffff7fffffffffff8000000000007fffffffffff", -+ "7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", -+ "255705fa2a306654b1f4cb03d6a750a30c250102d4988717d9ba15ab6d3e", -+ "6768ae8e18bb92cfcf005c949aa2c6d94853d0e660bbf854b1c9505fe95a", -+ "1607e6898f390c06bc1d552bad226f3b6fcfe48b6e818499af18e3ed6cf3", -+ "7fffffffffffffffffffffff7fffff975deb41b3a6057c3c432146526551", -+ 1) -+ ); -+ -+ ecCurveDefinitions.add( -+ new ECCurveDefinition( -+ "sect113r1", -+ "1.3.132.0.4", -+ "020000000000000000000000000201", -+ "003088250ca6e7c7fe649ce85820f7", -+ "00e8bee4d3e2260744188be0e9c723", -+ "009d73616f35f4ab1407d73562c10f", -+ "00a52830277958ee84d1315ed31886", -+ "0100000000000000d9ccec8a39e56f", -+ 2) -+ ); -+ -+ ecCurveDefinitions.add( -+ new ECCurveDefinition( -+ "sect113r2", -+ "1.3.132.0.5", -+ "020000000000000000000000000201", -+ "00689918dbec7e5a0dd6dfc0aa55c7", -+ "0095e9a9ec9b297bd4bf36e059184f", -+ "01a57a6a7b26ca5ef52fcdb8164797", -+ "00b3adc94ed1fe674c06e695baba1d", -+ "010000000000000108789b2496af93", -+ 2) -+ ); -+ -+ ecCurveDefinitions.add( -+ new ECCurveDefinition( -+ "sect131r1", -+ "1.3.132.0.22", -+ "080000000000000000000000000000010d", -+ "07a11b09a76b562144418ff3ff8c2570b8", -+ "0217c05610884b63b9c6c7291678f9d341", -+ "0081baf91fdf9833c40f9c181343638399", -+ "078c6e7ea38c001f73c8134b1b4ef9e150", -+ "0400000000000000023123953a9464b54d", -+ 2) -+ ); -+ -+ ecCurveDefinitions.add( -+ new ECCurveDefinition( -+ "sect131r2", -+ "1.3.132.0.23", -+ "080000000000000000000000000000010d", -+ "03e5a88919d7cafcbf415f07c2176573b2", -+ "04b8266a46c55657ac734ce38f018f2192", -+ "0356dcd8f2f95031ad652d23951bb366a8", -+ "0648f06d867940a5366d9e265de9eb240f", -+ "0400000000000000016954a233049ba98f", -+ 2) -+ ); -+ -+ ecCurveDefinitions.add( -+ new ECCurveDefinition( -+ "sect163k1 [NIST K-163]", -+ "1.3.132.0.1", -+ "0800000000000000000000000000000000000000c9", -+ "000000000000000000000000000000000000000001", -+ "000000000000000000000000000000000000000001", -+ "02fe13c0537bbc11acaa07d793de4e6d5e5c94eee8", -+ "0289070fb05d38ff58321f2e800536d538ccdaa3d9", -+ "04000000000000000000020108a2e0cc0d99f8a5ef", -+ 2) -+ ); -+ -+ ecCurveDefinitions.add( -+ new ECCurveDefinition( -+ "sect163r1", -+ "1.3.132.0.2", -+ "0800000000000000000000000000000000000000c9", -+ "07b6882caaefa84f9554ff8428bd88e246d2782ae2", -+ "0713612dcddcb40aab946bda29ca91f73af958afd9", -+ "0369979697ab43897789566789567f787a7876a654", -+ "00435edb42efafb2989d51fefce3c80988f41ff883", -+ "03ffffffffffffffffffff48aab689c29ca710279b", -+ 2) -+ ); -+ -+ ecCurveDefinitions.add( -+ new ECCurveDefinition( -+ "sect163r2 [NIST B-163]", -+ "1.3.132.0.15", -+ "0800000000000000000000000000000000000000c9", -+ "000000000000000000000000000000000000000001", -+ "020a601907b8c953ca1481eb10512f78744a3205fd", -+ "03f0eba16286a2d57ea0991168d4994637e8343e36", -+ "00d51fbc6c71a0094fa2cdd545b11c5c0c797324f1", -+ "040000000000000000000292fe77e70c12a4234c33", -+ 2) -+ ); -+ -+ ecCurveDefinitions.add( -+ new ECCurveDefinition( -+ "sect193r1", -+ "1.3.132.0.24", -+ "02000000000000000000000000000000000000000000008001", -+ "0017858feb7a98975169e171f77b4087de098ac8a911df7b01", -+ "00fdfb49bfe6c3a89facadaa7a1e5bbc7cc1c2e5d831478814", -+ "01f481bc5f0ff84a74ad6cdf6fdef4bf6179625372d8c0c5e1", -+ "0025e399f2903712ccf3ea9e3a1ad17fb0b3201b6af7ce1b05", -+ "01000000000000000000000000c7f34a778f443acc920eba49", -+ 2) -+ ); -+ -+ ecCurveDefinitions.add( -+ new ECCurveDefinition( -+ "sect193r2", -+ "1.3.132.0.25", -+ "02000000000000000000000000000000000000000000008001", -+ "0163f35a5137c2ce3ea6ed8667190b0bc43ecd69977702709b", -+ "00c9bb9e8927d4d64c377e2ab2856a5b16e3efb7f61d4316ae", -+ "00d9b67d192e0367c803f39e1a7e82ca14a651350aae617e8f", -+ "01ce94335607c304ac29e7defbd9ca01f596f927224cdecf6c", -+ "010000000000000000000000015aab561b005413ccd4ee99d5", -+ 2) -+ ); -+ -+ ecCurveDefinitions.add( -+ new ECCurveDefinition( -+ "sect233k1 [NIST K-233]", -+ "1.3.132.0.26", -+ "020000000000000000000000000000000000000004000000000000000001", -+ "000000000000000000000000000000000000000000000000000000000000", -+ "000000000000000000000000000000000000000000000000000000000001", -+ "017232ba853a7e731af129f22ff4149563a419c26bf50a4c9d6eefad6126", -+ "01db537dece819b7f70f555a67c427a8cd9bf18aeb9b56e0c11056fae6a3", -+ "008000000000000000000000000000069d5bb915bcd46efb1ad5f173abdf", -+ 4) -+ ); -+ -+ ecCurveDefinitions.add( -+ new ECCurveDefinition( -+ "sect233r1 [NIST B-233]", -+ "1.3.132.0.27", -+ "020000000000000000000000000000000000000004000000000000000001", -+ "000000000000000000000000000000000000000000000000000000000001", -+ "0066647ede6c332c7f8c0923bb58213b333b20e9ce4281fe115f7d8f90ad", -+ "00fac9dfcbac8313bb2139f1bb755fef65bc391f8b36f8f8eb7371fd558b", -+ "01006a08a41903350678e58528bebf8a0beff867a7ca36716f7e01f81052", -+ "01000000000000000000000000000013e974e72f8a6922031d2603cfe0d7", -+ 2) -+ ); -+ -+ ecCurveDefinitions.add( -+ new ECCurveDefinition( -+ "sect239k1", -+ "1.3.132.0.3", -+ "800000000000000000004000000000000000000000000000000000000001", -+ "000000000000000000000000000000000000000000000000000000000000", -+ "000000000000000000000000000000000000000000000000000000000001", -+ "29a0b6a887a983e9730988a68727a8b2d126c44cc2cc7b2a6555193035dc", -+ "76310804f12e549bdb011c103089e73510acb275fc312a5dc6b76553f0ca", -+ "2000000000000000000000000000005a79fec67cb6e91f1c1da800e478a5", -+ 4) -+ ); -+ -+ ecCurveDefinitions.add( -+ new ECCurveDefinition( -+ "sect283k1 [NIST K-283]", -+ "1.3.132.0.16", -+ "0800000000000000000000000000000000000000000000000000000000000000000010a1", -+ "000000000000000000000000000000000000000000000000000000000000000000000000", -+ "000000000000000000000000000000000000000000000000000000000000000000000001", -+ "0503213f78ca44883f1a3b8162f188e553cd265f23c1567a16876913b0c2ac2458492836", -+ "01ccda380f1c9e318d90f95d07e5426fe87e45c0e8184698e45962364e34116177dd2259", -+ "01ffffffffffffffffffffffffffffffffffe9ae2ed07577265dff7f94451e061e163c61", -+ 4) -+ ); -+ -+ ecCurveDefinitions.add( -+ new ECCurveDefinition( -+ "sect283r1 [NIST B-283]", -+ "1.3.132.0.17", -+ "0800000000000000000000000000000000000000000000000000000000000000000010a1", -+ "000000000000000000000000000000000000000000000000000000000000000000000001", -+ "027b680ac8b8596da5a4af8a19a0303fca97fd7645309fa2a581485af6263e313b79a2f5", -+ "05f939258db7dd90e1934f8c70b0dfec2eed25b8557eac9c80e2e198f8cdbecd86b12053", -+ "03676854fe24141cb98fe6d4b20d02b4516ff702350eddb0826779c813f0df45be8112f4", -+ "03ffffffffffffffffffffffffffffffffffef90399660fc938a90165b042a7cefadb307", -+ 2) -+ ); -+ -+ ecCurveDefinitions.add( -+ new ECCurveDefinition( -+ "sect409k1 [NIST K-409]", -+ "1.3.132.0.36", -+ "02000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001", -+ "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", -+ "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", -+ "0060f05f658f49c1ad3ab1890f7184210efd0987e307c84c27accfb8f9f67cc2c460189eb5aaaa62ee222eb1b35540cfe9023746", -+ "01e369050b7c4e42acba1dacbf04299c3460782f918ea427e6325165e9ea10e3da5f6c42e9c55215aa9ca27a5863ec48d8e0286b", -+ "007ffffffffffffffffffffffffffffffffffffffffffffffffffe5f83b2d4ea20400ec4557d5ed3e3e7ca5b4b5c83b8e01e5fcf", -+ 4) -+ ); -+ -+ ecCurveDefinitions.add( -+ new ECCurveDefinition( -+ "sect409r1 [NIST B-409]", -+ "1.3.132.0.37", -+ "02000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001", -+ "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", -+ "0021a5c2c8ee9feb5c4b9a753b7b476b7fd6422ef1f3dd674761fa99d6ac27c8a9a197b272822f6cd57a55aa4f50ae317b13545f", -+ "015d4860d088ddb3496b0c6064756260441cde4af1771d4db01ffe5b34e59703dc255a868a1180515603aeab60794e54bb7996a7", -+ "0061b1cfab6be5f32bbfa78324ed106a7636b9c5a7bd198d0158aa4f5488d08f38514f1fdf4b4f40d2181b3681c364ba0273c706", -+ "010000000000000000000000000000000000000000000000000001e2aad6a612f33307be5fa47c3c9e052f838164cd37d9a21173", -+ 2) -+ ); -+ -+ ecCurveDefinitions.add( -+ new ECCurveDefinition( -+ "sect571k1 [NIST K-571]", -+ "1.3.132.0.38", -+ "080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425", -+ "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", -+ "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", -+ "026eb7a859923fbc82189631f8103fe4ac9ca2970012d5d46024804801841ca44370958493b205e647da304db4ceb08cbbd1ba39494776fb988b47174dca88c7e2945283a01c8972", -+ "0349dc807f4fbf374f4aeade3bca95314dd58cec9f307a54ffc61efc006d8a2c9d4979c0ac44aea74fbebbb9f772aedcb620b01a7ba7af1b320430c8591984f601cd4c143ef1c7a3", -+ "020000000000000000000000000000000000000000000000000000000000000000000000131850e1f19a63e4b391a8db917f4138b630d84be5d639381e91deb45cfe778f637c1001", -+ 4) -+ ); -+ -+ ecCurveDefinitions.add( -+ new ECCurveDefinition( -+ "sect571r1 [NIST B-571]", -+ "1.3.132.0.39", -+ "080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425", -+ "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", -+ "02f40e7e2221f295de297117b7f3d62f5c6a97ffcb8ceff1cd6ba8ce4a9a18ad84ffabbd8efa59332be7ad6756a66e294afd185a78ff12aa520e4de739baca0c7ffeff7f2955727a", -+ "0303001d34b856296c16c0d40d3cd7750a93d1d2955fa80aa5f40fc8db7b2abdbde53950f4c0d293cdd711a35b67fb1499ae60038614f1394abfa3b4c850d927e1e7769c8eec2d19", -+ "037bf27342da639b6dccfffeb73d69d78c6c27a6009cbbca1980f8533921e8a684423e43bab08a576291af8f461bb2a8b3531d2f0485c19b16e2f1516e23dd3c1a4827af1b8ac15b", -+ "03ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe661ce18ff55987308059b186823851ec7dd9ca1161de93d5174d66e8382e9bb2fe84e47", -+ 2) -+ ); -+ -+ ecCurveDefinitions.add( -+ new ECCurveDefinition( -+ "X9.62 c2tnb191v1", -+ "1.2.840.10045.3.0.5", -+ "800000000000000000000000000000000000000000000201", -+ "2866537b676752636a68f56554e12640276b649ef7526267", -+ "2e45ef571f00786f67b0081b9495a3d95462f5de0aa185ec", -+ "36b3daf8a23206f9c4f299d7b21a9c369137f2c84ae1aa0d", -+ "765be73433b3f95e332932e70ea245ca2418ea0ef98018fb", -+ "40000000000000000000000004a20e90c39067c893bbb9a5", -+ 2) -+ ); -+ -+ ecCurveDefinitions.add( -+ new ECCurveDefinition( -+ "X9.62 c2tnb191v2", -+ "1.2.840.10045.3.0.6", -+ "800000000000000000000000000000000000000000000201", -+ "401028774d7777c7b7666d1366ea432071274f89ff01e718", -+ "0620048d28bcbd03b6249c99182b7c8cd19700c362c46a01", -+ "3809b2b7cc1b28cc5a87926aad83fd28789e81e2c9e3bf10", -+ "17434386626d14f3dbf01760d9213a3e1cf37aec437d668a", -+ "20000000000000000000000050508cb89f652824e06b8173", -+ 4) -+ ); -+ -+ ecCurveDefinitions.add( -+ new ECCurveDefinition( -+ "X9.62 c2tnb191v3", -+ "1.2.840.10045.3.0.7", -+ "800000000000000000000000000000000000000000000201", -+ "6c01074756099122221056911c77d77e77a777e7e7e77fcb", -+ "71fe1af926cf847989efef8db459f66394d90f32ad3f15e8", -+ "375d4ce24fde434489de8746e71786015009e66e38a926dd", -+ "545a39176196575d985999366e6ad34ce0a77cd7127b06be", -+ "155555555555555555555555610c0b196812bfb6288a3ea3", -+ 6) -+ ); -+ -+ ecCurveDefinitions.add( -+ new ECCurveDefinition( -+ "X9.62 c2tnb239v1", -+ "1.2.840.10045.3.0.11", -+ "800000000000000000000000000000000000000000000000001000000001", -+ "32010857077c5431123a46b808906756f543423e8d27877578125778ac76", -+ "790408f2eedaf392b012edefb3392f30f4327c0ca3f31fc383c422aa8c16", -+ "57927098fa932e7c0a96d3fd5b706ef7e5f5c156e16b7e7c86038552e91d", -+ "61d8ee5077c33fecf6f1a16b268de469c3c7744ea9a971649fc7a9616305", -+ "2000000000000000000000000000000f4d42ffe1492a4993f1cad666e447", -+ 4) -+ ); -+ -+ ecCurveDefinitions.add( -+ new ECCurveDefinition( -+ "X9.62 c2tnb239v2", -+ "1.2.840.10045.3.0.12", -+ "800000000000000000000000000000000000000000000000001000000001", -+ "4230017757a767fae42398569b746325d45313af0766266479b75654e65f", -+ "5037ea654196cff0cd82b2c14a2fcf2e3ff8775285b545722f03eacdb74b", -+ "28f9d04e900069c8dc47a08534fe76d2b900b7d7ef31f5709f200c4ca205", -+ "5667334c45aff3b5a03bad9dd75e2c71a99362567d5453f7fa6e227ec833", -+ "1555555555555555555555555555553c6f2885259c31e3fcdf154624522d", -+ 6) -+ ); -+ -+ ecCurveDefinitions.add( -+ new ECCurveDefinition( -+ "X9.62 c2tnb239v3", -+ "1.2.840.10045.3.0.13", -+ "800000000000000000000000000000000000000000000000001000000001", -+ "01238774666a67766d6676f778e676b66999176666e687666d8766c66a9f", -+ "6a941977ba9f6a435199acfc51067ed587f519c5ecb541b8e44111de1d40", -+ "70f6e9d04d289c4e89913ce3530bfde903977d42b146d539bf1bde4e9c92", -+ "2e5a0eaf6e5e1305b9004dce5c0ed7fe59a35608f33837c816d80b79f461", -+ "0cccccccccccccccccccccccccccccac4912d2d9df903ef9888b8a0e4cff", -+ 0xA) -+ ); -+ -+ ecCurveDefinitions.add( -+ new ECCurveDefinition( -+ "X9.62 c2tnb359v1", -+ "1.2.840.10045.3.0.18", -+ "800000000000000000000000000000000000000000000000000000000000000000000000100000000000000001", -+ "5667676a654b20754f356ea92017d946567c46675556f19556a04616b567d223a5e05656fb549016a96656a557", -+ "2472e2d0197c49363f1fe7f5b6db075d52b6947d135d8ca445805d39bc345626089687742b6329e70680231988", -+ "3c258ef3047767e7ede0f1fdaa79daee3841366a132e163aced4ed2401df9c6bdcde98e8e707c07a2239b1b097", -+ "53d7e08529547048121e9c95f3791dd804963948f34fae7bf44ea82365dc7868fe57e4ae2de211305a407104bd", -+ "01af286bca1af286bca1af286bca1af286bca1af286bc9fb8f6b85c556892c20a7eb964fe7719e74f490758d3b", -+ 0x4C) -+ ); -+ -+ ecCurveDefinitions.add( -+ new ECCurveDefinition( -+ "X9.62 c2tnb431r1", -+ "1.2.840.10045.3.0.20", -+ "800000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000001", -+ "1a827ef00dd6fc0e234caf046c6a5d8a85395b236cc4ad2cf32a0cadbdc9ddf620b0eb9906d0957f6c6feacd615468df104de296cd8f", -+ "10d9b4a3d9047d8b154359abfb1b7f5485b04ceb868237ddc9deda982a679a5a919b626d4e50a8dd731b107a9962381fb5d807bf2618", -+ "120fc05d3c67a99de161d2f4092622feca701be4f50f4758714e8a87bbf2a658ef8c21e7c5efe965361f6c2999c0c247b0dbd70ce6b7", -+ "20d0af8903a96f8d5fa2c255745d3c451b302c9346d9b7e485e7bce41f6b591f3e8f6addcbb0bc4c2f947a7de1a89b625d6a598b3760", -+ "0340340340340340340340340340340340340340340340340340340323c313fab50589703b5ec68d3587fec60d161cc149c1ad4a91", -+ 0x2760) -+ ); - } - - public static String getOIDFromPublicKey(ECPublicKey ecPublicKey) { -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.crypto.ec/share/native/libsunec/impl/ec2_163.c jdk11u-ls/src/jdk.crypto.ec/share/native/libsunec/impl/ec2_163.c ---- openjdk/src/jdk.crypto.ec/share/native/libsunec/impl/ec2_163.c 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/jdk.crypto.ec/share/native/libsunec/impl/ec2_163.c 2023-09-12 13:54:26.289575680 +0800 -@@ -0,0 +1,260 @@ +diff --git a/src/hotspot/share/utilities/vmassert_uninstall.hpp b/src/hotspot/share/utilities/vmassert_uninstall.hpp +new file mode 100644 +index 000000000..dd6d51633 +--- /dev/null ++++ b/src/hotspot/share/utilities/vmassert_uninstall.hpp +@@ -0,0 +1,45 @@ +/* -+ * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. -+ * Use is subject to license terms. ++ * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. ++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. ++ * 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 library 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 -+ * Lesser General Public License for more details. ++ * 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 Lesser General Public License -+ * along with this library; if not, write to the Free Software Foundation, -+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ * 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. -+ */ -+ -+/* ********************************************************************* -+ * -+ * The Original Code is the elliptic curve math library for binary polynomial field curves. + * -+ * The Initial Developer of the Original Code is -+ * Sun Microsystems, Inc. -+ * Portions created by the Initial Developer are Copyright (C) 2003 -+ * the Initial Developer. All Rights Reserved. -+ * -+ * Contributor(s): -+ * Sheueling Chang-Shantz , -+ * Stephen Fung , and -+ * Douglas Stebila , Sun Microsystems Laboratories. -+ * -+ *********************************************************************** */ -+ -+#include "ec2.h" -+#include "mp_gf2m.h" -+#include "mp_gf2m-priv.h" -+#include "mpi.h" -+#include "mpi-priv.h" -+#ifndef _KERNEL -+#include -+#endif ++ */ + -+/* Fast reduction for polynomials over a 163-bit curve. Assumes reduction -+ * polynomial with terms {163, 7, 6, 3, 0}. */ -+mp_err -+ec_GF2m_163_mod(const mp_int *a, mp_int *r, const GFMethod *meth) -+{ -+ mp_err res = MP_OKAY; -+ mp_digit *u, z; ++// Intentionally no #include guard. May be included multiple times for effect. + -+ if (a != r) { -+ MP_CHECKOK(mp_copy(a, r)); -+ } -+#ifdef ECL_SIXTY_FOUR_BIT -+ if (MP_USED(r) < 6) { -+ MP_CHECKOK(s_mp_pad(r, 6)); ++// The files vmassert_uninstall.hpp and vmassert_reinstall.hpp provide a ++// workaround for the name collision between HotSpot's assert macro and the ++// Standard Library's assert macro. When including a 3rd-party header that ++// uses (and so includes) the standard assert macro, wrap that inclusion with ++// includes of these two files, e.g. ++// ++// #include "utilities/vmassert_uninstall.hpp" ++// #include
++// #include "utilities/vmassert_reinstall.hpp" ++// ++// This removes the HotSpot macro definition while pre-processing the ++// 3rd-party header, then reinstates the HotSpot macro (if previously defined) ++// for following code. ++ ++// Remove HotSpot's assert macro, if present. ++#ifdef vmassert ++#undef assert ++#endif // vmassert ++ +diff --git a/src/java.base/share/classes/com/sun/crypto/provider/RSACipher.java b/src/java.base/share/classes/com/sun/crypto/provider/RSACipher.java +index c6de64e97..d7dece47f 100644 +--- a/src/java.base/share/classes/com/sun/crypto/provider/RSACipher.java ++++ b/src/java.base/share/classes/com/sun/crypto/provider/RSACipher.java +@@ -384,7 +384,7 @@ public final class RSACipher extends CipherSpi { + byte[] decryptBuffer = RSACore.convert(buffer, 0, bufOfs); + paddingCopy = RSACore.rsa(decryptBuffer, privateKey, false); + result = padding.unpad(paddingCopy); +- if (result == null && !forTlsPremasterSecret) { ++ if (!forTlsPremasterSecret && result == null) { + throw new BadPaddingException + ("Padding error in decryption"); + } +@@ -404,6 +404,34 @@ public final class RSACipher extends CipherSpi { + } + } + ++ // TLS master secret decode version of the doFinal() method. ++ private byte[] doFinalForTls(int clientVersion, int serverVersion) ++ throws BadPaddingException, IllegalBlockSizeException { ++ if (bufOfs > buffer.length) { ++ throw new IllegalBlockSizeException("Data must not be longer " ++ + "than " + buffer.length + " bytes"); + } -+ u = MP_DIGITS(r); -+ MP_USED(r) = 6; -+ -+ /* u[5] only has 6 significant bits */ -+ z = u[5]; -+ u[2] ^= (z << 36) ^ (z << 35) ^ (z << 32) ^ (z << 29); -+ z = u[4]; -+ u[2] ^= (z >> 28) ^ (z >> 29) ^ (z >> 32) ^ (z >> 35); -+ u[1] ^= (z << 36) ^ (z << 35) ^ (z << 32) ^ (z << 29); -+ z = u[3]; -+ u[1] ^= (z >> 28) ^ (z >> 29) ^ (z >> 32) ^ (z >> 35); -+ u[0] ^= (z << 36) ^ (z << 35) ^ (z << 32) ^ (z << 29); -+ z = u[2] >> 35; /* z only has 29 significant bits */ -+ u[0] ^= (z << 7) ^ (z << 6) ^ (z << 3) ^ z; -+ /* clear bits above 163 */ -+ u[5] = u[4] = u[3] = 0; -+ u[2] ^= z << 35; -+#else -+ if (MP_USED(r) < 11) { -+ MP_CHECKOK(s_mp_pad(r, 11)); ++ byte[] paddingCopy = null; ++ byte[] result = null; ++ try { ++ byte[] decryptBuffer = RSACore.convert(buffer, 0, bufOfs); ++ ++ paddingCopy = RSACore.rsa(decryptBuffer, privateKey, false); ++ result = padding.unpadForTls(paddingCopy, clientVersion, ++ serverVersion); ++ ++ return result; ++ } finally { ++ Arrays.fill(buffer, 0, bufOfs, (byte)0); ++ bufOfs = 0; ++ if (paddingCopy != null ++ && paddingCopy != buffer // already cleaned ++ && paddingCopy != result) { // DO NOT CLEAN, THIS IS RESULT ++ Arrays.fill(paddingCopy, (byte)0); ++ } + } -+ u = MP_DIGITS(r); -+ MP_USED(r) = 11; -+ -+ /* u[11] only has 6 significant bits */ -+ z = u[10]; -+ u[5] ^= (z << 4) ^ (z << 3) ^ z ^ (z >> 3); -+ u[4] ^= (z << 29); -+ z = u[9]; -+ u[5] ^= (z >> 28) ^ (z >> 29); -+ u[4] ^= (z << 4) ^ (z << 3) ^ z ^ (z >> 3); -+ u[3] ^= (z << 29); -+ z = u[8]; -+ u[4] ^= (z >> 28) ^ (z >> 29); -+ u[3] ^= (z << 4) ^ (z << 3) ^ z ^ (z >> 3); -+ u[2] ^= (z << 29); -+ z = u[7]; -+ u[3] ^= (z >> 28) ^ (z >> 29); -+ u[2] ^= (z << 4) ^ (z << 3) ^ z ^ (z >> 3); -+ u[1] ^= (z << 29); -+ z = u[6]; -+ u[2] ^= (z >> 28) ^ (z >> 29); -+ u[1] ^= (z << 4) ^ (z << 3) ^ z ^ (z >> 3); -+ u[0] ^= (z << 29); -+ z = u[5] >> 3; /* z only has 29 significant bits */ -+ u[1] ^= (z >> 25) ^ (z >> 26); -+ u[0] ^= (z << 7) ^ (z << 6) ^ (z << 3) ^ z; -+ /* clear bits above 163 */ -+ u[11] = u[10] = u[9] = u[8] = u[7] = u[6] = 0; -+ u[5] ^= z << 3; -+#endif -+ s_mp_clamp(r); -+ -+ CLEANUP: -+ return res; -+} -+ -+/* Fast squaring for polynomials over a 163-bit curve. Assumes reduction -+ * polynomial with terms {163, 7, 6, 3, 0}. */ -+mp_err -+ec_GF2m_163_sqr(const mp_int *a, mp_int *r, const GFMethod *meth) -+{ -+ mp_err res = MP_OKAY; -+ mp_digit *u, *v; -+ -+ v = MP_DIGITS(a); ++ } + -+#ifdef ECL_SIXTY_FOUR_BIT -+ if (MP_USED(a) < 3) { -+ return mp_bsqrmod(a, meth->irr_arr, r); -+ } -+ if (MP_USED(r) < 6) { -+ MP_CHECKOK(s_mp_pad(r, 6)); -+ } -+ MP_USED(r) = 6; -+#else -+ if (MP_USED(a) < 6) { -+ return mp_bsqrmod(a, meth->irr_arr, r); -+ } -+ if (MP_USED(r) < 12) { -+ MP_CHECKOK(s_mp_pad(r, 12)); -+ } -+ MP_USED(r) = 12; -+#endif -+ u = MP_DIGITS(r); -+ -+#ifdef ECL_THIRTY_TWO_BIT -+ u[11] = gf2m_SQR1(v[5]); -+ u[10] = gf2m_SQR0(v[5]); -+ u[9] = gf2m_SQR1(v[4]); -+ u[8] = gf2m_SQR0(v[4]); -+ u[7] = gf2m_SQR1(v[3]); -+ u[6] = gf2m_SQR0(v[3]); -+#endif -+ u[5] = gf2m_SQR1(v[2]); -+ u[4] = gf2m_SQR0(v[2]); -+ u[3] = gf2m_SQR1(v[1]); -+ u[2] = gf2m_SQR0(v[1]); -+ u[1] = gf2m_SQR1(v[0]); -+ u[0] = gf2m_SQR0(v[0]); -+ return ec_GF2m_163_mod(r, r, meth); -+ -+ CLEANUP: -+ return res; -+} + // see JCE spec + protected byte[] engineUpdate(byte[] in, int inOfs, int inLen) { + update(in, inOfs, inLen); +@@ -476,38 +504,34 @@ public final class RSACipher extends CipherSpi { + byte[] encoded = null; + + update(wrappedKey, 0, wrappedKey.length); +- try { +- encoded = doFinal(); +- } catch (BadPaddingException | IllegalBlockSizeException e) { +- // BadPaddingException cannot happen for TLS RSA unwrap. +- // In that case, padding error is indicated by returning null. +- // IllegalBlockSizeException cannot happen in any case, +- // because of the length check above. +- throw new InvalidKeyException("Unwrapping failed", e); +- } +- + try { + if (isTlsRsaPremasterSecret) { + if (!forTlsPremasterSecret) { + throw new IllegalStateException( + "No TlsRsaPremasterSecretParameterSpec specified"); + } +- +- // polish the TLS premaster secret +- encoded = KeyUtil.checkTlsPreMasterSecretKey( +- ((TlsRsaPremasterSecretParameterSpec) spec).getClientVersion(), +- ((TlsRsaPremasterSecretParameterSpec) spec).getServerVersion(), +- random, encoded, encoded == null); ++ TlsRsaPremasterSecretParameterSpec parameterSpec = ++ (TlsRsaPremasterSecretParameterSpec) spec; ++ encoded = doFinalForTls(parameterSpec.getClientVersion(), ++ parameterSpec.getServerVersion()); ++ } else { ++ encoded = doFinal(); + } +- + return ConstructKeys.constructKey(encoded, algorithm, type); ++ ++ } catch (BadPaddingException | IllegalBlockSizeException e) { ++ // BadPaddingException cannot happen for TLS RSA unwrap. ++ // Neither padding error nor server version error is indicated ++ // for TLS, but a fake unwrapped value is returned. ++ // IllegalBlockSizeException cannot happen in any case, ++ // because of the length check above. ++ throw new InvalidKeyException("Unwrapping failed", e); + } finally { + if (encoded != null) { + Arrays.fill(encoded, (byte) 0); + } + } + } +- + // see JCE spec + protected int engineGetKeySize(Key key) throws InvalidKeyException { + RSAKey rsaKey = RSAKeyFactory.toRSAKey(key); +diff --git a/src/java.base/share/classes/java/util/jar/JarFile.java b/src/java.base/share/classes/java/util/jar/JarFile.java +index cce897c0d..6d5172777 100644 +--- a/src/java.base/share/classes/java/util/jar/JarFile.java ++++ b/src/java.base/share/classes/java/util/jar/JarFile.java +@@ -424,7 +424,8 @@ class JarFile extends ZipFile { + jv = new JarVerifier(manEntry.getName(), b); + } else { + if (JarVerifier.debug != null) { +- JarVerifier.debug.println("Multiple MANIFEST.MF found. Treat JAR file as unsigned"); ++ JarVerifier.debug.println( ++ JarVerifier.MULTIPLE_MANIFEST_WARNING); + } + } + } +diff --git a/src/java.base/share/classes/java/util/jar/JarInputStream.java b/src/java.base/share/classes/java/util/jar/JarInputStream.java +index e55704a37..c4e2fed46 100644 +--- a/src/java.base/share/classes/java/util/jar/JarInputStream.java ++++ b/src/java.base/share/classes/java/util/jar/JarInputStream.java +@@ -98,7 +98,17 @@ class JarInputStream extends ZipInputStream { + jv = new JarVerifier(e.getName(), bytes); + mev = new ManifestEntryVerifier(man, jv.manifestName); + } +- return (JarEntry)super.getNextEntry(); ++ JarEntry nextEntry = (JarEntry)super.getNextEntry(); ++ if (nextEntry != null && ++ JarFile.MANIFEST_NAME.equalsIgnoreCase(nextEntry.getName())) { ++ if (JarVerifier.debug != null) { ++ JarVerifier.debug.println(JarVerifier.MULTIPLE_MANIFEST_WARNING); ++ } + -+/* Fast multiplication for polynomials over a 163-bit curve. Assumes -+ * reduction polynomial with terms {163, 7, 6, 3, 0}. */ -+mp_err -+ec_GF2m_163_mul(const mp_int *a, const mp_int *b, mp_int *r, -+ const GFMethod *meth) -+{ -+ mp_err res = MP_OKAY; -+ mp_digit a2 = 0, a1 = 0, a0, b2 = 0, b1 = 0, b0; ++ jv = null; ++ mev = null; ++ } ++ return nextEntry; + } + return e; + } +diff --git a/src/java.base/share/classes/java/util/jar/JarVerifier.java b/src/java.base/share/classes/java/util/jar/JarVerifier.java +index 666558fee..6f97f182e 100644 +--- a/src/java.base/share/classes/java/util/jar/JarVerifier.java ++++ b/src/java.base/share/classes/java/util/jar/JarVerifier.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -44,6 +44,9 @@ import sun.security.util.Debug; + */ + class JarVerifier { + ++ public static final String MULTIPLE_MANIFEST_WARNING = ++ "WARNING: Multiple MANIFEST.MF found. Treat JAR file as unsigned."; + -+#ifdef ECL_THIRTY_TWO_BIT -+ mp_digit a5 = 0, a4 = 0, a3 = 0, b5 = 0, b4 = 0, b3 = 0; -+ mp_digit rm[6]; -+#endif + /* Are we debugging ? */ + static final Debug debug = Debug.getInstance("jar"); + +diff --git a/src/java.base/share/classes/java/util/zip/DeflaterOutputStream.java b/src/java.base/share/classes/java/util/zip/DeflaterOutputStream.java +index fab0a4d66..ee9a6c208 100644 +--- a/src/java.base/share/classes/java/util/zip/DeflaterOutputStream.java ++++ b/src/java.base/share/classes/java/util/zip/DeflaterOutputStream.java +@@ -41,6 +41,26 @@ import java.io.IOException; + */ + public + class DeflaterOutputStream extends FilterOutputStream { + -+ if (a == b) { -+ return ec_GF2m_163_sqr(a, r, meth); -+ } else { -+ switch (MP_USED(a)) { -+#ifdef ECL_THIRTY_TWO_BIT -+ case 6: -+ a5 = MP_DIGIT(a, 5); -+ case 5: -+ a4 = MP_DIGIT(a, 4); -+ case 4: -+ a3 = MP_DIGIT(a, 3); -+#endif -+ case 3: -+ a2 = MP_DIGIT(a, 2); -+ case 2: -+ a1 = MP_DIGIT(a, 1); -+ default: -+ a0 = MP_DIGIT(a, 0); -+ } -+ switch (MP_USED(b)) { -+#ifdef ECL_THIRTY_TWO_BIT -+ case 6: -+ b5 = MP_DIGIT(b, 5); -+ case 5: -+ b4 = MP_DIGIT(b, 4); -+ case 4: -+ b3 = MP_DIGIT(b, 3); -+#endif -+ case 3: -+ b2 = MP_DIGIT(b, 2); -+ case 2: -+ b1 = MP_DIGIT(b, 1); -+ default: -+ b0 = MP_DIGIT(b, 0); -+ } -+#ifdef ECL_SIXTY_FOUR_BIT -+ MP_CHECKOK(s_mp_pad(r, 6)); -+ s_bmul_3x3(MP_DIGITS(r), a2, a1, a0, b2, b1, b0); -+ MP_USED(r) = 6; -+ s_mp_clamp(r); -+#else -+ MP_CHECKOK(s_mp_pad(r, 12)); -+ s_bmul_3x3(MP_DIGITS(r) + 6, a5, a4, a3, b5, b4, b3); -+ s_bmul_3x3(MP_DIGITS(r), a2, a1, a0, b2, b1, b0); -+ s_bmul_3x3(rm, a5 ^ a2, a4 ^ a1, a3 ^ a0, b5 ^ b2, b4 ^ b1, -+ b3 ^ b0); -+ rm[5] ^= MP_DIGIT(r, 5) ^ MP_DIGIT(r, 11); -+ rm[4] ^= MP_DIGIT(r, 4) ^ MP_DIGIT(r, 10); -+ rm[3] ^= MP_DIGIT(r, 3) ^ MP_DIGIT(r, 9); -+ rm[2] ^= MP_DIGIT(r, 2) ^ MP_DIGIT(r, 8); -+ rm[1] ^= MP_DIGIT(r, 1) ^ MP_DIGIT(r, 7); -+ rm[0] ^= MP_DIGIT(r, 0) ^ MP_DIGIT(r, 6); -+ MP_DIGIT(r, 8) ^= rm[5]; -+ MP_DIGIT(r, 7) ^= rm[4]; -+ MP_DIGIT(r, 6) ^= rm[3]; -+ MP_DIGIT(r, 5) ^= rm[2]; -+ MP_DIGIT(r, 4) ^= rm[1]; -+ MP_DIGIT(r, 3) ^= rm[0]; -+ MP_USED(r) = 12; -+ s_mp_clamp(r); -+#endif -+ return ec_GF2m_163_mod(r, r, meth); -+ } ++ /* ++ * The default size of the output buffer ++ */ ++ static final int DEFAULT_BUF_SIZE = 512; + -+ CLEANUP: -+ return res; -+} ++ /* ++ * When calling Deflater.deflate() with Deflater.SYNC_FLUSH or Deflater.FULL_FLUSH, ++ * the callers are expected to ensure that the size of the buffer is greater than 6. ++ * This expectation comes from the underlying zlib library which in its zlib.h ++ * states: ++ * "If deflate returns with avail_out == 0, this function must be called again ++ * with the same value of the flush parameter and more output space (updated ++ * avail_out), until the flush is complete (deflate returns with non-zero ++ * avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that ++ * avail_out is greater than six when the flush marker begins, in order to avoid ++ * repeated flush markers upon calling deflate() again when avail_out == 0." ++ */ ++ private static final int SYNC_FLUSH_MIN_BUF_SIZE = 7; + -+/* Wire in fast field arithmetic for 163-bit curves. */ -+mp_err -+ec_group_set_gf2m163(ECGroup *group, ECCurveName name) -+{ -+ group->meth->field_mod = &ec_GF2m_163_mod; -+ group->meth->field_mul = &ec_GF2m_163_mul; -+ group->meth->field_sqr = &ec_GF2m_163_sqr; -+ return MP_OKAY; -+} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.crypto.ec/share/native/libsunec/impl/ec2_193.c jdk11u-ls/src/jdk.crypto.ec/share/native/libsunec/impl/ec2_193.c ---- openjdk/src/jdk.crypto.ec/share/native/libsunec/impl/ec2_193.c 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/jdk.crypto.ec/share/native/libsunec/impl/ec2_193.c 2023-09-12 13:54:26.289575680 +0800 -@@ -0,0 +1,277 @@ + /** + * Compressor for this stream. + */ +@@ -124,7 +144,7 @@ class DeflaterOutputStream extends FilterOutputStream { + public DeflaterOutputStream(OutputStream out, + Deflater def, + boolean syncFlush) { +- this(out, def, 512, syncFlush); ++ this(out, def, DEFAULT_BUF_SIZE, syncFlush); + } + + +@@ -139,7 +159,7 @@ class DeflaterOutputStream extends FilterOutputStream { + * @param def the compressor ("deflater") + */ + public DeflaterOutputStream(OutputStream out, Deflater def) { +- this(out, def, 512, false); ++ this(out, def, DEFAULT_BUF_SIZE, false); + } + + boolean usesDefaultDeflater = false; +@@ -159,7 +179,7 @@ class DeflaterOutputStream extends FilterOutputStream { + * @since 1.7 + */ + public DeflaterOutputStream(OutputStream out, boolean syncFlush) { +- this(out, new Deflater(), 512, syncFlush); ++ this(out, new Deflater(), DEFAULT_BUF_SIZE, syncFlush); + usesDefaultDeflater = true; + } + +@@ -182,6 +202,7 @@ class DeflaterOutputStream extends FilterOutputStream { + * @param b the byte to be written + * @exception IOException if an I/O error has occurred + */ ++ @Override + public void write(int b) throws IOException { + byte[] buf = new byte[1]; + buf[0] = (byte)(b & 0xff); +@@ -196,6 +217,7 @@ class DeflaterOutputStream extends FilterOutputStream { + * @param len the length of the data + * @exception IOException if an I/O error has occurred + */ ++ @Override + public void write(byte[] b, int off, int len) throws IOException { + if (def.finished()) { + throw new IOException("write beyond end of stream"); +@@ -239,6 +261,7 @@ class DeflaterOutputStream extends FilterOutputStream { + * underlying stream. + * @exception IOException if an I/O error has occurred + */ ++ @Override + public void close() throws IOException { + if (!closed) { + try { +@@ -278,13 +301,20 @@ class DeflaterOutputStream extends FilterOutputStream { + * + * @since 1.7 + */ ++ @Override + public void flush() throws IOException { + if (syncFlush && !def.finished()) { + int len = 0; +- while ((len = def.deflate(buf, 0, buf.length, Deflater.SYNC_FLUSH)) > 0) +- { +- out.write(buf, 0, len); +- if (len < buf.length) ++ // For SYNC_FLUSH, the Deflater.deflate() expects the callers ++ // to use a buffer whose length is greater than 6 to avoid ++ // flush marker (5 bytes) being repeatedly output to the output buffer ++ // every time it is invoked. ++ final byte[] flushBuf = buf.length < SYNC_FLUSH_MIN_BUF_SIZE ++ ? new byte[DEFAULT_BUF_SIZE] ++ : buf; ++ while ((len = def.deflate(flushBuf, 0, flushBuf.length, Deflater.SYNC_FLUSH)) > 0) { ++ out.write(flushBuf, 0, len); ++ if (len < flushBuf.length) + break; + } + } +diff --git a/src/java.base/share/classes/java/util/zip/GZIPOutputStream.java b/src/java.base/share/classes/java/util/zip/GZIPOutputStream.java +index 3ddf50a4c..d1a34daad 100644 +--- a/src/java.base/share/classes/java/util/zip/GZIPOutputStream.java ++++ b/src/java.base/share/classes/java/util/zip/GZIPOutputStream.java +@@ -107,7 +107,7 @@ class GZIPOutputStream extends DeflaterOutputStream { + * @exception IOException If an I/O error has occurred. + */ + public GZIPOutputStream(OutputStream out) throws IOException { +- this(out, 512, false); ++ this(out, DeflaterOutputStream.DEFAULT_BUF_SIZE, false); + } + + /** +@@ -129,7 +129,7 @@ class GZIPOutputStream extends DeflaterOutputStream { + public GZIPOutputStream(OutputStream out, boolean syncFlush) + throws IOException + { +- this(out, 512, syncFlush); ++ this(out, DeflaterOutputStream.DEFAULT_BUF_SIZE, syncFlush); + } + + /** +diff --git a/src/java.base/share/classes/sun/net/ftp/impl/FtpClient.java b/src/java.base/share/classes/sun/net/ftp/impl/FtpClient.java +index 5262541c1..021cbd567 100644 +--- a/src/java.base/share/classes/sun/net/ftp/impl/FtpClient.java ++++ b/src/java.base/share/classes/sun/net/ftp/impl/FtpClient.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2009, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -24,7 +24,6 @@ + */ + package sun.net.ftp.impl; + +- + import java.io.BufferedInputStream; + import java.io.BufferedOutputStream; + import java.io.BufferedReader; +@@ -62,6 +61,7 @@ import java.util.regex.Matcher; + import java.util.regex.Pattern; + import javax.net.ssl.SSLSocket; + import javax.net.ssl.SSLSocketFactory; ++ + import sun.net.ftp.FtpDirEntry; + import sun.net.ftp.FtpDirParser; + import sun.net.ftp.FtpProtocolException; +@@ -69,6 +69,7 @@ import sun.net.ftp.FtpReplyCode; + import sun.net.util.IPAddressUtil; + import sun.util.logging.PlatformLogger; + ++import static sun.net.util.ProxyUtil.copyProxy; + + public class FtpClient extends sun.net.ftp.FtpClient { + +@@ -996,7 +997,7 @@ public class FtpClient extends sun.net.ftp.FtpClient { + } + + public sun.net.ftp.FtpClient setProxy(Proxy p) { +- proxy = p; ++ proxy = copyProxy(p); + return this; + } + +diff --git a/src/java.base/share/classes/sun/net/util/ProxyUtil.java b/src/java.base/share/classes/sun/net/util/ProxyUtil.java +new file mode 100644 +index 000000000..dfb60671e +--- /dev/null ++++ b/src/java.base/share/classes/sun/net/util/ProxyUtil.java +@@ -0,0 +1,49 @@ +/* -+ * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. -+ * Use is subject to license terms. ++ * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. ++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. ++ * 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 library 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 -+ * Lesser General Public License for more details. ++ * 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 Lesser General Public License -+ * along with this library; if not, write to the Free Software Foundation, -+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ * 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. + */ + -+/* ********************************************************************* -+ * -+ * The Original Code is the elliptic curve math library for binary polynomial field curves. -+ * -+ * The Initial Developer of the Original Code is -+ * Sun Microsystems, Inc. -+ * Portions created by the Initial Developer are Copyright (C) 2003 -+ * the Initial Developer. All Rights Reserved. -+ * -+ * Contributor(s): -+ * Sheueling Chang-Shantz , -+ * Stephen Fung , and -+ * Douglas Stebila , Sun Microsystems Laboratories. -+ * -+ *********************************************************************** */ ++package sun.net.util; + -+#include "ec2.h" -+#include "mp_gf2m.h" -+#include "mp_gf2m-priv.h" -+#include "mpi.h" -+#include "mpi-priv.h" -+#ifndef _KERNEL -+#include -+#endif ++import sun.net.ApplicationProxy; + -+/* Fast reduction for polynomials over a 193-bit curve. Assumes reduction -+ * polynomial with terms {193, 15, 0}. */ -+mp_err -+ec_GF2m_193_mod(const mp_int *a, mp_int *r, const GFMethod *meth) -+{ -+ mp_err res = MP_OKAY; -+ mp_digit *u, z; ++import java.net.Proxy; + -+ if (a != r) { -+ MP_CHECKOK(mp_copy(a, r)); -+ } -+#ifdef ECL_SIXTY_FOUR_BIT -+ if (MP_USED(r) < 7) { -+ MP_CHECKOK(s_mp_pad(r, 7)); -+ } -+ u = MP_DIGITS(r); -+ MP_USED(r) = 7; -+ -+ /* u[6] only has 2 significant bits */ -+ z = u[6]; -+ u[3] ^= (z << 14) ^ (z >> 1); -+ u[2] ^= (z << 63); -+ z = u[5]; -+ u[3] ^= (z >> 50); -+ u[2] ^= (z << 14) ^ (z >> 1); -+ u[1] ^= (z << 63); -+ z = u[4]; -+ u[2] ^= (z >> 50); -+ u[1] ^= (z << 14) ^ (z >> 1); -+ u[0] ^= (z << 63); -+ z = u[3] >> 1; /* z only has 63 significant bits */ -+ u[1] ^= (z >> 49); -+ u[0] ^= (z << 15) ^ z; -+ /* clear bits above 193 */ -+ u[6] = u[5] = u[4] = 0; -+ u[3] ^= z << 1; -+#else -+ if (MP_USED(r) < 13) { -+ MP_CHECKOK(s_mp_pad(r, 13)); -+ } -+ u = MP_DIGITS(r); -+ MP_USED(r) = 13; -+ -+ /* u[12] only has 2 significant bits */ -+ z = u[12]; -+ u[6] ^= (z << 14) ^ (z >> 1); -+ u[5] ^= (z << 31); -+ z = u[11]; -+ u[6] ^= (z >> 18); -+ u[5] ^= (z << 14) ^ (z >> 1); -+ u[4] ^= (z << 31); -+ z = u[10]; -+ u[5] ^= (z >> 18); -+ u[4] ^= (z << 14) ^ (z >> 1); -+ u[3] ^= (z << 31); -+ z = u[9]; -+ u[4] ^= (z >> 18); -+ u[3] ^= (z << 14) ^ (z >> 1); -+ u[2] ^= (z << 31); -+ z = u[8]; -+ u[3] ^= (z >> 18); -+ u[2] ^= (z << 14) ^ (z >> 1); -+ u[1] ^= (z << 31); -+ z = u[7]; -+ u[2] ^= (z >> 18); -+ u[1] ^= (z << 14) ^ (z >> 1); -+ u[0] ^= (z << 31); -+ z = u[6] >> 1; /* z only has 31 significant bits */ -+ u[1] ^= (z >> 17); -+ u[0] ^= (z << 15) ^ z; -+ /* clear bits above 193 */ -+ u[12] = u[11] = u[10] = u[9] = u[8] = u[7] = 0; -+ u[6] ^= z << 1; -+#endif -+ s_mp_clamp(r); -+ -+ CLEANUP: -+ return res; -+} ++public final class ProxyUtil { + -+/* Fast squaring for polynomials over a 193-bit curve. Assumes reduction -+ * polynomial with terms {193, 15, 0}. */ -+mp_err -+ec_GF2m_193_sqr(const mp_int *a, mp_int *r, const GFMethod *meth) -+{ -+ mp_err res = MP_OKAY; -+ mp_digit *u, *v; ++ private ProxyUtil() {} + -+ v = MP_DIGITS(a); ++ /** ++ * Creates a new {@link Proxy} instance for the given proxy iff it is ++ * neither null, {@link Proxy#NO_PROXY Proxy.NO_PROXY}, an ++ * {@link ApplicationProxy} instance, nor already a {@code Proxy} instance. ++ */ ++ public static Proxy copyProxy(Proxy proxy) { ++ return proxy == null ++ || proxy.getClass() == Proxy.class ++ || proxy instanceof ApplicationProxy ++ ? proxy ++ : new Proxy(proxy.type(), proxy.address()); ++ } + -+#ifdef ECL_SIXTY_FOUR_BIT -+ if (MP_USED(a) < 4) { -+ return mp_bsqrmod(a, meth->irr_arr, r); -+ } -+ if (MP_USED(r) < 7) { -+ MP_CHECKOK(s_mp_pad(r, 7)); ++} +diff --git a/src/java.base/share/classes/sun/net/www/http/HttpClient.java b/src/java.base/share/classes/sun/net/www/http/HttpClient.java +index 3d0deb319..e10955276 100644 +--- a/src/java.base/share/classes/sun/net/www/http/HttpClient.java ++++ b/src/java.base/share/classes/sun/net/www/http/HttpClient.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 1994, 2019, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 1994, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -40,6 +40,8 @@ import sun.net.www.ParseUtil; + import sun.net.www.protocol.http.AuthenticatorKeys; + import sun.net.www.protocol.http.HttpURLConnection; + import sun.util.logging.PlatformLogger; ++ ++import static sun.net.util.ProxyUtil.copyProxy; + import static sun.net.www.protocol.http.HttpURLConnection.TunnelState.*; + import sun.security.action.GetPropertyAction; + +@@ -264,7 +266,7 @@ public class HttpClient extends NetworkClient { + } + + protected HttpClient(URL url, Proxy p, int to) throws IOException { +- proxy = (p == null) ? Proxy.NO_PROXY : p; ++ proxy = p == null ? Proxy.NO_PROXY : copyProxy(p); + this.host = url.getHost(); + this.url = url; + port = url.getPort(); +@@ -329,9 +331,7 @@ public class HttpClient extends NetworkClient { + public static HttpClient New(URL url, Proxy p, int to, boolean useCache, + HttpURLConnection httpuc) throws IOException + { +- if (p == null) { +- p = Proxy.NO_PROXY; +- } ++ p = p == null ? Proxy.NO_PROXY : copyProxy(p); + HttpClient ret = null; + /* see if one's already around */ + if (useCache) { +diff --git a/src/java.base/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java b/src/java.base/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java +index fccf99b33..6f77b4e95 100644 +--- a/src/java.base/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java ++++ b/src/java.base/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 1994, 2019, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 1994, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -48,6 +48,7 @@ import java.util.StringTokenizer; + import java.util.Iterator; + import java.security.Permission; + import java.util.Properties; ++ + import sun.net.NetworkClient; + import sun.net.util.IPAddressUtil; + import sun.net.www.MessageHeader; +@@ -61,6 +62,7 @@ import sun.net.ProgressMonitor; + import sun.net.www.ParseUtil; + import sun.security.action.GetPropertyAction; + ++import static sun.net.util.ProxyUtil.copyProxy; + + /** + * This class Opens an FTP input (or output) stream given a URL. +@@ -244,7 +246,7 @@ public class FtpURLConnection extends URLConnection { + URI uri = sun.net.www.ParseUtil.toURI(url); + Iterator it = sel.select(uri).iterator(); + while (it.hasNext()) { +- p = it.next(); ++ p = copyProxy(it.next()); + if (p == null || p == Proxy.NO_PROXY || + p.type() == Proxy.Type.SOCKS) { + break; +diff --git a/src/java.base/share/classes/sun/net/www/protocol/ftp/Handler.java b/src/java.base/share/classes/sun/net/www/protocol/ftp/Handler.java +index f5caad651..41f4344aa 100644 +--- a/src/java.base/share/classes/sun/net/www/protocol/ftp/Handler.java ++++ b/src/java.base/share/classes/sun/net/www/protocol/ftp/Handler.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 1994, 2003, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 1994, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -32,10 +32,7 @@ package sun.net.www.protocol.ftp; + import java.io.IOException; + import java.net.URL; + import java.net.Proxy; +-import java.util.Map; +-import java.util.HashMap; +-import sun.net.ftp.FtpClient; +-import sun.net.www.protocol.http.HttpURLConnection; ++import static sun.net.util.ProxyUtil.copyProxy; + + /** open an ftp connection given a URL */ + public class Handler extends java.net.URLStreamHandler { +@@ -56,8 +53,8 @@ public class Handler extends java.net.URLStreamHandler { + return openConnection(u, null); + } + +- protected java.net.URLConnection openConnection(URL u, Proxy p) ++ protected java.net.URLConnection openConnection(URL u, Proxy proxy) + throws IOException { +- return new FtpURLConnection(u, p); ++ return new FtpURLConnection(u, copyProxy(proxy)); + } + } +diff --git a/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java b/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java +index 8840d0c5e..f4eb1092f 100644 +--- a/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java ++++ b/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 1995, 2022, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 1995, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -81,6 +81,8 @@ import java.net.MalformedURLException; + import java.nio.ByteBuffer; + import java.util.Objects; + import java.util.Properties; ++ ++import static sun.net.util.ProxyUtil.copyProxy; + import static sun.net.www.protocol.http.AuthScheme.BASIC; + import static sun.net.www.protocol.http.AuthScheme.DIGEST; + import static sun.net.www.protocol.http.AuthScheme.NTLM; +@@ -300,7 +302,8 @@ public class HttpURLConnection extends java.net.HttpURLConnection { + } + + static final String httpVersion = "HTTP/1.1"; +- static final String acceptString = "*/*"; ++ static final String acceptString = ++ "text/html, image/gif, image/jpeg, */*; q=0.2"; + + // the following http request headers should NOT have their values + // returned for security reasons. +@@ -897,7 +900,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection { + responses = new MessageHeader(maxHeaderSize); + userHeaders = new MessageHeader(); + this.handler = handler; +- instProxy = p; ++ instProxy = copyProxy(p); + if (instProxy instanceof sun.net.ApplicationProxy) { + /* Application set Proxies should not have access to cookies + * in a secure environment unless explicitly allowed. */ +@@ -1195,7 +1198,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection { + Iterator it = sel.select(uri).iterator(); + Proxy p; + while (it.hasNext()) { +- p = it.next(); ++ p = copyProxy(it.next()); + try { + if (!failedOnce) { + http = getNewHttpClient(url, p, connectTimeout); +diff --git a/src/java.base/share/classes/sun/security/rsa/RSAPadding.java b/src/java.base/share/classes/sun/security/rsa/RSAPadding.java +index 0cd1c8a7a..07599632e 100644 +--- a/src/java.base/share/classes/sun/security/rsa/RSAPadding.java ++++ b/src/java.base/share/classes/sun/security/rsa/RSAPadding.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2003, 2024, 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 +@@ -327,48 +327,103 @@ public final class RSAPadding { + * Note that we want to make it a constant-time operation + */ + private byte[] unpadV15(byte[] padded) { +- int k = 0; +- boolean bp = false; ++ int paddedLength = padded.length; + +- if (padded[k++] != 0) { +- bp = true; +- } +- if (padded[k++] != type) { +- bp = true; ++ if (paddedLength < 2) { ++ return null; + } +- int p = 0; +- while (k < padded.length) { ++ ++ // The following check ensures that the lead byte is zero and ++ // the second byte is equivalent to the padding type. The ++ // bp (bad padding) variable throughout this unpadding process will ++ // be updated and remain 0 if good padding, 1 if bad. ++ int p0 = padded[0]; ++ int p1 = padded[1]; ++ int bp = (-(p0 & 0xff) | ((p1 - type) | (type - p1))) >>> 31; ++ ++ int padLen = 0; ++ int k = 2; ++ // Walk through the random, nonzero padding bytes. For each padding ++ // byte bp and padLen will remain zero. When the end-of-padding ++ // byte (0x00) is reached then padLen will be set to the index of the ++ // first byte of the message content. ++ while (k < paddedLength) { + int b = padded[k++] & 0xff; +- if ((b == 0) && (p == 0)) { +- p = k; +- } +- if ((k == padded.length) && (p == 0)) { +- bp = true; +- } +- if ((type == PAD_BLOCKTYPE_1) && (b != 0xff) && +- (p == 0)) { +- bp = true; ++ padLen += (k * (1 - ((-(b | padLen)) >>> 31))); ++ if (k == paddedLength) { ++ bp = bp | (1 - ((-padLen) >>> 31)); + } ++ bp = bp | (1 - (-(((type - PAD_BLOCKTYPE_1) & 0xff) | ++ padLen | (1 - ((b - 0xff) >>> 31))) >>> 31)); + } +- int n = padded.length - p; +- if (n > maxDataSize) { +- bp = true; +- } ++ int n = paddedLength - padLen; ++ // So long as n <= maxDataSize, bp will remain zero ++ bp = bp | ((maxDataSize - n) >>> 31); + + // copy useless padding array for a constant-time method +- byte[] padding = new byte[p]; +- System.arraycopy(padded, 0, padding, 0, p); ++ byte[] padding = new byte[padLen + 2]; ++ for (int i = 0; i < padLen; i++) { ++ padding[i] = padded[i]; + } -+ MP_USED(r) = 7; -+#else -+ if (MP_USED(a) < 7) { -+ return mp_bsqrmod(a, meth->irr_arr, r); + + byte[] data = new byte[n]; +- System.arraycopy(padded, p, data, 0, n); ++ for (int i = 0; i < n; i++) { ++ data[i] = padded[padLen + i]; + } -+ if (MP_USED(r) < 13) { -+ MP_CHECKOK(s_mp_pad(r, 13)); + +- if (bp) { ++ if ((bp | padding[bp]) != 0) { ++ // using the array padding here hoping that this way ++ // the compiler does not eliminate the above useless copy + return null; + } else { + return data; + } + } + ++ public byte[] unpadForTls(byte[] padded, int clientVersion, ++ int serverVersion) { ++ int paddedLength = padded.length; ++ ++ // bp is positive if the padding is bad and 0 if it is good so far ++ int bp = (((int) padded[0] | ((int)padded[1] - PAD_BLOCKTYPE_2)) & ++ 0xFFF); ++ ++ int k = 2; ++ while (k < paddedLength - 49) { ++ int b = padded[k++] & 0xFF; ++ bp = bp | (1 - (-b >>> 31)); // if (padded[k] == 0) bp |= 1; + } -+ MP_USED(r) = 13; -+#endif -+ u = MP_DIGITS(r); -+ -+#ifdef ECL_THIRTY_TWO_BIT -+ u[12] = gf2m_SQR0(v[6]); -+ u[11] = gf2m_SQR1(v[5]); -+ u[10] = gf2m_SQR0(v[5]); -+ u[9] = gf2m_SQR1(v[4]); -+ u[8] = gf2m_SQR0(v[4]); -+ u[7] = gf2m_SQR1(v[3]); -+#endif -+ u[6] = gf2m_SQR0(v[3]); -+ u[5] = gf2m_SQR1(v[2]); -+ u[4] = gf2m_SQR0(v[2]); -+ u[3] = gf2m_SQR1(v[1]); -+ u[2] = gf2m_SQR0(v[1]); -+ u[1] = gf2m_SQR1(v[0]); -+ u[0] = gf2m_SQR0(v[0]); -+ return ec_GF2m_193_mod(r, r, meth); -+ -+ CLEANUP: -+ return res; -+} ++ bp |= ((int)padded[k++] & 0xFF); ++ int encodedVersion = ((padded[k] & 0xFF) << 8) | (padded[k + 1] & 0xFF); + -+/* Fast multiplication for polynomials over a 193-bit curve. Assumes -+ * reduction polynomial with terms {193, 15, 0}. */ -+mp_err -+ec_GF2m_193_mul(const mp_int *a, const mp_int *b, mp_int *r, -+ const GFMethod *meth) -+{ -+ mp_err res = MP_OKAY; -+ mp_digit a3 = 0, a2 = 0, a1 = 0, a0, b3 = 0, b2 = 0, b1 = 0, b0; ++ int bv1 = clientVersion - encodedVersion; ++ bv1 |= -bv1; ++ int bv3 = serverVersion - encodedVersion; ++ bv3 |= -bv3; ++ int bv2 = (0x301 - clientVersion); + -+#ifdef ECL_THIRTY_TWO_BIT -+ mp_digit a6 = 0, a5 = 0, a4 = 0, b6 = 0, b5 = 0, b4 = 0; -+ mp_digit rm[8]; -+#endif ++ bp |= ((bv1 & (bv2 | bv3)) >>> 28); + -+ if (a == b) { -+ return ec_GF2m_193_sqr(a, r, meth); -+ } else { -+ switch (MP_USED(a)) { -+#ifdef ECL_THIRTY_TWO_BIT -+ case 7: -+ a6 = MP_DIGIT(a, 6); -+ case 6: -+ a5 = MP_DIGIT(a, 5); -+ case 5: -+ a4 = MP_DIGIT(a, 4); -+#endif -+ case 4: -+ a3 = MP_DIGIT(a, 3); -+ case 3: -+ a2 = MP_DIGIT(a, 2); -+ case 2: -+ a1 = MP_DIGIT(a, 1); -+ default: -+ a0 = MP_DIGIT(a, 0); -+ } -+ switch (MP_USED(b)) { -+#ifdef ECL_THIRTY_TWO_BIT -+ case 7: -+ b6 = MP_DIGIT(b, 6); -+ case 6: -+ b5 = MP_DIGIT(b, 5); -+ case 5: -+ b4 = MP_DIGIT(b, 4); -+#endif -+ case 4: -+ b3 = MP_DIGIT(b, 3); -+ case 3: -+ b2 = MP_DIGIT(b, 2); -+ case 2: -+ b1 = MP_DIGIT(b, 1); -+ default: -+ b0 = MP_DIGIT(b, 0); -+ } -+#ifdef ECL_SIXTY_FOUR_BIT -+ MP_CHECKOK(s_mp_pad(r, 8)); -+ s_bmul_4x4(MP_DIGITS(r), a3, a2, a1, a0, b3, b2, b1, b0); -+ MP_USED(r) = 8; -+ s_mp_clamp(r); -+#else -+ MP_CHECKOK(s_mp_pad(r, 14)); -+ s_bmul_3x3(MP_DIGITS(r) + 8, a6, a5, a4, b6, b5, b4); -+ s_bmul_4x4(MP_DIGITS(r), a3, a2, a1, a0, b3, b2, b1, b0); -+ s_bmul_4x4(rm, a3, a6 ^ a2, a5 ^ a1, a4 ^ a0, b3, b6 ^ b2, b5 ^ b1, -+ b4 ^ b0); -+ rm[7] ^= MP_DIGIT(r, 7); -+ rm[6] ^= MP_DIGIT(r, 6); -+ rm[5] ^= MP_DIGIT(r, 5) ^ MP_DIGIT(r, 13); -+ rm[4] ^= MP_DIGIT(r, 4) ^ MP_DIGIT(r, 12); -+ rm[3] ^= MP_DIGIT(r, 3) ^ MP_DIGIT(r, 11); -+ rm[2] ^= MP_DIGIT(r, 2) ^ MP_DIGIT(r, 10); -+ rm[1] ^= MP_DIGIT(r, 1) ^ MP_DIGIT(r, 9); -+ rm[0] ^= MP_DIGIT(r, 0) ^ MP_DIGIT(r, 8); -+ MP_DIGIT(r, 11) ^= rm[7]; -+ MP_DIGIT(r, 10) ^= rm[6]; -+ MP_DIGIT(r, 9) ^= rm[5]; -+ MP_DIGIT(r, 8) ^= rm[4]; -+ MP_DIGIT(r, 7) ^= rm[3]; -+ MP_DIGIT(r, 6) ^= rm[2]; -+ MP_DIGIT(r, 5) ^= rm[1]; -+ MP_DIGIT(r, 4) ^= rm[0]; -+ MP_USED(r) = 14; -+ s_mp_clamp(r); -+#endif -+ return ec_GF2m_193_mod(r, r, meth); ++ byte[] data = Arrays.copyOfRange(padded, paddedLength - 48, ++ paddedLength); ++ if (random == null) { ++ random = JCAUtil.getSecureRandom(); + } + -+ CLEANUP: -+ return res; -+} ++ byte[] fake = new byte[48]; ++ random.nextBytes(fake); + -+/* Wire in fast field arithmetic for 193-bit curves. */ -+mp_err -+ec_group_set_gf2m193(ECGroup *group, ECCurveName name) -+{ -+ group->meth->field_mod = &ec_GF2m_193_mod; -+ group->meth->field_mul = &ec_GF2m_193_mul; -+ group->meth->field_sqr = &ec_GF2m_193_sqr; -+ return MP_OKAY; -+} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.crypto.ec/share/native/libsunec/impl/ec2_233.c jdk11u-ls/src/jdk.crypto.ec/share/native/libsunec/impl/ec2_233.c ---- openjdk/src/jdk.crypto.ec/share/native/libsunec/impl/ec2_233.c 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/jdk.crypto.ec/share/native/libsunec/impl/ec2_233.c 2023-09-12 13:54:26.289575680 +0800 -@@ -0,0 +1,300 @@ -+/* -+ * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. -+ * Use is subject to license terms. -+ * -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. -+ * -+ * This library 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 -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public License -+ * along with this library; if not, write to the Free Software Foundation, -+ * Inc., 51 Franklin Street, 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. -+ */ ++ bp = (-bp >> 24); + -+/* ********************************************************************* -+ * -+ * The Original Code is the elliptic curve math library for binary polynomial field curves. -+ * -+ * The Initial Developer of the Original Code is -+ * Sun Microsystems, Inc. -+ * Portions created by the Initial Developer are Copyright (C) 2003 -+ * the Initial Developer. All Rights Reserved. -+ * -+ * Contributor(s): -+ * Sheueling Chang-Shantz , -+ * Stephen Fung , and -+ * Douglas Stebila , Sun Microsystems Laboratories. -+ * -+ *********************************************************************** */ ++ // Now bp is 0 if the padding and version number were good and ++ // -1 otherwise. ++ for (int i = 0; i < 48; i++) { ++ data[i] = (byte)((~bp & data[i]) | (bp & fake[i])); ++ } + -+#include "ec2.h" -+#include "mp_gf2m.h" -+#include "mp_gf2m-priv.h" -+#include "mpi.h" -+#include "mpi-priv.h" -+#ifndef _KERNEL -+#include -+#endif ++ return data; ++ } + -+/* Fast reduction for polynomials over a 233-bit curve. Assumes reduction -+ * polynomial with terms {233, 74, 0}. */ -+mp_err -+ec_GF2m_233_mod(const mp_int *a, mp_int *r, const GFMethod *meth) -+{ -+ mp_err res = MP_OKAY; -+ mp_digit *u, z; + /** + * PKCS#1 v2.0 OAEP padding (MGF1). + * Paragraph references refer to PKCS#1 v2.1 (June 14, 2002) +diff --git a/src/java.base/share/classes/sun/security/ssl/CertificateMessage.java b/src/java.base/share/classes/sun/security/ssl/CertificateMessage.java +index 4d19043ac..49f6a095c 100644 +--- a/src/java.base/share/classes/sun/security/ssl/CertificateMessage.java ++++ b/src/java.base/share/classes/sun/security/ssl/CertificateMessage.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -1166,6 +1166,15 @@ final class CertificateMessage { + + // clean up this consumer + hc.handshakeConsumers.remove(SSLHandshake.CERTIFICATE.id); ++ ++ // Ensure that the Certificate message has not been sent w/o ++ // an EncryptedExtensions preceding ++ if (hc.handshakeConsumers.containsKey( ++ SSLHandshake.ENCRYPTED_EXTENSIONS.id)) { ++ throw hc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, ++ "Unexpected Certificate handshake message"); ++ } + -+ if (a != r) { -+ MP_CHECKOK(mp_copy(a, r)); -+ } -+#ifdef ECL_SIXTY_FOUR_BIT -+ if (MP_USED(r) < 8) { -+ MP_CHECKOK(s_mp_pad(r, 8)); -+ } -+ u = MP_DIGITS(r); -+ MP_USED(r) = 8; -+ -+ /* u[7] only has 18 significant bits */ -+ z = u[7]; -+ u[4] ^= (z << 33) ^ (z >> 41); -+ u[3] ^= (z << 23); -+ z = u[6]; -+ u[4] ^= (z >> 31); -+ u[3] ^= (z << 33) ^ (z >> 41); -+ u[2] ^= (z << 23); -+ z = u[5]; -+ u[3] ^= (z >> 31); -+ u[2] ^= (z << 33) ^ (z >> 41); -+ u[1] ^= (z << 23); -+ z = u[4]; -+ u[2] ^= (z >> 31); -+ u[1] ^= (z << 33) ^ (z >> 41); -+ u[0] ^= (z << 23); -+ z = u[3] >> 41; /* z only has 23 significant bits */ -+ u[1] ^= (z << 10); -+ u[0] ^= z; -+ /* clear bits above 233 */ -+ u[7] = u[6] = u[5] = u[4] = 0; -+ u[3] ^= z << 41; -+#else -+ if (MP_USED(r) < 15) { -+ MP_CHECKOK(s_mp_pad(r, 15)); -+ } -+ u = MP_DIGITS(r); -+ MP_USED(r) = 15; -+ -+ /* u[14] only has 18 significant bits */ -+ z = u[14]; -+ u[9] ^= (z << 1); -+ u[7] ^= (z >> 9); -+ u[6] ^= (z << 23); -+ z = u[13]; -+ u[9] ^= (z >> 31); -+ u[8] ^= (z << 1); -+ u[6] ^= (z >> 9); -+ u[5] ^= (z << 23); -+ z = u[12]; -+ u[8] ^= (z >> 31); -+ u[7] ^= (z << 1); -+ u[5] ^= (z >> 9); -+ u[4] ^= (z << 23); -+ z = u[11]; -+ u[7] ^= (z >> 31); -+ u[6] ^= (z << 1); -+ u[4] ^= (z >> 9); -+ u[3] ^= (z << 23); -+ z = u[10]; -+ u[6] ^= (z >> 31); -+ u[5] ^= (z << 1); -+ u[3] ^= (z >> 9); -+ u[2] ^= (z << 23); -+ z = u[9]; -+ u[5] ^= (z >> 31); -+ u[4] ^= (z << 1); -+ u[2] ^= (z >> 9); -+ u[1] ^= (z << 23); -+ z = u[8]; -+ u[4] ^= (z >> 31); -+ u[3] ^= (z << 1); -+ u[1] ^= (z >> 9); -+ u[0] ^= (z << 23); -+ z = u[7] >> 9; /* z only has 23 significant bits */ -+ u[3] ^= (z >> 22); -+ u[2] ^= (z << 10); -+ u[0] ^= z; -+ /* clear bits above 233 */ -+ u[14] = u[13] = u[12] = u[11] = u[10] = u[9] = u[8] = 0; -+ u[7] ^= z << 9; -+#endif -+ s_mp_clamp(r); -+ -+ CLEANUP: -+ return res; -+} + T13CertificateMessage cm = new T13CertificateMessage(hc, message); + if (hc.sslConfig.isClientMode) { + if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { +diff --git a/src/java.base/share/classes/sun/security/ssl/CertificateVerify.java b/src/java.base/share/classes/sun/security/ssl/CertificateVerify.java +index 4e6e613d3..e708c0e51 100644 +--- a/src/java.base/share/classes/sun/security/ssl/CertificateVerify.java ++++ b/src/java.base/share/classes/sun/security/ssl/CertificateVerify.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -1157,6 +1157,14 @@ final class CertificateVerify { + // Clean up this consumer + hc.handshakeConsumers.remove(SSLHandshake.CERTIFICATE_VERIFY.id); + ++ // Ensure that the Certificate Verify message has not been sent w/o ++ // a Certificate message preceding ++ if (hc.handshakeConsumers.containsKey( ++ SSLHandshake.CERTIFICATE.id)) { ++ throw hc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, ++ "Unexpected Certificate Verify handshake message"); ++ } + -+/* Fast squaring for polynomials over a 233-bit curve. Assumes reduction -+ * polynomial with terms {233, 74, 0}. */ -+mp_err -+ec_GF2m_233_sqr(const mp_int *a, mp_int *r, const GFMethod *meth) -+{ -+ mp_err res = MP_OKAY; -+ mp_digit *u, *v; + T13CertificateVerifyMessage cvm = + new T13CertificateVerifyMessage(hc, message); + if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { +diff --git a/src/java.base/share/classes/sun/security/ssl/Finished.java b/src/java.base/share/classes/sun/security/ssl/Finished.java +index 626fbd5c1..58dc461cc 100644 +--- a/src/java.base/share/classes/sun/security/ssl/Finished.java ++++ b/src/java.base/share/classes/sun/security/ssl/Finished.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -881,6 +881,14 @@ final class Finished { + + private void onConsumeFinished(ClientHandshakeContext chc, + ByteBuffer message) throws IOException { ++ // Ensure that the Finished message has not been sent w/o ++ // an EncryptedExtensions preceding ++ if (chc.handshakeConsumers.containsKey( ++ SSLHandshake.ENCRYPTED_EXTENSIONS.id)) { ++ throw chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, ++ "Unexpected Finished handshake message"); ++ } + -+ v = MP_DIGITS(a); + // Make sure that any expected CertificateVerify message + // has been received and processed. + if (!chc.isResumption) { +diff --git a/src/java.base/share/classes/sun/security/util/DerValue.java b/src/java.base/share/classes/sun/security/util/DerValue.java +index 64dcf2c97..a3a95e857 100644 +--- a/src/java.base/share/classes/sun/security/util/DerValue.java ++++ b/src/java.base/share/classes/sun/security/util/DerValue.java +@@ -821,6 +821,22 @@ public class DerValue { + doEquals(other, this); + } + ++ /** ++ * Checks that the BMPString does not contain any surrogate characters, ++ * which are outside the Basic Multilingual Plane. ++ * ++ * @throws IOException if illegal characters are detected ++ */ ++ public void validateBMPString() throws IOException { ++ String bmpString = getBMPString(); ++ for (int i = 0; i < bmpString.length(); i++) { ++ if (Character.isSurrogate(bmpString.charAt(i))) { ++ throw new IOException( ++ "Illegal character in BMPString, index: " + i); ++ } ++ } ++ } + -+#ifdef ECL_SIXTY_FOUR_BIT -+ if (MP_USED(a) < 4) { -+ return mp_bsqrmod(a, meth->irr_arr, r); -+ } -+ if (MP_USED(r) < 8) { -+ MP_CHECKOK(s_mp_pad(r, 8)); -+ } -+ MP_USED(r) = 8; -+#else -+ if (MP_USED(a) < 8) { -+ return mp_bsqrmod(a, meth->irr_arr, r); -+ } -+ if (MP_USED(r) < 15) { -+ MP_CHECKOK(s_mp_pad(r, 15)); -+ } -+ MP_USED(r) = 15; -+#endif -+ u = MP_DIGITS(r); -+ -+#ifdef ECL_THIRTY_TWO_BIT -+ u[14] = gf2m_SQR0(v[7]); -+ u[13] = gf2m_SQR1(v[6]); -+ u[12] = gf2m_SQR0(v[6]); -+ u[11] = gf2m_SQR1(v[5]); -+ u[10] = gf2m_SQR0(v[5]); -+ u[9] = gf2m_SQR1(v[4]); -+ u[8] = gf2m_SQR0(v[4]); -+#endif -+ u[7] = gf2m_SQR1(v[3]); -+ u[6] = gf2m_SQR0(v[3]); -+ u[5] = gf2m_SQR1(v[2]); -+ u[4] = gf2m_SQR0(v[2]); -+ u[3] = gf2m_SQR1(v[1]); -+ u[2] = gf2m_SQR0(v[1]); -+ u[1] = gf2m_SQR1(v[0]); -+ u[0] = gf2m_SQR0(v[0]); -+ return ec_GF2m_233_mod(r, r, meth); -+ -+ CLEANUP: -+ return res; -+} + /** + * Helper for public method equals() + */ +diff --git a/src/java.base/share/classes/sun/security/util/KeyUtil.java b/src/java.base/share/classes/sun/security/util/KeyUtil.java +index 781d3344b..2f05f0c83 100644 +--- a/src/java.base/share/classes/sun/security/util/KeyUtil.java ++++ b/src/java.base/share/classes/sun/security/util/KeyUtil.java +@@ -288,19 +288,31 @@ public final class KeyUtil { + tmp = encoded; + } + ++ // At this point tmp.length is 48 + int encodedVersion = + ((tmp[0] & 0xFF) << 8) | (tmp[1] & 0xFF); +- int check1 = 0; +- int check2 = 0; +- int check3 = 0; +- if (clientVersion != encodedVersion) check1 = 1; +- if (clientVersion > 0x0301) check2 = 1; +- if (serverVersion != encodedVersion) check3 = 1; +- if ((check1 & (check2 | check3)) == 1) { +- return replacer; +- } else { +- return tmp; ++ ++ // The following code is a time-constant version of ++ // if ((clientVersion != encodedVersion) || ++ // ((clientVersion > 0x301) && (serverVersion != encodedVersion))) { ++ // return replacer; ++ // } else { return tmp; } ++ int check1 = (clientVersion - encodedVersion) | ++ (encodedVersion - clientVersion); ++ int check2 = 0x0301 - clientVersion; ++ int check3 = (serverVersion - encodedVersion) | ++ (encodedVersion - serverVersion); ++ ++ check1 = (check1 & (check2 | check3)) >> 24; ++ ++ // Now check1 is either 0 or -1 ++ check2 = ~check1; ++ ++ for (int i = 0; i < 48; i++) { ++ tmp[i] = (byte) ((tmp[i] & check2) | (replacer[i] & check1)); + } + -+/* Fast multiplication for polynomials over a 233-bit curve. Assumes -+ * reduction polynomial with terms {233, 74, 0}. */ -+mp_err -+ec_GF2m_233_mul(const mp_int *a, const mp_int *b, mp_int *r, -+ const GFMethod *meth) -+{ -+ mp_err res = MP_OKAY; -+ mp_digit a3 = 0, a2 = 0, a1 = 0, a0, b3 = 0, b2 = 0, b1 = 0, b0; ++ return tmp; + } + + /** +diff --git a/src/java.base/share/classes/sun/security/util/SignatureFileVerifier.java b/src/java.base/share/classes/sun/security/util/SignatureFileVerifier.java +index a766b8249..d829f9e01 100644 +--- a/src/java.base/share/classes/sun/security/util/SignatureFileVerifier.java ++++ b/src/java.base/share/classes/sun/security/util/SignatureFileVerifier.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -501,6 +501,8 @@ public class SignatureFileVerifier { + boolean attrsVerified = true; + // If only weak algorithms are used. + boolean weakAlgs = true; ++ // If only unsupported algorithms are used. ++ boolean unsupportedAlgs = true; + // If a ATTR_DIGEST entry is found. + boolean validEntry = false; + +@@ -525,6 +527,7 @@ public class SignatureFileVerifier { + + MessageDigest digest = getDigest(algorithm); + if (digest != null) { ++ unsupportedAlgs = false; + ManifestDigester.Entry mde = md.getMainAttsEntry(false); + if (mde == null) { + throw new SignatureException("Manifest Main Attribute check " + +@@ -567,12 +570,22 @@ public class SignatureFileVerifier { + } + } + +- // If there were only weak algorithms entries used, throw an exception. +- if (validEntry && weakAlgs) { +- throw new SignatureException("Manifest Main Attribute check " + +- "failed (" + ATTR_DIGEST + "). " + +- "Disabled algorithm(s) used: " + +- getWeakAlgorithms(ATTR_DIGEST)); ++ if (validEntry) { ++ // If there were only weak algorithms entries used, throw an exception. ++ if (weakAlgs) { ++ throw new SignatureException( ++ "Manifest Main Attribute check " ++ + "failed (" + ATTR_DIGEST + "). " ++ + "Disabled algorithm(s) used: " ++ + getWeakAlgorithms(ATTR_DIGEST)); ++ } + -+#ifdef ECL_THIRTY_TWO_BIT -+ mp_digit a7 = 0, a6 = 0, a5 = 0, a4 = 0, b7 = 0, b6 = 0, b5 = 0, b4 = -+ 0; -+ mp_digit rm[8]; -+#endif ++ // If there were only unsupported algorithms entries used, throw an exception. ++ if (unsupportedAlgs) { ++ throw new SignatureException( ++ "Manifest Main Attribute check failed (" ++ + ATTR_DIGEST + "). Unsupported algorithm(s) used"); ++ } + } + + // this method returns 'true' if either: +diff --git a/src/java.base/share/classes/sun/security/validator/CADistrustPolicy.java b/src/java.base/share/classes/sun/security/validator/CADistrustPolicy.java +index 39aecc27e..36837c60e 100644 +--- a/src/java.base/share/classes/sun/security/validator/CADistrustPolicy.java ++++ b/src/java.base/share/classes/sun/security/validator/CADistrustPolicy.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -69,6 +69,22 @@ enum CADistrustPolicy { + } + EntrustTLSPolicy.checkDistrust(chain); + } ++ }, + -+ if (a == b) { -+ return ec_GF2m_233_sqr(a, r, meth); -+ } else { -+ switch (MP_USED(a)) { -+#ifdef ECL_THIRTY_TWO_BIT -+ case 8: -+ a7 = MP_DIGIT(a, 7); -+ case 7: -+ a6 = MP_DIGIT(a, 6); -+ case 6: -+ a5 = MP_DIGIT(a, 5); -+ case 5: -+ a4 = MP_DIGIT(a, 4); -+#endif -+ case 4: -+ a3 = MP_DIGIT(a, 3); -+ case 3: -+ a2 = MP_DIGIT(a, 2); -+ case 2: -+ a1 = MP_DIGIT(a, 1); -+ default: -+ a0 = MP_DIGIT(a, 0); -+ } -+ switch (MP_USED(b)) { -+#ifdef ECL_THIRTY_TWO_BIT -+ case 8: -+ b7 = MP_DIGIT(b, 7); -+ case 7: -+ b6 = MP_DIGIT(b, 6); -+ case 6: -+ b5 = MP_DIGIT(b, 5); -+ case 5: -+ b4 = MP_DIGIT(b, 4); -+#endif -+ case 4: -+ b3 = MP_DIGIT(b, 3); -+ case 3: -+ b2 = MP_DIGIT(b, 2); -+ case 2: -+ b1 = MP_DIGIT(b, 1); -+ default: -+ b0 = MP_DIGIT(b, 0); -+ } -+#ifdef ECL_SIXTY_FOUR_BIT -+ MP_CHECKOK(s_mp_pad(r, 8)); -+ s_bmul_4x4(MP_DIGITS(r), a3, a2, a1, a0, b3, b2, b1, b0); -+ MP_USED(r) = 8; -+ s_mp_clamp(r); -+#else -+ MP_CHECKOK(s_mp_pad(r, 16)); -+ s_bmul_4x4(MP_DIGITS(r) + 8, a7, a6, a5, a4, b7, b6, b5, b4); -+ s_bmul_4x4(MP_DIGITS(r), a3, a2, a1, a0, b3, b2, b1, b0); -+ s_bmul_4x4(rm, a7 ^ a3, a6 ^ a2, a5 ^ a1, a4 ^ a0, b7 ^ b3, -+ b6 ^ b2, b5 ^ b1, b4 ^ b0); -+ rm[7] ^= MP_DIGIT(r, 7) ^ MP_DIGIT(r, 15); -+ rm[6] ^= MP_DIGIT(r, 6) ^ MP_DIGIT(r, 14); -+ rm[5] ^= MP_DIGIT(r, 5) ^ MP_DIGIT(r, 13); -+ rm[4] ^= MP_DIGIT(r, 4) ^ MP_DIGIT(r, 12); -+ rm[3] ^= MP_DIGIT(r, 3) ^ MP_DIGIT(r, 11); -+ rm[2] ^= MP_DIGIT(r, 2) ^ MP_DIGIT(r, 10); -+ rm[1] ^= MP_DIGIT(r, 1) ^ MP_DIGIT(r, 9); -+ rm[0] ^= MP_DIGIT(r, 0) ^ MP_DIGIT(r, 8); -+ MP_DIGIT(r, 11) ^= rm[7]; -+ MP_DIGIT(r, 10) ^= rm[6]; -+ MP_DIGIT(r, 9) ^= rm[5]; -+ MP_DIGIT(r, 8) ^= rm[4]; -+ MP_DIGIT(r, 7) ^= rm[3]; -+ MP_DIGIT(r, 6) ^= rm[2]; -+ MP_DIGIT(r, 5) ^= rm[1]; -+ MP_DIGIT(r, 4) ^= rm[0]; -+ MP_USED(r) = 16; -+ s_mp_clamp(r); -+#endif -+ return ec_GF2m_233_mod(r, r, meth); ++ /** ++ * Distrust TLS Server certificates anchored by a CAMERFIRMA root CA and ++ * issued after April 15, 2025. If enabled, this policy is currently ++ * enforced by the PKIX and SunX509 TrustManager implementations ++ * of the SunJSSE provider implementation. ++ */ ++ CAMERFIRMA_TLS { ++ void checkDistrust(String variant, X509Certificate[] chain) ++ throws ValidatorException { ++ if (!variant.equals(Validator.VAR_TLS_SERVER)) { ++ return; ++ } ++ CamerfirmaTLSPolicy.checkDistrust(chain); + } -+ -+ CLEANUP: -+ return res; -+} -+ -+/* Wire in fast field arithmetic for 233-bit curves. */ -+mp_err -+ec_group_set_gf2m233(ECGroup *group, ECCurveName name) -+{ -+ group->meth->field_mod = &ec_GF2m_233_mod; -+ group->meth->field_mul = &ec_GF2m_233_mul; -+ group->meth->field_sqr = &ec_GF2m_233_sqr; -+ return MP_OKAY; -+} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.crypto.ec/share/native/libsunec/impl/ec2_aff.c jdk11u-ls/src/jdk.crypto.ec/share/native/libsunec/impl/ec2_aff.c ---- openjdk/src/jdk.crypto.ec/share/native/libsunec/impl/ec2_aff.c 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/jdk.crypto.ec/share/native/libsunec/impl/ec2_aff.c 2023-09-12 13:54:26.289575680 +0800 -@@ -0,0 +1,349 @@ + }; + + /** +diff --git a/src/java.base/share/classes/sun/security/validator/CamerfirmaTLSPolicy.java b/src/java.base/share/classes/sun/security/validator/CamerfirmaTLSPolicy.java +new file mode 100644 +index 000000000..1d2f88f50 +--- /dev/null ++++ b/src/java.base/share/classes/sun/security/validator/CamerfirmaTLSPolicy.java +@@ -0,0 +1,102 @@ +/* -+ * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved. -+ * Use is subject to license terms. ++ * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. ++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. ++ * 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 library 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 -+ * Lesser General Public License for more details. ++ * 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 Lesser General Public License -+ * along with this library; if not, write to the Free Software Foundation, -+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ * You should have received a copy of the GNU General Public License version ++ * 2 along with this work; if not, write to the Free Software Foundation, ++ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ ++package sun.security.validator; + -+/* ********************************************************************* -+ * -+ * The Original Code is the elliptic curve math library for binary polynomial field curves. -+ * -+ * The Initial Developer of the Original Code is -+ * Sun Microsystems, Inc. -+ * Portions created by the Initial Developer are Copyright (C) 2003 -+ * the Initial Developer. All Rights Reserved. -+ * -+ * Contributor(s): -+ * Douglas Stebila , Sun Microsystems Laboratories -+ * -+ * Last Modified Date from the Original Code: May 2017 -+ *********************************************************************** */ ++import java.security.cert.X509Certificate; ++import java.time.LocalDate; ++import java.time.Month; ++import java.time.ZoneOffset; ++import java.util.Date; ++import java.util.Map; ++import java.util.Set; + -+#include "ec2.h" -+#include "mplogic.h" -+#include "mp_gf2m.h" -+#ifndef _KERNEL -+#include -+#endif ++import sun.security.util.Debug; ++import sun.security.x509.X509CertImpl; + -+/* Checks if point P(px, py) is at infinity. Uses affine coordinates. */ -+mp_err -+ec_GF2m_pt_is_inf_aff(const mp_int *px, const mp_int *py) -+{ ++/** ++ * This class checks if Camerfirma issued TLS Server certificates should be ++ * restricted. ++ */ ++final class CamerfirmaTLSPolicy { + -+ if ((mp_cmp_z(px) == 0) && (mp_cmp_z(py) == 0)) { -+ return MP_YES; -+ } else { -+ return MP_NO; -+ } ++ private static final Debug debug = Debug.getInstance("certpath"); + -+} ++ // SHA-256 certificate fingerprint of distrusted root for TLS ++ // cacerts alias: camerfirmachambersca ++ // DN: CN=Chambers of Commerce Root - 2008, ++ // O=AC Camerfirma S.A., SERIALNUMBER=A82743287, ++ // L=Madrid (see current address at www.camerfirma.com/address), ++ // C=EU ++ private static final String FINGERPRINT = ++ "063E4AFAC491DFD332F3089B8542E94617D893D7FE944E10A7937EE29D9693C0"; + -+/* Sets P(px, py) to be the point at infinity. Uses affine coordinates. */ -+mp_err -+ec_GF2m_pt_set_inf_aff(mp_int *px, mp_int *py) -+{ -+ mp_zero(px); -+ mp_zero(py); -+ return MP_OKAY; -+} ++ // Any TLS Server certificate that is anchored by one of the Camerfirma ++ // roots above and is issued after this date will be distrusted. ++ private static final LocalDate APRIL_15_2025 = ++ LocalDate.of(2025, Month.APRIL, 15); + -+/* Computes R = P + Q based on IEEE P1363 A.10.2. Elliptic curve points P, -+ * Q, and R can all be identical. Uses affine coordinates. */ -+mp_err -+ec_GF2m_pt_add_aff(const mp_int *px, const mp_int *py, const mp_int *qx, -+ const mp_int *qy, mp_int *rx, mp_int *ry, -+ const ECGroup *group) -+{ -+ mp_err res = MP_OKAY; -+ mp_int lambda, tempx, tempy; -+ -+ MP_DIGITS(&lambda) = 0; -+ MP_DIGITS(&tempx) = 0; -+ MP_DIGITS(&tempy) = 0; -+ MP_CHECKOK(mp_init(&lambda, FLAG(px))); -+ MP_CHECKOK(mp_init(&tempx, FLAG(px))); -+ MP_CHECKOK(mp_init(&tempy, FLAG(px))); -+ /* if P = inf, then R = Q */ -+ if (ec_GF2m_pt_is_inf_aff(px, py) == 0) { -+ MP_CHECKOK(mp_copy(qx, rx)); -+ MP_CHECKOK(mp_copy(qy, ry)); -+ res = MP_OKAY; -+ goto CLEANUP; -+ } -+ /* if Q = inf, then R = P */ -+ if (ec_GF2m_pt_is_inf_aff(qx, qy) == 0) { -+ MP_CHECKOK(mp_copy(px, rx)); -+ MP_CHECKOK(mp_copy(py, ry)); -+ res = MP_OKAY; -+ goto CLEANUP; ++ /** ++ * This method assumes the eeCert is a TLS Server Cert and chains back to ++ * the anchor. ++ * ++ * @param chain the end-entity's certificate chain. The end entity cert ++ * is at index 0, the trust anchor at index n-1. ++ * @throws ValidatorException if the certificate is distrusted ++ */ ++ static void checkDistrust(X509Certificate[] chain) ++ throws ValidatorException { ++ X509Certificate anchor = chain[chain.length-1]; ++ String fp = fingerprint(anchor); ++ if (fp == null) { ++ throw new ValidatorException("Cannot generate fingerprint for " ++ + "trust anchor of TLS server certificate"); + } -+ /* if px != qx, then lambda = (py+qy) / (px+qx), tempx = a + lambda^2 -+ * + lambda + px + qx */ -+ if (mp_cmp(px, qx) != 0) { -+ MP_CHECKOK(group->meth->field_add(py, qy, &tempy, group->meth)); -+ MP_CHECKOK(group->meth->field_add(px, qx, &tempx, group->meth)); -+ MP_CHECKOK(group->meth-> -+ field_div(&tempy, &tempx, &lambda, group->meth)); -+ MP_CHECKOK(group->meth->field_sqr(&lambda, &tempx, group->meth)); -+ MP_CHECKOK(group->meth-> -+ field_add(&tempx, &lambda, &tempx, group->meth)); -+ MP_CHECKOK(group->meth-> -+ field_add(&tempx, &group->curvea, &tempx, group->meth)); -+ MP_CHECKOK(group->meth-> -+ field_add(&tempx, px, &tempx, group->meth)); -+ MP_CHECKOK(group->meth-> -+ field_add(&tempx, qx, &tempx, group->meth)); -+ } else { -+ /* if py != qy or qx = 0, then R = inf */ -+ if (((mp_cmp(py, qy) != 0)) || (mp_cmp_z(qx) == 0)) { -+ mp_zero(rx); -+ mp_zero(ry); -+ res = MP_OKAY; -+ goto CLEANUP; -+ } -+ /* lambda = qx + qy / qx */ -+ MP_CHECKOK(group->meth->field_div(qy, qx, &lambda, group->meth)); -+ MP_CHECKOK(group->meth-> -+ field_add(&lambda, qx, &lambda, group->meth)); -+ /* tempx = a + lambda^2 + lambda */ -+ MP_CHECKOK(group->meth->field_sqr(&lambda, &tempx, group->meth)); -+ MP_CHECKOK(group->meth-> -+ field_add(&tempx, &lambda, &tempx, group->meth)); -+ MP_CHECKOK(group->meth-> -+ field_add(&tempx, &group->curvea, &tempx, group->meth)); ++ if (FINGERPRINT.equalsIgnoreCase(fp)) { ++ Date notBefore = chain[0].getNotBefore(); ++ LocalDate ldNotBefore = LocalDate.ofInstant(notBefore.toInstant(), ++ ZoneOffset.UTC); ++ // reject if certificate is issued after April 15, 2025 ++ checkNotBefore(ldNotBefore, APRIL_15_2025, anchor); + } -+ /* ry = (qx + tempx) * lambda + tempx + qy */ -+ MP_CHECKOK(group->meth->field_add(qx, &tempx, &tempy, group->meth)); -+ MP_CHECKOK(group->meth-> -+ field_mul(&tempy, &lambda, &tempy, group->meth)); -+ MP_CHECKOK(group->meth-> -+ field_add(&tempy, &tempx, &tempy, group->meth)); -+ MP_CHECKOK(group->meth->field_add(&tempy, qy, ry, group->meth)); -+ /* rx = tempx */ -+ MP_CHECKOK(mp_copy(&tempx, rx)); -+ -+ CLEANUP: -+ mp_clear(&lambda); -+ mp_clear(&tempx); -+ mp_clear(&tempy); -+ return res; -+} -+ -+/* Computes R = P - Q. Elliptic curve points P, Q, and R can all be -+ * identical. Uses affine coordinates. */ -+mp_err -+ec_GF2m_pt_sub_aff(const mp_int *px, const mp_int *py, const mp_int *qx, -+ const mp_int *qy, mp_int *rx, mp_int *ry, -+ const ECGroup *group) -+{ -+ mp_err res = MP_OKAY; -+ mp_int nqy; -+ -+ MP_DIGITS(&nqy) = 0; -+ MP_CHECKOK(mp_init(&nqy, FLAG(px))); -+ /* nqy = qx+qy */ -+ MP_CHECKOK(group->meth->field_add(qx, qy, &nqy, group->meth)); -+ MP_CHECKOK(group->point_add(px, py, qx, &nqy, rx, ry, group)); -+ CLEANUP: -+ mp_clear(&nqy); -+ return res; -+} ++ } + -+/* Computes R = 2P. Elliptic curve points P and R can be identical. Uses -+ * affine coordinates. */ -+mp_err -+ec_GF2m_pt_dbl_aff(const mp_int *px, const mp_int *py, mp_int *rx, -+ mp_int *ry, const ECGroup *group) -+{ -+ return group->point_add(px, py, px, py, rx, ry, group); -+} ++ private static String fingerprint(X509Certificate cert) { ++ return X509CertImpl.getFingerprint("SHA-256", cert); ++ } + -+/* by default, this routine is unused and thus doesn't need to be compiled */ -+#ifdef ECL_ENABLE_GF2M_PT_MUL_AFF -+/* Computes R = nP based on IEEE P1363 A.10.3. Elliptic curve points P and -+ * R can be identical. Uses affine coordinates. */ -+mp_err -+ec_GF2m_pt_mul_aff(const mp_int *n, const mp_int *px, const mp_int *py, -+ mp_int *rx, mp_int *ry, const ECGroup *group) -+{ -+ mp_err res = MP_OKAY; -+ mp_int k, k3, qx, qy, sx, sy; -+ int b1, b3, i, l; -+ -+ MP_DIGITS(&k) = 0; -+ MP_DIGITS(&k3) = 0; -+ MP_DIGITS(&qx) = 0; -+ MP_DIGITS(&qy) = 0; -+ MP_DIGITS(&sx) = 0; -+ MP_DIGITS(&sy) = 0; -+ MP_CHECKOK(mp_init(&k)); -+ MP_CHECKOK(mp_init(&k3)); -+ MP_CHECKOK(mp_init(&qx)); -+ MP_CHECKOK(mp_init(&qy)); -+ MP_CHECKOK(mp_init(&sx)); -+ MP_CHECKOK(mp_init(&sy)); -+ -+ /* if n = 0 then r = inf */ -+ if (mp_cmp_z(n) == 0) { -+ mp_zero(rx); -+ mp_zero(ry); -+ res = MP_OKAY; -+ goto CLEANUP; -+ } -+ /* Q = P, k = n */ -+ MP_CHECKOK(mp_copy(px, &qx)); -+ MP_CHECKOK(mp_copy(py, &qy)); -+ MP_CHECKOK(mp_copy(n, &k)); -+ /* if n < 0 then Q = -Q, k = -k */ -+ if (mp_cmp_z(n) < 0) { -+ MP_CHECKOK(group->meth->field_add(&qx, &qy, &qy, group->meth)); -+ MP_CHECKOK(mp_neg(&k, &k)); ++ private static void checkNotBefore(LocalDate notBeforeDate, ++ LocalDate distrustDate, X509Certificate anchor) ++ throws ValidatorException { ++ if (notBeforeDate.isAfter(distrustDate)) { ++ throw new ValidatorException ++ ("TLS Server certificate issued after " + distrustDate + ++ " and anchored by a distrusted legacy Camerfirma root CA: " ++ + anchor.getSubjectX500Principal(), ++ ValidatorException.T_UNTRUSTED_CERT, anchor); + } -+#ifdef ECL_DEBUG /* basic double and add method */ -+ l = mpl_significant_bits(&k) - 1; -+ MP_CHECKOK(mp_copy(&qx, &sx)); -+ MP_CHECKOK(mp_copy(&qy, &sy)); -+ for (i = l - 1; i >= 0; i--) { -+ /* S = 2S */ -+ MP_CHECKOK(group->point_dbl(&sx, &sy, &sx, &sy, group)); -+ /* if k_i = 1, then S = S + Q */ -+ if (mpl_get_bit(&k, i) != 0) { -+ MP_CHECKOK(group-> -+ point_add(&sx, &sy, &qx, &qy, &sx, &sy, group)); -+ } -+ } -+#else /* double and add/subtract method from -+ * standard */ -+ /* k3 = 3 * k */ -+ MP_CHECKOK(mp_set_int(&k3, 3)); -+ MP_CHECKOK(mp_mul(&k, &k3, &k3)); -+ /* S = Q */ -+ MP_CHECKOK(mp_copy(&qx, &sx)); -+ MP_CHECKOK(mp_copy(&qy, &sy)); -+ /* l = index of high order bit in binary representation of 3*k */ -+ l = mpl_significant_bits(&k3) - 1; -+ /* for i = l-1 downto 1 */ -+ for (i = l - 1; i >= 1; i--) { -+ /* S = 2S */ -+ MP_CHECKOK(group->point_dbl(&sx, &sy, &sx, &sy, group)); -+ b3 = MP_GET_BIT(&k3, i); -+ b1 = MP_GET_BIT(&k, i); -+ /* if k3_i = 1 and k_i = 0, then S = S + Q */ -+ if ((b3 == 1) && (b1 == 0)) { -+ MP_CHECKOK(group-> -+ point_add(&sx, &sy, &qx, &qy, &sx, &sy, group)); -+ /* if k3_i = 0 and k_i = 1, then S = S - Q */ -+ } else if ((b3 == 0) && (b1 == 1)) { -+ MP_CHECKOK(group-> -+ point_sub(&sx, &sy, &qx, &qy, &sx, &sy, group)); -+ } -+ } -+#endif -+ /* output S */ -+ MP_CHECKOK(mp_copy(&sx, rx)); -+ MP_CHECKOK(mp_copy(&sy, ry)); -+ -+ CLEANUP: -+ mp_clear(&k); -+ mp_clear(&k3); -+ mp_clear(&qx); -+ mp_clear(&qy); -+ mp_clear(&sx); -+ mp_clear(&sy); -+ return res; ++ } ++ ++ private CamerfirmaTLSPolicy() {} +} -+#endif +diff --git a/src/java.base/share/classes/sun/security/validator/EntrustTLSPolicy.java b/src/java.base/share/classes/sun/security/validator/EntrustTLSPolicy.java +index a19c2e503..10841a101 100644 +--- a/src/java.base/share/classes/sun/security/validator/EntrustTLSPolicy.java ++++ b/src/java.base/share/classes/sun/security/validator/EntrustTLSPolicy.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -71,19 +71,7 @@ final class EntrustTLSPolicy { + // OU=(c) 1999 Entrust.net Limited, + // OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.), + // O=Entrust.net +- "6DC47172E01CBCB0BF62580D895FE2B8AC9AD4F873801E0C10B9C837D21EB177", +- // cacerts alias: affirmtrustcommercialca +- // DN: CN=AffirmTrust Commercial, O=AffirmTrust, C=US +- "0376AB1D54C5F9803CE4B2E201A0EE7EEF7B57B636E8A93C9B8D4860C96F5FA7", +- // cacerts alias: affirmtrustnetworkingca +- // DN: CN=AffirmTrust Networking, O=AffirmTrust, C=US +- "0A81EC5A929777F145904AF38D5D509F66B5E2C58FCDB531058B0E17F3F0B41B", +- // cacerts alias: affirmtrustpremiumca +- // DN: CN=AffirmTrust Premium, O=AffirmTrust, C=US +- "70A73F7F376B60074248904534B11482D5BF0E698ECC498DF52577EBF2E93B9A", +- // cacerts alias: affirmtrustpremiumeccca +- // DN: CN=AffirmTrust Premium ECC, O=AffirmTrust, C=US +- "BD71FDF6DA97E4CF62D1647ADD2581B07D79ADF8397EB4ECBA9C5E8488821423" ++ "6DC47172E01CBCB0BF62580D895FE2B8AC9AD4F873801E0C10B9C837D21EB177" + ); + + // Any TLS Server certificate that is anchored by one of the Entrust +diff --git a/src/java.base/share/classes/sun/security/x509/AVA.java b/src/java.base/share/classes/sun/security/x509/AVA.java +index 77bc088af..c446c37cc 100644 +--- a/src/java.base/share/classes/sun/security/x509/AVA.java ++++ b/src/java.base/share/classes/sun/security/x509/AVA.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 1996, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -30,9 +30,14 @@ import java.io.IOException; + import java.io.OutputStream; + import java.io.Reader; + import java.security.AccessController; ++import java.nio.charset.Charset; + import java.text.Normalizer; + import java.util.*; + ++import static java.nio.charset.StandardCharsets.ISO_8859_1; ++import static java.nio.charset.StandardCharsets.UTF_8; ++import static java.nio.charset.StandardCharsets.UTF_16BE; ++ + import sun.security.action.GetBooleanAction; + import sun.security.util.*; + import sun.security.pkcs.PKCS9Attribute; +@@ -606,6 +611,10 @@ public class AVA implements DerEncoder { + throw new IOException("AVA, extra bytes = " + + derval.data.available()); + } + -+/* Validates a point on a GF2m curve. */ -+mp_err -+ec_GF2m_validate_point(const mp_int *px, const mp_int *py, const ECGroup *group) -+{ -+ mp_err res = MP_NO; -+ mp_int accl, accr, tmp, pxt, pyt; -+ -+ MP_DIGITS(&accl) = 0; -+ MP_DIGITS(&accr) = 0; -+ MP_DIGITS(&tmp) = 0; -+ MP_DIGITS(&pxt) = 0; -+ MP_DIGITS(&pyt) = 0; -+ MP_CHECKOK(mp_init(&accl, FLAG(px))); -+ MP_CHECKOK(mp_init(&accr, FLAG(px))); -+ MP_CHECKOK(mp_init(&tmp, FLAG(px))); -+ MP_CHECKOK(mp_init(&pxt, FLAG(px))); -+ MP_CHECKOK(mp_init(&pyt, FLAG(px))); -+ -+ /* 1: Verify that publicValue is not the point at infinity */ -+ if (ec_GF2m_pt_is_inf_aff(px, py) == MP_YES) { -+ res = MP_NO; -+ goto CLEANUP; ++ if (value.tag == DerValue.tag_BMPString) { ++ value.validateBMPString(); + } -+ /* 2: Verify that the coordinates of publicValue are elements -+ * of the field. -+ */ -+ if ((MP_SIGN(px) == MP_NEG) || (mp_cmp(px, &group->meth->irr) >= 0) || -+ (MP_SIGN(py) == MP_NEG) || (mp_cmp(py, &group->meth->irr) >= 0)) { -+ res = MP_NO; -+ goto CLEANUP; -+ } -+ /* 3: Verify that publicValue is on the curve. */ -+ if (group->meth->field_enc) { -+ group->meth->field_enc(px, &pxt, group->meth); -+ group->meth->field_enc(py, &pyt, group->meth); -+ } else { -+ mp_copy(px, &pxt); -+ mp_copy(py, &pyt); -+ } -+ /* left-hand side: y^2 + x*y */ -+ MP_CHECKOK( group->meth->field_sqr(&pyt, &accl, group->meth) ); -+ MP_CHECKOK( group->meth->field_mul(&pxt, &pyt, &tmp, group->meth) ); -+ MP_CHECKOK( group->meth->field_add(&accl, &tmp, &accl, group->meth) ); -+ /* right-hand side: x^3 + a*x^2 + b */ -+ MP_CHECKOK( group->meth->field_sqr(&pxt, &tmp, group->meth) ); -+ MP_CHECKOK( group->meth->field_mul(&pxt, &tmp, &accr, group->meth) ); -+ MP_CHECKOK( group->meth->field_mul(&group->curvea, &tmp, &tmp, group->meth) ); -+ MP_CHECKOK( group->meth->field_add(&tmp, &accr, &accr, group->meth) ); -+ MP_CHECKOK( group->meth->field_add(&accr, &group->curveb, &accr, group->meth) ); -+ /* check LHS - RHS == 0 */ -+ MP_CHECKOK( group->meth->field_add(&accl, &accr, &accr, group->meth) ); -+ if (mp_cmp_z(&accr) != 0) { -+ res = MP_NO; -+ goto CLEANUP; -+ } -+ /* 4: Verify that the order of the curve times the publicValue -+ * is the point at infinity. + } + + AVA(DerInputStream in) throws IOException { +@@ -753,7 +762,7 @@ public class AVA implements DerEncoder { + */ + String valStr = null; + try { +- valStr = new String(value.getDataBytes(), "UTF8"); ++ valStr = new String(value.getDataBytes(), getCharset(value, false)); + } catch (IOException ie) { + throw new IllegalArgumentException("DER Value conversion"); + } +@@ -906,7 +915,7 @@ public class AVA implements DerEncoder { + */ + String valStr = null; + try { +- valStr = new String(value.getDataBytes(), "UTF8"); ++ valStr = new String(value.getDataBytes(), getCharset(value, true)); + } catch (IOException ie) { + throw new IllegalArgumentException("DER Value conversion"); + } +@@ -1026,6 +1035,46 @@ public class AVA implements DerEncoder { + } + } + ++ /* ++ * Returns the charset that should be used to decode each DN string type. ++ * ++ * This method ensures that multi-byte (UTF8String and BMPString) types ++ * are decoded using the correct charset and the String forms represent ++ * the correct characters. For 8-bit ASCII-based types (PrintableString ++ * and IA5String), we return ISO_8859_1 rather than ASCII, so that the ++ * complete range of characters can be represented, as many certificates ++ * do not comply with the Internationalized Domain Name ACE format. ++ * ++ * NOTE: this method only supports DirectoryStrings of the types returned ++ * by isDerString(). + */ -+ /* timing mitigation is not supported */ -+ MP_CHECKOK( ECPoint_mul(group, &group->order, px, py, &pxt, &pyt, /*timing*/ 0) ); -+ if (ec_GF2m_pt_is_inf_aff(&pxt, &pyt) != MP_YES) { -+ res = MP_NO; -+ goto CLEANUP; ++ private static Charset getCharset(DerValue value, boolean canonical) { ++ if (canonical) { ++ switch (value.tag) { ++ case DerValue.tag_PrintableString: ++ return ISO_8859_1; ++ case DerValue.tag_UTF8String: ++ return UTF_8; ++ default: ++ throw new Error("unexpected tag: " + value.tag); ++ } + } + -+ res = MP_YES; ++ switch (value.tag) { ++ case DerValue.tag_PrintableString: ++ case DerValue.tag_T61String: ++ case DerValue.tag_IA5String: ++ case DerValue.tag_GeneralString: ++ return ISO_8859_1; ++ case DerValue.tag_BMPString: ++ return UTF_16BE; ++ case DerValue.tag_UTF8String: ++ return UTF_8; ++ default: ++ throw new Error("unexpected tag: " + value.tag); ++ } ++ } + -+CLEANUP: -+ mp_clear(&accl); -+ mp_clear(&accr); -+ mp_clear(&tmp); -+ mp_clear(&pxt); -+ mp_clear(&pyt); -+ return res; -+} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.crypto.ec/share/native/libsunec/impl/ec2.h jdk11u-ls/src/jdk.crypto.ec/share/native/libsunec/impl/ec2.h ---- openjdk/src/jdk.crypto.ec/share/native/libsunec/impl/ec2.h 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/jdk.crypto.ec/share/native/libsunec/impl/ec2.h 2023-09-12 13:54:26.289575680 +0800 -@@ -0,0 +1,126 @@ -+/* -+ * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved. -+ * Use is subject to license terms. -+ * -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. -+ * -+ * This library 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 -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public License -+ * along with this library; if not, write to the Free Software Foundation, -+ * Inc., 51 Franklin Street, 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. -+ */ -+ -+/* ********************************************************************* -+ * -+ * The Original Code is the elliptic curve math library for binary polynomial field curves. -+ * -+ * The Initial Developer of the Original Code is -+ * Sun Microsystems, Inc. -+ * Portions created by the Initial Developer are Copyright (C) 2003 -+ * the Initial Developer. All Rights Reserved. -+ * -+ * Contributor(s): -+ * Douglas Stebila , Sun Microsystems Laboratories -+ * -+ * Last Modified Date from the Original Code: May 2017 -+ *********************************************************************** */ -+ -+#ifndef _EC2_H -+#define _EC2_H -+ -+#include "ecl-priv.h" -+ -+/* Checks if point P(px, py) is at infinity. Uses affine coordinates. */ -+mp_err ec_GF2m_pt_is_inf_aff(const mp_int *px, const mp_int *py); -+ -+/* Sets P(px, py) to be the point at infinity. Uses affine coordinates. */ -+mp_err ec_GF2m_pt_set_inf_aff(mp_int *px, mp_int *py); -+ -+/* Computes R = P + Q where R is (rx, ry), P is (px, py) and Q is (qx, -+ * qy). Uses affine coordinates. */ -+mp_err ec_GF2m_pt_add_aff(const mp_int *px, const mp_int *py, -+ const mp_int *qx, const mp_int *qy, mp_int *rx, -+ mp_int *ry, const ECGroup *group); -+ -+/* Computes R = P - Q. Uses affine coordinates. */ -+mp_err ec_GF2m_pt_sub_aff(const mp_int *px, const mp_int *py, -+ const mp_int *qx, const mp_int *qy, mp_int *rx, -+ mp_int *ry, const ECGroup *group); -+ -+/* Computes R = 2P. Uses affine coordinates. */ -+mp_err ec_GF2m_pt_dbl_aff(const mp_int *px, const mp_int *py, mp_int *rx, -+ mp_int *ry, const ECGroup *group); -+ -+/* Validates a point on a GF2m curve. */ -+mp_err ec_GF2m_validate_point(const mp_int *px, const mp_int *py, const ECGroup *group); -+ -+/* by default, this routine is unused and thus doesn't need to be compiled */ -+#ifdef ECL_ENABLE_GF2M_PT_MUL_AFF -+/* Computes R = nP where R is (rx, ry) and P is (px, py). The parameters -+ * a, b and p are the elliptic curve coefficients and the irreducible that -+ * determines the field GF2m. Uses affine coordinates. */ -+mp_err ec_GF2m_pt_mul_aff(const mp_int *n, const mp_int *px, -+ const mp_int *py, mp_int *rx, mp_int *ry, -+ const ECGroup *group); -+#endif -+ -+/* Computes R = nP where R is (rx, ry) and P is (px, py). The parameters -+ * a, b and p are the elliptic curve coefficients and the irreducible that -+ * determines the field GF2m. Uses Montgomery projective coordinates. */ -+mp_err ec_GF2m_pt_mul_mont(const mp_int *n, const mp_int *px, -+ const mp_int *py, mp_int *rx, mp_int *ry, -+ const ECGroup *group, int timing); -+ -+#ifdef ECL_ENABLE_GF2M_PROJ -+/* Converts a point P(px, py) from affine coordinates to projective -+ * coordinates R(rx, ry, rz). */ -+mp_err ec_GF2m_pt_aff2proj(const mp_int *px, const mp_int *py, mp_int *rx, -+ mp_int *ry, mp_int *rz, const ECGroup *group); -+ -+/* Converts a point P(px, py, pz) from projective coordinates to affine -+ * coordinates R(rx, ry). */ -+mp_err ec_GF2m_pt_proj2aff(const mp_int *px, const mp_int *py, -+ const mp_int *pz, mp_int *rx, mp_int *ry, -+ const ECGroup *group); -+ -+/* Checks if point P(px, py, pz) is at infinity. Uses projective -+ * coordinates. */ -+mp_err ec_GF2m_pt_is_inf_proj(const mp_int *px, const mp_int *py, -+ const mp_int *pz); -+ -+/* Sets P(px, py, pz) to be the point at infinity. Uses projective -+ * coordinates. */ -+mp_err ec_GF2m_pt_set_inf_proj(mp_int *px, mp_int *py, mp_int *pz); -+ -+/* Computes R = P + Q where R is (rx, ry, rz), P is (px, py, pz) and Q is -+ * (qx, qy, qz). Uses projective coordinates. */ -+mp_err ec_GF2m_pt_add_proj(const mp_int *px, const mp_int *py, -+ const mp_int *pz, const mp_int *qx, -+ const mp_int *qy, mp_int *rx, mp_int *ry, -+ mp_int *rz, const ECGroup *group); -+ -+/* Computes R = 2P. Uses projective coordinates. */ -+mp_err ec_GF2m_pt_dbl_proj(const mp_int *px, const mp_int *py, -+ const mp_int *pz, mp_int *rx, mp_int *ry, -+ mp_int *rz, const ECGroup *group); -+ -+/* Computes R = nP where R is (rx, ry) and P is (px, py). The parameters -+ * a, b and p are the elliptic curve coefficients and the prime that -+ * determines the field GF2m. Uses projective coordinates. */ -+mp_err ec_GF2m_pt_mul_proj(const mp_int *n, const mp_int *px, -+ const mp_int *py, mp_int *rx, mp_int *ry, -+ const ECGroup *group); -+#endif -+ -+#endif /* _EC2_H */ -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.crypto.ec/share/native/libsunec/impl/ec2_mont.c jdk11u-ls/src/jdk.crypto.ec/share/native/libsunec/impl/ec2_mont.c ---- openjdk/src/jdk.crypto.ec/share/native/libsunec/impl/ec2_mont.c 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/jdk.crypto.ec/share/native/libsunec/impl/ec2_mont.c 2023-09-12 13:54:26.289575680 +0800 -@@ -0,0 +1,278 @@ -+/* -+ * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved. -+ * Use is subject to license terms. -+ * -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. -+ * -+ * This library 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 -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public License -+ * along with this library; if not, write to the Free Software Foundation, -+ * Inc., 51 Franklin Street, 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. -+ */ -+ -+/* ********************************************************************* -+ * -+ * The Original Code is the elliptic curve math library for binary polynomial field curves. -+ * -+ * The Initial Developer of the Original Code is -+ * Sun Microsystems, Inc. -+ * Portions created by the Initial Developer are Copyright (C) 2003 -+ * the Initial Developer. All Rights Reserved. -+ * -+ * Contributor(s): -+ * Sheueling Chang-Shantz , -+ * Stephen Fung , and -+ * Douglas Stebila , Sun Microsystems Laboratories. -+ * -+ * Last Modified Date from the Original Code: May 2017 -+ *********************************************************************** */ -+ -+#include "ec2.h" -+#include "mplogic.h" -+#include "mp_gf2m.h" -+#ifndef _KERNEL -+#include -+#endif -+ -+/* Compute the x-coordinate x/z for the point 2*(x/z) in Montgomery -+ * projective coordinates. Uses algorithm Mdouble in appendix of Lopez, J. -+ * and Dahab, R. "Fast multiplication on elliptic curves over GF(2^m) -+ * without precomputation". modified to not require precomputation of -+ * c=b^{2^{m-1}}. */ -+static mp_err -+gf2m_Mdouble(mp_int *x, mp_int *z, const ECGroup *group, int kmflag) -+{ -+ mp_err res = MP_OKAY; -+ mp_int t1; -+ -+ MP_DIGITS(&t1) = 0; -+ MP_CHECKOK(mp_init(&t1, kmflag)); -+ -+ MP_CHECKOK(group->meth->field_sqr(x, x, group->meth)); -+ MP_CHECKOK(group->meth->field_sqr(z, &t1, group->meth)); -+ MP_CHECKOK(group->meth->field_mul(x, &t1, z, group->meth)); -+ MP_CHECKOK(group->meth->field_sqr(x, x, group->meth)); -+ MP_CHECKOK(group->meth->field_sqr(&t1, &t1, group->meth)); -+ MP_CHECKOK(group->meth-> -+ field_mul(&group->curveb, &t1, &t1, group->meth)); -+ MP_CHECKOK(group->meth->field_add(x, &t1, x, group->meth)); -+ -+ CLEANUP: -+ mp_clear(&t1); -+ return res; -+} -+ -+/* Compute the x-coordinate x1/z1 for the point (x1/z1)+(x2/x2) in -+ * Montgomery projective coordinates. Uses algorithm Madd in appendix of -+ * Lopex, J. and Dahab, R. "Fast multiplication on elliptic curves over -+ * GF(2^m) without precomputation". */ -+static mp_err -+gf2m_Madd(const mp_int *x, mp_int *x1, mp_int *z1, mp_int *x2, mp_int *z2, -+ const ECGroup *group, int kmflag) -+{ -+ mp_err res = MP_OKAY; -+ mp_int t1, t2; -+ -+ MP_DIGITS(&t1) = 0; -+ MP_DIGITS(&t2) = 0; -+ MP_CHECKOK(mp_init(&t1, kmflag)); -+ MP_CHECKOK(mp_init(&t2, kmflag)); -+ -+ MP_CHECKOK(mp_copy(x, &t1)); -+ MP_CHECKOK(group->meth->field_mul(x1, z2, x1, group->meth)); -+ MP_CHECKOK(group->meth->field_mul(z1, x2, z1, group->meth)); -+ MP_CHECKOK(group->meth->field_mul(x1, z1, &t2, group->meth)); -+ MP_CHECKOK(group->meth->field_add(z1, x1, z1, group->meth)); -+ MP_CHECKOK(group->meth->field_sqr(z1, z1, group->meth)); -+ MP_CHECKOK(group->meth->field_mul(z1, &t1, x1, group->meth)); -+ MP_CHECKOK(group->meth->field_add(x1, &t2, x1, group->meth)); -+ -+ CLEANUP: -+ mp_clear(&t1); -+ mp_clear(&t2); -+ return res; -+} -+ -+/* Compute the x, y affine coordinates from the point (x1, z1) (x2, z2) -+ * using Montgomery point multiplication algorithm Mxy() in appendix of -+ * Lopex, J. and Dahab, R. "Fast multiplication on elliptic curves over -+ * GF(2^m) without precomputation". Returns: 0 on error 1 if return value -+ * should be the point at infinity 2 otherwise */ -+static int -+gf2m_Mxy(const mp_int *x, const mp_int *y, mp_int *x1, mp_int *z1, -+ mp_int *x2, mp_int *z2, const ECGroup *group) -+{ -+ mp_err res = MP_OKAY; -+ int ret = 0; -+ mp_int t3, t4, t5; -+ -+ MP_DIGITS(&t3) = 0; -+ MP_DIGITS(&t4) = 0; -+ MP_DIGITS(&t5) = 0; -+ MP_CHECKOK(mp_init(&t3, FLAG(x2))); -+ MP_CHECKOK(mp_init(&t4, FLAG(x2))); -+ MP_CHECKOK(mp_init(&t5, FLAG(x2))); -+ -+ if (mp_cmp_z(z1) == 0) { -+ mp_zero(x2); -+ mp_zero(z2); -+ ret = 1; -+ goto CLEANUP; -+ } -+ -+ if (mp_cmp_z(z2) == 0) { -+ MP_CHECKOK(mp_copy(x, x2)); -+ MP_CHECKOK(group->meth->field_add(x, y, z2, group->meth)); -+ ret = 2; -+ goto CLEANUP; -+ } -+ -+ MP_CHECKOK(mp_set_int(&t5, 1)); -+ if (group->meth->field_enc) { -+ MP_CHECKOK(group->meth->field_enc(&t5, &t5, group->meth)); -+ } -+ -+ MP_CHECKOK(group->meth->field_mul(z1, z2, &t3, group->meth)); -+ -+ MP_CHECKOK(group->meth->field_mul(z1, x, z1, group->meth)); -+ MP_CHECKOK(group->meth->field_add(z1, x1, z1, group->meth)); -+ MP_CHECKOK(group->meth->field_mul(z2, x, z2, group->meth)); -+ MP_CHECKOK(group->meth->field_mul(z2, x1, x1, group->meth)); -+ MP_CHECKOK(group->meth->field_add(z2, x2, z2, group->meth)); -+ -+ MP_CHECKOK(group->meth->field_mul(z2, z1, z2, group->meth)); -+ MP_CHECKOK(group->meth->field_sqr(x, &t4, group->meth)); -+ MP_CHECKOK(group->meth->field_add(&t4, y, &t4, group->meth)); -+ MP_CHECKOK(group->meth->field_mul(&t4, &t3, &t4, group->meth)); -+ MP_CHECKOK(group->meth->field_add(&t4, z2, &t4, group->meth)); -+ -+ MP_CHECKOK(group->meth->field_mul(&t3, x, &t3, group->meth)); -+ MP_CHECKOK(group->meth->field_div(&t5, &t3, &t3, group->meth)); -+ MP_CHECKOK(group->meth->field_mul(&t3, &t4, &t4, group->meth)); -+ MP_CHECKOK(group->meth->field_mul(x1, &t3, x2, group->meth)); -+ MP_CHECKOK(group->meth->field_add(x2, x, z2, group->meth)); -+ -+ MP_CHECKOK(group->meth->field_mul(z2, &t4, z2, group->meth)); -+ MP_CHECKOK(group->meth->field_add(z2, y, z2, group->meth)); -+ -+ ret = 2; -+ -+ CLEANUP: -+ mp_clear(&t3); -+ mp_clear(&t4); -+ mp_clear(&t5); -+ if (res == MP_OKAY) { -+ return ret; -+ } else { -+ return 0; -+ } -+} -+ -+/* Computes R = nP based on algorithm 2P of Lopex, J. and Dahab, R. "Fast -+ * multiplication on elliptic curves over GF(2^m) without -+ * precomputation". Elliptic curve points P and R can be identical. Uses -+ * Montgomery projective coordinates. The timing parameter is ignored -+ * because this algorithm resists timing attacks by default. */ -+mp_err -+ec_GF2m_pt_mul_mont(const mp_int *n, const mp_int *px, const mp_int *py, -+ mp_int *rx, mp_int *ry, const ECGroup *group, -+ int timing) + boolean hasRFC2253Keyword() { + return AVAKeyword.hasKeyword(oid, RFC2253); + } +diff --git a/src/java.base/share/classes/sun/util/resources/CurrencyNames.properties b/src/java.base/share/classes/sun/util/resources/CurrencyNames.properties +index 3ed4f873a..e543398fa 100644 +--- a/src/java.base/share/classes/sun/util/resources/CurrencyNames.properties ++++ b/src/java.base/share/classes/sun/util/resources/CurrencyNames.properties +@@ -1,5 +1,5 @@ + # +-# Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. ++# Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. + # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + # + # This code is free software; you can redistribute it and/or modify it +@@ -258,6 +258,7 @@ VES=VES + VND=VND + VUV=VUV + WST=WST ++XAD=XAD + XAF=XAF + XAG=XAG + XAU=XAU +@@ -485,6 +486,7 @@ ves=Venezuelan Bol\u00edvar Soberano + vnd=Vietnamese Dong + vuv=Vanuatu Vatu + wst=Samoan Tala ++xad=Arab Accounting Dinar + xaf=CFA Franc BEAC + xag=Silver + xau=Gold +diff --git a/src/java.base/share/conf/security/java.security b/src/java.base/share/conf/security/java.security +index 6f3f5448b..7d4366836 100644 +--- a/src/java.base/share/conf/security/java.security ++++ b/src/java.base/share/conf/security/java.security +@@ -1290,6 +1290,9 @@ jdk.sasl.disabledMechanisms= + # ENTRUST_TLS : Distrust TLS Server certificates anchored by + # an Entrust root CA and issued after November 11, 2024. + # ++# CAMERFIRMA_TLS : Distrust TLS Server certificates anchored by ++# a Camerfirma root CA and issued after April 15, 2025. ++# + # Leading and trailing whitespace surrounding each value are ignored. + # Unknown values are ignored. If the property is commented out or set to the + # empty String, no policies are enforced. +@@ -1301,7 +1304,7 @@ jdk.sasl.disabledMechanisms= + # jdk.certpath.disabledAlgorithms; those restrictions are still enforced even + # if this property is not enabled. + # +-jdk.security.caDistrustPolicies=SYMANTEC_TLS,ENTRUST_TLS ++jdk.security.caDistrustPolicies=SYMANTEC_TLS,ENTRUST_TLS,CAMERFIRMA_TLS + + # + # FilePermission path canonicalization +diff --git a/src/java.base/share/native/libverify/check_code.c b/src/java.base/share/native/libverify/check_code.c +index 45891f45e..3ef252150 100644 +--- a/src/java.base/share/native/libverify/check_code.c ++++ b/src/java.base/share/native/libverify/check_code.c +@@ -398,7 +398,8 @@ static jboolean is_superclass(context_type *, fullinfo_type); + + static void initialize_exception_table(context_type *); + static int instruction_length(unsigned char *iptr, unsigned char *end); +-static jboolean isLegalTarget(context_type *, int offset); ++static jboolean isLegalOffset(context_type *, int bci, int offset); ++static jboolean isLegalTarget(context_type *, int target); + static void verify_constant_pool_type(context_type *, int, unsigned); + + static void initialize_dataflow(context_type *); +@@ -1169,9 +1170,9 @@ verify_opcode_operands(context_type *context, unsigned int inumber, int offset) + case JVM_OPC_goto: { + /* Set the ->operand to be the instruction number of the target. */ + int jump = (((signed char)(code[offset+1])) << 8) + code[offset+2]; +- int target = offset + jump; +- if (!isLegalTarget(context, target)) ++ if (!isLegalOffset(context, offset, jump)) + CCerror(context, "Illegal target of jump or branch"); ++ int target = offset + jump; + this_idata->operand.i = code_data[target]; + break; + } +@@ -1185,9 +1186,9 @@ verify_opcode_operands(context_type *context, unsigned int inumber, int offset) + int jump = (((signed char)(code[offset+1])) << 24) + + (code[offset+2] << 16) + (code[offset+3] << 8) + + (code[offset + 4]); +- int target = offset + jump; +- if (!isLegalTarget(context, target)) ++ if (!isLegalOffset(context, offset, jump)) + CCerror(context, "Illegal target of jump or branch"); ++ int target = offset + jump; + this_idata->operand.i = code_data[target]; + break; + } +@@ -1226,13 +1227,16 @@ verify_opcode_operands(context_type *context, unsigned int inumber, int offset) + } + } + saved_operand = NEW(int, keys + 2); +- if (!isLegalTarget(context, offset + _ck_ntohl(lpc[0]))) ++ int jump = _ck_ntohl(lpc[0]); ++ if (!isLegalOffset(context, offset, jump)) + CCerror(context, "Illegal default target in switch"); +- saved_operand[keys + 1] = code_data[offset + _ck_ntohl(lpc[0])]; ++ int target = offset + jump; ++ saved_operand[keys + 1] = code_data[target]; + for (k = keys, lptr = &lpc[3]; --k >= 0; lptr += delta) { +- int target = offset + _ck_ntohl(lptr[0]); +- if (!isLegalTarget(context, target)) ++ jump = _ck_ntohl(lptr[0]); ++ if (!isLegalOffset(context, offset, jump)) + CCerror(context, "Illegal branch in tableswitch"); ++ target = offset + jump; + saved_operand[k + 1] = code_data[target]; + } + saved_operand[0] = keys + 1; /* number of successors */ +@@ -1756,11 +1760,24 @@ static int instruction_length(unsigned char *iptr, unsigned char *end) + + /* Given the target of a branch, make sure that it's a legal target. */ + static jboolean +-isLegalTarget(context_type *context, int offset) ++isLegalTarget(context_type *context, int target) +{ -+ mp_err res = MP_OKAY; -+ mp_int x1, x2, z1, z2; -+ int i, j; -+ mp_digit top_bit, mask; -+ -+ MP_DIGITS(&x1) = 0; -+ MP_DIGITS(&x2) = 0; -+ MP_DIGITS(&z1) = 0; -+ MP_DIGITS(&z2) = 0; -+ MP_CHECKOK(mp_init(&x1, FLAG(n))); -+ MP_CHECKOK(mp_init(&x2, FLAG(n))); -+ MP_CHECKOK(mp_init(&z1, FLAG(n))); -+ MP_CHECKOK(mp_init(&z2, FLAG(n))); -+ -+ /* if result should be point at infinity */ -+ if ((mp_cmp_z(n) == 0) || (ec_GF2m_pt_is_inf_aff(px, py) == MP_YES)) { -+ MP_CHECKOK(ec_GF2m_pt_set_inf_aff(rx, ry)); -+ goto CLEANUP; -+ } -+ -+ MP_CHECKOK(mp_copy(px, &x1)); /* x1 = px */ -+ MP_CHECKOK(mp_set_int(&z1, 1)); /* z1 = 1 */ -+ MP_CHECKOK(group->meth->field_sqr(&x1, &z2, group->meth)); /* z2 = -+ * x1^2 = -+ * px^2 */ -+ MP_CHECKOK(group->meth->field_sqr(&z2, &x2, group->meth)); -+ MP_CHECKOK(group->meth->field_add(&x2, &group->curveb, &x2, group->meth)); /* x2 -+ * = -+ * px^4 -+ * + -+ * b -+ */ -+ -+ /* find top-most bit and go one past it */ -+ i = MP_USED(n) - 1; -+ j = MP_DIGIT_BIT - 1; -+ top_bit = 1; -+ top_bit <<= MP_DIGIT_BIT - 1; -+ mask = top_bit; -+ while (!(MP_DIGITS(n)[i] & mask)) { -+ mask >>= 1; -+ j--; -+ } -+ mask >>= 1; -+ j--; -+ -+ /* if top most bit was at word break, go to next word */ -+ if (!mask) { -+ i--; -+ j = MP_DIGIT_BIT - 1; -+ mask = top_bit; -+ } -+ -+ for (; i >= 0; i--) { -+ for (; j >= 0; j--) { -+ if (MP_DIGITS(n)[i] & mask) { -+ MP_CHECKOK(gf2m_Madd(px, &x1, &z1, &x2, &z2, group, FLAG(n))); -+ MP_CHECKOK(gf2m_Mdouble(&x2, &z2, group, FLAG(n))); -+ } else { -+ MP_CHECKOK(gf2m_Madd(px, &x2, &z2, &x1, &z1, group, FLAG(n))); -+ MP_CHECKOK(gf2m_Mdouble(&x1, &z1, group, FLAG(n))); -+ } -+ mask >>= 1; -+ } -+ j = MP_DIGIT_BIT - 1; -+ mask = top_bit; -+ } -+ -+ /* convert out of "projective" coordinates */ -+ i = gf2m_Mxy(px, py, &x1, &z1, &x2, &z2, group); -+ if (i == 0) { -+ res = MP_BADARG; -+ goto CLEANUP; -+ } else if (i == 1) { -+ MP_CHECKOK(ec_GF2m_pt_set_inf_aff(rx, ry)); -+ } else { -+ MP_CHECKOK(mp_copy(&x2, rx)); -+ MP_CHECKOK(mp_copy(&z2, ry)); -+ } -+ -+ CLEANUP: -+ mp_clear(&x1); -+ mp_clear(&x2); -+ mp_clear(&z1); -+ mp_clear(&z2); -+ return res; -+} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.crypto.ec/share/native/libsunec/impl/ecl.c jdk11u-ls/src/jdk.crypto.ec/share/native/libsunec/impl/ecl.c ---- openjdk/src/jdk.crypto.ec/share/native/libsunec/impl/ecl.c 2022-10-12 23:00:07.000000000 +0800 -+++ jdk11u-ls/src/jdk.crypto.ec/share/native/libsunec/impl/ecl.c 2023-09-12 13:54:26.293575685 +0800 -@@ -39,6 +39,7 @@ - #include "mplogic.h" - #include "ecl.h" - #include "ecl-priv.h" -+#include "ec2.h" - #include "ecp.h" - #ifndef _KERNEL - #include -@@ -169,6 +170,50 @@ - return group; ++ int code_length = context->code_length; ++ int *code_data = context->code_data; ++ return (target >= 0 && target < code_length && code_data[target] >= 0); ++} ++ ++/* Given a bci and offset, make sure the offset is valid and the target is legal */ ++static jboolean ++isLegalOffset(context_type *context, int bci, int offset) + { + int code_length = context->code_length; + int *code_data = context->code_data; +- return (offset >= 0 && offset < code_length && code_data[offset] >= 0); ++ int max_offset = 65535; // JVMS 4.11 ++ int min_offset = -65535; ++ if (offset < min_offset || offset > max_offset) return JNI_FALSE; ++ int target = bci + offset; ++ return (target >= 0 && target < code_length && code_data[target] >= 0); } -+#ifdef NSS_ECC_MORE_THAN_SUITE_B -+/* Construct a generic ECGroup for elliptic curves over binary polynomial -+ * fields. */ -+ECGroup * -+ECGroup_consGF2m(const mp_int *irr, const unsigned int irr_arr[5], -+ const mp_int *curvea, const mp_int *curveb, -+ const mp_int *genx, const mp_int *geny, -+ const mp_int *order, int cofactor) -+{ -+ mp_err res = MP_OKAY; -+ ECGroup *group = NULL; -+ -+ group = ECGroup_new(FLAG(irr)); -+ if (group == NULL) -+ return NULL; -+ -+ group->meth = GFMethod_consGF2m(irr, irr_arr); -+ if (group->meth == NULL) { -+ res = MP_MEM; -+ goto CLEANUP; -+ } -+ MP_CHECKOK(mp_copy(curvea, &group->curvea)); -+ MP_CHECKOK(mp_copy(curveb, &group->curveb)); -+ MP_CHECKOK(mp_copy(genx, &group->genx)); -+ MP_CHECKOK(mp_copy(geny, &group->geny)); -+ MP_CHECKOK(mp_copy(order, &group->order)); -+ group->cofactor = cofactor; -+ group->point_add = &ec_GF2m_pt_add_aff; -+ group->point_sub = &ec_GF2m_pt_sub_aff; -+ group->point_dbl = &ec_GF2m_pt_dbl_aff; -+ group->point_mul = &ec_GF2m_pt_mul_mont; -+ group->base_point_mul = NULL; -+ group->points_mul = &ec_pts_mul_basic; -+ group->validate_point = &ec_GF2m_validate_point; -+ -+ CLEANUP: -+ if (res != MP_OKAY) { -+ ECGroup_free(group); -+ return NULL; -+ } -+ return group; -+} -+#endif -+ - /* Construct ECGroup from hex parameters and name, if any. Called by - * ECGroup_fromHex and ECGroup_fromName. */ - ECGroup * -@@ -209,10 +254,85 @@ - - /* determine which optimizations (if any) to use */ - if (params->field == ECField_GFp) { -+#ifdef NSS_ECC_MORE_THAN_SUITE_B -+ switch (name) { -+#ifdef ECL_USE_FP -+ case ECCurve_SECG_PRIME_160R1: -+ group = -+ ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny, -+ &order, params->cofactor); -+ if (group == NULL) { res = MP_UNDEF; goto CLEANUP; } -+ MP_CHECKOK(ec_group_set_secp160r1_fp(group)); -+ break; -+#endif -+ case ECCurve_SECG_PRIME_192R1: -+#ifdef ECL_USE_FP -+ group = -+ ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny, -+ &order, params->cofactor); -+ if (group == NULL) { res = MP_UNDEF; goto CLEANUP; } -+ MP_CHECKOK(ec_group_set_nistp192_fp(group)); -+#else -+ group = -+ ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny, -+ &order, params->cofactor); -+ if (group == NULL) { res = MP_UNDEF; goto CLEANUP; } -+ MP_CHECKOK(ec_group_set_gfp192(group, name)); -+#endif -+ break; -+ case ECCurve_SECG_PRIME_224R1: -+#ifdef ECL_USE_FP -+ group = -+ ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny, -+ &order, params->cofactor); -+ if (group == NULL) { res = MP_UNDEF; goto CLEANUP; } -+ MP_CHECKOK(ec_group_set_nistp224_fp(group)); -+#else -+ group = -+ ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny, -+ &order, params->cofactor); -+ if (group == NULL) { res = MP_UNDEF; goto CLEANUP; } -+ MP_CHECKOK(ec_group_set_gfp224(group, name)); -+#endif -+ break; -+ case ECCurve_SECG_PRIME_256R1: -+ group = -+ ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny, -+ &order, params->cofactor); -+ if (group == NULL) { res = MP_UNDEF; goto CLEANUP; } -+ MP_CHECKOK(ec_group_set_gfp256(group, name)); -+ break; -+ case ECCurve_SECG_PRIME_521R1: -+ group = -+ ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny, -+ &order, params->cofactor); -+ if (group == NULL) { res = MP_UNDEF; goto CLEANUP; } -+ MP_CHECKOK(ec_group_set_gfp521(group, name)); -+ break; -+ default: -+ /* use generic arithmetic */ -+#endif - group = - ECGroup_consGFp_mont(&irr, &curvea, &curveb, &genx, &geny, - &order, params->cofactor); - if (group == NULL) { res = MP_UNDEF; goto CLEANUP; } -+#ifdef NSS_ECC_MORE_THAN_SUITE_B -+ } -+ } else if (params->field == ECField_GF2m) { -+ group = ECGroup_consGF2m(&irr, NULL, &curvea, &curveb, &genx, &geny, &order, params->cofactor); -+ if (group == NULL) { res = MP_UNDEF; goto CLEANUP; } -+ if ((name == ECCurve_NIST_K163) || -+ (name == ECCurve_NIST_B163) || -+ (name == ECCurve_SECG_CHAR2_163R1)) { -+ MP_CHECKOK(ec_group_set_gf2m163(group, name)); -+ } else if ((name == ECCurve_SECG_CHAR2_193R1) || -+ (name == ECCurve_SECG_CHAR2_193R2)) { -+ MP_CHECKOK(ec_group_set_gf2m193(group, name)); -+ } else if ((name == ECCurve_NIST_K233) || -+ (name == ECCurve_NIST_B233)) { -+ MP_CHECKOK(ec_group_set_gf2m233(group, name)); -+ } -+#endif - } else { - res = MP_UNDEF; - goto CLEANUP; -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.crypto.ec/share/native/libsunec/impl/ecl-curve.h jdk11u-ls/src/jdk.crypto.ec/share/native/libsunec/impl/ecl-curve.h ---- openjdk/src/jdk.crypto.ec/share/native/libsunec/impl/ecl-curve.h 2022-10-12 23:00:07.000000000 +0800 -+++ jdk11u-ls/src/jdk.crypto.ec/share/native/libsunec/impl/ecl-curve.h 2023-09-12 13:54:26.293575685 +0800 -@@ -44,6 +44,25 @@ - #endif - /* NIST prime curves */ -+static const ECCurveParams ecCurve_NIST_P192 = { -+ "NIST-P192", ECField_GFp, 192, -+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", -+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC", -+ "64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1", -+ "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012", -+ "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811", -+ "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831", 1 -+}; -+ -+static const ECCurveParams ecCurve_NIST_P224 = { -+ "NIST-P224", ECField_GFp, 224, -+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001", -+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE", -+ "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4", -+ "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21", -+ "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34", -+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D", 1 -+}; +diff --git a/src/java.base/windows/classes/java/lang/ProcessImpl.java b/src/java.base/windows/classes/java/lang/ProcessImpl.java +index 8b491ecf6..6ab8f2316 100644 +--- a/src/java.base/windows/classes/java/lang/ProcessImpl.java ++++ b/src/java.base/windows/classes/java/lang/ProcessImpl.java +@@ -211,13 +211,14 @@ final class ProcessImpl extends Process { + private static final int VERIFICATION_LEGACY = 3; + // See Command shell overview for documentation of special characters. + // https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-xp/bb490954(v=technet.10) +- private static final char ESCAPE_VERIFICATION[][] = { ++ private static final String ESCAPE_VERIFICATION[] = { + // We guarantee the only command file execution for implicit [cmd.exe] run. + // http://technet.microsoft.com/en-us/library/bb490954.aspx +- {' ', '\t', '\"', '<', '>', '&', '|', '^'}, +- {' ', '\t', '\"', '<', '>'}, +- {' ', '\t', '\"', '<', '>'}, +- {' ', '\t'} ++ // All space characters require quoting are checked in needsEscaping(). ++ "\"<>&|^", ++ "\"<>", ++ "\"<>", ++ "" + }; - static const ECCurveParams ecCurve_NIST_P256 = { - "NIST-P256", ECField_GFp, 256, -@@ -77,7 +96,411 @@ - 1 - }; + private static String createCommandLine(int verificationType, +@@ -332,9 +333,14 @@ final class ProcessImpl extends Process { + } -+/* NIST binary curves */ -+static const ECCurveParams ecCurve_NIST_K163 = { -+ "NIST-K163", ECField_GF2m, 163, -+ "0800000000000000000000000000000000000000C9", -+ "000000000000000000000000000000000000000001", -+ "000000000000000000000000000000000000000001", -+ "02FE13C0537BBC11ACAA07D793DE4E6D5E5C94EEE8", -+ "0289070FB05D38FF58321F2E800536D538CCDAA3D9", -+ "04000000000000000000020108A2E0CC0D99F8A5EF", 2 -+}; -+ -+static const ECCurveParams ecCurve_NIST_B163 = { -+ "NIST-B163", ECField_GF2m, 163, -+ "0800000000000000000000000000000000000000C9", -+ "000000000000000000000000000000000000000001", -+ "020A601907B8C953CA1481EB10512F78744A3205FD", -+ "03F0EBA16286A2D57EA0991168D4994637E8343E36", -+ "00D51FBC6C71A0094FA2CDD545B11C5C0C797324F1", -+ "040000000000000000000292FE77E70C12A4234C33", 2 -+}; -+ -+static const ECCurveParams ecCurve_NIST_K233 = { -+ "NIST-K233", ECField_GF2m, 233, -+ "020000000000000000000000000000000000000004000000000000000001", -+ "000000000000000000000000000000000000000000000000000000000000", -+ "000000000000000000000000000000000000000000000000000000000001", -+ "017232BA853A7E731AF129F22FF4149563A419C26BF50A4C9D6EEFAD6126", -+ "01DB537DECE819B7F70F555A67C427A8CD9BF18AEB9B56E0C11056FAE6A3", -+ "008000000000000000000000000000069D5BB915BCD46EFB1AD5F173ABDF", 4 -+}; -+ -+static const ECCurveParams ecCurve_NIST_B233 = { -+ "NIST-B233", ECField_GF2m, 233, -+ "020000000000000000000000000000000000000004000000000000000001", -+ "000000000000000000000000000000000000000000000000000000000001", -+ "0066647EDE6C332C7F8C0923BB58213B333B20E9CE4281FE115F7D8F90AD", -+ "00FAC9DFCBAC8313BB2139F1BB755FEF65BC391F8B36F8F8EB7371FD558B", -+ "01006A08A41903350678E58528BEBF8A0BEFF867A7CA36716F7E01F81052", -+ "01000000000000000000000000000013E974E72F8A6922031D2603CFE0D7", 2 -+}; -+ -+static const ECCurveParams ecCurve_NIST_K283 = { -+ "NIST-K283", ECField_GF2m, 283, -+ "0800000000000000000000000000000000000000000000000000000000000000000010A1", -+ "000000000000000000000000000000000000000000000000000000000000000000000000", -+ "000000000000000000000000000000000000000000000000000000000000000000000001", -+ "0503213F78CA44883F1A3B8162F188E553CD265F23C1567A16876913B0C2AC2458492836", -+ "01CCDA380F1C9E318D90F95D07E5426FE87E45C0E8184698E45962364E34116177DD2259", -+ "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE9AE2ED07577265DFF7F94451E061E163C61", 4 -+}; -+ -+static const ECCurveParams ecCurve_NIST_B283 = { -+ "NIST-B283", ECField_GF2m, 283, -+ "0800000000000000000000000000000000000000000000000000000000000000000010A1", -+ "000000000000000000000000000000000000000000000000000000000000000000000001", -+ "027B680AC8B8596DA5A4AF8A19A0303FCA97FD7645309FA2A581485AF6263E313B79A2F5", -+ "05F939258DB7DD90E1934F8C70B0DFEC2EED25B8557EAC9C80E2E198F8CDBECD86B12053", -+ "03676854FE24141CB98FE6D4B20D02B4516FF702350EDDB0826779C813F0DF45BE8112F4", -+ "03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF90399660FC938A90165B042A7CEFADB307", 2 -+}; -+ -+static const ECCurveParams ecCurve_NIST_K409 = { -+ "NIST-K409", ECField_GF2m, 409, -+ "02000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001", -+ "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", -+ "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", -+ "0060F05F658F49C1AD3AB1890F7184210EFD0987E307C84C27ACCFB8F9F67CC2C460189EB5AAAA62EE222EB1B35540CFE9023746", -+ "01E369050B7C4E42ACBA1DACBF04299C3460782F918EA427E6325165E9EA10E3DA5F6C42E9C55215AA9CA27A5863EC48D8E0286B", -+ "007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE5F83B2D4EA20400EC4557D5ED3E3E7CA5B4B5C83B8E01E5FCF", 4 -+}; -+ -+static const ECCurveParams ecCurve_NIST_B409 = { -+ "NIST-B409", ECField_GF2m, 409, -+ "02000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001", -+ "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", -+ "0021A5C2C8EE9FEB5C4B9A753B7B476B7FD6422EF1F3DD674761FA99D6AC27C8A9A197B272822F6CD57A55AA4F50AE317B13545F", -+ "015D4860D088DDB3496B0C6064756260441CDE4AF1771D4DB01FFE5B34E59703DC255A868A1180515603AEAB60794E54BB7996A7", -+ "0061B1CFAB6BE5F32BBFA78324ED106A7636B9C5A7BD198D0158AA4F5488D08F38514F1FDF4B4F40D2181B3681C364BA0273C706", -+ "010000000000000000000000000000000000000000000000000001E2AAD6A612F33307BE5FA47C3C9E052F838164CD37D9A21173", 2 -+}; -+ -+static const ECCurveParams ecCurve_NIST_K571 = { -+ "NIST-K571", ECField_GF2m, 571, -+ "080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425", -+ "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", -+ "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", -+ "026EB7A859923FBC82189631F8103FE4AC9CA2970012D5D46024804801841CA44370958493B205E647DA304DB4CEB08CBBD1BA39494776FB988B47174DCA88C7E2945283A01C8972", -+ "0349DC807F4FBF374F4AEADE3BCA95314DD58CEC9F307A54FFC61EFC006D8A2C9D4979C0AC44AEA74FBEBBB9F772AEDCB620B01A7BA7AF1B320430C8591984F601CD4C143EF1C7A3", -+ "020000000000000000000000000000000000000000000000000000000000000000000000131850E1F19A63E4B391A8DB917F4138B630D84BE5D639381E91DEB45CFE778F637C1001", 4 -+}; -+ -+static const ECCurveParams ecCurve_NIST_B571 = { -+ "NIST-B571", ECField_GF2m, 571, -+ "080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425", -+ "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", -+ "02F40E7E2221F295DE297117B7F3D62F5C6A97FFCB8CEFF1CD6BA8CE4A9A18AD84FFABBD8EFA59332BE7AD6756A66E294AFD185A78FF12AA520E4DE739BACA0C7FFEFF7F2955727A", -+ "0303001D34B856296C16C0D40D3CD7750A93D1D2955FA80AA5F40FC8DB7B2ABDBDE53950F4C0D293CDD711A35B67FB1499AE60038614F1394ABFA3B4C850D927E1E7769C8EEC2D19", -+ "037BF27342DA639B6DCCFFFEB73D69D78C6C27A6009CBBCA1980F8533921E8A684423E43BAB08A576291AF8F461BB2A8B3531D2F0485C19B16E2F1516E23DD3C1A4827AF1B8AC15B", -+ "03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE661CE18FF55987308059B186823851EC7DD9CA1161DE93D5174D66E8382E9BB2FE84E47", 2 -+}; -+ -+/* ANSI X9.62 prime curves */ -+static const ECCurveParams ecCurve_X9_62_PRIME_192V2 = { -+ "X9.62 P-192V2", ECField_GFp, 192, -+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", -+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC", -+ "CC22D6DFB95C6B25E49C0D6364A4E5980C393AA21668D953", -+ "EEA2BAE7E1497842F2DE7769CFE9C989C072AD696F48034A", -+ "6574D11D69B6EC7A672BB82A083DF2F2B0847DE970B2DE15", -+ "FFFFFFFFFFFFFFFFFFFFFFFE5FB1A724DC80418648D8DD31", 1 -+}; -+ -+static const ECCurveParams ecCurve_X9_62_PRIME_192V3 = { -+ "X9.62 P-192V3", ECField_GFp, 192, -+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", -+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC", -+ "22123DC2395A05CAA7423DAECCC94760A7D462256BD56916", -+ "7D29778100C65A1DA1783716588DCE2B8B4AEE8E228F1896", -+ "38A90F22637337334B49DCB66A6DC8F9978ACA7648A943B0", -+ "FFFFFFFFFFFFFFFFFFFFFFFF7A62D031C83F4294F640EC13", 1 -+}; -+ -+static const ECCurveParams ecCurve_X9_62_PRIME_239V1 = { -+ "X9.62 P-239V1", ECField_GFp, 239, -+ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF", -+ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC", -+ "6B016C3BDCF18941D0D654921475CA71A9DB2FB27D1D37796185C2942C0A", -+ "0FFA963CDCA8816CCC33B8642BEDF905C3D358573D3F27FBBD3B3CB9AAAF", -+ "7DEBE8E4E90A5DAE6E4054CA530BA04654B36818CE226B39FCCB7B02F1AE", -+ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFF9E5E9A9F5D9071FBD1522688909D0B", 1 -+}; -+ -+static const ECCurveParams ecCurve_X9_62_PRIME_239V2 = { -+ "X9.62 P-239V2", ECField_GFp, 239, -+ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF", -+ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC", -+ "617FAB6832576CBBFED50D99F0249C3FEE58B94BA0038C7AE84C8C832F2C", -+ "38AF09D98727705120C921BB5E9E26296A3CDCF2F35757A0EAFD87B830E7", -+ "5B0125E4DBEA0EC7206DA0FC01D9B081329FB555DE6EF460237DFF8BE4BA", -+ "7FFFFFFFFFFFFFFFFFFFFFFF800000CFA7E8594377D414C03821BC582063", 1 -+}; -+ -+static const ECCurveParams ecCurve_X9_62_PRIME_239V3 = { -+ "X9.62 P-239V3", ECField_GFp, 239, -+ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF", -+ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC", -+ "255705FA2A306654B1F4CB03D6A750A30C250102D4988717D9BA15AB6D3E", -+ "6768AE8E18BB92CFCF005C949AA2C6D94853D0E660BBF854B1C9505FE95A", -+ "1607E6898F390C06BC1D552BAD226F3B6FCFE48B6E818499AF18E3ED6CF3", -+ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFF975DEB41B3A6057C3C432146526551", 1 -+}; -+ -+/* ANSI X9.62 binary curves */ -+static const ECCurveParams ecCurve_X9_62_CHAR2_PNB163V1 = { -+ "X9.62 C2-PNB163V1", ECField_GF2m, 163, -+ "080000000000000000000000000000000000000107", -+ "072546B5435234A422E0789675F432C89435DE5242", -+ "00C9517D06D5240D3CFF38C74B20B6CD4D6F9DD4D9", -+ "07AF69989546103D79329FCC3D74880F33BBE803CB", -+ "01EC23211B5966ADEA1D3F87F7EA5848AEF0B7CA9F", -+ "0400000000000000000001E60FC8821CC74DAEAFC1", 2 -+}; -+ -+static const ECCurveParams ecCurve_X9_62_CHAR2_PNB163V2 = { -+ "X9.62 C2-PNB163V2", ECField_GF2m, 163, -+ "080000000000000000000000000000000000000107", -+ "0108B39E77C4B108BED981ED0E890E117C511CF072", -+ "0667ACEB38AF4E488C407433FFAE4F1C811638DF20", -+ "0024266E4EB5106D0A964D92C4860E2671DB9B6CC5", -+ "079F684DDF6684C5CD258B3890021B2386DFD19FC5", -+ "03FFFFFFFFFFFFFFFFFFFDF64DE1151ADBB78F10A7", 2 -+}; -+ -+static const ECCurveParams ecCurve_X9_62_CHAR2_PNB163V3 = { -+ "X9.62 C2-PNB163V3", ECField_GF2m, 163, -+ "080000000000000000000000000000000000000107", -+ "07A526C63D3E25A256A007699F5447E32AE456B50E", -+ "03F7061798EB99E238FD6F1BF95B48FEEB4854252B", -+ "02F9F87B7C574D0BDECF8A22E6524775F98CDEBDCB", -+ "05B935590C155E17EA48EB3FF3718B893DF59A05D0", -+ "03FFFFFFFFFFFFFFFFFFFE1AEE140F110AFF961309", 2 -+}; -+ -+static const ECCurveParams ecCurve_X9_62_CHAR2_PNB176V1 = { -+ "X9.62 C2-PNB176V1", ECField_GF2m, 176, -+ "0100000000000000000000000000000000080000000007", -+ "E4E6DB2995065C407D9D39B8D0967B96704BA8E9C90B", -+ "5DDA470ABE6414DE8EC133AE28E9BBD7FCEC0AE0FFF2", -+ "8D16C2866798B600F9F08BB4A8E860F3298CE04A5798", -+ "6FA4539C2DADDDD6BAB5167D61B436E1D92BB16A562C", -+ "00010092537397ECA4F6145799D62B0A19CE06FE26AD", 0xFF6E -+}; -+ -+static const ECCurveParams ecCurve_X9_62_CHAR2_TNB191V1 = { -+ "X9.62 C2-TNB191V1", ECField_GF2m, 191, -+ "800000000000000000000000000000000000000000000201", -+ "2866537B676752636A68F56554E12640276B649EF7526267", -+ "2E45EF571F00786F67B0081B9495A3D95462F5DE0AA185EC", -+ "36B3DAF8A23206F9C4F299D7B21A9C369137F2C84AE1AA0D", -+ "765BE73433B3F95E332932E70EA245CA2418EA0EF98018FB", -+ "40000000000000000000000004A20E90C39067C893BBB9A5", 2 -+}; -+ -+static const ECCurveParams ecCurve_X9_62_CHAR2_TNB191V2 = { -+ "X9.62 C2-TNB191V2", ECField_GF2m, 191, -+ "800000000000000000000000000000000000000000000201", -+ "401028774D7777C7B7666D1366EA432071274F89FF01E718", -+ "0620048D28BCBD03B6249C99182B7C8CD19700C362C46A01", -+ "3809B2B7CC1B28CC5A87926AAD83FD28789E81E2C9E3BF10", -+ "17434386626D14F3DBF01760D9213A3E1CF37AEC437D668A", -+ "20000000000000000000000050508CB89F652824E06B8173", 4 -+}; -+ -+static const ECCurveParams ecCurve_X9_62_CHAR2_TNB191V3 = { -+ "X9.62 C2-TNB191V3", ECField_GF2m, 191, -+ "800000000000000000000000000000000000000000000201", -+ "6C01074756099122221056911C77D77E77A777E7E7E77FCB", -+ "71FE1AF926CF847989EFEF8DB459F66394D90F32AD3F15E8", -+ "375D4CE24FDE434489DE8746E71786015009E66E38A926DD", -+ "545A39176196575D985999366E6AD34CE0A77CD7127B06BE", -+ "155555555555555555555555610C0B196812BFB6288A3EA3", 6 -+}; -+ -+static const ECCurveParams ecCurve_X9_62_CHAR2_PNB208W1 = { -+ "X9.62 C2-PNB208W1", ECField_GF2m, 208, -+ "010000000000000000000000000000000800000000000000000007", -+ "0000000000000000000000000000000000000000000000000000", -+ "C8619ED45A62E6212E1160349E2BFA844439FAFC2A3FD1638F9E", -+ "89FDFBE4ABE193DF9559ECF07AC0CE78554E2784EB8C1ED1A57A", -+ "0F55B51A06E78E9AC38A035FF520D8B01781BEB1A6BB08617DE3", -+ "000101BAF95C9723C57B6C21DA2EFF2D5ED588BDD5717E212F9D", 0xFE48 -+}; -+ -+static const ECCurveParams ecCurve_X9_62_CHAR2_TNB239V1 = { -+ "X9.62 C2-TNB239V1", ECField_GF2m, 239, -+ "800000000000000000000000000000000000000000000000001000000001", -+ "32010857077C5431123A46B808906756F543423E8D27877578125778AC76", -+ "790408F2EEDAF392B012EDEFB3392F30F4327C0CA3F31FC383C422AA8C16", -+ "57927098FA932E7C0A96D3FD5B706EF7E5F5C156E16B7E7C86038552E91D", -+ "61D8EE5077C33FECF6F1A16B268DE469C3C7744EA9A971649FC7A9616305", -+ "2000000000000000000000000000000F4D42FFE1492A4993F1CAD666E447", 4 -+}; -+ -+static const ECCurveParams ecCurve_X9_62_CHAR2_TNB239V2 = { -+ "X9.62 C2-TNB239V2", ECField_GF2m, 239, -+ "800000000000000000000000000000000000000000000000001000000001", -+ "4230017757A767FAE42398569B746325D45313AF0766266479B75654E65F", -+ "5037EA654196CFF0CD82B2C14A2FCF2E3FF8775285B545722F03EACDB74B", -+ "28F9D04E900069C8DC47A08534FE76D2B900B7D7EF31F5709F200C4CA205", -+ "5667334C45AFF3B5A03BAD9DD75E2C71A99362567D5453F7FA6E227EC833", -+ "1555555555555555555555555555553C6F2885259C31E3FCDF154624522D", 6 -+}; -+ -+static const ECCurveParams ecCurve_X9_62_CHAR2_TNB239V3 = { -+ "X9.62 C2-TNB239V3", ECField_GF2m, 239, -+ "800000000000000000000000000000000000000000000000001000000001", -+ "01238774666A67766D6676F778E676B66999176666E687666D8766C66A9F", -+ "6A941977BA9F6A435199ACFC51067ED587F519C5ECB541B8E44111DE1D40", -+ "70F6E9D04D289C4E89913CE3530BFDE903977D42B146D539BF1BDE4E9C92", -+ "2E5A0EAF6E5E1305B9004DCE5C0ED7FE59A35608F33837C816D80B79F461", -+ "0CCCCCCCCCCCCCCCCCCCCCCCCCCCCCAC4912D2D9DF903EF9888B8A0E4CFF", 0xA -+}; -+ -+static const ECCurveParams ecCurve_X9_62_CHAR2_PNB272W1 = { -+ "X9.62 C2-PNB272W1", ECField_GF2m, 272, -+ "010000000000000000000000000000000000000000000000000000010000000000000B", -+ "91A091F03B5FBA4AB2CCF49C4EDD220FB028712D42BE752B2C40094DBACDB586FB20", -+ "7167EFC92BB2E3CE7C8AAAFF34E12A9C557003D7C73A6FAF003F99F6CC8482E540F7", -+ "6108BABB2CEEBCF787058A056CBE0CFE622D7723A289E08A07AE13EF0D10D171DD8D", -+ "10C7695716851EEF6BA7F6872E6142FBD241B830FF5EFCACECCAB05E02005DDE9D23", -+ "000100FAF51354E0E39E4892DF6E319C72C8161603FA45AA7B998A167B8F1E629521", -+ 0xFF06 -+}; -+ -+static const ECCurveParams ecCurve_X9_62_CHAR2_PNB304W1 = { -+ "X9.62 C2-PNB304W1", ECField_GF2m, 304, -+ "010000000000000000000000000000000000000000000000000000000000000000000000000807", -+ "FD0D693149A118F651E6DCE6802085377E5F882D1B510B44160074C1288078365A0396C8E681", -+ "BDDB97E555A50A908E43B01C798EA5DAA6788F1EA2794EFCF57166B8C14039601E55827340BE", -+ "197B07845E9BE2D96ADB0F5F3C7F2CFFBD7A3EB8B6FEC35C7FD67F26DDF6285A644F740A2614", -+ "E19FBEB76E0DA171517ECF401B50289BF014103288527A9B416A105E80260B549FDC1B92C03B", -+ "000101D556572AABAC800101D556572AABAC8001022D5C91DD173F8FB561DA6899164443051D", 0xFE2E -+}; -+ -+static const ECCurveParams ecCurve_X9_62_CHAR2_TNB359V1 = { -+ "X9.62 C2-TNB359V1", ECField_GF2m, 359, -+ "800000000000000000000000000000000000000000000000000000000000000000000000100000000000000001", -+ "5667676A654B20754F356EA92017D946567C46675556F19556A04616B567D223A5E05656FB549016A96656A557", -+ "2472E2D0197C49363F1FE7F5B6DB075D52B6947D135D8CA445805D39BC345626089687742B6329E70680231988", -+ "3C258EF3047767E7EDE0F1FDAA79DAEE3841366A132E163ACED4ED2401DF9C6BDCDE98E8E707C07A2239B1B097", -+ "53D7E08529547048121E9C95F3791DD804963948F34FAE7BF44EA82365DC7868FE57E4AE2DE211305A407104BD", -+ "01AF286BCA1AF286BCA1AF286BCA1AF286BCA1AF286BC9FB8F6B85C556892C20A7EB964FE7719E74F490758D3B", 0x4C -+}; -+ -+static const ECCurveParams ecCurve_X9_62_CHAR2_PNB368W1 = { -+ "X9.62 C2-PNB368W1", ECField_GF2m, 368, -+ "0100000000000000000000000000000000000000000000000000000000000000000000002000000000000000000007", -+ "E0D2EE25095206F5E2A4F9ED229F1F256E79A0E2B455970D8D0D865BD94778C576D62F0AB7519CCD2A1A906AE30D", -+ "FC1217D4320A90452C760A58EDCD30C8DD069B3C34453837A34ED50CB54917E1C2112D84D164F444F8F74786046A", -+ "1085E2755381DCCCE3C1557AFA10C2F0C0C2825646C5B34A394CBCFA8BC16B22E7E789E927BE216F02E1FB136A5F", -+ "7B3EB1BDDCBA62D5D8B2059B525797FC73822C59059C623A45FF3843CEE8F87CD1855ADAA81E2A0750B80FDA2310", -+ "00010090512DA9AF72B08349D98A5DD4C7B0532ECA51CE03E2D10F3B7AC579BD87E909AE40A6F131E9CFCE5BD967", 0xFF70 -+}; -+ -+static const ECCurveParams ecCurve_X9_62_CHAR2_TNB431R1 = { -+ "X9.62 C2-TNB431R1", ECField_GF2m, 431, -+ "800000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000001", -+ "1A827EF00DD6FC0E234CAF046C6A5D8A85395B236CC4AD2CF32A0CADBDC9DDF620B0EB9906D0957F6C6FEACD615468DF104DE296CD8F", -+ "10D9B4A3D9047D8B154359ABFB1B7F5485B04CEB868237DDC9DEDA982A679A5A919B626D4E50A8DD731B107A9962381FB5D807BF2618", -+ "120FC05D3C67A99DE161D2F4092622FECA701BE4F50F4758714E8A87BBF2A658EF8C21E7C5EFE965361F6C2999C0C247B0DBD70CE6B7", -+ "20D0AF8903A96F8D5FA2C255745D3C451B302C9346D9B7E485E7BCE41F6B591F3E8F6ADDCBB0BC4C2F947A7DE1A89B625D6A598B3760", -+ "0340340340340340340340340340340340340340340340340340340323C313FAB50589703B5EC68D3587FEC60D161CC149C1AD4A91", 0x2760 -+}; -+ - /* SEC2 prime curves */ -+static const ECCurveParams ecCurve_SECG_PRIME_112R1 = { -+ "SECP-112R1", ECField_GFp, 112, -+ "DB7C2ABF62E35E668076BEAD208B", -+ "DB7C2ABF62E35E668076BEAD2088", -+ "659EF8BA043916EEDE8911702B22", -+ "09487239995A5EE76B55F9C2F098", -+ "A89CE5AF8724C0A23E0E0FF77500", -+ "DB7C2ABF62E35E7628DFAC6561C5", 1 -+}; -+ -+static const ECCurveParams ecCurve_SECG_PRIME_112R2 = { -+ "SECP-112R2", ECField_GFp, 112, -+ "DB7C2ABF62E35E668076BEAD208B", -+ "6127C24C05F38A0AAAF65C0EF02C", -+ "51DEF1815DB5ED74FCC34C85D709", -+ "4BA30AB5E892B4E1649DD0928643", -+ "adcd46f5882e3747def36e956e97", -+ "36DF0AAFD8B8D7597CA10520D04B", 4 -+}; -+ -+static const ECCurveParams ecCurve_SECG_PRIME_128R1 = { -+ "SECP-128R1", ECField_GFp, 128, -+ "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF", -+ "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFC", -+ "E87579C11079F43DD824993C2CEE5ED3", -+ "161FF7528B899B2D0C28607CA52C5B86", -+ "CF5AC8395BAFEB13C02DA292DDED7A83", -+ "FFFFFFFE0000000075A30D1B9038A115", 1 -+}; -+ -+static const ECCurveParams ecCurve_SECG_PRIME_128R2 = { -+ "SECP-128R2", ECField_GFp, 128, -+ "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF", -+ "D6031998D1B3BBFEBF59CC9BBFF9AEE1", -+ "5EEEFCA380D02919DC2C6558BB6D8A5D", -+ "7B6AA5D85E572983E6FB32A7CDEBC140", -+ "27B6916A894D3AEE7106FE805FC34B44", -+ "3FFFFFFF7FFFFFFFBE0024720613B5A3", 4 -+}; -+ -+static const ECCurveParams ecCurve_SECG_PRIME_160K1 = { -+ "SECP-160K1", ECField_GFp, 160, -+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73", -+ "0000000000000000000000000000000000000000", -+ "0000000000000000000000000000000000000007", -+ "3B4C382CE37AA192A4019E763036F4F5DD4D7EBB", -+ "938CF935318FDCED6BC28286531733C3F03C4FEE", -+ "0100000000000000000001B8FA16DFAB9ACA16B6B3", 1 -+}; -+ -+static const ECCurveParams ecCurve_SECG_PRIME_160R1 = { -+ "SECP-160R1", ECField_GFp, 160, -+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF", -+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC", -+ "1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45", -+ "4A96B5688EF573284664698968C38BB913CBFC82", -+ "23A628553168947D59DCC912042351377AC5FB32", -+ "0100000000000000000001F4C8F927AED3CA752257", 1 -+}; -+ -+static const ECCurveParams ecCurve_SECG_PRIME_160R2 = { -+ "SECP-160R2", ECField_GFp, 160, -+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73", -+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC70", -+ "B4E134D3FB59EB8BAB57274904664D5AF50388BA", -+ "52DCB034293A117E1F4FF11B30F7199D3144CE6D", -+ "FEAFFEF2E331F296E071FA0DF9982CFEA7D43F2E", -+ "0100000000000000000000351EE786A818F3A1A16B", 1 -+}; -+ -+static const ECCurveParams ecCurve_SECG_PRIME_192K1 = { -+ "SECP-192K1", ECField_GFp, 192, -+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37", -+ "000000000000000000000000000000000000000000000000", -+ "000000000000000000000000000000000000000000000003", -+ "DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D", -+ "9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D", -+ "FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D", 1 -+}; -+ -+static const ECCurveParams ecCurve_SECG_PRIME_224K1 = { -+ "SECP-224K1", ECField_GFp, 224, -+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFE56D", -+ "00000000000000000000000000000000000000000000000000000000", -+ "00000000000000000000000000000000000000000000000000000005", -+ "A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C", -+ "7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5", -+ "010000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7", 1 -+}; -+ - static const ECCurveParams ecCurve_SECG_PRIME_256K1 = { - "SECP-256K1", ECField_GFp, 256, - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", -@@ -88,70 +511,222 @@ - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", 1 - }; + if (!argIsQuoted) { +- char testEscape[] = ESCAPE_VERIFICATION[verificationType]; +- for (int i = 0; i < testEscape.length; ++i) { +- if (arg.indexOf(testEscape[i]) >= 0) { ++ for (int i = 0; i < arg.length(); i++) { ++ char ch = arg.charAt(i); ++ if (Character.isLetterOrDigit(ch)) ++ continue; // skip over common characters ++ // All space chars require quotes and other mode specific characters ++ if (Character.isSpaceChar(ch) || ++ Character.isWhitespace(ch) || ++ ESCAPE_VERIFICATION[verificationType].indexOf(ch) >= 0) { + return true; + } + } +diff --git a/src/java.base/windows/native/libjava/java_props_md.c b/src/java.base/windows/native/libjava/java_props_md.c +index c63c7b71b..89c3a44cb 100644 +--- a/src/java.base/windows/native/libjava/java_props_md.c ++++ b/src/java.base/windows/native/libjava/java_props_md.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 1998, 2024, 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 +@@ -486,6 +486,8 @@ GetJavaProperties(JNIEnv* env) + * where (buildNumber > 17762) + * Windows Server 2022 10 0 (!VER_NT_WORKSTATION) + * where (buildNumber > 20347) ++ * Windows Server 2025 10 0 (!VER_NT_WORKSTATION) ++ * where (buildNumber > 26039) + * + * This mapping will presumably be augmented as new Windows + * versions are released. +@@ -569,7 +571,10 @@ GetJavaProperties(JNIEnv* env) + case 0: + /* Windows server 2019 GA 10/2018 build number is 17763 */ + /* Windows server 2022 build number is 20348 */ +- if (buildNumber > 20347) { ++ /* Windows server 2025 Preview build is 26040 */ ++ if (buildNumber > 26039) { ++ sprops.os_name = "Windows Server 2025"; ++ } else if (buildNumber > 20347) { + sprops.os_name = "Windows Server 2022"; + } else if (buildNumber > 17676) { + sprops.os_name = "Windows Server 2019"; +diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaTabbedPaneCopyFromBasicUI.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaTabbedPaneCopyFromBasicUI.java +index 066fc16d6..40ed43630 100644 +--- a/src/java.desktop/macosx/classes/com/apple/laf/AquaTabbedPaneCopyFromBasicUI.java ++++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaTabbedPaneCopyFromBasicUI.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -404,7 +404,11 @@ public class AquaTabbedPaneCopyFromBasicUI extends TabbedPaneUI implements Swing + } + tabPane.addContainerListener(getHandler()); + if (tabPane.getTabCount() > 0) { +- htmlViews = createHTMLVector(); ++ Boolean htmlDisabled = (Boolean) ++ tabPane.getClientProperty("html.disable"); ++ if (!(Boolean.TRUE.equals(htmlDisabled))) { ++ htmlViews = createHTMLVector(); ++ } + } + } -+/* SEC2 binary curves */ -+static const ECCurveParams ecCurve_SECG_CHAR2_113R1 = { -+ "SECT-113R1", ECField_GF2m, 113, -+ "020000000000000000000000000201", -+ "003088250CA6E7C7FE649CE85820F7", -+ "00E8BEE4D3E2260744188BE0E9C723", -+ "009D73616F35F4AB1407D73562C10F", -+ "00A52830277958EE84D1315ED31886", -+ "0100000000000000D9CCEC8A39E56F", 2 -+}; -+ -+static const ECCurveParams ecCurve_SECG_CHAR2_113R2 = { -+ "SECT-113R2", ECField_GF2m, 113, -+ "020000000000000000000000000201", -+ "00689918DBEC7E5A0DD6DFC0AA55C7", -+ "0095E9A9EC9B297BD4BF36E059184F", -+ "01A57A6A7B26CA5EF52FCDB8164797", -+ "00B3ADC94ED1FE674C06E695BABA1D", -+ "010000000000000108789B2496AF93", 2 -+}; -+ -+static const ECCurveParams ecCurve_SECG_CHAR2_131R1 = { -+ "SECT-131R1", ECField_GF2m, 131, -+ "080000000000000000000000000000010D", -+ "07A11B09A76B562144418FF3FF8C2570B8", -+ "0217C05610884B63B9C6C7291678F9D341", -+ "0081BAF91FDF9833C40F9C181343638399", -+ "078C6E7EA38C001F73C8134B1B4EF9E150", -+ "0400000000000000023123953A9464B54D", 2 -+}; -+ -+static const ECCurveParams ecCurve_SECG_CHAR2_131R2 = { -+ "SECT-131R2", ECField_GF2m, 131, -+ "080000000000000000000000000000010D", -+ "03E5A88919D7CAFCBF415F07C2176573B2", -+ "04B8266A46C55657AC734CE38F018F2192", -+ "0356DCD8F2F95031AD652D23951BB366A8", -+ "0648F06D867940A5366D9E265DE9EB240F", -+ "0400000000000000016954A233049BA98F", 2 -+}; -+ -+static const ECCurveParams ecCurve_SECG_CHAR2_163R1 = { -+ "SECT-163R1", ECField_GF2m, 163, -+ "0800000000000000000000000000000000000000C9", -+ "07B6882CAAEFA84F9554FF8428BD88E246D2782AE2", -+ "0713612DCDDCB40AAB946BDA29CA91F73AF958AFD9", -+ "0369979697AB43897789566789567F787A7876A654", -+ "00435EDB42EFAFB2989D51FEFCE3C80988F41FF883", -+ "03FFFFFFFFFFFFFFFFFFFF48AAB689C29CA710279B", 2 -+}; -+ -+static const ECCurveParams ecCurve_SECG_CHAR2_193R1 = { -+ "SECT-193R1", ECField_GF2m, 193, -+ "02000000000000000000000000000000000000000000008001", -+ "0017858FEB7A98975169E171F77B4087DE098AC8A911DF7B01", -+ "00FDFB49BFE6C3A89FACADAA7A1E5BBC7CC1C2E5D831478814", -+ "01F481BC5F0FF84A74AD6CDF6FDEF4BF6179625372D8C0C5E1", -+ "0025E399F2903712CCF3EA9E3A1AD17FB0B3201B6AF7CE1B05", -+ "01000000000000000000000000C7F34A778F443ACC920EBA49", 2 -+}; -+ -+static const ECCurveParams ecCurve_SECG_CHAR2_193R2 = { -+ "SECT-193R2", ECField_GF2m, 193, -+ "02000000000000000000000000000000000000000000008001", -+ "0163F35A5137C2CE3EA6ED8667190B0BC43ECD69977702709B", -+ "00C9BB9E8927D4D64C377E2AB2856A5B16E3EFB7F61D4316AE", -+ "00D9B67D192E0367C803F39E1A7E82CA14A651350AAE617E8F", -+ "01CE94335607C304AC29E7DEFBD9CA01F596F927224CDECF6C", -+ "010000000000000000000000015AAB561B005413CCD4EE99D5", 2 -+}; -+ -+static const ECCurveParams ecCurve_SECG_CHAR2_239K1 = { -+ "SECT-239K1", ECField_GF2m, 239, -+ "800000000000000000004000000000000000000000000000000000000001", -+ "000000000000000000000000000000000000000000000000000000000000", -+ "000000000000000000000000000000000000000000000000000000000001", -+ "29A0B6A887A983E9730988A68727A8B2D126C44CC2CC7B2A6555193035DC", -+ "76310804F12E549BDB011C103089E73510ACB275FC312A5DC6B76553F0CA", -+ "2000000000000000000000000000005A79FEC67CB6E91F1C1DA800E478A5", 4 -+}; -+ -+/* WTLS curves */ -+static const ECCurveParams ecCurve_WTLS_1 = { -+ "WTLS-1", ECField_GF2m, 113, -+ "020000000000000000000000000201", -+ "000000000000000000000000000001", -+ "000000000000000000000000000001", -+ "01667979A40BA497E5D5C270780617", -+ "00F44B4AF1ECC2630E08785CEBCC15", -+ "00FFFFFFFFFFFFFFFDBF91AF6DEA73", 2 -+}; -+ -+static const ECCurveParams ecCurve_WTLS_8 = { -+ "WTLS-8", ECField_GFp, 112, -+ "FFFFFFFFFFFFFFFFFFFFFFFFFDE7", -+ "0000000000000000000000000000", -+ "0000000000000000000000000003", -+ "0000000000000000000000000001", -+ "0000000000000000000000000002", -+ "0100000000000001ECEA551AD837E9", 1 -+}; -+ -+static const ECCurveParams ecCurve_WTLS_9 = { -+ "WTLS-9", ECField_GFp, 160, -+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC808F", -+ "0000000000000000000000000000000000000000", -+ "0000000000000000000000000000000000000003", -+ "0000000000000000000000000000000000000001", -+ "0000000000000000000000000000000000000002", -+ "0100000000000000000001CDC98AE0E2DE574ABF33", 1 -+}; +@@ -3443,8 +3447,10 @@ public class AquaTabbedPaneCopyFromBasicUI extends TabbedPaneUI implements Swing + + private void updateHtmlViews(int index, boolean inserted) { + final String title = tabPane.getTitleAt(index); ++ Boolean htmlDisabled = (Boolean) ++ tabPane.getClientProperty("html.disable"); + final boolean isHTML = BasicHTML.isHTMLString(title); +- if (isHTML) { ++ if (isHTML && !(Boolean.TRUE.equals(htmlDisabled))) { + if (htmlViews == null) { // Initialize vector + htmlViews = createHTMLVector(); + } else { // Vector already exists +diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m +index 1bf9feda7..387314bfb 100644 +--- a/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m ++++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m +@@ -39,6 +39,9 @@ + // keyboard layout + static NSString *kbdLayout; + ++// Constant for keyman layouts ++#define KEYMAN_LAYOUT "keyman" + -+static const ECCurveParams ecCurve_BrainpoolP256r1 = { -+ "brainpoolP256r1", ECField_GFp, 256, -+ "A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377", -+ "7D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9", -+ "26DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B6", -+ "8BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262", -+ "547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997", -+ "A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7", 1 -+}; + @interface AWTView() + @property (retain) CDropTarget *_dropTarget; + @property (retain) CDragSource *_dragSource; +@@ -281,7 +284,7 @@ static BOOL shouldUsePressAndHold() { + + - (void) keyDown: (NSEvent *)event { + fProcessingKeystroke = YES; +- fKeyEventsNeeded = YES; ++ fKeyEventsNeeded = ![(NSString *)kbdLayout containsString:@KEYMAN_LAYOUT]; + + // Allow TSM to look at the event and potentially send back NSTextInputClient messages. + [self interpretKeyEvents:[NSArray arrayWithObject:event]]; +@@ -989,7 +992,7 @@ static jclass jc_CInputMethod = NULL; + + if ((utf16Length > 2) || + ((utf8Length > 1) && [self isCodePointInUnicodeBlockNeedingIMEvent:codePoint]) || +- ((codePoint == 0x5c) && ([(NSString *)kbdLayout containsString:@"Kotoeri"]))) { ++ [(NSString *)kbdLayout containsString:@KEYMAN_LAYOUT]) { + aStringIsComplex = YES; + } + +diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.m +index 7fe2e394c..fd31a9d19 100644 +--- a/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.m ++++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.m +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2011, 2024, 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 +@@ -1647,6 +1647,7 @@ JNI_COCOA_ENTER(env); + int shieldLevel = CGShieldingWindowLevel(); + window.preFullScreenLevel = [nsWindow level]; + [nsWindow setLevel: shieldLevel]; ++ [nsWindow makeKeyAndOrderFront: nil]; + + NSRect screenRect = [[nsWindow screen] frame]; + [nsWindow setFrame:screenRect display:YES]; +diff --git a/src/java.desktop/macosx/native/libawt_lwawt/font/AWTStrike.m b/src/java.desktop/macosx/native/libawt_lwawt/font/AWTStrike.m +index 2c991a2fc..a35d54014 100644 +--- a/src/java.desktop/macosx/native/libawt_lwawt/font/AWTStrike.m ++++ b/src/java.desktop/macosx/native/libawt_lwawt/font/AWTStrike.m +@@ -151,7 +151,7 @@ JNI_COCOA_ENTER(env); + // to indicate we should use CoreText to substitute the character + CGGlyph glyph; + const CTFontRef fallback = CTS_CopyCTFallbackFontAndGlyphForJavaGlyphCode(awtFont, glyphCode, &glyph); +- CTFontGetAdvancesForGlyphs(fallback, kCTFontDefaultOrientation, &glyph, &advance, 1); ++ CGGlyphImages_GetGlyphMetrics(fallback, &awtStrike->fAltTx, awtStrike->fStyle, &glyph, 1, NULL, &advance); + CFRelease(fallback); + advance = CGSizeApplyAffineTransform(advance, awtStrike->fFontTx); + if (!JRSFontStyleUsesFractionalMetrics(awtStrike->fStyle)) { +@@ -188,7 +188,7 @@ JNI_COCOA_ENTER(env); + const CTFontRef fallback = CTS_CopyCTFallbackFontAndGlyphForJavaGlyphCode(awtFont, glyphCode, &glyph); + + CGRect bbox; +- JRSFontGetBoundingBoxesForGlyphsAndStyle(fallback, &tx, awtStrike->fStyle, &glyph, 1, &bbox); ++ CGGlyphImages_GetGlyphMetrics(fallback, &tx, awtStrike->fStyle, &glyph, 1, &bbox, NULL); + CFRelease(fallback); + + // the origin of this bounding box is relative to the bottom-left corner baseline +diff --git a/src/java.desktop/macosx/native/libawt_lwawt/font/CGGlyphImages.h b/src/java.desktop/macosx/native/libawt_lwawt/font/CGGlyphImages.h +index 73cb604bc..736167d2a 100644 +--- a/src/java.desktop/macosx/native/libawt_lwawt/font/CGGlyphImages.h ++++ b/src/java.desktop/macosx/native/libawt_lwawt/font/CGGlyphImages.h +@@ -33,5 +33,12 @@ void + CGGlyphImages_GetGlyphImagePtrs(jlong glyphInfos[], + const AWTStrike *strike, + jint rawGlyphCodes[], const CFIndex len); +- ++void ++CGGlyphImages_GetGlyphMetrics(const CTFontRef font, ++ const CGAffineTransform *tx, ++ const JRSFontRenderingStyle style, ++ const CGGlyph glyphs[], ++ size_t count, ++ CGRect bboxes[], ++ CGSize advances[]); + #endif /* __CGGLYPHIMAGES_H */ +diff --git a/src/java.desktop/macosx/native/libawt_lwawt/font/CGGlyphImages.m b/src/java.desktop/macosx/native/libawt_lwawt/font/CGGlyphImages.m +index d8deec3b2..d15fcb67c 100644 +--- a/src/java.desktop/macosx/native/libawt_lwawt/font/CGGlyphImages.m ++++ b/src/java.desktop/macosx/native/libawt_lwawt/font/CGGlyphImages.m +@@ -237,6 +237,7 @@ CGGI_CopyImageFromCanvasToRGBInfo(CGGI_GlyphCanvas *canvas, GlyphInfo *info) + { + UInt32 *src = (UInt32 *)canvas->image->data; + size_t srcRowWidth = canvas->image->width; ++ size_t srcHeight = canvas->image->height; + + UInt8 *dest = (UInt8 *)info->image; + size_t destRowWidth = info->width; +@@ -246,12 +247,12 @@ CGGI_CopyImageFromCanvasToRGBInfo(CGGI_GlyphCanvas *canvas, GlyphInfo *info) + size_t y; + + // fill empty glyph image with black-on-white glyph +- for (y = 0; y < height; y++) { ++ for (y = 0; y < height && y < srcHeight; y++) { + size_t destRow = y * destRowWidth * 3; + size_t srcRow = y * srcRowWidth; + + size_t x; +- for (x = 0; x < destRowWidth; x++) { ++ for (x = 0; x < destRowWidth && x < srcRowWidth; x++) { + CGGI_CopyARGBPixelToRGBPixel(src[srcRow + x], + dest + destRow + x * 3); + } +@@ -289,6 +290,7 @@ CGGI_CopyImageFromCanvasToAlphaInfo(CGGI_GlyphCanvas *canvas, GlyphInfo *info) + { + UInt32 *src = (UInt32 *)canvas->image->data; + size_t srcRowWidth = canvas->image->width; ++ size_t srcHeight = canvas->image->height; + + UInt8 *dest = (UInt8 *)info->image; + size_t destRowWidth = info->width; +@@ -298,11 +300,11 @@ CGGI_CopyImageFromCanvasToAlphaInfo(CGGI_GlyphCanvas *canvas, GlyphInfo *info) + size_t y; + + // fill empty glyph image with black-on-white glyph +- for (y = 0; y < height; y++) { ++ for (y = 0; y < height && y < srcHeight; y++) { + size_t destRow = y * destRowWidth; + size_t srcRow = y * srcRowWidth; + size_t x; +- for (x = 0; x < destRowWidth; x++) { ++ for (x = 0; x < destRowWidth && x < srcRowWidth; x++) { + UInt32 p = src[srcRow + x]; + dest[destRow + x] = CGGI_ConvertBWPixelToByteGray(p); + } +@@ -384,8 +386,10 @@ CGGI_InitCanvas(CGGI_GlyphCanvas *canvas, + + canvas->image->data = (void *)calloc(byteCount, sizeof(UInt8)); + if (canvas->image->data == NULL) { +- [[NSException exceptionWithName:NSMallocException +- reason:@"Failed to allocate memory for the buffer which backs the CGContext for glyph strikes." userInfo:nil] raise]; ++ canvas->image->width = 0; ++ canvas->image->height = 0; ++ canvas->image->rowBytes = 0; ++ canvas->image->data = malloc(0); + } + + uint32_t bmpInfo = kCGImageAlphaPremultipliedFirst; +@@ -435,6 +439,10 @@ CGGI_FreeCanvas(CGGI_GlyphCanvas *canvas) + + /* + * Quick and easy inline to check if this canvas is big enough. ++ * This function only increases the size. To get a smaller canvas, free it first. ++ * This function adds padding / slack multiplier to the requested size. ++ * So resizes must be based on the size you need, not the size of the canvas. ++ * The function will internally account for the multiplier it uses. + */ + static inline void + CGGI_SizeCanvas(CGGI_GlyphCanvas *canvas, const vImagePixelCount width, +@@ -442,18 +450,31 @@ CGGI_SizeCanvas(CGGI_GlyphCanvas *canvas, const vImagePixelCount width, + const CGGI_RenderingMode* mode) + { + if (canvas->image != NULL && +- width < canvas->image->width && +- height < canvas->image->height) ++ width * CGGI_GLYPH_CANVAS_SLACK <= canvas->image->width && ++ height * CGGI_GLYPH_CANVAS_SLACK <= canvas->image->height) + { + return; + } + ++ vImagePixelCount w = width * CGGI_GLYPH_CANVAS_SLACK; ++ vImagePixelCount h = height * CGGI_GLYPH_CANVAS_SLACK; + -+static const ECCurveParams ecCurve_BrainpoolP320r1 = { -+ "brainpoolP320r1", ECField_GFp, 320, -+ "D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E27", -+ "3EE30B568FBAB0F883CCEBD46D3F3BB8A2A73513F5EB79DA66190EB085FFA9F492F375A97D860EB4", -+ "520883949DFDBC42D3AD198640688A6FE13F41349554B49ACC31DCCD884539816F5EB4AC8FB1F1A6", -+ "43BD7E9AFB53D8B85289BCC48EE5BFE6F20137D10A087EB6E7871E2A10A599C710AF8D0D39E20611", -+ "14FDD05545EC1CC8AB4093247F77275E0743FFED117182EAA9C77877AAAC6AC7D35245D1692E8EE1", -+ "D35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D482EC7EE8658E98691555B44C59311", 1 -+}; ++ // Do not allow the canvas to be resized smaller. ++ if (canvas->image != NULL) { ++ if (w < canvas->image->width) { ++ w = canvas->image->width; ++ } ++ if (h < canvas->image->height) { ++ h = canvas->image->height; ++ } ++ } + -+static const ECCurveParams ecCurve_BrainpoolP384r1 = { -+ "brainpoolP384r1", ECField_GFp, 384, -+ "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53", -+ "7BC382C63D8C150C3C72080ACE05AFA0C2BEA28E4FB22787139165EFBA91F90F8AA5814A503AD4EB04A8C7DD22CE2826", -+ "04A8C7DD22CE28268B39B55416F0447C2FB77DE107DCD2A62E880EA53EEB62D57CB4390295DBC9943AB78696FA504C11", -+ "1D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10E8E826E03436D646AAEF87B2E247D4AF1E", -+ "8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129280E4646217791811142820341263C5315", -+ "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565", 1 -+}; + // if we don't have enough space to strike the largest glyph in the + // run, resize the canvas + CGGI_FreeCanvas(canvas); + CGGI_InitCanvas(canvas, +- width * CGGI_GLYPH_CANVAS_SLACK, +- height * CGGI_GLYPH_CANVAS_SLACK, ++ w, ++ h, + mode); + JRSFontSetRenderingStyleOnContext(canvas->context, mode->cgFontMode); + } +@@ -469,6 +490,12 @@ CGGI_ClearCanvas(CGGI_GlyphCanvas *canvas, GlyphInfo *info) + canvasRectToClear.data = canvas->image->data; + canvasRectToClear.height = info->height; + canvasRectToClear.width = info->width; ++ if (canvas->image->width < canvasRectToClear.width) { ++ canvasRectToClear.width = canvas->image->width; ++ } ++ if (canvas->image->height < canvasRectToClear.height) { ++ canvasRectToClear.height = canvas->image->height; ++ } + // use the row stride of the canvas, not the info + canvasRectToClear.rowBytes = canvas->image->rowBytes; + +@@ -615,10 +642,8 @@ CGGI_CreateImageForUnicode + JRSFontRenderingStyle style = JRSFontAlignStyleForFractionalMeasurement(strike->fStyle); + + CGRect bbox; +- JRSFontGetBoundingBoxesForGlyphsAndStyle(fallback, &tx, style, &glyph, 1, &bbox); +- + CGSize advance; +- CTFontGetAdvancesForGlyphs(fallback, kCTFontDefaultOrientation, &glyph, &advance, 1); ++ CGGlyphImages_GetGlyphMetrics(fallback, &tx, style, &glyph, 1, &bbox, &advance); + + // create the Sun2D GlyphInfo we are going to strike into + GlyphInfo *info = CGGI_CreateNewGlyphInfoFrom(advance, bbox, strike, mode); +@@ -774,8 +799,8 @@ CGGI_CreateGlyphInfos(jlong *glyphInfos, const AWTStrike *strike, + CGAffineTransform tx = strike->fTx; + JRSFontRenderingStyle bboxCGMode = JRSFontAlignStyleForFractionalMeasurement(strike->fStyle); + +- JRSFontGetBoundingBoxesForGlyphsAndStyle((CTFontRef)font->fFont, &tx, bboxCGMode, glyphs, len, bboxes); +- CTFontGetAdvancesForGlyphs((CTFontRef)font->fFont, kCTFontDefaultOrientation, glyphs, advances, len); ++ CTFontRef fontRef = (CTFontRef)font->fFont; ++ CGGlyphImages_GetGlyphMetrics(fontRef, &tx, bboxCGMode, glyphs, len, bboxes, advances); + + size_t maxWidth = 1; + size_t maxHeight = 1; +@@ -793,7 +818,6 @@ CGGI_CreateGlyphInfos(jlong *glyphInfos, const AWTStrike *strike, + CGRect bbox = bboxes[i]; + + GlyphInfo *glyphInfo = CGGI_CreateNewGlyphInfoFrom(advance, bbox, strike, mode); +- + if (maxWidth < glyphInfo->width) maxWidth = glyphInfo->width; + if (maxHeight < glyphInfo->height) maxHeight = glyphInfo->height; + +@@ -869,22 +893,68 @@ CGGlyphImages_GetGlyphImagePtrs(jlong glyphInfos[], + return; + } + +- // just do one malloc, and carve it up for all the buffers +- void *buffer = malloc(sizeof(CGRect) * sizeof(CGSize) * +- sizeof(CGGlyph) * sizeof(UnicodeScalarValue) * len); +- if (buffer == NULL) { ++ CGRect *bboxes = (CGRect*)calloc(len, sizeof(CGRect)); ++ CGSize *advances = (CGSize*)calloc(len, sizeof(CGSize)); ++ CGGlyph *glyphs = (CGGlyph*)calloc(len, sizeof(CGGlyph)); ++ UnicodeScalarValue *uniChars = (UnicodeScalarValue*)calloc(len, sizeof(UnicodeScalarValue)); ++ ++ if (bboxes == NULL || advances == NULL || glyphs == NULL || uniChars == NULL) { ++ free(bboxes); ++ free(advances); ++ free(glyphs); ++ free(uniChars); + [[NSException exceptionWithName:NSMallocException + reason:@"Failed to allocate memory for the temporary glyph strike and measurement buffers." userInfo:nil] raise]; + } + +- CGRect *bboxes = (CGRect *)(buffer); +- CGSize *advances = (CGSize *)(bboxes + sizeof(CGRect) * len); +- CGGlyph *glyphs = (CGGlyph *)(advances + sizeof(CGGlyph) * len); +- UnicodeScalarValue *uniChars = (UnicodeScalarValue *)(glyphs + sizeof(UnicodeScalarValue) * len); +- + CGGI_CreateGlyphsAndScanForComplexities(glyphInfos, strike, &mode, + rawGlyphCodes, uniChars, glyphs, + advances, bboxes, len); + +- free(buffer); ++ free(bboxes); ++ free(advances); ++ free(glyphs); ++ free(uniChars); ++} + -+static const ECCurveParams ecCurve_BrainpoolP512r1 = { -+ "brainpoolP512r1", ECField_GFp, 512, -+ "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3", -+ "7830A3318B603B89E2327145AC234CC594CBDD8D3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CA", -+ "3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CADC083E67984050B75EBAE5DD2809BD638016F723", -+ "81AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D0098EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F822", -+ "7DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F8111B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892", -+ "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069", 1 -+}; ++#define TX_FIXED_UNSAFE(v) (isinf(v) || isnan(v) || fabs(v) >= (1<<30)) + - /* mapping between ECCurveName enum and pointers to ECCurveParams */ - static const ECCurveParams *ecCurve_map[] = { - NULL, /* ECCurve_noName */ -- NULL, /* ECCurve_noName */ -- NULL, /* ECCurve_noName */ -+ &ecCurve_NIST_P192, /* ECCurve_NIST_P192 */ -+ &ecCurve_NIST_P224, /* ECCurve_NIST_P224 */ - &ecCurve_NIST_P256, /* ECCurve_NIST_P256 */ - &ecCurve_NIST_P384, /* ECCurve_NIST_P384 */ - &ecCurve_NIST_P521, /* ECCurve_NIST_P521 */ -- NULL, /* ECCurve_noName */ -- NULL, /* ECCurve_noName */ -- NULL, /* ECCurve_noName */ -- NULL, /* ECCurve_noName */ -- NULL, /* ECCurve_noName */ -- NULL, /* ECCurve_noName */ -- NULL, /* ECCurve_noName */ -- NULL, /* ECCurve_noName */ -- NULL, /* ECCurve_noName */ -- NULL, /* ECCurve_noName */ -- NULL, /* ECCurve_noName */ -- NULL, /* ECCurve_noName */ -- NULL, /* ECCurve_noName */ -- NULL, /* ECCurve_noName */ -- NULL, /* ECCurve_noName */ -- NULL, /* ECCurve_noName */ -- NULL, /* ECCurve_noName */ -- NULL, /* ECCurve_noName */ -- NULL, /* ECCurve_noName */ -- NULL, /* ECCurve_noName */ -- NULL, /* ECCurve_noName */ -- NULL, /* ECCurve_noName */ -- NULL, /* ECCurve_noName */ -- NULL, /* ECCurve_noName */ -- NULL, /* ECCurve_noName */ -- NULL, /* ECCurve_noName */ -- NULL, /* ECCurve_noName */ -- NULL, /* ECCurve_noName */ -- NULL, /* ECCurve_noName */ -- NULL, /* ECCurve_noName */ -- NULL, /* ECCurve_noName */ -- NULL, /* ECCurve_noName */ -- NULL, /* ECCurve_noName */ -- NULL, /* ECCurve_noName */ -- NULL, /* ECCurve_noName */ -- NULL, /* ECCurve_noName */ -- NULL, /* ECCurve_noName */ -- NULL, /* ECCurve_noName */ -- NULL, /* ECCurve_noName */ -- NULL, /* ECCurve_noName */ -+ &ecCurve_NIST_K163, /* ECCurve_NIST_K163 */ -+ &ecCurve_NIST_B163, /* ECCurve_NIST_B163 */ -+ &ecCurve_NIST_K233, /* ECCurve_NIST_K233 */ -+ &ecCurve_NIST_B233, /* ECCurve_NIST_B233 */ -+ &ecCurve_NIST_K283, /* ECCurve_NIST_K283 */ -+ &ecCurve_NIST_B283, /* ECCurve_NIST_B283 */ -+ &ecCurve_NIST_K409, /* ECCurve_NIST_K409 */ -+ &ecCurve_NIST_B409, /* ECCurve_NIST_B409 */ -+ &ecCurve_NIST_K571, /* ECCurve_NIST_K571 */ -+ &ecCurve_NIST_B571, /* ECCurve_NIST_B571 */ -+ &ecCurve_X9_62_PRIME_192V2, /* ECCurve_X9_62_PRIME_192V2 */ -+ &ecCurve_X9_62_PRIME_192V3, /* ECCurve_X9_62_PRIME_192V3 */ -+ &ecCurve_X9_62_PRIME_239V1, /* ECCurve_X9_62_PRIME_239V1 */ -+ &ecCurve_X9_62_PRIME_239V2, /* ECCurve_X9_62_PRIME_239V2 */ -+ &ecCurve_X9_62_PRIME_239V3, /* ECCurve_X9_62_PRIME_239V3 */ -+ &ecCurve_X9_62_CHAR2_PNB163V1, /* ECCurve_X9_62_CHAR2_PNB163V1 */ -+ &ecCurve_X9_62_CHAR2_PNB163V2, /* ECCurve_X9_62_CHAR2_PNB163V2 */ -+ &ecCurve_X9_62_CHAR2_PNB163V3, /* ECCurve_X9_62_CHAR2_PNB163V3 */ -+ &ecCurve_X9_62_CHAR2_PNB176V1, /* ECCurve_X9_62_CHAR2_PNB176V1 */ -+ &ecCurve_X9_62_CHAR2_TNB191V1, /* ECCurve_X9_62_CHAR2_TNB191V1 */ -+ &ecCurve_X9_62_CHAR2_TNB191V2, /* ECCurve_X9_62_CHAR2_TNB191V2 */ -+ &ecCurve_X9_62_CHAR2_TNB191V3, /* ECCurve_X9_62_CHAR2_TNB191V3 */ -+ &ecCurve_X9_62_CHAR2_PNB208W1, /* ECCurve_X9_62_CHAR2_PNB208W1 */ -+ &ecCurve_X9_62_CHAR2_TNB239V1, /* ECCurve_X9_62_CHAR2_TNB239V1 */ -+ &ecCurve_X9_62_CHAR2_TNB239V2, /* ECCurve_X9_62_CHAR2_TNB239V2 */ -+ &ecCurve_X9_62_CHAR2_TNB239V3, /* ECCurve_X9_62_CHAR2_TNB239V3 */ -+ &ecCurve_X9_62_CHAR2_PNB272W1, /* ECCurve_X9_62_CHAR2_PNB272W1 */ -+ &ecCurve_X9_62_CHAR2_PNB304W1, /* ECCurve_X9_62_CHAR2_PNB304W1 */ -+ &ecCurve_X9_62_CHAR2_TNB359V1, /* ECCurve_X9_62_CHAR2_TNB359V1 */ -+ &ecCurve_X9_62_CHAR2_PNB368W1, /* ECCurve_X9_62_CHAR2_PNB368W1 */ -+ &ecCurve_X9_62_CHAR2_TNB431R1, /* ECCurve_X9_62_CHAR2_TNB431R1 */ -+ &ecCurve_SECG_PRIME_112R1, /* ECCurve_SECG_PRIME_112R1 */ -+ &ecCurve_SECG_PRIME_112R2, /* ECCurve_SECG_PRIME_112R2 */ -+ &ecCurve_SECG_PRIME_128R1, /* ECCurve_SECG_PRIME_128R1 */ -+ &ecCurve_SECG_PRIME_128R2, /* ECCurve_SECG_PRIME_128R2 */ -+ &ecCurve_SECG_PRIME_160K1, /* ECCurve_SECG_PRIME_160K1 */ -+ &ecCurve_SECG_PRIME_160R1, /* ECCurve_SECG_PRIME_160R1 */ -+ &ecCurve_SECG_PRIME_160R2, /* ECCurve_SECG_PRIME_160R2 */ -+ &ecCurve_SECG_PRIME_192K1, /* ECCurve_SECG_PRIME_192K1 */ -+ &ecCurve_SECG_PRIME_224K1, /* ECCurve_SECG_PRIME_224K1 */ - &ecCurve_SECG_PRIME_256K1, /* ECCurve_SECG_PRIME_256K1 */ -- NULL, /* ECCurve_noName */ -- NULL, /* ECCurve_noName */ -- NULL, /* ECCurve_noName */ -- NULL, /* ECCurve_noName */ -- NULL, /* ECCurve_noName */ -- NULL, /* ECCurve_noName */ -- NULL, /* ECCurve_noName */ -- NULL, /* ECCurve_noName */ -- NULL, /* ECCurve_noName */ -- NULL, /* ECCurve_noName */ -- NULL, /* ECCurve_noName */ -- NULL, /* ECCurve_noName */ -- NULL, /* ECCurve_noName */ -- NULL, /* ECCurve_noName */ -- NULL, /* ECCurve_noName */ -+ &ecCurve_SECG_CHAR2_113R1, /* ECCurve_SECG_CHAR2_113R1 */ -+ &ecCurve_SECG_CHAR2_113R2, /* ECCurve_SECG_CHAR2_113R2 */ -+ &ecCurve_SECG_CHAR2_131R1, /* ECCurve_SECG_CHAR2_131R1 */ -+ &ecCurve_SECG_CHAR2_131R2, /* ECCurve_SECG_CHAR2_131R2 */ -+ &ecCurve_SECG_CHAR2_163R1, /* ECCurve_SECG_CHAR2_163R1 */ -+ &ecCurve_SECG_CHAR2_193R1, /* ECCurve_SECG_CHAR2_193R1 */ -+ &ecCurve_SECG_CHAR2_193R2, /* ECCurve_SECG_CHAR2_193R2 */ -+ &ecCurve_SECG_CHAR2_239K1, /* ECCurve_SECG_CHAR2_239K1 */ -+ &ecCurve_WTLS_1, /* ECCurve_WTLS_1 */ -+ &ecCurve_WTLS_8, /* ECCurve_WTLS_8 */ -+ &ecCurve_WTLS_9, /* ECCurve_WTLS_9 */ -+ &ecCurve_BrainpoolP256r1, /* ECCurve_BrainpoolP256r1 */ -+ &ecCurve_BrainpoolP320r1, /* ECCurve_BrainpoolP320r1 */ -+ &ecCurve_BrainpoolP384r1, /* ECCurve_brainpoolP384r1 */ -+ &ecCurve_BrainpoolP512r1, /* ECCurve_brainpoolP512r1 */ - NULL /* ECCurve_pastLastCurve */ - }; - -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.crypto.ec/share/native/libsunec/impl/ecp_192.c jdk11u-ls/src/jdk.crypto.ec/share/native/libsunec/impl/ecp_192.c ---- openjdk/src/jdk.crypto.ec/share/native/libsunec/impl/ecp_192.c 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/jdk.crypto.ec/share/native/libsunec/impl/ecp_192.c 2023-09-12 13:54:26.293575685 +0800 -@@ -0,0 +1,517 @@ +/* -+ * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. -+ * Use is subject to license terms. -+ * -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. -+ * -+ * This library 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 -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public License -+ * along with this library; if not, write to the Free Software Foundation, -+ * Inc., 51 Franklin Street, 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. ++ * Calculates bounding boxes (for given transform) and advance (for untransformed 1pt-size font) for specified glyphs. + */ -+ -+/* ********************************************************************* -+ * -+ * The Original Code is the elliptic curve math library for prime field curves. -+ * -+ * The Initial Developer of the Original Code is -+ * Sun Microsystems, Inc. -+ * Portions created by the Initial Developer are Copyright (C) 2003 -+ * the Initial Developer. All Rights Reserved. -+ * -+ * Contributor(s): -+ * Douglas Stebila , Sun Microsystems Laboratories -+ * -+ *********************************************************************** */ -+ -+#include "ecp.h" -+#include "mpi.h" -+#include "mplogic.h" -+#include "mpi-priv.h" -+#ifndef _KERNEL -+#include -+#endif -+ -+#define ECP192_DIGITS ECL_CURVE_DIGITS(192) -+ -+/* Fast modular reduction for p192 = 2^192 - 2^64 - 1. a can be r. Uses -+ * algorithm 7 from Brown, Hankerson, Lopez, Menezes. Software -+ * Implementation of the NIST Elliptic Curves over Prime Fields. */ -+mp_err -+ec_GFp_nistp192_mod(const mp_int *a, mp_int *r, const GFMethod *meth) -+{ -+ mp_err res = MP_OKAY; -+ mp_size a_used = MP_USED(a); -+ mp_digit r3; -+#ifndef MPI_AMD64_ADD -+ mp_digit carry; -+#endif -+#ifdef ECL_THIRTY_TWO_BIT -+ mp_digit a5a = 0, a5b = 0, a4a = 0, a4b = 0, a3a = 0, a3b = 0; -+ mp_digit r0a, r0b, r1a, r1b, r2a, r2b; -+#else -+ mp_digit a5 = 0, a4 = 0, a3 = 0; -+ mp_digit r0, r1, r2; -+#endif -+ -+ /* reduction not needed if a is not larger than field size */ -+ if (a_used < ECP192_DIGITS) { -+ if (a == r) { -+ return MP_OKAY; -+ } -+ return mp_copy(a, r); ++void ++CGGlyphImages_GetGlyphMetrics(const CTFontRef font, ++ const CGAffineTransform *tx, ++ const JRSFontRenderingStyle style, ++ const CGGlyph glyphs[], ++ size_t count, ++ CGRect bboxes[], ++ CGSize advances[]) { ++ ++ if (TX_FIXED_UNSAFE(tx->a) || TX_FIXED_UNSAFE(tx->b) || TX_FIXED_UNSAFE(tx->c) || ++ TX_FIXED_UNSAFE(tx->d) || TX_FIXED_UNSAFE(tx->tx) || TX_FIXED_UNSAFE(tx->tx)) { ++ ++ if (bboxes) { ++ for (int i = 0; i < count; i++) { ++ bboxes[i].origin.x = 0; ++ bboxes[i].origin.y = 0; ++ bboxes[i].size.width = 0; ++ bboxes[i].size.height = 0; ++ } + } ++ if (advances) { ++ for (int i = 0; i < count; i++) { ++ advances[i].width = 0; ++ advances[i].height = 0; ++ } ++ } ++ return; ++ } + -+ /* for polynomials larger than twice the field size, use regular -+ * reduction */ -+ if (a_used > ECP192_DIGITS*2) { -+ MP_CHECKOK(mp_mod(a, &meth->irr, r)); -+ } else { -+ /* copy out upper words of a */ -+ -+#ifdef ECL_THIRTY_TWO_BIT -+ -+ /* in all the math below, -+ * nXb is most signifiant, nXa is least significant */ -+ switch (a_used) { -+ case 12: -+ a5b = MP_DIGIT(a, 11); -+ case 11: -+ a5a = MP_DIGIT(a, 10); -+ case 10: -+ a4b = MP_DIGIT(a, 9); -+ case 9: -+ a4a = MP_DIGIT(a, 8); -+ case 8: -+ a3b = MP_DIGIT(a, 7); -+ case 7: -+ a3a = MP_DIGIT(a, 6); -+ } -+ ++ if (bboxes) { ++ JRSFontGetBoundingBoxesForGlyphsAndStyle(font, tx, style, glyphs, count, bboxes); ++ } ++ if (advances) { ++ CTFontGetAdvancesForGlyphs(font, kCTFontDefaultOrientation, glyphs, advances, count); ++ } + } +diff --git a/src/java.desktop/share/classes/com/sun/java/swing/SwingUtilities3.java b/src/java.desktop/share/classes/com/sun/java/swing/SwingUtilities3.java +index c6968c2eb..ad5991d4c 100644 +--- a/src/java.desktop/share/classes/com/sun/java/swing/SwingUtilities3.java ++++ b/src/java.desktop/share/classes/com/sun/java/swing/SwingUtilities3.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -32,11 +32,20 @@ import java.util.Collections; + import java.util.Map; + import java.util.WeakHashMap; + import java.applet.Applet; ++import java.awt.Color; + import java.awt.Component; + import java.awt.Container; ++import java.awt.Graphics; ++import java.awt.Insets; ++import java.awt.Rectangle; + import java.awt.Window; ++import javax.swing.ButtonModel; ++import javax.swing.Icon; + import javax.swing.JComponent; ++import javax.swing.JMenu; + import javax.swing.RepaintManager; ++import sun.swing.MenuItemLayoutHelper; ++import sun.swing.SwingUtilities2; + + /** + * A collection of utility methods for Swing. +@@ -111,6 +120,119 @@ public class SwingUtilities3 { + return Boolean.TRUE == vsyncedMap.get(rootContainer); + } + ++ public static void applyInsets(Rectangle rect, Insets insets) { ++ if (insets != null) { ++ rect.x += insets.left; ++ rect.y += insets.top; ++ rect.width -= (insets.right + rect.x); ++ rect.height -= (insets.bottom + rect.y); ++ } ++ } + -+ r2b= MP_DIGIT(a, 5); -+ r2a= MP_DIGIT(a, 4); -+ r1b = MP_DIGIT(a, 3); -+ r1a = MP_DIGIT(a, 2); -+ r0b = MP_DIGIT(a, 1); -+ r0a = MP_DIGIT(a, 0); -+ -+ /* implement r = (a2,a1,a0)+(a5,a5,a5)+(a4,a4,0)+(0,a3,a3) */ -+ MP_ADD_CARRY(r0a, a3a, r0a, 0, carry); -+ MP_ADD_CARRY(r0b, a3b, r0b, carry, carry); -+ MP_ADD_CARRY(r1a, a3a, r1a, carry, carry); -+ MP_ADD_CARRY(r1b, a3b, r1b, carry, carry); -+ MP_ADD_CARRY(r2a, a4a, r2a, carry, carry); -+ MP_ADD_CARRY(r2b, a4b, r2b, carry, carry); -+ r3 = carry; carry = 0; -+ MP_ADD_CARRY(r0a, a5a, r0a, 0, carry); -+ MP_ADD_CARRY(r0b, a5b, r0b, carry, carry); -+ MP_ADD_CARRY(r1a, a5a, r1a, carry, carry); -+ MP_ADD_CARRY(r1b, a5b, r1b, carry, carry); -+ MP_ADD_CARRY(r2a, a5a, r2a, carry, carry); -+ MP_ADD_CARRY(r2b, a5b, r2b, carry, carry); -+ r3 += carry; -+ MP_ADD_CARRY(r1a, a4a, r1a, 0, carry); -+ MP_ADD_CARRY(r1b, a4b, r1b, carry, carry); -+ MP_ADD_CARRY(r2a, 0, r2a, carry, carry); -+ MP_ADD_CARRY(r2b, 0, r2b, carry, carry); -+ r3 += carry; -+ -+ /* reduce out the carry */ -+ while (r3) { -+ MP_ADD_CARRY(r0a, r3, r0a, 0, carry); -+ MP_ADD_CARRY(r0b, 0, r0b, carry, carry); -+ MP_ADD_CARRY(r1a, r3, r1a, carry, carry); -+ MP_ADD_CARRY(r1b, 0, r1b, carry, carry); -+ MP_ADD_CARRY(r2a, 0, r2a, carry, carry); -+ MP_ADD_CARRY(r2b, 0, r2b, carry, carry); -+ r3 = carry; -+ } ++ public static void paintCheckIcon(Graphics g, MenuItemLayoutHelper lh, ++ MenuItemLayoutHelper.LayoutResult lr, ++ Color holdc, Color foreground) { ++ if (lh.getCheckIcon() != null) { ++ ButtonModel model = lh.getMenuItem().getModel(); ++ if (model.isArmed() || (lh.getMenuItem() instanceof JMenu ++ && model.isSelected())) { ++ g.setColor(foreground); ++ } else { ++ g.setColor(holdc); ++ } ++ if (lh.useCheckAndArrow()) { ++ lh.getCheckIcon().paintIcon(lh.getMenuItem(), g, ++ lr.getCheckRect().x, lr.getCheckRect().y); ++ } ++ g.setColor(holdc); ++ } ++ } + -+ /* check for final reduction */ -+ /* -+ * our field is 0xffffffffffffffff, 0xfffffffffffffffe, -+ * 0xffffffffffffffff. That means we can only be over and need -+ * one more reduction -+ * if r2 == 0xffffffffffffffffff (same as r2+1 == 0) -+ * and -+ * r1 == 0xffffffffffffffffff or -+ * r1 == 0xfffffffffffffffffe and r0 = 0xfffffffffffffffff -+ * In all cases, we subtract the field (or add the 2's -+ * complement value (1,1,0)). (r0, r1, r2) -+ */ -+ if (((r2b == 0xffffffff) && (r2a == 0xffffffff) -+ && (r1b == 0xffffffff) ) && -+ ((r1a == 0xffffffff) || -+ (r1a == 0xfffffffe) && (r0a == 0xffffffff) && -+ (r0b == 0xffffffff)) ) { -+ /* do a quick subtract */ -+ MP_ADD_CARRY(r0a, 1, r0a, 0, carry); -+ r0b += carry; -+ r1a = r1b = r2a = r2b = 0; ++ public static void paintIcon(Graphics g, MenuItemLayoutHelper lh, ++ MenuItemLayoutHelper.LayoutResult lr, Color holdc) { ++ if (lh.getIcon() != null) { ++ Icon icon; ++ ButtonModel model = lh.getMenuItem().getModel(); ++ if (!model.isEnabled()) { ++ icon = lh.getMenuItem().getDisabledIcon(); ++ } else if (model.isPressed() && model.isArmed()) { ++ icon = lh.getMenuItem().getPressedIcon(); ++ if (icon == null) { ++ // Use default icon ++ icon = lh.getMenuItem().getIcon(); + } ++ } else { ++ icon = lh.getMenuItem().getIcon(); ++ } + -+ /* set the lower words of r */ -+ if (a != r) { -+ MP_CHECKOK(s_mp_pad(r, 6)); -+ } -+ MP_DIGIT(r, 5) = r2b; -+ MP_DIGIT(r, 4) = r2a; -+ MP_DIGIT(r, 3) = r1b; -+ MP_DIGIT(r, 2) = r1a; -+ MP_DIGIT(r, 1) = r0b; -+ MP_DIGIT(r, 0) = r0a; -+ MP_USED(r) = 6; -+#else -+ switch (a_used) { -+ case 6: -+ a5 = MP_DIGIT(a, 5); -+ case 5: -+ a4 = MP_DIGIT(a, 4); -+ case 4: -+ a3 = MP_DIGIT(a, 3); -+ } ++ if (icon != null) { ++ icon.paintIcon(lh.getMenuItem(), g, lr.getIconRect().x, ++ lr.getIconRect().y); ++ g.setColor(holdc); ++ } ++ } ++ } + -+ r2 = MP_DIGIT(a, 2); -+ r1 = MP_DIGIT(a, 1); -+ r0 = MP_DIGIT(a, 0); -+ -+ /* implement r = (a2,a1,a0)+(a5,a5,a5)+(a4,a4,0)+(0,a3,a3) */ -+#ifndef MPI_AMD64_ADD -+ MP_ADD_CARRY_ZERO(r0, a3, r0, carry); -+ MP_ADD_CARRY(r1, a3, r1, carry, carry); -+ MP_ADD_CARRY(r2, a4, r2, carry, carry); -+ r3 = carry; -+ MP_ADD_CARRY_ZERO(r0, a5, r0, carry); -+ MP_ADD_CARRY(r1, a5, r1, carry, carry); -+ MP_ADD_CARRY(r2, a5, r2, carry, carry); -+ r3 += carry; -+ MP_ADD_CARRY_ZERO(r1, a4, r1, carry); -+ MP_ADD_CARRY(r2, 0, r2, carry, carry); -+ r3 += carry; + -+#else -+ r2 = MP_DIGIT(a, 2); -+ r1 = MP_DIGIT(a, 1); -+ r0 = MP_DIGIT(a, 0); -+ -+ /* set the lower words of r */ -+ __asm__ ( -+ "xorq %3,%3 \n\t" -+ "addq %4,%0 \n\t" -+ "adcq %4,%1 \n\t" -+ "adcq %5,%2 \n\t" -+ "adcq $0,%3 \n\t" -+ "addq %6,%0 \n\t" -+ "adcq %6,%1 \n\t" -+ "adcq %6,%2 \n\t" -+ "adcq $0,%3 \n\t" -+ "addq %5,%1 \n\t" -+ "adcq $0,%2 \n\t" -+ "adcq $0,%3 \n\t" -+ : "=r"(r0), "=r"(r1), "=r"(r2), "=r"(r3), "=r"(a3), -+ "=r"(a4), "=r"(a5) -+ : "0" (r0), "1" (r1), "2" (r2), "3" (r3), -+ "4" (a3), "5" (a4), "6"(a5) -+ : "%cc" ); -+#endif -+ -+ /* reduce out the carry */ -+ while (r3) { -+#ifndef MPI_AMD64_ADD -+ MP_ADD_CARRY_ZERO(r0, r3, r0, carry); -+ MP_ADD_CARRY(r1, r3, r1, carry, carry); -+ MP_ADD_CARRY(r2, 0, r2, carry, carry); -+ r3 = carry; -+#else -+ a3=r3; -+ __asm__ ( -+ "xorq %3,%3 \n\t" -+ "addq %4,%0 \n\t" -+ "adcq %4,%1 \n\t" -+ "adcq $0,%2 \n\t" -+ "adcq $0,%3 \n\t" -+ : "=r"(r0), "=r"(r1), "=r"(r2), "=r"(r3), "=r"(a3) -+ : "0" (r0), "1" (r1), "2" (r2), "3" (r3), "4"(a3) -+ : "%cc" ); -+#endif ++ public static void paintAccText(Graphics g, MenuItemLayoutHelper lh, ++ MenuItemLayoutHelper.LayoutResult lr, ++ Color disabledForeground, ++ Color acceleratorSelectionForeground, ++ Color acceleratorForeground) { ++ if (!lh.getAccText().isEmpty()) { ++ ButtonModel model = lh.getMenuItem().getModel(); ++ g.setFont(lh.getAccFontMetrics().getFont()); ++ if (!model.isEnabled()) { ++ ++ // paint the accText disabled ++ if (disabledForeground != null) { ++ g.setColor(disabledForeground); ++ SwingUtilities2.drawString(lh.getMenuItem(), g, ++ lh.getAccText(), lr.getAccRect().x, ++ lr.getAccRect().y + lh.getAccFontMetrics().getAscent()); ++ } else { ++ g.setColor(lh.getMenuItem().getBackground().brighter()); ++ SwingUtilities2.drawString(lh.getMenuItem(), g, ++ lh.getAccText(), lr.getAccRect().x, ++ lr.getAccRect().y + lh.getAccFontMetrics().getAscent()); ++ g.setColor(lh.getMenuItem().getBackground().darker()); ++ SwingUtilities2.drawString(lh.getMenuItem(), g, ++ lh.getAccText(), lr.getAccRect().x - 1, ++ lr.getAccRect().y + lh.getFontMetrics().getAscent() - 1); + } ++ } else { + -+ /* check for final reduction */ -+ /* -+ * our field is 0xffffffffffffffff, 0xfffffffffffffffe, -+ * 0xffffffffffffffff. That means we can only be over and need -+ * one more reduction -+ * if r2 == 0xffffffffffffffffff (same as r2+1 == 0) -+ * and -+ * r1 == 0xffffffffffffffffff or -+ * r1 == 0xfffffffffffffffffe and r0 = 0xfffffffffffffffff -+ * In all cases, we subtract the field (or add the 2's -+ * complement value (1,1,0)). (r0, r1, r2) -+ */ -+ if (r3 || ((r2 == MP_DIGIT_MAX) && -+ ((r1 == MP_DIGIT_MAX) || -+ ((r1 == (MP_DIGIT_MAX-1)) && (r0 == MP_DIGIT_MAX))))) { -+ /* do a quick subtract */ -+ r0++; -+ r1 = r2 = 0; -+ } -+ /* set the lower words of r */ -+ if (a != r) { -+ MP_CHECKOK(s_mp_pad(r, 3)); ++ // paint the accText normally ++ if (model.isArmed() ++ || (lh.getMenuItem() instanceof JMenu ++ && model.isSelected())) { ++ g.setColor(acceleratorSelectionForeground); ++ } else { ++ g.setColor(acceleratorForeground); + } -+ MP_DIGIT(r, 2) = r2; -+ MP_DIGIT(r, 1) = r1; -+ MP_DIGIT(r, 0) = r0; -+ MP_USED(r) = 3; -+#endif -+ } -+ -+ CLEANUP: -+ return res; -+} -+ -+#ifndef ECL_THIRTY_TWO_BIT -+/* Compute the sum of 192 bit curves. Do the work in-line since the -+ * number of words are so small, we don't want to overhead of mp function -+ * calls. Uses optimized modular reduction for p192. -+ */ -+mp_err -+ec_GFp_nistp192_add(const mp_int *a, const mp_int *b, mp_int *r, -+ const GFMethod *meth) -+{ -+ mp_err res = MP_OKAY; -+ mp_digit a0 = 0, a1 = 0, a2 = 0; -+ mp_digit r0 = 0, r1 = 0, r2 = 0; -+ mp_digit carry; -+ -+ switch(MP_USED(a)) { -+ case 3: -+ a2 = MP_DIGIT(a,2); -+ case 2: -+ a1 = MP_DIGIT(a,1); -+ case 1: -+ a0 = MP_DIGIT(a,0); -+ } -+ switch(MP_USED(b)) { -+ case 3: -+ r2 = MP_DIGIT(b,2); -+ case 2: -+ r1 = MP_DIGIT(b,1); -+ case 1: -+ r0 = MP_DIGIT(b,0); ++ SwingUtilities2.drawString(lh.getMenuItem(), g, lh.getAccText(), ++ lr.getAccRect().x, lr.getAccRect().y + ++ lh.getAccFontMetrics().getAscent()); ++ } + } ++ } + -+#ifndef MPI_AMD64_ADD -+ MP_ADD_CARRY_ZERO(a0, r0, r0, carry); -+ MP_ADD_CARRY(a1, r1, r1, carry, carry); -+ MP_ADD_CARRY(a2, r2, r2, carry, carry); -+#else -+ __asm__ ( -+ "xorq %3,%3 \n\t" -+ "addq %4,%0 \n\t" -+ "adcq %5,%1 \n\t" -+ "adcq %6,%2 \n\t" -+ "adcq $0,%3 \n\t" -+ : "=r"(r0), "=r"(r1), "=r"(r2), "=r"(carry) -+ : "r" (a0), "r" (a1), "r" (a2), "0" (r0), -+ "1" (r1), "2" (r2) -+ : "%cc" ); -+#endif -+ -+ /* Do quick 'subract' if we've gone over -+ * (add the 2's complement of the curve field) */ -+ if (carry || ((r2 == MP_DIGIT_MAX) && -+ ((r1 == MP_DIGIT_MAX) || -+ ((r1 == (MP_DIGIT_MAX-1)) && (r0 == MP_DIGIT_MAX))))) { -+#ifndef MPI_AMD64_ADD -+ MP_ADD_CARRY_ZERO(r0, 1, r0, carry); -+ MP_ADD_CARRY(r1, 1, r1, carry, carry); -+ MP_ADD_CARRY(r2, 0, r2, carry, carry); -+#else -+ __asm__ ( -+ "addq $1,%0 \n\t" -+ "adcq $1,%1 \n\t" -+ "adcq $0,%2 \n\t" -+ : "=r"(r0), "=r"(r1), "=r"(r2) -+ : "0" (r0), "1" (r1), "2" (r2) -+ : "%cc" ); -+#endif ++ public static void paintArrowIcon(Graphics g, MenuItemLayoutHelper lh, ++ MenuItemLayoutHelper.LayoutResult lr, ++ Color foreground) { ++ if (lh.getArrowIcon() != null) { ++ ButtonModel model = lh.getMenuItem().getModel(); ++ if (model.isArmed() || (lh.getMenuItem() instanceof JMenu ++ && model.isSelected())) { ++ g.setColor(foreground); ++ } ++ if (lh.useCheckAndArrow()) { ++ lh.getArrowIcon().paintIcon(lh.getMenuItem(), g, ++ lr.getArrowRect().x, lr.getArrowRect().y); ++ } + } ++ } + -+ -+ MP_CHECKOK(s_mp_pad(r, 3)); -+ MP_DIGIT(r, 2) = r2; -+ MP_DIGIT(r, 1) = r1; -+ MP_DIGIT(r, 0) = r0; -+ MP_SIGN(r) = MP_ZPOS; -+ MP_USED(r) = 3; -+ s_mp_clamp(r); -+ -+ -+ CLEANUP: -+ return res; -+} -+ -+/* Compute the diff of 192 bit curves. Do the work in-line since the -+ * number of words are so small, we don't want to overhead of mp function -+ * calls. Uses optimized modular reduction for p192. -+ */ -+mp_err -+ec_GFp_nistp192_sub(const mp_int *a, const mp_int *b, mp_int *r, -+ const GFMethod *meth) -+{ -+ mp_err res = MP_OKAY; -+ mp_digit b0 = 0, b1 = 0, b2 = 0; -+ mp_digit r0 = 0, r1 = 0, r2 = 0; -+ mp_digit borrow; -+ -+ switch(MP_USED(a)) { -+ case 3: -+ r2 = MP_DIGIT(a,2); -+ case 2: -+ r1 = MP_DIGIT(a,1); -+ case 1: -+ r0 = MP_DIGIT(a,0); + /** + * Returns delegate {@code RepaintManager} for {@code component} hierarchy. + */ +diff --git a/src/java.desktop/share/classes/java/awt/image/ColorConvertOp.java b/src/java.desktop/share/classes/java/awt/image/ColorConvertOp.java +index 023b376d7..a32cb925e 100644 +--- a/src/java.desktop/share/classes/java/awt/image/ColorConvertOp.java ++++ b/src/java.desktop/share/classes/java/awt/image/ColorConvertOp.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 1997, 2024, 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 +@@ -811,7 +811,7 @@ public class ColorConvertOp implements BufferedImageOp, RasterOp { + } + float[] srcMinVal = new float[iccSrcNumComp]; + float[] srcInvDiffMinMax = new float[iccSrcNumComp]; +- for (int i = 0; i < srcNumComp; i++) { ++ for (int i = 0; i < iccSrcNumComp; i++) { + srcMinVal[i] = cs.getMinValue(i); + srcInvDiffMinMax[i] = maxNum / (cs.getMaxValue(i) - srcMinVal[i]); + } +@@ -825,7 +825,7 @@ public class ColorConvertOp implements BufferedImageOp, RasterOp { + } + float[] dstMinVal = new float[iccDstNumComp]; + float[] dstDiffMinMax = new float[iccDstNumComp]; +- for (int i = 0; i < dstNumComp; i++) { ++ for (int i = 0; i < iccDstNumComp; i++) { + dstMinVal[i] = cs.getMinValue(i); + dstDiffMinMax[i] = (cs.getMaxValue(i) - dstMinVal[i]) / maxNum; + } +@@ -878,7 +878,7 @@ public class ColorConvertOp implements BufferedImageOp, RasterOp { + dstDiffMinMax[i] + dstMinVal[i]; + } + if (nonICCDst) { +- color = srcColorSpace.fromCIEXYZ(dstColor); ++ color = dstColorSpace.fromCIEXYZ(dstColor); + for (int i = 0; i < dstNumComp; i++) { + dstColor[i] = color[i]; + } +diff --git a/src/java.desktop/share/classes/javax/swing/border/TitledBorder.java b/src/java.desktop/share/classes/javax/swing/border/TitledBorder.java +index 79a766fa6..635a1cb0f 100644 +--- a/src/java.desktop/share/classes/javax/swing/border/TitledBorder.java ++++ b/src/java.desktop/share/classes/javax/swing/border/TitledBorder.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -736,6 +736,11 @@ public class TitledBorder extends AbstractBorder + } + + private JLabel getLabel(Component c) { ++ if (c instanceof JComponent) { ++ JComponent comp = (JComponent)c; ++ this.label.putClientProperty("html.disable", ++ comp.getClientProperty("html.disable")); + } + this.label.setText(getTitle()); + this.label.setFont(getFont(c)); + this.label.setForeground(getColor(c)); +diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicMenuItemUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicMenuItemUI.java +index 5ac288cda..65f1dda2f 100644 +--- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicMenuItemUI.java ++++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicMenuItemUI.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -25,17 +25,52 @@ + + package javax.swing.plaf.basic; + +-import java.awt.*; +-import java.awt.event.*; ++import java.awt.Color; ++import java.awt.Component; ++import java.awt.Dimension; ++import java.awt.Font; ++import java.awt.FontMetrics; ++import java.awt.Graphics; ++import java.awt.Insets; ++import java.awt.Point; ++import java.awt.Rectangle; ++import java.awt.event.ActionEvent; ++import java.awt.event.InputEvent; ++import java.awt.event.MouseEvent; + import java.beans.PropertyChangeEvent; + import java.beans.PropertyChangeListener; + +-import javax.swing.*; +-import javax.swing.event.*; +-import javax.swing.plaf.*; ++import javax.swing.ButtonModel; ++import javax.swing.Icon; ++import javax.swing.InputMap; ++import javax.swing.JCheckBoxMenuItem; ++import javax.swing.JComponent; ++import javax.swing.JMenu; ++import javax.swing.JMenuItem; ++import javax.swing.JRadioButtonMenuItem; ++import javax.swing.KeyStroke; ++import javax.swing.LookAndFeel; ++import javax.swing.MenuElement; ++import javax.swing.MenuSelectionManager; ++import javax.swing.SwingUtilities; ++import javax.swing.UIManager; ++import javax.swing.event.MenuDragMouseEvent; ++import javax.swing.event.MenuDragMouseListener; ++import javax.swing.event.MenuKeyListener; ++ ++import javax.swing.event.MouseInputListener; ++import javax.swing.plaf.ComponentInputMapUIResource; ++import javax.swing.plaf.ComponentUI; ++import javax.swing.plaf.MenuItemUI; ++import javax.swing.plaf.UIResource; + import javax.swing.text.View; + +-import sun.swing.*; ++import com.sun.java.swing.SwingUtilities3; ++import sun.swing.MenuItemCheckIconFactory; ++import sun.swing.MenuItemLayoutHelper; ++import sun.swing.SwingUtilities2; ++import sun.swing.UIAction; + -+ switch(MP_USED(b)) { -+ case 3: -+ b2 = MP_DIGIT(b,2); -+ case 2: -+ b1 = MP_DIGIT(b,1); -+ case 1: -+ b0 = MP_DIGIT(b,0); -+ } + + /** + * BasicMenuItem implementation +@@ -672,84 +707,21 @@ public class BasicMenuItemUI extends MenuItemUI + + private void paintIcon(Graphics g, MenuItemLayoutHelper lh, + MenuItemLayoutHelper.LayoutResult lr, Color holdc) { +- if (lh.getIcon() != null) { +- Icon icon; +- ButtonModel model = lh.getMenuItem().getModel(); +- if (!model.isEnabled()) { +- icon = lh.getMenuItem().getDisabledIcon(); +- } else if (model.isPressed() && model.isArmed()) { +- icon = lh.getMenuItem().getPressedIcon(); +- if (icon == null) { +- // Use default icon +- icon = lh.getMenuItem().getIcon(); +- } +- } else { +- icon = lh.getMenuItem().getIcon(); +- } +- +- if (icon != null) { +- icon.paintIcon(lh.getMenuItem(), g, lr.getIconRect().x, +- lr.getIconRect().y); +- g.setColor(holdc); +- } +- } ++ SwingUtilities3.paintIcon(g, lh, lr, holdc); + } + + private void paintCheckIcon(Graphics g, MenuItemLayoutHelper lh, + MenuItemLayoutHelper.LayoutResult lr, + Color holdc, Color foreground) { +- if (lh.getCheckIcon() != null) { +- ButtonModel model = lh.getMenuItem().getModel(); +- if (model.isArmed() || (lh.getMenuItem() instanceof JMenu +- && model.isSelected())) { +- g.setColor(foreground); +- } else { +- g.setColor(holdc); +- } +- if (lh.useCheckAndArrow()) { +- lh.getCheckIcon().paintIcon(lh.getMenuItem(), g, +- lr.getCheckRect().x, lr.getCheckRect().y); +- } +- g.setColor(holdc); +- } ++ SwingUtilities3.paintCheckIcon(g, lh, lr, holdc, foreground); + } + + private void paintAccText(Graphics g, MenuItemLayoutHelper lh, + MenuItemLayoutHelper.LayoutResult lr) { +- if (!lh.getAccText().equals("")) { +- ButtonModel model = lh.getMenuItem().getModel(); +- g.setFont(lh.getAccFontMetrics().getFont()); +- if (!model.isEnabled()) { +- // *** paint the accText disabled +- if (disabledForeground != null) { +- g.setColor(disabledForeground); +- SwingUtilities2.drawString(lh.getMenuItem(), g, +- lh.getAccText(), lr.getAccRect().x, +- lr.getAccRect().y + lh.getAccFontMetrics().getAscent()); +- } else { +- g.setColor(lh.getMenuItem().getBackground().brighter()); +- SwingUtilities2.drawString(lh.getMenuItem(), g, +- lh.getAccText(), lr.getAccRect().x, +- lr.getAccRect().y + lh.getAccFontMetrics().getAscent()); +- g.setColor(lh.getMenuItem().getBackground().darker()); +- SwingUtilities2.drawString(lh.getMenuItem(), g, +- lh.getAccText(), lr.getAccRect().x - 1, +- lr.getAccRect().y + lh.getFontMetrics().getAscent() - 1); +- } +- } else { +- // *** paint the accText normally +- if (model.isArmed() +- || (lh.getMenuItem() instanceof JMenu +- && model.isSelected())) { +- g.setColor(acceleratorSelectionForeground); +- } else { +- g.setColor(acceleratorForeground); +- } +- SwingUtilities2.drawString(lh.getMenuItem(), g, lh.getAccText(), +- lr.getAccRect().x, lr.getAccRect().y + +- lh.getAccFontMetrics().getAscent()); +- } +- } ++ SwingUtilities3.paintAccText(g, lh, lr, ++ disabledForeground, ++ acceleratorSelectionForeground, ++ acceleratorForeground); + } + + private void paintText(Graphics g, MenuItemLayoutHelper lh, +@@ -768,26 +740,11 @@ public class BasicMenuItemUI extends MenuItemUI + private void paintArrowIcon(Graphics g, MenuItemLayoutHelper lh, + MenuItemLayoutHelper.LayoutResult lr, + Color foreground) { +- if (lh.getArrowIcon() != null) { +- ButtonModel model = lh.getMenuItem().getModel(); +- if (model.isArmed() || (lh.getMenuItem() instanceof JMenu +- && model.isSelected())) { +- g.setColor(foreground); +- } +- if (lh.useCheckAndArrow()) { +- lh.getArrowIcon().paintIcon(lh.getMenuItem(), g, +- lr.getArrowRect().x, lr.getArrowRect().y); +- } +- } ++ SwingUtilities3.paintArrowIcon(g, lh, lr, foreground); + } + + private void applyInsets(Rectangle rect, Insets insets) { +- if(insets != null) { +- rect.x += insets.left; +- rect.y += insets.top; +- rect.width -= (insets.right + rect.x); +- rect.height -= (insets.bottom + rect.y); +- } ++ SwingUtilities3.applyInsets(rect, insets); + } + + /** +diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicOptionPaneUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicOptionPaneUI.java +index b3a12edb5..593d65658 100644 +--- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicOptionPaneUI.java ++++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicOptionPaneUI.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -482,6 +482,10 @@ public class BasicOptionPaneUI extends OptionPaneUI { + } else { + JLabel label; + label = new JLabel( s, JLabel.LEADING ); ++ if (Boolean.TRUE.equals( ++ this.optionPane.getClientProperty("html.disable"))) { ++ label.putClientProperty("html.disable", true); ++ } + label.setName("OptionPane.label"); + configureMessageLabel(label); + addMessageComponents(container, cons, label, maxll, true); +diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTabbedPaneUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTabbedPaneUI.java +index fee26de92..4b7b98eb9 100644 +--- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTabbedPaneUI.java ++++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTabbedPaneUI.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -451,7 +451,11 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants { + } + tabPane.addContainerListener(getHandler()); + if (tabPane.getTabCount()>0) { +- htmlViews = createHTMLVector(); ++ Boolean htmlDisabled = (Boolean) ++ tabPane.getClientProperty("html.disable"); ++ if (!(Boolean.TRUE.equals(htmlDisabled))) { ++ htmlViews = createHTMLVector(); ++ } + } + } + +@@ -4017,8 +4021,10 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants { + + private void updateHtmlViews(int index, boolean inserted) { + String title = tabPane.getTitleAt(index); ++ Boolean htmlDisabled = (Boolean) ++ tabPane.getClientProperty("html.disable"); + boolean isHTML = BasicHTML.isHTMLString(title); +- if (isHTML) { ++ if (isHTML && !(Boolean.TRUE.equals(htmlDisabled))) { + if (htmlViews==null) { // Initialize vector + htmlViews = createHTMLVector(); + } else { // Vector already exists +diff --git a/src/java.desktop/share/legal/freetype.md b/src/java.desktop/share/legal/freetype.md +index 6bcb4976f..2c654e154 100644 +--- a/src/java.desktop/share/legal/freetype.md ++++ b/src/java.desktop/share/legal/freetype.md +@@ -1,4 +1,4 @@ +-## The FreeType Project: Freetype v2.13.2 ++## The FreeType Project: Freetype v2.13.3 + + + ### FreeType Notice +@@ -21,23 +21,23 @@ which fits your needs best. + ### FreeType License + ``` + +-Copyright (C) 1996-2023 by David Turner, Robert Wilhelm, and Werner Lemberg. +-Copyright (C) 2007-2023 by Dereg Clegg and Michael Toftdal. +-Copyright (C) 1996-2023 by Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg. +-Copyright (C) 2022-2023 by David Turner, Robert Wilhelm, Werner Lemberg, George Williams, and +-Copyright (C) 2004-2023 by Masatake YAMATO and Redhat K.K. +-Copyright (C) 2007-2023 by Derek Clegg and Michael Toftdal. +-Copyright (C) 2003-2023 by Masatake YAMATO, Red Hat K.K., +-Copyright (C) 1996-2023 by David Turner, Robert Wilhelm, Werner Lemberg, and Dominik Röttsches. +-Copyright (C) 2007-2023 by David Turner. +-Copyright (C) 2022-2023 by David Turner, Robert Wilhelm, Werner Lemberg, and Moazin Khatti. +-Copyright (C) 2007-2023 by Rahul Bhalerao , . +-Copyright (C) 2008-2023 by David Turner, Robert Wilhelm, Werner Lemberg, and suzuki toshiya. +-Copyright (C) 2013-2023 by Google, Inc. +-Copyright (C) 2019-2023 by Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg. +-Copyright (C) 2009-2023 by Oran Agra and Mickey Gabel. +-Copyright (C) 2018-2023 by David Turner, Robert Wilhelm, Dominik Röttsches, and Werner Lemberg. +-Copyright (C) 2004-2023 by David Turner, Robert Wilhelm, Werner Lemberg, and George Williams. ++Copyright (C) 1996-2024 by David Turner, Robert Wilhelm, and Werner Lemberg. ++Copyright (C) 2007-2024 by Dereg Clegg and Michael Toftdal. ++Copyright (C) 1996-2024 by Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg. ++Copyright (C) 2022-2024 by David Turner, Robert Wilhelm, Werner Lemberg, George Williams, and ++Copyright (C) 2004-2024 by Masatake YAMATO and Redhat K.K. ++Copyright (C) 2007-2024 by Derek Clegg and Michael Toftdal. ++Copyright (C) 2003-2024 by Masatake YAMATO, Red Hat K.K., ++Copyright (C) 1996-2024 by David Turner, Robert Wilhelm, Werner Lemberg, and Dominik Röttsches. ++Copyright (C) 2007-2024 by David Turner. ++Copyright (C) 2022-2024 by David Turner, Robert Wilhelm, Werner Lemberg, and Moazin Khatti. ++Copyright (C) 2007-2024 by Rahul Bhalerao , . ++Copyright (C) 2008-2024 by David Turner, Robert Wilhelm, Werner Lemberg, and suzuki toshiya. ++Copyright (C) 2013-2024 by Google, Inc. ++Copyright (C) 2019-2024 by Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg. ++Copyright (C) 2009-2024 by Oran Agra and Mickey Gabel. ++Copyright (C) 2018-2024 by David Turner, Robert Wilhelm, Dominik Röttsches, and Werner Lemberg. ++Copyright (C) 2004-2024 by David Turner, Robert Wilhelm, Werner Lemberg, and George Williams. + + + The FreeType Project LICENSE +@@ -559,7 +559,7 @@ Public License instead of this License. + ``` + + --------------------------------- +-The below license applies to the following files: ++The below applies to the following file(s): + libfreetype/src/psaux/psarrst.c + libfreetype/src/psaux/psarrst.h + libfreetype/src/psaux/psblues.c +@@ -582,7 +582,7 @@ libfreetype/src/psaux/psstack.c + libfreetype/src/psaux/psstack.h + libfreetype/src/psaux/pstypes.h + +-Copyright 2006-2014 Adobe Systems Incorporated. ++Copyright (C) 2006-2014 Adobe Systems Incorporated. + + This software, and all works of authorship, whether in source or + object code form as indicated by the copyright notice(s) included +@@ -618,12 +618,12 @@ and you accept them fully. + ``` + + --------------------------------- +-The below license applies to the following files: ++The below applies to the following file(s): + libfreetype/include/freetype/internal/fthash.h + libfreetype/src/base/fthash.c + +-Copyright 2000 Computing Research Labs, New Mexico State University +-Copyright 2001-2015 ++Copyright (C) 2000 Computing Research Labs, New Mexico State University ++Copyright (C) 2001-2015 + + Francesco Zappa Nardelli + +diff --git a/src/java.desktop/share/legal/harfbuzz.md b/src/java.desktop/share/legal/harfbuzz.md +index 3ae73d215..2d0a28ed3 100644 +--- a/src/java.desktop/share/legal/harfbuzz.md ++++ b/src/java.desktop/share/legal/harfbuzz.md +@@ -1,4 +1,4 @@ +-## Harfbuzz v8.2.2 ++## Harfbuzz v10.4.0 + + ### Harfbuzz License + +@@ -8,14 +8,14 @@ HarfBuzz is licensed under the so-called "Old MIT" license. Details follow. + For parts of HarfBuzz that are licensed under different licenses see individual + files names COPYING in subdirectories where applicable. + +-Copyright © 2010-2023 Google, Inc. ++Copyright © 2010-2024 Google, Inc. + Copyright © 2018-2020 Ebrahim Byagowi + Copyright © 2004-2013 Red Hat, Inc. + Copyright © 2019 Facebook, Inc. + Copyright (C) 2012 Zilong Tan (eric.zltan@gmail.com) + Copyright © 2007 Chris Wilson + Copyright © 2018-2019 Adobe Inc. +-Copyright © 2006-2023 Behdad Esfahbod ++Copyright © 2006-2025 Behdad Esfahbod + Copyright © 1998-2004 David Turner and Werner Lemberg + Copyright © 2009 Keith Stribley + Copyright © 2018 Khaled Hosny +@@ -54,7 +54,7 @@ exception is licensed with a slightly different MIT variant: + The contents of this directory are licensed under the following terms: + + --------------------------------- +-The below license applies to the following files: ++The below applies to the following file(s): + libharfbuzz/hb-ucd.cc + + Copyright (C) 2012 Grigori Goronzy +@@ -72,13 +72,14 @@ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + --------------------------------- +-The below license applies to the following files: ++The below applies to the following file(s): + libharfbuzz/hb-unicode-emoji-table.hh + +-© 2023 Unicode®, Inc. ++© 2024 Unicode®, Inc. + -+#ifndef MPI_AMD64_ADD -+ MP_SUB_BORROW(r0, b0, r0, 0, borrow); -+ MP_SUB_BORROW(r1, b1, r1, borrow, borrow); -+ MP_SUB_BORROW(r2, b2, r2, borrow, borrow); -+#else -+ __asm__ ( -+ "xorq %3,%3 \n\t" -+ "subq %4,%0 \n\t" -+ "sbbq %5,%1 \n\t" -+ "sbbq %6,%2 \n\t" -+ "adcq $0,%3 \n\t" -+ : "=r"(r0), "=r"(r1), "=r"(r2), "=r"(borrow) -+ : "r" (b0), "r" (b1), "r" (b2), "0" (r0), -+ "1" (r1), "2" (r2) -+ : "%cc" ); -+#endif -+ -+ /* Do quick 'add' if we've gone under 0 -+ * (subtract the 2's complement of the curve field) */ -+ if (borrow) { -+#ifndef MPI_AMD64_ADD -+ MP_SUB_BORROW(r0, 1, r0, 0, borrow); -+ MP_SUB_BORROW(r1, 1, r1, borrow, borrow); -+ MP_SUB_BORROW(r2, 0, r2, borrow, borrow); -+#else -+ __asm__ ( -+ "subq $1,%0 \n\t" -+ "sbbq $1,%1 \n\t" -+ "sbbq $0,%2 \n\t" -+ : "=r"(r0), "=r"(r1), "=r"(r2) -+ : "0" (r0), "1" (r1), "2" (r2) -+ : "%cc" ); -+#endif -+ } + Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. + in the U.S. and other countries. +-For terms of use, see https://www.unicode.org/terms_of_use.html ++For terms of use and license, see https://www.unicode.org/terms_of_use.html + + + +diff --git a/src/java.desktop/share/legal/lcms.md b/src/java.desktop/share/legal/lcms.md +index 02af4fff0..83c47d3ac 100644 +--- a/src/java.desktop/share/legal/lcms.md ++++ b/src/java.desktop/share/legal/lcms.md +@@ -1,11 +1,11 @@ +-## Little Color Management System (LCMS) v2.16 ++## Little Color Management System (LCMS) v2.17 + + ### LCMS License +
+ 
+ MIT License
+ 
+-Copyright (C) 1998-2023 Marti Maria Saguer
++Copyright (C) 1998-2025 Marti Maria Saguer
+ 
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the "Software"),
+@@ -26,10 +26,10 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ 
+ ---------------------------------
+-The below license applies to the following files:
++The below applies to the following file(s):
+ liblcms/cmssm.c
+ 
+-Copyright 2001, softSurfer (www.softsurfer.com)
++Copyright (C) 2001, softSurfer (www.softsurfer.com)
+ 
+ This code may be freely used and modified for any purpose
+ providing that this copyright notice is included with it.
+@@ -99,5 +99,5 @@ Christian Albrecht
+ Dimitrios Anastassakis
+ Lemke Software
+ Tim Zaman
+-
+-```
++Amir Montazery and Open Source Technology Improvement Fund (ostif.org), Google, for fuzzer fundings.
++```
+\ No newline at end of file
+diff --git a/src/java.desktop/share/legal/libpng.md b/src/java.desktop/share/legal/libpng.md
+index cbffed813..d43ccf2e8 100644
+--- a/src/java.desktop/share/legal/libpng.md
++++ b/src/java.desktop/share/legal/libpng.md
+@@ -1,4 +1,4 @@
+-## libpng v1.6.43
++## libpng v1.6.47
+ 
+ ### libpng License
+ 
+@@ -9,8 +9,8 @@ COPYRIGHT NOTICE, DISCLAIMER, and LICENSE
+ PNG Reference Library License version 2
+ ---------------------------------------
+ 
+-Copyright (C) 1995-2024 The PNG Reference Library Authors.
+-Copyright (C) 2018-2024 Cosmin Truta
++Copyright (c) 1995-2025 The PNG Reference Library Authors.
++Copyright (C) 2018-2025 Cosmin Truta
+ Copyright (C) 1998-2018 Glenn Randers-Pehrson
+ Copyright (C) 1996-1997 Andreas Dilger
+ Copyright (C) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
+@@ -170,6 +170,7 @@ Authors, for copyright and licensing purposes.
+  * James Yu
+  * John Bowler
+  * Kevin Bracey
++ * Lucas Chollet
+  * Magnus Holmgren
+  * Mandar Sahastrabuddhe
+  * Mans Rullgard
+diff --git a/src/java.desktop/share/native/libawt/java2d/SurfaceData.h b/src/java.desktop/share/native/libawt/java2d/SurfaceData.h
+index f8fd8e62a..ca2e985fa 100644
+--- a/src/java.desktop/share/native/libawt/java2d/SurfaceData.h
++++ b/src/java.desktop/share/native/libawt/java2d/SurfaceData.h
+@@ -60,7 +60,7 @@ typedef struct {
+ 
+ #define UNSAFE_TO_SUB(a, b) \
+     (((b >= 0) && (a < 0) && (a < (INT_MIN + b))) || \
+-     ((b < 0) && (a >= 0) && (-b > (INT_MAX - a)))) \
++     ((b < 0) && (a >= 0) && (a > (INT_MAX + b)))) \
+ 
+ /*
+  * The SurfaceDataRasInfo structure is used to pass in and return various
+diff --git a/src/java.desktop/share/native/libawt/java2d/loops/Blit.c b/src/java.desktop/share/native/libawt/java2d/loops/Blit.c
+index fee108b83..8a41584de 100644
+--- a/src/java.desktop/share/native/libawt/java2d/loops/Blit.c
++++ b/src/java.desktop/share/native/libawt/java2d/loops/Blit.c
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+@@ -68,14 +68,30 @@ Java_sun_java2d_loops_Blit_Blit
+         return;
+     }
+ 
++    if (width <= 0 || height <= 0) {
++        return;
++    }
 +
-+        MP_CHECKOK(s_mp_pad(r, 3));
-+        MP_DIGIT(r, 2) = r2;
-+        MP_DIGIT(r, 1) = r1;
-+        MP_DIGIT(r, 0) = r0;
-+        MP_SIGN(r) = MP_ZPOS;
-+        MP_USED(r) = 3;
-+        s_mp_clamp(r);
+     srcInfo.bounds.x1 = srcx;
+     srcInfo.bounds.y1 = srcy;
++    if (UNSAFE_TO_ADD(srcx, width) ||
++        UNSAFE_TO_ADD(srcy, height) ||
++        UNSAFE_TO_ADD(dstx, width) ||
++        UNSAFE_TO_ADD(dsty, height)) {
++        return;
++    }
 +
-+  CLEANUP:
-+        return res;
-+}
+     srcInfo.bounds.x2 = srcx + width;
+     srcInfo.bounds.y2 = srcy + height;
+     dstInfo.bounds.x1 = dstx;
+     dstInfo.bounds.y1 = dsty;
+     dstInfo.bounds.x2 = dstx + width;
+     dstInfo.bounds.y2 = dsty + height;
++    if (UNSAFE_TO_SUB(srcx, dstx) ||
++        UNSAFE_TO_SUB(srcy, dsty)) {
++        return;
++    }
 +
-+#endif
-+
-+/* Compute the square of polynomial a, reduce modulo p192. Store the
-+ * result in r.  r could be a.  Uses optimized modular reduction for p192.
-+ */
-+mp_err
-+ec_GFp_nistp192_sqr(const mp_int *a, mp_int *r, const GFMethod *meth)
-+{
-+        mp_err res = MP_OKAY;
-+
-+        MP_CHECKOK(mp_sqr(a, r));
-+        MP_CHECKOK(ec_GFp_nistp192_mod(r, r, meth));
-+  CLEANUP:
-+        return res;
-+}
-+
-+/* Compute the product of two polynomials a and b, reduce modulo p192.
-+ * Store the result in r.  r could be a or b; a could be b.  Uses
-+ * optimized modular reduction for p192. */
-+mp_err
-+ec_GFp_nistp192_mul(const mp_int *a, const mp_int *b, mp_int *r,
-+                                        const GFMethod *meth)
-+{
-+        mp_err res = MP_OKAY;
-+
-+        MP_CHECKOK(mp_mul(a, b, r));
-+        MP_CHECKOK(ec_GFp_nistp192_mod(r, r, meth));
-+  CLEANUP:
-+        return res;
-+}
-+
-+/* Divides two field elements. If a is NULL, then returns the inverse of
-+ * b. */
-+mp_err
-+ec_GFp_nistp192_div(const mp_int *a, const mp_int *b, mp_int *r,
-+                   const GFMethod *meth)
-+{
-+        mp_err res = MP_OKAY;
-+        mp_int t;
-+
-+        /* If a is NULL, then return the inverse of b, otherwise return a/b. */
-+        if (a == NULL) {
-+                return  mp_invmod(b, &meth->irr, r);
-+        } else {
-+                /* MPI doesn't support divmod, so we implement it using invmod and
-+                 * mulmod. */
-+                MP_CHECKOK(mp_init(&t, FLAG(b)));
-+                MP_CHECKOK(mp_invmod(b, &meth->irr, &t));
-+                MP_CHECKOK(mp_mul(a, &t, r));
-+                MP_CHECKOK(ec_GFp_nistp192_mod(r, r, meth));
-+          CLEANUP:
-+                mp_clear(&t);
-+                return res;
-+        }
-+}
-+
-+/* Wire in fast field arithmetic and precomputation of base point for
-+ * named curves. */
-+mp_err
-+ec_group_set_gfp192(ECGroup *group, ECCurveName name)
-+{
-+        if (name == ECCurve_NIST_P192) {
-+                group->meth->field_mod = &ec_GFp_nistp192_mod;
-+                group->meth->field_mul = &ec_GFp_nistp192_mul;
-+                group->meth->field_sqr = &ec_GFp_nistp192_sqr;
-+                group->meth->field_div = &ec_GFp_nistp192_div;
-+#ifndef ECL_THIRTY_TWO_BIT
-+                group->meth->field_add = &ec_GFp_nistp192_add;
-+                group->meth->field_sub = &ec_GFp_nistp192_sub;
-+#endif
-+        }
-+        return MP_OKAY;
-+}
-diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.crypto.ec/share/native/libsunec/impl/ecp_224.c jdk11u-ls/src/jdk.crypto.ec/share/native/libsunec/impl/ecp_224.c
---- openjdk/src/jdk.crypto.ec/share/native/libsunec/impl/ecp_224.c	1970-01-01 08:00:00.000000000 +0800
-+++ jdk11u-ls/src/jdk.crypto.ec/share/native/libsunec/impl/ecp_224.c	2023-09-12 13:54:26.293575685 +0800
-@@ -0,0 +1,373 @@
-+/*
-+ * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
-+ * Use is subject to license terms.
-+ *
-+ * This library is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU Lesser General Public
-+ * License as published by the Free Software Foundation; either
-+ * version 2.1 of the License, or (at your option) any later version.
-+ *
-+ * This library 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
-+ * Lesser General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU Lesser General Public License
-+ * along with this library; if not, write to the Free Software Foundation,
-+ * Inc., 51 Franklin Street, 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.
-+ */
-+
-+/* *********************************************************************
-+ *
-+ * The Original Code is the elliptic curve math library for prime field curves.
-+ *
-+ * The Initial Developer of the Original Code is
-+ * Sun Microsystems, Inc.
-+ * Portions created by the Initial Developer are Copyright (C) 2003
-+ * the Initial Developer. All Rights Reserved.
-+ *
-+ * Contributor(s):
-+ *   Douglas Stebila , Sun Microsystems Laboratories
-+ *
-+ *********************************************************************** */
-+
-+#include "ecp.h"
-+#include "mpi.h"
-+#include "mplogic.h"
-+#include "mpi-priv.h"
-+#ifndef _KERNEL
-+#include 
-+#endif
-+
-+#define ECP224_DIGITS ECL_CURVE_DIGITS(224)
-+
-+/* Fast modular reduction for p224 = 2^224 - 2^96 + 1.  a can be r. Uses
-+ * algorithm 7 from Brown, Hankerson, Lopez, Menezes. Software
-+ * Implementation of the NIST Elliptic Curves over Prime Fields. */
-+mp_err
-+ec_GFp_nistp224_mod(const mp_int *a, mp_int *r, const GFMethod *meth)
-+{
-+        mp_err res = MP_OKAY;
-+        mp_size a_used = MP_USED(a);
-+
-+        int    r3b;
-+        mp_digit carry;
-+#ifdef ECL_THIRTY_TWO_BIT
-+        mp_digit a6a = 0, a6b = 0,
-+                a5a = 0, a5b = 0, a4a = 0, a4b = 0, a3a = 0, a3b = 0;
-+        mp_digit r0a, r0b, r1a, r1b, r2a, r2b, r3a;
-+#else
-+        mp_digit a6 = 0, a5 = 0, a4 = 0, a3b = 0, a5a = 0;
-+        mp_digit a6b = 0, a6a_a5b = 0, a5b = 0, a5a_a4b = 0, a4a_a3b = 0;
-+        mp_digit r0, r1, r2, r3;
-+#endif
-+
-+        /* reduction not needed if a is not larger than field size */
-+        if (a_used < ECP224_DIGITS) {
-+                if (a == r) return MP_OKAY;
-+                return mp_copy(a, r);
-+        }
-+        /* for polynomials larger than twice the field size, use regular
-+         * reduction */
-+        if (a_used > ECL_CURVE_DIGITS(224*2)) {
-+                MP_CHECKOK(mp_mod(a, &meth->irr, r));
-+        } else {
-+#ifdef ECL_THIRTY_TWO_BIT
-+                /* copy out upper words of a */
-+                switch (a_used) {
-+                case 14:
-+                        a6b = MP_DIGIT(a, 13);
-+                case 13:
-+                        a6a = MP_DIGIT(a, 12);
-+                case 12:
-+                        a5b = MP_DIGIT(a, 11);
-+                case 11:
-+                        a5a = MP_DIGIT(a, 10);
-+                case 10:
-+                        a4b = MP_DIGIT(a, 9);
-+                case 9:
-+                        a4a = MP_DIGIT(a, 8);
-+                case 8:
-+                        a3b = MP_DIGIT(a, 7);
-+                }
-+                r3a = MP_DIGIT(a, 6);
-+                r2b= MP_DIGIT(a, 5);
-+                r2a= MP_DIGIT(a, 4);
-+                r1b = MP_DIGIT(a, 3);
-+                r1a = MP_DIGIT(a, 2);
-+                r0b = MP_DIGIT(a, 1);
-+                r0a = MP_DIGIT(a, 0);
-+
-+
-+                /* implement r = (a3a,a2,a1,a0)
-+                        +(a5a, a4,a3b,  0)
-+                        +(  0, a6,a5b,  0)
-+                        -(  0    0,    0|a6b, a6a|a5b )
-+                        -(  a6b, a6a|a5b, a5a|a4b, a4a|a3b ) */
-+                MP_ADD_CARRY (r1b, a3b, r1b, 0,     carry);
-+                MP_ADD_CARRY (r2a, a4a, r2a, carry, carry);
-+                MP_ADD_CARRY (r2b, a4b, r2b, carry, carry);
-+                MP_ADD_CARRY (r3a, a5a, r3a, carry, carry);
-+                r3b = carry;
-+                MP_ADD_CARRY (r1b, a5b, r1b, 0,     carry);
-+                MP_ADD_CARRY (r2a, a6a, r2a, carry, carry);
-+                MP_ADD_CARRY (r2b, a6b, r2b, carry, carry);
-+                MP_ADD_CARRY (r3a,   0, r3a, carry, carry);
-+                r3b += carry;
-+                MP_SUB_BORROW(r0a, a3b, r0a, 0,     carry);
-+                MP_SUB_BORROW(r0b, a4a, r0b, carry, carry);
-+                MP_SUB_BORROW(r1a, a4b, r1a, carry, carry);
-+                MP_SUB_BORROW(r1b, a5a, r1b, carry, carry);
-+                MP_SUB_BORROW(r2a, a5b, r2a, carry, carry);
-+                MP_SUB_BORROW(r2b, a6a, r2b, carry, carry);
-+                MP_SUB_BORROW(r3a, a6b, r3a, carry, carry);
-+                r3b -= carry;
-+                MP_SUB_BORROW(r0a, a5b, r0a, 0,     carry);
-+                MP_SUB_BORROW(r0b, a6a, r0b, carry, carry);
-+                MP_SUB_BORROW(r1a, a6b, r1a, carry, carry);
-+                if (carry) {
-+                        MP_SUB_BORROW(r1b, 0, r1b, carry, carry);
-+                        MP_SUB_BORROW(r2a, 0, r2a, carry, carry);
-+                        MP_SUB_BORROW(r2b, 0, r2b, carry, carry);
-+                        MP_SUB_BORROW(r3a, 0, r3a, carry, carry);
-+                        r3b -= carry;
-+                }
-+
-+                while (r3b > 0) {
-+                        int tmp;
-+                        MP_ADD_CARRY(r1b, r3b, r1b, 0,     carry);
-+                        if (carry) {
-+                                MP_ADD_CARRY(r2a,  0, r2a, carry, carry);
-+                                MP_ADD_CARRY(r2b,  0, r2b, carry, carry);
-+                                MP_ADD_CARRY(r3a,  0, r3a, carry, carry);
-+                        }
-+                        tmp = carry;
-+                        MP_SUB_BORROW(r0a, r3b, r0a, 0,     carry);
-+                        if (carry) {
-+                                MP_SUB_BORROW(r0b, 0, r0b, carry, carry);
-+                                MP_SUB_BORROW(r1a, 0, r1a, carry, carry);
-+                                MP_SUB_BORROW(r1b, 0, r1b, carry, carry);
-+                                MP_SUB_BORROW(r2a, 0, r2a, carry, carry);
-+                                MP_SUB_BORROW(r2b, 0, r2b, carry, carry);
-+                                MP_SUB_BORROW(r3a, 0, r3a, carry, carry);
-+                                tmp -= carry;
-+                        }
-+                        r3b = tmp;
-+                }
-+
-+                while (r3b < 0) {
-+                        mp_digit maxInt = MP_DIGIT_MAX;
-+                        MP_ADD_CARRY (r0a, 1, r0a, 0,     carry);
-+                        MP_ADD_CARRY (r0b, 0, r0b, carry, carry);
-+                        MP_ADD_CARRY (r1a, 0, r1a, carry, carry);
-+                        MP_ADD_CARRY (r1b, maxInt, r1b, carry, carry);
-+                        MP_ADD_CARRY (r2a, maxInt, r2a, carry, carry);
-+                        MP_ADD_CARRY (r2b, maxInt, r2b, carry, carry);
-+                        MP_ADD_CARRY (r3a, maxInt, r3a, carry, carry);
-+                        r3b += carry;
-+                }
-+                /* check for final reduction */
-+                /* now the only way we are over is if the top 4 words are all ones */
-+                if ((r3a == MP_DIGIT_MAX) && (r2b == MP_DIGIT_MAX)
-+                        && (r2a == MP_DIGIT_MAX) && (r1b == MP_DIGIT_MAX) &&
-+                         ((r1a != 0) || (r0b != 0) || (r0a != 0)) ) {
-+                        /* one last subraction */
-+                        MP_SUB_BORROW(r0a, 1, r0a, 0,     carry);
-+                        MP_SUB_BORROW(r0b, 0, r0b, carry, carry);
-+                        MP_SUB_BORROW(r1a, 0, r1a, carry, carry);
-+                        r1b = r2a = r2b = r3a = 0;
-+                }
-+
-+
-+                if (a != r) {
-+                        MP_CHECKOK(s_mp_pad(r, 7));
-+                }
-+                /* set the lower words of r */
-+                MP_SIGN(r) = MP_ZPOS;
-+                MP_USED(r) = 7;
-+                MP_DIGIT(r, 6) = r3a;
-+                MP_DIGIT(r, 5) = r2b;
-+                MP_DIGIT(r, 4) = r2a;
-+                MP_DIGIT(r, 3) = r1b;
-+                MP_DIGIT(r, 2) = r1a;
-+                MP_DIGIT(r, 1) = r0b;
-+                MP_DIGIT(r, 0) = r0a;
-+#else
-+                /* copy out upper words of a */
-+                switch (a_used) {
-+                case 7:
-+                        a6 = MP_DIGIT(a, 6);
-+                        a6b = a6 >> 32;
-+                        a6a_a5b = a6 << 32;
-+                case 6:
-+                        a5 = MP_DIGIT(a, 5);
-+                        a5b = a5 >> 32;
-+                        a6a_a5b |= a5b;
-+                        a5b = a5b << 32;
-+                        a5a_a4b = a5 << 32;
-+                        a5a = a5 & 0xffffffff;
-+                case 5:
-+                        a4 = MP_DIGIT(a, 4);
-+                        a5a_a4b |= a4 >> 32;
-+                        a4a_a3b = a4 << 32;
-+                case 4:
-+                        a3b = MP_DIGIT(a, 3) >> 32;
-+                        a4a_a3b |= a3b;
-+                        a3b = a3b << 32;
-+                }
-+
-+                r3 = MP_DIGIT(a, 3) & 0xffffffff;
-+                r2 = MP_DIGIT(a, 2);
-+                r1 = MP_DIGIT(a, 1);
-+                r0 = MP_DIGIT(a, 0);
-+
-+                /* implement r = (a3a,a2,a1,a0)
-+                        +(a5a, a4,a3b,  0)
-+                        +(  0, a6,a5b,  0)
-+                        -(  0    0,    0|a6b, a6a|a5b )
-+                        -(  a6b, a6a|a5b, a5a|a4b, a4a|a3b ) */
-+                MP_ADD_CARRY_ZERO (r1, a3b, r1, carry);
-+                MP_ADD_CARRY (r2, a4 , r2, carry, carry);
-+                MP_ADD_CARRY (r3, a5a, r3, carry, carry);
-+                MP_ADD_CARRY_ZERO (r1, a5b, r1, carry);
-+                MP_ADD_CARRY (r2, a6 , r2, carry, carry);
-+                MP_ADD_CARRY (r3,   0, r3, carry, carry);
-+
-+                MP_SUB_BORROW(r0, a4a_a3b, r0, 0,     carry);
-+                MP_SUB_BORROW(r1, a5a_a4b, r1, carry, carry);
-+                MP_SUB_BORROW(r2, a6a_a5b, r2, carry, carry);
-+                MP_SUB_BORROW(r3, a6b    , r3, carry, carry);
-+                MP_SUB_BORROW(r0, a6a_a5b, r0, 0,     carry);
-+                MP_SUB_BORROW(r1, a6b    , r1, carry, carry);
-+                if (carry) {
-+                        MP_SUB_BORROW(r2, 0, r2, carry, carry);
-+                        MP_SUB_BORROW(r3, 0, r3, carry, carry);
-+                }
-+
-+
-+                /* if the value is negative, r3 has a 2's complement
-+                 * high value */
-+                r3b = (int)(r3 >>32);
-+                while (r3b > 0) {
-+                        r3 &= 0xffffffff;
-+                        MP_ADD_CARRY_ZERO(r1,((mp_digit)r3b) << 32, r1, carry);
-+                        if (carry) {
-+                                MP_ADD_CARRY(r2,  0, r2, carry, carry);
-+                                MP_ADD_CARRY(r3,  0, r3, carry, carry);
-+                        }
-+                        MP_SUB_BORROW(r0, r3b, r0, 0, carry);
-+                        if (carry) {
-+                                MP_SUB_BORROW(r1, 0, r1, carry, carry);
-+                                MP_SUB_BORROW(r2, 0, r2, carry, carry);
-+                                MP_SUB_BORROW(r3, 0, r3, carry, carry);
-+                        }
-+                        r3b = (int)(r3 >>32);
-+                }
-+
-+                while (r3b < 0) {
-+                        MP_ADD_CARRY_ZERO (r0, 1, r0, carry);
-+                        MP_ADD_CARRY (r1, MP_DIGIT_MAX <<32, r1, carry, carry);
-+                        MP_ADD_CARRY (r2, MP_DIGIT_MAX, r2, carry, carry);
-+                        MP_ADD_CARRY (r3, MP_DIGIT_MAX >> 32, r3, carry, carry);
-+                        r3b = (int)(r3 >>32);
-+                }
-+                /* check for final reduction */
-+                /* now the only way we are over is if the top 4 words are all ones */
-+                if ((r3 == (MP_DIGIT_MAX >> 32)) && (r2 == MP_DIGIT_MAX)
-+                        && ((r1 & MP_DIGIT_MAX << 32)== MP_DIGIT_MAX << 32) &&
-+                         ((r1 != MP_DIGIT_MAX << 32 ) || (r0 != 0)) ) {
-+                        /* one last subraction */
-+                        MP_SUB_BORROW(r0, 1, r0, 0,     carry);
-+                        MP_SUB_BORROW(r1, 0, r1, carry, carry);
-+                        r2 = r3 = 0;
-+                }
-+
-+
-+                if (a != r) {
-+                        MP_CHECKOK(s_mp_pad(r, 4));
-+                }
-+                /* set the lower words of r */
-+                MP_SIGN(r) = MP_ZPOS;
-+                MP_USED(r) = 4;
-+                MP_DIGIT(r, 3) = r3;
-+                MP_DIGIT(r, 2) = r2;
-+                MP_DIGIT(r, 1) = r1;
-+                MP_DIGIT(r, 0) = r0;
-+#endif
-+        }
-+
-+  CLEANUP:
-+        return res;
-+}
-+
-+/* Compute the square of polynomial a, reduce modulo p224. Store the
-+ * result in r.  r could be a.  Uses optimized modular reduction for p224.
-+ */
-+mp_err
-+ec_GFp_nistp224_sqr(const mp_int *a, mp_int *r, const GFMethod *meth)
-+{
-+        mp_err res = MP_OKAY;
-+
-+        MP_CHECKOK(mp_sqr(a, r));
-+        MP_CHECKOK(ec_GFp_nistp224_mod(r, r, meth));
-+  CLEANUP:
-+        return res;
-+}
-+
-+/* Compute the product of two polynomials a and b, reduce modulo p224.
-+ * Store the result in r.  r could be a or b; a could be b.  Uses
-+ * optimized modular reduction for p224. */
-+mp_err
-+ec_GFp_nistp224_mul(const mp_int *a, const mp_int *b, mp_int *r,
-+                                        const GFMethod *meth)
-+{
-+        mp_err res = MP_OKAY;
-+
-+        MP_CHECKOK(mp_mul(a, b, r));
-+        MP_CHECKOK(ec_GFp_nistp224_mod(r, r, meth));
-+  CLEANUP:
-+        return res;
-+}
-+
-+/* Divides two field elements. If a is NULL, then returns the inverse of
-+ * b. */
-+mp_err
-+ec_GFp_nistp224_div(const mp_int *a, const mp_int *b, mp_int *r,
-+                   const GFMethod *meth)
-+{
-+        mp_err res = MP_OKAY;
-+        mp_int t;
-+
-+        /* If a is NULL, then return the inverse of b, otherwise return a/b. */
-+        if (a == NULL) {
-+                return  mp_invmod(b, &meth->irr, r);
-+        } else {
-+                /* MPI doesn't support divmod, so we implement it using invmod and
-+                 * mulmod. */
-+                MP_CHECKOK(mp_init(&t, FLAG(b)));
-+                MP_CHECKOK(mp_invmod(b, &meth->irr, &t));
-+                MP_CHECKOK(mp_mul(a, &t, r));
-+                MP_CHECKOK(ec_GFp_nistp224_mod(r, r, meth));
-+          CLEANUP:
-+                mp_clear(&t);
-+                return res;
-+        }
-+}
-+
-+/* Wire in fast field arithmetic and precomputation of base point for
-+ * named curves. */
-+mp_err
-+ec_group_set_gfp224(ECGroup *group, ECCurveName name)
-+{
-+        if (name == ECCurve_NIST_P224) {
-+                group->meth->field_mod = &ec_GFp_nistp224_mod;
-+                group->meth->field_mul = &ec_GFp_nistp224_mul;
-+                group->meth->field_sqr = &ec_GFp_nistp224_sqr;
-+                group->meth->field_div = &ec_GFp_nistp224_div;
-+        }
-+        return MP_OKAY;
-+}
-diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.crypto.ec/share/native/libsunec/impl/oid.c jdk11u-ls/src/jdk.crypto.ec/share/native/libsunec/impl/oid.c
---- openjdk/src/jdk.crypto.ec/share/native/libsunec/impl/oid.c	2022-10-12 23:00:07.000000000 +0800
-+++ jdk11u-ls/src/jdk.crypto.ec/share/native/libsunec/impl/oid.c	2023-09-12 13:54:26.297575690 +0800
-@@ -73,13 +73,87 @@
- /* NOTE: prime192v1 is the same as secp192r1, prime256v1 is the
-  * same as secp256r1
-  */
-+CONST_OID ansiX962prime192v1[] = { ANSI_X962_GFp_OID, 0x01 };
-+CONST_OID ansiX962prime192v2[] = { ANSI_X962_GFp_OID, 0x02 };
-+CONST_OID ansiX962prime192v3[] = { ANSI_X962_GFp_OID, 0x03 };
-+CONST_OID ansiX962prime239v1[] = { ANSI_X962_GFp_OID, 0x04 };
-+CONST_OID ansiX962prime239v2[] = { ANSI_X962_GFp_OID, 0x05 };
-+CONST_OID ansiX962prime239v3[] = { ANSI_X962_GFp_OID, 0x06 };
- CONST_OID ansiX962prime256v1[] = { ANSI_X962_GFp_OID, 0x07 };
- 
- /* SECG prime curve OIDs */
-+CONST_OID secgECsecp112r1[] = { SECG_OID, 0x06 };
-+CONST_OID secgECsecp112r2[] = { SECG_OID, 0x07 };
-+CONST_OID secgECsecp128r1[] = { SECG_OID, 0x1c };
-+CONST_OID secgECsecp128r2[] = { SECG_OID, 0x1d };
-+CONST_OID secgECsecp160k1[] = { SECG_OID, 0x09 };
-+CONST_OID secgECsecp160r1[] = { SECG_OID, 0x08 };
-+CONST_OID secgECsecp160r2[] = { SECG_OID, 0x1e };
-+CONST_OID secgECsecp192k1[] = { SECG_OID, 0x1f };
-+CONST_OID secgECsecp224k1[] = { SECG_OID, 0x20 };
-+CONST_OID secgECsecp224r1[] = { SECG_OID, 0x21 };
- CONST_OID secgECsecp256k1[] = { SECG_OID, 0x0a };
- CONST_OID secgECsecp384r1[] = { SECG_OID, 0x22 };
- CONST_OID secgECsecp521r1[] = { SECG_OID, 0x23 };
- 
-+/* SECG characterisitic two curve OIDs */
-+CONST_OID secgECsect113r1[] = {SECG_OID, 0x04 };
-+CONST_OID secgECsect113r2[] = {SECG_OID, 0x05 };
-+CONST_OID secgECsect131r1[] = {SECG_OID, 0x16 };
-+CONST_OID secgECsect131r2[] = {SECG_OID, 0x17 };
-+CONST_OID secgECsect163k1[] = {SECG_OID, 0x01 };
-+CONST_OID secgECsect163r1[] = {SECG_OID, 0x02 };
-+CONST_OID secgECsect163r2[] = {SECG_OID, 0x0f };
-+CONST_OID secgECsect193r1[] = {SECG_OID, 0x18 };
-+CONST_OID secgECsect193r2[] = {SECG_OID, 0x19 };
-+CONST_OID secgECsect233k1[] = {SECG_OID, 0x1a };
-+CONST_OID secgECsect233r1[] = {SECG_OID, 0x1b };
-+CONST_OID secgECsect239k1[] = {SECG_OID, 0x03 };
-+CONST_OID secgECsect283k1[] = {SECG_OID, 0x10 };
-+CONST_OID secgECsect283r1[] = {SECG_OID, 0x11 };
-+CONST_OID secgECsect409k1[] = {SECG_OID, 0x24 };
-+CONST_OID secgECsect409r1[] = {SECG_OID, 0x25 };
-+CONST_OID secgECsect571k1[] = {SECG_OID, 0x26 };
-+CONST_OID secgECsect571r1[] = {SECG_OID, 0x27 };
-+
-+/* ANSI X9.62 characteristic two curve OIDs */
-+CONST_OID ansiX962c2pnb163v1[] = { ANSI_X962_GF2m_OID, 0x01 };
-+CONST_OID ansiX962c2pnb163v2[] = { ANSI_X962_GF2m_OID, 0x02 };
-+CONST_OID ansiX962c2pnb163v3[] = { ANSI_X962_GF2m_OID, 0x03 };
-+CONST_OID ansiX962c2pnb176v1[] = { ANSI_X962_GF2m_OID, 0x04 };
-+CONST_OID ansiX962c2tnb191v1[] = { ANSI_X962_GF2m_OID, 0x05 };
-+CONST_OID ansiX962c2tnb191v2[] = { ANSI_X962_GF2m_OID, 0x06 };
-+CONST_OID ansiX962c2tnb191v3[] = { ANSI_X962_GF2m_OID, 0x07 };
-+CONST_OID ansiX962c2onb191v4[] = { ANSI_X962_GF2m_OID, 0x08 };
-+CONST_OID ansiX962c2onb191v5[] = { ANSI_X962_GF2m_OID, 0x09 };
-+CONST_OID ansiX962c2pnb208w1[] = { ANSI_X962_GF2m_OID, 0x0a };
-+CONST_OID ansiX962c2tnb239v1[] = { ANSI_X962_GF2m_OID, 0x0b };
-+CONST_OID ansiX962c2tnb239v2[] = { ANSI_X962_GF2m_OID, 0x0c };
-+CONST_OID ansiX962c2tnb239v3[] = { ANSI_X962_GF2m_OID, 0x0d };
-+CONST_OID ansiX962c2onb239v4[] = { ANSI_X962_GF2m_OID, 0x0e };
-+CONST_OID ansiX962c2onb239v5[] = { ANSI_X962_GF2m_OID, 0x0f };
-+CONST_OID ansiX962c2pnb272w1[] = { ANSI_X962_GF2m_OID, 0x10 };
-+CONST_OID ansiX962c2pnb304w1[] = { ANSI_X962_GF2m_OID, 0x11 };
-+CONST_OID ansiX962c2tnb359v1[] = { ANSI_X962_GF2m_OID, 0x12 };
-+CONST_OID ansiX962c2pnb368w1[] = { ANSI_X962_GF2m_OID, 0x13 };
-+CONST_OID ansiX962c2tnb431r1[] = { ANSI_X962_GF2m_OID, 0x14 };
-+
-+/* TeleTrusT ECC Brainpool prime curve OIDs */
-+CONST_OID brainpoolP160r1[] = { ECC_BRAINPOOL_EC_V1, 0x01 };
-+CONST_OID brainpoolP160t1[] = { ECC_BRAINPOOL_EC_V1, 0x02 };
-+CONST_OID brainpoolP192r1[] = { ECC_BRAINPOOL_EC_V1, 0x03 };
-+CONST_OID brainpoolP192t1[] = { ECC_BRAINPOOL_EC_V1, 0x04 };
-+CONST_OID brainpoolP224r1[] = { ECC_BRAINPOOL_EC_V1, 0x05 };
-+CONST_OID brainpoolP224t1[] = { ECC_BRAINPOOL_EC_V1, 0x06 };
-+CONST_OID brainpoolP256r1[] = { ECC_BRAINPOOL_EC_V1, 0x07 };
-+CONST_OID brainpoolP256t1[] = { ECC_BRAINPOOL_EC_V1, 0x08 };
-+CONST_OID brainpoolP320r1[] = { ECC_BRAINPOOL_EC_V1, 0x09 };
-+CONST_OID brainpoolP320t1[] = { ECC_BRAINPOOL_EC_V1, 0x0a };
-+CONST_OID brainpoolP384r1[] = { ECC_BRAINPOOL_EC_V1, 0x0b };
-+CONST_OID brainpoolP384t1[] = { ECC_BRAINPOOL_EC_V1, 0x0c };
-+CONST_OID brainpoolP512r1[] = { ECC_BRAINPOOL_EC_V1, 0x0d };
-+CONST_OID brainpoolP512t1[] = { ECC_BRAINPOOL_EC_V1, 0x0e };
-+
- #define OI(x) { siDEROID, (unsigned char *)x, sizeof x }
- #ifndef SECOID_NO_STRINGS
- #define OD(oid,tag,desc,mech,ext) { OI(oid), tag, desc, mech, ext }
-@@ -100,18 +174,30 @@
-     { { siDEROID, NULL, 0 }, ECCurve_noName,
-         "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
- 
--    { { siDEROID, NULL, 0 }, ECCurve_noName,
--        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
--    { { siDEROID, NULL, 0 }, ECCurve_noName,
--        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
--    { { siDEROID, NULL, 0 }, ECCurve_noName,
--        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
--    { { siDEROID, NULL, 0 }, ECCurve_noName,
--        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
--    { { siDEROID, NULL, 0 }, ECCurve_noName,
--        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
--    { { siDEROID, NULL, 0 }, ECCurve_noName,
--        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
-+    OD( ansiX962prime192v1, ECCurve_NIST_P192,
-+        "ANSI X9.62 elliptic curve prime192v1 (aka secp192r1, NIST P-192)",
-+        CKM_INVALID_MECHANISM,
-+        INVALID_CERT_EXTENSION ),
-+    OD( ansiX962prime192v2, ECCurve_X9_62_PRIME_192V2,
-+        "ANSI X9.62 elliptic curve prime192v2",
-+        CKM_INVALID_MECHANISM,
-+        INVALID_CERT_EXTENSION ),
-+    OD( ansiX962prime192v3, ECCurve_X9_62_PRIME_192V3,
-+        "ANSI X9.62 elliptic curve prime192v3",
-+        CKM_INVALID_MECHANISM,
-+        INVALID_CERT_EXTENSION ),
-+    OD( ansiX962prime239v1, ECCurve_X9_62_PRIME_239V1,
-+        "ANSI X9.62 elliptic curve prime239v1",
-+        CKM_INVALID_MECHANISM,
-+        INVALID_CERT_EXTENSION ),
-+    OD( ansiX962prime239v2, ECCurve_X9_62_PRIME_239V2,
-+        "ANSI X9.62 elliptic curve prime239v2",
-+        CKM_INVALID_MECHANISM,
-+        INVALID_CERT_EXTENSION ),
-+    OD( ansiX962prime239v3, ECCurve_X9_62_PRIME_239V3,
-+        "ANSI X9.62 elliptic curve prime239v3",
-+        CKM_INVALID_MECHANISM,
-+        INVALID_CERT_EXTENSION ),
-     OD( ansiX962prime256v1, ECCurve_NIST_P256,
-         "ANSI X9.62 elliptic curve prime256v1 (aka secp256r1, NIST P-256)",
-         CKM_INVALID_MECHANISM,
-@@ -122,24 +208,42 @@
-     { { siDEROID, NULL, 0 }, ECCurve_noName,
-         "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
- 
--    { { siDEROID, NULL, 0 }, ECCurve_noName,
--        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
--    { { siDEROID, NULL, 0 }, ECCurve_noName,
--        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
--    { { siDEROID, NULL, 0 }, ECCurve_noName,
--        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
--    { { siDEROID, NULL, 0 }, ECCurve_noName,
--        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
--    { { siDEROID, NULL, 0 }, ECCurve_noName,
--        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
--    { { siDEROID, NULL, 0 }, ECCurve_noName,
--        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
--    { { siDEROID, NULL, 0 }, ECCurve_noName,
--        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
--    { { siDEROID, NULL, 0 }, ECCurve_noName,
--        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
--    { { siDEROID, NULL, 0 }, ECCurve_noName,
--        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
-+    OD( secgECsect163k1, ECCurve_NIST_K163,
-+        "SECG elliptic curve sect163k1 (aka NIST K-163)",
-+        CKM_INVALID_MECHANISM,
-+        INVALID_CERT_EXTENSION ),
-+    OD( secgECsect163r1, ECCurve_SECG_CHAR2_163R1,
-+        "SECG elliptic curve sect163r1",
-+        CKM_INVALID_MECHANISM,
-+        INVALID_CERT_EXTENSION ),
-+    OD( secgECsect239k1, ECCurve_SECG_CHAR2_239K1,
-+        "SECG elliptic curve sect239k1",
-+        CKM_INVALID_MECHANISM,
-+        INVALID_CERT_EXTENSION ),
-+    OD( secgECsect113r1, ECCurve_SECG_CHAR2_113R1,
-+        "SECG elliptic curve sect113r1",
-+        CKM_INVALID_MECHANISM,
-+        INVALID_CERT_EXTENSION ),
-+    OD( secgECsect113r2, ECCurve_SECG_CHAR2_113R2,
-+        "SECG elliptic curve sect113r2",
-+        CKM_INVALID_MECHANISM,
-+        INVALID_CERT_EXTENSION ),
-+    OD( secgECsecp112r1, ECCurve_SECG_PRIME_112R1,
-+        "SECG elliptic curve secp112r1",
-+        CKM_INVALID_MECHANISM,
-+        INVALID_CERT_EXTENSION ),
-+    OD( secgECsecp112r2, ECCurve_SECG_PRIME_112R2,
-+        "SECG elliptic curve secp112r2",
-+        CKM_INVALID_MECHANISM,
-+        INVALID_CERT_EXTENSION ),
-+    OD( secgECsecp160r1, ECCurve_SECG_PRIME_160R1,
-+        "SECG elliptic curve secp160r1",
-+        CKM_INVALID_MECHANISM,
-+        INVALID_CERT_EXTENSION ),
-+    OD( secgECsecp160k1, ECCurve_SECG_PRIME_160K1,
-+        "SECG elliptic curve secp160k1",
-+        CKM_INVALID_MECHANISM,
-+        INVALID_CERT_EXTENSION ),
-     OD( secgECsecp256k1, ECCurve_SECG_PRIME_256K1,
-         "SECG elliptic curve secp256k1",
-         CKM_INVALID_MECHANISM,
-@@ -152,6 +256,18 @@
-         "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
-     { { siDEROID, NULL, 0 }, ECCurve_noName,
-         "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
-+    OD( secgECsect163r2, ECCurve_NIST_B163,
-+        "SECG elliptic curve sect163r2 (aka NIST B-163)",
-+        CKM_INVALID_MECHANISM,
-+        INVALID_CERT_EXTENSION ),
-+    OD( secgECsect283k1, ECCurve_NIST_K283,
-+        "SECG elliptic curve sect283k1 (aka NIST K-283)",
-+        CKM_INVALID_MECHANISM,
-+        INVALID_CERT_EXTENSION ),
-+    OD( secgECsect283r1, ECCurve_NIST_B283,
-+        "SECG elliptic curve sect283r1 (aka NIST B-283)",
-+        CKM_INVALID_MECHANISM,
-+        INVALID_CERT_EXTENSION ),
-     { { siDEROID, NULL, 0 }, ECCurve_noName,
-         "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
-     { { siDEROID, NULL, 0 }, ECCurve_noName,
-@@ -160,36 +276,54 @@
-         "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
-     { { siDEROID, NULL, 0 }, ECCurve_noName,
-         "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
--    { { siDEROID, NULL, 0 }, ECCurve_noName,
--        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
--    { { siDEROID, NULL, 0 }, ECCurve_noName,
--        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
--    { { siDEROID, NULL, 0 }, ECCurve_noName,
--        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
--    { { siDEROID, NULL, 0 }, ECCurve_noName,
--        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
--    { { siDEROID, NULL, 0 }, ECCurve_noName,
--        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
--    { { siDEROID, NULL, 0 }, ECCurve_noName,
--        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
--    { { siDEROID, NULL, 0 }, ECCurve_noName,
--        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
--    { { siDEROID, NULL, 0 }, ECCurve_noName,
--        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
--    { { siDEROID, NULL, 0 }, ECCurve_noName,
--        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
--    { { siDEROID, NULL, 0 }, ECCurve_noName,
--        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
--    { { siDEROID, NULL, 0 }, ECCurve_noName,
--        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
--    { { siDEROID, NULL, 0 }, ECCurve_noName,
--        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
--    { { siDEROID, NULL, 0 }, ECCurve_noName,
--        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
--    { { siDEROID, NULL, 0 }, ECCurve_noName,
--        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
--    { { siDEROID, NULL, 0 }, ECCurve_noName,
--        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
-+    OD( secgECsect131r1, ECCurve_SECG_CHAR2_131R1,
-+        "SECG elliptic curve sect131r1",
-+        CKM_INVALID_MECHANISM,
-+        INVALID_CERT_EXTENSION ),
-+    OD( secgECsect131r2, ECCurve_SECG_CHAR2_131R2,
-+        "SECG elliptic curve sect131r2",
-+        CKM_INVALID_MECHANISM,
-+        INVALID_CERT_EXTENSION ),
-+    OD( secgECsect193r1, ECCurve_SECG_CHAR2_193R1,
-+        "SECG elliptic curve sect193r1",
-+        CKM_INVALID_MECHANISM,
-+        INVALID_CERT_EXTENSION ),
-+    OD( secgECsect193r2, ECCurve_SECG_CHAR2_193R2,
-+        "SECG elliptic curve sect193r2",
-+        CKM_INVALID_MECHANISM,
-+        INVALID_CERT_EXTENSION ),
-+    OD( secgECsect233k1, ECCurve_NIST_K233,
-+        "SECG elliptic curve sect233k1 (aka NIST K-233)",
-+        CKM_INVALID_MECHANISM,
-+        INVALID_CERT_EXTENSION ),
-+    OD( secgECsect233r1, ECCurve_NIST_B233,
-+        "SECG elliptic curve sect233r1 (aka NIST B-233)",
-+        CKM_INVALID_MECHANISM,
-+        INVALID_CERT_EXTENSION ),
-+    OD( secgECsecp128r1, ECCurve_SECG_PRIME_128R1,
-+        "SECG elliptic curve secp128r1",
-+        CKM_INVALID_MECHANISM,
-+        INVALID_CERT_EXTENSION ),
-+    OD( secgECsecp128r2, ECCurve_SECG_PRIME_128R2,
-+        "SECG elliptic curve secp128r2",
-+        CKM_INVALID_MECHANISM,
-+        INVALID_CERT_EXTENSION ),
-+    OD( secgECsecp160r2, ECCurve_SECG_PRIME_160R2,
-+        "SECG elliptic curve secp160r2",
-+        CKM_INVALID_MECHANISM,
-+        INVALID_CERT_EXTENSION ),
-+    OD( secgECsecp192k1, ECCurve_SECG_PRIME_192K1,
-+        "SECG elliptic curve secp192k1",
-+        CKM_INVALID_MECHANISM,
-+        INVALID_CERT_EXTENSION ),
-+    OD( secgECsecp224k1, ECCurve_SECG_PRIME_224K1,
-+        "SECG elliptic curve secp224k1",
-+        CKM_INVALID_MECHANISM,
-+        INVALID_CERT_EXTENSION ),
-+    OD( secgECsecp224r1, ECCurve_NIST_P224,
-+        "SECG elliptic curve secp224r1 (aka NIST P-224)",
-+        CKM_INVALID_MECHANISM,
-+        INVALID_CERT_EXTENSION ),
-     OD( secgECsecp384r1, ECCurve_NIST_P384,
-         "SECG elliptic curve secp384r1 (aka NIST P-384)",
-         CKM_INVALID_MECHANISM,
-@@ -198,14 +332,22 @@
-         "SECG elliptic curve secp521r1 (aka NIST P-521)",
-         CKM_INVALID_MECHANISM,
-         INVALID_CERT_EXTENSION ),
--    { { siDEROID, NULL, 0 }, ECCurve_noName,
--        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
--    { { siDEROID, NULL, 0 }, ECCurve_noName,
--        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
--    { { siDEROID, NULL, 0 }, ECCurve_noName,
--        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
--    { { siDEROID, NULL, 0 }, ECCurve_noName,
--        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION }
-+    OD( secgECsect409k1, ECCurve_NIST_K409,
-+        "SECG elliptic curve sect409k1 (aka NIST K-409)",
-+        CKM_INVALID_MECHANISM,
-+        INVALID_CERT_EXTENSION ),
-+    OD( secgECsect409r1, ECCurve_NIST_B409,
-+        "SECG elliptic curve sect409r1 (aka NIST B-409)",
-+        CKM_INVALID_MECHANISM,
-+        INVALID_CERT_EXTENSION ),
-+    OD( secgECsect571k1, ECCurve_NIST_K571,
-+        "SECG elliptic curve sect571k1 (aka NIST K-571)",
-+        CKM_INVALID_MECHANISM,
-+        INVALID_CERT_EXTENSION ),
-+    OD( secgECsect571r1, ECCurve_NIST_B571,
-+        "SECG elliptic curve sect571r1 (aka NIST B-571)",
-+        CKM_INVALID_MECHANISM,
-+        INVALID_CERT_EXTENSION )
- };
+     srcx -= dstx;
+     srcy -= dsty;
+     SurfaceData_IntersectBounds(&dstInfo.bounds, &clipInfo.bounds);
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/config/ftconfig.h b/src/java.desktop/share/native/libfreetype/include/freetype/config/ftconfig.h
+index a85151699..0667493fe 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/config/ftconfig.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/config/ftconfig.h
+@@ -4,7 +4,7 @@
+  *
+  *   ANSI-specific configuration file (specification only).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/config/ftheader.h b/src/java.desktop/share/native/libfreetype/include/freetype/config/ftheader.h
+index e607bce15..f6ef2618d 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/config/ftheader.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/config/ftheader.h
+@@ -4,7 +4,7 @@
+  *
+  *   Build macros of the FreeType 2 library.
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/config/ftoption.h b/src/java.desktop/share/native/libfreetype/include/freetype/config/ftoption.h
+index 4375c7a6f..d29a0a7ce 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/config/ftoption.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/config/ftoption.h
+@@ -4,7 +4,7 @@
+  *
+  *   User-selectable configuration macros (specification only).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+@@ -757,6 +757,22 @@ FT_BEGIN_HEADER
+ #endif
  
- static SECOidData ANSI_oids[] = {
-@@ -213,46 +355,78 @@
-         "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
- 
-     /* ANSI X9.62 named elliptic curves (characteristic two field) */
-+    OD( ansiX962c2pnb163v1, ECCurve_X9_62_CHAR2_PNB163V1,
-+        "ANSI X9.62 elliptic curve c2pnb163v1",
-+        CKM_INVALID_MECHANISM,
-+        INVALID_CERT_EXTENSION ),
-+    OD( ansiX962c2pnb163v2, ECCurve_X9_62_CHAR2_PNB163V2,
-+        "ANSI X9.62 elliptic curve c2pnb163v2",
-+        CKM_INVALID_MECHANISM,
-+        INVALID_CERT_EXTENSION ),
-+    OD( ansiX962c2pnb163v3, ECCurve_X9_62_CHAR2_PNB163V3,
-+        "ANSI X9.62 elliptic curve c2pnb163v3",
-+        CKM_INVALID_MECHANISM,
-+        INVALID_CERT_EXTENSION ),
-+    OD( ansiX962c2pnb176v1, ECCurve_X9_62_CHAR2_PNB176V1,
-+        "ANSI X9.62 elliptic curve c2pnb176v1",
-+        CKM_INVALID_MECHANISM,
-+        INVALID_CERT_EXTENSION ),
-+    OD( ansiX962c2tnb191v1, ECCurve_X9_62_CHAR2_TNB191V1,
-+        "ANSI X9.62 elliptic curve c2tnb191v1",
-+        CKM_INVALID_MECHANISM,
-+        INVALID_CERT_EXTENSION ),
-+    OD( ansiX962c2tnb191v2, ECCurve_X9_62_CHAR2_TNB191V2,
-+        "ANSI X9.62 elliptic curve c2tnb191v2",
-+        CKM_INVALID_MECHANISM,
-+        INVALID_CERT_EXTENSION ),
-+    OD( ansiX962c2tnb191v3, ECCurve_X9_62_CHAR2_TNB191V3,
-+        "ANSI X9.62 elliptic curve c2tnb191v3",
-+        CKM_INVALID_MECHANISM,
-+        INVALID_CERT_EXTENSION ),
-     { { siDEROID, NULL, 0 }, ECCurve_noName,
-         "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
-     { { siDEROID, NULL, 0 }, ECCurve_noName,
-         "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
-+    OD( ansiX962c2pnb208w1, ECCurve_X9_62_CHAR2_PNB208W1,
-+        "ANSI X9.62 elliptic curve c2pnb208w1",
-+        CKM_INVALID_MECHANISM,
-+        INVALID_CERT_EXTENSION ),
-+    OD( ansiX962c2tnb239v1, ECCurve_X9_62_CHAR2_TNB239V1,
-+        "ANSI X9.62 elliptic curve c2tnb239v1",
-+        CKM_INVALID_MECHANISM,
-+        INVALID_CERT_EXTENSION ),
-+    OD( ansiX962c2tnb239v2, ECCurve_X9_62_CHAR2_TNB239V2,
-+        "ANSI X9.62 elliptic curve c2tnb239v2",
-+        CKM_INVALID_MECHANISM,
-+        INVALID_CERT_EXTENSION ),
-+    OD( ansiX962c2tnb239v3, ECCurve_X9_62_CHAR2_TNB239V3,
-+        "ANSI X9.62 elliptic curve c2tnb239v3",
-+        CKM_INVALID_MECHANISM,
-+        INVALID_CERT_EXTENSION ),
-     { { siDEROID, NULL, 0 }, ECCurve_noName,
-         "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
-     { { siDEROID, NULL, 0 }, ECCurve_noName,
-         "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
--    { { siDEROID, NULL, 0 }, ECCurve_noName,
--        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
--    { { siDEROID, NULL, 0 }, ECCurve_noName,
--        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
--    { { siDEROID, NULL, 0 }, ECCurve_noName,
--        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
--    { { siDEROID, NULL, 0 }, ECCurve_noName,
--        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
--    { { siDEROID, NULL, 0 }, ECCurve_noName,
--        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
--    { { siDEROID, NULL, 0 }, ECCurve_noName,
--        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
--    { { siDEROID, NULL, 0 }, ECCurve_noName,
--        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
--    { { siDEROID, NULL, 0 }, ECCurve_noName,
--        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
--    { { siDEROID, NULL, 0 }, ECCurve_noName,
--        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
--    { { siDEROID, NULL, 0 }, ECCurve_noName,
--        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
--    { { siDEROID, NULL, 0 }, ECCurve_noName,
--        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
--    { { siDEROID, NULL, 0 }, ECCurve_noName,
--        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
--    { { siDEROID, NULL, 0 }, ECCurve_noName,
--        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
--    { { siDEROID, NULL, 0 }, ECCurve_noName,
--        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
--    { { siDEROID, NULL, 0 }, ECCurve_noName,
--        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
--    { { siDEROID, NULL, 0 }, ECCurve_noName,
--        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION }
-+    OD( ansiX962c2pnb272w1, ECCurve_X9_62_CHAR2_PNB272W1,
-+        "ANSI X9.62 elliptic curve c2pnb272w1",
-+        CKM_INVALID_MECHANISM,
-+        INVALID_CERT_EXTENSION ),
-+    OD( ansiX962c2pnb304w1, ECCurve_X9_62_CHAR2_PNB304W1,
-+        "ANSI X9.62 elliptic curve c2pnb304w1",
-+        CKM_INVALID_MECHANISM,
-+        INVALID_CERT_EXTENSION ),
-+    OD( ansiX962c2tnb359v1, ECCurve_X9_62_CHAR2_TNB359V1,
-+        "ANSI X9.62 elliptic curve c2tnb359v1",
-+        CKM_INVALID_MECHANISM,
-+        INVALID_CERT_EXTENSION ),
-+    OD( ansiX962c2pnb368w1, ECCurve_X9_62_CHAR2_PNB368W1,
-+        "ANSI X9.62 elliptic curve c2pnb368w1",
-+        CKM_INVALID_MECHANISM,
-+        INVALID_CERT_EXTENSION ),
-+    OD( ansiX962c2tnb431r1, ECCurve_X9_62_CHAR2_TNB431R1,
-+        "ANSI X9.62 elliptic curve c2tnb431r1",
-+        CKM_INVALID_MECHANISM,
-+        INVALID_CERT_EXTENSION )
- };
  
- static SECOidData BRAINPOOL_oids[] = {
-@@ -272,14 +446,31 @@
-         "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
-     { { siDEROID, NULL, 0 }, ECCurve_noName,
-         "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
-+    OD( brainpoolP256r1, ECCurve_BrainpoolP256r1,
-+        "brainpoolP256r1 domain parameter set",
-+        CKM_INVALID_MECHANISM,
-+        INVALID_CERT_EXTENSION ),
-     { { siDEROID, NULL, 0 }, ECCurve_noName,
-         "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
-+    OD( brainpoolP320r1, ECCurve_BrainpoolP320r1,
-+        "brainpoolP320r1 domain parameter set",
-+        CKM_INVALID_MECHANISM,
-+        INVALID_CERT_EXTENSION ),
-     { { siDEROID, NULL, 0 }, ECCurve_noName,
-         "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
-+    OD( brainpoolP384r1, ECCurve_BrainpoolP384r1,
-+        "brainpoolP384r1 domain parameter set",
-+        CKM_INVALID_MECHANISM,
-+        INVALID_CERT_EXTENSION ),
-     { { siDEROID, NULL, 0 }, ECCurve_noName,
-         "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
-+    OD( brainpoolP512r1, ECCurve_BrainpoolP512r1,
-+        "brainpoolP512r1 domain parameter set",
-+        CKM_INVALID_MECHANISM,
-+        INVALID_CERT_EXTENSION ),
-     { { siDEROID, NULL, 0 }, ECCurve_noName,
--        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION }
-+        "Unknown OID", CKM_INVALID_MECHANISM,
-+        INVALID_CERT_EXTENSION }
- };
++  /**************************************************************************
++   *
++   * Option `TT_CONFIG_OPTION_GPOS_KERNING` enables a basic GPOS kerning
++   * implementation (for TrueType fonts only).  With this defined, FreeType
++   * is able to get kerning pair data from the GPOS 'kern' feature as well as
++   * legacy 'kern' tables; without this defined, FreeType will only be able
++   * to use legacy 'kern' tables.
++   *
++   * Note that FreeType does not support more advanced GPOS layout features;
++   * even the 'kern' feature implemented here doesn't handle more
++   * sophisticated kerning variants.  Use a higher-level library like
++   * HarfBuzz instead for that.
++   */
++/* #define TT_CONFIG_OPTION_GPOS_KERNING */
++
++
+   /*************************************************************************/
+   /*************************************************************************/
+   /****                                                                 ****/
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/config/ftstdlib.h b/src/java.desktop/share/native/libfreetype/include/freetype/config/ftstdlib.h
+index f65148a90..e17aa7b89 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/config/ftstdlib.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/config/ftstdlib.h
+@@ -5,7 +5,7 @@
+  *   ANSI-specific library and header configuration file (specification
+  *   only).
+  *
+- * Copyright (C) 2002-2023 by
++ * Copyright (C) 2002-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/config/integer-types.h b/src/java.desktop/share/native/libfreetype/include/freetype/config/integer-types.h
+index 7258b5085..c27505ffc 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/config/integer-types.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/config/integer-types.h
+@@ -4,7 +4,7 @@
+  *
+  *   FreeType integer types definitions.
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/config/mac-support.h b/src/java.desktop/share/native/libfreetype/include/freetype/config/mac-support.h
+index b77b96d5d..07b6f915b 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/config/mac-support.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/config/mac-support.h
+@@ -4,7 +4,7 @@
+  *
+  *   Mac/OS X support configuration header.
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/config/public-macros.h b/src/java.desktop/share/native/libfreetype/include/freetype/config/public-macros.h
+index 23d0fa6a3..f56581a6e 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/config/public-macros.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/config/public-macros.h
+@@ -4,7 +4,7 @@
+  *
+  *   Define a set of compiler macros used in public FreeType headers.
+  *
+- * Copyright (C) 2020-2023 by
++ * Copyright (C) 2020-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/freetype.h b/src/java.desktop/share/native/libfreetype/include/freetype/freetype.h
+index 92acf3794..58fc33dfe 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/freetype.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/freetype.h
+@@ -4,7 +4,7 @@
+  *
+  *   FreeType high-level API and common types (specification only).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+@@ -1322,9 +1322,13 @@ FT_BEGIN_HEADER
+    *   FT_FACE_FLAG_KERNING ::
+    *     The face contains kerning information.  If set, the kerning distance
+    *     can be retrieved using the function @FT_Get_Kerning.  Otherwise the
+-   *     function always returns the vector (0,0).  Note that FreeType
+-   *     doesn't handle kerning data from the SFNT 'GPOS' table (as present
+-   *     in many OpenType fonts).
++   *     function always returns the vector (0,0).
++   *
++   *     Note that for TrueType fonts only, FreeType supports both the 'kern'
++   *     table and the basic, pair-wise kerning feature from the 'GPOS' table
++   *     (with `TT_CONFIG_OPTION_GPOS_KERNING` enabled), though FreeType does
++   *     not support the more advanced GPOS layout features; use a library
++   *     like HarfBuzz for those instead.
+    *
+    *   FT_FACE_FLAG_FAST_GLYPHS ::
+    *     THIS FLAG IS DEPRECATED.  DO NOT USE OR TEST IT.
+@@ -3767,87 +3771,18 @@ FT_BEGIN_HEADER
+    *     pixels and use the @FT_PIXEL_MODE_LCD_V mode.
+    *
+    *   FT_RENDER_MODE_SDF ::
+-   *     This mode corresponds to 8-bit, single-channel signed distance field
+-   *     (SDF) bitmaps.  Each pixel in the SDF grid is the value from the
+-   *     pixel's position to the nearest glyph's outline.  The distances are
+-   *     calculated from the center of the pixel and are positive if they are
+-   *     filled by the outline (i.e., inside the outline) and negative
+-   *     otherwise.  Check the note below on how to convert the output values
+-   *     to usable data.
++   *     The positive (unsigned) 8-bit bitmap values can be converted to the
++   *     single-channel signed distance field (SDF) by subtracting 128, with
++   *     the positive and negative results corresponding to the inside and
++   *     the outside of a glyph contour, respectively.  The distance units are
++   *     arbitrarily determined by an adjustable @spread property.
+    *
+    * @note:
+-   *   The selected render mode only affects vector glyphs of a font.
++   *   The selected render mode only affects scalable vector glyphs of a font.
+    *   Embedded bitmaps often have a different pixel mode like
+    *   @FT_PIXEL_MODE_MONO.  You can use @FT_Bitmap_Convert to transform them
+    *   into 8-bit pixmaps.
+    *
+-   *   For @FT_RENDER_MODE_SDF the output bitmap buffer contains normalized
+-   *   distances that are packed into unsigned 8-bit values.  To get pixel
+-   *   values in floating point representation use the following pseudo-C
+-   *   code for the conversion.
+-   *
+-   *   ```
+-   *   // Load glyph and render using FT_RENDER_MODE_SDF,
+-   *   // then use the output buffer as follows.
+-   *
+-   *   ...
+-   *   FT_Byte  buffer = glyph->bitmap->buffer;
+-   *
+-   *
+-   *   for pixel in buffer
+-   *   {
+-   *     // `sd` is the signed distance and `spread` is the current spread;
+-   *     // the default spread is 2 and can be changed.
+-   *
+-   *     float  sd = (float)pixel - 128.0f;
+-   *
+-   *
+-   *     // Convert to pixel values.
+-   *     sd = ( sd / 128.0f ) * spread;
+-   *
+-   *     // Store `sd` in a buffer or use as required.
+-   *   }
+-   *
+-   *   ```
+-   *
+-   *   FreeType has two rasterizers for generating SDF, namely:
+-   *
+-   *   1. `sdf` for generating SDF directly from glyph's outline, and
+-   *
+-   *   2. `bsdf` for generating SDF from rasterized bitmaps.
+-   *
+-   *   Depending on the glyph type (i.e., outline or bitmap), one of the two
+-   *   rasterizers is chosen at runtime and used for generating SDFs.  To
+-   *   force the use of `bsdf` you should render the glyph with any of the
+-   *   FreeType's other rendering modes (e.g., `FT_RENDER_MODE_NORMAL`) and
+-   *   then re-render with `FT_RENDER_MODE_SDF`.
+-   *
+-   *   There are some issues with stability and possible failures of the SDF
+-   *   renderers (specifically `sdf`).
+-   *
+-   *   1. The `sdf` rasterizer is sensitive to really small features (e.g.,
+-   *      sharp turns that are less than 1~pixel) and imperfections in the
+-   *      glyph's outline, causing artifacts in the final output.
+-   *
+-   *   2. The `sdf` rasterizer has limited support for handling intersecting
+-   *      contours and *cannot* handle self-intersecting contours whatsoever.
+-   *      Self-intersection happens when a single connected contour
+-   *      intersects itself at some point; having these in your font
+-   *      definitely poses a problem to the rasterizer and cause artifacts,
+-   *      too.
+-   *
+-   *   3. Generating SDF for really small glyphs may result in undesirable
+-   *      output; the pixel grid (which stores distance information) becomes
+-   *      too coarse.
+-   *
+-   *   4. Since the output buffer is normalized, precision at smaller spreads
+-   *      is greater than precision at larger spread values because the
+-   *      output range of [0..255] gets mapped to a smaller SDF range.  A
+-   *      spread of~2 should be sufficient in most cases.
+-   *
+-   *   Points (1) and (2) can be avoided by using the `bsdf` rasterizer,
+-   *   which is more stable than the `sdf` rasterizer in general.
+-   *
+    */
+   typedef enum  FT_Render_Mode_
+   {
+@@ -4058,9 +3993,26 @@ FT_BEGIN_HEADER
+    *   out of the scope of this API function -- they can be implemented
+    *   through format-specific interfaces.
+    *
+-   *   Kerning for OpenType fonts implemented in a 'GPOS' table is not
+-   *   supported; use @FT_HAS_KERNING to find out whether a font has data
+-   *   that can be extracted with `FT_Get_Kerning`.
++   *   Note that, for TrueType fonts only, this can extract data from both
++   *   the 'kern' table and the basic, pair-wise kerning feature from the
++   *   GPOS table (with `TT_CONFIG_OPTION_GPOS_KERNING` enabled), though
++   *   FreeType does not support the more advanced GPOS layout features; use
++   *   a library like HarfBuzz for those instead.  If a font has both a
++   *   'kern' table and kern features of a GPOS table, the 'kern' table will
++   *   be used.
++   *
++   *   Also note for right-to-left scripts, the functionality may differ for
++   *   fonts with GPOS tables vs. 'kern' tables.  For GPOS, right-to-left
++   *   fonts typically use both a placement offset and an advance for pair
++   *   positioning, which this API does not support, so it would output
++   *   kerning values of zero; though if the right-to-left font used only
++   *   advances in GPOS pair positioning, then this API could output kerning
++   *   values for it, but it would use `left_glyph` to mean the first glyph
++   *   for that case.  Whereas 'kern' tables are always advance-only and
++   *   always store the left glyph first.
++   *
++   *   Use @FT_HAS_KERNING to find out whether a font has data that can be
++   *   extracted with `FT_Get_Kerning`.
+    */
+   FT_EXPORT( FT_Error )
+   FT_Get_Kerning( FT_Face     face,
+@@ -5222,7 +5174,7 @@ FT_BEGIN_HEADER
+    */
+ #define FREETYPE_MAJOR  2
+ #define FREETYPE_MINOR  13
+-#define FREETYPE_PATCH  2
++#define FREETYPE_PATCH  3
  
- int
-diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.hotspot.agent/linux/native/libsaproc/libproc.h jdk11u-ls/src/jdk.hotspot.agent/linux/native/libsaproc/libproc.h
---- openjdk/src/jdk.hotspot.agent/linux/native/libsaproc/libproc.h	2022-10-12 23:00:03.000000000 +0800
-+++ jdk11u-ls/src/jdk.hotspot.agent/linux/native/libsaproc/libproc.h	2023-09-12 13:54:26.313575711 +0800
-@@ -22,6 +22,13 @@
+ 
+   /**************************************************************************
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftadvanc.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftadvanc.h
+index 4560ded6d..85b8ba255 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftadvanc.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftadvanc.h
+@@ -4,7 +4,7 @@
   *
-  */
+  *   Quick computation of advance widths (specification only).
+  *
+- * Copyright (C) 2008-2023 by
++ * Copyright (C) 2008-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftbbox.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftbbox.h
+index fc21740fc..12bbfa63a 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftbbox.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftbbox.h
+@@ -4,7 +4,7 @@
+  *
+  *   FreeType exact bbox computation (specification).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftbdf.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftbdf.h
+index e8ce64312..6f63b0b1e 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftbdf.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftbdf.h
+@@ -4,7 +4,7 @@
+  *
+  *   FreeType API for accessing BDF-specific strings (specification).
+  *
+- * Copyright (C) 2002-2023 by
++ * Copyright (C) 2002-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftbitmap.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftbitmap.h
+index eb6b4b1ee..df9d46265 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftbitmap.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftbitmap.h
+@@ -4,7 +4,7 @@
+  *
+  *   FreeType utility functions for bitmaps (specification).
+  *
+- * Copyright (C) 2004-2023 by
++ * Copyright (C) 2004-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftcid.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftcid.h
+index ef2293902..96b2a90fc 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftcid.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftcid.h
+@@ -4,7 +4,7 @@
+  *
+  *   FreeType API for accessing CID font information (specification).
+  *
+- * Copyright (C) 2007-2023 by
++ * Copyright (C) 2007-2024 by
+  * Dereg Clegg and Michael Toftdal.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftcolor.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftcolor.h
+index eae200fdf..420720ddf 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftcolor.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftcolor.h
+@@ -4,7 +4,7 @@
+  *
+  *   FreeType's glyph color management (specification).
+  *
+- * Copyright (C) 2018-2023 by
++ * Copyright (C) 2018-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftdriver.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftdriver.h
+index 7af7465bc..1b7f539f5 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftdriver.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftdriver.h
+@@ -4,7 +4,7 @@
+  *
+  *   FreeType API for controlling driver modules (specification only).
+  *
+- * Copyright (C) 2017-2023 by
++ * Copyright (C) 2017-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+@@ -817,6 +817,80 @@ FT_BEGIN_HEADER
+    *   2.5
+    */
  
-+/*
-+ * This file has been modified by Loongson Technology in 2022. These
-+ * modifications are Copyright (c) 2022, Loongson Technology, and are made
-+ * available on the same license terms set forth above.
-+ *
-+ */
 +
- #ifndef _LIBPROC_H_
- #define _LIBPROC_H_
++  /**************************************************************************
++   *
++   * @property:
++   *   spread
++   *
++   * @description:
++   *   This property of the 'sdf' and 'bsdf' renderers defines how the signed
++   *   distance field (SDF) is represented in the output bitmap.  The output
++   *   values are calculated as follows, '128 * ( SDF / spread + 1 )', with
++   *   the result clamped to the 8-bit range [0..255].  Therefore, 'spread'
++   *   is also the maximum euclidean distance from the edge after which the
++   *   values are clamped.  The spread is specified in pixels with the
++   *   default value of 8.  For accurate SDF texture mapping (interpolation),
++   *   the spread should be large enough to accommodate the target grid unit.
++   *
++   * @example:
++   *   The following example code demonstrates how to set the SDF spread
++   *   (omitting the error handling).
++   *
++   *   ```
++   *     FT_Library  library;
++   *     FT_Int      spread = 2;
++   *
++   *
++   *     FT_Init_FreeType( &library );
++   *
++   *     FT_Property_Set( library, "sdf", "spread", &spread );
++   *   ```
++   *
++   * @note:
++   *   FreeType has two rasterizers for generating SDF, namely:
++   *
++   *   1. `sdf` for generating SDF directly from glyph's outline, and
++   *
++   *   2. `bsdf` for generating SDF from rasterized bitmaps.
++   *
++   *   Depending on the glyph type (i.e., outline or bitmap), one of the two
++   *   rasterizers is chosen at runtime and used for generating SDFs.  To
++   *   force the use of `bsdf` you should render the glyph with any of the
++   *   FreeType's other rendering modes (e.g., `FT_RENDER_MODE_NORMAL`) and
++   *   then re-render with `FT_RENDER_MODE_SDF`.
++   *
++   *   There are some issues with stability and possible failures of the SDF
++   *   renderers (specifically `sdf`).
++   *
++   *   1. The `sdf` rasterizer is sensitive to really small features (e.g.,
++   *      sharp turns that are less than 1~pixel) and imperfections in the
++   *      glyph's outline, causing artifacts in the final output.
++   *
++   *   2. The `sdf` rasterizer has limited support for handling intersecting
++   *      contours and *cannot* handle self-intersecting contours whatsoever.
++   *      Self-intersection happens when a single connected contour
++   *      intersects itself at some point; having these in your font
++   *      definitely poses a problem to the rasterizer and cause artifacts,
++   *      too.
++   *
++   *   3. Generating SDF for really small glyphs may result in undesirable
++   *      output; the pixel grid (which stores distance information) becomes
++   *      too coarse.
++   *
++   *   4. Since the output buffer is normalized, precision at smaller spreads
++   *      is greater than precision at larger spread values because the
++   *      output range of [0..255] gets mapped to a smaller SDF range.  A
++   *      spread of~2 should be sufficient in most cases.
++   *
++   *   Points (1) and (2) can be avoided by using the `bsdf` rasterizer,
++   *   which is more stable than the `sdf` rasterizer in general.
++   *
++   * @since:
++   *   2.11
++   */
++
++
+   /**************************************************************************
+    *
+    * @property:
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/fterrdef.h b/src/java.desktop/share/native/libfreetype/include/freetype/fterrdef.h
+index d59b3cc2d..710ca91bb 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/fterrdef.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/fterrdef.h
+@@ -4,7 +4,7 @@
+  *
+  *   FreeType error codes (specification).
+  *
+- * Copyright (C) 2002-2023 by
++ * Copyright (C) 2002-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/fterrors.h b/src/java.desktop/share/native/libfreetype/include/freetype/fterrors.h
+index 15ef3f76b..27c0ece5c 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/fterrors.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/fterrors.h
+@@ -4,7 +4,7 @@
+  *
+  *   FreeType error code handling (specification).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftfntfmt.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftfntfmt.h
+index c0018fc83..7c8b0874a 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftfntfmt.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftfntfmt.h
+@@ -4,7 +4,7 @@
+  *
+  *   Support functions for font formats.
+  *
+- * Copyright (C) 2002-2023 by
++ * Copyright (C) 2002-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftgasp.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftgasp.h
+index d5f19add8..30e5a9bf8 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftgasp.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftgasp.h
+@@ -4,7 +4,7 @@
+  *
+  *   Access of TrueType's 'gasp' table (specification).
+  *
+- * Copyright (C) 2007-2023 by
++ * Copyright (C) 2007-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftglyph.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftglyph.h
+index 4658895f7..dc1eb8873 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftglyph.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftglyph.h
+@@ -4,7 +4,7 @@
+  *
+  *   FreeType convenience functions to handle glyphs (specification).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftgzip.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftgzip.h
+index 443ec29db..9516dc030 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftgzip.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftgzip.h
+@@ -4,7 +4,7 @@
+  *
+  *   Gzip-compressed stream support.
+  *
+- * Copyright (C) 2002-2023 by
++ * Copyright (C) 2002-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftimage.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftimage.h
+index 6baa81256..2b4b4ac60 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftimage.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftimage.h
+@@ -5,7 +5,7 @@
+  *   FreeType glyph image formats and default raster interface
+  *   (specification).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+@@ -21,6 +21,11 @@
+    * Note: A 'raster' is simply a scan-line converter, used to render
+    *       `FT_Outline`s into `FT_Bitmap`s.
+    *
++   * Note: This file can be used for `STANDALONE_` compilation of raster
++   *       (B/W) and smooth (anti-aliased) renderers.  Therefore, it must
++   *       rely on standard variable types only instead of aliases in
++   *       `fttypes.h`.
++   *
+    */
  
-@@ -37,13 +44,17 @@
- #include 
- #define user_regs_struct  pt_regs
- #endif
--#if defined(aarch64) || defined(arm64)
-+#if defined(aarch64) || defined(arm64) || defined(loongarch64)
- #include 
- #define user_regs_struct user_pt_regs
- #elif defined(arm)
- #include 
- #define user_regs_struct  pt_regs
- #endif
-+#if defined(mips) || defined(mipsel) || defined(mips64) || defined(mips64el)
-+#include 
-+#define user_regs_struct  pt_regs
-+#endif
  
- // This C bool type must be int for compatibility with Linux calls and
- // it would be a mistake to equivalence it to C++ bool on many platforms
-diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.hotspot.agent/linux/native/libsaproc/LinuxDebuggerLocal.c jdk11u-ls/src/jdk.hotspot.agent/linux/native/libsaproc/LinuxDebuggerLocal.c
---- openjdk/src/jdk.hotspot.agent/linux/native/libsaproc/LinuxDebuggerLocal.c	2022-10-12 23:00:03.000000000 +0800
-+++ jdk11u-ls/src/jdk.hotspot.agent/linux/native/libsaproc/LinuxDebuggerLocal.c	2023-09-12 13:54:26.313575711 +0800
-@@ -22,6 +22,13 @@
+@@ -318,7 +323,7 @@ FT_BEGIN_HEADER
+    *
+    *     If bit~2 is set, bits 5-7 contain the drop-out mode (as defined in
+    *     the OpenType specification; the value is the same as the argument to
+-   *     the 'SCANMODE' instruction).
++   *     the 'SCANTYPE' instruction).
+    *
+    *     Bits 3 and~4 are reserved for internal purposes.
+    *
+@@ -341,14 +346,14 @@ FT_BEGIN_HEADER
+    */
+   typedef struct  FT_Outline_
+   {
+-    short       n_contours;      /* number of contours in glyph        */
+-    short       n_points;        /* number of points in the glyph      */
++    unsigned short   n_contours;  /* number of contours in glyph        */
++    unsigned short   n_points;    /* number of points in the glyph      */
+ 
+-    FT_Vector*  points;          /* the outline's points               */
+-    char*       tags;            /* the points flags                   */
+-    short*      contours;        /* the contour end points             */
++    FT_Vector*       points;      /* the outline's points               */
++    unsigned char*   tags;        /* the points flags                   */
++    unsigned short*  contours;    /* the contour end points             */
+ 
+-    int         flags;           /* outline masks                      */
++    int              flags;       /* outline masks                      */
+ 
+   } FT_Outline;
+ 
+@@ -356,8 +361,8 @@ FT_BEGIN_HEADER
+ 
+   /* Following limits must be consistent with */
+   /* FT_Outline.{n_contours,n_points}         */
+-#define FT_OUTLINE_CONTOURS_MAX  SHRT_MAX
+-#define FT_OUTLINE_POINTS_MAX    SHRT_MAX
++#define FT_OUTLINE_CONTOURS_MAX  USHRT_MAX
++#define FT_OUTLINE_POINTS_MAX    USHRT_MAX
+ 
+ 
+   /**************************************************************************
+@@ -434,8 +439,8 @@ FT_BEGIN_HEADER
+    *   rasterizer; see the `tags` field in @FT_Outline.
+    *
+    *   Please refer to the description of the 'SCANTYPE' instruction in the
+-   *   OpenType specification (in file `ttinst1.doc`) how simple drop-outs,
+-   *   smart drop-outs, and stubs are defined.
++   *   [OpenType specification](https://learn.microsoft.com/en-us/typography/opentype/spec/tt_instructions#scantype)
++   *   how simple drop-outs, smart drop-outs, and stubs are defined.
+    */
+ #define FT_OUTLINE_NONE             0x0
+ #define FT_OUTLINE_OWNER            0x1
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftincrem.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftincrem.h
+index 2d4f5def2..816581b78 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftincrem.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftincrem.h
+@@ -4,7 +4,7 @@
   *
-  */
+  *   FreeType incremental loading (specification).
+  *
+- * Copyright (C) 2002-2023 by
++ * Copyright (C) 2002-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftlcdfil.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftlcdfil.h
+index d3723e16f..25274dc4a 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftlcdfil.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftlcdfil.h
+@@ -5,7 +5,7 @@
+  *   FreeType API for color filtering of subpixel bitmap glyphs
+  *   (specification).
+  *
+- * Copyright (C) 2006-2023 by
++ * Copyright (C) 2006-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftlist.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftlist.h
+index b55313133..972fbfa2f 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftlist.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftlist.h
+@@ -4,7 +4,7 @@
+  *
+  *   Generic list support for FreeType (specification).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftlogging.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftlogging.h
+index 53b8b8964..1813cfc2c 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftlogging.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftlogging.h
+@@ -4,7 +4,7 @@
+  *
+  *   Additional debugging APIs.
+  *
+- * Copyright (C) 2020-2023 by
++ * Copyright (C) 2020-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftmac.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftmac.h
+index a91e38f9e..e4efde33d 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftmac.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftmac.h
+@@ -4,7 +4,7 @@
+  *
+  *   Additional Mac-specific API.
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftmm.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftmm.h
+index d145128a9..35ed039c8 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftmm.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftmm.h
+@@ -4,7 +4,7 @@
+  *
+  *   FreeType Multiple Master font interface (specification).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+@@ -19,8 +19,13 @@
+ #ifndef FTMM_H_
+ #define FTMM_H_
  
-+/*
-+ * This file has been modified by Loongson Technology in 2022. These
-+ * modifications are Copyright (c) 2021, 2022, Loongson Technology, and are made
-+ * available on the same license terms set forth above.
-+ *
-+ */
-+
- #include 
- #include "libproc.h"
- #include "proc_service.h"
-@@ -54,10 +61,18 @@
- #include "sun_jvm_hotspot_debugger_ppc64_PPC64ThreadContext.h"
- #endif
++#include 
  
-+#if defined(mips64) || defined(mips64el)
-+#include "sun_jvm_hotspot_debugger_mips64_MIPS64ThreadContext.h"
+-#include 
++#ifdef FREETYPE_H
++#error "freetype.h of FreeType 1 has been loaded!"
++#error "Please fix the directory search order for header files"
++#error "so that freetype.h of FreeType 2 is found first."
 +#endif
-+
- #ifdef aarch64
- #include "sun_jvm_hotspot_debugger_aarch64_AARCH64ThreadContext.h"
- #endif
  
-+#ifdef loongarch64
-+#include "sun_jvm_hotspot_debugger_loongarch64_LOONGARCH64ThreadContext.h"
-+#endif
-+
- static jfieldID p_ps_prochandle_ID = 0;
- static jfieldID threadList_ID = 0;
- static jfieldID loadObjectList_ID = 0;
-@@ -397,7 +412,7 @@
-   return (err == PS_OK)? array : 0;
- }
  
--#if defined(i386) || defined(amd64) || defined(sparc) || defined(sparcv9) | defined(ppc64) || defined(ppc64le) || defined(aarch64)
-+#if defined(i386) || defined(amd64) || defined(sparc) || defined(sparcv9) | defined(ppc64) || defined(ppc64le) || defined(aarch64) || defined(loongarch64)
- JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_getThreadIntegerRegisterSet0
-   (JNIEnv *env, jobject this_obj, jint lwp_id) {
+ FT_BEGIN_HEADER
+@@ -53,6 +58,30 @@ FT_BEGIN_HEADER
+    */
  
-@@ -425,9 +440,15 @@
- #if defined(sparc) || defined(sparcv9)
- #define NPRGREG sun_jvm_hotspot_debugger_sparc_SPARCThreadContext_NPRGREG
- #endif
-+#ifdef loongarch64
-+#define NPRGREG sun_jvm_hotspot_debugger_loongarch64_LOONGARCH64ThreadContext_NPRGREG
-+#endif
- #if defined(ppc64) || defined(ppc64le)
- #define NPRGREG sun_jvm_hotspot_debugger_ppc64_PPC64ThreadContext_NPRGREG
- #endif
-+#if defined(mips64) || defined(mips64el)
-+#define NPRGREG sun_jvm_hotspot_debugger_mips64_MIPS64ThreadContext_NPRGREG
-+#endif
  
++  /**************************************************************************
++   *
++   * @enum:
++   *   T1_MAX_MM_XXX
++   *
++   * @description:
++   *   Multiple Masters limits as defined in their specifications.
++   *
++   * @values:
++   *   T1_MAX_MM_AXIS ::
++   *     The maximum number of Multiple Masters axes.
++   *
++   *   T1_MAX_MM_DESIGNS ::
++   *     The maximum number of Multiple Masters designs.
++   *
++   *   T1_MAX_MM_MAP_POINTS ::
++   *     The maximum number of elements in a design map.
++   *
++   */
++#define T1_MAX_MM_AXIS         4
++#define T1_MAX_MM_DESIGNS     16
++#define T1_MAX_MM_MAP_POINTS  20
++
++
+   /**************************************************************************
+    *
+    * @struct:
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftmodapi.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftmodapi.h
+index c8f0c2c2a..0ee715898 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftmodapi.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftmodapi.h
+@@ -4,7 +4,7 @@
+  *
+  *   FreeType modules public interface (specification).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftmoderr.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftmoderr.h
+index c8c892dcc..6722fbf8b 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftmoderr.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftmoderr.h
+@@ -4,7 +4,7 @@
+  *
+  *   FreeType module error offsets (specification).
+  *
+- * Copyright (C) 2001-2023 by
++ * Copyright (C) 2001-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftoutln.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftoutln.h
+index f9329ca40..44e94b4f5 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftoutln.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftoutln.h
+@@ -5,7 +5,7 @@
+  *   Support for the FT_Outline type used to store glyph shapes of
+  *   most scalable font formats (specification).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+@@ -112,7 +112,7 @@ FT_BEGIN_HEADER
+    *   Degenerate contours, segments, and Bezier arcs may be reported.  In
+    *   most cases, it is best to filter these out before using the outline
+    *   for stroking or other path modification purposes (which may cause
+-   *   degenerate segments to become non-degenrate and visible, like when
++   *   degenerate segments to become non-degenerate and visible, like when
+    *   stroke caps are used or the path is otherwise outset).  Some glyph
+    *   outlines may contain deliberate degenerate single points for mark
+    *   attachement.
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftparams.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftparams.h
+index 6a9f243bc..43bf69c20 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftparams.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftparams.h
+@@ -4,7 +4,7 @@
+  *
+  *   FreeType API for possible FT_Parameter tags (specification only).
+  *
+- * Copyright (C) 2017-2023 by
++ * Copyright (C) 2017-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftrender.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftrender.h
+index 0b6fad32e..dc5018a1b 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftrender.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftrender.h
+@@ -4,7 +4,7 @@
+  *
+  *   FreeType renderer modules public interface (specification).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftsizes.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftsizes.h
+index 7bfb1aed4..4ef5c7955 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftsizes.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftsizes.h
+@@ -4,7 +4,7 @@
+  *
+  *   FreeType size objects management (specification).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftsnames.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftsnames.h
+index 9d5d22bb2..d5d5cd931 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftsnames.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftsnames.h
+@@ -7,7 +7,7 @@
+  *
+  *   This is _not_ used to retrieve glyph names!
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftstroke.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftstroke.h
+index b3d90802a..41626dc9d 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftstroke.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftstroke.h
+@@ -4,7 +4,7 @@
+  *
+  *   FreeType path stroker (specification).
+  *
+- * Copyright (C) 2002-2023 by
++ * Copyright (C) 2002-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftsynth.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftsynth.h
+index af90967dd..43081b6c3 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftsynth.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftsynth.h
+@@ -5,7 +5,7 @@
+  *   FreeType synthesizing code for emboldening and slanting
+  *   (specification).
+  *
+- * Copyright (C) 2000-2023 by
++ * Copyright (C) 2000-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftsystem.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftsystem.h
+index 3a08f4912..1eacb3af3 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftsystem.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftsystem.h
+@@ -4,7 +4,7 @@
+  *
+  *   FreeType low-level system interface definition (specification).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/fttrigon.h b/src/java.desktop/share/native/libfreetype/include/freetype/fttrigon.h
+index 294981a6f..a5299e938 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/fttrigon.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/fttrigon.h
+@@ -4,7 +4,7 @@
+  *
+  *   FreeType trigonometric functions (specification).
+  *
+- * Copyright (C) 2001-2023 by
++ * Copyright (C) 2001-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/fttypes.h b/src/java.desktop/share/native/libfreetype/include/freetype/fttypes.h
+index 5b109f0c7..27815143a 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/fttypes.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/fttypes.h
+@@ -4,7 +4,7 @@
+  *
+  *   FreeType simple types definitions (specification only).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/autohint.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/autohint.h
+index bf9c8b7cf..8865d53b3 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/autohint.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/autohint.h
+@@ -4,7 +4,7 @@
+  *
+  *   High-level 'autohint' module-specific interface (specification).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/cffotypes.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/cffotypes.h
+index 50d535384..36b0390a5 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/cffotypes.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/cffotypes.h
+@@ -4,7 +4,7 @@
+  *
+  *   Basic OpenType/CFF object type definitions (specification).
+  *
+- * Copyright (C) 2017-2023 by
++ * Copyright (C) 2017-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/cfftypes.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/cfftypes.h
+index c2521764c..ef2e8e756 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/cfftypes.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/cfftypes.h
+@@ -5,7 +5,7 @@
+  *   Basic OpenType/CFF type definitions and interface (specification
+  *   only).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+@@ -248,10 +248,10 @@ FT_BEGIN_HEADER
+     FT_Byte   num_family_blues;
+     FT_Byte   num_family_other_blues;
  
-   array = (*env)->NewLongArray(env, NPRGREG);
-@@ -534,6 +555,18 @@
-   }
- #endif /* aarch64 */
+-    FT_Pos    blue_values[14];
+-    FT_Pos    other_blues[10];
+-    FT_Pos    family_blues[14];
+-    FT_Pos    family_other_blues[10];
++    FT_Fixed  blue_values[14];
++    FT_Fixed  other_blues[10];
++    FT_Fixed  family_blues[14];
++    FT_Fixed  family_other_blues[10];
  
-+#if defined(loongarch64)
-+
-+#define REG_INDEX(reg) sun_jvm_hotspot_debugger_loongarch64_LOONGARCH64ThreadContext_##reg
-+
-+  {
-+    int i;
-+    for (i = 0; i < 31; i++)
-+      regs[i] = gregs.regs[i];
-+    regs[REG_INDEX(PC)] = gregs.csr_era;
-+  }
-+#endif /* loongarch64 */
-+
- #if defined(ppc64) || defined(ppc64le)
- #define REG_INDEX(reg) sun_jvm_hotspot_debugger_ppc64_PPC64ThreadContext_##reg
+     FT_Fixed  blue_scale;
+     FT_Pos    blue_shift;
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/compiler-macros.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/compiler-macros.h
+index 6f6765097..876f66e25 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/compiler-macros.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/compiler-macros.h
+@@ -4,7 +4,7 @@
+  *
+  *   Compiler-specific macro definitions used internally by FreeType.
+  *
+- * Copyright (C) 2020-2023 by
++ * Copyright (C) 2020-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftcalc.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftcalc.h
+index d9aea2360..71128a2df 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftcalc.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftcalc.h
+@@ -4,7 +4,7 @@
+  *
+  *   Arithmetic computations (specification).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+@@ -415,7 +415,7 @@ FT_BEGIN_HEADER
  
-@@ -574,6 +607,45 @@
+ #define FT_MSB( x )  ( 31 - _CountLeadingZeros( x ) )
  
- #endif
+-#elif defined( _M_ARM64 ) || defined( _M_ARM )
++#elif defined( _M_ARM64 ) || defined( _M_ARM ) || defined( _M_ARM64EC )
  
-+#if defined(mips64) || defined(mips64el)
+ #include 
+ #pragma intrinsic( _CountLeadingZeros )
+@@ -455,6 +455,12 @@ FT_BEGIN_HEADER
+ 
+ #define FT_MSB( x )  FT_MSB_i386( x )
+ 
++#elif defined( __SunOS_5_11 )
 +
-+#define REG_INDEX(reg) sun_jvm_hotspot_debugger_mips64_MIPS64ThreadContext_##reg
++#include 
 +
-+  regs[REG_INDEX(ZERO)]  = gregs.regs[0];
-+  regs[REG_INDEX(AT)]  = gregs.regs[1];
-+  regs[REG_INDEX(V0)]  = gregs.regs[2];
-+  regs[REG_INDEX(V1)]  = gregs.regs[3];
-+  regs[REG_INDEX(A0)]  = gregs.regs[4];
-+  regs[REG_INDEX(A1)]  = gregs.regs[5];
-+  regs[REG_INDEX(A2)]  = gregs.regs[6];
-+  regs[REG_INDEX(A3)]  = gregs.regs[7];
-+  regs[REG_INDEX(T0)]  = gregs.regs[8];
-+  regs[REG_INDEX(T1)]  = gregs.regs[9];
-+  regs[REG_INDEX(T2)]  = gregs.regs[10];
-+  regs[REG_INDEX(T3)]  = gregs.regs[11];
-+  regs[REG_INDEX(T4)]  = gregs.regs[12];
-+  regs[REG_INDEX(T5)]  = gregs.regs[13];
-+  regs[REG_INDEX(T6)]  = gregs.regs[14];
-+  regs[REG_INDEX(T7)]  = gregs.regs[15];
-+  regs[REG_INDEX(S0)]  = gregs.regs[16];
-+  regs[REG_INDEX(S1)]  = gregs.regs[17];
-+  regs[REG_INDEX(S2)]  = gregs.regs[18];
-+  regs[REG_INDEX(S3)]  = gregs.regs[19];
-+  regs[REG_INDEX(S4)]  = gregs.regs[20];
-+  regs[REG_INDEX(S5)]  = gregs.regs[21];
-+  regs[REG_INDEX(S6)]  = gregs.regs[22];
-+  regs[REG_INDEX(S7)]  = gregs.regs[23];
-+  regs[REG_INDEX(T8)]  = gregs.regs[24];
-+  regs[REG_INDEX(T9)]  = gregs.regs[25];
-+  regs[REG_INDEX(K0)]  = gregs.regs[26];
-+  regs[REG_INDEX(K1)]  = gregs.regs[27];
-+  regs[REG_INDEX(GP)]  = gregs.regs[28];
-+  regs[REG_INDEX(SP)]  = gregs.regs[29];
-+  regs[REG_INDEX(FP)]  = gregs.regs[30];
-+  regs[REG_INDEX(S8)]  = gregs.regs[30];
-+  regs[REG_INDEX(RA)]  = gregs.regs[31];
-+#endif /* mips */
++#define FT_MSB( x )  ( fls( x ) - 1 )
 +
-   (*env)->ReleaseLongArrayElements(env, array, regs, JNI_COMMIT);
-   return array;
- }
-diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.hotspot.agent/linux/native/libsaproc/ps_proc.c jdk11u-ls/src/jdk.hotspot.agent/linux/native/libsaproc/ps_proc.c
---- openjdk/src/jdk.hotspot.agent/linux/native/libsaproc/ps_proc.c	2022-10-12 23:00:03.000000000 +0800
-+++ jdk11u-ls/src/jdk.hotspot.agent/linux/native/libsaproc/ps_proc.c	2023-09-12 13:54:26.313575711 +0800
-@@ -22,6 +22,12 @@
-  *
-  */
+ #elif defined( __DECC ) || defined( __DECCXX )
  
-+/*
-+ * This file has been modified by Loongson Technology in 2022, These
-+ * modifications are Copyright (c) 2022, Loongson Technology, and are made
-+ * available on the same license terms set forth above.
-+ */
-+
- #include 
- #include 
- #include 
-@@ -142,7 +148,7 @@
- #define PTRACE_GETREGS_REQ PT_GETREGS
- #endif
+ #include 
+@@ -489,8 +495,6 @@ FT_BEGIN_HEADER
+             FT_Fixed  y );
  
--#ifdef PTRACE_GETREGS_REQ
-+#if defined(PTRACE_GETREGS_REQ) && !defined(loongarch64)
-  if (ptrace_getregs(PTRACE_GETREGS_REQ, pid, user, NULL) < 0) {
-    print_debug("ptrace(PTRACE_GETREGS, ...) failed for lwp %d\n", pid);
-    return false;
-diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxCDebugger.java jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxCDebugger.java
---- openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxCDebugger.java	2022-10-12 23:00:03.000000000 +0800
-+++ jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxCDebugger.java	2023-09-12 13:54:26.373575786 +0800
-@@ -23,6 +23,12 @@
+ 
+-#if 0
+-
+   /**************************************************************************
+    *
+    * @function:
+@@ -507,12 +511,11 @@ FT_BEGIN_HEADER
+    *   The result of 'sqrt(x)'.
+    *
+    * @note:
+-   *   This function is not very fast.
++   *   This function is slow and should be avoided.  Consider @FT_Hypot or
++   *   @FT_Vector_NormLen instead.
+    */
+-  FT_BASE( FT_Int32 )
+-  FT_SqrtFixed( FT_Int32  x );
+-
+-#endif /* 0 */
++  FT_BASE( FT_UInt32 )
++  FT_SqrtFixed( FT_UInt32  x );
+ 
+ 
+ #define INT_TO_F26DOT6( x )    ( (FT_Long)(x) * 64  )    /* << 6  */
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftdebug.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftdebug.h
+index 4e013ba1e..d7fa8dc93 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftdebug.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftdebug.h
+@@ -4,7 +4,7 @@
   *
-  */
+  *   Debugging and logging component (specification).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftdrv.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftdrv.h
+index 9001c07ad..5609b3ef1 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftdrv.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftdrv.h
+@@ -4,7 +4,7 @@
+  *
+  *   FreeType internal font driver interface (specification).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftgloadr.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftgloadr.h
+index 36e5509f9..f1c155b16 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftgloadr.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftgloadr.h
+@@ -4,7 +4,7 @@
+  *
+  *   The FreeType glyph loader (specification).
+  *
+- * Copyright (C) 2002-2023 by
++ * Copyright (C) 2002-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftmemory.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftmemory.h
+index 5eb1d21ff..4e05a29f1 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftmemory.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftmemory.h
+@@ -4,7 +4,7 @@
+  *
+  *   The FreeType memory management macros (specification).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg
+  *
+  * This file is part of the FreeType project, and may only be used,
+@@ -371,8 +371,11 @@ extern "C++"
+ #define FT_STRDUP( dst, str )                           \
+           FT_MEM_SET_ERROR( FT_MEM_STRDUP( dst, str ) )
  
-+/*
-+ * This file has been modified by Loongson Technology in 2022, These
-+ * modifications are Copyright (c) 2019, 2022, Loongson Technology, and are made
-+ * available on the same license terms set forth above.
-+ */
-+
- package sun.jvm.hotspot.debugger.linux;
+-#define FT_MEM_DUP( dst, address, size )                                    \
+-          (dst) = ft_mem_dup( memory, (address), (FT_ULong)(size), &error )
++#define FT_MEM_DUP( dst, address, size )                       \
++          FT_ASSIGNP_INNER( dst, ft_mem_dup( memory,           \
++                                             (address),        \
++                                             (FT_ULong)(size), \
++                                             &error ) )
  
- import java.io.*;
-@@ -34,12 +40,16 @@
- import sun.jvm.hotspot.debugger.amd64.*;
- import sun.jvm.hotspot.debugger.aarch64.*;
- import sun.jvm.hotspot.debugger.sparc.*;
-+import sun.jvm.hotspot.debugger.mips64.*;
-+import sun.jvm.hotspot.debugger.loongarch64.*;
- import sun.jvm.hotspot.debugger.ppc64.*;
- import sun.jvm.hotspot.debugger.linux.x86.*;
- import sun.jvm.hotspot.debugger.linux.amd64.*;
- import sun.jvm.hotspot.debugger.linux.sparc.*;
- import sun.jvm.hotspot.debugger.linux.ppc64.*;
- import sun.jvm.hotspot.debugger.linux.aarch64.*;
-+import sun.jvm.hotspot.debugger.linux.mips64.*;
-+import sun.jvm.hotspot.debugger.linux.loongarch64.*;
- import sun.jvm.hotspot.utilities.*;
+ #define FT_DUP( dst, address, size )                           \
+           FT_MEM_SET_ERROR( FT_MEM_DUP( dst, address, size ) )
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftmmtypes.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftmmtypes.h
+index c4b21d614..8449e7a01 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftmmtypes.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftmmtypes.h
+@@ -5,7 +5,7 @@
+  *   OpenType Variations type definitions for internal use
+  *   with the multi-masters service (specification).
+  *
+- * Copyright (C) 2022-2023 by
++ * Copyright (C) 2022-2024 by
+  * David Turner, Robert Wilhelm, Werner Lemberg, George Williams, and
+  * Dominik Röttsches.
+  *
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftobjs.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftobjs.h
+index 28bc9b65f..a1e93298f 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftobjs.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftobjs.h
+@@ -4,7 +4,7 @@
+  *
+  *   The FreeType private base classes (specification).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+@@ -604,12 +604,6 @@ FT_BEGIN_HEADER
+ #define FT_FACE_MEMORY( x )   FT_FACE( x )->memory
+ #define FT_FACE_STREAM( x )   FT_FACE( x )->stream
  
- class LinuxCDebugger implements CDebugger {
-@@ -102,7 +112,21 @@
-        Address pc  = context.getRegisterAsAddress(SPARCThreadContext.R_O7);
-        if (pc == null) return null;
-        return new LinuxSPARCCFrame(dbg, sp, pc, LinuxDebuggerLocal.getAddressSize());
--    }  else if (cpu.equals("ppc64")) {
-+    } else if (cpu.equals("mips64")) {
-+       MIPS64ThreadContext context = (MIPS64ThreadContext) thread.getContext();
-+       Address sp = context.getRegisterAsAddress(MIPS64ThreadContext.SP);
-+       if (sp == null) return null;
-+       Address pc  = context.getRegisterAsAddress(MIPS64ThreadContext.PC);
-+       if (pc == null) return null;
-+       return new LinuxMIPS64CFrame(dbg, sp, pc);
-+    } else if (cpu.equals("loongarch64")) {
-+       LOONGARCH64ThreadContext context = (LOONGARCH64ThreadContext) thread.getContext();
-+       Address fp = context.getRegisterAsAddress(LOONGARCH64ThreadContext.FP);
-+       if (fp == null) return null;
-+       Address pc  = context.getRegisterAsAddress(LOONGARCH64ThreadContext.PC);
-+       if (pc == null) return null;
-+       return new LinuxLOONGARCH64CFrame(dbg, fp, pc);
-+    } else if (cpu.equals("ppc64")) {
-         PPC64ThreadContext context = (PPC64ThreadContext) thread.getContext();
-         Address sp = context.getRegisterAsAddress(PPC64ThreadContext.SP);
-         if (sp == null) return null;
-diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxThreadContextFactory.java jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxThreadContextFactory.java
---- openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxThreadContextFactory.java	2022-10-12 23:00:03.000000000 +0800
-+++ jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxThreadContextFactory.java	2023-09-12 13:54:26.373575786 +0800
-@@ -22,6 +22,12 @@
+-#define FT_SIZE_FACE( x )     FT_SIZE( x )->face
+-#define FT_SLOT_FACE( x )     FT_SLOT( x )->face
+-
+-#define FT_FACE_SLOT( x )     FT_FACE( x )->glyph
+-#define FT_FACE_SIZE( x )     FT_FACE( x )->size
+-
+ 
+   /**************************************************************************
+    *
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftpsprop.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftpsprop.h
+index 1d5b287ad..4f11aa16b 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftpsprop.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftpsprop.h
+@@ -4,7 +4,7 @@
   *
-  */
+  *   Get and set properties of PostScript drivers (specification).
+  *
+- * Copyright (C) 2017-2023 by
++ * Copyright (C) 2017-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftrfork.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftrfork.h
+index e96459921..05c1d6c48 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftrfork.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftrfork.h
+@@ -4,7 +4,7 @@
+  *
+  *   Embedded resource forks accessor (specification).
+  *
+- * Copyright (C) 2004-2023 by
++ * Copyright (C) 2004-2024 by
+  * Masatake YAMATO and Redhat K.K.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftserv.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftserv.h
+index 1e85d6d38..8c35dbd71 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftserv.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftserv.h
+@@ -4,7 +4,7 @@
+  *
+  *   The FreeType services (specification only).
+  *
+- * Copyright (C) 2003-2023 by
++ * Copyright (C) 2003-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftstream.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftstream.h
+index 88e19287c..fd52f767e 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftstream.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftstream.h
+@@ -4,7 +4,7 @@
+  *
+  *   Stream handling (specification).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/fttrace.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/fttrace.h
+index 319fe56fd..42595a29f 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/fttrace.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/fttrace.h
+@@ -4,7 +4,7 @@
+  *
+  *   Tracing handling (specification only).
+  *
+- * Copyright (C) 2002-2023 by
++ * Copyright (C) 2002-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+@@ -64,6 +64,7 @@ FT_TRACE_DEF( ttbdf )     /* TrueType embedded BDF   (ttbdf.c)    */
+ FT_TRACE_DEF( ttcmap )    /* charmap handler         (ttcmap.c)   */
+ FT_TRACE_DEF( ttcolr )    /* glyph layer table       (ttcolr.c)   */
+ FT_TRACE_DEF( ttcpal )    /* color palette table     (ttcpal.c)   */
++FT_TRACE_DEF( ttgpos )    /* GPOS handler            (ttgpos.c)   */
+ FT_TRACE_DEF( ttsvg )     /* OpenType SVG table      (ttsvg.c)    */
+ FT_TRACE_DEF( ttkern )    /* kerning handler         (ttkern.c)   */
+ FT_TRACE_DEF( ttload )    /* basic TrueType tables   (ttload.c)   */
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftvalid.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftvalid.h
+index e98ee4e47..a1312f2ab 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftvalid.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftvalid.h
+@@ -4,7 +4,7 @@
+  *
+  *   FreeType validation support (specification).
+  *
+- * Copyright (C) 2004-2023 by
++ * Copyright (C) 2004-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/psaux.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/psaux.h
+index dfb1987f8..745d2cb56 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/psaux.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/psaux.h
+@@ -5,7 +5,7 @@
+  *   Auxiliary functions and data structures related to PostScript fonts
+  *   (specification).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+@@ -225,6 +225,7 @@ FT_BEGIN_HEADER
  
-+/*
-+ * This file has been modified by Loongson Technology in 2021, These
-+ * modifications are Copyright (c) 2019, 2021, Loongson Technology, and are made
-+ * available on the same license terms set forth above.
-+ */
-+
- package sun.jvm.hotspot.debugger.linux;
+   typedef enum  T1_FieldLocation_
+   {
++    T1_FIELD_LOCATION_NONE = 0,
+     T1_FIELD_LOCATION_CID_INFO,
+     T1_FIELD_LOCATION_FONT_DICT,
+     T1_FIELD_LOCATION_FONT_EXTRA,
+@@ -249,6 +250,7 @@ FT_BEGIN_HEADER
+   /* structure type used to model object fields */
+   typedef struct  T1_FieldRec_
+   {
++    FT_UInt             len;          /* field identifier length        */
+     const char*         ident;        /* field identifier               */
+     T1_FieldLocation    location;
+     T1_FieldType        type;         /* type of field                  */
+@@ -273,8 +275,9 @@ FT_BEGIN_HEADER
  
- import java.lang.reflect.*;
-@@ -30,6 +36,8 @@
- import sun.jvm.hotspot.debugger.linux.x86.*;
- import sun.jvm.hotspot.debugger.linux.ppc64.*;
- import sun.jvm.hotspot.debugger.linux.sparc.*;
-+import sun.jvm.hotspot.debugger.linux.mips64.*;
-+import sun.jvm.hotspot.debugger.linux.loongarch64.*;
+ #define T1_NEW_SIMPLE_FIELD( _ident, _type, _fname, _dict ) \
+           {                                                 \
++            sizeof ( _ident ) - 1,                          \
+             _ident, T1CODE, _type,                          \
+-            0,                                              \
++            NULL,                                           \
+             FT_FIELD_OFFSET( _fname ),                      \
+             FT_FIELD_SIZE( _fname ),                        \
+             0, 0,                                           \
+@@ -283,6 +286,7 @@ FT_BEGIN_HEADER
  
- class LinuxThreadContextFactory {
-    static ThreadContext createThreadContext(LinuxDebugger dbg) {
-@@ -40,7 +48,11 @@
-          return new LinuxAMD64ThreadContext(dbg);
-       } else if (cpu.equals("sparc")) {
-          return new LinuxSPARCThreadContext(dbg);
--      }  else if (cpu.equals("ppc64")) {
-+      } else if (cpu.equals("mips64")) {
-+         return new LinuxMIPS64ThreadContext(dbg);
-+      } else if (cpu.equals("loongarch64")) {
-+         return new LinuxLOONGARCH64ThreadContext(dbg);
-+      } else if (cpu.equals("ppc64")) {
-           return new LinuxPPC64ThreadContext(dbg);
-       } else  {
-         try {
-diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/loongarch64/LinuxLOONGARCH64CFrame.java jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/loongarch64/LinuxLOONGARCH64CFrame.java
---- openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/loongarch64/LinuxLOONGARCH64CFrame.java	1970-01-01 08:00:00.000000000 +0800
-+++ jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/loongarch64/LinuxLOONGARCH64CFrame.java	2023-09-12 13:54:26.373575786 +0800
-@@ -0,0 +1,92 @@
-+/*
-+ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
-+ * Copyright (c) 2015, 2022, Loongson Technology. 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 sun.jvm.hotspot.debugger.linux.loongarch64;
-+
-+import sun.jvm.hotspot.debugger.*;
-+import sun.jvm.hotspot.debugger.linux.*;
-+import sun.jvm.hotspot.debugger.cdbg.*;
-+import sun.jvm.hotspot.debugger.cdbg.basic.*;
-+import sun.jvm.hotspot.debugger.loongarch64.*;
-+
-+final public class LinuxLOONGARCH64CFrame extends BasicCFrame {
-+   // package/class internals only
-+   public LinuxLOONGARCH64CFrame(LinuxDebugger dbg, Address fp, Address pc) {
-+      super(dbg.getCDebugger());
-+      this.fp = fp;
-+      this.pc = pc;
-+      this.dbg = dbg;
-+   }
+ #define T1_NEW_CALLBACK_FIELD( _ident, _reader, _dict ) \
+           {                                             \
++            sizeof ( _ident ) - 1,                      \
+             _ident, T1CODE, T1_FIELD_TYPE_CALLBACK,     \
+             (T1_Field_ParseFunc)_reader,                \
+             0, 0,                                       \
+@@ -292,8 +296,9 @@ FT_BEGIN_HEADER
+ 
+ #define T1_NEW_TABLE_FIELD( _ident, _type, _fname, _max, _dict ) \
+           {                                                      \
++            sizeof ( _ident ) - 1,                               \
+             _ident, T1CODE, _type,                               \
+-            0,                                                   \
++            NULL,                                                \
+             FT_FIELD_OFFSET( _fname ),                           \
+             FT_FIELD_SIZE_DELTA( _fname ),                       \
+             _max,                                                \
+@@ -303,8 +308,9 @@ FT_BEGIN_HEADER
+ 
+ #define T1_NEW_TABLE_FIELD2( _ident, _type, _fname, _max, _dict ) \
+           {                                                       \
++            sizeof ( _ident ) - 1,                                \
+             _ident, T1CODE, _type,                                \
+-            0,                                                    \
++            NULL,                                                 \
+             FT_FIELD_OFFSET( _fname ),                            \
+             FT_FIELD_SIZE_DELTA( _fname ),                        \
+             _max, 0,                                              \
+@@ -354,6 +360,13 @@ FT_BEGIN_HEADER
+ #define T1_FIELD_CALLBACK( _ident, _name, _dict )       \
+           T1_NEW_CALLBACK_FIELD( _ident, _name, _dict )
+ 
++#define T1_FIELD_ZERO                                         \
++          {                                                   \
++            0,                                                \
++            NULL, T1_FIELD_LOCATION_NONE, T1_FIELD_TYPE_NONE, \
++            NULL, 0, 0, 0, 0, 0                               \
++          }
 +
-+   // override base class impl to avoid ELF parsing
-+   public ClosestSymbol closestSymbolToPC() {
-+      // try native lookup in debugger.
-+      return dbg.lookup(dbg.getAddressValue(pc()));
-+   }
+ 
+   /*************************************************************************/
+   /*************************************************************************/
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/pshints.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/pshints.h
+index ededc4c72..dba6c7303 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/pshints.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/pshints.h
+@@ -6,7 +6,7 @@
+  *   recorders (specification only).  These are used to support native
+  *   T1/T2 hints in the 'type1', 'cid', and 'cff' font drivers.
+  *
+- * Copyright (C) 2001-2023 by
++ * Copyright (C) 2001-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svbdf.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svbdf.h
+index bf0c1dcc7..89e9c2e5d 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svbdf.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svbdf.h
+@@ -4,7 +4,7 @@
+  *
+  *   The FreeType BDF services (specification).
+  *
+- * Copyright (C) 2003-2023 by
++ * Copyright (C) 2003-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svcfftl.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svcfftl.h
+index 4a20498ee..3cb483c34 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svcfftl.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svcfftl.h
+@@ -4,7 +4,7 @@
+  *
+  *   The FreeType CFF tables loader service (specification).
+  *
+- * Copyright (C) 2017-2023 by
++ * Copyright (C) 2017-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svcid.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svcid.h
+index 06d0cb8fd..8362cb872 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svcid.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svcid.h
+@@ -4,7 +4,7 @@
+  *
+  *   The FreeType CID font services (specification).
+  *
+- * Copyright (C) 2007-2023 by
++ * Copyright (C) 2007-2024 by
+  * Derek Clegg and Michael Toftdal.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svfntfmt.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svfntfmt.h
+index bc45e8056..6b837e79f 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svfntfmt.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svfntfmt.h
+@@ -4,7 +4,7 @@
+  *
+  *   The FreeType font format service (specification only).
+  *
+- * Copyright (C) 2003-2023 by
++ * Copyright (C) 2003-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svgldict.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svgldict.h
+index 6437abfbf..6126ec9ad 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svgldict.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svgldict.h
+@@ -4,7 +4,7 @@
+  *
+  *   The FreeType glyph dictionary services (specification).
+  *
+- * Copyright (C) 2003-2023 by
++ * Copyright (C) 2003-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svgxval.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svgxval.h
+index 31016afe0..29cf55281 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svgxval.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svgxval.h
+@@ -4,7 +4,7 @@
+  *
+  *   FreeType API for validating TrueTypeGX/AAT tables (specification).
+  *
+- * Copyright (C) 2004-2023 by
++ * Copyright (C) 2004-2024 by
+  * Masatake YAMATO, Red Hat K.K.,
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svkern.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svkern.h
+index bcabbc3e6..ac1bc30c4 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svkern.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svkern.h
+@@ -4,7 +4,7 @@
+  *
+  *   The FreeType Kerning service (specification).
+  *
+- * Copyright (C) 2006-2023 by
++ * Copyright (C) 2006-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svmetric.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svmetric.h
+index 167617ebb..8b3563b25 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svmetric.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svmetric.h
+@@ -4,7 +4,7 @@
+  *
+  *   The FreeType services for metrics variations (specification).
+  *
+- * Copyright (C) 2016-2023 by
++ * Copyright (C) 2016-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svmm.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svmm.h
+index 7e76ab832..5288fadf3 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svmm.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svmm.h
+@@ -4,7 +4,7 @@
+  *
+  *   The FreeType Multiple Masters and GX var services (specification).
+  *
+- * Copyright (C) 2003-2023 by
++ * Copyright (C) 2003-2024 by
+  * David Turner, Robert Wilhelm, Werner Lemberg, and Dominik Röttsches.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svotval.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svotval.h
+index a4683cd5f..7aea7ec11 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svotval.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svotval.h
+@@ -4,7 +4,7 @@
+  *
+  *   The FreeType OpenType validation service (specification).
+  *
+- * Copyright (C) 2004-2023 by
++ * Copyright (C) 2004-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpfr.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpfr.h
+index fd189c7de..b2fac6d08 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpfr.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpfr.h
+@@ -4,7 +4,7 @@
+  *
+  *   Internal PFR service functions (specification).
+  *
+- * Copyright (C) 2003-2023 by
++ * Copyright (C) 2003-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpostnm.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpostnm.h
+index 2b8f6dfec..d19f3adc6 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpostnm.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpostnm.h
+@@ -4,7 +4,7 @@
+  *
+  *   The FreeType PostScript name services (specification).
+  *
+- * Copyright (C) 2003-2023 by
++ * Copyright (C) 2003-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svprop.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svprop.h
+index 932ce32e0..ba39c0dd4 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svprop.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svprop.h
+@@ -4,7 +4,7 @@
+  *
+  *   The FreeType property service (specification).
+  *
+- * Copyright (C) 2012-2023 by
++ * Copyright (C) 2012-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpscmap.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpscmap.h
+index 6e599f3aa..d4908ee41 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpscmap.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpscmap.h
+@@ -4,7 +4,7 @@
+  *
+  *   The FreeType PostScript charmap service (specification).
+  *
+- * Copyright (C) 2003-2023 by
++ * Copyright (C) 2003-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpsinfo.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpsinfo.h
+index 09c4cdccc..2aadcdd02 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpsinfo.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpsinfo.h
+@@ -4,7 +4,7 @@
+  *
+  *   The FreeType PostScript info service (specification).
+  *
+- * Copyright (C) 2003-2023 by
++ * Copyright (C) 2003-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svsfnt.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svsfnt.h
+index f98df2ef5..9e0f4ff20 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svsfnt.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svsfnt.h
+@@ -4,7 +4,7 @@
+  *
+  *   The FreeType SFNT table loading service (specification).
+  *
+- * Copyright (C) 2003-2023 by
++ * Copyright (C) 2003-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svttcmap.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svttcmap.h
+index 5f9eb02d6..250886bcc 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svttcmap.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svttcmap.h
+@@ -4,7 +4,7 @@
+  *
+  *   The FreeType TrueType/sfnt cmap extra information service.
+  *
+- * Copyright (C) 2003-2023 by
++ * Copyright (C) 2003-2024 by
+  * Masatake YAMATO, Redhat K.K.,
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svtteng.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svtteng.h
+index ad577cb29..14967529a 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svtteng.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svtteng.h
+@@ -4,7 +4,7 @@
+  *
+  *   The FreeType TrueType engine query service (specification).
+  *
+- * Copyright (C) 2006-2023 by
++ * Copyright (C) 2006-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svttglyf.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svttglyf.h
+index ca6fff744..f190b3985 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svttglyf.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svttglyf.h
+@@ -4,7 +4,7 @@
+  *
+  *   The FreeType TrueType glyph service.
+  *
+- * Copyright (C) 2007-2023 by
++ * Copyright (C) 2007-2024 by
+  * David Turner.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svwinfnt.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svwinfnt.h
+index 002923f8c..49f3fb7f7 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svwinfnt.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svwinfnt.h
+@@ -4,7 +4,7 @@
+  *
+  *   The FreeType Windows FNT/FONT service (specification).
+  *
+- * Copyright (C) 2003-2023 by
++ * Copyright (C) 2003-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/sfnt.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/sfnt.h
+index a2d4e15ba..35e4e73af 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/sfnt.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/sfnt.h
+@@ -4,7 +4,7 @@
+  *
+  *   High-level 'sfnt' driver interface (specification).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+@@ -924,6 +924,7 @@ FT_BEGIN_HEADER
+     /* this field was called `load_kerning' up to version 2.1.10 */
+     TT_Load_Table_Func  load_kern;
+ 
++    TT_Load_Table_Func  load_gpos;
+     TT_Load_Table_Func  load_gasp;
+     TT_Load_Table_Func  load_pclt;
+ 
+@@ -944,6 +945,8 @@ FT_BEGIN_HEADER
+ 
+     /* new elements introduced after version 2.1.10 */
+ 
++    TT_Face_GetKerningFunc  get_gpos_kerning;
++
+     /* load the font directory, i.e., the offset table and */
+     /* the table directory                                 */
+     TT_Load_Table_Func    load_font_dir;
+@@ -1002,6 +1005,7 @@ FT_BEGIN_HEADER
+           load_name_,                    \
+           free_name_,                    \
+           load_kern_,                    \
++          load_gpos_,                    \
+           load_gasp_,                    \
+           load_pclt_,                    \
+           load_bhed_,                    \
+@@ -1009,6 +1013,7 @@ FT_BEGIN_HEADER
+           get_psname_,                   \
+           free_psnames_,                 \
+           get_kerning_,                  \
++          get_gpos_kerning_,             \
+           load_font_dir_,                \
+           load_hmtx_,                    \
+           load_eblc_,                    \
+@@ -1050,6 +1055,7 @@ FT_BEGIN_HEADER
+     load_name_,                          \
+     free_name_,                          \
+     load_kern_,                          \
++    load_gpos_,                          \
+     load_gasp_,                          \
+     load_pclt_,                          \
+     load_bhed_,                          \
+@@ -1057,6 +1063,7 @@ FT_BEGIN_HEADER
+     get_psname_,                         \
+     free_psnames_,                       \
+     get_kerning_,                        \
++    get_gpos_kerning_,                   \
+     load_font_dir_,                      \
+     load_hmtx_,                          \
+     load_eblc_,                          \
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/svginterface.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/svginterface.h
+index f464b2c05..68c99efb1 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/svginterface.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/svginterface.h
+@@ -4,7 +4,7 @@
+  *
+  *   Interface of ot-svg module (specification only).
+  *
+- * Copyright (C) 2022-2023 by
++ * Copyright (C) 2022-2024 by
+  * David Turner, Robert Wilhelm, Werner Lemberg, and Moazin Khatti.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/t1types.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/t1types.h
+index b9c94398f..1821ae5cc 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/t1types.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/t1types.h
+@@ -5,7 +5,7 @@
+  *   Basic Type1/Type2 type definitions and interface (specification
+  *   only).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+@@ -21,7 +21,7 @@
+ #define T1TYPES_H_
+ 
+ 
+-#include 
++#include 
+ #include 
+ #include 
+ #include 
+@@ -137,6 +137,54 @@ FT_BEGIN_HEADER
+   } CID_SubrsRec, *CID_Subrs;
+ 
+ 
++  /* this structure is used to store the BlendDesignMap entry for an axis */
++  typedef struct  PS_DesignMap_
++  {
++    FT_Byte    num_points;
++    FT_Long*   design_points;
++    FT_Fixed*  blend_points;
 +
-+   public Address pc() {
-+      return pc;
-+   }
++  } PS_DesignMapRec, *PS_DesignMap;
 +
-+   public Address localVariableBase() {
-+      return fp;
-+   }
++  /* backward compatible definition */
++  typedef PS_DesignMapRec  T1_DesignMap;
 +
-+   public CFrame sender(ThreadProxy thread) {
-+      LOONGARCH64ThreadContext context = (LOONGARCH64ThreadContext) thread.getContext();
-+      Address sp = context.getRegisterAsAddress(LOONGARCH64ThreadContext.SP);
-+      Address nextFP;
-+      Address nextPC;
 +
-+      if ((fp == null) || fp.lessThan(sp)) {
-+        return null;
-+      }
++  typedef struct  PS_BlendRec_
++  {
++    FT_UInt          num_designs;
++    FT_UInt          num_axis;
 +
-+      try {
-+        nextFP = fp.getAddressAt(-2 * ADDRESS_SIZE);
-+      } catch (Exception e) {
-+        return null;
-+      }
-+      if (nextFP == null) {
-+        return null;
-+      }
++    FT_String*       axis_names[T1_MAX_MM_AXIS];
++    FT_Fixed*        design_pos[T1_MAX_MM_DESIGNS];
++    PS_DesignMapRec  design_map[T1_MAX_MM_AXIS];
 +
-+      try {
-+        nextPC  = fp.getAddressAt(-1 * ADDRESS_SIZE);
-+      } catch (Exception e) {
-+        return null;
-+      }
-+      if (nextPC == null) {
-+        return null;
-+      }
++    FT_Fixed*        weight_vector;
++    FT_Fixed*        default_weight_vector;
 +
-+      return new LinuxLOONGARCH64CFrame(dbg, nextFP, nextPC);
-+   }
++    PS_FontInfo      font_infos[T1_MAX_MM_DESIGNS + 1];
++    PS_Private       privates  [T1_MAX_MM_DESIGNS + 1];
 +
-+   private static final int ADDRESS_SIZE = 8;
-+   private Address pc;
-+   private Address fp;
-+   private LinuxDebugger dbg;
-+}
-diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/loongarch64/LinuxLOONGARCH64ThreadContext.java jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/loongarch64/LinuxLOONGARCH64ThreadContext.java
---- openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/loongarch64/LinuxLOONGARCH64ThreadContext.java	1970-01-01 08:00:00.000000000 +0800
-+++ jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/loongarch64/LinuxLOONGARCH64ThreadContext.java	2023-09-12 13:54:26.373575786 +0800
-@@ -0,0 +1,47 @@
-+/*
-+ * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
-+ * Copyright (c) 2015, 2021, Loongson Technology. 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.
-+ *
-+ */
++    FT_ULong         blend_bitflags;
 +
-+package sun.jvm.hotspot.debugger.linux.loongarch64;
++    FT_BBox*         bboxes    [T1_MAX_MM_DESIGNS + 1];
 +
-+import sun.jvm.hotspot.debugger.*;
-+import sun.jvm.hotspot.debugger.loongarch64.*;
-+import sun.jvm.hotspot.debugger.linux.*;
++    /* since 2.3.0 */
 +
-+public class LinuxLOONGARCH64ThreadContext extends LOONGARCH64ThreadContext {
-+  private LinuxDebugger debugger;
++    /* undocumented, optional: the default design instance;   */
++    /* corresponds to default_weight_vector --                */
++    /* num_default_design_vector == 0 means it is not present */
++    /* in the font and associated metrics files               */
++    FT_UInt          default_design_vector[T1_MAX_MM_DESIGNS];
++    FT_UInt          num_default_design_vector;
 +
-+  public LinuxLOONGARCH64ThreadContext(LinuxDebugger debugger) {
-+    super();
-+    this.debugger = debugger;
-+  }
++  } PS_BlendRec, *PS_Blend;
 +
-+  public void setRegisterAsAddress(int index, Address value) {
-+    setRegister(index, debugger.getAddressValue(value));
-+  }
 +
-+  public Address getRegisterAsAddress(int index) {
-+    return debugger.newAddress(getRegister(index));
-+  }
-+}
-diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/mips64/LinuxMIPS64CFrame.java jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/mips64/LinuxMIPS64CFrame.java
---- openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/mips64/LinuxMIPS64CFrame.java	1970-01-01 08:00:00.000000000 +0800
-+++ jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/mips64/LinuxMIPS64CFrame.java	2023-09-12 13:54:26.373575786 +0800
-@@ -0,0 +1,80 @@
-+/*
-+ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
-+ * Copyright (c) 2015, 2018, Loongson Technology. 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.
-+ *
-+ */
++  /* backward compatible definition */
++  typedef PS_BlendRec  T1_Blend;
 +
-+package sun.jvm.hotspot.debugger.linux.mips64;
 +
-+import sun.jvm.hotspot.debugger.*;
-+import sun.jvm.hotspot.debugger.linux.*;
-+import sun.jvm.hotspot.debugger.cdbg.*;
-+import sun.jvm.hotspot.debugger.cdbg.basic.*;
-+import sun.jvm.hotspot.debugger.mips64.*;
+   /*************************************************************************/
+   /*************************************************************************/
+   /*************************************************************************/
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/tttypes.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/tttypes.h
+index b9788c783..7053e656a 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/tttypes.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/tttypes.h
+@@ -5,7 +5,7 @@
+  *   Basic SFNT/TrueType type definitions and interface (specification
+  *   only).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+@@ -24,6 +24,7 @@
+ #include 
+ #include 
+ #include 
++#include "freetype/fttypes.h"
+ 
+ #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+ #include 
+@@ -1581,6 +1582,11 @@ FT_BEGIN_HEADER
+     FT_UInt32             kern_avail_bits;
+     FT_UInt32             kern_order_bits;
+ 
++#ifdef TT_CONFIG_OPTION_GPOS_KERNING
++    FT_Byte*              gpos_table;
++    FT_Bool               gpos_kerning_available;
++#endif
++
+ #ifdef TT_CONFIG_OPTION_BDF
+     TT_BDFRec             bdf;
+ #endif /* TT_CONFIG_OPTION_BDF */
+@@ -1649,9 +1655,9 @@ FT_BEGIN_HEADER
+   {
+     FT_Memory   memory;
+     FT_UShort   max_points;
+-    FT_Short    max_contours;
++    FT_UShort   max_contours;
+     FT_UShort   n_points;    /* number of points in zone    */
+-    FT_Short    n_contours;  /* number of contours          */
++    FT_UShort   n_contours;  /* number of contours          */
+ 
+     FT_Vector*  org;         /* original point coordinates  */
+     FT_Vector*  cur;         /* current point coordinates   */
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/wofftypes.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/wofftypes.h
+index 0c1d8eeaf..4a169d12f 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/wofftypes.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/wofftypes.h
+@@ -5,7 +5,7 @@
+  *   Basic WOFF/WOFF2 type definitions and interface (specification
+  *   only).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/otsvg.h b/src/java.desktop/share/native/libfreetype/include/freetype/otsvg.h
+index bfe9a6ab7..9d356938c 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/otsvg.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/otsvg.h
+@@ -4,7 +4,7 @@
+  *
+  *   Interface for OT-SVG support related things (specification).
+  *
+- * Copyright (C) 2022-2023 by
++ * Copyright (C) 2022-2024 by
+  * David Turner, Robert Wilhelm, Werner Lemberg, and Moazin Khatti.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/t1tables.h b/src/java.desktop/share/native/libfreetype/include/freetype/t1tables.h
+index 1aecfbbd9..fbd558aa3 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/t1tables.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/t1tables.h
+@@ -5,7 +5,7 @@
+  *   Basic Type 1/Type 2 tables definitions and interface (specification
+  *   only).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+@@ -269,64 +269,6 @@ FT_BEGIN_HEADER
+   /* */
+ 
+ 
+-  /* maximum number of Multiple Masters designs, as defined in the spec */
+-#define T1_MAX_MM_DESIGNS     16
+-
+-  /* maximum number of Multiple Masters axes, as defined in the spec */
+-#define T1_MAX_MM_AXIS        4
+-
+-  /* maximum number of elements in a design map */
+-#define T1_MAX_MM_MAP_POINTS  20
+-
+-
+-  /* this structure is used to store the BlendDesignMap entry for an axis */
+-  typedef struct  PS_DesignMap_
+-  {
+-    FT_Byte    num_points;
+-    FT_Long*   design_points;
+-    FT_Fixed*  blend_points;
+-
+-  } PS_DesignMapRec, *PS_DesignMap;
+-
+-  /* backward compatible definition */
+-  typedef PS_DesignMapRec  T1_DesignMap;
+-
+-
+-  typedef struct  PS_BlendRec_
+-  {
+-    FT_UInt          num_designs;
+-    FT_UInt          num_axis;
+-
+-    FT_String*       axis_names[T1_MAX_MM_AXIS];
+-    FT_Fixed*        design_pos[T1_MAX_MM_DESIGNS];
+-    PS_DesignMapRec  design_map[T1_MAX_MM_AXIS];
+-
+-    FT_Fixed*        weight_vector;
+-    FT_Fixed*        default_weight_vector;
+-
+-    PS_FontInfo      font_infos[T1_MAX_MM_DESIGNS + 1];
+-    PS_Private       privates  [T1_MAX_MM_DESIGNS + 1];
+-
+-    FT_ULong         blend_bitflags;
+-
+-    FT_BBox*         bboxes    [T1_MAX_MM_DESIGNS + 1];
+-
+-    /* since 2.3.0 */
+-
+-    /* undocumented, optional: the default design instance;   */
+-    /* corresponds to default_weight_vector --                */
+-    /* num_default_design_vector == 0 means it is not present */
+-    /* in the font and associated metrics files               */
+-    FT_UInt          default_design_vector[T1_MAX_MM_DESIGNS];
+-    FT_UInt          num_default_design_vector;
+-
+-  } PS_BlendRec, *PS_Blend;
+-
+-
+-  /* backward compatible definition */
+-  typedef PS_BlendRec  T1_Blend;
+-
+-
+   /**************************************************************************
+    *
+    * @struct:
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ttnameid.h b/src/java.desktop/share/native/libfreetype/include/freetype/ttnameid.h
+index e31c68b9b..d5d470e38 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/ttnameid.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/ttnameid.h
+@@ -4,7 +4,7 @@
+  *
+  *   TrueType name ID definitions (specification only).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/tttables.h b/src/java.desktop/share/native/libfreetype/include/freetype/tttables.h
+index a9f60e762..2cf0ff1bc 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/tttables.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/tttables.h
+@@ -5,7 +5,7 @@
+  *   Basic SFNT/TrueType tables definitions and interface
+  *   (specification only).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+@@ -838,8 +838,9 @@ FT_BEGIN_HEADER
+    *     The target charmap.
+    *
+    * @return:
+-   *   The format of `charmap`.  If `charmap` doesn't belong to an SFNT face,
+-   *   return -1.
++   *   The format of `charmap`.  If `charmap` doesn't belong to an SFNT face
++   *   (including the synthetic Unicode charmap sometimes created by
++   *   FreeType), return -1.
+    */
+   FT_EXPORT( FT_Long )
+   FT_Get_CMap_Format( FT_CharMap  charmap );
+diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/tttags.h b/src/java.desktop/share/native/libfreetype/include/freetype/tttags.h
+index 9bf4fca23..da0af5d3f 100644
+--- a/src/java.desktop/share/native/libfreetype/include/freetype/tttags.h
++++ b/src/java.desktop/share/native/libfreetype/include/freetype/tttags.h
+@@ -4,7 +4,7 @@
+  *
+  *   Tags for TrueType and OpenType tables (specification only).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/include/ft2build.h b/src/java.desktop/share/native/libfreetype/include/ft2build.h
+index 58491ceea..d3d768503 100644
+--- a/src/java.desktop/share/native/libfreetype/include/ft2build.h
++++ b/src/java.desktop/share/native/libfreetype/include/ft2build.h
+@@ -4,7 +4,7 @@
+  *
+  *   FreeType 2 build and setup macros.
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afblue.c b/src/java.desktop/share/native/libfreetype/src/autofit/afblue.c
+index d7655b9b9..ea83969cd 100644
+--- a/src/java.desktop/share/native/libfreetype/src/autofit/afblue.c
++++ b/src/java.desktop/share/native/libfreetype/src/autofit/afblue.c
+@@ -7,7 +7,7 @@
+  *
+  *   Auto-fitter data for blue strings (body).
+  *
+- * Copyright (C) 2013-2023 by
++ * Copyright (C) 2013-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afblue.cin b/src/java.desktop/share/native/libfreetype/src/autofit/afblue.cin
+index d561c5093..d2270fac7 100644
+--- a/src/java.desktop/share/native/libfreetype/src/autofit/afblue.cin
++++ b/src/java.desktop/share/native/libfreetype/src/autofit/afblue.cin
+@@ -4,7 +4,7 @@
+  *
+  *   Auto-fitter data for blue strings (body).
+  *
+- * Copyright (C) 2013-2023 by
++ * Copyright (C) 2013-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afblue.dat b/src/java.desktop/share/native/libfreetype/src/autofit/afblue.dat
+index 8299baa25..88bab2632 100644
+--- a/src/java.desktop/share/native/libfreetype/src/autofit/afblue.dat
++++ b/src/java.desktop/share/native/libfreetype/src/autofit/afblue.dat
+@@ -2,7 +2,7 @@
+ //
+ //   Auto-fitter data for blue strings.
+ //
+-// Copyright (C) 2013-2023 by
++// Copyright (C) 2013-2024 by
+ // David Turner, Robert Wilhelm, and Werner Lemberg.
+ //
+ // This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afblue.h b/src/java.desktop/share/native/libfreetype/src/autofit/afblue.h
+index 76f2f47cb..2aa9d0984 100644
+--- a/src/java.desktop/share/native/libfreetype/src/autofit/afblue.h
++++ b/src/java.desktop/share/native/libfreetype/src/autofit/afblue.h
+@@ -7,7 +7,7 @@
+  *
+  *   Auto-fitter data for blue strings (specification).
+  *
+- * Copyright (C) 2013-2023 by
++ * Copyright (C) 2013-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afblue.hin b/src/java.desktop/share/native/libfreetype/src/autofit/afblue.hin
+index 6a31298e6..38031505a 100644
+--- a/src/java.desktop/share/native/libfreetype/src/autofit/afblue.hin
++++ b/src/java.desktop/share/native/libfreetype/src/autofit/afblue.hin
+@@ -4,7 +4,7 @@
+  *
+  *   Auto-fitter data for blue strings (specification).
+  *
+- * Copyright (C) 2013-2023 by
++ * Copyright (C) 2013-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afcjk.c b/src/java.desktop/share/native/libfreetype/src/autofit/afcjk.c
+index f414289ad..869b60487 100644
+--- a/src/java.desktop/share/native/libfreetype/src/autofit/afcjk.c
++++ b/src/java.desktop/share/native/libfreetype/src/autofit/afcjk.c
+@@ -4,7 +4,7 @@
+  *
+  *   Auto-fitter hinting routines for CJK writing system (body).
+  *
+- * Copyright (C) 2006-2023 by
++ * Copyright (C) 2006-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afcjk.h b/src/java.desktop/share/native/libfreetype/src/autofit/afcjk.h
+index f380ef6e0..bc5aaf12e 100644
+--- a/src/java.desktop/share/native/libfreetype/src/autofit/afcjk.h
++++ b/src/java.desktop/share/native/libfreetype/src/autofit/afcjk.h
+@@ -4,7 +4,7 @@
+  *
+  *   Auto-fitter hinting routines for CJK writing system (specification).
+  *
+- * Copyright (C) 2006-2023 by
++ * Copyright (C) 2006-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+@@ -84,7 +84,7 @@ FT_BEGIN_HEADER
+     /* used for horizontal metrics too for CJK */
+     FT_Bool        control_overshoot;
+     FT_UInt        blue_count;
+-    AF_CJKBlueRec  blues[AF_BLUE_STRINGSET_MAX];
++    AF_CJKBlueRec  blues[AF_BLUE_STRINGSET_MAX_LEN];
+ 
+     FT_Fixed       org_scale;
+     FT_Pos         org_delta;
+diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afcover.h b/src/java.desktop/share/native/libfreetype/src/autofit/afcover.h
+index 102ed4278..7980cf2e9 100644
+--- a/src/java.desktop/share/native/libfreetype/src/autofit/afcover.h
++++ b/src/java.desktop/share/native/libfreetype/src/autofit/afcover.h
+@@ -4,7 +4,7 @@
+  *
+  *   Auto-fitter coverages (specification only).
+  *
+- * Copyright (C) 2013-2023 by
++ * Copyright (C) 2013-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afdummy.c b/src/java.desktop/share/native/libfreetype/src/autofit/afdummy.c
+index a4629b528..ad667d2ed 100644
+--- a/src/java.desktop/share/native/libfreetype/src/autofit/afdummy.c
++++ b/src/java.desktop/share/native/libfreetype/src/autofit/afdummy.c
+@@ -5,7 +5,7 @@
+  *   Auto-fitter dummy routines to be used if no hinting should be
+  *   performed (body).
+  *
+- * Copyright (C) 2003-2023 by
++ * Copyright (C) 2003-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afdummy.h b/src/java.desktop/share/native/libfreetype/src/autofit/afdummy.h
+index a7af3f62c..613c2f88a 100644
+--- a/src/java.desktop/share/native/libfreetype/src/autofit/afdummy.h
++++ b/src/java.desktop/share/native/libfreetype/src/autofit/afdummy.h
+@@ -5,7 +5,7 @@
+  *   Auto-fitter dummy routines to be used if no hinting should be
+  *   performed (specification).
+  *
+- * Copyright (C) 2003-2023 by
++ * Copyright (C) 2003-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/aferrors.h b/src/java.desktop/share/native/libfreetype/src/autofit/aferrors.h
+index 88faf05c9..ae584ff06 100644
+--- a/src/java.desktop/share/native/libfreetype/src/autofit/aferrors.h
++++ b/src/java.desktop/share/native/libfreetype/src/autofit/aferrors.h
+@@ -4,7 +4,7 @@
+  *
+  *   Autofitter error codes (specification only).
+  *
+- * Copyright (C) 2005-2023 by
++ * Copyright (C) 2005-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afglobal.c b/src/java.desktop/share/native/libfreetype/src/autofit/afglobal.c
+index b1957570f..b7403fa65 100644
+--- a/src/java.desktop/share/native/libfreetype/src/autofit/afglobal.c
++++ b/src/java.desktop/share/native/libfreetype/src/autofit/afglobal.c
+@@ -4,7 +4,7 @@
+  *
+  *   Auto-fitter routines to compute global hinting values (body).
+  *
+- * Copyright (C) 2003-2023 by
++ * Copyright (C) 2003-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afglobal.h b/src/java.desktop/share/native/libfreetype/src/autofit/afglobal.h
+index 66170e419..ddb54c89b 100644
+--- a/src/java.desktop/share/native/libfreetype/src/autofit/afglobal.h
++++ b/src/java.desktop/share/native/libfreetype/src/autofit/afglobal.h
+@@ -5,7 +5,7 @@
+  *   Auto-fitter routines to compute global hinting values
+  *   (specification).
+  *
+- * Copyright (C) 2003-2023 by
++ * Copyright (C) 2003-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afhints.c b/src/java.desktop/share/native/libfreetype/src/autofit/afhints.c
+index e4a378fbf..96ffe343a 100644
+--- a/src/java.desktop/share/native/libfreetype/src/autofit/afhints.c
++++ b/src/java.desktop/share/native/libfreetype/src/autofit/afhints.c
+@@ -4,7 +4,7 @@
+  *
+  *   Auto-fitter hinting routines (body).
+  *
+- * Copyright (C) 2003-2023 by
++ * Copyright (C) 2003-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+@@ -979,8 +979,8 @@
+       /* compute coordinates & Bezier flags, next and prev */
+       {
+         FT_Vector*  vec           = outline->points;
+-        char*       tag           = outline->tags;
+-        FT_Short    endpoint      = outline->contours[0];
++        FT_Byte*    tag           = outline->tags;
++        FT_UShort   endpoint      = outline->contours[0];
+         AF_Point    end           = points + endpoint;
+         AF_Point    prev          = end;
+         FT_Int      contour_index = 0;
+@@ -1046,16 +1046,16 @@
+ 
+       /* set up the contours array */
+       {
+-        AF_Point*  contour       = hints->contours;
+-        AF_Point*  contour_limit = contour + hints->num_contours;
+-        short*     end           = outline->contours;
+-        short      idx           = 0;
++        AF_Point*   contour       = hints->contours;
++        AF_Point*   contour_limit = contour + hints->num_contours;
++        FT_UShort*  end           = outline->contours;
++        FT_Int      idx           = 0;
+ 
+ 
+         for ( ; contour < contour_limit; contour++, end++ )
+         {
+           contour[0] = points + idx;
+-          idx        = (short)( end[0] + 1 );
++          idx        = *end + 1;
+         }
+       }
+ 
+@@ -1292,7 +1292,7 @@
+     AF_Point    point = hints->points;
+     AF_Point    limit = point + hints->num_points;
+     FT_Vector*  vec   = outline->points;
+-    char*       tag   = outline->tags;
++    FT_Byte*    tag   = outline->tags;
+ 
+ 
+     for ( ; point < limit; point++, vec++, tag++ )
+diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afhints.h b/src/java.desktop/share/native/libfreetype/src/autofit/afhints.h
+index d1cf9529b..76fe83006 100644
+--- a/src/java.desktop/share/native/libfreetype/src/autofit/afhints.h
++++ b/src/java.desktop/share/native/libfreetype/src/autofit/afhints.h
+@@ -4,7 +4,7 @@
+  *
+  *   Auto-fitter hinting routines (specification).
+  *
+- * Copyright (C) 2003-2023 by
++ * Copyright (C) 2003-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afindic.c b/src/java.desktop/share/native/libfreetype/src/autofit/afindic.c
+index 7fb12c63d..c6d23efd8 100644
+--- a/src/java.desktop/share/native/libfreetype/src/autofit/afindic.c
++++ b/src/java.desktop/share/native/libfreetype/src/autofit/afindic.c
+@@ -4,7 +4,7 @@
+  *
+  *   Auto-fitter hinting routines for Indic writing system (body).
+  *
+- * Copyright (C) 2007-2023 by
++ * Copyright (C) 2007-2024 by
+  * Rahul Bhalerao , .
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afindic.h b/src/java.desktop/share/native/libfreetype/src/autofit/afindic.h
+index 3eb67f63b..a7f73f251 100644
+--- a/src/java.desktop/share/native/libfreetype/src/autofit/afindic.h
++++ b/src/java.desktop/share/native/libfreetype/src/autofit/afindic.h
+@@ -5,7 +5,7 @@
+  *   Auto-fitter hinting routines for Indic writing system
+  *   (specification).
+  *
+- * Copyright (C) 2007-2023 by
++ * Copyright (C) 2007-2024 by
+  * Rahul Bhalerao , .
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/aflatin.c b/src/java.desktop/share/native/libfreetype/src/autofit/aflatin.c
+index b86367aa9..89287f7ea 100644
+--- a/src/java.desktop/share/native/libfreetype/src/autofit/aflatin.c
++++ b/src/java.desktop/share/native/libfreetype/src/autofit/aflatin.c
+@@ -4,7 +4,7 @@
+  *
+  *   Auto-fitter hinting routines for latin writing system (body).
+  *
+- * Copyright (C) 2003-2023 by
++ * Copyright (C) 2003-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+@@ -981,7 +981,7 @@
+       /* `ref' and `shoot' values of two blue zones must not overlap */
+ 
+       FT_UInt       i;
+-      AF_LatinBlue  blue_sorted[AF_BLUE_STRINGSET_MAX_LEN + 2];
++      AF_LatinBlue  blue_sorted[AF_BLUE_STRINGSET_MAX_LEN];
+ 
+ 
+       for ( i = 0; i < axis->blue_count; i++ )
+@@ -1263,10 +1263,9 @@
+               max_height = FT_MAX( max_height, -Axis->blues[nn].descender );
+             }
+ 
+-            dist  = FT_ABS( FT_MulFix( max_height, new_scale - scale ) );
+-            dist &= ~127;
++            dist  = FT_MulFix( max_height, new_scale - scale );
+ 
+-            if ( dist == 0 )
++            if ( -128 < dist && dist < 128 )
+             {
+               FT_TRACE5(( "af_latin_metrics_scale_dim:"
+                           " x height alignment (style `%s'):\n",
+diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/aflatin.h b/src/java.desktop/share/native/libfreetype/src/autofit/aflatin.h
+index 31aa91d3b..54e506150 100644
+--- a/src/java.desktop/share/native/libfreetype/src/autofit/aflatin.h
++++ b/src/java.desktop/share/native/libfreetype/src/autofit/aflatin.h
+@@ -5,7 +5,7 @@
+  *   Auto-fitter hinting routines for latin writing system
+  *   (specification).
+  *
+- * Copyright (C) 2003-2023 by
++ * Copyright (C) 2003-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+@@ -98,7 +98,7 @@ FT_BEGIN_HEADER
+ 
+     /* ignored for horizontal metrics */
+     FT_UInt          blue_count;
+-    AF_LatinBlueRec  blues[AF_BLUE_STRINGSET_MAX];
++    AF_LatinBlueRec  blues[AF_BLUE_STRINGSET_MAX_LEN];
+ 
+     FT_Fixed         org_scale;
+     FT_Pos           org_delta;
+diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afloader.c b/src/java.desktop/share/native/libfreetype/src/autofit/afloader.c
+index 7c47d562a..af1d59a68 100644
+--- a/src/java.desktop/share/native/libfreetype/src/autofit/afloader.c
++++ b/src/java.desktop/share/native/libfreetype/src/autofit/afloader.c
+@@ -4,7 +4,7 @@
+  *
+  *   Auto-fitter glyph loading routines (body).
+  *
+- * Copyright (C) 2003-2023 by
++ * Copyright (C) 2003-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afloader.h b/src/java.desktop/share/native/libfreetype/src/autofit/afloader.h
+index e4e197e37..99f0e15f9 100644
+--- a/src/java.desktop/share/native/libfreetype/src/autofit/afloader.h
++++ b/src/java.desktop/share/native/libfreetype/src/autofit/afloader.h
+@@ -4,7 +4,7 @@
+  *
+  *   Auto-fitter glyph loading routines (specification).
+  *
+- * Copyright (C) 2003-2023 by
++ * Copyright (C) 2003-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afmodule.c b/src/java.desktop/share/native/libfreetype/src/autofit/afmodule.c
+index 20a6b96bc..726f6ca2b 100644
+--- a/src/java.desktop/share/native/libfreetype/src/autofit/afmodule.c
++++ b/src/java.desktop/share/native/libfreetype/src/autofit/afmodule.c
+@@ -4,7 +4,7 @@
+  *
+  *   Auto-fitter module implementation (body).
+  *
+- * Copyright (C) 2003-2023 by
++ * Copyright (C) 2003-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+@@ -438,7 +438,7 @@
+     AF_Module  module = (AF_Module)module_;
+ 
+     FT_Error   error  = FT_Err_Ok;
+-    FT_Memory  memory = module->root.library->memory;
++    FT_Memory  memory = module->root.memory;
+ 
+ #ifdef FT_DEBUG_AUTOFIT
+ 
+diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afmodule.h b/src/java.desktop/share/native/libfreetype/src/autofit/afmodule.h
+index 4b8b4562c..91a1abfef 100644
+--- a/src/java.desktop/share/native/libfreetype/src/autofit/afmodule.h
++++ b/src/java.desktop/share/native/libfreetype/src/autofit/afmodule.h
+@@ -4,7 +4,7 @@
+  *
+  *   Auto-fitter module implementation (specification).
+  *
+- * Copyright (C) 2003-2023 by
++ * Copyright (C) 2003-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afranges.c b/src/java.desktop/share/native/libfreetype/src/autofit/afranges.c
+index cfcaf340a..007b43281 100644
+--- a/src/java.desktop/share/native/libfreetype/src/autofit/afranges.c
++++ b/src/java.desktop/share/native/libfreetype/src/autofit/afranges.c
+@@ -4,7 +4,7 @@
+  *
+  *   Auto-fitter Unicode script ranges (body).
+  *
+- * Copyright (C) 2013-2023 by
++ * Copyright (C) 2013-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afranges.h b/src/java.desktop/share/native/libfreetype/src/autofit/afranges.h
+index 5775738bc..813b3ee78 100644
+--- a/src/java.desktop/share/native/libfreetype/src/autofit/afranges.h
++++ b/src/java.desktop/share/native/libfreetype/src/autofit/afranges.h
+@@ -4,7 +4,7 @@
+  *
+  *   Auto-fitter Unicode script ranges (specification).
+  *
+- * Copyright (C) 2013-2023 by
++ * Copyright (C) 2013-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afscript.h b/src/java.desktop/share/native/libfreetype/src/autofit/afscript.h
+index 3a101937d..0a83d7715 100644
+--- a/src/java.desktop/share/native/libfreetype/src/autofit/afscript.h
++++ b/src/java.desktop/share/native/libfreetype/src/autofit/afscript.h
+@@ -4,7 +4,7 @@
+  *
+  *   Auto-fitter scripts (specification only).
+  *
+- * Copyright (C) 2013-2023 by
++ * Copyright (C) 2013-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afshaper.c b/src/java.desktop/share/native/libfreetype/src/autofit/afshaper.c
+index abc6f1d29..df0f46ada 100644
+--- a/src/java.desktop/share/native/libfreetype/src/autofit/afshaper.c
++++ b/src/java.desktop/share/native/libfreetype/src/autofit/afshaper.c
+@@ -4,7 +4,7 @@
+  *
+  *   HarfBuzz interface for accessing OpenType features (body).
+  *
+- * Copyright (C) 2013-2023 by
++ * Copyright (C) 2013-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afshaper.h b/src/java.desktop/share/native/libfreetype/src/autofit/afshaper.h
+index 054a18ffb..2eb03bb5d 100644
+--- a/src/java.desktop/share/native/libfreetype/src/autofit/afshaper.h
++++ b/src/java.desktop/share/native/libfreetype/src/autofit/afshaper.h
+@@ -4,7 +4,7 @@
+  *
+  *   HarfBuzz interface for accessing OpenType features (specification).
+  *
+- * Copyright (C) 2013-2023 by
++ * Copyright (C) 2013-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afstyles.h b/src/java.desktop/share/native/libfreetype/src/autofit/afstyles.h
+index 73ebef017..7a33f37a8 100644
+--- a/src/java.desktop/share/native/libfreetype/src/autofit/afstyles.h
++++ b/src/java.desktop/share/native/libfreetype/src/autofit/afstyles.h
+@@ -4,7 +4,7 @@
+  *
+  *   Auto-fitter styles (specification only).
+  *
+- * Copyright (C) 2013-2023 by
++ * Copyright (C) 2013-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/aftypes.h b/src/java.desktop/share/native/libfreetype/src/autofit/aftypes.h
+index 661519449..27e4185e9 100644
+--- a/src/java.desktop/share/native/libfreetype/src/autofit/aftypes.h
++++ b/src/java.desktop/share/native/libfreetype/src/autofit/aftypes.h
+@@ -4,7 +4,7 @@
+  *
+  *   Auto-fitter types (specification only).
+  *
+- * Copyright (C) 2003-2023 by
++ * Copyright (C) 2003-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afws-decl.h b/src/java.desktop/share/native/libfreetype/src/autofit/afws-decl.h
+index 48c888afe..b78745af7 100644
+--- a/src/java.desktop/share/native/libfreetype/src/autofit/afws-decl.h
++++ b/src/java.desktop/share/native/libfreetype/src/autofit/afws-decl.h
+@@ -4,7 +4,7 @@
+  *
+  *   Auto-fitter writing system declarations (specification only).
+  *
+- * Copyright (C) 2013-2023 by
++ * Copyright (C) 2013-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afws-iter.h b/src/java.desktop/share/native/libfreetype/src/autofit/afws-iter.h
+index a0a686f8c..c86d609a3 100644
+--- a/src/java.desktop/share/native/libfreetype/src/autofit/afws-iter.h
++++ b/src/java.desktop/share/native/libfreetype/src/autofit/afws-iter.h
+@@ -4,7 +4,7 @@
+  *
+  *   Auto-fitter writing systems iterator (specification only).
+  *
+- * Copyright (C) 2013-2023 by
++ * Copyright (C) 2013-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftadvanc.c b/src/java.desktop/share/native/libfreetype/src/base/ftadvanc.c
+index de25476fe..717f7d08b 100644
+--- a/src/java.desktop/share/native/libfreetype/src/base/ftadvanc.c
++++ b/src/java.desktop/share/native/libfreetype/src/base/ftadvanc.c
+@@ -4,7 +4,7 @@
+  *
+  *   Quick computation of advance widths (body).
+  *
+- * Copyright (C) 2008-2023 by
++ * Copyright (C) 2008-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftbase.h b/src/java.desktop/share/native/libfreetype/src/base/ftbase.h
+index 00790d3b2..1d98b26dd 100644
+--- a/src/java.desktop/share/native/libfreetype/src/base/ftbase.h
++++ b/src/java.desktop/share/native/libfreetype/src/base/ftbase.h
+@@ -4,7 +4,7 @@
+  *
+  *   Private functions used in the `base' module (specification).
+  *
+- * Copyright (C) 2008-2023 by
++ * Copyright (C) 2008-2024 by
+  * David Turner, Robert Wilhelm, Werner Lemberg, and suzuki toshiya.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftbbox.c b/src/java.desktop/share/native/libfreetype/src/base/ftbbox.c
+index 385fea404..d6aa5d56d 100644
+--- a/src/java.desktop/share/native/libfreetype/src/base/ftbbox.c
++++ b/src/java.desktop/share/native/libfreetype/src/base/ftbbox.c
+@@ -4,7 +4,7 @@
+  *
+  *   FreeType bbox computation (body).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used
+@@ -489,7 +489,7 @@
+       return FT_THROW( Invalid_Outline );
+ 
+     /* if outline is empty, return (0,0,0,0) */
+-    if ( outline->n_points == 0 || outline->n_contours <= 0 )
++    if ( outline->n_points == 0 || outline->n_contours == 0 )
+     {
+       abbox->xMin = abbox->xMax = 0;
+       abbox->yMin = abbox->yMax = 0;
+diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftbitmap.c b/src/java.desktop/share/native/libfreetype/src/base/ftbitmap.c
+index 1c93648dc..4be145679 100644
+--- a/src/java.desktop/share/native/libfreetype/src/base/ftbitmap.c
++++ b/src/java.desktop/share/native/libfreetype/src/base/ftbitmap.c
+@@ -4,7 +4,7 @@
+  *
+  *   FreeType utility functions for bitmaps (body).
+  *
+- * Copyright (C) 2004-2023 by
++ * Copyright (C) 2004-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftcalc.c b/src/java.desktop/share/native/libfreetype/src/base/ftcalc.c
+index c5bc7e3b1..92de09ed8 100644
+--- a/src/java.desktop/share/native/libfreetype/src/base/ftcalc.c
++++ b/src/java.desktop/share/native/libfreetype/src/base/ftcalc.c
+@@ -4,7 +4,7 @@
+  *
+  *   Arithmetic computations (body).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+@@ -69,13 +69,15 @@
+ 
+   /* transfer sign, leaving a positive number;                        */
+   /* we need an unsigned value to safely negate INT_MIN (or LONG_MIN) */
+-#define FT_MOVE_SIGN( x, x_unsigned, s ) \
+-  FT_BEGIN_STMNT                         \
+-    if ( x < 0 )                         \
+-    {                                    \
+-      x_unsigned = 0U - (x_unsigned);    \
+-      s          = -s;                   \
+-    }                                    \
++#define FT_MOVE_SIGN( utype, x, x_unsigned, s ) \
++  FT_BEGIN_STMNT                                \
++    if ( x < 0 )                                \
++    {                                           \
++      x_unsigned = 0U - (utype)x;               \
++      s          = -s;                          \
++    }                                           \
++    else                                        \
++      x_unsigned = (utype)x;                    \
+   FT_END_STMNT
+ 
+   /* The following three functions are available regardless of whether */
+@@ -179,13 +181,9 @@
+     FT_Long    d_;
+ 
+ 
+-    a = (FT_UInt64)a_;
+-    b = (FT_UInt64)b_;
+-    c = (FT_UInt64)c_;
+-
+-    FT_MOVE_SIGN( a_, a, s );
+-    FT_MOVE_SIGN( b_, b, s );
+-    FT_MOVE_SIGN( c_, c, s );
++    FT_MOVE_SIGN( FT_UInt64, a_, a, s );
++    FT_MOVE_SIGN( FT_UInt64, b_, b, s );
++    FT_MOVE_SIGN( FT_UInt64, c_, c, s );
+ 
+     d = c > 0 ? ( a * b + ( c >> 1 ) ) / c
+               : 0x7FFFFFFFUL;
+@@ -208,13 +206,9 @@
+     FT_Long    d_;
+ 
+ 
+-    a = (FT_UInt64)a_;
+-    b = (FT_UInt64)b_;
+-    c = (FT_UInt64)c_;
+-
+-    FT_MOVE_SIGN( a_, a, s );
+-    FT_MOVE_SIGN( b_, b, s );
+-    FT_MOVE_SIGN( c_, c, s );
++    FT_MOVE_SIGN( FT_UInt64, a_, a, s );
++    FT_MOVE_SIGN( FT_UInt64, b_, b, s );
++    FT_MOVE_SIGN( FT_UInt64, c_, c, s );
+ 
+     d = c > 0 ? a * b / c
+               : 0x7FFFFFFFUL;
+@@ -257,11 +251,8 @@
+     FT_Long    q_;
+ 
+ 
+-    a = (FT_UInt64)a_;
+-    b = (FT_UInt64)b_;
+-
+-    FT_MOVE_SIGN( a_, a, s );
+-    FT_MOVE_SIGN( b_, b, s );
++    FT_MOVE_SIGN( FT_UInt64, a_, a, s );
++    FT_MOVE_SIGN( FT_UInt64, b_, b, s );
+ 
+     q = b > 0 ? ( ( a << 16 ) + ( b >> 1 ) ) / b
+               : 0x7FFFFFFFUL;
+@@ -422,13 +413,9 @@
+ 
+     /* XXX: this function does not allow 64-bit arguments */
+ 
+-    a = (FT_UInt32)a_;
+-    b = (FT_UInt32)b_;
+-    c = (FT_UInt32)c_;
+-
+-    FT_MOVE_SIGN( a_, a, s );
+-    FT_MOVE_SIGN( b_, b, s );
+-    FT_MOVE_SIGN( c_, c, s );
++    FT_MOVE_SIGN( FT_UInt32, a_, a, s );
++    FT_MOVE_SIGN( FT_UInt32, b_, b, s );
++    FT_MOVE_SIGN( FT_UInt32, c_, c, s );
+ 
+     if ( c == 0 )
+       a = 0x7FFFFFFFUL;
+@@ -470,13 +457,9 @@
+ 
+     /* XXX: this function does not allow 64-bit arguments */
+ 
+-    a = (FT_UInt32)a_;
+-    b = (FT_UInt32)b_;
+-    c = (FT_UInt32)c_;
+-
+-    FT_MOVE_SIGN( a_, a, s );
+-    FT_MOVE_SIGN( b_, b, s );
+-    FT_MOVE_SIGN( c_, c, s );
++    FT_MOVE_SIGN( FT_UInt32, a_, a, s );
++    FT_MOVE_SIGN( FT_UInt32, b_, b, s );
++    FT_MOVE_SIGN( FT_UInt32, c_, c, s );
+ 
+     if ( c == 0 )
+       a = 0x7FFFFFFFUL;
+@@ -575,11 +558,8 @@
+ 
+     /* XXX: this function does not allow 64-bit arguments */
+ 
+-    a = (FT_UInt32)a_;
+-    b = (FT_UInt32)b_;
+-
+-    FT_MOVE_SIGN( a_, a, s );
+-    FT_MOVE_SIGN( b_, b, s );
++    FT_MOVE_SIGN( FT_UInt32, a_, a, s );
++    FT_MOVE_SIGN( FT_UInt32, b_, b, s );
+ 
+     if ( a + ( b >> 8 ) <= 8190UL )
+       a = ( a * b + 0x8000UL ) >> 16;
+@@ -614,11 +594,8 @@
+ 
+     /* XXX: this function does not allow 64-bit arguments */
+ 
+-    a = (FT_UInt32)a_;
+-    b = (FT_UInt32)b_;
+-
+-    FT_MOVE_SIGN( a_, a, s );
+-    FT_MOVE_SIGN( b_, b, s );
++    FT_MOVE_SIGN( FT_UInt32, a_, a, s );
++    FT_MOVE_SIGN( FT_UInt32, b_, b, s );
+ 
+     if ( b == 0 )
+     {
+@@ -829,11 +806,8 @@
+     FT_Int     sx = 1, sy = 1, shift;
+ 
+ 
+-    x = (FT_UInt32)x_;
+-    y = (FT_UInt32)y_;
+-
+-    FT_MOVE_SIGN( x_, x, sx );
+-    FT_MOVE_SIGN( y_, y, sy );
++    FT_MOVE_SIGN( FT_UInt32, x_, x, sx );
++    FT_MOVE_SIGN( FT_UInt32, y_, y, sy );
+ 
+     /* trivial cases */
+     if ( x == 0 )
+@@ -913,43 +887,71 @@
+   }
+ 
+ 
+-#if 0
+-
+   /* documentation is in ftcalc.h */
+ 
+-  FT_BASE_DEF( FT_Int32 )
+-  FT_SqrtFixed( FT_Int32  x )
++  FT_BASE_DEF( FT_UInt32 )
++  FT_SqrtFixed( FT_UInt32  v )
+   {
+-    FT_UInt32  root, rem_hi, rem_lo, test_div;
+-    FT_Int     count;
+-
++    if ( v == 0 )
++      return 0;
+ 
+-    root = 0;
++#ifndef FT_INT64
+ 
+-    if ( x > 0 )
++    /* Algorithm by Christophe Meessen (1993) with overflow fixed and     */
++    /* rounding added.  Any unsigned fixed 16.16 argument is acceptable.  */
++    /* However, this algorithm is slower than the Babylonian method with  */
++    /* a good initial guess.  We only use it for large 32-bit values when */
++    /* 64-bit computations are not desirable.                             */
++    else if ( v > 0x10000U )
+     {
+-      rem_hi = 0;
+-      rem_lo = (FT_UInt32)x;
+-      count  = 24;
++      FT_UInt32  r = v >> 1;
++      FT_UInt32  q = ( v & 1 ) << 15;
++      FT_UInt32  b = 0x20000000;
++      FT_UInt32  t;
++
++
+       do
+       {
+-        rem_hi   = ( rem_hi << 2 ) | ( rem_lo >> 30 );
+-        rem_lo <<= 2;
+-        root   <<= 1;
+-        test_div = ( root << 1 ) + 1;
+-
+-        if ( rem_hi >= test_div )
++        t = q + b;
++        if ( r >= t )
+         {
+-          rem_hi -= test_div;
+-          root   += 1;
++          r -= t;
++          q  = t + b;  /* equivalent to q += 2*b */
+         }
+-      } while ( --count );
++        r <<= 1;
++        b >>= 1;
 +
-+final public class LinuxMIPS64CFrame extends BasicCFrame {
-+   // package/class internals only
-+   public LinuxMIPS64CFrame(LinuxDebugger dbg, Address ebp, Address pc) {
-+      super(dbg.getCDebugger());
-+      this.ebp = ebp;
-+      this.pc = pc;
-+      this.dbg = dbg;
-+   }
++      } while ( b > 0x10 );  /* exactly 25 cycles */
 +
-+   // override base class impl to avoid ELF parsing
-+   public ClosestSymbol closestSymbolToPC() {
-+      // try native lookup in debugger.
-+      return dbg.lookup(dbg.getAddressValue(pc()));
-+   }
++      return ( q + 0x40 ) >> 7;
+     }
++    else
++    {
++      FT_UInt32  r = ( v << 16 ) - 1;
+ 
+-    return (FT_Int32)root;
+-  }
++#else /* FT_INT64 */
+ 
+-#endif /* 0 */
++    else
++    {
++      FT_UInt64  r = ( (FT_UInt64)v << 16 ) - 1;
 +
-+   public Address pc() {
-+      return pc;
-+   }
++#endif /* FT_INT64 */
 +
-+   public Address localVariableBase() {
-+      return ebp;
-+   }
++      FT_UInt32  q = 1 << ( ( 17 + FT_MSB( v ) ) >> 1 );
++      FT_UInt32  t;
 +
-+   public CFrame sender(ThreadProxy thread) {
-+      MIPS64ThreadContext context = (MIPS64ThreadContext) thread.getContext();
-+      Address esp = context.getRegisterAsAddress(MIPS64ThreadContext.SP);
 +
-+      if ( (ebp == null) || ebp.lessThan(esp) ) {
-+        return null;
-+      }
++      /* Babylonian method with rounded-up division */
++      do
++      {
++        t = q;
++        q = ( t + (FT_UInt32)( r / t ) + 1 ) >> 1;
 +
-+      Address nextEBP = ebp.getAddressAt( 0 * ADDRESS_SIZE);
-+      if (nextEBP == null) {
-+        return null;
-+      }
-+      Address nextPC  = ebp.getAddressAt( 1 * ADDRESS_SIZE);
-+      if (nextPC == null) {
-+        return null;
-+      }
-+      return new LinuxMIPS64CFrame(dbg, nextEBP, nextPC);
-+   }
++      } while ( q != t );  /* less than 6 cycles */
 +
-+   private static final int ADDRESS_SIZE = 4;
-+   private Address pc;
-+   private Address ebp;
-+   private LinuxDebugger dbg;
-+}
-diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/mips64/LinuxMIPS64ThreadContext.java jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/mips64/LinuxMIPS64ThreadContext.java
---- openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/mips64/LinuxMIPS64ThreadContext.java	1970-01-01 08:00:00.000000000 +0800
-+++ jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/mips64/LinuxMIPS64ThreadContext.java	2023-09-12 13:54:26.373575786 +0800
-@@ -0,0 +1,47 @@
-+/*
-+ * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
-+ * Copyright (c) 2015, 2018, Loongson Technology. 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 sun.jvm.hotspot.debugger.linux.mips64;
-+
-+import sun.jvm.hotspot.debugger.*;
-+import sun.jvm.hotspot.debugger.mips64.*;
-+import sun.jvm.hotspot.debugger.linux.*;
-+
-+public class LinuxMIPS64ThreadContext extends MIPS64ThreadContext {
-+  private LinuxDebugger debugger;
-+
-+  public LinuxMIPS64ThreadContext(LinuxDebugger debugger) {
-+    super();
-+    this.debugger = debugger;
-+  }
-+
-+  public void setRegisterAsAddress(int index, Address value) {
-+    setRegister(index, debugger.getAddressValue(value));
-+  }
-+
-+  public Address getRegisterAsAddress(int index) {
-+    return debugger.newAddress(getRegister(index));
++      return q;
++    }
 +  }
-+}
-diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/loongarch64/LOONGARCH64ThreadContext.java jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/loongarch64/LOONGARCH64ThreadContext.java
---- openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/loongarch64/LOONGARCH64ThreadContext.java	1970-01-01 08:00:00.000000000 +0800
-+++ jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/loongarch64/LOONGARCH64ThreadContext.java	2023-09-12 13:54:26.373575786 +0800
-@@ -0,0 +1,128 @@
-+/*
-+ * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
-+ * Copyright (c) 2015, 2021, Loongson Technology. 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 sun.jvm.hotspot.debugger.loongarch64;
-+
-+import java.lang.annotation.Native;
-+
-+import sun.jvm.hotspot.debugger.*;
-+import sun.jvm.hotspot.debugger.cdbg.*;
-+
-+/** Specifies the thread context on loongarch64 platforms; only a sub-portion
-+    of the context is guaranteed to be present on all operating
-+    systems. */
-+
-+public abstract class LOONGARCH64ThreadContext implements ThreadContext {
-+
-+  // NOTE: the indices for the various registers must be maintained as
-+  // listed across various operating systems. However, only a small
-+  // subset of the registers' values are guaranteed to be present (and
-+  // must be present for the SA's stack walking to work): EAX, EBX,
-+  // ECX, EDX, ESI, EDI, EBP, ESP, and EIP.
-+
-+  // One instance of the Native annotation is enough to trigger header generation
-+  // for this file.
-+  @Native
-+  public static final int ZERO = 0;
-+  public static final int RA = 1;
-+  public static final int TP = 2;
-+  public static final int SP = 3;
-+  public static final int A0 = 4;
-+  public static final int A1 = 5;
-+  public static final int A2 = 6;
-+  public static final int A3 = 7;
-+  public static final int A4 = 8;
-+  public static final int A5 = 9;
-+  public static final int A6 = 10;
-+  public static final int A7 = 11;
-+  public static final int T0 = 12;
-+  public static final int T1 = 13;
-+  public static final int T2 = 14;
-+  public static final int T3 = 15;
-+  public static final int T4 = 16;
-+  public static final int T5 = 17;
-+  public static final int T6 = 18;
-+  public static final int T7 = 19;
-+  public static final int T8 = 20;
-+  public static final int RX = 21;
-+  public static final int FP = 22;
-+  public static final int S0 = 23;
-+  public static final int S1 = 24;
-+  public static final int S2 = 25;
-+  public static final int S3 = 26;
-+  public static final int S4 = 27;
-+  public static final int S5 = 28;
-+  public static final int S6 = 29;
-+  public static final int S7 = 30;
-+  public static final int S8 = 31;
-+  public static final int PC = 32;
-+  public static final int NPRGREG = 33;
-+
-+  private static final String[] regNames = {
-+    "ZERO",    "RA",    "TP",    "SP",
-+    "A0",      "A1",    "A2",    "A3",
-+    "A4",      "A5",    "A6",    "A7",
-+    "T0",      "T1",    "T2",    "T3",
-+    "T4",      "T5",    "T6",    "T7",
-+    "T8",      "RX",    "FP",    "S0",
-+    "S1",      "S2",    "S3",    "S4",
-+    "S5",      "S6",    "S7",    "S8",
-+    "PC"
-+  };
+ 
+ 
+   /* documentation is in ftcalc.h */
+@@ -1094,11 +1096,8 @@
+       FT_UInt32  factor;
+ 
+ 
+-      scalar = (FT_UInt32)s[i];
+-      factor = (FT_UInt32)f[i];
+-
+-      FT_MOVE_SIGN( s[i], scalar, sign );
+-      FT_MOVE_SIGN( f[i], factor, sign );
++      FT_MOVE_SIGN( FT_UInt32, s[i], scalar, sign );
++      FT_MOVE_SIGN( FT_UInt32, f[i], factor, sign );
+ 
+       ft_multo64( scalar, factor, &multResult );
+ 
+diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftcid.c b/src/java.desktop/share/native/libfreetype/src/base/ftcid.c
+index 866cd23e9..4f2deb19a 100644
+--- a/src/java.desktop/share/native/libfreetype/src/base/ftcid.c
++++ b/src/java.desktop/share/native/libfreetype/src/base/ftcid.c
+@@ -4,7 +4,7 @@
+  *
+  *   FreeType API for accessing CID font information.
+  *
+- * Copyright (C) 2007-2023 by
++ * Copyright (C) 2007-2024 by
+  * Derek Clegg and Michael Toftdal.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftcolor.c b/src/java.desktop/share/native/libfreetype/src/base/ftcolor.c
+index bcd6e893d..c6bf2a3cd 100644
+--- a/src/java.desktop/share/native/libfreetype/src/base/ftcolor.c
++++ b/src/java.desktop/share/native/libfreetype/src/base/ftcolor.c
+@@ -4,7 +4,7 @@
+  *
+  *   FreeType's glyph color management (body).
+  *
+- * Copyright (C) 2018-2023 by
++ * Copyright (C) 2018-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftdbgmem.c b/src/java.desktop/share/native/libfreetype/src/base/ftdbgmem.c
+index 8fab50dd0..902a5dc8b 100644
+--- a/src/java.desktop/share/native/libfreetype/src/base/ftdbgmem.c
++++ b/src/java.desktop/share/native/libfreetype/src/base/ftdbgmem.c
+@@ -4,7 +4,7 @@
+  *
+  *   Memory debugger (body).
+  *
+- * Copyright (C) 2001-2023 by
++ * Copyright (C) 2001-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftdebug.c b/src/java.desktop/share/native/libfreetype/src/base/ftdebug.c
+index 61c4563b0..11307eaac 100644
+--- a/src/java.desktop/share/native/libfreetype/src/base/ftdebug.c
++++ b/src/java.desktop/share/native/libfreetype/src/base/ftdebug.c
+@@ -4,7 +4,7 @@
+  *
+  *   Debugging and logging component (body).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftfntfmt.c b/src/java.desktop/share/native/libfreetype/src/base/ftfntfmt.c
+index 0b41f7cc8..77b4089e7 100644
+--- a/src/java.desktop/share/native/libfreetype/src/base/ftfntfmt.c
++++ b/src/java.desktop/share/native/libfreetype/src/base/ftfntfmt.c
+@@ -4,7 +4,7 @@
+  *
+  *   FreeType utility file for font formats (body).
+  *
+- * Copyright (C) 2002-2023 by
++ * Copyright (C) 2002-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftfstype.c b/src/java.desktop/share/native/libfreetype/src/base/ftfstype.c
+index ea24e64c6..1565c3b7e 100644
+--- a/src/java.desktop/share/native/libfreetype/src/base/ftfstype.c
++++ b/src/java.desktop/share/native/libfreetype/src/base/ftfstype.c
+@@ -4,7 +4,7 @@
+  *
+  *   FreeType utility file to access FSType data (body).
+  *
+- * Copyright (C) 2008-2023 by
++ * Copyright (C) 2008-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftgasp.c b/src/java.desktop/share/native/libfreetype/src/base/ftgasp.c
+index 29b7b08b7..c63d30e97 100644
+--- a/src/java.desktop/share/native/libfreetype/src/base/ftgasp.c
++++ b/src/java.desktop/share/native/libfreetype/src/base/ftgasp.c
+@@ -4,7 +4,7 @@
+  *
+  *   Access of TrueType's `gasp' table (body).
+  *
+- * Copyright (C) 2007-2023 by
++ * Copyright (C) 2007-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftgloadr.c b/src/java.desktop/share/native/libfreetype/src/base/ftgloadr.c
+index 9823d09e4..484d98f17 100644
+--- a/src/java.desktop/share/native/libfreetype/src/base/ftgloadr.c
++++ b/src/java.desktop/share/native/libfreetype/src/base/ftgloadr.c
+@@ -4,7 +4,7 @@
+  *
+  *   The FreeType glyph loader (body).
+  *
+- * Copyright (C) 2002-2023 by
++ * Copyright (C) 2002-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg
+  *
+  * This file is part of the FreeType project, and may only be used,
+@@ -355,34 +355,25 @@
+   FT_BASE_DEF( void )
+   FT_GlyphLoader_Add( FT_GlyphLoader  loader )
+   {
+-    FT_GlyphLoad  base;
+-    FT_GlyphLoad  current;
+-
+-    FT_Int        n_curr_contours;
+-    FT_Int        n_base_points;
+-    FT_Int        n;
++    FT_Outline*  base;
++    FT_Outline*  current;
++    FT_Int       n;
+ 
+ 
+     if ( !loader )
+       return;
+ 
+-    base    = &loader->base;
+-    current = &loader->current;
+-
+-    n_curr_contours = current->outline.n_contours;
+-    n_base_points   = base->outline.n_points;
++    base    = &loader->base.outline;
++    current = &loader->current.outline;
+ 
+-    base->outline.n_points =
+-      (short)( base->outline.n_points + current->outline.n_points );
+-    base->outline.n_contours =
+-      (short)( base->outline.n_contours + current->outline.n_contours );
++    /* adjust contours count in newest outline */
++    for ( n = 0; n < current->n_contours; n++ )
++      current->contours[n] += base->n_points;
+ 
+-    base->num_subglyphs += current->num_subglyphs;
++    base->n_points   += current->n_points;
++    base->n_contours += current->n_contours;
+ 
+-    /* adjust contours count in newest outline */
+-    for ( n = 0; n < n_curr_contours; n++ )
+-      current->outline.contours[n] =
+-        (short)( current->outline.contours[n] + n_base_points );
++    loader->base.num_subglyphs += loader->current.num_subglyphs;
+ 
+     /* prepare for another new glyph image */
+     FT_GlyphLoader_Prepare( loader );
+diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftglyph.c b/src/java.desktop/share/native/libfreetype/src/base/ftglyph.c
+index 393d4949f..1b5849f99 100644
+--- a/src/java.desktop/share/native/libfreetype/src/base/ftglyph.c
++++ b/src/java.desktop/share/native/libfreetype/src/base/ftglyph.c
+@@ -4,7 +4,7 @@
+  *
+  *   FreeType convenience functions to handle glyphs (body).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftinit.c b/src/java.desktop/share/native/libfreetype/src/base/ftinit.c
+index c9c71d24b..9a6c00e13 100644
+--- a/src/java.desktop/share/native/libfreetype/src/base/ftinit.c
++++ b/src/java.desktop/share/native/libfreetype/src/base/ftinit.c
+@@ -4,7 +4,7 @@
+  *
+  *   FreeType initialization layer (body).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftlcdfil.c b/src/java.desktop/share/native/libfreetype/src/base/ftlcdfil.c
+index 6c3fd66e0..1e69d4da7 100644
+--- a/src/java.desktop/share/native/libfreetype/src/base/ftlcdfil.c
++++ b/src/java.desktop/share/native/libfreetype/src/base/ftlcdfil.c
+@@ -4,7 +4,7 @@
+  *
+  *   FreeType API for color filtering of subpixel bitmap glyphs (body).
+  *
+- * Copyright (C) 2006-2023 by
++ * Copyright (C) 2006-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftmac.c b/src/java.desktop/share/native/libfreetype/src/base/ftmac.c
+index 492d05538..e8e35627b 100644
+--- a/src/java.desktop/share/native/libfreetype/src/base/ftmac.c
++++ b/src/java.desktop/share/native/libfreetype/src/base/ftmac.c
+@@ -8,7 +8,7 @@
+  * This file is for Mac OS X only; see builds/mac/ftoldmac.c for
+  * classic platforms built by MPW.
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+@@ -812,6 +812,7 @@
+     ResourceIndex  res_index;
+     Handle         fond;
+     short          num_faces_in_res;
++    FT_Long        count;
+ 
+ 
+     if ( noErr != FT_FSPathMakeRes( pathname, &res_ref ) )
+@@ -821,8 +822,10 @@
+     if ( ResError() )
+       return FT_THROW( Cannot_Open_Resource );
+ 
++    res_index        = 1;
+     num_faces_in_res = 0;
+-    for ( res_index = 1; ; res_index++ )
++    count            = face_index;
++    while ( count >= 0 )
+     {
+       short  num_faces_in_fond;
+ 
+@@ -834,15 +837,21 @@
+       num_faces_in_fond  = count_faces( fond, pathname );
+       num_faces_in_res  += num_faces_in_fond;
+ 
+-      if ( 0 <= face_index && face_index < num_faces_in_fond && error )
+-        error = FT_New_Face_From_FOND( library, fond, face_index, aface );
++      if ( count < num_faces_in_fond )
++        error = FT_New_Face_From_FOND( library, fond, count, aface );
+ 
+-      face_index -= num_faces_in_fond;
++      res_index++;
++      count -= num_faces_in_fond;
+     }
+ 
+     CloseResFile( res_ref );
 +
-+  private long[] data;
+     if ( !error && aface && *aface )
+-      (*aface)->num_faces = num_faces_in_res;
++    {
++      (*aface)->num_faces  = num_faces_in_res;
++      (*aface)->face_index = face_index;
++    }
 +
-+  public LOONGARCH64ThreadContext() {
-+    data = new long[NPRGREG];
-+  }
+     return error;
+   }
+ 
+diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftmm.c b/src/java.desktop/share/native/libfreetype/src/base/ftmm.c
+index 9e2dd7ee7..cc4ca22fb 100644
+--- a/src/java.desktop/share/native/libfreetype/src/base/ftmm.c
++++ b/src/java.desktop/share/native/libfreetype/src/base/ftmm.c
+@@ -4,7 +4,7 @@
+  *
+  *   Multiple Master font support (body).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftobjs.c b/src/java.desktop/share/native/libfreetype/src/base/ftobjs.c
+index 89a25bc73..9b97820c3 100644
+--- a/src/java.desktop/share/native/libfreetype/src/base/ftobjs.c
++++ b/src/java.desktop/share/native/libfreetype/src/base/ftobjs.c
+@@ -4,7 +4,7 @@
+  *
+  *   The FreeType private base classes (body).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+@@ -2302,7 +2302,10 @@
+                                       face_index_internal, aface );
+       FT_FREE( data_offsets );
+       if ( !error )
+-        (*aface)->num_faces = count;
++      {
++        (*aface)->num_faces  = count;
++        (*aface)->face_index = face_index_internal;
++      }
+     }
+ 
+     return error;
+@@ -5791,7 +5794,7 @@
+     ttface = (TT_Face)face;
+     sfnt   = (SFNT_Service)ttface->sfnt;
+ 
+-    if ( sfnt->get_colr_layer )
++    if ( sfnt->get_colr_glyph_paint )
+       return sfnt->get_colr_glyph_paint( ttface,
+                                          base_glyph,
+                                          root_transform,
+diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftoutln.c b/src/java.desktop/share/native/libfreetype/src/base/ftoutln.c
+index 134f39d2b..ef699b3c7 100644
+--- a/src/java.desktop/share/native/libfreetype/src/base/ftoutln.c
++++ b/src/java.desktop/share/native/libfreetype/src/base/ftoutln.c
+@@ -4,7 +4,7 @@
+  *
+  *   FreeType outline management (body).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+@@ -53,7 +53,7 @@
+ 
+     FT_Vector*  point;
+     FT_Vector*  limit;
+-    char*       tags;
++    FT_Byte*    tags;
+ 
+     FT_Error    error;
+ 
+@@ -332,8 +332,8 @@
+          FT_NEW_ARRAY( anoutline->contours, numContours ) )
+       goto Fail;
+ 
+-    anoutline->n_points    = (FT_Short)numPoints;
+-    anoutline->n_contours  = (FT_Short)numContours;
++    anoutline->n_points    = (FT_UShort)numPoints;
++    anoutline->n_contours  = (FT_UShort)numContours;
+     anoutline->flags      |= FT_OUTLINE_OWNER;
+ 
+     return FT_Err_Ok;
+@@ -359,12 +359,14 @@
+       FT_Int  n;
+ 
+ 
++      FT_TRACE5(( "FT_Outline_Check: contours = %d, points = %d\n",
++                  n_contours, n_points ));
+       /* empty glyph? */
+       if ( n_points == 0 && n_contours == 0 )
+         return FT_Err_Ok;
+ 
+       /* check point and contour counts */
+-      if ( n_points <= 0 || n_contours <= 0 )
++      if ( n_points == 0 || n_contours == 0 )
+         goto Bad;
+ 
+       end0 = -1;
+@@ -576,13 +578,13 @@
+ 
+       /* reverse tags table */
+       {
+-        char*  p = outline->tags + first;
+-        char*  q = outline->tags + last;
++        FT_Byte*  p = outline->tags + first;
++        FT_Byte*  q = outline->tags + last;
+ 
+ 
+         while ( p < q )
+         {
+-          char  swap;
++          FT_Byte  swap;
+ 
+ 
+           swap = *p;
+diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftpatent.c b/src/java.desktop/share/native/libfreetype/src/base/ftpatent.c
+index cb5efadff..2055757e0 100644
+--- a/src/java.desktop/share/native/libfreetype/src/base/ftpatent.c
++++ b/src/java.desktop/share/native/libfreetype/src/base/ftpatent.c
+@@ -5,7 +5,7 @@
+  *   FreeType API for checking patented TrueType bytecode instructions
+  *   (body).  Obsolete, retained for backward compatibility.
+  *
+- * Copyright (C) 2007-2023 by
++ * Copyright (C) 2007-2024 by
+  * David Turner.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftpsprop.c b/src/java.desktop/share/native/libfreetype/src/base/ftpsprop.c
+index cefdf489d..37a6cee6c 100644
+--- a/src/java.desktop/share/native/libfreetype/src/base/ftpsprop.c
++++ b/src/java.desktop/share/native/libfreetype/src/base/ftpsprop.c
+@@ -5,7 +5,7 @@
+  *   Get and set properties of PostScript drivers (body).
+  *   See `ftdriver.h' for available properties.
+  *
+- * Copyright (C) 2017-2023 by
++ * Copyright (C) 2017-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftrfork.c b/src/java.desktop/share/native/libfreetype/src/base/ftrfork.c
+index 2ab430195..dc9b043d8 100644
+--- a/src/java.desktop/share/native/libfreetype/src/base/ftrfork.c
++++ b/src/java.desktop/share/native/libfreetype/src/base/ftrfork.c
+@@ -4,7 +4,7 @@
+  *
+  *   Embedded resource forks accessor (body).
+  *
+- * Copyright (C) 2004-2023 by
++ * Copyright (C) 2004-2024 by
+  * Masatake YAMATO and Redhat K.K.
+  *
+  * FT_Raccess_Get_HeaderInfo() and raccess_guess_darwin_hfsplus() are
+diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftsnames.c b/src/java.desktop/share/native/libfreetype/src/base/ftsnames.c
+index 1917a3f1d..f7231fd61 100644
+--- a/src/java.desktop/share/native/libfreetype/src/base/ftsnames.c
++++ b/src/java.desktop/share/native/libfreetype/src/base/ftsnames.c
+@@ -7,7 +7,7 @@
+  *
+  *   This is _not_ used to retrieve glyph names!
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftstream.c b/src/java.desktop/share/native/libfreetype/src/base/ftstream.c
+index 64826aceb..667222461 100644
+--- a/src/java.desktop/share/native/libfreetype/src/base/ftstream.c
++++ b/src/java.desktop/share/native/libfreetype/src/base/ftstream.c
+@@ -4,7 +4,7 @@
+  *
+  *   I/O stream support (body).
+  *
+- * Copyright (C) 2000-2023 by
++ * Copyright (C) 2000-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+@@ -763,10 +763,10 @@
+       case ft_frame_bytes:  /* read a byte sequence */
+       case ft_frame_skip:   /* skip some bytes      */
+         {
+-          FT_UInt  len = fields->size;
++          FT_Offset  len = fields->size;
+ 
+ 
+-          if ( cursor + len > stream->limit )
++          if ( len > (FT_Offset)( stream->limit - cursor ) )
+           {
+             error = FT_THROW( Invalid_Stream_Operation );
+             goto Exit;
+@@ -830,7 +830,7 @@
+         goto Exit;
+       }
+ 
+-      /* now, compute the signed value is necessary */
++      /* now, compute the signed value if necessary */
+       if ( fields->value & FT_FRAME_OP_SIGNED )
+         value = (FT_ULong)( (FT_Int32)( value << sign_shift ) >> sign_shift );
+ 
+diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftstroke.c b/src/java.desktop/share/native/libfreetype/src/base/ftstroke.c
+index 92f1e4308..64f46ce43 100644
+--- a/src/java.desktop/share/native/libfreetype/src/base/ftstroke.c
++++ b/src/java.desktop/share/native/libfreetype/src/base/ftstroke.c
+@@ -4,7 +4,7 @@
+  *
+  *   FreeType path stroker (body).
+  *
+- * Copyright (C) 2002-2023 by
++ * Copyright (C) 2002-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+@@ -711,7 +711,7 @@
+     {
+       FT_UInt   count = border->num_points;
+       FT_Byte*  read  = border->tags;
+-      FT_Byte*  write = (FT_Byte*)outline->tags + outline->n_points;
++      FT_Byte*  write = outline->tags + outline->n_points;
+ 
+ 
+       for ( ; count > 0; count--, read++, write++ )
+@@ -727,10 +727,10 @@
+ 
+     /* copy contours */
+     {
+-      FT_UInt    count = border->num_points;
+-      FT_Byte*   tags  = border->tags;
+-      FT_Short*  write = outline->contours + outline->n_contours;
+-      FT_Short   idx   = (FT_Short)outline->n_points;
++      FT_UInt     count = border->num_points;
++      FT_Byte*    tags  = border->tags;
++      FT_UShort*  write = outline->contours + outline->n_contours;
++      FT_UShort   idx   = outline->n_points;
+ 
+ 
+       for ( ; count > 0; count--, tags++, idx++ )
+@@ -743,7 +743,7 @@
+       }
+     }
+ 
+-    outline->n_points += (short)border->num_points;
++    outline->n_points += (FT_UShort)border->num_points;
+ 
+     FT_ASSERT( FT_Outline_Check( outline ) == 0 );
+   }
+@@ -2050,7 +2050,7 @@
+ 
+     FT_Vector*  point;
+     FT_Vector*  limit;
+-    char*       tags;
++    FT_Byte*    tags;
+ 
+     FT_Error    error;
+ 
+diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftsynth.c b/src/java.desktop/share/native/libfreetype/src/base/ftsynth.c
+index f32edd338..ec05bce33 100644
+--- a/src/java.desktop/share/native/libfreetype/src/base/ftsynth.c
++++ b/src/java.desktop/share/native/libfreetype/src/base/ftsynth.c
+@@ -4,7 +4,7 @@
+  *
+  *   FreeType synthesizing code for emboldening and slanting (body).
+  *
+- * Copyright (C) 2000-2023 by
++ * Copyright (C) 2000-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftsystem.c b/src/java.desktop/share/native/libfreetype/src/base/ftsystem.c
+index 61c99e363..eee364233 100644
+--- a/src/java.desktop/share/native/libfreetype/src/base/ftsystem.c
++++ b/src/java.desktop/share/native/libfreetype/src/base/ftsystem.c
+@@ -4,7 +4,7 @@
+  *
+  *   ANSI-specific FreeType low-level system interface (body).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/base/fttrigon.c b/src/java.desktop/share/native/libfreetype/src/base/fttrigon.c
+index 2dd2c3459..4b1aced1c 100644
+--- a/src/java.desktop/share/native/libfreetype/src/base/fttrigon.c
++++ b/src/java.desktop/share/native/libfreetype/src/base/fttrigon.c
+@@ -4,7 +4,7 @@
+  *
+  *   FreeType trigonometric functions (body).
+  *
+- * Copyright (C) 2001-2023 by
++ * Copyright (C) 2001-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/base/fttype1.c b/src/java.desktop/share/native/libfreetype/src/base/fttype1.c
+index 637c5cf77..cedf7c405 100644
+--- a/src/java.desktop/share/native/libfreetype/src/base/fttype1.c
++++ b/src/java.desktop/share/native/libfreetype/src/base/fttype1.c
+@@ -4,7 +4,7 @@
+  *
+  *   FreeType utility file for PS names support (body).
+  *
+- * Copyright (C) 2002-2023 by
++ * Copyright (C) 2002-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftutil.c b/src/java.desktop/share/native/libfreetype/src/base/ftutil.c
+index 6120846d2..b13512f87 100644
+--- a/src/java.desktop/share/native/libfreetype/src/base/ftutil.c
++++ b/src/java.desktop/share/native/libfreetype/src/base/ftutil.c
+@@ -4,7 +4,7 @@
+  *
+  *   FreeType utility file for memory and list management (body).
+  *
+- * Copyright (C) 2002-2023 by
++ * Copyright (C) 2002-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffcmap.c b/src/java.desktop/share/native/libfreetype/src/cff/cffcmap.c
+index 10d287bc8..ea5f8ed28 100644
+--- a/src/java.desktop/share/native/libfreetype/src/cff/cffcmap.c
++++ b/src/java.desktop/share/native/libfreetype/src/cff/cffcmap.c
+@@ -4,7 +4,7 @@
+  *
+  *   CFF character mapping table (cmap) support (body).
+  *
+- * Copyright (C) 2002-2023 by
++ * Copyright (C) 2002-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffcmap.h b/src/java.desktop/share/native/libfreetype/src/cff/cffcmap.h
+index b2afc2fab..1dd8700cd 100644
+--- a/src/java.desktop/share/native/libfreetype/src/cff/cffcmap.h
++++ b/src/java.desktop/share/native/libfreetype/src/cff/cffcmap.h
+@@ -4,7 +4,7 @@
+  *
+  *   CFF character mapping table (cmap) support (specification).
+  *
+- * Copyright (C) 2002-2023 by
++ * Copyright (C) 2002-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffdrivr.c b/src/java.desktop/share/native/libfreetype/src/cff/cffdrivr.c
+index 9898d625c..f6ebdb381 100644
+--- a/src/java.desktop/share/native/libfreetype/src/cff/cffdrivr.c
++++ b/src/java.desktop/share/native/libfreetype/src/cff/cffdrivr.c
+@@ -4,7 +4,7 @@
+  *
+  *   OpenType font driver implementation (body).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, Werner Lemberg, and Dominik Röttsches.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffdrivr.h b/src/java.desktop/share/native/libfreetype/src/cff/cffdrivr.h
+index ab1f147bb..fd5bc37ec 100644
+--- a/src/java.desktop/share/native/libfreetype/src/cff/cffdrivr.h
++++ b/src/java.desktop/share/native/libfreetype/src/cff/cffdrivr.h
+@@ -4,7 +4,7 @@
+  *
+  *   High-level OpenType driver interface (specification).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cfferrs.h b/src/java.desktop/share/native/libfreetype/src/cff/cfferrs.h
+index bc9a3043f..128adc3b7 100644
+--- a/src/java.desktop/share/native/libfreetype/src/cff/cfferrs.h
++++ b/src/java.desktop/share/native/libfreetype/src/cff/cfferrs.h
+@@ -4,7 +4,7 @@
+  *
+  *   CFF error codes (specification only).
+  *
+- * Copyright (C) 2001-2023 by
++ * Copyright (C) 2001-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffgload.c b/src/java.desktop/share/native/libfreetype/src/cff/cffgload.c
+index c483d1d1a..cbb071abd 100644
+--- a/src/java.desktop/share/native/libfreetype/src/cff/cffgload.c
++++ b/src/java.desktop/share/native/libfreetype/src/cff/cffgload.c
+@@ -4,7 +4,7 @@
+  *
+  *   OpenType Glyph Loader (body).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffgload.h b/src/java.desktop/share/native/libfreetype/src/cff/cffgload.h
+index 3b8cf236d..346d4b11c 100644
+--- a/src/java.desktop/share/native/libfreetype/src/cff/cffgload.h
++++ b/src/java.desktop/share/native/libfreetype/src/cff/cffgload.h
+@@ -4,7 +4,7 @@
+  *
+  *   OpenType Glyph Loader (specification).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffload.c b/src/java.desktop/share/native/libfreetype/src/cff/cffload.c
+index af79082e9..979fd45f6 100644
+--- a/src/java.desktop/share/native/libfreetype/src/cff/cffload.c
++++ b/src/java.desktop/share/native/libfreetype/src/cff/cffload.c
+@@ -4,7 +4,7 @@
+  *
+  *   OpenType and CFF data/program tables loader (body).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+@@ -1202,17 +1202,21 @@
+         {
+           CFF_AxisCoords*  axis = ®ion->axisList[j];
+ 
+-          FT_Int16  start14, peak14, end14;
++          FT_Int  start, peak, end;
+ 
+ 
+-          if ( FT_READ_SHORT( start14 ) ||
+-               FT_READ_SHORT( peak14 )  ||
+-               FT_READ_SHORT( end14 )   )
++          if ( FT_READ_SHORT( start ) ||
++               FT_READ_SHORT( peak )  ||
++               FT_READ_SHORT( end )   )
+             goto Exit;
+ 
+-          axis->startCoord = FT_fdot14ToFixed( start14 );
+-          axis->peakCoord  = FT_fdot14ToFixed( peak14 );
+-          axis->endCoord   = FT_fdot14ToFixed( end14 );
++          /* immediately tag invalid ranges with special peak = 0 */
++          if ( ( start < 0 && end > 0 ) || start > peak || peak > end )
++            peak = 0;
++
++          axis->startCoord = FT_fdot14ToFixed( start );
++          axis->peakCoord  = FT_fdot14ToFixed( peak );
++          axis->endCoord   = FT_fdot14ToFixed( end );
+         }
+       }
+ 
+@@ -1379,10 +1383,10 @@
+       /* opcode in both CFF and CFF2 DICTs.  See `cff_parse_num' for    */
+       /* decode of this, which rounds to an integer.                    */
+       *subFont->blend_top++ = 255;
+-      *subFont->blend_top++ = (FT_Byte)( sum >> 24 );
+-      *subFont->blend_top++ = (FT_Byte)( sum >> 16 );
+-      *subFont->blend_top++ = (FT_Byte)( sum >>  8 );
+-      *subFont->blend_top++ = (FT_Byte)sum;
++      *subFont->blend_top++ = (FT_Byte)( (FT_UInt32)sum >> 24 );
++      *subFont->blend_top++ = (FT_Byte)( (FT_UInt32)sum >> 16 );
++      *subFont->blend_top++ = (FT_Byte)( (FT_UInt32)sum >>  8 );
++      *subFont->blend_top++ = (FT_Byte)( (FT_UInt32)sum );
+     }
+ 
+     /* leave only numBlends results on parser stack */
+@@ -1495,44 +1499,31 @@
+       for ( j = 0; j < lenNDV; j++ )
+       {
+         CFF_AxisCoords*  axis = &varRegion->axisList[j];
+-        FT_Fixed         axisScalar;
+-
+-
+-        /* compute the scalar contribution of this axis; */
+-        /* ignore invalid ranges                         */
+-        if ( axis->startCoord > axis->peakCoord ||
+-             axis->peakCoord > axis->endCoord   )
+-          axisScalar = FT_FIXED_ONE;
+ 
+-        else if ( axis->startCoord < 0 &&
+-                  axis->endCoord > 0   &&
+-                  axis->peakCoord != 0 )
+-          axisScalar = FT_FIXED_ONE;
+ 
+-        /* peak of 0 means ignore this axis */
+-        else if ( axis->peakCoord == 0 )
+-          axisScalar = FT_FIXED_ONE;
++        /* compute the scalar contribution of this axis */
++        /* with peak of 0 used for invalid axes         */
++        if ( axis->peakCoord == NDV[j] ||
++             axis->peakCoord == 0      )
++          continue;
+ 
+         /* ignore this region if coords are out of range */
+-        else if ( NDV[j] < axis->startCoord ||
+-                  NDV[j] > axis->endCoord   )
+-          axisScalar = 0;
+-
+-        /* calculate a proportional factor */
+-        else
++        else if ( NDV[j] <= axis->startCoord ||
++                  NDV[j] >= axis->endCoord   )
+         {
+-          if ( NDV[j] == axis->peakCoord )
+-            axisScalar = FT_FIXED_ONE;
+-          else if ( NDV[j] < axis->peakCoord )
+-            axisScalar = FT_DivFix( NDV[j] - axis->startCoord,
+-                                    axis->peakCoord - axis->startCoord );
+-          else
+-            axisScalar = FT_DivFix( axis->endCoord - NDV[j],
+-                                    axis->endCoord - axis->peakCoord );
++          blend->BV[master] = 0;
++          break;
+         }
+ 
+-        /* take product of all the axis scalars */
+-        blend->BV[master] = FT_MulFix( blend->BV[master], axisScalar );
++        /* adjust proportionally */
++        else if ( NDV[j] < axis->peakCoord )
++          blend->BV[master] = FT_MulDiv( blend->BV[master],
++                                         NDV[j] - axis->startCoord,
++                                         axis->peakCoord - axis->startCoord );
++        else   /* NDV[j] > axis->peakCoord ) */
++          blend->BV[master] = FT_MulDiv( blend->BV[master],
++                                         axis->endCoord - NDV[j],
++                                         axis->endCoord - axis->peakCoord );
+       }
+ 
+       FT_TRACE4(( ", %f ",
+diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffload.h b/src/java.desktop/share/native/libfreetype/src/cff/cffload.h
+index b5286b0c8..022092454 100644
+--- a/src/java.desktop/share/native/libfreetype/src/cff/cffload.h
++++ b/src/java.desktop/share/native/libfreetype/src/cff/cffload.h
+@@ -4,7 +4,7 @@
+  *
+  *   OpenType & CFF data/program tables loader (specification).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffobjs.c b/src/java.desktop/share/native/libfreetype/src/cff/cffobjs.c
+index 6d08620c4..7c6713739 100644
+--- a/src/java.desktop/share/native/libfreetype/src/cff/cffobjs.c
++++ b/src/java.desktop/share/native/libfreetype/src/cff/cffobjs.c
+@@ -4,7 +4,7 @@
+  *
+  *   OpenType objects manager (body).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+@@ -42,6 +42,8 @@
+ #include 
+ #include 
+ 
++#define CFF_fixedToInt( x )                          \
++          ( (FT_Short)( ( (x) + 0x8000U ) >> 16 ) )
+ 
+   /**************************************************************************
+    *
+@@ -124,19 +126,20 @@
+ 
+     count = priv->num_blue_values = cpriv->num_blue_values;
+     for ( n = 0; n < count; n++ )
+-      priv->blue_values[n] = (FT_Short)cpriv->blue_values[n];
++      priv->blue_values[n] = CFF_fixedToInt( cpriv->blue_values[n] );
+ 
+     count = priv->num_other_blues = cpriv->num_other_blues;
+     for ( n = 0; n < count; n++ )
+-      priv->other_blues[n] = (FT_Short)cpriv->other_blues[n];
++      priv->other_blues[n] = CFF_fixedToInt( cpriv->other_blues[n] );
+ 
+     count = priv->num_family_blues = cpriv->num_family_blues;
+     for ( n = 0; n < count; n++ )
+-      priv->family_blues[n] = (FT_Short)cpriv->family_blues[n];
++      priv->family_blues[n] = CFF_fixedToInt( cpriv->family_blues[n] );
+ 
+     count = priv->num_family_other_blues = cpriv->num_family_other_blues;
+     for ( n = 0; n < count; n++ )
+-      priv->family_other_blues[n] = (FT_Short)cpriv->family_other_blues[n];
++      priv->family_other_blues[n] =
++        CFF_fixedToInt( cpriv->family_other_blues[n] );
+ 
+     priv->blue_scale = cpriv->blue_scale;
+     priv->blue_shift = (FT_Int)cpriv->blue_shift;
+@@ -421,32 +424,23 @@
+   static void
+   remove_subset_prefix( FT_String*  name )
+   {
+-    FT_Int32  idx             = 0;
+-    FT_Int32  length          = (FT_Int32)ft_strlen( name ) + 1;
+-    FT_Bool   continue_search = 1;
++    FT_UInt32  i = 0, idx = 0;
+ 
+ 
+-    while ( continue_search )
++    /* six ASCII uppercase letters followed by a plus sign */
++    while ( 'A' <= name[i] && name[i++] <= 'Z' &&
++            'A' <= name[i] && name[i++] <= 'Z' &&
++            'A' <= name[i] && name[i++] <= 'Z' &&
++            'A' <= name[i] && name[i++] <= 'Z' &&
++            'A' <= name[i] && name[i++] <= 'Z' &&
++            'A' <= name[i] && name[i++] <= 'Z' &&
++                              name[i++] == '+' )
+     {
+-      if ( length >= 7 && name[6] == '+' )
+-      {
+-        for ( idx = 0; idx < 6; idx++ )
+-        {
+-          /* ASCII uppercase letters */
+-          if ( !( 'A' <= name[idx] && name[idx] <= 'Z' ) )
+-            continue_search = 0;
+-        }
+-
+-        if ( continue_search )
+-        {
+-          for ( idx = 7; idx < length; idx++ )
+-            name[idx - 7] = name[idx];
+-          length -= 7;
+-        }
+-      }
+-      else
+-        continue_search = 0;
++      idx = i;
+     }
 +
-+  public int getNumRegisters() {
-+    return NPRGREG;
-+  }
++    if ( idx )
++      FT_MEM_MOVE( name, name + idx, ft_strlen( name + idx ) + 1 );
+   }
+ 
+ 
+@@ -456,42 +450,20 @@
+   remove_style( FT_String*        family_name,
+                 const FT_String*  style_name )
+   {
+-    FT_Int32  family_name_length, style_name_length;
++    FT_String*        f = family_name + ft_strlen( family_name );
++    const FT_String*  s =  style_name + ft_strlen(  style_name );
+ 
+ 
+-    family_name_length = (FT_Int32)ft_strlen( family_name );
+-    style_name_length  = (FT_Int32)ft_strlen( style_name );
++    /* compare strings moving backwards */
++    while ( s > style_name )
++      if ( f == family_name || *--s != *--f )
++        return;
+ 
+-    if ( family_name_length > style_name_length )
+-    {
+-      FT_Int  idx;
+-
+-
+-      for ( idx = 1; idx <= style_name_length; idx++ )
+-      {
+-        if ( family_name[family_name_length - idx] !=
+-             style_name[style_name_length - idx] )
+-          break;
+-      }
+-
+-      if ( idx > style_name_length )
+-      {
+-        /* family_name ends with style_name; remove it */
+-        idx = family_name_length - style_name_length - 1;
+-
+-        /* also remove special characters     */
+-        /* between real family name and style */
+-        while ( idx > 0                     &&
+-                ( family_name[idx] == '-' ||
+-                  family_name[idx] == ' ' ||
+-                  family_name[idx] == '_' ||
+-                  family_name[idx] == '+' ) )
+-          idx--;
+-
+-        if ( idx > 0 )
+-          family_name[idx + 1] = '\0';
+-      }
+-    }
++    /* terminate and remove special characters */
++    do
++      *f = '\0';
++    while ( f-- > family_name                                    &&
++            ( *f == '-' || *f == ' ' || *f == '_' || *f == '+' ) );
+   }
+ 
+ 
+@@ -722,8 +694,7 @@
+         FT_UInt  instance_index = (FT_UInt)face_index >> 16;
+ 
+ 
+-        if ( FT_HAS_MULTIPLE_MASTERS( cffface ) &&
+-             instance_index > 0                 )
++        if ( FT_HAS_MULTIPLE_MASTERS( cffface ) )
+         {
+           error = FT_Set_Named_Instance( cffface, instance_index );
+           if ( error )
+diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffobjs.h b/src/java.desktop/share/native/libfreetype/src/cff/cffobjs.h
+index 8f05f6132..91ad83b1c 100644
+--- a/src/java.desktop/share/native/libfreetype/src/cff/cffobjs.h
++++ b/src/java.desktop/share/native/libfreetype/src/cff/cffobjs.h
+@@ -4,7 +4,7 @@
+  *
+  *   OpenType objects manager (specification).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffparse.c b/src/java.desktop/share/native/libfreetype/src/cff/cffparse.c
+index 3b076704c..92a69c3b5 100644
+--- a/src/java.desktop/share/native/libfreetype/src/cff/cffparse.c
++++ b/src/java.desktop/share/native/libfreetype/src/cff/cffparse.c
+@@ -4,7 +4,7 @@
+  *
+  *   CFF token stream parser (body)
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+@@ -501,10 +501,10 @@
+       return cff_parse_real( *d, parser->limit, scaling, NULL );
+     else if ( **d == 255 )
+     {
+-      FT_Fixed val = ( ( ( (FT_UInt32)*( d[0] + 1 ) << 24 ) |
+-                         ( (FT_UInt32)*( d[0] + 2 ) << 16 ) |
+-                         ( (FT_UInt32)*( d[0] + 3 ) <<  8 ) |
+-                           (FT_UInt32)*( d[0] + 4 )         ) );
++      FT_Fixed val = (FT_Int32)( ( ( (FT_UInt32)*( d[0] + 1 ) << 24 ) |
++                                   ( (FT_UInt32)*( d[0] + 2 ) << 16 ) |
++                                   ( (FT_UInt32)*( d[0] + 3 ) <<  8 ) |
++                                     (FT_UInt32)*( d[0] + 4 )         ) );
+ 
+       if ( scaling )
+       {
+@@ -1031,10 +1031,14 @@
+           CFF_FIELD( code, name, id, cff_kind_string )
+ #define CFF_FIELD_BOOL( code, name, id )             \
+           CFF_FIELD( code, name, id, cff_kind_bool )
++#define CFF_FIELD_DELTA( code, name, max, id )                        \
++          CFF_FIELD_DELTA_KIND( code, name, max, id, cff_kind_delta )
++#define CFF_FIELD_DELTA_FIXED( code, name, max, id )                        \
++          CFF_FIELD_DELTA_KIND( code, name, max, id, cff_kind_delta_fixed )
+ 
+ 
+ #undef  CFF_FIELD
+-#undef  CFF_FIELD_DELTA
++#undef  CFF_FIELD_DELTA_KIND
+ 
+ 
+ #ifndef FT_DEBUG_LEVEL_TRACE
+@@ -1064,18 +1068,18 @@
+             code | CFFCODE,               \
+             FT_FIELD_OFFSET( name ),      \
+             FT_FIELD_SIZE( name ),        \
+-            0, 0, 0                       \
++            NULL, 0, 0                    \
+           },
+ 
+-#define CFF_FIELD_DELTA( code, name, max, id ) \
+-          {                                    \
+-            cff_kind_delta,                    \
+-            code | CFFCODE,                    \
+-            FT_FIELD_OFFSET( name ),           \
+-            FT_FIELD_SIZE_DELTA( name ),       \
+-            0,                                 \
+-            max,                               \
+-            FT_FIELD_OFFSET( num_ ## name )    \
++#define CFF_FIELD_DELTA_KIND( code, name, max, id, kind ) \
++          {                                               \
++            kind,                                         \
++            code | CFFCODE,                               \
++            FT_FIELD_OFFSET( name ),                      \
++            FT_FIELD_SIZE_DELTA( name ),                  \
++            NULL,                                         \
++            max,                                          \
++            FT_FIELD_OFFSET( num_ ## name )               \
+           },
+ 
+   static const CFF_Field_Handler  cff_field_handlers[] =
+@@ -1083,7 +1087,7 @@
+ 
+ #include "cfftoken.h"
+ 
+-    { 0, 0, 0, 0, 0, 0, 0 }
++    { 0, 0, 0, 0, NULL, 0, 0 }
+   };
+ 
+ 
+@@ -1117,20 +1121,20 @@
+             code | CFFCODE,               \
+             FT_FIELD_OFFSET( name ),      \
+             FT_FIELD_SIZE( name ),        \
+-            0, 0, 0,                      \
++            NULL, 0, 0,                   \
+             id                            \
+           },
+ 
+-#define CFF_FIELD_DELTA( code, name, max, id ) \
+-          {                                    \
+-            cff_kind_delta,                    \
+-            code | CFFCODE,                    \
+-            FT_FIELD_OFFSET( name ),           \
+-            FT_FIELD_SIZE_DELTA( name ),       \
+-            0,                                 \
+-            max,                               \
+-            FT_FIELD_OFFSET( num_ ## name ),   \
+-            id                                 \
++#define CFF_FIELD_DELTA_KIND( code, name, max, id, kind ) \
++          {                                               \
++            kind,                                         \
++            code | CFFCODE,                               \
++            FT_FIELD_OFFSET( name ),                      \
++            FT_FIELD_SIZE_DELTA( name ),                  \
++            NULL,                                         \
++            max,                                          \
++            FT_FIELD_OFFSET( num_ ## name ),              \
++            id                                            \
+           },
+ 
+   static const CFF_Field_Handler  cff_field_handlers[] =
+@@ -1138,7 +1142,7 @@
+ 
+ #include "cfftoken.h"
+ 
+-    { 0, 0, 0, 0, 0, 0, 0, 0 }
++    { 0, 0, 0, 0, NULL, 0, 0, NULL }
+   };
+ 
+ 
+@@ -1356,7 +1360,8 @@
+ 
+             /* check that we have enough arguments -- except for */
+             /* delta encoded arrays, which can be empty          */
+-            if ( field->kind != cff_kind_delta && num_args < 1 )
++            if ( field->kind != cff_kind_delta                       &&
++                 field->kind != cff_kind_delta_fixed && num_args < 1 )
+               goto Stack_Underflow;
+ 
+             switch ( field->kind )
+@@ -1471,6 +1476,38 @@
+               }
+               break;
+ 
++            case cff_kind_delta_fixed:
++              {
++                FT_Byte*   qcount = (FT_Byte*)parser->object +
++                                      field->count_offset;
 +
-+  public String getRegisterName(int index) {
-+    return regNames[index];
-+  }
++                FT_Byte**  data = parser->stack;
 +
-+  public void setRegister(int index, long value) {
-+    data[index] = value;
-+  }
 +
-+  public long getRegister(int index) {
-+    return data[index];
-+  }
++                if ( num_args > field->array_max )
++                  num_args = field->array_max;
 +
-+  public CFrame getTopFrame(Debugger dbg) {
-+    return null;
-+  }
++                FT_TRACE4(( " [" ));
 +
-+  /** This can't be implemented in this class since we would have to
-+      tie the implementation to, for example, the debugging system */
-+  public abstract void setRegisterAsAddress(int index, Address value);
++                /* store count */
++                *qcount = (FT_Byte)num_args;
 +
-+  /** This can't be implemented in this class since we would have to
-+      tie the implementation to, for example, the debugging system */
-+  public abstract Address getRegisterAsAddress(int index);
-+}
-diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/MachineDescriptionLOONGARCH64.java jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/MachineDescriptionLOONGARCH64.java
---- openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/MachineDescriptionLOONGARCH64.java	1970-01-01 08:00:00.000000000 +0800
-+++ jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/MachineDescriptionLOONGARCH64.java	2023-09-12 13:54:26.361575771 +0800
-@@ -0,0 +1,41 @@
-+/*
-+ * Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved.
-+ * Copyright (c) 2018, 2021, Loongson Technology. 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.
-+ *
-+ */
++                val = 0;
++                while ( num_args > 0 )
++                {
++                  val = ADD_LONG( val, cff_parse_fixed( parser, data++ ) );
++                  *(FT_Long*)q = val;
 +
-+package sun.jvm.hotspot.debugger;
++                  FT_TRACE4(( " %f\n", (double)val / 65536 ));
 +
-+public class MachineDescriptionLOONGARCH64 extends MachineDescriptionTwosComplement implements MachineDescription {
-+  public long getAddressSize() {
-+    return 8;
-+  }
++                  q += field->size;
++                  num_args--;
++                }
 +
++                FT_TRACE4(( "]\n" ));
++              }
++              break;
 +
-+  public boolean isBigEndian() {
-+    return false;
-+  }
+             default:  /* callback or blend */
+               error = field->reader( parser );
+               if ( error )
+diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffparse.h b/src/java.desktop/share/native/libfreetype/src/cff/cffparse.h
+index 418caacc6..ca6b18af6 100644
+--- a/src/java.desktop/share/native/libfreetype/src/cff/cffparse.h
++++ b/src/java.desktop/share/native/libfreetype/src/cff/cffparse.h
+@@ -4,7 +4,7 @@
+  *
+  *   CFF token stream parser (specification)
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+@@ -107,6 +107,7 @@ FT_BEGIN_HEADER
+     cff_kind_string,
+     cff_kind_bool,
+     cff_kind_delta,
++    cff_kind_delta_fixed,
+     cff_kind_callback,
+     cff_kind_blend,
+ 
+diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cfftoken.h b/src/java.desktop/share/native/libfreetype/src/cff/cfftoken.h
+index b61cb0e66..da45faa7f 100644
+--- a/src/java.desktop/share/native/libfreetype/src/cff/cfftoken.h
++++ b/src/java.desktop/share/native/libfreetype/src/cff/cfftoken.h
+@@ -4,7 +4,7 @@
+  *
+  *   CFF token definitions (specification only).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+@@ -80,26 +80,26 @@
+ #undef  CFFCODE
+ #define CFFCODE       CFF_CODE_PRIVATE
+ 
+-  CFF_FIELD_DELTA     ( 6,     blue_values, 14,        "BlueValues" )
+-  CFF_FIELD_DELTA     ( 7,     other_blues, 10,        "OtherBlues" )
+-  CFF_FIELD_DELTA     ( 8,     family_blues, 14,       "FamilyBlues" )
+-  CFF_FIELD_DELTA     ( 9,     family_other_blues, 10, "FamilyOtherBlues" )
+-  CFF_FIELD_FIXED_1000( 0x109, blue_scale,             "BlueScale" )
+-  CFF_FIELD_NUM       ( 0x10A, blue_shift,             "BlueShift" )
+-  CFF_FIELD_NUM       ( 0x10B, blue_fuzz,              "BlueFuzz" )
+-  CFF_FIELD_NUM       ( 10,    standard_width,         "StdHW" )
+-  CFF_FIELD_NUM       ( 11,    standard_height,        "StdVW" )
+-  CFF_FIELD_DELTA     ( 0x10C, snap_widths, 13,        "StemSnapH" )
+-  CFF_FIELD_DELTA     ( 0x10D, snap_heights, 13,       "StemSnapV" )
+-  CFF_FIELD_BOOL      ( 0x10E, force_bold,             "ForceBold" )
+-  CFF_FIELD_FIXED     ( 0x10F, force_bold_threshold,   "ForceBoldThreshold" )
+-  CFF_FIELD_NUM       ( 0x110, lenIV,                  "lenIV" )
+-  CFF_FIELD_NUM       ( 0x111, language_group,         "LanguageGroup" )
+-  CFF_FIELD_FIXED     ( 0x112, expansion_factor,       "ExpansionFactor" )
+-  CFF_FIELD_NUM       ( 0x113, initial_random_seed,    "initialRandomSeed" )
+-  CFF_FIELD_NUM       ( 19,    local_subrs_offset,     "Subrs" )
+-  CFF_FIELD_NUM       ( 20,    default_width,          "defaultWidthX" )
+-  CFF_FIELD_NUM       ( 21,    nominal_width,          "nominalWidthX" )
++  CFF_FIELD_DELTA_FIXED( 6,     blue_values, 14,        "BlueValues" )
++  CFF_FIELD_DELTA_FIXED( 7,     other_blues, 10,        "OtherBlues" )
++  CFF_FIELD_DELTA_FIXED( 8,     family_blues, 14,       "FamilyBlues" )
++  CFF_FIELD_DELTA_FIXED( 9,     family_other_blues, 10, "FamilyOtherBlues" )
++  CFF_FIELD_FIXED_1000 ( 0x109, blue_scale,             "BlueScale" )
++  CFF_FIELD_NUM        ( 0x10A, blue_shift,             "BlueShift" )
++  CFF_FIELD_NUM        ( 0x10B, blue_fuzz,              "BlueFuzz" )
++  CFF_FIELD_NUM        ( 10,    standard_width,         "StdHW" )
++  CFF_FIELD_NUM        ( 11,    standard_height,        "StdVW" )
++  CFF_FIELD_DELTA      ( 0x10C, snap_widths, 13,        "StemSnapH" )
++  CFF_FIELD_DELTA      ( 0x10D, snap_heights, 13,       "StemSnapV" )
++  CFF_FIELD_BOOL       ( 0x10E, force_bold,             "ForceBold" )
++  CFF_FIELD_FIXED      ( 0x10F, force_bold_threshold,   "ForceBoldThreshold" )
++  CFF_FIELD_NUM        ( 0x110, lenIV,                  "lenIV" )
++  CFF_FIELD_NUM        ( 0x111, language_group,         "LanguageGroup" )
++  CFF_FIELD_FIXED      ( 0x112, expansion_factor,       "ExpansionFactor" )
++  CFF_FIELD_NUM        ( 0x113, initial_random_seed,    "initialRandomSeed" )
++  CFF_FIELD_NUM        ( 19,    local_subrs_offset,     "Subrs" )
++  CFF_FIELD_NUM        ( 20,    default_width,          "defaultWidthX" )
++  CFF_FIELD_NUM        ( 21,    nominal_width,          "nominalWidthX" )
+ 
+ 
+ #undef  FT_STRUCTURE
+@@ -129,22 +129,22 @@
+ #undef  CFFCODE
+ #define CFFCODE       CFF2_CODE_PRIVATE
+ 
+-  CFF_FIELD_DELTA     ( 6,     blue_values, 14,        "BlueValues" )
+-  CFF_FIELD_DELTA     ( 7,     other_blues, 10,        "OtherBlues" )
+-  CFF_FIELD_DELTA     ( 8,     family_blues, 14,       "FamilyBlues" )
+-  CFF_FIELD_DELTA     ( 9,     family_other_blues, 10, "FamilyOtherBlues" )
+-  CFF_FIELD_FIXED_1000( 0x109, blue_scale,             "BlueScale" )
+-  CFF_FIELD_NUM       ( 0x10A, blue_shift,             "BlueShift" )
+-  CFF_FIELD_NUM       ( 0x10B, blue_fuzz,              "BlueFuzz" )
+-  CFF_FIELD_NUM       ( 10,    standard_width,         "StdHW" )
+-  CFF_FIELD_NUM       ( 11,    standard_height,        "StdVW" )
+-  CFF_FIELD_DELTA     ( 0x10C, snap_widths, 13,        "StemSnapH" )
+-  CFF_FIELD_DELTA     ( 0x10D, snap_heights, 13,       "StemSnapV" )
+-  CFF_FIELD_NUM       ( 0x111, language_group,         "LanguageGroup" )
+-  CFF_FIELD_FIXED     ( 0x112, expansion_factor,       "ExpansionFactor" )
+-  CFF_FIELD_CALLBACK  ( 22,    vsindex,                "vsindex" )
+-  CFF_FIELD_BLEND     ( 23,                            "blend" )
+-  CFF_FIELD_NUM       ( 19,    local_subrs_offset,     "Subrs" )
++  CFF_FIELD_DELTA_FIXED( 6,     blue_values, 14,        "BlueValues" )
++  CFF_FIELD_DELTA_FIXED( 7,     other_blues, 10,        "OtherBlues" )
++  CFF_FIELD_DELTA_FIXED( 8,     family_blues, 14,       "FamilyBlues" )
++  CFF_FIELD_DELTA_FIXED( 9,     family_other_blues, 10, "FamilyOtherBlues" )
++  CFF_FIELD_FIXED_1000 ( 0x109, blue_scale,             "BlueScale" )
++  CFF_FIELD_NUM        ( 0x10A, blue_shift,             "BlueShift" )
++  CFF_FIELD_NUM        ( 0x10B, blue_fuzz,              "BlueFuzz" )
++  CFF_FIELD_NUM        ( 10,    standard_width,         "StdHW" )
++  CFF_FIELD_NUM        ( 11,    standard_height,        "StdVW" )
++  CFF_FIELD_DELTA      ( 0x10C, snap_widths, 13,        "StemSnapH" )
++  CFF_FIELD_DELTA      ( 0x10D, snap_heights, 13,       "StemSnapV" )
++  CFF_FIELD_NUM        ( 0x111, language_group,         "LanguageGroup" )
++  CFF_FIELD_FIXED      ( 0x112, expansion_factor,       "ExpansionFactor" )
++  CFF_FIELD_CALLBACK   ( 22,    vsindex,                "vsindex" )
++  CFF_FIELD_BLEND      ( 23,                            "blend" )
++  CFF_FIELD_NUM        ( 19,    local_subrs_offset,     "Subrs" )
+ 
+ 
+ /* END */
+diff --git a/src/java.desktop/share/native/libfreetype/src/cid/ciderrs.h b/src/java.desktop/share/native/libfreetype/src/cid/ciderrs.h
+index 40a1097d0..c439a8c4a 100644
+--- a/src/java.desktop/share/native/libfreetype/src/cid/ciderrs.h
++++ b/src/java.desktop/share/native/libfreetype/src/cid/ciderrs.h
+@@ -4,7 +4,7 @@
+  *
+  *   CID error codes (specification only).
+  *
+- * Copyright (C) 2001-2023 by
++ * Copyright (C) 2001-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidgload.c b/src/java.desktop/share/native/libfreetype/src/cid/cidgload.c
+index eaca765ad..7b571322d 100644
+--- a/src/java.desktop/share/native/libfreetype/src/cid/cidgload.c
++++ b/src/java.desktop/share/native/libfreetype/src/cid/cidgload.c
+@@ -4,7 +4,7 @@
+  *
+  *   CID-keyed Type1 Glyph Loader (body).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidgload.h b/src/java.desktop/share/native/libfreetype/src/cid/cidgload.h
+index edd622923..9fdc9db58 100644
+--- a/src/java.desktop/share/native/libfreetype/src/cid/cidgload.h
++++ b/src/java.desktop/share/native/libfreetype/src/cid/cidgload.h
+@@ -4,7 +4,7 @@
+  *
+  *   OpenType Glyph Loader (specification).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidload.c b/src/java.desktop/share/native/libfreetype/src/cid/cidload.c
+index a7da8ea39..722f5a34d 100644
+--- a/src/java.desktop/share/native/libfreetype/src/cid/cidload.c
++++ b/src/java.desktop/share/native/libfreetype/src/cid/cidload.c
+@@ -4,7 +4,7 @@
+  *
+  *   CID-keyed Type1 font loader (body).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+@@ -388,7 +388,7 @@
+     T1_FIELD_CALLBACK( "ExpansionFactor", parse_expansion_factor, 0 )
+     T1_FIELD_CALLBACK( "FontName",        parse_font_name, 0 )
+ 
+-    { 0, T1_FIELD_LOCATION_CID_INFO, T1_FIELD_TYPE_NONE, 0, 0, 0, 0, 0, 0 }
++    T1_FIELD_ZERO
+   };
+ 
+ 
+@@ -469,36 +469,23 @@
+             T1_Field  keyword = (T1_Field)cid_field_records;
+ 
+ 
+-            for (;;)
++            while ( keyword->len )
+             {
+-              FT_Byte*  name;
++              FT_Byte*  name = (FT_Byte*)keyword->ident;
+ 
+ 
+-              name = (FT_Byte*)keyword->ident;
+-              if ( !name )
+-                break;
+-
+-              if ( cur[0] == name[0]                     &&
+-                   len == ft_strlen( (const char*)name ) )
++              if ( keyword->len == len              &&
++                   ft_memcmp( cur, name, len ) == 0 )
+               {
+-                FT_UInt  n;
+-
+-
+-                for ( n = 1; n < len; n++ )
+-                  if ( cur[n] != name[n] )
+-                    break;
+-
+-                if ( n >= len )
+-                {
+-                  /* we found it - run the parsing callback */
+-                  parser->root.error = cid_load_keyword( face,
+-                                                         loader,
+-                                                         keyword );
+-                  if ( parser->root.error )
+-                    return parser->root.error;
+-                  break;
+-                }
++                /* we found it - run the parsing callback */
++                parser->root.error = cid_load_keyword( face,
++                                                       loader,
++                                                       keyword );
++                if ( parser->root.error )
++                  return parser->root.error;
++                break;
+               }
 +
-+  public boolean isLP64() {
-+    return true;
-+  }
-+}
-diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/MachineDescriptionMIPS64.java jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/MachineDescriptionMIPS64.java
---- openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/MachineDescriptionMIPS64.java	1970-01-01 08:00:00.000000000 +0800
-+++ jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/MachineDescriptionMIPS64.java	2023-09-12 13:54:26.365575776 +0800
-@@ -0,0 +1,41 @@
-+/*
-+ * Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved.
-+ * Copyright (c) 2018, Loongson Technology. 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 sun.jvm.hotspot.debugger;
-+
-+public class MachineDescriptionMIPS64 extends MachineDescriptionTwosComplement implements MachineDescription {
-+  public long getAddressSize() {
-+    return 8;
-+  }
-+
-+
-+  public boolean isBigEndian() {
-+    return "big".equals(System.getProperty("sun.cpu.endian"));
-+  }
-+
-+  public boolean isLP64() {
-+    return true;
-+  }
-+}
-diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/mips64/MIPS64ThreadContext.java jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/mips64/MIPS64ThreadContext.java
---- openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/mips64/MIPS64ThreadContext.java	1970-01-01 08:00:00.000000000 +0800
-+++ jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/mips64/MIPS64ThreadContext.java	2023-09-12 13:54:26.373575786 +0800
-@@ -0,0 +1,128 @@
-+/*
-+ * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
-+ * Copyright (c) 2015, 2018, Loongson Technology. 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.
-+ *
-+ */
+               keyword++;
+             }
+           }
+diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidload.h b/src/java.desktop/share/native/libfreetype/src/cid/cidload.h
+index d12d2962a..7f030b32d 100644
+--- a/src/java.desktop/share/native/libfreetype/src/cid/cidload.h
++++ b/src/java.desktop/share/native/libfreetype/src/cid/cidload.h
+@@ -4,7 +4,7 @@
+  *
+  *   CID-keyed Type1 font loader (specification).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidobjs.c b/src/java.desktop/share/native/libfreetype/src/cid/cidobjs.c
+index f698a4192..8d337c411 100644
+--- a/src/java.desktop/share/native/libfreetype/src/cid/cidobjs.c
++++ b/src/java.desktop/share/native/libfreetype/src/cid/cidobjs.c
+@@ -4,7 +4,7 @@
+  *
+  *   CID objects manager (body).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidobjs.h b/src/java.desktop/share/native/libfreetype/src/cid/cidobjs.h
+index 83c0c61c3..d371cbe99 100644
+--- a/src/java.desktop/share/native/libfreetype/src/cid/cidobjs.h
++++ b/src/java.desktop/share/native/libfreetype/src/cid/cidobjs.h
+@@ -4,7 +4,7 @@
+  *
+  *   CID objects manager (specification).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidparse.c b/src/java.desktop/share/native/libfreetype/src/cid/cidparse.c
+index 171a88621..73a3ade89 100644
+--- a/src/java.desktop/share/native/libfreetype/src/cid/cidparse.c
++++ b/src/java.desktop/share/native/libfreetype/src/cid/cidparse.c
+@@ -4,7 +4,7 @@
+  *
+  *   CID-keyed Type1 parser (body).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+@@ -90,10 +90,15 @@
+     if ( error )
+       goto Exit;
+ 
+-  Again:
+-    /* now, read the rest of the file until we find */
+-    /* `StartData' or `/sfnts'                      */
++    if ( !stream->read ) {
++      /* just parse memory-based streams */
++      offset = stream->size;
++    }
++    else
+     {
++      /* Find the last `StartData` or `/sfnts`.  The parser requires */
++      /* contiguous memory; attempt to pin as little as necessary.   */
++
+       /*
+        * The algorithm is as follows (omitting the case with less than 256
+        * bytes to fill for simplicity).
+@@ -119,7 +124,8 @@
+       FT_Byte*  p           = buffer;
+ 
+ 
+-      for ( offset = FT_STREAM_POS(); ; offset += 256 )
++      offset = 0;
++      while ( 1 )
+       {
+         FT_ULong  stream_len;
+ 
+@@ -127,7 +133,7 @@
+         stream_len = stream->size - FT_STREAM_POS();
+ 
+         read_len = FT_MIN( read_len, stream_len );
+-        if ( FT_STREAM_READ( p, read_len ) )
++        if ( read_len && FT_STREAM_READ( p, read_len ) )
+           goto Exit;
+ 
+         /* ensure that we do not compare with data beyond the buffer */
+@@ -141,20 +147,23 @@
+                ft_strncmp( (char*)p, STARTDATA, STARTDATA_LEN ) == 0 )
+           {
+             /* save offset of binary data after `StartData' */
+-            offset += (FT_ULong)( p - buffer ) + STARTDATA_LEN + 1;
+-            goto Found;
++            offset = FT_STREAM_POS() - read_len - read_offset
++                     + (FT_ULong)( p - buffer ) + STARTDATA_LEN + 1;
+           }
+           else if ( p[1] == 's'                                   &&
+                     ft_strncmp( (char*)p, SFNTS, SFNTS_LEN ) == 0 )
+           {
+-            offset += (FT_ULong)( p - buffer ) + SFNTS_LEN + 1;
+-            goto Found;
++            offset = FT_STREAM_POS() - read_len - read_offset
++                     + (FT_ULong)( p - buffer ) + SFNTS_LEN + 1;
+           }
+         }
+ 
+-        if ( read_offset + read_len < STARTDATA_LEN )
++        if ( read_offset + read_len <= STARTDATA_LEN )
+         {
+-          FT_TRACE2(( "cid_parser_new: no `StartData' keyword found\n" ));
++          if ( offset )
++            goto Found;
++
++          FT_TRACE2(( "cid_parser_new: no `StartData` keyword found\n" ));
+           error = FT_THROW( Invalid_File_Format );
+           goto Exit;
+         }
+@@ -171,9 +180,9 @@
+     }
+ 
+   Found:
+-    /* We have found the start of the binary data or the `/sfnts' token. */
+-    /* Now rewind and extract the frame corresponding to this PostScript */
+-    /* section.                                                          */
++    /* We have found an efficient range to look for the binary data or    */
++    /* `/sfnts' token.  Now rewind and extract the frame corresponding to */
++    /* this PostScript section.                                           */
+ 
+     ps_len = offset - base_offset;
+     if ( FT_STREAM_SEEK( base_offset )                  ||
+@@ -187,8 +196,8 @@
+     parser->root.limit     = parser->root.cursor + ps_len;
+     parser->num_dict       = FT_UINT_MAX;
+ 
+-    /* Finally, we check whether `StartData' or `/sfnts' was real --  */
+-    /* it could be in a comment or string.  We also get the arguments */
++    /* Find the first real `StartData' or `/sfnts' -- the last one    */
++    /* could be in a comment or string.  We also get the arguments    */
+     /* of `StartData' to find out whether the data is represented in  */
+     /* binary or hex format.                                          */
+ 
+@@ -216,6 +225,7 @@
+       {
+         T1_TokenRec  type_token;
+         FT_Long      binary_length;
++        FT_ULong     found_offset;
+ 
+ 
+         parser->root.cursor = arg1;
+@@ -234,6 +244,24 @@
+             parser->binary_length = (FT_ULong)binary_length;
+         }
+ 
++        /* set the real values for the parser, if different */
++        found_offset = (FT_ULong)( cur - parser->postscript )
++                       + STARTDATA_LEN + 1;
++        if ( found_offset != offset )
++        {
++          FT_FRAME_RELEASE( parser->postscript );
++
++          ps_len = found_offset - base_offset;
++          if ( FT_STREAM_SEEK( base_offset )                  ||
++               FT_FRAME_EXTRACT( ps_len, parser->postscript ) )
++            goto Exit;
++
++          parser->data_offset    = found_offset;
++          parser->postscript_len = ps_len;
++          parser->root.base      = parser->postscript;
++          parser->root.cursor    = parser->postscript;
++          parser->root.limit     = parser->root.cursor + ps_len;
++        }
+         goto Exit;
+       }
+       else if ( cur[1] == 's'                                   &&
+@@ -251,11 +279,8 @@
+       cur  = parser->root.cursor;
+     }
+ 
+-    /* we haven't found the correct `StartData'; go back and continue */
+-    /* searching                                                      */
+-    FT_FRAME_RELEASE( parser->postscript );
+-    if ( !FT_STREAM_SEEK( offset ) )
+-      goto Again;
++    FT_TRACE2(( "cid_parser_new: no `StartData` token found\n" ));
++    error = FT_THROW( Invalid_File_Format );
+ 
+   Exit:
+     return error;
+diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidparse.h b/src/java.desktop/share/native/libfreetype/src/cid/cidparse.h
+index 2fd4e7a93..0f5baddcb 100644
+--- a/src/java.desktop/share/native/libfreetype/src/cid/cidparse.h
++++ b/src/java.desktop/share/native/libfreetype/src/cid/cidparse.h
+@@ -4,7 +4,7 @@
+  *
+  *   CID-keyed Type1 parser (specification).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidriver.c b/src/java.desktop/share/native/libfreetype/src/cid/cidriver.c
+index 99e7b1183..4be8a5c00 100644
+--- a/src/java.desktop/share/native/libfreetype/src/cid/cidriver.c
++++ b/src/java.desktop/share/native/libfreetype/src/cid/cidriver.c
+@@ -4,7 +4,7 @@
+  *
+  *   CID driver interface (body).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidriver.h b/src/java.desktop/share/native/libfreetype/src/cid/cidriver.h
+index a6249385c..7ddce431c 100644
+--- a/src/java.desktop/share/native/libfreetype/src/cid/cidriver.h
++++ b/src/java.desktop/share/native/libfreetype/src/cid/cidriver.h
+@@ -4,7 +4,7 @@
+  *
+  *   High-level CID driver interface (specification).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidtoken.h b/src/java.desktop/share/native/libfreetype/src/cid/cidtoken.h
+index 925951acd..160897d14 100644
+--- a/src/java.desktop/share/native/libfreetype/src/cid/cidtoken.h
++++ b/src/java.desktop/share/native/libfreetype/src/cid/cidtoken.h
+@@ -4,7 +4,7 @@
+  *
+  *   CID token definitions (specification only).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/afmparse.c b/src/java.desktop/share/native/libfreetype/src/psaux/afmparse.c
+index db08941de..e2f6a8e5a 100644
+--- a/src/java.desktop/share/native/libfreetype/src/psaux/afmparse.c
++++ b/src/java.desktop/share/native/libfreetype/src/psaux/afmparse.c
+@@ -4,7 +4,7 @@
+  *
+  *   AFM parser (body).
+  *
+- * Copyright (C) 2006-2023 by
++ * Copyright (C) 2006-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/afmparse.h b/src/java.desktop/share/native/libfreetype/src/psaux/afmparse.h
+index 2d3b6e6e1..b77663728 100644
+--- a/src/java.desktop/share/native/libfreetype/src/psaux/afmparse.h
++++ b/src/java.desktop/share/native/libfreetype/src/psaux/afmparse.h
+@@ -4,7 +4,7 @@
+  *
+  *   AFM parser (specification).
+  *
+- * Copyright (C) 2006-2023 by
++ * Copyright (C) 2006-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/cffdecode.c b/src/java.desktop/share/native/libfreetype/src/psaux/cffdecode.c
+index 562d17d22..9556e11a5 100644
+--- a/src/java.desktop/share/native/libfreetype/src/psaux/cffdecode.c
++++ b/src/java.desktop/share/native/libfreetype/src/psaux/cffdecode.c
+@@ -4,7 +4,7 @@
+  *
+  *   PostScript CFF (Type 2) decoding routines (body).
+  *
+- * Copyright (C) 2017-2023 by
++ * Copyright (C) 2017-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+@@ -17,6 +17,7 @@
+ 
+ 
+ #include 
++#include 
+ #include 
+ #include 
+ #include 
+@@ -1752,22 +1753,9 @@
+ 
+           /* without upper limit the loop below might not finish */
+           if ( args[0] > 0x7FFFFFFFL )
+-            args[0] = 46341;
++            args[0] = 0xB504F4L;    /* sqrt( 32768.0044 ) */
+           else if ( args[0] > 0 )
+-          {
+-            FT_Fixed  root = args[0];
+-            FT_Fixed  new_root;
+-
+-
+-            for (;;)
+-            {
+-              new_root = ( root + FT_DivFix( args[0], root ) + 1 ) >> 1;
+-              if ( new_root == root )
+-                break;
+-              root = new_root;
+-            }
+-            args[0] = new_root;
+-          }
++            args[0] = (FT_Fixed)FT_SqrtFixed( args[0] );
+           else
+             args[0] = 0;
+           args++;
+diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/cffdecode.h b/src/java.desktop/share/native/libfreetype/src/psaux/cffdecode.h
+index e8bb4001c..038f7235c 100644
+--- a/src/java.desktop/share/native/libfreetype/src/psaux/cffdecode.h
++++ b/src/java.desktop/share/native/libfreetype/src/psaux/cffdecode.h
+@@ -4,7 +4,7 @@
+  *
+  *   PostScript CFF (Type 2) decoding routines (specification).
+  *
+- * Copyright (C) 2017-2023 by
++ * Copyright (C) 2017-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/psauxerr.h b/src/java.desktop/share/native/libfreetype/src/psaux/psauxerr.h
+index 895ffa48c..18428c40d 100644
+--- a/src/java.desktop/share/native/libfreetype/src/psaux/psauxerr.h
++++ b/src/java.desktop/share/native/libfreetype/src/psaux/psauxerr.h
+@@ -4,7 +4,7 @@
+  *
+  *   PS auxiliary module error codes (specification only).
+  *
+- * Copyright (C) 2001-2023 by
++ * Copyright (C) 2001-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/psauxmod.c b/src/java.desktop/share/native/libfreetype/src/psaux/psauxmod.c
+index 45e35aa53..6826f9d8d 100644
+--- a/src/java.desktop/share/native/libfreetype/src/psaux/psauxmod.c
++++ b/src/java.desktop/share/native/libfreetype/src/psaux/psauxmod.c
+@@ -4,7 +4,7 @@
+  *
+  *   FreeType auxiliary PostScript module implementation (body).
+  *
+- * Copyright (C) 2000-2023 by
++ * Copyright (C) 2000-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/psauxmod.h b/src/java.desktop/share/native/libfreetype/src/psaux/psauxmod.h
+index 94dbf4881..82d7e348a 100644
+--- a/src/java.desktop/share/native/libfreetype/src/psaux/psauxmod.h
++++ b/src/java.desktop/share/native/libfreetype/src/psaux/psauxmod.h
+@@ -4,7 +4,7 @@
+  *
+  *   FreeType auxiliary PostScript module implementation (specification).
+  *
+- * Copyright (C) 2000-2023 by
++ * Copyright (C) 2000-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/psblues.c b/src/java.desktop/share/native/libfreetype/src/psaux/psblues.c
+index f9c864fea..213b943b4 100644
+--- a/src/java.desktop/share/native/libfreetype/src/psaux/psblues.c
++++ b/src/java.desktop/share/native/libfreetype/src/psaux/psblues.c
+@@ -54,14 +54,6 @@
+ #define FT_COMPONENT  cf2blues
+ 
+ 
+-  /*
+-   * For blue values, the FreeType parser produces an array of integers,
+-   * while the Adobe CFF engine produces an array of fixed.
+-   * Define a macro to convert FreeType to fixed.
+-   */
+-#define cf2_blueToFixed( x )  cf2_intToFixed( x )
+-
+-
+   FT_LOCAL_DEF( void )
+   cf2_blues_init( CF2_Blues  blues,
+                   CF2_Font   font )
+@@ -78,10 +70,10 @@
+     size_t  numFamilyBlues;
+     size_t  numFamilyOtherBlues;
+ 
+-    FT_Pos*  blueValues;
+-    FT_Pos*  otherBlues;
+-    FT_Pos*  familyBlues;
+-    FT_Pos*  familyOtherBlues;
++    FT_Fixed*  blueValues;
++    FT_Fixed*  otherBlues;
++    FT_Fixed*  familyBlues;
++    FT_Fixed*  familyOtherBlues;
+ 
+     size_t     i;
+     CF2_Fixed  emBoxBottom, emBoxTop;
+@@ -138,13 +130,13 @@
+       emBoxTop    = CF2_ICF_Top;
+     }
+ 
+-    if ( cf2_getLanguageGroup( decoder ) == 1                   &&
+-         ( numBlueValues == 0                                 ||
+-           ( numBlueValues == 4                             &&
+-             cf2_blueToFixed( blueValues[0] ) < emBoxBottom &&
+-             cf2_blueToFixed( blueValues[1] ) < emBoxBottom &&
+-             cf2_blueToFixed( blueValues[2] ) > emBoxTop    &&
+-             cf2_blueToFixed( blueValues[3] ) > emBoxTop    ) ) )
++    if ( cf2_getLanguageGroup( decoder ) == 1     &&
++         ( numBlueValues == 0                   ||
++           ( numBlueValues == 4               &&
++             blueValues[0] < emBoxBottom      &&
++             blueValues[1] < emBoxBottom      &&
++             blueValues[2] > emBoxTop         &&
++             blueValues[3] > emBoxTop         ) ) )
+     {
+       /*
+        * Construct hint edges suitable for synthetic ghost hints at top
+@@ -189,10 +181,8 @@
+     /* bottom zones                                                      */
+     for ( i = 0; i < numBlueValues; i += 2 )
+     {
+-      blues->zone[blues->count].csBottomEdge =
+-        cf2_blueToFixed( blueValues[i] );
+-      blues->zone[blues->count].csTopEdge =
+-        cf2_blueToFixed( blueValues[i + 1] );
++      blues->zone[blues->count].csBottomEdge = blueValues[i];
++      blues->zone[blues->count].csTopEdge    = blueValues[i + 1];
+ 
+       zoneHeight = SUB_INT32( blues->zone[blues->count].csTopEdge,
+                               blues->zone[blues->count].csBottomEdge );
+@@ -238,10 +228,8 @@
+ 
+     for ( i = 0; i < numOtherBlues; i += 2 )
+     {
+-      blues->zone[blues->count].csBottomEdge =
+-        cf2_blueToFixed( otherBlues[i] );
+-      blues->zone[blues->count].csTopEdge =
+-        cf2_blueToFixed( otherBlues[i + 1] );
++      blues->zone[blues->count].csBottomEdge = otherBlues[i];
++      blues->zone[blues->count].csTopEdge    = otherBlues[i + 1];
+ 
+       zoneHeight = SUB_INT32( blues->zone[blues->count].csTopEdge,
+                               blues->zone[blues->count].csBottomEdge );
+@@ -299,7 +287,7 @@
+         for ( j = 0; j < numFamilyOtherBlues; j += 2 )
+         {
+           /* top edge */
+-          flatFamilyEdge = cf2_blueToFixed( familyOtherBlues[j + 1] );
++          flatFamilyEdge = familyOtherBlues[j + 1];
+ 
+           diff = cf2_fixedAbs( SUB_INT32( flatEdge, flatFamilyEdge ) );
+ 
+@@ -317,7 +305,7 @@
+         if ( numFamilyBlues >= 2 )
+         {
+           /* top edge */
+-          flatFamilyEdge = cf2_blueToFixed( familyBlues[1] );
++          flatFamilyEdge = familyBlues[1];
+ 
+           diff = cf2_fixedAbs( SUB_INT32( flatEdge, flatFamilyEdge ) );
+ 
+@@ -337,7 +325,7 @@
+         for ( j = 2; j < numFamilyBlues; j += 2 )
+         {
+           /* bottom edge */
+-          flatFamilyEdge = cf2_blueToFixed( familyBlues[j] );
++          flatFamilyEdge = familyBlues[j];
+ 
+           /* adjust edges of top zone upward by twice darkening amount */
+           flatFamilyEdge += 2 * font->darkenY;      /* bottom edge */
+diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/psconv.c b/src/java.desktop/share/native/libfreetype/src/psaux/psconv.c
+index b9c7138d8..56c0ecd1d 100644
+--- a/src/java.desktop/share/native/libfreetype/src/psaux/psconv.c
++++ b/src/java.desktop/share/native/libfreetype/src/psaux/psconv.c
+@@ -4,7 +4,7 @@
+  *
+  *   Some convenience conversions (body).
+  *
+- * Copyright (C) 2006-2023 by
++ * Copyright (C) 2006-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/psconv.h b/src/java.desktop/share/native/libfreetype/src/psaux/psconv.h
+index b7c3ee00b..91fcd15a1 100644
+--- a/src/java.desktop/share/native/libfreetype/src/psaux/psconv.h
++++ b/src/java.desktop/share/native/libfreetype/src/psaux/psconv.h
+@@ -4,7 +4,7 @@
+  *
+  *   Some convenience conversions (specification).
+  *
+- * Copyright (C) 2006-2023 by
++ * Copyright (C) 2006-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/psft.c b/src/java.desktop/share/native/libfreetype/src/psaux/psft.c
+index 618864e6e..fd0abe171 100644
+--- a/src/java.desktop/share/native/libfreetype/src/psaux/psft.c
++++ b/src/java.desktop/share/native/libfreetype/src/psaux/psft.c
+@@ -566,12 +566,12 @@
+   FT_LOCAL_DEF( void )
+   cf2_getBlueValues( PS_Decoder*  decoder,
+                      size_t*      count,
+-                     FT_Pos*     *data )
++                     FT_Fixed*   *data )
+   {
+     FT_ASSERT( decoder && decoder->current_subfont );
+ 
+     *count = decoder->current_subfont->private_dict.num_blue_values;
+-    *data  = (FT_Pos*)
++    *data  = (FT_Fixed*)
+                &decoder->current_subfont->private_dict.blue_values;
+   }
+ 
+@@ -579,12 +579,12 @@
+   FT_LOCAL_DEF( void )
+   cf2_getOtherBlues( PS_Decoder*  decoder,
+                      size_t*      count,
+-                     FT_Pos*     *data )
++                     FT_Fixed*   *data )
+   {
+     FT_ASSERT( decoder && decoder->current_subfont );
+ 
+     *count = decoder->current_subfont->private_dict.num_other_blues;
+-    *data  = (FT_Pos*)
++    *data  = (FT_Fixed*)
+                &decoder->current_subfont->private_dict.other_blues;
+   }
+ 
+@@ -592,12 +592,12 @@
+   FT_LOCAL_DEF( void )
+   cf2_getFamilyBlues( PS_Decoder*  decoder,
+                       size_t*      count,
+-                      FT_Pos*     *data )
++                      FT_Fixed*   *data )
+   {
+     FT_ASSERT( decoder && decoder->current_subfont );
+ 
+     *count = decoder->current_subfont->private_dict.num_family_blues;
+-    *data  = (FT_Pos*)
++    *data  = (FT_Fixed*)
+                &decoder->current_subfont->private_dict.family_blues;
+   }
+ 
+@@ -605,12 +605,12 @@
+   FT_LOCAL_DEF( void )
+   cf2_getFamilyOtherBlues( PS_Decoder*  decoder,
+                            size_t*      count,
+-                           FT_Pos*     *data )
++                           FT_Fixed*   *data )
+   {
+     FT_ASSERT( decoder && decoder->current_subfont );
+ 
+     *count = decoder->current_subfont->private_dict.num_family_other_blues;
+-    *data  = (FT_Pos*)
++    *data  = (FT_Fixed*)
+                &decoder->current_subfont->private_dict.family_other_blues;
+   }
+ 
+diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/psft.h b/src/java.desktop/share/native/libfreetype/src/psaux/psft.h
+index 3da454e60..d9082f3a2 100644
+--- a/src/java.desktop/share/native/libfreetype/src/psaux/psft.h
++++ b/src/java.desktop/share/native/libfreetype/src/psaux/psft.h
+@@ -92,19 +92,19 @@ FT_BEGIN_HEADER
+   FT_LOCAL( void )
+   cf2_getBlueValues( PS_Decoder*  decoder,
+                      size_t*      count,
+-                     FT_Pos*     *data );
++                     FT_Fixed*   *data );
+   FT_LOCAL( void )
+   cf2_getOtherBlues( PS_Decoder*  decoder,
+                      size_t*      count,
+-                     FT_Pos*     *data );
++                     FT_Fixed*   *data );
+   FT_LOCAL( void )
+   cf2_getFamilyBlues( PS_Decoder*  decoder,
+                       size_t*      count,
+-                      FT_Pos*     *data );
++                      FT_Fixed*   *data );
+   FT_LOCAL( void )
+   cf2_getFamilyOtherBlues( PS_Decoder*  decoder,
+                            size_t*      count,
+-                           FT_Pos*     *data );
++                           FT_Fixed*   *data );
+ 
+   FT_LOCAL( CF2_Int )
+   cf2_getLanguageGroup( PS_Decoder*  decoder );
+diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/psintrp.c b/src/java.desktop/share/native/libfreetype/src/psaux/psintrp.c
+index 6c640eebd..7572e225e 100644
+--- a/src/java.desktop/share/native/libfreetype/src/psaux/psintrp.c
++++ b/src/java.desktop/share/native/libfreetype/src/psaux/psintrp.c
+@@ -37,6 +37,7 @@
+ 
+ 
+ #include "psft.h"
++#include 
+ #include 
+ #include 
+ 
+@@ -428,6 +429,8 @@
+     base  = cf2_stack_count( opStack ) - numOperands;
+     delta = base + numBlends;
+ 
++    FT_TRACE6(( " (" ));
 +
-+package sun.jvm.hotspot.debugger.mips64;
+     for ( i = 0; i < numBlends; i++ )
+     {
+       const CF2_Fixed*  weight = &blend->BV[1];
+@@ -442,10 +445,14 @@
+                                     cf2_stack_getReal( opStack,
+                                                        delta++ ) ) );
+ 
++      FT_TRACE6(( "%f ", (double)sum / 65536 ));
 +
-+import java.lang.annotation.Native;
+       /* store blended result  */
+       cf2_stack_setReal( opStack, i + base, sum );
+     }
+ 
++    FT_TRACE6(( "blended)\n" ));
 +
-+import sun.jvm.hotspot.debugger.*;
-+import sun.jvm.hotspot.debugger.cdbg.*;
+     /* leave only `numBlends' results on stack */
+     cf2_stack_pop( opStack, numOperands - numBlends );
+   }
+@@ -734,7 +741,7 @@
+           FT_UInt  numBlends;
+ 
+ 
+-          FT_TRACE4(( " blend\n" ));
++          FT_TRACE4(( " blend" ));
+ 
+           if ( !font->isCFF2 )
+             break;    /* clear stack & ignore */
+@@ -2275,23 +2282,7 @@
+ 
+                     arg = cf2_stack_popFixed( opStack );
+                     if ( arg > 0 )
+-                    {
+-                      /* use a start value that doesn't make */
+-                      /* the algorithm's addition overflow   */
+-                      FT_Fixed  root = arg < 10 ? arg : arg >> 1;
+-                      FT_Fixed  new_root;
+-
+-
+-                      /* Babylonian method */
+-                      for (;;)
+-                      {
+-                        new_root = ( root + FT_DivFix( arg, root ) + 1 ) >> 1;
+-                        if ( new_root == root )
+-                          break;
+-                        root = new_root;
+-                      }
+-                      arg = new_root;
+-                    }
++                      arg = (CF2_F16Dot16)FT_SqrtFixed( (FT_UInt32)arg );
+                     else
+                       arg = 0;
+ 
+diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/psobjs.c b/src/java.desktop/share/native/libfreetype/src/psaux/psobjs.c
+index 8da755d0e..eca465f00 100644
+--- a/src/java.desktop/share/native/libfreetype/src/psaux/psobjs.c
++++ b/src/java.desktop/share/native/libfreetype/src/psaux/psobjs.c
+@@ -4,7 +4,7 @@
+  *
+  *   Auxiliary functions for PostScript fonts (body).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+@@ -23,6 +23,7 @@
+ 
+ #include "psobjs.h"
+ #include "psconv.h"
++#include "psft.h"
+ 
+ #include "psauxerr.h"
+ #include "psauxmod.h"
+@@ -200,7 +201,9 @@
+     /* add the object to the base block and adjust offset */
+     table->elements[idx] = FT_OFFSET( table->block, table->cursor );
+     table->lengths [idx] = length;
+-    FT_MEM_COPY( table->block + table->cursor, object, length );
++    /* length == 0 also implies a NULL destination, so skip the copy call */
++    if ( length > 0 )
++      FT_MEM_COPY( table->block + table->cursor, object, length );
+ 
+     table->cursor += length;
+     return FT_Err_Ok;
+@@ -1624,7 +1627,7 @@
+     if ( builder->load_points )
+     {
+       FT_Vector*  point   = outline->points + outline->n_points;
+-      FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points;
++      FT_Byte*    control = outline->tags   + outline->n_points;
+ 
+ 
+       point->x = FIXED_TO_INT( x );
+@@ -1677,8 +1680,7 @@
+     if ( !error )
+     {
+       if ( outline->n_contours > 0 )
+-        outline->contours[outline->n_contours - 1] =
+-          (short)( outline->n_points - 1 );
++        outline->contours[outline->n_contours - 1] = outline->n_points - 1;
+ 
+       outline->n_contours++;
+     }
+@@ -1740,7 +1742,7 @@
+     {
+       FT_Vector*  p1      = outline->points + first;
+       FT_Vector*  p2      = outline->points + outline->n_points - 1;
+-      FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points - 1;
++      FT_Byte*    control = outline->tags   + outline->n_points - 1;
+ 
+ 
+       /* `delete' last point only if it coincides with the first */
+@@ -1760,8 +1762,7 @@
+         outline->n_points--;
+       }
+       else
+-        outline->contours[outline->n_contours - 1] =
+-          (short)( outline->n_points - 1 );
++        outline->contours[outline->n_contours - 1] = outline->n_points - 1;
+     }
+   }
+ 
+@@ -1899,7 +1900,7 @@
+     if ( builder->load_points )
+     {
+       FT_Vector*  point   = outline->points + outline->n_points;
+-      FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points;
++      FT_Byte*    control = outline->tags   + outline->n_points;
+ 
+ #ifdef CFF_CONFIG_OPTION_OLD_ENGINE
+       PS_Driver  driver   = (PS_Driver)FT_FACE_DRIVER( builder->face );
+@@ -1959,8 +1960,7 @@
+     if ( !error )
+     {
+       if ( outline->n_contours > 0 )
+-        outline->contours[outline->n_contours - 1] =
+-          (short)( outline->n_points - 1 );
++        outline->contours[outline->n_contours - 1] = outline->n_points - 1;
+ 
+       outline->n_contours++;
+     }
+@@ -2019,7 +2019,7 @@
+     {
+       FT_Vector*  p1      = outline->points + first;
+       FT_Vector*  p2      = outline->points + outline->n_points - 1;
+-      FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points - 1;
++      FT_Byte*    control = outline->tags   + outline->n_points - 1;
+ 
+ 
+       /* `delete' last point only if it coincides with the first    */
+@@ -2039,8 +2039,7 @@
+         outline->n_points--;
+       }
+       else
+-        outline->contours[outline->n_contours - 1] =
+-          (short)( outline->n_points - 1 );
++        outline->contours[outline->n_contours - 1] = outline->n_points - 1;
+     }
+   }
+ 
+@@ -2188,7 +2187,7 @@
+     if ( builder->load_points )
+     {
+       FT_Vector*  point   = outline->points + outline->n_points;
+-      FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points;
++      FT_Byte*    control = outline->tags   + outline->n_points;
+ 
+ #ifdef CFF_CONFIG_OPTION_OLD_ENGINE
+       PS_Driver  driver   = (PS_Driver)FT_FACE_DRIVER( builder->face );
+@@ -2267,8 +2266,7 @@
+     if ( !error )
+     {
+       if ( outline->n_contours > 0 )
+-        outline->contours[outline->n_contours - 1] =
+-          (short)( outline->n_points - 1 );
++        outline->contours[outline->n_contours - 1] = outline->n_points - 1;
+ 
+       outline->n_contours++;
+     }
+@@ -2327,7 +2325,7 @@
+     {
+       FT_Vector*  p1      = outline->points + first;
+       FT_Vector*  p2      = outline->points + outline->n_points - 1;
+-      FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points - 1;
++      FT_Byte*    control = outline->tags   + outline->n_points - 1;
+ 
+ 
+       /* `delete' last point only if it coincides with the first */
+@@ -2347,8 +2345,7 @@
+         outline->n_points--;
+       }
+       else
+-        outline->contours[outline->n_contours - 1] =
+-          (short)( outline->n_points - 1 );
++        outline->contours[outline->n_contours - 1] = outline->n_points - 1;
+     }
+   }
+ 
+@@ -2463,19 +2460,20 @@
+ 
+     count = cpriv->num_blue_values = priv->num_blue_values;
+     for ( n = 0; n < count; n++ )
+-      cpriv->blue_values[n] = (FT_Pos)priv->blue_values[n];
++      cpriv->blue_values[n] = cf2_intToFixed( priv->blue_values[n] );
+ 
+     count = cpriv->num_other_blues = priv->num_other_blues;
+     for ( n = 0; n < count; n++ )
+-      cpriv->other_blues[n] = (FT_Pos)priv->other_blues[n];
++      cpriv->other_blues[n] = cf2_intToFixed( priv->other_blues[n] );
+ 
+     count = cpriv->num_family_blues = priv->num_family_blues;
+     for ( n = 0; n < count; n++ )
+-      cpriv->family_blues[n] = (FT_Pos)priv->family_blues[n];
++      cpriv->family_blues[n] = cf2_intToFixed( priv->family_blues[n] );
+ 
+     count = cpriv->num_family_other_blues = priv->num_family_other_blues;
+     for ( n = 0; n < count; n++ )
+-      cpriv->family_other_blues[n] = (FT_Pos)priv->family_other_blues[n];
++      cpriv->family_other_blues[n] =
++        cf2_intToFixed( priv->family_other_blues[n] );
+ 
+     cpriv->blue_scale = priv->blue_scale;
+     cpriv->blue_shift = (FT_Pos)priv->blue_shift;
+diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/psobjs.h b/src/java.desktop/share/native/libfreetype/src/psaux/psobjs.h
+index d5bce5410..345fc8a73 100644
+--- a/src/java.desktop/share/native/libfreetype/src/psaux/psobjs.h
++++ b/src/java.desktop/share/native/libfreetype/src/psaux/psobjs.h
+@@ -4,7 +4,7 @@
+  *
+  *   Auxiliary functions for PostScript fonts (specification).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/t1cmap.c b/src/java.desktop/share/native/libfreetype/src/psaux/t1cmap.c
+index c4bcf599e..5681c3bd0 100644
+--- a/src/java.desktop/share/native/libfreetype/src/psaux/t1cmap.c
++++ b/src/java.desktop/share/native/libfreetype/src/psaux/t1cmap.c
+@@ -4,7 +4,7 @@
+  *
+  *   Type 1 character map support (body).
+  *
+- * Copyright (C) 2002-2023 by
++ * Copyright (C) 2002-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/t1cmap.h b/src/java.desktop/share/native/libfreetype/src/psaux/t1cmap.h
+index b3702498a..445e6a278 100644
+--- a/src/java.desktop/share/native/libfreetype/src/psaux/t1cmap.h
++++ b/src/java.desktop/share/native/libfreetype/src/psaux/t1cmap.h
+@@ -4,7 +4,7 @@
+  *
+  *   Type 1 character map support (specification).
+  *
+- * Copyright (C) 2002-2023 by
++ * Copyright (C) 2002-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/t1decode.c b/src/java.desktop/share/native/libfreetype/src/psaux/t1decode.c
+index 4b6b969bc..c74baa803 100644
+--- a/src/java.desktop/share/native/libfreetype/src/psaux/t1decode.c
++++ b/src/java.desktop/share/native/libfreetype/src/psaux/t1decode.c
+@@ -4,7 +4,7 @@
+  *
+  *   PostScript Type 1 decoding routines (body).
+  *
+- * Copyright (C) 2000-2023 by
++ * Copyright (C) 2000-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/t1decode.h b/src/java.desktop/share/native/libfreetype/src/psaux/t1decode.h
+index 0970def96..16203b8f7 100644
+--- a/src/java.desktop/share/native/libfreetype/src/psaux/t1decode.h
++++ b/src/java.desktop/share/native/libfreetype/src/psaux/t1decode.h
+@@ -4,7 +4,7 @@
+  *
+  *   PostScript Type 1 decoding routines (specification).
+  *
+- * Copyright (C) 2000-2023 by
++ * Copyright (C) 2000-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/pshinter/pshalgo.c b/src/java.desktop/share/native/libfreetype/src/pshinter/pshalgo.c
+index 4f622e1e4..967767b34 100644
+--- a/src/java.desktop/share/native/libfreetype/src/pshinter/pshalgo.c
++++ b/src/java.desktop/share/native/libfreetype/src/pshinter/pshalgo.c
+@@ -4,7 +4,7 @@
+  *
+  *   PostScript hinting algorithm (body).
+  *
+- * Copyright (C) 2001-2023 by
++ * Copyright (C) 2001-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used
+@@ -1118,7 +1118,7 @@
+     FT_UInt     n;
+     PSH_Point   point = glyph->points;
+     FT_Vector*  vec   = glyph->outline->points;
+-    char*       tags  = glyph->outline->tags;
++    FT_Byte*    tags  = glyph->outline->tags;
+ 
+ 
+     for ( n = 0; n < glyph->num_points; n++ )
+@@ -1171,8 +1171,8 @@
+          FT_QNEW_ARRAY( glyph->contours, outline->n_contours ) )
+       goto Exit;
+ 
+-    glyph->num_points   = (FT_UInt)outline->n_points;
+-    glyph->num_contours = (FT_UInt)outline->n_contours;
++    glyph->num_points   = outline->n_points;
++    glyph->num_contours = outline->n_contours;
+ 
+     {
+       FT_UInt      first = 0, next, n;
+@@ -1186,7 +1186,7 @@
+         PSH_Point  point;
+ 
+ 
+-        next  = (FT_UInt)outline->contours[n] + 1;
++        next  = outline->contours[n] + 1;
+         count = next - first;
+ 
+         contour->start = points + first;
+diff --git a/src/java.desktop/share/native/libfreetype/src/pshinter/pshalgo.h b/src/java.desktop/share/native/libfreetype/src/pshinter/pshalgo.h
+index 3f0ba28a6..fb362f061 100644
+--- a/src/java.desktop/share/native/libfreetype/src/pshinter/pshalgo.h
++++ b/src/java.desktop/share/native/libfreetype/src/pshinter/pshalgo.h
+@@ -4,7 +4,7 @@
+  *
+  *   PostScript hinting algorithm (specification).
+  *
+- * Copyright (C) 2001-2023 by
++ * Copyright (C) 2001-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/pshinter/pshglob.c b/src/java.desktop/share/native/libfreetype/src/pshinter/pshglob.c
+index d4c5eb32b..435f45838 100644
+--- a/src/java.desktop/share/native/libfreetype/src/pshinter/pshglob.c
++++ b/src/java.desktop/share/native/libfreetype/src/pshinter/pshglob.c
+@@ -5,7 +5,7 @@
+  *   PostScript hinter global hinting management (body).
+  *   Inspired by the new auto-hinter module.
+  *
+- * Copyright (C) 2001-2023 by
++ * Copyright (C) 2001-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used
+diff --git a/src/java.desktop/share/native/libfreetype/src/pshinter/pshglob.h b/src/java.desktop/share/native/libfreetype/src/pshinter/pshglob.h
+index 579eb2148..c5a5c9131 100644
+--- a/src/java.desktop/share/native/libfreetype/src/pshinter/pshglob.h
++++ b/src/java.desktop/share/native/libfreetype/src/pshinter/pshglob.h
+@@ -4,7 +4,7 @@
+  *
+  *   PostScript hinter global hinting management.
+  *
+- * Copyright (C) 2001-2023 by
++ * Copyright (C) 2001-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/pshinter/pshmod.c b/src/java.desktop/share/native/libfreetype/src/pshinter/pshmod.c
+index 974a99e01..9965d5b16 100644
+--- a/src/java.desktop/share/native/libfreetype/src/pshinter/pshmod.c
++++ b/src/java.desktop/share/native/libfreetype/src/pshinter/pshmod.c
+@@ -4,7 +4,7 @@
+  *
+  *   FreeType PostScript hinter module implementation (body).
+  *
+- * Copyright (C) 2001-2023 by
++ * Copyright (C) 2001-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/pshinter/pshmod.h b/src/java.desktop/share/native/libfreetype/src/pshinter/pshmod.h
+index 4bd781a35..62ac0a60f 100644
+--- a/src/java.desktop/share/native/libfreetype/src/pshinter/pshmod.h
++++ b/src/java.desktop/share/native/libfreetype/src/pshinter/pshmod.h
+@@ -4,7 +4,7 @@
+  *
+  *   PostScript hinter module interface (specification).
+  *
+- * Copyright (C) 2001-2023 by
++ * Copyright (C) 2001-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/pshinter/pshnterr.h b/src/java.desktop/share/native/libfreetype/src/pshinter/pshnterr.h
+index 97624952d..e9641340e 100644
+--- a/src/java.desktop/share/native/libfreetype/src/pshinter/pshnterr.h
++++ b/src/java.desktop/share/native/libfreetype/src/pshinter/pshnterr.h
+@@ -4,7 +4,7 @@
+  *
+  *   PS Hinter error codes (specification only).
+  *
+- * Copyright (C) 2003-2023 by
++ * Copyright (C) 2003-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/pshinter/pshrec.c b/src/java.desktop/share/native/libfreetype/src/pshinter/pshrec.c
+index 680e6d013..0b2b549fc 100644
+--- a/src/java.desktop/share/native/libfreetype/src/pshinter/pshrec.c
++++ b/src/java.desktop/share/native/libfreetype/src/pshinter/pshrec.c
+@@ -4,7 +4,7 @@
+  *
+  *   FreeType PostScript hints recorder (body).
+  *
+- * Copyright (C) 2001-2023 by
++ * Copyright (C) 2001-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+@@ -806,7 +806,7 @@
+   ps_hints_stem( PS_Hints  hints,
+                  FT_UInt   dimension,
+                  FT_Int    count,
+-                 FT_Long*  stems )
++                 FT_Pos*   stems )
+   {
+     PS_Dimension  dim;
+ 
+diff --git a/src/java.desktop/share/native/libfreetype/src/pshinter/pshrec.h b/src/java.desktop/share/native/libfreetype/src/pshinter/pshrec.h
+index 0b2484af1..7e375af7b 100644
+--- a/src/java.desktop/share/native/libfreetype/src/pshinter/pshrec.h
++++ b/src/java.desktop/share/native/libfreetype/src/pshinter/pshrec.h
+@@ -4,7 +4,7 @@
+  *
+  *   Postscript (Type1/Type2) hints recorder (specification).
+  *
+- * Copyright (C) 2001-2023 by
++ * Copyright (C) 2001-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/psnames/psmodule.c b/src/java.desktop/share/native/libfreetype/src/psnames/psmodule.c
+index 8203a0465..35d054d1c 100644
+--- a/src/java.desktop/share/native/libfreetype/src/psnames/psmodule.c
++++ b/src/java.desktop/share/native/libfreetype/src/psnames/psmodule.c
+@@ -4,7 +4,7 @@
+  *
+  *   psnames module implementation (body).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/psnames/psmodule.h b/src/java.desktop/share/native/libfreetype/src/psnames/psmodule.h
+index 0904700bf..770458316 100644
+--- a/src/java.desktop/share/native/libfreetype/src/psnames/psmodule.h
++++ b/src/java.desktop/share/native/libfreetype/src/psnames/psmodule.h
+@@ -4,7 +4,7 @@
+  *
+  *   High-level psnames module interface (specification).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/psnames/psnamerr.h b/src/java.desktop/share/native/libfreetype/src/psnames/psnamerr.h
+index 0073f8228..e123eb65e 100644
+--- a/src/java.desktop/share/native/libfreetype/src/psnames/psnamerr.h
++++ b/src/java.desktop/share/native/libfreetype/src/psnames/psnamerr.h
+@@ -4,7 +4,7 @@
+  *
+  *   PS names module error codes (specification only).
+  *
+- * Copyright (C) 2001-2023 by
++ * Copyright (C) 2001-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/psnames/pstables.h b/src/java.desktop/share/native/libfreetype/src/psnames/pstables.h
+index 7f92cce60..2a941b046 100644
+--- a/src/java.desktop/share/native/libfreetype/src/psnames/pstables.h
++++ b/src/java.desktop/share/native/libfreetype/src/psnames/pstables.h
+@@ -4,7 +4,7 @@
+  *
+  *   PostScript glyph names.
+  *
+- * Copyright (C) 2005-2023 by
++ * Copyright (C) 2005-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/raster/ftmisc.h b/src/java.desktop/share/native/libfreetype/src/raster/ftmisc.h
+index 33dbfd631..943f2aa0a 100644
+--- a/src/java.desktop/share/native/libfreetype/src/raster/ftmisc.h
++++ b/src/java.desktop/share/native/libfreetype/src/raster/ftmisc.h
+@@ -5,7 +5,7 @@
+  *   Miscellaneous macros for stand-alone rasterizer (specification
+  *   only).
+  *
+- * Copyright (C) 2005-2023 by
++ * Copyright (C) 2005-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used
+@@ -92,27 +92,6 @@
+ #endif
+ 
+ 
+-  static FT_Long
+-  FT_MulDiv( FT_Long  a,
+-             FT_Long  b,
+-             FT_Long  c )
+-  {
+-    FT_Int   s;
+-    FT_Long  d;
+-
+-
+-    s = 1;
+-    if ( a < 0 ) { a = -a; s = -1; }
+-    if ( b < 0 ) { b = -b; s = -s; }
+-    if ( c < 0 ) { c = -c; s = -s; }
+-
+-    d = (FT_Long)( c > 0 ? ( (FT_Int64)a * b + ( c >> 1 ) ) / c
+-                         : 0x7FFFFFFFL );
+-
+-    return ( s > 0 ) ? d : -d;
+-  }
+-
+-
+   static FT_Long
+   FT_MulDiv_No_Round( FT_Long  a,
+                       FT_Long  b,
+diff --git a/src/java.desktop/share/native/libfreetype/src/raster/ftraster.c b/src/java.desktop/share/native/libfreetype/src/raster/ftraster.c
+index 192ca0701..e4b7b937d 100644
+--- a/src/java.desktop/share/native/libfreetype/src/raster/ftraster.c
++++ b/src/java.desktop/share/native/libfreetype/src/raster/ftraster.c
+@@ -4,7 +4,7 @@
+  *
+  *   The FreeType glyph rasterizer (body).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+@@ -63,8 +63,7 @@
+ #else /* !STANDALONE_ */
+ 
+ #include "ftraster.h"
+-#include  /* for FT_MulDiv and FT_MulDiv_No_Round */
+-#include          /* for FT_Outline_Get_CBox              */
++#include  /* for FT_MulDiv_No_Round */
+ 
+ #endif /* !STANDALONE_ */
+ 
+@@ -115,12 +114,12 @@
+    *   a change of direction is detected in the outline, a new profile is
+    *   generated until the end of the outline.
+    *
+-   *   Note that when all profiles have been generated, the function
+-   *   Finalize_Profile_Table() is used to record, for each profile, its
+-   *   bottom-most scanline as well as the scanline above its upmost
+-   *   boundary.  These positions are called `y-turns' because they (sort
+-   *   of) correspond to local extrema.  They are stored in a sorted list
+-   *   built from the top of the render pool as a downwards stack:
++   *   Note that, for all generated profiles, the function End_Profile()
++   *   is used to record all their bottom-most scanlines as well as the
++   *   scanline above their upmost boundary.  These positions are called
++   *   `y-turns' because they (sort of) correspond to local extrema.
++   *   They are stored in a sorted list built from the top of the render
++   *   pool as a downwards stack:
+    *
+    *     _ _ _______________________________________
+    *                           |                    |
+@@ -136,7 +135,7 @@
+    *   optimize performance (see technical note on the sweep below).
+    *
+    *   Of course, the raster detects whether the two stacks collide and
+-   *   handles the situation properly.
++   *   handles the situation by bisecting the job and restarting.
+    *
+    */
+ 
+@@ -252,7 +251,6 @@
+   /* On the other hand, SMulDiv means `Slow MulDiv', and is used typically */
+   /* for clipping computations.  It simply uses the FT_MulDiv() function   */
+   /* defined in `ftcalc.h'.                                                */
+-#define SMulDiv           FT_MulDiv
+ #define SMulDiv_No_Round  FT_MulDiv_No_Round
+ 
+   /* The rasterizer is a very general purpose component; please leave */
+@@ -305,16 +303,6 @@
+   typedef unsigned char   Byte, *PByte;
+   typedef char            Bool;
+ 
+-
+-  typedef union  Alignment_
+-  {
+-    Long    l;
+-    void*   p;
+-    void  (*f)(void);
+-
+-  } Alignment, *PAlignment;
+-
+-
+   typedef struct  TPoint_
+   {
+     Long  x;
+@@ -327,6 +315,7 @@
+ #define Flow_Up           0x08U
+ #define Overshoot_Top     0x10U
+ #define Overshoot_Bottom  0x20U
++#define Dropout           0x40U
+ 
+ 
+   /* States of each line, arc, and profile */
+@@ -345,31 +334,28 @@
+ 
+   struct  TProfile_
+   {
+-    FT_F26Dot6  X;           /* current coordinate during sweep          */
+     PProfile    link;        /* link to next profile (various purposes)  */
+-    PLong       offset;      /* start of profile's data in render pool   */
++    PProfile    next;        /* next profile in same contour, used       */
++                             /* during drop-out control                  */
++    Int         offset;      /* bottom or currently scanned array index  */
++    Int         height;      /* profile's height in scanlines            */
++    Int         start;       /* profile's starting scanline, also use    */
++                             /* as activation counter                    */
+     UShort      flags;       /* Bit 0-2: drop-out mode                   */
+                              /* Bit 3: profile orientation (up/down)     */
+                              /* Bit 4: is top profile?                   */
+                              /* Bit 5: is bottom profile?                */
+-    Long        height;      /* profile's height in scanlines            */
+-    Long        start;       /* profile's starting scanline              */
++                             /* Bit 6: dropout detected                  */
+ 
+-    Int         countL;      /* number of lines to step before this      */
+-                             /* profile becomes drawable                 */
+-
+-    PProfile    next;        /* next profile in same contour, used       */
+-                             /* during drop-out control                  */
++    FT_F26Dot6  X;           /* current coordinate during sweep          */
++    Long        x[1];        /* actually variable array of scanline      */
++                             /* intersections with `height` elements     */
+   };
+ 
+   typedef PProfile   TProfileList;
+   typedef PProfile*  PProfileList;
+ 
+ 
+-#define AlignProfileSize \
+-  ( ( sizeof ( TProfile ) + sizeof ( Alignment ) - 1 ) / sizeof ( Long ) )
+-
+-
+ #undef RAS_ARG
+ #undef RAS_ARGS
+ #undef RAS_VAR
+@@ -407,15 +393,13 @@
+ 
+   /* prototypes used for sweep function dispatch */
+   typedef void
+-  Function_Sweep_Init( RAS_ARGS Short  min,
+-                                Short  max );
++  Function_Sweep_Init( RAS_ARGS Int  min,
++                                Int  max );
+ 
+   typedef void
+-  Function_Sweep_Span( RAS_ARGS Short       y,
++  Function_Sweep_Span( RAS_ARGS Int         y,
+                                 FT_F26Dot6  x1,
+-                                FT_F26Dot6  x2,
+-                                PProfile    left,
+-                                PProfile    right );
++                                FT_F26Dot6  x2 );
+ 
+   typedef void
+   Function_Sweep_Step( RAS_ARG );
+@@ -441,8 +425,7 @@
+           (Bool)( x - FLOOR( x ) >= ras.precision_half )
+ 
+   /* Smart dropout rounding to find which pixel is closer to span ends. */
+-  /* To mimick Windows, symmetric cases break down indepenently of the  */
+-  /* precision.                                                         */
++  /* To mimic Windows, symmetric cases do not depend on the precision.  */
+ #define SMART( p, q )  FLOOR( ( (p) + (q) + ras.precision * 63 / 64 ) >> 1 )
+ 
+ #if FT_RENDER_POOL_SIZE > 2048
+@@ -462,7 +445,6 @@
+     Int         precision_half;
+     Int         precision_scale;
+     Int         precision_step;
+-    Int         precision_jitter;
+ 
+     PLong       buff;               /* The profiles buffer                 */
+     PLong       sizeBuff;           /* Render pool size                    */
+@@ -471,24 +453,14 @@
+ 
+     FT_Error    error;
+ 
+-    Int         numTurns;           /* number of Y-turns in outline        */
+-
+     Byte        dropOutControl;     /* current drop_out control method     */
+ 
+-    UShort      bWidth;             /* target bitmap width                 */
+-    PByte       bOrigin;            /* target bitmap bottom-left origin    */
+-    PByte       bLine;              /* target bitmap current line          */
+-
+     Long        lastX, lastY;
+     Long        minY, maxY;
+ 
+     UShort      num_Profs;          /* current number of profiles          */
++    Int         numTurns;           /* number of Y-turns in outline        */
+ 
+-    Bool        fresh;              /* signals a fresh new profile which   */
+-                                    /* `start' field must be completed     */
+-    Bool        joint;              /* signals that the last arc ended     */
+-                                    /* exactly on a scanline.  Allows      */
+-                                    /* removal of doublets                 */
+     PProfile    cProfile;           /* current profile                     */
+     PProfile    fProfile;           /* head of linked list of profiles     */
+     PProfile    gProfile;           /* contour's first profile in case     */
+@@ -496,9 +468,14 @@
+ 
+     TStates     state;              /* rendering state                     */
+ 
+-    FT_Bitmap   target;             /* description of target bit/pixmap    */
+     FT_Outline  outline;
+ 
++    Int         bTop;               /* target bitmap max line  index       */
++    Int         bRight;             /* target bitmap rightmost index       */
++    Int         bPitch;             /* target bitmap pitch                 */
++    PByte       bOrigin;            /* target bitmap bottom-left origin    */
++    PByte       bLine;              /* target bitmap current line          */
 +
-+/** Specifies the thread context on mips64 platforms; only a sub-portion
-+    of the context is guaranteed to be present on all operating
-+    systems. */
+     /* dispatch variables */
+ 
+     Function_Sweep_Init*  Proc_Sweep_Init;
+@@ -563,37 +540,82 @@
+      *
+      *   256 / (1 << 12) = 0.0625 pixels.
+      *
+-     * `precision_jitter' is an epsilon threshold used in
+-     * `Vertical_Sweep_Span' to deal with small imperfections in the Bezier
+-     * decomposition (after all, we are working with approximations only);
+-     * it avoids switching on additional pixels which would cause artifacts
+-     * otherwise.
+-     *
+-     * The value of `precision_jitter' has been determined heuristically.
+-     *
+      */
+ 
+     if ( High )
+     {
+       ras.precision_bits   = 12;
+       ras.precision_step   = 256;
+-      ras.precision_jitter = 30;
+     }
+     else
+     {
+       ras.precision_bits   = 6;
+       ras.precision_step   = 32;
+-      ras.precision_jitter = 2;
+     }
+ 
+-    FT_TRACE6(( "Set_High_Precision(%s)\n", High ? "true" : "false" ));
+-
+     ras.precision       = 1 << ras.precision_bits;
+     ras.precision_half  = ras.precision >> 1;
+     ras.precision_scale = ras.precision >> Pixel_Bits;
+   }
+ 
+ 
++  /**************************************************************************
++   *
++   * @Function:
++   *   Insert_Y_Turn
++   *
++   * @Description:
++   *   Insert a salient into the sorted list placed on top of the render
++   *   pool.
++   *
++   * @Input:
++   *   New y scanline position.
++   *
++   * @Return:
++   *   SUCCESS on success.  FAILURE in case of overflow.
++   */
++  static Bool
++  Insert_Y_Turns( RAS_ARGS Int  y,
++                           Int  top )
++  {
++    Int    n       = ras.numTurns;
++    PLong  y_turns = ras.maxBuff;
 +
-+public abstract class MIPS64ThreadContext implements ThreadContext {
 +
-+  // NOTE: the indices for the various registers must be maintained as
-+  // listed across various operating systems. However, only a small
-+  // subset of the registers' values are guaranteed to be present (and
-+  // must be present for the SA's stack walking to work): EAX, EBX,
-+  // ECX, EDX, ESI, EDI, EBP, ESP, and EIP.
++    /* update top value */
++    if ( n == 0 || top > y_turns[n] )
++      y_turns[n] = top;
 +
-+  // One instance of the Native annotation is enough to trigger header generation
-+  // for this file.
-+  @Native
-+  public static final int ZERO = 0;
-+  public static final int AT = 1;
-+  public static final int V0 = 2;
-+  public static final int V1 = 3;
-+  public static final int A0 = 4;
-+  public static final int A1 = 5;
-+  public static final int A2 = 6;
-+  public static final int A3 = 7;
-+  public static final int T0 = 8;
-+  public static final int T1 = 9;
-+  public static final int T2 = 10;
-+  public static final int T3 = 11;
-+  public static final int T4 = 12;
-+  public static final int T5 = 13;
-+  public static final int T6 = 14;
-+  public static final int T7 = 15;
-+  public static final int S0 = 16;
-+  public static final int S1 = 17;
-+  public static final int S2 = 18;
-+  public static final int S3 = 19;
-+  public static final int S4 = 20;
-+  public static final int S5 = 21;
-+  public static final int S6 = 22;
-+  public static final int S7 = 23;
-+  public static final int T8 = 24;
-+  public static final int T9 = 25;
-+  public static final int K0 = 26;
-+  public static final int K1 = 27;
-+  public static final int GP = 28;
-+  public static final int SP = 29;
-+  public static final int FP = 30;
-+  public static final int RA = 31;
-+  public static final int PC = 32;
-+  public static final int NPRGREG = 33;
++    /* look for first y value that is <= */
++    while ( n-- && y < y_turns[n] )
++      ;
 +
-+  private static final String[] regNames = {
-+    "ZERO",    "AT",    "V0",    "V1",
-+    "A0",      "A1",    "A2",    "A3",
-+    "T0",      "T1",    "T2",    "T3",
-+    "T4",      "T5",    "T6",    "T7",
-+    "S0",      "S1",    "S2",    "S3",
-+    "S4",      "S5",    "S6",    "S7",
-+    "T8",      "T9",    "K0",    "K1",
-+    "GP",      "SP",    "FP",    "RA",
-+    "PC"
-+  };
++    /* if it is <, simply insert it, ignore if == */
++    if ( n < 0 || y > y_turns[n] )
++    {
++      ras.maxBuff--;
++      if ( ras.maxBuff <= ras.top )
++      {
++        ras.error = FT_THROW( Raster_Overflow );
++        return FAILURE;
++      }
 +
-+  private long[] data;
++      do
++      {
++        Int  y2 = (Int)y_turns[n];
 +
-+  public MIPS64ThreadContext() {
-+    data = new long[NPRGREG];
-+  }
 +
-+  public int getNumRegisters() {
-+    return NPRGREG;
-+  }
++        y_turns[n] = y;
++        y = y2;
++      } while ( n-- >= 0 );
 +
-+  public String getRegisterName(int index) {
-+    return regNames[index];
-+  }
++      ras.numTurns++;
++    }
 +
-+  public void setRegister(int index, long value) {
-+    data[index] = value;
++    return SUCCESS;
 +  }
 +
-+  public long getRegister(int index) {
-+    return data[index];
-+  }
 +
-+  public CFrame getTopFrame(Debugger dbg) {
-+    return null;
-+  }
+   /**************************************************************************
+    *
+    * @Function:
+@@ -606,52 +628,48 @@
+    *   aState ::
+    *     The state/orientation of the new profile.
+    *
+-   *   overshoot ::
+-   *     Whether the profile's unrounded start position
+-   *     differs by at least a half pixel.
+-   *
+    * @Return:
+    *  SUCCESS on success.  FAILURE in case of overflow or of incoherent
+    *  profile.
+    */
+   static Bool
+-  New_Profile( RAS_ARGS TStates  aState,
+-                        Bool     overshoot )
++  New_Profile( RAS_ARGS TStates  aState )
+   {
+-    if ( !ras.fProfile )
++    Long  e;
 +
-+  /** This can't be implemented in this class since we would have to
-+      tie the implementation to, for example, the debugging system */
-+  public abstract void setRegisterAsAddress(int index, Address value);
 +
-+  /** This can't be implemented in this class since we would have to
-+      tie the implementation to, for example, the debugging system */
-+  public abstract Address getRegisterAsAddress(int index);
-+}
-diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/posix/elf/ELFHeader.java jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/posix/elf/ELFHeader.java
---- openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/posix/elf/ELFHeader.java	2022-10-12 23:00:03.000000000 +0800
-+++ jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/posix/elf/ELFHeader.java	2023-09-12 13:54:26.373575786 +0800
-@@ -22,6 +22,12 @@
-  *
-  */
++    if ( !ras.cProfile || ras.cProfile->height )
+     {
+       ras.cProfile  = (PProfile)ras.top;
+-      ras.fProfile  = ras.cProfile;
+-      ras.top      += AlignProfileSize;
+-    }
++      ras.top       = ras.cProfile->x;
  
-+/*
-+ * This file has been modified by Loongson Technology in 2021, These
-+ * modifications are Copyright (c) 2019, 2021, Loongson Technology, and are made
-+ * available on the same license terms set forth above.
-+ */
+-    if ( ras.top >= ras.maxBuff )
+-    {
+-      ras.error = FT_THROW( Raster_Overflow );
+-      return FAILURE;
++      if ( ras.top >= ras.maxBuff )
++      {
++        FT_TRACE1(( "overflow in New_Profile\n" ));
++        ras.error = FT_THROW( Raster_Overflow );
++        return FAILURE;
++      }
 +
- package sun.jvm.hotspot.debugger.posix.elf;
++      ras.cProfile->height = 0;
+     }
  
- import java.io.FileInputStream;
-@@ -63,6 +69,8 @@
-     public static final int ARCH_i860 = 7;
-     /** MIPS architecture type. */
-     public static final int ARCH_MIPS = 8;
-+    /** LOONGARCH architecture type. */
-+    public static final int ARCH_LOONGARCH = 9;
+-    ras.cProfile->start  = 0;
+-    ras.cProfile->height = 0;
+-    ras.cProfile->offset = ras.top;
+-    ras.cProfile->link   = (PProfile)0;
+-    ras.cProfile->next   = (PProfile)0;
+     ras.cProfile->flags  = ras.dropOutControl;
  
-     /** Returns a file type which is defined by the file type constants. */
-     public short getFileType();
-diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/loongarch64/ProcLOONGARCH64ThreadContext.java jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/loongarch64/ProcLOONGARCH64ThreadContext.java
---- openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/loongarch64/ProcLOONGARCH64ThreadContext.java	1970-01-01 08:00:00.000000000 +0800
-+++ jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/loongarch64/ProcLOONGARCH64ThreadContext.java	2023-09-12 13:54:26.377575791 +0800
-@@ -0,0 +1,47 @@
-+/*
-+ * Copyright (c) 2002, 2003, Oracle and/or its affiliates. All rights reserved.
-+ * Copyright (c) 2015, 2021, Loongson Technology. 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 sun.jvm.hotspot.debugger.proc.loongarch64;
-+
-+import sun.jvm.hotspot.debugger.*;
-+import sun.jvm.hotspot.debugger.loongarch64.*;
-+import sun.jvm.hotspot.debugger.proc.*;
-+
-+public class ProcLOONGARCH64ThreadContext extends LOONGARCH64ThreadContext {
-+  private ProcDebugger debugger;
+     switch ( aState )
+     {
+     case Ascending_State:
+       ras.cProfile->flags |= Flow_Up;
+-      if ( overshoot )
++      if ( IS_BOTTOM_OVERSHOOT( ras.lastY ) )
+         ras.cProfile->flags |= Overshoot_Bottom;
+ 
+-      FT_TRACE6(( "  new ascending profile = %p\n", (void *)ras.cProfile ));
++      e = CEILING( ras.lastY );
+       break;
+ 
+     case Descending_State:
+-      if ( overshoot )
++      if ( IS_TOP_OVERSHOOT( ras.lastY ) )
+         ras.cProfile->flags |= Overshoot_Top;
+-      FT_TRACE6(( "  new descending profile = %p\n", (void *)ras.cProfile ));
 +
-+  public ProcLOONGARCH64ThreadContext(ProcDebugger debugger) {
-+    super();
-+    this.debugger = debugger;
++      e = FLOOR( ras.lastY );
+       break;
+ 
+     default:
+@@ -660,12 +678,20 @@
+       return FAILURE;
+     }
+ 
+-    if ( !ras.gProfile )
+-      ras.gProfile = ras.cProfile;
++    if ( e > ras.maxY )
++      e = ras.maxY;
++    if ( e < ras.minY )
++      e = ras.minY;
++    ras.cProfile->start = (Int)TRUNC( e );
++
++    FT_TRACE7(( "  new %s profile = %p, start = %d\n",
++                aState == Ascending_State ? "ascending" : "descending",
++                (void *)ras.cProfile, ras.cProfile->start ));
++
++    if ( ras.lastY == e )
++      *ras.top++ = ras.lastX;
+ 
+     ras.state = aState;
+-    ras.fresh = TRUE;
+-    ras.joint = FALSE;
+ 
+     return SUCCESS;
+   }
+@@ -677,24 +703,19 @@
+    *   End_Profile
+    *
+    * @Description:
+-   *   Finalize the current profile.
+-   *
+-   * @Input:
+-   *   overshoot ::
+-   *     Whether the profile's unrounded end position differs
+-   *     by at least a half pixel.
++   *   Finalize the current profile and record y-turns.
+    *
+    * @Return:
+    *   SUCCESS on success.  FAILURE in case of overflow or incoherency.
+    */
+   static Bool
+-  End_Profile( RAS_ARGS Bool  overshoot )
++  End_Profile( RAS_ARG )
+   {
+-    Long  h;
++    PProfile  p = ras.cProfile;
++    Int       h = (Int)( ras.top - p->x );
++    Int       bottom, top;
+ 
+ 
+-    h = (Long)( ras.top - ras.cProfile->offset );
+-
+     if ( h < 0 )
+     {
+       FT_ERROR(( "End_Profile: negative height encountered\n" ));
+@@ -704,98 +725,46 @@
+ 
+     if ( h > 0 )
+     {
+-      PProfile  oldProfile;
++      FT_TRACE7(( "  ending profile %p, start = %2d, height = %+3d\n",
++                  (void *)p, p->start, p->flags & Flow_Up ? h : -h ));
+ 
++      p->height = h;
+ 
+-      FT_TRACE6(( "  ending profile %p, start = %ld, height = %ld\n",
+-                  (void *)ras.cProfile, ras.cProfile->start, h ));
++      if ( p->flags & Flow_Up )
++      {
++        if ( IS_TOP_OVERSHOOT( ras.lastY ) )
++          p->flags |= Overshoot_Top;
+ 
+-      ras.cProfile->height = h;
+-      if ( overshoot )
++        bottom    = p->start;
++        top       = bottom + h;
++        p->offset = 0;
++        p->X      = p->x[0];
++      }
++      else
+       {
+-        if ( ras.cProfile->flags & Flow_Up )
+-          ras.cProfile->flags |= Overshoot_Top;
+-        else
+-          ras.cProfile->flags |= Overshoot_Bottom;
++        if ( IS_BOTTOM_OVERSHOOT( ras.lastY ) )
++          p->flags |= Overshoot_Bottom;
++
++        top       = p->start + 1;
++        bottom    = top - h;
++        p->start  = bottom;
++        p->offset = h - 1;
++        p->X      = p->x[h - 1];
+       }
+ 
+-      oldProfile   = ras.cProfile;
+-      ras.cProfile = (PProfile)ras.top;
++      if ( Insert_Y_Turns( RAS_VARS bottom, top ) )
++        return FAILURE;
+ 
+-      ras.top += AlignProfileSize;
++      if ( !ras.gProfile )
++        ras.gProfile = p;
+ 
+-      ras.cProfile->height = 0;
+-      ras.cProfile->offset = ras.top;
++      /* preliminary values to be finalized */
++      p->next = ras.gProfile;
++      p->link = (PProfile)ras.top;
+ 
+-      oldProfile->next = ras.cProfile;
+       ras.num_Profs++;
+     }
+ 
+-    if ( ras.top >= ras.maxBuff )
+-    {
+-      FT_TRACE1(( "overflow in End_Profile\n" ));
+-      ras.error = FT_THROW( Raster_Overflow );
+-      return FAILURE;
+-    }
+-
+-    ras.joint = FALSE;
+-
+-    return SUCCESS;
+-  }
+-
+-
+-  /**************************************************************************
+-   *
+-   * @Function:
+-   *   Insert_Y_Turn
+-   *
+-   * @Description:
+-   *   Insert a salient into the sorted list placed on top of the render
+-   *   pool.
+-   *
+-   * @Input:
+-   *   New y scanline position.
+-   *
+-   * @Return:
+-   *   SUCCESS on success.  FAILURE in case of overflow.
+-   */
+-  static Bool
+-  Insert_Y_Turn( RAS_ARGS Int  y )
+-  {
+-    PLong  y_turns;
+-    Int    n;
+-
+-
+-    n       = ras.numTurns - 1;
+-    y_turns = ras.sizeBuff - ras.numTurns;
+-
+-    /* look for first y value that is <= */
+-    while ( n >= 0 && y < y_turns[n] )
+-      n--;
+-
+-    /* if it is <, simply insert it, ignore if == */
+-    if ( n >= 0 && y > y_turns[n] )
+-      do
+-      {
+-        Int  y2 = (Int)y_turns[n];
+-
+-
+-        y_turns[n] = y;
+-        y = y2;
+-      } while ( --n >= 0 );
+-
+-    if ( n < 0 )
+-    {
+-      ras.maxBuff--;
+-      if ( ras.maxBuff <= ras.top )
+-      {
+-        ras.error = FT_THROW( Raster_Overflow );
+-        return FAILURE;
+-      }
+-      ras.numTurns++;
+-      ras.sizeBuff[-ras.numTurns] = y;
+-    }
+-
+     return SUCCESS;
+   }
+ 
+@@ -807,56 +776,29 @@
+    *
+    * @Description:
+    *   Adjust all links in the profiles list.
+-   *
+-   * @Return:
+-   *   SUCCESS on success.  FAILURE in case of overflow.
+    */
+-  static Bool
++  static void
+   Finalize_Profile_Table( RAS_ARG )
+   {
+-    UShort    n;
+-    PProfile  p;
+-
++    UShort    n = ras.num_Profs;
++    PProfile  p = ras.fProfile;
++    PProfile  q;
+ 
+-    n = ras.num_Profs;
+-    p = ras.fProfile;
+ 
+-    if ( n > 1 && p )
++    /* there should be at least two profiles, up and down */
++    while ( --n )
+     {
+-      do
+-      {
+-        Int  bottom, top;
++      q = p->link;
+ 
++      /* fix the contour loop */
++      if ( q->next == p->next )
++        p->next = q;
+ 
+-        if ( n > 1 )
+-          p->link = (PProfile)( p->offset + p->height );
+-        else
+-          p->link = NULL;
+-
+-        if ( p->flags & Flow_Up )
+-        {
+-          bottom = (Int)p->start;
+-          top    = (Int)( p->start + p->height - 1 );
+-        }
+-        else
+-        {
+-          bottom     = (Int)( p->start - p->height + 1 );
+-          top        = (Int)p->start;
+-          p->start   = bottom;
+-          p->offset += p->height - 1;
+-        }
+-
+-        if ( Insert_Y_Turn( RAS_VARS bottom )  ||
+-             Insert_Y_Turn( RAS_VARS top + 1 ) )
+-          return FAILURE;
+-
+-        p = p->link;
+-      } while ( --n );
++      p = q;
+     }
+-    else
+-      ras.fProfile = NULL;
+ 
+-    return SUCCESS;
++    /* null-terminate */
++    p->link = NULL;
+   }
+ 
+ 
+@@ -986,107 +928,78 @@
+                     Long  miny,
+                     Long  maxy )
+   {
+-    Long   Dx, Dy;
+-    Int    e1, e2, f1, f2, size;     /* XXX: is `Short' sufficient? */
+-    Long   Ix, Rx, Ax;
++    Long  e, e2, Dx, Dy;
++    Long  Ix, Rx, Ax;
++    Int   size;
+ 
+     PLong  top;
+ 
+ 
+-    Dx = x2 - x1;
+-    Dy = y2 - y1;
+-
+-    if ( Dy <= 0 || y2 < miny || y1 > maxy )
++    if ( y2 < miny || y1 > maxy )
+       return SUCCESS;
+ 
+-    if ( y1 < miny )
+-    {
+-      /* Take care: miny-y1 can be a very large value; we use     */
+-      /*            a slow MulDiv function to avoid clipping bugs */
+-      x1 += SMulDiv( Dx, miny - y1, Dy );
+-      e1  = (Int)TRUNC( miny );
+-      f1  = 0;
+-    }
+-    else
+-    {
+-      e1 = (Int)TRUNC( y1 );
+-      f1 = (Int)FRAC( y1 );
+-    }
++    e2 = y2 > maxy ? maxy : FLOOR( y2 );
++    e  = y1 < miny ? miny : CEILING( y1 );
+ 
+-    if ( y2 > maxy )
+-    {
+-      /* x2 += FMulDiv( Dx, maxy - y2, Dy );  UNNECESSARY */
+-      e2  = (Int)TRUNC( maxy );
+-      f2  = 0;
+-    }
+-    else
+-    {
+-      e2 = (Int)TRUNC( y2 );
+-      f2 = (Int)FRAC( y2 );
+-    }
++    if ( y1 == e )
++      e += ras.precision;
+ 
+-    if ( f1 > 0 )
+-    {
+-      if ( e1 == e2 )
+-        return SUCCESS;
+-      else
+-      {
+-        x1 += SMulDiv( Dx, ras.precision - f1, Dy );
+-        e1 += 1;
+-      }
+-    }
+-    else
+-      if ( ras.joint )
+-      {
+-        ras.top--;
+-        ras.joint = FALSE;
+-      }
+-
+-    ras.joint = (char)( f2 == 0 );
++    if ( e2 < e )  /* nothing to do */
++      return SUCCESS;
+ 
+-    if ( ras.fresh )
+-    {
+-      ras.cProfile->start = e1;
+-      ras.fresh           = FALSE;
+-    }
++    size = (Int)TRUNC( e2 - e ) + 1;
++    top  = ras.top;
+ 
+-    size = e2 - e1 + 1;
+-    if ( ras.top + size >= ras.maxBuff )
++    if ( top + size >= ras.maxBuff )
+     {
+       ras.error = FT_THROW( Raster_Overflow );
+       return FAILURE;
+     }
+ 
+-    if ( Dx > 0 )
+-    {
+-      Ix = SMulDiv_No_Round( ras.precision, Dx, Dy );
+-      Rx = ( ras.precision * Dx ) % Dy;
+-      Dx = 1;
+-    }
+-    else
++    Dx = x2 - x1;
++    Dy = y2 - y1;
++
++    if ( Dx == 0 )  /* very easy */
+     {
+-      Ix = -SMulDiv_No_Round( ras.precision, -Dx, Dy );
+-      Rx = ( ras.precision * -Dx ) % Dy;
+-      Dx = -1;
++      do
++        *top++ = x1;
++      while ( --size );
++      goto Fin;
+     }
+ 
+-    Ax  = -Dy;
+-    top = ras.top;
++    Ix     = SMulDiv_No_Round( e - y1, Dx, Dy );
++    x1    += Ix;
++    *top++ = x1;
+ 
+-    while ( size > 0 )
++    if ( --size )
+     {
+-      *top++ = x1;
++      Ax = Dx * ( e - y1 )    - Dy * Ix;  /* remainder */
++      Ix = FMulDiv( ras.precision, Dx, Dy );
++      Rx = Dx * ras.precision - Dy * Ix;  /* remainder */
++      Dx = 1;
+ 
+-      x1 += Ix;
+-      Ax += Rx;
+-      if ( Ax >= 0 )
++      if ( x2 < x1 )
++      {
++        Ax = -Ax;
++        Rx = -Rx;
++        Dx = -Dx;
++      }
++
++      do
+       {
+-        Ax -= Dy;
+-        x1 += Dx;
++        x1 += Ix;
++        Ax += Rx;
++        if ( Ax >= Dy )
++        {
++          Ax -= Dy;
++          x1 += Dx;
++        }
++        *top++ = x1;
+       }
+-      size--;
++      while ( --size );
+     }
+ 
++  Fin:
+     ras.top = top;
+     return SUCCESS;
+   }
+@@ -1131,17 +1044,7 @@
+                       Long  miny,
+                       Long  maxy )
+   {
+-    Bool  result, fresh;
+-
+-
+-    fresh  = ras.fresh;
+-
+-    result = Line_Up( RAS_VARS x1, -y1, x2, -y2, -maxy, -miny );
+-
+-    if ( fresh && !ras.fresh )
+-      ras.cProfile->start = -ras.cProfile->start;
+-
+-    return result;
++    return Line_Up( RAS_VARS x1, -y1, x2, -y2, -maxy, -miny );
+   }
+ 
+ 
+@@ -1181,105 +1084,73 @@
+                       Long       miny,
+                       Long       maxy )
+   {
+-    Long   y1, y2, e, e2, e0;
+-    Short  f1;
++    Long  y1, y2, e, e2, dy;
++    Long  dx, x2;
+ 
+-    TPoint*  start_arc;
+-
+-    PLong top;
++    PLong  top;
+ 
+ 
+     y1  = arc[degree].y;
+     y2  = arc[0].y;
+-    top = ras.top;
+ 
+     if ( y2 < miny || y1 > maxy )
+-      goto Fin;
+-
+-    e2 = FLOOR( y2 );
+-
+-    if ( e2 > maxy )
+-      e2 = maxy;
+-
+-    e0 = miny;
+-
+-    if ( y1 < miny )
+-      e = miny;
+-    else
+-    {
+-      e  = CEILING( y1 );
+-      f1 = (Short)( FRAC( y1 ) );
+-      e0 = e;
+-
+-      if ( f1 == 0 )
+-      {
+-        if ( ras.joint )
+-        {
+-          top--;
+-          ras.joint = FALSE;
+-        }
++      return SUCCESS;
+ 
+-        *top++ = arc[degree].x;
++    e2 = y2 > maxy ? maxy : FLOOR( y2 );
++    e  = y1 < miny ? miny : CEILING( y1 );
+ 
+-        e += ras.precision;
+-      }
+-    }
++    if ( y1 == e )
++      e += ras.precision;
+ 
+-    if ( ras.fresh )
+-    {
+-      ras.cProfile->start = TRUNC( e0 );
+-      ras.fresh = FALSE;
+-    }
++    if ( e2 < e )  /* nothing to do */
++      return SUCCESS;
+ 
+-    if ( e2 < e )
+-      goto Fin;
++    top = ras.top;
+ 
+     if ( ( top + TRUNC( e2 - e ) + 1 ) >= ras.maxBuff )
+     {
+-      ras.top   = top;
+       ras.error = FT_THROW( Raster_Overflow );
+       return FAILURE;
+     }
+ 
+-    start_arc = arc;
+-
+     do
+     {
+-      ras.joint = FALSE;
+-
+       y2 = arc[0].y;
++      x2 = arc[0].x;
+ 
+       if ( y2 > e )
+       {
+-        y1 = arc[degree].y;
+-        if ( y2 - y1 >= ras.precision_step )
++        dy = y2 - arc[degree].y;
++        dx = x2 - arc[degree].x;
++
++        /* split condition should be invariant of direction */
++        if (  dy > ras.precision_step ||
++              dx > ras.precision_step ||
++             -dx > ras.precision_step )
+         {
+           splitter( arc );
+           arc += degree;
+         }
+         else
+         {
+-          *top++ = arc[degree].x + FMulDiv( arc[0].x - arc[degree].x,
+-                                            e - y1, y2 - y1 );
++          *top++ = x2 - FMulDiv( y2 - e, dx, dy );
++          e     += ras.precision;
+           arc -= degree;
+-          e   += ras.precision;
+         }
+       }
+       else
+       {
+         if ( y2 == e )
+         {
+-          ras.joint  = TRUE;
+-          *top++     = arc[0].x;
+-
+-          e += ras.precision;
++          *top++ = x2;
++          e     += ras.precision;
+         }
+-        arc -= degree;
++        arc   -= degree;
+       }
+-    } while ( arc >= start_arc && e <= e2 );
++    }
++    while ( e <= e2 );
+ 
+-  Fin:
+-    ras.top  = top;
++    ras.top = top;
+     return SUCCESS;
+   }
+ 
+@@ -1316,7 +1187,7 @@
+                         Long       miny,
+                         Long       maxy )
+   {
+-    Bool     result, fresh;
++    Bool  result;
+ 
+ 
+     arc[0].y = -arc[0].y;
+@@ -1325,13 +1196,8 @@
+     if ( degree > 2 )
+       arc[3].y = -arc[3].y;
+ 
+-    fresh = ras.fresh;
+-
+     result = Bezier_Up( RAS_VARS degree, arc, splitter, -maxy, -miny );
+ 
+-    if ( fresh && !ras.fresh )
+-      ras.cProfile->start = -ras.cProfile->start;
+-
+     arc[0].y = -arc[0].y;
+     return result;
+   }
+@@ -1362,74 +1228,50 @@
+   Line_To( RAS_ARGS Long  x,
+                     Long  y )
+   {
+-    /* First, detect a change of direction */
++    TStates  state;
+ 
+-    switch ( ras.state )
+-    {
+-    case Unknown_State:
+-      if ( y > ras.lastY )
+-      {
+-        if ( New_Profile( RAS_VARS Ascending_State,
+-                                   IS_BOTTOM_OVERSHOOT( ras.lastY ) ) )
+-          return FAILURE;
+-      }
+-      else
+-      {
+-        if ( y < ras.lastY )
+-          if ( New_Profile( RAS_VARS Descending_State,
+-                                     IS_TOP_OVERSHOOT( ras.lastY ) ) )
+-            return FAILURE;
+-      }
+-      break;
+ 
+-    case Ascending_State:
+-      if ( y < ras.lastY )
+-      {
+-        if ( End_Profile( RAS_VARS IS_TOP_OVERSHOOT( ras.lastY ) ) ||
+-             New_Profile( RAS_VARS Descending_State,
+-                                   IS_TOP_OVERSHOOT( ras.lastY ) ) )
+-          return FAILURE;
+-      }
+-      break;
++    if ( y == ras.lastY )
++      goto Fin;
+ 
+-    case Descending_State:
+-      if ( y > ras.lastY )
+-      {
+-        if ( End_Profile( RAS_VARS IS_BOTTOM_OVERSHOOT( ras.lastY ) ) ||
+-             New_Profile( RAS_VARS Ascending_State,
+-                                   IS_BOTTOM_OVERSHOOT( ras.lastY ) ) )
+-          return FAILURE;
+-      }
+-      break;
++    /* First, detect a change of direction */
+ 
+-    default:
+-      ;
++    state = ras.lastY < y ? Ascending_State : Descending_State;
++
++    if ( ras.state != state )
++    {
++      /* finalize current profile if any */
++      if ( ras.state != Unknown_State &&
++           End_Profile( RAS_VAR )     )
++        goto Fail;
++
++      /* create a new profile */
++      if ( New_Profile( RAS_VARS state ) )
++        goto Fail;
+     }
+ 
+     /* Then compute the lines */
+ 
+-    switch ( ras.state )
++    if ( state == Ascending_State )
+     {
+-    case Ascending_State:
+       if ( Line_Up( RAS_VARS ras.lastX, ras.lastY,
+                              x, y, ras.minY, ras.maxY ) )
+-        return FAILURE;
+-      break;
+-
+-    case Descending_State:
++        goto Fail;
++    }
++    else
++    {
+       if ( Line_Down( RAS_VARS ras.lastX, ras.lastY,
+                                x, y, ras.minY, ras.maxY ) )
+-        return FAILURE;
+-      break;
+-
+-    default:
+-      ;
++        goto Fail;
+     }
+ 
++  Fin:
+     ras.lastX = x;
+     ras.lastY = y;
+-
+     return SUCCESS;
++
++  Fail:
++    return FAILURE;
+   }
+ 
+ 
+@@ -1500,7 +1342,7 @@
+         ymax = y1;
+       }
+ 
+-      if ( y2 < ymin || y2 > ymax )
++      if ( y2 < FLOOR( ymin ) || y2 > CEILING( ymax ) )
+       {
+         /* this arc has no given direction, split it! */
+         Split_Conic( arc );
+@@ -1508,8 +1350,12 @@
+       }
+       else if ( y1 == y3 )
+       {
+-        /* this arc is flat, ignore it and pop it from the Bezier stack */
++        /* this arc is flat, advance position */
++        /* and pop it from the Bezier stack   */
+         arc -= 2;
++
++        ras.lastX = x3;
++        ras.lastY = y3;
+       }
+       else
+       {
+@@ -1518,18 +1364,13 @@
+         state_bez = y1 < y3 ? Ascending_State : Descending_State;
+         if ( ras.state != state_bez )
+         {
+-          Bool  o = ( state_bez == Ascending_State )
+-                      ? IS_BOTTOM_OVERSHOOT( y1 )
+-                      : IS_TOP_OVERSHOOT( y1 );
+-
+-
+           /* finalize current profile if any */
+           if ( ras.state != Unknown_State &&
+-               End_Profile( RAS_VARS o )  )
++               End_Profile( RAS_VAR )     )
+             goto Fail;
+ 
+           /* create a new profile */
+-          if ( New_Profile( RAS_VARS state_bez, o ) )
++          if ( New_Profile( RAS_VARS state_bez ) )
+             goto Fail;
+         }
+ 
+@@ -1545,13 +1386,13 @@
+                                      ras.minY, ras.maxY ) )
+             goto Fail;
+         arc -= 2;
++
++        ras.lastX = x3;
++        ras.lastY = y3;
+       }
+ 
+     } while ( arc >= arcs );
+ 
+-    ras.lastX = x3;
+-    ras.lastY = y3;
+-
+     return SUCCESS;
+ 
+   Fail:
+@@ -1648,7 +1489,7 @@
+         ymax2 = y2;
+       }
+ 
+-      if ( ymin2 < ymin1 || ymax2 > ymax1 )
++      if ( ymin2 < FLOOR( ymin1 ) || ymax2 > CEILING( ymax1 ) )
+       {
+         /* this arc has no given direction, split it! */
+         Split_Cubic( arc );
+@@ -1656,27 +1497,26 @@
+       }
+       else if ( y1 == y4 )
+       {
+-        /* this arc is flat, ignore it and pop it from the Bezier stack */
++        /* this arc is flat, advance position */
++        /* and pop it from the Bezier stack   */
+         arc -= 3;
++
++        ras.lastX = x4;
++        ras.lastY = y4;
+       }
+       else
+       {
+-        state_bez = ( y1 <= y4 ) ? Ascending_State : Descending_State;
++        state_bez = y1 < y4 ? Ascending_State : Descending_State;
+ 
+         /* detect a change of direction */
+         if ( ras.state != state_bez )
+         {
+-          Bool  o = ( state_bez == Ascending_State )
+-                      ? IS_BOTTOM_OVERSHOOT( y1 )
+-                      : IS_TOP_OVERSHOOT( y1 );
+-
+-
+           /* finalize current profile if any */
+           if ( ras.state != Unknown_State &&
+-               End_Profile( RAS_VARS o )  )
++               End_Profile( RAS_VAR )     )
+             goto Fail;
+ 
+-          if ( New_Profile( RAS_VARS state_bez, o ) )
++          if ( New_Profile( RAS_VARS state_bez ) )
+             goto Fail;
+         }
+ 
+@@ -1692,13 +1532,13 @@
+                                      ras.minY, ras.maxY ) )
+             goto Fail;
+         arc -= 3;
++
++        ras.lastX = x4;
++        ras.lastY = y4;
+       }
+ 
+     } while ( arc >= arcs );
+ 
+-    ras.lastX = x4;
+-    ras.lastY = y4;
+-
+     return SUCCESS;
+ 
+   Fail:
+@@ -1740,6 +1580,11 @@
+    *
+    * @Return:
+    *   SUCCESS on success, FAILURE on error.
++   *
++   * @Note:
++   *   Unlike FT_Outline_Decompose(), this function handles the scanmode
++   *   dropout tags in the individual contours.  Therefore, it cannot be
++   *   replaced.
+    */
+   static Bool
+   Decompose_Curve( RAS_ARGS Int  first,
+@@ -1753,7 +1598,7 @@
+     FT_Vector*  points;
+     FT_Vector*  point;
+     FT_Vector*  limit;
+-    char*       tags;
++    FT_Byte*    tags;
+ 
+     UInt        tag;       /* current point's state           */
+ 
+@@ -1974,24 +1819,17 @@
+ 
+ 
+     ras.fProfile = NULL;
+-    ras.joint    = FALSE;
+-    ras.fresh    = FALSE;
+-
+-    ras.maxBuff  = ras.sizeBuff - AlignProfileSize;
++    ras.cProfile = NULL;
+ 
+-    ras.numTurns = 0;
++    ras.top      = ras.buff;
++    ras.maxBuff  = ras.sizeBuff - 1;  /* top reserve */
+ 
+-    ras.cProfile         = (PProfile)ras.top;
+-    ras.cProfile->offset = ras.top;
+-    ras.num_Profs        = 0;
++    ras.numTurns  = 0;
++    ras.num_Profs = 0;
+ 
+     last = -1;
+     for ( i = 0; i < ras.outline.n_contours; i++ )
+     {
+-      PProfile  lastProfile;
+-      Bool      o;
+-
+-
+       ras.state    = Unknown_State;
+       ras.gProfile = NULL;
+ 
+@@ -2001,35 +1839,30 @@
+       if ( Decompose_Curve( RAS_VARS first, last, flipped ) )
+         return FAILURE;
+ 
++      /* Note that ras.gProfile can stay nil if the contour was */
++      /* too small to be drawn or degenerate.                   */
++      if ( !ras.gProfile )
++        continue;
++
+       /* we must now check whether the extreme arcs join or not */
+       if ( FRAC( ras.lastY ) == 0 &&
+            ras.lastY >= ras.minY  &&
+            ras.lastY <= ras.maxY  )
+-        if ( ras.gProfile                        &&
+-             ( ras.gProfile->flags & Flow_Up ) ==
++        if ( ( ras.gProfile->flags & Flow_Up ) ==
+                ( ras.cProfile->flags & Flow_Up ) )
+           ras.top--;
+-        /* Note that ras.gProfile can be nil if the contour was too small */
+-        /* to be drawn.                                                   */
+ 
+-      lastProfile = ras.cProfile;
+-      if ( ras.top != ras.cProfile->offset &&
+-           ( ras.cProfile->flags & Flow_Up ) )
+-        o = IS_TOP_OVERSHOOT( ras.lastY );
+-      else
+-        o = IS_BOTTOM_OVERSHOOT( ras.lastY );
+-      if ( End_Profile( RAS_VARS o ) )
++      if ( End_Profile( RAS_VAR ) )
+         return FAILURE;
+ 
+-      /* close the `next profile in contour' linked list */
+-      if ( ras.gProfile )
+-        lastProfile->next = ras.gProfile;
++      if ( !ras.fProfile )
++        ras.fProfile = ras.gProfile;
+     }
+ 
+-    if ( Finalize_Profile_Table( RAS_VAR ) )
+-      return FAILURE;
++    if ( ras.fProfile )
++      Finalize_Profile_Table( RAS_VAR );
+ 
+-    return (Bool)( ras.top < ras.maxBuff ? SUCCESS : FAILURE );
++    return SUCCESS;
+   }
+ 
+ 
+@@ -2042,24 +1875,11 @@
+   /*************************************************************************/
+ 
+ 
+-  /**************************************************************************
+-   *
+-   * Init_Linked
+-   *
+-   *   Initializes an empty linked list.
+-   */
+-  static void
+-  Init_Linked( TProfileList*  l )
+-  {
+-    *l = NULL;
+-  }
+-
+-
+   /**************************************************************************
+    *
+    * InsNew
+    *
+-   *   Inserts a new profile in a linked list.
++   *   Inserts a new profile in a linked list, sorted by coordinate.
+    */
+   static void
+   InsNew( PProfileList  list,
+@@ -2073,10 +1893,8 @@
+     current = *old;
+     x       = profile->X;
+ 
+-    while ( current )
++    while ( current && current->X < x )
+     {
+-      if ( x < current->X )
+-        break;
+       old     = ¤t->link;
+       current = *old;
+     }
+@@ -2088,79 +1906,51 @@
+ 
+   /**************************************************************************
+    *
+-   * DelOld
++   * Increment
+    *
+-   *   Removes an old profile from a linked list.
++   *   Advances all profile in the list to the next scanline.  It also
++   *   sorts the trace list in the unlikely case of profile crossing.
++   *   The profiles are inserted in sorted order.  We might need a single
++   *   swap to fix it when profiles (contours) cross.
++   *   Bubble sort with immediate restart is good enough and simple.
+    */
+   static void
+-  DelOld( PProfileList    list,
+-          const PProfile  profile )
++  Increment( PProfileList  list,
++             Int           flow )
+   {
+-    PProfile  *old, current;
+-
++    PProfile  *old, current, next;
+ 
+-    old     = list;
+-    current = *old;
+ 
+-    while ( current )
++    /* First, set the new X coordinates and remove exhausted profiles */
++    old = list;
++    while ( *old )
+     {
+-      if ( current == profile )
++      current = *old;
++      if ( --current->height )
+       {
+-        *old = current->link;
+-        return;
++        current->offset += flow;
++        current->X       = current->x[current->offset];
++        old = ¤t->link;
+       }
+-
+-      old     = ¤t->link;
+-      current = *old;
+-    }
+-
+-    /* we should never get there, unless the profile was not part of */
+-    /* the list.                                                     */
+-  }
+-
+-
+-  /**************************************************************************
+-   *
+-   * Sort
+-   *
+-   *   Sorts a trace list.  In 95%, the list is already sorted.  We need
+-   *   an algorithm which is fast in this case.  Bubble sort is enough
+-   *   and simple.
+-   */
+-  static void
+-  Sort( PProfileList  list )
+-  {
+-    PProfile  *old, current, next;
+-
+-
+-    /* First, set the new X coordinate of each profile */
+-    current = *list;
+-    while ( current )
+-    {
+-      current->X       = *current->offset;
+-      current->offset += ( current->flags & Flow_Up ) ? 1 : -1;
+-      current->height--;
+-      current = current->link;
++      else
++        *old = current->link;  /* remove */
+     }
+ 
+-    /* Then sort them */
++    /* Then make sure the list remains sorted */
+     old     = list;
+     current = *old;
+ 
+     if ( !current )
+       return;
+ 
+-    next = current->link;
+-
+-    while ( next )
++    while ( current->link )
+     {
++      next = current->link;
++
+       if ( current->X <= next->X )
+       {
+         old     = ¤t->link;
+-        current = *old;
+-
+-        if ( !current )
+-          return;
++        current = next;
+       }
+       else
+       {
+@@ -2168,11 +1958,10 @@
+         current->link = next->link;
+         next->link    = current;
+ 
++        /* this is likely the only necessary swap -- restart */
+         old     = list;
+         current = *old;
+       }
+-
+-      next = current->link;
+     }
+   }
+ 
+@@ -2187,74 +1976,51 @@
+    */
+ 
+   static void
+-  Vertical_Sweep_Init( RAS_ARGS Short  min,
+-                                Short  max )
++  Vertical_Sweep_Init( RAS_ARGS Int  min,
++                                Int  max )
+   {
+     FT_UNUSED( max );
+ 
+ 
+-    ras.bLine = ras.bOrigin - min * ras.target.pitch;
++    ras.bLine = ras.bOrigin - min * ras.bPitch;
+   }
+ 
+ 
+   static void
+-  Vertical_Sweep_Span( RAS_ARGS Short       y,
++  Vertical_Sweep_Span( RAS_ARGS Int         y,
+                                 FT_F26Dot6  x1,
+-                                FT_F26Dot6  x2,
+-                                PProfile    left,
+-                                PProfile    right )
++                                FT_F26Dot6  x2 )
+   {
+-    Long  e1, e2;
+-
+-    Int  dropOutControl = left->flags & 7;
++    Int  e1 = (Int)TRUNC( CEILING( x1 ) );
++    Int  e2 = (Int)TRUNC(   FLOOR( x2 ) );
+ 
+     FT_UNUSED( y );
+-    FT_UNUSED( left );
+-    FT_UNUSED( right );
+ 
+ 
+-    /* in high-precision mode, we need 12 digits after the comma to */
+-    /* represent multiples of 1/(1<<12) = 1/4096                    */
+-    FT_TRACE7(( "  y=%d x=[% .12f;% .12f]",
++    FT_TRACE7(( "  y=%d x=[% .*f;% .*f]",
+                 y,
+-                (double)x1 / (double)ras.precision,
+-                (double)x2 / (double)ras.precision ));
+-
+-    /* Drop-out control */
+-
+-    e1 = CEILING( x1 );
+-    e2 = FLOOR( x2 );
+-
+-    /* take care of the special case where both the left */
+-    /* and right contour lie exactly on pixel centers    */
+-    if ( dropOutControl != 2                             &&
+-         x2 - x1 - ras.precision <= ras.precision_jitter &&
+-         e1 != x1 && e2 != x2                            )
+-      e2 = e1;
++                ras.precision_bits, (double)x1 / (double)ras.precision,
++                ras.precision_bits, (double)x2 / (double)ras.precision ));
+ 
+-    e1 = TRUNC( e1 );
+-    e2 = TRUNC( e2 );
+-
+-    if ( e2 >= 0 && e1 < ras.bWidth )
++    if ( e2 >= 0 && e1 <= ras.bRight )
+     {
+-      Byte*  target;
++      PByte  target;
+ 
+-      Int   c1, c2;
+-      Byte  f1, f2;
++      Int   c1, f1, c2, f2;
+ 
+ 
+       if ( e1 < 0 )
+         e1 = 0;
+-      if ( e2 >= ras.bWidth )
+-        e2 = ras.bWidth - 1;
++      if ( e2 > ras.bRight )
++        e2 = ras.bRight;
+ 
+-      FT_TRACE7(( " -> x=[%ld;%ld]", e1, e2 ));
++      FT_TRACE7(( " -> x=[%d;%d]", e1, e2 ));
+ 
+-      c1 = (Short)( e1 >> 3 );
+-      c2 = (Short)( e2 >> 3 );
++      c1 = e1 >> 3;
++      c2 = e2 >> 3;
+ 
+-      f1 = (Byte)  ( 0xFF >> ( e1 & 7 ) );
+-      f2 = (Byte) ~( 0x7F >> ( e2 & 7 ) );
++      f1 =  0xFF >> ( e1 & 7 );
++      f2 = ~0x7F >> ( e2 & 7 );
+ 
+       target = ras.bLine + c1;
+       c2 -= c1;
+@@ -2280,163 +2046,50 @@
+ 
+ 
+   static void
+-  Vertical_Sweep_Drop( RAS_ARGS Short       y,
++  Vertical_Sweep_Drop( RAS_ARGS Int         y,
+                                 FT_F26Dot6  x1,
+-                                FT_F26Dot6  x2,
+-                                PProfile    left,
+-                                PProfile    right )
++                                FT_F26Dot6  x2 )
+   {
+-    Long   e1, e2, pxl;
+-    Short  c1, f1;
+-
+-
+-    FT_TRACE7(( "  y=%d x=[% .12f;% .12f]",
+-                y,
+-                (double)x1 / (double)ras.precision,
+-                (double)x2 / (double)ras.precision ));
+-
+-    /* Drop-out control */
+-
+-    /*   e2            x2                    x1           e1   */
+-    /*                                                         */
+-    /*                 ^                     |                 */
+-    /*                 |                     |                 */
+-    /*   +-------------+---------------------+------------+    */
+-    /*                 |                     |                 */
+-    /*                 |                     v                 */
+-    /*                                                         */
+-    /* pixel         contour              contour       pixel  */
+-    /* center                                           center */
+-
+-    /* drop-out mode    scan conversion rules (as defined in OpenType) */
+-    /* --------------------------------------------------------------- */
+-    /*  0                1, 2, 3                                       */
+-    /*  1                1, 2, 4                                       */
+-    /*  2                1, 2                                          */
+-    /*  3                same as mode 2                                */
+-    /*  4                1, 2, 5                                       */
+-    /*  5                1, 2, 6                                       */
+-    /*  6, 7             same as mode 2                                */
+-
+-    e1  = CEILING( x1 );
+-    e2  = FLOOR  ( x2 );
+-    pxl = e1;
+-
+-    if ( e1 > e2 )
+-    {
+-      Int  dropOutControl = left->flags & 7;
+-
+-
+-      if ( e1 == e2 + ras.precision )
+-      {
+-        switch ( dropOutControl )
+-        {
+-        case 0: /* simple drop-outs including stubs */
+-          pxl = e2;
+-          break;
+-
+-        case 4: /* smart drop-outs including stubs */
+-          pxl = SMART( x1, x2 );
+-          break;
+-
+-        case 1: /* simple drop-outs excluding stubs */
+-        case 5: /* smart drop-outs excluding stubs  */
+-
+-          /* Drop-out Control Rules #4 and #6 */
+-
+-          /* The specification neither provides an exact definition */
+-          /* of a `stub' nor gives exact rules to exclude them.     */
+-          /*                                                        */
+-          /* Here the constraints we use to recognize a stub.       */
+-          /*                                                        */
+-          /*  upper stub:                                           */
+-          /*                                                        */
+-          /*   - P_Left and P_Right are in the same contour         */
+-          /*   - P_Right is the successor of P_Left in that contour */
+-          /*   - y is the top of P_Left and P_Right                 */
+-          /*                                                        */
+-          /*  lower stub:                                           */
+-          /*                                                        */
+-          /*   - P_Left and P_Right are in the same contour         */
+-          /*   - P_Left is the successor of P_Right in that contour */
+-          /*   - y is the bottom of P_Left                          */
+-          /*                                                        */
+-          /* We draw a stub if the following constraints are met.   */
+-          /*                                                        */
+-          /*   - for an upper or lower stub, there is top or bottom */
+-          /*     overshoot, respectively                            */
+-          /*   - the covered interval is greater or equal to a half */
+-          /*     pixel                                              */
+-
+-          /* upper stub test */
+-          if ( left->next == right                &&
+-               left->height <= 0                  &&
+-               !( left->flags & Overshoot_Top   &&
+-                  x2 - x1 >= ras.precision_half ) )
+-            goto Exit;
+-
+-          /* lower stub test */
+-          if ( right->next == left                 &&
+-               left->start == y                    &&
+-               !( left->flags & Overshoot_Bottom &&
+-                  x2 - x1 >= ras.precision_half  ) )
+-            goto Exit;
+-
+-          if ( dropOutControl == 1 )
+-            pxl = e2;
+-          else
+-            pxl = SMART( x1, x2 );
+-          break;
+-
+-        default: /* modes 2, 3, 6, 7 */
+-          goto Exit;  /* no drop-out control */
+-        }
++    Int  e1 = (Int)TRUNC( x1 );
++    Int  e2 = (Int)TRUNC( x2 );
++    Int  c1, f1;
+ 
+-        /* undocumented but confirmed: If the drop-out would result in a  */
+-        /* pixel outside of the bounding box, use the pixel inside of the */
+-        /* bounding box instead                                           */
+-        if ( pxl < 0 )
+-          pxl = e1;
+-        else if ( TRUNC( pxl ) >= ras.bWidth )
+-          pxl = e2;
++    FT_UNUSED( y );
+ 
+-        /* check that the other pixel isn't set */
+-        e1 = ( pxl == e1 ) ? e2 : e1;
+ 
+-        e1 = TRUNC( e1 );
++    /* undocumented but confirmed: If the drop-out would result in a  */
++    /* pixel outside of the bounding box, use the pixel inside of the */
++    /* bounding box instead                                           */
++    if ( e1 < 0 || e1 > ras.bRight )
++      e1 = e2;
+ 
+-        c1 = (Short)( e1 >> 3 );
+-        f1 = (Short)( e1 &  7 );
++    /* otherwise check that the other pixel isn't set */
++    else if ( e2 >=0 && e2 <= ras.bRight )
++    {
++      c1 = e2 >> 3;
++      f1 = 0x80 >> ( e2 & 7 );
+ 
+-        if ( e1 >= 0 && e1 < ras.bWidth     &&
+-             ras.bLine[c1] & ( 0x80 >> f1 ) )
+-          goto Exit;
+-      }
+-      else
+-        goto Exit;
++      if ( ras.bLine[c1] & f1 )
++        return;
+     }
+ 
+-    e1 = TRUNC( pxl );
+-
+-    if ( e1 >= 0 && e1 < ras.bWidth )
++    if ( e1 >= 0 && e1 <= ras.bRight )
+     {
+-      FT_TRACE7(( " -> x=%ld", e1 ));
++      c1 = e1 >> 3;
++      f1 = 0x80 >> ( e1 & 7 );
+ 
+-      c1 = (Short)( e1 >> 3 );
+-      f1 = (Short)( e1 & 7 );
++      FT_TRACE7(( "  y=%d x=%d%s\n", y, e1,
++                  ras.bLine[c1] & f1 ? " redundant" : "" ));
+ 
+-      ras.bLine[c1] |= (char)( 0x80 >> f1 );
++      ras.bLine[c1] |= f1;
+     }
+-
+-  Exit:
+-    FT_TRACE7(( " dropout=%d\n", left->flags & 7 ));
+   }
+ 
+ 
+   static void
+   Vertical_Sweep_Step( RAS_ARG )
+   {
+-    ras.bLine -= ras.target.pitch;
++    ras.bLine -= ras.bPitch;
+   }
+ 
+ 
+@@ -2450,8 +2103,8 @@
+    */
+ 
+   static void
+-  Horizontal_Sweep_Init( RAS_ARGS Short  min,
+-                                  Short  max )
++  Horizontal_Sweep_Init( RAS_ARGS Int  min,
++                                  Int  max )
+   {
+     /* nothing, really */
+     FT_UNUSED_RASTER;
+@@ -2461,22 +2114,18 @@
+ 
+ 
+   static void
+-  Horizontal_Sweep_Span( RAS_ARGS Short       y,
++  Horizontal_Sweep_Span( RAS_ARGS Int         y,
+                                   FT_F26Dot6  x1,
+-                                  FT_F26Dot6  x2,
+-                                  PProfile    left,
+-                                  PProfile    right )
++                                  FT_F26Dot6  x2 )
+   {
+-    Long  e1, e2;
++    Long  e1 = CEILING( x1 );
++    Long  e2 =   FLOOR( x2 );
+ 
+-    FT_UNUSED( left );
+-    FT_UNUSED( right );
+ 
+-
+-    FT_TRACE7(( "  x=%d y=[% .12f;% .12f]",
++    FT_TRACE7(( "  x=%d y=[% .*f;% .*f]",
+                 y,
+-                (double)x1 / (double)ras.precision,
+-                (double)x2 / (double)ras.precision ));
++                ras.precision_bits, (double)x1 / (double)ras.precision,
++                ras.precision_bits, (double)x2 / (double)ras.precision ));
+ 
+     /* We should not need this procedure but the vertical sweep   */
+     /* mishandles horizontal lines through pixel centers.  So we  */
+@@ -2484,20 +2133,18 @@
+     /*                                                            */
+     /* XXX: Can we handle horizontal lines better and drop this?  */
+ 
+-    e1 = CEILING( x1 );
+-
+     if ( x1 == e1 )
+     {
+       e1 = TRUNC( e1 );
+ 
+-      if ( e1 >= 0 && (ULong)e1 < ras.target.rows )
++      if ( e1 >= 0 && e1 <= ras.bTop )
+       {
+-        Byte   f1;
++        Int    f1;
+         PByte  bits;
+ 
+ 
+-        bits = ras.bOrigin + ( y >> 3 ) - e1 * ras.target.pitch;
+-        f1   = (Byte)( 0x80 >> ( y & 7 ) );
++        bits = ras.bOrigin + ( y >> 3 ) - e1 * ras.bPitch;
++        f1   = 0x80 >> ( y & 7 );
+ 
+         FT_TRACE7(( bits[0] & f1 ? " redundant"
+                                  : " -> y=%ld edge", e1 ));
+@@ -2506,20 +2153,18 @@
+       }
+     }
+ 
+-    e2 = FLOOR  ( x2 );
+-
+     if ( x2 == e2 )
+     {
+       e2 = TRUNC( e2 );
+ 
+-      if ( e2 >= 0 && (ULong)e2 < ras.target.rows )
++      if ( e2 >= 0 && e2 <= ras.bTop )
+       {
+-        Byte   f1;
++        Int    f1;
+         PByte  bits;
+ 
+ 
+-        bits = ras.bOrigin + ( y >> 3 ) - e2 * ras.target.pitch;
+-        f1   = (Byte)( 0x80 >> ( y & 7 ) );
++        bits = ras.bOrigin + ( y >> 3 ) - e2 * ras.bPitch;
++        f1   = 0x80 >> ( y & 7 );
+ 
+         FT_TRACE7(( bits[0] & f1 ? " redundant"
+                                  : " -> y=%ld edge", e2 ));
+@@ -2533,122 +2178,42 @@
+ 
+ 
+   static void
+-  Horizontal_Sweep_Drop( RAS_ARGS Short       y,
++  Horizontal_Sweep_Drop( RAS_ARGS Int         y,
+                                   FT_F26Dot6  x1,
+-                                  FT_F26Dot6  x2,
+-                                  PProfile    left,
+-                                  PProfile    right )
++                                  FT_F26Dot6  x2 )
+   {
+-    Long   e1, e2, pxl;
++    Int    e1 = (Int)TRUNC( x1 );
++    Int    e2 = (Int)TRUNC( x2 );
+     PByte  bits;
+-    Byte   f1;
+-
+-
+-    FT_TRACE7(( "  x=%d y=[% .12f;% .12f]",
+-                y,
+-                (double)x1 / (double)ras.precision,
+-                (double)x2 / (double)ras.precision ));
+-
+-    /* During the horizontal sweep, we only take care of drop-outs */
+-
+-    /* e1     +       <-- pixel center */
+-    /*        |                        */
+-    /* x1  ---+-->    <-- contour      */
+-    /*        |                        */
+-    /*        |                        */
+-    /* x2  <--+---    <-- contour      */
+-    /*        |                        */
+-    /*        |                        */
+-    /* e2     +       <-- pixel center */
+-
+-    e1  = CEILING( x1 );
+-    e2  = FLOOR  ( x2 );
+-    pxl = e1;
+-
+-    if ( e1 > e2 )
+-    {
+-      Int  dropOutControl = left->flags & 7;
+-
++    Int    f1;
+ 
+-      if ( e1 == e2 + ras.precision )
+-      {
+-        switch ( dropOutControl )
+-        {
+-        case 0: /* simple drop-outs including stubs */
+-          pxl = e2;
+-          break;
+-
+-        case 4: /* smart drop-outs including stubs */
+-          pxl = SMART( x1, x2 );
+-          break;
+-
+-        case 1: /* simple drop-outs excluding stubs */
+-        case 5: /* smart drop-outs excluding stubs  */
+-          /* see Vertical_Sweep_Drop for details */
+-
+-          /* rightmost stub test */
+-          if ( left->next == right                &&
+-               left->height <= 0                  &&
+-               !( left->flags & Overshoot_Top   &&
+-                  x2 - x1 >= ras.precision_half ) )
+-            goto Exit;
+-
+-          /* leftmost stub test */
+-          if ( right->next == left                 &&
+-               left->start == y                    &&
+-               !( left->flags & Overshoot_Bottom &&
+-                  x2 - x1 >= ras.precision_half  ) )
+-            goto Exit;
+-
+-          if ( dropOutControl == 1 )
+-            pxl = e2;
+-          else
+-            pxl = SMART( x1, x2 );
+-          break;
+ 
+-        default: /* modes 2, 3, 6, 7 */
+-          goto Exit;  /* no drop-out control */
+-        }
+-
+-        /* undocumented but confirmed: If the drop-out would result in a  */
+-        /* pixel outside of the bounding box, use the pixel inside of the */
+-        /* bounding box instead                                           */
+-        if ( pxl < 0 )
+-          pxl = e1;
+-        else if ( (ULong)( TRUNC( pxl ) ) >= ras.target.rows )
+-          pxl = e2;
+-
+-        /* check that the other pixel isn't set */
+-        e1 = ( pxl == e1 ) ? e2 : e1;
+-
+-        e1 = TRUNC( e1 );
++    /* undocumented but confirmed: If the drop-out would result in a  */
++    /* pixel outside of the bounding box, use the pixel inside of the */
++    /* bounding box instead                                           */
++    if ( e1 < 0 || e1 > ras.bTop )
++      e1 = e2;
+ 
+-        bits = ras.bOrigin + ( y >> 3 ) - e1 * ras.target.pitch;
+-        f1   = (Byte)( 0x80 >> ( y & 7 ) );
++    /* otherwise check that the other pixel isn't set */
++    else if ( e2 >=0 && e2 <= ras.bTop )
++    {
++      bits = ras.bOrigin + ( y >> 3 ) - e2 * ras.bPitch;
++      f1   = 0x80 >> ( y & 7 );
+ 
+-        if ( e1 >= 0                     &&
+-             (ULong)e1 < ras.target.rows &&
+-             *bits & f1                  )
+-          goto Exit;
+-      }
+-      else
+-        goto Exit;
++      if ( *bits & f1 )
++        return;
+     }
+ 
+-    e1 = TRUNC( pxl );
+-
+-    if ( e1 >= 0 && (ULong)e1 < ras.target.rows )
++    if ( e1 >= 0 && e1 <= ras.bTop )
+     {
+-      FT_TRACE7(( " -> y=%ld", e1 ));
++      bits  = ras.bOrigin + ( y >> 3 ) - e1 * ras.bPitch;
++      f1    = 0x80 >> ( y & 7 );
+ 
+-      bits  = ras.bOrigin + ( y >> 3 ) - e1 * ras.target.pitch;
+-      f1    = (Byte)( 0x80 >> ( y & 7 ) );
++      FT_TRACE7(( "  x=%d y=%d%s\n", y, e1,
++                  *bits & f1 ? " redundant" : "" ));
+ 
+-      bits[0] |= f1;
++      *bits |= f1;
+     }
+-
+-  Exit:
+-    FT_TRACE7(( " dropout=%d\n", left->flags & 7 ));
+   }
+ 
+ 
+@@ -2664,116 +2229,61 @@
+    *
+    * Generic Sweep Drawing routine
+    *
++   * Note that this routine is executed with the pool containing at least
++   * two valid profiles (up and down) and two y-turns (top and bottom).
++   *
+    */
+ 
+-  static Bool
++  static void
+   Draw_Sweep( RAS_ARG )
+   {
+-    Short         y, y_change, y_height;
+-
+-    PProfile      P, Q, P_Left, P_Right;
+-
+-    Short         min_Y, max_Y, top, bottom, dropouts;
+-
+-    Long          x1, x2, xs, e1, e2;
+-
+-    TProfileList  waiting;
+-    TProfileList  draw_left, draw_right;
+-
+-
+-    /* initialize empty linked lists */
+-
+-    Init_Linked( &waiting );
+-
+-    Init_Linked( &draw_left  );
+-    Init_Linked( &draw_right );
+-
+-    /* first, compute min and max Y */
+-
+-    P     = ras.fProfile;
+-    max_Y = (Short)TRUNC( ras.minY );
+-    min_Y = (Short)TRUNC( ras.maxY );
+-
+-    while ( P )
+-    {
+-      Q = P->link;
++    Int           min_Y, max_Y, dropouts;
++    Int           y, y_turn;
+ 
+-      bottom = (Short)P->start;
+-      top    = (Short)( P->start + P->height - 1 );
++    PProfile      *Q, P, P_Left, P_Right;
+ 
+-      if ( min_Y > bottom )
+-        min_Y = bottom;
+-      if ( max_Y < top )
+-        max_Y = top;
++    TProfileList  waiting    = ras.fProfile;
++    TProfileList  draw_left  = NULL;
++    TProfileList  draw_right = NULL;
+ 
+-      P->X = 0;
+-      InsNew( &waiting, P );
+ 
+-      P = Q;
+-    }
++    /* use y_turns to set the drawing range */
+ 
+-    /* check the Y-turns */
+-    if ( ras.numTurns == 0 )
+-    {
+-      ras.error = FT_THROW( Invalid_Outline );
+-      return FAILURE;
+-    }
++    min_Y = (Int)ras.maxBuff[0];
++    max_Y = (Int)ras.maxBuff[ras.numTurns] - 1;
+ 
+     /* now initialize the sweep */
+ 
+     ras.Proc_Sweep_Init( RAS_VARS min_Y, max_Y );
+ 
+-    /* then compute the distance of each profile from min_Y */
+-
+-    P = waiting;
+-
+-    while ( P )
+-    {
+-      P->countL = P->start - min_Y;
+-      P = P->link;
+-    }
+-
+     /* let's go */
+ 
+-    y        = min_Y;
+-    y_height = 0;
+-
+-    if ( ras.numTurns > 0                     &&
+-         ras.sizeBuff[-ras.numTurns] == min_Y )
+-      ras.numTurns--;
+-
+-    while ( ras.numTurns > 0 )
++    for ( y = min_Y; y <= max_Y; )
+     {
+-      /* check waiting list for new activations */
+-
+-      P = waiting;
++      /* check waiting list for new profile activations */
+ 
+-      while ( P )
++      Q = &waiting;
++      while ( *Q )
+       {
+-        Q = P->link;
+-        P->countL -= y_height;
+-        if ( P->countL == 0 )
++        P = *Q;
++        if ( P->start == y )
+         {
+-          DelOld( &waiting, P );
++          *Q = P->link;  /* remove */
+ 
++          /* each active list contains profiles with the same flow */
++          /* left and right are arbitrary, correspond to TrueType  */
+           if ( P->flags & Flow_Up )
+             InsNew( &draw_left,  P );
+           else
+             InsNew( &draw_right, P );
+         }
+-
+-        P = Q;
++        else
++          Q = &P->link;
+       }
+ 
+-      /* sort the drawing lists */
++      y_turn = (Int)*++ras.maxBuff;
+ 
+-      Sort( &draw_left );
+-      Sort( &draw_right );
+-
+-      y_change = (Short)ras.sizeBuff[-ras.numTurns--];
+-      y_height = (Short)( y_change - y );
+-
+-      while ( y < y_change )
++      do
+       {
+         /* let's trace */
+ 
+@@ -2784,9 +2294,13 @@
+ 
+         while ( P_Left && P_Right )
+         {
+-          x1 = P_Left ->X;
+-          x2 = P_Right->X;
++          Long  x1 = P_Left ->X;
++          Long  x2 = P_Right->X;
++          Long  xs;
++
+ 
++          /* TrueType should have x2 > x1, but can be opposite */
++          /* by mistake or in CFF/Type1, fix it then           */
+           if ( x1 > x2 )
+           {
+             xs = x1;
+@@ -2794,205 +2308,130 @@
+             x2 = xs;
+           }
+ 
+-          e1 = FLOOR( x1 );
+-          e2 = CEILING( x2 );
++          if ( CEILING( x1 ) <= FLOOR( x2 ) )
++            ras.Proc_Sweep_Span( RAS_VARS y, x1, x2 );
+ 
+-          if ( x2 - x1 <= ras.precision &&
+-               e1 != x1 && e2 != x2     )
++          /* otherwise, bottom ceiling > top floor, it is a drop-out */
++          else
+           {
+-            if ( e1 > e2 || e2 == e1 + ras.precision )
++            Int  dropOutControl = P_Left->flags & 7;
++
++
++            /* Drop-out control */
++
++            /*   e2            x2                    x1           e1   */
++            /*                                                         */
++            /*                 ^                     |                 */
++            /*                 |                     |                 */
++            /*   +-------------+---------------------+------------+    */
++            /*                 |                     |                 */
++            /*                 |                     v                 */
++            /*                                                         */
++            /* pixel         contour              contour       pixel  */
++            /* center                                           center */
++
++            /* drop-out mode   scan conversion rules (OpenType specs)  */
++            /* ------------------------------------------------------- */
++            /*  bit 0          exclude stubs if set                    */
++            /*  bit 1          ignore drop-outs if set                 */
++            /*  bit 2          smart rounding if set                   */
++
++            if ( dropOutControl & 2 )
++              goto Next_Pair;
++
++            /* The specification neither provides an exact definition */
++            /* of a `stub' nor gives exact rules to exclude them.     */
++            /*                                                        */
++            /* Here the constraints we use to recognize a stub.       */
++            /*                                                        */
++            /*  upper stub:                                           */
++            /*                                                        */
++            /*   - P_Left and P_Right are in the same contour         */
++            /*   - P_Right is the successor of P_Left in that contour */
++            /*   - y is the top of P_Left and P_Right                 */
++            /*                                                        */
++            /*  lower stub:                                           */
++            /*                                                        */
++            /*   - P_Left and P_Right are in the same contour         */
++            /*   - P_Left is the successor of P_Right in that contour */
++            /*   - y is the bottom of P_Left                          */
++            /*                                                        */
++            /* We draw a stub if the following constraints are met.   */
++            /*                                                        */
++            /*   - for an upper or lower stub, there is top or bottom */
++            /*     overshoot, respectively                            */
++            /*   - the covered interval is greater or equal to a half */
++            /*     pixel                                              */
++
++            if ( dropOutControl & 1 )
+             {
+-              Int  dropOutControl = P_Left->flags & 7;
+-
+-
+-              if ( dropOutControl != 2 )
+-              {
+-                /* a drop-out was detected */
+-
+-                P_Left ->X = x1;
+-                P_Right->X = x2;
+-
+-                /* mark profile for drop-out processing */
+-                P_Left->countL = 1;
+-                dropouts++;
+-              }
++              /* upper stub test */
++              if ( P_Left->height == 1                &&
++                   P_Left->next == P_Right            &&
++                   !( P_Left->flags & Overshoot_Top   &&
++                      x2 - x1 >= ras.precision_half   ) )
++                goto Next_Pair;
++
++              /* lower stub test */
++              if ( P_Left->offset == 0                 &&
++                   P_Right->next == P_Left             &&
++                   !( P_Left->flags & Overshoot_Bottom &&
++                      x2 - x1 >= ras.precision_half    ) )
++                goto Next_Pair;
++            }
+ 
+-              goto Skip_To_Next;
++            /* select the pixel to set and the other pixel */
++            if ( dropOutControl & 4 )
++            {
++              x2 = SMART( x1, x2 );
++              x1 = x1 > x2 ? x2 + ras.precision : x2 - ras.precision;
++            }
++            else
++            {
++              x2 = FLOOR  ( x2 );
++              x1 = CEILING( x1 );
+             }
+-          }
+ 
+-          ras.Proc_Sweep_Span( RAS_VARS y, x1, x2, P_Left, P_Right );
++            P_Left ->X = x2;
++            P_Right->X = x1;
+ 
+-        Skip_To_Next:
++            /* mark profile for drop-out processing */
++            P_Left->flags |= Dropout;
++            dropouts++;
++          }
+ 
++        Next_Pair:
+           P_Left  = P_Left->link;
+           P_Right = P_Right->link;
+         }
+ 
+-        /* handle drop-outs _after_ the span drawing --       */
+-        /* drop-out processing has been moved out of the loop */
+-        /* for performance tuning                             */
+-        if ( dropouts > 0 )
+-          goto Scan_DropOuts;
+-
+-      Next_Line:
+-
+-        ras.Proc_Sweep_Step( RAS_VAR );
+-
+-        y++;
++        /* handle drop-outs _after_ the span drawing */
++        P_Left  = draw_left;
++        P_Right = draw_right;
+ 
+-        if ( y < y_change )
++        while ( dropouts )
+         {
+-          Sort( &draw_left  );
+-          Sort( &draw_right );
+-        }
+-      }
+-
+-      /* now finalize the profiles that need it */
+-
+-      P = draw_left;
+-      while ( P )
+-      {
+-        Q = P->link;
+-        if ( P->height == 0 )
+-          DelOld( &draw_left, P );
+-        P = Q;
+-      }
+-
+-      P = draw_right;
+-      while ( P )
+-      {
+-        Q = P->link;
+-        if ( P->height == 0 )
+-          DelOld( &draw_right, P );
+-        P = Q;
+-      }
+-    }
+-
+-    /* for gray-scaling, flush the bitmap scanline cache */
+-    while ( y <= max_Y )
+-    {
+-      ras.Proc_Sweep_Step( RAS_VAR );
+-      y++;
+-    }
+-
+-    return SUCCESS;
+-
+-  Scan_DropOuts:
+-
+-    P_Left  = draw_left;
+-    P_Right = draw_right;
+-
+-    while ( P_Left && P_Right )
+-    {
+-      if ( P_Left->countL )
+-      {
+-        P_Left->countL = 0;
+-#if 0
+-        dropouts--;  /* -- this is useful when debugging only */
+-#endif
+-        ras.Proc_Sweep_Drop( RAS_VARS y,
+-                                      P_Left->X,
+-                                      P_Right->X,
+-                                      P_Left,
+-                                      P_Right );
+-      }
+-
+-      P_Left  = P_Left->link;
+-      P_Right = P_Right->link;
+-    }
+-
+-    goto Next_Line;
+-  }
+-
+-
+-#ifdef STANDALONE_
+-
+-  /**************************************************************************
+-   *
+-   * The following functions should only compile in stand-alone mode,
+-   * i.e., when building this component without the rest of FreeType.
+-   *
+-   */
+-
+-  /**************************************************************************
+-   *
+-   * @Function:
+-   *   FT_Outline_Get_CBox
+-   *
+-   * @Description:
+-   *   Return an outline's `control box'.  The control box encloses all
+-   *   the outline's points, including Bézier control points.  Though it
+-   *   coincides with the exact bounding box for most glyphs, it can be
+-   *   slightly larger in some situations (like when rotating an outline
+-   *   that contains Bézier outside arcs).
+-   *
+-   *   Computing the control box is very fast, while getting the bounding
+-   *   box can take much more time as it needs to walk over all segments
+-   *   and arcs in the outline.  To get the latter, you can use the
+-   *   `ftbbox' component, which is dedicated to this single task.
+-   *
+-   * @Input:
+-   *   outline ::
+-   *     A pointer to the source outline descriptor.
+-   *
+-   * @Output:
+-   *   acbox ::
+-   *     The outline's control box.
+-   *
+-   * @Note:
+-   *   See @FT_Glyph_Get_CBox for a discussion of tricky fonts.
+-   */
+-
+-  static void
+-  FT_Outline_Get_CBox( const FT_Outline*  outline,
+-                       FT_BBox           *acbox )
+-  {
+-    if ( outline && acbox )
+-    {
+-      Long  xMin, yMin, xMax, yMax;
+-
+-
+-      if ( outline->n_points == 0 )
+-      {
+-        xMin = 0;
+-        yMin = 0;
+-        xMax = 0;
+-        yMax = 0;
+-      }
+-      else
+-      {
+-        FT_Vector*  vec   = outline->points;
+-        FT_Vector*  limit = vec + outline->n_points;
+-
+-
+-        xMin = xMax = vec->x;
+-        yMin = yMax = vec->y;
+-        vec++;
++          if ( P_Left->flags & Dropout )
++          {
++            ras.Proc_Sweep_Drop( RAS_VARS y, P_Left->X, P_Right->X );
+ 
+-        for ( ; vec < limit; vec++ )
+-        {
+-          Long  x, y;
++            P_Left->flags &= ~Dropout;
++            dropouts--;
++          }
+ 
++          P_Left  = P_Left->link;
++          P_Right = P_Right->link;
++        }
+ 
+-          x = vec->x;
+-          if ( x < xMin ) xMin = x;
+-          if ( x > xMax ) xMax = x;
++        ras.Proc_Sweep_Step( RAS_VAR );
+ 
+-          y = vec->y;
+-          if ( y < yMin ) yMin = y;
+-          if ( y > yMax ) yMax = y;
+-        }
++        Increment( &draw_left,   1 );
++        Increment( &draw_right, -1 );
+       }
+-      acbox->xMin = xMin;
+-      acbox->xMax = xMax;
+-      acbox->yMin = yMin;
+-      acbox->yMax = yMax;
++      while ( ++y < y_turn );
+     }
+   }
+ 
+-#endif /* STANDALONE_ */
+-
+ 
+   /**************************************************************************
+    *
+@@ -3019,13 +2458,15 @@
+     Int  band_stack[32];  /* enough to bisect 32-bit int bands */
+ 
+ 
++    FT_TRACE6(( "%s pass [%d..%d]\n",
++                flipped ? "Horizontal" : "Vertical",
++                y_min, y_max ));
++
+     while ( 1 )
+     {
+       ras.minY = (Long)y_min * ras.precision;
+       ras.maxY = (Long)y_max * ras.precision;
+ 
+-      ras.top = ras.buff;
+-
+       ras.error = Raster_Err_Ok;
+ 
+       if ( Convert_Glyph( RAS_VARS flipped ) )
+@@ -3038,6 +2479,9 @@
+         if ( y_min == y_max )
+           return ras.error;  /* still Raster_Overflow */
+ 
++        FT_TRACE6(( "band [%d..%d]: to be bisected\n",
++                    y_min, y_max ));
++
+         y_mid = ( y_min + y_max ) >> 1;
+ 
+         band_stack[band_top++] = y_min;
+@@ -3045,9 +2489,12 @@
+       }
+       else
+       {
++        FT_TRACE6(( "band [%d..%d]: %hd profiles; %td bytes remaining\n",
++                    y_min, y_max, ras.num_Profs,
++                    (char*)ras.maxBuff - (char*)ras.top ));
++
+         if ( ras.fProfile )
+-          if ( Draw_Sweep( RAS_VAR ) )
+-             return ras.error;
++          Draw_Sweep( RAS_VAR );
+ 
+         if ( --band_top < 0 )
+           break;
+@@ -3076,53 +2523,48 @@
+   Render_Glyph( RAS_ARG )
+   {
+     FT_Error  error;
++    Long      buffer[FT_MAX_BLACK_POOL];
+ 
+ 
++    ras.buff     = buffer;
++    ras.sizeBuff = (&buffer)[1]; /* Points to right after buffer. */
++
+     Set_High_Precision( RAS_VARS ras.outline.flags &
+                                  FT_OUTLINE_HIGH_PRECISION );
+ 
++    ras.dropOutControl = 0;
++
+     if ( ras.outline.flags & FT_OUTLINE_IGNORE_DROPOUTS )
+-      ras.dropOutControl = 2;
+-    else
+-    {
+-      if ( ras.outline.flags & FT_OUTLINE_SMART_DROPOUTS )
+-        ras.dropOutControl = 4;
+-      else
+-        ras.dropOutControl = 0;
++      ras.dropOutControl |= 2;
+ 
+-      if ( !( ras.outline.flags & FT_OUTLINE_INCLUDE_STUBS ) )
+-        ras.dropOutControl += 1;
+-    }
++    if ( ras.outline.flags & FT_OUTLINE_SMART_DROPOUTS )
++      ras.dropOutControl |= 4;
+ 
+-    /* Vertical Sweep */
+-    FT_TRACE7(( "Vertical pass (ftraster)\n" ));
++    if ( !( ras.outline.flags & FT_OUTLINE_INCLUDE_STUBS ) )
++      ras.dropOutControl |= 1;
++
++    FT_TRACE6(( "BW Raster: precision 1/%d, dropout mode %d\n",
++                ras.precision, ras.dropOutControl ));
+ 
++    /* Vertical Sweep */
+     ras.Proc_Sweep_Init = Vertical_Sweep_Init;
+     ras.Proc_Sweep_Span = Vertical_Sweep_Span;
+     ras.Proc_Sweep_Drop = Vertical_Sweep_Drop;
+     ras.Proc_Sweep_Step = Vertical_Sweep_Step;
+ 
+-    ras.bWidth  = (UShort)ras.target.width;
+-    ras.bOrigin = (Byte*)ras.target.buffer;
+-
+-    if ( ras.target.pitch > 0 )
+-      ras.bOrigin += (Long)( ras.target.rows - 1 ) * ras.target.pitch;
+-
+-    error = Render_Single_Pass( RAS_VARS 0, 0, (Int)ras.target.rows - 1 );
++    error = Render_Single_Pass( RAS_VARS 0, 0, ras.bTop );
+     if ( error )
+       return error;
+ 
+     /* Horizontal Sweep */
+     if ( !( ras.outline.flags & FT_OUTLINE_SINGLE_PASS ) )
+     {
+-      FT_TRACE7(( "Horizontal pass (ftraster)\n" ));
+-
+       ras.Proc_Sweep_Init = Horizontal_Sweep_Init;
+       ras.Proc_Sweep_Span = Horizontal_Sweep_Span;
+       ras.Proc_Sweep_Drop = Horizontal_Sweep_Drop;
+       ras.Proc_Sweep_Step = Horizontal_Sweep_Step;
+ 
+-      error = Render_Single_Pass( RAS_VARS 1, 0, (Int)ras.target.width - 1 );
++      error = Render_Single_Pass( RAS_VARS 1, 0, ras.bRight );
+       if ( error )
+         return error;
+     }
+@@ -3233,8 +2675,6 @@
+     black_TWorker  worker[1];
+ #endif
+ 
+-    Long  buffer[FT_MAX_BLACK_POOL];
+-
+ 
+     if ( !raster )
+       return FT_THROW( Raster_Uninitialized );
+@@ -3243,7 +2683,7 @@
+       return FT_THROW( Invalid_Outline );
+ 
+     /* return immediately if the outline is empty */
+-    if ( outline->n_points == 0 || outline->n_contours <= 0 )
++    if ( outline->n_points == 0 || outline->n_contours == 0 )
+       return Raster_Err_Ok;
+ 
+     if ( !outline->contours || !outline->points )
+@@ -3269,10 +2709,14 @@
+       return FT_THROW( Invalid_Argument );
+ 
+     ras.outline = *outline;
+-    ras.target  = *target_map;
+ 
+-    ras.buff     = buffer;
+-    ras.sizeBuff = (&buffer)[1]; /* Points to right after buffer. */
++    ras.bTop    =   (Int)target_map->rows - 1;
++    ras.bRight  =   (Int)target_map->width - 1;
++    ras.bPitch  =   (Int)target_map->pitch;
++    ras.bOrigin = (PByte)target_map->buffer;
++
++    if ( ras.bPitch > 0 )
++      ras.bOrigin += ras.bTop * ras.bPitch;
+ 
+     return Render_Glyph( RAS_VAR );
+   }
+diff --git a/src/java.desktop/share/native/libfreetype/src/raster/ftraster.h b/src/java.desktop/share/native/libfreetype/src/raster/ftraster.h
+index b511b3a99..ad9cb1b9f 100644
+--- a/src/java.desktop/share/native/libfreetype/src/raster/ftraster.h
++++ b/src/java.desktop/share/native/libfreetype/src/raster/ftraster.h
+@@ -4,7 +4,7 @@
+  *
+  *   The FreeType glyph rasterizer (specification).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used
+diff --git a/src/java.desktop/share/native/libfreetype/src/raster/ftrend1.c b/src/java.desktop/share/native/libfreetype/src/raster/ftrend1.c
+index 6d442b1ff..fd9f174f2 100644
+--- a/src/java.desktop/share/native/libfreetype/src/raster/ftrend1.c
++++ b/src/java.desktop/share/native/libfreetype/src/raster/ftrend1.c
+@@ -4,7 +4,7 @@
+  *
+  *   The FreeType glyph rasterizer interface (body).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/raster/ftrend1.h b/src/java.desktop/share/native/libfreetype/src/raster/ftrend1.h
+index cec35c852..cf3e73c0a 100644
+--- a/src/java.desktop/share/native/libfreetype/src/raster/ftrend1.h
++++ b/src/java.desktop/share/native/libfreetype/src/raster/ftrend1.h
+@@ -4,7 +4,7 @@
+  *
+  *   The FreeType glyph rasterizer interface (specification).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/raster/rasterrs.h b/src/java.desktop/share/native/libfreetype/src/raster/rasterrs.h
+index 989d8b44b..326d42e04 100644
+--- a/src/java.desktop/share/native/libfreetype/src/raster/rasterrs.h
++++ b/src/java.desktop/share/native/libfreetype/src/raster/rasterrs.h
+@@ -4,7 +4,7 @@
+  *
+  *   monochrome renderer error codes (specification only).
+  *
+- * Copyright (C) 2001-2023 by
++ * Copyright (C) 2001-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/pngshim.c b/src/java.desktop/share/native/libfreetype/src/sfnt/pngshim.c
+index 33712162e..76181568a 100644
+--- a/src/java.desktop/share/native/libfreetype/src/sfnt/pngshim.c
++++ b/src/java.desktop/share/native/libfreetype/src/sfnt/pngshim.c
+@@ -4,7 +4,7 @@
+  *
+  *   PNG Bitmap glyph support.
+  *
+- * Copyright (C) 2013-2023 by
++ * Copyright (C) 2013-2024 by
+  * Google, Inc.
+  * Written by Stuart Gill and Behdad Esfahbod.
+  *
+diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/pngshim.h b/src/java.desktop/share/native/libfreetype/src/sfnt/pngshim.h
+index 903bd2bc3..6e7a5c08e 100644
+--- a/src/java.desktop/share/native/libfreetype/src/sfnt/pngshim.h
++++ b/src/java.desktop/share/native/libfreetype/src/sfnt/pngshim.h
+@@ -4,7 +4,7 @@
+  *
+  *   PNG Bitmap glyph support.
+  *
+- * Copyright (C) 2013-2023 by
++ * Copyright (C) 2013-2024 by
+  * Google, Inc.
+  * Written by Stuart Gill and Behdad Esfahbod.
+  *
+diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/sfdriver.c b/src/java.desktop/share/native/libfreetype/src/sfnt/sfdriver.c
+index 0925940b0..81072207b 100644
+--- a/src/java.desktop/share/native/libfreetype/src/sfnt/sfdriver.c
++++ b/src/java.desktop/share/native/libfreetype/src/sfnt/sfdriver.c
+@@ -4,7 +4,7 @@
+  *
+  *   High-level SFNT driver interface (body).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+@@ -49,6 +49,10 @@
+ #include 
+ #endif
+ 
++#ifdef TT_CONFIG_OPTION_GPOS_KERNING
++#include "ttgpos.h"
++#endif
++
+ #include "ttcmap.h"
+ #include "ttkern.h"
+ #include "ttmtx.h"
+@@ -1249,6 +1253,12 @@
+ #define PUT_PS_NAMES( a )  a
+ #else
+ #define PUT_PS_NAMES( a )  NULL
++#endif
++
++#ifdef TT_CONFIG_OPTION_GPOS_KERNING
++#define PUT_GPOS_KERNING( a )  a
++#else
++#define PUT_GPOS_KERNING( a )  NULL
+ #endif
+ 
+   FT_DEFINE_SFNT_INTERFACE(
+@@ -1274,6 +1284,8 @@
+     tt_face_free_name,      /* TT_Free_Table_Func      free_name       */
+ 
+     tt_face_load_kern,      /* TT_Load_Table_Func      load_kern       */
++    PUT_GPOS_KERNING( tt_face_load_gpos ),
++                            /* TT_Load_Table_Func      load_gpos       */
+     tt_face_load_gasp,      /* TT_Load_Table_Func      load_gasp       */
+     tt_face_load_pclt,      /* TT_Load_Table_Func      load_init       */
+ 
+@@ -1292,6 +1304,9 @@
+     /* since version 2.1.8 */
+     tt_face_get_kerning,    /* TT_Face_GetKerningFunc  get_kerning     */
+ 
++    PUT_GPOS_KERNING( tt_face_get_gpos_kerning ),
++                           /* TT_Face_GetKerningFunc  get_gpos_kerning */
++
+     /* since version 2.2 */
+     tt_face_load_font_dir,  /* TT_Load_Table_Func      load_font_dir   */
+     tt_face_load_hmtx,      /* TT_Load_Metrics_Func    load_hmtx       */
+diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/sfdriver.h b/src/java.desktop/share/native/libfreetype/src/sfnt/sfdriver.h
+index 2445958b6..6f71489fd 100644
+--- a/src/java.desktop/share/native/libfreetype/src/sfnt/sfdriver.h
++++ b/src/java.desktop/share/native/libfreetype/src/sfnt/sfdriver.h
+@@ -4,7 +4,7 @@
+  *
+  *   High-level SFNT driver interface (specification).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/sferrors.h b/src/java.desktop/share/native/libfreetype/src/sfnt/sferrors.h
+index e7a8eb04b..d3ca1d9aa 100644
+--- a/src/java.desktop/share/native/libfreetype/src/sfnt/sferrors.h
++++ b/src/java.desktop/share/native/libfreetype/src/sfnt/sferrors.h
+@@ -4,7 +4,7 @@
+  *
+  *   SFNT error codes (specification only).
+  *
+- * Copyright (C) 2001-2023 by
++ * Copyright (C) 2001-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/sfobjs.c b/src/java.desktop/share/native/libfreetype/src/sfnt/sfobjs.c
+index f5d66ef84..6ee4e5e93 100644
+--- a/src/java.desktop/share/native/libfreetype/src/sfnt/sfobjs.c
++++ b/src/java.desktop/share/native/libfreetype/src/sfnt/sfobjs.c
+@@ -4,7 +4,7 @@
+  *
+  *   SFNT object management (base).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+@@ -40,6 +40,10 @@
+ #include "ttbdf.h"
+ #endif
+ 
++#ifdef TT_CONFIG_OPTION_GPOS_KERNING
++#include "ttgpos.h"
++#endif
++
+ 
+   /**************************************************************************
+    *
+@@ -1026,6 +1030,10 @@
+     LOAD_( gasp );
+     LOAD_( kern );
+ 
++#ifdef TT_CONFIG_OPTION_GPOS_KERNING
++    LOAD_( gpos );
++#endif
++
+     face->root.num_glyphs = face->max_profile.numGlyphs;
+ 
+     /* Bit 8 of the `fsSelection' field in the `OS/2' table denotes  */
+@@ -1119,7 +1127,11 @@
+         flags |= FT_FACE_FLAG_VERTICAL;
+ 
+       /* kerning available ? */
+-      if ( TT_FACE_HAS_KERNING( face ) )
++      if ( TT_FACE_HAS_KERNING( face )
++#ifdef TT_CONFIG_OPTION_GPOS_KERNING
++           || face->gpos_kerning_available
++#endif
++         )
+         flags |= FT_FACE_FLAG_KERNING;
+ 
+ #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+@@ -1470,6 +1482,11 @@
+     /* freeing the kerning table */
+     tt_face_done_kern( face );
+ 
++#ifdef TT_CONFIG_OPTION_GPOS_KERNING
++    /* freeing the GPOS table */
++    tt_face_done_gpos( face );
++#endif
++
+     /* freeing the collection table */
+     FT_FREE( face->ttc_header.offsets );
+     face->ttc_header.count = 0;
+diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/sfobjs.h b/src/java.desktop/share/native/libfreetype/src/sfnt/sfobjs.h
+index 906aebbf9..90847d957 100644
+--- a/src/java.desktop/share/native/libfreetype/src/sfnt/sfobjs.h
++++ b/src/java.desktop/share/native/libfreetype/src/sfnt/sfobjs.h
+@@ -4,7 +4,7 @@
+  *
+  *   SFNT object management (specification).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff.c b/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff.c
+index 7c0ce2205..14514bf95 100644
+--- a/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff.c
++++ b/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff.c
+@@ -4,7 +4,7 @@
+  *
+  *   WOFF format management (base).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+@@ -18,6 +18,7 @@
+ 
+ #include "sfwoff.h"
+ #include 
++#include 
+ #include 
+ #include 
+ #include 
+@@ -149,6 +150,7 @@
+     /* Miscellaneous checks. */
+     if ( woff.length != stream->size                              ||
+          woff.num_tables == 0                                     ||
++         woff.num_tables >  0xFFFU                                ||
+          44 + woff.num_tables * 20UL >= woff.length               ||
+          12 + woff.num_tables * 16UL >= woff.totalSfntSize        ||
+          ( woff.totalSfntSize & 3 ) != 0                          ||
+@@ -169,21 +171,11 @@
+ 
+     /* Write sfnt header. */
+     {
+-      FT_UInt  searchRange, entrySelector, rangeShift, x;
++      FT_Int  entrySelector = FT_MSB( woff.num_tables );
++      FT_Int  searchRange   = ( 1 << entrySelector ) * 16;
++      FT_Int  rangeShift    = woff.num_tables * 16 - searchRange;
+ 
+ 
+-      x             = woff.num_tables;
+-      entrySelector = 0;
+-      while ( x )
+-      {
+-        x            >>= 1;
+-        entrySelector += 1;
+-      }
+-      entrySelector--;
+-
+-      searchRange = ( 1 << entrySelector ) * 16;
+-      rangeShift  = woff.num_tables * 16 - searchRange;
+-
+       WRITE_ULONG ( sfnt_header, woff.flavor );
+       WRITE_USHORT( sfnt_header, woff.num_tables );
+       WRITE_USHORT( sfnt_header, searchRange );
+diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff.h b/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff.h
+index d43842273..a04735ffe 100644
+--- a/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff.h
++++ b/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff.h
+@@ -4,7 +4,7 @@
+  *
+  *   WOFFF format management (specification).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff2.c b/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff2.c
+index 2be44a347..589b3e0c6 100644
+--- a/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff2.c
++++ b/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff2.c
+@@ -4,7 +4,7 @@
+  *
+  *   WOFF2 format management (base).
+  *
+- * Copyright (C) 2019-2023 by
++ * Copyright (C) 2019-2024 by
+  * Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+@@ -18,6 +18,7 @@
+ #include "sfwoff2.h"
+ #include "woff2tags.h"
+ #include 
++#include 
+ #include 
+ #include 
+ 
+@@ -289,23 +290,15 @@
+     FT_ULong  checksum     = 0;
+     FT_ULong  aligned_size = size & ~3UL;
+     FT_ULong  i;
+-    FT_ULong  v;
++    FT_Int    shift;
+ 
+ 
+     for ( i = 0; i < aligned_size; i += 4 )
+-      checksum += ( (FT_ULong)buf[i    ] << 24 ) |
+-                  ( (FT_ULong)buf[i + 1] << 16 ) |
+-                  ( (FT_ULong)buf[i + 2] <<  8 ) |
+-                  ( (FT_ULong)buf[i + 3] <<  0 );
++      checksum += FT_NEXT_ULONG( buf );
+ 
+-    /* If size is not aligned to 4, treat as if it is padded with 0s. */
+-    if ( size != aligned_size )
+-    {
+-      v = 0;
+-      for ( i = aligned_size ; i < size; ++i )
+-        v |= (FT_ULong)buf[i] << ( 24 - 8 * ( i & 3 ) );
+-      checksum += v;
+-    }
++    /* remaining bytes can be shifted and added one at a time */
++    for ( shift = 24; i < size; i++, shift -= 8 )
++      checksum += (FT_UInt32)FT_NEXT_BYTE( buf ) << shift;
+ 
+     return checksum;
+   }
+@@ -1799,7 +1792,6 @@
+ 
+     FT_Byte*   sfnt        = NULL;
+     FT_Stream  sfnt_stream = NULL;
+-    FT_Byte*   sfnt_header;
+     FT_ULong   sfnt_size;
+ 
+     FT_Byte*  uncompressed_buf = NULL;
+@@ -1853,6 +1845,7 @@
+     /* Miscellaneous checks. */
+     if ( woff2.length != stream->size                               ||
+          woff2.num_tables == 0                                      ||
++         woff2.num_tables >  0xFFFU                                 ||
+          48 + woff2.num_tables * 20UL >= woff2.length               ||
+          ( woff2.metaOffset == 0 && ( woff2.metaLength != 0     ||
+                                       woff2.metaOrigLength != 0 ) ) ||
+@@ -2143,6 +2136,13 @@
+       WOFF2_TtcFont  ttc_font = woff2.ttc_fonts + face_index;
+ 
+ 
++      if ( ttc_font->num_tables == 0 || ttc_font->num_tables > 0xFFFU )
++      {
++        FT_ERROR(( "woff2_open_font: invalid WOFF2 CollectionFontEntry\n" ));
++        error = FT_THROW( Invalid_Table );
++        goto Exit;
++      }
++
+       /* Create a temporary array. */
+       if ( FT_QNEW_ARRAY( temp_indices,
+                           ttc_font->num_tables ) )
+@@ -2198,27 +2198,15 @@
+          FT_NEW( sfnt_stream )        )
+       goto Exit;
+ 
+-    sfnt_header = sfnt;
+-
+-    WRITE_ULONG( sfnt_header, woff2.flavor );
+-
+-    if ( woff2.num_tables )
+     {
+-      FT_UInt  searchRange, entrySelector, rangeShift, x;
++      FT_Byte*  sfnt_header = sfnt;
+ 
++      FT_Int  entrySelector = FT_MSB( woff2.num_tables );
++      FT_Int  searchRange   = ( 1 << entrySelector ) * 16;
++      FT_Int  rangeShift    = woff2.num_tables * 16 - searchRange;
+ 
+-      x             = woff2.num_tables;
+-      entrySelector = 0;
+-      while ( x )
+-      {
+-        x            >>= 1;
+-        entrySelector += 1;
+-      }
+-      entrySelector--;
+-
+-      searchRange = ( 1 << entrySelector ) * 16;
+-      rangeShift  = ( woff2.num_tables * 16 ) - searchRange;
+ 
++      WRITE_ULONG ( sfnt_header, woff2.flavor );
+       WRITE_USHORT( sfnt_header, woff2.num_tables );
+       WRITE_USHORT( sfnt_header, searchRange );
+       WRITE_USHORT( sfnt_header, entrySelector );
+diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff2.h b/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff2.h
+index 4901286ee..f41140648 100644
+--- a/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff2.h
++++ b/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff2.h
+@@ -4,7 +4,7 @@
+  *
+  *   WOFFF2 format management (specification).
+  *
+- * Copyright (C) 2019-2023 by
++ * Copyright (C) 2019-2024 by
+  * Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmap.c b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmap.c
+index 9ba25dcbc..28f4d1173 100644
+--- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmap.c
++++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmap.c
+@@ -4,7 +4,7 @@
+  *
+  *   TrueType character mapping table (cmap) support (body).
+  *
+- * Copyright (C) 2002-2023 by
++ * Copyright (C) 2002-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmap.h b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmap.h
+index ff52917ed..e2c5e72bf 100644
+--- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmap.h
++++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmap.h
+@@ -4,7 +4,7 @@
+  *
+  *   TrueType character mapping table (cmap) support (specification).
+  *
+- * Copyright (C) 2002-2023 by
++ * Copyright (C) 2002-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmapc.h b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmapc.h
+index 0af48c247..370898363 100644
+--- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmapc.h
++++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmapc.h
+@@ -4,7 +4,7 @@
+  *
+  *   TT CMAP classes definitions (specification only).
+  *
+- * Copyright (C) 2009-2023 by
++ * Copyright (C) 2009-2024 by
+  * Oran Agra and Mickey Gabel.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcolr.c b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcolr.c
+index 281e7135e..b37658dde 100644
+--- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcolr.c
++++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcolr.c
+@@ -4,7 +4,7 @@
+  *
+  *   TrueType and OpenType colored glyph layer support (body).
+  *
+- * Copyright (C) 2018-2023 by
++ * Copyright (C) 2018-2024 by
+  * David Turner, Robert Wilhelm, Dominik Röttsches, and Werner Lemberg.
+  *
+  * Originally written by Shao Yu Zhang .
+@@ -208,18 +208,19 @@
+     colr->num_base_glyphs = FT_NEXT_USHORT( p );
+     base_glyph_offset     = FT_NEXT_ULONG( p );
+ 
+-    if ( base_glyph_offset >= table_size )
++    if ( table_size <= base_glyph_offset )
+       goto InvalidTable;
+-    if ( colr->num_base_glyphs * BASE_GLYPH_SIZE >
+-           table_size - base_glyph_offset )
++    if ( ( table_size - base_glyph_offset ) / BASE_GLYPH_SIZE
++             < colr->num_base_glyphs )
+       goto InvalidTable;
+ 
+     layer_offset     = FT_NEXT_ULONG( p );
+     colr->num_layers = FT_NEXT_USHORT( p );
+ 
+-    if ( layer_offset >= table_size )
++    if ( table_size <= layer_offset )
+       goto InvalidTable;
+-    if ( colr->num_layers * LAYER_SIZE > table_size - layer_offset )
++    if ( ( table_size - layer_offset ) / LAYER_SIZE
++             < colr->num_layers )
+       goto InvalidTable;
+ 
+     if ( colr->version == 1 )
+@@ -229,14 +230,14 @@
+ 
+       base_glyphs_offset_v1 = FT_NEXT_ULONG( p );
+ 
+-      if ( base_glyphs_offset_v1 >= table_size - 4 )
++      if ( table_size - 4 <= base_glyphs_offset_v1 )
+         goto InvalidTable;
+ 
+       p1                 = (FT_Byte*)( table + base_glyphs_offset_v1 );
+       num_base_glyphs_v1 = FT_PEEK_ULONG( p1 );
+ 
+-      if ( num_base_glyphs_v1 * BASE_GLYPH_PAINT_RECORD_SIZE >
+-             table_size - base_glyphs_offset_v1 )
++      if ( ( table_size - base_glyphs_offset_v1 ) / BASE_GLYPH_PAINT_RECORD_SIZE
++               < num_base_glyphs_v1 )
+         goto InvalidTable;
+ 
+       colr->num_base_glyphs_v1 = num_base_glyphs_v1;
+@@ -244,19 +245,19 @@
+ 
+       layer_offset_v1 = FT_NEXT_ULONG( p );
+ 
+-      if ( layer_offset_v1 >= table_size )
++      if ( table_size <= layer_offset_v1 )
+         goto InvalidTable;
+ 
+       if ( layer_offset_v1 )
+       {
+-        if ( layer_offset_v1 >= table_size - 4 )
++        if ( table_size - 4 <= layer_offset_v1 )
+           goto InvalidTable;
+ 
+         p1            = (FT_Byte*)( table + layer_offset_v1 );
+         num_layers_v1 = FT_PEEK_ULONG( p1 );
+ 
+-        if ( num_layers_v1 * LAYER_V1_LIST_PAINT_OFFSET_SIZE >
+-               table_size - layer_offset_v1 )
++        if ( ( table_size - layer_offset_v1 ) / LAYER_V1_LIST_PAINT_OFFSET_SIZE
++                < num_layers_v1 )
+           goto InvalidTable;
+ 
+         colr->num_layers_v1 = num_layers_v1;
+@@ -279,7 +280,7 @@
+ 
+       clip_list_offset = FT_NEXT_ULONG( p );
+ 
+-      if ( clip_list_offset >= table_size )
++      if ( table_size <= clip_list_offset )
+         goto InvalidTable;
+ 
+       if ( clip_list_offset )
+@@ -311,7 +312,7 @@
+           goto InvalidTable;
+ 
+         var_store_offset = FT_NEXT_ULONG( p );
+-        if ( var_store_offset >= table_size )
++        if ( table_size <= var_store_offset )
+           goto InvalidTable;
+ 
+         if ( var_store_offset )
+@@ -661,6 +662,7 @@
+       FT_UInt32  first_layer_index;
+ 
+ 
++      ENSURE_READ_BYTES( 5 );
+       num_layers = FT_NEXT_BYTE( p );
+       if ( num_layers > colr->num_layers_v1 )
+         return 0;
+@@ -1278,7 +1280,8 @@
+ 
+     while ( min < max )
+     {
+-      FT_UInt  mid = min + ( max - min ) / 2;
++      FT_UInt    mid = min + ( max - min ) / 2;
++      FT_UShort  gid;
+ 
+       /*
+        * `base_glyph_begin` is the beginning of `BaseGlyphV1List`;
+@@ -1287,8 +1290,7 @@
+        */
+       FT_Byte  *p = base_glyph_begin + 4 + mid * BASE_GLYPH_PAINT_RECORD_SIZE;
+ 
+-      FT_UShort  gid = FT_NEXT_USHORT( p );
+-
++      gid = FT_NEXT_USHORT( p );
+ 
+       if ( gid < glyph_id )
+         min = mid + 1;
+diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcolr.h b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcolr.h
+index 20c85f035..30031464c 100644
+--- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcolr.h
++++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcolr.h
+@@ -4,7 +4,7 @@
+  *
+  *   TrueType and OpenType colored glyph layer support (specification).
+  *
+- * Copyright (C) 2018-2023 by
++ * Copyright (C) 2018-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * Originally written by Shao Yu Zhang .
+diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcpal.c b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcpal.c
+index 46ae08596..997eb869f 100644
+--- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcpal.c
++++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcpal.c
+@@ -4,7 +4,7 @@
+  *
+  *   TrueType and OpenType color palette support (body).
+  *
+- * Copyright (C) 2018-2023 by
++ * Copyright (C) 2018-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * Originally written by Shao Yu Zhang .
+diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcpal.h b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcpal.h
+index 8e9913f0c..bb301ae88 100644
+--- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcpal.h
++++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcpal.h
+@@ -4,7 +4,7 @@
+  *
+  *   TrueType and OpenType color palette support (specification).
+  *
+- * Copyright (C) 2018-2023 by
++ * Copyright (C) 2018-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * Originally written by Shao Yu Zhang .
+diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttkern.c b/src/java.desktop/share/native/libfreetype/src/sfnt/ttkern.c
+index a47d08bd6..f0411366a 100644
+--- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttkern.c
++++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttkern.c
+@@ -5,7 +5,7 @@
+  *   Load the basic TrueType kerning table.  This doesn't handle
+  *   kerning data within the GPOS table at the moment.
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttkern.h b/src/java.desktop/share/native/libfreetype/src/sfnt/ttkern.h
+index 960c7da49..a54e51df1 100644
+--- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttkern.h
++++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttkern.h
+@@ -5,7 +5,7 @@
+  *   Load the basic TrueType kerning table.  This doesn't handle
+  *   kerning data within the GPOS table at the moment.
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttload.c b/src/java.desktop/share/native/libfreetype/src/sfnt/ttload.c
+index 7b44e9cd2..c3a5fae2c 100644
+--- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttload.c
++++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttload.c
+@@ -5,7 +5,7 @@
+  *   Load the basic TrueType tables, i.e., tables that can be either in
+  *   TTF or OTF fonts (body).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+@@ -1046,7 +1046,7 @@
+   FT_LOCAL_DEF( void )
+   tt_face_free_name( TT_Face  face )
+   {
+-    FT_Memory     memory = face->root.driver->root.memory;
++    FT_Memory     memory = face->root.memory;
+     TT_NameTable  table  = &face->name_table;
+ 
+ 
+diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttload.h b/src/java.desktop/share/native/libfreetype/src/sfnt/ttload.h
+index 1499dd573..2b1d62d9b 100644
+--- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttload.h
++++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttload.h
+@@ -5,7 +5,7 @@
+  *   Load the basic TrueType tables, i.e., tables that can be either in
+  *   TTF or OTF fonts (specification).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttmtx.c b/src/java.desktop/share/native/libfreetype/src/sfnt/ttmtx.c
+index 38ee9ae72..278841185 100644
+--- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttmtx.c
++++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttmtx.c
+@@ -4,7 +4,7 @@
+  *
+  *   Load the metrics tables common to TTF and OTF fonts (body).
+  *
+- * Copyright (C) 2006-2023 by
++ * Copyright (C) 2006-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttmtx.h b/src/java.desktop/share/native/libfreetype/src/sfnt/ttmtx.h
+index 56d2b6276..34b3c0e18 100644
+--- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttmtx.h
++++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttmtx.h
+@@ -4,7 +4,7 @@
+  *
+  *   Load the metrics tables common to TTF and OTF fonts (specification).
+  *
+- * Copyright (C) 2006-2023 by
++ * Copyright (C) 2006-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttpost.c b/src/java.desktop/share/native/libfreetype/src/sfnt/ttpost.c
+index 1dfad4298..5698a62c8 100644
+--- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttpost.c
++++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttpost.c
+@@ -5,7 +5,7 @@
+  *   PostScript name table processing for TrueType and OpenType fonts
+  *   (body).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+@@ -204,8 +204,8 @@
+     /* now load the name strings */
+     if ( num_names )
+     {
+-      FT_ULong   p;
+-      FT_Byte*   strings;
++      FT_Byte*   p;
++      FT_Byte*   p_end;
+ 
+ 
+       post_len -= (FT_ULong)num_glyphs * 2;
+@@ -214,36 +214,36 @@
+                                     post_len + 1 ) )
+         goto Fail;
+ 
+-      strings = (FT_Byte*)( name_strings + num_names );
+-      if ( FT_STREAM_READ( strings, post_len ) )
++      p = (FT_Byte*)( name_strings + num_names );
++      if ( FT_STREAM_READ( p, post_len ) )
+         goto Fail;
+ 
++      p_end = p + post_len;
++
+       /* convert from Pascal- to C-strings and set pointers */
+-      for ( p = 0, n = 0; p < post_len && n < num_names; n++ )
++      for ( n = 0; p < p_end && n < num_names; n++ )
+       {
+-        FT_UInt  len = strings[p];
++        FT_UInt  len = *p;
+ 
+ 
+-        if ( len > 63U )
+-        {
+-          error = FT_THROW( Invalid_File_Format );
+-          goto Fail;
+-        }
++        /* names in the Adobe Glyph List are shorter than 40 characters */
++        if ( len >= 40U )
++          FT_TRACE4(( "load_format_20: unusual %u-char name found\n", len ));
+ 
+-        strings[p]      = 0;
+-        name_strings[n] = strings + p + 1;
+-        p              += len + 1;
++        *p++            = 0;
++        name_strings[n] = p;
++        p              += len;
+       }
+-      strings[post_len] = 0;
++      *p_end = 0;
+ 
+       /* deal with missing or insufficient string data */
+       if ( n < num_names )
+       {
+         FT_TRACE4(( "load_format_20: %hu PostScript names are truncated\n",
+-                    num_names - n ));
++                    (FT_UShort)( num_names - n ) ));
+ 
+         for ( ; n < num_names; n++ )
+-          name_strings[n] = strings + post_len;
++          name_strings[n] = p_end;
+       }
+     }
+ 
+@@ -436,13 +436,8 @@
+ 
+     format = face->postscript.FormatType;
+ 
+-    if ( format == 0x00010000L )
+-    {
+-      if ( idx < 258 )                    /* paranoid checking */
+-        *PSname = MAC_NAME( idx );
+-    }
+-    else if ( format == 0x00020000L ||
+-              format == 0x00025000L )
++    if ( format == 0x00020000L ||
++         format == 0x00025000L )
+     {
+       TT_Post_Names  names = &face->postscript_names;
+ 
+@@ -466,6 +461,11 @@
+       }
+     }
+ 
++    /* version 1.0 is only valid with 258 glyphs */
++    else if ( format == 0x00010000L              &&
++              face->max_profile.numGlyphs == 258 )
++      *PSname = MAC_NAME( idx );
++
+     /* nothing to do for format == 0x00030000L */
+ 
+   End:
+diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttpost.h b/src/java.desktop/share/native/libfreetype/src/sfnt/ttpost.h
+index 528f1c5f2..150db6c39 100644
+--- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttpost.h
++++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttpost.h
+@@ -5,7 +5,7 @@
+  *   PostScript name table processing for TrueType and OpenType fonts
+  *   (specification).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttsbit.c b/src/java.desktop/share/native/libfreetype/src/sfnt/ttsbit.c
+index 03f90a628..cb3a8abf1 100644
+--- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttsbit.c
++++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttsbit.c
+@@ -4,7 +4,7 @@
+  *
+  *   TrueType and OpenType embedded bitmap support (body).
+  *
+- * Copyright (C) 2005-2023 by
++ * Copyright (C) 2005-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * Copyright 2013 by Google, Inc.
+diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttsbit.h b/src/java.desktop/share/native/libfreetype/src/sfnt/ttsbit.h
+index 07e2db461..96f80a584 100644
+--- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttsbit.h
++++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttsbit.h
+@@ -4,7 +4,7 @@
+  *
+  *   TrueType and OpenType embedded bitmap support (specification).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/woff2tags.c b/src/java.desktop/share/native/libfreetype/src/sfnt/woff2tags.c
+index eeedd9906..532ccfa17 100644
+--- a/src/java.desktop/share/native/libfreetype/src/sfnt/woff2tags.c
++++ b/src/java.desktop/share/native/libfreetype/src/sfnt/woff2tags.c
+@@ -4,7 +4,7 @@
+  *
+  *   WOFF2 Font table tags (base).
+  *
+- * Copyright (C) 2019-2023 by
++ * Copyright (C) 2019-2024 by
+  * Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/woff2tags.h b/src/java.desktop/share/native/libfreetype/src/sfnt/woff2tags.h
+index 1201848e5..d03b4b41b 100644
+--- a/src/java.desktop/share/native/libfreetype/src/sfnt/woff2tags.h
++++ b/src/java.desktop/share/native/libfreetype/src/sfnt/woff2tags.h
+@@ -4,7 +4,7 @@
+  *
+  *   WOFF2 Font table tags (specification).
+  *
+- * Copyright (C) 2019-2023 by
++ * Copyright (C) 2019-2024 by
+  * Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/smooth/ftgrays.c b/src/java.desktop/share/native/libfreetype/src/smooth/ftgrays.c
+index 0918272f8..b7c0632a6 100644
+--- a/src/java.desktop/share/native/libfreetype/src/smooth/ftgrays.c
++++ b/src/java.desktop/share/native/libfreetype/src/smooth/ftgrays.c
+@@ -4,7 +4,7 @@
+  *
+  *   A new `perfect' anti-aliasing renderer (body).
+  *
+- * Copyright (C) 2000-2023 by
++ * Copyright (C) 2000-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+@@ -489,7 +489,7 @@ typedef ptrdiff_t  FT_PtrDist;
+ 
+   typedef struct  gray_TWorker_
+   {
+-    ft_jmp_buf  jump_buffer;
++    FT_BBox     cbox;
+ 
+     TCoord  min_ex, max_ex;  /* min and max integer pixel coordinates */
+     TCoord  min_ey, max_ey;
+@@ -510,6 +510,8 @@ typedef ptrdiff_t  FT_PtrDist;
+     FT_Raster_Span_Func  render_span;
+     void*                render_span_data;
+ 
++    ft_jmp_buf  jump_buffer;
++
+   } gray_TWorker, *gray_PWorker;
+ 
+ #if defined( _MSC_VER )
+@@ -997,49 +999,12 @@ typedef ptrdiff_t  FT_PtrDist;
+ #endif
+ 
+   /*
+-   * Benchmarking shows that using DDA to flatten the quadratic Bézier arcs
+-   * is slightly faster in the following cases:
+-   *
+-   *   - When the host CPU is 64-bit.
+-   *   - When SSE2 SIMD registers and instructions are available (even on
+-   *     x86).
+-   *
+-   * For other cases, using binary splits is actually slightly faster.
+-   */
+-#if ( defined( __SSE2__ )                          ||   \
+-      defined( __x86_64__ )                        ||   \
+-      defined( _M_AMD64 )                          ||   \
+-      ( defined( _M_IX86_FP ) && _M_IX86_FP >= 2 ) ) && \
+-    !defined( __VMS )
+-#  define FT_SSE2 1
+-#else
+-#  define FT_SSE2 0
+-#endif
+-
+-#if FT_SSE2                || \
+-    defined( __aarch64__ ) || \
+-    defined( _M_ARM64 )
+-#  define BEZIER_USE_DDA  1
+-#else
+-#  define BEZIER_USE_DDA  0
+-#endif
+-
+-  /*
+-   * For now, the code that depends on `BEZIER_USE_DDA` requires `FT_Int64`
+-   * to be defined.  If `FT_INT64` is not defined, meaning there is no
+-   * 64-bit type available, disable it to avoid compilation errors.  See for
+-   * example https://gitlab.freedesktop.org/freetype/freetype/-/issues/1071.
++   * For now, the code that uses DDA to render conic curves requires
++   * `FT_Int64` to be defined.  See for example
++   *    https://gitlab.freedesktop.org/freetype/freetype/-/issues/1071.
+    */
+-#if !defined( FT_INT64 )
+-#  undef BEZIER_USE_DDA
+-#  define BEZIER_USE_DDA  0
+-#endif
+-
+-#if BEZIER_USE_DDA
+ 
+-#if FT_SSE2
+-#  include 
+-#endif
++#ifdef FT_INT64
+ 
+ #define LEFT_SHIFT( a, b )  (FT_Int64)( (FT_UInt64)(a) << (b) )
+ 
+@@ -1095,16 +1060,17 @@ typedef ptrdiff_t  FT_PtrDist;
+       return;
+     }
+ 
+-    /* We can calculate the number of necessary bisections because  */
++    /* We can calculate the number of necessary segments because    */
+     /* each bisection predictably reduces deviation exactly 4-fold. */
+     /* Even 32-bit deviation would vanish after 16 bisections.      */
+-    shift = 0;
++    shift = 16;
+     do
+     {
+-      dx   >>= 2;
+-      shift += 1;
++      dx >>= 2;
++      shift--;
+ 
+     } while ( dx > ONE_PIXEL / 4 );
++    count = 0x10000U >> shift;
+ 
+     /*
+      * The (P0,P1,P2) arc equation, for t in [0,1] range:
+@@ -1150,75 +1116,19 @@ typedef ptrdiff_t  FT_PtrDist;
+      *             = (B << (33 - N)) + (A << (32 - 2*N))
+      */
+ 
+-#if FT_SSE2
+-    /* Experience shows that for small shift values, */
+-    /* SSE2 is actually slower.                      */
+-    if ( shift > 2 )
+-    {
+-      union
+-      {
+-        struct { FT_Int64  ax, ay, bx, by; }  i;
+-        struct { __m128i  a, b; }  vec;
+-
+-      } u;
+-
+-      union
+-      {
+-        struct { FT_Int32  px_lo, px_hi, py_lo, py_hi; }  i;
+-        __m128i  vec;
+-
+-      } v;
+-
+-      __m128i  a, b;
+-      __m128i  r, q, q2;
+-      __m128i  p;
+-
+-
+-      u.i.ax = ax;
+-      u.i.ay = ay;
+-      u.i.bx = bx;
+-      u.i.by = by;
+-
+-      a = _mm_load_si128( &u.vec.a );
+-      b = _mm_load_si128( &u.vec.b );
+-
+-      r  = _mm_slli_epi64( a, 33 - 2 * shift );
+-      q  = _mm_slli_epi64( b, 33 - shift );
+-      q2 = _mm_slli_epi64( a, 32 - 2 * shift );
+-
+-      q = _mm_add_epi64( q2, q );
+-
+-      v.i.px_lo = 0;
+-      v.i.px_hi = p0.x;
+-      v.i.py_lo = 0;
+-      v.i.py_hi = p0.y;
+-
+-      p = _mm_load_si128( &v.vec );
+-
+-      for ( count = 1U << shift; count > 0; count-- )
+-      {
+-        p = _mm_add_epi64( p, q );
+-        q = _mm_add_epi64( q, r );
+-
+-        _mm_store_si128( &v.vec, p );
+-
+-        gray_render_line( RAS_VAR_ v.i.px_hi, v.i.py_hi );
+-      }
+-
+-      return;
+-    }
+-#endif  /* FT_SSE2 */
++    rx = LEFT_SHIFT( ax, shift + shift );
++    ry = LEFT_SHIFT( ay, shift + shift );
+ 
+-    rx = LEFT_SHIFT( ax, 33 - 2 * shift );
+-    ry = LEFT_SHIFT( ay, 33 - 2 * shift );
++    qx = LEFT_SHIFT( bx, shift + 17 ) + rx;
++    qy = LEFT_SHIFT( by, shift + 17 ) + ry;
+ 
+-    qx = LEFT_SHIFT( bx, 33 - shift ) + LEFT_SHIFT( ax, 32 - 2 * shift );
+-    qy = LEFT_SHIFT( by, 33 - shift ) + LEFT_SHIFT( ay, 32 - 2 * shift );
++    rx *= 2;
++    ry *= 2;
+ 
+     px = LEFT_SHIFT( p0.x, 32 );
+     py = LEFT_SHIFT( p0.y, 32 );
+ 
+-    for ( count = 1U << shift; count > 0; count-- )
++    do
+     {
+       px += qx;
+       py += qy;
+@@ -1227,10 +1137,10 @@ typedef ptrdiff_t  FT_PtrDist;
+ 
+       gray_render_line( RAS_VAR_ (FT_Pos)( px >> 32 ),
+                                  (FT_Pos)( py >> 32 ) );
+-    }
++    } while ( --count );
+   }
+ 
+-#else  /* !BEZIER_USE_DDA */
++#else  /* !FT_INT64 */
+ 
+   /*
+    * Note that multiple attempts to speed up the function below
+@@ -1324,7 +1234,7 @@ typedef ptrdiff_t  FT_PtrDist;
+     } while ( --draw );
+   }
+ 
+-#endif  /* !BEZIER_USE_DDA */
++#endif  /* !FT_INT64 */
+ 
+ 
+   /*
+@@ -1486,139 +1396,6 @@ typedef ptrdiff_t  FT_PtrDist;
+   }
+ 
+ 
+-  static void
+-  gray_sweep( RAS_ARG )
+-  {
+-    int  fill = ( ras.outline.flags & FT_OUTLINE_EVEN_ODD_FILL ) ? 0x100
+-                                                                 : INT_MIN;
+-    int  coverage;
+-    int  y;
+-
+-
+-    for ( y = ras.min_ey; y < ras.max_ey; y++ )
+-    {
+-      PCell   cell  = ras.ycells[y - ras.min_ey];
+-      TCoord  x     = ras.min_ex;
+-      TArea   cover = 0;
+-
+-      unsigned char*  line = ras.target.origin - ras.target.pitch * y;
+-
+-
+-      for ( ; cell != ras.cell_null; cell = cell->next )
+-      {
+-        TArea  area;
+-
+-
+-        if ( cover != 0 && cell->x > x )
+-        {
+-          FT_FILL_RULE( coverage, cover, fill );
+-          FT_GRAY_SET( line + x, coverage, cell->x - x );
+-        }
+-
+-        cover += (TArea)cell->cover * ( ONE_PIXEL * 2 );
+-        area   = cover - cell->area;
+-
+-        if ( area != 0 && cell->x >= ras.min_ex )
+-        {
+-          FT_FILL_RULE( coverage, area, fill );
+-          line[cell->x] = (unsigned char)coverage;
+-        }
+-
+-        x = cell->x + 1;
+-      }
+-
+-      if ( cover != 0 )  /* only if cropped */
+-      {
+-        FT_FILL_RULE( coverage, cover, fill );
+-        FT_GRAY_SET( line + x, coverage, ras.max_ex - x );
+-      }
+-    }
+-  }
+-
+-
+-  static void
+-  gray_sweep_direct( RAS_ARG )
+-  {
+-    int  fill = ( ras.outline.flags & FT_OUTLINE_EVEN_ODD_FILL ) ? 0x100
+-                                                                 : INT_MIN;
+-    int  coverage;
+-    int  y;
+-
+-    FT_Span  span[FT_MAX_GRAY_SPANS];
+-    int      n = 0;
+-
+-
+-    for ( y = ras.min_ey; y < ras.max_ey; y++ )
+-    {
+-      PCell   cell  = ras.ycells[y - ras.min_ey];
+-      TCoord  x     = ras.min_ex;
+-      TArea   cover = 0;
+-
+-
+-      for ( ; cell != ras.cell_null; cell = cell->next )
+-      {
+-        TArea  area;
+-
+-
+-        if ( cover != 0 && cell->x > x )
+-        {
+-          FT_FILL_RULE( coverage, cover, fill );
+-
+-          span[n].coverage = (unsigned char)coverage;
+-          span[n].x        = (short)x;
+-          span[n].len      = (unsigned short)( cell->x - x );
+-
+-          if ( ++n == FT_MAX_GRAY_SPANS )
+-          {
+-            /* flush the span buffer and reset the count */
+-            ras.render_span( y, n, span, ras.render_span_data );
+-            n = 0;
+-          }
+-        }
+-
+-        cover += (TArea)cell->cover * ( ONE_PIXEL * 2 );
+-        area   = cover - cell->area;
+-
+-        if ( area != 0 && cell->x >= ras.min_ex )
+-        {
+-          FT_FILL_RULE( coverage, area, fill );
+-
+-          span[n].coverage = (unsigned char)coverage;
+-          span[n].x        = (short)cell->x;
+-          span[n].len      = 1;
+-
+-          if ( ++n == FT_MAX_GRAY_SPANS )
+-          {
+-            /* flush the span buffer and reset the count */
+-            ras.render_span( y, n, span, ras.render_span_data );
+-            n = 0;
+-          }
+-        }
+-
+-        x = cell->x + 1;
+-      }
+-
+-      if ( cover != 0 )  /* only if cropped */
+-      {
+-        FT_FILL_RULE( coverage, cover, fill );
+-
+-        span[n].coverage = (unsigned char)coverage;
+-        span[n].x        = (short)x;
+-        span[n].len      = (unsigned short)( ras.max_ex - x );
+-
+-        ++n;
+-      }
+-
+-      if ( n )
+-      {
+-        /* flush the span buffer and reset the count */
+-        ras.render_span( y, n, span, ras.render_span_data );
+-        n = 0;
+-      }
+-    }
+-  }
+-
+-
+ #ifdef STANDALONE_
+ 
+   /**************************************************************************
+@@ -1934,7 +1711,7 @@ typedef ptrdiff_t  FT_PtrDist;
+       if ( continued )
+         FT_Trace_Enable();
+ 
+-      FT_TRACE7(( "band [%d..%d]: %td cell%s remaining/\n",
++      FT_TRACE7(( "band [%d..%d]: %td cell%s remaining\n",
+                   ras.min_ey,
+                   ras.max_ey,
+                   ras.cell_null - ras.cell_free,
+@@ -1952,14 +1729,144 @@ typedef ptrdiff_t  FT_PtrDist;
+   }
+ 
+ 
++  static void
++  gray_sweep( RAS_ARG )
++  {
++    int  fill = ( ras.outline.flags & FT_OUTLINE_EVEN_ODD_FILL ) ? 0x100
++                                                                 : INT_MIN;
++    int  coverage;
++    int  y;
++
++
++    for ( y = ras.min_ey; y < ras.max_ey; y++ )
++    {
++      PCell   cell  = ras.ycells[y - ras.min_ey];
++      TCoord  x     = ras.min_ex;
++      TArea   cover = 0;
++
++      unsigned char*  line = ras.target.origin - ras.target.pitch * y;
++
++
++      for ( ; cell != ras.cell_null; cell = cell->next )
++      {
++        TArea  area;
++
++
++        if ( cover != 0 && cell->x > x )
++        {
++          FT_FILL_RULE( coverage, cover, fill );
++          FT_GRAY_SET( line + x, coverage, cell->x - x );
++        }
++
++        cover += (TArea)cell->cover * ( ONE_PIXEL * 2 );
++        area   = cover - cell->area;
++
++        if ( area != 0 && cell->x >= ras.min_ex )
++        {
++          FT_FILL_RULE( coverage, area, fill );
++          line[cell->x] = (unsigned char)coverage;
++        }
++
++        x = cell->x + 1;
++      }
++
++      if ( cover != 0 )  /* only if cropped */
++      {
++        FT_FILL_RULE( coverage, cover, fill );
++        FT_GRAY_SET( line + x, coverage, ras.max_ex - x );
++      }
++    }
++  }
++
++
++  static void
++  gray_sweep_direct( RAS_ARG )
++  {
++    int  fill = ( ras.outline.flags & FT_OUTLINE_EVEN_ODD_FILL ) ? 0x100
++                                                                 : INT_MIN;
++    int  coverage;
++    int  y;
++
++    FT_Span  span[FT_MAX_GRAY_SPANS];
++    int      n = 0;
++
++
++    for ( y = ras.min_ey; y < ras.max_ey; y++ )
++    {
++      PCell   cell  = ras.ycells[y - ras.min_ey];
++      TCoord  x     = ras.min_ex;
++      TArea   cover = 0;
++
++
++      for ( ; cell != ras.cell_null; cell = cell->next )
++      {
++        TArea  area;
++
++
++        if ( cover != 0 && cell->x > x )
++        {
++          FT_FILL_RULE( coverage, cover, fill );
++
++          span[n].coverage = (unsigned char)coverage;
++          span[n].x        = (short)x;
++          span[n].len      = (unsigned short)( cell->x - x );
++
++          if ( ++n == FT_MAX_GRAY_SPANS )
++          {
++            /* flush the span buffer and reset the count */
++            ras.render_span( y, n, span, ras.render_span_data );
++            n = 0;
++          }
++        }
++
++        cover += (TArea)cell->cover * ( ONE_PIXEL * 2 );
++        area   = cover - cell->area;
++
++        if ( area != 0 && cell->x >= ras.min_ex )
++        {
++          FT_FILL_RULE( coverage, area, fill );
++
++          span[n].coverage = (unsigned char)coverage;
++          span[n].x        = (short)cell->x;
++          span[n].len      = 1;
++
++          if ( ++n == FT_MAX_GRAY_SPANS )
++          {
++            /* flush the span buffer and reset the count */
++            ras.render_span( y, n, span, ras.render_span_data );
++            n = 0;
++          }
++        }
++
++        x = cell->x + 1;
++      }
++
++      if ( cover != 0 )  /* only if cropped */
++      {
++        FT_FILL_RULE( coverage, cover, fill );
++
++        span[n].coverage = (unsigned char)coverage;
++        span[n].x        = (short)x;
++        span[n].len      = (unsigned short)( ras.max_ex - x );
++
++        ++n;
++      }
++
++      if ( n )
++      {
++        /* flush the span buffer and reset the count */
++        ras.render_span( y, n, span, ras.render_span_data );
++        n = 0;
++      }
++    }
++  }
++
++
+   static int
+   gray_convert_glyph( RAS_ARG )
+   {
+-    const TCoord  yMin = ras.min_ey;
+-    const TCoord  yMax = ras.max_ey;
+-
+     TCell    buffer[FT_MAX_GRAY_POOL];
+-    size_t   height = (size_t)( yMax - yMin );
++    size_t   height = (size_t)( ras.cbox.yMax - ras.cbox.yMin );
+     size_t   n = FT_MAX_GRAY_POOL / 8;
+     TCoord   y;
+     TCoord   bands[32];  /* enough to accommodate bisections */
+@@ -1985,35 +1892,36 @@ typedef ptrdiff_t  FT_PtrDist;
+       height  = ( height + n - 1 ) / n;
+     }
+ 
+-    for ( y = yMin; y < yMax; )
++    for ( y = ras.cbox.yMin; y < ras.cbox.yMax; )
+     {
+       ras.min_ey = y;
+       y         += height;
+-      ras.max_ey = FT_MIN( y, yMax );
++      ras.max_ey = FT_MIN( y, ras.cbox.yMax );
++
++      ras.count_ey = ras.max_ey - ras.min_ey;
+ 
+       band    = bands;
+-      band[1] = ras.min_ey;
+-      band[0] = ras.max_ey;
++      band[1] = ras.cbox.xMin;
++      band[0] = ras.cbox.xMax;
+ 
+       do
+       {
+-        TCoord  width = band[0] - band[1];
+-        TCoord  w;
++        TCoord  i;
+         int     error;
+ 
+ 
+-        for ( w = 0; w < width; ++w )
+-          ras.ycells[w] = ras.cell_null;
++        ras.min_ex = band[1];
++        ras.max_ex = band[0];
++
++        /* memory management: zero out and skip ycells */
++        for ( i = 0; i < ras.count_ey; ++i )
++          ras.ycells[i] = ras.cell_null;
+ 
+-        /* memory management: skip ycells */
+-        n = ( (size_t)width * sizeof ( PCell ) + sizeof ( TCell ) - 1 ) /
+-              sizeof ( TCell );
++        n = ( (size_t)ras.count_ey * sizeof ( PCell ) + sizeof ( TCell ) - 1 )
++              / sizeof ( TCell );
+ 
+         ras.cell_free = buffer + n;
+         ras.cell      = ras.cell_null;
+-        ras.min_ey    = band[1];
+-        ras.max_ey    = band[0];
+-        ras.count_ey  = width;
+ 
+         error     = gray_convert_glyph_inner( RAS_VAR_ continued );
+         continued = 1;
+@@ -2031,10 +1939,10 @@ typedef ptrdiff_t  FT_PtrDist;
+           return error;
+ 
+         /* render pool overflow; we will reduce the render band by half */
+-        width >>= 1;
++        i = ( band[0] - band[1] ) >> 1;
+ 
+         /* this should never happen even with tiny rendering pool */
+-        if ( width == 0 )
++        if ( i == 0 )
+         {
+           FT_TRACE7(( "gray_convert_glyph: rotten glyph\n" ));
+           return FT_THROW( Raster_Overflow );
+@@ -2042,7 +1950,7 @@ typedef ptrdiff_t  FT_PtrDist;
+ 
+         band++;
+         band[1]  = band[0];
+-        band[0] += width;
++        band[0] += i;
+       } while ( band >= bands );
+     }
+ 
+@@ -2073,7 +1981,7 @@ typedef ptrdiff_t  FT_PtrDist;
+       return FT_THROW( Invalid_Outline );
+ 
+     /* return immediately if the outline is empty */
+-    if ( outline->n_points == 0 || outline->n_contours <= 0 )
++    if ( outline->n_points == 0 || outline->n_contours == 0 )
+       return Smooth_Err_Ok;
+ 
+     if ( !outline->contours || !outline->points )
+@@ -2093,10 +2001,7 @@ typedef ptrdiff_t  FT_PtrDist;
+       ras.render_span      = (FT_Raster_Span_Func)params->gray_spans;
+       ras.render_span_data = params->user;
+ 
+-      ras.min_ex = params->clip_box.xMin;
+-      ras.min_ey = params->clip_box.yMin;
+-      ras.max_ex = params->clip_box.xMax;
+-      ras.max_ey = params->clip_box.yMax;
++      ras.cbox = params->clip_box;
+     }
+     else
+     {
+@@ -2122,14 +2027,14 @@ typedef ptrdiff_t  FT_PtrDist;
+       ras.render_span      = (FT_Raster_Span_Func)NULL;
+       ras.render_span_data = NULL;
+ 
+-      ras.min_ex = 0;
+-      ras.min_ey = 0;
+-      ras.max_ex = (FT_Pos)target_map->width;
+-      ras.max_ey = (FT_Pos)target_map->rows;
++      ras.cbox.xMin = 0;
++      ras.cbox.yMin = 0;
++      ras.cbox.xMax = (FT_Pos)target_map->width;
++      ras.cbox.yMax = (FT_Pos)target_map->rows;
+     }
+ 
+     /* exit if nothing to do */
+-    if ( ras.max_ex <= ras.min_ex || ras.max_ey <= ras.min_ey )
++    if ( ras.cbox.xMin >= ras.cbox.xMax || ras.cbox.yMin >= ras.cbox.yMax )
+       return Smooth_Err_Ok;
+ 
+     return gray_convert_glyph( RAS_VAR );
+diff --git a/src/java.desktop/share/native/libfreetype/src/smooth/ftgrays.h b/src/java.desktop/share/native/libfreetype/src/smooth/ftgrays.h
+index a5001bf40..940fbe8c7 100644
+--- a/src/java.desktop/share/native/libfreetype/src/smooth/ftgrays.h
++++ b/src/java.desktop/share/native/libfreetype/src/smooth/ftgrays.h
+@@ -4,7 +4,7 @@
+  *
+  *   FreeType smooth renderer declaration
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/smooth/ftsmerrs.h b/src/java.desktop/share/native/libfreetype/src/smooth/ftsmerrs.h
+index f4ac93dc4..6d41fb8e0 100644
+--- a/src/java.desktop/share/native/libfreetype/src/smooth/ftsmerrs.h
++++ b/src/java.desktop/share/native/libfreetype/src/smooth/ftsmerrs.h
+@@ -4,7 +4,7 @@
+  *
+  *   smooth renderer error codes (specification only).
+  *
+- * Copyright (C) 2001-2023 by
++ * Copyright (C) 2001-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/smooth/ftsmooth.c b/src/java.desktop/share/native/libfreetype/src/smooth/ftsmooth.c
+index 9b0e8886c..f0acc1ea4 100644
+--- a/src/java.desktop/share/native/libfreetype/src/smooth/ftsmooth.c
++++ b/src/java.desktop/share/native/libfreetype/src/smooth/ftsmooth.c
+@@ -4,7 +4,7 @@
+  *
+  *   Anti-aliasing renderer interface (body).
+  *
+- * Copyright (C) 2000-2023 by
++ * Copyright (C) 2000-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/smooth/ftsmooth.h b/src/java.desktop/share/native/libfreetype/src/smooth/ftsmooth.h
+index f8bdc9938..d7b61a9e6 100644
+--- a/src/java.desktop/share/native/libfreetype/src/smooth/ftsmooth.h
++++ b/src/java.desktop/share/native/libfreetype/src/smooth/ftsmooth.h
+@@ -4,7 +4,7 @@
+  *
+  *   Anti-aliasing renderer interface (specification).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttdriver.c b/src/java.desktop/share/native/libfreetype/src/truetype/ttdriver.c
+index d1496fec7..4ab68eb9a 100644
+--- a/src/java.desktop/share/native/libfreetype/src/truetype/ttdriver.c
++++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttdriver.c
+@@ -4,7 +4,7 @@
+  *
+  *   TrueType font driver implementation (body).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+@@ -217,7 +217,20 @@
+     kerning->y = 0;
+ 
+     if ( sfnt )
+-      kerning->x = sfnt->get_kerning( ttface, left_glyph, right_glyph );
++    {
++      /* Use 'kern' table if available since that can be faster; otherwise */
++      /* use GPOS kerning pairs if available.                              */
++      if ( ttface->kern_avail_bits != 0 )
++        kerning->x = sfnt->get_kerning( ttface,
++                                        left_glyph,
++                                        right_glyph );
++#ifdef TT_CONFIG_OPTION_GPOS_KERNING
++      else if ( ttface->gpos_kerning_available )
++        kerning->x = sfnt->get_gpos_kerning( ttface,
++                                             left_glyph,
++                                             right_glyph );
++#endif
++    }
+ 
+     return 0;
+   }
+diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttdriver.h b/src/java.desktop/share/native/libfreetype/src/truetype/ttdriver.h
+index 757a66f42..3e1cf234f 100644
+--- a/src/java.desktop/share/native/libfreetype/src/truetype/ttdriver.h
++++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttdriver.h
+@@ -4,7 +4,7 @@
+  *
+  *   High-level TrueType driver interface (specification).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/tterrors.h b/src/java.desktop/share/native/libfreetype/src/truetype/tterrors.h
+index 008ee9985..7ad937bd0 100644
+--- a/src/java.desktop/share/native/libfreetype/src/truetype/tterrors.h
++++ b/src/java.desktop/share/native/libfreetype/src/truetype/tterrors.h
+@@ -4,7 +4,7 @@
+  *
+  *   TrueType error codes (specification only).
+  *
+- * Copyright (C) 2001-2023 by
++ * Copyright (C) 2001-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttgload.c b/src/java.desktop/share/native/libfreetype/src/truetype/ttgload.c
+index dc427e8a1..b656ccf04 100644
+--- a/src/java.desktop/share/native/libfreetype/src/truetype/ttgload.c
++++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttgload.c
+@@ -4,7 +4,7 @@
+  *
+  *   TrueType Glyph Loader (body).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+@@ -353,7 +353,8 @@
+     FT_Byte         c, count;
+     FT_Vector       *vec, *vec_limit;
+     FT_Pos          x, y;
+-    FT_Short        *cont, *cont_limit, last;
++    FT_UShort       *cont, *cont_limit;
++    FT_Int          last;
+ 
+ 
+     /* check that we can add the contours to the glyph */
+@@ -372,7 +373,7 @@
+     last = -1;
+     for ( ; cont < cont_limit; cont++ )
+     {
+-      *cont = FT_NEXT_SHORT( p );
++      *cont = FT_NEXT_USHORT( p );
+ 
+       if ( *cont <= last )
+         goto Invalid_Outline;
+@@ -418,11 +419,9 @@
+       /* and thus allocate the bytecode array size by ourselves     */
+       if ( n_ins )
+       {
+-        if ( FT_QNEW_ARRAY( exec->glyphIns, n_ins ) )
++        if ( FT_DUP( exec->glyphIns, p, n_ins ) )
+           return error;
+ 
+-        FT_MEM_COPY( exec->glyphIns, p, (FT_Long)n_ins );
+-
+         exec->glyphSize  = n_ins;
+       }
+     }
+@@ -432,7 +431,7 @@
+     p += n_ins;
+ 
+     /* reading the point tags */
+-    flag       = (FT_Byte*)outline->tags;
++    flag       = outline->tags;
+     flag_limit = flag + n_points;
+ 
+     FT_ASSERT( flag );
+@@ -465,7 +464,7 @@
+ 
+     vec       = outline->points;
+     vec_limit = vec + n_points;
+-    flag      = (FT_Byte*)outline->tags;
++    flag      = outline->tags;
+     x         = 0;
+ 
+     for ( ; vec < vec_limit; vec++, flag++ )
+@@ -499,7 +498,7 @@
+ 
+     vec       = outline->points;
+     vec_limit = vec + n_points;
+-    flag      = (FT_Byte*)outline->tags;
++    flag      = outline->tags;
+     y         = 0;
+ 
+     for ( ; vec < vec_limit; vec++, flag++ )
+@@ -532,8 +531,8 @@
+       *flag  = (FT_Byte)( f & ON_CURVE_POINT );
+     }
+ 
+-    outline->n_points   = (FT_Short)n_points;
+-    outline->n_contours = (FT_Short)n_contours;
++    outline->n_points   = (FT_UShort)n_points;
++    outline->n_contours = (FT_UShort)n_contours;
+ 
+     load->cursor = p;
+ 
+@@ -754,15 +753,13 @@
+                    FT_UInt       start_point,
+                    FT_UInt       start_contour )
+   {
+-    zone->n_points    = (FT_UShort)load->outline.n_points + 4 -
+-                          (FT_UShort)start_point;
+-    zone->n_contours  = load->outline.n_contours -
+-                          (FT_Short)start_contour;
++    zone->n_points    = load->outline.n_points + 4 - (FT_UShort)start_point;
++    zone->n_contours  = load->outline.n_contours - (FT_UShort)start_contour;
+     zone->org         = load->extra_points + start_point;
+     zone->cur         = load->outline.points + start_point;
+     zone->orus        = load->extra_points2 + start_point;
+-    zone->tags        = (FT_Byte*)load->outline.tags + start_point;
+-    zone->contours    = (FT_UShort*)load->outline.contours + start_contour;
++    zone->tags        = load->outline.tags + start_point;
++    zone->contours    = load->outline.contours + start_contour;
+     zone->first_point = (FT_UShort)start_point;
+   }
+ 
+@@ -1046,7 +1043,7 @@
+     current.points   = gloader->base.outline.points +
+                          num_base_points;
+     current.n_points = gloader->base.outline.n_points -
+-                         (short)num_base_points;
++                         (FT_UShort)num_base_points;
+ 
+     have_scale = FT_BOOL( subglyph->flags & ( WE_HAVE_A_SCALE     |
+                                               WE_HAVE_AN_XY_SCALE |
+@@ -1059,7 +1056,7 @@
+     /* get offset */
+     if ( !( subglyph->flags & ARGS_ARE_XY_VALUES ) )
+     {
+-      FT_UInt     num_points = (FT_UInt)gloader->base.outline.n_points;
++      FT_UInt     num_points = gloader->base.outline.n_points;
+       FT_UInt     k = (FT_UInt)subglyph->arg1;
+       FT_UInt     l = (FT_UInt)subglyph->arg2;
+       FT_Vector*  p1;
+@@ -1721,8 +1718,8 @@
+         FT_List_Add( &loader->composites, node );
+       }
+ 
+-      start_point   = (FT_UInt)gloader->base.outline.n_points;
+-      start_contour = (FT_UInt)gloader->base.outline.n_contours;
++      start_point   = gloader->base.outline.n_points;
++      start_contour = gloader->base.outline.n_contours;
+ 
+       /* for each subglyph, read composite header */
+       error = face->read_composite_glyph( loader );
+@@ -1741,14 +1738,14 @@
+       if ( FT_IS_NAMED_INSTANCE( FT_FACE( face ) ) ||
+            FT_IS_VARIATION( FT_FACE( face ) )      )
+       {
+-        short        i, limit;
++        FT_UShort    i, limit;
+         FT_SubGlyph  subglyph;
+ 
+         FT_Outline  outline = { 0, 0, NULL, NULL, NULL, 0 };
+         FT_Vector*  unrounded = NULL;
+ 
+ 
+-        limit = (short)gloader->current.num_subglyphs;
++        limit = (FT_UShort)gloader->current.num_subglyphs;
+ 
+         /* construct an outline structure for              */
+         /* communication with `TT_Vary_Apply_Glyph_Deltas' */
+@@ -1874,7 +1871,7 @@
+           linear_hadvance = loader->linear;
+           linear_vadvance = loader->vadvance;
+ 
+-          num_base_points = (FT_UInt)gloader->base.outline.n_points;
++          num_base_points = gloader->base.outline.n_points;
+ 
+           error = load_truetype_glyph( loader,
+                                        (FT_UInt)subglyph->index,
+@@ -1898,7 +1895,7 @@
+             loader->vadvance = linear_vadvance;
+           }
+ 
+-          num_points = (FT_UInt)gloader->base.outline.n_points;
++          num_points = gloader->base.outline.n_points;
+ 
+           if ( num_points == num_base_points )
+             continue;
+@@ -2313,7 +2310,7 @@
+        *
+        * 1) we have a `tricky' font that heavily relies on the interpreter to
+        *    render glyphs correctly, for example DFKai-SB, or
+-       * 2) FT_RENDER_MODE_MONO (i.e, monochome rendering) is requested.
++       * 2) FT_RENDER_MODE_MONO (i.e, monochrome rendering) is requested.
+        *
+        * In those cases, backward compatibility needs to be turned off to get
+        * correct rendering.  The rendering is then completely up to the
+@@ -2719,7 +2716,7 @@
+          size->metrics->y_ppem < 24         )
+       glyph->outline.flags |= FT_OUTLINE_HIGH_PRECISION;
+ 
+-    FT_TRACE1(( "  subglyphs = %u, contours = %hd, points = %hd,"
++    FT_TRACE1(( "  subglyphs = %u, contours = %hu, points = %hu,"
+                 " flags = 0x%.3x\n",
+                 loader.gloader->base.num_subglyphs,
+                 glyph->outline.n_contours,
+diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttgload.h b/src/java.desktop/share/native/libfreetype/src/truetype/ttgload.h
+index f18637dce..22ea967f3 100644
+--- a/src/java.desktop/share/native/libfreetype/src/truetype/ttgload.h
++++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttgload.h
+@@ -4,7 +4,7 @@
+  *
+  *   TrueType Glyph Loader (specification).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttgxvar.c b/src/java.desktop/share/native/libfreetype/src/truetype/ttgxvar.c
+index 9d149ea36..4f0083c96 100644
+--- a/src/java.desktop/share/native/libfreetype/src/truetype/ttgxvar.c
++++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttgxvar.c
+@@ -4,7 +4,7 @@
+  *
+  *   TrueType GX Font Variation loader
+  *
+- * Copyright (C) 2004-2023 by
++ * Copyright (C) 2004-2024 by
+  * David Turner, Robert Wilhelm, Werner Lemberg, and George Williams.
+  *
+  * This file is part of the FreeType project, and may only be used,
+@@ -129,9 +129,6 @@
+    *   stream ::
+    *     The data stream.
+    *
+-   *   size ::
+-   *     The size of the table holding the data.
+-   *
+    * @Output:
+    *   point_cnt ::
+    *     The number of points read.  A zero value means that
+@@ -144,14 +141,14 @@
+    */
+   static FT_UShort*
+   ft_var_readpackedpoints( FT_Stream  stream,
+-                           FT_ULong   size,
+                            FT_UInt   *point_cnt )
+   {
+     FT_UShort *points = NULL;
+     FT_UInt    n;
+-    FT_UInt    runcnt;
++    FT_UInt    runcnt, cnt;
+     FT_UInt    i, j;
+     FT_UShort  first;
++    FT_Byte*   p;
+     FT_Memory  memory = stream->memory;
+     FT_Error   error;
+ 
+@@ -169,56 +166,60 @@
+       n  |= FT_GET_BYTE();
+     }
+ 
+-    if ( n > size )
+-    {
+-      FT_TRACE1(( "ft_var_readpackedpoints: number of points too large\n" ));
++    if ( FT_QNEW_ARRAY( points, n ) )
+       return NULL;
+-    }
+-
+-    /* in the nested loops below we increase `i' twice; */
+-    /* it is faster to simply allocate one more slot    */
+-    /* than to add another test within the loop         */
+-    if ( FT_QNEW_ARRAY( points, n + 1 ) )
+-      return NULL;
+-
+-    *point_cnt = n;
+ 
++    p     = stream->cursor;
+     first = 0;
+     i     = 0;
+     while ( i < n )
+     {
+-      runcnt = FT_GET_BYTE();
++      if ( p >= stream->limit )
++        goto Fail;
++
++      runcnt = FT_NEXT_BYTE( p );
++      cnt    = runcnt & GX_PT_POINT_RUN_COUNT_MASK;
++
++      /* first point not included in run count */
++      cnt++;
++      if ( cnt > n - i )
++        cnt = n - i;
++
+       if ( runcnt & GX_PT_POINTS_ARE_WORDS )
+       {
+-        runcnt     &= GX_PT_POINT_RUN_COUNT_MASK;
+-        first      += FT_GET_USHORT();
+-        points[i++] = first;
++        if ( 2 * cnt > (FT_UInt)( stream->limit - p ) )
++          goto Fail;
+ 
+-        /* first point not included in run count */
+-        for ( j = 0; j < runcnt; j++ )
++        for ( j = 0; j < cnt; j++ )
+         {
+-          first      += FT_GET_USHORT();
++          first      += FT_NEXT_USHORT( p );
+           points[i++] = first;
+-          if ( i >= n )
+-            break;
+         }
+       }
+       else
+       {
+-        first      += FT_GET_BYTE();
+-        points[i++] = first;
++        if ( cnt > (FT_UInt)( stream->limit - p ) )
++          goto Fail;
+ 
+-        for ( j = 0; j < runcnt; j++ )
++        for ( j = 0; j < cnt; j++ )
+         {
+-          first      += FT_GET_BYTE();
++          first      += FT_NEXT_BYTE( p );
+           points[i++] = first;
+-          if ( i >= n )
+-            break;
+         }
+       }
+     }
+ 
++    stream->cursor = p;
++
++    *point_cnt = n;
++
+     return points;
++
++  Fail:
++    FT_TRACE1(( "ft_var_readpackedpoints: invalid table\n" ));
++
++    FT_FREE( points );
++    return NULL;
+   }
+ 
+ 
+@@ -240,9 +241,6 @@
+    *   stream ::
+    *     The data stream.
+    *
+-   *   size ::
+-   *     The size of the table holding the data.
+-   *
+    *   delta_cnt ::
+    *     The number of deltas to be read.
+    *
+@@ -258,13 +256,12 @@
+    */
+   static FT_Fixed*
+   ft_var_readpackeddeltas( FT_Stream  stream,
+-                           FT_ULong   size,
+                            FT_UInt    delta_cnt )
+   {
+     FT_Fixed  *deltas = NULL;
+     FT_UInt    runcnt, cnt;
+     FT_UInt    i, j;
+-    FT_UInt    bytes_used;
++    FT_Byte*   p;
+     FT_Memory  memory = stream->memory;
+     FT_Error   error;
+ 
+@@ -272,68 +269,51 @@
+     if ( FT_QNEW_ARRAY( deltas, delta_cnt ) )
+       return NULL;
+ 
+-    i          = 0;
+-    bytes_used = 0;
+-
+-    while ( i < delta_cnt && bytes_used < size )
++    p = stream->cursor;
++    i = 0;
++    while ( i < delta_cnt )
+     {
+-      runcnt = FT_GET_BYTE();
++      if ( p >= stream->limit )
++        goto Fail;
++
++      runcnt = FT_NEXT_BYTE( p );
+       cnt    = runcnt & GX_DT_DELTA_RUN_COUNT_MASK;
+ 
+-      bytes_used++;
++      /* first point not included in run count */
++      cnt++;
++      if ( cnt > delta_cnt - i )
++        cnt = delta_cnt - i;
+ 
+       if ( runcnt & GX_DT_DELTAS_ARE_ZERO )
+       {
+-        /* `cnt` + 1 zeroes get added */
+-        for ( j = 0; j <= cnt && i < delta_cnt; j++ )
++        for ( j = 0; j < cnt; j++ )
+           deltas[i++] = 0;
+       }
+       else if ( runcnt & GX_DT_DELTAS_ARE_WORDS )
+       {
+-        /* `cnt` + 1 shorts from the stack */
+-        bytes_used += 2 * ( cnt + 1 );
+-        if ( bytes_used > size )
+-        {
+-          FT_TRACE1(( "ft_var_readpackeddeltas:"
+-                      " number of short deltas too large\n" ));
++        if ( 2 * cnt > (FT_UInt)( stream->limit - p ) )
+           goto Fail;
+-        }
+ 
+-        for ( j = 0; j <= cnt && i < delta_cnt; j++ )
+-          deltas[i++] = FT_intToFixed( FT_GET_SHORT() );
++        for ( j = 0; j < cnt; j++ )
++          deltas[i++] = FT_intToFixed( FT_NEXT_SHORT( p ) );
+       }
+       else
+       {
+-        /* `cnt` + 1 signed bytes from the stack */
+-        bytes_used += cnt + 1;
+-        if ( bytes_used > size )
+-        {
+-          FT_TRACE1(( "ft_var_readpackeddeltas:"
+-                      " number of byte deltas too large\n" ));
++        if ( cnt > (FT_UInt)( stream->limit - p ) )
+           goto Fail;
+-        }
+ 
+-        for ( j = 0; j <= cnt && i < delta_cnt; j++ )
+-          deltas[i++] = FT_intToFixed( FT_GET_CHAR() );
+-      }
+-
+-      if ( j <= cnt )
+-      {
+-        FT_TRACE1(( "ft_var_readpackeddeltas:"
+-                    " number of deltas too large\n" ));
+-        goto Fail;
++        for ( j = 0; j < cnt; j++ )
++          deltas[i++] = FT_intToFixed( FT_NEXT_CHAR( p ) );
+       }
+     }
+ 
+-    if ( i < delta_cnt )
+-    {
+-      FT_TRACE1(( "ft_var_readpackeddeltas: not enough deltas\n" ));
+-      goto Fail;
+-    }
++    stream->cursor = p;
+ 
+     return deltas;
+ 
+   Fail:
++    FT_TRACE1(( "ft_var_readpackeddeltas: invalid table\n" ));
++
+     FT_FREE( deltas );
+     return NULL;
+   }
+@@ -596,7 +576,7 @@
+ 
+       for ( j = 0; j < itemStore->axisCount; j++ )
+       {
+-        FT_Short  start, peak, end;
++        FT_Int  start, peak, end;
+ 
+ 
+         if ( FT_READ_SHORT( start ) ||
+@@ -604,6 +584,10 @@
+              FT_READ_SHORT( end )   )
+           goto Exit;
+ 
++        /* immediately tag invalid ranges with special peak = 0 */
++        if ( ( start < 0 && end > 0 ) || start > peak || peak > end )
++          peak = 0;
++
+         axisCoords[j].startCoord = FT_fdot14ToFixed( start );
+         axisCoords[j].peakCoord  = FT_fdot14ToFixed( peak );
+         axisCoords[j].endCoord   = FT_fdot14ToFixed( end );
+@@ -1024,6 +1008,9 @@
+     if ( innerIndex >= varData->itemCount )
+       return 0; /* Out of range. */
+ 
++    if ( varData->regionIdxCount == 0 )
++      return 0; /* Avoid "applying zero offset to null pointer". */
++
+     if ( varData->regionIdxCount < 16 )
+     {
+       deltaSet = deltaSetStack;
+@@ -1074,43 +1061,32 @@
+       /* inner loop steps through axes in this region */
+       for ( j = 0; j < itemStore->axisCount; j++, axis++ )
+       {
+-        /* compute the scalar contribution of this axis; */
+-        /* ignore invalid ranges                         */
+-        if ( axis->startCoord > axis->peakCoord ||
+-             axis->peakCoord > axis->endCoord   )
+-          continue;
++        FT_Fixed  ncv = ttface->blend->normalizedcoords[j];
+ 
+-        else if ( axis->startCoord < 0 &&
+-                  axis->endCoord > 0   &&
+-                  axis->peakCoord != 0 )
+-          continue;
+ 
+-        /* peak of 0 means ignore this axis */
+-        else if ( axis->peakCoord == 0 )
+-          continue;
+-
+-        else if ( ttface->blend->normalizedcoords[j] == axis->peakCoord )
++        /* compute the scalar contribution of this axis */
++        /* with peak of 0 used for invalid axes         */
++        if ( axis->peakCoord == ncv ||
++             axis->peakCoord == 0   )
+           continue;
+ 
+         /* ignore this region if coords are out of range */
+-        else if ( ttface->blend->normalizedcoords[j] <= axis->startCoord ||
+-                  ttface->blend->normalizedcoords[j] >= axis->endCoord   )
++        else if ( ncv <= axis->startCoord ||
++                  ncv >= axis->endCoord   )
+         {
+           scalar = 0;
+           break;
+         }
+ 
+         /* cumulative product of all the axis scalars */
+-        else if ( ttface->blend->normalizedcoords[j] < axis->peakCoord )
+-          scalar =
+-            FT_MulDiv( scalar,
+-                       ttface->blend->normalizedcoords[j] - axis->startCoord,
+-                       axis->peakCoord - axis->startCoord );
+-        else
+-          scalar =
+-            FT_MulDiv( scalar,
+-                       axis->endCoord - ttface->blend->normalizedcoords[j],
+-                       axis->endCoord - axis->peakCoord );
++        else if ( ncv < axis->peakCoord )
++          scalar = FT_MulDiv( scalar,
++                              ncv - axis->startCoord,
++                              axis->peakCoord - axis->startCoord );
++        else   /* ncv > axis->peakCoord */
++          scalar = FT_MulDiv( scalar,
++                              axis->endCoord - ncv,
++                              axis->endCoord - axis->peakCoord );
+ 
+       } /* per-axis loop */
+ 
+@@ -1920,32 +1896,27 @@
+ 
+     for ( i = 0; i < blend->num_axis; i++ )
+     {
+-      FT_TRACE6(( "    axis %d coordinate %.5f:\n",
+-                  i, (double)blend->normalizedcoords[i] / 65536 ));
++      FT_Fixed  ncv = blend->normalizedcoords[i];
++
++
++      FT_TRACE6(( "    axis %d coordinate %.5f:\n", i, (double)ncv / 65536 ));
+ 
+       /* It's not clear why (for intermediate tuples) we don't need     */
+       /* to check against start/end -- the documentation says we don't. */
+       /* Similarly, it's unclear why we don't need to scale along the   */
+       /* axis.                                                          */
+ 
+-      if ( tuple_coords[i] == 0 )
++      if ( tuple_coords[i] == ncv )
+       {
+-        FT_TRACE6(( "      tuple coordinate is zero, ignore\n" ));
++        FT_TRACE6(( "      tuple coordinate %.5f fits perfectly\n",
++                    (double)tuple_coords[i] / 65536 ));
++        /* `apply' does not change */
+         continue;
+       }
+ 
+-      if ( blend->normalizedcoords[i] == 0 )
+-      {
+-        FT_TRACE6(( "      axis coordinate is zero, stop\n" ));
+-        apply = 0;
+-        break;
+-      }
+-
+-      if ( blend->normalizedcoords[i] == tuple_coords[i] )
++      if ( tuple_coords[i] == 0 )
+       {
+-        FT_TRACE6(( "      tuple coordinate %.5f fits perfectly\n",
+-                    (double)tuple_coords[i] / 65536 ));
+-        /* `apply' does not change */
++        FT_TRACE6(( "      tuple coordinate is zero, ignore\n" ));
+         continue;
+       }
+ 
+@@ -1953,27 +1924,27 @@
+       {
+         /* not an intermediate tuple */
+ 
+-        if ( blend->normalizedcoords[i] < FT_MIN( 0, tuple_coords[i] ) ||
+-             blend->normalizedcoords[i] > FT_MAX( 0, tuple_coords[i] ) )
++        if ( ( tuple_coords[i] > ncv && ncv > 0 ) ||
++             ( tuple_coords[i] < ncv && ncv < 0 ) )
++        {
++          FT_TRACE6(( "      tuple coordinate %.5f fits\n",
++                      (double)tuple_coords[i] / 65536 ));
++          apply = FT_MulDiv( apply, ncv, tuple_coords[i] );
++        }
++        else
+         {
+           FT_TRACE6(( "      tuple coordinate %.5f is exceeded, stop\n",
+                       (double)tuple_coords[i] / 65536 ));
+           apply = 0;
+           break;
+         }
+-
+-        FT_TRACE6(( "      tuple coordinate %.5f fits\n",
+-                    (double)tuple_coords[i] / 65536 ));
+-        apply = FT_MulDiv( apply,
+-                           blend->normalizedcoords[i],
+-                           tuple_coords[i] );
+       }
+       else
+       {
+         /* intermediate tuple */
+ 
+-        if ( blend->normalizedcoords[i] <= im_start_coords[i] ||
+-             blend->normalizedcoords[i] >= im_end_coords[i]   )
++        if ( ncv <= im_start_coords[i] ||
++             ncv >= im_end_coords[i]   )
+         {
+           FT_TRACE6(( "      intermediate tuple range ]%.5f;%.5f[ is exceeded,"
+                       " stop\n",
+@@ -1986,13 +1957,13 @@
+         FT_TRACE6(( "      intermediate tuple range ]%.5f;%.5f[ fits\n",
+                     (double)im_start_coords[i] / 65536,
+                     (double)im_end_coords[i] / 65536 ));
+-        if ( blend->normalizedcoords[i] < tuple_coords[i] )
++        if ( ncv < tuple_coords[i] )
+           apply = FT_MulDiv( apply,
+-                             blend->normalizedcoords[i] - im_start_coords[i],
++                             ncv - im_start_coords[i],
+                              tuple_coords[i] - im_start_coords[i] );
+-        else
++        else /* ncv > tuple_coords[i] */
+           apply = FT_MulDiv( apply,
+-                             im_end_coords[i] - blend->normalizedcoords[i],
++                             im_end_coords[i] - ncv,
+                              im_end_coords[i] - tuple_coords[i] );
+       }
+     }
+@@ -2141,11 +2112,12 @@
+                                          outerIndex,
+                                          innerIndex );
+ 
+-      v += delta << 2;
++          /* Convert delta in F2DOT14 to 16.16 before adding. */
++          v += MUL_INT( delta, 4 );
+ 
+-      /* Clamp value range. */
+-      v = v >=  0x10000L ?  0x10000 : v;
+-      v = v <= -0x10000L ? -0x10000 : v;
++          /* Clamp value to range [-1, 1]. */
++          v = v >=  0x10000L ?  0x10000 : v;
++          v = v <= -0x10000L ? -0x10000 : v;
+ 
+           new_normalized[i] = v;
+         }
+@@ -2721,9 +2693,8 @@
+       FT_UInt  n;
+ 
+ 
+-      if ( FT_ALLOC( mmvar, ttface->blend->mmvar_len ) )
++      if ( FT_DUP( mmvar, ttface->blend->mmvar, ttface->blend->mmvar_len ) )
+         goto Exit;
+-      FT_MEM_COPY( mmvar, ttface->blend->mmvar, ttface->blend->mmvar_len );
+ 
+       axis_flags =
+         (FT_UShort*)( (char*)mmvar + mmvar_size );
+@@ -3533,9 +3504,10 @@
+     FT_ULong  here;
+     FT_UInt   i, j;
+ 
+-    FT_Fixed*  tuple_coords    = NULL;
+-    FT_Fixed*  im_start_coords = NULL;
+-    FT_Fixed*  im_end_coords   = NULL;
++    FT_Fixed*  peak_coords = NULL;
++    FT_Fixed*  tuple_coords;
++    FT_Fixed*  im_start_coords;
++    FT_Fixed*  im_end_coords;
+ 
+     GX_Blend  blend = face->blend;
+ 
+@@ -3556,16 +3528,16 @@
+     {
+       FT_TRACE2(( "\n" ));
+       FT_TRACE2(( "tt_face_vary_cvt: no blend specified\n" ));
+-      error = FT_Err_Ok;
+-      goto Exit;
++
++      return FT_Err_Ok;
+     }
+ 
+     if ( !face->cvt )
+     {
+       FT_TRACE2(( "\n" ));
+       FT_TRACE2(( "tt_face_vary_cvt: no `cvt ' table\n" ));
+-      error = FT_Err_Ok;
+-      goto Exit;
++
++      return FT_Err_Ok;
+     }
+ 
+     error = face->goto_table( face, TTAG_cvar, stream, &table_len );
+@@ -3573,15 +3545,11 @@
+     {
+       FT_TRACE2(( "is missing\n" ));
+ 
+-      error = FT_Err_Ok;
+-      goto Exit;
++      return FT_Err_Ok;
+     }
+ 
+     if ( FT_FRAME_ENTER( table_len ) )
+-    {
+-      error = FT_Err_Ok;
+-      goto Exit;
+-    }
++      return FT_Err_Ok;
+ 
+     table_start = FT_Stream_FTell( stream );
+     if ( FT_GET_LONG() != 0x00010000L )
+@@ -3594,11 +3562,6 @@
+ 
+     FT_TRACE2(( "loaded\n" ));
+ 
+-    if ( FT_NEW_ARRAY( tuple_coords, blend->num_axis )    ||
+-         FT_NEW_ARRAY( im_start_coords, blend->num_axis ) ||
+-         FT_NEW_ARRAY( im_end_coords, blend->num_axis )   )
+-      goto FExit;
+-
+     tupleCount   = FT_GET_USHORT();
+     offsetToData = FT_GET_USHORT();
+ 
+@@ -3621,9 +3584,8 @@
+ 
+       FT_Stream_SeekSet( stream, offsetToData );
+ 
+-      sharedpoints = ft_var_readpackedpoints( stream,
+-                                              table_len,
+-                                              &spoint_count );
++      sharedpoints = ft_var_readpackedpoints( stream, &spoint_count );
++
+       offsetToData = FT_Stream_FTell( stream );
+ 
+       FT_Stream_SeekSet( stream, here );
+@@ -3634,8 +3596,12 @@
+                 tupleCount & GX_TC_TUPLE_COUNT_MASK,
+                 ( tupleCount & GX_TC_TUPLE_COUNT_MASK ) == 1 ? "" : "s" ));
+ 
+-    if ( FT_NEW_ARRAY( cvt_deltas, face->cvt_size ) )
+-      goto FExit;
++    if ( FT_QNEW_ARRAY( peak_coords, 3 * blend->num_axis ) ||
++         FT_NEW_ARRAY( cvt_deltas, face->cvt_size )        )
++      goto Exit;
++
++    im_start_coords = peak_coords + blend->num_axis;
++    im_end_coords = im_start_coords + blend->num_axis;
+ 
+     for ( i = 0; i < ( tupleCount & GX_TC_TUPLE_COUNT_MASK ); i++ )
+     {
+@@ -3652,32 +3618,19 @@
+       if ( tupleIndex & GX_TI_EMBEDDED_TUPLE_COORD )
+       {
+         for ( j = 0; j < blend->num_axis; j++ )
+-          tuple_coords[j] = FT_fdot14ToFixed( FT_GET_SHORT() );
++          peak_coords[j] = FT_fdot14ToFixed( FT_GET_SHORT() );
++        tuple_coords = peak_coords;
+       }
+-      else if ( ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) >= blend->tuplecount )
++      else if ( ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) < blend->tuplecount )
++        tuple_coords = blend->tuplecoords +
++            ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) * blend->num_axis;
++      else
+       {
+         FT_TRACE2(( "tt_face_vary_cvt:"
+                     " invalid tuple index\n" ));
+ 
+         error = FT_THROW( Invalid_Table );
+-        goto FExit;
+-      }
+-      else
+-      {
+-        if ( !blend->tuplecoords )
+-        {
+-          FT_TRACE2(( "tt_face_vary_cvt:"
+-                      " no valid tuple coordinates available\n" ));
+-
+-          error = FT_THROW( Invalid_Table );
+-          goto FExit;
+-        }
+-
+-        FT_MEM_COPY(
+-          tuple_coords,
+-          blend->tuplecoords +
+-            ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) * blend->num_axis,
+-          blend->num_axis * sizeof ( FT_Fixed ) );
++        goto Exit;
+       }
+ 
+       if ( tupleIndex & GX_TI_INTERMEDIATE_TUPLE )
+@@ -3706,9 +3659,7 @@
+ 
+       if ( tupleIndex & GX_TI_PRIVATE_POINT_NUMBERS )
+       {
+-        localpoints = ft_var_readpackedpoints( stream,
+-                                               table_len,
+-                                               &point_count );
++        localpoints = ft_var_readpackedpoints( stream, &point_count );
+         points      = localpoints;
+       }
+       else
+@@ -3719,7 +3670,6 @@
+       }
+ 
+       deltas = ft_var_readpackeddeltas( stream,
+-                                        table_len,
+                                         point_count == 0 ? face->cvt_size
+                                                          : point_count );
+ 
+@@ -3820,22 +3770,20 @@
+     for ( i = 0; i < face->cvt_size; i++ )
+       face->cvt[i] += FT_fixedToFdot6( cvt_deltas[i] );
+ 
+-  FExit:
+-    FT_FRAME_EXIT();
++    /* Iterate over all `FT_Size` objects and set `cvt_ready` to -1 */
++    /* to trigger rescaling of all CVT values.                      */
++    FT_List_Iterate( &root->sizes_list,
++                     tt_cvt_ready_iterator,
++                     NULL );
+ 
+   Exit:
+     if ( sharedpoints != ALL_POINTS )
+       FT_FREE( sharedpoints );
+-    FT_FREE( tuple_coords );
+-    FT_FREE( im_start_coords );
+-    FT_FREE( im_end_coords );
+     FT_FREE( cvt_deltas );
++    FT_FREE( peak_coords );
+ 
+-    /* iterate over all FT_Size objects and set `cvt_ready' to -1 */
+-    /* to trigger rescaling of all CVT values                     */
+-    FT_List_Iterate( &root->sizes_list,
+-                     tt_cvt_ready_iterator,
+-                     NULL );
++  FExit:
++    FT_FRAME_EXIT();
+ 
+     return error;
+ 
+@@ -4099,9 +4047,10 @@
+     FT_ULong  here;
+     FT_UInt   i, j;
+ 
+-    FT_Fixed*  tuple_coords    = NULL;
+-    FT_Fixed*  im_start_coords = NULL;
+-    FT_Fixed*  im_end_coords   = NULL;
++    FT_Fixed*  peak_coords = NULL;
++    FT_Fixed*  tuple_coords;
++    FT_Fixed*  im_start_coords;
++    FT_Fixed*  im_end_coords;
+ 
+     GX_Blend  blend = face->blend;
+ 
+@@ -4136,27 +4085,17 @@
+       return FT_Err_Ok;
+     }
+ 
+-    if ( FT_NEW_ARRAY( points_org, n_points ) ||
+-         FT_NEW_ARRAY( points_out, n_points ) ||
+-         FT_NEW_ARRAY( has_delta, n_points )  )
+-      goto Fail1;
+-
+     dataSize = blend->glyphoffsets[glyph_index + 1] -
+                  blend->glyphoffsets[glyph_index];
+ 
+     if ( FT_STREAM_SEEK( blend->glyphoffsets[glyph_index] ) ||
+          FT_FRAME_ENTER( dataSize )                         )
+-      goto Fail1;
++      return error;
+ 
+     glyph_start = FT_Stream_FTell( stream );
+ 
+     /* each set of glyph variation data is formatted similarly to `cvar' */
+ 
+-    if ( FT_NEW_ARRAY( tuple_coords, blend->num_axis )    ||
+-         FT_NEW_ARRAY( im_start_coords, blend->num_axis ) ||
+-         FT_NEW_ARRAY( im_end_coords, blend->num_axis )   )
+-      goto Fail2;
+-
+     tupleCount   = FT_GET_USHORT();
+     offsetToData = FT_GET_USHORT();
+ 
+@@ -4168,7 +4107,7 @@
+                   " invalid glyph variation array header\n" ));
+ 
+       error = FT_THROW( Invalid_Table );
+-      goto Fail2;
++      goto FExit;
+     }
+ 
+     offsetToData += glyph_start;
+@@ -4179,9 +4118,8 @@
+ 
+       FT_Stream_SeekSet( stream, offsetToData );
+ 
+-      sharedpoints = ft_var_readpackedpoints( stream,
+-                                              blend->gvar_size,
+-                                              &spoint_count );
++      sharedpoints = ft_var_readpackedpoints( stream, &spoint_count );
++
+       offsetToData = FT_Stream_FTell( stream );
+ 
+       FT_Stream_SeekSet( stream, here );
+@@ -4192,9 +4130,16 @@
+                 tupleCount & GX_TC_TUPLE_COUNT_MASK,
+                 ( tupleCount & GX_TC_TUPLE_COUNT_MASK ) == 1 ? "" : "s" ));
+ 
+-    if ( FT_NEW_ARRAY( point_deltas_x, n_points ) ||
+-         FT_NEW_ARRAY( point_deltas_y, n_points ) )
+-      goto Fail3;
++    if ( FT_QNEW_ARRAY( peak_coords, 3 * blend->num_axis ) ||
++         FT_NEW_ARRAY( point_deltas_x, 2 * n_points )      ||
++         FT_QNEW_ARRAY( points_org, n_points )             ||
++         FT_QNEW_ARRAY( points_out, n_points )             ||
++         FT_QNEW_ARRAY( has_delta, n_points )              )
++      goto Exit;
++
++    im_start_coords = peak_coords + blend->num_axis;
++    im_end_coords   = im_start_coords + blend->num_axis;
++    point_deltas_y  = point_deltas_x + n_points;
+ 
+     for ( j = 0; j < n_points; j++ )
+     {
+@@ -4217,22 +4162,20 @@
+       if ( tupleIndex & GX_TI_EMBEDDED_TUPLE_COORD )
+       {
+         for ( j = 0; j < blend->num_axis; j++ )
+-          tuple_coords[j] = FT_fdot14ToFixed( FT_GET_SHORT() );
++          peak_coords[j] = FT_fdot14ToFixed( FT_GET_SHORT() );
++        tuple_coords = peak_coords;
+       }
+-      else if ( ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) >= blend->tuplecount )
++      else if ( ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) < blend->tuplecount )
++        tuple_coords = blend->tuplecoords +
++            ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) * blend->num_axis;
++      else
+       {
+         FT_TRACE2(( "TT_Vary_Apply_Glyph_Deltas:"
+                     " invalid tuple index\n" ));
+ 
+         error = FT_THROW( Invalid_Table );
+-        goto Fail3;
++        goto Exit;
+       }
+-      else
+-        FT_MEM_COPY(
+-          tuple_coords,
+-          blend->tuplecoords +
+-            ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) * blend->num_axis,
+-          blend->num_axis * sizeof ( FT_Fixed ) );
+ 
+       if ( tupleIndex & GX_TI_INTERMEDIATE_TUPLE )
+       {
+@@ -4260,9 +4203,7 @@
+ 
+       if ( tupleIndex & GX_TI_PRIVATE_POINT_NUMBERS )
+       {
+-        localpoints = ft_var_readpackedpoints( stream,
+-                                               blend->gvar_size,
+-                                               &point_count );
++        localpoints = ft_var_readpackedpoints( stream, &point_count );
+         points      = localpoints;
+       }
+       else
+@@ -4272,11 +4213,9 @@
+       }
+ 
+       deltas_x = ft_var_readpackeddeltas( stream,
+-                                          blend->gvar_size,
+                                           point_count == 0 ? n_points
+                                                            : point_count );
+       deltas_y = ft_var_readpackeddeltas( stream,
+-                                          blend->gvar_size,
+                                           point_count == 0 ? n_points
+                                                            : point_count );
+ 
+@@ -4460,23 +4399,17 @@
+                                        unrounded[n_points - 2].y ) / 64;
+     }
+ 
+-  Fail3:
+-    FT_FREE( point_deltas_x );
+-    FT_FREE( point_deltas_y );
+-
+-  Fail2:
++  Exit:
+     if ( sharedpoints != ALL_POINTS )
+       FT_FREE( sharedpoints );
+-    FT_FREE( tuple_coords );
+-    FT_FREE( im_start_coords );
+-    FT_FREE( im_end_coords );
+-
+-    FT_FRAME_EXIT();
+-
+-  Fail1:
+     FT_FREE( points_org );
+     FT_FREE( points_out );
+     FT_FREE( has_delta );
++    FT_FREE( peak_coords );
++    FT_FREE( point_deltas_x );
++
++  FExit:
++    FT_FRAME_EXIT();
+ 
+     return error;
+   }
+diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttgxvar.h b/src/java.desktop/share/native/libfreetype/src/truetype/ttgxvar.h
+index e3da6d170..9326011e3 100644
+--- a/src/java.desktop/share/native/libfreetype/src/truetype/ttgxvar.h
++++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttgxvar.h
+@@ -4,7 +4,7 @@
+  *
+  *   TrueType GX Font Variation loader (specification)
+  *
+- * Copyright (C) 2004-2023 by
++ * Copyright (C) 2004-2024 by
+  * David Turner, Robert Wilhelm, Werner Lemberg and George Williams.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.c b/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.c
+index 79df4555d..951891dbf 100644
+--- a/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.c
++++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.c
+@@ -4,7 +4,7 @@
+  *
+  *   TrueType bytecode interpreter (body).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+@@ -5270,11 +5270,11 @@
+     FT_UShort        refp;
+     FT_F26Dot6       dx, dy;
+ 
+-    FT_Short         contour, bounds;
++    FT_UShort        contour, bounds;
+     FT_UShort        start, limit, i;
+ 
+ 
+-    contour = (FT_Short)args[0];
++    contour = (FT_UShort)args[0];
+     bounds  = ( exc->GS.gep2 == 0 ) ? 1 : exc->zp2.n_contours;
+ 
+     if ( BOUNDS( contour, bounds ) )
+@@ -5290,15 +5290,13 @@
+     if ( contour == 0 )
+       start = 0;
+     else
+-      start = (FT_UShort)( exc->zp2.contours[contour - 1] + 1 -
+-                           exc->zp2.first_point );
++      start = exc->zp2.contours[contour - 1] + 1 - exc->zp2.first_point;
+ 
+     /* we use the number of points if in the twilight zone */
+     if ( exc->GS.gep2 == 0 )
+       limit = exc->zp2.n_points;
+     else
+-      limit = (FT_UShort)( exc->zp2.contours[contour] -
+-                           exc->zp2.first_point + 1 );
++      limit = exc->zp2.contours[contour] + 1 - exc->zp2.first_point;
+ 
+     for ( i = start; i < limit; i++ )
+     {
+@@ -5341,9 +5339,9 @@
+     /*      Normal zone's `n_points' includes phantoms, so must    */
+     /*      use end of last contour.                               */
+     if ( exc->GS.gep2 == 0 )
+-      limit = (FT_UShort)exc->zp2.n_points;
++      limit = exc->zp2.n_points;
+     else if ( exc->GS.gep2 == 1 && exc->zp2.n_contours > 0 )
+-      limit = (FT_UShort)( exc->zp2.contours[exc->zp2.n_contours - 1] + 1 );
++      limit = exc->zp2.contours[exc->zp2.n_contours - 1] + 1;
+     else
+       limit = 0;
+ 
+diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.h b/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.h
+index e98e258fe..4f1a9bbc6 100644
+--- a/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.h
++++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.h
+@@ -4,7 +4,7 @@
+  *
+  *   TrueType bytecode interpreter (specification).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttobjs.c b/src/java.desktop/share/native/libfreetype/src/truetype/ttobjs.c
+index 5b56af711..d0ac31812 100644
+--- a/src/java.desktop/share/native/libfreetype/src/truetype/ttobjs.c
++++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttobjs.c
+@@ -4,7 +4,7 @@
+  *
+  *   Objects manager (body).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+@@ -115,7 +115,7 @@
+   FT_LOCAL_DEF( FT_Error )
+   tt_glyphzone_new( FT_Memory     memory,
+                     FT_UShort     maxPoints,
+-                    FT_Short      maxContours,
++                    FT_UShort     maxContours,
+                     TT_GlyphZone  zone )
+   {
+     FT_Error  error;
+@@ -152,18 +152,20 @@
+   static const FT_String*
+   tt_skip_pdffont_random_tag( const FT_String*  name )
+   {
+-    unsigned int  i;
+-
+-
+-    if ( ft_strlen( name ) < 8 || name[6] != '+' )
+-      return name;
+-
+-    for ( i = 0; i < 6; i++ )
+-      if ( !ft_isupper( name[i] ) )
+-        return name;
++    if ( ft_isupper( name[0] ) &&
++         ft_isupper( name[1] ) &&
++         ft_isupper( name[2] ) &&
++         ft_isupper( name[3] ) &&
++         ft_isupper( name[4] ) &&
++         ft_isupper( name[5] ) &&
++              '+' == name[6]   &&
++                     name[7]   )
++    {
++      FT_TRACE7(( "name without randomization tag: %s\n", name + 7 ));
++      return name + 7;
++    }
+ 
+-    FT_TRACE7(( "name without randomization tag: %s\n", name + 7 ));
+-    return name + 7;
++    return name;
+   }
+ 
+ 
+@@ -254,17 +256,20 @@
+   {
+     FT_Error   error;
+     FT_UInt32  checksum = 0;
+-    FT_UInt    i;
++    FT_Byte*   p;
++    FT_Int     shift;
+ 
+ 
+     if ( FT_FRAME_ENTER( length ) )
+       return 0;
+ 
++    p = (FT_Byte*)stream->cursor;
++
+     for ( ; length > 3; length -= 4 )
+-      checksum += (FT_UInt32)FT_GET_ULONG();
++      checksum += FT_NEXT_ULONG( p );
+ 
+-    for ( i = 3; length > 0; length--, i-- )
+-      checksum += (FT_UInt32)FT_GET_BYTE() << ( i * 8 );
++    for ( shift = 24; length > 0; length--, shift -=8 )
++      checksum += (FT_UInt32)FT_NEXT_BYTE( p ) << shift;
+ 
+     FT_FRAME_EXIT();
+ 
+@@ -782,8 +787,7 @@
+       FT_UInt  instance_index = (FT_UInt)face_index >> 16;
+ 
+ 
+-      if ( FT_HAS_MULTIPLE_MASTERS( ttface ) &&
+-           instance_index > 0                )
++      if ( FT_HAS_MULTIPLE_MASTERS( ttface ) )
+       {
+         error = FT_Set_Named_Instance( ttface, instance_index );
+         if ( error )
+@@ -990,16 +994,16 @@
+     FT_Error        error;
+     FT_UInt         i;
+ 
+-    /* unscaled CVT values are already stored in 26.6 format */
+-    FT_Fixed  scale = size->ttmetrics.scale >> 6;
+-
+ 
+     /* Scale the cvt values to the new ppem.            */
+     /* By default, we use the y ppem value for scaling. */
+     FT_TRACE6(( "CVT values:\n" ));
+     for ( i = 0; i < size->cvt_size; i++ )
+     {
+-      size->cvt[i] = FT_MulFix( face->cvt[i], scale );
++      /* Unscaled CVT values are already stored in 26.6 format.            */
++      /* Note that this scaling operation is very sensitive to rounding;   */
++      /* the integer division by 64 must be applied to the first argument. */
++      size->cvt[i] = FT_MulFix( face->cvt[i] / 64, size->ttmetrics.scale );
+       FT_TRACE6(( "  %3d: %f (%f)\n",
+                   i, (double)face->cvt[i] / 64, (double)size->cvt[i] / 64 ));
+     }
+diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttobjs.h b/src/java.desktop/share/native/libfreetype/src/truetype/ttobjs.h
+index 40eb37b4c..9c36ca783 100644
+--- a/src/java.desktop/share/native/libfreetype/src/truetype/ttobjs.h
++++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttobjs.h
+@@ -4,7 +4,7 @@
+  *
+  *   Objects manager (specification).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+@@ -105,7 +105,7 @@ FT_BEGIN_HEADER
+   FT_LOCAL( FT_Error )
+   tt_glyphzone_new( FT_Memory     memory,
+                     FT_UShort     maxPoints,
+-                    FT_Short      maxContours,
++                    FT_UShort     maxContours,
+                     TT_GlyphZone  zone );
+ 
+ #endif /* TT_USE_BYTECODE_INTERPRETER */
+diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttpload.c b/src/java.desktop/share/native/libfreetype/src/truetype/ttpload.c
+index 54a64c7b4..9505b5f17 100644
+--- a/src/java.desktop/share/native/libfreetype/src/truetype/ttpload.c
++++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttpload.c
+@@ -4,7 +4,7 @@
+  *
+  *   TrueType-specific tables loader (body).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttpload.h b/src/java.desktop/share/native/libfreetype/src/truetype/ttpload.h
+index ed229fa46..bc32b5802 100644
+--- a/src/java.desktop/share/native/libfreetype/src/truetype/ttpload.h
++++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttpload.h
+@@ -4,7 +4,7 @@
+  *
+  *   TrueType-specific tables loader (specification).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1afm.c b/src/java.desktop/share/native/libfreetype/src/type1/t1afm.c
+index d9b9398b0..a63cd4dc4 100644
+--- a/src/java.desktop/share/native/libfreetype/src/type1/t1afm.c
++++ b/src/java.desktop/share/native/libfreetype/src/type1/t1afm.c
+@@ -4,7 +4,7 @@
+  *
+  *   AFM support for Type 1 fonts (body).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1afm.h b/src/java.desktop/share/native/libfreetype/src/type1/t1afm.h
+index e0d5aa5a8..7f5cdda19 100644
+--- a/src/java.desktop/share/native/libfreetype/src/type1/t1afm.h
++++ b/src/java.desktop/share/native/libfreetype/src/type1/t1afm.h
+@@ -4,7 +4,7 @@
+  *
+  *   AFM support for Type 1 fonts (specification).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1driver.c b/src/java.desktop/share/native/libfreetype/src/type1/t1driver.c
+index a4cdf372a..8ed01914a 100644
+--- a/src/java.desktop/share/native/libfreetype/src/type1/t1driver.c
++++ b/src/java.desktop/share/native/libfreetype/src/type1/t1driver.c
+@@ -4,7 +4,7 @@
+  *
+  *   Type 1 driver interface (body).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+@@ -312,10 +312,7 @@
+       {
+         retval = ft_strlen( type1->glyph_names[idx] ) + 1;
+         if ( value && value_len >= retval )
+-        {
+           ft_memcpy( value, (void *)( type1->glyph_names[idx] ), retval );
+-          ((FT_Char *)value)[retval - 1] = (FT_Char)'\0';
+-        }
+       }
+       break;
+ 
+@@ -344,11 +341,8 @@
+       {
+         retval = ft_strlen( type1->encoding.char_name[idx] ) + 1;
+         if ( value && value_len >= retval )
+-        {
+           ft_memcpy( value, (void *)( type1->encoding.char_name[idx] ),
+-                     retval - 1 );
+-          ((FT_Char *)value)[retval - 1] = (FT_Char)'\0';
+-        }
++                     retval );
+       }
+       break;
+ 
+diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1driver.h b/src/java.desktop/share/native/libfreetype/src/type1/t1driver.h
+index ee7fcf43e..5ff52b55b 100644
+--- a/src/java.desktop/share/native/libfreetype/src/type1/t1driver.h
++++ b/src/java.desktop/share/native/libfreetype/src/type1/t1driver.h
+@@ -4,7 +4,7 @@
+  *
+  *   High-level Type 1 driver interface (specification).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1errors.h b/src/java.desktop/share/native/libfreetype/src/type1/t1errors.h
+index 2fbd1e513..8aeb24ae1 100644
+--- a/src/java.desktop/share/native/libfreetype/src/type1/t1errors.h
++++ b/src/java.desktop/share/native/libfreetype/src/type1/t1errors.h
+@@ -4,7 +4,7 @@
+  *
+  *   Type 1 error codes (specification only).
+  *
+- * Copyright (C) 2001-2023 by
++ * Copyright (C) 2001-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1gload.c b/src/java.desktop/share/native/libfreetype/src/type1/t1gload.c
+index a32a4649d..c29e68251 100644
+--- a/src/java.desktop/share/native/libfreetype/src/type1/t1gload.c
++++ b/src/java.desktop/share/native/libfreetype/src/type1/t1gload.c
+@@ -4,7 +4,7 @@
+  *
+  *   Type 1 Glyph Loader (body).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1gload.h b/src/java.desktop/share/native/libfreetype/src/type1/t1gload.h
+index c06484758..17a6a5941 100644
+--- a/src/java.desktop/share/native/libfreetype/src/type1/t1gload.h
++++ b/src/java.desktop/share/native/libfreetype/src/type1/t1gload.h
+@@ -4,7 +4,7 @@
+  *
+  *   Type 1 Glyph Loader (specification).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1load.c b/src/java.desktop/share/native/libfreetype/src/type1/t1load.c
+index be7cd0fd5..ee7fb42a5 100644
+--- a/src/java.desktop/share/native/libfreetype/src/type1/t1load.c
++++ b/src/java.desktop/share/native/libfreetype/src/type1/t1load.c
+@@ -4,7 +4,7 @@
+  *
+  *   Type 1 font loader (body).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+@@ -751,6 +751,7 @@
+         PS_DesignMap  dmap = blend->design_map + n;
+ 
+ 
++        FT_FREE( dmap->blend_points );
+         FT_FREE( dmap->design_points );
+         dmap->num_points = 0;
+       }
+@@ -1043,9 +1044,9 @@
+       }
+ 
+       /* allocate design map data */
+-      if ( FT_QNEW_ARRAY( map->design_points, num_points * 2 ) )
++      if ( FT_QNEW_ARRAY( map->design_points, num_points ) ||
++           FT_QNEW_ARRAY( map->blend_points,  num_points ) )
+         goto Exit;
+-      map->blend_points = map->design_points + num_points;
+       map->num_points   = (FT_Byte)num_points;
+ 
+       for ( p = 0; p < num_points; p++ )
+@@ -1876,9 +1877,8 @@
+         }
+ 
+         /* t1_decrypt() shouldn't write to base -- make temporary copy */
+-        if ( FT_QALLOC( temp, size ) )
++        if ( FT_DUP( temp, base, size ) )
+           goto Fail;
+-        FT_MEM_COPY( temp, base, size );
+         psaux->t1_decrypt( temp, size, 4330 );
+         size -= (FT_ULong)t1face->type1.private_dict.lenIV;
+         error = T1_Add_Table( table,
+@@ -2090,9 +2090,8 @@
+           }
+ 
+           /* t1_decrypt() shouldn't write to base -- make temporary copy */
+-          if ( FT_QALLOC( temp, size ) )
++          if ( FT_DUP( temp, base, size ) )
+             goto Fail;
+-          FT_MEM_COPY( temp, base, size );
+           psaux->t1_decrypt( temp, size, 4330 );
+           size -= (FT_ULong)t1face->type1.private_dict.lenIV;
+           error = T1_Add_Table( code_table,
+@@ -2284,7 +2283,7 @@
+                        T1_FIELD_DICT_PRIVATE )
+ #endif
+ 
+-    { 0, T1_FIELD_LOCATION_CID_INFO, T1_FIELD_TYPE_NONE, 0, 0, 0, 0, 0, 0 }
++    T1_FIELD_ZERO
+   };
+ 
+ 
+@@ -2392,18 +2391,13 @@
+           T1_Field  keyword = (T1_Field)t1_keywords;
+ 
+ 
+-          for (;;)
++          while ( keyword->len )
+           {
+-            FT_Byte*  name;
++            FT_Byte*  name = (FT_Byte*)keyword->ident;
+ 
+ 
+-            name = (FT_Byte*)keyword->ident;
+-            if ( !name )
+-              break;
+-
+-            if ( cur[0] == name[0]                      &&
+-                 len == ft_strlen( (const char *)name ) &&
+-                 ft_memcmp( cur, name, len ) == 0       )
++            if ( keyword->len == len              &&
++                 ft_memcmp( cur, name, len ) == 0 )
+             {
+               /* We found it -- run the parsing callback!     */
+               /* We record every instance of every field      */
+diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1load.h b/src/java.desktop/share/native/libfreetype/src/type1/t1load.h
+index d8c9d2d8a..a45efa7cb 100644
+--- a/src/java.desktop/share/native/libfreetype/src/type1/t1load.h
++++ b/src/java.desktop/share/native/libfreetype/src/type1/t1load.h
+@@ -4,7 +4,7 @@
+  *
+  *   Type 1 font loader (specification).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1objs.c b/src/java.desktop/share/native/libfreetype/src/type1/t1objs.c
+index 69e4fd506..b1b27c31f 100644
+--- a/src/java.desktop/share/native/libfreetype/src/type1/t1objs.c
++++ b/src/java.desktop/share/native/libfreetype/src/type1/t1objs.c
+@@ -4,7 +4,7 @@
+  *
+  *   Type 1 objects manager (body).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1objs.h b/src/java.desktop/share/native/libfreetype/src/type1/t1objs.h
+index 03847b27e..3809370c1 100644
+--- a/src/java.desktop/share/native/libfreetype/src/type1/t1objs.h
++++ b/src/java.desktop/share/native/libfreetype/src/type1/t1objs.h
+@@ -4,7 +4,7 @@
+  *
+  *   Type 1 objects manager (specification).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1parse.c b/src/java.desktop/share/native/libfreetype/src/type1/t1parse.c
+index 6dec6c16c..3717ea7c5 100644
+--- a/src/java.desktop/share/native/libfreetype/src/type1/t1parse.c
++++ b/src/java.desktop/share/native/libfreetype/src/type1/t1parse.c
+@@ -4,7 +4,7 @@
+  *
+  *   Type 1 parser (body).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1parse.h b/src/java.desktop/share/native/libfreetype/src/type1/t1parse.h
+index 0d9a2865d..a0a2134d4 100644
+--- a/src/java.desktop/share/native/libfreetype/src/type1/t1parse.h
++++ b/src/java.desktop/share/native/libfreetype/src/type1/t1parse.h
+@@ -4,7 +4,7 @@
+  *
+  *   Type 1 parser (specification).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1tokens.h b/src/java.desktop/share/native/libfreetype/src/type1/t1tokens.h
+index 40f360926..5a3d2f1ef 100644
+--- a/src/java.desktop/share/native/libfreetype/src/type1/t1tokens.h
++++ b/src/java.desktop/share/native/libfreetype/src/type1/t1tokens.h
+@@ -4,7 +4,7 @@
+  *
+  *   Type 1 tokenizer (specification).
+  *
+- * Copyright (C) 1996-2023 by
++ * Copyright (C) 1996-2024 by
+  * David Turner, Robert Wilhelm, and Werner Lemberg.
+  *
+  * This file is part of the FreeType project, and may only be used,
+diff --git a/src/java.desktop/share/native/libharfbuzz/OT/Color/CBDT/CBDT.hh b/src/java.desktop/share/native/libharfbuzz/OT/Color/CBDT/CBDT.hh
+index d7b2b13e4..43a611a00 100644
+--- a/src/java.desktop/share/native/libharfbuzz/OT/Color/CBDT/CBDT.hh
++++ b/src/java.desktop/share/native/libharfbuzz/OT/Color/CBDT/CBDT.hh
+@@ -204,6 +204,7 @@ struct IndexSubtable
+   {
+     TRACE_SANITIZE (this);
+     if (!u.header.sanitize (c)) return_trace (false);
++    hb_barrier ();
+     switch (u.header.indexFormat)
+     {
+     case 1: return_trace (u.format1.sanitize (c, glyph_count));
+@@ -378,6 +379,7 @@ struct IndexSubtableRecord
+   {
+     TRACE_SANITIZE (this);
+     return_trace (c->check_struct (this) &&
++                  hb_barrier () &&
+                   firstGlyphIndex <= lastGlyphIndex &&
+                   offsetToSubtable.sanitize (c, base, lastGlyphIndex - firstGlyphIndex + 1));
+   }
+@@ -635,6 +637,7 @@ struct BitmapSizeTable
+   {
+     TRACE_SANITIZE (this);
+     return_trace (c->check_struct (this) &&
++                  hb_barrier () &&
+                   indexSubtableArrayOffset.sanitize (c, base, numberOfIndexSubtables) &&
+                   horizontal.sanitize (c) &&
+                   vertical.sanitize (c));
+@@ -738,7 +741,9 @@ struct CBLC
+   {
+     TRACE_SANITIZE (this);
+     return_trace (c->check_struct (this) &&
++                  hb_barrier () &&
+                   likely (version.major == 2 || version.major == 3) &&
++                  hb_barrier () &&
+                   sizeTables.sanitize (c, this));
+   }
+ 
+@@ -936,10 +941,12 @@ struct CBDT
+       }
+     }
+ 
+-    bool has_data () const { return cbdt.get_length (); }
++    bool has_data () const { return cbdt->version.major; }
+ 
+     bool paint_glyph (hb_font_t *font, hb_codepoint_t glyph, hb_paint_funcs_t *funcs, void *data) const
+     {
++      if (!has_data ()) return false;
++
+       hb_glyph_extents_t extents;
+       hb_glyph_extents_t pixel_extents;
+       hb_blob_t *blob = reference_png (font, glyph);
+@@ -975,6 +982,7 @@ struct CBDT
+   {
+     TRACE_SANITIZE (this);
+     return_trace (c->check_struct (this) &&
++                  hb_barrier () &&
+                   likely (version.major == 2 || version.major == 3));
+   }
+ 
+diff --git a/src/java.desktop/share/native/libharfbuzz/OT/Color/COLR/COLR.hh b/src/java.desktop/share/native/libharfbuzz/OT/Color/COLR/COLR.hh
+index fb2c42a88..4d6272d05 100644
+--- a/src/java.desktop/share/native/libharfbuzz/OT/Color/COLR/COLR.hh
++++ b/src/java.desktop/share/native/libharfbuzz/OT/Color/COLR/COLR.hh
+@@ -29,11 +29,14 @@
+ #define OT_COLOR_COLR_COLR_HH
+ 
+ #include "../../../hb.hh"
++#include "../../../hb-decycler.hh"
+ #include "../../../hb-open-type.hh"
+ #include "../../../hb-ot-var-common.hh"
+ #include "../../../hb-paint.hh"
+ #include "../../../hb-paint-extents.hh"
+ 
++#include "../CPAL/CPAL.hh"
++
+ /*
+  * COLR -- Color
+  * https://docs.microsoft.com/en-us/typography/opentype/spec/colr
+@@ -66,13 +69,13 @@ public:
+   hb_paint_funcs_t *funcs;
+   void *data;
+   hb_font_t *font;
+-  unsigned int palette_index;
++  hb_array_t palette;
+   hb_color_t foreground;
+-  VarStoreInstancer &instancer;
+-  hb_map_t current_glyphs;
+-  hb_map_t current_layers;
++  ItemVarStoreInstancer &instancer;
++  hb_decycler_t glyphs_decycler;
++  hb_decycler_t layers_decycler;
+   int depth_left = HB_MAX_NESTING_LEVEL;
+-  int edge_count = HB_COLRV1_MAX_EDGE_COUNT;
++  int edge_count = HB_MAX_GRAPH_EDGE_COUNT;
+ 
+   hb_paint_context_t (const void *base_,
+                       hb_paint_funcs_t *funcs_,
+@@ -80,12 +83,16 @@ public:
+                       hb_font_t *font_,
+                       unsigned int palette_,
+                       hb_color_t foreground_,
+-                      VarStoreInstancer &instancer_) :
++                      ItemVarStoreInstancer &instancer_) :
+     base (base_),
+     funcs (funcs_),
+     data (data_),
+     font (font_),
+-    palette_index (palette_),
++    palette (
++#ifndef HB_NO_COLOR
++             font->face->table.CPAL->get_palette_colors (palette_)
++#endif
++    ),
+     foreground (foreground_),
+     instancer (instancer_)
+   { }
+@@ -99,12 +106,7 @@ public:
+     if (color_index != 0xffff)
+     {
+       if (!funcs->custom_palette_color (data, color_index, &color))
+-      {
+-        unsigned int clen = 1;
+-        hb_face_t *face = hb_font_get_face (font);
+-
+-        hb_ot_color_palette_get_colors (face, palette_index, color_index, &clen, &color);
+-      }
++        color = palette[color_index];
+ 
+       *is_foreground = false;
+     }
+@@ -159,23 +161,35 @@ struct hb_colrv1_closure_context_t :
+   void add_palette_index (unsigned palette_index)
+   { palette_indices->add (palette_index); }
+ 
++  void add_var_idxes (unsigned first_var_idx, unsigned num_idxes)
++  {
++    if (!num_idxes || first_var_idx == VarIdx::NO_VARIATION) return;
++    variation_indices->add_range (first_var_idx, first_var_idx + num_idxes - 1);
++  }
++
+   public:
+   const void *base;
+   hb_set_t visited_paint;
+   hb_set_t *glyphs;
+   hb_set_t *layer_indices;
+   hb_set_t *palette_indices;
++  hb_set_t *variation_indices;
++  unsigned num_var_idxes;
+   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_,
++                               hb_set_t *variation_indices_,
++                               unsigned num_var_idxes_ = 1,
+                                unsigned nesting_level_left_ = HB_MAX_NESTING_LEVEL) :
+                           base (base_),
+                           glyphs (glyphs_),
+                           layer_indices (layer_indices_),
+                           palette_indices (palette_indices_),
++                          variation_indices (variation_indices_),
++                          num_var_idxes (num_var_idxes_),
+                           nesting_level_left (nesting_level_left_)
+   {}
+ };
+@@ -242,18 +256,33 @@ struct Variable
+   }
+ 
+   void closurev1 (hb_colrv1_closure_context_t* c) const
+-  { value.closurev1 (c); }
++  {
++    c->num_var_idxes = 0;
++    // update c->num_var_idxes during value closure
++    value.closurev1 (c);
++    c->add_var_idxes (varIdxBase, c->num_var_idxes);
++  }
+ 
+   bool subset (hb_subset_context_t *c,
+-               const VarStoreInstancer &instancer) const
++               const ItemVarStoreInstancer &instancer) const
+   {
+     TRACE_SUBSET (this);
+     if (!value.subset (c, instancer, varIdxBase)) return_trace (false);
+     if (c->plan->all_axes_pinned)
+       return_trace (true);
+ 
+-    //TODO: update varIdxBase for partial-instancing
+-    return_trace (c->serializer->embed (varIdxBase));
++    VarIdx new_varidx;
++    new_varidx = varIdxBase;
++    if (varIdxBase != VarIdx::NO_VARIATION)
++    {
++      hb_pair_t *new_varidx_delta;
++      if (!c->plan->colrv1_variation_idx_delta_map.has (varIdxBase, &new_varidx_delta))
++        return_trace (false);
++
++      new_varidx = hb_first (*new_varidx_delta);
++    }
++
++    return_trace (c->serializer->embed (new_varidx));
+   }
+ 
+   bool sanitize (hb_sanitize_context_t *c) const
+@@ -270,7 +299,7 @@ struct Variable
+ 
+   void get_color_stop (hb_paint_context_t *c,
+                        hb_color_stop_t *stop,
+-                       const VarStoreInstancer &instancer) const
++                       const ItemVarStoreInstancer &instancer) const
+   {
+     value.get_color_stop (c, stop, varIdxBase, instancer);
+   }
+@@ -305,7 +334,7 @@ struct NoVariable
+   { value.closurev1 (c); }
+ 
+   bool subset (hb_subset_context_t *c,
+-               const VarStoreInstancer &instancer) const
++               const ItemVarStoreInstancer &instancer) const
+   {
+     TRACE_SUBSET (this);
+     return_trace (value.subset (c, instancer, varIdxBase));
+@@ -325,7 +354,7 @@ struct NoVariable
+ 
+   void get_color_stop (hb_paint_context_t *c,
+                        hb_color_stop_t *stop,
+-                       const VarStoreInstancer &instancer) const
++                       const ItemVarStoreInstancer &instancer) const
+   {
+     value.get_color_stop (c, stop, VarIdx::NO_VARIATION, instancer);
+   }
+@@ -345,10 +374,13 @@ struct NoVariable
+ struct ColorStop
+ {
+   void closurev1 (hb_colrv1_closure_context_t* c) const
+-  { c->add_palette_index (paletteIndex); }
++  {
++    c->add_palette_index (paletteIndex);
++    c->num_var_idxes = 2;
++  }
+ 
+   bool subset (hb_subset_context_t *c,
+-               const VarStoreInstancer &instancer,
++               const ItemVarStoreInstancer &instancer,
+                uint32_t varIdxBase) const
+   {
+     TRACE_SUBSET (this);
+@@ -374,7 +406,7 @@ struct ColorStop
+   void get_color_stop (hb_paint_context_t *c,
+                        hb_color_stop_t *out,
+                        uint32_t varIdx,
+-                       const VarStoreInstancer &instancer) const
++                       const ItemVarStoreInstancer &instancer) const
+   {
+     out->offset = stopOffset.to_float(instancer (varIdx, 0));
+     out->color = c->get_color (paletteIndex,
+@@ -410,7 +442,7 @@ struct ColorLine
+   }
+ 
+   bool subset (hb_subset_context_t *c,
+-               const VarStoreInstancer &instancer) const
++               const ItemVarStoreInstancer &instancer) const
+   {
+     TRACE_SUBSET (this);
+     auto *out = c->serializer->start_embed (this);
+@@ -439,7 +471,7 @@ struct ColorLine
+                    unsigned int start,
+                    unsigned int *count,
+                    hb_color_stop_t *color_stops,
+-                   const VarStoreInstancer &instancer) const
++                   const ItemVarStoreInstancer &instancer) const
+   {
+     unsigned int len = stops.len;
+ 
+@@ -542,8 +574,11 @@ struct Affine2x3
+     return_trace (c->check_struct (this));
+   }
+ 
++  void closurev1 (hb_colrv1_closure_context_t* c) const
++  { c->num_var_idxes = 6; }
++
+   bool subset (hb_subset_context_t *c,
+-               const VarStoreInstancer &instancer,
++               const ItemVarStoreInstancer &instancer,
+                uint32_t varIdxBase) const
+   {
+     TRACE_SUBSET (this);
+@@ -588,7 +623,7 @@ struct PaintColrLayers
+   void closurev1 (hb_colrv1_closure_context_t* c) const;
+ 
+   bool subset (hb_subset_context_t *c,
+-               const VarStoreInstancer &instancer HB_UNUSED) const
++               const ItemVarStoreInstancer &instancer HB_UNUSED) const
+   {
+     TRACE_SUBSET (this);
+     auto *out = c->serializer->embed (this);
+@@ -617,10 +652,13 @@ struct PaintColrLayers
+ struct PaintSolid
+ {
+   void closurev1 (hb_colrv1_closure_context_t* c) const
+-  { c->add_palette_index (paletteIndex); }
++  {
++    c->add_palette_index (paletteIndex);
++    c->num_var_idxes = 1;
++  }
+ 
+   bool subset (hb_subset_context_t *c,
+-               const VarStoreInstancer &instancer,
++               const ItemVarStoreInstancer &instancer,
+                uint32_t varIdxBase) const
+   {
+     TRACE_SUBSET (this);
+@@ -666,10 +704,13 @@ template  class Var>
+ struct PaintLinearGradient
+ {
+   void closurev1 (hb_colrv1_closure_context_t* c) const
+-  { (this+colorLine).closurev1 (c); }
++  {
++    (this+colorLine).closurev1 (c);
++    c->num_var_idxes = 6;
++  }
+ 
+   bool subset (hb_subset_context_t *c,
+-               const VarStoreInstancer &instancer,
++               const ItemVarStoreInstancer &instancer,
+                uint32_t varIdxBase) const
+   {
+     TRACE_SUBSET (this);
+@@ -733,10 +774,13 @@ template  class Var>
+ struct PaintRadialGradient
+ {
+   void closurev1 (hb_colrv1_closure_context_t* c) const
+-  { (this+colorLine).closurev1 (c); }
++  {
++    (this+colorLine).closurev1 (c);
++    c->num_var_idxes = 6;
++  }
+ 
+   bool subset (hb_subset_context_t *c,
+-               const VarStoreInstancer &instancer,
++               const ItemVarStoreInstancer &instancer,
+                uint32_t varIdxBase) const
+   {
+     TRACE_SUBSET (this);
+@@ -800,10 +844,13 @@ template  class Var>
+ struct PaintSweepGradient
+ {
+   void closurev1 (hb_colrv1_closure_context_t* c) const
+-  { (this+colorLine).closurev1 (c); }
++  {
++    (this+colorLine).closurev1 (c);
++    c->num_var_idxes = 4;
++  }
+ 
+   bool subset (hb_subset_context_t *c,
+-               const VarStoreInstancer &instancer,
++               const ItemVarStoreInstancer &instancer,
+                uint32_t varIdxBase) const
+   {
+     TRACE_SUBSET (this);
+@@ -863,7 +910,7 @@ struct PaintGlyph
+   void closurev1 (hb_colrv1_closure_context_t* c) const;
+ 
+   bool subset (hb_subset_context_t *c,
+-               const VarStoreInstancer &instancer) const
++               const ItemVarStoreInstancer &instancer) const
+   {
+     TRACE_SUBSET (this);
+     auto *out = c->serializer->embed (this);
+@@ -906,7 +953,7 @@ struct PaintColrGlyph
+   void closurev1 (hb_colrv1_closure_context_t* c) const;
+ 
+   bool subset (hb_subset_context_t *c,
+-               const VarStoreInstancer &instancer HB_UNUSED) const
++               const ItemVarStoreInstancer &instancer HB_UNUSED) const
+   {
+     TRACE_SUBSET (this);
+     auto *out = c->serializer->embed (this);
+@@ -936,7 +983,7 @@ struct PaintTransform
+   HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
+ 
+   bool subset (hb_subset_context_t *c,
+-               const VarStoreInstancer &instancer) const
++               const ItemVarStoreInstancer &instancer) const
+   {
+     TRACE_SUBSET (this);
+     auto *out = c->serializer->embed (this);
+@@ -958,7 +1005,7 @@ struct PaintTransform
+   void paint_glyph (hb_paint_context_t *c) const
+   {
+     TRACE_PAINT (this);
+-    (this+transform).paint_glyph (c);
++    (this+transform).paint_glyph (c); // This does a push_transform()
+     c->recurse (this+src);
+     c->funcs->pop_transform (c->data);
+   }
+@@ -975,7 +1022,7 @@ struct PaintTranslate
+   HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
+ 
+   bool subset (hb_subset_context_t *c,
+-               const VarStoreInstancer &instancer,
++               const ItemVarStoreInstancer &instancer,
+                uint32_t varIdxBase) const
+   {
+     TRACE_SUBSET (this);
+@@ -1024,7 +1071,7 @@ struct PaintScale
+   HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
+ 
+   bool subset (hb_subset_context_t *c,
+-               const VarStoreInstancer &instancer,
++               const ItemVarStoreInstancer &instancer,
+                uint32_t varIdxBase) const
+   {
+     TRACE_SUBSET (this);
+@@ -1073,7 +1120,7 @@ struct PaintScaleAroundCenter
+   HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
+ 
+   bool subset (hb_subset_context_t *c,
+-               const VarStoreInstancer &instancer,
++               const ItemVarStoreInstancer &instancer,
+                uint32_t varIdxBase) const
+   {
+     TRACE_SUBSET (this);
+@@ -1132,7 +1179,7 @@ struct PaintScaleUniform
+   HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
+ 
+   bool subset (hb_subset_context_t *c,
+-               const VarStoreInstancer &instancer,
++               const ItemVarStoreInstancer &instancer,
+                uint32_t varIdxBase) const
+   {
+     TRACE_SUBSET (this);
+@@ -1176,7 +1223,7 @@ struct PaintScaleUniformAroundCenter
+   HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
+ 
+   bool subset (hb_subset_context_t *c,
+-               const VarStoreInstancer &instancer,
++               const ItemVarStoreInstancer &instancer,
+                uint32_t varIdxBase) const
+   {
+     TRACE_SUBSET (this);
+@@ -1232,7 +1279,7 @@ struct PaintRotate
+   HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
+ 
+   bool subset (hb_subset_context_t *c,
+-               const VarStoreInstancer &instancer,
++               const ItemVarStoreInstancer &instancer,
+                uint32_t varIdxBase) const
+   {
+     TRACE_SUBSET (this);
+@@ -1276,7 +1323,7 @@ struct PaintRotateAroundCenter
+   HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
+ 
+   bool subset (hb_subset_context_t *c,
+-               const VarStoreInstancer &instancer,
++               const ItemVarStoreInstancer &instancer,
+                uint32_t varIdxBase) const
+   {
+     TRACE_SUBSET (this);
+@@ -1332,7 +1379,7 @@ struct PaintSkew
+   HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
+ 
+   bool subset (hb_subset_context_t *c,
+-               const VarStoreInstancer &instancer,
++               const ItemVarStoreInstancer &instancer,
+                uint32_t varIdxBase) const
+   {
+     TRACE_SUBSET (this);
+@@ -1381,7 +1428,7 @@ struct PaintSkewAroundCenter
+   HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
+ 
+   bool subset (hb_subset_context_t *c,
+-               const VarStoreInstancer &instancer,
++               const ItemVarStoreInstancer &instancer,
+                uint32_t varIdxBase) const
+   {
+     TRACE_SUBSET (this);
+@@ -1440,7 +1487,7 @@ struct PaintComposite
+   void closurev1 (hb_colrv1_closure_context_t* c) const;
+ 
+   bool subset (hb_subset_context_t *c,
+-               const VarStoreInstancer &instancer) const
++               const ItemVarStoreInstancer &instancer) const
+   {
+     TRACE_SUBSET (this);
+     auto *out = c->serializer->embed (this);
+@@ -1491,7 +1538,7 @@ struct ClipBoxFormat1
+     return_trace (c->check_struct (this));
+   }
+ 
+-  void get_clip_box (ClipBoxData &clip_box, const VarStoreInstancer &instancer HB_UNUSED) const
++  void get_clip_box (ClipBoxData &clip_box, const ItemVarStoreInstancer &instancer HB_UNUSED) const
+   {
+     clip_box.xMin = xMin;
+     clip_box.yMin = yMin;
+@@ -1500,7 +1547,7 @@ struct ClipBoxFormat1
+   }
+ 
+   bool subset (hb_subset_context_t *c,
+-               const VarStoreInstancer &instancer,
++               const ItemVarStoreInstancer &instancer,
+                uint32_t varIdxBase) const
+   {
+     TRACE_SUBSET (this);
+@@ -1533,7 +1580,7 @@ struct ClipBoxFormat1
+ 
+ struct ClipBoxFormat2 : Variable
+ {
+-  void get_clip_box (ClipBoxData &clip_box, const VarStoreInstancer &instancer) const
++  void get_clip_box (ClipBoxData &clip_box, const ItemVarStoreInstancer &instancer) const
+   {
+     value.get_clip_box(clip_box, instancer);
+     if (instancer)
+@@ -1544,12 +1591,15 @@ struct ClipBoxFormat2 : Variable
+       clip_box.yMax += roundf (instancer (varIdxBase, 3));
+     }
+   }
++
++  void closurev1 (hb_colrv1_closure_context_t* c) const
++  { c->variation_indices->add_range (varIdxBase, varIdxBase + 3); }
+ };
+ 
+ struct ClipBox
+ {
+   bool subset (hb_subset_context_t *c,
+-               const VarStoreInstancer &instancer) const
++               const ItemVarStoreInstancer &instancer) const
+   {
+     TRACE_SUBSET (this);
+     switch (u.format) {
+@@ -1559,6 +1609,14 @@ struct ClipBox
+     }
+   }
+ 
++  void closurev1 (hb_colrv1_closure_context_t* c) const
++  {
++    switch (u.format) {
++    case 2: u.format2.closurev1 (c);
++    default:return;
++    }
++  }
++
+   template 
+   typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
+   {
+@@ -1572,7 +1630,7 @@ struct ClipBox
+   }
+ 
+   bool get_extents (hb_glyph_extents_t *extents,
+-                    const VarStoreInstancer &instancer) const
++                    const ItemVarStoreInstancer &instancer) const
+   {
+     ClipBoxData clip_box;
+     switch (u.format) {
+@@ -1606,9 +1664,15 @@ struct ClipRecord
+   int cmp (hb_codepoint_t g) const
+   { return g < startGlyphID ? -1 : g <= endGlyphID ? 0 : +1; }
+ 
++  void closurev1 (hb_colrv1_closure_context_t* c, const void *base) const
++  {
++    if (!c->glyphs->intersects (startGlyphID, endGlyphID)) return;
++    (base+clipBox).closurev1 (c);
++  }
++
+   bool subset (hb_subset_context_t *c,
+                const void *base,
+-               const VarStoreInstancer &instancer) const
++               const ItemVarStoreInstancer &instancer) const
+   {
+     TRACE_SUBSET (this);
+     auto *out = c->serializer->embed (*this);
+@@ -1625,7 +1689,7 @@ struct ClipRecord
+ 
+   bool get_extents (hb_glyph_extents_t *extents,
+                     const void *base,
+-                    const VarStoreInstancer &instancer) const
++                    const ItemVarStoreInstancer &instancer) const
+   {
+     return (base+clipBox).get_extents (extents, instancer);
+   }
+@@ -1642,7 +1706,7 @@ DECLARE_NULL_NAMESPACE_BYTES (OT, ClipRecord);
+ struct ClipList
+ {
+   unsigned serialize_clip_records (hb_subset_context_t *c,
+-                                   const VarStoreInstancer &instancer,
++                                   const ItemVarStoreInstancer &instancer,
+                                    const hb_set_t& gids,
+                                    const hb_map_t& gid_offset_map) const
+   {
+@@ -1695,7 +1759,7 @@ struct ClipList
+   }
+ 
+   bool subset (hb_subset_context_t *c,
+-               const VarStoreInstancer &instancer) const
++               const ItemVarStoreInstancer &instancer) const
+   {
+     TRACE_SUBSET (this);
+     auto *out = c->serializer->start_embed (*this);
+@@ -1735,7 +1799,7 @@ struct ClipList
+   bool
+   get_extents (hb_codepoint_t gid,
+                hb_glyph_extents_t *extents,
+-               const VarStoreInstancer &instancer) const
++               const ItemVarStoreInstancer &instancer) const
+   {
+     auto *rec = clips.as_array ().bsearch (gid);
+     if (rec)
+@@ -1855,7 +1919,7 @@ struct BaseGlyphPaintRecord
+ 
+   bool serialize (hb_serialize_context_t *s, const hb_map_t* glyph_map,
+                   const void* src_base, hb_subset_context_t *c,
+-                  const VarStoreInstancer &instancer) const
++                  const ItemVarStoreInstancer &instancer) const
+   {
+     TRACE_SERIALIZE (this);
+     auto *out = s->embed (this);
+@@ -1884,7 +1948,7 @@ struct BaseGlyphPaintRecord
+ struct BaseGlyphList : SortedArray32Of
+ {
+   bool subset (hb_subset_context_t *c,
+-               const VarStoreInstancer &instancer) const
++               const ItemVarStoreInstancer &instancer) const
+   {
+     TRACE_SUBSET (this);
+     auto *out = c->serializer->start_embed (this);
+@@ -1916,7 +1980,7 @@ struct LayerList : Array32OfOffset32To
+   { return this+(*this)[i]; }
+ 
+   bool subset (hb_subset_context_t *c,
+-               const VarStoreInstancer &instancer) const
++               const ItemVarStoreInstancer &instancer) const
+   {
+     TRACE_SUBSET (this);
+     auto *out = c->serializer->start_embed (this);
+@@ -1941,6 +2005,76 @@ struct LayerList : Array32OfOffset32To
+   }
+ };
+ 
++struct delta_set_index_map_subset_plan_t
++{
++  unsigned get_inner_bit_count () const { return inner_bit_count; }
++  unsigned get_width ()           const { return ((outer_bit_count + inner_bit_count + 7) / 8); }
++  hb_array_t get_output_map () const { return output_map.as_array (); }
++
++  delta_set_index_map_subset_plan_t (const hb_map_t &new_deltaset_idx_varidx_map)
++  {
++    map_count = 0;
++    outer_bit_count = 0;
++    inner_bit_count = 1;
++    output_map.init ();
++
++    /* search backwards */
++    unsigned count = new_deltaset_idx_varidx_map.get_population ();
++    if (!count) return;
++
++    unsigned last_idx = (unsigned)-1;
++    unsigned last_varidx = (unsigned)-1;
++
++    for (unsigned i = count; i; i--)
++    {
++      unsigned delta_set_idx = i - 1;
++      unsigned var_idx = new_deltaset_idx_varidx_map.get (delta_set_idx);
++      if (i == count)
++      {
++        last_idx = delta_set_idx;
++        last_varidx = var_idx;
++        continue;
++      }
++      if (var_idx != last_varidx)
++        break;
++      last_idx = delta_set_idx;
++    }
++
++    map_count = last_idx + 1;
++  }
++
++  bool remap (const hb_map_t &new_deltaset_idx_varidx_map)
++  {
++    /* recalculate bit_count */
++    outer_bit_count = 1;
++    inner_bit_count = 1;
++
++    if (unlikely (!output_map.resize (map_count, false))) return false;
++
++    for (unsigned idx = 0; idx < map_count; idx++)
++    {
++      uint32_t *var_idx;
++      if (!new_deltaset_idx_varidx_map.has (idx, &var_idx)) return false;
++      output_map.arrayZ[idx] = *var_idx;
++
++      unsigned outer = (*var_idx) >> 16;
++      unsigned bit_count = (outer == 0) ? 1 : hb_bit_storage (outer);
++      outer_bit_count = hb_max (bit_count, outer_bit_count);
++
++      unsigned inner = (*var_idx) & 0xFFFF;
++      bit_count = (inner == 0) ? 1 : hb_bit_storage (inner);
++      inner_bit_count = hb_max (bit_count, inner_bit_count);
++    }
++    return true;
++  }
++
++  private:
++  unsigned map_count;
++  unsigned outer_bit_count;
++  unsigned inner_bit_count;
++  hb_vector_t output_map;
++};
++
+ struct COLR
+ {
+   static constexpr hb_tag_t tableTag = HB_OT_TAG_COLR;
+@@ -1948,10 +2082,11 @@ struct COLR
+   bool has_v0_data () const { return numBaseGlyphs; }
+   bool has_v1_data () const
+   {
+-    if (version == 1)
+-      return (this+baseGlyphList).len > 0;
++    if (version < 1)
++      return false;
++    hb_barrier ();
+ 
+-    return false;
++    return (this+baseGlyphList).len > 0;
+   }
+ 
+   unsigned int get_glyph_layers (hb_codepoint_t       glyph,
+@@ -1991,8 +2126,26 @@ struct COLR
+ 
+     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); }
++                        hb_set_t *palette_indices,
++                        hb_set_t *variation_indices,
++                        hb_set_t *delta_set_indices) const
++    { colr->closure_forV1 (glyphset, layer_indices, palette_indices, variation_indices, delta_set_indices); }
++
++    bool has_var_store () const
++    { return colr->has_var_store (); }
++
++    const ItemVariationStore &get_var_store () const
++    { return colr->get_var_store (); }
++    const ItemVariationStore *get_var_store_ptr () const
++    { return colr->get_var_store_ptr (); }
++
++    bool has_delta_set_index_map () const
++    { return colr->has_delta_set_index_map (); }
++
++    const DeltaSetIndexMap &get_delta_set_index_map () const
++    { return colr->get_delta_set_index_map (); }
++    const DeltaSetIndexMap *get_delta_set_index_map_ptr () const
++    { return colr->get_delta_set_index_map_ptr (); }
+ 
+     private:
+     hb_blob_ptr_t colr;
+@@ -2029,12 +2182,16 @@ struct COLR
+ 
+   void closure_forV1 (hb_set_t *glyphset,
+                       hb_set_t *layer_indices,
+-                      hb_set_t *palette_indices) const
++                      hb_set_t *palette_indices,
++                      hb_set_t *variation_indices,
++                      hb_set_t *delta_set_indices) const
+   {
+-    if (version != 1) return;
++    if (version < 1) return;
++    hb_barrier ();
++
+     hb_set_t visited_glyphs;
+ 
+-    hb_colrv1_closure_context_t c (this, &visited_glyphs, layer_indices, palette_indices);
++    hb_colrv1_closure_context_t c (this, &visited_glyphs, layer_indices, palette_indices, variation_indices);
+     const BaseGlyphList &baseglyph_paintrecords = this+baseGlyphList;
+ 
+     for (const BaseGlyphPaintRecord &baseglyph_paintrecord: baseglyph_paintrecords.iter ())
+@@ -2046,6 +2203,22 @@ struct COLR
+       paint.dispatch (&c);
+     }
+     hb_set_union (glyphset, &visited_glyphs);
++
++    const ClipList &cliplist = this+clipList;
++    c.glyphs = glyphset;
++    for (const ClipRecord &clip_record : cliplist.clips.iter())
++      clip_record.closurev1 (&c, &cliplist);
++
++    // if a DeltaSetIndexMap is included, collected variation indices are
++    // actually delta set indices, we need to map them into variation indices
++    if (has_delta_set_index_map ())
++    {
++      const DeltaSetIndexMap &var_idx_map = this+varIdxMap;
++      delta_set_indices->set (*variation_indices);
++      variation_indices->clear ();
++      for (unsigned delta_set_idx : *delta_set_indices)
++        variation_indices->add (var_idx_map.map (delta_set_idx));
++    }
+   }
+ 
+   const LayerList& get_layerList () const
+@@ -2054,14 +2227,37 @@ struct COLR
+   const BaseGlyphList& get_baseglyphList () const
+   { return (this+baseGlyphList); }
+ 
++  bool has_var_store () const
++  { return version >= 1 && hb_barrier () && varStore != 0; }
++
++  bool has_delta_set_index_map () const
++  { return version >= 1 && hb_barrier () && varIdxMap != 0; }
++
++  bool has_clip_list () const
++  { return version >= 1 && hb_barrier () && clipList != 0; }
++
++  const DeltaSetIndexMap &get_delta_set_index_map () const
++  { return has_delta_set_index_map () && hb_barrier () ? this+varIdxMap : Null (DeltaSetIndexMap); }
++  const DeltaSetIndexMap *get_delta_set_index_map_ptr () const
++  { return has_delta_set_index_map () && hb_barrier () ? &(this+varIdxMap) : nullptr; }
++
++  const ItemVariationStore &get_var_store () const
++  { return has_var_store () && hb_barrier () ? this+varStore : Null (ItemVariationStore); }
++  const ItemVariationStore *get_var_store_ptr () const
++  { return has_var_store () && hb_barrier () ? &(this+varStore) : nullptr; }
++
++  const ClipList &get_clip_list () const
++  { return has_clip_list () && hb_barrier () ? this+clipList : Null (ClipList); }
++
+   bool sanitize (hb_sanitize_context_t *c) const
+   {
+     TRACE_SANITIZE (this);
+     return_trace (c->check_struct (this) &&
++                  hb_barrier () &&
+                   (this+baseGlyphsZ).sanitize (c, numBaseGlyphs) &&
+                   (this+layersZ).sanitize (c, numLayers) &&
+                   (version == 0 ||
+-                   (version == 1 &&
++                   (hb_barrier () &&
+                     baseGlyphList.sanitize (c, this) &&
+                     layerList.sanitize (c, this) &&
+                     clipList.sanitize (c, this) &&
+@@ -2127,6 +2323,94 @@ struct COLR
+     return record;
+   }
+ 
++  bool downgrade_to_V0 (const hb_set_t &glyphset) const
++  {
++    //no more COLRv1 glyphs, downgrade to version 0
++    for (const BaseGlyphPaintRecord& _ : get_baseglyphList ())
++      if (glyphset.has (_.glyphId))
++        return false;
++
++    return true;
++  }
++
++  bool subset_varstore (hb_subset_context_t *c,
++                        COLR* out /* OUT */) const
++  {
++    TRACE_SUBSET (this);
++    if (!varStore || c->plan->all_axes_pinned ||
++        !c->plan->colrv1_variation_idx_delta_map)
++      return_trace (true);
++
++    const ItemVariationStore& var_store = this+varStore;
++    if (c->plan->normalized_coords)
++    {
++      item_variations_t item_vars;
++      /* turn off varstore optimization when varIdxMap is null, so we maintain
++       * original var_idx sequence */
++      bool optimize = (varIdxMap != 0) ? true : false;
++      if (!item_vars.instantiate (var_store, c->plan,
++                                  optimize, /* optimization */
++                                  optimize, /* use_no_variation_idx = false */
++                                  c->plan->colrv1_varstore_inner_maps.as_array ()))
++        return_trace (false);
++
++      /* do not serialize varStore if there's no variation data after
++       * instancing: region_list or var_data is empty */
++      if (item_vars.get_region_list () &&
++          item_vars.get_vardata_encodings () &&
++          !out->varStore.serialize_serialize (c->serializer,
++                                              item_vars.has_long_word (),
++                                              c->plan->axis_tags,
++                                              item_vars.get_region_list (),
++                                              item_vars.get_vardata_encodings ()))
++        return_trace (false);
++
++      /* if varstore is optimized, update colrv1_new_deltaset_idx_varidx_map in
++       * subset plan.
++       * If varstore is empty after instancing, varidx_map would be empty and
++       * all var_idxes will be updated to VarIdx::NO_VARIATION */
++      if (optimize)
++      {
++        const hb_map_t &varidx_map = item_vars.get_varidx_map ();
++        for (auto _ : c->plan->colrv1_new_deltaset_idx_varidx_map.iter_ref ())
++        {
++          uint32_t varidx = _.second;
++          uint32_t *new_varidx;
++          if (varidx_map.has (varidx, &new_varidx))
++            _.second = *new_varidx;
++          else
++            _.second = VarIdx::NO_VARIATION;
++        }
++      }
++    }
++    else
++    {
++      if (unlikely (!out->varStore.serialize_serialize (c->serializer,
++                                                        &var_store,
++                                                        c->plan->colrv1_varstore_inner_maps.as_array ())))
++        return_trace (false);
++    }
++
++    return_trace (true);
++  }
++
++  bool subset_delta_set_index_map (hb_subset_context_t *c,
++                                   COLR* out /* OUT */) const
++  {
++    TRACE_SUBSET (this);
++    if (!varIdxMap || c->plan->all_axes_pinned ||
++        !c->plan->colrv1_new_deltaset_idx_varidx_map)
++      return_trace (true);
++
++    const hb_map_t &deltaset_idx_varidx_map = c->plan->colrv1_new_deltaset_idx_varidx_map;
++    delta_set_index_map_subset_plan_t index_map_plan (deltaset_idx_varidx_map);
++
++    if (unlikely (!index_map_plan.remap (deltaset_idx_varidx_map)))
++      return_trace (false);
++
++    return_trace (out->varIdxMap.serialize_serialize (c->serializer, index_map_plan));
++  }
++
+   bool subset (hb_subset_context_t *c) const
+   {
+     TRACE_SUBSET (this);
+@@ -2195,34 +2479,30 @@ struct COLR
+     auto *colr_prime = c->serializer->start_embed ();
+     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));
++    if (version == 0 || downgrade_to_V0 (glyphset))
++      return_trace (colr_prime->serialize_V0 (c->serializer, 0, base_it, layer_it));
++
++    hb_barrier ();
+ 
+-    auto snap = c->serializer->snapshot ();
++    //start version 1
+     if (!c->serializer->allocate_size (5 * HBUINT32::static_size)) return_trace (false);
++    if (!colr_prime->serialize_V0 (c->serializer, version, base_it, layer_it)) return_trace (false);
+ 
+-    VarStoreInstancer instancer (varStore ? &(this+varStore) : nullptr,
+-                                 varIdxMap ? &(this+varIdxMap) : nullptr,
+-                                 c->plan->normalized_coords.as_array ());
++    /* subset ItemVariationStore first, cause varidx_map needs to be updated
++     * after instancing */
++    if (!subset_varstore (c, colr_prime)) return_trace (false);
+ 
+-    if (!colr_prime->baseGlyphList.serialize_subset (c, baseGlyphList, this, instancer))
+-    {
+-      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));
+-    }
++    ItemVarStoreInstancer instancer (get_var_store_ptr (),
++                                     get_delta_set_index_map_ptr (),
++                                     c->plan->normalized_coords.as_array ());
+ 
+-    if (!colr_prime->serialize_V0 (c->serializer, version, base_it, layer_it)) return_trace (false);
++    if (!colr_prime->baseGlyphList.serialize_subset (c, baseGlyphList, this, instancer))
++      return_trace (false);
+ 
+     colr_prime->layerList.serialize_subset (c, layerList, this, instancer);
+     colr_prime->clipList.serialize_subset (c, clipList, this, instancer);
+-    if (!varStore || c->plan->all_axes_pinned)
+-      return_trace (true);
+ 
+-    colr_prime->varIdxMap.serialize_copy (c->serializer, varIdxMap, this);
+-    colr_prime->varStore.serialize_copy (c->serializer, varStore, this);
+-    return_trace (true);
++    return_trace (subset_delta_set_index_map (c, colr_prime));
+   }
+ 
+   const Paint *get_base_glyph_paint (hb_codepoint_t glyph) const
+@@ -2242,12 +2522,10 @@ struct COLR
+   bool
+   get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const
+   {
+-    if (version != 1)
+-      return false;
+ 
+-    VarStoreInstancer instancer (&(this+varStore),
+-                                 &(this+varIdxMap),
+-                                 hb_array (font->coords, font->num_coords));
++    ItemVarStoreInstancer instancer (get_var_store_ptr (),
++                                     get_delta_set_index_map_ptr (),
++                                     hb_array (font->coords, font->num_coords));
+ 
+     if (get_clip (glyph, extents, instancer))
+     {
+@@ -2282,8 +2560,10 @@ struct COLR
+   bool
+   has_paint_for_glyph (hb_codepoint_t glyph) const
+   {
+-    if (version == 1)
++    if (version >= 1)
+     {
++      hb_barrier ();
++
+       const Paint *paint = get_base_glyph_paint (glyph);
+ 
+       return paint != nullptr;
+@@ -2294,9 +2574,9 @@ struct COLR
+ 
+   bool get_clip (hb_codepoint_t glyph,
+                  hb_glyph_extents_t *extents,
+-                 const VarStoreInstancer instancer) const
++                 const ItemVarStoreInstancer instancer) const
+   {
+-    return (this+clipList).get_extents (glyph,
++    return get_clip_list ().get_extents (glyph,
+                                         extents,
+                                         instancer);
+   }
+@@ -2305,23 +2585,23 @@ struct COLR
+   bool
+   paint_glyph (hb_font_t *font, hb_codepoint_t glyph, hb_paint_funcs_t *funcs, void *data, unsigned int palette_index, hb_color_t foreground, bool clip = true) const
+   {
+-    VarStoreInstancer instancer (&(this+varStore),
+-                                 &(this+varIdxMap),
+-                                 hb_array (font->coords, font->num_coords));
++    ItemVarStoreInstancer instancer (get_var_store_ptr (),
++                                     get_delta_set_index_map_ptr (),
++                                     hb_array (font->coords, font->num_coords));
+     hb_paint_context_t c (this, funcs, data, font, palette_index, foreground, instancer);
+-    c.current_glyphs.add (glyph);
+ 
+-    if (version == 1)
++    hb_decycler_node_t node (c.glyphs_decycler);
++    node.visit (glyph);
++
++    if (version >= 1)
+     {
++      hb_barrier ();
++
+       const Paint *paint = get_base_glyph_paint (glyph);
+       if (paint)
+       {
+         // COLRv1 glyph
+ 
+-        VarStoreInstancer instancer (&(this+varStore),
+-                                     &(this+varIdxMap),
+-                                     hb_array (font->coords, font->num_coords));
+-
+         bool is_bounded = true;
+         if (clip)
+         {
+@@ -2404,7 +2684,7 @@ struct COLR
+   Offset32To                 layerList;
+   Offset32To                  clipList;   // Offset to ClipList table (may be NULL)
+   Offset32To          varIdxMap;  // Offset to DeltaSetIndexMap table (may be NULL)
+-  Offset32To            varStore;
++  Offset32To        varStore;
+   public:
+   DEFINE_SIZE_MIN (14);
+ };
+@@ -2427,19 +2707,16 @@ void PaintColrLayers::paint_glyph (hb_paint_context_t *c) const
+ {
+   TRACE_PAINT (this);
+   const LayerList &paint_offset_lists = c->get_colr_table ()->get_layerList ();
++  hb_decycler_node_t node (c->layers_decycler);
+   for (unsigned i = firstLayerIndex; i < firstLayerIndex + numLayers; i++)
+   {
+-    if (unlikely (c->current_layers.has (i)))
+-      continue;
+-
+-    c->current_layers.add (i);
++    if (unlikely (!node.visit (i)))
++      return;
+ 
+     const Paint &paint = paint_offset_lists.get_paint (i);
+     c->funcs->push_group (c->data);
+     c->recurse (paint);
+     c->funcs->pop_group (c->data, HB_PAINT_COMPOSITE_MODE_SRC_OVER);
+-
+-    c->current_layers.del (i);
+   }
+ }
+ 
+@@ -2447,16 +2724,14 @@ void PaintColrGlyph::paint_glyph (hb_paint_context_t *c) const
+ {
+   TRACE_PAINT (this);
+ 
+-  if (unlikely (c->current_glyphs.has (gid)))
++  hb_decycler_node_t node (c->glyphs_decycler);
++  if (unlikely (!node.visit (gid)))
+     return;
+ 
+-  c->current_glyphs.add (gid);
+-
+   c->funcs->push_inverse_root_transform (c->data, c->font);
+   if (c->funcs->color_glyph (c->data, gid, c->font))
+   {
+     c->funcs->pop_transform (c->data);
+-    c->current_glyphs.del (gid);
+     return;
+   }
+   c->funcs->pop_transform (c->data);
+@@ -2479,8 +2754,6 @@ void PaintColrGlyph::paint_glyph (hb_paint_context_t *c) const
+ 
+   if (has_clip_box)
+     c->funcs->pop_clip (c->data);
+-
+-  c->current_glyphs.del (gid);
+ }
+ 
+ } /* namespace OT */
+diff --git a/src/java.desktop/share/native/libharfbuzz/OT/Color/COLR/colrv1-closure.hh b/src/java.desktop/share/native/libharfbuzz/OT/Color/COLR/colrv1-closure.hh
+index 705863d4a..9ed0aa563 100644
+--- a/src/java.desktop/share/native/libharfbuzz/OT/Color/COLR/colrv1-closure.hh
++++ b/src/java.desktop/share/native/libharfbuzz/OT/Color/COLR/colrv1-closure.hh
+@@ -66,34 +66,64 @@ HB_INTERNAL void PaintColrGlyph::closurev1 (hb_colrv1_closure_context_t* c) cons
+ 
+ template  class Var>
+ HB_INTERNAL void PaintTransform::closurev1 (hb_colrv1_closure_context_t* c) const
+-{ (this+src).dispatch (c); }
++{
++  (this+src).dispatch (c);
++  (this+transform).closurev1 (c);
++}
+ 
+ HB_INTERNAL void PaintTranslate::closurev1 (hb_colrv1_closure_context_t* c) const
+-{ (this+src).dispatch (c); }
++{
++  (this+src).dispatch (c);
++  c->num_var_idxes = 2;
++}
+ 
+ HB_INTERNAL void PaintScale::closurev1 (hb_colrv1_closure_context_t* c) const
+-{ (this+src).dispatch (c); }
++{
++  (this+src).dispatch (c);
++  c->num_var_idxes = 2;
++}
+ 
+ HB_INTERNAL void PaintScaleAroundCenter::closurev1 (hb_colrv1_closure_context_t* c) const
+-{ (this+src).dispatch (c); }
++{
++  (this+src).dispatch (c);
++  c->num_var_idxes = 4;
++}
+ 
+ HB_INTERNAL void PaintScaleUniform::closurev1 (hb_colrv1_closure_context_t* c) const
+-{ (this+src).dispatch (c); }
++{
++  (this+src).dispatch (c);
++  c->num_var_idxes = 1;
++}
+ 
+ HB_INTERNAL void PaintScaleUniformAroundCenter::closurev1 (hb_colrv1_closure_context_t* c) const
+-{ (this+src).dispatch (c); }
++{
++  (this+src).dispatch (c);
++  c->num_var_idxes = 3;
++}
+ 
+ HB_INTERNAL void PaintRotate::closurev1 (hb_colrv1_closure_context_t* c) const
+-{ (this+src).dispatch (c); }
++{
++  (this+src).dispatch (c);
++  c->num_var_idxes = 1;
++}
+ 
+ HB_INTERNAL void PaintRotateAroundCenter::closurev1 (hb_colrv1_closure_context_t* c) const
+-{ (this+src).dispatch (c); }
++{
++  (this+src).dispatch (c);
++  c->num_var_idxes = 3;
++}
+ 
+ HB_INTERNAL void PaintSkew::closurev1 (hb_colrv1_closure_context_t* c) const
+-{ (this+src).dispatch (c); }
++{
++  (this+src).dispatch (c);
++  c->num_var_idxes = 2;
++}
+ 
+ HB_INTERNAL void PaintSkewAroundCenter::closurev1 (hb_colrv1_closure_context_t* c) const
+-{ (this+src).dispatch (c); }
++{
++  (this+src).dispatch (c);
++  c->num_var_idxes = 4;
++}
+ 
+ HB_INTERNAL void PaintComposite::closurev1 (hb_colrv1_closure_context_t* c) const
+ {
+diff --git a/src/java.desktop/share/native/libharfbuzz/OT/Color/CPAL/CPAL.hh b/src/java.desktop/share/native/libharfbuzz/OT/Color/CPAL/CPAL.hh
+index ed8f5957e..51fc1b52a 100644
+--- a/src/java.desktop/share/native/libharfbuzz/OT/Color/CPAL/CPAL.hh
++++ b/src/java.desktop/share/native/libharfbuzz/OT/Color/CPAL/CPAL.hh
+@@ -187,6 +187,14 @@ struct CPAL
+   hb_ot_name_id_t get_color_name_id (unsigned int color_index) const
+   { return v1 ().get_color_name_id (this, color_index, numColors); }
+ 
++  hb_array_t get_palette_colors (unsigned int palette_index) const
++  {
++    if (unlikely (palette_index >= numPalettes))
++      return hb_array_t ();
++    unsigned int start_index = colorRecordIndicesZ[palette_index];
++    hb_array_t all_colors ((this+colorRecordsZ).arrayZ, numColorRecords);
++    return all_colors.sub_array (start_index, numColors);
++  }
+   unsigned int get_palette_colors (unsigned int  palette_index,
+                                    unsigned int  start_offset,
+                                    unsigned int *color_count, /* IN/OUT.  May be NULL. */
+@@ -214,13 +222,17 @@ struct CPAL
+                          hb_set_t *nameids_to_retain /* OUT */) const
+   {
+     if (version == 1)
++    {
++      hb_barrier ();
+       v1 ().collect_name_ids (this, numPalettes, numColors, color_index_map, nameids_to_retain);
++    }
+   }
+ 
+   private:
+   const CPALV1Tail& v1 () const
+   {
+     if (version == 0) return Null (CPALV1Tail);
++    hb_barrier ();
+     return StructAfter (*this);
+   }
+ 
+@@ -312,7 +324,10 @@ struct CPAL
+       return_trace (false);
+ 
+     if (version == 1)
++    {
++      hb_barrier ();
+       return_trace (v1 ().serialize (c->serializer, numPalettes, numColors, this, color_index_map));
++    }
+ 
+     return_trace (true);
+   }
+@@ -321,6 +336,7 @@ struct CPAL
+   {
+     TRACE_SANITIZE (this);
+     return_trace (c->check_struct (this) &&
++                  hb_barrier () &&
+                   (this+colorRecordsZ).sanitize (c, numColorRecords) &&
+                   colorRecordIndicesZ.sanitize (c, numPalettes) &&
+                   (version == 0 || v1 ().sanitize (c, this, numPalettes, numColors)));
+diff --git a/src/java.desktop/share/native/libharfbuzz/OT/Color/sbix/sbix.hh b/src/java.desktop/share/native/libharfbuzz/OT/Color/sbix/sbix.hh
+index 20b06ab13..e95d8c13a 100644
+--- a/src/java.desktop/share/native/libharfbuzz/OT/Color/sbix/sbix.hh
++++ b/src/java.desktop/share/native/libharfbuzz/OT/Color/sbix/sbix.hh
+@@ -368,6 +368,7 @@ struct sbix
+   {
+     TRACE_SANITIZE (this);
+     return_trace (likely (c->check_struct (this) &&
++                          hb_barrier () &&
+                           version >= 1 &&
+                           strikes.sanitize (c, this)));
+   }
+diff --git a/src/java.desktop/share/native/libharfbuzz/OT/Color/svg/svg.hh b/src/java.desktop/share/native/libharfbuzz/OT/Color/svg/svg.hh
+index c8ff6ab74..9f676f968 100644
+--- a/src/java.desktop/share/native/libharfbuzz/OT/Color/svg/svg.hh
++++ b/src/java.desktop/share/native/libharfbuzz/OT/Color/svg/svg.hh
+@@ -56,6 +56,7 @@ struct SVGDocumentIndexEntry
+   {
+     TRACE_SANITIZE (this);
+     return_trace (c->check_struct (this) &&
++                  hb_barrier () &&
+                   svgDoc.sanitize (c, base, svgDocLength));
+   }
+ 
+diff --git a/src/java.desktop/share/native/libharfbuzz/OT/Layout/Common/Coverage.hh b/src/java.desktop/share/native/libharfbuzz/OT/Layout/Common/Coverage.hh
+index 257b2a336..35d73c7b8 100644
+--- a/src/java.desktop/share/native/libharfbuzz/OT/Layout/Common/Coverage.hh
++++ b/src/java.desktop/share/native/libharfbuzz/OT/Layout/Common/Coverage.hh
+@@ -64,6 +64,7 @@ struct Coverage
+   {
+     TRACE_SANITIZE (this);
+     if (!u.format.sanitize (c)) return_trace (false);
++    hb_barrier ();
+     switch (u.format)
+     {
+     case 1: return_trace (u.format1.sanitize (c));
+@@ -95,6 +96,15 @@ struct Coverage
+     default:return NOT_COVERED;
+     }
+   }
++  unsigned int get_coverage (hb_codepoint_t glyph_id,
++                             hb_ot_lookup_cache_t *cache) const
++  {
++    unsigned coverage;
++    if (cache && cache->get (glyph_id, &coverage)) return coverage;
++    coverage = get_coverage (glyph_id);
++    if (cache) cache->set (glyph_id, coverage);
++    return coverage;
++  }
+ 
+   unsigned get_population () const
+   {
+@@ -200,6 +210,19 @@ struct Coverage
+     }
+   }
+ 
++  unsigned cost () const
++  {
++    switch (u.format) {
++    case 1: hb_barrier (); return u.format1.cost ();
++    case 2: hb_barrier (); return u.format2.cost ();
++#ifndef HB_NO_BEYOND_64K
++    case 3: hb_barrier (); return u.format3.cost ();
++    case 4: hb_barrier (); return u.format4.cost ();
++#endif
++    default:return 0u;
++    }
++  }
++
+   /* Might return false if array looks unsorted.
+    * Used for faster rejection of corrupt data. */
+   template 
+diff --git a/src/java.desktop/share/native/libharfbuzz/OT/Layout/Common/CoverageFormat1.hh b/src/java.desktop/share/native/libharfbuzz/OT/Layout/Common/CoverageFormat1.hh
+index 995f1ebdb..4a925763b 100644
+--- a/src/java.desktop/share/native/libharfbuzz/OT/Layout/Common/CoverageFormat1.hh
++++ b/src/java.desktop/share/native/libharfbuzz/OT/Layout/Common/CoverageFormat1.hh
+@@ -103,6 +103,8 @@ struct CoverageFormat1_3
+         intersect_glyphs << glyphArray[i];
+   }
+ 
++  unsigned cost () const { return hb_bit_storage ((unsigned) glyphArray.len); /* bsearch cost */ }
++
+   template 
+   bool collect_coverage (set_t *glyphs) const
+   { return glyphs->add_sorted_array (glyphArray.as_array ()); }
+diff --git a/src/java.desktop/share/native/libharfbuzz/OT/Layout/Common/CoverageFormat2.hh b/src/java.desktop/share/native/libharfbuzz/OT/Layout/Common/CoverageFormat2.hh
+index d47c7eea9..247b7274b 100644
+--- a/src/java.desktop/share/native/libharfbuzz/OT/Layout/Common/CoverageFormat2.hh
++++ b/src/java.desktop/share/native/libharfbuzz/OT/Layout/Common/CoverageFormat2.hh
+@@ -157,6 +157,8 @@ struct CoverageFormat2_4
+     }
+   }
+ 
++  unsigned cost () const { return hb_bit_storage ((unsigned) rangeRecord.len); /* bsearch cost */ }
++
+   template 
+   bool collect_coverage (set_t *glyphs) const
+   {
+diff --git a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GDEF/GDEF.hh b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GDEF/GDEF.hh
+index 98543f56c..542480d2d 100644
+--- a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GDEF/GDEF.hh
++++ b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GDEF/GDEF.hh
+@@ -189,7 +189,7 @@ struct CaretValueFormat3
+   friend struct CaretValue;
+ 
+   hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction,
+-                                 const VariationStore &var_store) const
++                                 const ItemVariationStore &var_store) const
+   {
+     return HB_DIRECTION_IS_HORIZONTAL (direction) ?
+            font->em_scale_x (coordinate) + (this+deviceTable).get_x_delta (font, var_store) :
+@@ -251,7 +251,7 @@ struct CaretValue
+   hb_position_t get_caret_value (hb_font_t *font,
+                                  hb_direction_t direction,
+                                  hb_codepoint_t glyph_id,
+-                                 const VariationStore &var_store) const
++                                 const ItemVariationStore &var_store) const
+   {
+     switch (u.format) {
+     case 1: return u.format1.get_caret_value (font, direction);
+@@ -291,6 +291,7 @@ struct CaretValue
+   {
+     TRACE_SANITIZE (this);
+     if (!u.format.sanitize (c)) return_trace (false);
++    hb_barrier ();
+     switch (u.format) {
+     case 1: return_trace (u.format1.sanitize (c));
+     case 2: return_trace (u.format2.sanitize (c));
+@@ -315,7 +316,7 @@ struct LigGlyph
+   unsigned get_lig_carets (hb_font_t            *font,
+                            hb_direction_t        direction,
+                            hb_codepoint_t        glyph_id,
+-                           const VariationStore &var_store,
++                           const ItemVariationStore &var_store,
+                            unsigned              start_offset,
+                            unsigned             *caret_count /* IN/OUT */,
+                            hb_position_t        *caret_array /* OUT */) const
+@@ -371,7 +372,7 @@ struct LigCaretList
+   unsigned int get_lig_carets (hb_font_t *font,
+                                hb_direction_t direction,
+                                hb_codepoint_t glyph_id,
+-                               const VariationStore &var_store,
++                               const ItemVariationStore &var_store,
+                                unsigned int start_offset,
+                                unsigned int *caret_count /* IN/OUT */,
+                                hb_position_t *caret_array /* OUT */) const
+@@ -441,6 +442,20 @@ struct MarkGlyphSetsFormat1
+   bool covers (unsigned int set_index, hb_codepoint_t glyph_id) const
+   { return (this+coverage[set_index]).get_coverage (glyph_id) != NOT_COVERED; }
+ 
++  void collect_used_mark_sets (const hb_set_t& glyph_set,
++                               hb_set_t& used_mark_sets /* OUT */) const
++  {
++    unsigned i = 0;
++    for (const auto &offset : coverage)
++     {
++       const auto &cov = this+offset;
++       if (cov.intersects (&glyph_set))
++         used_mark_sets.add (i);
++
++       i++;
++     }
++  }
++
+   template 
+   void collect_coverage (hb_vector_t &sets) const
+   {
+@@ -461,6 +476,7 @@ struct MarkGlyphSetsFormat1
+     bool ret = true;
+     for (const Offset32To& offset : coverage.iter ())
+     {
++      auto snap = c->serializer->snapshot ();
+       auto *o = out->coverage.serialize_append (c->serializer);
+       if (unlikely (!o))
+       {
+@@ -468,11 +484,17 @@ struct MarkGlyphSetsFormat1
+         break;
+       }
+ 
+-      //not using o->serialize_subset (c, offset, this, out) here because
+-      //OTS doesn't allow null offset.
+-      //See issue: https://github.com/khaledhosny/ots/issues/172
++      //skip empty coverage
+       c->serializer->push ();
+-      c->dispatch (this+offset);
++      bool res = false;
++      if (offset) res = c->dispatch (this+offset);
++      if (!res)
++      {
++        c->serializer->pop_discard ();
++        c->serializer->revert (snap);
++        (out->coverage.len)--;
++        continue;
++      }
+       c->serializer->add_link (*o, c->serializer->pop_pack ());
+     }
+ 
+@@ -513,6 +535,15 @@ struct MarkGlyphSets
+     }
+   }
+ 
++  void collect_used_mark_sets (const hb_set_t& glyph_set,
++                               hb_set_t& used_mark_sets /* OUT */) const
++  {
++    switch (u.format) {
++    case 1: u.format1.collect_used_mark_sets (glyph_set, used_mark_sets); return;
++    default:return;
++    }
++  }
++
+   bool subset (hb_subset_context_t *c) const
+   {
+     TRACE_SUBSET (this);
+@@ -526,6 +557,7 @@ struct MarkGlyphSets
+   {
+     TRACE_SANITIZE (this);
+     if (!u.format.sanitize (c)) return_trace (false);
++    hb_barrier ();
+     switch (u.format) {
+     case 1: return_trace (u.format1.sanitize (c));
+     default:return_trace (true);
+@@ -577,7 +609,7 @@ struct GDEFVersion1_2
+                                          * definitions--from beginning of GDEF
+                                          * header (may be NULL).  Introduced
+                                          * in version 0x00010002. */
+-  Offset32To
++  Offset32To
+                 varStore;               /* Offset to the table of Item Variation
+                                          * Store--from beginning of GDEF
+                                          * header (may be NULL).  Introduced
+@@ -600,8 +632,9 @@ struct GDEFVersion1_2
+                   attachList.sanitize (c, this) &&
+                   ligCaretList.sanitize (c, this) &&
+                   markAttachClassDef.sanitize (c, this) &&
+-                  (version.to_int () < 0x00010002u || markGlyphSetsDef.sanitize (c, this)) &&
+-                  (version.to_int () < 0x00010003u || varStore.sanitize (c, this)));
++                  hb_barrier () &&
++                  ((version.to_int () < 0x00010002u && hb_barrier ()) || markGlyphSetsDef.sanitize (c, this)) &&
++                  ((version.to_int () < 0x00010003u && hb_barrier ()) || varStore.sanitize (c, this)));
+   }
+ 
+   static void remap_varidx_after_instantiation (const hb_map_t& varidx_map,
+@@ -627,23 +660,23 @@ struct GDEFVersion1_2
+   bool subset (hb_subset_context_t *c) const
+   {
+     TRACE_SUBSET (this);
+-    auto *out = c->serializer->embed (*this);
+-    if (unlikely (!out)) return_trace (false);
+-
+-    bool subset_glyphclassdef = out->glyphClassDef.serialize_subset (c, glyphClassDef, this, nullptr, false, true);
+-    bool subset_attachlist = out->attachList.serialize_subset (c, attachList, this);
+-    bool subset_ligcaretlist = out->ligCaretList.serialize_subset (c, ligCaretList, this);
+-    bool subset_markattachclassdef = out->markAttachClassDef.serialize_subset (c, markAttachClassDef, this, nullptr, false, true);
++    auto *out = c->serializer->start_embed (*this);
++    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+ 
+-    bool subset_markglyphsetsdef = false;
+-    if (version.to_int () >= 0x00010002u)
+-    {
+-      subset_markglyphsetsdef = out->markGlyphSetsDef.serialize_subset (c, markGlyphSetsDef, this);
+-    }
++    // Push var store first (if it's needed) so that it's last in the
++    // serialization order. Some font consumers assume that varstore runs to
++    // the end of the GDEF table.
++    // See: https://github.com/harfbuzz/harfbuzz/issues/4636
++    auto snapshot_version0 = c->serializer->snapshot ();
++    if (unlikely (version.to_int () >= 0x00010002u && hb_barrier () && !c->serializer->embed (markGlyphSetsDef)))
++      return_trace (false);
+ 
+     bool subset_varstore = false;
+-    if (version.to_int () >= 0x00010003u)
++    unsigned varstore_index = (unsigned) -1;
++    auto snapshot_version2 = c->serializer->snapshot ();
++    if (version.to_int () >= 0x00010003u && hb_barrier ())
+     {
++      if (unlikely (!c->serializer->embed (varStore))) return_trace (false);
+       if (c->plan->all_axes_pinned)
+         out->varStore = 0;
+       else if (c->plan->normalized_coords)
+@@ -652,27 +685,56 @@ struct GDEFVersion1_2
+         {
+           item_variations_t item_vars;
+           if (item_vars.instantiate (this+varStore, c->plan, true, true,
+-                                     c->plan->gdef_varstore_inner_maps.as_array ()))
++                                     c->plan->gdef_varstore_inner_maps.as_array ())) {
+             subset_varstore = out->varStore.serialize_serialize (c->serializer,
+                                                                  item_vars.has_long_word (),
+                                                                  c->plan->axis_tags,
+                                                                  item_vars.get_region_list (),
+                                                                  item_vars.get_vardata_encodings ());
++            varstore_index = c->serializer->last_added_child_index();
++          }
+           remap_varidx_after_instantiation (item_vars.get_varidx_map (),
+                                             c->plan->layout_variation_idx_delta_map);
+         }
+       }
+       else
++      {
+         subset_varstore = out->varStore.serialize_subset (c, varStore, this, c->plan->gdef_varstore_inner_maps.as_array ());
++        varstore_index = c->serializer->last_added_child_index();
++      }
++    }
++
++    out->version.major = version.major;
++    out->version.minor = version.minor;
++
++    if (!subset_varstore && version.to_int () >= 0x00010002u) {
++      c->serializer->revert (snapshot_version2);
++    }
++
++    bool subset_markglyphsetsdef = false;
++    if (version.to_int () >= 0x00010002u && hb_barrier ())
++    {
++      subset_markglyphsetsdef = out->markGlyphSetsDef.serialize_subset (c, markGlyphSetsDef, this);
+     }
+ 
+     if (subset_varstore)
+     {
+       out->version.minor = 3;
++      c->plan->has_gdef_varstore = true;
+     } else if (subset_markglyphsetsdef) {
+       out->version.minor = 2;
+     } else  {
+       out->version.minor = 0;
++      c->serializer->revert (snapshot_version0);
++    }
++
++    bool subset_glyphclassdef = out->glyphClassDef.serialize_subset (c, glyphClassDef, this, nullptr, false, true);
++    bool subset_attachlist = out->attachList.serialize_subset (c, attachList, this);
++    bool subset_markattachclassdef = out->markAttachClassDef.serialize_subset (c, markAttachClassDef, this, nullptr, false, true);
++    bool subset_ligcaretlist = out->ligCaretList.serialize_subset (c, ligCaretList, this);
++
++    if (subset_varstore && varstore_index != (unsigned) -1) {
++      c->serializer->repack_last(varstore_index);
+     }
+ 
+     return_trace (subset_glyphclassdef || subset_attachlist ||
+@@ -709,6 +771,7 @@ struct GDEF
+   {
+     TRACE_SANITIZE (this);
+     if (unlikely (!u.version.sanitize (c))) return_trace (false);
++    hb_barrier ();
+     switch (u.version.major) {
+     case 1: return_trace (u.version1.sanitize (c));
+ #ifndef HB_NO_BEYOND_64K
+@@ -812,7 +875,7 @@ struct GDEF
+   bool has_mark_glyph_sets () const
+   {
+     switch (u.version.major) {
+-    case 1: return u.version.to_int () >= 0x00010002u && u.version1.markGlyphSetsDef != 0;
++    case 1: return u.version.to_int () >= 0x00010002u && hb_barrier () && u.version1.markGlyphSetsDef != 0;
+ #ifndef HB_NO_BEYOND_64K
+     case 2: return u.version2.markGlyphSetsDef != 0;
+ #endif
+@@ -822,7 +885,7 @@ struct GDEF
+   const MarkGlyphSets &get_mark_glyph_sets () const
+   {
+     switch (u.version.major) {
+-    case 1: return u.version.to_int () >= 0x00010002u ? this+u.version1.markGlyphSetsDef : Null(MarkGlyphSets);
++    case 1: return u.version.to_int () >= 0x00010002u && hb_barrier () ? this+u.version1.markGlyphSetsDef : Null(MarkGlyphSets);
+ #ifndef HB_NO_BEYOND_64K
+     case 2: return this+u.version2.markGlyphSetsDef;
+ #endif
+@@ -832,21 +895,21 @@ struct GDEF
+   bool has_var_store () const
+   {
+     switch (u.version.major) {
+-    case 1: return u.version.to_int () >= 0x00010003u && u.version1.varStore != 0;
++    case 1: return u.version.to_int () >= 0x00010003u && hb_barrier () && u.version1.varStore != 0;
+ #ifndef HB_NO_BEYOND_64K
+     case 2: return u.version2.varStore != 0;
+ #endif
+     default: return false;
+     }
+   }
+-  const VariationStore &get_var_store () const
++  const ItemVariationStore &get_var_store () const
+   {
+     switch (u.version.major) {
+-    case 1: return u.version.to_int () >= 0x00010003u ? this+u.version1.varStore : Null(VariationStore);
++    case 1: return u.version.to_int () >= 0x00010003u && hb_barrier () ? this+u.version1.varStore : Null(ItemVariationStore);
+ #ifndef HB_NO_BEYOND_64K
+     case 2: return this+u.version2.varStore;
+ #endif
+-    default: return Null(VariationStore);
++    default: return Null(ItemVariationStore);
+     }
+   }
+ 
+@@ -959,47 +1022,6 @@ struct GDEF
+   void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
+   { get_lig_caret_list ().collect_variation_indices (c); }
+ 
+-  void remap_layout_variation_indices (const hb_set_t *layout_variation_indices,
+-                                       const hb_vector_t& normalized_coords,
+-                                       bool calculate_delta, /* not pinned at default */
+-                                       bool no_variations, /* all axes pinned */
+-                                       hb_hashmap_t> *layout_variation_idx_delta_map /* OUT */) const
+-  {
+-    if (!has_var_store ()) return;
+-    const VariationStore &var_store = get_var_store ();
+-    float *store_cache = var_store.create_cache ();
+-
+-    unsigned new_major = 0, new_minor = 0;
+-    unsigned last_major = (layout_variation_indices->get_min ()) >> 16;
+-    for (unsigned idx : layout_variation_indices->iter ())
+-    {
+-      int delta = 0;
+-      if (calculate_delta)
+-        delta = roundf (var_store.get_delta (idx, normalized_coords.arrayZ,
+-                                             normalized_coords.length, store_cache));
+-
+-      if (no_variations)
+-      {
+-        layout_variation_idx_delta_map->set (idx, hb_pair_t (HB_OT_LAYOUT_NO_VARIATIONS_INDEX, delta));
+-        continue;
+-      }
+-
+-      uint16_t major = idx >> 16;
+-      if (major >= var_store.get_sub_table_count ()) break;
+-      if (major != last_major)
+-      {
+-        new_minor = 0;
+-        ++new_major;
+-      }
+-
+-      unsigned new_idx = (new_major << 16) + new_minor;
+-      layout_variation_idx_delta_map->set (idx, hb_pair_t (new_idx, delta));
+-      ++new_minor;
+-      last_major = major;
+-    }
+-    var_store.destroy_cache (store_cache);
+-  }
+-
+   protected:
+   union {
+   FixedVersion<>                version;        /* Version identifier */
+diff --git a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/Anchor.hh b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/Anchor.hh
+index 49e76e775..7802e397f 100644
+--- a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/Anchor.hh
++++ b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/Anchor.hh
+@@ -25,6 +25,7 @@ struct Anchor
+   {
+     TRACE_SANITIZE (this);
+     if (!u.format.sanitize (c)) return_trace (false);
++    hb_barrier ();
+     switch (u.format) {
+     case 1: return_trace (u.format1.sanitize (c));
+     case 2: return_trace (u.format2.sanitize (c));
+diff --git a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/AnchorFormat3.hh b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/AnchorFormat3.hh
+index 23821a49c..61bd90310 100644
+--- a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/AnchorFormat3.hh
++++ b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/AnchorFormat3.hh
+@@ -38,9 +38,15 @@ struct AnchorFormat3
+     *y = font->em_fscale_y (yCoordinate);
+ 
+     if ((font->x_ppem || font->num_coords) && xDeviceTable.sanitize (&c->sanitizer, this))
++    {
++      hb_barrier ();
+       *x += (this+xDeviceTable).get_x_delta (font, c->var_store, c->var_store_cache);
++    }
+     if ((font->y_ppem || font->num_coords) && yDeviceTable.sanitize (&c->sanitizer, this))
++    {
++      hb_barrier ();
+       *y += (this+yDeviceTable).get_y_delta (font, c->var_store, c->var_store_cache);
++    }
+   }
+ 
+   bool subset (hb_subset_context_t *c) const
+diff --git a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/AnchorMatrix.hh b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/AnchorMatrix.hh
+index b61f1413e..9da9fff50 100644
+--- a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/AnchorMatrix.hh
++++ b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/AnchorMatrix.hh
+@@ -8,7 +8,7 @@ namespace GPOS_impl {
+ struct AnchorMatrix
+ {
+   HBUINT16      rows;                   /* Number of rows */
+-  UnsizedArrayOf>
++  UnsizedArrayOf>
+                 matrixZ;                /* Matrix of offsets to Anchor tables--
+                                          * from beginning of AnchorMatrix table */
+   public:
+@@ -18,6 +18,7 @@ struct AnchorMatrix
+   {
+     TRACE_SANITIZE (this);
+     if (!c->check_struct (this)) return_trace (false);
++    hb_barrier ();
+     if (unlikely (hb_unsigned_mul_overflows (rows, cols))) return_trace (false);
+     unsigned int count = rows * cols;
+     if (!c->check_array (matrixZ.arrayZ, count)) return_trace (false);
+@@ -25,6 +26,7 @@ struct AnchorMatrix
+     if (c->lazy_some_gpos)
+       return_trace (true);
+ 
++    hb_barrier ();
+     for (unsigned int i = 0; i < count; i++)
+       if (!matrixZ[i].sanitize (c, this)) return_trace (false);
+     return_trace (true);
+@@ -38,6 +40,7 @@ struct AnchorMatrix
+     if (unlikely (row >= rows || col >= cols)) return Null (Anchor);
+     auto &offset = matrixZ[row * cols + col];
+     if (unlikely (!offset.sanitize (&c->sanitizer, this))) return Null (Anchor);
++    hb_barrier ();
+     *found = !offset.is_null ();
+     return this+offset;
+   }
+@@ -65,15 +68,14 @@ struct AnchorMatrix
+     if (unlikely (!c->serializer->extend_min (out)))  return_trace (false);
+ 
+     out->rows = num_rows;
+-    bool ret = false;
+     for (const unsigned i : index_iter)
+     {
+       auto *offset = c->serializer->embed (matrixZ[i]);
+       if (!offset) return_trace (false);
+-      ret |= offset->serialize_subset (c, matrixZ[i], this);
++      offset->serialize_subset (c, matrixZ[i], this);
+     }
+ 
+-    return_trace (ret);
++    return_trace (true);
+   }
+ };
+ 
+diff --git a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/Common.hh b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/Common.hh
+index 408197454..696d25d75 100644
+--- a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/Common.hh
++++ b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/Common.hh
+@@ -23,7 +23,7 @@ static void SinglePos_serialize (hb_serialize_context_t *c,
+                                  const SrcLookup *src,
+                                  Iterator it,
+                                  const hb_hashmap_t> *layout_variation_idx_delta_map,
+-                                 bool all_axes_pinned);
++                                 unsigned new_format);
+ 
+ 
+ }
+diff --git a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/CursivePosFormat1.hh b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/CursivePosFormat1.hh
+index 3a2957af1..361aaed65 100644
+--- a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/CursivePosFormat1.hh
++++ b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/CursivePosFormat1.hh
+@@ -11,21 +11,21 @@ struct EntryExitRecord
+ {
+   friend struct CursivePosFormat1;
+ 
+-  bool sanitize (hb_sanitize_context_t *c, const void *base) const
++  bool sanitize (hb_sanitize_context_t *c, const struct CursivePosFormat1 *base) const
+   {
+     TRACE_SANITIZE (this);
+     return_trace (entryAnchor.sanitize (c, base) && exitAnchor.sanitize (c, base));
+   }
+ 
+   void collect_variation_indices (hb_collect_variation_indices_context_t *c,
+-                                  const void *src_base) const
++                                  const struct CursivePosFormat1 *src_base) const
+   {
+     (src_base+entryAnchor).collect_variation_indices (c);
+     (src_base+exitAnchor).collect_variation_indices (c);
+   }
+ 
+   bool subset (hb_subset_context_t *c,
+-               const void *src_base) const
++               const struct CursivePosFormat1 *src_base) const
+   {
+     TRACE_SERIALIZE (this);
+     auto *out = c->serializer->embed (this);
+@@ -38,11 +38,11 @@ struct EntryExitRecord
+   }
+ 
+   protected:
+-  Offset16To
++  Offset16To
+                 entryAnchor;            /* Offset to EntryAnchor table--from
+                                          * beginning of CursivePos
+                                          * subtable--may be NULL */
+-  Offset16To
++  Offset16To
+                 exitAnchor;             /* Offset to ExitAnchor table--from
+                                          * beginning of CursivePos
+                                          * subtable--may be NULL */
+@@ -128,6 +128,7 @@ struct CursivePosFormat1
+     const EntryExitRecord &this_record = entryExitRecord[(this+coverage).get_coverage  (buffer->cur().codepoint)];
+     if (!this_record.entryAnchor ||
+         unlikely (!this_record.entryAnchor.sanitize (&c->sanitizer, this))) return_trace (false);
++    hb_barrier ();
+ 
+     hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
+     skippy_iter.reset_fast (buffer->idx);
+@@ -145,6 +146,7 @@ struct CursivePosFormat1
+       buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
+       return_trace (false);
+     }
++    hb_barrier ();
+ 
+     unsigned int i = skippy_iter.idx;
+     unsigned int j = buffer->idx;
+@@ -262,7 +264,7 @@ struct CursivePosFormat1
+             hb_requires (hb_is_iterator (Iterator))>
+   void serialize (hb_subset_context_t *c,
+                   Iterator it,
+-                  const void *src_base)
++                  const struct CursivePosFormat1 *src_base)
+   {
+     if (unlikely (!c->serializer->extend_min ((*this)))) return;
+     this->format = 1;
+diff --git a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/MarkMarkPosFormat1.hh b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/MarkMarkPosFormat1.hh
+index ea196581a..6519e79b4 100644
+--- a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/MarkMarkPosFormat1.hh
++++ b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/MarkMarkPosFormat1.hh
+@@ -42,6 +42,7 @@ struct MarkMarkPosFormat1_2
+                   mark1Coverage.sanitize (c, this) &&
+                   mark2Coverage.sanitize (c, this) &&
+                   mark1Array.sanitize (c, this) &&
++                  hb_barrier () &&
+                   mark2Array.sanitize (c, this, (unsigned int) classCount));
+   }
+ 
+diff --git a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/PairPosFormat1.hh b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/PairPosFormat1.hh
+index 478c72df7..597ff4c08 100644
+--- a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/PairPosFormat1.hh
++++ b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/PairPosFormat1.hh
+@@ -36,6 +36,7 @@ struct PairPosFormat1_3
+     TRACE_SANITIZE (this);
+ 
+     if (!c->check_struct (this)) return_trace (false);
++    hb_barrier ();
+ 
+     unsigned int len1 = valueFormat[0].get_len ();
+     unsigned int len2 = valueFormat[1].get_len ();
+@@ -102,12 +103,50 @@ struct PairPosFormat1_3
+ 
+   const Coverage &get_coverage () const { return this+coverage; }
+ 
+-  bool apply (hb_ot_apply_context_t *c) const
++  unsigned cache_cost () const
++  {
++    return (this+coverage).cost ();
++  }
++  static void * cache_func (void *p, hb_ot_lookup_cache_op_t op)
++  {
++    switch (op)
++    {
++      case hb_ot_lookup_cache_op_t::CREATE:
++      {
++        hb_ot_lookup_cache_t *cache = (hb_ot_lookup_cache_t *) hb_malloc (sizeof (hb_ot_lookup_cache_t));
++        if (likely (cache))
++          cache->clear ();
++        return cache;
++      }
++      case hb_ot_lookup_cache_op_t::ENTER:
++        return (void *) true;
++      case hb_ot_lookup_cache_op_t::LEAVE:
++        return nullptr;
++      case hb_ot_lookup_cache_op_t::DESTROY:
++      {
++        hb_ot_lookup_cache_t *cache = (hb_ot_lookup_cache_t *) p;
++        hb_free (cache);
++        return nullptr;
++      }
++    }
++    return nullptr;
++  }
++
++  bool apply_cached (hb_ot_apply_context_t *c) const { return _apply (c, true); }
++  bool apply (hb_ot_apply_context_t *c) const { return _apply (c, false); }
++  bool _apply (hb_ot_apply_context_t *c, bool cached) const
+   {
+     TRACE_APPLY (this);
++
+     hb_buffer_t *buffer = c->buffer;
++
++#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
++    hb_ot_lookup_cache_t *cache = cached ? (hb_ot_lookup_cache_t *) c->lookup_accel->cache : nullptr;
++    unsigned int index = (this+coverage).get_coverage  (buffer->cur().codepoint, cache);
++#else
+     unsigned int index = (this+coverage).get_coverage  (buffer->cur().codepoint);
+-    if (likely (index == NOT_COVERED)) return_trace (false);
++#endif
++    if (index == NOT_COVERED) return_trace (false);
+ 
+     hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
+     skippy_iter.reset_fast (buffer->idx);
+@@ -131,21 +170,34 @@ struct PairPosFormat1_3
+     auto *out = c->serializer->start_embed (*this);
+     if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+     out->format = format;
+-    out->valueFormat[0] = valueFormat[0];
+-    out->valueFormat[1] = valueFormat[1];
+-    if (c->plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
++
++    hb_pair_t newFormats = hb_pair (valueFormat[0], valueFormat[1]);
++
++    if (c->plan->normalized_coords)
+     {
+-      hb_pair_t newFormats = compute_effective_value_formats (glyphset);
+-      out->valueFormat[0] = newFormats.first;
+-      out->valueFormat[1] = newFormats.second;
++      /* all device flags will be dropped when full instancing, no need to strip
++       * hints, also do not strip emtpy cause we don't compute the new default
++       * value during stripping */
++      newFormats = compute_effective_value_formats (glyphset, false, false, &c->plan->layout_variation_idx_delta_map);
+     }
+-
+-    if (c->plan->all_axes_pinned)
++    /* do not strip hints for VF */
++    else if (c->plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
+     {
+-      out->valueFormat[0] = out->valueFormat[0].drop_device_table_flags ();
+-      out->valueFormat[1] = out->valueFormat[1].drop_device_table_flags ();
++      hb_blob_t* blob = hb_face_reference_table (c->plan->source, HB_TAG ('f','v','a','r'));
++      bool has_fvar = (blob != hb_blob_get_empty ());
++      hb_blob_destroy (blob);
++
++      bool strip = !has_fvar;
++      /* special case: strip hints when a VF has no GDEF varstore after
++       * subsetting*/
++      if (has_fvar && !c->plan->has_gdef_varstore)
++        strip = true;
++      newFormats = compute_effective_value_formats (glyphset, strip, true);
+     }
+ 
++    out->valueFormat[0] = newFormats.first;
++    out->valueFormat[1] = newFormats.second;
++
+     hb_sorted_vector_t new_coverage;
+ 
+     + hb_zip (this+coverage, pairSet)
+@@ -175,7 +227,9 @@ struct PairPosFormat1_3
+   }
+ 
+ 
+-  hb_pair_t compute_effective_value_formats (const hb_set_t& glyphset) const
++  hb_pair_t compute_effective_value_formats (const hb_set_t& glyphset,
++                                                                 bool strip_hints, bool strip_empty,
++                                                                 const hb_hashmap_t> *varidx_delta_map = nullptr) const
+   {
+     unsigned record_size = PairSet::get_size (valueFormat);
+ 
+@@ -195,8 +249,8 @@ struct PairPosFormat1_3
+       {
+         if (record->intersects (glyphset))
+         {
+-          format1 = format1 | valueFormat[0].get_effective_format (record->get_values_1 ());
+-          format2 = format2 | valueFormat[1].get_effective_format (record->get_values_2 (valueFormat[0]));
++          format1 = format1 | valueFormat[0].get_effective_format (record->get_values_1 (), strip_hints, strip_empty, &set, varidx_delta_map);
++          format2 = format2 | valueFormat[1].get_effective_format (record->get_values_2 (valueFormat[0]), strip_hints, strip_empty, &set, varidx_delta_map);
+         }
+         record = &StructAtOffset (record, record_size);
+       }
+diff --git a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/PairPosFormat2.hh b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/PairPosFormat2.hh
+index ce6eec4f2..d85b1ac2c 100644
+--- a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/PairPosFormat2.hh
++++ b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/PairPosFormat2.hh
+@@ -8,7 +8,7 @@ namespace Layout {
+ namespace GPOS_impl {
+ 
+ template 
+-struct PairPosFormat2_4
++struct PairPosFormat2_4 : ValueBase
+ {
+   protected:
+   HBUINT16      format;                 /* Format identifier--format = 2 */
+@@ -123,12 +123,61 @@ struct PairPosFormat2_4
+ 
+   const Coverage &get_coverage () const { return this+coverage; }
+ 
+-  bool apply (hb_ot_apply_context_t *c) const
++  struct pair_pos_cache_t
++  {
++    hb_ot_lookup_cache_t coverage;
++    hb_ot_lookup_cache_t first;
++    hb_ot_lookup_cache_t second;
++  };
++
++  unsigned cache_cost () const
++  {
++    return (this+coverage).cost () + (this+classDef1).cost () + (this+classDef2).cost ();
++  }
++  static void * cache_func (void *p, hb_ot_lookup_cache_op_t op)
++  {
++    switch (op)
++    {
++      case hb_ot_lookup_cache_op_t::CREATE:
++      {
++        pair_pos_cache_t *cache = (pair_pos_cache_t *) hb_malloc (sizeof (pair_pos_cache_t));
++        if (likely (cache))
++        {
++          cache->coverage.clear ();
++          cache->first.clear ();
++          cache->second.clear ();
++        }
++        return cache;
++      }
++      case hb_ot_lookup_cache_op_t::ENTER:
++        return (void *) true;
++      case hb_ot_lookup_cache_op_t::LEAVE:
++        return nullptr;
++      case hb_ot_lookup_cache_op_t::DESTROY:
++        {
++          pair_pos_cache_t *cache = (pair_pos_cache_t *) p;
++          hb_free (cache);
++          return nullptr;
++        }
++    }
++    return nullptr;
++  }
++
++  bool apply_cached (hb_ot_apply_context_t *c) const { return _apply (c, true); }
++  bool apply (hb_ot_apply_context_t *c) const { return _apply (c, false); }
++  bool _apply (hb_ot_apply_context_t *c, bool cached) const
+   {
+     TRACE_APPLY (this);
++
+     hb_buffer_t *buffer = c->buffer;
++
++#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
++    pair_pos_cache_t *cache = cached ? (pair_pos_cache_t *) c->lookup_accel->cache : nullptr;
++    unsigned int index = (this+coverage).get_coverage  (buffer->cur().codepoint, cache ? &cache->coverage : nullptr);
++#else
+     unsigned int index = (this+coverage).get_coverage  (buffer->cur().codepoint);
+-    if (likely (index == NOT_COVERED)) return_trace (false);
++#endif
++    if (index == NOT_COVERED) return_trace (false);
+ 
+     hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
+     skippy_iter.reset_fast (buffer->idx);
+@@ -139,14 +188,13 @@ struct PairPosFormat2_4
+       return_trace (false);
+     }
+ 
+-    unsigned int klass2 = (this+classDef2).get_class (buffer->info[skippy_iter.idx].codepoint);
+-    if (!klass2)
+-    {
+-      buffer->unsafe_to_concat (buffer->idx, skippy_iter.idx + 1);
+-      return_trace (false);
+-    }
+-
++#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
++    unsigned int klass1 = (this+classDef1).get_class (buffer->cur().codepoint, cache ? &cache->first : nullptr);
++    unsigned int klass2 = (this+classDef2).get_class (buffer->info[skippy_iter.idx].codepoint, cache ? &cache->second : nullptr);
++#else
+     unsigned int klass1 = (this+classDef1).get_class (buffer->cur().codepoint);
++    unsigned int klass2 = (this+classDef2).get_class (buffer->info[skippy_iter.idx].codepoint);
++#endif
+     if (unlikely (klass1 >= class1Count || klass2 >= class2Count))
+     {
+       buffer->unsafe_to_concat (buffer->idx, skippy_iter.idx + 1);
+@@ -287,18 +335,31 @@ struct PairPosFormat2_4
+     unsigned len2 = valueFormat2.get_len ();
+ 
+     hb_pair_t newFormats = hb_pair (valueFormat1, valueFormat2);
+-    if (c->plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
+-      newFormats = compute_effective_value_formats (klass1_map, klass2_map);
+-
+-    out->valueFormat1 = newFormats.first;
+-    out->valueFormat2 = newFormats.second;
+ 
+-    if (c->plan->all_axes_pinned)
++    if (c->plan->normalized_coords)
+     {
+-      out->valueFormat1 = out->valueFormat1.drop_device_table_flags ();
+-      out->valueFormat2 = out->valueFormat2.drop_device_table_flags ();
++      /* in case of full instancing, all var device flags will be dropped so no
++       * need to strip hints here */
++      newFormats = compute_effective_value_formats (klass1_map, klass2_map, false, false, &c->plan->layout_variation_idx_delta_map);
++    }
++    /* do not strip hints for VF */
++    else if (c->plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
++    {
++      hb_blob_t* blob = hb_face_reference_table (c->plan->source, HB_TAG ('f','v','a','r'));
++      bool has_fvar = (blob != hb_blob_get_empty ());
++      hb_blob_destroy (blob);
++
++      bool strip = !has_fvar;
++      /* special case: strip hints when a VF has no GDEF varstore after
++       * subsetting*/
++      if (has_fvar && !c->plan->has_gdef_varstore)
++        strip = true;
++      newFormats = compute_effective_value_formats (klass1_map, klass2_map, strip, true);
+     }
+ 
++    out->valueFormat1 = newFormats.first;
++    out->valueFormat2 = newFormats.second;
++
+     unsigned total_len = len1 + len2;
+     hb_vector_t class2_idxs (+ hb_range ((unsigned) class2Count) | hb_filter (klass2_map));
+     for (unsigned class1_idx : + hb_range ((unsigned) class1Count) | hb_filter (klass1_map))
+@@ -311,22 +372,15 @@ struct PairPosFormat2_4
+       }
+     }
+ 
+-    const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+-    const hb_map_t &glyph_map = *c->plan->glyph_map;
+-
+-    auto it =
+-    + hb_iter (this+coverage)
+-    | hb_filter (glyphset)
+-    | hb_map_retains_sorting (glyph_map)
+-    ;
+-
+-    out->coverage.serialize_serialize (c->serializer, it);
+-    return_trace (out->class1Count && out->class2Count && bool (it));
++    bool ret = out->coverage.serialize_subset(c, coverage, this);
++    return_trace (out->class1Count && out->class2Count && ret);
+   }
+ 
+ 
+   hb_pair_t compute_effective_value_formats (const hb_map_t& klass1_map,
+-                                                                 const hb_map_t& klass2_map) const
++                                                                 const hb_map_t& klass2_map,
++                                                                 bool strip_hints, bool strip_empty,
++                                                                 const hb_hashmap_t> *varidx_delta_map = nullptr) const
+   {
+     unsigned len1 = valueFormat1.get_len ();
+     unsigned len2 = valueFormat2.get_len ();
+@@ -340,8 +394,8 @@ struct PairPosFormat2_4
+       for (unsigned class2_idx : + hb_range ((unsigned) class2Count) | hb_filter (klass2_map))
+       {
+         unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * record_size;
+-        format1 = format1 | valueFormat1.get_effective_format (&values[idx]);
+-        format2 = format2 | valueFormat2.get_effective_format (&values[idx + len1]);
++        format1 = format1 | valueFormat1.get_effective_format (&values[idx], strip_hints, strip_empty, this, varidx_delta_map);
++        format2 = format2 | valueFormat2.get_effective_format (&values[idx + len1], strip_hints, strip_empty, this, varidx_delta_map);
+       }
+ 
+       if (format1 == valueFormat1 && format2 == valueFormat2)
+diff --git a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/PairSet.hh b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/PairSet.hh
+index 7ccec1df8..e610fcd75 100644
+--- a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/PairSet.hh
++++ b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/PairSet.hh
+@@ -9,7 +9,7 @@ namespace GPOS_impl {
+ 
+ 
+ template 
+-struct PairSet
++struct PairSet : ValueBase
+ {
+   template 
+   friend struct PairPosFormat1_3;
+@@ -45,10 +45,12 @@ struct PairSet
+   bool sanitize (hb_sanitize_context_t *c, const sanitize_closure_t *closure) const
+   {
+     TRACE_SANITIZE (this);
+-    if (!(c->check_struct (this)
+-       && c->check_range (&firstPairValueRecord,
++    if (!(c->check_struct (this) &&
++          hb_barrier () &&
++          c->check_range (&firstPairValueRecord,
+                           len,
+                           closure->stride))) return_trace (false);
++    hb_barrier ();
+ 
+     unsigned int count = len;
+     const PairValueRecord *record = &firstPairValueRecord;
+diff --git a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/PairValueRecord.hh b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/PairValueRecord.hh
+index b32abe46d..fe9595f12 100644
+--- a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/PairValueRecord.hh
++++ b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/PairValueRecord.hh
+@@ -29,7 +29,7 @@ struct PairValueRecord
+ 
+   struct context_t
+   {
+-    const void          *base;
++    const ValueBase     *base;
+     const ValueFormat   *valueFormats;
+     const ValueFormat   *newFormats;
+     unsigned            len1; /* valueFormats[0].get_len() */
+@@ -62,7 +62,7 @@ struct PairValueRecord
+ 
+   void collect_variation_indices (hb_collect_variation_indices_context_t *c,
+                                   const ValueFormat *valueFormats,
+-                                  const void *base) const
++                                  const ValueBase *base) const
+   {
+     unsigned record1_len = valueFormats[0].get_len ();
+     unsigned record2_len = valueFormats[1].get_len ();
+diff --git a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/SinglePos.hh b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/SinglePos.hh
+index 3af6c4996..a0243a218 100644
+--- a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/SinglePos.hh
++++ b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/SinglePos.hh
+@@ -39,14 +39,12 @@ struct SinglePos
+                   const SrcLookup* src,
+                   Iterator glyph_val_iter_pairs,
+                   const hb_hashmap_t> *layout_variation_idx_delta_map,
+-                  bool all_axes_pinned)
++                  unsigned newFormat)
+   {
+     if (unlikely (!c->extend_min (u.format))) return;
+     unsigned format = 2;
+-    ValueFormat new_format = src->get_value_format ();
+-
+-    if (all_axes_pinned)
+-      new_format = new_format.drop_device_table_flags ();
++    ValueFormat new_format;
++    new_format = newFormat;
+ 
+     if (glyph_val_iter_pairs)
+       format = get_format (glyph_val_iter_pairs);
+@@ -89,8 +87,8 @@ SinglePos_serialize (hb_serialize_context_t *c,
+                      const SrcLookup *src,
+                      Iterator it,
+                      const hb_hashmap_t> *layout_variation_idx_delta_map,
+-                     bool all_axes_pinned)
+-{ c->start_embed ()->serialize (c, src, it, layout_variation_idx_delta_map, all_axes_pinned); }
++                     unsigned new_format)
++{ c->start_embed ()->serialize (c, src, it, layout_variation_idx_delta_map, new_format); }
+ 
+ 
+ }
+diff --git a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/SinglePosFormat1.hh b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/SinglePosFormat1.hh
+index 8e21c5f8e..1a14be020 100644
+--- a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/SinglePosFormat1.hh
++++ b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/SinglePosFormat1.hh
+@@ -8,7 +8,7 @@ namespace OT {
+ namespace Layout {
+ namespace GPOS_impl {
+ 
+-struct SinglePosFormat1
++struct SinglePosFormat1 : ValueBase
+ {
+   protected:
+   HBUINT16      format;                 /* Format identifier--format = 1 */
+@@ -28,6 +28,7 @@ struct SinglePosFormat1
+     TRACE_SANITIZE (this);
+     return_trace (c->check_struct (this) &&
+                   coverage.sanitize (c, this) &&
++                  hb_barrier () &&
+                   /* The coverage  table may use a range to represent a set
+                    * of glyphs, which means a small number of bytes can
+                    * generate a large glyph set. Manually modify the
+@@ -66,7 +67,7 @@ struct SinglePosFormat1
+     TRACE_APPLY (this);
+     hb_buffer_t *buffer = c->buffer;
+     unsigned int index = (this+coverage).get_coverage  (buffer->cur().codepoint);
+-    if (likely (index == NOT_COVERED)) return_trace (false);
++    if (index == NOT_COVERED) return_trace (false);
+ 
+     if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+     {
+@@ -146,6 +147,30 @@ struct SinglePosFormat1
+     hb_set_t intersection;
+     (this+coverage).intersect_set (glyphset, intersection);
+ 
++    unsigned new_format = valueFormat;
++
++    if (c->plan->normalized_coords)
++    {
++      new_format = valueFormat.get_effective_format (values.arrayZ, false, false, this, &c->plan->layout_variation_idx_delta_map);
++    }
++    /* do not strip hints for VF */
++    else if (c->plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
++    {
++      hb_blob_t* blob = hb_face_reference_table (c->plan->source, HB_TAG ('f','v','a','r'));
++      bool has_fvar = (blob != hb_blob_get_empty ());
++      hb_blob_destroy (blob);
++
++      bool strip = !has_fvar;
++      /* special case: strip hints when a VF has no GDEF varstore after
++       * subsetting*/
++      if (has_fvar && !c->plan->has_gdef_varstore)
++        strip = true;
++      new_format = valueFormat.get_effective_format (values.arrayZ,
++                                                     strip, /* strip hints */
++                                                     true, /* strip empty */
++                                                     this, nullptr);
++    }
++
+     auto it =
+     + hb_iter (intersection)
+     | hb_map_retains_sorting (glyph_map)
+@@ -153,7 +178,7 @@ struct SinglePosFormat1
+     ;
+ 
+     bool ret = bool (it);
+-    SinglePos_serialize (c->serializer, this, it, &c->plan->layout_variation_idx_delta_map, c->plan->all_axes_pinned);
++    SinglePos_serialize (c->serializer, this, it, &c->plan->layout_variation_idx_delta_map, new_format);
+     return_trace (ret);
+   }
+ };
+diff --git a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/SinglePosFormat2.hh b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/SinglePosFormat2.hh
+index ddc4c18ec..455796b4b 100644
+--- a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/SinglePosFormat2.hh
++++ b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/SinglePosFormat2.hh
+@@ -7,7 +7,7 @@ namespace OT {
+ namespace Layout {
+ namespace GPOS_impl {
+ 
+-struct SinglePosFormat2
++struct SinglePosFormat2 : ValueBase
+ {
+   protected:
+   HBUINT16      format;                 /* Format identifier--format = 2 */
+@@ -66,7 +66,7 @@ struct SinglePosFormat2
+     TRACE_APPLY (this);
+     hb_buffer_t *buffer = c->buffer;
+     unsigned int index = (this+coverage).get_coverage  (buffer->cur().codepoint);
+-    if (likely (index == NOT_COVERED)) return_trace (false);
++    if (index == NOT_COVERED) return_trace (false);
+ 
+     if (unlikely (index >= valueCount)) return_trace (false);
+ 
+@@ -143,6 +143,37 @@ struct SinglePosFormat2
+     coverage.serialize_serialize (c, glyphs);
+   }
+ 
++  template
++  unsigned compute_effective_format (const hb_face_t *face,
++                                     Iterator it,
++                                     bool is_instancing, bool strip_hints,
++                                     bool has_gdef_varstore,
++                                     const hb_hashmap_t> *varidx_delta_map) const
++  {
++    hb_blob_t* blob = hb_face_reference_table (face, HB_TAG ('f','v','a','r'));
++    bool has_fvar = (blob != hb_blob_get_empty ());
++    hb_blob_destroy (blob);
++
++    unsigned new_format = 0;
++    if (is_instancing)
++    {
++      new_format = new_format | valueFormat.get_effective_format (+ it | hb_map (hb_second), false, false, this, varidx_delta_map);
++    }
++    /* do not strip hints for VF */
++    else if (strip_hints)
++    {
++      bool strip = !has_fvar;
++      if (has_fvar && !has_gdef_varstore)
++        strip = true;
++      new_format = new_format | valueFormat.get_effective_format (+ it | hb_map (hb_second), strip, true, this, nullptr);
++    }
++    else
++      new_format = valueFormat;
++
++    return new_format;
++  }
++
+   bool subset (hb_subset_context_t *c) const
+   {
+     TRACE_SUBSET (this);
+@@ -163,8 +194,13 @@ struct SinglePosFormat2
+                               })
+     ;
+ 
++    unsigned new_format = compute_effective_format (c->plan->source, it,
++                                                    bool (c->plan->normalized_coords),
++                                                    bool (c->plan->flags & HB_SUBSET_FLAGS_NO_HINTING),
++                                                    c->plan->has_gdef_varstore,
++                                                    &c->plan->layout_variation_idx_delta_map);
+     bool ret = bool (it);
+-    SinglePos_serialize (c->serializer, this, it, &c->plan->layout_variation_idx_delta_map, c->plan->all_axes_pinned);
++    SinglePos_serialize (c->serializer, this, it, &c->plan->layout_variation_idx_delta_map, new_format);
+     return_trace (ret);
+   }
+ };
+diff --git a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/ValueFormat.hh b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/ValueFormat.hh
+index 8618cddad..731d1ffca 100644
+--- a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/ValueFormat.hh
++++ b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GPOS/ValueFormat.hh
+@@ -9,6 +9,8 @@ namespace GPOS_impl {
+ 
+ typedef HBUINT16 Value;
+ 
++struct ValueBase {}; // Dummy base class tag for OffsetTo bases.
++
+ typedef UnsizedArrayOf ValueRecord;
+ 
+ struct ValueFormat : HBUINT16
+@@ -78,7 +80,7 @@ struct ValueFormat : HBUINT16
+   }
+ 
+   bool apply_value (hb_ot_apply_context_t *c,
+-                    const void            *base,
++                    const ValueBase       *base,
+                     const Value           *values,
+                     hb_glyph_position_t   &glyph_pos) const
+   {
+@@ -114,7 +116,7 @@ struct ValueFormat : HBUINT16
+ 
+     if (!use_x_device && !use_y_device) return ret;
+ 
+-    const VariationStore &store = c->var_store;
++    const ItemVariationStore &store = c->var_store;
+     auto *cache = c->var_store_cache;
+ 
+     /* pixel -> fractional pixel */
+@@ -142,11 +144,29 @@ struct ValueFormat : HBUINT16
+     return ret;
+   }
+ 
+-  unsigned int get_effective_format (const Value *values) const
++  unsigned int get_effective_format (const Value *values, bool strip_hints, bool strip_empty, const ValueBase *base,
++                                     const hb_hashmap_t> *varidx_delta_map) const
+   {
+     unsigned int format = *this;
+     for (unsigned flag = xPlacement; flag <= yAdvDevice; flag = flag << 1) {
+-      if (format & flag) should_drop (*values++, (Flags) flag, &format);
++      if (format & flag)
++      {
++        if (strip_hints && flag >= xPlaDevice)
++        {
++          format = format & ~flag;
++          values++;
++          continue;
++        }
++        if (varidx_delta_map && flag >= xPlaDevice)
++        {
++          update_var_flag (values++, (Flags) flag, &format, base, varidx_delta_map);
++          continue;
++        }
++        /* do not strip empty when instancing, cause we don't know whether the new
++         * default value is 0 or not */
++        if (strip_empty) should_drop (*values, (Flags) flag, &format);
++        values++;
++      }
+     }
+ 
+     return format;
+@@ -154,18 +174,19 @@ struct ValueFormat : HBUINT16
+ 
+   template
+-  unsigned int get_effective_format (Iterator it) const {
++  unsigned int get_effective_format (Iterator it, bool strip_hints, bool strip_empty, const ValueBase *base,
++                                     const hb_hashmap_t> *varidx_delta_map) const {
+     unsigned int new_format = 0;
+ 
+     for (const hb_array_t& values : it)
+-      new_format = new_format | get_effective_format (&values);
++      new_format = new_format | get_effective_format (&values, strip_hints, strip_empty, base, varidx_delta_map);
+ 
+     return new_format;
+   }
+ 
+   void copy_values (hb_serialize_context_t *c,
+                     unsigned int new_format,
+-                    const void *base,
++                    const ValueBase *base,
+                     const Value *values,
+                     const hb_hashmap_t> *layout_variation_idx_delta_map) const
+   {
+@@ -217,7 +238,7 @@ struct ValueFormat : HBUINT16
+   }
+ 
+   void collect_variation_indices (hb_collect_variation_indices_context_t *c,
+-                                  const void *base,
++                                  const ValueBase *base,
+                                   const hb_array_t& values) const
+   {
+     unsigned format = *this;
+@@ -251,17 +272,8 @@ struct ValueFormat : HBUINT16
+     }
+   }
+ 
+-  unsigned drop_device_table_flags () const
+-  {
+-    unsigned format = *this;
+-    for (unsigned flag = xPlaDevice; flag <= yAdvDevice; flag = flag << 1)
+-      format = format & ~flag;
+-
+-    return format;
+-  }
+-
+   private:
+-  bool sanitize_value_devices (hb_sanitize_context_t *c, const void *base, const Value *values) const
++  bool sanitize_value_devices (hb_sanitize_context_t *c, const ValueBase *base, const Value *values) const
+   {
+     unsigned int format = *this;
+ 
+@@ -278,17 +290,17 @@ struct ValueFormat : HBUINT16
+     return true;
+   }
+ 
+-  static inline Offset16To& get_device (Value* value)
++  static inline Offset16To& get_device (Value* value)
+   {
+-    return *static_cast *> (value);
++    return *static_cast *> (value);
+   }
+-  static inline const Offset16To& get_device (const Value* value)
++  static inline const Offset16To& get_device (const Value* value)
+   {
+-    return *static_cast *> (value);
++    return *static_cast *> (value);
+   }
+   static inline const Device& get_device (const Value* value,
+                                           bool *worked,
+-                                          const void *base,
++                                          const ValueBase *base,
+                                           hb_sanitize_context_t &c)
+   {
+     if (worked) *worked |= bool (*value);
+@@ -296,12 +308,13 @@ struct ValueFormat : HBUINT16
+ 
+     if (unlikely (!offset.sanitize (&c, base)))
+       return Null(Device);
++    hb_barrier ();
+ 
+     return base + offset;
+   }
+ 
+   void add_delta_to_value (HBINT16 *value,
+-                           const void *base,
++                           const ValueBase *base,
+                            const Value *src_value,
+                            const hb_hashmap_t> *layout_variation_idx_delta_map) const
+   {
+@@ -313,7 +326,8 @@ struct ValueFormat : HBUINT16
+     *value += hb_second (*varidx_delta);
+   }
+ 
+-  bool copy_device (hb_serialize_context_t *c, const void *base,
++  bool copy_device (hb_serialize_context_t *c,
++                    const ValueBase *base,
+                     const Value *src_value,
+                     const hb_hashmap_t> *layout_variation_idx_delta_map,
+                     unsigned int new_format, Flags flag) const
+@@ -354,7 +368,7 @@ struct ValueFormat : HBUINT16
+     return (format & devices) != 0;
+   }
+ 
+-  bool sanitize_value (hb_sanitize_context_t *c, const void *base, const Value *values) const
++  bool sanitize_value (hb_sanitize_context_t *c, const ValueBase *base, const Value *values) const
+   {
+     TRACE_SANITIZE (this);
+ 
+@@ -366,7 +380,7 @@ struct ValueFormat : HBUINT16
+     return_trace (!has_device () || sanitize_value_devices (c, base, values));
+   }
+ 
+-  bool sanitize_values (hb_sanitize_context_t *c, const void *base, const Value *values, unsigned int count) const
++  bool sanitize_values (hb_sanitize_context_t *c, const ValueBase *base, const Value *values, unsigned int count) const
+   {
+     TRACE_SANITIZE (this);
+     unsigned size = get_size ();
+@@ -376,11 +390,12 @@ struct ValueFormat : HBUINT16
+     if (c->lazy_some_gpos)
+       return_trace (true);
+ 
++    hb_barrier ();
+     return_trace (sanitize_values_stride_unsafe (c, base, values, count, size));
+   }
+ 
+   /* Just sanitize referenced Device tables.  Doesn't check the values themselves. */
+-  bool sanitize_values_stride_unsafe (hb_sanitize_context_t *c, const void *base, const Value *values, unsigned int count, unsigned int stride) const
++  bool sanitize_values_stride_unsafe (hb_sanitize_context_t *c, const ValueBase *base, const Value *values, unsigned int count, unsigned int stride) const
+   {
+     TRACE_SANITIZE (this);
+ 
+@@ -403,6 +418,20 @@ struct ValueFormat : HBUINT16
+     *format = *format & ~flag;
+   }
+ 
++  void update_var_flag (const Value* value, Flags flag,
++                        unsigned int* format, const ValueBase *base,
++                        const hb_hashmap_t> *varidx_delta_map) const
++  {
++    if (*value)
++    {
++      unsigned varidx = (base + get_device (value)).get_variation_index ();
++      hb_pair_t *varidx_delta;
++      if (varidx_delta_map->has (varidx, &varidx_delta) &&
++          varidx_delta->first != HB_OT_LAYOUT_NO_VARIATIONS_INDEX)
++        return;
++    }
++    *format = *format & ~flag;
++  }
+ };
+ 
+ }
+diff --git a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/AlternateSubstFormat1.hh b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/AlternateSubstFormat1.hh
+index adec65d58..421a6e066 100644
+--- a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/AlternateSubstFormat1.hh
++++ b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/AlternateSubstFormat1.hh
+@@ -74,7 +74,7 @@ struct AlternateSubstFormat1_2
+     TRACE_APPLY (this);
+ 
+     unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
+-    if (likely (index == NOT_COVERED)) return_trace (false);
++    if (index == NOT_COVERED) return_trace (false);
+ 
+     return_trace ((this+alternateSet[index]).apply (c));
+   }
+diff --git a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/Ligature.hh b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/Ligature.hh
+index de4a111b4..726da458f 100644
+--- a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/Ligature.hh
++++ b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/Ligature.hh
+@@ -90,8 +90,17 @@ struct Ligature
+ 
+     unsigned int total_component_count = 0;
+ 
++    if (unlikely (count > HB_MAX_CONTEXT_LENGTH)) return false;
++    unsigned match_positions_stack[4];
++    unsigned *match_positions = match_positions_stack;
++    if (unlikely (count > ARRAY_LENGTH (match_positions_stack)))
++    {
++      match_positions = (unsigned *) hb_malloc (hb_max (count, 1u) * sizeof (unsigned));
++      if (unlikely (!match_positions))
++        return_trace (false);
++    }
++
+     unsigned int match_end = 0;
+-    unsigned int match_positions[HB_MAX_CONTEXT_LENGTH];
+ 
+     if (likely (!match_input (c, count,
+                               &component[1],
+@@ -102,6 +111,8 @@ struct Ligature
+                               &total_component_count)))
+     {
+       c->buffer->unsafe_to_concat (c->buffer->idx, match_end);
++      if (match_positions != match_positions_stack)
++        hb_free (match_positions);
+       return_trace (false);
+     }
+ 
+@@ -145,6 +156,8 @@ struct Ligature
+                           pos);
+     }
+ 
++    if (match_positions != match_positions_stack)
++      hb_free (match_positions);
+     return_trace (true);
+   }
+ 
+diff --git a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/LigatureSubstFormat1.hh b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/LigatureSubstFormat1.hh
+index 5c7df97d1..6ae24b337 100644
+--- a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/LigatureSubstFormat1.hh
++++ b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/LigatureSubstFormat1.hh
+@@ -78,12 +78,49 @@ struct LigatureSubstFormat1_2
+     return lig_set.would_apply (c);
+   }
+ 
+-  bool apply (hb_ot_apply_context_t *c) const
++  unsigned cache_cost () const
+   {
+-    TRACE_APPLY (this);
++    return (this+coverage).cost ();
++  }
++  static void * cache_func (void *p, hb_ot_lookup_cache_op_t op)
++  {
++    switch (op)
++    {
++      case hb_ot_lookup_cache_op_t::CREATE:
++      {
++        hb_ot_lookup_cache_t *cache = (hb_ot_lookup_cache_t *) hb_malloc (sizeof (hb_ot_lookup_cache_t));
++        if (likely (cache))
++          cache->clear ();
++        return cache;
++      }
++      case hb_ot_lookup_cache_op_t::ENTER:
++        return (void *) true;
++      case hb_ot_lookup_cache_op_t::LEAVE:
++        return nullptr;
++      case hb_ot_lookup_cache_op_t::DESTROY:
++      {
++        hb_ot_lookup_cache_t *cache = (hb_ot_lookup_cache_t *) p;
++        hb_free (cache);
++        return nullptr;
++      }
++    }
++    return nullptr;
++  }
+ 
+-    unsigned int index = (this+coverage).get_coverage (c->buffer->cur ().codepoint);
+-    if (likely (index == NOT_COVERED)) return_trace (false);
++  bool apply_cached (hb_ot_apply_context_t *c) const { return _apply (c, true); }
++  bool apply (hb_ot_apply_context_t *c) const { return _apply (c, false); }
++  bool _apply (hb_ot_apply_context_t *c, bool cached) const
++  {
++    TRACE_APPLY (this);
++    hb_buffer_t *buffer = c->buffer;
++
++#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
++    hb_ot_lookup_cache_t *cache = cached ? (hb_ot_lookup_cache_t *) c->lookup_accel->cache : nullptr;
++    unsigned int index = (this+coverage).get_coverage  (buffer->cur().codepoint, cache);
++#else
++    unsigned int index = (this+coverage).get_coverage  (buffer->cur().codepoint);
++#endif
++    if (index == NOT_COVERED) return_trace (false);
+ 
+     const auto &lig_set = this+ligatureSet[index];
+     return_trace (lig_set.apply (c));
+diff --git a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/MultipleSubstFormat1.hh b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/MultipleSubstFormat1.hh
+index 4a9972c29..aec8d0f2c 100644
+--- a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/MultipleSubstFormat1.hh
++++ b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/MultipleSubstFormat1.hh
+@@ -66,7 +66,7 @@ struct MultipleSubstFormat1_2
+     TRACE_APPLY (this);
+ 
+     unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
+-    if (likely (index == NOT_COVERED)) return_trace (false);
++    if (index == NOT_COVERED) return_trace (false);
+ 
+     return_trace ((this+sequence[index]).apply (c));
+   }
+diff --git a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh
+index ec6dfa476..400a9e737 100644
+--- a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh
++++ b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh
+@@ -33,9 +33,11 @@ struct ReverseChainSingleSubstFormat1
+     TRACE_SANITIZE (this);
+     if (!(coverage.sanitize (c, this) && backtrack.sanitize (c, this)))
+       return_trace (false);
++    hb_barrier ();
+     const auto &lookahead = StructAfter (backtrack);
+     if (!lookahead.sanitize (c, this))
+       return_trace (false);
++    hb_barrier ();
+     const auto &substitute = StructAfter (lookahead);
+     return_trace (substitute.sanitize (c));
+   }
+@@ -109,12 +111,12 @@ struct ReverseChainSingleSubstFormat1
+   bool apply (hb_ot_apply_context_t *c) const
+   {
+     TRACE_APPLY (this);
++    unsigned int index = (this+coverage).get_coverage (c->buffer->cur ().codepoint);
++    if (index == NOT_COVERED) return_trace (false);
++
+     if (unlikely (c->nesting_level_left != HB_MAX_NESTING_LEVEL))
+       return_trace (false); /* No chaining to this type */
+ 
+-    unsigned int index = (this+coverage).get_coverage (c->buffer->cur ().codepoint);
+-    if (likely (index == NOT_COVERED)) return_trace (false);
+-
+     const auto &lookahead = StructAfter (backtrack);
+     const auto &substitute = StructAfter (lookahead);
+ 
+diff --git a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/SingleSubstFormat1.hh b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/SingleSubstFormat1.hh
+index 268487c5a..be6cd820d 100644
+--- a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/SingleSubstFormat1.hh
++++ b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/SingleSubstFormat1.hh
+@@ -128,7 +128,7 @@ struct SingleSubstFormat1_3
+     TRACE_APPLY (this);
+     hb_codepoint_t glyph_id = c->buffer->cur().codepoint;
+     unsigned int index = (this+coverage).get_coverage (glyph_id);
+-    if (likely (index == NOT_COVERED)) return_trace (false);
++    if (index == NOT_COVERED) return_trace (false);
+ 
+     hb_codepoint_t d = deltaGlyphID;
+     hb_codepoint_t mask = get_mask ();
+diff --git a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/SingleSubstFormat2.hh b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/SingleSubstFormat2.hh
+index 518900116..e90964604 100644
+--- a/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/SingleSubstFormat2.hh
++++ b/src/java.desktop/share/native/libharfbuzz/OT/Layout/GSUB/SingleSubstFormat2.hh
+@@ -104,7 +104,7 @@ struct SingleSubstFormat2_4
+   {
+     TRACE_APPLY (this);
+     unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
+-    if (likely (index == NOT_COVERED)) return_trace (false);
++    if (index == NOT_COVERED) return_trace (false);
+ 
+     if (unlikely (index >= substitute.len)) return_trace (false);
+ 
+diff --git a/src/java.desktop/share/native/libharfbuzz/OT/Layout/types.hh b/src/java.desktop/share/native/libharfbuzz/OT/Layout/types.hh
+index 6a43403e9..527f64114 100644
+--- a/src/java.desktop/share/native/libharfbuzz/OT/Layout/types.hh
++++ b/src/java.desktop/share/native/libharfbuzz/OT/Layout/types.hh
+@@ -29,6 +29,9 @@
+ #ifndef OT_LAYOUT_TYPES_HH
+ #define OT_LAYOUT_TYPES_HH
+ 
++using hb_ot_lookup_cache_t = hb_cache_t<15, 8, 7>;
++static_assert (sizeof (hb_ot_lookup_cache_t) == 256, "");
++
+ namespace OT {
+ namespace Layout {
+ 
+@@ -38,8 +41,8 @@ struct SmallTypes {
+   using HBUINT = HBUINT16;
+   using HBGlyphID = HBGlyphID16;
+   using Offset = Offset16;
+-  template 
+-  using OffsetTo = OT::Offset16To;
++  template 
++  using OffsetTo = OT::Offset16To;
+   template 
+   using ArrayOf = OT::Array16Of;
+   template 
+@@ -52,8 +55,8 @@ struct MediumTypes {
+   using HBUINT = HBUINT24;
+   using HBGlyphID = HBGlyphID24;
+   using Offset = Offset24;
+-  template 
+-  using OffsetTo = OT::Offset24To;
++  template 
++  using OffsetTo = OT::Offset24To;
+   template 
+   using ArrayOf = OT::Array24Of;
+   template 
+diff --git a/src/java.desktop/share/native/libharfbuzz/OT/Var/VARC/VARC.hh b/src/java.desktop/share/native/libharfbuzz/OT/Var/VARC/VARC.hh
+new file mode 100644
+index 000000000..dbbbec9ee
+--- /dev/null
++++ b/src/java.desktop/share/native/libharfbuzz/OT/Var/VARC/VARC.hh
+@@ -0,0 +1,218 @@
++#ifndef OT_VAR_VARC_VARC_HH
++#define OT_VAR_VARC_VARC_HH
++
++#include "../../../hb-decycler.hh"
++#include "../../../hb-geometry.hh"
++#include "../../../hb-ot-layout-common.hh"
++#include "../../../hb-ot-glyf-table.hh"
++#include "../../../hb-ot-cff2-table.hh"
++#include "../../../hb-ot-cff1-table.hh"
++
++#include "coord-setter.hh"
++
++namespace OT {
++
++//namespace Var {
++
++/*
++ * VARC -- Variable Composites
++ * https://github.com/harfbuzz/boring-expansion-spec/blob/main/VARC.md
++ */
++
++#ifndef HB_NO_VAR_COMPOSITES
++
++struct VarComponent
++{
++  enum class flags_t : uint32_t
++  {
++    RESET_UNSPECIFIED_AXES      = 1u << 0,
++    HAVE_AXES                   = 1u << 1,
++    AXIS_VALUES_HAVE_VARIATION  = 1u << 2,
++    TRANSFORM_HAS_VARIATION     = 1u << 3,
++    HAVE_TRANSLATE_X            = 1u << 4,
++    HAVE_TRANSLATE_Y            = 1u << 5,
++    HAVE_ROTATION               = 1u << 6,
++    HAVE_CONDITION              = 1u << 7,
++    HAVE_SCALE_X                = 1u << 8,
++    HAVE_SCALE_Y                = 1u << 9,
++    HAVE_TCENTER_X              = 1u << 10,
++    HAVE_TCENTER_Y              = 1u << 11,
++    GID_IS_24BIT                = 1u << 12,
++    HAVE_SKEW_X                 = 1u << 13,
++    HAVE_SKEW_Y                 = 1u << 14,
++    RESERVED_MASK               = ~((1u << 15) - 1),
++  };
++
++  HB_INTERNAL hb_ubytes_t
++  get_path_at (hb_font_t *font,
++               hb_codepoint_t parent_gid,
++               hb_draw_session_t &draw_session,
++               hb_array_t coords,
++               hb_transform_t transform,
++               hb_ubytes_t record,
++               hb_decycler_t *decycler,
++               signed *edges_left,
++               signed depth_left,
++               hb_glyf_scratch_t &scratch,
++               VarRegionList::cache_t *cache = nullptr) const;
++};
++
++struct VarCompositeGlyph
++{
++  static void
++  get_path_at (hb_font_t *font,
++               hb_codepoint_t glyph,
++               hb_draw_session_t &draw_session,
++               hb_array_t coords,
++               hb_transform_t transform,
++               hb_ubytes_t record,
++               hb_decycler_t *decycler,
++               signed *edges_left,
++               signed depth_left,
++               hb_glyf_scratch_t &scratch,
++               VarRegionList::cache_t *cache = nullptr)
++  {
++    while (record)
++    {
++      const VarComponent &comp = * (const VarComponent *) (record.arrayZ);
++      record = comp.get_path_at (font, glyph,
++                                 draw_session, coords, transform,
++                                 record,
++                                 decycler, edges_left, depth_left, scratch, cache);
++    }
++  }
++};
++
++HB_MARK_AS_FLAG_T (VarComponent::flags_t);
++
++struct VARC
++{
++  friend struct VarComponent;
++
++  static constexpr hb_tag_t tableTag = HB_TAG ('V', 'A', 'R', 'C');
++
++  HB_INTERNAL bool
++  get_path_at (hb_font_t *font,
++               hb_codepoint_t glyph,
++               hb_draw_session_t &draw_session,
++               hb_array_t coords,
++               hb_transform_t transform,
++               hb_codepoint_t parent_glyph,
++               hb_decycler_t *decycler,
++               signed *edges_left,
++               signed depth_left,
++               hb_glyf_scratch_t &scratch) const;
++
++  bool
++  get_path (hb_font_t *font,
++            hb_codepoint_t gid,
++            hb_draw_session_t &draw_session,
++            hb_glyf_scratch_t &scratch) const
++  {
++    hb_decycler_t decycler;
++    signed edges = HB_MAX_GRAPH_EDGE_COUNT;
++
++    return get_path_at (font,
++                        gid,
++                        draw_session,
++                        hb_array (font->coords, font->num_coords),
++                        HB_TRANSFORM_IDENTITY,
++                        HB_CODEPOINT_INVALID,
++                        &decycler,
++                        &edges,
++                        HB_MAX_NESTING_LEVEL,
++                        scratch);
++  }
++
++  bool sanitize (hb_sanitize_context_t *c) const
++  {
++    TRACE_SANITIZE (this);
++    return_trace (version.sanitize (c) &&
++                  hb_barrier () &&
++                  version.major == 1 &&
++                  coverage.sanitize (c, this) &&
++                  varStore.sanitize (c, this) &&
++                  conditionList.sanitize (c, this) &&
++                  axisIndicesList.sanitize (c, this) &&
++                  glyphRecords.sanitize (c, this));
++  }
++
++  struct accelerator_t
++  {
++    friend struct VarComponent;
++
++    accelerator_t (hb_face_t *face)
++    {
++      table = hb_sanitize_context_t ().reference_table (face);
++    }
++    ~accelerator_t ()
++    {
++      auto *scratch = cached_scratch.get_relaxed ();
++      if (scratch)
++      {
++        scratch->~hb_glyf_scratch_t ();
++        hb_free (scratch);
++      }
++
++      table.destroy ();
++    }
++
++    bool
++    get_path (hb_font_t *font, hb_codepoint_t gid, hb_draw_session_t &draw_session) const
++    {
++      if (!table->has_data ()) return false;
++
++      hb_glyf_scratch_t *scratch;
++
++      // Borrow the cached strach buffer.
++      {
++        scratch = cached_scratch.get_acquire ();
++        if (!scratch || unlikely (!cached_scratch.cmpexch (scratch, nullptr)))
++        {
++          scratch = (hb_glyf_scratch_t *) hb_calloc (1, sizeof (hb_glyf_scratch_t));
++          if (unlikely (!scratch))
++            return true;
++        }
++      }
++
++      bool ret = table->get_path (font, gid, draw_session, *scratch);
++
++      // Put it back.
++      if (!cached_scratch.cmpexch (nullptr, scratch))
++      {
++        scratch->~hb_glyf_scratch_t ();
++        hb_free (scratch);
++      }
++
++      return ret;
++    }
++
++    private:
++    hb_blob_ptr_t table;
++    hb_atomic_ptr_t cached_scratch;
++  };
++
++  bool has_data () const { return version.major != 0; }
++
++  protected:
++  FixedVersion<> version; /* Version identifier */
++  Offset32To coverage;
++  Offset32To varStore;
++  Offset32To conditionList;
++  Offset32To axisIndicesList;
++  Offset32To*/> glyphRecords;
++  public:
++  DEFINE_SIZE_STATIC (24);
++};
++
++struct VARC_accelerator_t : VARC::accelerator_t {
++  VARC_accelerator_t (hb_face_t *face) : VARC::accelerator_t (face) {}
++};
++
++#endif
++
++//}
++
++}
++
++#endif  /* OT_VAR_VARC_VARC_HH */
+diff --git a/src/java.desktop/share/native/libharfbuzz/OT/Var/VARC/coord-setter.hh b/src/java.desktop/share/native/libharfbuzz/OT/Var/VARC/coord-setter.hh
+new file mode 100644
+index 000000000..70c0968e1
+--- /dev/null
++++ b/src/java.desktop/share/native/libharfbuzz/OT/Var/VARC/coord-setter.hh
+@@ -0,0 +1,63 @@
++#ifndef OT_VAR_VARC_COORD_SETTER_HH
++#define OT_VAR_VARC_COORD_SETTER_HH
++
++
++#include "../../../hb.hh"
++
++
++namespace OT {
++//namespace Var {
++
++
++struct coord_setter_t
++{
++  coord_setter_t (hb_array_t coords_)
++  {
++    length = coords_.length;
++    if (length <= ARRAY_LENGTH (static_coords))
++      hb_memcpy (static_coords, coords_.arrayZ, length * sizeof (int));
++    else
++      dynamic_coords.extend (coords_);
++  }
++
++  int& operator [] (unsigned idx)
++  {
++    if (unlikely (idx >= HB_VAR_COMPOSITE_MAX_AXES))
++      return Crap(int);
++
++    if (length <= ARRAY_LENGTH (static_coords))
++    {
++      if (idx < ARRAY_LENGTH (static_coords))
++      {
++        while (length <= idx)
++          static_coords[length++] = 0;
++        return static_coords[idx];
++      }
++      else
++        dynamic_coords.extend (hb_array (static_coords, length));
++    }
++
++    if (dynamic_coords.length <= idx)
++    {
++      if (unlikely (!dynamic_coords.resize (idx + 1)))
++        return Crap(int);
++      length = idx + 1;
++    }
++    return dynamic_coords.arrayZ[idx];
++  }
++
++  hb_array_t get_coords ()
++  { return length <= ARRAY_LENGTH (static_coords) ? hb_array (static_coords, length) : dynamic_coords.as_array (); }
++
++  private:
++  hb_vector_t dynamic_coords;
++  unsigned length;
++  int static_coords[sizeof (void *) * 8];
++};
++
++
++//} // namespace Var
++
++} // namespace OT
++
++#endif /* OT_VAR_VARC_COORD_SETTER_HH */
+diff --git a/src/java.desktop/share/native/libharfbuzz/OT/glyf/CompositeGlyph.hh b/src/java.desktop/share/native/libharfbuzz/OT/glyf/CompositeGlyph.hh
+index 151c1ac48..fb347770e 100644
+--- a/src/java.desktop/share/native/libharfbuzz/OT/glyf/CompositeGlyph.hh
++++ b/src/java.desktop/share/native/libharfbuzz/OT/glyf/CompositeGlyph.hh
+@@ -143,7 +143,7 @@ struct CompositeGlyphRecord
+     float matrix[4];
+     contour_point_t trans;
+     get_transformation (matrix, trans);
+-    if (unlikely (!points.alloc (points.length + 4))) return false; // For phantom points
++    if (unlikely (!points.alloc (points.length + 1 + 4))) return false; // For phantom points
+     points.push (trans);
+     return true;
+   }
+@@ -240,7 +240,8 @@ struct CompositeGlyphRecord
+     }
+     if (is_anchored ()) tx = ty = 0;
+ 
+-    trans.init ((float) tx, (float) ty);
++    /* set is_end_point flag to true, used by IUP delta optimization */
++    trans.init ((float) tx, (float) ty, true);
+ 
+     {
+       const F2DOT14 *points = (const F2DOT14 *) p;
+diff --git a/src/java.desktop/share/native/libharfbuzz/OT/glyf/Glyph.hh b/src/java.desktop/share/native/libharfbuzz/OT/glyf/Glyph.hh
+index b295e4151..1805df262 100644
+--- a/src/java.desktop/share/native/libharfbuzz/OT/glyf/Glyph.hh
++++ b/src/java.desktop/share/native/libharfbuzz/OT/glyf/Glyph.hh
+@@ -7,8 +7,6 @@
+ #include "GlyphHeader.hh"
+ #include "SimpleGlyph.hh"
+ #include "CompositeGlyph.hh"
+-#include "VarCompositeGlyph.hh"
+-#include "coord-setter.hh"
+ 
+ 
+ namespace OT {
+@@ -33,9 +31,6 @@ struct Glyph
+     EMPTY,
+     SIMPLE,
+     COMPOSITE,
+-#ifndef HB_NO_VAR_COMPOSITES
+-    VAR_COMPOSITE,
+-#endif
+   };
+ 
+   public:
+@@ -44,22 +39,10 @@ struct Glyph
+     if (type != COMPOSITE) return composite_iter_t ();
+     return CompositeGlyph (*header, bytes).iter ();
+   }
+-  var_composite_iter_t get_var_composite_iterator () const
+-  {
+-#ifndef HB_NO_VAR_COMPOSITES
+-    if (type != VAR_COMPOSITE) return var_composite_iter_t ();
+-    return VarCompositeGlyph (*header, bytes).iter ();
+-#else
+-    return var_composite_iter_t ();
+-#endif
+-  }
+ 
+   const hb_bytes_t trim_padding () const
+   {
+     switch (type) {
+-#ifndef HB_NO_VAR_COMPOSITES
+-    case VAR_COMPOSITE: return VarCompositeGlyph (*header, bytes).trim_padding ();
+-#endif
+     case COMPOSITE: return CompositeGlyph (*header, bytes).trim_padding ();
+     case SIMPLE:    return SimpleGlyph (*header, bytes).trim_padding ();
+     case EMPTY:     return bytes;
+@@ -70,9 +53,6 @@ struct Glyph
+   void drop_hints ()
+   {
+     switch (type) {
+-#ifndef HB_NO_VAR_COMPOSITES
+-    case VAR_COMPOSITE: return; // No hinting
+-#endif
+     case COMPOSITE: CompositeGlyph (*header, bytes).drop_hints (); return;
+     case SIMPLE:    SimpleGlyph (*header, bytes).drop_hints (); return;
+     case EMPTY:     return;
+@@ -82,9 +62,6 @@ struct Glyph
+   void set_overlaps_flag ()
+   {
+     switch (type) {
+-#ifndef HB_NO_VAR_COMPOSITES
+-    case VAR_COMPOSITE: return; // No overlaps flag
+-#endif
+     case COMPOSITE: CompositeGlyph (*header, bytes).set_overlaps_flag (); return;
+     case SIMPLE:    SimpleGlyph (*header, bytes).set_overlaps_flag (); return;
+     case EMPTY:     return;
+@@ -94,15 +71,15 @@ struct Glyph
+   void drop_hints_bytes (hb_bytes_t &dest_start, hb_bytes_t &dest_end) const
+   {
+     switch (type) {
+-#ifndef HB_NO_VAR_COMPOSITES
+-    case VAR_COMPOSITE: return; // No hinting
+-#endif
+     case COMPOSITE: CompositeGlyph (*header, bytes).drop_hints_bytes (dest_start); return;
+     case SIMPLE:    SimpleGlyph (*header, bytes).drop_hints_bytes (dest_start, dest_end); return;
+     case EMPTY:     return;
+     }
+   }
+ 
++  bool is_composite () const
++  { return type == COMPOSITE; }
++
+   bool get_all_points_without_var (const hb_face_t *face,
+                                    contour_point_vector_t &points /* OUT */) const
+   {
+@@ -117,14 +94,6 @@ struct Glyph
+         if (unlikely (!item.get_points (points))) return false;
+       break;
+     }
+-#ifndef HB_NO_VAR_COMPOSITES
+-    case VAR_COMPOSITE:
+-    {
+-      for (auto &item : get_var_composite_iterator ())
+-        if (unlikely (!item.get_points (points))) return false;
+-      break;
+-    }
+-#endif
+     case EMPTY:
+       break;
+     }
+@@ -282,7 +251,8 @@ struct Glyph
+       composite_contours_p = nullptr;
+     }
+ 
+-    if (!get_points (font, glyf, all_points, &points_with_deltas, head_maxp_info_p, composite_contours_p, false, false))
++    hb_glyf_scratch_t scratch;
++    if (!get_points (font, glyf, all_points, scratch, &points_with_deltas, head_maxp_info_p, composite_contours_p, false, false))
+       return false;
+ 
+     // .notdef, set type to empty so we only update metrics and don't compile bytes for
+@@ -300,13 +270,6 @@ struct Glyph
+     {
+       switch (type)
+       {
+-#ifndef HB_NO_VAR_COMPOSITES
+-      case VAR_COMPOSITE:
+-        // TODO
+-        dest_end = hb_bytes_t ();
+-        break;
+-#endif
+-
+       case COMPOSITE:
+         if (!CompositeGlyph (*header, bytes).compile_bytes_with_deltas (dest_start,
+                                                                         points_with_deltas,
+@@ -343,27 +306,23 @@ struct Glyph
+   template 
+   bool get_points (hb_font_t *font, const accelerator_t &glyf_accelerator,
+                    contour_point_vector_t &all_points /* OUT */,
++                   hb_glyf_scratch_t &scratch,
+                    contour_point_vector_t *points_with_deltas = nullptr, /* OUT */
+                    head_maxp_info_t * head_maxp_info = nullptr, /* OUT */
+                    unsigned *composite_contours = nullptr, /* OUT */
+                    bool shift_points_hori = true,
+                    bool use_my_metrics = true,
+                    bool phantom_only = false,
+-                   hb_array_t coords = hb_array_t (),
+-                   hb_map_t *current_glyphs = nullptr,
++                   hb_array_t coords = hb_array_t (),
+                    unsigned int depth = 0,
+                    unsigned *edge_count = nullptr) const
+   {
+     if (unlikely (depth > HB_MAX_NESTING_LEVEL)) return false;
+     unsigned stack_edge_count = 0;
+     if (!edge_count) edge_count = &stack_edge_count;
+-    if (unlikely (*edge_count > HB_GLYF_MAX_EDGE_COUNT)) return false;
++    if (unlikely (*edge_count > HB_MAX_GRAPH_EDGE_COUNT)) return false;
+     (*edge_count)++;
+ 
+-    hb_map_t current_glyphs_stack;
+-    if (current_glyphs == nullptr)
+-      current_glyphs = ¤t_glyphs_stack;
+-
+     if (head_maxp_info)
+     {
+       head_maxp_info->maxComponentDepth = hb_max (head_maxp_info->maxComponentDepth, depth);
+@@ -372,8 +331,7 @@ struct Glyph
+     if (!coords)
+       coords = hb_array (font->coords, font->num_coords);
+ 
+-    contour_point_vector_t stack_points;
+-    contour_point_vector_t &points = type == SIMPLE ? all_points : stack_points;
++    contour_point_vector_t &points = type == SIMPLE ? all_points : scratch.comp_points;
+     unsigned old_length = points.length;
+ 
+     switch (type) {
+@@ -391,14 +349,6 @@ struct Glyph
+         if (unlikely (!item.get_points (points))) return false;
+       break;
+     }
+-#ifndef HB_NO_VAR_COMPOSITES
+-    case VAR_COMPOSITE:
+-    {
+-      for (auto &item : get_var_composite_iterator ())
+-        if (unlikely (!item.get_points (points))) return false;
+-      break;
+-    }
+-#endif
+     case EMPTY:
+       break;
+     }
+@@ -434,36 +384,53 @@ struct Glyph
+ 
+ #ifndef HB_NO_VAR
+     if (coords)
+-      glyf_accelerator.gvar->apply_deltas_to_points (gid,
+-                                                     coords,
+-                                                     points.as_array ().sub_array (old_length),
+-                                                     phantom_only && type == SIMPLE);
++    {
++#ifndef HB_NO_BEYOND_64K
++      if (glyf_accelerator.GVAR->has_data ())
++        glyf_accelerator.GVAR->apply_deltas_to_points (gid,
++                                                       coords,
++                                                       points.as_array ().sub_array (old_length),
++                                                       scratch,
++                                                       phantom_only && type == SIMPLE);
++      else
++#endif
++        glyf_accelerator.gvar->apply_deltas_to_points (gid,
++                                                       coords,
++                                                       points.as_array ().sub_array (old_length),
++                                                       scratch,
++                                                       phantom_only && type == SIMPLE);
++    }
+ #endif
+ 
+     // mainly used by CompositeGlyph calculating new X/Y offset value so no need to extend it
+     // with child glyphs' points
+     if (points_with_deltas != nullptr && depth == 0 && type == COMPOSITE)
+     {
+-      if (unlikely (!points_with_deltas->resize (points.length))) return false;
++      assert (old_length == 0);
+       *points_with_deltas = points;
+     }
+ 
++    float shift = 0;
+     switch (type) {
+     case SIMPLE:
+       if (depth == 0 && head_maxp_info)
+         head_maxp_info->maxPoints = hb_max (head_maxp_info->maxPoints, all_points.length - old_length - 4);
++      shift = phantoms[PHANTOM_LEFT].x;
+       break;
+     case COMPOSITE:
+     {
++      hb_decycler_node_t decycler_node (scratch.decycler);
++
+       unsigned int comp_index = 0;
+       for (auto &item : get_composite_iterator ())
+       {
+         hb_codepoint_t item_gid = item.get_gid ();
+ 
+-        if (unlikely (current_glyphs->has (item_gid)))
++        if (unlikely (!decycler_node.visit (item_gid)))
++        {
++          comp_index++;
+           continue;
+-
+-        current_glyphs->add (item_gid);
++        }
+ 
+         unsigned old_count = all_points.length;
+ 
+@@ -472,6 +439,7 @@ struct Glyph
+                                        .get_points (font,
+                                                     glyf_accelerator,
+                                                     all_points,
++                                                    scratch,
+                                                     points_with_deltas,
+                                                     head_maxp_info,
+                                                     composite_contours,
+@@ -479,14 +447,16 @@ struct Glyph
+                                                     use_my_metrics,
+                                                     phantom_only,
+                                                     coords,
+-                                                    current_glyphs,
+                                                     depth + 1,
+                                                     edge_count)))
+         {
+-          current_glyphs->del (item_gid);
++          points.resize (old_length);
+           return false;
+         }
+ 
++        // points might have been reallocated. Relocate phantoms.
++        phantoms = points.as_array ().sub_array (points.length - PHANTOM_COUNT, PHANTOM_COUNT);
++
+         auto comp_points = all_points.as_array ().sub_array (old_count);
+ 
+         /* Copy phantom points from component if USE_MY_METRICS flag set */
+@@ -501,7 +471,7 @@ struct Glyph
+           item.get_transformation (matrix, default_trans);
+ 
+           /* Apply component transformation & translation (with deltas applied) */
+-          item.transform_points (comp_points, matrix, points[comp_index]);
++          item.transform_points (comp_points, matrix, points[old_length + comp_index]);
+         }
+ 
+         if (item.is_anchored () && !phantom_only)
+@@ -522,12 +492,11 @@ struct Glyph
+ 
+         if (all_points.length > HB_GLYF_MAX_POINTS)
+         {
+-          current_glyphs->del (item_gid);
++          points.resize (old_length);
+           return false;
+         }
+ 
+         comp_index++;
+-        current_glyphs->del (item_gid);
+       }
+ 
+       if (head_maxp_info && depth == 0)
+@@ -538,84 +507,13 @@ struct Glyph
+         head_maxp_info->maxComponentElements = hb_max (head_maxp_info->maxComponentElements, comp_index);
+       }
+       all_points.extend (phantoms);
++      shift = phantoms[PHANTOM_LEFT].x;
++      points.resize (old_length);
+     } break;
+-#ifndef HB_NO_VAR_COMPOSITES
+-    case VAR_COMPOSITE:
+-    {
+-      hb_array_t points_left = points.as_array ();
+-      for (auto &item : get_var_composite_iterator ())
+-      {
+-        hb_codepoint_t item_gid = item.get_gid ();
+-
+-        if (unlikely (current_glyphs->has (item_gid)))
+-          continue;
+-
+-        current_glyphs->add (item_gid);
+-
+-        unsigned item_num_points = item.get_num_points ();
+-        hb_array_t record_points = points_left.sub_array (0, item_num_points);
+-        assert (record_points.length == item_num_points);
+-
+-        auto component_coords = coords;
+-        /* Copying coords is expensive; so we have put an arbitrary
+-         * limit on the max number of coords for now. */
+-        if (item.is_reset_unspecified_axes () ||
+-            coords.length > HB_GLYF_VAR_COMPOSITE_MAX_AXES)
+-          component_coords = hb_array ();
+-
+-        coord_setter_t coord_setter (component_coords);
+-        item.set_variations (coord_setter, record_points);
+-
+-        unsigned old_count = all_points.length;
+-
+-        if (unlikely ((!phantom_only || (use_my_metrics && item.is_use_my_metrics ())) &&
+-                      !glyf_accelerator.glyph_for_gid (item_gid)
+-                                       .get_points (font,
+-                                                    glyf_accelerator,
+-                                                    all_points,
+-                                                    points_with_deltas,
+-                                                    head_maxp_info,
+-                                                    nullptr,
+-                                                    shift_points_hori,
+-                                                    use_my_metrics,
+-                                                    phantom_only,
+-                                                    coord_setter.get_coords (),
+-                                                    current_glyphs,
+-                                                    depth + 1,
+-                                                    edge_count)))
+-        {
+-          current_glyphs->del (item_gid);
+-          return false;
+-        }
+-
+-        auto comp_points = all_points.as_array ().sub_array (old_count);
+-
+-        /* Apply component transformation */
+-        if (comp_points) // Empty in case of phantom_only
+-          item.transform_points (record_points, comp_points);
+-
+-        /* Copy phantom points from component if USE_MY_METRICS flag set */
+-        if (use_my_metrics && item.is_use_my_metrics ())
+-          for (unsigned int i = 0; i < PHANTOM_COUNT; i++)
+-            phantoms[i] = comp_points[comp_points.length - PHANTOM_COUNT + i];
+-
+-        all_points.resize (all_points.length - PHANTOM_COUNT);
+-
+-        if (all_points.length > HB_GLYF_MAX_POINTS)
+-        {
+-          current_glyphs->del (item_gid);
+-          return false;
+-        }
+-
+-        points_left += item_num_points;
+-
+-        current_glyphs->del (item_gid);
+-      }
+-      all_points.extend (phantoms);
+-    } break;
+-#endif
+     case EMPTY:
+       all_points.extend (phantoms);
++      shift = phantoms[PHANTOM_LEFT].x;
++      points.resize (old_length);
+       break;
+     }
+ 
+@@ -624,10 +522,9 @@ struct Glyph
+       /* Undocumented rasterizer behavior:
+        * Shift points horizontally by the updated left side bearing
+        */
+-      int v = -phantoms[PHANTOM_LEFT].x;
+-      if (v)
++      if (shift)
+         for (auto &point : all_points)
+-          point.x += v;
++          point.x -= shift;
+     }
+ 
+     return !all_points.in_error ();
+@@ -658,10 +555,7 @@ struct Glyph
+     int num_contours = header->numberOfContours;
+     if (unlikely (num_contours == 0)) type = EMPTY;
+     else if (num_contours > 0) type = SIMPLE;
+-    else if (num_contours == -1) type = COMPOSITE;
+-#ifndef HB_NO_VAR_COMPOSITES
+-    else if (num_contours == -2) type = VAR_COMPOSITE;
+-#endif
++    else if (num_contours <= -1) type = COMPOSITE;
+     else type = EMPTY; // Spec deviation; Spec says COMPOSITE, but not seen in the wild.
+   }
+ 
+diff --git a/src/java.desktop/share/native/libharfbuzz/OT/glyf/SimpleGlyph.hh b/src/java.desktop/share/native/libharfbuzz/OT/glyf/SimpleGlyph.hh
+index 508839726..601e13037 100644
+--- a/src/java.desktop/share/native/libharfbuzz/OT/glyf/SimpleGlyph.hh
++++ b/src/java.desktop/share/native/libharfbuzz/OT/glyf/SimpleGlyph.hh
+@@ -127,19 +127,20 @@ struct SimpleGlyph
+                           hb_array_t points_ /* IN/OUT */,
+                           const HBUINT8 *end)
+   {
++    auto *points = points_.arrayZ;
+     unsigned count = points_.length;
+     for (unsigned int i = 0; i < count;)
+     {
+       if (unlikely (p + 1 > end)) return false;
+       uint8_t flag = *p++;
+-      points_.arrayZ[i++].flag = flag;
++      points[i++].flag = flag;
+       if (flag & FLAG_REPEAT)
+       {
+         if (unlikely (p + 1 > end)) return false;
+         unsigned int repeat_count = *p++;
+         unsigned stop = hb_min (i + repeat_count, count);
+         for (; i < stop; i++)
+-          points_.arrayZ[i].flag = flag;
++          points[i].flag = flag;
+       }
+     }
+     return true;
+@@ -160,10 +161,7 @@ struct SimpleGlyph
+       if (flag & short_flag)
+       {
+         if (unlikely (p + 1 > end)) return false;
+-        if (flag & same_flag)
+-          v += *p++;
+-        else
+-          v -= *p++;
++        v += (bool(flag & same_flag) * 2 - 1) * *p++;
+       }
+       else
+       {
+@@ -190,7 +188,7 @@ struct SimpleGlyph
+     unsigned int num_points = endPtsOfContours[num_contours - 1] + 1;
+ 
+     unsigned old_length = points.length;
+-    points.alloc (points.length + num_points + 4, true); // Allocate for phantom points, to avoid a possible copy
++    points.alloc (points.length + num_points + 4); // Allocate for phantom points, to avoid a possible copy
+     if (unlikely (!points.resize (points.length + num_points, false))) return false;
+     auto points_ = points.as_array ().sub_array (old_length);
+     if (!phantom_only)
+@@ -281,9 +279,9 @@ struct SimpleGlyph
+     unsigned num_points = all_points.length - 4;
+ 
+     hb_vector_t flags, x_coords, y_coords;
+-    if (unlikely (!flags.alloc (num_points, true))) return false;
+-    if (unlikely (!x_coords.alloc (2*num_points, true))) return false;
+-    if (unlikely (!y_coords.alloc (2*num_points, true))) return false;
++    if (unlikely (!flags.alloc_exact (num_points))) return false;
++    if (unlikely (!x_coords.alloc_exact (2*num_points))) return false;
++    if (unlikely (!y_coords.alloc_exact (2*num_points))) return false;
+ 
+     unsigned lastflag = 255, repeat = 0;
+     int prev_x = 0, prev_y = 0;
+diff --git a/src/java.desktop/share/native/libharfbuzz/OT/glyf/SubsetGlyph.hh b/src/java.desktop/share/native/libharfbuzz/OT/glyf/SubsetGlyph.hh
+index 9c04d890d..643b02264 100644
+--- a/src/java.desktop/share/native/libharfbuzz/OT/glyf/SubsetGlyph.hh
++++ b/src/java.desktop/share/native/libharfbuzz/OT/glyf/SubsetGlyph.hh
+@@ -53,23 +53,12 @@ struct SubsetGlyph
+       if (plan->new_gid_for_old_gid (_.get_gid(), &new_gid))
+         const_cast (_).set_gid (new_gid);
+     }
+-#ifndef HB_NO_VAR_COMPOSITES
+-    for (auto &_ : Glyph (dest_glyph).get_var_composite_iterator ())
+-    {
+-      hb_codepoint_t new_gid;
+-      if (plan->new_gid_for_old_gid (_.get_gid(), &new_gid))
+-        const_cast (_).set_gid (new_gid);
+-    }
+-#endif
+ 
+ #ifndef HB_NO_BEYOND_64K
+     auto it = Glyph (dest_glyph).get_composite_iterator ();
+     if (it)
+     {
+-      /* lower GID24 to GID16 in components if possible.
+-       *
+-       * TODO: VarComposite. Not as critical, since VarComposite supports
+-       * gid24 from the first version. */
++      /* lower GID24 to GID16 in components if possible. */
+       char *p = it ? (char *) &*it : nullptr;
+       char *q = p;
+       const char *end = dest_glyph.arrayZ + dest_glyph.length;
+diff --git a/src/java.desktop/share/native/libharfbuzz/OT/glyf/VarCompositeGlyph.hh b/src/java.desktop/share/native/libharfbuzz/OT/glyf/VarCompositeGlyph.hh
+deleted file mode 100644
+index 4f29f0aab..000000000
+--- a/src/java.desktop/share/native/libharfbuzz/OT/glyf/VarCompositeGlyph.hh
++++ /dev/null
+@@ -1,401 +0,0 @@
+-#ifndef OT_GLYF_VARCOMPOSITEGLYPH_HH
+-#define OT_GLYF_VARCOMPOSITEGLYPH_HH
+-
+-
+-#include "../../hb-open-type.hh"
+-#include "coord-setter.hh"
+-
+-
+-namespace OT {
+-namespace glyf_impl {
+-
+-
+-struct VarCompositeGlyphRecord
+-{
+-  protected:
+-  enum var_composite_glyph_flag_t
+-  {
+-    USE_MY_METRICS              = 0x0001,
+-    AXIS_INDICES_ARE_SHORT      = 0x0002,
+-    UNIFORM_SCALE               = 0x0004,
+-    HAVE_TRANSLATE_X            = 0x0008,
+-    HAVE_TRANSLATE_Y            = 0x0010,
+-    HAVE_ROTATION               = 0x0020,
+-    HAVE_SCALE_X                = 0x0040,
+-    HAVE_SCALE_Y                = 0x0080,
+-    HAVE_SKEW_X                 = 0x0100,
+-    HAVE_SKEW_Y                 = 0x0200,
+-    HAVE_TCENTER_X              = 0x0400,
+-    HAVE_TCENTER_Y              = 0x0800,
+-    GID_IS_24BIT                = 0x1000,
+-    AXES_HAVE_VARIATION         = 0x2000,
+-    RESET_UNSPECIFIED_AXES      = 0x4000,
+-  };
+-
+-  public:
+-
+-  unsigned int get_size () const
+-  {
+-    unsigned fl = flags;
+-    unsigned int size = min_size;
+-
+-    unsigned axis_width = (fl & AXIS_INDICES_ARE_SHORT) ? 4 : 3;
+-    size += numAxes * axis_width;
+-
+-    if (fl & GID_IS_24BIT)      size += 1;
+-
+-    // 2 bytes each for the following flags
+-    fl = fl & (HAVE_TRANSLATE_X | HAVE_TRANSLATE_Y |
+-               HAVE_ROTATION |
+-               HAVE_SCALE_X | HAVE_SCALE_Y |
+-               HAVE_SKEW_X | HAVE_SKEW_Y |
+-               HAVE_TCENTER_X | HAVE_TCENTER_Y);
+-    size += hb_popcount (fl) * 2;
+-
+-    return size;
+-  }
+-
+-  bool has_more () const { return true; }
+-
+-  bool is_use_my_metrics () const { return flags & USE_MY_METRICS; }
+-  bool is_reset_unspecified_axes () const { return flags & RESET_UNSPECIFIED_AXES; }
+-
+-  hb_codepoint_t get_gid () const
+-  {
+-    if (flags & GID_IS_24BIT)
+-      return * (const HBGlyphID24 *) &pad;
+-    else
+-      return * (const HBGlyphID16 *) &pad;
+-  }
+-
+-  void set_gid (hb_codepoint_t gid)
+-  {
+-    if (flags & GID_IS_24BIT)
+-      * (HBGlyphID24 *) &pad = gid;
+-    else
+-      * (HBGlyphID16 *) &pad = gid;
+-  }
+-
+-  unsigned get_numAxes () const
+-  {
+-    return numAxes;
+-  }
+-
+-  unsigned get_num_points () const
+-  {
+-    unsigned fl = flags;
+-    unsigned num = 0;
+-    if (fl & AXES_HAVE_VARIATION)                       num += numAxes;
+-
+-    /* Hopefully faster code, relying on the value of the flags. */
+-    fl = (((fl & (HAVE_TRANSLATE_Y | HAVE_SCALE_Y | HAVE_SKEW_Y | HAVE_TCENTER_Y)) >> 1) | fl) &
+-         (HAVE_TRANSLATE_X | HAVE_ROTATION | HAVE_SCALE_X | HAVE_SKEW_X | HAVE_TCENTER_X);
+-    num += hb_popcount (fl);
+-    return num;
+-
+-    /* Slower but more readable code. */
+-    if (fl & (HAVE_TRANSLATE_X | HAVE_TRANSLATE_Y))     num++;
+-    if (fl & HAVE_ROTATION)                             num++;
+-    if (fl & (HAVE_SCALE_X | HAVE_SCALE_Y))             num++;
+-    if (fl & (HAVE_SKEW_X | HAVE_SKEW_Y))               num++;
+-    if (fl & (HAVE_TCENTER_X | HAVE_TCENTER_Y))         num++;
+-    return num;
+-  }
+-
+-  void transform_points (hb_array_t record_points,
+-                         hb_array_t points) const
+-  {
+-    float matrix[4];
+-    contour_point_t trans;
+-
+-    get_transformation_from_points (record_points.arrayZ, matrix, trans);
+-
+-    auto arrayZ = points.arrayZ;
+-    unsigned count = points.length;
+-
+-    if (matrix[0] != 1.f || matrix[1] != 0.f ||
+-        matrix[2] != 0.f || matrix[3] != 1.f)
+-      for (unsigned i = 0; i < count; i++)
+-        arrayZ[i].transform (matrix);
+-
+-    if (trans.x != 0.f || trans.y != 0.f)
+-      for (unsigned i = 0; i < count; i++)
+-        arrayZ[i].translate (trans);
+-  }
+-
+-  static inline void transform (float (&matrix)[4], contour_point_t &trans,
+-                                float (other)[6])
+-  {
+-    // https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L268
+-    float xx1 = other[0];
+-    float xy1 = other[1];
+-    float yx1 = other[2];
+-    float yy1 = other[3];
+-    float dx1 = other[4];
+-    float dy1 = other[5];
+-    float xx2 = matrix[0];
+-    float xy2 = matrix[1];
+-    float yx2 = matrix[2];
+-    float yy2 = matrix[3];
+-    float dx2 = trans.x;
+-    float dy2 = trans.y;
+-
+-    matrix[0] = xx1*xx2 + xy1*yx2;
+-    matrix[1] = xx1*xy2 + xy1*yy2;
+-    matrix[2] = yx1*xx2 + yy1*yx2;
+-    matrix[3] = yx1*xy2 + yy1*yy2;
+-    trans.x = xx2*dx1 + yx2*dy1 + dx2;
+-    trans.y = xy2*dx1 + yy2*dy1 + dy2;
+-  }
+-
+-  static void translate (float (&matrix)[4], contour_point_t &trans,
+-                         float translateX, float translateY)
+-  {
+-    if (!translateX && !translateY)
+-      return;
+-
+-    trans.x += matrix[0] * translateX + matrix[2] * translateY;
+-    trans.y += matrix[1] * translateX + matrix[3] * translateY;
+-  }
+-
+-  static void scale (float (&matrix)[4], contour_point_t &trans,
+-                     float scaleX, float scaleY)
+-  {
+-    if (scaleX == 1.f && scaleY == 1.f)
+-      return;
+-
+-    matrix[0] *= scaleX;
+-    matrix[1] *= scaleX;
+-    matrix[2] *= scaleY;
+-    matrix[3] *= scaleY;
+-  }
+-
+-  static void rotate (float (&matrix)[4], contour_point_t &trans,
+-                      float rotation)
+-  {
+-    if (!rotation)
+-      return;
+-
+-    // https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L240
+-    rotation = rotation * HB_PI;
+-    float c;
+-    float s;
+-#ifdef HAVE_SINCOSF
+-    sincosf (rotation, &s, &c);
+-#else
+-    c = cosf (rotation);
+-    s = sinf (rotation);
+-#endif
+-    float other[6] = {c, s, -s, c, 0.f, 0.f};
+-    transform (matrix, trans, other);
+-  }
+-
+-  static void skew (float (&matrix)[4], contour_point_t &trans,
+-                    float skewX, float skewY)
+-  {
+-    if (!skewX && !skewY)
+-      return;
+-
+-    // https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L255
+-    skewX = skewX * HB_PI;
+-    skewY = skewY * HB_PI;
+-    float other[6] = {1.f,
+-                      skewY ? tanf (skewY) : 0.f,
+-                      skewX ? tanf (skewX) : 0.f,
+-                      1.f,
+-                      0.f, 0.f};
+-    transform (matrix, trans, other);
+-  }
+-
+-  bool get_points (contour_point_vector_t &points) const
+-  {
+-    unsigned num_points = get_num_points ();
+-
+-    points.alloc (points.length + num_points + 4); // For phantom points
+-    if (unlikely (!points.resize (points.length + num_points, false))) return false;
+-    contour_point_t *rec_points = points.arrayZ + (points.length - num_points);
+-    hb_memset (rec_points, 0, num_points * sizeof (rec_points[0]));
+-
+-    unsigned fl = flags;
+-
+-    unsigned num_axes = numAxes;
+-    unsigned axis_width = (fl & AXIS_INDICES_ARE_SHORT) ? 2 : 1;
+-    unsigned axes_size = num_axes * axis_width;
+-
+-    const F2DOT14 *q = (const F2DOT14 *) (axes_size +
+-                                          (fl & GID_IS_24BIT ? 3 : 2) +
+-                                          (const HBUINT8 *) &pad);
+-
+-    unsigned count = num_axes;
+-    if (fl & AXES_HAVE_VARIATION)
+-    {
+-      for (unsigned i = 0; i < count; i++)
+-        rec_points++->x = q++->to_int ();
+-    }
+-    else
+-      q += count;
+-
+-    const HBUINT16 *p = (const HBUINT16 *) q;
+-
+-    if (fl & (HAVE_TRANSLATE_X | HAVE_TRANSLATE_Y))
+-    {
+-      int translateX = (fl & HAVE_TRANSLATE_X) ? * (const FWORD *) p++ : 0;
+-      int translateY = (fl & HAVE_TRANSLATE_Y) ? * (const FWORD *) p++ : 0;
+-      rec_points->x = translateX;
+-      rec_points->y = translateY;
+-      rec_points++;
+-    }
+-    if (fl & HAVE_ROTATION)
+-    {
+-      int rotation = (fl & HAVE_ROTATION) ? ((const F4DOT12 *) p++)->to_int () : 0;
+-      rec_points->x = rotation;
+-      rec_points++;
+-    }
+-    if (fl & (HAVE_SCALE_X | HAVE_SCALE_Y))
+-    {
+-      int scaleX = (fl & HAVE_SCALE_X) ? ((const F6DOT10 *) p++)->to_int () : 1 << 10;
+-      int scaleY = (fl & HAVE_SCALE_Y) ? ((const F6DOT10 *) p++)->to_int () : 1 << 10;
+-      if ((fl & UNIFORM_SCALE) && !(fl & HAVE_SCALE_Y))
+-        scaleY = scaleX;
+-      rec_points->x = scaleX;
+-      rec_points->y = scaleY;
+-      rec_points++;
+-    }
+-    if (fl & (HAVE_SKEW_X | HAVE_SKEW_Y))
+-    {
+-      int skewX = (fl & HAVE_SKEW_X) ? ((const F4DOT12 *) p++)->to_int () : 0;
+-      int skewY = (fl & HAVE_SKEW_Y) ? ((const F4DOT12 *) p++)->to_int () : 0;
+-      rec_points->x = skewX;
+-      rec_points->y = skewY;
+-      rec_points++;
+-    }
+-    if (fl & (HAVE_TCENTER_X | HAVE_TCENTER_Y))
+-    {
+-      int tCenterX = (fl & HAVE_TCENTER_X) ? * (const FWORD *) p++ : 0;
+-      int tCenterY = (fl & HAVE_TCENTER_Y) ? * (const FWORD *) p++ : 0;
+-      rec_points->x = tCenterX;
+-      rec_points->y = tCenterY;
+-      rec_points++;
+-    }
+-
+-    return true;
+-  }
+-
+-  void get_transformation_from_points (const contour_point_t *rec_points,
+-                                       float (&matrix)[4], contour_point_t &trans) const
+-  {
+-    unsigned fl = flags;
+-
+-    if (fl & AXES_HAVE_VARIATION)
+-      rec_points += numAxes;
+-
+-    matrix[0] = matrix[3] = 1.f;
+-    matrix[1] = matrix[2] = 0.f;
+-    trans.init (0.f, 0.f);
+-
+-    float translateX = 0.f;
+-    float translateY = 0.f;
+-    float rotation = 0.f;
+-    float scaleX = 1.f;
+-    float scaleY = 1.f;
+-    float skewX = 0.f;
+-    float skewY = 0.f;
+-    float tCenterX = 0.f;
+-    float tCenterY = 0.f;
+-
+-    if (fl & (HAVE_TRANSLATE_X | HAVE_TRANSLATE_Y))
+-    {
+-      translateX = rec_points->x;
+-      translateY = rec_points->y;
+-      rec_points++;
+-    }
+-    if (fl & HAVE_ROTATION)
+-    {
+-      rotation = rec_points->x / (1 << 12);
+-      rec_points++;
+-    }
+-    if (fl & (HAVE_SCALE_X | HAVE_SCALE_Y))
+-    {
+-      scaleX = rec_points->x / (1 << 10);
+-      scaleY = rec_points->y / (1 << 10);
+-      rec_points++;
+-    }
+-    if (fl & (HAVE_SKEW_X | HAVE_SKEW_Y))
+-    {
+-      skewX = rec_points->x / (1 << 12);
+-      skewY = rec_points->y / (1 << 12);
+-      rec_points++;
+-    }
+-    if (fl & (HAVE_TCENTER_X | HAVE_TCENTER_Y))
+-    {
+-      tCenterX = rec_points->x;
+-      tCenterY = rec_points->y;
+-      rec_points++;
+-    }
+-
+-    translate (matrix, trans, translateX + tCenterX, translateY + tCenterY);
+-    rotate (matrix, trans, rotation);
+-    scale (matrix, trans, scaleX, scaleY);
+-    skew (matrix, trans, -skewX, skewY);
+-    translate (matrix, trans, -tCenterX, -tCenterY);
+-  }
+-
+-  void set_variations (coord_setter_t &setter,
+-                       hb_array_t rec_points) const
+-  {
+-    bool have_variations = flags & AXES_HAVE_VARIATION;
+-    unsigned axis_width = (flags & AXIS_INDICES_ARE_SHORT) ? 2 : 1;
+-    unsigned num_axes = numAxes;
+-
+-    const HBUINT8  *p = (const HBUINT8 *)  (((HBUINT8 *) &numAxes) + numAxes.static_size + (flags & GID_IS_24BIT ? 3 : 2));
+-    const HBUINT16 *q = (const HBUINT16 *) (((HBUINT8 *) &numAxes) + numAxes.static_size + (flags & GID_IS_24BIT ? 3 : 2));
+-
+-    const F2DOT14 *a = (const F2DOT14 *) ((HBUINT8 *) (axis_width == 1 ? (p + num_axes) : (HBUINT8 *) (q + num_axes)));
+-
+-    unsigned count = num_axes;
+-    for (unsigned i = 0; i < count; i++)
+-    {
+-      unsigned axis_index = axis_width == 1 ? (unsigned) *p++ : (unsigned) *q++;
+-
+-      signed v = have_variations ? rec_points.arrayZ[i].x : a++->to_int ();
+-
+-      v = hb_clamp (v, -(1<<14), (1<<14));
+-      setter[axis_index] = v;
+-    }
+-  }
+-
+-  protected:
+-  HBUINT16      flags;
+-  HBUINT8       numAxes;
+-  HBUINT16      pad;
+-  public:
+-  DEFINE_SIZE_MIN (5);
+-};
+-
+-using var_composite_iter_t = composite_iter_tmpl;
+-
+-struct VarCompositeGlyph
+-{
+-  const GlyphHeader &header;
+-  hb_bytes_t bytes;
+-  VarCompositeGlyph (const GlyphHeader &header_, hb_bytes_t bytes_) :
+-    header (header_), bytes (bytes_) {}
+-
+-  var_composite_iter_t iter () const
+-  { return var_composite_iter_t (bytes, &StructAfter (header)); }
+-
+-  const hb_bytes_t trim_padding () const
+-  {
+-    unsigned length = GlyphHeader::static_size;
+-    for (auto &comp : iter ())
+-      length += comp.get_size ();
+-    return bytes.sub_array (0, length);
+-  }
+-};
+-
+-
+-} /* namespace glyf_impl */
+-} /* namespace OT */
+-
+-
+-#endif /* OT_GLYF_VARCOMPOSITEGLYPH_HH */
+diff --git a/src/java.desktop/share/native/libharfbuzz/OT/glyf/coord-setter.hh b/src/java.desktop/share/native/libharfbuzz/OT/glyf/coord-setter.hh
+deleted file mode 100644
+index cf0592936..000000000
+--- a/src/java.desktop/share/native/libharfbuzz/OT/glyf/coord-setter.hh
++++ /dev/null
+@@ -1,36 +0,0 @@
+-#ifndef OT_GLYF_COORD_SETTER_HH
+-#define OT_GLYF_COORD_SETTER_HH
+-
+-
+-#include "../../hb.hh"
+-
+-
+-namespace OT {
+-namespace glyf_impl {
+-
+-
+-struct coord_setter_t
+-{
+-  coord_setter_t (hb_array_t coords) :
+-    coords (coords) {}
+-
+-  int& operator [] (unsigned idx)
+-  {
+-    if (unlikely (idx >= HB_GLYF_VAR_COMPOSITE_MAX_AXES))
+-      return Crap(int);
+-    if (coords.length < idx + 1)
+-      coords.resize (idx + 1);
+-    return coords[idx];
+-  }
+-
+-  hb_array_t get_coords ()
+-  { return coords.as_array (); }
+-
+-  hb_vector_t coords;
+-};
+-
+-
+-} /* namespace glyf_impl */
+-} /* namespace OT */
+-
+-#endif /* OT_GLYF_COORD_SETTER_HH */
+diff --git a/src/java.desktop/share/native/libharfbuzz/OT/glyf/glyf-helpers.hh b/src/java.desktop/share/native/libharfbuzz/OT/glyf/glyf-helpers.hh
+index 3462e4d1e..bd07e9413 100644
+--- a/src/java.desktop/share/native/libharfbuzz/OT/glyf/glyf-helpers.hh
++++ b/src/java.desktop/share/native/libharfbuzz/OT/glyf/glyf-helpers.hh
+@@ -38,7 +38,7 @@ _write_loca (IteratorIn&& it,
+ 
+     unsigned padded_size = *it++;
+     offset += padded_size;
+-    DEBUG_MSG (SUBSET, nullptr, "loca entry gid %u offset %u padded-size %u", gid, offset, padded_size);
++    DEBUG_MSG (SUBSET, nullptr, "loca entry gid %" PRIu32 " offset %u padded-size %u", gid, offset, padded_size);
+     value = offset >> right_shift;
+     *dest++ = value;
+ 
+diff --git a/src/java.desktop/share/native/libharfbuzz/OT/glyf/glyf.hh b/src/java.desktop/share/native/libharfbuzz/OT/glyf/glyf.hh
+index 175e1de30..681c3b9a0 100644
+--- a/src/java.desktop/share/native/libharfbuzz/OT/glyf/glyf.hh
++++ b/src/java.desktop/share/native/libharfbuzz/OT/glyf/glyf.hh
+@@ -94,7 +94,7 @@ struct glyf
+     }
+ 
+     hb_vector_t padded_offsets;
+-    if (unlikely (!padded_offsets.alloc (c->plan->new_to_old_gid_list.length, true)))
++    if (unlikely (!padded_offsets.alloc_exact (c->plan->new_to_old_gid_list.length)))
+       return_trace (false);
+ 
+     hb_vector_t glyphs;
+@@ -172,6 +172,9 @@ struct glyf_accelerator_t
+     glyf_table = nullptr;
+ #ifndef HB_NO_VAR
+     gvar = nullptr;
++#ifndef HB_NO_BEYOND_64K
++    GVAR = nullptr;
++#endif
+ #endif
+     hmtx = nullptr;
+ #ifndef HB_NO_VERTICAL
+@@ -187,6 +190,9 @@ struct glyf_accelerator_t
+     glyf_table = hb_sanitize_context_t ().reference_table (face);
+ #ifndef HB_NO_VAR
+     gvar = face->table.gvar;
++#ifndef HB_NO_BEYOND_64K
++    GVAR = face->table.GVAR;
++#endif
+ #endif
+     hmtx = face->table.hmtx;
+ #ifndef HB_NO_VERTICAL
+@@ -198,6 +204,13 @@ struct glyf_accelerator_t
+   }
+   ~glyf_accelerator_t ()
+   {
++    auto *scratch = cached_scratch.get_relaxed ();
++    if (scratch)
++    {
++      scratch->~hb_glyf_scratch_t ();
++      hb_free (scratch);
++    }
++
+     glyf_table.destroy ();
+   }
+ 
+@@ -205,18 +218,17 @@ struct glyf_accelerator_t
+ 
+   protected:
+   template
+-  bool get_points (hb_font_t *font, hb_codepoint_t gid, T consumer) const
++  bool get_points (hb_font_t *font, hb_codepoint_t gid, T consumer,
++                   hb_array_t coords,
++                   hb_glyf_scratch_t &scratch) const
+   {
+     if (gid >= num_glyphs) return false;
+ 
+-    /* Making this allocfree 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;
++    auto &all_points = scratch.all_points;
++    all_points.resize (0);
+ 
+     bool phantom_only = !consumer.is_consuming_contour_points ();
+-    if (unlikely (!glyph_for_gid (gid).get_points (font, *this, all_points, nullptr, nullptr, nullptr, true, true, phantom_only)))
++    if (unlikely (!glyph_for_gid (gid).get_points (font, *this, all_points, scratch, nullptr, nullptr, nullptr, true, true, phantom_only, coords)))
+       return false;
+ 
+     unsigned count = all_points.length;
+@@ -225,8 +237,61 @@ struct glyf_accelerator_t
+ 
+     if (consumer.is_consuming_contour_points ())
+     {
+-      for (auto &point : all_points.as_array ().sub_array (0, count))
+-        consumer.consume_point (point);
++      auto *points = all_points.arrayZ;
++
++      if (false)
++      {
++        /* Our path-builder was designed to work with this simple loop.
++         * But FreeType and CoreText do it differently, so we match those
++         * with the other, more complicated, code branch below. */
++        for (unsigned i = 0; i < count; i++)
++        {
++          consumer.consume_point (points[i]);
++          if (points[i].is_end_point)
++            consumer.contour_end ();
++        }
++      }
++      else
++      {
++        for (unsigned i = 0; i < count; i++)
++        {
++          // Start of a contour.
++          if (points[i].flag & glyf_impl::SimpleGlyph::FLAG_ON_CURVE)
++          {
++            // First point is on-curve. Draw the contour.
++            for (; i < count; i++)
++            {
++              consumer.consume_point (points[i]);
++              if (points[i].is_end_point)
++              {
++                consumer.contour_end ();
++                break;
++              }
++            }
++          }
++          else
++          {
++            unsigned start = i;
++
++            // Find end of the contour.
++            for (; i < count; i++)
++              if (points[i].is_end_point)
++                break;
++
++            unsigned end = i;
++
++            // Enough to start from the end. Our path-builder takes care of the rest.
++            if (likely (end < count)) // Can only fail in case of alloc failure *maybe*.
++              consumer.consume_point (points[end]);
++
++            for (i = start; i < end; i++)
++              consumer.consume_point (points[i]);
++
++            consumer.contour_end ();
++          }
++        }
++      }
++
+       consumer.points_end ();
+     }
+ 
+@@ -299,6 +364,7 @@ struct glyf_accelerator_t
+ 
+     HB_ALWAYS_INLINE
+     void consume_point (const contour_point_t &point) { bounds.add (point); }
++    void contour_end () {}
+     void points_end () { bounds.get_extents (font, extents, scaled); }
+ 
+     bool is_consuming_contour_points () { return extents; }
+@@ -314,7 +380,12 @@ struct glyf_accelerator_t
+ 
+     contour_point_t phantoms[glyf_impl::PHANTOM_COUNT];
+     if (font->num_coords)
+-      success = get_points (font, gid, points_aggregator_t (font, nullptr, phantoms, false));
++    {
++      hb_glyf_scratch_t scratch;
++      success = get_points (font, gid, points_aggregator_t (font, nullptr, phantoms, false),
++                            hb_array (font->coords, font->num_coords),
++                            scratch);
++    }
+ 
+     if (unlikely (!success))
+       return
+@@ -334,9 +405,11 @@ struct glyf_accelerator_t
+     if (unlikely (gid >= num_glyphs)) return false;
+ 
+     hb_glyph_extents_t extents;
+-
++    hb_glyf_scratch_t scratch;
+     contour_point_t phantoms[glyf_impl::PHANTOM_COUNT];
+-    if (unlikely (!get_points (font, gid, points_aggregator_t (font, &extents, phantoms, false))))
++    if (unlikely (!get_points (font, gid, points_aggregator_t (font, &extents, phantoms, false),
++                               hb_array (font->coords, font->num_coords),
++                               scratch)))
+       return false;
+ 
+     *lsb = is_vertical
+@@ -362,20 +435,16 @@ struct glyf_accelerator_t
+ 
+ #ifndef HB_NO_VAR
+     if (font->num_coords)
+-      return get_points (font, gid, points_aggregator_t (font, extents, nullptr, true));
++    {
++      hb_glyf_scratch_t scratch;
++      return get_points (font, gid, points_aggregator_t (font, extents, nullptr, true),
++                         hb_array (font->coords, font->num_coords),
++                         scratch);
++    }
+ #endif
+     return glyph_for_gid (gid).get_extents_without_var_scaled (font, *this, extents);
+   }
+ 
+-  bool paint_glyph (hb_font_t *font, hb_codepoint_t gid, hb_paint_funcs_t *funcs, void *data, hb_color_t foreground) const
+-  {
+-    funcs->push_clip_glyph (data, gid, font);
+-    funcs->color (data, true, foreground);
+-    funcs->pop_clip (data);
+-
+-    return true;
+-  }
+-
+   const glyf_impl::Glyph
+   glyph_for_gid (hb_codepoint_t gid, bool needs_padding_removal = false) const
+   {
+@@ -406,10 +475,52 @@ struct glyf_accelerator_t
+ 
+   bool
+   get_path (hb_font_t *font, hb_codepoint_t gid, hb_draw_session_t &draw_session) const
+-  { return get_points (font, gid, glyf_impl::path_builder_t (font, draw_session)); }
++  {
++    if (!has_data ()) return false;
++
++    hb_glyf_scratch_t *scratch;
++
++    // Borrow the cached strach buffer.
++    {
++      scratch = cached_scratch.get_acquire ();
++      if (!scratch || unlikely (!cached_scratch.cmpexch (scratch, nullptr)))
++      {
++        scratch = (hb_glyf_scratch_t *) hb_calloc (1, sizeof (hb_glyf_scratch_t));
++        if (unlikely (!scratch))
++          return true;
++      }
++    }
++
++    bool ret = get_points (font, gid, glyf_impl::path_builder_t (font, draw_session),
++                           hb_array (font->coords, font->num_coords),
++                           *scratch);
++
++    // Put it back.
++    if (!cached_scratch.cmpexch (nullptr, scratch))
++    {
++      scratch->~hb_glyf_scratch_t ();
++      hb_free (scratch);
++    }
++
++    return ret;
++  }
++
++  bool
++  get_path_at (hb_font_t *font, hb_codepoint_t gid, hb_draw_session_t &draw_session,
++               hb_array_t coords,
++               hb_glyf_scratch_t &scratch) const
++  {
++    if (!has_data ()) return false;
++    return get_points (font, gid, glyf_impl::path_builder_t (font, draw_session),
++                       coords,
++                       scratch);
++  }
+ 
+ #ifndef HB_NO_VAR
+   const gvar_accelerator_t *gvar;
++#ifndef HB_NO_BEYOND_64K
++  const GVAR_accelerator_t *GVAR;
++#endif
+ #endif
+   const hmtx_accelerator_t *hmtx;
+ #ifndef HB_NO_VERTICAL
+@@ -421,6 +532,7 @@ struct glyf_accelerator_t
+   unsigned int num_glyphs;
+   hb_blob_ptr_t loca_table;
+   hb_blob_ptr_t glyf_table;
++  hb_atomic_ptr_t cached_scratch;
+ };
+ 
+ 
+@@ -430,7 +542,7 @@ glyf::_populate_subset_glyphs (const hb_subset_plan_t   *plan,
+                                hb_vector_t& glyphs /* OUT */) const
+ {
+   OT::glyf_accelerator_t glyf (plan->source);
+-  if (!glyphs.alloc (plan->new_to_old_gid_list.length, true)) return false;
++  if (!glyphs.alloc_exact (plan->new_to_old_gid_list.length)) return false;
+ 
+   for (const auto &pair : plan->new_to_old_gid_list)
+   {
+diff --git a/src/java.desktop/share/native/libharfbuzz/OT/glyf/path-builder.hh b/src/java.desktop/share/native/libharfbuzz/OT/glyf/path-builder.hh
+index d56ea3e45..f5495f923 100644
+--- a/src/java.desktop/share/native/libharfbuzz/OT/glyf/path-builder.hh
++++ b/src/java.desktop/share/native/libharfbuzz/OT/glyf/path-builder.hh
+@@ -42,7 +42,7 @@ struct path_builder_t
+   {
+     bool is_on_curve = point.flag & glyf_impl::SimpleGlyph::FLAG_ON_CURVE;
+ #ifdef HB_NO_CUBIC_GLYF
+-    bool is_cubic = false;
++    constexpr bool is_cubic = false;
+ #else
+     bool is_cubic = !is_on_curve && (point.flag & glyf_impl::SimpleGlyph::FLAG_CUBIC);
+ #endif
+@@ -124,58 +124,60 @@ struct path_builder_t
+       }
+     }
+ 
+-    if (unlikely (point.is_end_point))
+-    {
+-      if (first_offcurve && last_offcurve)
+-      {
+-        optional_point_t mid = last_offcurve.mid (first_offcurve2 ?
+-                                                  first_offcurve2 :
+-                                                  first_offcurve);
+-        if (last_offcurve2)
+-          draw_session->cubic_to (last_offcurve2.x, last_offcurve2.y,
+-                                  last_offcurve.x, last_offcurve.y,
+-                                  mid.x, mid.y);
+-        else
+-          draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
+-                                     mid.x, mid.y);
+-        last_offcurve = optional_point_t ();
+-      }
+-      /* now check the rest */
++  }
+ 
+-      if (first_offcurve && first_oncurve)
+-      {
+-        if (first_offcurve2)
+-          draw_session->cubic_to (first_offcurve2.x, first_offcurve2.y,
+-                                  first_offcurve.x, first_offcurve.y,
+-                                  first_oncurve.x, first_oncurve.y);
+-        else
+-          draw_session->quadratic_to (first_offcurve.x, first_offcurve.y,
+-                                     first_oncurve.x, first_oncurve.y);
+-      }
+-      else if (last_offcurve && first_oncurve)
+-      {
+-        if (last_offcurve2)
+-          draw_session->cubic_to (last_offcurve2.x, last_offcurve2.y,
+-                                  last_offcurve.x, last_offcurve.y,
+-                                  first_oncurve.x, first_oncurve.y);
+-        else
+-          draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
+-                                     first_oncurve.x, first_oncurve.y);
+-      }
+-      else if (first_oncurve)
+-        draw_session->line_to (first_oncurve.x, first_oncurve.y);
+-      else if (first_offcurve)
+-      {
+-        float x = first_offcurve.x, y = first_offcurve.y;
+-        draw_session->move_to (x, y);
+-        draw_session->quadratic_to (x, y, x, y);
+-      }
++  void contour_end ()
++  {
++    if (first_offcurve && last_offcurve)
++    {
++      optional_point_t mid = last_offcurve.mid (first_offcurve2 ?
++                                                first_offcurve2 :
++                                                first_offcurve);
++      if (last_offcurve2)
++        draw_session->cubic_to (last_offcurve2.x, last_offcurve2.y,
++                                last_offcurve.x, last_offcurve.y,
++                                mid.x, mid.y);
++      else
++        draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
++                                   mid.x, mid.y);
++      last_offcurve = optional_point_t ();
++    }
++    /* now check the rest */
+ 
+-      /* Getting ready for the next contour */
+-      first_oncurve = first_offcurve = last_offcurve = last_offcurve2 = optional_point_t ();
+-      draw_session->close_path ();
++    if (first_offcurve && first_oncurve)
++    {
++      if (first_offcurve2)
++        draw_session->cubic_to (first_offcurve2.x, first_offcurve2.y,
++                                first_offcurve.x, first_offcurve.y,
++                                first_oncurve.x, first_oncurve.y);
++      else
++        draw_session->quadratic_to (first_offcurve.x, first_offcurve.y,
++                                   first_oncurve.x, first_oncurve.y);
+     }
++    else if (last_offcurve && first_oncurve)
++    {
++      if (last_offcurve2)
++        draw_session->cubic_to (last_offcurve2.x, last_offcurve2.y,
++                                last_offcurve.x, last_offcurve.y,
++                                first_oncurve.x, first_oncurve.y);
++      else
++        draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
++                                   first_oncurve.x, first_oncurve.y);
++    }
++    else if (first_oncurve)
++      draw_session->line_to (first_oncurve.x, first_oncurve.y);
++    else if (first_offcurve)
++    {
++      float x = first_offcurve.x, y = first_offcurve.y;
++      draw_session->move_to (x, y);
++      draw_session->quadratic_to (x, y, x, y);
++    }
++
++    /* Getting ready for the next contour */
++    first_oncurve = first_offcurve = last_offcurve = last_offcurve2 = optional_point_t ();
++    draw_session->close_path ();
+   }
++
+   void points_end () {}
+ 
+   bool is_consuming_contour_points () { return true; }
+diff --git a/src/java.desktop/share/native/libharfbuzz/OT/name/name.hh b/src/java.desktop/share/native/libharfbuzz/OT/name/name.hh
+index f14c2da2d..b440379af 100644
+--- a/src/java.desktop/share/native/libharfbuzz/OT/name/name.hh
++++ b/src/java.desktop/share/native/libharfbuzz/OT/name/name.hh
+@@ -242,7 +242,9 @@ struct NameRecord
+   bool sanitize (hb_sanitize_context_t *c, const void *base) const
+   {
+     TRACE_SANITIZE (this);
+-    return_trace (c->check_struct (this) && offset.sanitize (c, base, length));
++    return_trace (c->check_struct (this) &&
++                  hb_barrier () &&
++                  offset.sanitize (c, base, length));
+   }
+ 
+   HBUINT16      platformID;     /* Platform ID. */
+@@ -465,6 +467,7 @@ struct name
+   {
+     TRACE_SANITIZE (this);
+     return_trace (c->check_struct (this) &&
++                  hb_barrier () &&
+                   likely (format == 0 || format == 1) &&
+                   c->check_array (nameRecordZ.arrayZ, count) &&
+                   c->check_range (this, stringOffset) &&
+@@ -482,7 +485,7 @@ struct name
+       const hb_array_t all_names (this->table->nameRecordZ.arrayZ,
+                                                     this->table->count);
+ 
+-      this->names.alloc (all_names.length, true);
++      this->names.alloc_exact (all_names.length);
+ 
+       for (unsigned int i = 0; i < all_names.length; i++)
+       {
+diff --git a/src/java.desktop/share/native/libharfbuzz/UPDATING.txt b/src/java.desktop/share/native/libharfbuzz/UPDATING.txt
+index 3f72983a4..d536fad05 100644
+--- a/src/java.desktop/share/native/libharfbuzz/UPDATING.txt
++++ b/src/java.desktop/share/native/libharfbuzz/UPDATING.txt
+@@ -53,9 +53,9 @@ STEP 2: BUILD CHANGES INCREMENTALLY
+ 
+ STEP 3: COMPILER WARNINGS AND SETTING FLAGS
+ -------------------------------------------
+-- Update make parameters in Awt2DLibraries.gmk
++- Update make parameters in make/modules/java.desktop/lib/ClientLibraries.gmk
+   Since we don't use configure we need to manually specify the options
+-  we need in the Harfbuzz section of Awt2DLibraries.gmk.
++  we need in the Harfbuzz section of ClientLibraries.gmk.
+   As well as adding new options, we may need to clean up obsolete options.
+   Note there may be platform variations in the flags.
+ 
+diff --git a/src/java.desktop/share/native/libharfbuzz/graph/classdef-graph.hh b/src/java.desktop/share/native/libharfbuzz/graph/classdef-graph.hh
+index c1432883f..da6378820 100644
+--- a/src/java.desktop/share/native/libharfbuzz/graph/classdef-graph.hh
++++ b/src/java.desktop/share/native/libharfbuzz/graph/classdef-graph.hh
+@@ -39,6 +39,7 @@ struct ClassDefFormat1 : public OT::ClassDefFormat1_3
+     int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
+     constexpr unsigned min_size = OT::ClassDefFormat1_3::min_size;
+     if (vertex_len < min_size) return false;
++    hb_barrier ();
+     return vertex_len >= min_size + classValue.get_size () - classValue.len.get_size ();
+   }
+ };
+@@ -50,6 +51,7 @@ struct ClassDefFormat2 : public OT::ClassDefFormat2_4
+     int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
+     constexpr unsigned min_size = OT::ClassDefFormat2_4::min_size;
+     if (vertex_len < min_size) return false;
++    hb_barrier ();
+     return vertex_len >= min_size + rangeRecord.get_size () - rangeRecord.len.get_size ();
+   }
+ };
+@@ -114,6 +116,7 @@ struct ClassDef : public OT::ClassDef
+   {
+     int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
+     if (vertex_len < OT::ClassDef::min_size) return false;
++    hb_barrier ();
+     switch (u.format)
+     {
+     case 1: return ((ClassDefFormat1*)this)->sanitize (vertex);
+@@ -131,20 +134,23 @@ struct ClassDef : public OT::ClassDef
+ 
+ struct class_def_size_estimator_t
+ {
++  // TODO(garretrieger): update to support beyond64k coverage/classdef tables.
++  constexpr static unsigned class_def_format1_base_size = 6;
++  constexpr static unsigned class_def_format2_base_size = 4;
++  constexpr static unsigned coverage_base_size = 4;
++  constexpr static unsigned bytes_per_range = 6;
++  constexpr static unsigned bytes_per_glyph = 2;
++
+   template
+   class_def_size_estimator_t (It glyph_and_class)
+-      : gids_consecutive (true), num_ranges_per_class (), glyphs_per_class ()
++      : num_ranges_per_class (), glyphs_per_class ()
+   {
+-    unsigned last_gid = (unsigned) -1;
++    reset();
+     for (auto p : + glyph_and_class)
+     {
+       unsigned gid = p.first;
+       unsigned klass = p.second;
+ 
+-      if (last_gid != (unsigned) -1 && gid != last_gid + 1)
+-        gids_consecutive = false;
+-      last_gid = gid;
+-
+       hb_set_t* glyphs;
+       if (glyphs_per_class.has (klass, &glyphs) && glyphs) {
+         glyphs->add (gid);
+@@ -174,28 +180,54 @@ struct class_def_size_estimator_t
+     }
+   }
+ 
+-  // Incremental increase in the Coverage and ClassDef table size
+-  // (worst case) if all glyphs associated with 'klass' were added.
+-  unsigned incremental_coverage_size (unsigned klass) const
++  void reset() {
++    class_def_1_size = class_def_format1_base_size;
++    class_def_2_size = class_def_format2_base_size;
++    included_glyphs.clear();
++    included_classes.clear();
++  }
++
++  // Compute the size of coverage for all glyphs added via 'add_class_def_size'.
++  unsigned coverage_size () const
+   {
+-    // Coverage takes 2 bytes per glyph worst case,
+-    return 2 * glyphs_per_class.get (klass).get_population ();
++    unsigned format1_size = coverage_base_size + bytes_per_glyph * included_glyphs.get_population();
++    unsigned format2_size = coverage_base_size + bytes_per_range * num_glyph_ranges();
++    return hb_min(format1_size, format2_size);
+   }
+ 
+-  // Incremental increase in the Coverage and ClassDef table size
+-  // (worst case) if all glyphs associated with 'klass' were added.
+-  unsigned incremental_class_def_size (unsigned klass) const
++  // Compute the new size of the ClassDef table if all glyphs associated with 'klass' were added.
++  unsigned add_class_def_size (unsigned klass)
+   {
+-    // ClassDef takes 6 bytes per range
+-    unsigned class_def_2_size = 6 * num_ranges_per_class.get (klass);
+-    if (gids_consecutive)
+-    {
+-      // ClassDef1 takes 2 bytes per glyph, but only can be used
+-      // when gids are consecutive.
+-      return hb_min (2 * glyphs_per_class.get (klass).get_population (), class_def_2_size);
++    if (!included_classes.has(klass)) {
++      hb_set_t* glyphs = nullptr;
++      if (glyphs_per_class.has(klass, &glyphs)) {
++        included_glyphs.union_(*glyphs);
++      }
++
++      class_def_1_size = class_def_format1_base_size;
++      if (!included_glyphs.is_empty()) {
++        unsigned min_glyph = included_glyphs.get_min();
++        unsigned max_glyph = included_glyphs.get_max();
++        class_def_1_size += bytes_per_glyph * (max_glyph - min_glyph + 1);
++      }
++
++      class_def_2_size += bytes_per_range * num_ranges_per_class.get (klass);
++
++      included_classes.add(klass);
+     }
+ 
+-    return class_def_2_size;
++    return hb_min (class_def_1_size, class_def_2_size);
++  }
++
++  unsigned num_glyph_ranges() const {
++    hb_codepoint_t start = HB_SET_VALUE_INVALID;
++    hb_codepoint_t end = HB_SET_VALUE_INVALID;
++
++    unsigned count = 0;
++    while (included_glyphs.next_range (&start, &end)) {
++        count++;
++    }
++    return count;
+   }
+ 
+   bool in_error ()
+@@ -211,9 +243,12 @@ struct class_def_size_estimator_t
+   }
+ 
+  private:
+-  bool gids_consecutive;
+   hb_hashmap_t num_ranges_per_class;
+   hb_hashmap_t glyphs_per_class;
++  hb_set_t included_classes;
++  hb_set_t included_glyphs;
++  unsigned class_def_1_size;
++  unsigned class_def_2_size;
+ };
+ 
+ 
+diff --git a/src/java.desktop/share/native/libharfbuzz/graph/coverage-graph.hh b/src/java.desktop/share/native/libharfbuzz/graph/coverage-graph.hh
+index 4f44e076d..61ca063e3 100644
+--- a/src/java.desktop/share/native/libharfbuzz/graph/coverage-graph.hh
++++ b/src/java.desktop/share/native/libharfbuzz/graph/coverage-graph.hh
+@@ -39,6 +39,7 @@ struct CoverageFormat1 : public OT::Layout::Common::CoverageFormat1_3::min_size;
+     if (vertex_len < min_size) return false;
++    hb_barrier ();
+     return vertex_len >= min_size + glyphArray.get_size () - glyphArray.len.get_size ();
+   }
+ };
+@@ -50,6 +51,7 @@ struct CoverageFormat2 : public OT::Layout::Common::CoverageFormat2_4::min_size;
+     if (vertex_len < min_size) return false;
++    hb_barrier ();
+     return vertex_len >= min_size + rangeRecord.get_size () - rangeRecord.len.get_size ();
+   }
+ };
+@@ -138,6 +140,7 @@ struct Coverage : public OT::Layout::Common::Coverage
+   {
+     int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
+     if (vertex_len < OT::Layout::Common::Coverage::min_size) return false;
++    hb_barrier ();
+     switch (u.format)
+     {
+     case 1: return ((CoverageFormat1*)this)->sanitize (vertex);
+diff --git a/src/java.desktop/share/native/libharfbuzz/graph/graph.hh b/src/java.desktop/share/native/libharfbuzz/graph/graph.hh
+index 4a1f7ebf5..ed1026f58 100644
+--- a/src/java.desktop/share/native/libharfbuzz/graph/graph.hh
++++ b/src/java.desktop/share/native/libharfbuzz/graph/graph.hh
+@@ -195,6 +195,15 @@ struct graph_t
+       return incoming_edges_;
+     }
+ 
++    unsigned incoming_edges_from_parent (unsigned parent_index) const {
++      if (single_parent != (unsigned) -1) {
++        return single_parent == parent_index ? 1 : 0;
++      }
++
++      unsigned* count;
++      return  parents.has(parent_index, &count) ? *count : 0;
++    }
++
+     void reset_parents ()
+     {
+       incoming_edges_ = 0;
+@@ -334,6 +343,16 @@ struct graph_t
+       return true;
+     }
+ 
++    bool give_max_priority ()
++    {
++      bool result = false;
++      while (!has_max_priority()) {
++        result = true;
++        priority++;
++      }
++      return result;
++    }
++
+     bool has_max_priority () const {
+       return priority >= 3;
+     }
+@@ -349,7 +368,7 @@ struct graph_t
+       // it's parent where possible.
+ 
+       int64_t modified_distance =
+-          hb_min (hb_max(distance + distance_modifier (), 0), 0x7FFFFFFFFFF);
++          hb_clamp (distance + distance_modifier (), (int64_t) 0, 0x7FFFFFFFFFF);
+       if (has_max_priority ()) {
+         modified_distance = 0;
+       }
+@@ -567,6 +586,7 @@ struct graph_t
+     update_distances ();
+ 
+     hb_priority_queue_t queue;
++    queue.alloc (vertices_.length);
+     hb_vector_t &sorted_graph = vertices_scratch_;
+     if (unlikely (!check_success (sorted_graph.resize (vertices_.length)))) return;
+     hb_vector_t id_map;
+@@ -1022,6 +1042,11 @@ struct graph_t
+    * 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.
++   *
++   * Returns the index of the newly created duplicate.
++   *
++   * If the child_idx only has incoming edges from parent_idx, this
++   * will do nothing and return the original child_idx.
+    */
+   unsigned duplicate_if_shared (unsigned parent_idx, unsigned child_idx)
+   {
+@@ -1035,18 +1060,20 @@ struct graph_t
+    * 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.
++   *
++   * Returns the index of the newly created duplicate.
++   *
++   * If the child_idx only has incoming edges from parent_idx,
++   * duplication isn't possible and this will return -1.
+    */
+   unsigned 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++;
+-    }
++    const auto& child = vertices_[child_idx];
++    unsigned links_to_child = child.incoming_edges_from_parent(parent_idx);
+ 
+-    if (vertices_[child_idx].incoming_edges () <= links_to_child)
++    if (child.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.
+@@ -1059,7 +1086,7 @@ struct graph_t
+                parent_idx, child_idx);
+ 
+     unsigned clone_idx = duplicate (child_idx);
+-    if (clone_idx == (unsigned) -1) return false;
++    if (clone_idx == (unsigned) -1) return -1;
+     // duplicate shifts the root node idx, so if parent_idx was root update it.
+     if (parent_idx == clone_idx) parent_idx++;
+ 
+@@ -1075,6 +1102,62 @@ struct graph_t
+     return clone_idx;
+   }
+ 
++  /*
++   * Creates a copy of child and re-assigns the links from
++   * parents to the clone. The copy is a shallow copy, objects
++   * linked from child are not duplicated.
++   *
++   * Returns the index of the newly created duplicate.
++   *
++   * If the child_idx only has incoming edges from parents,
++   * duplication isn't possible or duplication fails and this will
++   * return -1.
++   */
++  unsigned duplicate (const hb_set_t* parents, unsigned child_idx)
++  {
++    if (parents->is_empty()) {
++      return -1;
++    }
++
++    update_parents ();
++
++    const auto& child = vertices_[child_idx];
++    unsigned links_to_child = 0;
++    unsigned last_parent = parents->get_max();
++    unsigned first_parent = parents->get_min();
++    for (unsigned parent_idx : *parents) {
++      links_to_child += child.incoming_edges_from_parent(parent_idx);
++    }
++
++    if (child.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 %u, ..., %u => %u", first_parent, last_parent, child_idx);
++      return -1;
++    }
++
++    DEBUG_MSG (SUBSET_REPACK, nullptr, "  Duplicating %u, ..., %u => %u", first_parent, last_parent, child_idx);
++
++    unsigned clone_idx = duplicate (child_idx);
++    if (clone_idx == (unsigned) -1) return false;
++
++    for (unsigned parent_idx : *parents) {
++      // 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 clone_idx;
++  }
++
+ 
+   /*
+    * Adds a new node to the graph, not connected to anything.
+@@ -1370,6 +1453,7 @@ struct graph_t
+     vertices_.tail ().distance = 0;
+ 
+     hb_priority_queue_t queue;
++    queue.alloc (count);
+     queue.insert (0, vertices_.length - 1);
+ 
+     hb_vector_t visited;
+diff --git a/src/java.desktop/share/native/libharfbuzz/graph/gsubgpos-graph.hh b/src/java.desktop/share/native/libharfbuzz/graph/gsubgpos-graph.hh
+index a5f9223e6..7ad2ba430 100644
+--- a/src/java.desktop/share/native/libharfbuzz/graph/gsubgpos-graph.hh
++++ b/src/java.desktop/share/native/libharfbuzz/graph/gsubgpos-graph.hh
+@@ -76,6 +76,7 @@ struct Lookup : public OT::Lookup
+   {
+     int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
+     if (vertex_len < OT::Lookup::min_size) return false;
++    hb_barrier ();
+     return vertex_len >= this->get_size ();
+   }
+ 
+@@ -351,6 +352,7 @@ struct LookupList : public OT::LookupList
+   {
+     int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
+     if (vertex_len < OT::LookupList::min_size) return false;
++    hb_barrier ();
+     return vertex_len >= OT::LookupList::item_size * this->len;
+   }
+ };
+@@ -364,6 +366,7 @@ struct GSTAR : public OT::GSUBGPOS
+     GSTAR* gstar = (GSTAR*) r.obj.head;
+     if (!gstar || !gstar->sanitize (r))
+       return nullptr;
++    hb_barrier ();
+ 
+     return gstar;
+   }
+@@ -383,6 +386,7 @@ struct GSTAR : public OT::GSUBGPOS
+   {
+     int64_t len = vertex.obj.tail - vertex.obj.head;
+     if (len < OT::GSUBGPOS::min_size) return false;
++    hb_barrier ();
+     return len >= get_size ();
+   }
+ 
+diff --git a/src/java.desktop/share/native/libharfbuzz/graph/markbasepos-graph.hh b/src/java.desktop/share/native/libharfbuzz/graph/markbasepos-graph.hh
+index ae5ebd0d1..fb4166128 100644
+--- a/src/java.desktop/share/native/libharfbuzz/graph/markbasepos-graph.hh
++++ b/src/java.desktop/share/native/libharfbuzz/graph/markbasepos-graph.hh
+@@ -40,6 +40,7 @@ struct AnchorMatrix : public OT::Layout::GPOS_impl::AnchorMatrix
+   {
+     int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
+     if (vertex_len < AnchorMatrix::min_size) return false;
++    hb_barrier ();
+ 
+     return vertex_len >= AnchorMatrix::min_size +
+         OT::Offset16::static_size * class_count * this->rows;
+@@ -128,6 +129,7 @@ struct MarkArray : public OT::Layout::GPOS_impl::MarkArray
+     int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
+     unsigned min_size = MarkArray::min_size;
+     if (vertex_len < min_size) return false;
++    hb_barrier ();
+ 
+     return vertex_len >= get_size ();
+   }
+@@ -495,6 +497,7 @@ struct MarkBasePos : public OT::Layout::GPOS_impl::MarkBasePos
+   {
+     int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
+     if (vertex_len < u.format.get_size ()) return false;
++    hb_barrier ();
+ 
+     switch (u.format) {
+     case 1:
+diff --git a/src/java.desktop/share/native/libharfbuzz/graph/pairpos-graph.hh b/src/java.desktop/share/native/libharfbuzz/graph/pairpos-graph.hh
+index ad158cc9e..fd46861de 100644
+--- a/src/java.desktop/share/native/libharfbuzz/graph/pairpos-graph.hh
++++ b/src/java.desktop/share/native/libharfbuzz/graph/pairpos-graph.hh
+@@ -42,6 +42,7 @@ struct PairPosFormat1 : public OT::Layout::GPOS_impl::PairPosFormat1_3::min_size;
+     if (vertex_len < min_size) return false;
++    hb_barrier ();
+ 
+     return vertex_len >=
+         min_size + pairSet.get_size () - pairSet.len.get_size();
+@@ -198,6 +199,7 @@ struct PairPosFormat2 : public OT::Layout::GPOS_impl::PairPosFormat2_4::min_size;
+     if (vertex_len < min_size) return false;
++    hb_barrier ();
+ 
+     const unsigned class1_count = class1Count;
+     return vertex_len >=
+@@ -245,8 +247,8 @@ struct PairPosFormat2 : public OT::Layout::GPOS_impl::PairPosFormat2_4check_struct (this) &&
++                          hb_barrier () &&
+                           version == 0 &&
+                           c->check_range (this, anchorData) &&
+                           lookupTable.sanitize (c, this, &(this+anchorData))));
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-bsln-table.hh b/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-bsln-table.hh
+index 24d53e224..b14540f3a 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-bsln-table.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-bsln-table.hh
+@@ -123,6 +123,7 @@ struct bsln
+     TRACE_SANITIZE (this);
+     if (unlikely (!(c->check_struct (this) && defaultBaseline < 32)))
+       return_trace (false);
++    hb_barrier ();
+ 
+     switch (format)
+     {
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-common.hh b/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-common.hh
+index b2d1b7b67..673c7fbe9 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-common.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-common.hh
+@@ -30,6 +30,10 @@
+ #include "hb-aat-layout.hh"
+ #include "hb-aat-map.hh"
+ #include "hb-open-type.hh"
++#include "hb-cache.hh"
++#include "hb-bit-set.hh"
++#include "hb-bit-page.hh"
++
+ 
+ namespace OT {
+ struct GDEF;
+@@ -39,15 +43,18 @@ namespace AAT {
+ 
+ using namespace OT;
+ 
+-
+ struct ankr;
+ 
++using hb_aat_class_cache_t = hb_cache_t<15, 8, 7>;
++static_assert (sizeof (hb_aat_class_cache_t) == 256, "");
++
+ struct hb_aat_apply_context_t :
+        hb_dispatch_context_t
+ {
+   const char *get_name () { return "APPLY"; }
+-  template 
+-  return_t dispatch (const T &obj) { return obj.apply (this); }
++  template 
++  return_t dispatch (const T &obj, Ts&&... ds)
++  { return obj.apply (this, std::forward (ds)...); }
+   static return_t default_return_value () { return false; }
+   bool stop_sublookup_iteration (return_t r) const { return r; }
+ 
+@@ -59,6 +66,12 @@ struct hb_aat_apply_context_t :
+   const ankr *ankr_table;
+   const OT::GDEF *gdef_table;
+   const hb_sorted_vector_t *range_flags = nullptr;
++  bool using_buffer_glyph_set = false;
++  hb_bit_set_t buffer_glyph_set;
++  const hb_bit_set_t *left_set = nullptr;
++  const hb_bit_set_t *right_set = nullptr;
++  const hb_bit_set_t *machine_glyph_set = nullptr;
++  hb_aat_class_cache_t *machine_class_cache = nullptr;
+   hb_mask_t subtable_flags = 0;
+ 
+   /* Unused. For debug tracing only. */
+@@ -74,6 +87,25 @@ struct hb_aat_apply_context_t :
+   HB_INTERNAL void set_ankr_table (const AAT::ankr *ankr_table_);
+ 
+   void set_lookup_index (unsigned int i) { lookup_index = i; }
++
++  void setup_buffer_glyph_set ()
++  {
++    using_buffer_glyph_set = buffer->len >= 4;
++
++    if (using_buffer_glyph_set)
++      buffer->collect_codepoints (buffer_glyph_set);
++  }
++  bool buffer_intersects_machine () const
++  {
++    if (using_buffer_glyph_set)
++      return buffer_glyph_set.intersects (*machine_glyph_set);
++
++    // Faster for shorter buffers.
++    for (unsigned i = 0; i < buffer->len; i++)
++      if (machine_glyph_set->has (buffer->info[i].codepoint))
++        return true;
++    return false;
++  }
+ };
+ 
+ 
+@@ -81,6 +113,8 @@ struct hb_aat_apply_context_t :
+  * Lookup Table
+  */
+ 
++enum { DELETED_GLYPH = 0xFFFF };
++
+ template  struct Lookup;
+ 
+ template 
+@@ -95,6 +129,19 @@ struct LookupFormat0
+     return &arrayZ[glyph_id];
+   }
+ 
++  template 
++  void collect_glyphs (set_t &glyphs, unsigned num_glyphs) const
++  {
++    glyphs.add_range (0, num_glyphs - 1);
++  }
++  template 
++  void collect_glyphs_filtered (set_t &glyphs, unsigned num_glyphs, const filter_t &filter) const
++  {
++    for (unsigned i = 0; i < num_glyphs; i++)
++      if (filter (arrayZ[i]))
++        glyphs.add (i);
++  }
++
+   bool sanitize (hb_sanitize_context_t *c) const
+   {
+     TRACE_SANITIZE (this);
+@@ -123,6 +170,19 @@ struct LookupSegmentSingle
+   int cmp (hb_codepoint_t g) const
+   { return g < first ? -1 : g <= last ? 0 : +1 ; }
+ 
++  template 
++  void collect_glyphs (set_t &glyphs) const
++  {
++    if (first == DELETED_GLYPH) return;
++    glyphs.add_range (first, last);
++  }
++  template 
++  void collect_glyphs_filtered (set_t &glyphs, const filter_t &filter) const
++  {
++    if (!filter (value)) return;
++    glyphs.add_range (first, last);
++  }
++
+   bool sanitize (hb_sanitize_context_t *c) const
+   {
+     TRACE_SANITIZE (this);
+@@ -153,6 +213,21 @@ struct LookupFormat2
+     return v ? &v->value : nullptr;
+   }
+ 
++  template 
++  void collect_glyphs (set_t &glyphs) const
++  {
++    unsigned count = segments.get_length ();
++    for (unsigned int i = 0; i < count; i++)
++      segments[i].collect_glyphs (glyphs);
++  }
++  template 
++  void collect_glyphs_filtered (set_t &glyphs, const filter_t &filter) const
++  {
++    unsigned count = segments.get_length ();
++    for (unsigned int i = 0; i < count; i++)
++      segments[i].collect_glyphs_filtered (glyphs, filter);
++  }
++
+   bool sanitize (hb_sanitize_context_t *c) const
+   {
+     TRACE_SANITIZE (this);
+@@ -184,6 +259,21 @@ struct LookupSegmentArray
+     return first <= glyph_id && glyph_id <= last ? &(base+valuesZ)[glyph_id - first] : nullptr;
+   }
+ 
++  template 
++  void collect_glyphs (set_t &glyphs) const
++  {
++    if (first == DELETED_GLYPH) return;
++    glyphs.add_range (first, last);
++  }
++  template 
++  void collect_glyphs_filtered (set_t &glyphs, const void *base, const filter_t &filter) const
++  {
++    const auto &values = base+valuesZ;
++    for (hb_codepoint_t i = first; i <= last; i++)
++      if (filter (values[i - first]))
++        glyphs.add (i);
++  }
++
+   int cmp (hb_codepoint_t g) const
+   { return g < first ? -1 : g <= last ? 0 : +1; }
+ 
+@@ -191,6 +281,7 @@ struct LookupSegmentArray
+   {
+     TRACE_SANITIZE (this);
+     return_trace (c->check_struct (this) &&
++                  hb_barrier () &&
+                   first <= last &&
+                   valuesZ.sanitize (c, base, last - first + 1));
+   }
+@@ -199,6 +290,7 @@ struct LookupSegmentArray
+   {
+     TRACE_SANITIZE (this);
+     return_trace (c->check_struct (this) &&
++                  hb_barrier () &&
+                   first <= last &&
+                   valuesZ.sanitize (c, base, last - first + 1, std::forward (ds)...));
+   }
+@@ -224,6 +316,21 @@ struct LookupFormat4
+     return v ? v->get_value (glyph_id, this) : nullptr;
+   }
+ 
++  template 
++  void collect_glyphs (set_t &glyphs) const
++  {
++    unsigned count = segments.get_length ();
++    for (unsigned i = 0; i < count; i++)
++      segments[i].collect_glyphs (glyphs);
++  }
++  template 
++  void collect_glyphs_filtered (set_t &glyphs, const filter_t &filter) const
++  {
++    unsigned count = segments.get_length ();
++    for (unsigned i = 0; i < count; i++)
++      segments[i].collect_glyphs_filtered (glyphs, this, filter);
++  }
++
+   bool sanitize (hb_sanitize_context_t *c) const
+   {
+     TRACE_SANITIZE (this);
+@@ -252,6 +359,19 @@ struct LookupSingle
+ 
+   int cmp (hb_codepoint_t g) const { return glyph.cmp (g); }
+ 
++  template 
++  void collect_glyphs (set_t &glyphs) const
++  {
++    if (glyph == DELETED_GLYPH) return;
++    glyphs.add (glyph);
++  }
++  template 
++  void collect_glyphs_filtered (set_t &glyphs, const filter_t &filter) const
++  {
++    if (!filter (value)) return;
++    glyphs.add (glyph);
++  }
++
+   bool sanitize (hb_sanitize_context_t *c) const
+   {
+     TRACE_SANITIZE (this);
+@@ -281,6 +401,21 @@ struct LookupFormat6
+     return v ? &v->value : nullptr;
+   }
+ 
++  template 
++  void collect_glyphs (set_t &glyphs) const
++  {
++    unsigned count = entries.get_length ();
++    for (unsigned i = 0; i < count; i++)
++      entries[i].collect_glyphs (glyphs);
++  }
++  template 
++  void collect_glyphs_filtered (set_t &glyphs, const filter_t &filter) const
++  {
++    unsigned count = entries.get_length ();
++    for (unsigned i = 0; i < count; i++)
++      entries[i].collect_glyphs_filtered (glyphs, filter);
++  }
++
+   bool sanitize (hb_sanitize_context_t *c) const
+   {
+     TRACE_SANITIZE (this);
+@@ -312,6 +447,24 @@ struct LookupFormat8
+            &valueArrayZ[glyph_id - firstGlyph] : nullptr;
+   }
+ 
++  template 
++  void collect_glyphs (set_t &glyphs) const
++  {
++    if (unlikely (!glyphCount)) return;
++    if (firstGlyph == DELETED_GLYPH) return;
++    glyphs.add_range (firstGlyph, firstGlyph + glyphCount - 1);
++  }
++  template 
++  void collect_glyphs_filtered (set_t &glyphs, const filter_t &filter) const
++  {
++    if (unlikely (!glyphCount)) return;
++    if (firstGlyph == DELETED_GLYPH) return;
++    const T *p = valueArrayZ.arrayZ;
++    for (unsigned i = 0; i < glyphCount; i++)
++      if (filter (p[i]))
++        glyphs.add (firstGlyph + i);
++  }
++
+   bool sanitize (hb_sanitize_context_t *c) const
+   {
+     TRACE_SANITIZE (this);
+@@ -356,10 +509,19 @@ struct LookupFormat10
+     return v;
+   }
+ 
++  template 
++  void collect_glyphs (set_t &glyphs) const
++  {
++    if (unlikely (!glyphCount)) return;
++    if (firstGlyph == DELETED_GLYPH) return;
++    glyphs.add_range (firstGlyph, firstGlyph + glyphCount - 1);
++  }
++
+   bool sanitize (hb_sanitize_context_t *c) const
+   {
+     TRACE_SANITIZE (this);
+     return_trace (c->check_struct (this) &&
++                  hb_barrier () &&
+                   valueSize <= 4 &&
+                   valueArrayZ.sanitize (c, glyphCount * valueSize));
+   }
+@@ -383,11 +545,11 @@ struct Lookup
+   const T* get_value (hb_codepoint_t glyph_id, unsigned int num_glyphs) const
+   {
+     switch (u.format) {
+-    case 0: return u.format0.get_value (glyph_id, num_glyphs);
+-    case 2: return u.format2.get_value (glyph_id);
+-    case 4: return u.format4.get_value (glyph_id);
+-    case 6: return u.format6.get_value (glyph_id);
+-    case 8: return u.format8.get_value (glyph_id);
++    case 0: hb_barrier (); return u.format0.get_value (glyph_id, num_glyphs);
++    case 2: hb_barrier (); return u.format2.get_value (glyph_id);
++    case 4: hb_barrier (); return u.format4.get_value (glyph_id);
++    case 6: hb_barrier (); return u.format6.get_value (glyph_id);
++    case 8: hb_barrier (); return u.format8.get_value (glyph_id);
+     default:return nullptr;
+     }
+   }
+@@ -396,13 +558,39 @@ struct Lookup
+   {
+     switch (u.format) {
+       /* Format 10 cannot return a pointer. */
+-      case 10: return u.format10.get_value_or_null (glyph_id);
++      case 10: hb_barrier (); return u.format10.get_value_or_null (glyph_id);
+       default:
+       const T *v = get_value (glyph_id, num_glyphs);
+       return v ? *v : Null (T);
+     }
+   }
+ 
++  template 
++  void collect_glyphs (set_t &glyphs, unsigned int num_glyphs) const
++  {
++    switch (u.format) {
++    case 0: hb_barrier (); u.format0.collect_glyphs (glyphs, num_glyphs); return;
++    case 2: hb_barrier (); u.format2.collect_glyphs (glyphs); return;
++    case 4: hb_barrier (); u.format4.collect_glyphs (glyphs); return;
++    case 6: hb_barrier (); u.format6.collect_glyphs (glyphs); return;
++    case 8: hb_barrier (); u.format8.collect_glyphs (glyphs); return;
++    case 10: hb_barrier (); u.format10.collect_glyphs (glyphs); return;
++    default:return;
++    }
++  }
++  template 
++  void collect_glyphs_filtered (set_t &glyphs, unsigned num_glyphs, const filter_t &filter) const
++  {
++    switch (u.format) {
++    case 0: hb_barrier (); u.format0.collect_glyphs_filtered (glyphs, num_glyphs, filter); return;
++    case 2: hb_barrier (); u.format2.collect_glyphs_filtered (glyphs, filter); return;
++    case 4: hb_barrier (); u.format4.collect_glyphs_filtered (glyphs, filter); return;
++    case 6: hb_barrier (); u.format6.collect_glyphs_filtered (glyphs, filter); return;
++    case 8: hb_barrier (); u.format8.collect_glyphs_filtered (glyphs, filter); return;
++    default:return;
++    }
++  }
++
+   typename T::type get_class (hb_codepoint_t glyph_id,
+                               unsigned int num_glyphs,
+                               unsigned int outOfRange) const
+@@ -415,13 +603,14 @@ struct Lookup
+   {
+     TRACE_SANITIZE (this);
+     if (!u.format.sanitize (c)) return_trace (false);
++    hb_barrier ();
+     switch (u.format) {
+-    case 0: return_trace (u.format0.sanitize (c));
+-    case 2: return_trace (u.format2.sanitize (c));
+-    case 4: return_trace (u.format4.sanitize (c));
+-    case 6: return_trace (u.format6.sanitize (c));
+-    case 8: return_trace (u.format8.sanitize (c));
+-    case 10: return_trace (u.format10.sanitize (c));
++    case 0: hb_barrier (); return_trace (u.format0.sanitize (c));
++    case 2: hb_barrier (); return_trace (u.format2.sanitize (c));
++    case 4: hb_barrier (); return_trace (u.format4.sanitize (c));
++    case 6: hb_barrier (); return_trace (u.format6.sanitize (c));
++    case 8: hb_barrier (); return_trace (u.format8.sanitize (c));
++    case 10: hb_barrier (); return_trace (u.format10.sanitize (c));
+     default:return_trace (true);
+     }
+   }
+@@ -429,12 +618,13 @@ struct Lookup
+   {
+     TRACE_SANITIZE (this);
+     if (!u.format.sanitize (c)) return_trace (false);
++    hb_barrier ();
+     switch (u.format) {
+-    case 0: return_trace (u.format0.sanitize (c, base));
+-    case 2: return_trace (u.format2.sanitize (c, base));
+-    case 4: return_trace (u.format4.sanitize (c, base));
+-    case 6: return_trace (u.format6.sanitize (c, base));
+-    case 8: return_trace (u.format8.sanitize (c, base));
++    case 0: hb_barrier (); return_trace (u.format0.sanitize (c, base));
++    case 2: hb_barrier (); return_trace (u.format2.sanitize (c, base));
++    case 4: hb_barrier (); return_trace (u.format4.sanitize (c, base));
++    case 6: hb_barrier (); return_trace (u.format6.sanitize (c, base));
++    case 8: hb_barrier (); return_trace (u.format8.sanitize (c, base));
+     case 10: return_trace (false); /* We don't support format10 here currently. */
+     default:return_trace (true);
+     }
+@@ -455,8 +645,6 @@ struct Lookup
+ };
+ DECLARE_NULL_NAMESPACE_BYTES_TEMPLATE1 (AAT, Lookup, 2);
+ 
+-enum { DELETED_GLYPH = 0xFFFF };
+-
+ /*
+  * (Extended) State Table
+  */
+@@ -464,7 +652,7 @@ enum { DELETED_GLYPH = 0xFFFF };
+ template 
+ struct Entry
+ {
+-  // This does seem like it's ever called.
++  // This doesn't seem like it's ever called.
+   bool sanitize (hb_sanitize_context_t *c) const
+   {
+     TRACE_SANITIZE (this);
+@@ -507,6 +695,14 @@ struct Entry
+   DEFINE_SIZE_STATIC (4);
+ };
+ 
++enum Class
++{
++  CLASS_END_OF_TEXT = 0,
++  CLASS_OUT_OF_BOUNDS = 1,
++  CLASS_DELETED_GLYPH = 2,
++  CLASS_END_OF_LINE = 3,
++};
++
+ template 
+ struct StateTable
+ {
+@@ -519,21 +715,53 @@ struct StateTable
+     STATE_START_OF_TEXT = 0,
+     STATE_START_OF_LINE = 1,
+   };
+-  enum Class
++
++  template 
++  void collect_glyphs (set_t &glyphs, unsigned num_glyphs) const
+   {
+-    CLASS_END_OF_TEXT = 0,
+-    CLASS_OUT_OF_BOUNDS = 1,
+-    CLASS_DELETED_GLYPH = 2,
+-    CLASS_END_OF_LINE = 3,
+-  };
++    (this+classTable).collect_glyphs (glyphs, num_glyphs);
++  }
++  template 
++  void collect_initial_glyphs (set_t &glyphs, unsigned num_glyphs, const table_t &table) const
++  {
++    unsigned num_classes = nClasses;
++
++    if (unlikely (num_classes > hb_bit_page_t::BITS))
++    {
++      (this+classTable).collect_glyphs (glyphs, num_glyphs);
++      return;
++    }
++
++    // Collect all classes going out from the start state.
++    hb_bit_page_t filter;
++
++    for (unsigned i = 0; i < num_classes; i++)
++    {
++      const auto &entry = get_entry (STATE_START_OF_TEXT, i);
++      if (new_state (entry.newState) == STATE_START_OF_TEXT &&
++          !table.is_action_initiable (entry) && !table.is_actionable (entry))
++        continue;
++
++      filter.add (i);
++    }
++
++    // And glyphs in those classes.
++    (this+classTable).collect_glyphs_filtered (glyphs, num_glyphs, filter);
++  }
+ 
+   int new_state (unsigned int newState) const
+   { return Types::extended ? newState : ((int) newState - (int) stateArrayTable) / (int) nClasses; }
+ 
+-  unsigned int get_class (hb_codepoint_t glyph_id, unsigned int num_glyphs) const
++  unsigned int get_class (hb_codepoint_t glyph_id,
++                          unsigned int num_glyphs,
++                          hb_aat_class_cache_t *cache = nullptr) const
+   {
++    unsigned klass;
++    if (cache && cache->get (glyph_id, &klass)) return klass;
+     if (unlikely (glyph_id == DELETED_GLYPH)) return CLASS_DELETED_GLYPH;
+-    return (this+classTable).get_class (glyph_id, num_glyphs, 1);
++    klass = (this+classTable).get_class (glyph_id, num_glyphs, CLASS_OUT_OF_BOUNDS);
++    if (cache) cache->set (glyph_id, klass);
++    return klass;
+   }
+ 
+   const Entry *get_entries () const
+@@ -541,13 +769,14 @@ struct StateTable
+ 
+   const Entry &get_entry (int state, unsigned int klass) const
+   {
+-    if (unlikely (klass >= nClasses))
+-      klass = StateTable::CLASS_OUT_OF_BOUNDS;
++    unsigned n_classes = nClasses;
++    if (unlikely (klass >= n_classes))
++      klass = CLASS_OUT_OF_BOUNDS;
+ 
+     const HBUSHORT *states = (this+stateArrayTable).arrayZ;
+     const Entry *entries = (this+entryTable).arrayZ;
+ 
+-    unsigned int entry = states[state * nClasses + klass];
++    unsigned int entry = states[state * n_classes + klass];
+     DEBUG_MSG (APPLY, nullptr, "e%u", entry);
+ 
+     return entries[entry];
+@@ -558,6 +787,7 @@ struct StateTable
+   {
+     TRACE_SANITIZE (this);
+     if (unlikely (!(c->check_struct (this) &&
++                    hb_barrier () &&
+                     nClasses >= 4 /* Ensure pre-defined classes fit.  */ &&
+                     classTable.sanitize (c, this)))) return_trace (false);
+ 
+@@ -684,6 +914,22 @@ struct ClassTable
+   {
+     return get_class (glyph_id, outOfRange);
+   }
++
++  template 
++  void collect_glyphs (set_t &glyphs, unsigned num_glyphs) const
++  {
++    for (unsigned i = 0; i < classArray.len; i++)
++      if (classArray.arrayZ[i] != CLASS_OUT_OF_BOUNDS)
++        glyphs.add (firstGlyph + i);
++  }
++  template 
++  void collect_glyphs_filtered (set_t &glyphs, unsigned num_glyphs, const filter_t &filter) const
++  {
++    for (unsigned i = 0; i < classArray.len; i++)
++      if (filter (classArray.arrayZ[i]))
++        glyphs.add (firstGlyph + i);
++  }
++
+   bool sanitize (hb_sanitize_context_t *c) const
+   {
+     TRACE_SANITIZE (this);
+@@ -697,6 +943,38 @@ struct ClassTable
+   DEFINE_SIZE_ARRAY (4, classArray);
+ };
+ 
++struct SubtableGlyphCoverage
++{
++  bool sanitize (hb_sanitize_context_t *c, unsigned subtable_count) const
++  {
++    TRACE_SANITIZE (this);
++
++    if (unlikely (!c->check_array (&subtableOffsets, subtable_count)))
++      return_trace (false);
++
++    unsigned bytes = (c->get_num_glyphs () + CHAR_BIT - 1) / CHAR_BIT;
++    for (unsigned i = 0; i < subtable_count; i++)
++    {
++      uint32_t offset = (uint32_t) subtableOffsets[i];
++      if (offset == 0 || offset == 0xFFFFFFFF)
++        continue;
++      if (unlikely (!subtableOffsets[i].sanitize (c, this, bytes)))
++        return_trace (false);
++    }
++
++    return_trace (true);
++  }
++  protected:
++  UnsizedArrayOf>> subtableOffsets;
++                                            /* Array of offsets from the beginning of the
++                                             * subtable glyph coverage table to the glyph
++                                             * coverage bitfield for a given subtable; there
++                                             * is one offset for each subtable in the chain */
++  /* UnsizedArrayOf coverageBitfields; *//* The individual coverage bitfields. */
++  public:
++  DEFINE_SIZE_ARRAY (0, subtableOffsets);
++};
++
+ struct ObsoleteTypes
+ {
+   static constexpr bool extended = false;
+@@ -766,22 +1044,22 @@ struct ExtendedTypes
+   }
+ };
+ 
+-template 
++template 
+ struct StateTableDriver
+ {
+   using StateTableT = StateTable;
+   using EntryT = Entry;
+ 
+   StateTableDriver (const StateTableT &machine_,
+-                    hb_buffer_t *buffer_,
+                     hb_face_t *face_) :
+               machine (machine_),
+-              buffer (buffer_),
+               num_glyphs (face_->get_num_glyphs ()) {}
+ 
+   template 
+   void drive (context_t *c, hb_aat_apply_context_t *ac)
+   {
++    hb_buffer_t *buffer = ac->buffer;
++
+     if (!c->in_place)
+       buffer->clear_output ();
+ 
+@@ -816,9 +1094,9 @@ struct StateTableDriver
+         }
+       }
+ 
+-      unsigned int klass = buffer->idx < buffer->len ?
+-                           machine.get_class (buffer->cur().codepoint, num_glyphs) :
+-                           (unsigned) StateTableT::CLASS_END_OF_TEXT;
++      unsigned int klass = likely (buffer->idx < buffer->len) ?
++                           machine.get_class (buffer->cur().codepoint, num_glyphs, ac->machine_class_cache) :
++                           (unsigned) CLASS_END_OF_TEXT;
+       DEBUG_MSG (APPLY, nullptr, "c%u at %u", klass, buffer->idx);
+       const EntryT &entry = machine.get_entry (state, klass);
+       const int next_state = machine.new_state (entry.newState);
+@@ -851,44 +1129,39 @@ struct StateTableDriver
+        *
+        *   https://github.com/harfbuzz/harfbuzz/issues/2860
+        */
+-
+-      const auto is_safe_to_break_extra = [&]()
+-      {
+-          /* 2c. */
+-          const auto wouldbe_entry = machine.get_entry(StateTableT::STATE_START_OF_TEXT, klass);
+-
+-          /* 2c'. */
+-          if (c->is_actionable (this, wouldbe_entry))
+-              return false;
+-
+-          /* 2c". */
+-          return next_state == machine.new_state(wouldbe_entry.newState)
+-              && (entry.flags & context_t::DontAdvance) == (wouldbe_entry.flags & context_t::DontAdvance);
+-      };
+-
+-      const auto is_safe_to_break = [&]()
+-      {
++      const EntryT *wouldbe_entry;
++      bool is_safe_to_break =
++      (
+           /* 1. */
+-          if (c->is_actionable (this, entry))
+-              return false;
++          !c->table->is_actionable (entry) &&
+ 
+           /* 2. */
+           // This one is meh, I know...
+-          const auto ok =
++          (
+                  state == StateTableT::STATE_START_OF_TEXT
+-              || ((entry.flags & context_t::DontAdvance) && next_state == StateTableT::STATE_START_OF_TEXT)
+-              || is_safe_to_break_extra();
+-          if (!ok)
+-              return false;
++              || ((entry.flags & Flags::DontAdvance) && next_state == StateTableT::STATE_START_OF_TEXT)
++              || (
++                    /* 2c. */
++                    wouldbe_entry = &machine.get_entry(StateTableT::STATE_START_OF_TEXT, klass)
++                    ,
++                    /* 2c'. */
++                    !c->table->is_actionable (*wouldbe_entry) &&
++                    /* 2c". */
++                    (
++                      next_state == machine.new_state(wouldbe_entry->newState) &&
++                      (entry.flags & Flags::DontAdvance) == (wouldbe_entry->flags & Flags::DontAdvance)
++                    )
++                 )
++          ) &&
+ 
+           /* 3. */
+-          return !c->is_actionable (this, machine.get_entry (state, StateTableT::CLASS_END_OF_TEXT));
+-      };
++          !c->table->is_actionable (machine.get_entry (state, CLASS_END_OF_TEXT))
++      );
+ 
+-      if (!is_safe_to_break () && buffer->backtrack_len () && buffer->idx < buffer->len)
++      if (!is_safe_to_break && buffer->backtrack_len () && buffer->idx < buffer->len)
+         buffer->unsafe_to_break_from_outbuffer (buffer->backtrack_len () - 1, buffer->idx + 1);
+ 
+-      c->transition (this, entry);
++      c->transition (buffer, this, entry);
+ 
+       state = next_state;
+       DEBUG_MSG (APPLY, nullptr, "s%d", state);
+@@ -896,7 +1169,7 @@ struct StateTableDriver
+       if (buffer->idx == buffer->len || unlikely (!buffer->successful))
+         break;
+ 
+-      if (!(entry.flags & context_t::DontAdvance) || buffer->max_ops-- <= 0)
++      if (!(entry.flags & Flags::DontAdvance) || buffer->max_ops-- <= 0)
+         (void) buffer->next_glyph ();
+     }
+ 
+@@ -906,7 +1179,6 @@ struct StateTableDriver
+ 
+   public:
+   const StateTableT &machine;
+-  hb_buffer_t *buffer;
+   unsigned int num_glyphs;
+ };
+ 
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-feat-table.hh b/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-feat-table.hh
+index 04260a946..7b68a932c 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-feat-table.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-feat-table.hh
+@@ -138,6 +138,7 @@ struct FeatureName
+   {
+     TRACE_SANITIZE (this);
+     return_trace (likely (c->check_struct (this) &&
++                          hb_barrier () &&
+                           (base+settingTableZ).sanitize (c, nSettings)));
+   }
+ 
+@@ -200,6 +201,7 @@ struct feat
+   {
+     TRACE_SANITIZE (this);
+     return_trace (likely (c->check_struct (this) &&
++                          hb_barrier () &&
+                           version.major == 1 &&
+                           namesZ.sanitize (c, featureNameCount, this)));
+   }
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-just-table.hh b/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-just-table.hh
+index 0588310b5..193d14d94 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-just-table.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-just-table.hh
+@@ -185,15 +185,16 @@ struct ActionSubrecord
+     TRACE_SANITIZE (this);
+     if (unlikely (!c->check_struct (this)))
+       return_trace (false);
++    hb_barrier ();
+ 
+     switch (u.header.actionType)
+     {
+-    case 0:  return_trace (u.decompositionAction.sanitize (c));
+-    case 1:  return_trace (u.unconditionalAddGlyphAction.sanitize (c));
+-    case 2:  return_trace (u.conditionalAddGlyphAction.sanitize (c));
+-    // case 3: return_trace (u.stretchGlyphAction.sanitize (c));
+-    case 4:  return_trace (u.decompositionAction.sanitize (c));
+-    case 5:  return_trace (u.decompositionAction.sanitize (c));
++    case 0: hb_barrier ();  return_trace (u.decompositionAction.sanitize (c));
++    case 1: hb_barrier ();  return_trace (u.unconditionalAddGlyphAction.sanitize (c));
++    case 2: hb_barrier ();  return_trace (u.conditionalAddGlyphAction.sanitize (c));
++    // case 3: hb_barrier (); return_trace (u.stretchGlyphAction.sanitize (c));
++    case 4: hb_barrier ();  return_trace (u.decompositionAction.sanitize (c));
++    case 5: hb_barrier ();  return_trace (u.decompositionAction.sanitize (c));
+     default: return_trace (true);
+     }
+   }
+@@ -220,6 +221,7 @@ struct PostcompensationActionChain
+     TRACE_SANITIZE (this);
+     if (unlikely (!c->check_struct (this)))
+       return_trace (false);
++    hb_barrier ();
+ 
+     unsigned int offset = min_size;
+     for (unsigned int i = 0; i < count; i++)
+@@ -389,6 +391,7 @@ struct just
+     TRACE_SANITIZE (this);
+ 
+     return_trace (likely (c->check_struct (this) &&
++                          hb_barrier () &&
+                           version.major == 1 &&
+                           horizData.sanitize (c, this, this) &&
+                           vertData.sanitize (c, this, this)));
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-kerx-table.hh b/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-kerx-table.hh
+index 2bc7b03ce..a091b0566 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-kerx-table.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-kerx-table.hh
+@@ -30,6 +30,7 @@
+ 
+ #include "hb-kern.hh"
+ #include "hb-aat-layout-ankr-table.hh"
++#include "hb-set-digest.hh"
+ 
+ /*
+  * kerx -- Extended Kerning
+@@ -54,6 +55,7 @@ kerxTupleKern (int value,
+   unsigned int offset = value;
+   const FWORD *pv = &StructAtOffset (base, offset);
+   if (unlikely (!c->sanitizer.check_array (pv, tupleCount))) return 0;
++  hb_barrier ();
+   return *pv;
+ }
+ 
+@@ -81,7 +83,7 @@ struct KernPair
+     return_trace (c->check_struct (this));
+   }
+ 
+-  protected:
++  public:
+   HBGlyphID16   left;
+   HBGlyphID16   right;
+   FWORD         value;
+@@ -105,10 +107,10 @@ struct KerxSubTableFormat0
+     TRACE_APPLY (this);
+ 
+     if (!c->plan->requested_kerning)
+-      return false;
++      return_trace (false);
+ 
+     if (header.coverage & header.Backwards)
+-      return false;
++      return_trace (false);
+ 
+     accelerator_t accel (*this, c);
+     hb_kern_machine_t machine (accel, header.coverage & header.CrossStream);
+@@ -117,6 +119,16 @@ struct KerxSubTableFormat0
+     return_trace (true);
+   }
+ 
++  template 
++  void collect_glyphs (set_t &left_set, set_t &right_set, unsigned num_glyphs) const
++  {
++    for (const KernPair& pair : pairs)
++    {
++      left_set.add (pair.left);
++      right_set.add (pair.right);
++    }
++  }
++
+   struct accelerator_t
+   {
+     const KerxSubTableFormat0 &table;
+@@ -127,7 +139,10 @@ struct KerxSubTableFormat0
+                      table (table_), c (c_) {}
+ 
+     int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
+-    { return table.get_kerning (left, right, c); }
++    {
++      if (!(*c->left_set)[left] || !(*c->right_set)[right]) return 0;
++      return table.get_kerning (left, right, c);
++    }
+   };
+ 
+ 
+@@ -192,6 +207,9 @@ struct Format1Entry
+ 
+   typedef void EntryData;
+ 
++  static bool initiateAction (const Entry &entry)
++  { return entry.flags & Push; }
++
+   static bool performAction (const Entry &entry)
+   { return entry.flags & Offset; }
+ 
+@@ -208,13 +226,23 @@ struct KerxSubTableFormat1
+   typedef Format1Entry Format1EntryT;
+   typedef typename Format1EntryT::EntryData EntryData;
+ 
++  enum Flags
++  {
++    DontAdvance = Format1EntryT::DontAdvance,
++  };
++
++  bool is_action_initiable (const Entry &entry) const
++  {
++    return Format1EntryT::initiateAction (entry);
++  }
++  bool is_actionable (const Entry &entry) const
++  {
++    return Format1EntryT::performAction (entry);
++  }
++
+   struct driver_context_t
+   {
+     static constexpr bool in_place = true;
+-    enum
+-    {
+-      DontAdvance       = Format1EntryT::DontAdvance,
+-    };
+ 
+     driver_context_t (const KerxSubTableFormat1 *table_,
+                       hb_aat_apply_context_t *c_) :
+@@ -227,13 +255,10 @@ struct KerxSubTableFormat1
+         depth (0),
+         crossStream (table->header.coverage & table->header.CrossStream) {}
+ 
+-    bool is_actionable (StateTableDriver *driver HB_UNUSED,
+-                        const Entry &entry)
+-    { return Format1EntryT::performAction (entry); }
+-    void transition (StateTableDriver *driver,
++    void transition (hb_buffer_t *buffer,
++                     StateTableDriver *driver,
+                      const Entry &entry)
+     {
+-      hb_buffer_t *buffer = driver->buffer;
+       unsigned int flags = entry.flags;
+ 
+       if (flags & Format1EntryT::Reset)
+@@ -259,6 +284,7 @@ struct KerxSubTableFormat1
+           depth = 0;
+           return;
+         }
++        hb_barrier ();
+ 
+         hb_mask_t kern_mask = c->plan->kern_mask;
+ 
+@@ -330,9 +356,10 @@ struct KerxSubTableFormat1
+       }
+     }
+ 
+-    private:
++    public:
+     hb_aat_apply_context_t *c;
+     const KerxSubTableFormat1 *table;
++    private:
+     const UnsizedArrayOf &kernAction;
+     unsigned int stack[8];
+     unsigned int depth;
+@@ -349,7 +376,8 @@ struct KerxSubTableFormat1
+ 
+     driver_context_t dc (this, c);
+ 
+-    StateTableDriver driver (machine, c->buffer, c->font->face);
++    StateTableDriver driver (machine, c->font->face);
++
+     driver.drive (&dc, c);
+ 
+     return_trace (true);
+@@ -363,12 +391,21 @@ struct KerxSubTableFormat1
+                           machine.sanitize (c)));
+   }
+ 
++  template 
++  void collect_glyphs (set_t &left_set, set_t &right_set, unsigned num_glyphs) const
++  {
++    set_t set;
++    machine.collect_glyphs (set, num_glyphs);
++    left_set.union_ (set);
++    right_set.union_ (set);
++  }
++
+   protected:
+   KernSubTableHeader                            header;
+   StateTable                  machine;
+   NNOffsetTo, HBUINT>     kernAction;
+   public:
+-  DEFINE_SIZE_STATIC (KernSubTableHeader::static_size + 5 * sizeof (HBUINT));
++  DEFINE_SIZE_STATIC (KernSubTableHeader::static_size + (StateTable::static_size + HBUINT::static_size));
+ };
+ 
+ template 
+@@ -389,6 +426,7 @@ struct KerxSubTableFormat2
+     kern_idx = Types::offsetToIndex (kern_idx, this, arrayZ.arrayZ);
+     const FWORD *v = &arrayZ[kern_idx];
+     if (unlikely (!v->sanitize (&c->sanitizer))) return 0;
++    hb_barrier ();
+ 
+     return kerxTupleKern (*v, header.tuple_count (), this, c);
+   }
+@@ -398,10 +436,10 @@ struct KerxSubTableFormat2
+     TRACE_APPLY (this);
+ 
+     if (!c->plan->requested_kerning)
+-      return false;
++      return_trace (false);
+ 
+     if (header.coverage & header.Backwards)
+-      return false;
++      return_trace (false);
+ 
+     accelerator_t accel (*this, c);
+     hb_kern_machine_t machine (accel, header.coverage & header.CrossStream);
+@@ -410,6 +448,13 @@ struct KerxSubTableFormat2
+     return_trace (true);
+   }
+ 
++  template 
++  void collect_glyphs (set_t &left_set, set_t &right_set, unsigned num_glyphs) const
++  {
++    (this+leftClassTable).collect_glyphs (left_set, num_glyphs);
++    (this+rightClassTable).collect_glyphs (right_set, num_glyphs);
++  }
++
+   struct accelerator_t
+   {
+     const KerxSubTableFormat2 &table;
+@@ -420,7 +465,10 @@ struct KerxSubTableFormat2
+                      table (table_), c (c_) {}
+ 
+     int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
+-    { return table.get_kerning (left, right, c); }
++    {
++      if (!(*c->left_set)[left] || !(*c->right_set)[right]) return 0;
++      return table.get_kerning (left, right, c);
++    }
+   };
+ 
+   bool sanitize (hb_sanitize_context_t *c) const
+@@ -429,6 +477,7 @@ struct KerxSubTableFormat2
+     return_trace (likely (c->check_struct (this) &&
+                           leftClassTable.sanitize (c, this) &&
+                           rightClassTable.sanitize (c, this) &&
++                          hb_barrier () &&
+                           c->check_range (this, array)));
+   }
+ 
+@@ -461,17 +510,26 @@ struct KerxSubTableFormat4
+     DEFINE_SIZE_STATIC (2);
+   };
+ 
+-  struct driver_context_t
++  enum Flags
+   {
+-    static constexpr bool in_place = true;
+-    enum Flags
+-    {
+-      Mark              = 0x8000,       /* If set, remember this glyph as the marked glyph. */
+-      DontAdvance       = 0x4000,       /* If set, don't advance to the next glyph before
++    Mark                = 0x8000,       /* If set, remember this glyph as the marked glyph. */
++    DontAdvance         = 0x4000,       /* If set, don't advance to the next glyph before
+                                          * going to the new state. */
+-      Reserved          = 0x3FFF,       /* Not used; set to 0. */
+-    };
++    Reserved            = 0x3FFF,       /* Not used; set to 0. */
++  };
++
++  bool is_action_initiable (const Entry &entry) const
++  {
++    return (entry.flags & Mark);
++  }
++  bool is_actionable (const Entry &entry) const
++  {
++    return entry.data.ankrActionIndex != 0xFFFF;
++  }
+ 
++  struct driver_context_t
++  {
++    static constexpr bool in_place = true;
+     enum SubTableFlags
+     {
+       ActionType        = 0xC0000000,   /* A two-bit field containing the action type. */
+@@ -481,22 +539,19 @@ struct KerxSubTableFormat4
+                                          * point table. */
+     };
+ 
+-    driver_context_t (const KerxSubTableFormat4 *table,
++    driver_context_t (const KerxSubTableFormat4 *table_,
+                       hb_aat_apply_context_t *c_) :
+         c (c_),
++        table (table_),
+         action_type ((table->flags & ActionType) >> 30),
+         ankrData ((HBUINT16 *) ((const char *) &table->machine + (table->flags & Offset))),
+         mark_set (false),
+         mark (0) {}
+ 
+-    bool is_actionable (StateTableDriver *driver HB_UNUSED,
+-                        const Entry &entry)
+-    { return entry.data.ankrActionIndex != 0xFFFF; }
+-    void transition (StateTableDriver *driver,
++    void transition (hb_buffer_t *buffer,
++                     StateTableDriver *driver,
+                      const Entry &entry)
+     {
+-      hb_buffer_t *buffer = driver->buffer;
+-
+       if (mark_set && entry.data.ankrActionIndex != 0xFFFF && buffer->idx < buffer->len)
+       {
+         hb_glyph_position_t &o = buffer->cur_pos();
+@@ -509,6 +564,7 @@ struct KerxSubTableFormat4
+                double the ankrActionIndex to get the correct offset here. */
+             const HBUINT16 *data = &ankrData[entry.data.ankrActionIndex * 2];
+             if (!c->sanitizer.check_array (data, 2)) return;
++            hb_barrier ();
+             unsigned int markControlPoint = *data++;
+             unsigned int currControlPoint = *data++;
+             hb_position_t markX = 0;
+@@ -537,6 +593,7 @@ struct KerxSubTableFormat4
+                double the ankrActionIndex to get the correct offset here. */
+             const HBUINT16 *data = &ankrData[entry.data.ankrActionIndex * 2];
+             if (!c->sanitizer.check_array (data, 2)) return;
++            hb_barrier ();
+             unsigned int markAnchorPoint = *data++;
+             unsigned int currAnchorPoint = *data++;
+             const Anchor &markAnchor = c->ankr_table->get_anchor (c->buffer->info[mark].codepoint,
+@@ -557,6 +614,7 @@ struct KerxSubTableFormat4
+                by 4 to get the correct offset for the given action. */
+             const FWORD *data = (const FWORD *) &ankrData[entry.data.ankrActionIndex * 4];
+             if (!c->sanitizer.check_array (data, 4)) return;
++            hb_barrier ();
+             int markX = *data++;
+             int markY = *data++;
+             int currX = *data++;
+@@ -579,8 +637,10 @@ struct KerxSubTableFormat4
+       }
+     }
+ 
+-    private:
++    public:
+     hb_aat_apply_context_t *c;
++    const KerxSubTableFormat4 *table;
++    private:
+     unsigned int action_type;
+     const HBUINT16 *ankrData;
+     bool mark_set;
+@@ -593,7 +653,8 @@ struct KerxSubTableFormat4
+ 
+     driver_context_t dc (this, c);
+ 
+-    StateTableDriver driver (machine, c->buffer, c->font->face);
++    StateTableDriver driver (machine, c->font->face);
++
+     driver.drive (&dc, c);
+ 
+     return_trace (true);
+@@ -607,12 +668,21 @@ struct KerxSubTableFormat4
+                           machine.sanitize (c)));
+   }
+ 
++  template 
++  void collect_glyphs (set_t &left_set, set_t &right_set, unsigned num_glyphs) const
++  {
++    set_t set;
++    machine.collect_glyphs (set, num_glyphs);
++    left_set.union_ (set);
++    right_set.union_ (set);
++  }
++
+   protected:
+   KernSubTableHeader            header;
+   StateTable  machine;
+   HBUINT32                      flags;
+   public:
+-  DEFINE_SIZE_STATIC (KernSubTableHeader::static_size + 20);
++  DEFINE_SIZE_STATIC (KernSubTableHeader::static_size + (StateTable::static_size + HBUINT32::static_size));
+ };
+ 
+ template 
+@@ -631,7 +701,7 @@ struct KerxSubTableFormat6
+     unsigned int num_glyphs = c->sanitizer.get_num_glyphs ();
+     if (is_long ())
+     {
+-      const typename U::Long &t = u.l;
++      const auto &t = u.l;
+       unsigned int l = (this+t.rowIndexTable).get_value_or_null (left, num_glyphs);
+       unsigned int r = (this+t.columnIndexTable).get_value_or_null (right, num_glyphs);
+       unsigned int offset = l + r;
+@@ -639,16 +709,18 @@ struct KerxSubTableFormat6
+       if (unlikely (hb_unsigned_mul_overflows (offset, sizeof (FWORD32)))) return 0;
+       const FWORD32 *v = &StructAtOffset (&(this+t.array), offset * sizeof (FWORD32));
+       if (unlikely (!v->sanitize (&c->sanitizer))) return 0;
++      hb_barrier ();
+       return kerxTupleKern (*v, header.tuple_count (), &(this+vector), c);
+     }
+     else
+     {
+-      const typename U::Short &t = u.s;
++      const auto &t = u.s;
+       unsigned int l = (this+t.rowIndexTable).get_value_or_null (left, num_glyphs);
+       unsigned int r = (this+t.columnIndexTable).get_value_or_null (right, num_glyphs);
+       unsigned int offset = l + r;
+       const FWORD *v = &StructAtOffset (&(this+t.array), offset * sizeof (FWORD));
+       if (unlikely (!v->sanitize (&c->sanitizer))) return 0;
++      hb_barrier ();
+       return kerxTupleKern (*v, header.tuple_count (), &(this+vector), c);
+     }
+   }
+@@ -658,10 +730,10 @@ struct KerxSubTableFormat6
+     TRACE_APPLY (this);
+ 
+     if (!c->plan->requested_kerning)
+-      return false;
++      return_trace (false);
+ 
+     if (header.coverage & header.Backwards)
+-      return false;
++      return_trace (false);
+ 
+     accelerator_t accel (*this, c);
+     hb_kern_machine_t machine (accel, header.coverage & header.CrossStream);
+@@ -674,6 +746,7 @@ struct KerxSubTableFormat6
+   {
+     TRACE_SANITIZE (this);
+     return_trace (likely (c->check_struct (this) &&
++                          hb_barrier () &&
+                           (is_long () ?
+                            (
+                              u.l.rowIndexTable.sanitize (c, this) &&
+@@ -688,6 +761,23 @@ struct KerxSubTableFormat6
+                            c->check_range (this, vector))));
+   }
+ 
++  template 
++  void collect_glyphs (set_t &left_set, set_t &right_set, unsigned num_glyphs) const
++  {
++    if (is_long ())
++    {
++      const auto &t = u.l;
++      (this+t.rowIndexTable).collect_glyphs (left_set, num_glyphs);
++      (this+t.columnIndexTable).collect_glyphs (right_set, num_glyphs);
++    }
++    else
++    {
++      const auto &t = u.s;
++      (this+t.rowIndexTable).collect_glyphs (left_set, num_glyphs);
++      (this+t.columnIndexTable).collect_glyphs (right_set, num_glyphs);
++    }
++  }
++
+   struct accelerator_t
+   {
+     const KerxSubTableFormat6 &table;
+@@ -698,7 +788,10 @@ struct KerxSubTableFormat6
+                      table (table_), c (c_) {}
+ 
+     int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
+-    { return table.get_kerning (left, right, c); }
++    {
++      if (!(*c->left_set)[left] || !(*c->right_set)[right]) return 0;
++      return table.get_kerning (left, right, c);
++    }
+   };
+ 
+   protected:
+@@ -784,12 +877,27 @@ struct KerxSubTable
+     }
+   }
+ 
++  template 
++  void collect_glyphs (set_t &left_set, set_t &right_set, unsigned num_glyphs) const
++  {
++    unsigned int subtable_type = get_type ();
++    switch (subtable_type) {
++    case 0:     u.format0.collect_glyphs (left_set, right_set, num_glyphs); return;
++    case 1:     u.format1.collect_glyphs (left_set, right_set, num_glyphs); return;
++    case 2:     u.format2.collect_glyphs (left_set, right_set, num_glyphs); return;
++    case 4:     u.format4.collect_glyphs (left_set, right_set, num_glyphs); return;
++    case 6:     u.format6.collect_glyphs (left_set, right_set, num_glyphs); return;
++    default:    return;
++    }
++  }
++
+   bool sanitize (hb_sanitize_context_t *c) const
+   {
+     TRACE_SANITIZE (this);
+-    if (!u.header.sanitize (c) ||
+-        u.header.length <= u.header.static_size ||
+-        !c->check_range (this, u.header.length))
++    if (!(u.header.sanitize (c) &&
++          hb_barrier () &&
++          u.header.length >= u.header.static_size &&
++          c->check_range (this, u.header.length)))
+       return_trace (false);
+ 
+     return_trace (dispatch (c));
+@@ -813,6 +921,8 @@ struct KerxSubTable
+  * The 'kerx' Table
+  */
+ 
++using kern_accelerator_data_t = hb_vector_t>;
++
+ template 
+ struct KerxTable
+ {
+@@ -829,6 +939,9 @@ struct KerxTable
+     {
+       if (st->get_type () == 1)
+         return true;
++
++      // TODO: What about format 4? What's this API used for anyway?
++
+       st = &StructAfter (*st);
+     }
+     return false;
+@@ -867,7 +980,8 @@ struct KerxTable
+     return v;
+   }
+ 
+-  bool apply (AAT::hb_aat_apply_context_t *c) const
++  bool apply (AAT::hb_aat_apply_context_t *c,
++              const kern_accelerator_data_t &accel_data) const
+   {
+     c->buffer->unsafe_to_concat ();
+ 
+@@ -914,6 +1028,9 @@ struct KerxTable
+       if (reverse)
+         c->buffer->reverse ();
+ 
++      c->left_set = &accel_data[i].first;
++      c->right_set = &accel_data[i].second;
++
+       {
+         /* See comment in sanitize() for conditional here. */
+         hb_sanitize_with_object_t with (&c->sanitizer, i < count - 1 ? st : (const SubTable *) nullptr);
+@@ -936,9 +1053,10 @@ struct KerxTable
+   bool sanitize (hb_sanitize_context_t *c) const
+   {
+     TRACE_SANITIZE (this);
+-    if (unlikely (!thiz()->version.sanitize (c) ||
+-                  (unsigned) thiz()->version < (unsigned) T::minVersion ||
+-                  !thiz()->tableCount.sanitize (c)))
++    if (unlikely (!(thiz()->version.sanitize (c) &&
++                    hb_barrier () &&
++                    (unsigned) thiz()->version >= (unsigned) T::minVersion &&
++                    thiz()->tableCount.sanitize (c))))
+       return_trace (false);
+ 
+     typedef typename T::SubTable SubTable;
+@@ -949,6 +1067,7 @@ struct KerxTable
+     {
+       if (unlikely (!st->u.header.sanitize (c)))
+         return_trace (false);
++      hb_barrier ();
+       /* OpenType kern table has 2-byte subtable lengths.  That's limiting.
+        * MS implementation also only supports one subtable, of format 0,
+        * anyway.  Certain versions of some fonts, like Calibry, contain
+@@ -964,8 +1083,61 @@ struct KerxTable
+       st = &StructAfter (*st);
+     }
+ 
++    unsigned majorVersion = thiz()->version;
++    if (sizeof (thiz()->version) == 4)
++      majorVersion = majorVersion >> 16;
++    if (majorVersion >= 3)
++    {
++      const SubtableGlyphCoverage *coverage = (const SubtableGlyphCoverage *) st;
++      if (!coverage->sanitize (c, count))
++        return_trace (false);
++    }
++
+     return_trace (true);
+   }
++
++  kern_accelerator_data_t create_accelerator_data (unsigned num_glyphs) const
++  {
++    kern_accelerator_data_t accel_data;
++
++    typedef typename T::SubTable SubTable;
++
++    const SubTable *st = &thiz()->firstSubTable;
++    unsigned int count = thiz()->tableCount;
++    for (unsigned int i = 0; i < count; i++)
++    {
++      hb_bit_set_t left_set, right_set;
++      st->collect_glyphs (left_set, right_set, num_glyphs);
++      accel_data.push (hb_pair (left_set, right_set));
++      st = &StructAfter (*st);
++    }
++
++    return accel_data;
++  }
++
++  struct accelerator_t
++  {
++    accelerator_t (hb_face_t *face)
++    {
++      hb_sanitize_context_t sc;
++      this->table = sc.reference_table (face);
++      this->accel_data = this->table->create_accelerator_data (face->get_num_glyphs ());
++    }
++    ~accelerator_t ()
++    {
++      this->table.destroy ();
++    }
++
++    hb_blob_t *get_blob () const { return table.get_blob (); }
++
++    bool apply (AAT::hb_aat_apply_context_t *c) const
++    {
++      return table->apply (c, accel_data);
++    }
++
++    hb_blob_ptr_t table;
++    kern_accelerator_data_t accel_data;
++  };
+ };
+ 
+ struct kerx : KerxTable
+@@ -994,8 +1166,10 @@ struct kerx : KerxTable
+   DEFINE_SIZE_MIN (8);
+ };
+ 
++struct kerx_accelerator_t : kerx::accelerator_t {
++  kerx_accelerator_t (hb_face_t *face) : kerx::accelerator_t (face) {}
++};
+ 
+ } /* namespace AAT */
+ 
+-
+ #endif /* HB_AAT_LAYOUT_KERX_TABLE_HH */
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-morx-table.hh b/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-morx-table.hh
+index 81e126d5e..cabdc0eb5 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-morx-table.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-morx-table.hh
+@@ -29,6 +29,7 @@
+ 
+ #include "hb-open-type.hh"
+ #include "hb-aat-layout-common.hh"
++#include "hb-ot-layout.hh"
+ #include "hb-ot-layout-common.hh"
+ #include "hb-ot-layout-gdef-table.hh"
+ #include "hb-aat-map.hh"
+@@ -53,36 +54,42 @@ struct RearrangementSubtable
+ 
+   typedef void EntryData;
+ 
+-  struct driver_context_t
++  enum Flags
+   {
+-    static constexpr bool in_place = true;
+-    enum Flags
+-    {
+-      MarkFirst         = 0x8000,       /* If set, make the current glyph the first
++    MarkFirst           = 0x8000,       /* If set, make the current glyph the first
+                                          * glyph to be rearranged. */
+-      DontAdvance       = 0x4000,       /* If set, don't advance to the next glyph
++    DontAdvance         = 0x4000,       /* If set, don't advance to the next glyph
+                                          * before going to the new state. This means
+                                          * that the glyph index doesn't change, even
+                                          * if the glyph at that index has changed. */
+-      MarkLast          = 0x2000,       /* If set, make the current glyph the last
++    MarkLast            = 0x2000,       /* If set, make the current glyph the last
+                                          * glyph to be rearranged. */
+-      Reserved          = 0x1FF0,       /* These bits are reserved and should be set to 0. */
+-      Verb              = 0x000F,       /* The type of rearrangement specified. */
+-    };
++    Reserved            = 0x1FF0,       /* These bits are reserved and should be set to 0. */
++    Verb                = 0x000F,       /* The type of rearrangement specified. */
++  };
++
++  bool is_action_initiable (const Entry &entry) const
++  {
++    return (entry.flags & MarkFirst);
++  }
++  bool is_actionable (const Entry &entry) const
++  {
++    return (entry.flags & Verb);
++  }
++
++  struct driver_context_t
++  {
++    static constexpr bool in_place = true;
+ 
+-    driver_context_t (const RearrangementSubtable *table HB_UNUSED) :
++    driver_context_t (const RearrangementSubtable *table_) :
+         ret (false),
++        table (table_),
+         start (0), end (0) {}
+ 
+-    bool is_actionable (StateTableDriver *driver HB_UNUSED,
+-                        const Entry &entry)
+-    {
+-      return (entry.flags & Verb) && start < end;
+-    }
+-    void transition (StateTableDriver *driver,
++    void transition (hb_buffer_t *buffer,
++                     StateTableDriver *driver,
+                      const Entry &entry)
+     {
+-      hb_buffer_t *buffer = driver->buffer;
+       unsigned int flags = entry.flags;
+ 
+       if (flags & MarkFirst)
+@@ -157,6 +164,7 @@ struct RearrangementSubtable
+ 
+     public:
+     bool ret;
++    const RearrangementSubtable *table;
+     private:
+     unsigned int start;
+     unsigned int end;
+@@ -168,7 +176,14 @@ struct RearrangementSubtable
+ 
+     driver_context_t dc (this);
+ 
+-    StateTableDriver driver (machine, c->buffer, c->face);
++    StateTableDriver driver (machine, c->face);
++
++    if (!c->buffer_intersects_machine ())
++    {
++      (void) c->buffer->message (c->font, "skipped chainsubtable because no glyph matches");
++      return_trace (false);
++    }
++
+     driver.drive (&dc, c);
+ 
+     return_trace (dc.ret);
+@@ -180,10 +195,10 @@ struct RearrangementSubtable
+     return_trace (machine.sanitize (c));
+   }
+ 
+-  protected:
++  public:
+   StateTable  machine;
+   public:
+-  DEFINE_SIZE_STATIC (16);
++  DEFINE_SIZE_STATIC ((StateTable::static_size));
+ };
+ 
+ template 
+@@ -201,43 +216,42 @@ struct ContextualSubtable
+     DEFINE_SIZE_STATIC (4);
+   };
+ 
++  enum Flags
++  {
++    SetMark             = 0x8000,       /* If set, make the current glyph the marked glyph. */
++    DontAdvance         = 0x4000,       /* If set, don't advance to the next glyph before
++                                         * going to the new state. */
++    Reserved            = 0x3FFF,       /* These bits are reserved and should be set to 0. */
++  };
++
++  bool is_action_initiable (const Entry &entry) const
++  {
++    return (entry.flags & SetMark);
++  }
++  bool is_actionable (const Entry &entry) const
++  {
++    return entry.data.markIndex != 0xFFFF || entry.data.currentIndex != 0xFFFF;
++  }
++
+   struct driver_context_t
+   {
+     static constexpr bool in_place = true;
+-    enum Flags
+-    {
+-      SetMark           = 0x8000,       /* If set, make the current glyph the marked glyph. */
+-      DontAdvance       = 0x4000,       /* If set, don't advance to the next glyph before
+-                                         * going to the new state. */
+-      Reserved          = 0x3FFF,       /* These bits are reserved and should be set to 0. */
+-    };
+ 
+     driver_context_t (const ContextualSubtable *table_,
+                              hb_aat_apply_context_t *c_) :
+         ret (false),
+         c (c_),
++        table (table_),
+         gdef (*c->gdef_table),
+         mark_set (false),
+         has_glyph_classes (gdef.has_glyph_classes ()),
+         mark (0),
+-        table (table_),
+         subs (table+table->substitutionTables) {}
+ 
+-    bool is_actionable (StateTableDriver *driver,
+-                        const Entry &entry)
+-    {
+-      hb_buffer_t *buffer = driver->buffer;
+-
+-      if (buffer->idx == buffer->len && !mark_set)
+-        return false;
+-
+-      return entry.data.markIndex != 0xFFFF || entry.data.currentIndex != 0xFFFF;
+-    }
+-    void transition (StateTableDriver *driver,
++    void transition (hb_buffer_t *buffer,
++                     StateTableDriver *driver,
+                      const Entry &entry)
+     {
+-      hb_buffer_t *buffer = driver->buffer;
+-
+       /* Looks like CoreText applies neither mark nor current substitution for
+        * end-of-text if mark was not explicitly set. */
+       if (buffer->idx == buffer->len && !mark_set)
+@@ -259,13 +273,17 @@ struct ContextualSubtable
+         unsigned int offset = entry.data.markIndex + buffer->info[mark].codepoint;
+         const UnsizedArrayOf &subs_old = (const UnsizedArrayOf &) subs;
+         replacement = &subs_old[Types::wordOffsetToIndex (offset, table, subs_old.arrayZ)];
+-        if (!replacement->sanitize (&c->sanitizer) || !*replacement)
++        if (!(replacement->sanitize (&c->sanitizer) &&
++              hb_barrier () &&
++              *replacement))
+           replacement = nullptr;
+       }
+       if (replacement)
+       {
+         buffer->unsafe_to_break (mark, hb_min (buffer->idx + 1, buffer->len));
+-        buffer->info[mark].codepoint = *replacement;
++        hb_codepoint_t glyph = *replacement;
++        buffer->info[mark].codepoint = glyph;
++        c->buffer_glyph_set.add (glyph);
+         if (has_glyph_classes)
+           _hb_glyph_info_set_glyph_props (&buffer->info[mark],
+                                           gdef.get_glyph_props (*replacement));
+@@ -287,12 +305,16 @@ struct ContextualSubtable
+         unsigned int offset = entry.data.currentIndex + buffer->info[idx].codepoint;
+         const UnsizedArrayOf &subs_old = (const UnsizedArrayOf &) subs;
+         replacement = &subs_old[Types::wordOffsetToIndex (offset, table, subs_old.arrayZ)];
+-        if (!replacement->sanitize (&c->sanitizer) || !*replacement)
++        if (!(replacement->sanitize (&c->sanitizer) &&
++              hb_barrier () &&
++              *replacement))
+           replacement = nullptr;
+       }
+       if (replacement)
+       {
+-        buffer->info[idx].codepoint = *replacement;
++        hb_codepoint_t glyph = *replacement;
++        buffer->info[idx].codepoint = glyph;
++        c->buffer_glyph_set.add (glyph);
+         if (has_glyph_classes)
+           _hb_glyph_info_set_glyph_props (&buffer->info[idx],
+                                           gdef.get_glyph_props (*replacement));
+@@ -308,14 +330,14 @@ struct ContextualSubtable
+ 
+     public:
+     bool ret;
+-    private:
+     hb_aat_apply_context_t *c;
++    const ContextualSubtable *table;
++    private:
+     const OT::GDEF &gdef;
+     bool mark_set;
+     bool has_glyph_classes;
+     unsigned int mark;
+-    const ContextualSubtable *table;
+-    const UnsizedListOfOffset16To, HBUINT, false> &subs;
++    const UnsizedListOfOffset16To, HBUINT, void, false> &subs;
+   };
+ 
+   bool apply (hb_aat_apply_context_t *c) const
+@@ -324,7 +346,14 @@ struct ContextualSubtable
+ 
+     driver_context_t dc (this, c);
+ 
+-    StateTableDriver driver (machine, c->buffer, c->face);
++    StateTableDriver driver (machine, c->face);
++
++    if (!c->buffer_intersects_machine ())
++    {
++      (void) c->buffer->message (c->font, "skipped chainsubtable because no glyph matches");
++      return_trace (false);
++    }
++
+     driver.drive (&dc, c);
+ 
+     return_trace (dc.ret);
+@@ -336,6 +365,7 @@ struct ContextualSubtable
+ 
+     unsigned int num_entries = 0;
+     if (unlikely (!machine.sanitize (c, &num_entries))) return_trace (false);
++    hb_barrier ();
+ 
+     if (!Types::extended)
+       return_trace (substitutionTables.sanitize (c, this, 0));
+@@ -356,13 +386,14 @@ struct ContextualSubtable
+     return_trace (substitutionTables.sanitize (c, this, num_lookups));
+   }
+ 
+-  protected:
++  public:
+   StateTable
+                 machine;
+-  NNOffsetTo, HBUINT, false>, HBUINT>
++  protected:
++  NNOffsetTo, HBUINT, void, false>, HBUINT>
+                 substitutionTables;
+   public:
+-  DEFINE_SIZE_STATIC (20);
++  DEFINE_SIZE_STATIC ((StateTable::static_size + HBUINT::static_size));
+ };
+ 
+ 
+@@ -372,6 +403,16 @@ struct LigatureEntry;
+ template <>
+ struct LigatureEntry
+ {
++
++  struct EntryData
++  {
++    HBUINT16    ligActionIndex; /* Index to the first ligActionTable entry
++                                 * for processing this group, if indicated
++                                 * by the flags. */
++    public:
++    DEFINE_SIZE_STATIC (2);
++  };
++
+   enum Flags
+   {
+     SetComponent        = 0x8000,       /* Push this glyph onto the component stack for
+@@ -383,14 +424,8 @@ struct LigatureEntry
+     Reserved            = 0x1FFF,       /* These bits are reserved and should be set to 0. */
+   };
+ 
+-  struct EntryData
+-  {
+-    HBUINT16    ligActionIndex; /* Index to the first ligActionTable entry
+-                                 * for processing this group, if indicated
+-                                 * by the flags. */
+-    public:
+-    DEFINE_SIZE_STATIC (2);
+-  };
++  static bool initiateAction (const Entry &entry)
++  { return entry.flags & SetComponent; }
+ 
+   static bool performAction (const Entry &entry)
+   { return entry.flags & PerformAction; }
+@@ -401,6 +436,8 @@ struct LigatureEntry
+ template <>
+ struct LigatureEntry
+ {
++  typedef void EntryData;
++
+   enum Flags
+   {
+     SetComponent        = 0x8000,       /* Push this glyph onto the component stack for
+@@ -412,7 +449,8 @@ struct LigatureEntry
+                                          * multiple of 4. */
+   };
+ 
+-  typedef void EntryData;
++  static bool initiateAction (const Entry &entry)
++  { return entry.flags & SetComponent; }
+ 
+   static bool performAction (const Entry &entry)
+   { return entry.flags & Offset; }
+@@ -430,13 +468,23 @@ struct LigatureSubtable
+   typedef LigatureEntry LigatureEntryT;
+   typedef typename LigatureEntryT::EntryData EntryData;
+ 
++  enum Flags
++  {
++    DontAdvance = LigatureEntryT::DontAdvance,
++  };
++
++  bool is_action_initiable (const Entry &entry) const
++  {
++    return LigatureEntryT::initiateAction (entry);
++  }
++  bool is_actionable (const Entry &entry) const
++  {
++    return LigatureEntryT::performAction (entry);
++  }
++
+   struct driver_context_t
+   {
+     static constexpr bool in_place = false;
+-    enum
+-    {
+-      DontAdvance       = LigatureEntryT::DontAdvance,
+-    };
+     enum LigActionFlags
+     {
+       LigActionLast     = 0x80000000,   /* This is the last action in the list. This also
+@@ -459,16 +507,10 @@ struct LigatureSubtable
+         ligature (table+table->ligature),
+         match_length (0) {}
+ 
+-    bool is_actionable (StateTableDriver *driver HB_UNUSED,
+-                        const Entry &entry)
+-    {
+-      return LigatureEntryT::performAction (entry);
+-    }
+-    void transition (StateTableDriver *driver,
++    void transition (hb_buffer_t *buffer,
++                     StateTableDriver *driver,
+                      const Entry &entry)
+     {
+-      hb_buffer_t *buffer = driver->buffer;
+-
+       DEBUG_MSG (APPLY, nullptr, "Ligature transition at %u", buffer->idx);
+       if (entry.flags & LigatureEntryT::SetComponent)
+       {
+@@ -513,6 +555,7 @@ struct LigatureSubtable
+           if (unlikely (!buffer->move_to (match_positions[--cursor % ARRAY_LENGTH (match_positions)]))) return;
+ 
+           if (unlikely (!actionData->sanitize (&c->sanitizer))) break;
++          hb_barrier ();
+           action = *actionData;
+ 
+           uint32_t uoffset = action & LigActionOffset;
+@@ -523,6 +566,7 @@ struct LigatureSubtable
+           component_idx = Types::wordOffsetToIndex (component_idx, table, component.arrayZ);
+           const HBUINT16 &componentData = component[component_idx];
+           if (unlikely (!componentData.sanitize (&c->sanitizer))) break;
++          hb_barrier ();
+           ligature_idx += componentData;
+ 
+           DEBUG_MSG (APPLY, nullptr, "Action store %d last %d",
+@@ -533,6 +577,7 @@ struct LigatureSubtable
+             ligature_idx = Types::offsetToIndex (ligature_idx, table, ligature.arrayZ);
+             const HBGlyphID16 &ligatureData = ligature[ligature_idx];
+             if (unlikely (!ligatureData.sanitize (&c->sanitizer))) break;
++            hb_barrier ();
+             hb_codepoint_t lig = ligatureData;
+ 
+             DEBUG_MSG (APPLY, nullptr, "Produced ligature %u", lig);
+@@ -544,6 +589,7 @@ struct LigatureSubtable
+             {
+               DEBUG_MSG (APPLY, nullptr, "Skipping ligature component");
+               if (unlikely (!buffer->move_to (match_positions[--match_length % ARRAY_LENGTH (match_positions)]))) return;
++              _hb_glyph_info_set_default_ignorable (&buffer->cur());
+               if (unlikely (!buffer->replace_glyph (DELETED_GLYPH))) return;
+             }
+ 
+@@ -560,9 +606,9 @@ struct LigatureSubtable
+ 
+     public:
+     bool ret;
+-    private:
+     hb_aat_apply_context_t *c;
+     const LigatureSubtable *table;
++    private:
+     const UnsizedArrayOf &ligAction;
+     const UnsizedArrayOf &component;
+     const UnsizedArrayOf &ligature;
+@@ -576,7 +622,14 @@ struct LigatureSubtable
+ 
+     driver_context_t dc (this, c);
+ 
+-    StateTableDriver driver (machine, c->buffer, c->face);
++    StateTableDriver driver (machine, c->face);
++
++    if (!c->buffer_intersects_machine ())
++    {
++      (void) c->buffer->message (c->font, "skipped chainsubtable because no glyph matches");
++      return_trace (false);
++    }
++
+     driver.drive (&dc, c);
+ 
+     return_trace (dc.ret);
+@@ -587,12 +640,14 @@ struct LigatureSubtable
+     TRACE_SANITIZE (this);
+     /* The rest of array sanitizations are done at run-time. */
+     return_trace (c->check_struct (this) && machine.sanitize (c) &&
++                  hb_barrier () &&
+                   ligAction && component && ligature);
+   }
+ 
+-  protected:
++  public:
+   StateTable
+                 machine;
++  protected:
+   NNOffsetTo, HBUINT>
+                 ligAction;      /* Offset to the ligature action table. */
+   NNOffsetTo, HBUINT>
+@@ -600,7 +655,7 @@ struct LigatureSubtable
+   NNOffsetTo, HBUINT>
+                 ligature;       /* Offset to the actual ligature lists. */
+   public:
+-  DEFINE_SIZE_STATIC (28);
++  DEFINE_SIZE_STATIC ((StateTable::static_size + 3 * HBUINT::static_size));
+ };
+ 
+ template 
+@@ -610,6 +665,12 @@ struct NoncontextualSubtable
+   {
+     TRACE_APPLY (this);
+ 
++    if (!c->buffer_intersects_machine ())
++    {
++      (void) c->buffer->message (c->font, "skipped chainsubtable because no glyph matches");
++      return_trace (false);
++    }
++
+     const OT::GDEF &gdef (*c->gdef_table);
+     bool has_glyph_classes = gdef.has_glyph_classes ();
+ 
+@@ -642,7 +703,9 @@ struct NoncontextualSubtable
+       const HBGlyphID16 *replacement = substitute.get_value (info[i].codepoint, num_glyphs);
+       if (replacement)
+       {
+-        info[i].codepoint = *replacement;
++        hb_codepoint_t glyph = *replacement;
++        info[i].codepoint = glyph;
++        c->buffer_glyph_set.add (glyph);
+         if (has_glyph_classes)
+           _hb_glyph_info_set_glyph_props (&info[i],
+                                           gdef.get_glyph_props (*replacement));
+@@ -653,6 +716,12 @@ struct NoncontextualSubtable
+     return_trace (ret);
+   }
+ 
++  template 
++  void collect_initial_glyphs (set_t &glyphs, unsigned num_glyphs) const
++  {
++    substitute.collect_glyphs (glyphs, num_glyphs);
++  }
++
+   bool sanitize (hb_sanitize_context_t *c) const
+   {
+     TRACE_SANITIZE (this);
+@@ -686,74 +755,80 @@ struct InsertionSubtable
+     DEFINE_SIZE_STATIC (4);
+   };
+ 
++  enum Flags
++  {
++    SetMark             = 0x8000,     /* If set, mark the current glyph. */
++    DontAdvance         = 0x4000,     /* If set, don't advance to the next glyph before
++                                       * going to the new state.  This does not mean
++                                       * that the glyph pointed to is the same one as
++                                       * before. If you've made insertions immediately
++                                       * downstream of the current glyph, the next glyph
++                                       * processed would in fact be the first one
++                                       * inserted. */
++    CurrentIsKashidaLike= 0x2000,     /* If set, and the currentInsertList is nonzero,
++                                       * then the specified glyph list will be inserted
++                                       * as a kashida-like insertion, either before or
++                                       * after the current glyph (depending on the state
++                                       * of the currentInsertBefore flag). If clear, and
++                                       * the currentInsertList is nonzero, then the
++                                       * specified glyph list will be inserted as a
++                                       * split-vowel-like insertion, either before or
++                                       * after the current glyph (depending on the state
++                                       * of the currentInsertBefore flag). */
++    MarkedIsKashidaLike= 0x1000,      /* If set, and the markedInsertList is nonzero,
++                                       * then the specified glyph list will be inserted
++                                       * as a kashida-like insertion, either before or
++                                       * after the marked glyph (depending on the state
++                                       * of the markedInsertBefore flag). If clear, and
++                                       * the markedInsertList is nonzero, then the
++                                       * specified glyph list will be inserted as a
++                                       * split-vowel-like insertion, either before or
++                                       * after the marked glyph (depending on the state
++                                       * of the markedInsertBefore flag). */
++    CurrentInsertBefore= 0x0800,      /* If set, specifies that insertions are to be made
++                                       * to the left of the current glyph. If clear,
++                                       * they're made to the right of the current glyph. */
++    MarkedInsertBefore= 0x0400,       /* If set, specifies that insertions are to be
++                                       * made to the left of the marked glyph. If clear,
++                                       * they're made to the right of the marked glyph. */
++    CurrentInsertCount= 0x3E0,        /* This 5-bit field is treated as a count of the
++                                       * number of glyphs to insert at the current
++                                       * position. Since zero means no insertions, the
++                                       * largest number of insertions at any given
++                                       * current location is 31 glyphs. */
++    MarkedInsertCount= 0x001F,        /* This 5-bit field is treated as a count of the
++                                       * number of glyphs to insert at the marked
++                                       * position. Since zero means no insertions, the
++                                       * largest number of insertions at any given
++                                       * marked location is 31 glyphs. */
++  };
++
++  bool is_action_initiable (const Entry &entry) const
++  {
++    return (entry.flags & SetMark);
++  }
++  bool is_actionable (const Entry &entry) const
++  {
++    return (entry.flags & (CurrentInsertCount | MarkedInsertCount)) &&
++           (entry.data.currentInsertIndex != 0xFFFF ||entry.data.markedInsertIndex != 0xFFFF);
++  }
++
+   struct driver_context_t
+   {
+     static constexpr bool in_place = false;
+-    enum Flags
+-    {
+-      SetMark           = 0x8000,       /* If set, mark the current glyph. */
+-      DontAdvance       = 0x4000,       /* If set, don't advance to the next glyph before
+-                                         * going to the new state.  This does not mean
+-                                         * that the glyph pointed to is the same one as
+-                                         * before. If you've made insertions immediately
+-                                         * downstream of the current glyph, the next glyph
+-                                         * processed would in fact be the first one
+-                                         * inserted. */
+-      CurrentIsKashidaLike= 0x2000,     /* If set, and the currentInsertList is nonzero,
+-                                         * then the specified glyph list will be inserted
+-                                         * as a kashida-like insertion, either before or
+-                                         * after the current glyph (depending on the state
+-                                         * of the currentInsertBefore flag). If clear, and
+-                                         * the currentInsertList is nonzero, then the
+-                                         * specified glyph list will be inserted as a
+-                                         * split-vowel-like insertion, either before or
+-                                         * after the current glyph (depending on the state
+-                                         * of the currentInsertBefore flag). */
+-      MarkedIsKashidaLike= 0x1000,      /* If set, and the markedInsertList is nonzero,
+-                                         * then the specified glyph list will be inserted
+-                                         * as a kashida-like insertion, either before or
+-                                         * after the marked glyph (depending on the state
+-                                         * of the markedInsertBefore flag). If clear, and
+-                                         * the markedInsertList is nonzero, then the
+-                                         * specified glyph list will be inserted as a
+-                                         * split-vowel-like insertion, either before or
+-                                         * after the marked glyph (depending on the state
+-                                         * of the markedInsertBefore flag). */
+-      CurrentInsertBefore= 0x0800,      /* If set, specifies that insertions are to be made
+-                                         * to the left of the current glyph. If clear,
+-                                         * they're made to the right of the current glyph. */
+-      MarkedInsertBefore= 0x0400,       /* If set, specifies that insertions are to be
+-                                         * made to the left of the marked glyph. If clear,
+-                                         * they're made to the right of the marked glyph. */
+-      CurrentInsertCount= 0x3E0,        /* This 5-bit field is treated as a count of the
+-                                         * number of glyphs to insert at the current
+-                                         * position. Since zero means no insertions, the
+-                                         * largest number of insertions at any given
+-                                         * current location is 31 glyphs. */
+-      MarkedInsertCount= 0x001F,        /* This 5-bit field is treated as a count of the
+-                                         * number of glyphs to insert at the marked
+-                                         * position. Since zero means no insertions, the
+-                                         * largest number of insertions at any given
+-                                         * marked location is 31 glyphs. */
+-    };
+ 
+-    driver_context_t (const InsertionSubtable *table,
++    driver_context_t (const InsertionSubtable *table_,
+                       hb_aat_apply_context_t *c_) :
+         ret (false),
+         c (c_),
++        table (table_),
+         mark (0),
+         insertionAction (table+table->insertionAction) {}
+ 
+-    bool is_actionable (StateTableDriver *driver HB_UNUSED,
+-                        const Entry &entry)
+-    {
+-      return (entry.flags & (CurrentInsertCount | MarkedInsertCount)) &&
+-             (entry.data.currentInsertIndex != 0xFFFF ||entry.data.markedInsertIndex != 0xFFFF);
+-    }
+-    void transition (StateTableDriver *driver,
++    void transition (hb_buffer_t *buffer,
++                     StateTableDriver *driver,
+                      const Entry &entry)
+     {
+-      hb_buffer_t *buffer = driver->buffer;
+       unsigned int flags = entry.flags;
+ 
+       unsigned mark_loc = buffer->out_len;
+@@ -765,6 +840,7 @@ struct InsertionSubtable
+         unsigned int start = entry.data.markedInsertIndex;
+         const HBGlyphID16 *glyphs = &insertionAction[start];
+         if (unlikely (!c->sanitizer.check_array (glyphs, count))) count = 0;
++        hb_barrier ();
+ 
+         bool before = flags & MarkedInsertBefore;
+ 
+@@ -775,6 +851,9 @@ struct InsertionSubtable
+           if (unlikely (!buffer->copy_glyph ())) return;
+         /* TODO We ignore KashidaLike setting. */
+         if (unlikely (!buffer->replace_glyphs (0, count, glyphs))) return;
++        for (unsigned int i = 0; i < count; i++)
++          c->buffer_glyph_set.add (glyphs[i]);
++        ret = true;
+         if (buffer->idx < buffer->len && !before)
+           buffer->skip_glyph ();
+ 
+@@ -793,6 +872,7 @@ struct InsertionSubtable
+         unsigned int start = entry.data.currentInsertIndex;
+         const HBGlyphID16 *glyphs = &insertionAction[start];
+         if (unlikely (!c->sanitizer.check_array (glyphs, count))) count = 0;
++        hb_barrier ();
+ 
+         bool before = flags & CurrentInsertBefore;
+ 
+@@ -826,8 +906,9 @@ struct InsertionSubtable
+ 
+     public:
+     bool ret;
+-    private:
+     hb_aat_apply_context_t *c;
++    const InsertionSubtable *table;
++    private:
+     unsigned int mark;
+     const UnsizedArrayOf &insertionAction;
+   };
+@@ -838,7 +919,14 @@ struct InsertionSubtable
+ 
+     driver_context_t dc (this, c);
+ 
+-    StateTableDriver driver (machine, c->buffer, c->face);
++    StateTableDriver driver (machine, c->face);
++
++    if (!c->buffer_intersects_machine ())
++    {
++      (void) c->buffer->message (c->font, "skipped chainsubtable because no glyph matches");
++      return_trace (false);
++    }
++
+     driver.drive (&dc, c);
+ 
+     return_trace (dc.ret);
+@@ -849,17 +937,19 @@ struct InsertionSubtable
+     TRACE_SANITIZE (this);
+     /* The rest of array sanitizations are done at run-time. */
+     return_trace (c->check_struct (this) && machine.sanitize (c) &&
++                  hb_barrier () &&
+                   insertionAction);
+   }
+ 
+-  protected:
++  public:
+   StateTable
+                 machine;
++  protected:
+   NNOffsetTo, HBUINT>
+                 insertionAction;        /* Byte offset from stateHeader to the start of
+                                          * the insertion glyph table. */
+   public:
+-  DEFINE_SIZE_STATIC (20);
++  DEFINE_SIZE_STATIC ((StateTable::static_size + HBUINT::static_size));
+ };
+ 
+ 
+@@ -883,6 +973,107 @@ struct Feature
+   DEFINE_SIZE_STATIC (12);
+ };
+ 
++
++struct hb_accelerate_subtables_context_t :
++       hb_dispatch_context_t
++{
++  struct hb_applicable_t
++  {
++    friend struct hb_accelerate_subtables_context_t;
++    friend struct hb_aat_layout_lookup_accelerator_t;
++
++    public:
++    hb_bit_set_t glyph_set;
++    mutable hb_aat_class_cache_t class_cache;
++
++    template 
++    auto init_ (const T &obj_, unsigned num_glyphs, hb_priority<1>) HB_AUTO_RETURN
++    (
++      obj_.machine.collect_initial_glyphs (glyph_set, num_glyphs, obj_)
++    )
++
++    template 
++    void init_ (const T &obj_, unsigned num_glyphs, hb_priority<0>)
++    {
++      obj_.collect_initial_glyphs (glyph_set, num_glyphs);
++    }
++
++    template 
++    void init (const T &obj_, unsigned num_glyphs)
++    {
++      glyph_set.init ();
++      init_ (obj_, num_glyphs, hb_prioritize);
++      class_cache.clear ();
++    }
++
++    void
++    fini ()
++    {
++      glyph_set.fini ();
++    }
++  };
++
++  /* Dispatch interface. */
++  template 
++  return_t dispatch (const T &obj)
++  {
++    hb_applicable_t *entry = &array[i++];
++
++    entry->init (obj, num_glyphs);
++
++    return hb_empty_t ();
++  }
++  static return_t default_return_value () { return hb_empty_t (); }
++
++  bool stop_sublookup_iteration (return_t r) const { return false; }
++
++  hb_accelerate_subtables_context_t (hb_applicable_t *array_, unsigned num_glyphs_) :
++                                     hb_dispatch_context_t (),
++                                     array (array_), num_glyphs (num_glyphs_) {}
++
++  hb_applicable_t *array;
++  unsigned num_glyphs;
++  unsigned i = 0;
++};
++
++struct hb_aat_layout_chain_accelerator_t
++{
++  template 
++  static hb_aat_layout_chain_accelerator_t *create (const TChain &chain, unsigned num_glyphs)
++  {
++    unsigned count = chain.get_subtable_count ();
++
++    unsigned size = sizeof (hb_aat_layout_chain_accelerator_t) -
++                    HB_VAR_ARRAY * sizeof (hb_accelerate_subtables_context_t::hb_applicable_t) +
++                    count * sizeof (hb_accelerate_subtables_context_t::hb_applicable_t);
++
++    /* The following is a calloc because when we are collecting subtables,
++     * some of them might be invalid and hence not collect; as a result,
++     * we might not fill in all the count entries of the subtables array.
++     * Zeroing it allows the set digest to gatekeep it without having to
++     * initialize it further. */
++    auto *thiz = (hb_aat_layout_chain_accelerator_t *) hb_calloc (1, size);
++    if (unlikely (!thiz))
++      return nullptr;
++
++    thiz->count = count;
++
++    hb_accelerate_subtables_context_t c_accelerate_subtables (thiz->subtables, num_glyphs);
++    chain.dispatch (&c_accelerate_subtables);
++
++    return thiz;
++  }
++
++  void destroy ()
++  {
++    for (unsigned i = 0; i < count; i++)
++      subtables[i].fini ();
++  }
++
++  unsigned count;
++  hb_accelerate_subtables_context_t::hb_applicable_t subtables[HB_VAR_ARRAY];
++};
++
+ template 
+ struct ChainSubtable
+ {
+@@ -937,19 +1128,22 @@ struct ChainSubtable
+   bool apply (hb_aat_apply_context_t *c) const
+   {
+     TRACE_APPLY (this);
+-    hb_sanitize_with_object_t with (&c->sanitizer, this);
++    // Disabled for https://github.com/harfbuzz/harfbuzz/issues/4873
++    //hb_sanitize_with_object_t with (&c->sanitizer, this);
+     return_trace (dispatch (c));
+   }
+ 
+   bool sanitize (hb_sanitize_context_t *c) const
+   {
+     TRACE_SANITIZE (this);
+-    if (!length.sanitize (c) ||
+-        length <= min_size ||
+-        !c->check_range (this, length))
++    if (!(length.sanitize (c) &&
++          hb_barrier () &&
++          length >= min_size &&
++          c->check_range (this, length)))
+       return_trace (false);
+ 
+-    hb_sanitize_with_object_t with (c, this);
++    // Disabled for https://github.com/harfbuzz/harfbuzz/issues/4873
++    //hb_sanitize_with_object_t with (c, this);
+     return_trace (dispatch (c));
+   }
+ 
+@@ -973,6 +1167,8 @@ struct Chain
+ {
+   typedef typename Types::HBUINT HBUINT;
+ 
++  unsigned get_subtable_count () const { return subtableCount; }
++
+   hb_mask_t compile_flags (const hb_aat_map_builder_t *map) const
+   {
+     hb_mask_t flags = defaultFlags;
+@@ -1013,7 +1209,8 @@ struct Chain
+     return flags;
+   }
+ 
+-  void apply (hb_aat_apply_context_t *c) const
++  void apply (hb_aat_apply_context_t *c,
++              const hb_aat_layout_chain_accelerator_t *accel) const
+   {
+     const ChainSubtable *subtable = &StructAfter> (featureZ.as_array (featureCount));
+     unsigned int count = subtableCount;
+@@ -1021,14 +1218,19 @@ struct Chain
+     {
+       bool reverse;
+ 
++      auto coverage = subtable->get_coverage ();
++
++      hb_mask_t subtable_flags = subtable->subFeatureFlags;
+       if (hb_none (hb_iter (c->range_flags) |
+-                   hb_map ([&subtable] (const hb_aat_map_t::range_flags_t _) -> bool { return subtable->subFeatureFlags & (_.flags); })))
++                   hb_map ([subtable_flags] (const hb_aat_map_t::range_flags_t _) -> bool { return subtable_flags & (_.flags); })))
+         goto skip;
+-      c->subtable_flags = subtable->subFeatureFlags;
++      c->subtable_flags = subtable_flags;
++      c->machine_glyph_set = accel ? &accel->subtables[i].glyph_set : &Null(hb_bit_set_t);
++      c->machine_class_cache = accel ? &accel->subtables[i].class_cache : nullptr;
+ 
+-      if (!(subtable->get_coverage() & ChainSubtable::AllDirections) &&
++      if (!(coverage & ChainSubtable::AllDirections) &&
+           HB_DIRECTION_IS_VERTICAL (c->buffer->props.direction) !=
+-          bool (subtable->get_coverage() & ChainSubtable::Vertical))
++          bool (coverage & ChainSubtable::Vertical))
+         goto skip;
+ 
+       /* Buffer contents is always in logical direction.  Determine if
+@@ -1058,9 +1260,9 @@ struct Chain
+                                 (the order opposite that of the characters, which
+                                 may be right-to-left or left-to-right).
+        */
+-      reverse = subtable->get_coverage () & ChainSubtable::Logical ?
+-                bool (subtable->get_coverage () & ChainSubtable::Backwards) :
+-                bool (subtable->get_coverage () & ChainSubtable::Backwards) !=
++      reverse = coverage & ChainSubtable::Logical ?
++                bool (coverage & ChainSubtable::Backwards) :
++                bool (coverage & ChainSubtable::Backwards) !=
+                 HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction);
+ 
+       if (!c->buffer->message (c->font, "start chainsubtable %u", c->lookup_index))
+@@ -1086,12 +1288,28 @@ struct Chain
+ 
+   unsigned int get_size () const { return length; }
+ 
+-  bool sanitize (hb_sanitize_context_t *c, unsigned int version HB_UNUSED) const
++  template 
++  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
++  {
++    const ChainSubtable *subtable = &StructAfter> (featureZ.as_array (featureCount));
++    unsigned int count = subtableCount;
++    for (unsigned int i = 0; i < count; i++)
++    {
++      typename context_t::return_t ret = subtable->dispatch (c, std::forward (ds)...);
++      if (c->stop_sublookup_iteration (ret))
++        return ret;
++      subtable = &StructAfter> (*subtable);
++    }
++    return c->default_return_value ();
++  }
++
++  bool sanitize (hb_sanitize_context_t *c, unsigned int version) const
+   {
+     TRACE_SANITIZE (this);
+-    if (!length.sanitize (c) ||
+-        length < min_size ||
+-        !c->check_range (this, length))
++    if (!(length.sanitize (c) &&
++          hb_barrier () &&
++          length >= min_size &&
++          c->check_range (this, length)))
+       return_trace (false);
+ 
+     if (!c->check_array (featureZ.arrayZ, featureCount))
+@@ -1103,9 +1321,17 @@ struct Chain
+     {
+       if (!subtable->sanitize (c))
+         return_trace (false);
++      hb_barrier ();
+       subtable = &StructAfter> (*subtable);
+     }
+ 
++    if (version >= 3)
++    {
++      const SubtableGlyphCoverage *coverage = (const SubtableGlyphCoverage *) subtable;
++      if (!coverage->sanitize (c, count))
++        return_trace (false);
++    }
++
+     return_trace (true);
+   }
+ 
+@@ -1117,7 +1343,7 @@ struct Chain
+ 
+   UnsizedArrayOf       featureZ;       /* Features. */
+ /*ChainSubtable firstSubtable;*//* Subtables. */
+-/*subtableGlyphCoverageArray*/  /* Only if version >= 3. We don't use. */
++/*SubtableGlyphCoverage coverages*//* Only if version >= 3. */
+ 
+   public:
+   DEFINE_SIZE_MIN (8 + 2 * sizeof (HBUINT));
+@@ -1128,13 +1354,79 @@ struct Chain
+  * The 'mort'/'morx' Table
+  */
+ 
+-template 
++template 
+ struct mortmorx
+ {
+   static constexpr hb_tag_t tableTag = TAG;
+ 
+   bool has_data () const { return version != 0; }
+ 
++  struct accelerator_t
++  {
++    accelerator_t (hb_face_t *face)
++    {
++      hb_sanitize_context_t sc;
++      this->table = sc.reference_table (face);
++
++      if (unlikely (this->table->is_blocklisted (this->table.get_blob (), face)))
++      {
++        hb_blob_destroy (this->table.get_blob ());
++        this->table = hb_blob_get_empty ();
++      }
++
++      this->chain_count = table->get_chain_count ();
++
++      this->accels = (hb_atomic_ptr_t *) hb_calloc (this->chain_count, sizeof (*accels));
++      if (unlikely (!this->accels))
++      {
++        this->chain_count = 0;
++        this->table.destroy ();
++        this->table = hb_blob_get_empty ();
++      }
++    }
++    ~accelerator_t ()
++    {
++      for (unsigned int i = 0; i < this->chain_count; i++)
++      {
++        if (this->accels[i])
++          this->accels[i]->destroy ();
++        hb_free (this->accels[i]);
++      }
++      hb_free (this->accels);
++      this->table.destroy ();
++    }
++
++    hb_blob_t *get_blob () const { return table.get_blob (); }
++
++    template 
++    hb_aat_layout_chain_accelerator_t *get_accel (unsigned chain_index, const Chain &chain, unsigned num_glyphs) const
++    {
++      if (unlikely (chain_index >= chain_count)) return nullptr;
++
++    retry:
++      auto *accel = accels[chain_index].get_acquire ();
++      if (unlikely (!accel))
++      {
++        accel = hb_aat_layout_chain_accelerator_t::create (chain, num_glyphs);
++        if (unlikely (!accel))
++          return nullptr;
++
++        if (unlikely (!accels[chain_index].cmpexch (nullptr, accel)))
++        {
++          hb_free (accel);
++          goto retry;
++        }
++      }
++
++      return accel;
++    }
++
++    hb_blob_ptr_t table;
++    unsigned int chain_count;
++    hb_atomic_ptr_t *accels;
++  };
++
++
+   void compile_flags (const hb_aat_map_builder_t *mapper,
+                       hb_aat_map_t *map) const
+   {
+@@ -1151,20 +1443,28 @@ struct mortmorx
+     }
+   }
+ 
++  unsigned get_chain_count () const
++  {
++    return chainCount;
++  }
+   void apply (hb_aat_apply_context_t *c,
+-              const hb_aat_map_t &map) const
++              const hb_aat_map_t &map,
++              const accelerator_t &accel) const
+   {
+     if (unlikely (!c->buffer->successful)) return;
+ 
+     c->buffer->unsafe_to_concat ();
+ 
++    c->setup_buffer_glyph_set ();
++
+     c->set_lookup_index (0);
+     const Chain *chain = &firstChain;
+     unsigned int count = chainCount;
+     for (unsigned int i = 0; i < count; i++)
+     {
++      auto *chain_accel = accel.get_accel (i, *chain, c->face->get_num_glyphs ());
+       c->range_flags = &map.chain_flags[i];
+-      chain->apply (c);
++      chain->apply (c, chain_accel);
+       if (unlikely (!c->buffer->successful)) return;
+       chain = &StructAfter> (*chain);
+     }
+@@ -1173,7 +1473,10 @@ struct mortmorx
+   bool sanitize (hb_sanitize_context_t *c) const
+   {
+     TRACE_SANITIZE (this);
+-    if (!version.sanitize (c) || !version || !chainCount.sanitize (c))
++    if (!(version.sanitize (c) &&
++          hb_barrier () &&
++          version &&
++          chainCount.sanitize (c)))
+       return_trace (false);
+ 
+     const Chain *chain = &firstChain;
+@@ -1182,6 +1485,7 @@ struct mortmorx
+     {
+       if (!chain->sanitize (c, version))
+         return_trace (false);
++      hb_barrier ();
+       chain = &StructAfter> (*chain);
+     }
+ 
+@@ -1200,8 +1504,24 @@ struct mortmorx
+   DEFINE_SIZE_MIN (8);
+ };
+ 
+-struct morx : mortmorx {};
+-struct mort : mortmorx {};
++struct morx : mortmorx
++{
++  HB_INTERNAL bool is_blocklisted (hb_blob_t *blob,
++                                   hb_face_t *face) const;
++};
++
++struct mort : mortmorx
++{
++  HB_INTERNAL bool is_blocklisted (hb_blob_t *blob,
++                                   hb_face_t *face) const;
++};
++
++struct morx_accelerator_t : morx::accelerator_t {
++  morx_accelerator_t (hb_face_t *face) : morx::accelerator_t (face) {}
++};
++struct mort_accelerator_t : mort::accelerator_t {
++  mort_accelerator_t (hb_face_t *face) : mort::accelerator_t (face) {}
++};
+ 
+ 
+ } /* namespace AAT */
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-opbd-table.hh b/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-opbd-table.hh
+index 959382f35..f28ec326b 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-opbd-table.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-opbd-table.hh
+@@ -133,8 +133,8 @@ struct opbd
+   {
+     switch (format)
+     {
+-    case 0: return u.format0.get_bounds (font, glyph_id, extents, this);
+-    case 1: return u.format1.get_bounds (font, glyph_id, extents, this);
++    case 0: hb_barrier (); return u.format0.get_bounds (font, glyph_id, extents, this);
++    case 1: hb_barrier (); return u.format1.get_bounds (font, glyph_id, extents, this);
+     default:return false;
+     }
+   }
+@@ -144,11 +144,12 @@ struct opbd
+     TRACE_SANITIZE (this);
+     if (unlikely (!c->check_struct (this) || version.major != 1))
+       return_trace (false);
++    hb_barrier ();
+ 
+     switch (format)
+     {
+-    case 0: return_trace (u.format0.sanitize (c, this));
+-    case 1: return_trace (u.format1.sanitize (c, this));
++    case 0: hb_barrier (); return_trace (u.format0.sanitize (c, this));
++    case 1: hb_barrier (); return_trace (u.format1.sanitize (c, this));
+     default:return_trace (true);
+     }
+   }
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-trak-table.hh b/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-trak-table.hh
+index 5c49d1f05..0db4035fd 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-trak-table.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-aat-layout-trak-table.hh
+@@ -48,17 +48,69 @@ struct TrackTableEntry
+ 
+   float get_track_value () const { return track.to_float (); }
+ 
+-  int get_value (const void *base, unsigned int index,
+-                 unsigned int table_size) const
+-  { return (base+valuesZ).as_array (table_size)[index]; }
++  float interpolate_at (unsigned int idx,
++                        float ptem,
++                        const void *base,
++                        hb_array_t size_table) const
++  {
++    const FWORD *values = (base+valuesZ).arrayZ;
++
++    float s0 = size_table[idx].to_float ();
++    float s1 = size_table[idx + 1].to_float ();
++    int v0 = values[idx];
++    int v1 = values[idx + 1];
++
++    // Deal with font bugs.
++    if (unlikely (s1 < s0))
++    { hb_swap (s0, s1); hb_swap (v0, v1); }
++    if (unlikely (ptem < s0)) return v0;
++    if (unlikely (ptem > s1)) return v1;
++    if (unlikely (s0 == s1)) return (v0 + v1) * 0.5f;
++
++    float t = (ptem - s0) / (s1 - s0);
++    return v0 + t * (v1 - v0);
++  }
++
++  float get_value (float ptem,
++                   const void *base,
++                   hb_array_t size_table) const
++  {
++    const FWORD *values = (base+valuesZ).arrayZ;
++
++    unsigned int n_sizes = size_table.length;
++
++    /*
++     * Choose size.
++     */
++    if (!n_sizes) return 0.f;
++    if (n_sizes == 1) return values[0];
++
++    // At least two entries.
++
++    unsigned i;
++    for (i = 0; i < n_sizes; i++)
++      if (size_table[i].to_float () >= ptem)
++        break;
++
++    // Boundary conditions.
++    if (i == 0)       return values[0];
++    if (i == n_sizes) return values[n_sizes - 1];
++
++    // Exact match.
++    if (size_table[i].to_float () == ptem) return values[i];
++
++    // Interpolate.
++    return interpolate_at (i - 1, ptem, base, size_table);
++  }
+ 
+   public:
+-  bool sanitize (hb_sanitize_context_t *c, const void *base,
+-                 unsigned int table_size) const
++  bool sanitize (hb_sanitize_context_t *c,
++                 const void *base,
++                 unsigned int n_sizes) const
+   {
+     TRACE_SANITIZE (this);
+     return_trace (likely (c->check_struct (this) &&
+-                          (valuesZ.sanitize (c, base, table_size))));
++                          (valuesZ.sanitize (c, base, n_sizes))));
+   }
+ 
+   protected:
+@@ -76,64 +128,45 @@ struct TrackTableEntry
+ 
+ struct TrackData
+ {
+-  float interpolate_at (unsigned int idx,
+-                        float target_size,
+-                        const TrackTableEntry &trackTableEntry,
+-                        const void *base) const
++  float get_tracking (const void *base, float ptem, float track = 0.f) const
+   {
+-    unsigned int sizes = nSizes;
+-    hb_array_t size_table ((base+sizeTable).arrayZ, sizes);
++    unsigned count = nTracks;
++    hb_array_t size_table = (base+sizeTable).as_array (nSizes);
+ 
+-    float s0 = size_table[idx].to_float ();
+-    float s1 = size_table[idx + 1].to_float ();
+-    float t = unlikely (s0 == s1) ? 0.f : (target_size - s0) / (s1 - s0);
+-    return t * trackTableEntry.get_value (base, idx + 1, sizes) +
+-           (1.f - t) * trackTableEntry.get_value (base, idx, sizes);
+-  }
++    if (!count) return 0.f;
++    if (count == 1) return trackTable[0].get_value (ptem, base, size_table);
+ 
+-  int get_tracking (const void *base, float ptem) const
+-  {
+-    /*
+-     * Choose track.
+-     */
+-    const TrackTableEntry *trackTableEntry = nullptr;
+-    unsigned int count = nTracks;
+-    for (unsigned int i = 0; i < count; i++)
+-    {
+-      /* Note: Seems like the track entries are sorted by values.  But the
+-       * spec doesn't explicitly say that.  It just mentions it in the example. */
+-
+-      /* For now we only seek for track entries with zero tracking value */
+-
+-      if (trackTable[i].get_track_value () == 0.f)
+-      {
+-        trackTableEntry = &trackTable[i];
+-        break;
+-      }
+-    }
+-    if (!trackTableEntry) return 0;
++    // At least two entries.
+ 
+-    /*
+-     * Choose size.
+-     */
+-    unsigned int sizes = nSizes;
+-    if (!sizes) return 0;
+-    if (sizes == 1) return trackTableEntry->get_value (base, 0, sizes);
+-
+-    hb_array_t size_table ((base+sizeTable).arrayZ, sizes);
+-    unsigned int size_index;
+-    for (size_index = 0; size_index < sizes - 1; size_index++)
+-      if (size_table[size_index].to_float () >= ptem)
+-        break;
++    unsigned i = 0;
++    unsigned j = count - 1;
++
++    // Find the two entries that track is between.
++    while (i + 1 < count && trackTable[i + 1].get_track_value () < track)
++      i++;
++    while (j > 0 && trackTable[j - 1].get_track_value () > track)
++      j--;
++
++    // Exact match.
++    if (i == j) return trackTable[i].get_value (ptem, base, size_table);
++
++    // Interpolate.
+ 
+-    return roundf (interpolate_at (size_index ? size_index - 1 : 0, ptem,
+-                                   *trackTableEntry, base));
++    float t0 = trackTable[i].get_track_value ();
++    float t1 = trackTable[j].get_track_value ();
++
++    float t = (track - t0) / (t1 - t0);
++
++    float a = trackTable[i].get_value (ptem, base, size_table);
++    float b = trackTable[j].get_value (ptem, base, size_table);
++    return a + t * (b - a);
+   }
+ 
+   bool sanitize (hb_sanitize_context_t *c, const void *base) const
+   {
+     TRACE_SANITIZE (this);
+     return_trace (likely (c->check_struct (this) &&
++                          hb_barrier () &&
+                           sizeTable.sanitize (c, base, nSizes) &&
+                           trackTable.sanitize (c, nTracks, base, nSizes)));
+   }
+@@ -157,45 +190,15 @@ struct trak
+ 
+   bool has_data () const { return version.to_int (); }
+ 
+-  bool apply (hb_aat_apply_context_t *c) const
++  hb_position_t get_h_tracking (hb_font_t *font, float track = 0.f) const
++  {
++    float ptem = font->ptem > 0.f ? font->ptem : HB_CORETEXT_DEFAULT_FONT_SIZE;
++    return font->em_scalef_x ((this+horizData).get_tracking (this, ptem, track));
++  }
++  hb_position_t get_v_tracking (hb_font_t *font, float track = 0.f) const
+   {
+-    TRACE_APPLY (this);
+-
+-    hb_mask_t trak_mask = c->plan->trak_mask;
+-
+-    const float ptem = c->font->ptem;
+-    if (unlikely (ptem <= 0.f))
+-      return_trace (false);
+-
+-    hb_buffer_t *buffer = c->buffer;
+-    if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction))
+-    {
+-      const TrackData &trackData = this+horizData;
+-      int tracking = trackData.get_tracking (this, ptem);
+-      hb_position_t offset_to_add = c->font->em_scalef_x (tracking / 2);
+-      hb_position_t advance_to_add = c->font->em_scalef_x (tracking);
+-      foreach_grapheme (buffer, start, end)
+-      {
+-        if (!(buffer->info[start].mask & trak_mask)) continue;
+-        buffer->pos[start].x_advance += advance_to_add;
+-        buffer->pos[start].x_offset += offset_to_add;
+-      }
+-    }
+-    else
+-    {
+-      const TrackData &trackData = this+vertData;
+-      int tracking = trackData.get_tracking (this, ptem);
+-      hb_position_t offset_to_add = c->font->em_scalef_y (tracking / 2);
+-      hb_position_t advance_to_add = c->font->em_scalef_y (tracking);
+-      foreach_grapheme (buffer, start, end)
+-      {
+-        if (!(buffer->info[start].mask & trak_mask)) continue;
+-        buffer->pos[start].y_advance += advance_to_add;
+-        buffer->pos[start].y_offset += offset_to_add;
+-      }
+-    }
+-
+-    return_trace (true);
++    float ptem = font->ptem > 0.f ? font->ptem : HB_CORETEXT_DEFAULT_FONT_SIZE;
++    return font->em_scalef_y ((this+vertData).get_tracking (this, ptem, track));
+   }
+ 
+   bool sanitize (hb_sanitize_context_t *c) const
+@@ -203,6 +206,7 @@ struct trak
+     TRACE_SANITIZE (this);
+ 
+     return_trace (likely (c->check_struct (this) &&
++                          hb_barrier () &&
+                           version.major == 1 &&
+                           horizData.sanitize (c, this, this) &&
+                           vertData.sanitize (c, this, this)));
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-aat-layout.cc b/src/java.desktop/share/native/libharfbuzz/hb-aat-layout.cc
+index fc5834c7c..2cc94257a 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-aat-layout.cc
++++ b/src/java.desktop/share/native/libharfbuzz/hb-aat-layout.cc
+@@ -34,9 +34,12 @@
+ #include "hb-aat-layout-just-table.hh" // Just so we compile it; unused otherwise.
+ #include "hb-aat-layout-kerx-table.hh"
+ #include "hb-aat-layout-morx-table.hh"
+-#include "hb-aat-layout-trak-table.hh"
++#include "hb-aat-layout-trak-table.hh" // Just so we compile it; unused otherwise.
+ #include "hb-aat-ltag-table.hh"
+ 
++#include "hb-ot-layout-gsub-table.hh"
++#include "hb-ot-layout-gdef-table.hh"
++
+ 
+ /*
+  * hb_aat_apply_context_t
+@@ -207,18 +210,48 @@ hb_aat_layout_find_feature_mapping (hb_tag_t tag)
+  */
+ 
+ 
++bool
++AAT::morx::is_blocklisted (hb_blob_t *blob,
++                           hb_face_t *face) const
++{
++#ifdef HB_NO_AAT_LAYOUT_BLOCKLIST
++  return false;
++#endif
++
++  switch HB_CODEPOINT_ENCODE3 (blob->length,
++                               face->table.GSUB->table.get_length (),
++                               face->table.GDEF->table.get_length ())
++  {
++    /* https://github.com/harfbuzz/harfbuzz/issues/4108
++       sha1sum:a71ca6813b7e56a772cffff7c24a5166b087197c  AALMAGHRIBI.ttf */
++    case HB_CODEPOINT_ENCODE3 (19892, 2794, 340):
++      return true;
++  }
++  return false;
++}
++
++bool
++AAT::mort::is_blocklisted (hb_blob_t *blob,
++                           hb_face_t *face) const
++{
++#ifdef HB_NO_AAT_LAYOUT_BLOCKLIST
++  return false;
++#endif
++  return false;
++}
++
+ void
+ hb_aat_layout_compile_map (const hb_aat_map_builder_t *mapper,
+                            hb_aat_map_t *map)
+ {
+-  const AAT::morx& morx = *mapper->face->table.morx;
++  const AAT::morx& morx = *mapper->face->table.morx->table;
+   if (morx.has_data ())
+   {
+     morx.compile_flags (mapper, map);
+     return;
+   }
+ 
+-  const AAT::mort& mort = *mapper->face->table.mort;
++  const AAT::mort& mort = *mapper->face->table.mort->table;
+   if (mort.has_data ())
+   {
+     mort.compile_flags (mapper, map);
+@@ -243,8 +276,8 @@ hb_aat_layout_compile_map (const hb_aat_map_builder_t *mapper,
+ hb_bool_t
+ hb_aat_layout_has_substitution (hb_face_t *face)
+ {
+-  return face->table.morx->has_data () ||
+-         face->table.mort->has_data ();
++  return face->table.morx->table->has_data () ||
++         face->table.mort->table->has_data ();
+ }
+ 
+ void
+@@ -260,26 +293,30 @@ hb_aat_layout_substitute (const hb_ot_shape_plan_t *plan,
+   hb_aat_map_t map;
+   builder.compile (map);
+ 
+-  hb_blob_t *morx_blob = font->face->table.morx.get_blob ();
+-  const AAT::morx& morx = *morx_blob->as ();
+-  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, map);
+-    (void) buffer->message (font, "end table morx");
+-    return;
++    auto &accel = *font->face->table.morx;
++    const AAT::morx& morx = *accel.table;
++    if (morx.has_data ())
++    {
++      AAT::hb_aat_apply_context_t c (plan, font, buffer, accel.get_blob ());
++      if (!buffer->message (font, "start table morx")) return;
++      morx.apply (&c, map, accel);
++      (void) buffer->message (font, "end table morx");
++      return;
++    }
+   }
+ 
+-  hb_blob_t *mort_blob = font->face->table.mort.get_blob ();
+-  const AAT::mort& mort = *mort_blob->as ();
+-  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, map);
+-    (void) buffer->message (font, "end table mort");
+-    return;
++    auto &accel = *font->face->table.mort;
++    const AAT::mort& mort = *accel.table;
++    if (mort.has_data ())
++    {
++      AAT::hb_aat_apply_context_t c (plan, font, buffer, accel.get_blob ());
++      if (!buffer->message (font, "start table mort")) return;
++      mort.apply (&c, map, accel);
++      (void) buffer->message (font, "end table mort");
++      return;
++    }
+   }
+ }
+ 
+@@ -322,7 +359,7 @@ hb_aat_layout_remove_deleted_glyphs (hb_buffer_t *buffer)
+ hb_bool_t
+ hb_aat_layout_has_positioning (hb_face_t *face)
+ {
+-  return face->table.kerx->has_data ();
++  return face->table.kerx->table->has_data ();
+ }
+ 
+ void
+@@ -330,13 +367,12 @@ hb_aat_layout_position (const hb_ot_shape_plan_t *plan,
+                         hb_font_t *font,
+                         hb_buffer_t *buffer)
+ {
+-  hb_blob_t *kerx_blob = font->face->table.kerx.get_blob ();
+-  const AAT::kerx& kerx = *kerx_blob->as ();
++  auto &accel = *font->face->table.kerx;
+ 
+-  AAT::hb_aat_apply_context_t c (plan, font, buffer, kerx_blob);
++  AAT::hb_aat_apply_context_t c (plan, font, buffer, accel.get_blob ());
+   if (!buffer->message (font, "start table kerx")) return;
+   c.set_ankr_table (font->face->table.ankr.get ());
+-  kerx.apply (&c);
++  accel.apply (&c);
+   (void) buffer->message (font, "end table kerx");
+ }
+ 
+@@ -358,17 +394,6 @@ hb_aat_layout_has_tracking (hb_face_t *face)
+   return face->table.trak->has_data ();
+ }
+ 
+-void
+-hb_aat_layout_track (const hb_ot_shape_plan_t *plan,
+-                     hb_font_t *font,
+-                     hb_buffer_t *buffer)
+-{
+-  const AAT::trak& trak = *font->face->table.trak;
+-
+-  AAT::hb_aat_apply_context_t c (plan, font, buffer);
+-  trak.apply (&c);
+-}
+-
+ /**
+  * hb_aat_layout_get_feature_types:
+  * @face: #hb_face_t to work upon
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-aat-layout.h b/src/java.desktop/share/native/libharfbuzz/hb-aat-layout.h
+index c833ea8f6..88e040d7e 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-aat-layout.h
++++ b/src/java.desktop/share/native/libharfbuzz/hb-aat-layout.h
+@@ -40,7 +40,7 @@ HB_BEGIN_DECLS
+  * @HB_AAT_LAYOUT_FEATURE_TYPE_INVALID: Initial, unset feature type
+  * @HB_AAT_LAYOUT_FEATURE_TYPE_ALL_TYPOGRAPHIC: [All Typographic Features](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type0)
+  * @HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES: [Ligatures](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type1)
+- * @HB_AAT_LAYOUT_FEATURE_TYPE_CURISVE_CONNECTION: [Cursive Connection](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type2)
++ * @HB_AAT_LAYOUT_FEATURE_TYPE_CURSIVE_CONNECTION: [Cursive Connection](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type2)
+  * @HB_AAT_LAYOUT_FEATURE_TYPE_LETTER_CASE: [Letter Case](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type3)
+  * @HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_SUBSTITUTION: [Vertical Substitution](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type4)
+  * @HB_AAT_LAYOUT_FEATURE_TYPE_LINGUISTIC_REARRANGEMENT: [Linguistic Rearrangement](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type5)
+@@ -88,7 +88,7 @@ typedef enum
+ 
+   HB_AAT_LAYOUT_FEATURE_TYPE_ALL_TYPOGRAPHIC                    = 0,
+   HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES                          = 1,
+-  HB_AAT_LAYOUT_FEATURE_TYPE_CURISVE_CONNECTION                 = 2,
++  HB_AAT_LAYOUT_FEATURE_TYPE_CURSIVE_CONNECTION                 = 2,
+   HB_AAT_LAYOUT_FEATURE_TYPE_LETTER_CASE                        = 3,
+   HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_SUBSTITUTION              = 4,
+   HB_AAT_LAYOUT_FEATURE_TYPE_LINGUISTIC_REARRANGEMENT           = 5,
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-aat-layout.hh b/src/java.desktop/share/native/libharfbuzz/hb-aat-layout.hh
+index 36bb0ef07..ee3322365 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-aat-layout.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-aat-layout.hh
+@@ -32,6 +32,9 @@
+ #include "hb-ot-shape.hh"
+ #include "hb-aat-ltag-table.hh"
+ 
++/* https://developer.apple.com/documentation/coretext/1508745-ctfontcreatewithgraphicsfont */
++#define HB_CORETEXT_DEFAULT_FONT_SIZE 12.f
++
+ struct hb_aat_feature_mapping_t
+ {
+   hb_tag_t otFeatureTag;
+@@ -68,10 +71,5 @@ hb_aat_layout_position (const hb_ot_shape_plan_t *plan,
+                         hb_font_t *font,
+                         hb_buffer_t *buffer);
+ 
+-HB_INTERNAL void
+-hb_aat_layout_track (const hb_ot_shape_plan_t *plan,
+-                     hb_font_t *font,
+-                     hb_buffer_t *buffer);
+-
+ 
+ #endif /* HB_AAT_LAYOUT_HH */
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-aat-ltag-table.hh b/src/java.desktop/share/native/libharfbuzz/hb-aat-ltag-table.hh
+index 17b341ef2..da4dcb121 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-aat-ltag-table.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-aat-ltag-table.hh
+@@ -46,7 +46,9 @@ struct FTStringRange
+   bool sanitize (hb_sanitize_context_t *c, const void *base) const
+   {
+     TRACE_SANITIZE (this);
+-    return_trace (c->check_struct (this) && (base+tag).sanitize (c, length));
++    return_trace (c->check_struct (this) &&
++                  hb_barrier () &&
++                  (base+tag).sanitize (c, length));
+   }
+ 
+   protected:
+@@ -73,6 +75,7 @@ struct ltag
+   {
+     TRACE_SANITIZE (this);
+     return_trace (likely (c->check_struct (this) &&
++                          hb_barrier () &&
+                           version >= 1 &&
+                           tagRanges.sanitize (c, this)));
+   }
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-aat-map.cc b/src/java.desktop/share/native/libharfbuzz/hb-aat-map.cc
+index 122f29dc6..e0e9d14d9 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-aat-map.cc
++++ b/src/java.desktop/share/native/libharfbuzz/hb-aat-map.cc
+@@ -88,22 +88,23 @@ hb_aat_map_builder_t::compile (hb_aat_map_t  &m)
+ 
+   /* Sort features by start/end events. */
+   hb_vector_t feature_events;
++  feature_events.alloc_exact (features.length * 2 + 1);
+   for (unsigned int i = 0; i < features.length; i++)
+   {
+-    auto &feature = features[i];
++    auto &feature = features.arrayZ[i];
+ 
+-    if (features[i].start == features[i].end)
++    if (feature.start == feature.end)
+       continue;
+ 
+     feature_event_t *event;
+ 
+     event = feature_events.push ();
+-    event->index = features[i].start;
++    event->index = feature.start;
+     event->start = true;
+     event->feature = feature.info;
+ 
+     event = feature_events.push ();
+-    event->index = features[i].end;
++    event->index = feature.end;
+     event->start = false;
+     event->feature = feature.info;
+   }
+@@ -139,12 +140,12 @@ hb_aat_map_builder_t::compile (hb_aat_map_t  &m)
+         current_features.qsort ();
+         unsigned int j = 0;
+         for (unsigned int i = 1; i < current_features.length; i++)
+-          if (current_features[i].type != current_features[j].type ||
++          if (current_features.arrayZ[i].type != current_features.arrayZ[j].type ||
+               /* Nonexclusive feature selectors come in even/odd pairs to turn a setting on/off
+                * respectively, so we mask out the low-order bit when checking for "duplicates"
+                * (selectors referring to the same feature setting) here. */
+-              (!current_features[i].is_exclusive && ((current_features[i].setting & ~1) != (current_features[j].setting & ~1))))
+-            current_features[++j] = current_features[i];
++              (!current_features.arrayZ[i].is_exclusive && ((current_features.arrayZ[i].setting & ~1) != (current_features.arrayZ[j].setting & ~1))))
++            current_features.arrayZ[++j] = current_features.arrayZ[i];
+         current_features.shrink (j + 1);
+       }
+ 
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-algs.hh b/src/java.desktop/share/native/libharfbuzz/hb-algs.hh
+index b2b7c2567..6e250bfde 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-algs.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-algs.hh
+@@ -202,8 +202,12 @@ struct BEInt
+ /* Floats. */
+ 
+ /* We want our rounding towards +infinity. */
++static inline double
++_hb_roundf (double x) { return floor (x + .5); }
++
+ static inline float
+ _hb_roundf (float x) { return floorf (x + .5f); }
++
+ #define roundf(x) _hb_roundf(x)
+ 
+ 
+@@ -282,7 +286,7 @@ HB_FUNCOBJ (hb_bool);
+ 
+ // Compression function for Merkle-Damgard construction.
+ // This function is generated using the framework provided.
+-#define mix(h) (                                        \
++#define fasthash_mix(h) (                                       \
+                         (void) ((h) ^= (h) >> 23),              \
+                         (void) ((h) *= 0x2127599bf4325c37ULL),  \
+                         (h) ^= (h) >> 47)
+@@ -306,7 +310,7 @@ static inline uint64_t fasthash64(const void *buf, size_t len, uint64_t seed)
+ #pragma GCC diagnostic ignored "-Wcast-align"
+             v  = * (const uint64_t *) (pos++);
+ #pragma GCC diagnostic pop
+-            h ^= mix(v);
++            h ^= fasthash_mix(v);
+             h *= m;
+           }
+         }
+@@ -316,7 +320,7 @@ static inline uint64_t fasthash64(const void *buf, size_t len, uint64_t seed)
+           while (pos != end)
+           {
+             v  = pos++->v;
+-            h ^= mix(v);
++            h ^= fasthash_mix(v);
+             h *= m;
+           }
+         }
+@@ -332,11 +336,11 @@ static inline uint64_t fasthash64(const void *buf, size_t len, uint64_t seed)
+         case 3: v ^= (uint64_t)pos2[2] << 16; HB_FALLTHROUGH;
+         case 2: v ^= (uint64_t)pos2[1] <<  8; HB_FALLTHROUGH;
+         case 1: v ^= (uint64_t)pos2[0];
+-                h ^= mix(v);
++                h ^= fasthash_mix(v);
+                 h *= m;
+         }
+ 
+-        return mix(h);
++        return fasthash_mix(h);
+ }
+ 
+ static inline uint32_t fasthash32(const void *buf, size_t len, uint32_t seed)
+@@ -671,7 +675,7 @@ struct hb_pair_t
+     return 0;
+   }
+ 
+-  friend void swap (hb_pair_t& a, hb_pair_t& b)
++  friend void swap (hb_pair_t& a, hb_pair_t& b) noexcept
+   {
+     hb_swap (a.first, b.first);
+     hb_swap (a.second, b.second);
+@@ -1053,6 +1057,18 @@ _hb_cmp_method (const void *pkey, const void *pval, Ts... ds)
+   return val.cmp (key, ds...);
+ }
+ 
++template 
++static int
++_hb_cmp_operator (const void *pkey, const void *pval)
++{
++  const K& key = * (const K*) pkey;
++  const V& val = * (const V*) pval;
++
++  if (key < val) return -1;
++  if (key > val) return  1;
++  return 0;
++}
++
+ template 
+ static inline bool
+ hb_bsearch_impl (unsigned *pos, /* Out */
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-array.hh b/src/java.desktop/share/native/libharfbuzz/hb-array.hh
+index 439f18259..d65bbc5c7 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-array.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-array.hh
+@@ -47,6 +47,8 @@ enum hb_not_found_t
+ template 
+ struct hb_array_t : hb_iter_with_fallback_t, Type&>
+ {
++  static constexpr bool realloc_move = true;
++
+   /*
+    * Constructors.
+    */
+@@ -249,7 +251,8 @@ struct hb_array_t : hb_iter_with_fallback_t, Type&>
+     if (end < start + 2)
+       return;
+ 
+-    for (unsigned lhs = start, rhs = end - 1; lhs < rhs; lhs++, rhs--)
++    unsigned stop = start + (end - start) / 2;
++    for (unsigned lhs = start, rhs = end - 1; lhs < stop; lhs++, rhs--)
+       hb_swap (arrayZ[rhs], arrayZ[lhs]);
+   }
+ 
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-atomic.hh b/src/java.desktop/share/native/libharfbuzz/hb-atomic.hh
+index 459d82e0f..d2de5f693 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-atomic.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-atomic.hh
+@@ -118,12 +118,12 @@ _hb_atomic_ptr_impl_cmplexch (const void **P, const void *O_, const void *N)
+  */
+ #ifndef _hb_compiler_memory_r_barrier
+ #if defined(__ATOMIC_ACQUIRE) // gcc-like
+-#define _hb_compiler_memory_r_barrier() asm volatile("": : :"memory")
++static inline void _hb_compiler_memory_r_barrier () { asm volatile("": : :"memory"); }
+ #elif !defined(_MSC_VER)
+ #include 
+ #define _hb_compiler_memory_r_barrier() std::atomic_signal_fence (std::memory_order_acquire)
+ #else
+-#define _hb_compiler_memory_r_barrier() do {} while (0)
++static inline void _hb_compiler_memory_r_barrier () {}
+ #endif
+ #endif
+ 
+@@ -212,11 +212,18 @@ struct hb_atomic_ptr_t
+   T *get_acquire () const { return (T *) hb_atomic_ptr_impl_get ((void **) &v); }
+   bool cmpexch (const T *old, T *new_) const { return hb_atomic_ptr_impl_cmpexch ((void **) &v, (void *) old, (void *) new_); }
+ 
++  operator bool () const { return get_acquire () != nullptr; }
+   T * operator -> () const                    { return get_acquire (); }
+   template  operator C * () const { return get_acquire (); }
+ 
+   T *v = nullptr;
+ };
+ 
++static inline bool hb_barrier ()
++{
++  _hb_compiler_memory_r_barrier ();
++  return true;
++}
++
+ 
+ #endif /* HB_ATOMIC_HH */
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-bit-page.hh b/src/java.desktop/share/native/libharfbuzz/hb-bit-page.hh
+index 404a19ce5..9562a9674 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-bit-page.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-bit-page.hh
+@@ -78,6 +78,28 @@ struct hb_vector_size_t
+   hb_vector_size_t operator ~ () const
+   { return process (hb_bitwise_neg); }
+ 
++  operator bool () const
++  {
++    for (unsigned int i = 0; i < ARRAY_LENGTH (v); i++)
++      if (v[i])
++        return true;
++    return false;
++  }
++  operator unsigned int () const
++  {
++    unsigned int r = 0;
++    for (unsigned int i = 0; i < ARRAY_LENGTH (v); i++)
++      r += hb_popcount (v[i]);
++    return r;
++  }
++  bool operator == (const hb_vector_size_t &o) const
++  {
++    for (unsigned int i = 0; i < ARRAY_LENGTH (v); i++)
++      if (v[i] != o.v[i])
++        return false;
++    return true;
++  }
++
+   hb_array_t iter () const
+   { return hb_array (v); }
+ 
+@@ -89,6 +111,8 @@ struct hb_vector_size_t
+ 
+ struct hb_bit_page_t
+ {
++  hb_bit_page_t () { init0 (); }
++
+   void init0 () { v.init0 (); population = 0; }
+   void init1 () { v.init1 (); population = PAGE_BITS; }
+ 
+@@ -101,10 +125,9 @@ struct hb_bit_page_t
+   bool is_empty () const
+   {
+     if (has_population ()) return !population;
+-    return
+-    + hb_iter (v)
+-    | hb_none
+-    ;
++    bool empty = !v;
++    if (empty) population = 0;
++    return empty;
+   }
+   uint32_t hash () const
+   {
+@@ -115,6 +138,10 @@ struct hb_bit_page_t
+   void del (hb_codepoint_t g) { elt (g) &= ~mask (g); dirty (); }
+   void set (hb_codepoint_t g, bool value) { if (value) add (g); else del (g); }
+   bool get (hb_codepoint_t g) const { return elt (g) & mask (g); }
++  bool may_have (hb_codepoint_t g) const { return get (g); }
++
++  bool operator [] (hb_codepoint_t g) const { return get (g); }
++  bool operator () (hb_codepoint_t g) const { return get (g); }
+ 
+   void add_range (hb_codepoint_t a, hb_codepoint_t b)
+   {
+@@ -220,13 +247,17 @@ struct hb_bit_page_t
+   }
+ 
+   bool operator == (const hb_bit_page_t &other) const { return is_equal (other); }
+-  bool is_equal (const hb_bit_page_t &other) const
++  bool is_equal (const hb_bit_page_t &other) const { return v == other.v; }
++  bool intersects (const hb_bit_page_t &other) const
+   {
+     for (unsigned i = 0; i < len (); i++)
+-      if (v[i] != other.v[i])
+-        return false;
+-    return true;
++      if (v[i] & other.v[i])
++        return true;
++    return false;
+   }
++  bool may_intersect (const hb_bit_page_t &other) const
++  { return intersects (other); }
++
+   bool operator <= (const hb_bit_page_t &larger_page) const { return is_subset (larger_page); }
+   bool is_subset (const hb_bit_page_t &larger_page) const
+   {
+@@ -241,14 +272,10 @@ struct hb_bit_page_t
+   }
+ 
+   bool has_population () const { return population != UINT_MAX; }
+-  unsigned int get_population () const
++  unsigned get_population () const
+   {
+     if (has_population ()) return population;
+-    population =
+-    + hb_iter (v)
+-    | hb_reduce ([] (unsigned pop, const elt_t &_) { return pop + hb_popcount (_); }, 0u)
+-    ;
+-    return population;
++    return population = v;
+   }
+ 
+   bool next (hb_codepoint_t *codepoint) const
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-bit-set-invertible.hh b/src/java.desktop/share/native/libharfbuzz/hb-bit-set-invertible.hh
+index 2e335549e..740a24376 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-bit-set-invertible.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-bit-set-invertible.hh
+@@ -39,10 +39,10 @@ struct hb_bit_set_invertible_t
+ 
+   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 (hb_bit_set_invertible_t&& other)  noexcept : 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)
++  hb_bit_set_invertible_t& operator= (hb_bit_set_invertible_t&& other)  noexcept { hb_swap (*this, other); return *this; }
++  friend void swap (hb_bit_set_invertible_t &a, hb_bit_set_invertible_t &b) noexcept
+   {
+     if (likely (!a.s.successful || !b.s.successful))
+       return;
+@@ -126,6 +126,7 @@ struct hb_bit_set_invertible_t
+   { 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; }
++  bool may_have (hb_codepoint_t g) const { return get (g); }
+ 
+   /* Has interface. */
+   bool operator [] (hb_codepoint_t k) const { return get (k); }
+@@ -139,6 +140,9 @@ struct hb_bit_set_invertible_t
+   hb_bit_set_invertible_t& operator << (const hb_codepoint_pair_t& range)
+   { add_range (range.first, range.second); return *this; }
+ 
++  bool may_intersect (const hb_bit_set_invertible_t &other) const
++  { return inverted || other.inverted || s.intersects (other.s); }
++
+   bool intersects (hb_codepoint_t first, hb_codepoint_t last) const
+   {
+     hb_codepoint_t c = first - 1;
+@@ -359,8 +363,8 @@ struct hb_bit_set_invertible_t
+     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); }
++    void __next__ () { s->next (&v); if (likely (l)) l--; }
++    void __prev__ () { s->previous (&v); l++; }
+     unsigned __len__ () const { return l; }
+     iter_t end () const { return iter_t (*s, false); }
+     bool operator != (const iter_t& o) const
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-bit-set.hh b/src/java.desktop/share/native/libharfbuzz/hb-bit-set.hh
+index b900711a3..c42e617f6 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-bit-set.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-bit-set.hh
+@@ -38,10 +38,10 @@ struct hb_bit_set_t
+   ~hb_bit_set_t () = default;
+ 
+   hb_bit_set_t (const hb_bit_set_t& other) : hb_bit_set_t () { set (other, true); }
+-  hb_bit_set_t ( hb_bit_set_t&& other) : hb_bit_set_t () { hb_swap (*this, other); }
++  hb_bit_set_t ( hb_bit_set_t&& other)  noexcept : 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)
++  hb_bit_set_t& operator= (hb_bit_set_t&& other)  noexcept { hb_swap (*this, other); return *this; }
++  friend void swap (hb_bit_set_t &a, hb_bit_set_t &b) noexcept
+   {
+     if (likely (!a.successful || !b.successful))
+       return;
+@@ -88,10 +88,11 @@ struct hb_bit_set_t
+   {
+     if (unlikely (!successful)) return false;
+ 
+-    if (pages.length == 0 && count == 1)
++    if (pages.length < count && count <= 2)
+       exact_size = true; // Most sets are small and local
+ 
+-    if (unlikely (!pages.resize (count, clear, exact_size) || !page_map.resize (count, clear, exact_size)))
++    if (unlikely (!pages.resize (count, clear, exact_size) ||
++        !page_map.resize (count, clear)))
+     {
+       pages.resize (page_map.length, clear, exact_size);
+       successful = false;
+@@ -297,9 +298,9 @@ struct hb_bit_set_t
+       unsigned int write_index = 0;
+       for (unsigned int i = 0; i < page_map.length; i++)
+       {
+-        int m = (int) page_map[i].major;
++        int m = (int) page_map.arrayZ[i].major;
+         if (m < ds || de < m)
+-          page_map[write_index++] = page_map[i];
++          page_map.arrayZ[write_index++] = page_map.arrayZ[i];
+       }
+       compact (compact_workspace, write_index);
+       resize (write_index);
+@@ -345,6 +346,7 @@ struct hb_bit_set_t
+       return false;
+     return page->get (g);
+   }
++  bool may_have (hb_codepoint_t g) const { return get (g); }
+ 
+   /* Has interface. */
+   bool operator [] (hb_codepoint_t k) const { return get (k); }
+@@ -358,6 +360,31 @@ struct hb_bit_set_t
+   hb_bit_set_t& operator << (const hb_codepoint_pair_t& range)
+   { add_range (range.first, range.second); return *this; }
+ 
++  bool intersects (const hb_bit_set_t &other) const
++  {
++    unsigned int na = pages.length;
++    unsigned int nb = other.pages.length;
++
++    unsigned int a = 0, b = 0;
++    for (; a < na && b < nb; )
++    {
++      if (page_map.arrayZ[a].major == other.page_map.arrayZ[b].major)
++      {
++        if (page_at (a).intersects (other.page_at (b)))
++          return true;
++        a++;
++        b++;
++      }
++      else if (page_map.arrayZ[a].major < other.page_map.arrayZ[b].major)
++        a++;
++      else
++        b++;
++    }
++    return false;
++  }
++  bool may_intersect (const hb_bit_set_t &other) const
++  { return intersects (other); }
++
+   bool intersects (hb_codepoint_t first, hb_codepoint_t last) const
+   {
+     hb_codepoint_t c = first - 1;
+@@ -389,7 +416,7 @@ struct hb_bit_set_t
+     {
+       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 ||
++      if (page_map.arrayZ[a].major != other.page_map.arrayZ[b].major ||
+           !page_at (a).is_equal (other.page_at (b)))
+         return false;
+       a++;
+@@ -412,8 +439,8 @@ struct hb_bit_set_t
+     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;
++      uint32_t spm = page_map.arrayZ[spi].major;
++      uint32_t lpm = larger_set.page_map.arrayZ[lpi].major;
+       auto sp = page_at (spi);
+ 
+       if (spm < lpm && !sp.is_empty ())
+@@ -503,7 +530,7 @@ struct hb_bit_set_t
+ 
+     for (; a < na && b < nb; )
+     {
+-      if (page_map[a].major == other.page_map[b].major)
++      if (page_map.arrayZ[a].major == other.page_map.arrayZ[b].major)
+       {
+         if (!passthru_left)
+         {
+@@ -512,7 +539,7 @@ struct hb_bit_set_t
+           // 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];
++            page_map.arrayZ[write_index] = page_map.arrayZ[a];
+           write_index++;
+         }
+ 
+@@ -520,7 +547,7 @@ struct hb_bit_set_t
+         a++;
+         b++;
+       }
+-      else if (page_map[a].major < other.page_map[b].major)
++      else if (page_map.arrayZ[a].major < other.page_map.arrayZ[b].major)
+       {
+         if (passthru_left)
+           count++;
+@@ -765,8 +792,8 @@ struct hb_bit_set_t
+     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);
++      uint32_t base = major_start (page_map.arrayZ[i].major);
++      unsigned int n = pages[page_map.arrayZ[i].index].write (base, start_page_value, out, size);
+       out += n;
+       size -= n;
+       start_page_value = 0;
+@@ -814,8 +841,8 @@ struct hb_bit_set_t
+     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];
++      const auto& map = page_map.arrayZ[(unsigned) i];
++      const auto& page = pages.arrayZ[map.index];
+ 
+       if (!page.is_empty ())
+         return map.major * page_t::PAGE_BITS + page.get_max ();
+@@ -961,7 +988,7 @@ struct hb_bit_set_t
+       return nullptr;
+ 
+     last_page_lookup = i;
+-    return &pages.arrayZ[page_map[i].index];
++    return &pages.arrayZ[page_map.arrayZ[i].index];
+   }
+   page_t &page_at (unsigned int i)
+   {
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-blob.cc b/src/java.desktop/share/native/libharfbuzz/hb-blob.cc
+index 2a43afa1a..a19599fac 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-blob.cc
++++ b/src/java.desktop/share/native/libharfbuzz/hb-blob.cc
+@@ -598,6 +598,11 @@ _open_resource_fork (const char *file_name, hb_mapped_file_t *file)
+  * Creates a new blob containing the data from the
+  * specified binary font file.
+  *
++ * The filename is passed directly to the system on all platforms,
++ * except on Windows, where the filename is interpreted as UTF-8.
++ * Only if the filename is not valid UTF-8, it will be interpreted
++ * according to the system codepage.
++ *
+  * Returns: An #hb_blob_t pointer with the content of the file,
+  * or hb_blob_get_empty() if failed.
+  *
+@@ -612,10 +617,14 @@ hb_blob_create_from_file (const char *file_name)
+ 
+ /**
+  * hb_blob_create_from_file_or_fail:
+- * @file_name: A font filename
++ * @file_name: A filename
+  *
+- * Creates a new blob containing the data from the
+- * specified binary font file.
++ * Creates a new blob containing the data from the specified file.
++ *
++ * The filename is passed directly to the system on all platforms,
++ * except on Windows, where the filename is interpreted as UTF-8.
++ * Only if the filename is not valid UTF-8, it will be interpreted
++ * according to the system codepage.
+  *
+  * Returns: An #hb_blob_t pointer with the content of the file,
+  * or `NULL` if failed.
+@@ -672,10 +681,19 @@ fail_without_close:
+   if (unlikely (!file)) return nullptr;
+ 
+   HANDLE fd;
++  int conversion;
+   unsigned int size = strlen (file_name) + 1;
+   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);
++
++  /* Assume file name is given in UTF-8 encoding */
++  conversion = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, file_name, -1, wchar_file_name, size);
++  if (conversion <= 0)
++  {
++    /* Conversion failed due to invalid UTF-8 characters,
++       Repeat conversion based on system code page */
++    mbstowcs(wchar_file_name, file_name, size);
++  }
+ #if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)
+   {
+     CREATEFILE2_EXTENDED_PARAMETERS ceparams = { 0 };
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-buffer-deserialize-json.hh b/src/java.desktop/share/native/libharfbuzz/hb-buffer-deserialize-json.hh
+index 2a90cbfe3..69cc16402 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-buffer-deserialize-json.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-buffer-deserialize-json.hh
+@@ -34,36 +34,36 @@
+ 
+ #line 36 "hb-buffer-deserialize-json.hh"
+ static const unsigned char _deserialize_json_trans_keys[] = {
+-        0u, 0u, 9u, 123u, 9u, 34u, 97u, 117u, 120u, 121u, 34u, 34u, 9u, 58u, 9u, 57u,
+-        48u, 57u, 9u, 125u, 9u, 125u, 9u, 93u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u,
++        0u, 0u, 9u, 123u, 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, 108u, 108u, 34u, 34u,
+         9u, 58u, 9u, 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, 123u, 0u, 0u, 0
++        9u, 93u, 9u, 123u, 0u, 0u, 0
+ };
+ 
+ static const char _deserialize_json_key_spans[] = {
+-        0, 115, 26, 21, 2, 1, 50, 49,
+-        10, 117, 117, 85, 117, 1, 50, 49,
++        0, 115, 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, 1,
+         50, 49, 117, 117, 1, 50, 49, 59,
+         117, 59, 117, 117, 1, 50, 49, 117,
+-        115, 0
++        85, 115, 0
+ };
+ 
+ static const short _deserialize_json_index_offsets[] = {
+-        0, 0, 116, 143, 165, 168, 170, 221,
+-        271, 282, 400, 518, 604, 722, 724, 775,
+-        825, 836, 954, 1072, 1074, 1076, 1127, 1177,
+-        1295, 1413, 1416, 1418, 1469, 1519, 1530, 1648,
+-        1766, 1768, 1819, 1869, 1880, 1998, 2116, 2118,
+-        2120, 2171, 2221, 2339, 2457, 2459, 2510, 2560,
+-        2620, 2738, 2798, 2916, 3034, 3036, 3087, 3137,
+-        3255, 3371
++        0, 0, 116, 232, 259, 281, 284, 286,
++        337, 387, 398, 516, 634, 752, 754, 805,
++        855, 866, 984, 1102, 1104, 1106, 1157, 1207,
++        1325, 1443, 1446, 1448, 1499, 1549, 1560, 1678,
++        1796, 1798, 1849, 1899, 1910, 2028, 2146, 2148,
++        2150, 2201, 2251, 2369, 2487, 2489, 2540, 2590,
++        2650, 2768, 2828, 2946, 3064, 3066, 3117, 3167,
++        3285, 3371, 3487
+ };
+ 
+ static const char _deserialize_json_indicies[] = {
+@@ -77,51 +77,51 @@ static const char _deserialize_json_indicies[] = {
+         1, 1, 1, 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, 1, 3, 1, 2, 2, 2,
++        2, 2, 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, 2, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+-        1, 1, 1, 1, 3, 1, 4, 1,
+-        5, 1, 6, 7, 1, 8, 9, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+-        1, 1, 1, 1, 10, 1, 11, 12,
+-        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, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+-        1, 1, 1, 1, 14, 1, 14, 14,
+-        14, 14, 14, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+-        1, 1, 1, 1, 1, 14, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+-        1, 1, 15, 1, 1, 16, 17, 17,
+-        17, 17, 17, 17, 17, 17, 17, 1,
+-        18, 19, 19, 19, 19, 19, 19, 19,
+-        19, 19, 1, 20, 20, 20, 20, 20,
+         1, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+-        1, 1, 20, 1, 1, 1, 1, 1,
+-        1, 1, 1, 1, 1, 1, 21, 1,
++        1, 1, 1, 1, 1, 1, 1, 3,
++        1, 4, 4, 4, 4, 4, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
++        4, 1, 5, 1, 6, 1, 7, 8,
++        1, 9, 10, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
++        11, 1, 12, 13, 1, 14, 1, 14,
++        14, 14, 14, 14, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
++        1, 1, 1, 1, 1, 1, 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,
++        15, 1, 15, 15, 15, 15, 15, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+-        1, 1, 1, 1, 1, 1, 1, 22,
+-        1, 23, 23, 23, 23, 23, 1, 1,
++        1, 15, 1, 1, 1, 1, 1, 1,
++        1, 1, 1, 1, 1, 1, 16, 1,
++        1, 17, 18, 18, 18, 18, 18, 18,
++        18, 18, 18, 1, 19, 20, 20, 20,
++        20, 20, 20, 20, 20, 20, 1, 21,
++        21, 21, 21, 21, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
++        1, 1, 1, 1, 1, 1, 21, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+-        23, 1, 1, 1, 1, 1, 1, 1,
+-        1, 1, 1, 1, 3, 1, 1, 1,
++        1, 1, 22, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+@@ -131,94 +131,99 @@ static const char _deserialize_json_indicies[] = {
+         1, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+-        1, 1, 1, 1, 1, 24, 1, 25,
+-        25, 25, 25, 25, 1, 1, 1, 1,
++        1, 1, 1, 23, 1, 24, 24, 24,
++        24, 24, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+-        1, 1, 1, 1, 1, 1, 25, 1,
++        1, 1, 1, 1, 24, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+-        1, 1, 26, 1, 1, 1, 1, 1,
++        4, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+-        1, 1, 1, 27, 1, 20, 20, 20,
+-        20, 20, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+-        1, 1, 1, 1, 20, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+-        21, 1, 1, 1, 19, 19, 19, 19,
+-        19, 19, 19, 19, 19, 19, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
++        1, 25, 1, 21, 21, 21, 21, 21,
+         1, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
++        1, 1, 21, 1, 1, 1, 1, 1,
++        1, 1, 1, 1, 1, 1, 22, 1,
++        1, 1, 20, 20, 20, 20, 20, 20,
++        20, 20, 20, 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, 22, 1, 28, 1, 28, 28, 28,
+-        28, 28, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+-        1, 1, 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, 29, 1,
+-        29, 29, 29, 29, 29, 1, 1, 1,
++        1, 1, 1, 1, 1, 1, 1, 23,
++        1, 26, 1, 26, 26, 26, 26, 26,
+         1, 1, 1, 1, 1, 1, 1, 1,
+-        1, 1, 1, 1, 1, 1, 1, 29,
+         1, 1, 1, 1, 1, 1, 1, 1,
+-        1, 1, 1, 1, 30, 1, 1, 31,
+-        32, 32, 32, 32, 32, 32, 32, 32,
+-        32, 1, 33, 34, 34, 34, 34, 34,
+-        34, 34, 34, 34, 1, 35, 35, 35,
+-        35, 35, 1, 1, 1, 1, 1, 1,
++        1, 1, 26, 1, 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, 1, 1, 1,
++        1, 1, 1, 1, 27, 1, 27, 27,
++        27, 27, 27, 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, 27, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
++        1, 1, 28, 1, 1, 29, 30, 30,
++        30, 30, 30, 30, 30, 30, 30, 1,
++        31, 32, 32, 32, 32, 32, 32, 32,
++        32, 32, 1, 33, 33, 33, 33, 33,
+         1, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
++        1, 1, 33, 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, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+-        1, 37, 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, 36, 1,
+-        1, 1, 34, 34, 34, 34, 34, 34,
+-        34, 34, 34, 34, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
++        1, 1, 1, 1, 1, 1, 1, 35,
++        1, 33, 33, 33, 33, 33, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
++        33, 1, 1, 1, 1, 1, 1, 1,
++        1, 1, 1, 1, 34, 1, 1, 1,
++        32, 32, 32, 32, 32, 32, 32, 32,
++        32, 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, 37,
+-        1, 38, 1, 39, 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, 40, 1,
+-        40, 40, 40, 40, 40, 1, 1, 1,
++        1, 1, 1, 1, 1, 35, 1, 36,
++        1, 37, 1, 37, 37, 37, 37, 37,
+         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, 37, 1, 1, 1, 1, 1,
++        1, 1, 1, 1, 1, 1, 1, 1,
++        1, 1, 1, 1, 1, 1, 1, 1,
++        1, 1, 1, 1, 38, 1, 38, 38,
++        38, 38, 38, 1, 1, 1, 1, 1,
++        1, 1, 1, 1, 1, 1, 1, 1,
++        1, 1, 1, 1, 1, 38, 1, 1,
++        1, 1, 1, 1, 1, 1, 1, 1,
++        1, 1, 1, 1, 1, 39, 40, 40,
++        40, 40, 40, 40, 40, 40, 40, 1,
++        41, 41, 41, 41, 41, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 41,
+-        42, 42, 42, 42, 42, 42, 42, 42,
+-        42, 1, 43, 43, 43, 43, 43, 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, 43, 1, 1, 1, 1, 1, 1,
+-        1, 1, 1, 1, 1, 44, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+@@ -227,15 +232,14 @@ static const char _deserialize_json_indicies[] = {
+         1, 1, 1, 1, 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, 41, 41,
++        41, 41, 41, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+-        1, 1, 1, 1, 1, 1, 45, 1,
+-        43, 43, 43, 43, 43, 1, 1, 1,
++        1, 1, 1, 1, 1, 41, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+-        1, 1, 1, 1, 1, 1, 1, 43,
++        1, 42, 1, 1, 1, 44, 44, 44,
++        44, 44, 44, 44, 44, 44, 44, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+-        1, 1, 1, 44, 1, 1, 1, 46,
+-        46, 46, 46, 46, 46, 46, 46, 46,
+-        46, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+@@ -243,26 +247,26 @@ static const char _deserialize_json_indicies[] = {
+         1, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+-        1, 1, 1, 1, 45, 1, 47, 48,
+-        1, 49, 1, 49, 49, 49, 49, 49,
++        1, 1, 43, 1, 45, 46, 1, 47,
++        1, 47, 47, 47, 47, 47, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+-        1, 1, 49, 1, 1, 1, 1, 1,
++        47, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+-        1, 1, 1, 1, 50, 1, 50, 50,
+-        50, 50, 50, 1, 1, 1, 1, 1,
++        1, 1, 48, 1, 48, 48, 48, 48,
++        48, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+-        1, 1, 1, 1, 1, 50, 1, 1,
++        1, 1, 1, 48, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+-        1, 1, 51, 1, 1, 52, 53, 53,
+-        53, 53, 53, 53, 53, 53, 53, 1,
+-        54, 55, 55, 55, 55, 55, 55, 55,
+-        55, 55, 1, 56, 56, 56, 56, 56,
++        49, 1, 1, 50, 51, 51, 51, 51,
++        51, 51, 51, 51, 51, 1, 52, 53,
++        53, 53, 53, 53, 53, 53, 53, 53,
++        1, 54, 54, 54, 54, 54, 1, 1,
+         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, 57, 1,
++        54, 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, 1, 1,
+@@ -272,14 +276,13 @@ static const char _deserialize_json_indicies[] = {
+         1, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+-        1, 1, 1, 1, 1, 1, 1, 58,
+-        1, 56, 56, 56, 56, 56, 1, 1,
++        1, 1, 1, 1, 1, 56, 1, 54,
++        54, 54, 54, 54, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
++        1, 1, 1, 1, 1, 1, 54, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+-        56, 1, 1, 1, 1, 1, 1, 1,
+-        1, 1, 1, 1, 57, 1, 1, 1,
+-        55, 55, 55, 55, 55, 55, 55, 55,
+-        55, 55, 1, 1, 1, 1, 1, 1,
++        1, 1, 55, 1, 1, 1, 53, 53,
++        53, 53, 53, 53, 53, 53, 53, 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,
+@@ -287,119 +290,120 @@ static const char _deserialize_json_indicies[] = {
+         1, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+-        1, 1, 1, 1, 1, 58, 1, 59,
+-        1, 59, 59, 59, 59, 59, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
++        1, 1, 1, 56, 1, 57, 1, 57,
++        57, 57, 57, 57, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+-        59, 1, 1, 1, 1, 1, 1, 1,
++        1, 1, 1, 1, 1, 1, 57, 1,
++        1, 1, 1, 1, 1, 1, 1, 1,
++        1, 1, 1, 1, 1, 1, 1, 1,
++        1, 1, 1, 1, 1, 1, 1, 1,
++        58, 1, 58, 58, 58, 58, 58, 1,
++        1, 1, 1, 1, 1, 1, 1, 1,
++        1, 1, 1, 1, 1, 1, 1, 1,
++        1, 58, 1, 1, 1, 1, 1, 1,
++        1, 1, 1, 1, 1, 1, 59, 1,
++        1, 60, 61, 61, 61, 61, 61, 61,
++        61, 61, 61, 1, 62, 63, 63, 63,
++        63, 63, 63, 63, 63, 63, 1, 64,
++        64, 64, 64, 64, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
++        1, 1, 1, 1, 1, 1, 64, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+-        1, 1, 60, 1, 60, 60, 60, 60,
+-        60, 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, 60, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+-        61, 1, 1, 62, 63, 63, 63, 63,
+-        63, 63, 63, 63, 63, 1, 64, 65,
+-        65, 65, 65, 65, 65, 65, 65, 65,
+-        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, 1, 1, 1, 1, 1, 1,
+-        1, 1, 1, 1, 67, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 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, 64, 64, 64,
++        64, 64, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
++        1, 1, 1, 1, 64, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
++        65, 1, 1, 1, 63, 63, 63, 63,
++        63, 63, 63, 63, 63, 63, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+-        1, 1, 1, 1, 1, 68, 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,
+         1, 1, 1, 1, 1, 1, 1, 1,
+-        1, 1, 67, 1, 1, 1, 65, 65,
+-        65, 65, 65, 65, 65, 65, 65, 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, 66, 1, 67, 1, 68, 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, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+-        1, 1, 1, 68, 1, 69, 1, 70,
+-        1, 70, 70, 70, 70, 70, 1, 1,
++        69, 1, 69, 69, 69, 69, 69, 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, 69, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
++        1, 70, 71, 71, 71, 71, 71, 71,
++        71, 71, 71, 1, 72, 72, 72, 72,
++        72, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+-        1, 1, 71, 1, 71, 71, 71, 71,
+-        71, 1, 1, 1, 1, 1, 1, 1,
++        1, 1, 1, 72, 1, 1, 1, 1,
++        1, 1, 1, 1, 1, 1, 1, 73,
+         1, 1, 1, 1, 1, 1, 1, 1,
+-        1, 1, 1, 71, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+-        1, 1, 1, 72, 73, 73, 73, 73,
+-        73, 73, 73, 73, 73, 1, 74, 74,
+-        74, 74, 74, 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, 75, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+         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, 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, 1, 73, 1, 1,
++        1, 75, 75, 75, 75, 75, 75, 75,
++        75, 75, 75, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+-        1, 1, 76, 1, 74, 74, 74, 74,
+-        74, 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, 75,
+-        1, 1, 1, 77, 77, 77, 77, 77,
+-        77, 77, 77, 77, 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, 74, 1,
++        76, 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, 1, 1, 1,
+-        76, 1, 78, 1, 78, 78, 78, 78,
+-        78, 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, 77, 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, 78, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+-        1, 1, 1, 1, 1, 79, 1, 79,
+-        79, 79, 79, 79, 1, 1, 1, 1,
++        1, 1, 1, 1, 79, 80, 80, 80,
++        80, 80, 80, 80, 80, 80, 1, 82,
++        81, 81, 81, 81, 81, 81, 81, 81,
++        81, 81, 81, 81, 81, 81, 81, 81,
++        81, 81, 81, 81, 81, 81, 81, 81,
++        81, 81, 81, 81, 81, 81, 81, 81,
++        81, 81, 81, 81, 81, 81, 81, 81,
++        81, 81, 81, 81, 81, 81, 81, 81,
++        81, 81, 81, 81, 81, 81, 81, 81,
++        81, 83, 81, 84, 84, 84, 84, 84,
+         1, 1, 1, 1, 1, 1, 1, 1,
+-        1, 1, 1, 1, 1, 1, 79, 1,
+-        80, 1, 1, 1, 1, 1, 1, 1,
+-        1, 1, 1, 1, 1, 1, 81, 82,
+-        82, 82, 82, 82, 82, 82, 82, 82,
+-        1, 84, 83, 83, 83, 83, 83, 83,
+-        83, 83, 83, 83, 83, 83, 83, 83,
+-        83, 83, 83, 83, 83, 83, 83, 83,
+-        83, 83, 83, 83, 83, 83, 83, 83,
+-        83, 83, 83, 83, 83, 83, 83, 83,
+-        83, 83, 83, 83, 83, 83, 83, 83,
+-        83, 83, 83, 83, 83, 83, 83, 83,
+-        83, 83, 83, 85, 83, 86, 86, 86,
+-        86, 86, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+-        1, 1, 1, 1, 86, 1, 1, 1,
++        1, 1, 84, 1, 1, 1, 1, 1,
++        1, 1, 1, 1, 1, 1, 85, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+-        87, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+@@ -408,20 +412,21 @@ static const char _deserialize_json_indicies[] = {
+         1, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
++        1, 1, 1, 1, 1, 1, 1, 86,
++        1, 81, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+-        1, 88, 1, 83, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 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, 87, 87, 87,
++        87, 87, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+-        1, 1, 1, 1, 1, 83, 1, 89,
+-        89, 89, 89, 89, 1, 1, 1, 1,
++        1, 1, 1, 1, 87, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+-        1, 1, 1, 1, 1, 1, 89, 1,
++        88, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+-        1, 1, 90, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+@@ -430,97 +435,107 @@ static const char _deserialize_json_indicies[] = {
+         1, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
++        1, 89, 1, 87, 87, 87, 87, 87,
+         1, 1, 1, 1, 1, 1, 1, 1,
+-        1, 1, 1, 91, 1, 89, 89, 89,
+-        89, 89, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+-        1, 1, 1, 1, 89, 1, 1, 1,
++        1, 1, 87, 1, 1, 1, 1, 1,
++        1, 1, 1, 1, 1, 1, 88, 1,
++        1, 1, 90, 90, 90, 90, 90, 90,
++        90, 90, 90, 90, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+-        90, 1, 1, 1, 92, 92, 92, 92,
+-        92, 92, 92, 92, 92, 92, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
++        1, 1, 1, 1, 1, 1, 1, 89,
++        1, 91, 1, 91, 91, 91, 91, 91,
+         1, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+-        1, 91, 1, 93, 1, 93, 93, 93,
+-        93, 93, 1, 1, 1, 1, 1, 1,
++        1, 1, 91, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+-        1, 1, 1, 1, 93, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
++        1, 1, 1, 1, 92, 1, 92, 92,
++        92, 92, 92, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+-        1, 1, 1, 1, 1, 1, 94, 1,
+-        94, 94, 94, 94, 94, 1, 1, 1,
++        1, 1, 1, 1, 1, 92, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+-        1, 1, 1, 1, 1, 1, 1, 94,
++        1, 1, 1, 1, 1, 93, 94, 94,
++        94, 94, 94, 94, 94, 94, 94, 1,
++        87, 87, 87, 87, 87, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+-        1, 1, 1, 1, 1, 1, 1, 95,
+-        96, 96, 96, 96, 96, 96, 96, 96,
+-        96, 1, 89, 89, 89, 89, 89, 1,
++        1, 1, 1, 1, 1, 1, 1, 87,
+         1, 1, 1, 1, 1, 1, 1, 1,
++        1, 1, 1, 88, 1, 1, 1, 95,
++        95, 95, 95, 95, 95, 95, 95, 95,
++        95, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+-        1, 89, 1, 1, 1, 1, 1, 1,
+-        1, 1, 1, 1, 1, 90, 1, 1,
+-        1, 97, 97, 97, 97, 97, 97, 97,
+-        97, 97, 97, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
++        1, 1, 1, 1, 89, 1, 96, 96,
++        96, 96, 96, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+-        1, 1, 1, 1, 1, 1, 91, 1,
+-        0, 0, 0, 0, 0, 1, 1, 1,
++        1, 1, 1, 1, 1, 96, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+-        1, 1, 1, 1, 1, 1, 1, 0,
++        1, 97, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
++        1, 1, 98, 1, 2, 2, 2, 2,
++        2, 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, 1, 1, 1, 1, 1, 1,
+         1, 1, 1, 1, 1, 1, 1, 1,
+-        1, 1, 2, 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, 3, 1,
++        1, 0
+ };
+ 
+ static const char _deserialize_json_trans_targs[] = {
+-        1, 0, 2, 2, 3, 4, 19, 25,
+-        38, 44, 52, 5, 13, 6, 7, 8,
+-        9, 12, 9, 12, 10, 2, 11, 10,
+-        11, 11, 56, 57, 14, 15, 16, 17,
+-        18, 17, 18, 10, 2, 11, 20, 21,
+-        22, 23, 24, 10, 2, 11, 24, 26,
+-        32, 27, 28, 29, 30, 31, 30, 31,
+-        10, 2, 11, 33, 34, 35, 36, 37,
+-        36, 37, 10, 2, 11, 39, 40, 41,
+-        42, 43, 10, 2, 11, 43, 45, 46,
+-        47, 50, 51, 47, 48, 49, 10, 2,
+-        11, 10, 2, 11, 51, 53, 54, 50,
+-        55, 55
++        1, 0, 2, 3, 3, 4, 5, 19,
++        25, 38, 44, 52, 6, 13, 7, 8,
++        9, 10, 12, 10, 12, 11, 3, 56,
++        11, 56, 14, 15, 16, 17, 18, 17,
++        18, 11, 3, 56, 20, 21, 22, 23,
++        24, 11, 3, 56, 24, 26, 32, 27,
++        28, 29, 30, 31, 30, 31, 11, 3,
++        56, 33, 34, 35, 36, 37, 36, 37,
++        11, 3, 56, 39, 40, 41, 42, 43,
++        11, 3, 56, 43, 45, 46, 47, 50,
++        51, 47, 48, 49, 11, 3, 56, 11,
++        3, 56, 51, 53, 54, 50, 55, 55,
++        56, 57, 58
+ };
+ 
+ static const char _deserialize_json_trans_actions[] = {
+-        0, 0, 1, 0, 0, 0, 0, 0,
+-        0, 0, 0, 0, 0, 0, 0, 2,
+-        2, 2, 0, 0, 3, 3, 4, 0,
+-        5, 0, 0, 0, 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, 0,
+-        2, 2, 14, 14, 15, 0, 0, 0,
+-        2, 16, 16, 0, 17, 0, 18, 18,
+-        19, 20, 20, 21, 17, 0, 0, 22,
+-        22, 23
++        0, 0, 0, 1, 0, 0, 0, 0,
++        0, 0, 0, 0, 0, 0, 0, 0,
++        2, 2, 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, 0, 2, 2,
++        14, 14, 15, 0, 0, 0, 2, 16,
++        16, 0, 17, 0, 18, 18, 19, 20,
++        20, 21, 17, 0, 0, 22, 22, 23,
++        0, 0, 0
+ };
+ 
+ static const int deserialize_json_start = 1;
+@@ -545,22 +560,17 @@ _hb_buffer_deserialize_json (hb_buffer_t *buffer,
+   /* Ensure we have positions. */
+   (void) hb_buffer_get_glyph_positions (buffer, nullptr);
+ 
+-  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 559 "hb-buffer-deserialize-json.hh"
++#line 569 "hb-buffer-deserialize-json.hh"
+         {
+         cs = deserialize_json_start;
+         }
+ 
+-#line 564 "hb-buffer-deserialize-json.hh"
++#line 574 "hb-buffer-deserialize-json.hh"
+         {
+         int _slen;
+         int _trans;
+@@ -772,7 +782,7 @@ _resume:
+         *end_ptr = p;
+ }
+         break;
+-#line 776 "hb-buffer-deserialize-json.hh"
++#line 786 "hb-buffer-deserialize-json.hh"
+         }
+ 
+ _again:
+@@ -784,7 +794,7 @@ _again:
+         _out: {}
+         }
+ 
+-#line 137 "hb-buffer-deserialize-json.rl"
++#line 132 "hb-buffer-deserialize-json.rl"
+ 
+ 
+   *end_ptr = p;
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-buffer-verify.cc b/src/java.desktop/share/native/libharfbuzz/hb-buffer-verify.cc
+index 3bdea30ed..3a4c9c9f3 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-buffer-verify.cc
++++ b/src/java.desktop/share/native/libharfbuzz/hb-buffer-verify.cc
+@@ -149,7 +149,7 @@ buffer_verify_unsafe_to_break (hb_buffer_t  *buffer,
+     }
+     assert (text_start < text_end);
+ 
+-    if (0)
++    if (false)
+       printf("start %u end %u text start %u end %u\n", start, end, text_start, text_end);
+ 
+     hb_buffer_clear_contents (fragment);
+@@ -288,7 +288,7 @@ buffer_verify_unsafe_to_concat (hb_buffer_t        *buffer,
+       }
+       assert (text_start < text_end);
+ 
+-      if (0)
++      if (false)
+         printf("start %u end %u text start %u end %u\n", start, end, text_start, text_end);
+ 
+ #if 0
+@@ -412,7 +412,7 @@ hb_buffer_t::verify (hb_buffer_t        *text_buffer,
+                                    &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);
++      buffer_verify_error (this, font, BUFFER_VERIFY_ERROR "text was: %s.", bytes.arrayZ ? bytes.arrayZ : "");
+     }
+ #endif
+   }
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-buffer.cc b/src/java.desktop/share/native/libharfbuzz/hb-buffer.cc
+index 5f9329e07..72970c9c2 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-buffer.cc
++++ b/src/java.desktop/share/native/libharfbuzz/hb-buffer.cc
+@@ -271,6 +271,7 @@ hb_buffer_t::similar (const hb_buffer_t &src)
+   replacement = src.replacement;
+   invisible = src.invisible;
+   not_found = src.not_found;
++  not_found_variation_selector = src.not_found_variation_selector;
+ }
+ 
+ void
+@@ -283,6 +284,7 @@ hb_buffer_t::reset ()
+   replacement = HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT;
+   invisible = 0;
+   not_found = 0;
++  not_found_variation_selector = HB_CODEPOINT_INVALID;
+ 
+   clear ();
+ }
+@@ -309,6 +311,7 @@ hb_buffer_t::clear ()
+ 
+   deallocate_var_all ();
+   serial = 0;
++  random_state = 1;
+   scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT;
+ }
+ 
+@@ -704,6 +707,7 @@ DEFINE_NULL_INSTANCE (hb_buffer_t) =
+   HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT,
+   0, /* invisible */
+   0, /* not_found */
++  HB_CODEPOINT_INVALID, /* not_found_variation_selector */
+ 
+ 
+   HB_BUFFER_CONTENT_TYPE_INVALID,
+@@ -1359,6 +1363,89 @@ hb_buffer_get_not_found_glyph (const hb_buffer_t *buffer)
+   return buffer->not_found;
+ }
+ 
++/**
++ * hb_buffer_set_not_found_variation_selector_glyph:
++ * @buffer: An #hb_buffer_t
++ * @not_found_variation_selector: the not-found-variation-selector #hb_codepoint_t
++ *
++ * Sets the #hb_codepoint_t that replaces variation-selector characters not resolved
++ * in the font during shaping.
++ *
++ * The not-found-variation-selector glyph defaults to #HB_CODEPOINT_INVALID,
++ * in which case an unresolved variation-selector will be removed from the glyph
++ * string during shaping. This API allows for changing that and retaining a glyph,
++ * such that the situation can be detected by the client and handled accordingly
++ * (e.g. by using a different font).
++ *
++ * Since: 10.0.0
++ **/
++void
++hb_buffer_set_not_found_variation_selector_glyph (hb_buffer_t    *buffer,
++                                                  hb_codepoint_t  not_found_variation_selector)
++{
++  buffer->not_found_variation_selector = not_found_variation_selector;
++}
++
++/**
++ * hb_buffer_get_not_found_variation_selector_glyph:
++ * @buffer: An #hb_buffer_t
++ *
++ * See hb_buffer_set_not_found_variation_selector_glyph().
++ *
++ * Return value:
++ * The @buffer not-found-variation-selector #hb_codepoint_t
++ *
++ * Since: 10.0.0
++ **/
++hb_codepoint_t
++hb_buffer_get_not_found_variation_selector_glyph (const hb_buffer_t *buffer)
++{
++  return buffer->not_found_variation_selector;
++}
++
++/**
++ * hb_buffer_set_random_state:
++ * @buffer: An #hb_buffer_t
++ * @state: the new random state
++ *
++ * Sets the random state of the buffer. The state changes
++ * every time a glyph uses randomness (eg. the `rand`
++ * OpenType feature). This function together with
++ * hb_buffer_get_random_state() allow for transferring
++ * the current random state to a subsequent buffer, to
++ * get better randomness distribution.
++ *
++ * Defaults to 1 and when buffer contents are cleared.
++ * A value of 0 disables randomness during shaping.
++ *
++ * Since: 8.4.0
++ **/
++void
++hb_buffer_set_random_state (hb_buffer_t    *buffer,
++                            unsigned        state)
++{
++  if (unlikely (hb_object_is_immutable (buffer)))
++    return;
++
++  buffer->random_state = state;
++}
++
++/**
++ * hb_buffer_get_random_state:
++ * @buffer: An #hb_buffer_t
++ *
++ * See hb_buffer_set_random_state().
++ *
++ * Return value:
++ * The @buffer random state
++ *
++ * Since: 8.4.0
++ **/
++unsigned
++hb_buffer_get_random_state (const hb_buffer_t *buffer)
++{
++  return buffer->random_state;
++}
+ 
+ /**
+  * hb_buffer_clear_contents:
+@@ -1896,7 +1983,7 @@ hb_buffer_add_codepoints (hb_buffer_t          *buffer,
+  * @buffer: An #hb_buffer_t
+  * @source: source #hb_buffer_t
+  * @start: start index into source buffer to copy.  Use 0 to copy from start of buffer.
+- * @end: end index into source buffer to copy.  Use @HB_FEATURE_GLOBAL_END to copy to end of buffer.
++ * @end: end index into source buffer to copy.  Use @UINT_MAX (or ((unsigned int) -1)) to copy to end of buffer.
+  *
+  * Append (part of) contents of another buffer to this buffer.
+  *
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-buffer.h b/src/java.desktop/share/native/libharfbuzz/hb-buffer.h
+index 6fc215d16..d2258634f 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-buffer.h
++++ b/src/java.desktop/share/native/libharfbuzz/hb-buffer.h
+@@ -487,6 +487,19 @@ hb_buffer_set_not_found_glyph (hb_buffer_t    *buffer,
+ HB_EXTERN hb_codepoint_t
+ hb_buffer_get_not_found_glyph (const hb_buffer_t *buffer);
+ 
++HB_EXTERN void
++hb_buffer_set_not_found_variation_selector_glyph (hb_buffer_t    *buffer,
++                                                  hb_codepoint_t  not_found_variation_selector);
++
++HB_EXTERN hb_codepoint_t
++hb_buffer_get_not_found_variation_selector_glyph (const hb_buffer_t *buffer);
++
++HB_EXTERN void
++hb_buffer_set_random_state (hb_buffer_t    *buffer,
++                            unsigned        state);
++
++HB_EXTERN unsigned
++hb_buffer_get_random_state (const hb_buffer_t *buffer);
+ 
+ /*
+  * Content API.
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-buffer.hh b/src/java.desktop/share/native/libharfbuzz/hb-buffer.hh
+index 7f8ce14e9..c92e7df32 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-buffer.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-buffer.hh
+@@ -32,7 +32,6 @@
+ 
+ #include "hb.hh"
+ #include "hb-unicode.hh"
+-#include "hb-set-digest.hh"
+ 
+ 
+ static_assert ((sizeof (hb_glyph_info_t) == 20), "");
+@@ -52,6 +51,7 @@ enum hb_buffer_scratch_flags_t {
+   HB_BUFFER_SCRATCH_FLAG_HAS_CGJ                        = 0x00000010u,
+   HB_BUFFER_SCRATCH_FLAG_HAS_GLYPH_FLAGS                = 0x00000020u,
+   HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE            = 0x00000040u,
++  HB_BUFFER_SCRATCH_FLAG_HAS_VARIATION_SELECTOR_FALLBACK= 0x00000080u,
+ 
+   /* Reserved for shapers' internal use. */
+   HB_BUFFER_SCRATCH_FLAG_SHAPER0                        = 0x01000000u,
+@@ -80,6 +80,7 @@ struct hb_buffer_t
+   hb_codepoint_t replacement; /* U+FFFD or something else. */
+   hb_codepoint_t invisible; /* 0 or something else. */
+   hb_codepoint_t not_found; /* 0 or something else. */
++  hb_codepoint_t not_found_variation_selector; /* HB_CODEPOINT_INVALID or something else. */
+ 
+   /*
+    * Buffer contents
+@@ -116,6 +117,7 @@ struct hb_buffer_t
+ 
+   uint8_t allocated_var_bits;
+   uint8_t serial;
++  uint32_t random_state;
+   hb_buffer_scratch_flags_t scratch_flags; /* Have space-fallback, etc. */
+   unsigned int max_len; /* Maximum allowed len. */
+   int max_ops; /* Maximum allowed operations. */
+@@ -179,22 +181,24 @@ struct hb_buffer_t
+     allocated_var_bits = 0;
+   }
+ 
++  HB_ALWAYS_INLINE
+   hb_glyph_info_t &cur (unsigned int i = 0) { return info[idx + i]; }
++  HB_ALWAYS_INLINE
+   hb_glyph_info_t cur (unsigned int i = 0) const { return info[idx + i]; }
+ 
++  HB_ALWAYS_INLINE
+   hb_glyph_position_t &cur_pos (unsigned int i = 0) { return pos[idx + i]; }
++  HB_ALWAYS_INLINE
+   hb_glyph_position_t cur_pos (unsigned int i = 0) const { return pos[idx + i]; }
+ 
++  HB_ALWAYS_INLINE
+   hb_glyph_info_t &prev ()      { return out_info[out_len ? out_len - 1 : 0]; }
++  HB_ALWAYS_INLINE
+   hb_glyph_info_t prev () const { return out_info[out_len ? out_len - 1 : 0]; }
+ 
+-  hb_set_digest_t digest () const
+-  {
+-    hb_set_digest_t d;
+-    d.init ();
+-    d.add_array (&info[0].codepoint, len, sizeof (info[0]));
+-    return d;
+-  }
++  template 
++  void collect_codepoints (set_t &d) const
++  { d.clear (); d.add_array (&info[0].codepoint, len, sizeof (info[0])); }
+ 
+   HB_INTERNAL void similar (const hb_buffer_t &src);
+   HB_INTERNAL void reset ();
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-cff-interp-common.hh b/src/java.desktop/share/native/libharfbuzz/hb-cff-interp-common.hh
+index 8d9ff5faf..79d7c4c71 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-cff-interp-common.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-cff-interp-common.hh
+@@ -522,7 +522,7 @@ struct parsed_values_t
+ 
+   void alloc (unsigned n)
+   {
+-    values.alloc (n, true);
++    values.alloc_exact (n);
+   }
+ 
+   void add_op (op_code_t op, const byte_str_ref_t& str_ref = byte_str_ref_t (), const VAL &v = VAL ())
+@@ -624,7 +624,6 @@ struct opset_t
+         } else {
+           /* invalid unknown operator */
+           env.clear_args ();
+-          env.set_error ();
+         }
+         break;
+     }
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-cff-interp-dict-common.hh b/src/java.desktop/share/native/libharfbuzz/hb-cff-interp-dict-common.hh
+index 0c0cec998..6a227e5e8 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-cff-interp-dict-common.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-cff-interp-dict-common.hh
+@@ -54,8 +54,8 @@ struct top_dict_values_t : dict_values_t
+   }
+   void fini () { dict_values_t::fini (); }
+ 
+-  unsigned int  charStringsOffset;
+-  unsigned int  FDArrayOffset;
++  int  charStringsOffset;
++  int  FDArrayOffset;
+ };
+ 
+ struct dict_opset_t : opset_t
+@@ -84,7 +84,7 @@ struct dict_opset_t : opset_t
+ 
+     enum Nibble { DECIMAL=10, EXP_POS, EXP_NEG, RESERVED, NEG, END };
+ 
+-    char buf[32];
++    char buf[32] = {0};
+     unsigned char byte = 0;
+     for (unsigned i = 0, count = 0; count < ARRAY_LENGTH (buf); ++i, ++count)
+     {
+@@ -157,11 +157,11 @@ struct top_dict_opset_t : dict_opset_t
+   {
+     switch (op) {
+       case OpCode_CharStrings:
+-        dictval.charStringsOffset = env.argStack.pop_uint ();
++        dictval.charStringsOffset = env.argStack.pop_int ();
+         env.clear_args ();
+         break;
+       case OpCode_FDArray:
+-        dictval.FDArrayOffset = env.argStack.pop_uint ();
++        dictval.FDArrayOffset = env.argStack.pop_int ();
+         env.clear_args ();
+         break;
+       case OpCode_FontMatrix:
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-cff2-interp-cs.hh b/src/java.desktop/share/native/libharfbuzz/hb-cff2-interp-cs.hh
+index c970633e0..ab17d6831 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-cff2-interp-cs.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-cff2-interp-cs.hh
+@@ -76,16 +76,12 @@ struct cff2_cs_interp_env_t : cs_interp_env_t
+     coords = coords_;
+     num_coords = num_coords_;
+     varStore = acc.varStore;
+-    seen_blend = false;
+-    seen_vsindex_ = false;
+-    scalars.init ();
+     do_blend = num_coords && coords && varStore->size;
+     set_ivs (acc.privateDicts[fd].ivs);
+   }
+ 
+   void fini ()
+   {
+-    scalars.fini ();
+     SUPER::fini ();
+   }
+ 
+@@ -168,13 +164,13 @@ struct cff2_cs_interp_env_t : cs_interp_env_t
+   protected:
+   const int     *coords;
+   unsigned int  num_coords;
+-  const  CFF2VariationStore *varStore;
++  const  CFF2ItemVariationStore *varStore;
+   unsigned int  region_count;
+   unsigned int  ivs;
+   hb_vector_t  scalars;
+   bool    do_blend;
+-  bool    seen_vsindex_;
+-  bool    seen_blend;
++  bool    seen_vsindex_ = false;
++  bool    seen_blend = false;
+ 
+   typedef cs_interp_env_t SUPER;
+ };
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-common.cc b/src/java.desktop/share/native/libharfbuzz/hb-common.cc
+index 3afab4284..bce0d09d2 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-common.cc
++++ b/src/java.desktop/share/native/libharfbuzz/hb-common.cc
+@@ -625,6 +625,9 @@ hb_script_get_horizontal_direction (hb_script_t script)
+     /* Unicode-14.0 additions */
+     case HB_SCRIPT_OLD_UYGHUR:
+ 
++    /* Unicode-16.0 additions */
++    case HB_SCRIPT_GARAY:
++
+       return HB_DIRECTION_RTL;
+ 
+ 
+@@ -996,7 +999,7 @@ hb_feature_to_string (hb_feature_t *feature,
+   if (feature->value > 1)
+   {
+     s[len++] = '=';
+-    len += hb_max (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->value));
++    len += hb_max (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%" PRIu32, feature->value));
+   }
+   assert (len < ARRAY_LENGTH (s));
+   len = hb_min (len, size - 1);
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-common.h b/src/java.desktop/share/native/libharfbuzz/hb-common.h
+index 0d7956764..a8bae366f 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-common.h
++++ b/src/java.desktop/share/native/libharfbuzz/hb-common.h
+@@ -47,14 +47,10 @@
+ # endif /* !__cplusplus */
+ #endif
+ 
+-#if defined (_SVR4) || defined (SVR4) || defined (__OpenBSD__) || \
+-    defined (_sgi) || defined (__sun) || defined (sun) || \
+-    defined (__digital__) || defined (__HP_cc)
+-#  include 
+-#elif defined (_AIX)
++#if defined (_AIX)
+ #  include 
+ #elif defined (_MSC_VER) && _MSC_VER < 1600
+-/* VS 2010 (_MSC_VER 1600) has stdint.h */
++/* VS 2010 (_MSC_VER 1600) has stdint.h   */
+ typedef __int8 int8_t;
+ typedef unsigned __int8 uint8_t;
+ typedef __int16 int16_t;
+@@ -63,10 +59,11 @@ typedef __int32 int32_t;
+ typedef unsigned __int32 uint32_t;
+ typedef __int64 int64_t;
+ typedef unsigned __int64 uint64_t;
+-#elif defined (__KERNEL__)
+-#  include 
+-#else
++#elif defined (_MSC_VER) && _MSC_VER < 1800
++/* VS 2013 (_MSC_VER 1800) has inttypes.h */
+ #  include 
++#else
++#  include 
+ #endif
+ 
+ #if defined(__GNUC__) && ((__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
+@@ -507,6 +504,13 @@ hb_language_matches (hb_language_t language,
+  * @HB_SCRIPT_MATH: `Zmth`, Since: 3.4.0
+  * @HB_SCRIPT_KAWI: `Kawi`, Since: 5.2.0
+  * @HB_SCRIPT_NAG_MUNDARI: `Nagm`, Since: 5.2.0
++ * @HB_SCRIPT_GARAY: `Gara`, Since: 10.0.0
++ * @HB_SCRIPT_GURUNG_KHEMA: `Gukh`, Since: 10.0.0
++ * @HB_SCRIPT_KIRAT_RAI: `Krai`, Since: 10.0.0
++ * @HB_SCRIPT_OL_ONAL: `Onao`, Since: 10.0.0
++ * @HB_SCRIPT_SUNUWAR: `Sunu`, Since: 10.0.0
++ * @HB_SCRIPT_TODHRI: `Todr`, Since: 10.0.0
++ * @HB_SCRIPT_TULU_TIGALARI: `Tutg`, Since: 10.0.0
+  * @HB_SCRIPT_INVALID: No script set
+  *
+  * Data type for scripts. Each #hb_script_t's value is an #hb_tag_t corresponding
+@@ -734,6 +738,17 @@ typedef enum
+   HB_SCRIPT_KAWI                        = HB_TAG ('K','a','w','i'), /*15.0*/
+   HB_SCRIPT_NAG_MUNDARI                 = HB_TAG ('N','a','g','m'), /*15.0*/
+ 
++  /*
++   * Since 10.0.0
++   */
++  HB_SCRIPT_GARAY                       = HB_TAG ('G','a','r','a'), /*16.0*/
++  HB_SCRIPT_GURUNG_KHEMA                = HB_TAG ('G','u','k','h'), /*16.0*/
++  HB_SCRIPT_KIRAT_RAI                   = HB_TAG ('K','r','a','i'), /*16.0*/
++  HB_SCRIPT_OL_ONAL                     = HB_TAG ('O','n','a','o'), /*16.0*/
++  HB_SCRIPT_SUNUWAR                     = HB_TAG ('S','u','n','u'), /*16.0*/
++  HB_SCRIPT_TODHRI                      = HB_TAG ('T','o','d','r'), /*16.0*/
++  HB_SCRIPT_TULU_TIGALARI               = HB_TAG ('T','u','t','g'), /*16.0*/
++
+   /* No script set. */
+   HB_SCRIPT_INVALID                     = HB_TAG_NONE,
+ 
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-config.hh b/src/java.desktop/share/native/libharfbuzz/hb-config.hh
+index 816c55c7d..40cc2403c 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-config.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-config.hh
+@@ -56,7 +56,6 @@
+ 
+ #ifdef HB_LEAN
+ #define HB_DISABLE_DEPRECATED
+-#define HB_NDEBUG
+ #define HB_NO_ATEXIT
+ #define HB_NO_BUFFER_MESSAGE
+ #define HB_NO_BUFFER_SERIALIZE
+@@ -69,8 +68,6 @@
+ #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
+ #define HB_NO_LAYOUT_RARELY_USED
+@@ -118,6 +115,10 @@
+ #define HB_NO_VAR_COMPOSITES
+ #endif
+ 
++#ifdef HB_NO_VAR
++#define HB_NO_VAR_COMPOSITES
++#endif
++
+ #ifdef HB_DISABLE_DEPRECATED
+ #define HB_IF_NOT_DEPRECATED(x)
+ #else
+@@ -156,6 +157,7 @@
+ #define HB_NO_FALLBACK_SHAPE
+ #define HB_NO_OT_KERN
+ #define HB_NO_OT_LAYOUT_BLOCKLIST
++#define HB_NO_AAT_LAYOUT_BLOCKLIST
+ #define HB_NO_OT_SHAPE_FALLBACK
+ #endif
+ 
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-cplusplus.hh b/src/java.desktop/share/native/libharfbuzz/hb-cplusplus.hh
+index eac4ff03e..82d397415 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-cplusplus.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-cplusplus.hh
+@@ -27,9 +27,6 @@
+ 
+ #include "hb.h"
+ 
+-HB_BEGIN_DECLS
+-HB_END_DECLS
+-
+ #ifdef __cplusplus
+ 
+ #include 
+@@ -56,15 +53,15 @@ struct shared_ptr
+ 
+   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 (shared_ptr &&o)  noexcept : 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& operator = (shared_ptr &&o)  noexcept { 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); }
++  void swap (shared_ptr &o)  noexcept { std::swap (p, o.p); }
++  friend void swap (shared_ptr &a, shared_ptr &b)  noexcept { std::swap (a.p, b.p); }
+ 
+   operator T * () const { return p; }
+   T& operator * () const { return *get (); }
+@@ -98,16 +95,16 @@ struct unique_ptr
+ 
+   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 (unique_ptr &&o)  noexcept : 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& operator = (unique_ptr &&o)  noexcept { 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); }
++  void swap (unique_ptr &o)  noexcept { std::swap (p, o.p); }
++  friend void swap (unique_ptr &a, unique_ptr &b)  noexcept { std::swap (a.p, b.p); }
+ 
+   operator T * () const { return p; }
+   T& operator * () const { return *get (); }
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-decycler.hh b/src/java.desktop/share/native/libharfbuzz/hb-decycler.hh
+new file mode 100644
+index 000000000..95b961027
+--- /dev/null
++++ b/src/java.desktop/share/native/libharfbuzz/hb-decycler.hh
+@@ -0,0 +1,164 @@
++/*
++ * Copyright © 2025 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.
++ *
++ * Author(s): Behdad Esfahbod
++ */
++
++#ifndef HB_DECYCLER_HH
++#define HB_DECYCLER_HH
++
++#include "hb.hh"
++
++/*
++ * hb_decycler_t is an efficient cycle detector for graph traversal.
++ * It's a simple tortoise-and-hare algorithm with a twist: it's
++ * designed to detect cycles while traversing a graph in a DFS manner,
++ * instead of just a linked list.
++ *
++ * For Floyd's tortoise and hare algorithm, see:
++ * https://en.wikipedia.org/wiki/Cycle_detection#Floyd's_tortoise_and_hare
++ *
++ * hb_decycler_t is O(n) in the number of nodes in the DFS traversal
++ * if there are no cycles. Unlike Floyd's algorithm, hb_decycler_t
++ * can be used in a DFS traversal, where the graph is not a simple
++ * linked list, but a tree with possible cycles.  Like Floyd's algorithm,
++ * it is constant-memory (~three  pointers).
++ *
++ * The decycler works by creating an implicit linked-list on the stack,
++ * of the path from the root to the current node, and apply Floyd's
++ * algorithm on that list as it goes.
++ *
++ * The decycler is malloc-free, and as such, much faster to use than a
++ * hb_set_t or hb_map_t equivalent.
++ *
++ * The decycler detects cycles in the graph *eventually*, not *immediately*.
++ * That is, it may not detect a cycle until the cycle is fully traversed,
++ * even multiple times. See Floyd's algorithm analysis for details.
++ *
++ * The implementation saves a pointer storage on the stack by combining
++ * this->u.decycler and this->u.next into a union.  This is possible because
++ * at any point we only need one of those values. The invariant is that
++ * after construction, and before destruction, of a node, the u.decycler
++ * field is always valid. The u.next field is only valid when the node is
++ * in the traversal path, parent to another node.
++ *
++ * There are three method's:
++ *
++ *   - hb_decycler_node_t() constructor: Creates a new node in the traversal.
++ *     The constructor takes a reference to the decycler object and inserts
++ *     itself as the latest node in the traversal path, by advancing the hare
++ *     pointer, and for every other descent, advancing the tortoise pointer.
++ *
++ *   - ~hb_decycler_node_t() destructor: Restores the decycler object to its
++ *      previous state by removing the node from the traversal path.
++ *
++ *   - bool visit(uintptr_t value): Called on every node in the graph.  Returns
++ *     true if the node is not part of a cycle, and false if it is.  The value
++ *     parameter is used to detect cycles.  It's the caller's responsibility
++ *     to ensure that the value is unique for each node in the graph.
++ *     The cycle detection is as simple as comparing the value to the value
++ *     held by the tortoise pointer, which is the Floyd's algorithm.
++ *
++ * For usage examples see test-decycler.cc.
++ */
++
++struct hb_decycler_node_t;
++
++struct hb_decycler_t
++{
++  friend struct hb_decycler_node_t;
++
++  private:
++  bool tortoise_awake = false;
++  hb_decycler_node_t *tortoise = nullptr;
++  hb_decycler_node_t *hare = nullptr;
++};
++
++struct hb_decycler_node_t
++{
++  hb_decycler_node_t (hb_decycler_t &decycler)
++  {
++    u.decycler = &decycler;
++
++    decycler.tortoise_awake = !decycler.tortoise_awake;
++
++    if (!decycler.tortoise)
++    {
++      // First node.
++      assert (decycler.tortoise_awake);
++      assert (!decycler.hare);
++      decycler.tortoise = decycler.hare = this;
++      return;
++    }
++
++    if (decycler.tortoise_awake)
++      decycler.tortoise = decycler.tortoise->u.next; // Time to move.
++
++    this->prev = decycler.hare;
++    decycler.hare->u.next = this;
++    decycler.hare = this;
++  }
++
++  ~hb_decycler_node_t ()
++  {
++    hb_decycler_t &decycler = *u.decycler;
++
++    // Inverse of the constructor.
++
++    assert (decycler.hare == this);
++    decycler.hare = prev;
++    if (prev)
++      prev->u.decycler = &decycler;
++
++    assert (decycler.tortoise);
++    if (decycler.tortoise_awake)
++      decycler.tortoise = decycler.tortoise->prev;
++
++    decycler.tortoise_awake = !decycler.tortoise_awake;
++  }
++
++  bool visit (uintptr_t value_)
++  {
++    value = value_;
++
++    hb_decycler_t &decycler = *u.decycler;
++
++    if (decycler.tortoise == this)
++      return true; // First node; not a cycle.
++
++    if (decycler.tortoise->value == value)
++      return false; // Cycle detected.
++
++    return true;
++  }
++
++  private:
++  union {
++    hb_decycler_t *decycler;
++    hb_decycler_node_t *next;
++  } u = {nullptr};
++  hb_decycler_node_t *prev = nullptr;
++  uintptr_t value = 0;
++};
++
++#endif /* HB_DECYCLER_HH */
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-deprecated.h b/src/java.desktop/share/native/libharfbuzz/hb-deprecated.h
+index 200e8ff49..d854a2b16 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-deprecated.h
++++ b/src/java.desktop/share/native/libharfbuzz/hb-deprecated.h
+@@ -56,7 +56,7 @@ HB_BEGIN_DECLS
+ /**
+  * HB_SCRIPT_CANADIAN_ABORIGINAL:
+  *
+- * Use #HB_SCRIPT_CANADIAN_SYLLABICS instead:
++ * Use #HB_SCRIPT_CANADIAN_SYLLABICS instead.
+  *
+  * Deprecated: 0.9.20
+  */
+@@ -301,6 +301,15 @@ hb_font_get_glyph_shape (hb_font_t *font,
+                          hb_draw_funcs_t *dfuncs, void *draw_data);
+ 
+ 
++/**
++ * HB_AAT_LAYOUT_FEATURE_TYPE_CURISVE_CONNECTION:
++ *
++ * Use #HB_AAT_LAYOUT_FEATURE_TYPE_CURSIVE_CONNECTION instead.
++ *
++ * Deprecated: 8.3.0
++ */
++#define HB_AAT_LAYOUT_FEATURE_TYPE_CURISVE_CONNECTION HB_AAT_LAYOUT_FEATURE_TYPE_CURSIVE_CONNECTION
++
+ #endif
+ 
+ 
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-draw.h b/src/java.desktop/share/native/libharfbuzz/hb-draw.h
+index eba791d10..4556b082d 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-draw.h
++++ b/src/java.desktop/share/native/libharfbuzz/hb-draw.h
+@@ -70,7 +70,7 @@ typedef struct hb_draw_state_t {
+  *
+  * 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.}}
++#define HB_DRAW_STATE_DEFAULT {0, 0.f, 0.f, 0.f, 0.f, {0.}, {0.}, {0.}, {0.}, {0.}, {0.}, {0.}}
+ 
+ 
+ /**
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-draw.hh b/src/java.desktop/share/native/libharfbuzz/hb-draw.hh
+index e1adf9ddc..2c30843de 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-draw.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-draw.hh
+@@ -232,7 +232,7 @@ struct hb_draw_session_t
+     funcs->close_path (draw_data, st);
+   }
+ 
+-  protected:
++  public:
+   float slant;
+   bool not_slanted;
+   hb_draw_funcs_t *funcs;
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-face-builder.cc b/src/java.desktop/share/native/libharfbuzz/hb-face-builder.cc
+index ff723ac70..6b7e19130 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-face-builder.cc
++++ b/src/java.desktop/share/native/libharfbuzz/hb-face-builder.cc
+@@ -42,7 +42,7 @@
+ struct face_table_info_t
+ {
+   hb_blob_t* data;
+-  signed order;
++  unsigned order;
+ };
+ 
+ struct hb_face_builder_data_t
+@@ -153,6 +153,50 @@ _hb_face_builder_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void
+   return hb_blob_reference (data->tables[tag].data);
+ }
+ 
++static unsigned
++_hb_face_builder_get_table_tags (const hb_face_t *face HB_UNUSED,
++                                 unsigned int start_offset,
++                                 unsigned int *table_count,
++                                 hb_tag_t *table_tags,
++                                 void *user_data)
++{
++  hb_face_builder_data_t *data = (hb_face_builder_data_t *) user_data;
++
++  unsigned population = data->tables.get_population ();
++
++  if (!table_count)
++    return population;
++
++  if (unlikely (start_offset >= population))
++  {
++    if (table_count)
++      *table_count = 0;
++    return population;
++  }
++
++  // Sort the tags.
++  hb_vector_t sorted_tags;
++  data->tables.keys () | hb_sink (sorted_tags);
++  if (unlikely (sorted_tags.in_error ()))
++  {
++    // Not much to do...
++  }
++  sorted_tags.qsort ([] (const void* a, const void* b) {
++    return * (hb_tag_t *) a <  * (hb_tag_t *) b ? -1 :
++           * (hb_tag_t *) a == * (hb_tag_t *) b ?  0 :
++                                                  +1;
++  });
++
++  auto array = sorted_tags.as_array ().sub_array (start_offset, table_count);
++  auto out = hb_array (table_tags, *table_count);
++
++  + array.iter ()
++  | hb_sink (out)
++  ;
++
++  return population;
++}
++
+ 
+ /**
+  * hb_face_builder_create:
+@@ -171,9 +215,16 @@ hb_face_builder_create ()
+   hb_face_builder_data_t *data = _hb_face_builder_data_create ();
+   if (unlikely (!data)) return hb_face_get_empty ();
+ 
+-  return hb_face_create_for_tables (_hb_face_builder_reference_table,
+-                                    data,
+-                                    _hb_face_builder_data_destroy);
++  hb_face_t *face = hb_face_create_for_tables (_hb_face_builder_reference_table,
++                                               data,
++                                               _hb_face_builder_data_destroy);
++
++  hb_face_set_get_table_tags_func (face,
++                                   _hb_face_builder_get_table_tags,
++                                   data,
++                                   nullptr);
++
++  return face;
+ }
+ 
+ /**
+@@ -199,7 +250,7 @@ hb_face_builder_add_table (hb_face_t *face, hb_tag_t tag, hb_blob_t *blob)
+   hb_face_builder_data_t *data = (hb_face_builder_data_t *) face->user_data;
+ 
+   hb_blob_t* previous = data->tables.get (tag).data;
+-  if (!data->tables.set (tag, face_table_info_t {hb_blob_reference (blob), -1}))
++  if (!data->tables.set (tag, face_table_info_t {hb_blob_reference (blob), (unsigned) -1}))
+   {
+     hb_blob_destroy (blob);
+     return false;
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-face.cc b/src/java.desktop/share/native/libharfbuzz/hb-face.cc
+index bc19bb9d5..7967ae324 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-face.cc
++++ b/src/java.desktop/share/native/libharfbuzz/hb-face.cc
+@@ -90,10 +90,6 @@ DEFINE_NULL_INSTANCE (hb_face_t) =
+ {
+   HB_OBJECT_HEADER_STATIC,
+ 
+-  nullptr, /* reference_table_func */
+-  nullptr, /* user_data */
+-  nullptr, /* destroy */
+-
+   0,    /* index */
+   1000, /* upem */
+   0,    /* num_glyphs */
+@@ -110,8 +106,9 @@ DEFINE_NULL_INSTANCE (hb_face_t) =
+  *
+  * Variant of hb_face_create(), built for those cases where it is more
+  * convenient to provide data for individual tables instead of the whole font
+- * data. With the caveat that hb_face_get_table_tags() does not currently work
+- * with faces created this way.
++ * data. With the caveat that hb_face_get_table_tags() would not work
++ * with faces created this way. You can address that by calling the
++ * hb_face_set_get_table_tags_func() function and setting the appropriate callback.
+  *
+  * Creates a new face object from the specified @user_data and @reference_table_func,
+  * with the @destroy callback.
+@@ -194,6 +191,22 @@ _hb_face_for_data_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void
+   return blob;
+ }
+ 
++static unsigned
++_hb_face_for_data_get_table_tags (const hb_face_t *face HB_UNUSED,
++                                  unsigned int start_offset,
++                                  unsigned int *table_count,
++                                  hb_tag_t *table_tags,
++                                  void *user_data)
++{
++  hb_face_for_data_closure_t *data = (hb_face_for_data_closure_t *) user_data;
++
++  const OT::OpenTypeFontFile &ot_file = *data->blob->as ();
++  const OT::OpenTypeFontFace &ot_face = ot_file.get_face (data->index);
++
++  return ot_face.get_table_tags (start_offset, table_count, table_tags);
++}
++
++
+ /**
+  * hb_face_create:
+  * @blob: #hb_blob_t to work upon
+@@ -240,12 +253,73 @@ hb_face_create (hb_blob_t    *blob,
+   face = hb_face_create_for_tables (_hb_face_for_data_reference_table,
+                                     closure,
+                                     _hb_face_for_data_closure_destroy);
++  hb_face_set_get_table_tags_func (face,
++                                   _hb_face_for_data_get_table_tags,
++                                   closure,
++                                   nullptr);
+ 
+   face->index = index;
+ 
+   return face;
+ }
+ 
++/**
++ * hb_face_create_or_fail:
++ * @blob: #hb_blob_t to work upon
++ * @index: The index of the face within @blob
++ *
++ * Like hb_face_create(), but returns `NULL` if the blob data
++ * contains no usable font face at the specified index.
++ *
++ * Return value: (transfer full): The new face object, or `NULL` if
++ * no face is found at the specified index.
++ *
++ * Since: 10.1.0
++ **/
++hb_face_t *
++hb_face_create_or_fail (hb_blob_t    *blob,
++                        unsigned int  index)
++{
++  unsigned num_faces = hb_face_count (blob);
++  if (index >= num_faces)
++    return nullptr;
++
++  hb_face_t *face = hb_face_create (blob, index);
++  if (hb_object_is_immutable (face))
++    return nullptr;
++
++  return face;
++}
++
++#ifndef HB_NO_OPEN
++/**
++ * hb_face_create_from_file_or_fail:
++ * @file_name: A font filename
++ * @index: The index of the face within the file
++ *
++ * A thin wrapper around hb_blob_create_from_file_or_fail()
++ * followed by hb_face_create_or_fail().
++ *
++ * Return value: (transfer full): The new face object, or `NULL` if
++ * no face is found at the specified index or the file cannot be read.
++ *
++ * Since: 10.1.0
++ **/
++HB_EXTERN hb_face_t *
++hb_face_create_from_file_or_fail (const char   *file_name,
++                                  unsigned int  index)
++{
++  hb_blob_t *blob = hb_blob_create_from_file_or_fail (file_name);
++  if (unlikely (!blob))
++    return nullptr;
++
++  hb_face_t *face = hb_face_create_or_fail (blob, index);
++  hb_blob_destroy (blob);
++
++  return face;
++}
++#endif
++
+ /**
+  * hb_face_get_empty:
+  *
+@@ -306,6 +380,9 @@ hb_face_destroy (hb_face_t *face)
+   face->data.fini ();
+   face->table.fini ();
+ 
++  if (face->get_table_tags_destroy)
++    face->get_table_tags_destroy (face->get_table_tags_user_data);
++
+   if (face->destroy)
+     face->destroy (face->user_data);
+ 
+@@ -395,7 +472,8 @@ hb_face_is_immutable (const hb_face_t *face)
+  * @tag: The #hb_tag_t of the table to query
+  *
+  * Fetches a reference to the specified table within
+- * the specified face.
++ * the specified face. Returns an empty blob if referencing table data is not
++ * possible.
+  *
+  * Return value: (transfer full): A pointer to the @tag table within @face
+  *
+@@ -415,9 +493,10 @@ hb_face_reference_table (const hb_face_t *face,
+  * hb_face_reference_blob:
+  * @face: A face object
+  *
+- * Fetches a pointer to the binary blob that contains the
+- * specified face. Returns an empty blob if referencing face data is not
+- * possible.
++ * Fetches a pointer to the binary blob that contains the specified face.
++ * If referencing the face data is not possible, this function creates a blob
++ * out of individual table blobs if hb_face_get_table_tags() works with this
++ * face, otherwise it returns an empty blob.
+  *
+  * Return value: (transfer full): A pointer to the blob for @face
+  *
+@@ -426,7 +505,41 @@ hb_face_reference_table (const hb_face_t *face,
+ hb_blob_t *
+ hb_face_reference_blob (hb_face_t *face)
+ {
+-  return face->reference_table (HB_TAG_NONE);
++  hb_blob_t *blob = face->reference_table (HB_TAG_NONE);
++
++  if (blob == hb_blob_get_empty ())
++  {
++    // If referencing the face blob is not possible (e.g. not implemented by the
++    // font functions), use face builder to create a blob out of individual
++    // table blobs.
++    unsigned total_count = hb_face_get_table_tags (face, 0, nullptr, nullptr);
++    if (total_count)
++    {
++      hb_tag_t tags[64];
++      unsigned count = ARRAY_LENGTH (tags);
++      hb_face_t* builder = hb_face_builder_create ();
++
++      for (unsigned offset = 0; offset < total_count; offset += count)
++      {
++        hb_face_get_table_tags (face, offset, &count, tags);
++        if (unlikely (!count))
++          break; // Allocation error
++        for (unsigned i = 0; i < count; i++)
++        {
++          if (unlikely (!tags[i]))
++            continue;
++          hb_blob_t *table = hb_face_reference_table (face, tags[i]);
++          hb_face_builder_add_table (builder, tags[i], table);
++          hb_blob_destroy (table);
++        }
++      }
++
++      blob = hb_face_reference_blob (builder);
++      hb_face_destroy (builder);
++    }
++  }
++
++  return blob;
+ }
+ 
+ /**
+@@ -547,6 +660,38 @@ hb_face_get_glyph_count (const hb_face_t *face)
+   return face->get_num_glyphs ();
+ }
+ 
++/**
++ * hb_face_set_get_table_tags_func:
++ * @face: A face object
++ * @func: (closure user_data) (destroy destroy) (scope notified): The table-tag-fetching function
++ * @user_data: A pointer to the user data, to be destroyed by @destroy when not needed anymore
++ * @destroy: (nullable): A callback to call when @func is not needed anymore
++ *
++ * Sets the table-tag-fetching function for the specified face object.
++ *
++ * Since: 10.0.0
++ */
++HB_EXTERN void
++hb_face_set_get_table_tags_func (hb_face_t *face,
++                                 hb_get_table_tags_func_t func,
++                                 void                    *user_data,
++                                 hb_destroy_func_t        destroy)
++{
++  if (hb_object_is_immutable (face))
++  {
++    if (destroy)
++      destroy (user_data);
++    return;
++  }
++
++  if (face->get_table_tags_destroy)
++    face->get_table_tags_destroy (face->get_table_tags_user_data);
++
++  face->get_table_tags_func = func;
++  face->get_table_tags_user_data = user_data;
++  face->get_table_tags_destroy = destroy;
++}
++
+ /**
+  * hb_face_get_table_tags:
+  * @face: A face object
+@@ -568,19 +713,14 @@ hb_face_get_table_tags (const hb_face_t *face,
+                         unsigned int *table_count, /* IN/OUT */
+                         hb_tag_t     *table_tags /* OUT */)
+ {
+-  if (face->destroy != (hb_destroy_func_t) _hb_face_for_data_closure_destroy)
++  if (!face->get_table_tags_func)
+   {
+     if (table_count)
+       *table_count = 0;
+     return 0;
+   }
+ 
+-  hb_face_for_data_closure_t *data = (hb_face_for_data_closure_t *) face->user_data;
+-
+-  const OT::OpenTypeFontFile &ot_file = *data->blob->as ();
+-  const OT::OpenTypeFontFace &ot_face = ot_file.get_face (data->index);
+-
+-  return ot_face.get_table_tags (start_offset, table_count, table_tags);
++  return face->get_table_tags_func (face, start_offset, table_count, table_tags, face->get_table_tags_user_data);
+ }
+ 
+ 
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-face.h b/src/java.desktop/share/native/libharfbuzz/hb-face.h
+index 2e5fb1509..953298fa5 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-face.h
++++ b/src/java.desktop/share/native/libharfbuzz/hb-face.h
+@@ -59,15 +59,28 @@ HB_EXTERN hb_face_t *
+ hb_face_create (hb_blob_t    *blob,
+                 unsigned int  index);
+ 
++HB_EXTERN hb_face_t *
++hb_face_create_or_fail (hb_blob_t    *blob,
++                        unsigned int  index);
++
++HB_EXTERN hb_face_t *
++hb_face_create_from_file_or_fail (const char   *file_name,
++                                  unsigned int  index);
++
+ /**
+  * hb_reference_table_func_t:
+  * @face: an #hb_face_t to reference table for
+  * @tag: the tag of the table to reference
+  * @user_data: User data pointer passed by the caller
+  *
+- * Callback function for hb_face_create_for_tables().
++ * Callback function for hb_face_create_for_tables(). The @tag is the tag of the
++ * table to reference, and the special tag #HB_TAG_NONE is used to reference the
++ * blob of the face itself. If referencing the face blob is not possible, it is
++ * recommended to set hb_get_table_tags_func_t on the @face to allow
++ * hb_face_reference_blob() to create a face blob out of individual table blobs.
+  *
+- * Return value: (transfer full): A pointer to the @tag table within @face
++ * Return value: (transfer full): A pointer to the @tag table within @face or
++ * `NULL` if the table is not found or cannot be referenced.
+  *
+  * Since: 0.9.2
+  */
+@@ -135,6 +148,34 @@ hb_face_set_glyph_count (hb_face_t    *face,
+ HB_EXTERN unsigned int
+ hb_face_get_glyph_count (const hb_face_t *face);
+ 
++
++/**
++ * hb_get_table_tags_func_t:
++ * @face: A face object
++ * @start_offset: The index of first table tag to retrieve
++ * @table_count: (inout): Input = the maximum number of table tags to return;
++ *                Output = the actual number of table tags returned (may be zero)
++ * @table_tags: (out) (array length=table_count): The array of table tags found
++ * @user_data: User data pointer passed by the caller
++ *
++ * Callback function for hb_face_get_table_tags().
++ *
++ * Return value: Total number of tables, or zero if it is not possible to list
++ *
++ * Since: 10.0.0
++ */
++typedef unsigned int (*hb_get_table_tags_func_t) (const hb_face_t *face,
++                                                  unsigned int  start_offset,
++                                                  unsigned int *table_count, /* IN/OUT */
++                                                  hb_tag_t     *table_tags /* OUT */,
++                                                  void         *user_data);
++
++HB_EXTERN void
++hb_face_set_get_table_tags_func (hb_face_t *face,
++                                 hb_get_table_tags_func_t func,
++                                 void                    *user_data,
++                                 hb_destroy_func_t        destroy);
++
+ HB_EXTERN unsigned int
+ hb_face_get_table_tags (const hb_face_t *face,
+                         unsigned int  start_offset,
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-face.hh b/src/java.desktop/share/native/libharfbuzz/hb-face.hh
+index 4c6b252e8..4d12030f1 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-face.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-face.hh
+@@ -48,13 +48,17 @@ struct hb_face_t
+ {
+   hb_object_header_t header;
+ 
++  unsigned int index;                   /* Face index in a collection, zero-based. */
++  mutable hb_atomic_int_t upem;         /* Units-per-EM. */
++  mutable hb_atomic_int_t num_glyphs;   /* Number of glyphs. */
++
+   hb_reference_table_func_t  reference_table_func;
+   void                      *user_data;
+   hb_destroy_func_t          destroy;
+ 
+-  unsigned int index;                   /* Face index in a collection, zero-based. */
+-  mutable hb_atomic_int_t upem;         /* Units-per-EM. */
+-  mutable hb_atomic_int_t num_glyphs;   /* Number of glyphs. */
++  hb_get_table_tags_func_t   get_table_tags_func;
++  void                      *get_table_tags_user_data;
++  hb_destroy_func_t          get_table_tags_destroy;
+ 
+   hb_shaper_object_dataset_t data;/* Various shaper data. */
+   hb_ot_face_t table;                   /* All the face's tables. */
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-font.cc b/src/java.desktop/share/native/libharfbuzz/hb-font.cc
+index 9ce55bbeb..0c9084c57 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-font.cc
++++ b/src/java.desktop/share/native/libharfbuzz/hb-font.cc
+@@ -231,7 +231,7 @@ hb_font_get_glyph_v_advance_nil (hb_font_t      *font,
+                                  void           *user_data HB_UNUSED)
+ {
+   /* TODO use font_extents.ascender+descender */
+-  return font->y_scale;
++  return -font->y_scale;
+ }
+ 
+ static hb_position_t
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-font.hh b/src/java.desktop/share/native/libharfbuzz/hb-font.hh
+index c3198830c..8273f3475 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-font.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-font.hh
+@@ -651,7 +651,7 @@ struct hb_font_t
+   {
+     if (get_glyph_name (glyph, s, size)) return;
+ 
+-    if (size && snprintf (s, size, "gid%u", glyph) < 0)
++    if (size && snprintf (s, size, "gid%" PRIu32, glyph) < 0)
+       *s = '\0';
+   }
+ 
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ft.cc b/src/java.desktop/share/native/libharfbuzz/hb-ft.cc
+index 32f5d3012..b126d2022 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-ft.cc
++++ b/src/java.desktop/share/native/libharfbuzz/hb-ft.cc
+@@ -37,10 +37,15 @@
+ #include "hb-draw.hh"
+ #include "hb-font.hh"
+ #include "hb-machinery.hh"
++#ifndef HB_NO_AAT
++#include "hb-aat-layout-trak-table.hh"
++#endif
+ #include "hb-ot-os2-table.hh"
++#include "hb-ot-stat-table.hh"
+ #include "hb-ot-shaper-arabic-pua.hh"
+ #include "hb-paint.hh"
+ 
++#include FT_MODULE_H
+ #include FT_ADVANCES_H
+ #include FT_MULTIPLE_MASTERS_H
+ #include FT_OUTLINE_H
+@@ -225,7 +230,7 @@ _hb_ft_hb_font_check_changed (hb_font_t *font,
+  * Sets the FT_Load_Glyph load flags for the specified #hb_font_t.
+  *
+  * For more information, see
+- * https://www.freetype.org/freetype2/docs/reference/ft2-base_interface.html#ft_load_xxx
++ * 
+  *
+  * This function works with #hb_font_t objects created by
+  * hb_ft_font_create() or hb_ft_font_create_referenced().
+@@ -253,7 +258,7 @@ hb_ft_font_set_load_flags (hb_font_t *font, int load_flags)
+  * Fetches the FT_Load_Glyph load flags of the specified #hb_font_t.
+  *
+  * For more information, see
+- * https://www.freetype.org/freetype2/docs/reference/ft2-base_interface.html#ft_load_xxx
++ * 
+  *
+  * This function works with #hb_font_t objects created by
+  * hb_ft_font_create() or hb_ft_font_create_referenced().
+@@ -274,7 +279,7 @@ hb_ft_font_get_load_flags (hb_font_t *font)
+ }
+ 
+ /**
+- * hb_ft_font_get_face: (skip)
++ * hb_ft_font_get_ft_face: (skip)
+  * @font: #hb_font_t to work upon
+  *
+  * Fetches the FT_Face associated with the specified #hb_font_t
+@@ -285,10 +290,10 @@ hb_ft_font_get_load_flags (hb_font_t *font)
+  *
+  * Return value: (nullable): the FT_Face found or `NULL`
+  *
+- * Since: 0.9.2
++ * Since: 10.4.0
+  **/
+ FT_Face
+-hb_ft_font_get_face (hb_font_t *font)
++hb_ft_font_get_ft_face (hb_font_t *font)
+ {
+   if (unlikely (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy))
+     return nullptr;
+@@ -298,6 +303,31 @@ hb_ft_font_get_face (hb_font_t *font)
+   return ft_font->ft_face;
+ }
+ 
++#ifndef HB_DISABLE_DEPRECATED
++
++/**
++ * hb_ft_font_get_face: (skip)
++ * @font: #hb_font_t to work upon
++ *
++ * Fetches the FT_Face associated with the specified #hb_font_t
++ * font object.
++ *
++ * This function works with #hb_font_t objects created by
++ * hb_ft_font_create() or hb_ft_font_create_referenced().
++ *
++ * Return value: (nullable): the FT_Face found or `NULL`
++ *
++ * Since: 0.9.2
++ * Deprecated: 10.4.0: Use hb_ft_font_get_ft_face() instead.
++ **/
++FT_Face
++hb_ft_font_get_face (hb_font_t *font)
++{
++  return hb_ft_font_get_ft_face (font);
++}
++
++#endif
++
+ /**
+  * hb_ft_font_lock_face: (skip)
+  * @font: #hb_font_t to work upon
+@@ -501,6 +531,26 @@ hb_ft_get_glyph_h_advances (hb_font_t* font, void* font_data,
+       first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride);
+     }
+   }
++
++#ifndef HB_NO_AAT
++  /* According to Ned, trak is applied by default for "modern fonts", as detected by presence of STAT table. */
++#ifndef HB_NO_STYLE
++  bool apply_trak = font->face->table.STAT->has_data () && font->face->table.trak->has_data ();
++#else
++  bool apply_trak = false;
++#endif
++  if (apply_trak)
++  {
++    hb_position_t tracking = font->face->table.trak->get_h_tracking (font);
++    first_advance = orig_first_advance;
++    for (unsigned int i = 0; i < count; i++)
++    {
++      *first_advance += tracking;
++      first_glyph = &StructAtOffsetUnaligned (first_glyph, glyph_stride);
++      first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride);
++    }
++  }
++#endif
+ }
+ 
+ #ifndef HB_NO_VERTICAL
+@@ -537,7 +587,20 @@ hb_ft_get_glyph_v_advance (hb_font_t *font,
+    * have a Y growing upward.  Hence the extra negation. */
+ 
+   hb_position_t y_strength = font->y_scale >= 0 ? font->y_strength : -font->y_strength;
+-  return ((-v + (1<<9)) >> 10) + (font->embolden_in_place ? 0 : y_strength);
++  v = ((-v + (1<<9)) >> 10) + (font->embolden_in_place ? 0 : y_strength);
++
++#ifndef HB_NO_AAT
++  /* According to Ned, trak is applied by default for "modern fonts", as detected by presence of STAT table. */
++#ifndef HB_NO_STYLE
++  bool apply_trak = font->face->table.STAT->has_data () && font->face->table.trak->has_data ();
++#else
++  bool apply_trak = false;
++#endif
++  if (apply_trak)
++    v += font->face->table.trak->get_v_tracking (font);
++#endif
++
++  return v;
+ }
+ #endif
+ 
+@@ -930,11 +993,15 @@ hb_ft_paint_glyph (hb_font_t *font,
+   hb_lock_t lock (ft_font->lock);
+   FT_Face ft_face = ft_font->ft_face;
+ 
++  FT_Long load_flags = ft_font->load_flags | FT_LOAD_NO_BITMAP | FT_LOAD_COLOR;
++#if (FREETYPE_MAJOR*10000 + FREETYPE_MINOR*100 + FREETYPE_PATCH) >= 21301
++  load_flags |= FT_LOAD_NO_SVG;
++#endif
++
+   /* We release the lock before calling into glyph callbacks, such that
+    * eg. draw API can call back into the face.*/
+ 
+-  if (unlikely (FT_Load_Glyph (ft_face, gid,
+-                               ft_font->load_flags | FT_LOAD_COLOR)))
++  if (unlikely (FT_Load_Glyph (ft_face, gid, load_flags)))
+     return;
+ 
+   if (ft_face->glyph->format == FT_GLYPH_FORMAT_OUTLINE)
+@@ -1104,6 +1171,45 @@ _hb_ft_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data
+                          buffer, hb_free);
+ }
+ 
++static unsigned
++_hb_ft_get_table_tags (const hb_face_t *face HB_UNUSED,
++                       unsigned int start_offset,
++                       unsigned int *table_count,
++                       hb_tag_t *table_tags,
++                       void *user_data)
++{
++  FT_Face ft_face = (FT_Face) user_data;
++
++  FT_ULong population = 0;
++  FT_Sfnt_Table_Info (ft_face,
++                      0, // table_index; ignored
++                      nullptr,
++                      &population);
++
++  if (!table_count)
++    return population;
++  else
++    *table_count = 0;
++
++  if (unlikely (start_offset >= population))
++    return population;
++
++  unsigned end_offset = hb_min (start_offset + *table_count, (unsigned) population);
++  if (unlikely (end_offset < start_offset))
++    return population;
++
++  *table_count = end_offset - start_offset;
++  for (unsigned i = start_offset; i < end_offset; i++)
++  {
++    FT_ULong tag = 0, length;
++    FT_Sfnt_Table_Info (ft_face, i, &tag, &length);
++    table_tags[i - start_offset] = tag;
++  }
++
++  return population;
++}
++
++
+ /**
+  * hb_ft_face_create:
+  * @ft_face: (destroy destroy) (scope notified): FT_Face to work upon
+@@ -1145,6 +1251,7 @@ hb_ft_face_create (FT_Face           ft_face,
+     hb_blob_destroy (blob);
+   } else {
+     face = hb_face_create_for_tables (_hb_ft_reference_table, ft_face, destroy);
++    hb_face_set_get_table_tags_func (face, _hb_ft_get_table_tags, ft_face, nullptr);
+   }
+ 
+   hb_face_set_index (face, ft_face->face_index);
+@@ -1215,7 +1322,7 @@ hb_ft_face_finalize (void *arg)
+ hb_face_t *
+ hb_ft_face_create_cached (FT_Face ft_face)
+ {
+-  if (unlikely (!ft_face->generic.data || ft_face->generic.finalizer != (FT_Generic_Finalizer) hb_ft_face_finalize))
++  if (unlikely (!ft_face->generic.data || ft_face->generic.finalizer != hb_ft_face_finalize))
+   {
+     if (ft_face->generic.finalizer)
+       ft_face->generic.finalizer (ft_face);
+@@ -1245,7 +1352,7 @@ hb_ft_face_create_cached (FT_Face ft_face)
+  *
+  * If you know you have valid reasons not to use hb_ft_font_create_referenced(),
+  * then it is the client program's responsibility to destroy @ft_face
+- * after the #hb_font_t font object has been destroyed.
++ * only after the #hb_font_t font object has been destroyed.
+  *
+  * HarfBuzz will use the @destroy callback on the #hb_font_t font object
+  * if it is supplied when you use this function. However, even if @destroy
+@@ -1392,6 +1499,24 @@ hb_ft_font_create_referenced (FT_Face ft_face)
+   return hb_ft_font_create (ft_face, _hb_ft_face_destroy);
+ }
+ 
++
++static void * _hb_ft_alloc (FT_Memory memory, long size)
++{ return hb_malloc (size); }
++
++static void _hb_ft_free (FT_Memory memory, void *block)
++{ hb_free (block); }
++
++static void * _hb_ft_realloc (FT_Memory memory, long cur_size, long new_size, void *block)
++{ return hb_realloc (block, new_size); }
++
++static FT_MemoryRec_ m =
++{
++  nullptr,
++  _hb_ft_alloc,
++  _hb_ft_free,
++  _hb_ft_realloc
++};
++
+ static inline void free_static_ft_library ();
+ 
+ static struct hb_ft_library_lazy_loader_t : hb_lazy_loader_t,
+@@ -1400,16 +1525,19 @@ static struct hb_ft_library_lazy_loader_t : hb_lazy_loader_tgeneric.data);
++}
++
++static void
++destroy_ft_library (void *arg)
++{
++  FT_Done_Library ((FT_Library) arg);
++}
++
++/**
++ * hb_ft_face_create_from_file_or_fail:
++ * @file_name: A font filename
++ * @index: The index of the face within the file
++ *
++ * Creates an #hb_face_t face object from the specified
++ * font file and face index.
++ *
++ * This is similar in functionality to hb_face_create_from_file_or_fail(),
++ * but uses the FreeType library for loading the font file.
++ *
++ * Return value: (transfer full): The new face object, or `NULL` if
++ * no face is found at the specified index or the file cannot be read.
++ *
++ * Since: 10.1.0
++ */
++hb_face_t *
++hb_ft_face_create_from_file_or_fail (const char   *file_name,
++                                     unsigned int  index)
+ {
+-  return static_ft_library.get_unconst ();
++  FT_Library ft_library = reference_ft_library ();
++  if (unlikely (!ft_library))
++  {
++    DEBUG_MSG (FT, ft_library, "reference_ft_library failed");
++    return nullptr;
++  }
++
++  FT_Face ft_face;
++  if (unlikely (FT_New_Face (ft_library,
++                             file_name,
++                             index,
++                             &ft_face)))
++    return nullptr;
++
++  hb_face_t *face = hb_ft_face_create_referenced (ft_face);
++  FT_Done_Face (ft_face);
++
++  ft_face->generic.data = ft_library;
++  ft_face->generic.finalizer = finalize_ft_library;
++
++  if (hb_face_is_immutable (face))
++    return nullptr;
++
++  return face;
+ }
+ 
+ static void
+@@ -1465,32 +1660,47 @@ _release_blob (void *arg)
+ void
+ hb_ft_font_set_funcs (hb_font_t *font)
+ {
++  // In case of failure...
++  hb_font_set_funcs (font,
++                     hb_font_funcs_get_empty (),
++                     nullptr, nullptr);
++
+   hb_blob_t *blob = hb_face_reference_blob (font->face);
+   unsigned int blob_length;
+   const char *blob_data = hb_blob_get_data (blob, &blob_length);
+   if (unlikely (!blob_length))
+     DEBUG_MSG (FT, font, "Font face has empty blob");
+ 
+-  FT_Face ft_face = nullptr;
+-  FT_Error err = FT_New_Memory_Face (get_ft_library (),
+-                                     (const FT_Byte *) blob_data,
+-                                     blob_length,
+-                                     hb_face_get_index (font->face),
+-                                     &ft_face);
++  FT_Library ft_library = reference_ft_library ();
++  if (unlikely (!ft_library))
++  {
++    hb_blob_destroy (blob);
++    DEBUG_MSG (FT, font, "reference_ft_library failed");
++    return;
++  }
+ 
+-  if (unlikely (err)) {
++  FT_Face ft_face = nullptr;
++  if (unlikely (FT_New_Memory_Face (ft_library,
++                                    (const FT_Byte *) blob_data,
++                                    blob_length,
++                                    hb_face_get_index (font->face),
++                                    &ft_face)))
++  {
+     hb_blob_destroy (blob);
+-    DEBUG_MSG (FT, font, "Font face FT_New_Memory_Face() failed");
++    DEBUG_MSG (FT, font, "FT_New_Memory_Face() failed");
+     return;
+   }
+ 
+   if (FT_Select_Charmap (ft_face, FT_ENCODING_MS_SYMBOL))
+     FT_Select_Charmap (ft_face, FT_ENCODING_UNICODE);
+ 
+-
++  // Hook the blob to the FT_Face
+   ft_face->generic.data = blob;
+   ft_face->generic.finalizer = _release_blob;
+ 
++  // And the FT_Library to the blob
++  hb_blob_set_user_data (blob, &ft_library_key, ft_library, destroy_ft_library, true);
++
+   _hb_ft_font_set_funcs (font, ft_face, true);
+   hb_ft_font_set_load_flags (font, FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING);
+ 
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ft.h b/src/java.desktop/share/native/libharfbuzz/hb-ft.h
+index b2d148014..94952f48a 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-ft.h
++++ b/src/java.desktop/share/native/libharfbuzz/hb-ft.h
+@@ -84,6 +84,9 @@ hb_ft_face_create_cached (FT_Face ft_face);
+ HB_EXTERN hb_face_t *
+ hb_ft_face_create_referenced (FT_Face ft_face);
+ 
++HB_EXTERN hb_face_t *
++hb_ft_face_create_from_file_or_fail (const char   *file_name,
++                                     unsigned int  index);
+ 
+ /*
+  * hb-font from ft-face.
+@@ -108,7 +111,7 @@ HB_EXTERN hb_font_t *
+ hb_ft_font_create_referenced (FT_Face ft_face);
+ 
+ HB_EXTERN FT_Face
+-hb_ft_font_get_face (hb_font_t *font);
++hb_ft_font_get_ft_face (hb_font_t *font);
+ 
+ HB_EXTERN FT_Face
+ hb_ft_font_lock_face (hb_font_t *font);
+@@ -139,6 +142,13 @@ hb_ft_hb_font_changed (hb_font_t *font);
+ HB_EXTERN void
+ hb_ft_font_set_funcs (hb_font_t *font);
+ 
++#ifndef HB_DISABLE_DEPRECATED
++
++HB_DEPRECATED_FOR (hb_ft_font_get_ft_face)
++HB_EXTERN FT_Face
++hb_ft_font_get_face (hb_font_t *font);
++
++#endif
+ 
+ HB_END_DECLS
+ 
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-geometry.hh b/src/java.desktop/share/native/libharfbuzz/hb-geometry.hh
+new file mode 100644
+index 000000000..e91e371dc
+--- /dev/null
++++ b/src/java.desktop/share/native/libharfbuzz/hb-geometry.hh
+@@ -0,0 +1,293 @@
++/*
++ * 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_GEOMETRY_HH
++#define HB_GEOMETRY_HH
++
++#include "hb.hh"
++
++
++struct hb_extents_t
++{
++  hb_extents_t () {}
++  hb_extents_t (float xmin, float ymin, float xmax, float ymax) :
++    xmin (xmin), ymin (ymin), xmax (xmax), ymax (ymax) {}
++
++  bool is_empty () const { return xmin >= xmax || ymin >= ymax; }
++  bool is_void () const { return xmin > xmax; }
++
++  void union_ (const hb_extents_t &o)
++  {
++    xmin = hb_min (xmin, o.xmin);
++    ymin = hb_min (ymin, o.ymin);
++    xmax = hb_max (xmax, o.xmax);
++    ymax = hb_max (ymax, o.ymax);
++  }
++
++  void intersect (const hb_extents_t &o)
++  {
++    xmin = hb_max (xmin, o.xmin);
++    ymin = hb_max (ymin, o.ymin);
++    xmax = hb_min (xmax, o.xmax);
++    ymax = hb_min (ymax, o.ymax);
++  }
++
++  void
++  add_point (float x, float y)
++  {
++    if (unlikely (is_void ()))
++    {
++      xmin = xmax = x;
++      ymin = ymax = y;
++    }
++    else
++    {
++      xmin = hb_min (xmin, x);
++      ymin = hb_min (ymin, y);
++      xmax = hb_max (xmax, x);
++      ymax = hb_max (ymax, y);
++    }
++  }
++
++  float xmin = 0.f;
++  float ymin = 0.f;
++  float xmax = -1.f;
++  float ymax = -1.f;
++};
++
++struct hb_transform_t
++{
++  hb_transform_t () {}
++  hb_transform_t (float xx, float yx,
++                  float xy, float yy,
++                  float x0, float y0) :
++    xx (xx), yx (yx), xy (xy), yy (yy), x0 (x0), y0 (y0) {}
++
++  bool is_identity () const
++  {
++    return xx == 1.f && yx == 0.f &&
++           xy == 0.f && yy == 1.f &&
++           x0 == 0.f && y0 == 0.f;
++  }
++
++  void multiply (const hb_transform_t &o)
++  {
++    /* Copied from cairo, with "o" being "a" there and "this" being "b" there. */
++    hb_transform_t r;
++
++    r.xx = o.xx * xx + o.yx * xy;
++    r.yx = o.xx * yx + o.yx * yy;
++
++    r.xy = o.xy * xx + o.yy * xy;
++    r.yy = o.xy * yx + o.yy * yy;
++
++    r.x0 = o.x0 * xx + o.y0 * xy + x0;
++    r.y0 = o.x0 * yx + o.y0 * yy + y0;
++
++    *this = r;
++  }
++
++  void transform_distance (float &dx, float &dy) const
++  {
++    float new_x = xx * dx + xy * dy;
++    float new_y = yx * dx + yy * dy;
++    dx = new_x;
++    dy = new_y;
++  }
++
++  void transform_point (float &x, float &y) const
++  {
++    transform_distance (x, y);
++    x += x0;
++    y += y0;
++  }
++
++  void transform_extents (hb_extents_t &extents) const
++  {
++    float quad_x[4], quad_y[4];
++
++    quad_x[0] = extents.xmin;
++    quad_y[0] = extents.ymin;
++    quad_x[1] = extents.xmin;
++    quad_y[1] = extents.ymax;
++    quad_x[2] = extents.xmax;
++    quad_y[2] = extents.ymin;
++    quad_x[3] = extents.xmax;
++    quad_y[3] = extents.ymax;
++
++    extents = hb_extents_t {};
++    for (unsigned i = 0; i < 4; i++)
++    {
++      transform_point (quad_x[i], quad_y[i]);
++      extents.add_point (quad_x[i], quad_y[i]);
++    }
++  }
++
++  void transform (const hb_transform_t &o) { multiply (o); }
++
++  void translate (float x, float y)
++  {
++    if (x == 0.f && y == 0.f)
++      return;
++
++    x0 += xx * x + xy * y;
++    y0 += yx * x + yy * y;
++  }
++
++  void scale (float scaleX, float scaleY)
++  {
++    if (scaleX == 1.f && scaleY == 1.f)
++      return;
++
++    xx *= scaleX;
++    yx *= scaleX;
++    xy *= scaleY;
++    yy *= scaleY;
++  }
++
++  void rotate (float rotation)
++  {
++    if (rotation == 0.f)
++      return;
++
++    // https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L240
++    rotation = rotation * HB_PI;
++    float c;
++    float s;
++#ifdef HAVE_SINCOSF
++    sincosf (rotation, &s, &c);
++#else
++    c = cosf (rotation);
++    s = sinf (rotation);
++#endif
++    auto other = hb_transform_t{c, s, -s, c, 0.f, 0.f};
++    transform (other);
++  }
++
++  void skew (float skewX, float skewY)
++  {
++    if (skewX == 0.f && skewY == 0.f)
++      return;
++
++    // https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L255
++    skewX = skewX * HB_PI;
++    skewY = skewY * HB_PI;
++    auto other = hb_transform_t{1.f,
++                                skewY ? tanf (skewY) : 0.f,
++                                skewX ? tanf (skewX) : 0.f,
++                                1.f,
++                                0.f, 0.f};
++    transform (other);
++  }
++
++  float xx = 1.f;
++  float yx = 0.f;
++  float xy = 0.f;
++  float yy = 1.f;
++  float x0 = 0.f;
++  float y0 = 0.f;
++};
++
++#define HB_TRANSFORM_IDENTITY hb_transform_t{1.f, 0.f, 0.f, 1.f, 0.f, 0.f}
++
++struct hb_bounds_t
++{
++  enum status_t {
++    UNBOUNDED,
++    BOUNDED,
++    EMPTY,
++  };
++
++  hb_bounds_t (status_t status) : status (status) {}
++  hb_bounds_t (const hb_extents_t &extents) :
++    status (extents.is_empty () ? EMPTY : BOUNDED), extents (extents) {}
++
++  void union_ (const hb_bounds_t &o)
++  {
++    if (o.status == UNBOUNDED)
++      status = UNBOUNDED;
++    else if (o.status == BOUNDED)
++    {
++      if (status == EMPTY)
++        *this = o;
++      else if (status == BOUNDED)
++        extents.union_ (o.extents);
++    }
++  }
++
++  void intersect (const hb_bounds_t &o)
++  {
++    if (o.status == EMPTY)
++      status = EMPTY;
++    else if (o.status == BOUNDED)
++    {
++      if (status == UNBOUNDED)
++        *this = o;
++      else if (status == BOUNDED)
++      {
++        extents.intersect (o.extents);
++        if (extents.is_empty ())
++          status = EMPTY;
++      }
++    }
++  }
++
++  status_t status;
++  hb_extents_t extents;
++};
++
++struct hb_transform_decomposed_t
++{
++  float translateX = 0;
++  float translateY = 0;
++  float rotation = 0;  // in degrees, counter-clockwise
++  float scaleX = 1;
++  float scaleY = 1;
++  float skewX = 0;  // in degrees, counter-clockwise
++  float skewY = 0;  // in degrees, counter-clockwise
++  float tCenterX = 0;
++  float tCenterY = 0;
++
++  operator bool () const
++  {
++    return translateX || translateY ||
++           rotation ||
++           scaleX != 1 || scaleY != 1 ||
++           skewX || skewY ||
++           tCenterX || tCenterY;
++  }
++
++  hb_transform_t to_transform () const
++  {
++    hb_transform_t t;
++    t.translate (translateX + tCenterX, translateY + tCenterY);
++    t.rotate (rotation);
++    t.scale (scaleX, scaleY);
++    t.skew (-skewX, skewY);
++    t.translate (-tCenterX, -tCenterY);
++    return t;
++  }
++};
++
++
++#endif /* HB_GEOMETRY_HH */
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-iter.hh b/src/java.desktop/share/native/libharfbuzz/hb-iter.hh
+index ad45dcf2c..21d9544a7 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-iter.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-iter.hh
+@@ -324,6 +324,16 @@ struct hb_is_sink_of
+         (hb_is_source_of(Iter, Item) && Iter::is_sorted_iterator)
+ 
+ 
++struct
++{
++  template 
++  unsigned operator () (const Iterable &_) const { return hb_len (hb_iter (_)); }
++
++  unsigned operator () (unsigned _) const { return _; }
++}
++HB_FUNCOBJ (hb_len_of);
++
+ /* Range-based 'for' for iterables. */
+ 
+ template 
+ struct hb_hashmap_t
+ {
++  static constexpr bool realloc_move = true;
++
+   hb_hashmap_t ()  { init (); }
+   ~hb_hashmap_t () { fini (); }
+ 
+-  hb_hashmap_t (const hb_hashmap_t& o) : hb_hashmap_t () { alloc (o.population); hb_copy (o, *this); }
+-  hb_hashmap_t (hb_hashmap_t&& o) : hb_hashmap_t () { hb_swap (*this, o); }
++  hb_hashmap_t (const hb_hashmap_t& o) : hb_hashmap_t ()
++  {
++    if (unlikely (!o.mask)) return;
++
++    if (item_t::is_trivial)
++    {
++      items = (item_t *) hb_malloc (sizeof (item_t) * (o.mask + 1));
++      if (unlikely (!items))
++      {
++        successful = false;
++        return;
++      }
++      population = o.population;
++      occupancy = o.occupancy;
++      mask = o.mask;
++      prime = o.prime;
++      max_chain_length = o.max_chain_length;
++      memcpy (items, o.items, sizeof (item_t) * (mask + 1));
++      return;
++    }
++
++    alloc (o.population); hb_copy (o, *this);
++  }
++  hb_hashmap_t (hb_hashmap_t&& o)  noexcept : hb_hashmap_t () { hb_swap (*this, o); }
+   hb_hashmap_t& operator= (const hb_hashmap_t& o)  { reset (); alloc (o.population); hb_copy (o, *this); return *this; }
+-  hb_hashmap_t& operator= (hb_hashmap_t&& o)  { hb_swap (*this, o); return *this; }
++  hb_hashmap_t& operator= (hb_hashmap_t&& o)   noexcept { hb_swap (*this, o); return *this; }
+ 
+   hb_hashmap_t (std::initializer_list> lst) : hb_hashmap_t ()
+   {
+@@ -113,26 +137,23 @@ struct hb_hashmap_t
+   };
+ 
+   hb_object_header_t header;
+-  unsigned int successful : 1; /* Allocations successful */
+-  unsigned int population : 31; /* Not including tombstones. */
++  bool successful; /* Allocations successful */
++  unsigned short max_chain_length;
++  unsigned int population; /* Not including tombstones. */
+   unsigned int occupancy; /* Including tombstones. */
+   unsigned int mask;
+   unsigned int prime;
+-  unsigned int max_chain_length;
+   item_t *items;
+ 
+-  friend void swap (hb_hashmap_t& a, hb_hashmap_t& b)
++  friend void swap (hb_hashmap_t& a, hb_hashmap_t& b) noexcept
+   {
+     if (unlikely (!a.successful || !b.successful))
+       return;
+-    unsigned tmp = a.population;
+-    a.population = b.population;
+-    b.population = tmp;
+-    //hb_swap (a.population, b.population);
++    hb_swap (a.max_chain_length, b.max_chain_length);
++    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.max_chain_length, b.max_chain_length);
+     hb_swap (a.items, b.items);
+   }
+   void init ()
+@@ -140,10 +161,10 @@ struct hb_hashmap_t
+     hb_object_init (this);
+ 
+     successful = true;
++    max_chain_length = 0;
+     population = occupancy = 0;
+     mask = 0;
+     prime = 0;
+-    max_chain_length = 0;
+     items = nullptr;
+   }
+   void fini ()
+@@ -209,9 +230,10 @@ struct hb_hashmap_t
+                        old_items[i].hash,
+                        std::move (old_items[i].value));
+       }
+-      if (!item_t::is_trivial)
+-        old_items[i].~item_t ();
+     }
++    if (!item_t::is_trivial)
++      for (unsigned int i = 0; i < old_size; i++)
++        old_items[i].~item_t ();
+ 
+     hb_free (old_items);
+ 
+@@ -285,7 +307,7 @@ struct hb_hashmap_t
+   const V& get_with_hash (const K &key, uint32_t hash) const
+   {
+     if (!items) return item_t::default_value ();
+-    auto *item = fetch_item (key, hb_hash (key));
++    auto *item = fetch_item (key, hash);
+     if (item)
+       return item->value;
+     return item_t::default_value ();
+@@ -533,7 +555,7 @@ struct hb_map_t : hb_hashmap_t lst) : hashmap (lst) {}
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-null.hh b/src/java.desktop/share/native/libharfbuzz/hb-null.hh
+index 4a5270e34..63ec9a7c6 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-null.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-null.hh
+@@ -176,7 +176,7 @@ template 
+ static inline Type& Crap () {
+   static_assert (hb_null_size (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE.");
+   Type *obj = reinterpret_cast (_hb_CrapPool);
+-  memcpy (obj, std::addressof (Null (Type)), sizeof (*obj));
++  memcpy (reinterpret_cast(obj), std::addressof (Null (Type)), sizeof (*obj));
+   return *obj;
+ }
+ template 
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-object.hh b/src/java.desktop/share/native/libharfbuzz/hb-object.hh
+index ef675f835..c02ec8bfa 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-object.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-object.hh
+@@ -325,7 +325,7 @@ retry:
+   hb_user_data_array_t *user_data = obj->header.user_data.get_acquire ();
+   if (unlikely (!user_data))
+   {
+-    user_data = (hb_user_data_array_t *) hb_calloc (sizeof (hb_user_data_array_t), 1);
++    user_data = (hb_user_data_array_t *) hb_calloc (1, sizeof (hb_user_data_array_t));
+     if (unlikely (!user_data))
+       return false;
+     user_data->init ();
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-open-file.hh b/src/java.desktop/share/native/libharfbuzz/hb-open-file.hh
+index 387b1430a..382ee2dda 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-open-file.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-open-file.hh
+@@ -250,7 +250,7 @@ struct TTCHeader
+   {
+     switch (u.header.version.major) {
+     case 2: /* version 2 is compatible with version 1 */
+-    case 1: return u.version1.get_face_count ();
++    case 1: hb_barrier (); return u.version1.get_face_count ();
+     default:return 0;
+     }
+   }
+@@ -258,7 +258,7 @@ struct TTCHeader
+   {
+     switch (u.header.version.major) {
+     case 2: /* version 2 is compatible with version 1 */
+-    case 1: return u.version1.get_face (i);
++    case 1: hb_barrier (); return u.version1.get_face (i);
+     default:return Null (OpenTypeFontFace);
+     }
+   }
+@@ -267,9 +267,10 @@ struct TTCHeader
+   {
+     TRACE_SANITIZE (this);
+     if (unlikely (!u.header.version.sanitize (c))) return_trace (false);
++    hb_barrier ();
+     switch (u.header.version.major) {
+     case 2: /* version 2 is compatible with version 1 */
+-    case 1: return_trace (u.version1.sanitize (c));
++    case 1: hb_barrier (); return_trace (u.version1.sanitize (c));
+     default:return_trace (true);
+     }
+   }
+@@ -302,6 +303,7 @@ struct ResourceRecord
+     TRACE_SANITIZE (this);
+     return_trace (c->check_struct (this) &&
+                   offset.sanitize (c, data_base) &&
++                  hb_barrier () &&
+                   get_face (data_base).sanitize (c));
+   }
+ 
+@@ -337,6 +339,7 @@ struct ResourceTypeRecord
+   {
+     TRACE_SANITIZE (this);
+     return_trace (c->check_struct (this) &&
++                  hb_barrier () &&
+                   resourcesZ.sanitize (c, type_base,
+                                        get_resource_count (),
+                                        data_base));
+@@ -385,6 +388,7 @@ struct ResourceMap
+   {
+     TRACE_SANITIZE (this);
+     return_trace (c->check_struct (this) &&
++                  hb_barrier () &&
+                   typeList.sanitize (c, this,
+                                      &(this+typeList),
+                                      data_base));
+@@ -428,6 +432,7 @@ struct ResourceForkHeader
+   {
+     TRACE_SANITIZE (this);
+     return_trace (c->check_struct (this) &&
++                  hb_barrier () &&
+                   data.sanitize (c, this, dataLen) &&
+                   map.sanitize (c, this, &(this+data)));
+   }
+@@ -508,6 +513,7 @@ struct OpenTypeFontFile
+   {
+     TRACE_SANITIZE (this);
+     if (unlikely (!u.tag.sanitize (c))) return_trace (false);
++    hb_barrier ();
+     switch (u.tag) {
+     case CFFTag:        /* All the non-collection tags */
+     case TrueTag:
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-open-type.hh b/src/java.desktop/share/native/libharfbuzz/hb-open-type.hh
+index 25142da44..89da9c7bc 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-open-type.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-open-type.hh
+@@ -86,21 +86,12 @@ struct IntType
+ 
+     return pb->cmp (*pa);
+   }
+-  template ::value &&
+-                          sizeof (Type2) < sizeof (int) &&
+-                          sizeof (Type) < sizeof (int))>
+-  int cmp (Type2 a) const
+-  {
+-    Type b = v;
+-    return (int) a - (int) b;
+-  }
+   template 
+   int cmp (Type2 a) const
+   {
+     Type b = v;
+-    return a < b ? -1 : a == b ? 0 : +1;
++    return (a > b) - (a < b);
+   }
+   bool sanitize (hb_sanitize_context_t *c) const
+   {
+@@ -132,6 +123,89 @@ struct HBUINT15 : HBUINT16
+   DEFINE_SIZE_STATIC (2);
+ };
+ 
++/* 32-bit unsigned integer with variable encoding. */
++struct HBUINT32VAR
++{
++  unsigned get_size () const
++  {
++    unsigned b0 = v[0];
++    if (b0 < 0x80)
++      return 1;
++    else if (b0 < 0xC0)
++      return 2;
++    else if (b0 < 0xE0)
++      return 3;
++    else if (b0 < 0xF0)
++      return 4;
++    else
++      return 5;
++  }
++
++  static unsigned get_size (uint32_t v)
++  {
++    if (v < 0x80)
++      return 1;
++    else if (v < 0x4000)
++      return 2;
++    else if (v < 0x200000)
++      return 3;
++    else if (v < 0x10000000)
++      return 4;
++    else
++      return 5;
++  }
++
++  bool sanitize (hb_sanitize_context_t *c) const
++  {
++    TRACE_SANITIZE (this);
++    return_trace (c->check_range (v, 1) &&
++                  hb_barrier () &&
++                  c->check_range (v, get_size ()));
++  }
++
++  operator uint32_t () const
++  {
++    unsigned b0 = v[0];
++    if (b0 < 0x80)
++      return b0;
++    else if (b0 < 0xC0)
++      return ((b0 & 0x3F) << 8) | v[1];
++    else if (b0 < 0xE0)
++      return ((b0 & 0x1F) << 16) | (v[1] << 8) | v[2];
++    else if (b0 < 0xF0)
++      return ((b0 & 0x0F) << 24) | (v[1] << 16) | (v[2] << 8) | v[3];
++    else
++      return (v[1] << 24) | (v[2] << 16) | (v[3] << 8) | v[4];
++  }
++
++  static bool serialize (hb_serialize_context_t *c, uint32_t v)
++  {
++    unsigned len = get_size (v);
++
++    unsigned char *buf = c->allocate_size (len, false);
++    if (unlikely (!buf))
++      return false;
++
++    unsigned char *p = buf + len;
++    for (unsigned i = 0; i < len; i++)
++    {
++      *--p = v & 0xFF;
++      v >>= 8;
++    }
++
++    if (len > 1)
++      buf[0] |= ((1 << (len - 1)) - 1) << (9 - len);
++
++    return true;
++  }
++
++  protected:
++  unsigned char v[5];
++
++  public:
++  DEFINE_SIZE_MIN (1);
++};
++
+ /* 16-bit signed integer (HBINT16) that describes a quantity in FUnits. */
+ typedef HBINT16 FWORD;
+ 
+@@ -149,6 +223,7 @@ struct HBFixed : Type
+ 
+   operator signed () const = delete;
+   operator unsigned () const = delete;
++  explicit operator float () const { return to_float (); }
+   typename Type::type to_int () const { return Type::v; }
+   void set_int (typename Type::type i ) { Type::v = i; }
+   float to_float (float offset = 0) const  { return ((int32_t) Type::v + offset) / shift; }
+@@ -215,11 +290,6 @@ typedef Index NameID;
+ struct VarIdx : HBUINT32 {
+   static constexpr unsigned NO_VARIATION = 0xFFFFFFFFu;
+   static_assert (NO_VARIATION == HB_OT_LAYOUT_NO_VARIATIONS_INDEX, "");
+-  static uint32_t add (uint32_t i, unsigned short v)
+-  {
+-    if (i == NO_VARIATION) return i;
+-    return i + v;
+-  }
+   VarIdx& operator = (uint32_t i) { HBUINT32::operator= (i); return *this; }
+ };
+ DECLARE_NULL_NAMESPACE_BYTES (OT, VarIdx);
+@@ -309,7 +379,7 @@ struct _hb_has_null
+   static       Type *get_crap () { return &Crap (Type); }
+ };
+ 
+-template 
++template 
+ struct OffsetTo : Offset
+ {
+   using target_t = Type;
+@@ -335,22 +405,22 @@ struct OffsetTo : Offset
+   }
+ 
+   template 
++            hb_enable_if (hb_is_convertible (const Base, const BaseType *))>
+   friend const Type& operator + (const Base &base, const OffsetTo &offset) { return offset ((const void *) base); }
+   template 
++            hb_enable_if (hb_is_convertible (const Base, const BaseType *))>
+   friend const Type& operator + (const OffsetTo &offset, const Base &base) { return offset ((const void *) base); }
+   template 
++            hb_enable_if (hb_is_convertible (Base, BaseType *))>
+   friend Type& operator + (Base &&base, OffsetTo &offset) { return offset ((void *) base); }
+   template 
++            hb_enable_if (hb_is_convertible (Base, BaseType *))>
+   friend Type& operator + (OffsetTo &offset, Base &&base) { return offset ((void *) base); }
+ 
+ 
+-  template 
++  template 
+   bool serialize_subset (hb_subset_context_t *c, const OffsetTo& src,
+-                         const void *src_base, Ts&&... ds)
++                         const Base *src_base, Ts&&... ds)
+   {
+     *this = 0;
+     if (src.is_null ())
+@@ -414,10 +484,11 @@ struct OffsetTo : Offset
+                        const void *src_base, unsigned dst_bias = 0)
+   { return serialize_copy (c, src, src_base, dst_bias, hb_serialize_context_t::Head); }
+ 
+-  bool sanitize_shallow (hb_sanitize_context_t *c, const void *base) const
++  bool sanitize_shallow (hb_sanitize_context_t *c, const BaseType *base) const
+   {
+     TRACE_SANITIZE (this);
+     if (unlikely (!c->check_struct (this))) return_trace (false);
++    hb_barrier ();
+     //if (unlikely (this->is_null ())) return_trace (true);
+     if (unlikely ((const char *) base + (unsigned) *this < (const char *) base)) return_trace (false);
+     return_trace (true);
+@@ -427,10 +498,11 @@ struct OffsetTo : Offset
+ #ifndef HB_OPTIMIZE_SIZE
+   HB_ALWAYS_INLINE
+ #endif
+-  bool sanitize (hb_sanitize_context_t *c, const void *base, Ts&&... ds) const
++  bool sanitize (hb_sanitize_context_t *c, const BaseType *base, Ts&&... ds) const
+   {
+     TRACE_SANITIZE (this);
+     return_trace (sanitize_shallow (c, base) &&
++                  hb_barrier () &&
+                   (this->is_null () ||
+                    c->dispatch (StructAtOffset (base, *this), std::forward (ds)...) ||
+                    neuter (c)));
+@@ -445,14 +517,14 @@ struct OffsetTo : Offset
+   DEFINE_SIZE_STATIC (sizeof (OffsetType));
+ };
+ /* Partial specializations. */
+-template  using Offset16To = OffsetTo;
+-template  using Offset24To = OffsetTo;
+-template  using Offset32To = OffsetTo;
++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;
++template  using NNOffsetTo = OffsetTo;
++template  using NNOffset16To = Offset16To;
++template  using NNOffset24To = Offset24To;
++template  using NNOffset32To = Offset32To;
+ 
+ 
+ /*
+@@ -536,6 +608,7 @@ struct UnsizedArrayOf
+     TRACE_SANITIZE (this);
+     if (unlikely (!sanitize_shallow (c, count))) return_trace (false);
+     if (!sizeof... (Ts) && hb_is_trivially_copyable(Type)) return_trace (true);
++    hb_barrier ();
+     for (unsigned int i = 0; i < count; i++)
+       if (unlikely (!c->dispatch (arrayZ[i], std::forward (ds)...)))
+         return_trace (false);
+@@ -555,27 +628,27 @@ struct UnsizedArrayOf
+ };
+ 
+ /* Unsized array of offset's */
+-template 
+-using UnsizedArray16OfOffsetTo = UnsizedArrayOf>;
++template 
++using UnsizedArray16OfOffsetTo = UnsizedArrayOf>;
+ 
+ /* Unsized array of offsets relative to the beginning of the array itself. */
+-template 
+-struct UnsizedListOfOffset16To : UnsizedArray16OfOffsetTo
++template 
++struct UnsizedListOfOffset16To : UnsizedArray16OfOffsetTo
+ {
+   const Type& operator [] (int i_) const
+   {
+     unsigned int i = (unsigned int) i_;
+-    const OffsetTo *p = &this->arrayZ[i];
++    const OffsetTo *p = &this->arrayZ[i];
+     if (unlikely ((const void *) p < (const void *) this->arrayZ)) return Null (Type); /* Overflowed. */
+-    _hb_compiler_memory_r_barrier ();
++    hb_barrier ();
+     return this+*p;
+   }
+   Type& operator [] (int i_)
+   {
+     unsigned int i = (unsigned int) i_;
+-    const OffsetTo *p = &this->arrayZ[i];
++    const OffsetTo *p = &this->arrayZ[i];
+     if (unlikely ((const void *) p < (const void *) this->arrayZ)) return Crap (Type); /* Overflowed. */
+-    _hb_compiler_memory_r_barrier ();
++    hb_barrier ();
+     return this+*p;
+   }
+ 
+@@ -583,7 +656,7 @@ struct UnsizedListOfOffset16To : UnsizedArray16OfOffsetTo
++    return_trace ((UnsizedArray16OfOffsetTo
+                    ::sanitize (c, count, this, std::forward (ds)...)));
+   }
+ };
+@@ -626,14 +699,14 @@ struct ArrayOf
+   {
+     unsigned int i = (unsigned int) i_;
+     if (unlikely (i >= len)) return Null (Type);
+-    _hb_compiler_memory_r_barrier ();
++    hb_barrier ();
+     return arrayZ[i];
+   }
+   Type& operator [] (int i_)
+   {
+     unsigned int i = (unsigned int) i_;
+     if (unlikely (i >= len)) return Crap (Type);
+-    _hb_compiler_memory_r_barrier ();
++    hb_barrier ();
+     return arrayZ[i];
+   }
+ 
+@@ -725,6 +798,7 @@ struct ArrayOf
+     TRACE_SANITIZE (this);
+     if (unlikely (!sanitize_shallow (c))) return_trace (false);
+     if (!sizeof... (Ts) && hb_is_trivially_copyable(Type)) return_trace (true);
++    hb_barrier ();
+     unsigned int count = len;
+     for (unsigned int i = 0; i < count; i++)
+       if (unlikely (!c->dispatch (arrayZ[i], std::forward (ds)...)))
+@@ -735,7 +809,9 @@ struct ArrayOf
+   bool sanitize_shallow (hb_sanitize_context_t *c) const
+   {
+     TRACE_SANITIZE (this);
+-    return_trace (len.sanitize (c) && c->check_array_sized (arrayZ, len, sizeof (LenType)));
++    return_trace (len.sanitize (c) &&
++                  hb_barrier () &&
++                  c->check_array_sized (arrayZ, len, sizeof (LenType)));
+   }
+ 
+   public:
+@@ -750,6 +826,7 @@ template  using Array32Of = ArrayOf;
+ using PString = ArrayOf;
+ 
+ /* Array of Offset's */
++template  using Array8OfOffset24To = ArrayOf, HBUINT8>;
+ template  using Array16OfOffset16To = ArrayOf, HBUINT16>;
+ template  using Array16OfOffset32To = ArrayOf, HBUINT16>;
+ template  using Array32OfOffset32To = ArrayOf, HBUINT32>;
+@@ -762,14 +839,14 @@ struct List16OfOffsetTo : ArrayOf, HBUINT16>
+   {
+     unsigned int i = (unsigned int) i_;
+     if (unlikely (i >= this->len)) return Null (Type);
+-    _hb_compiler_memory_r_barrier ();
++    hb_barrier ();
+     return this+this->arrayZ[i];
+   }
+   const Type& operator [] (int i_)
+   {
+     unsigned int i = (unsigned int) i_;
+     if (unlikely (i >= this->len)) return Crap (Type);
+-    _hb_compiler_memory_r_barrier ();
++    hb_barrier ();
+     return this+this->arrayZ[i];
+   }
+ 
+@@ -807,14 +884,14 @@ struct HeadlessArrayOf
+   {
+     unsigned int i = (unsigned int) i_;
+     if (unlikely (i >= lenP1 || !i)) return Null (Type);
+-    _hb_compiler_memory_r_barrier ();
++    hb_barrier ();
+     return arrayZ[i-1];
+   }
+   Type& operator [] (int i_)
+   {
+     unsigned int i = (unsigned int) i_;
+     if (unlikely (i >= lenP1 || !i)) return Crap (Type);
+-    _hb_compiler_memory_r_barrier ();
++    hb_barrier ();
+     return arrayZ[i-1];
+   }
+   unsigned int get_size () const
+@@ -866,6 +943,7 @@ struct HeadlessArrayOf
+     TRACE_SANITIZE (this);
+     if (unlikely (!sanitize_shallow (c))) return_trace (false);
+     if (!sizeof... (Ts) && hb_is_trivially_copyable(Type)) return_trace (true);
++    hb_barrier ();
+     unsigned int count = get_length ();
+     for (unsigned int i = 0; i < count; i++)
+       if (unlikely (!c->dispatch (arrayZ[i], std::forward (ds)...)))
+@@ -878,6 +956,7 @@ struct HeadlessArrayOf
+   {
+     TRACE_SANITIZE (this);
+     return_trace (lenP1.sanitize (c) &&
++                  hb_barrier () &&
+                   (!lenP1 || c->check_array_sized (arrayZ, lenP1 - 1, sizeof (LenType))));
+   }
+ 
+@@ -899,14 +978,14 @@ struct ArrayOfM1
+   {
+     unsigned int i = (unsigned int) i_;
+     if (unlikely (i > lenM1)) return Null (Type);
+-    _hb_compiler_memory_r_barrier ();
++    hb_barrier ();
+     return arrayZ[i];
+   }
+   Type& operator [] (int i_)
+   {
+     unsigned int i = (unsigned int) i_;
+     if (unlikely (i > lenM1)) return Crap (Type);
+-    _hb_compiler_memory_r_barrier ();
++    hb_barrier ();
+     return arrayZ[i];
+   }
+   unsigned int get_size () const
+@@ -919,6 +998,7 @@ struct ArrayOfM1
+     TRACE_SANITIZE (this);
+     if (unlikely (!sanitize_shallow (c))) return_trace (false);
+     if (!sizeof... (Ts) && hb_is_trivially_copyable(Type)) return_trace (true);
++    hb_barrier ();
+     unsigned int count = lenM1 + 1;
+     for (unsigned int i = 0; i < count; i++)
+       if (unlikely (!c->dispatch (arrayZ[i], std::forward (ds)...)))
+@@ -931,6 +1011,7 @@ struct ArrayOfM1
+   {
+     TRACE_SANITIZE (this);
+     return_trace (lenM1.sanitize (c) &&
++                  hb_barrier () &&
+                   (c->check_array_sized (arrayZ, lenM1 + 1, sizeof (LenType))));
+   }
+ 
+@@ -975,6 +1056,13 @@ struct SortedArrayOf : ArrayOf
+     return_trace (ret);
+   }
+ 
++  SortedArrayOf* copy (hb_serialize_context_t *c) const
++  {
++    TRACE_SERIALIZE (this);
++    SortedArrayOf* out = reinterpret_cast (ArrayOf::copy (c));
++    return_trace (out);
++  }
++
+   template 
+   Type &bsearch (const T &x, Type ¬_found = Crap (Type))
+   { return *as_array ().bsearch (x, ¬_found); }
+@@ -1082,14 +1170,14 @@ struct VarSizedBinSearchArrayOf
+   {
+     unsigned int i = (unsigned int) i_;
+     if (unlikely (i >= get_length ())) return Null (Type);
+-    _hb_compiler_memory_r_barrier ();
++    hb_barrier ();
+     return StructAtOffset (&bytesZ, i * header.unitSize);
+   }
+   Type& operator [] (int i_)
+   {
+     unsigned int i = (unsigned int) i_;
+     if (unlikely (i >= get_length ())) return Crap (Type);
+-    _hb_compiler_memory_r_barrier ();
++    hb_barrier ();
+     return StructAtOffset (&bytesZ, i * header.unitSize);
+   }
+   unsigned int get_length () const
+@@ -1104,6 +1192,7 @@ struct VarSizedBinSearchArrayOf
+     TRACE_SANITIZE (this);
+     if (unlikely (!sanitize_shallow (c))) return_trace (false);
+     if (!sizeof... (Ts) && hb_is_trivially_copyable(Type)) return_trace (true);
++    hb_barrier ();
+     unsigned int count = get_length ();
+     for (unsigned int i = 0; i < count; i++)
+       if (unlikely (!(*this)[i].sanitize (c, std::forward (ds)...)))
+@@ -1130,6 +1219,7 @@ struct VarSizedBinSearchArrayOf
+   {
+     TRACE_SANITIZE (this);
+     return_trace (header.sanitize (c) &&
++                  hb_barrier () &&
+                   Type::static_size <= header.unitSize &&
+                   c->check_range (bytesZ.arrayZ,
+                                   header.nUnits,
+@@ -1144,6 +1234,800 @@ struct VarSizedBinSearchArrayOf
+ };
+ 
+ 
++/* CFF INDEX */
++
++template 
++struct CFFIndex
++{
++  unsigned int offset_array_size () const
++  { return offSize * (count + 1); }
++
++  template 
++  bool serialize (hb_serialize_context_t *c,
++                  const Iterable &iterable,
++                  const unsigned *p_data_size = nullptr,
++                  unsigned min_off_size = 0)
++  {
++    TRACE_SERIALIZE (this);
++    unsigned data_size;
++    if (p_data_size)
++      data_size = *p_data_size;
++    else
++      total_size (iterable, &data_size);
++
++    auto it = hb_iter (iterable);
++    if (unlikely (!serialize_header (c, +it, data_size, min_off_size))) return_trace (false);
++    unsigned char *ret = c->allocate_size (data_size, false);
++    if (unlikely (!ret)) return_trace (false);
++    for (const auto &_ : +it)
++    {
++      unsigned len = _.length;
++      if (!len)
++        continue;
++      if (len <= 1)
++      {
++        *ret++ = *_.arrayZ;
++        continue;
++      }
++      hb_memcpy (ret, _.arrayZ, len);
++      ret += len;
++    }
++    return_trace (true);
++  }
++
++  template 
++  bool serialize_header (hb_serialize_context_t *c,
++                         Iterator it,
++                         unsigned data_size,
++                         unsigned min_off_size = 0)
++  {
++    TRACE_SERIALIZE (this);
++
++    unsigned off_size = (hb_bit_storage (data_size + 1) + 7) / 8;
++    off_size = hb_max(min_off_size, off_size);
++
++    /* serialize CFFIndex header */
++    if (unlikely (!c->extend_min (this))) return_trace (false);
++    this->count = hb_len (it);
++    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 * (this->count + 1), false)))
++      return_trace (false);
++
++    /* serialize indices */
++    unsigned int offset = 1;
++    if (HB_OPTIMIZE_SIZE_VAL)
++    {
++      unsigned int i = 0;
++      for (const auto &_ : +it)
++      {
++        set_offset_at (i++, offset);
++        offset += hb_len_of (_);
++      }
++      set_offset_at (i, offset);
++    }
++    else
++      switch (off_size)
++      {
++        case 1:
++        {
++          HBUINT8 *p = (HBUINT8 *) offsets;
++          for (const auto &_ : +it)
++          {
++            *p++ = offset;
++            offset += hb_len_of (_);
++          }
++          *p = offset;
++        }
++        break;
++        case 2:
++        {
++          HBUINT16 *p = (HBUINT16 *) offsets;
++          for (const auto &_ : +it)
++          {
++            *p++ = offset;
++            offset += hb_len_of (_);
++          }
++          *p = offset;
++        }
++        break;
++        case 3:
++        {
++          HBUINT24 *p = (HBUINT24 *) offsets;
++          for (const auto &_ : +it)
++          {
++            *p++ = offset;
++            offset += hb_len_of (_);
++          }
++          *p = offset;
++        }
++        break;
++        case 4:
++        {
++          HBUINT32 *p = (HBUINT32 *) offsets;
++          for (const auto &_ : +it)
++          {
++            *p++ = offset;
++            offset += hb_len_of (_);
++          }
++          *p = offset;
++        }
++        break;
++        default:
++        break;
++      }
++
++    assert (offset == data_size + 1);
++    return_trace (true);
++  }
++
++  template 
++  static unsigned total_size (const Iterable &iterable, unsigned *data_size = nullptr, unsigned min_off_size = 0)
++  {
++    auto it = + hb_iter (iterable);
++    if (!it)
++    {
++      if (data_size) *data_size = 0;
++      return min_size;
++    }
++
++    unsigned total = 0;
++    for (const auto &_ : +it)
++      total += hb_len_of (_);
++
++    if (data_size) *data_size = total;
++
++    unsigned off_size = (hb_bit_storage (total + 1) + 7) / 8;
++    off_size = hb_max(min_off_size, off_size);
++
++    return min_size + HBUINT8::static_size + (hb_len (it) + 1) * off_size + total;
++  }
++
++  void set_offset_at (unsigned int index, unsigned int offset)
++  {
++    assert (index <= count);
++
++    unsigned int size = offSize;
++    const HBUINT8 *p = offsets;
++    switch (size)
++    {
++      case 1: ((HBUINT8  *) p)[index] = offset; break;
++      case 2: ((HBUINT16 *) p)[index] = offset; break;
++      case 3: ((HBUINT24 *) p)[index] = offset; break;
++      case 4: ((HBUINT32 *) p)[index] = offset; break;
++      default: return;
++    }
++  }
++
++  private:
++  unsigned int offset_at (unsigned int index) const
++  {
++    assert (index <= count);
++
++    unsigned int size = offSize;
++    const HBUINT8 *p = offsets;
++    switch (size)
++    {
++      case 1: return ((HBUINT8  *) p)[index];
++      case 2: return ((HBUINT16 *) p)[index];
++      case 3: return ((HBUINT24 *) p)[index];
++      case 4: return ((HBUINT32 *) p)[index];
++      default: return 0;
++    }
++  }
++
++  const unsigned char *data_base () const
++  { return (const unsigned char *) this + min_size + offSize.static_size - 1 + offset_array_size (); }
++  public:
++
++  hb_ubytes_t operator [] (unsigned int index) const
++  {
++    if (unlikely (index >= count)) return hb_ubytes_t ();
++    hb_barrier ();
++    unsigned offset0 = offset_at (index);
++    unsigned offset1 = offset_at (index + 1);
++    if (unlikely (offset1 < offset0 || offset1 > offset_at (count)))
++      return hb_ubytes_t ();
++    return hb_ubytes_t (data_base () + offset0, offset1 - offset0);
++  }
++
++  unsigned int get_size () const
++  {
++    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) &&
++                          hb_barrier () &&
++                          (count == 0 || /* empty INDEX */
++                           (count < count + 1u &&
++                            c->check_struct (&offSize) && offSize >= 1 && offSize <= 4 &&
++                            c->check_array (offsets, offSize, count + 1u) &&
++                            c->check_range (data_base (), offset_at (count))))));
++  }
++
++  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_MIN (COUNT::static_size);
++};
++typedef CFFIndex CFF1Index;
++typedef CFFIndex CFF2Index;
++
++
++/* TupleValues */
++struct TupleValues
++{
++  enum packed_value_flag_t
++  {
++    VALUES_ARE_ZEROS     = 0x80,
++    VALUES_ARE_BYTES     = 0x00,
++    VALUES_ARE_WORDS     = 0x40,
++    VALUES_ARE_LONGS     = 0xC0,
++    VALUES_SIZE_MASK     = 0xC0,
++    VALUE_RUN_COUNT_MASK = 0x3F
++  };
++
++  static unsigned compile (hb_array_t values, /* IN */
++                           hb_array_t encoded_bytes /* OUT */)
++  {
++    unsigned num_values = values.length;
++    unsigned encoded_len = 0;
++    unsigned i = 0;
++    while (i < num_values)
++    {
++      int val = values.arrayZ[i];
++      if (val == 0)
++        encoded_len += encode_value_run_as_zeroes (i, encoded_bytes.sub_array (encoded_len), values);
++      else if (val >= -128 && val <= 127)
++        encoded_len += encode_value_run_as_bytes (i, encoded_bytes.sub_array (encoded_len), values);
++      else if (val >= -32768 && val <= 32767)
++        encoded_len += encode_value_run_as_words (i, encoded_bytes.sub_array (encoded_len), values);
++      else
++        encoded_len += encode_value_run_as_longs (i, encoded_bytes.sub_array (encoded_len), values);
++    }
++    return encoded_len;
++  }
++
++  static unsigned encode_value_run_as_zeroes (unsigned& i,
++                                              hb_array_t encoded_bytes,
++                                              hb_array_t values)
++  {
++    unsigned num_values = values.length;
++    unsigned run_length = 0;
++    auto it = encoded_bytes.iter ();
++    unsigned encoded_len = 0;
++    while (i < num_values && values.arrayZ[i] == 0)
++    {
++      i++;
++      run_length++;
++    }
++
++    while (run_length >= 64)
++    {
++      *it++ = char (VALUES_ARE_ZEROS | 63);
++      run_length -= 64;
++      encoded_len++;
++    }
++
++    if (run_length)
++    {
++      *it++ = char (VALUES_ARE_ZEROS | (run_length - 1));
++      encoded_len++;
++    }
++    return encoded_len;
++  }
++
++  static unsigned encode_value_run_as_bytes (unsigned &i,
++                                             hb_array_t encoded_bytes,
++                                             hb_array_t values)
++  {
++    unsigned start = i;
++    unsigned num_values = values.length;
++    while (i < num_values)
++    {
++      int val = values.arrayZ[i];
++      if (val > 127 || val < -128)
++        break;
++
++      /* from fonttools: if there're 2 or more zeros in a sequence,
++       * it is better to start a new run to save bytes. */
++      if (val == 0 && i + 1 < num_values && values.arrayZ[i+1] == 0)
++        break;
++
++      i++;
++    }
++    unsigned run_length = i - start;
++
++    unsigned encoded_len = 0;
++    auto it = encoded_bytes.iter ();
++
++    while (run_length >= 64)
++    {
++      *it++ = (VALUES_ARE_BYTES | 63);
++      encoded_len++;
++
++      for (unsigned j = 0; j < 64; j++)
++      {
++        *it++ = static_cast (values.arrayZ[start + j]);
++        encoded_len++;
++      }
++
++      start += 64;
++      run_length -= 64;
++    }
++
++    if (run_length)
++    {
++      *it++ = (VALUES_ARE_BYTES | (run_length - 1));
++      encoded_len++;
++
++      while (start < i)
++      {
++        *it++ = static_cast (values.arrayZ[start++]);
++        encoded_len++;
++      }
++    }
++
++    return encoded_len;
++  }
++
++  static unsigned encode_value_run_as_words (unsigned &i,
++                                             hb_array_t encoded_bytes,
++                                             hb_array_t values)
++  {
++    unsigned start = i;
++    unsigned num_values = values.length;
++    while (i < num_values)
++    {
++      int val = values.arrayZ[i];
++
++      /* start a new run for a single zero value*/
++      if (val == 0) break;
++
++      /* from fonttools: continue word-encoded run if there's only one
++       * single value in the range [-128, 127] because it is more compact.
++       * Only start a new run when there're 2 continuous such values. */
++      if (val >= -128 && val <= 127 &&
++          i + 1 < num_values &&
++          values.arrayZ[i+1] >= -128 && values.arrayZ[i+1] <= 127)
++        break;
++
++      i++;
++    }
++
++    unsigned run_length = i - start;
++    auto it = encoded_bytes.iter ();
++    unsigned encoded_len = 0;
++    while (run_length >= 64)
++    {
++      *it++ = (VALUES_ARE_WORDS | 63);
++      encoded_len++;
++
++      for (unsigned j = 0; j < 64; j++)
++      {
++        int16_t value_val = values.arrayZ[start + j];
++        *it++ = static_cast (value_val >> 8);
++        *it++ = static_cast (value_val & 0xFF);
++
++        encoded_len += 2;
++      }
++
++      start += 64;
++      run_length -= 64;
++    }
++
++    if (run_length)
++    {
++      *it++ = (VALUES_ARE_WORDS | (run_length - 1));
++      encoded_len++;
++      while (start < i)
++      {
++        int16_t value_val = values.arrayZ[start++];
++        *it++ = static_cast (value_val >> 8);
++        *it++ = static_cast (value_val & 0xFF);
++
++        encoded_len += 2;
++      }
++    }
++    return encoded_len;
++  }
++
++  static unsigned encode_value_run_as_longs (unsigned &i,
++                                             hb_array_t encoded_bytes,
++                                             hb_array_t values)
++  {
++    unsigned start = i;
++    unsigned num_values = values.length;
++    while (i < num_values)
++    {
++      int val = values.arrayZ[i];
++
++      if (val >= -32768 && val <= 32767)
++        break;
++
++      i++;
++    }
++
++    unsigned run_length = i - start;
++    auto it = encoded_bytes.iter ();
++    unsigned encoded_len = 0;
++    while (run_length >= 64)
++    {
++      *it++ = (VALUES_ARE_LONGS | 63);
++      encoded_len++;
++
++      for (unsigned j = 0; j < 64; j++)
++      {
++        int32_t value_val = values.arrayZ[start + j];
++        *it++ = static_cast (value_val >> 24);
++        *it++ = static_cast (value_val >> 16);
++        *it++ = static_cast (value_val >> 8);
++        *it++ = static_cast (value_val & 0xFF);
++
++        encoded_len += 4;
++      }
++
++      start += 64;
++      run_length -= 64;
++    }
++
++    if (run_length)
++    {
++      *it++ = (VALUES_ARE_LONGS | (run_length - 1));
++      encoded_len++;
++      while (start < i)
++      {
++        int32_t value_val = values.arrayZ[start++];
++        *it++ = static_cast (value_val >> 24);
++        *it++ = static_cast (value_val >> 16);
++        *it++ = static_cast (value_val >> 8);
++        *it++ = static_cast (value_val & 0xFF);
++
++        encoded_len += 4;
++      }
++    }
++    return encoded_len;
++  }
++
++  template 
++  static bool decompile (const HBUINT8 *&p /* IN/OUT */,
++                         hb_vector_t &values /* IN/OUT */,
++                         const HBUINT8 *end,
++                         bool consume_all = false)
++  {
++    unsigned i = 0;
++    unsigned count = consume_all ? UINT_MAX : values.length;
++    if (consume_all)
++      values.alloc ((end - p) / 2);
++    while (i < count)
++    {
++      if (unlikely (p + 1 > end)) return consume_all;
++      unsigned control = *p++;
++      unsigned run_count = (control & VALUE_RUN_COUNT_MASK) + 1;
++      if (consume_all)
++      {
++        if (unlikely (!values.resize (values.length + run_count, false)))
++          return false;
++      }
++      unsigned stop = i + run_count;
++      if (unlikely (stop > count)) return false;
++      if ((control & VALUES_SIZE_MASK) == VALUES_ARE_ZEROS)
++      {
++        for (; i < stop; i++)
++          values.arrayZ[i] = 0;
++      }
++      else if ((control & VALUES_SIZE_MASK) ==  VALUES_ARE_WORDS)
++      {
++        if (unlikely (p + run_count * HBINT16::static_size > end)) return false;
++#ifndef HB_OPTIMIZE_SIZE
++        for (; i + 3 < stop; i += 4)
++        {
++          values.arrayZ[i] = * (const HBINT16 *) p;
++          p += HBINT16::static_size;
++          values.arrayZ[i + 1] = * (const HBINT16 *) p;
++          p += HBINT16::static_size;
++          values.arrayZ[i + 2] = * (const HBINT16 *) p;
++          p += HBINT16::static_size;
++          values.arrayZ[i + 3] = * (const HBINT16 *) p;
++          p += HBINT16::static_size;
++        }
++#endif
++        for (; i < stop; i++)
++        {
++          values.arrayZ[i] = * (const HBINT16 *) p;
++          p += HBINT16::static_size;
++        }
++      }
++      else if ((control & VALUES_SIZE_MASK) ==  VALUES_ARE_LONGS)
++      {
++        if (unlikely (p + run_count * HBINT32::static_size > end)) return false;
++        for (; i < stop; i++)
++        {
++          values.arrayZ[i] = * (const HBINT32 *) p;
++          p += HBINT32::static_size;
++        }
++      }
++      else if ((control & VALUES_SIZE_MASK) ==  VALUES_ARE_BYTES)
++      {
++        if (unlikely (p + run_count > end)) return false;
++#ifndef HB_OPTIMIZE_SIZE
++        for (; i + 3 < stop; i += 4)
++        {
++          values.arrayZ[i] = * (const HBINT8 *) p++;
++          values.arrayZ[i + 1] = * (const HBINT8 *) p++;
++          values.arrayZ[i + 2] = * (const HBINT8 *) p++;
++          values.arrayZ[i + 3] = * (const HBINT8 *) p++;
++        }
++#endif
++        for (; i < stop; i++)
++          values.arrayZ[i] = * (const HBINT8 *) p++;
++      }
++    }
++    return true;
++  }
++
++  struct iter_t : hb_iter_with_fallback_t
++  {
++    iter_t (const unsigned char *p_, unsigned len_)
++            : p (p_), endp (p_ + len_)
++    { if (ensure_run ()) read_value (); }
++
++    private:
++    const unsigned char *p;
++    const unsigned char * const endp;
++    int current_value = 0;
++    signed run_count = 0;
++    unsigned width = 0;
++
++    bool ensure_run ()
++    {
++      if (likely (run_count > 0)) return true;
++
++      if (unlikely (p >= endp))
++      {
++        run_count = 0;
++        current_value = 0;
++        return false;
++      }
++
++      unsigned control = *p++;
++      run_count = (control & VALUE_RUN_COUNT_MASK) + 1;
++      width = control & VALUES_SIZE_MASK;
++      switch (width)
++      {
++        case VALUES_ARE_ZEROS: width = 0; break;
++        case VALUES_ARE_BYTES: width = HBINT8::static_size;  break;
++        case VALUES_ARE_WORDS: width = HBINT16::static_size; break;
++        case VALUES_ARE_LONGS: width = HBINT32::static_size; break;
++        default: assert (false);
++      }
++
++      if (unlikely (p + run_count * width > endp))
++      {
++        run_count = 0;
++        current_value = 0;
++        return false;
++      }
++
++      return true;
++    }
++    void read_value ()
++    {
++      switch (width)
++      {
++        case 0: current_value = 0; break;
++        case 1: current_value = * (const HBINT8  *) p; break;
++        case 2: current_value = * (const HBINT16 *) p; break;
++        case 4: current_value = * (const HBINT32 *) p; break;
++      }
++      p += width;
++    }
++
++    public:
++
++    typedef int __item_t__;
++    __item_t__ __item__ () const
++    { return current_value; }
++
++    bool __more__ () const { return run_count || p < endp; }
++    void __next__ ()
++    {
++      run_count--;
++      if (unlikely (!ensure_run ()))
++        return;
++      read_value ();
++    }
++    void __forward__ (unsigned n)
++    {
++      if (unlikely (!ensure_run ()))
++        return;
++      while (n)
++      {
++        unsigned i = hb_min (n, (unsigned) run_count);
++        run_count -= i;
++        n -= i;
++        p += (i - 1) * width;
++        if (unlikely (!ensure_run ()))
++          return;
++        read_value ();
++      }
++    }
++    bool operator != (const iter_t& o) const
++    { return p != o.p || run_count != o.run_count; }
++    iter_t __end__ () const
++    {
++      iter_t it (endp, 0);
++      return it;
++    }
++  };
++
++  struct fetcher_t
++  {
++    fetcher_t (const unsigned char *p_, unsigned len_)
++              : p (p_), end (p_ + len_) {}
++
++    private:
++    const unsigned char *p;
++    const unsigned char * const end;
++    signed run_count = 0;
++    unsigned width = 0;
++
++    bool ensure_run ()
++    {
++      if (likely (run_count > 0)) return true;
++
++      if (unlikely (p >= end))
++      {
++        run_count = 0;
++        return false;
++      }
++
++      unsigned control = *p++;
++      run_count = (control & VALUE_RUN_COUNT_MASK) + 1;
++      width = control & VALUES_SIZE_MASK;
++      switch (width)
++      {
++        case VALUES_ARE_ZEROS: width = 0; break;
++        case VALUES_ARE_BYTES: width = HBINT8::static_size;  break;
++        case VALUES_ARE_WORDS: width = HBINT16::static_size; break;
++        case VALUES_ARE_LONGS: width = HBINT32::static_size; break;
++        default: assert (false);
++      }
++
++      if (unlikely (p + run_count * width > end))
++      {
++        run_count = 0;
++        return false;
++      }
++
++      return true;
++    }
++
++    void skip (unsigned n)
++    {
++      while (n)
++      {
++        if (unlikely (!ensure_run ()))
++          return;
++        unsigned i = hb_min (n, (unsigned) run_count);
++        run_count -= i;
++        n -= i;
++        p += i * width;
++      }
++    }
++
++    template 
++    void _add_to (hb_array_t out, float scale = 1.0f)
++    {
++      unsigned n = out.length;
++      float *arrayZ = out.arrayZ;
++
++      for (unsigned i = 0; i < n;)
++      {
++        if (unlikely (!ensure_run ()))
++          break;
++        unsigned count = hb_min (n - i, (unsigned) run_count);
++        switch (width)
++        {
++          case 1:
++          {
++            const auto *pp = (const HBINT8 *) p;
++            unsigned j = 0;
++#ifndef HB_OPTIMIZE_SIZE
++            for (; j + 3 < count; j += 4)
++            {
++              *arrayZ++ += scaled ? *pp++ * scale : *pp++;
++              *arrayZ++ += scaled ? *pp++ * scale : *pp++;
++              *arrayZ++ += scaled ? *pp++ * scale : *pp++;
++              *arrayZ++ += scaled ? *pp++ * scale : *pp++;
++            }
++#endif
++            for (; j < count; j++)
++              *arrayZ++ += scaled ? *pp++ * scale : *pp++;
++          }
++          break;
++          case 2:
++          {
++            const auto *pp = (const HBINT16 *) p;
++            unsigned j = 0;
++#ifndef HB_OPTIMIZE_SIZE
++            for (; j + 3 < count; j += 4)
++            {
++              *arrayZ++ += scaled ? *pp++ * scale : *pp++;
++              *arrayZ++ += scaled ? *pp++ * scale : *pp++;
++              *arrayZ++ += scaled ? *pp++ * scale : *pp++;
++              *arrayZ++ += scaled ? *pp++ * scale : *pp++;
++            }
++#endif
++            for (; j < count; j++)
++              *arrayZ++ += scaled ? *pp++ * scale : *pp++;
++          }
++          break;
++          case 4:
++          {
++            const auto *pp = (const HBINT32 *) p;
++            for (unsigned j = 0; j < count; j++)
++              *arrayZ++ += scaled ? *pp++ * scale : *pp++;
++          }
++          break;
++        }
++        p += count * width;
++        run_count -= count;
++        i += count;
++      }
++    }
++
++    public:
++    void add_to (hb_array_t out, float scale = 1.0f)
++    {
++      unsigned n = out.length;
++
++      if (scale == 0.0f)
++      {
++        skip (n);
++        return;
++      }
++
++#ifndef HB_OPTIMIZE_SIZE
++      if (scale == 1.0f)
++        _add_to (out);
++      else
++#endif
++        _add_to (out, scale);
++    }
++  };
++};
++
++struct TupleList : CFF2Index
++{
++  TupleValues::iter_t operator [] (unsigned i) const
++  {
++    auto bytes = CFF2Index::operator [] (i);
++    return TupleValues::iter_t (bytes.arrayZ, bytes.length);
++  }
++
++  TupleValues::fetcher_t fetcher (unsigned i) const
++  {
++    auto bytes = CFF2Index::operator [] (i);
++    return TupleValues::fetcher_t (bytes.arrayZ, bytes.length);
++  }
++};
++
++
+ } /* namespace OT */
+ 
+ 
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-cff-common.hh b/src/java.desktop/share/native/libharfbuzz/hb-ot-cff-common.hh
+index 081c333f5..1e3e0be51 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-cff-common.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-cff-common.hh
+@@ -41,10 +41,21 @@ using namespace OT;
+ using objidx_t = hb_serialize_context_t::objidx_t;
+ using whence_t = hb_serialize_context_t::whence_t;
+ 
+-/* utility macro */
+-template
+-static inline const Type& StructAtOffsetOrNull (const void *P, unsigned int offset)
+-{ return offset ? StructAtOffset (P, offset) : Null (Type); }
++/* CFF offsets can technically be negative */
++template
++static inline const Type& StructAtOffsetOrNull (const void *P, int offset, hb_sanitize_context_t &sc, Ts&&... ds)
++{
++  if (!offset) return Null (Type);
++
++  const char *p = (const char *) P + offset;
++  if (!sc.check_point (p)) return Null (Type);
++
++  const Type &obj = *reinterpret_cast (p);
++  if (!obj.sanitize (&sc, std::forward (ds)...)) return Null (Type);
++
++  return obj;
++}
++
+ 
+ struct code_pair_t
+ {
+@@ -57,241 +68,6 @@ using str_buff_t = hb_vector_t;
+ using str_buff_vec_t = hb_vector_t;
+ using glyph_to_sid_map_t = hb_vector_t;
+ 
+-struct length_f_t
+-{
+-  template 
+-  unsigned operator () (const Iterable &_) const { return hb_len (hb_iter (_)); }
+-
+-  unsigned operator () (unsigned _) const { return _; }
+-}
+-HB_FUNCOBJ (length_f);
+-
+-/* CFF INDEX */
+-template 
+-struct CFFIndex
+-{
+-  unsigned int offset_array_size () const
+-  { return offSize * (count + 1); }
+-
+-  template 
+-  bool serialize (hb_serialize_context_t *c,
+-                  const Iterable &iterable,
+-                  const unsigned *p_data_size = nullptr)
+-  {
+-    TRACE_SERIALIZE (this);
+-    unsigned data_size;
+-    if (p_data_size)
+-      data_size = *p_data_size;
+-    else
+-      total_size (iterable, &data_size);
+-
+-    auto it = hb_iter (iterable);
+-    if (unlikely (!serialize_header (c, +it, data_size))) return_trace (false);
+-    unsigned char *ret = c->allocate_size (data_size, false);
+-    if (unlikely (!ret)) return_trace (false);
+-    for (const auto &_ : +it)
+-    {
+-      unsigned len = _.length;
+-      if (!len)
+-        continue;
+-      if (len <= 1)
+-      {
+-        *ret++ = *_.arrayZ;
+-        continue;
+-      }
+-      hb_memcpy (ret, _.arrayZ, len);
+-      ret += len;
+-    }
+-    return_trace (true);
+-  }
+-
+-  template 
+-  bool serialize_header (hb_serialize_context_t *c,
+-                         Iterator it,
+-                         unsigned data_size)
+-  {
+-    TRACE_SERIALIZE (this);
+-
+-    unsigned off_size = (hb_bit_storage (data_size + 1) + 7) / 8;
+-
+-    /* serialize CFFIndex header */
+-    if (unlikely (!c->extend_min (this))) return_trace (false);
+-    this->count = hb_len (it);
+-    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 * (this->count + 1), false)))
+-      return_trace (false);
+-
+-    /* serialize indices */
+-    unsigned int offset = 1;
+-    if (HB_OPTIMIZE_SIZE_VAL)
+-    {
+-      unsigned int i = 0;
+-      for (const auto &_ : +it)
+-      {
+-        set_offset_at (i++, offset);
+-        offset += length_f (_);
+-      }
+-      set_offset_at (i, offset);
+-    }
+-    else
+-      switch (off_size)
+-      {
+-        case 1:
+-        {
+-          HBUINT8 *p = (HBUINT8 *) offsets;
+-          for (const auto &_ : +it)
+-          {
+-            *p++ = offset;
+-            offset += length_f (_);
+-          }
+-          *p = offset;
+-        }
+-        break;
+-        case 2:
+-        {
+-          HBUINT16 *p = (HBUINT16 *) offsets;
+-          for (const auto &_ : +it)
+-          {
+-            *p++ = offset;
+-            offset += length_f (_);
+-          }
+-          *p = offset;
+-        }
+-        break;
+-        case 3:
+-        {
+-          HBUINT24 *p = (HBUINT24 *) offsets;
+-          for (const auto &_ : +it)
+-          {
+-            *p++ = offset;
+-            offset += length_f (_);
+-          }
+-          *p = offset;
+-        }
+-        break;
+-        case 4:
+-        {
+-          HBUINT32 *p = (HBUINT32 *) offsets;
+-          for (const auto &_ : +it)
+-          {
+-            *p++ = offset;
+-            offset += length_f (_);
+-          }
+-          *p = offset;
+-        }
+-        break;
+-        default:
+-        break;
+-      }
+-
+-    assert (offset == data_size + 1);
+-    return_trace (true);
+-  }
+-
+-  template 
+-  static unsigned total_size (const Iterable &iterable, unsigned *data_size = nullptr)
+-  {
+-    auto it = + hb_iter (iterable);
+-    if (!it)
+-    {
+-      if (data_size) *data_size = 0;
+-      return min_size;
+-    }
+-
+-    unsigned total = 0;
+-    for (const auto &_ : +it)
+-      total += length_f (_);
+-
+-    if (data_size) *data_size = total;
+-
+-    unsigned off_size = (hb_bit_storage (total + 1) + 7) / 8;
+-
+-    return min_size + HBUINT8::static_size + (hb_len (it) + 1) * off_size + total;
+-  }
+-
+-  void set_offset_at (unsigned int index, unsigned int offset)
+-  {
+-    assert (index <= count);
+-
+-    unsigned int size = offSize;
+-    const HBUINT8 *p = offsets;
+-    switch (size)
+-    {
+-      case 1: ((HBUINT8  *) p)[index] = offset; break;
+-      case 2: ((HBUINT16 *) p)[index] = offset; break;
+-      case 3: ((HBUINT24 *) p)[index] = offset; break;
+-      case 4: ((HBUINT32 *) p)[index] = offset; break;
+-      default: return;
+-    }
+-  }
+-
+-  private:
+-  unsigned int offset_at (unsigned int index) const
+-  {
+-    assert (index <= count);
+-
+-    unsigned int size = offSize;
+-    const HBUINT8 *p = offsets;
+-    switch (size)
+-    {
+-      case 1: return ((HBUINT8  *) p)[index];
+-      case 2: return ((HBUINT16 *) p)[index];
+-      case 3: return ((HBUINT24 *) p)[index];
+-      case 4: return ((HBUINT32 *) p)[index];
+-      default: return 0;
+-    }
+-  }
+-
+-  const unsigned char *data_base () const
+-  { return (const unsigned char *) this + min_size + offSize.static_size - 1 + offset_array_size (); }
+-  public:
+-
+-  hb_ubytes_t operator [] (unsigned int index) const
+-  {
+-    if (unlikely (index >= count)) return hb_ubytes_t ();
+-    _hb_compiler_memory_r_barrier ();
+-    unsigned offset0 = offset_at (index);
+-    unsigned offset1 = offset_at (index + 1);
+-    if (unlikely (offset1 < offset0 || offset1 > offset_at (count)))
+-      return hb_ubytes_t ();
+-    return hb_ubytes_t (data_base () + offset0, offset1 - offset0);
+-  }
+-
+-  unsigned int get_size () const
+-  {
+-    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 */
+-                           (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))))));
+-  }
+-
+-  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_MIN (COUNT::static_size);
+-};
+-
+ /* Top Dict, Font Dict, Private Dict */
+ struct Dict : UnsizedByteStr
+ {
+@@ -412,6 +188,7 @@ struct FDSelect0 {
+     TRACE_SANITIZE (this);
+     if (unlikely (!(c->check_struct (this))))
+       return_trace (false);
++    hb_barrier ();
+     if (unlikely (!c->check_array (fds, c->get_num_glyphs ())))
+       return_trace (false);
+ 
+@@ -438,7 +215,9 @@ struct FDSelect3_4_Range
+   bool sanitize (hb_sanitize_context_t *c, const void * /*nullptr*/, unsigned int fdcount) const
+   {
+     TRACE_SANITIZE (this);
+-    return_trace (first < c->get_num_glyphs () && (fd < fdcount));
++    return_trace (c->check_struct (this) &&
++                  hb_barrier () &&
++                  first < c->get_num_glyphs () && (fd < fdcount));
+   }
+ 
+   GID_TYPE    first;
+@@ -456,15 +235,20 @@ struct FDSelect3_4
+   bool sanitize (hb_sanitize_context_t *c, unsigned int fdcount) const
+   {
+     TRACE_SANITIZE (this);
+-    if (unlikely (!c->check_struct (this) || !ranges.sanitize (c, nullptr, fdcount) ||
+-                  (nRanges () == 0) || ranges[0].first != 0))
++    if (unlikely (!(c->check_struct (this) &&
++                    ranges.sanitize (c, nullptr, fdcount) &&
++                    hb_barrier () &&
++                    (nRanges () != 0) &&
++                    ranges[0].first == 0)))
+       return_trace (false);
+ 
+     for (unsigned int i = 1; i < nRanges (); i++)
+       if (unlikely (ranges[i - 1].first >= ranges[i].first))
+         return_trace (false);
+ 
+-    if (unlikely (!sentinel().sanitize (c) || (sentinel() != c->get_num_glyphs ())))
++    if (unlikely (!(sentinel().sanitize (c) &&
++                   hb_barrier () &&
++                   (sentinel() == c->get_num_glyphs ()))))
+       return_trace (false);
+ 
+     return_trace (true);
+@@ -524,8 +308,8 @@ struct FDSelect
+   {
+     switch (format)
+     {
+-    case 0: return format.static_size + u.format0.get_size (num_glyphs);
+-    case 3: return format.static_size + u.format3.get_size ();
++    case 0: hb_barrier (); return format.static_size + u.format0.get_size (num_glyphs);
++    case 3: hb_barrier (); return format.static_size + u.format3.get_size ();
+     default:return 0;
+     }
+   }
+@@ -536,8 +320,8 @@ struct FDSelect
+ 
+     switch (format)
+     {
+-    case 0: return u.format0.get_fd (glyph);
+-    case 3: return u.format3.get_fd (glyph);
++    case 0: hb_barrier (); return u.format0.get_fd (glyph);
++    case 3: hb_barrier (); return u.format3.get_fd (glyph);
+     default:return 0;
+     }
+   }
+@@ -548,8 +332,8 @@ struct FDSelect
+ 
+     switch (format)
+     {
+-    case 0: return u.format0.get_fd_range (glyph);
+-    case 3: return u.format3.get_fd_range (glyph);
++    case 0: hb_barrier (); return u.format0.get_fd_range (glyph);
++    case 3: hb_barrier (); return u.format3.get_fd_range (glyph);
+     default:return {0, 1};
+     }
+   }
+@@ -559,11 +343,12 @@ struct FDSelect
+     TRACE_SANITIZE (this);
+     if (unlikely (!c->check_struct (this)))
+       return_trace (false);
++    hb_barrier ();
+ 
+     switch (format)
+     {
+-    case 0: return_trace (u.format0.sanitize (c, fdcount));
+-    case 3: return_trace (u.format3.sanitize (c, fdcount));
++    case 0: hb_barrier (); return_trace (u.format0.sanitize (c, fdcount));
++    case 3: hb_barrier (); return_trace (u.format3.sanitize (c, fdcount));
+     default:return_trace (false);
+     }
+   }
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-cff1-table.cc b/src/java.desktop/share/native/libharfbuzz/hb-ot-cff1-table.cc
+index 6fcc8c465..b06936f94 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-cff1-table.cc
++++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-cff1-table.cc
+@@ -553,15 +553,6 @@ bool _get_path (const OT::cff1::accelerator_t *cff, hb_font_t *font, hb_codepoin
+   return true;
+ }
+ 
+-bool OT::cff1::accelerator_t::paint_glyph (hb_font_t *font, hb_codepoint_t glyph, hb_paint_funcs_t *funcs, void *data, hb_color_t foreground) const
+-{
+-  funcs->push_clip_glyph (data, glyph, font);
+-  funcs->color (data, true, foreground);
+-  funcs->pop_clip (data);
+-
+-  return true;
+-}
+-
+ 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
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-cff1-table.hh b/src/java.desktop/share/native/libharfbuzz/hb-ot-cff1-table.hh
+index d1310c66f..0116a0c91 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-cff1-table.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-cff1-table.hh
+@@ -51,9 +51,6 @@ namespace CFF {
+ enum EncodingID { StandardEncoding = 0, ExpertEncoding = 1 };
+ enum CharsetID { ISOAdobeCharset = 0, ExpertCharset = 1, ExpertSubsetCharset = 2 };
+ 
+-typedef CFFIndex  CFF1Index;
+-
+-typedef CFFIndex CFF1Index;
+ typedef CFF1Index          CFF1CharStrings;
+ typedef Subrs    CFF1Subrs;
+ 
+@@ -242,8 +239,8 @@ struct Encoding
+     unsigned int size = min_size;
+     switch (table_format ())
+     {
+-    case 0: size += u.format0.get_size (); break;
+-    case 1: size += u.format1.get_size (); break;
++    case 0: hb_barrier (); size += u.format0.get_size (); break;
++    case 1: hb_barrier (); size += u.format1.get_size (); break;
+     }
+     if (has_supplement ())
+       size += suppEncData ().get_size ();
+@@ -254,8 +251,8 @@ struct Encoding
+   {
+     switch (table_format ())
+     {
+-    case 0: return u.format0.get_code (glyph);
+-    case 1: return u.format1.get_code (glyph);
++    case 0: hb_barrier (); return u.format0.get_code (glyph);
++    case 1: hb_barrier (); return u.format1.get_code (glyph);
+     default:return 0;
+     }
+   }
+@@ -275,11 +272,12 @@ struct Encoding
+     TRACE_SANITIZE (this);
+     if (unlikely (!c->check_struct (this)))
+       return_trace (false);
++    hb_barrier ();
+ 
+     switch (table_format ())
+     {
+-    case 0: if (unlikely (!u.format0.sanitize (c))) { return_trace (false); } break;
+-    case 1: if (unlikely (!u.format1.sanitize (c))) { return_trace (false); } break;
++    case 0: hb_barrier (); if (unlikely (!u.format0.sanitize (c))) { return_trace (false); } break;
++    case 1: hb_barrier (); if (unlikely (!u.format1.sanitize (c))) { return_trace (false); } break;
+     default:return_trace (false);
+     }
+     return_trace (likely (!has_supplement () || suppEncData ().sanitize (c)));
+@@ -290,8 +288,8 @@ struct Encoding
+   {
+     switch (table_format ())
+     {
+-    case 0: return StructAfter (u.format0.codes[u.format0.nCodes ()-1]);
+-    case 1: return StructAfter (u.format1.ranges[u.format1.nRanges ()-1]);
++    case 0: hb_barrier (); return StructAfter (u.format0.codes[u.format0.nCodes ()-1]);
++    case 1: hb_barrier (); return StructAfter (u.format1.ranges[u.format1.nRanges ()-1]);
+     default:return Null (CFF1SuppEncData);
+     }
+   }
+@@ -376,13 +374,13 @@ struct Charset1_2 {
+   bool sanitize (hb_sanitize_context_t *c, unsigned int num_glyphs, unsigned *num_charset_entries) const
+   {
+     TRACE_SANITIZE (this);
+-    if (unlikely (!c->check_struct (this)))
+-      return_trace (false);
+     num_glyphs--;
+     unsigned i;
+     for (i = 0; num_glyphs > 0; i++)
+     {
+-      if (unlikely (!ranges[i].sanitize (c) || (num_glyphs < ranges[i].nLeft + 1)))
++      if (unlikely (!(ranges[i].sanitize (c) &&
++                      hb_barrier () &&
++                      (num_glyphs >= ranges[i].nLeft + 1))))
+         return_trace (false);
+       num_glyphs -= (ranges[i].nLeft + 1);
+     }
+@@ -569,9 +567,9 @@ struct Charset
+   {
+     switch (format)
+     {
+-    case 0: return min_size + u.format0.get_size (num_glyphs);
+-    case 1: return min_size + u.format1.get_size (num_glyphs);
+-    case 2: return min_size + u.format2.get_size (num_glyphs);
++    case 0: hb_barrier (); return min_size + u.format0.get_size (num_glyphs);
++    case 1: hb_barrier (); return min_size + u.format1.get_size (num_glyphs);
++    case 2: hb_barrier (); return min_size + u.format2.get_size (num_glyphs);
+     default:return 0;
+     }
+   }
+@@ -581,9 +579,9 @@ struct Charset
+   {
+     switch (format)
+     {
+-    case 0: return u.format0.get_sid (glyph, num_glyphs);
+-    case 1: return u.format1.get_sid (glyph, num_glyphs, cache);
+-    case 2: return u.format2.get_sid (glyph, num_glyphs, cache);
++    case 0: hb_barrier (); return u.format0.get_sid (glyph, num_glyphs);
++    case 1: hb_barrier (); return u.format1.get_sid (glyph, num_glyphs, cache);
++    case 2: hb_barrier (); return u.format2.get_sid (glyph, num_glyphs, cache);
+     default:return 0;
+     }
+   }
+@@ -592,9 +590,9 @@ struct Charset
+   {
+     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;
++    case 0: hb_barrier (); u.format0.collect_glyph_to_sid_map (mapping, num_glyphs); return;
++    case 1: hb_barrier (); u.format1.collect_glyph_to_sid_map (mapping, num_glyphs); return;
++    case 2: hb_barrier (); u.format2.collect_glyph_to_sid_map (mapping, num_glyphs); return;
+     default:return;
+     }
+   }
+@@ -603,9 +601,9 @@ struct Charset
+   {
+     switch (format)
+     {
+-    case 0: return u.format0.get_glyph (sid, num_glyphs);
+-    case 1: return u.format1.get_glyph (sid, num_glyphs);
+-    case 2: return u.format2.get_glyph (sid, num_glyphs);
++    case 0: hb_barrier (); return u.format0.get_glyph (sid, num_glyphs);
++    case 1: hb_barrier (); return u.format1.get_glyph (sid, num_glyphs);
++    case 2: hb_barrier (); return u.format2.get_glyph (sid, num_glyphs);
+     default:return 0;
+     }
+   }
+@@ -615,12 +613,13 @@ struct Charset
+     TRACE_SANITIZE (this);
+     if (unlikely (!c->check_struct (this)))
+       return_trace (false);
++    hb_barrier ();
+ 
+     switch (format)
+     {
+-    case 0: return_trace (u.format0.sanitize (c, c->get_num_glyphs (), num_charset_entries));
+-    case 1: return_trace (u.format1.sanitize (c, c->get_num_glyphs (), num_charset_entries));
+-    case 2: return_trace (u.format2.sanitize (c, c->get_num_glyphs (), num_charset_entries));
++    case 0: hb_barrier (); return_trace (u.format0.sanitize (c, c->get_num_glyphs (), num_charset_entries));
++    case 1: hb_barrier (); return_trace (u.format1.sanitize (c, c->get_num_glyphs (), num_charset_entries));
++    case 2: hb_barrier (); return_trace (u.format2.sanitize (c, c->get_num_glyphs (), num_charset_entries));
+     default:return_trace (false);
+     }
+   }
+@@ -761,9 +760,9 @@ struct cff1_top_dict_values_t : top_dict_values_t
+   unsigned int    ros_supplement;
+   unsigned int    cidCount;
+ 
+-  unsigned int    EncodingOffset;
+-  unsigned int    CharsetOffset;
+-  unsigned int    FDSelectOffset;
++  int             EncodingOffset;
++  int             CharsetOffset;
++  int             FDSelectOffset;
+   table_info_t    privateDictInfo;
+ };
+ 
+@@ -819,24 +818,24 @@ struct cff1_top_dict_opset_t : top_dict_opset_t
+         break;
+ 
+       case OpCode_Encoding:
+-        dictval.EncodingOffset = env.argStack.pop_uint ();
++        dictval.EncodingOffset = env.argStack.pop_int ();
+         env.clear_args ();
+         if (unlikely (dictval.EncodingOffset == 0)) return;
+         break;
+ 
+       case OpCode_charset:
+-        dictval.CharsetOffset = env.argStack.pop_uint ();
++        dictval.CharsetOffset = env.argStack.pop_int ();
+         env.clear_args ();
+         if (unlikely (dictval.CharsetOffset == 0)) return;
+         break;
+ 
+       case OpCode_FDSelect:
+-        dictval.FDSelectOffset = env.argStack.pop_uint ();
++        dictval.FDSelectOffset = env.argStack.pop_int ();
+         env.clear_args ();
+         break;
+ 
+       case OpCode_Private:
+-        dictval.privateDictInfo.offset = env.argStack.pop_uint ();
++        dictval.privateDictInfo.offset = env.argStack.pop_int ();
+         dictval.privateDictInfo.size = env.argStack.pop_uint ();
+         env.clear_args ();
+         break;
+@@ -911,7 +910,7 @@ struct cff1_private_dict_values_base_t : dict_values_t
+   }
+   void fini () { dict_values_t::fini (); }
+ 
+-  unsigned int      subrsOffset;
++  int                 subrsOffset;
+   const CFF1Subrs    *localSubrs;
+ };
+ 
+@@ -946,7 +945,7 @@ struct cff1_private_dict_opset_t : dict_opset_t
+         env.clear_args ();
+         break;
+       case OpCode_Subrs:
+-        dictval.subrsOffset = env.argStack.pop_uint ();
++        dictval.subrsOffset = env.argStack.pop_int ();
+         env.clear_args ();
+         break;
+ 
+@@ -988,7 +987,7 @@ struct cff1_private_dict_opset_subset_t : dict_opset_t
+         break;
+ 
+       case OpCode_Subrs:
+-        dictval.subrsOffset = env.argStack.pop_uint ();
++        dictval.subrsOffset = env.argStack.pop_int ();
+         env.clear_args ();
+         break;
+ 
+@@ -1055,6 +1054,7 @@ struct cff1
+   {
+     TRACE_SANITIZE (this);
+     return_trace (c->check_struct (this) &&
++                  hb_barrier () &&
+                   likely (version.major == 1));
+   }
+ 
+@@ -1085,14 +1085,17 @@ struct cff1
+       nameIndex = &cff->nameIndex (cff);
+       if ((nameIndex == &Null (CFF1NameIndex)) || !nameIndex->sanitize (&sc))
+         goto fail;
++      hb_barrier ();
+ 
+-      topDictIndex = &StructAtOffset (nameIndex, nameIndex->get_size ());
+-      if ((topDictIndex == &Null (CFF1TopDictIndex)) || !topDictIndex->sanitize (&sc) || (topDictIndex->count == 0))
++      topDictIndex = &StructAtOffsetOrNull (nameIndex, nameIndex->get_size (), sc);
++      if (topDictIndex == &Null (CFF1TopDictIndex) || (topDictIndex->count == 0))
+         goto fail;
++      hb_barrier ();
+ 
+       { /* parse top dict */
+         const hb_ubytes_t topDictStr = (*topDictIndex)[0];
+         if (unlikely (!topDictStr.sanitize (&sc)))   goto fail;
++        hb_barrier ();
+         cff1_top_dict_interp_env_t env (topDictStr);
+         cff1_top_dict_interpreter_t top_interp (env);
+         if (unlikely (!top_interp.interpret (topDict)))   goto fail;
+@@ -1102,17 +1105,17 @@ struct cff1
+         charset = &Null (Charset);
+       else
+       {
+-        charset = &StructAtOffsetOrNull (cff, topDict.CharsetOffset);
+-        if (unlikely ((charset == &Null (Charset)) || !charset->sanitize (&sc, &num_charset_entries)))   goto fail;
++        charset = &StructAtOffsetOrNull (cff, topDict.CharsetOffset, sc, &num_charset_entries);
++        if (unlikely (charset == &Null (Charset)))   goto fail;
+       }
+ 
+       fdCount = 1;
+       if (is_CID ())
+       {
+-        fdArray = &StructAtOffsetOrNull (cff, topDict.FDArrayOffset);
+-        fdSelect = &StructAtOffsetOrNull (cff, topDict.FDSelectOffset);
+-        if (unlikely ((fdArray == &Null (CFF1FDArray)) || !fdArray->sanitize (&sc) ||
+-            (fdSelect == &Null (CFF1FDSelect)) || !fdSelect->sanitize (&sc, fdArray->count)))
++        fdArray = &StructAtOffsetOrNull (cff, topDict.FDArrayOffset, sc);
++        fdSelect = &StructAtOffsetOrNull (cff, topDict.FDSelectOffset, sc, fdArray->count);
++        if (unlikely (fdArray == &Null (CFF1FDArray) ||
++                      fdSelect == &Null (CFF1FDSelect)))
+           goto fail;
+ 
+         fdCount = fdArray->count;
+@@ -1132,22 +1135,18 @@ struct cff1
+       {
+         if (!is_predef_encoding ())
+         {
+-          encoding = &StructAtOffsetOrNull (cff, topDict.EncodingOffset);
+-          if (unlikely ((encoding == &Null (Encoding)) || !encoding->sanitize (&sc)))   goto fail;
++          encoding = &StructAtOffsetOrNull (cff, topDict.EncodingOffset, sc);
++          if (unlikely (encoding == &Null (Encoding)))   goto fail;
+         }
+       }
+ 
+-      stringIndex = &StructAtOffset (topDictIndex, topDictIndex->get_size ());
+-      if ((stringIndex == &Null (CFF1StringIndex)) || !stringIndex->sanitize (&sc))
++      stringIndex = &StructAtOffsetOrNull (topDictIndex, topDictIndex->get_size (), sc);
++      if (stringIndex == &Null (CFF1StringIndex))
+         goto fail;
+ 
+-      globalSubrs = &StructAtOffset (stringIndex, stringIndex->get_size ());
+-      if ((globalSubrs != &Null (CFF1Subrs)) && !globalSubrs->sanitize (&sc))
+-        goto fail;
+-
+-      charStrings = &StructAtOffsetOrNull (cff, topDict.charStringsOffset);
+-
+-      if ((charStrings == &Null (CFF1CharStrings)) || unlikely (!charStrings->sanitize (&sc)))
++      globalSubrs = &StructAtOffsetOrNull (stringIndex, stringIndex->get_size (), sc);
++      charStrings = &StructAtOffsetOrNull (cff, topDict.charStringsOffset, sc);
++      if (charStrings == &Null (CFF1CharStrings))
+         goto fail;
+ 
+       num_glyphs = charStrings->count;
+@@ -1166,6 +1165,7 @@ struct cff1
+         {
+           hb_ubytes_t fontDictStr = (*fdArray)[i];
+           if (unlikely (!fontDictStr.sanitize (&sc)))   goto fail;
++          hb_barrier ();
+           cff1_font_dict_values_t *font;
+           cff1_top_dict_interp_env_t env (fontDictStr);
+           cff1_font_dict_interpreter_t font_interp (env);
+@@ -1175,17 +1175,14 @@ struct cff1
+           font->init ();
+           if (unlikely (!font_interp.interpret (*font)))   goto fail;
+           PRIVDICTVAL *priv = &privateDicts[i];
+-          const hb_ubytes_t privDictStr = StructAtOffset (cff, font->privateDictInfo.offset).as_ubytes (font->privateDictInfo.size);
+-          if (unlikely (!privDictStr.sanitize (&sc)))   goto fail;
++          const hb_ubytes_t privDictStr = StructAtOffsetOrNull (cff, font->privateDictInfo.offset, sc, font->privateDictInfo.size).as_ubytes (font->privateDictInfo.size);
++          if (unlikely (privDictStr == (const unsigned char *) &Null (UnsizedByteStr))) goto fail;
+           num_interp_env_t env2 (privDictStr);
+           dict_interpreter_t priv_interp (env2);
+           priv->init ();
+           if (unlikely (!priv_interp.interpret (*priv)))   goto fail;
+ 
+-          priv->localSubrs = &StructAtOffsetOrNull (&privDictStr, priv->subrsOffset);
+-          if (priv->localSubrs != &Null (CFF1Subrs) &&
+-              unlikely (!priv->localSubrs->sanitize (&sc)))
+-            goto fail;
++          priv->localSubrs = &StructAtOffsetOrNull (&privDictStr, priv->subrsOffset, sc);
+         }
+       }
+       else  /* non-CID */
+@@ -1193,17 +1190,15 @@ struct cff1
+         cff1_top_dict_values_t *font = &topDict;
+         PRIVDICTVAL *priv = &privateDicts[0];
+ 
+-        const hb_ubytes_t privDictStr = StructAtOffset (cff, font->privateDictInfo.offset).as_ubytes (font->privateDictInfo.size);
+-        if (unlikely (!privDictStr.sanitize (&sc)))   goto fail;
++        const hb_ubytes_t privDictStr = StructAtOffsetOrNull (cff, font->privateDictInfo.offset, sc, font->privateDictInfo.size).as_ubytes (font->privateDictInfo.size);
++        if (unlikely (privDictStr == (const unsigned char *) &Null (UnsizedByteStr))) goto fail;
+         num_interp_env_t env (privDictStr);
+         dict_interpreter_t priv_interp (env);
+         priv->init ();
+         if (unlikely (!priv_interp.interpret (*priv)))   goto fail;
+ 
+-        priv->localSubrs = &StructAtOffsetOrNull (&privDictStr, priv->subrsOffset);
+-        if (priv->localSubrs != &Null (CFF1Subrs) &&
+-            unlikely (!priv->localSubrs->sanitize (&sc)))
+-          goto fail;
++        priv->localSubrs = &StructAtOffsetOrNull (&privDictStr, priv->subrsOffset, sc);
++        hb_barrier ();
+       }
+ 
+       return;
+@@ -1420,7 +1415,7 @@ struct cff1
+       hb_sorted_vector_t *names = glyph_names.get_acquire ();
+       if (unlikely (!names))
+       {
+-        names = (hb_sorted_vector_t *) hb_calloc (sizeof (hb_sorted_vector_t), 1);
++        names = (hb_sorted_vector_t *) hb_calloc (1, sizeof (hb_sorted_vector_t));
+         if (likely (names))
+         {
+           names->init ();
+@@ -1467,7 +1462,6 @@ struct cff1
+     }
+ 
+     HB_INTERNAL bool get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const;
+-    HB_INTERNAL bool paint_glyph (hb_font_t *font, hb_codepoint_t glyph, hb_paint_funcs_t *funcs, void *data, hb_color_t foreground) const;
+     HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const;
+ 
+     private:
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-cff2-table.cc b/src/java.desktop/share/native/libharfbuzz/hb-ot-cff2-table.cc
+index ed430ee59..fce39da21 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-cff2-table.cc
++++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-cff2-table.cc
+@@ -143,15 +143,6 @@ bool OT::cff2::accelerator_t::get_extents (hb_font_t *font,
+   return true;
+ }
+ 
+-bool OT::cff2::accelerator_t::paint_glyph (hb_font_t *font, hb_codepoint_t glyph, hb_paint_funcs_t *funcs, void *data, hb_color_t foreground) const
+-{
+-  funcs->push_clip_glyph (data, glyph, font);
+-  funcs->color (data, true, foreground);
+-  funcs->pop_clip (data);
+-
+-  return true;
+-}
+-
+ struct cff2_path_param_t
+ {
+   cff2_path_param_t (hb_font_t *font_, hb_draw_session_t &draw_session_)
+@@ -202,6 +193,11 @@ struct cff2_path_procs_path_t : path_procs_t {};
+ 
+ bool OT::cff2::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const
++{
++  return get_path_at (font, glyph, draw_session, hb_array (font->coords, font->num_coords));
++}
++
++bool OT::cff2::accelerator_t::get_path_at (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session, hb_array_t coords) const
+ {
+ #ifdef HB_NO_OT_FONT_CFF
+   /* XXX Remove check when this code moves to .hh file. */
+@@ -212,7 +208,7 @@ bool OT::cff2::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, h
+ 
+   unsigned int fd = fdSelect->get_fd (glyph);
+   const hb_ubytes_t str = (*charStrings)[glyph];
+-  cff2_cs_interp_env_t env (str, *this, fd, font->coords, font->num_coords);
++  cff2_cs_interp_env_t env (str, *this, fd, coords.arrayZ, coords.length);
+   cff2_cs_interpreter_t interp (env);
+   cff2_path_param_t param (font, draw_session);
+   if (unlikely (!interp.interpret (param))) return false;
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-cff2-table.hh b/src/java.desktop/share/native/libharfbuzz/hb-ot-cff2-table.hh
+index db10f22ec..81d30f57a 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-cff2-table.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-cff2-table.hh
+@@ -40,8 +40,6 @@ namespace CFF {
+  */
+ #define HB_OT_TAG_CFF2 HB_TAG('C','F','F','2')
+ 
+-typedef CFFIndex  CFF2Index;
+-
+ typedef CFF2Index         CFF2CharStrings;
+ typedef Subrs   CFF2Subrs;
+ 
+@@ -64,9 +62,9 @@ struct CFF2FDSelect
+   {
+     switch (format)
+     {
+-    case 0: return format.static_size + u.format0.get_size (num_glyphs);
+-    case 3: return format.static_size + u.format3.get_size ();
+-    case 4: return format.static_size + u.format4.get_size ();
++    case 0: hb_barrier (); return format.static_size + u.format0.get_size (num_glyphs);
++    case 3: hb_barrier (); return format.static_size + u.format3.get_size ();
++    case 4: hb_barrier (); return format.static_size + u.format4.get_size ();
+     default:return 0;
+     }
+   }
+@@ -78,9 +76,9 @@ struct CFF2FDSelect
+ 
+     switch (format)
+     {
+-    case 0: return u.format0.get_fd (glyph);
+-    case 3: return u.format3.get_fd (glyph);
+-    case 4: return u.format4.get_fd (glyph);
++    case 0: hb_barrier (); return u.format0.get_fd (glyph);
++    case 3: hb_barrier (); return u.format3.get_fd (glyph);
++    case 4: hb_barrier (); return u.format4.get_fd (glyph);
+     default:return 0;
+     }
+   }
+@@ -90,12 +88,13 @@ struct CFF2FDSelect
+     TRACE_SANITIZE (this);
+     if (unlikely (!c->check_struct (this)))
+       return_trace (false);
++    hb_barrier ();
+ 
+     switch (format)
+     {
+-    case 0: return_trace (u.format0.sanitize (c, fdcount));
+-    case 3: return_trace (u.format3.sanitize (c, fdcount));
+-    case 4: return_trace (u.format4.sanitize (c, fdcount));
++    case 0: hb_barrier (); return_trace (u.format0.sanitize (c, fdcount));
++    case 3: hb_barrier (); return_trace (u.format3.sanitize (c, fdcount));
++    case 4: hb_barrier (); return_trace (u.format4.sanitize (c, fdcount));
+     default:return_trace (false);
+     }
+   }
+@@ -110,19 +109,22 @@ struct CFF2FDSelect
+   DEFINE_SIZE_MIN (2);
+ };
+ 
+-struct CFF2VariationStore
++struct CFF2ItemVariationStore
+ {
+   bool sanitize (hb_sanitize_context_t *c) const
+   {
+     TRACE_SANITIZE (this);
+-    return_trace (likely (c->check_struct (this)) && c->check_range (&varStore, size) && varStore.sanitize (c));
++    return_trace (c->check_struct (this) &&
++                  hb_barrier () &&
++                  c->check_range (&varStore, size) &&
++                  varStore.sanitize (c));
+   }
+ 
+-  bool serialize (hb_serialize_context_t *c, const CFF2VariationStore *varStore)
++  bool serialize (hb_serialize_context_t *c, const CFF2ItemVariationStore *varStore)
+   {
+     TRACE_SERIALIZE (this);
+     unsigned int size_ = varStore->get_size ();
+-    CFF2VariationStore *dest = c->allocate_size (size_);
++    CFF2ItemVariationStore *dest = c->allocate_size (size_);
+     if (unlikely (!dest)) return_trace (false);
+     hb_memcpy (dest, varStore, size_);
+     return_trace (true);
+@@ -131,9 +133,9 @@ struct CFF2VariationStore
+   unsigned int get_size () const { return HBUINT16::static_size + size; }
+ 
+   HBUINT16      size;
+-  VariationStore  varStore;
++  ItemVariationStore  varStore;
+ 
+-  DEFINE_SIZE_MIN (2 + VariationStore::min_size);
++  DEFINE_SIZE_MIN (2 + ItemVariationStore::min_size);
+ };
+ 
+ struct cff2_top_dict_values_t : top_dict_values_t<>
+@@ -146,8 +148,8 @@ struct cff2_top_dict_values_t : top_dict_values_t<>
+   }
+   void fini () { top_dict_values_t<>::fini (); }
+ 
+-  unsigned int  vstoreOffset;
+-  unsigned int  FDSelectOffset;
++  int  vstoreOffset;
++  int  FDSelectOffset;
+ };
+ 
+ struct cff2_top_dict_opset_t : top_dict_opset_t<>
+@@ -165,11 +167,11 @@ struct cff2_top_dict_opset_t : top_dict_opset_t<>
+         break;
+ 
+       case OpCode_vstore:
+-        dictval.vstoreOffset = env.argStack.pop_uint ();
++        dictval.vstoreOffset = env.argStack.pop_int ();
+         env.clear_args ();
+         break;
+       case OpCode_FDSelect:
+-        dictval.FDSelectOffset = env.argStack.pop_uint ();
++        dictval.FDSelectOffset = env.argStack.pop_int ();
+         env.clear_args ();
+         break;
+ 
+@@ -237,7 +239,7 @@ struct cff2_private_dict_values_base_t : dict_values_t
+   }
+   void fini () { dict_values_t::fini (); }
+ 
+-  unsigned int      subrsOffset;
++  int                subrsOffset;
+   const CFF2Subrs   *localSubrs;
+   unsigned int      ivs;
+ };
+@@ -291,7 +293,7 @@ struct cff2_private_dict_opset_t : dict_opset_t
+         env.clear_args ();
+         break;
+       case OpCode_Subrs:
+-        dictval.subrsOffset = env.argStack.pop_uint ();
++        dictval.subrsOffset = env.argStack.pop_int ();
+         env.clear_args ();
+         break;
+       case OpCode_vsindexdict:
+@@ -340,7 +342,7 @@ struct cff2_private_dict_opset_subset_t : dict_opset_t
+         return;
+ 
+       case OpCode_Subrs:
+-        dictval.subrsOffset = env.argStack.pop_uint ();
++        dictval.subrsOffset = env.argStack.pop_int ();
+         env.clear_args ();
+         break;
+ 
+@@ -384,6 +386,7 @@ struct cff2
+   {
+     TRACE_SANITIZE (this);
+     return_trace (c->check_struct (this) &&
++                  hb_barrier () &&
+                   likely (version.major == 2));
+   }
+ 
+@@ -414,23 +417,22 @@ struct cff2
+       { /* parse top dict */
+         hb_ubytes_t topDictStr = (cff2 + cff2->topDict).as_ubytes (cff2->topDictSize);
+         if (unlikely (!topDictStr.sanitize (&sc))) goto fail;
++        hb_barrier ();
+         num_interp_env_t env (topDictStr);
+         cff2_top_dict_interpreter_t top_interp (env);
+         topDict.init ();
+         if (unlikely (!top_interp.interpret (topDict))) goto fail;
+       }
+ 
+-      globalSubrs = &StructAtOffset (cff2, cff2->topDict + cff2->topDictSize);
+-      varStore = &StructAtOffsetOrNull (cff2, topDict.vstoreOffset);
+-      charStrings = &StructAtOffsetOrNull (cff2, topDict.charStringsOffset);
+-      fdArray = &StructAtOffsetOrNull (cff2, topDict.FDArrayOffset);
+-      fdSelect = &StructAtOffsetOrNull (cff2, topDict.FDSelectOffset);
+-
+-      if (((varStore != &Null (CFF2VariationStore)) && unlikely (!varStore->sanitize (&sc))) ||
+-          (charStrings == &Null (CFF2CharStrings)) || unlikely (!charStrings->sanitize (&sc)) ||
+-          (globalSubrs == &Null (CFF2Subrs)) || unlikely (!globalSubrs->sanitize (&sc)) ||
+-          (fdArray == &Null (CFF2FDArray)) || unlikely (!fdArray->sanitize (&sc)) ||
+-          (((fdSelect != &Null (CFF2FDSelect)) && unlikely (!fdSelect->sanitize (&sc, fdArray->count)))))
++      globalSubrs = &StructAtOffsetOrNull (cff2, cff2->topDict + cff2->topDictSize, sc);
++      varStore = &StructAtOffsetOrNull (cff2, topDict.vstoreOffset, sc);
++      charStrings = &StructAtOffsetOrNull (cff2, topDict.charStringsOffset, sc);
++      fdArray = &StructAtOffsetOrNull (cff2, topDict.FDArrayOffset, sc);
++      fdSelect = &StructAtOffsetOrNull (cff2, topDict.FDSelectOffset, sc, fdArray->count);
++
++      if (charStrings == &Null (CFF2CharStrings) ||
++          globalSubrs == &Null (CFF2Subrs) ||
++          fdArray == &Null (CFF2FDArray))
+         goto fail;
+ 
+       num_glyphs = charStrings->count;
+@@ -446,6 +448,7 @@ struct cff2
+       {
+         const hb_ubytes_t fontDictStr = (*fdArray)[i];
+         if (unlikely (!fontDictStr.sanitize (&sc))) goto fail;
++        hb_barrier ();
+         cff2_font_dict_values_t  *font;
+         num_interp_env_t env (fontDictStr);
+         cff2_font_dict_interpreter_t font_interp (env);
+@@ -454,17 +457,14 @@ struct cff2
+         font->init ();
+         if (unlikely (!font_interp.interpret (*font))) goto fail;
+ 
+-        const hb_ubytes_t privDictStr = StructAtOffsetOrNull (cff2, font->privateDictInfo.offset).as_ubytes (font->privateDictInfo.size);
+-        if (unlikely (!privDictStr.sanitize (&sc))) goto fail;
++        const hb_ubytes_t privDictStr = StructAtOffsetOrNull (cff2, font->privateDictInfo.offset, sc, font->privateDictInfo.size).as_ubytes (font->privateDictInfo.size);
++        if (unlikely (privDictStr == (const unsigned char *) &Null (UnsizedByteStr))) 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]))) goto fail;
+ 
+-        privateDicts[i].localSubrs = &StructAtOffsetOrNull (&privDictStr[0], privateDicts[i].subrsOffset);
+-        if (privateDicts[i].localSubrs != &Null (CFF2Subrs) &&
+-          unlikely (!privateDicts[i].localSubrs->sanitize (&sc)))
+-          goto fail;
++        privateDicts[i].localSubrs = &StructAtOffsetOrNull (&privDictStr[0], privateDicts[i].subrsOffset, sc);
+       }
+ 
+       return;
+@@ -499,7 +499,7 @@ struct cff2
+     hb_blob_t                   *blob = nullptr;
+     cff2_top_dict_values_t      topDict;
+     const CFF2Subrs             *globalSubrs = nullptr;
+-    const CFF2VariationStore    *varStore = nullptr;
++    const CFF2ItemVariationStore        *varStore = nullptr;
+     const CFF2CharStrings       *charStrings = nullptr;
+     const CFF2FDArray           *fdArray = nullptr;
+     const CFF2FDSelect          *fdSelect = nullptr;
+@@ -518,8 +518,8 @@ struct cff2
+     HB_INTERNAL bool get_extents (hb_font_t *font,
+                                   hb_codepoint_t glyph,
+                                   hb_glyph_extents_t *extents) const;
+-    HB_INTERNAL bool paint_glyph (hb_font_t *font, hb_codepoint_t glyph, hb_paint_funcs_t *funcs, void *data, hb_color_t foreground) const;
+     HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const;
++    HB_INTERNAL bool get_path_at (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session, hb_array_t coords) const;
+   };
+ 
+   struct accelerator_subset_t : accelerator_templ_t
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-cmap-table.hh b/src/java.desktop/share/native/libharfbuzz/hb-ot-cmap-table.hh
+index 7e6ced3df..249d4cac5 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-cmap-table.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-cmap-table.hh
+@@ -41,6 +41,148 @@
+ 
+ namespace OT {
+ 
++static inline uint8_t unicode_to_macroman (hb_codepoint_t u)
++{
++  static const struct unicode_to_macroman_t
++  {
++    uint16_t unicode;
++    uint8_t macroman;
++  }
++  mapping[] =
++  {
++    { 0x00A0, 0xCA },
++    { 0x00A1, 0xC1 },
++    { 0x00A2, 0xA2 },
++    { 0x00A3, 0xA3 },
++    { 0x00A5, 0xB4 },
++    { 0x00A7, 0xA4 },
++    { 0x00A8, 0xAC },
++    { 0x00A9, 0xA9 },
++    { 0x00AA, 0xBB },
++    { 0x00AB, 0xC7 },
++    { 0x00AC, 0xC2 },
++    { 0x00AE, 0xA8 },
++    { 0x00AF, 0xF8 },
++    { 0x00B0, 0xA1 },
++    { 0x00B1, 0xB1 },
++    { 0x00B4, 0xAB },
++    { 0x00B5, 0xB5 },
++    { 0x00B6, 0xA6 },
++    { 0x00B7, 0xE1 },
++    { 0x00B8, 0xFC },
++    { 0x00BA, 0xBC },
++    { 0x00BB, 0xC8 },
++    { 0x00BF, 0xC0 },
++    { 0x00C0, 0xCB },
++    { 0x00C1, 0xE7 },
++    { 0x00C2, 0xE5 },
++    { 0x00C3, 0xCC },
++    { 0x00C4, 0x80 },
++    { 0x00C5, 0x81 },
++    { 0x00C6, 0xAE },
++    { 0x00C7, 0x82 },
++    { 0x00C8, 0xE9 },
++    { 0x00C9, 0x83 },
++    { 0x00CA, 0xE6 },
++    { 0x00CB, 0xE8 },
++    { 0x00CC, 0xED },
++    { 0x00CD, 0xEA },
++    { 0x00CE, 0xEB },
++    { 0x00CF, 0xEC },
++    { 0x00D1, 0x84 },
++    { 0x00D2, 0xF1 },
++    { 0x00D3, 0xEE },
++    { 0x00D4, 0xEF },
++    { 0x00D5, 0xCD },
++    { 0x00D6, 0x85 },
++    { 0x00D8, 0xAF },
++    { 0x00D9, 0xF4 },
++    { 0x00DA, 0xF2 },
++    { 0x00DB, 0xF3 },
++    { 0x00DC, 0x86 },
++    { 0x00DF, 0xA7 },
++    { 0x00E0, 0x88 },
++    { 0x00E1, 0x87 },
++    { 0x00E2, 0x89 },
++    { 0x00E3, 0x8B },
++    { 0x00E4, 0x8A },
++    { 0x00E5, 0x8C },
++    { 0x00E6, 0xBE },
++    { 0x00E7, 0x8D },
++    { 0x00E8, 0x8F },
++    { 0x00E9, 0x8E },
++    { 0x00EA, 0x90 },
++    { 0x00EB, 0x91 },
++    { 0x00EC, 0x93 },
++    { 0x00ED, 0x92 },
++    { 0x00EE, 0x94 },
++    { 0x00EF, 0x95 },
++    { 0x00F1, 0x96 },
++    { 0x00F2, 0x98 },
++    { 0x00F3, 0x97 },
++    { 0x00F4, 0x99 },
++    { 0x00F5, 0x9B },
++    { 0x00F6, 0x9A },
++    { 0x00F7, 0xD6 },
++    { 0x00F8, 0xBF },
++    { 0x00F9, 0x9D },
++    { 0x00FA, 0x9C },
++    { 0x00FB, 0x9E },
++    { 0x00FC, 0x9F },
++    { 0x00FF, 0xD8 },
++    { 0x0131, 0xF5 },
++    { 0x0152, 0xCE },
++    { 0x0153, 0xCF },
++    { 0x0178, 0xD9 },
++    { 0x0192, 0xC4 },
++    { 0x02C6, 0xF6 },
++    { 0x02C7, 0xFF },
++    { 0x02D8, 0xF9 },
++    { 0x02D9, 0xFA },
++    { 0x02DA, 0xFB },
++    { 0x02DB, 0xFE },
++    { 0x02DC, 0xF7 },
++    { 0x02DD, 0xFD },
++    { 0x03A9, 0xBD },
++    { 0x03C0, 0xB9 },
++    { 0x2013, 0xD0 },
++    { 0x2014, 0xD1 },
++    { 0x2018, 0xD4 },
++    { 0x2019, 0xD5 },
++    { 0x201A, 0xE2 },
++    { 0x201C, 0xD2 },
++    { 0x201D, 0xD3 },
++    { 0x201E, 0xE3 },
++    { 0x2020, 0xA0 },
++    { 0x2021, 0xE0 },
++    { 0x2022, 0xA5 },
++    { 0x2026, 0xC9 },
++    { 0x2030, 0xE4 },
++    { 0x2039, 0xDC },
++    { 0x203A, 0xDD },
++    { 0x2044, 0xDA },
++    { 0x20AC, 0xDB },
++    { 0x2122, 0xAA },
++    { 0x2202, 0xB6 },
++    { 0x2206, 0xC6 },
++    { 0x220F, 0xB8 },
++    { 0x2211, 0xB7 },
++    { 0x221A, 0xC3 },
++    { 0x221E, 0xB0 },
++    { 0x222B, 0xBA },
++    { 0x2248, 0xC5 },
++    { 0x2260, 0xAD },
++    { 0x2264, 0xB2 },
++    { 0x2265, 0xB3 },
++    { 0x25CA, 0xD7 },
++    { 0xF8FF, 0xF0 },
++    { 0xFB01, 0xDE },
++    { 0xFB02, 0xDF },
++  };
++  auto *c = hb_bsearch (u, mapping, ARRAY_LENGTH (mapping), sizeof (mapping[0]),
++                        _hb_cmp_operator);
++  return c ? c->macroman : 0;
++}
+ 
+ struct CmapSubtableFormat0
+ {
+@@ -556,6 +698,7 @@ struct CmapSubtableFormat4
+     TRACE_SANITIZE (this);
+     if (unlikely (!c->check_struct (this)))
+       return_trace (false);
++    hb_barrier ();
+ 
+     if (unlikely (!c->check_range (this, length)))
+     {
+@@ -742,10 +885,11 @@ struct CmapSubtableLongSegmented
+                         unsigned num_glyphs) const
+   {
+     hb_codepoint_t last_end = 0;
+-    for (unsigned i = 0; i < this->groups.len; i++)
++    unsigned count = this->groups.len;
++    for (unsigned i = 0; i < count; 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 start = this->groups.arrayZ[i].startCharCode;
++      hb_codepoint_t end = hb_min ((hb_codepoint_t) this->groups.arrayZ[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.
+@@ -754,7 +898,7 @@ struct CmapSubtableLongSegmented
+       last_end = end;
+ 
+ 
+-      hb_codepoint_t gid = this->groups[i].glyphID;
++      hb_codepoint_t gid = this->groups.arrayZ[i].glyphID;
+       if (!gid)
+       {
+         if (T::formatNumber == 13) continue;
+@@ -767,9 +911,9 @@ struct CmapSubtableLongSegmented
+ 
+       mapping->alloc (mapping->get_population () + end - start + 1);
+ 
++      unicodes->add_range (start, end);
+       for (unsigned cp = start; cp <= end; cp++)
+       {
+-        unicodes->add (cp);
+         mapping->set (cp, gid);
+         gid += T::increment;
+       }
+@@ -1253,6 +1397,9 @@ struct CmapSubtableFormat14
+     hb_vector_t> obj_indices;
+     for (int i = src_tbl->record.len - 1; i >= 0; i--)
+     {
++      if (!unicodes->has(src_tbl->record[i].varSelector))
++        continue;
++
+       hb_pair_t result = src_tbl->record[i].copy (c, unicodes, glyphs_requested, glyph_map, base);
+       if (result.first || result.second)
+         obj_indices.push (result);
+@@ -1309,6 +1456,7 @@ struct CmapSubtableFormat14
+   {
+     + hb_iter (record)
+     | hb_filter (hb_bool, &VariationSelectorRecord::nonDefaultUVS)
++    | hb_filter (unicodes, &VariationSelectorRecord::varSelector)
+     | hb_map (&VariationSelectorRecord::nonDefaultUVS)
+     | hb_map (hb_add (this))
+     | hb_apply ([=] (const NonDefaultUVS& _) { _.closure_glyphs (unicodes, glyphset); })
+@@ -1353,12 +1501,12 @@ struct CmapSubtable
+                   hb_codepoint_t *glyph) const
+   {
+     switch (u.format) {
+-    case  0: return u.format0 .get_glyph (codepoint, glyph);
+-    case  4: return u.format4 .get_glyph (codepoint, glyph);
+-    case  6: return u.format6 .get_glyph (codepoint, glyph);
+-    case 10: return u.format10.get_glyph (codepoint, glyph);
+-    case 12: return u.format12.get_glyph (codepoint, glyph);
+-    case 13: return u.format13.get_glyph (codepoint, glyph);
++    case  0: hb_barrier (); return u.format0 .get_glyph (codepoint, glyph);
++    case  4: hb_barrier (); return u.format4 .get_glyph (codepoint, glyph);
++    case  6: hb_barrier (); return u.format6 .get_glyph (codepoint, glyph);
++    case 10: hb_barrier (); return u.format10.get_glyph (codepoint, glyph);
++    case 12: hb_barrier (); return u.format12.get_glyph (codepoint, glyph);
++    case 13: hb_barrier (); return u.format13.get_glyph (codepoint, glyph);
+     case 14:
+     default: return false;
+     }
+@@ -1366,12 +1514,12 @@ struct CmapSubtable
+   void collect_unicodes (hb_set_t *out, unsigned int num_glyphs = UINT_MAX) const
+   {
+     switch (u.format) {
+-    case  0: u.format0 .collect_unicodes (out); return;
+-    case  4: u.format4 .collect_unicodes (out); return;
+-    case  6: u.format6 .collect_unicodes (out); return;
+-    case 10: u.format10.collect_unicodes (out); return;
+-    case 12: u.format12.collect_unicodes (out, num_glyphs); return;
+-    case 13: u.format13.collect_unicodes (out, num_glyphs); return;
++    case  0: hb_barrier (); u.format0 .collect_unicodes (out); return;
++    case  4: hb_barrier (); u.format4 .collect_unicodes (out); return;
++    case  6: hb_barrier (); u.format6 .collect_unicodes (out); return;
++    case 10: hb_barrier (); u.format10.collect_unicodes (out); return;
++    case 12: hb_barrier (); u.format12.collect_unicodes (out, num_glyphs); return;
++    case 13: hb_barrier (); u.format13.collect_unicodes (out, num_glyphs); return;
+     case 14:
+     default: return;
+     }
+@@ -1382,12 +1530,12 @@ struct CmapSubtable
+                         unsigned num_glyphs = UINT_MAX) const
+   {
+     switch (u.format) {
+-    case  0: u.format0 .collect_mapping (unicodes, mapping); return;
+-    case  4: u.format4 .collect_mapping (unicodes, mapping); return;
+-    case  6: u.format6 .collect_mapping (unicodes, mapping); return;
+-    case 10: u.format10.collect_mapping (unicodes, mapping); return;
+-    case 12: u.format12.collect_mapping (unicodes, mapping, num_glyphs); return;
+-    case 13: u.format13.collect_mapping (unicodes, mapping, num_glyphs); return;
++    case  0: hb_barrier (); u.format0 .collect_mapping (unicodes, mapping); return;
++    case  4: hb_barrier (); u.format4 .collect_mapping (unicodes, mapping); return;
++    case  6: hb_barrier (); u.format6 .collect_mapping (unicodes, mapping); return;
++    case 10: hb_barrier (); u.format10.collect_mapping (unicodes, mapping); return;
++    case 12: hb_barrier (); u.format12.collect_mapping (unicodes, mapping, num_glyphs); return;
++    case 13: hb_barrier (); u.format13.collect_mapping (unicodes, mapping, num_glyphs); return;
+     case 14:
+     default: return;
+     }
+@@ -1396,12 +1544,12 @@ struct CmapSubtable
+   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  0: hb_barrier (); return u.format0 .get_language ();
++    case  4: hb_barrier (); return u.format4 .get_language ();
++    case  6: hb_barrier (); return u.format6 .get_language ();
++    case 10: hb_barrier (); return u.format10.get_language ();
++    case 12: hb_barrier (); return u.format12.get_language ();
++    case 13: hb_barrier (); return u.format13.get_language ();
+     case 14:
+     default: return 0;
+     }
+@@ -1416,9 +1564,9 @@ struct CmapSubtable
+                   const void *base)
+   {
+     switch (format) {
+-    case  4: return u.format4.serialize (c, it);
+-    case 12: return u.format12.serialize (c, it);
+-    case 14: return u.format14.serialize (c, &plan->unicodes, &plan->glyphs_requested, plan->glyph_map, base);
++    case  4: hb_barrier (); return u.format4.serialize (c, it);
++    case 12: hb_barrier (); return u.format12.serialize (c, it);
++    case 14: hb_barrier (); return u.format14.serialize (c, &plan->unicodes, &plan->glyphs_requested, plan->glyph_map, base);
+     default: return;
+     }
+   }
+@@ -1427,14 +1575,15 @@ struct CmapSubtable
+   {
+     TRACE_SANITIZE (this);
+     if (!u.format.sanitize (c)) return_trace (false);
++    hb_barrier ();
+     switch (u.format) {
+-    case  0: return_trace (u.format0 .sanitize (c));
+-    case  4: return_trace (u.format4 .sanitize (c));
+-    case  6: return_trace (u.format6 .sanitize (c));
+-    case 10: return_trace (u.format10.sanitize (c));
+-    case 12: return_trace (u.format12.sanitize (c));
+-    case 13: return_trace (u.format13.sanitize (c));
+-    case 14: return_trace (u.format14.sanitize (c));
++    case  0: hb_barrier (); return_trace (u.format0 .sanitize (c));
++    case  4: hb_barrier (); return_trace (u.format4 .sanitize (c));
++    case  6: hb_barrier (); return_trace (u.format6 .sanitize (c));
++    case 10: hb_barrier (); return_trace (u.format10.sanitize (c));
++    case 12: hb_barrier (); return_trace (u.format12.sanitize (c));
++    case 13: hb_barrier (); return_trace (u.format13.sanitize (c));
++    case 14: hb_barrier (); return_trace (u.format14.sanitize (c));
+     default:return_trace (true);
+     }
+   }
+@@ -1462,8 +1611,11 @@ struct EncodingRecord
+     int ret;
+     ret = platformID.cmp (other.platformID);
+     if (ret) return ret;
+-    ret = encodingID.cmp (other.encodingID);
+-    if (ret) return ret;
++    if (other.encodingID != 0xFFFF)
++    {
++      ret = encodingID.cmp (other.encodingID);
++      if (ret) return ret;
++    }
+     return 0;
+   }
+ 
+@@ -1811,9 +1963,13 @@ struct cmap
+                                          c->plan));
+   }
+ 
+-  const CmapSubtable *find_best_subtable (bool *symbol = nullptr) const
++  const CmapSubtable *find_best_subtable (bool *symbol = nullptr,
++                                          bool *mac = nullptr,
++                                          bool *macroman = nullptr) const
+   {
+     if (symbol) *symbol = false;
++    if (mac) *mac = false;
++    if (macroman) *macroman = false;
+ 
+     const CmapSubtable *subtable;
+ 
+@@ -1838,6 +1994,20 @@ struct cmap
+     if ((subtable = this->find_subtable (0, 1))) return subtable;
+     if ((subtable = this->find_subtable (0, 0))) return subtable;
+ 
++    /* MacRoman subtable. */
++    if ((subtable = this->find_subtable (1, 0)))
++    {
++      if (mac) *mac = true;
++      if (macroman) *macroman = true;
++      return subtable;
++    }
++    /* Any other Mac subtable; we just map ASCII for these. */
++    if ((subtable = this->find_subtable (1, 0xFFFF)))
++    {
++      if (mac) *mac = true;
++      return subtable;
++    }
++
+     /* Meh. */
+     return &Null (CmapSubtable);
+   }
+@@ -1849,8 +2019,8 @@ struct cmap
+     accelerator_t (hb_face_t *face)
+     {
+       this->table = hb_sanitize_context_t ().reference_table (face);
+-      bool symbol;
+-      this->subtable = table->find_best_subtable (&symbol);
++      bool symbol, mac, macroman;
++      this->subtable = table->find_best_subtable (&symbol, &mac, ¯oman);
+       this->subtable_uvs = &Null (CmapSubtableFormat14);
+       {
+         const CmapSubtable *st = table->find_subtable (0, 5);
+@@ -1859,6 +2029,7 @@ struct cmap
+       }
+ 
+       this->get_glyph_data = subtable;
++#ifndef HB_NO_CMAP_LEGACY_SUBTABLES
+       if (unlikely (symbol))
+       {
+         switch ((unsigned) face->table.OS2->get_font_page ()) {
+@@ -1878,7 +2049,16 @@ struct cmap
+           break;
+         }
+       }
++      else if (unlikely (macroman))
++      {
++        this->get_glyph_funcZ = get_glyph_from_macroman;
++      }
++      else if (unlikely (mac))
++      {
++        this->get_glyph_funcZ = get_glyph_from_ascii;
++      }
+       else
++#endif
+       {
+         switch (subtable->u.format) {
+         /* Accelerate format 4 and format 12. */
+@@ -1921,7 +2101,7 @@ struct cmap
+                             hb_codepoint_t *glyph,
+                             cache_t *cache = nullptr) const
+     {
+-      if (unlikely (!this->get_glyph_funcZ)) return 0;
++      if (unlikely (!this->get_glyph_funcZ)) return false;
+       return _cached_get (unicode, glyph, cache);
+     }
+ 
+@@ -2003,6 +2183,28 @@ struct cmap
+       return false;
+     }
+ 
++    template 
++    HB_INTERNAL static bool get_glyph_from_ascii (const void *obj,
++                                                  hb_codepoint_t codepoint,
++                                                  hb_codepoint_t *glyph)
++    {
++      const Type *typed_obj = (const Type *) obj;
++      return codepoint < 0x80 && typed_obj->get_glyph (codepoint, glyph);
++    }
++
++    template 
++    HB_INTERNAL static bool get_glyph_from_macroman (const void *obj,
++                                                     hb_codepoint_t codepoint,
++                                                     hb_codepoint_t *glyph)
++    {
++      if (get_glyph_from_ascii (obj, codepoint, glyph))
++        return true;
++
++      const Type *typed_obj = (const Type *) obj;
++      unsigned c = unicode_to_macroman (codepoint);
++      return c && typed_obj->get_glyph (c, glyph);
++    }
++
+     private:
+     hb_nonnull_ptr_t subtable;
+     hb_nonnull_ptr_t subtable_uvs;
+@@ -2032,34 +2234,13 @@ struct cmap
+     return &(this+result.subtable);
+   }
+ 
+-  const EncodingRecord *find_encodingrec (unsigned int platform_id,
+-                                          unsigned int encoding_id) const
+-  {
+-    EncodingRecord key;
+-    key.platformID = platform_id;
+-    key.encodingID = encoding_id;
+-
+-    return encodingRecord.as_array ().bsearch (key);
+-  }
+-
+-  bool find_subtable (unsigned format) const
+-  {
+-    auto it =
+-    + hb_iter (encodingRecord)
+-    | hb_map (&EncodingRecord::subtable)
+-    | hb_map (hb_add (this))
+-    | hb_filter ([&] (const CmapSubtable& _) { return _.u.format == format; })
+-    ;
+-
+-    return it.len ();
+-  }
+-
+   public:
+ 
+   bool sanitize (hb_sanitize_context_t *c) const
+   {
+     TRACE_SANITIZE (this);
+     return_trace (c->check_struct (this) &&
++                  hb_barrier () &&
+                   likely (version == 0) &&
+                   encodingRecord.sanitize (c, this));
+   }
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-face-table-list.hh b/src/java.desktop/share/native/libharfbuzz/hb-ot-face-table-list.hh
+index b552dfdd9..97825f4d1 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-face-table-list.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-face-table-list.hh
+@@ -95,12 +95,18 @@ HB_OT_CORE_TABLE (OT, fvar)
+ HB_OT_CORE_TABLE (OT, avar)
+ HB_OT_CORE_TABLE (OT, cvar)
+ HB_OT_ACCELERATOR (OT, gvar)
++#ifndef HB_NO_BEYOND_64K
++HB_OT_ACCELERATOR (OT, GVAR)
++#endif
+ HB_OT_CORE_TABLE (OT, MVAR)
++#ifndef HB_NO_VAR_COMPOSITES
++HB_OT_ACCELERATOR (OT, VARC)
++#endif
+ #endif
+ 
+ /* Legacy kern. */
+ #ifndef HB_NO_OT_KERN
+-HB_OT_CORE_TABLE (OT, kern)
++HB_OT_ACCELERATOR (OT, kern)
+ #endif
+ 
+ /* OpenType shaping. */
+@@ -118,9 +124,9 @@ HB_OT_CORE_TABLE (OT, BASE)
+ 
+ /* AAT shaping. */
+ #ifndef HB_NO_AAT
+-HB_OT_TABLE (AAT, morx)
+-HB_OT_TABLE (AAT, mort)
+-HB_OT_TABLE (AAT, kerx)
++HB_OT_ACCELERATOR (AAT, morx)
++HB_OT_ACCELERATOR (AAT, mort)
++HB_OT_ACCELERATOR (AAT, kerx)
+ HB_OT_TABLE (AAT, ankr)
+ HB_OT_TABLE (AAT, trak)
+ HB_OT_TABLE (AAT, ltag)
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-face.cc b/src/java.desktop/share/native/libharfbuzz/hb-ot-face.cc
+index 2243ee028..1cf14f3eb 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-face.cc
++++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-face.cc
+@@ -41,6 +41,9 @@
+ #include "hb-ot-layout-gdef-table.hh"
+ #include "hb-ot-layout-gsub-table.hh"
+ #include "hb-ot-layout-gpos-table.hh"
++#include "hb-ot-var-varc-table.hh"
++#include "hb-aat-layout-kerx-table.hh"
++#include "hb-aat-layout-morx-table.hh"
+ 
+ 
+ void hb_ot_face_t::init0 (hb_face_t *face)
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-font.cc b/src/java.desktop/share/native/libharfbuzz/hb-ot-font.cc
+index deec909b2..2a633c778 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-font.cc
++++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-font.cc
+@@ -36,13 +36,17 @@
+ #include "hb-ot-face.hh"
+ #include "hb-outline.hh"
+ 
++#ifndef HB_NO_AAT
++#include "hb-aat-layout-trak-table.hh"
++#endif
+ #include "hb-ot-cmap-table.hh"
+ #include "hb-ot-glyf-table.hh"
+ #include "hb-ot-cff2-table.hh"
+ #include "hb-ot-cff1-table.hh"
+ #include "hb-ot-hmtx-table.hh"
+ #include "hb-ot-post-table.hh"
+-#include "hb-ot-stat-table.hh" // Just so we compile it; unused otherwise.
++#include "hb-ot-stat-table.hh"
++#include "hb-ot-var-varc-table.hh"
+ #include "hb-ot-vorg-table.hh"
+ #include "OT/Color/CBDT/CBDT.hh"
+ #include "OT/Color/COLR/COLR.hh"
+@@ -72,6 +76,10 @@ struct hb_ot_font_t
+ {
+   const hb_ot_face_t *ot_face;
+ 
++#ifndef HB_NO_AAT
++  bool apply_trak;
++#endif
++
+ #ifndef HB_NO_OT_FONT_CMAP_CACHE
+   hb_ot_font_cmap_cache_t *cmap_cache;
+ #endif
+@@ -90,6 +98,15 @@ _hb_ot_font_create (hb_font_t *font)
+ 
+   ot_font->ot_face = &font->face->table;
+ 
++#ifndef HB_NO_AAT
++  /* According to Ned, trak is applied by default for "modern fonts", as detected by presence of STAT table. */
++#ifndef HB_NO_STYLE
++  ot_font->apply_trak = font->face->table.STAT->has_data () && font->face->table.trak->has_data ();
++#else
++  ot_font->apply_trak = false;
++#endif
++#endif
++
+ #ifndef HB_NO_OT_FONT_CMAP_CACHE
+   // retry:
+   auto *cmap_cache  = (hb_ot_font_cmap_cache_t *) hb_face_get_user_data (font->face,
+@@ -199,7 +216,6 @@ hb_ot_get_glyph_h_advances (hb_font_t* font, void* font_data,
+                             unsigned advance_stride,
+                             void *user_data HB_UNUSED)
+ {
+-
+   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;
+@@ -208,12 +224,12 @@ hb_ot_get_glyph_h_advances (hb_font_t* font, void* font_data,
+ 
+ #if !defined(HB_NO_VAR) && !defined(HB_NO_OT_FONT_ADVANCE_CACHE)
+   const OT::HVAR &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;
++  const OT::ItemVariationStore &varStore = &HVAR + HVAR.varStore;
++  OT::ItemVariationStore::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;
++  OT::ItemVariationStore::cache_t *varStore_cache = nullptr;
+   bool use_cache = false;
+ #endif
+ 
+@@ -277,7 +293,7 @@ hb_ot_get_glyph_h_advances (hb_font_t* font, void* font_data,
+   }
+ 
+ #if !defined(HB_NO_VAR) && !defined(HB_NO_OT_FONT_ADVANCE_CACHE)
+-  OT::VariationStore::destroy_cache (varStore_cache);
++  OT::ItemVariationStore::destroy_cache (varStore_cache);
+ #endif
+ 
+   if (font->x_strength && !font->embolden_in_place)
+@@ -291,6 +307,20 @@ hb_ot_get_glyph_h_advances (hb_font_t* font, void* font_data,
+       first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride);
+     }
+   }
++
++#ifndef HB_NO_AAT
++  if (ot_font->apply_trak)
++  {
++    hb_position_t tracking = font->face->table.trak->get_h_tracking (font);
++    first_advance = orig_first_advance;
++    for (unsigned int i = 0; i < count; i++)
++    {
++      *first_advance += tracking;
++      first_glyph = &StructAtOffsetUnaligned (first_glyph, glyph_stride);
++      first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride);
++    }
++  }
++#endif
+ }
+ 
+ #ifndef HB_NO_VERTICAL
+@@ -313,10 +343,10 @@ hb_ot_get_glyph_v_advances (hb_font_t* font, void* font_data,
+   {
+ #if !defined(HB_NO_VAR) && !defined(HB_NO_OT_FONT_ADVANCE_CACHE)
+     const OT::VVAR &VVAR = *vmtx.var_table;
+-    const OT::VariationStore &varStore = &VVAR + VVAR.varStore;
+-    OT::VariationStore::cache_t *varStore_cache = font->num_coords ? varStore.create_cache () : nullptr;
++    const OT::ItemVariationStore &varStore = &VVAR + VVAR.varStore;
++    OT::ItemVariationStore::cache_t *varStore_cache = font->num_coords ? varStore.create_cache () : nullptr;
+ #else
+-    OT::VariationStore::cache_t *varStore_cache = nullptr;
++    OT::ItemVariationStore::cache_t *varStore_cache = nullptr;
+ #endif
+ 
+     for (unsigned int i = 0; i < count; i++)
+@@ -327,7 +357,7 @@ hb_ot_get_glyph_v_advances (hb_font_t* font, void* font_data,
+     }
+ 
+ #if !defined(HB_NO_VAR) && !defined(HB_NO_OT_FONT_ADVANCE_CACHE)
+-    OT::VariationStore::destroy_cache (varStore_cache);
++    OT::ItemVariationStore::destroy_cache (varStore_cache);
+ #endif
+   }
+   else
+@@ -355,6 +385,20 @@ hb_ot_get_glyph_v_advances (hb_font_t* font, void* font_data,
+       first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride);
+     }
+   }
++
++#ifndef HB_NO_AAT
++  if (ot_font->apply_trak)
++  {
++    hb_position_t tracking = font->face->table.trak->get_v_tracking (font);
++    first_advance = orig_first_advance;
++    for (unsigned int i = 0; i < count; i++)
++    {
++      *first_advance += tracking;
++      first_glyph = &StructAtOffsetUnaligned (first_glyph, glyph_stride);
++      first_advance = &StructAtOffsetUnaligned (first_advance, advance_stride);
++    }
++  }
++#endif
+ }
+ #endif
+ 
+@@ -523,6 +567,10 @@ hb_ot_draw_glyph (hb_font_t *font,
+   { // Need draw_session to be destructed before emboldening.
+     hb_draw_session_t draw_session (embolden ? hb_outline_recording_pen_get_funcs () : draw_funcs,
+                                     embolden ? &outline : draw_data, font->slant_xy);
++#ifndef HB_NO_VAR_COMPOSITES
++    if (!font->face->table.VARC->get_path (font, glyph, draw_session))
++#endif
++    // Keep the following in synch with VARC::get_path_at()
+     if (!font->face->table.glyf->get_path (font, glyph, draw_session))
+ #ifndef HB_NO_CFF
+     if (!font->face->table.cff2->get_path (font, glyph, draw_session))
+@@ -563,11 +611,11 @@ hb_ot_paint_glyph (hb_font_t *font,
+   if (font->face->table.sbix->paint_glyph (font, glyph, paint_funcs, paint_data)) return;
+ #endif
+ #endif
+-  if (font->face->table.glyf->paint_glyph (font, glyph, paint_funcs, paint_data, foreground)) return;
+-#ifndef HB_NO_CFF
+-  if (font->face->table.cff2->paint_glyph (font, glyph, paint_funcs, paint_data, foreground)) return;
+-  if (font->face->table.cff1->paint_glyph (font, glyph, paint_funcs, paint_data, foreground)) return;
+-#endif
++
++  // Outline glyph
++  paint_funcs->push_clip_glyph (paint_data, glyph, font);
++  paint_funcs->color (paint_data, true, foreground);
++  paint_funcs->pop_clip (paint_data);
+ }
+ #endif
+ 
+@@ -634,7 +682,9 @@ _hb_ot_get_font_funcs ()
+  * hb_ot_font_set_funcs:
+  * @font: #hb_font_t to work upon
+  *
+- * Sets the font functions to use when working with @font.
++ * Sets the font functions to use when working with @font to
++ * the HarfBuzz's native implementation. This is the default
++ * for fonts newly created.
+  *
+  * Since: 0.9.28
+  **/
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-hdmx-table.hh b/src/java.desktop/share/native/libharfbuzz/hb-ot-hdmx-table.hh
+index 77e68dbca..918cf32dc 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-hdmx-table.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-hdmx-table.hh
+@@ -71,6 +71,7 @@ struct DeviceRecord
+   {
+     TRACE_SANITIZE (this);
+     return_trace (likely (c->check_struct (this) &&
++                          hb_barrier () &&
+                           c->check_range (this, sizeDeviceRecord)));
+   }
+ 
+@@ -94,7 +95,7 @@ struct hdmx
+   bool serialize (hb_serialize_context_t *c,
+                   unsigned version,
+                   Iterator it,
+-                  const hb_vector_t &new_to_old_gid_list,
++                  hb_array_t new_to_old_gid_list,
+                   unsigned num_glyphs)
+   {
+     TRACE_SERIALIZE (this);
+@@ -152,6 +153,7 @@ struct hdmx
+   {
+     TRACE_SANITIZE (this);
+     return_trace (c->check_struct (this) &&
++                  hb_barrier () &&
+                   !hb_unsigned_mul_overflows (numRecords, sizeDeviceRecord) &&
+                   min_size + numRecords * sizeDeviceRecord > numRecords * sizeDeviceRecord &&
+                   sizeDeviceRecord >= DeviceRecord::min_size &&
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-head-table.hh b/src/java.desktop/share/native/libharfbuzz/hb-ot-head-table.hh
+index ab057fcfe..34535e228 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-head-table.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-head-table.hh
+@@ -103,6 +103,7 @@ struct head
+   {
+     TRACE_SANITIZE (this);
+     return_trace (c->check_struct (this) &&
++                  hb_barrier () &&
+                   version.major == 1 &&
+                   magicNumber == 0x5F0F3CF5u);
+   }
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-hhea-table.hh b/src/java.desktop/share/native/libharfbuzz/hb-ot-hhea-table.hh
+index 37ef87445..5e3be5be5 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-hhea-table.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-hhea-table.hh
+@@ -50,7 +50,9 @@ struct _hea
+   bool sanitize (hb_sanitize_context_t *c) const
+   {
+     TRACE_SANITIZE (this);
+-    return_trace (c->check_struct (this) && likely (version.major == 1));
++    return_trace (c->check_struct (this) &&
++                  hb_barrier () &&
++                  likely (version.major == 1));
+   }
+ 
+   public:
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-hmtx-table.hh b/src/java.desktop/share/native/libharfbuzz/hb-ot-hmtx-table.hh
+index 39e1f4830..f7b4ca721 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-hmtx-table.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-hmtx-table.hh
+@@ -30,6 +30,7 @@
+ #include "hb-open-type.hh"
+ #include "hb-ot-maxp-table.hh"
+ #include "hb-ot-hhea-table.hh"
++#include "hb-ot-os2-table.hh"
+ #include "hb-ot-var-hvar-table.hh"
+ #include "hb-ot-var-mvar-table.hh"
+ #include "hb-ot-metrics.hh"
+@@ -145,6 +146,29 @@ struct hmtxvmtx
+         table->minTrailingBearing = min_rsb;
+         table->maxExtent = max_extent;
+       }
++
++      if (T::is_horizontal)
++      {
++        const auto &OS2 = *c->plan->source->table.OS2;
++        if (OS2.has_data () &&
++            table->ascender == OS2.sTypoAscender &&
++            table->descender == OS2.sTypoDescender &&
++            table->lineGap == OS2.sTypoLineGap)
++        {
++          table->ascender = static_cast (roundf (OS2.sTypoAscender +
++                                                      MVAR.get_var (HB_OT_METRICS_TAG_HORIZONTAL_ASCENDER,
++                                                                    c->plan->normalized_coords.arrayZ,
++                                                                    c->plan->normalized_coords.length)));
++          table->descender = static_cast (roundf (OS2.sTypoDescender +
++                                                       MVAR.get_var (HB_OT_METRICS_TAG_HORIZONTAL_DESCENDER,
++                                                                     c->plan->normalized_coords.arrayZ,
++                                                                     c->plan->normalized_coords.length)));
++          table->lineGap = static_cast (roundf (OS2.sTypoLineGap +
++                                                     MVAR.get_var (HB_OT_METRICS_TAG_HORIZONTAL_LINE_GAP,
++                                                                   c->plan->normalized_coords.arrayZ,
++                                                                   c->plan->normalized_coords.length)));
++        }
++      }
+     }
+ #endif
+ 
+@@ -158,7 +182,7 @@ struct hmtxvmtx
+            hb_requires (hb_is_iterator (Iterator))>
+   void serialize (hb_serialize_context_t *c,
+                   Iterator it,
+-                  const hb_vector_t new_to_old_gid_list,
++                  hb_array_t new_to_old_gid_list,
+                   unsigned num_long_metrics,
+                   unsigned total_num_metrics)
+   {
+@@ -374,7 +398,7 @@ struct hmtxvmtx
+ 
+     unsigned get_advance_with_var_unscaled (hb_codepoint_t  glyph,
+                                             hb_font_t      *font,
+-                                            VariationStore::cache_t *store_cache = nullptr) const
++                                            ItemVariationStore::cache_t *store_cache = nullptr) const
+     {
+       unsigned int advance = get_advance_without_var_unscaled (glyph);
+ 
+@@ -387,7 +411,8 @@ struct hmtxvmtx
+                                                                         font->coords, font->num_coords,
+                                                                         store_cache));
+ 
+-      return _glyf_get_advance_with_var_unscaled (font, glyph, T::tableTag == HB_OT_TAG_vmtx);
++      unsigned glyf_advance = _glyf_get_advance_with_var_unscaled (font, glyph, T::tableTag == HB_OT_TAG_vmtx);
++      return glyf_advance ? glyf_advance : advance;
+ #else
+       return advance;
+ #endif
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-kern-table.hh b/src/java.desktop/share/native/libharfbuzz/hb-ot-kern-table.hh
+index 291683369..bc90c345d 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-kern-table.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-kern-table.hh
+@@ -79,12 +79,23 @@ struct KernSubTableFormat3
+   {
+     TRACE_SANITIZE (this);
+     return_trace (c->check_struct (this) &&
++                  hb_barrier () &&
+                   c->check_range (kernValueZ,
+                                   kernValueCount * sizeof (FWORD) +
+                                   glyphCount * 2 +
+                                   leftClassCount * rightClassCount));
+   }
+ 
++  template 
++  void collect_glyphs (set_t &left_set, set_t &right_set, unsigned num_glyphs) const
++  {
++    set_t set;
++    if (likely (glyphCount))
++      set.add_range (0, glyphCount - 1);
++    left_set.union_ (set);
++    right_set.union_ (set);
++  }
++
+   protected:
+   KernSubTableHeader
+                 header;
+@@ -121,7 +132,7 @@ struct KernSubTable
+   {
+     switch (get_type ()) {
+     /* This method hooks up to hb_font_t's get_h_kerning.  Only support Format0. */
+-    case 0: return u.format0.get_kerning (left, right);
++    case 0: hb_barrier (); return u.format0.get_kerning (left, right);
+     default:return 0;
+     }
+   }
+@@ -134,22 +145,36 @@ struct KernSubTable
+     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, std::forward (ds)...) : c->default_return_value ());
++    case 1:     return_trace (c->dispatch (u.format1, std::forward (ds)...));
+ #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, std::forward (ds)...) : c->default_return_value ());
++    case 3:     return_trace (c->dispatch (u.format3, std::forward (ds)...));
+ #endif
+     default:    return_trace (c->default_return_value ());
+     }
+   }
+ 
++  template 
++  void collect_glyphs (set_t &left_set, set_t &right_set, unsigned num_glyphs) const
++  {
++    unsigned int subtable_type = get_type ();
++    switch (subtable_type) {
++    case 0:     u.format0.collect_glyphs (left_set, right_set, num_glyphs); return;
++    case 1:     u.format1.collect_glyphs (left_set, right_set, num_glyphs); return;
++    case 2:     u.format2.collect_glyphs (left_set, right_set, num_glyphs); return;
++    case 3:     u.format3.collect_glyphs (left_set, right_set, num_glyphs); return;
++    default:    return;
++    }
++  }
++
+   bool sanitize (hb_sanitize_context_t *c) const
+   {
+     TRACE_SANITIZE (this);
+-    if (unlikely (!u.header.sanitize (c) ||
+-                  u.header.length < u.header.min_size ||
+-                  !c->check_range (this, u.header.length))) return_trace (false);
++    if (unlikely (!(u.header.sanitize (c) &&
++                    hb_barrier () &&
++                    u.header.length >= u.header.min_size &&
++                    c->check_range (this, u.header.length)))) return_trace (false);
+ 
+     return_trace (dispatch (c));
+   }
+@@ -286,9 +311,9 @@ struct kern
+   bool has_state_machine () const
+   {
+     switch (get_type ()) {
+-    case 0: return u.ot.has_state_machine ();
++    case 0: hb_barrier (); return u.ot.has_state_machine ();
+ #ifndef HB_NO_AAT_SHAPE
+-    case 1: return u.aat.has_state_machine ();
++    case 1: hb_barrier (); return u.aat.has_state_machine ();
+ #endif
+     default:return false;
+     }
+@@ -297,9 +322,9 @@ struct kern
+   bool has_cross_stream () const
+   {
+     switch (get_type ()) {
+-    case 0: return u.ot.has_cross_stream ();
++    case 0: hb_barrier (); return u.ot.has_cross_stream ();
+ #ifndef HB_NO_AAT_SHAPE
+-    case 1: return u.aat.has_cross_stream ();
++    case 1: hb_barrier (); return u.aat.has_cross_stream ();
+ #endif
+     default:return false;
+     }
+@@ -308,16 +333,17 @@ struct kern
+   int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right) const
+   {
+     switch (get_type ()) {
+-    case 0: return u.ot.get_h_kerning (left, right);
++    case 0: hb_barrier (); return u.ot.get_h_kerning (left, right);
+ #ifndef HB_NO_AAT_SHAPE
+-    case 1: return u.aat.get_h_kerning (left, right);
++    case 1: hb_barrier (); return u.aat.get_h_kerning (left, right);
+ #endif
+     default:return 0;
+     }
+   }
+ 
+-  bool apply (AAT::hb_aat_apply_context_t *c) const
+-  { return dispatch (c); }
++  bool apply (AAT::hb_aat_apply_context_t *c,
++              const AAT::kern_accelerator_data_t &accel_data) const
++  { return dispatch (c, accel_data); }
+ 
+   template 
+   typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
+@@ -337,9 +363,45 @@ struct kern
+   {
+     TRACE_SANITIZE (this);
+     if (!u.version32.sanitize (c)) return_trace (false);
++    hb_barrier ();
+     return_trace (dispatch (c));
+   }
+ 
++  AAT::kern_accelerator_data_t create_accelerator_data (unsigned num_glyphs) const
++  {
++    switch (get_type ()) {
++    case 0: hb_barrier (); return u.ot.create_accelerator_data (num_glyphs);
++#ifndef HB_NO_AAT_SHAPE
++    case 1: hb_barrier (); return u.aat.create_accelerator_data (num_glyphs);
++#endif
++    default:return AAT::kern_accelerator_data_t ();
++    }
++  }
++
++  struct accelerator_t
++  {
++    accelerator_t (hb_face_t *face)
++    {
++      hb_sanitize_context_t sc;
++      this->table = sc.reference_table (face);
++      this->accel_data = this->table->create_accelerator_data (face->get_num_glyphs ());
++    }
++    ~accelerator_t ()
++    {
++      this->table.destroy ();
++    }
++
++    hb_blob_t *get_blob () const { return table.get_blob (); }
++
++    bool apply (AAT::hb_aat_apply_context_t *c) const
++    {
++      return table->apply (c, accel_data);
++    }
++
++    hb_blob_ptr_t table;
++    AAT::kern_accelerator_data_t accel_data;
++  };
++
+   protected:
+   union {
+   HBUINT32              version32;
+@@ -353,6 +415,10 @@ struct kern
+   DEFINE_SIZE_UNION (4, version32);
+ };
+ 
++struct kern_accelerator_t : kern::accelerator_t {
++  kern_accelerator_t (hb_face_t *face) : kern::accelerator_t (face) {}
++};
++
+ } /* namespace OT */
+ 
+ 
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-base-table.hh b/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-base-table.hh
+index 0e57a6c79..5a3679e4b 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-base-table.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-base-table.hh
+@@ -46,6 +46,12 @@ struct BaseCoordFormat1
+     return HB_DIRECTION_IS_HORIZONTAL (direction) ? font->em_scale_y (coordinate) : font->em_scale_x (coordinate);
+   }
+ 
++  bool subset (hb_subset_context_t *c) const
++  {
++    TRACE_SUBSET (this);
++    return_trace ((bool) c->serializer->embed (*this));
++  }
++
+   bool sanitize (hb_sanitize_context_t *c) const
+   {
+     TRACE_SANITIZE (this);
+@@ -67,6 +73,17 @@ struct BaseCoordFormat2
+     return HB_DIRECTION_IS_HORIZONTAL (direction) ? font->em_scale_y (coordinate) : font->em_scale_x (coordinate);
+   }
+ 
++  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->referenceGlyph,
++                                               c->plan->glyph_map->get (referenceGlyph),
++                                               HB_SERIALIZE_ERROR_INT_OVERFLOW));
++  }
++
+   bool sanitize (hb_sanitize_context_t *c) const
+   {
+     TRACE_SANITIZE (this);
+@@ -86,7 +103,7 @@ struct BaseCoordFormat2
+ struct BaseCoordFormat3
+ {
+   hb_position_t get_coord (hb_font_t *font,
+-                           const VariationStore &var_store,
++                           const ItemVariationStore &var_store,
+                            hb_direction_t direction) const
+   {
+     const Device &device = this+deviceTable;
+@@ -96,6 +113,37 @@ struct BaseCoordFormat3
+          : font->em_scale_x (coordinate) + device.get_x_delta (font, var_store);
+   }
+ 
++  void collect_variation_indices (hb_set_t& varidx_set /* OUT */) const
++  {
++    unsigned varidx = (this+deviceTable).get_variation_index ();
++    varidx_set.add (varidx);
++  }
++
++  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->plan->pinned_at_default)
++    {
++      unsigned var_idx = (this+deviceTable).get_variation_index ();
++      if (var_idx != VarIdx::NO_VARIATION)
++      {
++        hb_pair_t *v;
++        if (!c->plan->base_variation_idx_map.has (var_idx, &v))
++          return_trace (false);
++
++        if (unlikely (!c->serializer->check_assign (out->coordinate, coordinate + hb_second (*v),
++                                                    HB_SERIALIZE_ERROR_INT_OVERFLOW)))
++          return_trace (false);
++      }
++    }
++    return_trace (out->deviceTable.serialize_copy (c->serializer, deviceTable,
++                                                   this, 0,
++                                                   hb_serialize_context_t::Head,
++                                                   &c->plan->base_variation_idx_map));
++  }
+ 
+   bool sanitize (hb_sanitize_context_t *c) const
+   {
+@@ -120,25 +168,47 @@ struct BaseCoord
+   bool has_data () const { return u.format; }
+ 
+   hb_position_t get_coord (hb_font_t            *font,
+-                           const VariationStore &var_store,
++                           const ItemVariationStore &var_store,
+                            hb_direction_t        direction) const
+   {
+     switch (u.format) {
+-    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);
++    case 1: hb_barrier (); return u.format1.get_coord (font, direction);
++    case 2: hb_barrier (); return u.format2.get_coord (font, direction);
++    case 3: hb_barrier (); return u.format3.get_coord (font, var_store, direction);
+     default:return 0;
+     }
+   }
+ 
++  void collect_variation_indices (hb_set_t& varidx_set /* OUT */) const
++  {
++    switch (u.format) {
++    case 3: hb_barrier (); u.format3.collect_variation_indices (varidx_set);
++    default:return;
++    }
++  }
++
++  template 
++  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
++  {
++    if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
++    TRACE_DISPATCH (this, u.format);
++    switch (u.format) {
++    case 1: hb_barrier (); return_trace (c->dispatch (u.format1, std::forward (ds)...));
++    case 2: hb_barrier (); return_trace (c->dispatch (u.format2, std::forward (ds)...));
++    case 3: hb_barrier (); return_trace (c->dispatch (u.format3, std::forward (ds)...));
++    default:return_trace (c->default_return_value ());
++    }
++  }
++
+   bool sanitize (hb_sanitize_context_t *c) const
+   {
+     TRACE_SANITIZE (this);
+     if (unlikely (!u.format.sanitize (c))) return_trace (false);
++    hb_barrier ();
+     switch (u.format) {
+-    case 1: return_trace (u.format1.sanitize (c));
+-    case 2: return_trace (u.format2.sanitize (c));
+-    case 3: return_trace (u.format3.sanitize (c));
++    case 1: hb_barrier (); return_trace (u.format1.sanitize (c));
++    case 2: hb_barrier (); return_trace (u.format2.sanitize (c));
++    case 3: hb_barrier (); return_trace (u.format3.sanitize (c));
+     default:return_trace (false);
+     }
+   }
+@@ -160,12 +230,37 @@ struct FeatMinMaxRecord
+ 
+   bool has_data () const { return tag; }
+ 
++  hb_tag_t get_feature_tag () const { return tag; }
++
+   void get_min_max (const BaseCoord **min, const BaseCoord **max) const
+   {
+     if (likely (min)) *min = &(this+minCoord);
+     if (likely (max)) *max = &(this+maxCoord);
+   }
+ 
++  void collect_variation_indices (const hb_subset_plan_t* plan,
++                                  const void *base,
++                                  hb_set_t& varidx_set /* OUT */) const
++  {
++    if (!plan->layout_features.has (tag))
++      return;
++
++    (base+minCoord).collect_variation_indices (varidx_set);
++    (base+maxCoord).collect_variation_indices (varidx_set);
++  }
++
++  bool subset (hb_subset_context_t *c,
++               const void *base) const
++  {
++    TRACE_SUBSET (this);
++    auto *out = c->serializer->embed (*this);
++    if (unlikely (!out)) return_trace (false);
++    if (!(out->minCoord.serialize_subset (c, minCoord, base)))
++      return_trace (false);
++
++    return_trace (out->maxCoord.serialize_subset (c, maxCoord, base));
++  }
++
+   bool sanitize (hb_sanitize_context_t *c, const void *base) const
+   {
+     TRACE_SANITIZE (this);
+@@ -205,6 +300,39 @@ struct MinMax
+     }
+   }
+ 
++  void collect_variation_indices (const hb_subset_plan_t* plan,
++                                  hb_set_t& varidx_set /* OUT */) const
++  {
++    (this+minCoord).collect_variation_indices (varidx_set);
++    (this+maxCoord).collect_variation_indices (varidx_set);
++    for (const FeatMinMaxRecord& record : featMinMaxRecords)
++      record.collect_variation_indices (plan, this, varidx_set);
++  }
++
++  bool subset (hb_subset_context_t *c) const
++  {
++    TRACE_SUBSET (this);
++    auto *out = c->serializer->start_embed (*this);
++    if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
++
++    if (!(out->minCoord.serialize_subset (c, minCoord, this)) ||
++        !(out->maxCoord.serialize_subset (c, maxCoord, this)))
++      return_trace (false);
++
++    unsigned len = 0;
++    for (const FeatMinMaxRecord& _ : featMinMaxRecords)
++    {
++      hb_tag_t feature_tag = _.get_feature_tag ();
++      if (!c->plan->layout_features.has (feature_tag))
++        continue;
++
++      if (!_.subset (c, this)) return false;
++      len++;
++    }
++    return_trace (c->serializer->check_assign (out->featMinMaxRecords.len, len,
++                                               HB_SERIALIZE_ERROR_INT_OVERFLOW));
++  }
++
+   bool sanitize (hb_sanitize_context_t *c) const
+   {
+     TRACE_SANITIZE (this);
+@@ -239,6 +367,26 @@ struct BaseValues
+     return this+baseCoords[baseline_tag_index];
+   }
+ 
++  void collect_variation_indices (hb_set_t& varidx_set /* OUT */) const
++  {
++    for (const auto& _ : baseCoords)
++      (this+_).collect_variation_indices (varidx_set);
++  }
++
++  bool subset (hb_subset_context_t *c) const
++  {
++    TRACE_SUBSET (this);
++    auto *out = c->serializer->start_embed (*this);
++    if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
++    out->defaultIndex = defaultIndex;
++
++    for (const auto& _ : baseCoords)
++      if (!subset_offset_array (c, out->baseCoords, this) (_))
++        return_trace (false);
++
++    return_trace (bool (out->baseCoords));
++  }
++
+   bool sanitize (hb_sanitize_context_t *c) const
+   {
+     TRACE_SANITIZE (this);
+@@ -267,7 +415,22 @@ struct BaseLangSysRecord
+ 
+   bool has_data () const { return baseLangSysTag; }
+ 
+-  const MinMax &get_min_max () const { return this+minMax; }
++  const MinMax &get_min_max (const void* base) const { return base+minMax; }
++
++  void collect_variation_indices (const void* base,
++                                  const hb_subset_plan_t* plan,
++                                  hb_set_t& varidx_set /* OUT */) const
++  { (base+minMax).collect_variation_indices (plan, varidx_set); }
++
++  bool subset (hb_subset_context_t *c,
++               const void *base) const
++  {
++    TRACE_SUBSET (this);
++    auto *out = c->serializer->embed (*this);
++    if (unlikely (!out)) return_trace (false);
++
++    return_trace (out->minMax.serialize_subset (c, minMax, base));
++  }
+ 
+   bool sanitize (hb_sanitize_context_t *c, const void *base) const
+   {
+@@ -290,14 +453,43 @@ struct BaseScript
+   const MinMax &get_min_max (hb_tag_t language_tag) const
+   {
+     const BaseLangSysRecord& record = baseLangSysRecords.bsearch (language_tag);
+-    return record.has_data () ? record.get_min_max () : this+defaultMinMax;
++    return record.has_data () ? record.get_min_max (this) : this+defaultMinMax;
+   }
+ 
+   const BaseCoord &get_base_coord (int baseline_tag_index) const
+   { return (this+baseValues).get_base_coord (baseline_tag_index); }
+ 
+   bool has_values () const { return baseValues; }
+-  bool has_min_max () const { return defaultMinMax; /* TODO What if only per-language is present? */ }
++  bool has_min_max () const { return defaultMinMax || baseLangSysRecords; }
++
++  void collect_variation_indices (const hb_subset_plan_t* plan,
++                                  hb_set_t& varidx_set /* OUT */) const
++  {
++    (this+baseValues).collect_variation_indices (varidx_set);
++    (this+defaultMinMax).collect_variation_indices (plan, varidx_set);
++
++    for (const BaseLangSysRecord& _ : baseLangSysRecords)
++      _.collect_variation_indices (this, plan, varidx_set);
++  }
++
++  bool subset (hb_subset_context_t *c) const
++  {
++    TRACE_SUBSET (this);
++    auto *out = c->serializer->start_embed (*this);
++    if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
++
++    if (baseValues && !out->baseValues.serialize_subset (c, baseValues, this))
++      return_trace (false);
++
++    if (defaultMinMax && !out->defaultMinMax.serialize_subset (c, defaultMinMax, this))
++      return_trace (false);
++
++    for (const auto& _ : baseLangSysRecords)
++      if (!_.subset (c, this)) return_trace (false);
++
++    return_trace (c->serializer->check_assign (out->baseLangSysRecords.len, baseLangSysRecords.len,
++                                               HB_SERIALIZE_ERROR_INT_OVERFLOW));
++  }
+ 
+   bool sanitize (hb_sanitize_context_t *c) const
+   {
+@@ -331,9 +523,31 @@ struct BaseScriptRecord
+ 
+   bool has_data () const { return baseScriptTag; }
+ 
++  hb_tag_t get_script_tag () const { return baseScriptTag; }
++
+   const BaseScript &get_base_script (const BaseScriptList *list) const
+   { return list+baseScript; }
+ 
++  void collect_variation_indices (const hb_subset_plan_t* plan,
++                                  const void* list,
++                                  hb_set_t& varidx_set /* OUT */) const
++  {
++    if (!plan->layout_scripts.has (baseScriptTag))
++      return;
++
++    (list+baseScript).collect_variation_indices (plan, varidx_set);
++  }
++
++  bool subset (hb_subset_context_t *c,
++               const void *base) const
++  {
++    TRACE_SUBSET (this);
++    auto *out = c->serializer->embed (*this);
++    if (unlikely (!out)) return_trace (false);
++
++    return_trace (out->baseScript.serialize_subset (c, baseScript, base));
++  }
++
+   bool sanitize (hb_sanitize_context_t *c, const void *base) const
+   {
+     TRACE_SANITIZE (this);
+@@ -360,6 +574,33 @@ struct BaseScriptList
+     return record->has_data () ? record->get_base_script (this) : Null (BaseScript);
+   }
+ 
++  void collect_variation_indices (const hb_subset_plan_t* plan,
++                                  hb_set_t& varidx_set /* OUT */) const
++  {
++    for (const BaseScriptRecord& _ : baseScriptRecords)
++      _.collect_variation_indices (plan, this, varidx_set);
++  }
++
++  bool subset (hb_subset_context_t *c) const
++  {
++    TRACE_SUBSET (this);
++    auto *out = c->serializer->start_embed (*this);
++    if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
++
++    unsigned len = 0;
++    for (const BaseScriptRecord& _ : baseScriptRecords)
++    {
++      hb_tag_t script_tag = _.get_script_tag ();
++      if (!c->plan->layout_scripts.has (script_tag))
++        continue;
++
++      if (!_.subset (c, this)) return false;
++      len++;
++    }
++    return_trace (c->serializer->check_assign (out->baseScriptRecords.len, len,
++                                               HB_SERIALIZE_ERROR_INT_OVERFLOW));
++  }
++
+   bool sanitize (hb_sanitize_context_t *c) const
+   {
+     TRACE_SANITIZE (this);
+@@ -421,6 +662,20 @@ struct Axis
+     return true;
+   }
+ 
++  void collect_variation_indices (const hb_subset_plan_t* plan,
++                                  hb_set_t& varidx_set /* OUT */) const
++  { (this+baseScriptList).collect_variation_indices (plan, varidx_set); }
++
++  bool subset (hb_subset_context_t *c) const
++  {
++    TRACE_SUBSET (this);
++    auto *out = c->serializer->embed (*this);
++    if (unlikely (!out)) return_trace (false);
++
++    out->baseTagList.serialize_copy (c->serializer, baseTagList, this);
++    return_trace (out->baseScriptList.serialize_subset (c, baseScriptList, this));
++  }
++
+   bool sanitize (hb_sanitize_context_t *c) const
+   {
+     TRACE_SANITIZE (this);
+@@ -452,8 +707,77 @@ struct BASE
+   const Axis &get_axis (hb_direction_t direction) const
+   { return HB_DIRECTION_IS_VERTICAL (direction) ? this+vAxis : this+hAxis; }
+ 
+-  const VariationStore &get_var_store () const
+-  { return version.to_int () < 0x00010001u ? Null (VariationStore) : this+varStore; }
++  bool has_var_store () const
++  { return version.to_int () >= 0x00010001u && varStore != 0; }
++
++  const ItemVariationStore &get_var_store () const
++  { return version.to_int () < 0x00010001u ? Null (ItemVariationStore) : this+varStore; }
++
++  void collect_variation_indices (const hb_subset_plan_t* plan,
++                                  hb_set_t& varidx_set /* OUT */) const
++  {
++    (this+hAxis).collect_variation_indices (plan, varidx_set);
++    (this+vAxis).collect_variation_indices (plan, varidx_set);
++  }
++
++  bool subset_varstore (hb_subset_context_t *c,
++                        BASE *out /* OUT */) const
++  {
++    TRACE_SUBSET (this);
++    if (!c->serializer->allocate_size> (Offset32To::static_size))
++        return_trace (false);
++    if (!c->plan->normalized_coords)
++      return_trace (out->varStore.serialize_subset (c, varStore, this, c->plan->base_varstore_inner_maps.as_array ()));
++
++    if (c->plan->all_axes_pinned)
++      return_trace (true);
++
++    item_variations_t item_vars;
++    if (!item_vars.instantiate (this+varStore, c->plan, true, true,
++                                c->plan->base_varstore_inner_maps.as_array ()))
++      return_trace (false);
++
++    if (!out->varStore.serialize_serialize (c->serializer,
++                                            item_vars.has_long_word (),
++                                            c->plan->axis_tags,
++                                            item_vars.get_region_list (),
++                                            item_vars.get_vardata_encodings ()))
++      return_trace (false);
++
++    const hb_map_t &varidx_map = item_vars.get_varidx_map ();
++    /* base_variation_idx_map in the plan is old_varidx->(varidx, delta)
++     * mapping, new varidx is generated for subsetting, we need to remap this
++     * after instancing */
++    for (auto _ : c->plan->base_variation_idx_map.iter_ref ())
++    {
++      uint32_t varidx = _.second.first;
++      uint32_t *new_varidx;
++      if (varidx_map.has (varidx, &new_varidx))
++        _.second.first = *new_varidx;
++      else
++        _.second.first = HB_OT_LAYOUT_NO_VARIATIONS_INDEX;
++    }
++    return_trace (true);
++  }
++
++  bool subset (hb_subset_context_t *c) const
++  {
++    TRACE_SUBSET (this);
++    auto *out = c->serializer->start_embed (*this);
++    if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
++
++    out->version = version;
++    if (has_var_store () && !subset_varstore (c, out))
++        return_trace (false);
++
++    if (hAxis && !out->hAxis.serialize_subset (c, hAxis, this))
++      return_trace (false);
++
++    if (vAxis && !out->vAxis.serialize_subset (c, vAxis, this))
++      return_trace (false);
++
++    return_trace (true);
++  }
+ 
+   bool get_baseline (hb_font_t      *font,
+                      hb_tag_t        baseline_tag,
+@@ -486,7 +810,7 @@ struct BASE
+                                            &min_coord, &max_coord))
+       return false;
+ 
+-    const VariationStore &var_store = get_var_store ();
++    const ItemVariationStore &var_store = get_var_store ();
+     if (likely (min && min_coord)) *min = min_coord->get_coord (font, var_store, direction);
+     if (likely (max && max_coord)) *max = max_coord->get_coord (font, var_store, direction);
+     return true;
+@@ -496,6 +820,7 @@ struct BASE
+   {
+     TRACE_SANITIZE (this);
+     return_trace (likely (c->check_struct (this) &&
++                          hb_barrier () &&
+                           likely (version.major == 1) &&
+                           hAxis.sanitize (c, this) &&
+                           vAxis.sanitize (c, this) &&
+@@ -508,7 +833,7 @@ struct BASE
+                                  * of BASE table (may be NULL) */
+   Offset16TovAxis;                /* Offset to vertical Axis table, from beginning
+                                  * of BASE table (may be NULL) */
+-  Offset32To
++  Offset32To
+                 varStore;       /* Offset to the table of Item Variation
+                                  * Store--from beginning of BASE
+                                  * header (may be NULL).  Introduced
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-common.hh b/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-common.hh
+index 9216a9a0f..f14675295 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-common.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-common.hh
+@@ -34,6 +34,7 @@
+ #include "hb-open-type.hh"
+ #include "hb-set.hh"
+ #include "hb-bimap.hh"
++#include "hb-cache.hh"
+ 
+ #include "OT/Layout/Common/Coverage.hh"
+ #include "OT/Layout/types.hh"
+@@ -64,7 +65,7 @@ struct hb_collect_feature_substitutes_with_var_context_t
+   const hb_hashmap_t *axes_location;
+   hb_hashmap_t> *record_cond_idx_map;
+   hb_hashmap_t *feature_substitutes_map;
+-  bool& insert_catch_all_feature_variation_record;
++  hb_set_t& catch_all_record_feature_idxes;
+ 
+   // not stored in subset_plan
+   hb_set_t *feature_indices;
+@@ -142,6 +143,8 @@ struct hb_subset_layout_context_t :
+   const hb_map_t *feature_index_map;
+   const hb_hashmap_t *feature_substitutes_map;
+   hb_hashmap_t> *feature_record_cond_idx_map;
++  const hb_set_t *catch_all_record_feature_idxes;
++  const hb_hashmap_t> *feature_idx_tag_map;
+ 
+   unsigned cur_script_index;
+   unsigned cur_feature_var_record_idx;
+@@ -164,6 +167,8 @@ struct hb_subset_layout_context_t :
+       feature_index_map = &c_->plan->gsub_features;
+       feature_substitutes_map = &c_->plan->gsub_feature_substitutes_map;
+       feature_record_cond_idx_map = c_->plan->user_axes_location.is_empty () ? nullptr : &c_->plan->gsub_feature_record_cond_idx_map;
++      catch_all_record_feature_idxes = &c_->plan->gsub_old_features;
++      feature_idx_tag_map = &c_->plan->gsub_old_feature_idx_tag_map;
+     }
+     else
+     {
+@@ -172,6 +177,8 @@ struct hb_subset_layout_context_t :
+       feature_index_map = &c_->plan->gpos_features;
+       feature_substitutes_map = &c_->plan->gpos_feature_substitutes_map;
+       feature_record_cond_idx_map = c_->plan->user_axes_location.is_empty () ? nullptr : &c_->plan->gpos_feature_record_cond_idx_map;
++      catch_all_record_feature_idxes = &c_->plan->gpos_old_features;
++      feature_idx_tag_map = &c_->plan->gpos_old_feature_idx_tag_map;
+     }
+   }
+ 
+@@ -182,7 +189,7 @@ struct hb_subset_layout_context_t :
+   unsigned lookup_index_count;
+ };
+ 
+-struct VariationStore;
++struct ItemVariationStore;
+ struct hb_collect_variation_indices_context_t :
+        hb_dispatch_context_t
+ {
+@@ -454,6 +461,7 @@ struct FeatureParamsSize
+   {
+     TRACE_SANITIZE (this);
+     if (unlikely (!c->check_struct (this))) return_trace (false);
++    hb_barrier ();
+ 
+     /* This subtable has some "history", if you will.  Some earlier versions of
+      * Adobe tools calculated the offset of the FeatureParams subtable from the
+@@ -639,8 +647,7 @@ struct FeatureParamsCharacterVariants
+       return;
+ 
+     unsigned last_name_id = (unsigned) firstParamUILabelNameID + (unsigned) numNamedParameters - 1;
+-    if (last_name_id >= 256 && last_name_id <= 32767)
+-      nameids_to_retain->add_range (firstParamUILabelNameID, last_name_id);
++    nameids_to_retain->add_range (firstParamUILabelNameID, last_name_id);
+   }
+ 
+   bool subset (hb_subset_context_t *c) const
+@@ -820,6 +827,7 @@ struct Feature
+     TRACE_SANITIZE (this);
+     if (unlikely (!(c->check_struct (this) && lookupIndex.sanitize (c))))
+       return_trace (false);
++    hb_barrier ();
+ 
+     /* Some earlier versions of Adobe tools calculated the offset of the
+      * FeatureParams subtable from the beginning of the FeatureList table!
+@@ -838,6 +846,7 @@ struct Feature
+     unsigned int orig_offset = featureParams;
+     if (unlikely (!featureParams.sanitize (c, this, closure ? closure->tag : HB_TAG_NONE)))
+       return_trace (false);
++    hb_barrier ();
+ 
+     if (featureParams == 0 && closure &&
+         closure->tag == HB_TAG ('s','i','z','e') &&
+@@ -900,7 +909,8 @@ struct Record
+   {
+     TRACE_SANITIZE (this);
+     const Record_sanitize_closure_t closure = {tag, base};
+-    return_trace (c->check_struct (this) && offset.sanitize (c, base, &closure));
++    return_trace (c->check_struct (this) &&
++                  offset.sanitize (c, base, &closure));
+   }
+ 
+   Tag           tag;            /* 4-byte Tag identifier */
+@@ -1371,10 +1381,20 @@ struct Lookup
+ 
+     if (lookupFlag & LookupFlag::UseMarkFilteringSet)
+     {
+-      if (unlikely (!c->serializer->extend (out))) return_trace (false);
+       const HBUINT16 &markFilteringSet = StructAfter (subTable);
+-      HBUINT16 &outMarkFilteringSet = StructAfter (out->subTable);
+-      outMarkFilteringSet = markFilteringSet;
++      hb_codepoint_t *idx;
++      if (!c->plan->used_mark_sets_map.has (markFilteringSet, &idx))
++      {
++        unsigned new_flag = lookupFlag;
++        new_flag &= ~LookupFlag::UseMarkFilteringSet;
++        out->lookupFlag = new_flag;
++      }
++      else
++      {
++        if (unlikely (!c->serializer->extend (out))) return_trace (false);
++        HBUINT16 &outMarkFilteringSet = StructAfter (out->subTable);
++        outMarkFilteringSet = *idx;
++      }
+     }
+ 
+     // Always keep the lookup even if it's empty. The rest of layout subsetting depends on lookup
+@@ -1391,6 +1411,7 @@ struct Lookup
+   {
+     TRACE_SANITIZE (this);
+     if (!(c->check_struct (this) && subTable.sanitize (c))) return_trace (false);
++    hb_barrier ();
+ 
+     unsigned subtables = get_subtable_count ();
+     if (unlikely (!c->visit_subtables (subtables))) return_trace (false);
+@@ -1406,6 +1427,8 @@ struct Lookup
+ 
+     if (unlikely (get_type () == TSubTable::Extension && !c->get_edit_count ()))
+     {
++      hb_barrier ();
++
+       /* The spec says all subtables of an Extension lookup should
+        * have the same type, which shall not be the Extension type
+        * itself (but we already checked for that).
+@@ -2045,24 +2068,33 @@ struct ClassDef
+   unsigned int get_class (hb_codepoint_t glyph_id) const
+   {
+     switch (u.format) {
+-    case 1: return u.format1.get_class (glyph_id);
+-    case 2: return u.format2.get_class (glyph_id);
++    case 1: hb_barrier (); return u.format1.get_class (glyph_id);
++    case 2: hb_barrier (); return u.format2.get_class (glyph_id);
+ #ifndef HB_NO_BEYOND_64K
+-    case 3: return u.format3.get_class (glyph_id);
+-    case 4: return u.format4.get_class (glyph_id);
++    case 3: hb_barrier (); return u.format3.get_class (glyph_id);
++    case 4: hb_barrier (); return u.format4.get_class (glyph_id);
+ #endif
+     default:return 0;
+     }
+   }
++  unsigned int get_class (hb_codepoint_t glyph_id,
++                          hb_ot_lookup_cache_t *cache) const
++  {
++    unsigned klass;
++    if (cache && cache->get (glyph_id, &klass)) return klass;
++    klass = get_class (glyph_id);
++    if (cache) cache->set (glyph_id, klass);
++    return klass;
++  }
+ 
+   unsigned get_population () const
+   {
+     switch (u.format) {
+-    case 1: return u.format1.get_population ();
+-    case 2: return u.format2.get_population ();
++    case 1: hb_barrier (); return u.format1.get_population ();
++    case 2: hb_barrier (); return u.format2.get_population ();
+ #ifndef HB_NO_BEYOND_64K
+-    case 3: return u.format3.get_population ();
+-    case 4: return u.format4.get_population ();
++    case 3: hb_barrier (); return u.format3.get_population ();
++    case 4: hb_barrier (); return u.format4.get_population ();
+ #endif
+     default:return NOT_COVERED;
+     }
+@@ -2124,11 +2156,11 @@ struct ClassDef
+ 
+     switch (u.format)
+     {
+-    case 1: return_trace (u.format1.serialize (c, it));
+-    case 2: return_trace (u.format2.serialize (c, it));
++    case 1: hb_barrier (); return_trace (u.format1.serialize (c, it));
++    case 2: hb_barrier (); return_trace (u.format2.serialize (c, it));
+ #ifndef HB_NO_BEYOND_64K
+-    case 3: return_trace (u.format3.serialize (c, it));
+-    case 4: return_trace (u.format4.serialize (c, it));
++    case 3: hb_barrier (); return_trace (u.format3.serialize (c, it));
++    case 4: hb_barrier (); return_trace (u.format4.serialize (c, it));
+ #endif
+     default:return_trace (false);
+     }
+@@ -2142,11 +2174,11 @@ struct ClassDef
+   {
+     TRACE_SUBSET (this);
+     switch (u.format) {
+-    case 1: return_trace (u.format1.subset (c, klass_map, keep_empty_table, use_class_zero, glyph_filter));
+-    case 2: return_trace (u.format2.subset (c, klass_map, keep_empty_table, use_class_zero, glyph_filter));
++    case 1: hb_barrier (); return_trace (u.format1.subset (c, klass_map, keep_empty_table, use_class_zero, glyph_filter));
++    case 2: hb_barrier (); return_trace (u.format2.subset (c, klass_map, keep_empty_table, use_class_zero, glyph_filter));
+ #ifndef HB_NO_BEYOND_64K
+-    case 3: return_trace (u.format3.subset (c, klass_map, keep_empty_table, use_class_zero, glyph_filter));
+-    case 4: return_trace (u.format4.subset (c, klass_map, keep_empty_table, use_class_zero, glyph_filter));
++    case 3: hb_barrier (); return_trace (u.format3.subset (c, klass_map, keep_empty_table, use_class_zero, glyph_filter));
++    case 4: hb_barrier (); return_trace (u.format4.subset (c, klass_map, keep_empty_table, use_class_zero, glyph_filter));
+ #endif
+     default:return_trace (false);
+     }
+@@ -2156,12 +2188,13 @@ struct ClassDef
+   {
+     TRACE_SANITIZE (this);
+     if (!u.format.sanitize (c)) return_trace (false);
++    hb_barrier ();
+     switch (u.format) {
+-    case 1: return_trace (u.format1.sanitize (c));
+-    case 2: return_trace (u.format2.sanitize (c));
++    case 1: hb_barrier (); return_trace (u.format1.sanitize (c));
++    case 2: hb_barrier (); return_trace (u.format2.sanitize (c));
+ #ifndef HB_NO_BEYOND_64K
+-    case 3: return_trace (u.format3.sanitize (c));
+-    case 4: return_trace (u.format4.sanitize (c));
++    case 3: hb_barrier (); return_trace (u.format3.sanitize (c));
++    case 4: hb_barrier (); return_trace (u.format4.sanitize (c));
+ #endif
+     default:return_trace (true);
+     }
+@@ -2170,11 +2203,11 @@ struct ClassDef
+   unsigned cost () const
+   {
+     switch (u.format) {
+-    case 1: return u.format1.cost ();
+-    case 2: return u.format2.cost ();
++    case 1: hb_barrier (); return u.format1.cost ();
++    case 2: hb_barrier (); return u.format2.cost ();
+ #ifndef HB_NO_BEYOND_64K
+-    case 3: return u.format3.cost ();
+-    case 4: return u.format4.cost ();
++    case 3: hb_barrier (); return u.format3.cost ();
++    case 4: hb_barrier (); return u.format4.cost ();
+ #endif
+     default:return 0u;
+     }
+@@ -2186,11 +2219,11 @@ struct ClassDef
+   bool collect_coverage (set_t *glyphs) const
+   {
+     switch (u.format) {
+-    case 1: return u.format1.collect_coverage (glyphs);
+-    case 2: return u.format2.collect_coverage (glyphs);
++    case 1: hb_barrier (); return u.format1.collect_coverage (glyphs);
++    case 2: hb_barrier (); return u.format2.collect_coverage (glyphs);
+ #ifndef HB_NO_BEYOND_64K
+-    case 3: return u.format3.collect_coverage (glyphs);
+-    case 4: return u.format4.collect_coverage (glyphs);
++    case 3: hb_barrier (); return u.format3.collect_coverage (glyphs);
++    case 4: hb_barrier (); return u.format4.collect_coverage (glyphs);
+ #endif
+     default:return false;
+     }
+@@ -2202,11 +2235,11 @@ struct ClassDef
+   bool collect_class (set_t *glyphs, unsigned int klass) const
+   {
+     switch (u.format) {
+-    case 1: return u.format1.collect_class (glyphs, klass);
+-    case 2: return u.format2.collect_class (glyphs, klass);
++    case 1: hb_barrier (); return u.format1.collect_class (glyphs, klass);
++    case 2: hb_barrier (); return u.format2.collect_class (glyphs, klass);
+ #ifndef HB_NO_BEYOND_64K
+-    case 3: return u.format3.collect_class (glyphs, klass);
+-    case 4: return u.format4.collect_class (glyphs, klass);
++    case 3: hb_barrier (); return u.format3.collect_class (glyphs, klass);
++    case 4: hb_barrier (); return u.format4.collect_class (glyphs, klass);
+ #endif
+     default:return false;
+     }
+@@ -2215,11 +2248,11 @@ struct ClassDef
+   bool intersects (const hb_set_t *glyphs) const
+   {
+     switch (u.format) {
+-    case 1: return u.format1.intersects (glyphs);
+-    case 2: return u.format2.intersects (glyphs);
++    case 1: hb_barrier (); return u.format1.intersects (glyphs);
++    case 2: hb_barrier (); return u.format2.intersects (glyphs);
+ #ifndef HB_NO_BEYOND_64K
+-    case 3: return u.format3.intersects (glyphs);
+-    case 4: return u.format4.intersects (glyphs);
++    case 3: hb_barrier (); return u.format3.intersects (glyphs);
++    case 4: hb_barrier (); return u.format4.intersects (glyphs);
+ #endif
+     default:return false;
+     }
+@@ -2227,11 +2260,11 @@ struct ClassDef
+   bool intersects_class (const hb_set_t *glyphs, unsigned int klass) const
+   {
+     switch (u.format) {
+-    case 1: return u.format1.intersects_class (glyphs, klass);
+-    case 2: return u.format2.intersects_class (glyphs, klass);
++    case 1: hb_barrier (); return u.format1.intersects_class (glyphs, klass);
++    case 2: hb_barrier (); return u.format2.intersects_class (glyphs, klass);
+ #ifndef HB_NO_BEYOND_64K
+-    case 3: return u.format3.intersects_class (glyphs, klass);
+-    case 4: return u.format4.intersects_class (glyphs, klass);
++    case 3: hb_barrier (); return u.format3.intersects_class (glyphs, klass);
++    case 4: hb_barrier (); return u.format4.intersects_class (glyphs, klass);
+ #endif
+     default:return false;
+     }
+@@ -2240,11 +2273,11 @@ struct ClassDef
+   void intersected_class_glyphs (const hb_set_t *glyphs, unsigned klass, hb_set_t *intersect_glyphs) const
+   {
+     switch (u.format) {
+-    case 1: return u.format1.intersected_class_glyphs (glyphs, klass, intersect_glyphs);
+-    case 2: return u.format2.intersected_class_glyphs (glyphs, klass, intersect_glyphs);
++    case 1: hb_barrier (); return u.format1.intersected_class_glyphs (glyphs, klass, intersect_glyphs);
++    case 2: hb_barrier (); return u.format2.intersected_class_glyphs (glyphs, klass, intersect_glyphs);
+ #ifndef HB_NO_BEYOND_64K
+-    case 3: return u.format3.intersected_class_glyphs (glyphs, klass, intersect_glyphs);
+-    case 4: return u.format4.intersected_class_glyphs (glyphs, klass, intersect_glyphs);
++    case 3: hb_barrier (); return u.format3.intersected_class_glyphs (glyphs, klass, intersect_glyphs);
++    case 4: hb_barrier (); return u.format4.intersected_class_glyphs (glyphs, klass, intersect_glyphs);
+ #endif
+     default:return;
+     }
+@@ -2253,11 +2286,11 @@ struct ClassDef
+   void intersected_classes (const hb_set_t *glyphs, hb_set_t *intersect_classes) const
+   {
+     switch (u.format) {
+-    case 1: return u.format1.intersected_classes (glyphs, intersect_classes);
+-    case 2: return u.format2.intersected_classes (glyphs, intersect_classes);
++    case 1: hb_barrier (); return u.format1.intersected_classes (glyphs, intersect_classes);
++    case 2: hb_barrier (); return u.format2.intersected_classes (glyphs, intersect_classes);
+ #ifndef HB_NO_BEYOND_64K
+-    case 3: return u.format3.intersected_classes (glyphs, intersect_classes);
+-    case 4: return u.format4.intersected_classes (glyphs, intersect_classes);
++    case 3: hb_barrier (); return u.format3.intersected_classes (glyphs, intersect_classes);
++    case 4: hb_barrier (); return u.format4.intersected_classes (glyphs, intersect_classes);
+ #endif
+     default:return;
+     }
+@@ -2447,6 +2480,8 @@ struct VarRegionAxis
+     int peak = peakCoord.to_int ();
+     if (peak == 0 || coord == peak)
+       return 1.f;
++    else if (coord == 0) // Faster
++      return 0.f;
+ 
+     int start = startCoord.to_int (), end = endCoord.to_int ();
+ 
+@@ -2470,8 +2505,6 @@ struct VarRegionAxis
+   {
+     TRACE_SANITIZE (this);
+     return_trace (c->check_struct (this));
+-    /* TODO Handle invalid start/peak/end configs, so we don't
+-     * have to do that at runtime. */
+   }
+ 
+   bool serialize (hb_serialize_context_t *c) const
+@@ -2487,6 +2520,33 @@ struct VarRegionAxis
+   public:
+   DEFINE_SIZE_STATIC (6);
+ };
++struct SparseVarRegionAxis
++{
++  float evaluate (const int *coords, unsigned int coord_len) const
++  {
++    unsigned i = axisIndex;
++    int coord = i < coord_len ? coords[i] : 0;
++    return axis.evaluate (coord);
++  }
++
++  bool sanitize (hb_sanitize_context_t *c) const
++  {
++    TRACE_SANITIZE (this);
++    return_trace (c->check_struct (this));
++  }
++
++  bool serialize (hb_serialize_context_t *c) const
++  {
++    TRACE_SERIALIZE (this);
++    return_trace (c->embed (this));
++  }
++
++  public:
++  HBUINT16 axisIndex;
++  VarRegionAxis axis;
++  public:
++  DEFINE_SIZE_STATIC (8);
++};
+ 
+ #define REGION_CACHE_ITEM_CACHE_INVALID 2.f
+ 
+@@ -2534,7 +2594,9 @@ struct VarRegionList
+   bool sanitize (hb_sanitize_context_t *c) const
+   {
+     TRACE_SANITIZE (this);
+-    return_trace (c->check_struct (this) && axesZ.sanitize (c, axisCount * regionCount));
++    return_trace (c->check_struct (this) &&
++                  hb_barrier () &&
++                  axesZ.sanitize (c, axisCount * regionCount));
+   }
+ 
+   bool serialize (hb_serialize_context_t *c,
+@@ -2615,7 +2677,7 @@ struct VarRegionList
+       float max_val = axis_region->endCoord.to_float ();
+ 
+       if (def_val != 0.f)
+-        axis_tuples.set (*axis_tag, Triple (min_val, def_val, max_val));
++        axis_tuples.set (*axis_tag, Triple ((double) min_val, (double) def_val, (double) max_val));
+       axis_region++;
+     }
+     return !axis_tuples.in_error ();
+@@ -2649,6 +2711,65 @@ struct VarRegionList
+   DEFINE_SIZE_ARRAY (4, axesZ);
+ };
+ 
++struct SparseVariationRegion : Array16Of
++{
++  float evaluate (const int *coords, unsigned int coord_len) const
++  {
++    float v = 1.f;
++    unsigned int count = len;
++    for (unsigned int i = 0; i < count; i++)
++    {
++      float factor = arrayZ[i].evaluate (coords, coord_len);
++      if (factor == 0.f)
++        return 0.;
++      v *= factor;
++    }
++    return v;
++  }
++};
++
++struct SparseVarRegionList
++{
++  using cache_t = float;
++
++  float evaluate (unsigned int region_index,
++                  const int *coords, unsigned int coord_len,
++                  cache_t *cache = nullptr) const
++  {
++    if (unlikely (region_index >= regions.len))
++      return 0.;
++
++    float *cached_value = nullptr;
++    if (cache)
++    {
++      cached_value = &(cache[region_index]);
++      if (likely (*cached_value != REGION_CACHE_ITEM_CACHE_INVALID))
++        return *cached_value;
++    }
++
++    const SparseVariationRegion ®ion = this+regions[region_index];
++
++    float v = region.evaluate (coords, coord_len);
++
++    if (cache)
++      *cached_value = v;
++    return v;
++  }
++
++  bool sanitize (hb_sanitize_context_t *c) const
++  {
++    TRACE_SANITIZE (this);
++    return_trace (regions.sanitize (c, this));
++  }
++
++  public:
++  Array16Of>
++                regions;
++  public:
++  DEFINE_SIZE_ARRAY (2, regions);
++};
++
++
+ struct VarData
+ {
+   unsigned int get_item_count () const
+@@ -2728,6 +2849,7 @@ struct VarData
+     TRACE_SANITIZE (this);
+     return_trace (c->check_struct (this) &&
+                   regionIndices.sanitize (c) &&
++                  hb_barrier () &&
+                   wordCount () <= regionIndices.len &&
+                   c->check_range (get_delta_bytes (),
+                                   itemCount,
+@@ -3009,7 +3131,53 @@ struct VarData
+   DEFINE_SIZE_ARRAY (6, regionIndices);
+ };
+ 
+-struct VariationStore
++struct MultiVarData
++{
++  unsigned int get_size () const
++  { return min_size
++         - regionIndices.min_size + regionIndices.get_size ()
++         + StructAfter (regionIndices).get_size ();
++  }
++
++  void get_delta (unsigned int inner,
++                  const int *coords, unsigned int coord_count,
++                  const SparseVarRegionList ®ions,
++                  hb_array_t out,
++                  SparseVarRegionList::cache_t *cache = nullptr) const
++  {
++    auto &deltaSets = StructAfter (regionIndices);
++
++    auto values_iter = deltaSets.fetcher (inner);
++    unsigned regionCount = regionIndices.len;
++    for (unsigned regionIndex = 0; regionIndex < regionCount; regionIndex++)
++    {
++      float scalar = regions.evaluate (regionIndices.arrayZ[regionIndex],
++                                       coords, coord_count,
++                                       cache);
++      values_iter.add_to (out, scalar);
++    }
++  }
++
++  bool sanitize (hb_sanitize_context_t *c) const
++  {
++    TRACE_SANITIZE (this);
++    return_trace (format.sanitize (c) &&
++                  hb_barrier () &&
++                  format == 1 &&
++                  regionIndices.sanitize (c) &&
++                  hb_barrier () &&
++                  StructAfter (regionIndices).sanitize (c));
++  }
++
++  protected:
++  HBUINT8             format; // 1
++  Array16Of regionIndices;
++  TupleList           deltaSetsX;
++  public:
++  DEFINE_SIZE_MIN (8);
++};
++
++struct ItemVariationStore
+ {
+   friend struct item_variations_t;
+   using cache_t = VarRegionList::cache_t;
+@@ -3061,7 +3229,7 @@ struct VariationStore
+     return get_delta (outer, inner, coords, coord_count, cache);
+   }
+   float get_delta (unsigned int index,
+-                   hb_array_t coords,
++                   hb_array_t coords,
+                    VarRegionList::cache_t *cache = nullptr) const
+   {
+     return get_delta (index,
+@@ -3077,6 +3245,7 @@ struct VariationStore
+ 
+     TRACE_SANITIZE (this);
+     return_trace (c->check_struct (this) &&
++                  hb_barrier () &&
+                   format == 1 &&
+                   regions.sanitize (c, this) &&
+                   dataSets.sanitize (c, this));
+@@ -3113,7 +3282,7 @@ struct VariationStore
+   }
+ 
+   bool serialize (hb_serialize_context_t *c,
+-                  const VariationStore *src,
++                  const ItemVariationStore *src,
+                   const hb_array_t  &inner_maps)
+   {
+     TRACE_SERIALIZE (this);
+@@ -3169,7 +3338,7 @@ struct VariationStore
+     return_trace (true);
+   }
+ 
+-  VariationStore *copy (hb_serialize_context_t *c) const
++  ItemVariationStore *copy (hb_serialize_context_t *c) const
+   {
+     TRACE_SERIALIZE (this);
+     auto *out = c->start_embed (this);
+@@ -3180,6 +3349,8 @@ struct VariationStore
+     for (unsigned i = 0; i < count; i++)
+     {
+       hb_inc_bimap_t *map = inner_maps.push ();
++      if (!c->propagate_error(inner_maps))
++        return_trace(nullptr);
+       auto &data = this+dataSets[i];
+ 
+       unsigned itemCount = data.get_item_count ();
+@@ -3199,7 +3370,7 @@ struct VariationStore
+     return_trace (false);
+ #endif
+ 
+-    VariationStore *varstore_prime = c->serializer->start_embed ();
++    ItemVariationStore *varstore_prime = c->serializer->start_embed ();
+     if (unlikely (!varstore_prime)) return_trace (false);
+ 
+     varstore_prime->serialize (c->serializer, this, inner_maps);
+@@ -3265,8 +3436,370 @@ struct VariationStore
+   DEFINE_SIZE_ARRAY_SIZED (8, dataSets);
+ };
+ 
++struct MultiItemVariationStore
++{
++  using cache_t = SparseVarRegionList::cache_t;
++
++  cache_t *create_cache (hb_array_t static_cache = hb_array_t ()) const
++  {
++#ifdef HB_NO_VAR
++    return nullptr;
++#endif
++    auto &r = this+regions;
++    unsigned count = r.regions.len;
++
++    float *cache;
++    if (count <= static_cache.length)
++      cache = static_cache.arrayZ;
++    else
++    {
++      cache = (float *) hb_malloc (sizeof (float) * count);
++      if (unlikely (!cache)) return nullptr;
++    }
++
++    for (unsigned i = 0; i < count; i++)
++      cache[i] = REGION_CACHE_ITEM_CACHE_INVALID;
++
++    return cache;
++  }
++
++  static void destroy_cache (cache_t *cache,
++                             hb_array_t static_cache = hb_array_t ())
++  {
++    if (cache != static_cache.arrayZ)
++      hb_free (cache);
++  }
++
++  private:
++  void get_delta (unsigned int outer, unsigned int inner,
++                  const int *coords, unsigned int coord_count,
++                  hb_array_t out,
++                  VarRegionList::cache_t *cache = nullptr) const
++  {
++#ifdef HB_NO_VAR
++    return;
++#endif
++
++    if (unlikely (outer >= dataSets.len))
++      return;
++
++    return (this+dataSets[outer]).get_delta (inner,
++                                             coords, coord_count,
++                                             this+regions,
++                                             out,
++                                             cache);
++  }
++
++  public:
++  void get_delta (unsigned int index,
++                  const int *coords, unsigned int coord_count,
++                  hb_array_t out,
++                  VarRegionList::cache_t *cache = nullptr) const
++  {
++    unsigned int outer = index >> 16;
++    unsigned int inner = index & 0xFFFF;
++    get_delta (outer, inner, coords, coord_count, out, cache);
++  }
++  void get_delta (unsigned int index,
++                  hb_array_t coords,
++                  hb_array_t out,
++                  VarRegionList::cache_t *cache = nullptr) const
++  {
++    return get_delta (index,
++                      coords.arrayZ, coords.length,
++                      out,
++                      cache);
++  }
++
++  bool sanitize (hb_sanitize_context_t *c) const
++  {
++#ifdef HB_NO_VAR
++    return true;
++#endif
++
++    TRACE_SANITIZE (this);
++    return_trace (c->check_struct (this) &&
++                  hb_barrier () &&
++                  format == 1 &&
++                  regions.sanitize (c, this) &&
++                  dataSets.sanitize (c, this));
++  }
++
++  protected:
++  HBUINT16                              format; // 1
++  Offset32To       regions;
++  Array16OfOffset32To     dataSets;
++  public:
++  DEFINE_SIZE_ARRAY_SIZED (8, dataSets);
++};
++
+ #undef REGION_CACHE_ITEM_CACHE_INVALID
+ 
++template 
++struct DeltaSetIndexMapFormat01
++{
++  friend struct DeltaSetIndexMap;
++
++  unsigned get_size () const
++  { return min_size + mapCount * get_width (); }
++
++  private:
++  DeltaSetIndexMapFormat01* copy (hb_serialize_context_t *c) const
++  {
++    TRACE_SERIALIZE (this);
++    return_trace (c->embed (this));
++  }
++
++  template 
++  bool serialize (hb_serialize_context_t *c, const T &plan)
++  {
++    unsigned int width = plan.get_width ();
++    unsigned int inner_bit_count = plan.get_inner_bit_count ();
++    const hb_array_t output_map = plan.get_output_map ();
++
++    TRACE_SERIALIZE (this);
++    if (unlikely (output_map.length && ((((inner_bit_count-1)&~0xF)!=0) || (((width-1)&~0x3)!=0))))
++      return_trace (false);
++    if (unlikely (!c->extend_min (this))) return_trace (false);
++
++    entryFormat = ((width-1)<<4)|(inner_bit_count-1);
++    mapCount = output_map.length;
++    HBUINT8 *p = c->allocate_size (width * output_map.length);
++    if (unlikely (!p)) return_trace (false);
++    for (unsigned int i = 0; i < output_map.length; i++)
++    {
++      unsigned int v = output_map.arrayZ[i];
++      if (v)
++      {
++        unsigned int outer = v >> 16;
++        unsigned int inner = v & 0xFFFF;
++        unsigned int u = (outer << inner_bit_count) | inner;
++        for (unsigned int w = width; w > 0;)
++        {
++          p[--w] = u;
++          u >>= 8;
++        }
++      }
++      p += width;
++    }
++    return_trace (true);
++  }
++
++  uint32_t map (unsigned int v) const /* Returns 16.16 outer.inner. */
++  {
++    /* If count is zero, pass value unchanged.  This takes
++     * care of direct mapping for advance map. */
++    if (!mapCount)
++      return v;
++
++    if (v >= mapCount)
++      v = mapCount - 1;
++
++    unsigned int u = 0;
++    { /* Fetch it. */
++      unsigned int w = get_width ();
++      const HBUINT8 *p = mapDataZ.arrayZ + w * v;
++      for (; w; w--)
++        u = (u << 8) + *p++;
++    }
++
++    { /* Repack it. */
++      unsigned int n = get_inner_bit_count ();
++      unsigned int outer = u >> n;
++      unsigned int inner = u & ((1 << n) - 1);
++      u = (outer<<16) | inner;
++    }
++
++    return u;
++  }
++
++  unsigned get_map_count () const       { return mapCount; }
++  unsigned get_width () const           { return ((entryFormat >> 4) & 3) + 1; }
++  unsigned get_inner_bit_count () const { return (entryFormat & 0xF) + 1; }
++
++
++  bool sanitize (hb_sanitize_context_t *c) const
++  {
++    TRACE_SANITIZE (this);
++    return_trace (c->check_struct (this) &&
++                  hb_barrier () &&
++                  c->check_range (mapDataZ.arrayZ,
++                                  mapCount,
++                                  get_width ()));
++  }
++
++  protected:
++  HBUINT8       format;         /* Format identifier--format = 0 */
++  HBUINT8       entryFormat;    /* A packed field that describes the compressed
++                                 * representation of delta-set indices. */
++  MapCountT     mapCount;       /* The number of mapping entries. */
++  UnsizedArrayOf
++                mapDataZ;       /* The delta-set index mapping data. */
++
++  public:
++  DEFINE_SIZE_ARRAY (2+MapCountT::static_size, mapDataZ);
++};
++
++struct DeltaSetIndexMap
++{
++  template 
++  bool serialize (hb_serialize_context_t *c, const T &plan)
++  {
++    TRACE_SERIALIZE (this);
++    unsigned length = plan.get_output_map ().length;
++    u.format = length <= 0xFFFF ? 0 : 1;
++    switch (u.format) {
++    case 0: hb_barrier (); return_trace (u.format0.serialize (c, plan));
++    case 1: hb_barrier (); return_trace (u.format1.serialize (c, plan));
++    default:return_trace (false);
++    }
++  }
++
++  uint32_t map (unsigned v) const
++  {
++    switch (u.format) {
++    case 0: hb_barrier (); return (u.format0.map (v));
++    case 1: hb_barrier (); return (u.format1.map (v));
++    default:return v;
++    }
++  }
++
++  unsigned get_map_count () const
++  {
++    switch (u.format) {
++    case 0: hb_barrier (); return u.format0.get_map_count ();
++    case 1: hb_barrier (); return u.format1.get_map_count ();
++    default:return 0;
++    }
++  }
++
++  unsigned get_width () const
++  {
++    switch (u.format) {
++    case 0: hb_barrier (); return u.format0.get_width ();
++    case 1: hb_barrier (); return u.format1.get_width ();
++    default:return 0;
++    }
++  }
++
++  unsigned get_inner_bit_count () const
++  {
++    switch (u.format) {
++    case 0: hb_barrier (); return u.format0.get_inner_bit_count ();
++    case 1: hb_barrier (); return u.format1.get_inner_bit_count ();
++    default:return 0;
++    }
++  }
++
++  bool sanitize (hb_sanitize_context_t *c) const
++  {
++    TRACE_SANITIZE (this);
++    if (!u.format.sanitize (c)) return_trace (false);
++    hb_barrier ();
++    switch (u.format) {
++    case 0: hb_barrier (); return_trace (u.format0.sanitize (c));
++    case 1: hb_barrier (); return_trace (u.format1.sanitize (c));
++    default:return_trace (true);
++    }
++  }
++
++  DeltaSetIndexMap* copy (hb_serialize_context_t *c) const
++  {
++    TRACE_SERIALIZE (this);
++    switch (u.format) {
++    case 0: hb_barrier (); return_trace (reinterpret_cast (u.format0.copy (c)));
++    case 1: hb_barrier (); return_trace (reinterpret_cast (u.format1.copy (c)));
++    default:return_trace (nullptr);
++    }
++  }
++
++  protected:
++  union {
++  HBUINT8                            format;         /* Format identifier */
++  DeltaSetIndexMapFormat01 format0;
++  DeltaSetIndexMapFormat01 format1;
++  } u;
++  public:
++  DEFINE_SIZE_UNION (1, format);
++};
++
++
++struct ItemVarStoreInstancer
++{
++  ItemVarStoreInstancer (const ItemVariationStore *varStore_,
++                         const DeltaSetIndexMap *varIdxMap,
++                         hb_array_t coords,
++                         VarRegionList::cache_t *cache = nullptr) :
++    varStore (varStore_), varIdxMap (varIdxMap), coords (coords), cache (cache)
++  {
++    if (!varStore)
++      varStore = &Null(ItemVariationStore);
++  }
++
++  operator bool () const { return varStore && bool (coords); }
++
++  float operator[] (uint32_t varIdx) const
++  { return (*this) (varIdx); }
++
++  float operator() (uint32_t varIdx, unsigned short offset = 0) const
++  {
++   if (!coords || varIdx == VarIdx::NO_VARIATION)
++     return 0.f;
++
++    varIdx += offset;
++    if (varIdxMap)
++      varIdx = varIdxMap->map (varIdx);
++    return varStore->get_delta (varIdx, coords, cache);
++  }
++
++  const ItemVariationStore *varStore;
++  const DeltaSetIndexMap *varIdxMap;
++  hb_array_t coords;
++  VarRegionList::cache_t *cache;
++};
++
++struct MultiItemVarStoreInstancer
++{
++  MultiItemVarStoreInstancer (const MultiItemVariationStore *varStore,
++                              const DeltaSetIndexMap *varIdxMap,
++                              hb_array_t coords,
++                              SparseVarRegionList::cache_t *cache = nullptr) :
++    varStore (varStore), varIdxMap (varIdxMap), coords (coords), cache (cache)
++  {
++    if (!varStore)
++      varStore = &Null(MultiItemVariationStore);
++  }
++
++  operator bool () const { return varStore && bool (coords); }
++
++  float operator[] (uint32_t varIdx) const
++  {
++    float v = 0;
++    (*this) (hb_array (&v, 1), varIdx);
++    return v;
++  }
++
++  void operator() (hb_array_t out, uint32_t varIdx, unsigned short offset = 0) const
++  {
++    if (coords && varIdx != VarIdx::NO_VARIATION)
++    {
++      varIdx += offset;
++      if (varIdxMap)
++        varIdx = varIdxMap->map (varIdx);
++      varStore->get_delta (varIdx, coords, out, cache);
++    }
++    else
++      for (unsigned i = 0; i < out.length; i++)
++        out.arrayZ[i] = 0.f;
++  }
++
++  const MultiItemVariationStore *varStore;
++  const DeltaSetIndexMap *varIdxMap;
++  hb_array_t coords;
++  SparseVarRegionList::cache_t *cache;
++};
++
++
+ /*
+  * Feature Variations
+  */
+@@ -3278,7 +3811,16 @@ enum Cond_with_Var_flag_t
+   DROP_RECORD_WITH_VAR = 3,
+ };
+ 
+-struct ConditionFormat1
++struct Condition;
++
++template 
++static bool
++_hb_recurse_condition_evaluate (const struct Condition &condition,
++                                const int *coords,
++                                unsigned int coord_len,
++                                Instancer *instancer);
++
++struct ConditionAxisRange
+ {
+   friend struct Condition;
+ 
+@@ -3298,19 +3840,19 @@ struct ConditionFormat1
+       return_trace (false);
+ 
+     const hb_hashmap_t& normalized_axes_location = c->plan->axes_location;
+-    Triple axis_limit{-1.f, 0.f, 1.f};
++    Triple axis_limit{-1.0, 0.0, 1.0};
+     Triple *normalized_limit;
+     if (normalized_axes_location.has (*axis_tag, &normalized_limit))
+       axis_limit = *normalized_limit;
+ 
+     const hb_hashmap_t& axes_triple_distances = c->plan->axes_triple_distances;
+-    TripleDistances axis_triple_distances{1.f, 1.f};
++    TripleDistances axis_triple_distances{1.0, 1.0};
+     TripleDistances *triple_dists;
+     if (axes_triple_distances.has (*axis_tag, &triple_dists))
+       axis_triple_distances = *triple_dists;
+ 
+-    float normalized_min = renormalizeValue (filterRangeMinValue.to_float (), axis_limit, axis_triple_distances, false);
+-    float normalized_max = renormalizeValue (filterRangeMaxValue.to_float (), axis_limit, axis_triple_distances, false);
++    float normalized_min = renormalizeValue ((double) filterRangeMinValue.to_float (), axis_limit, axis_triple_distances, false);
++    float normalized_max = renormalizeValue ((double) filterRangeMaxValue.to_float (), axis_limit, axis_triple_distances, false);
+     out->filterRangeMinValue.set_float (normalized_min);
+     out->filterRangeMaxValue.set_float (normalized_max);
+ 
+@@ -3328,10 +3870,14 @@ struct ConditionFormat1
+ 
+     hb_tag_t axis_tag = c->axes_index_tag_map->get (axisIndex);
+ 
+-    Triple axis_range (-1.f, 0.f, 1.f);
++    Triple axis_range (-1.0, 0.0, 1.0);
+     Triple *axis_limit;
++    bool axis_set_by_user = false;
+     if (c->axes_location->has (axis_tag, &axis_limit))
++    {
+       axis_range = *axis_limit;
++      axis_set_by_user = true;
++    }
+ 
+     float axis_min_val = axis_range.minimum;
+     float axis_default_val = axis_range.middle;
+@@ -3350,26 +3896,26 @@ struct ConditionFormat1
+       return DROP_RECORD_WITH_VAR;
+ 
+     //condition met and axis pinned, drop the condition
+-    if (c->axes_location->has (axis_tag) &&
+-        c->axes_location->get (axis_tag).is_point ())
++    if (axis_set_by_user && axis_range.is_point ())
+       return DROP_COND_WITH_VAR;
+ 
+     if (filter_max_val != axis_max_val || filter_min_val != axis_min_val)
+     {
+       // add axisIndex->value into the hashmap so we can check if the record is
+       // unique with variations
+-      int16_t int_filter_max_val = filterRangeMaxValue.to_int ();
+-      int16_t int_filter_min_val = filterRangeMinValue.to_int ();
++      uint16_t int_filter_max_val = (uint16_t) filterRangeMaxValue.to_int ();
++      uint16_t int_filter_min_val = (uint16_t) filterRangeMinValue.to_int ();
+       hb_codepoint_t val = (int_filter_max_val << 16) + int_filter_min_val;
+ 
+       condition_map->set (axisIndex, val);
+       return KEEP_COND_WITH_VAR;
+     }
+-
+     return KEEP_RECORD_WITH_VAR;
+   }
+ 
+-  bool evaluate (const int *coords, unsigned int coord_len) const
++  template 
++  bool evaluate (const int *coords, unsigned int coord_len,
++                 Instancer *instancer HB_UNUSED) const
+   {
+     int coord = axisIndex < coord_len ? coords[axisIndex] : 0;
+     return filterRangeMinValue.to_int () <= coord && coord <= filterRangeMaxValue.to_int ();
+@@ -3390,12 +3936,199 @@ struct ConditionFormat1
+   DEFINE_SIZE_STATIC (8);
+ };
+ 
++struct ConditionValue
++{
++  friend struct Condition;
++
++  bool subset (hb_subset_context_t *c) const
++  {
++    TRACE_SUBSET (this);
++    // TODO(subset)
++    return_trace (false);
++  }
++
++  private:
++  template 
++  bool evaluate (const int *coords, unsigned int coord_len,
++                 Instancer *instancer) const
++  {
++    signed value = defaultValue;
++    value += (*instancer)[varIdx];
++    return value > 0;
++  }
++
++  bool subset (hb_subset_context_t *c,
++               hb_subset_layout_context_t *l,
++               bool insert_catch_all) const
++  {
++    TRACE_SUBSET (this);
++    // TODO(subset)
++    return_trace (false);
++  }
++
++  bool sanitize (hb_sanitize_context_t *c) const
++  {
++    TRACE_SANITIZE (this);
++    return_trace (c->check_struct (this));
++  }
++
++  protected:
++  HBUINT16      format;         /* Format identifier--format = 2 */
++  HBINT16       defaultValue;   /* Value at default instance. */
++  VarIdx        varIdx;         /* Variation index */
++  public:
++  DEFINE_SIZE_STATIC (8);
++};
++
++struct ConditionAnd
++{
++  friend struct Condition;
++
++  bool subset (hb_subset_context_t *c) const
++  {
++    TRACE_SUBSET (this);
++    // TODO(subset)
++    return_trace (false);
++  }
++
++  private:
++  template 
++  bool evaluate (const int *coords, unsigned int coord_len,
++                 Instancer *instancer) const
++  {
++    unsigned int count = conditions.len;
++    for (unsigned int i = 0; i < count; i++)
++      if (!_hb_recurse_condition_evaluate (this+conditions.arrayZ[i],
++                                           coords, coord_len,
++                                           instancer))
++        return false;
++    return true;
++  }
++
++  bool subset (hb_subset_context_t *c,
++               hb_subset_layout_context_t *l,
++               bool insert_catch_all) const
++  {
++    TRACE_SUBSET (this);
++    // TODO(subset)
++    return_trace (false);
++  }
++
++  bool sanitize (hb_sanitize_context_t *c) const
++  {
++    TRACE_SANITIZE (this);
++    return_trace (conditions.sanitize (c, this));
++  }
++
++  protected:
++  HBUINT16      format;         /* Format identifier--format = 3 */
++  Array8OfOffset24To  conditions;
++  public:
++  DEFINE_SIZE_ARRAY (3, conditions);
++};
++
++struct ConditionOr
++{
++  friend struct Condition;
++
++  bool subset (hb_subset_context_t *c) const
++  {
++    TRACE_SUBSET (this);
++    // TODO(subset)
++    return_trace (false);
++  }
++
++  private:
++  template 
++  bool evaluate (const int *coords, unsigned int coord_len,
++                 Instancer *instancer) const
++  {
++    unsigned int count = conditions.len;
++    for (unsigned int i = 0; i < count; i++)
++      if (_hb_recurse_condition_evaluate (this+conditions.arrayZ[i],
++                                          coords, coord_len,
++                                          instancer))
++        return true;
++    return false;
++  }
++
++  bool subset (hb_subset_context_t *c,
++               hb_subset_layout_context_t *l,
++               bool insert_catch_all) const
++  {
++    TRACE_SUBSET (this);
++    // TODO(subset)
++    return_trace (false);
++  }
++
++  bool sanitize (hb_sanitize_context_t *c) const
++  {
++    TRACE_SANITIZE (this);
++    return_trace (conditions.sanitize (c, this));
++  }
++
++  protected:
++  HBUINT16      format;         /* Format identifier--format = 4 */
++  Array8OfOffset24To  conditions;
++  public:
++  DEFINE_SIZE_ARRAY (3, conditions);
++};
++
++struct ConditionNegate
++{
++  friend struct Condition;
++
++  bool subset (hb_subset_context_t *c) const
++  {
++    TRACE_SUBSET (this);
++    // TODO(subset)
++    return_trace (false);
++  }
++
++  private:
++  template 
++  bool evaluate (const int *coords, unsigned int coord_len,
++                 Instancer *instancer) const
++  {
++    return !_hb_recurse_condition_evaluate (this+condition,
++                                            coords, coord_len,
++                                            instancer);
++  }
++
++  bool subset (hb_subset_context_t *c,
++               hb_subset_layout_context_t *l,
++               bool insert_catch_all) const
++  {
++    TRACE_SUBSET (this);
++    // TODO(subset)
++    return_trace (false);
++  }
++
++  bool sanitize (hb_sanitize_context_t *c) const
++  {
++    TRACE_SANITIZE (this);
++    return_trace (condition.sanitize (c, this));
++  }
++
++  protected:
++  HBUINT16      format;         /* Format identifier--format = 5 */
++  Offset24To  condition;
++  public:
++  DEFINE_SIZE_STATIC (5);
++};
++
+ struct Condition
+ {
+-  bool evaluate (const int *coords, unsigned int coord_len) const
++  template 
++  bool evaluate (const int *coords, unsigned int coord_len,
++                 Instancer *instancer) const
+   {
+     switch (u.format) {
+-    case 1: return u.format1.evaluate (coords, coord_len);
++    case 1: hb_barrier (); return u.format1.evaluate (coords, coord_len, instancer);
++    case 2: hb_barrier (); return u.format2.evaluate (coords, coord_len, instancer);
++    case 3: hb_barrier (); return u.format3.evaluate (coords, coord_len, instancer);
++    case 4: hb_barrier (); return u.format4.evaluate (coords, coord_len, instancer);
++    case 5: hb_barrier (); return u.format5.evaluate (coords, coord_len, instancer);
+     default:return false;
+     }
+   }
+@@ -3404,7 +4137,8 @@ struct Condition
+                                              hb_map_t *condition_map /* OUT */) const
+   {
+     switch (u.format) {
+-    case 1: return u.format1.keep_with_variations (c, condition_map);
++    case 1: hb_barrier (); return u.format1.keep_with_variations (c, condition_map);
++    // TODO(subset)
+     default: c->apply = false; return KEEP_COND_WITH_VAR;
+     }
+   }
+@@ -3415,7 +4149,11 @@ struct Condition
+     if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
+     TRACE_DISPATCH (this, u.format);
+     switch (u.format) {
+-    case 1: return_trace (c->dispatch (u.format1, std::forward (ds)...));
++    case 1: hb_barrier (); return_trace (c->dispatch (u.format1, std::forward (ds)...));
++    case 2: hb_barrier (); return_trace (c->dispatch (u.format2, std::forward (ds)...));
++    case 3: hb_barrier (); return_trace (c->dispatch (u.format3, std::forward (ds)...));
++    case 4: hb_barrier (); return_trace (c->dispatch (u.format4, std::forward (ds)...));
++    case 5: hb_barrier (); return_trace (c->dispatch (u.format5, std::forward (ds)...));
+     default:return_trace (c->default_return_value ());
+     }
+   }
+@@ -3424,8 +4162,13 @@ struct Condition
+   {
+     TRACE_SANITIZE (this);
+     if (!u.format.sanitize (c)) return_trace (false);
++    hb_barrier ();
+     switch (u.format) {
+-    case 1: return_trace (u.format1.sanitize (c));
++    case 1: hb_barrier (); return_trace (u.format1.sanitize (c));
++    case 2: hb_barrier (); return_trace (u.format2.sanitize (c));
++    case 3: hb_barrier (); return_trace (u.format3.sanitize (c));
++    case 4: hb_barrier (); return_trace (u.format4.sanitize (c));
++    case 5: hb_barrier (); return_trace (u.format5.sanitize (c));
+     default:return_trace (true);
+     }
+   }
+@@ -3433,19 +4176,51 @@ struct Condition
+   protected:
+   union {
+   HBUINT16              format;         /* Format identifier */
+-  ConditionFormat1      format1;
++  ConditionAxisRange    format1;
++  ConditionValue        format2;
++  ConditionAnd          format3;
++  ConditionOr           format4;
++  ConditionNegate       format5;
+   } u;
+   public:
+   DEFINE_SIZE_UNION (2, format);
+ };
+ 
++template 
++bool
++_hb_recurse_condition_evaluate (const struct Condition &condition,
++                                const int *coords,
++                                unsigned int coord_len,
++                                Instancer *instancer)
++{
++  return condition.evaluate (coords, coord_len, instancer);
++}
++
++struct ConditionList
++{
++  const Condition& operator[] (unsigned i) const
++  { return this+conditions[i]; }
++
++  bool sanitize (hb_sanitize_context_t *c) const
++  {
++    TRACE_SANITIZE (this);
++    return_trace (conditions.sanitize (c, this));
++  }
++
++  protected:
++  Array32OfOffset32To conditions;
++  public:
++  DEFINE_SIZE_ARRAY (4, conditions);
++};
++
+ struct ConditionSet
+ {
+-  bool evaluate (const int *coords, unsigned int coord_len) const
++  bool evaluate (const int *coords, unsigned int coord_len,
++                 ItemVarStoreInstancer *instancer) const
+   {
+     unsigned int count = conditions.len;
+     for (unsigned int i = 0; i < count; i++)
+-      if (!(this+conditions.arrayZ[i]).evaluate (coords, coord_len))
++      if (!(this+conditions.arrayZ[i]).evaluate (coords, coord_len, instancer))
+         return false;
+     return true;
+   }
+@@ -3497,12 +4272,15 @@ struct ConditionSet
+   }
+ 
+   bool subset (hb_subset_context_t *c,
+-               hb_subset_layout_context_t *l) const
++               hb_subset_layout_context_t *l,
++               bool insert_catch_all) const
+   {
+     TRACE_SUBSET (this);
+     auto *out = c->serializer->start_embed (this);
+     if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
+ 
++    if (insert_catch_all) return_trace (true);
++
+     hb_set_t *retained_cond_set = nullptr;
+     if (l->feature_record_cond_idx_map != nullptr)
+       retained_cond_set = l->feature_record_cond_idx_map->get (l->cur_feature_var_record_idx);
+@@ -3548,27 +4326,51 @@ struct FeatureTableSubstitutionRecord
+   }
+ 
+   void collect_feature_substitutes_with_variations (hb_hashmap_t *feature_substitutes_map,
++                                                    hb_set_t& catch_all_record_feature_idxes,
+                                                     const hb_set_t *feature_indices,
+                                                     const void *base) const
+   {
+     if (feature_indices->has (featureIndex))
++    {
+       feature_substitutes_map->set (featureIndex, &(base+feature));
++      catch_all_record_feature_idxes.add (featureIndex);
++    }
++  }
++
++  bool serialize (hb_subset_layout_context_t *c,
++                  unsigned feature_index,
++                  const Feature *f, const Tag *tag)
++  {
++    TRACE_SERIALIZE (this);
++    hb_serialize_context_t *s = c->subset_context->serializer;
++    if (unlikely (!s->extend_min (this))) return_trace (false);
++
++    uint32_t *new_feature_idx;
++    if (!c->feature_index_map->has (feature_index, &new_feature_idx))
++      return_trace (false);
++
++    if (!s->check_assign (featureIndex, *new_feature_idx, HB_SERIALIZE_ERROR_INT_OVERFLOW))
++      return_trace (false);
++
++    s->push ();
++    bool ret = f->subset (c->subset_context, c, tag);
++    if (ret) s->add_link (feature, s->pop_pack ());
++    else s->pop_discard ();
++
++    return_trace (ret);
+   }
+ 
+   bool subset (hb_subset_layout_context_t *c, const void *base) const
+   {
+     TRACE_SUBSET (this);
+-    if (!c->feature_index_map->has (featureIndex) ||
+-        c->feature_substitutes_map->has (featureIndex)) {
+-      // Feature that is being substituted is not being retained, so we don't
+-      // need this.
++    uint32_t *new_feature_index;
++    if (!c->feature_index_map->has (featureIndex, &new_feature_index))
+       return_trace (false);
+-    }
+ 
+     auto *out = c->subset_context->serializer->embed (this);
+     if (unlikely (!out)) return_trace (false);
+ 
+-    out->featureIndex = c->feature_index_map->get (featureIndex);
++    out->featureIndex = *new_feature_index;
+     return_trace (out->feature.serialize_subset (c->subset_context, feature, base, c));
+   }
+ 
+@@ -3600,16 +4402,10 @@ struct FeatureTableSubstitution
+   }
+ 
+   void collect_lookups (const hb_set_t *feature_indexes,
+-                        const hb_hashmap_t *feature_substitutes_map,
+                         hb_set_t       *lookup_indexes /* OUT */) const
+   {
+     + hb_iter (substitutions)
+     | hb_filter (feature_indexes, &FeatureTableSubstitutionRecord::featureIndex)
+-    | hb_filter ([feature_substitutes_map] (const FeatureTableSubstitutionRecord& record)
+-                 {
+-                   if (feature_substitutes_map == nullptr) return true;
+-                   return !feature_substitutes_map->has (record.featureIndex);
+-                 })
+     | hb_apply ([this, lookup_indexes] (const FeatureTableSubstitutionRecord& r)
+                 { r.collect_lookups (this, lookup_indexes); })
+     ;
+@@ -3634,11 +4430,14 @@ struct FeatureTableSubstitution
+   void collect_feature_substitutes_with_variations (hb_collect_feature_substitutes_with_var_context_t *c) const
+   {
+     for (const FeatureTableSubstitutionRecord& record : substitutions)
+-      record.collect_feature_substitutes_with_variations (c->feature_substitutes_map, c->feature_indices, this);
++      record.collect_feature_substitutes_with_variations (c->feature_substitutes_map,
++                                                          c->catch_all_record_feature_idxes,
++                                                          c->feature_indices, this);
+   }
+ 
+   bool subset (hb_subset_context_t        *c,
+-               hb_subset_layout_context_t *l) const
++               hb_subset_layout_context_t *l,
++               bool insert_catch_all) const
+   {
+     TRACE_SUBSET (this);
+     auto *out = c->serializer->start_embed (*this);
+@@ -3647,6 +4446,22 @@ struct FeatureTableSubstitution
+     out->version.major = version.major;
+     out->version.minor = version.minor;
+ 
++    if (insert_catch_all)
++    {
++      for (unsigned feature_index : *(l->catch_all_record_feature_idxes))
++      {
++        hb_pair_t *p;
++        if (!l->feature_idx_tag_map->has (feature_index, &p))
++          return_trace (false);
++        auto *o = out->substitutions.serialize_append (c->serializer);
++        if (!o->serialize (l, feature_index,
++                           reinterpret_cast (p->first),
++                           reinterpret_cast (p->second)))
++          return_trace (false);
++      }
++      return_trace (true);
++    }
++
+     + substitutions.iter ()
+     | hb_apply (subset_record_array (l, &(out->substitutions), this))
+     ;
+@@ -3658,6 +4473,7 @@ struct FeatureTableSubstitution
+   {
+     TRACE_SANITIZE (this);
+     return_trace (version.sanitize (c) &&
++                  hb_barrier () &&
+                   likely (version.major == 1) &&
+                   substitutions.sanitize (c, this));
+   }
+@@ -3676,10 +4492,9 @@ struct FeatureVariationRecord
+ 
+   void collect_lookups (const void     *base,
+                         const hb_set_t *feature_indexes,
+-                        const hb_hashmap_t *feature_substitutes_map,
+                         hb_set_t       *lookup_indexes /* OUT */) const
+   {
+-    return (base+substitutions).collect_lookups (feature_indexes, feature_substitutes_map, lookup_indexes);
++    return (base+substitutions).collect_lookups (feature_indexes, lookup_indexes);
+   }
+ 
+   void closure_features (const void     *base,
+@@ -3705,14 +4520,15 @@ struct FeatureVariationRecord
+     }
+   }
+ 
+-  bool subset (hb_subset_layout_context_t *c, const void *base) const
++  bool subset (hb_subset_layout_context_t *c, const void *base,
++               bool insert_catch_all = false) const
+   {
+     TRACE_SUBSET (this);
+     auto *out = c->subset_context->serializer->embed (this);
+     if (unlikely (!out)) return_trace (false);
+ 
+-    out->conditions.serialize_subset (c->subset_context, conditions, base, c);
+-    out->substitutions.serialize_subset (c->subset_context, substitutions, base, c);
++    out->conditions.serialize_subset (c->subset_context, conditions, base, c, insert_catch_all);
++    out->substitutions.serialize_subset (c->subset_context, substitutions, base, c, insert_catch_all);
+ 
+     return_trace (true);
+   }
+@@ -3738,13 +4554,14 @@ struct FeatureVariations
+   static constexpr unsigned NOT_FOUND_INDEX = 0xFFFFFFFFu;
+ 
+   bool find_index (const int *coords, unsigned int coord_len,
+-                   unsigned int *index) const
++                   unsigned int *index,
++                   ItemVarStoreInstancer *instancer) const
+   {
+     unsigned int count = varRecords.len;
+     for (unsigned int i = 0; i < count; i++)
+     {
+       const FeatureVariationRecord &record = varRecords.arrayZ[i];
+-      if ((this+record.conditions).evaluate (coords, coord_len))
++      if ((this+record.conditions).evaluate (coords, coord_len, instancer))
+       {
+         *index = i;
+         return true;
+@@ -3771,9 +4588,8 @@ struct FeatureVariations
+       if (c->universal)
+         break;
+     }
+-    if (c->variation_applied && !c->universal &&
+-        !c->record_cond_idx_map->is_empty ())
+-      c->insert_catch_all_feature_variation_record = true;
++    if (c->universal || c->record_cond_idx_map->is_empty ())
++      c->catch_all_record_feature_idxes.reset ();
+   }
+ 
+   FeatureVariations* copy (hb_serialize_context_t *c) const
+@@ -3783,11 +4599,17 @@ struct FeatureVariations
+   }
+ 
+   void collect_lookups (const hb_set_t *feature_indexes,
+-                        const hb_hashmap_t *feature_substitutes_map,
++                        const hb_hashmap_t> *feature_record_cond_idx_map,
+                         hb_set_t       *lookup_indexes /* OUT */) const
+   {
+-    for (const FeatureVariationRecord& r : varRecords)
+-      r.collect_lookups (this, feature_indexes, feature_substitutes_map, lookup_indexes);
++    unsigned count = varRecords.len;
++    for (unsigned int i = 0; i < count; i++)
++    {
++      if (feature_record_cond_idx_map &&
++          !feature_record_cond_idx_map->has (i))
++        continue;
++      varRecords[i].collect_lookups (this, feature_indexes, lookup_indexes);
++    }
+   }
+ 
+   void closure_features (const hb_map_t *lookup_indexes,
+@@ -3832,6 +4654,13 @@ struct FeatureVariations
+       l->cur_feature_var_record_idx = i;
+       subset_record_array (l, &(out->varRecords), this) (varRecords[i]);
+     }
++
++    if (out->varRecords.len && !l->catch_all_record_feature_idxes->is_empty ())
++    {
++      bool insert_catch_all_record = true;
++      subset_record_array (l, &(out->varRecords), this, insert_catch_all_record) (varRecords[0]);
++    }
++
+     return_trace (bool (out->varRecords));
+   }
+ 
+@@ -3839,6 +4668,7 @@ struct FeatureVariations
+   {
+     TRACE_SANITIZE (this);
+     return_trace (version.sanitize (c) &&
++                  hb_barrier () &&
+                   likely (version.major == 1) &&
+                   varRecords.sanitize (c, this));
+   }
+@@ -3945,13 +4775,13 @@ struct VariationDevice
+   private:
+ 
+   hb_position_t get_x_delta (hb_font_t *font,
+-                             const VariationStore &store,
+-                             VariationStore::cache_t *store_cache = nullptr) const
++                             const ItemVariationStore &store,
++                             ItemVariationStore::cache_t *store_cache = nullptr) const
+   { return font->em_scalef_x (get_delta (font, store, store_cache)); }
+ 
+   hb_position_t get_y_delta (hb_font_t *font,
+-                             const VariationStore &store,
+-                             VariationStore::cache_t *store_cache = nullptr) const
++                             const ItemVariationStore &store,
++                             ItemVariationStore::cache_t *store_cache = nullptr) const
+   { return font->em_scalef_y (get_delta (font, store, store_cache)); }
+ 
+   VariationDevice* copy (hb_serialize_context_t *c,
+@@ -3985,14 +4815,14 @@ struct VariationDevice
+   private:
+ 
+   float get_delta (hb_font_t *font,
+-                   const VariationStore &store,
+-                   VariationStore::cache_t *store_cache = nullptr) const
++                   const ItemVariationStore &store,
++                   ItemVariationStore::cache_t *store_cache = nullptr) const
+   {
+-    return store.get_delta (varIdx, font->coords, font->num_coords, (VariationStore::cache_t *) store_cache);
++    return store.get_delta (varIdx, font->coords, font->num_coords, (ItemVariationStore::cache_t *) store_cache);
+   }
+ 
+   protected:
+-  VarIdx        varIdx;
++  VarIdx        varIdx;         /* Variation index */
+   HBUINT16      deltaFormat;    /* Format identifier for this table: 0x0x8000 */
+   public:
+   DEFINE_SIZE_STATIC (6);
+@@ -4012,8 +4842,8 @@ struct DeviceHeader
+ struct Device
+ {
+   hb_position_t get_x_delta (hb_font_t *font,
+-                             const VariationStore &store=Null (VariationStore),
+-                             VariationStore::cache_t *store_cache = nullptr) const
++                             const ItemVariationStore &store=Null (ItemVariationStore),
++                             ItemVariationStore::cache_t *store_cache = nullptr) const
+   {
+     switch (u.b.format)
+     {
+@@ -4030,8 +4860,8 @@ struct Device
+     }
+   }
+   hb_position_t get_y_delta (hb_font_t *font,
+-                             const VariationStore &store=Null (VariationStore),
+-                             VariationStore::cache_t *store_cache = nullptr) const
++                             const ItemVariationStore &store=Null (ItemVariationStore),
++                             ItemVariationStore::cache_t *store_cache = nullptr) const
+   {
+     switch (u.b.format)
+     {
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-gsubgpos.hh b/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-gsubgpos.hh
+index d5b5a488a..1a719391b 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-gsubgpos.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-gsubgpos.hh
+@@ -406,6 +406,7 @@ struct hb_ot_apply_context_t :
+ 
+     void set_ignore_zwnj (bool ignore_zwnj_) { ignore_zwnj = ignore_zwnj_; }
+     void set_ignore_zwj (bool ignore_zwj_) { ignore_zwj = ignore_zwj_; }
++    void set_ignore_hidden (bool ignore_hidden_) { ignore_hidden = ignore_hidden_; }
+     void set_lookup_props (unsigned int lookup_props_) { lookup_props = lookup_props_; }
+     void set_mask (hb_mask_t mask_) { mask = mask_; }
+     void set_per_syllable (bool per_syllable_) { per_syllable = per_syllable_; }
+@@ -451,9 +452,10 @@ struct hb_ot_apply_context_t :
+       if (!c->check_glyph_property (&info, lookup_props))
+         return SKIP_YES;
+ 
+-      if (unlikely (_hb_glyph_info_is_default_ignorable_and_not_hidden (&info) &&
++      if (unlikely (_hb_glyph_info_is_default_ignorable (&info) &&
+                     (ignore_zwnj || !_hb_glyph_info_is_zwnj (&info)) &&
+-                    (ignore_zwj || !_hb_glyph_info_is_zwj (&info))))
++                    (ignore_zwj || !_hb_glyph_info_is_zwj (&info)) &&
++                    (ignore_hidden || !_hb_glyph_info_is_hidden (&info))))
+         return SKIP_MAYBE;
+ 
+       return SKIP_NO;
+@@ -464,6 +466,7 @@ struct hb_ot_apply_context_t :
+     hb_mask_t mask = -1;
+     bool ignore_zwnj = false;
+     bool ignore_zwj = false;
++    bool ignore_hidden = false;
+     bool per_syllable = false;
+     uint8_t syllable = 0;
+     match_func_t match_func = nullptr;
+@@ -486,6 +489,8 @@ struct hb_ot_apply_context_t :
+       matcher.set_ignore_zwnj (c->table_index == 1 || (context_match && c->auto_zwnj));
+       /* Ignore ZWJ if we are matching context, or asked to. */
+       matcher.set_ignore_zwj  (context_match || c->auto_zwj);
++      /* Ignore hidden glyphs (like CGJ) during GPOS. */
++      matcher.set_ignore_hidden (c->table_index == 1);
+       matcher.set_mask (context_match ? -1 : c->lookup_mask);
+       /* Per syllable matching is only for GSUB. */
+       matcher.set_per_syllable (c->table_index == 0 && c->per_syllable);
+@@ -708,8 +713,9 @@ struct hb_ot_apply_context_t :
+   recurse_func_t recurse_func = nullptr;
+   const GDEF &gdef;
+   const GDEF::accelerator_t &gdef_accel;
+-  const VariationStore &var_store;
+-  VariationStore::cache_t *var_store_cache;
++  const hb_ot_layout_lookup_accelerator_t *lookup_accel = nullptr;
++  const ItemVariationStore &var_store;
++  ItemVariationStore::cache_t *var_store_cache;
+   hb_set_digest_t digest;
+ 
+   hb_direction_t direction;
+@@ -723,7 +729,6 @@ struct hb_ot_apply_context_t :
+   bool auto_zwj = true;
+   bool per_syllable = false;
+   bool random = false;
+-  uint32_t random_state = 1;
+   unsigned new_syllables = (unsigned) -1;
+ 
+   signed last_base = -1; // GPOS uses
+@@ -758,15 +763,17 @@ struct hb_ot_apply_context_t :
+                                          nullptr
+ #endif
+                                         ),
+-                        digest (buffer_->digest ()),
+                         direction (buffer_->props.direction),
+                         has_glyph_classes (gdef.has_glyph_classes ())
+-  { init_iters (); }
++  {
++    init_iters ();
++    buffer->collect_codepoints (digest);
++  }
+ 
+   ~hb_ot_apply_context_t ()
+   {
+ #ifndef HB_NO_VAR
+-    VariationStore::destroy_cache (var_store_cache);
++    ItemVariationStore::destroy_cache (var_store_cache);
+ #endif
+   }
+ 
+@@ -788,8 +795,8 @@ struct hb_ot_apply_context_t :
+   uint32_t random_number ()
+   {
+     /* http://www.cplusplus.com/reference/random/minstd_rand/ */
+-    random_state = random_state * 48271 % 2147483647;
+-    return random_state;
++    buffer->random_state = buffer->random_state * 48271 % 2147483647;
++    return buffer->random_state;
+   }
+ 
+   bool match_properties_mark (hb_codepoint_t  glyph,
+@@ -895,6 +902,13 @@ struct hb_ot_apply_context_t :
+   }
+ };
+ 
++enum class hb_ot_lookup_cache_op_t
++{
++  CREATE,
++  ENTER,
++  LEAVE,
++  DESTROY,
++};
+ 
+ struct hb_accelerate_subtables_context_t :
+        hb_dispatch_context_t
+@@ -919,19 +933,23 @@ struct hb_accelerate_subtables_context_t :
+   }
+ 
+   template 
+-  static inline auto cache_func_ (const T *obj, hb_ot_apply_context_t *c, bool enter, hb_priority<1>) HB_RETURN (bool, obj->cache_func (c, enter) )
+-  template 
+-  static inline bool cache_func_ (const T *obj, hb_ot_apply_context_t *c, bool enter, hb_priority<0>) { return false; }
++  static inline auto cache_func_ (void *p,
++                                  hb_ot_lookup_cache_op_t op,
++                                  hb_priority<1>) HB_RETURN (void *, T::cache_func (p, op) )
++  template 
++  static inline void * cache_func_ (void *p,
++                                    hb_ot_lookup_cache_op_t op HB_UNUSED,
++                                    hb_priority<0>) { return (void *) false; }
+   template 
+-  static inline bool cache_func_to (const void *obj, hb_ot_apply_context_t *c, bool enter)
++  static inline void * cache_func_to (void *p,
++                                      hb_ot_lookup_cache_op_t op)
+   {
+-    const Type *typed_obj = (const Type *) obj;
+-    return cache_func_ (typed_obj, c, enter, hb_prioritize);
++    return cache_func_ (p, op, hb_prioritize);
+   }
+ #endif
+ 
+   typedef bool (*hb_apply_func_t) (const void *obj, hb_ot_apply_context_t *c);
+-  typedef bool (*hb_cache_func_t) (const void *obj, hb_ot_apply_context_t *c, bool enter);
++  typedef void * (*hb_cache_func_t) (void *p, hb_ot_lookup_cache_op_t op);
+ 
+   struct hb_applicable_t
+   {
+@@ -968,11 +986,11 @@ struct hb_accelerate_subtables_context_t :
+     }
+     bool cache_enter (hb_ot_apply_context_t *c) const
+     {
+-      return cache_func (obj, c, true);
++      return (bool) cache_func (c, hb_ot_lookup_cache_op_t::ENTER);
+     }
+     void cache_leave (hb_ot_apply_context_t *c) const
+     {
+-      cache_func (obj, c, false);
++      cache_func (c, hb_ot_lookup_cache_op_t::LEAVE);
+     }
+ #endif
+ 
+@@ -1255,7 +1273,7 @@ static bool match_input (hb_ot_apply_context_t *c,
+                          match_func_t match_func,
+                          const void *match_data,
+                          unsigned int *end_position,
+-                         unsigned int match_positions[HB_MAX_CONTEXT_LENGTH],
++                         unsigned int *match_positions,
+                          unsigned int *p_total_component_count = nullptr)
+ {
+   TRACE_APPLY (nullptr);
+@@ -1379,7 +1397,7 @@ static bool match_input (hb_ot_apply_context_t *c,
+ }
+ static inline bool ligate_input (hb_ot_apply_context_t *c,
+                                  unsigned int count, /* Including the first glyph */
+-                                 const unsigned int match_positions[HB_MAX_CONTEXT_LENGTH], /* Including the first glyph */
++                                 const unsigned int *match_positions, /* Including the first glyph */
+                                  unsigned int match_end,
+                                  hb_codepoint_t lig_glyph,
+                                  unsigned int total_component_count)
+@@ -1458,6 +1476,7 @@ static inline bool ligate_input (hb_ot_apply_context_t *c,
+         unsigned int this_comp = _hb_glyph_info_get_lig_comp (&buffer->cur());
+         if (this_comp == 0)
+           this_comp = last_num_components;
++        assert (components_so_far >= last_num_components);
+         unsigned int new_lig_comp = components_so_far - last_num_components +
+                                     hb_min (this_comp, last_num_components);
+           _hb_glyph_info_set_lig_props_for_mark (&buffer->cur(), lig_id, new_lig_comp);
+@@ -1483,6 +1502,7 @@ static inline bool ligate_input (hb_ot_apply_context_t *c,
+       unsigned this_comp = _hb_glyph_info_get_lig_comp (&buffer->info[i]);
+       if (!this_comp) break;
+ 
++      assert (components_so_far >= last_num_components);
+       unsigned new_lig_comp = components_so_far - last_num_components +
+                               hb_min (this_comp, last_num_components);
+       _hb_glyph_info_set_lig_props_for_mark (&buffer->info[i], lig_id, new_lig_comp);
+@@ -1538,6 +1558,7 @@ static bool match_lookahead (hb_ot_apply_context_t *c,
+   TRACE_APPLY (nullptr);
+ 
+   hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_context;
++  assert (start_index >= 1);
+   skippy_iter.reset (start_index - 1);
+   skippy_iter.set_match_func (match_func, match_data);
+   skippy_iter.set_glyph_data (lookahead);
+@@ -1687,7 +1708,7 @@ static inline void recurse_lookups (context_t *c,
+ 
+ static inline void apply_lookup (hb_ot_apply_context_t *c,
+                                  unsigned int count, /* Including the first glyph */
+-                                 unsigned int match_positions[HB_MAX_CONTEXT_LENGTH], /* Including the first glyph */
++                                 unsigned int *match_positions, /* Including the first glyph */
+                                  unsigned int lookupCount,
+                                  const LookupRecord lookupRecord[], /* Array of LookupRecords--in design order */
+                                  unsigned int match_end)
+@@ -1695,6 +1716,9 @@ static inline void apply_lookup (hb_ot_apply_context_t *c,
+   hb_buffer_t *buffer = c->buffer;
+   int end;
+ 
++  unsigned int *match_positions_input = match_positions;
++  unsigned int match_positions_count = count;
++
+   /* All positions are distance from beginning of *output* buffer.
+    * Adjust. */
+   {
+@@ -1798,6 +1822,27 @@ static inline void apply_lookup (hb_ot_apply_context_t *c,
+     {
+       if (unlikely (delta + count > HB_MAX_CONTEXT_LENGTH))
+         break;
++      if (unlikely (delta + count > match_positions_count))
++      {
++        unsigned new_match_positions_count = hb_max (delta + count, hb_max(match_positions_count, 4u) * 1.5);
++        if (match_positions == match_positions_input)
++        {
++          match_positions = (unsigned int *) hb_malloc (new_match_positions_count * sizeof (match_positions[0]));
++          if (unlikely (!match_positions))
++            break;
++          memcpy (match_positions, match_positions_input, count * sizeof (match_positions[0]));
++          match_positions_count = new_match_positions_count;
++        }
++        else
++        {
++          unsigned int *new_match_positions = (unsigned int *) hb_realloc (match_positions, new_match_positions_count * sizeof (match_positions[0]));
++          if (unlikely (!new_match_positions))
++            break;
++          match_positions = new_match_positions;
++          match_positions_count = new_match_positions_count;
++        }
++      }
++
+     }
+     else
+     {
+@@ -1821,6 +1866,10 @@ static inline void apply_lookup (hb_ot_apply_context_t *c,
+       match_positions[next] += delta;
+   }
+ 
++  if (match_positions != match_positions_input)
++    hb_free (match_positions);
++
++  assert (end >= 0);
+   (void) buffer->move_to (end);
+ }
+ 
+@@ -1921,8 +1970,18 @@ static bool context_apply_lookup (hb_ot_apply_context_t *c,
+                                   const LookupRecord lookupRecord[],
+                                   const ContextApplyLookupContext &lookup_context)
+ {
++  if (unlikely (inputCount > HB_MAX_CONTEXT_LENGTH)) return false;
++  unsigned match_positions_stack[4];
++  unsigned *match_positions = match_positions_stack;
++  if (unlikely (inputCount > ARRAY_LENGTH (match_positions_stack)))
++  {
++    match_positions = (unsigned *) hb_malloc (hb_max (inputCount, 1u) * sizeof (match_positions[0]));
++    if (unlikely (!match_positions))
++      return false;
++  }
++
+   unsigned match_end = 0;
+-  unsigned match_positions[HB_MAX_CONTEXT_LENGTH];
++  bool ret = false;
+   if (match_input (c,
+                    inputCount, input,
+                    lookup_context.funcs.match, lookup_context.match_data,
+@@ -1933,13 +1992,18 @@ static bool context_apply_lookup (hb_ot_apply_context_t *c,
+                   inputCount, match_positions,
+                   lookupCount, lookupRecord,
+                   match_end);
+-    return true;
++    ret = true;
+   }
+   else
+   {
+     c->buffer->unsafe_to_concat (c->buffer->idx, match_end);
+-    return false;
++    ret = false;
+   }
++
++  if (unlikely (match_positions != match_positions_stack))
++    hb_free (match_positions);
++
++  return ret;
+ }
+ 
+ template 
+@@ -2051,6 +2115,7 @@ struct Rule
+   {
+     TRACE_SANITIZE (this);
+     return_trace (c->check_struct (this) &&
++                  hb_barrier () &&
+                   c->check_range (inputZ.arrayZ,
+                                   inputZ.item_size * (inputCount ? inputCount - 1 : 0) +
+                                   LookupRecord::static_size * lookupCount));
+@@ -2572,25 +2637,35 @@ struct ContextFormat2_5
+     unsigned c = (this+classDef).cost () * ruleSet.len;
+     return c >= 4 ? c : 0;
+   }
+-  bool cache_func (hb_ot_apply_context_t *c, bool enter) const
++  static void * cache_func (void *p, hb_ot_lookup_cache_op_t op)
+   {
+-    if (enter)
+-    {
+-      if (!HB_BUFFER_TRY_ALLOCATE_VAR (c->buffer, syllable))
+-        return false;
+-      auto &info = c->buffer->info;
+-      unsigned count = c->buffer->len;
+-      for (unsigned i = 0; i < count; i++)
+-        info[i].syllable() = 255;
+-      c->new_syllables = 255;
+-      return true;
+-    }
+-    else
++    switch (op)
+     {
+-      c->new_syllables = (unsigned) -1;
+-      HB_BUFFER_DEALLOCATE_VAR (c->buffer, syllable);
+-      return true;
++      case hb_ot_lookup_cache_op_t::CREATE:
++        return (void *) true;
++      case hb_ot_lookup_cache_op_t::ENTER:
++      {
++        hb_ot_apply_context_t *c = (hb_ot_apply_context_t *) p;
++        if (!HB_BUFFER_TRY_ALLOCATE_VAR (c->buffer, syllable))
++          return (void *) false;
++        auto &info = c->buffer->info;
++        unsigned count = c->buffer->len;
++        for (unsigned i = 0; i < count; i++)
++          info[i].syllable() = 255;
++        c->new_syllables = 255;
++        return (void *) true;
++      }
++      case hb_ot_lookup_cache_op_t::LEAVE:
++      {
++        hb_ot_apply_context_t *c = (hb_ot_apply_context_t *) p;
++        c->new_syllables = (unsigned) -1;
++        HB_BUFFER_DEALLOCATE_VAR (c->buffer, syllable);
++        return nullptr;
++      }
++      case hb_ot_lookup_cache_op_t::DESTROY:
++        return nullptr;
+     }
++    return nullptr;
+   }
+ 
+   bool apply_cached (hb_ot_apply_context_t *c) const { return _apply (c, true); }
+@@ -2599,7 +2674,7 @@ struct ContextFormat2_5
+   {
+     TRACE_APPLY (this);
+     unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
+-    if (likely (index == NOT_COVERED)) return_trace (false);
++    if (index == NOT_COVERED) return_trace (false);
+ 
+     const ClassDef &class_def = this+classDef;
+ 
+@@ -2785,7 +2860,7 @@ struct ContextFormat3
+   {
+     TRACE_APPLY (this);
+     unsigned int index = (this+coverageZ[0]).get_coverage (c->buffer->cur().codepoint);
+-    if (likely (index == NOT_COVERED)) return_trace (false);
++    if (index == NOT_COVERED) return_trace (false);
+ 
+     const LookupRecord *lookupRecord = &StructAfter (coverageZ.as_array (glyphCount));
+     struct ContextApplyLookupContext lookup_context = {
+@@ -2826,6 +2901,7 @@ struct ContextFormat3
+   {
+     TRACE_SANITIZE (this);
+     if (unlikely (!c->check_struct (this))) return_trace (false);
++    hb_barrier ();
+     unsigned int count = glyphCount;
+     if (unlikely (!count)) return_trace (false); /* We want to access coverageZ[0] freely. */
+     if (unlikely (!c->check_array (coverageZ.arrayZ, count))) return_trace (false);
+@@ -2858,12 +2934,12 @@ struct Context
+     if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
+     TRACE_DISPATCH (this, u.format);
+     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)...));
+-    case 3: return_trace (c->dispatch (u.format3, std::forward (ds)...));
++    case 1: hb_barrier (); return_trace (c->dispatch (u.format1, std::forward (ds)...));
++    case 2: hb_barrier (); return_trace (c->dispatch (u.format2, std::forward (ds)...));
++    case 3: hb_barrier (); return_trace (c->dispatch (u.format3, std::forward (ds)...));
+ #ifndef HB_NO_BEYOND_64K
+-    case 4: return_trace (c->dispatch (u.format4, std::forward (ds)...));
+-    case 5: return_trace (c->dispatch (u.format5, std::forward (ds)...));
++    case 4: hb_barrier (); return_trace (c->dispatch (u.format4, std::forward (ds)...));
++    case 5: hb_barrier (); return_trace (c->dispatch (u.format5, std::forward (ds)...));
+ #endif
+     default:return_trace (c->default_return_value ());
+     }
+@@ -3017,9 +3093,20 @@ static bool chain_context_apply_lookup (hb_ot_apply_context_t *c,
+                                         const LookupRecord lookupRecord[],
+                                         const ChainContextApplyLookupContext &lookup_context)
+ {
++  if (unlikely (inputCount > HB_MAX_CONTEXT_LENGTH)) return false;
++  unsigned match_positions_stack[4];
++  unsigned *match_positions = match_positions_stack;
++  if (unlikely (inputCount > ARRAY_LENGTH (match_positions_stack)))
++  {
++    match_positions = (unsigned *) hb_malloc (hb_max (inputCount, 1u) * sizeof (match_positions[0]));
++    if (unlikely (!match_positions))
++      return false;
++  }
++
++  unsigned start_index = c->buffer->out_len;
+   unsigned end_index = c->buffer->idx;
+   unsigned match_end = 0;
+-  unsigned match_positions[HB_MAX_CONTEXT_LENGTH];
++  bool ret = true;
+   if (!(match_input (c,
+                      inputCount, input,
+                      lookup_context.funcs.match[1], lookup_context.match_data[1],
+@@ -3030,17 +3117,18 @@ static bool chain_context_apply_lookup (hb_ot_apply_context_t *c,
+                            match_end, &end_index)))
+   {
+     c->buffer->unsafe_to_concat (c->buffer->idx, end_index);
+-    return false;
++    ret = false;
++    goto done;
+   }
+ 
+-  unsigned start_index = c->buffer->out_len;
+   if (!match_backtrack (c,
+                         backtrackCount, backtrack,
+                         lookup_context.funcs.match[0], lookup_context.match_data[0],
+                         &start_index))
+   {
+     c->buffer->unsafe_to_concat_from_outbuffer (start_index, end_index);
+-    return false;
++    ret = false;
++    goto done;
+   }
+ 
+   c->buffer->unsafe_to_break_from_outbuffer (start_index, end_index);
+@@ -3048,7 +3136,12 @@ static bool chain_context_apply_lookup (hb_ot_apply_context_t *c,
+                 inputCount, match_positions,
+                 lookupCount, lookupRecord,
+                 match_end);
+-  return true;
++  done:
++
++  if (unlikely (match_positions != match_positions_stack))
++    hb_free (match_positions);
++
++  return ret;
+ }
+ 
+ template 
+@@ -3219,10 +3312,13 @@ struct ChainRule
+     TRACE_SANITIZE (this);
+     /* Hyper-optimized sanitized because this is really hot. */
+     if (unlikely (!backtrack.len.sanitize (c))) return_trace (false);
++    hb_barrier ();
+     const auto &input = StructAfter (backtrack);
+     if (unlikely (!input.lenP1.sanitize (c))) return_trace (false);
++    hb_barrier ();
+     const auto &lookahead = StructAfter (input);
+     if (unlikely (!lookahead.len.sanitize (c))) return_trace (false);
++    hb_barrier ();
+     const auto &lookup = StructAfter (lookahead);
+     return_trace (likely (lookup.sanitize (c)));
+   }
+@@ -3327,6 +3423,15 @@ struct ChainRuleSet
+      *
+      * Replicated from LigatureSet::apply(). */
+ 
++    /* If the input skippy has non-auto joiners behavior (as in Indic shapers),
++     * skip this fast path, as we don't distinguish between input & lookahead
++     * matching in the fast path.
++     *
++     * https://github.com/harfbuzz/harfbuzz/issues/4813
++     */
++    if (!c->auto_zwnj || !c->auto_zwj)
++      goto slow;
++
+     hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
+     skippy_iter.reset (c->buffer->idx);
+     skippy_iter.set_match_func (match_always, nullptr);
+@@ -3366,10 +3471,10 @@ struct ChainRuleSet
+     }
+     matched = skippy_iter.next ();
+     if (likely (matched && !skippy_iter.may_skip (c->buffer->info[skippy_iter.idx])))
+-     {
++    {
+       second = &c->buffer->info[skippy_iter.idx];
+       unsafe_to2 = skippy_iter.idx + 1;
+-     }
++    }
+ 
+     auto match_input = lookup_context.funcs.match[1];
+     auto match_lookahead = lookup_context.funcs.match[2];
+@@ -3569,7 +3674,7 @@ struct ChainContextFormat1_4
+   {
+     TRACE_APPLY (this);
+     unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
+-    if (likely (index == NOT_COVERED)) return_trace (false);
++    if (index == NOT_COVERED) return_trace (false);
+ 
+     const ChainRuleSet &rule_set = this+ruleSet[index];
+     struct ChainContextApplyLookupContext lookup_context = {
+@@ -3780,28 +3885,37 @@ struct ChainContextFormat2_5
+ 
+   unsigned cache_cost () const
+   {
+-    unsigned c = (this+lookaheadClassDef).cost () * ruleSet.len;
+-    return c >= 4 ? c : 0;
++    return (this+lookaheadClassDef).cost () * ruleSet.len;
+   }
+-  bool cache_func (hb_ot_apply_context_t *c, bool enter) const
++  static void * cache_func (void *p, hb_ot_lookup_cache_op_t op)
+   {
+-    if (enter)
++    switch (op)
+     {
+-      if (!HB_BUFFER_TRY_ALLOCATE_VAR (c->buffer, syllable))
+-        return false;
+-      auto &info = c->buffer->info;
+-      unsigned count = c->buffer->len;
+-      for (unsigned i = 0; i < count; i++)
+-        info[i].syllable() = 255;
+-      c->new_syllables = 255;
+-      return true;
+-    }
+-    else
+-    {
+-      c->new_syllables = (unsigned) -1;
+-      HB_BUFFER_DEALLOCATE_VAR (c->buffer, syllable);
+-      return true;
++      case hb_ot_lookup_cache_op_t::CREATE:
++        return (void *) true;
++      case hb_ot_lookup_cache_op_t::ENTER:
++      {
++        hb_ot_apply_context_t *c = (hb_ot_apply_context_t *) p;
++        if (!HB_BUFFER_TRY_ALLOCATE_VAR (c->buffer, syllable))
++          return (void *) false;
++        auto &info = c->buffer->info;
++        unsigned count = c->buffer->len;
++        for (unsigned i = 0; i < count; i++)
++          info[i].syllable() = 255;
++        c->new_syllables = 255;
++        return (void *) true;
++      }
++      case hb_ot_lookup_cache_op_t::LEAVE:
++      {
++        hb_ot_apply_context_t *c = (hb_ot_apply_context_t *) p;
++        c->new_syllables = (unsigned) -1;
++        HB_BUFFER_DEALLOCATE_VAR (c->buffer, syllable);
++        return nullptr;
++      }
++      case hb_ot_lookup_cache_op_t::DESTROY:
++        return nullptr;
+     }
++    return nullptr;
+   }
+ 
+   bool apply_cached (hb_ot_apply_context_t *c) const { return _apply (c, true); }
+@@ -3810,7 +3924,7 @@ struct ChainContextFormat2_5
+   {
+     TRACE_APPLY (this);
+     unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
+-    if (likely (index == NOT_COVERED)) return_trace (false);
++    if (index == NOT_COVERED) return_trace (false);
+ 
+     const ClassDef &backtrack_class_def = this+backtrackClassDef;
+     const ClassDef &input_class_def = this+inputClassDef;
+@@ -4056,7 +4170,7 @@ struct ChainContextFormat3
+     const auto &input = StructAfter (backtrack);
+ 
+     unsigned int index = (this+input[0]).get_coverage (c->buffer->cur().codepoint);
+-    if (likely (index == NOT_COVERED)) return_trace (false);
++    if (index == NOT_COVERED) return_trace (false);
+ 
+     const auto &lookahead = StructAfter (input);
+     const auto &lookup = StructAfter (lookahead);
+@@ -4121,11 +4235,14 @@ struct ChainContextFormat3
+   {
+     TRACE_SANITIZE (this);
+     if (unlikely (!backtrack.sanitize (c, this))) return_trace (false);
++    hb_barrier ();
+     const auto &input = StructAfter (backtrack);
+     if (unlikely (!input.sanitize (c, this))) return_trace (false);
++    hb_barrier ();
+     if (unlikely (!input.len)) return_trace (false); /* To be consistent with Context. */
+     const auto &lookahead = StructAfter (input);
+     if (unlikely (!lookahead.sanitize (c, this))) return_trace (false);
++    hb_barrier ();
+     const auto &lookup = StructAfter (lookahead);
+     return_trace (likely (lookup.sanitize (c)));
+   }
+@@ -4159,12 +4276,12 @@ struct ChainContext
+     if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
+     TRACE_DISPATCH (this, u.format);
+     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)...));
+-    case 3: return_trace (c->dispatch (u.format3, std::forward (ds)...));
++    case 1: hb_barrier (); return_trace (c->dispatch (u.format1, std::forward (ds)...));
++    case 2: hb_barrier (); return_trace (c->dispatch (u.format2, std::forward (ds)...));
++    case 3: hb_barrier (); return_trace (c->dispatch (u.format3, std::forward (ds)...));
+ #ifndef HB_NO_BEYOND_64K
+-    case 4: return_trace (c->dispatch (u.format4, std::forward (ds)...));
+-    case 5: return_trace (c->dispatch (u.format5, std::forward (ds)...));
++    case 4: hb_barrier (); return_trace (c->dispatch (u.format4, std::forward (ds)...));
++    case 5: hb_barrier (); return_trace (c->dispatch (u.format5, std::forward (ds)...));
+ #endif
+     default:return_trace (c->default_return_value ());
+     }
+@@ -4209,6 +4326,7 @@ struct ExtensionFormat1
+   {
+     TRACE_SANITIZE (this);
+     return_trace (c->check_struct (this) &&
++                  hb_barrier () &&
+                   extensionLookupType != T::SubTable::Extension);
+   }
+ 
+@@ -4247,7 +4365,7 @@ struct Extension
+   unsigned int get_type () const
+   {
+     switch (u.format) {
+-    case 1: return u.format1.get_type ();
++    case 1: hb_barrier (); return u.format1.get_type ();
+     default:return 0;
+     }
+   }
+@@ -4255,7 +4373,7 @@ struct Extension
+   const X& get_subtable () const
+   {
+     switch (u.format) {
+-    case 1: return u.format1.template get_subtable ();
++    case 1: hb_barrier (); return u.format1.template get_subtable ();
+     default:return Null (typename T::SubTable);
+     }
+   }
+@@ -4267,7 +4385,7 @@ struct Extension
+   typename hb_subset_context_t::return_t dispatch (hb_subset_context_t *c, Ts&&... ds) const
+   {
+     switch (u.format) {
+-    case 1: return u.format1.subset (c);
++    case 1: hb_barrier (); return u.format1.subset (c);
+     default: return c->default_return_value ();
+     }
+   }
+@@ -4278,7 +4396,7 @@ struct Extension
+     if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
+     TRACE_DISPATCH (this, u.format);
+     switch (u.format) {
+-    case 1: return_trace (u.format1.dispatch (c, std::forward (ds)...));
++    case 1: hb_barrier (); return_trace (u.format1.dispatch (c, std::forward (ds)...));
+     default:return_trace (c->default_return_value ());
+     }
+   }
+@@ -4320,10 +4438,21 @@ struct hb_ot_layout_lookup_accelerator_t
+ 
+     thiz->digest.init ();
+     for (auto& subtable : hb_iter (thiz->subtables, count))
+-      thiz->digest.add (subtable.digest);
++      thiz->digest.union_ (subtable.digest);
+ 
+ #ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
++    if (c_accelerate_subtables.cache_user_cost < 4)
++      c_accelerate_subtables.cache_user_idx = (unsigned) -1;
++
+     thiz->cache_user_idx = c_accelerate_subtables.cache_user_idx;
++
++    if (thiz->cache_user_idx != (unsigned) -1)
++    {
++      thiz->cache = thiz->subtables[thiz->cache_user_idx].cache_func (nullptr, hb_ot_lookup_cache_op_t::CREATE);
++      if (!thiz->cache)
++        thiz->cache_user_idx = (unsigned) -1;
++    }
++
+     for (unsigned i = 0; i < count; i++)
+       if (i != thiz->cache_user_idx)
+         thiz->subtables[i].apply_cached_func = thiz->subtables[i].apply_func;
+@@ -4332,6 +4461,17 @@ struct hb_ot_layout_lookup_accelerator_t
+     return thiz;
+   }
+ 
++  void fini ()
++  {
++#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
++    if (cache)
++    {
++      assert (cache_user_idx != (unsigned) -1);
++      subtables[cache_user_idx].cache_func (cache, hb_ot_lookup_cache_op_t::DESTROY);
++    }
++#endif
++  }
++
+   bool may_have (hb_codepoint_t g) const
+   { return digest.may_have (g); }
+ 
+@@ -4340,6 +4480,7 @@ struct hb_ot_layout_lookup_accelerator_t
+ #endif
+   bool apply (hb_ot_apply_context_t *c, unsigned subtables_count, bool use_cache) const
+   {
++    c->lookup_accel = this;
+ #ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
+     if (use_cache)
+     {
+@@ -4379,10 +4520,13 @@ struct hb_ot_layout_lookup_accelerator_t
+ 
+ 
+   hb_set_digest_t digest;
+-  private:
+ #ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
++  public:
++  void *cache = nullptr;
++  private:
+   unsigned cache_user_idx = (unsigned) -1;
+ #endif
++  private:
+   hb_accelerate_subtables_context_t::hb_applicable_t subtables[HB_VAR_ARRAY];
+ };
+ 
+@@ -4472,13 +4616,6 @@ struct GSUBGPOSVersion1_2
+       if (!c->subset_context->serializer->extend_min (&out->featureVars))
+         return_trace (false);
+ 
+-      // TODO(qxliu76): the current implementation doesn't correctly handle feature variations
+-      //                that are dropped by instancing when the associated conditions don't trigger.
+-      //                Since partial instancing isn't yet supported this isn't an issue yet but will
+-      //                need to be fixed for partial instancing.
+-
+-
+-
+       // if all axes are pinned all feature vars are dropped.
+       bool ret = !c->subset_context->plan->all_axes_pinned
+                  && out->featureVars.serialize_subset (c->subset_context, featureVars, this, c);
+@@ -4500,9 +4637,9 @@ struct GSUBGPOS
+   unsigned int get_size () const
+   {
+     switch (u.version.major) {
+-    case 1: return u.version1.get_size ();
++    case 1: hb_barrier (); return u.version1.get_size ();
+ #ifndef HB_NO_BEYOND_64K
+-    case 2: return u.version2.get_size ();
++    case 2: hb_barrier (); return u.version2.get_size ();
+ #endif
+     default: return u.version.static_size;
+     }
+@@ -4513,10 +4650,11 @@ struct GSUBGPOS
+   {
+     TRACE_SANITIZE (this);
+     if (unlikely (!u.version.sanitize (c))) return_trace (false);
++    hb_barrier ();
+     switch (u.version.major) {
+-    case 1: return_trace (u.version1.sanitize (c));
++    case 1: hb_barrier (); return_trace (u.version1.sanitize (c));
+ #ifndef HB_NO_BEYOND_64K
+-    case 2: return_trace (u.version2.sanitize (c));
++    case 2: hb_barrier (); return_trace (u.version2.sanitize (c));
+ #endif
+     default: return_trace (true);
+     }
+@@ -4526,9 +4664,9 @@ struct GSUBGPOS
+   bool subset (hb_subset_layout_context_t *c) const
+   {
+     switch (u.version.major) {
+-    case 1: return u.version1.subset (c);
++    case 1: hb_barrier (); return u.version1.subset (c);
+ #ifndef HB_NO_BEYOND_64K
+-    case 2: return u.version2.subset (c);
++    case 2: hb_barrier (); return u.version2.subset (c);
+ #endif
+     default: return false;
+     }
+@@ -4537,9 +4675,9 @@ struct GSUBGPOS
+   const ScriptList &get_script_list () const
+   {
+     switch (u.version.major) {
+-    case 1: return this+u.version1.scriptList;
++    case 1: hb_barrier (); return this+u.version1.scriptList;
+ #ifndef HB_NO_BEYOND_64K
+-    case 2: return this+u.version2.scriptList;
++    case 2: hb_barrier (); return this+u.version2.scriptList;
+ #endif
+     default: return Null (ScriptList);
+     }
+@@ -4547,9 +4685,9 @@ struct GSUBGPOS
+   const FeatureList &get_feature_list () const
+   {
+     switch (u.version.major) {
+-    case 1: return this+u.version1.featureList;
++    case 1: hb_barrier (); return this+u.version1.featureList;
+ #ifndef HB_NO_BEYOND_64K
+-    case 2: return this+u.version2.featureList;
++    case 2: hb_barrier (); return this+u.version2.featureList;
+ #endif
+     default: return Null (FeatureList);
+     }
+@@ -4557,9 +4695,9 @@ struct GSUBGPOS
+   unsigned int get_lookup_count () const
+   {
+     switch (u.version.major) {
+-    case 1: return (this+u.version1.lookupList).len;
++    case 1: hb_barrier (); return (this+u.version1.lookupList).len;
+ #ifndef HB_NO_BEYOND_64K
+-    case 2: return (this+u.version2.lookupList).len;
++    case 2: hb_barrier (); return (this+u.version2.lookupList).len;
+ #endif
+     default: return 0;
+     }
+@@ -4567,9 +4705,9 @@ struct GSUBGPOS
+   const Lookup& get_lookup (unsigned int i) const
+   {
+     switch (u.version.major) {
+-    case 1: return (this+u.version1.lookupList)[i];
++    case 1: hb_barrier (); return (this+u.version1.lookupList)[i];
+ #ifndef HB_NO_BEYOND_64K
+-    case 2: return (this+u.version2.lookupList)[i];
++    case 2: hb_barrier (); return (this+u.version2.lookupList)[i];
+ #endif
+     default: return Null (Lookup);
+     }
+@@ -4577,9 +4715,9 @@ struct GSUBGPOS
+   const FeatureVariations &get_feature_variations () const
+   {
+     switch (u.version.major) {
+-    case 1: return (u.version.to_int () >= 0x00010001u ? this+u.version1.featureVars : Null (FeatureVariations));
++    case 1: hb_barrier (); return (u.version.to_int () >= 0x00010001u && hb_barrier () ? this+u.version1.featureVars : Null (FeatureVariations));
+ #ifndef HB_NO_BEYOND_64K
+-    case 2: return this+u.version2.featureVars;
++    case 2: hb_barrier (); return this+u.version2.featureVars;
+ #endif
+     default: return Null (FeatureVariations);
+     }
+@@ -4613,13 +4751,14 @@ struct GSUBGPOS
+   { return get_feature_list ().find_index (tag, index); }
+ 
+   bool find_variations_index (const int *coords, unsigned int num_coords,
+-                              unsigned int *index) const
++                              unsigned int *index,
++                              ItemVarStoreInstancer *instancer) const
+   {
+ #ifdef HB_NO_VAR
+     *index = FeatureVariations::NOT_FOUND_INDEX;
+     return false;
+ #endif
+-    return get_feature_variations ().find_index (coords, num_coords, index);
++    return get_feature_variations ().find_index (coords, num_coords, index, instancer);
+   }
+   const Feature& get_feature_variation (unsigned int feature_index,
+                                         unsigned int variations_index) const
+@@ -4638,11 +4777,11 @@ struct GSUBGPOS
+   }
+ 
+   void feature_variation_collect_lookups (const hb_set_t *feature_indexes,
+-                                          const hb_hashmap_t *feature_substitutes_map,
++                                          const hb_hashmap_t> *feature_record_cond_idx_map,
+                                           hb_set_t       *lookup_indexes /* OUT */) const
+   {
+ #ifndef HB_NO_VAR
+-    get_feature_variations ().collect_lookups (feature_indexes, feature_substitutes_map, lookup_indexes);
++    get_feature_variations ().collect_lookups (feature_indexes, feature_record_cond_idx_map, lookup_indexes);
+ #endif
+   }
+ 
+@@ -4772,7 +4911,12 @@ struct GSUBGPOS
+     ~accelerator_t ()
+     {
+       for (unsigned int i = 0; i < this->lookup_count; i++)
+-        hb_free (this->accels[i]);
++      {
++        auto *accel = this->accels[i].get_relaxed ();
++        if (accel)
++          accel->fini ();
++        hb_free (accel);
++      }
+       hb_free (this->accels);
+       this->table.destroy ();
+     }
+@@ -4793,6 +4937,7 @@ struct GSUBGPOS
+ 
+         if (unlikely (!accels[lookup_index].cmpexch (nullptr, accel)))
+         {
++          accel->fini ();
+           hb_free (accel);
+           goto retry;
+         }
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-jstf-table.hh b/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-jstf-table.hh
+index 948c88269..823520f74 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-jstf-table.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-layout-jstf-table.hh
+@@ -214,6 +214,7 @@ struct JSTF
+   {
+     TRACE_SANITIZE (this);
+     return_trace (version.sanitize (c) &&
++                  hb_barrier () &&
+                   likely (version.major == 1) &&
+                   scriptList.sanitize (c, this));
+   }
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-layout.cc b/src/java.desktop/share/native/libharfbuzz/hb-ot-layout.cc
+index 49465acb7..787119dc6 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-layout.cc
++++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-layout.cc
+@@ -87,7 +87,7 @@ using OT::Layout::GPOS;
+ bool
+ hb_ot_layout_has_kerning (hb_face_t *face)
+ {
+-  return face->table.kern->has_data ();
++  return face->table.kern->table->has_data ();
+ }
+ 
+ /**
+@@ -103,7 +103,7 @@ hb_ot_layout_has_kerning (hb_face_t *face)
+ bool
+ hb_ot_layout_has_machine_kerning (hb_face_t *face)
+ {
+-  return face->table.kern->has_state_machine ();
++  return face->table.kern->table->has_state_machine ();
+ }
+ 
+ /**
+@@ -123,7 +123,7 @@ hb_ot_layout_has_machine_kerning (hb_face_t *face)
+ bool
+ hb_ot_layout_has_cross_kerning (hb_face_t *face)
+ {
+-  return face->table.kern->has_cross_stream ();
++  return face->table.kern->table->has_cross_stream ();
+ }
+ 
+ void
+@@ -132,7 +132,7 @@ hb_ot_layout_kern (const hb_ot_shape_plan_t *plan,
+                    hb_buffer_t  *buffer)
+ {
+   hb_blob_t *blob = font->face->table.kern.get_blob ();
+-  const AAT::kern& kern = *blob->as ();
++  const auto& kern = *font->face->table.kern;
+ 
+   AAT::hb_aat_apply_context_t c (plan, font, buffer, blob);
+ 
+@@ -246,6 +246,18 @@ OT::GDEF::is_blocklisted (hb_blob_t *blob,
+     /* sha1sum: c26e41d567ed821bed997e937bc0c41435689e85  Padauk.ttf
+      *  "Padauk Regular" "Version 2.5", see https://crbug.com/681813 */
+     case HB_CODEPOINT_ENCODE3 (1004, 59092, 14836):
++    /* 88d2006ca084f04af2df1954ed714a8c71e8400f  Courier New.ttf from macOS 15 */
++    case HB_CODEPOINT_ENCODE3 (588, 5078, 14418):
++    /* 608e3ebb6dd1aee521cff08eb07d500a2c59df68  Courier New Bold.ttf from macOS 15 */
++    case HB_CODEPOINT_ENCODE3 (588, 5078, 14238):
++    /* d13221044ff054efd78f1cd8631b853c3ce85676  cour.ttf from Windows 10 */
++    case HB_CODEPOINT_ENCODE3 (894, 17162, 33960):
++    /* 68ed4a22d8067fcf1622ac6f6e2f4d3a2e3ec394  courbd.ttf from Windows 10 */
++    case HB_CODEPOINT_ENCODE3 (894, 17154, 34472):
++    /* 4cdb0259c96b7fd7c103821bb8f08f7cc6b211d7  cour.ttf from Windows 8.1 */
++    case HB_CODEPOINT_ENCODE3 (816, 7868, 17052):
++    /* 920483d8a8ed37f7f0afdabbe7f679aece7c75d8  courbd.ttf from Windows 8.1 */
++    case HB_CODEPOINT_ENCODE3 (816, 7868, 17138):
+       return true;
+   }
+   return false;
+@@ -1443,8 +1455,12 @@ hb_ot_layout_table_find_feature_variations (hb_face_t    *face,
+                                             unsigned int *variations_index /* out */)
+ {
+   const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
++  const OT::GDEF &gdef = *face->table.GDEF->table;
+ 
+-  return g.find_variations_index (coords, num_coords, variations_index);
++  auto instancer = OT::ItemVarStoreInstancer(&gdef.get_var_store(), nullptr,
++                                             hb_array (coords, num_coords));
++
++  return g.find_variations_index (coords, num_coords, variations_index, &instancer);
+ }
+ 
+ 
+@@ -1907,9 +1923,10 @@ apply_forward (OT::hb_ot_apply_context_t *c,
+   while (buffer->idx < buffer->len && buffer->successful)
+   {
+     bool applied = false;
+-    if (accel.digest.may_have (buffer->cur().codepoint) &&
+-        (buffer->cur().mask & c->lookup_mask) &&
+-        c->check_glyph_property (&buffer->cur(), c->lookup_props))
++    auto &cur = buffer->cur();
++    if (accel.digest.may_have (cur.codepoint) &&
++        (cur.mask & c->lookup_mask) &&
++        c->check_glyph_property (&cur, c->lookup_props))
+      {
+        applied = accel.apply (c, subtable_count, use_cache);
+      }
+@@ -1935,9 +1952,10 @@ apply_backward (OT::hb_ot_apply_context_t *c,
+   hb_buffer_t *buffer = c->buffer;
+   do
+   {
+-    if (accel.digest.may_have (buffer->cur().codepoint) &&
+-        (buffer->cur().mask & c->lookup_mask) &&
+-        c->check_glyph_property (&buffer->cur(), c->lookup_props))
++    auto &cur = buffer->cur();
++    if (accel.digest.may_have (cur.codepoint) &&
++        (cur.mask & c->lookup_mask) &&
++        c->check_glyph_property (&cur, c->lookup_props))
+       ret |= accel.apply (c, subtable_count, false);
+ 
+     /* The reverse lookup doesn't "advance" cursor (for good reason). */
+@@ -2017,7 +2035,7 @@ inline void hb_ot_map_t::apply (const Proxy &proxy,
+        * (plus some past glyphs).
+        *
+        * Only try applying the lookup if there is any overlap. */
+-      if (accel->digest.may_have (c.digest))
++      if (accel->digest.may_intersect (c.digest))
+       {
+         c.set_lookup_index (lookup_index);
+         c.set_lookup_mask (lookup.mask, false);
+@@ -2043,7 +2061,7 @@ inline void hb_ot_map_t::apply (const Proxy &proxy,
+       if (stage->pause_func (plan, font, buffer))
+       {
+         /* Refresh working buffer digest since buffer changed. */
+-        c.digest = buffer->digest ();
++        buffer->collect_codepoints (c.digest);
+       }
+     }
+   }
+@@ -2127,7 +2145,7 @@ hb_ot_layout_get_font_extents (hb_font_t         *font,
+                                hb_tag_t           language_tag,
+                                hb_font_extents_t *extents)
+ {
+-  hb_position_t min, max;
++  hb_position_t min = 0, max = 0;
+   if (font->face->table.BASE->get_min_max (font, direction, script_tag, language_tag, HB_TAG_NONE,
+                                            &min, &max))
+   {
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-layout.hh b/src/java.desktop/share/native/libharfbuzz/hb-ot-layout.hh
+index 2d9a184a8..71074a874 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-layout.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-layout.hh
+@@ -173,12 +173,12 @@ _hb_next_syllable (hb_buffer_t *buffer, unsigned int start)
+ 
+ /* Design:
+  * unicode_props() is a two-byte number.  The low byte includes:
+- * - General_Category: 5 bits.
++ * - Modified General_Category: 5 bits.
+  * - A bit each for:
+  *   * Is it Default_Ignorable(); we have a modified Default_Ignorable().
+  *   * Whether it's one of the four Mongolian Free Variation Selectors,
+  *     CGJ, or other characters that are hidden but should not be ignored
+- *     like most other Default_Ignorable()s do during matching.
++ *     like most other Default_Ignorable()s do during GSUB matching.
+  *   * Whether it's a grapheme continuation.
+  *
+  * The high-byte has different meanings, switched by the Gen-Cat:
+@@ -186,17 +186,23 @@ _hb_next_syllable (hb_buffer_t *buffer, unsigned int start)
+  * - For Cf: whether it's ZWJ, ZWNJ, or something else.
+  * - For Ws: index of which space character this is, if space fallback
+  *   is needed, ie. we don't set this by default, only if asked to.
++ *
++ * Above I said "modified" General_Category. This is because we need to
++ * remember Variation Selectors, and we don't have bits left. So we
++ * change their Gen_Cat from Mn to Cf, and use a bit of the high byte to
++ * remember them.
+  */
+ 
+ enum hb_unicode_props_flags_t {
+   UPROPS_MASK_GEN_CAT   = 0x001Fu,
+   UPROPS_MASK_IGNORABLE = 0x0020u,
+-  UPROPS_MASK_HIDDEN    = 0x0040u, /* MONGOLIAN FREE VARIATION SELECTOR 1..4, or TAG characters */
++  UPROPS_MASK_HIDDEN    = 0x0040u, /* MONGOLIAN FREE VARIATION SELECTOR 1..4, or TAG characters, or CGJ sometimes */
+   UPROPS_MASK_CONTINUATION=0x0080u,
+ 
+   /* If GEN_CAT=FORMAT, top byte masks: */
+   UPROPS_MASK_Cf_ZWJ    = 0x0100u,
+-  UPROPS_MASK_Cf_ZWNJ   = 0x0200u
++  UPROPS_MASK_Cf_ZWNJ   = 0x0200u,
++  UPROPS_MASK_Cf_VS     = 0x0400u
+ };
+ HB_MARK_AS_FLAG_T (hb_unicode_props_flags_t);
+ 
+@@ -229,7 +235,7 @@ _hb_glyph_info_set_unicode_props (hb_glyph_info_t *info, hb_buffer_t *buffer)
+       /* TAG characters need similar treatment. Fixes:
+        * https://github.com/harfbuzz/harfbuzz/issues/463 */
+       else if (unlikely (hb_in_range (u, 0xE0020u, 0xE007Fu))) props |= UPROPS_MASK_HIDDEN;
+-      /* COMBINING GRAPHEME JOINER should not be skipped; at least some times.
++      /* COMBINING GRAPHEME JOINER should not be skipped during GSUB either.
+        * https://github.com/harfbuzz/harfbuzz/issues/554 */
+       else if (unlikely (u == 0x034Fu))
+       {
+@@ -302,6 +308,27 @@ _hb_glyph_info_get_unicode_space_fallback_type (const hb_glyph_info_t *info)
+          (hb_unicode_funcs_t::space_t) (info->unicode_props()>>8) :
+          hb_unicode_funcs_t::NOT_SPACE;
+ }
++static inline bool
++_hb_glyph_info_is_variation_selector (const hb_glyph_info_t *info)
++{
++  return _hb_glyph_info_get_general_category (info) ==
++         HB_UNICODE_GENERAL_CATEGORY_FORMAT &&
++         (info->unicode_props() & UPROPS_MASK_Cf_VS);
++}
++static inline void
++_hb_glyph_info_set_variation_selector (hb_glyph_info_t *info, bool customize)
++{
++  if (customize)
++  {
++    _hb_glyph_info_set_general_category (info, HB_UNICODE_GENERAL_CATEGORY_FORMAT);
++    info->unicode_props() |= UPROPS_MASK_Cf_VS;
++  }
++  else
++  {
++    // Reset to their original condition
++    _hb_glyph_info_set_general_category (info, HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK);
++  }
++}
+ 
+ static inline bool _hb_glyph_info_substituted (const hb_glyph_info_t *info);
+ 
+@@ -311,12 +338,20 @@ _hb_glyph_info_is_default_ignorable (const hb_glyph_info_t *info)
+   return (info->unicode_props() & UPROPS_MASK_IGNORABLE) &&
+          !_hb_glyph_info_substituted (info);
+ }
++static inline void
++_hb_glyph_info_set_default_ignorable (hb_glyph_info_t *info)
++{
++  info->unicode_props() |= UPROPS_MASK_IGNORABLE;
++}
++static inline void
++_hb_glyph_info_clear_default_ignorable (hb_glyph_info_t *info)
++{
++  info->unicode_props() &= ~ UPROPS_MASK_IGNORABLE;
++}
+ static inline bool
+-_hb_glyph_info_is_default_ignorable_and_not_hidden (const hb_glyph_info_t *info)
++_hb_glyph_info_is_hidden (const hb_glyph_info_t *info)
+ {
+-  return ((info->unicode_props() & (UPROPS_MASK_IGNORABLE|UPROPS_MASK_HIDDEN))
+-          == UPROPS_MASK_IGNORABLE) &&
+-         !_hb_glyph_info_substituted (info);
++  return info->unicode_props() & UPROPS_MASK_HIDDEN;
+ }
+ static inline void
+ _hb_glyph_info_unhide (hb_glyph_info_t *info)
+@@ -330,7 +365,7 @@ _hb_glyph_info_set_continuation (hb_glyph_info_t *info)
+   info->unicode_props() |= UPROPS_MASK_CONTINUATION;
+ }
+ static inline void
+-_hb_glyph_info_reset_continuation (hb_glyph_info_t *info)
++_hb_glyph_info_clear_continuation (hb_glyph_info_t *info)
+ {
+   info->unicode_props() &= ~ UPROPS_MASK_CONTINUATION;
+ }
+@@ -603,8 +638,7 @@ _hb_buffer_assert_gsubgpos_vars (hb_buffer_t *buffer)
+ }
+ 
+ /* Make sure no one directly touches our props... */
+-#undef unicode_props0
+-#undef unicode_props1
++#undef unicode_props
+ #undef lig_props
+ #undef glyph_props
+ 
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-map.cc b/src/java.desktop/share/native/libharfbuzz/hb-ot-map.cc
+index 261ce4304..a0cdfddfa 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-map.cc
++++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-map.cc
+@@ -390,5 +390,19 @@ hb_ot_map_builder_t::compile (hb_ot_map_t                  &m,
+   }
+ }
+ 
++unsigned int hb_ot_map_t::get_feature_tags (unsigned int start_offset, unsigned int *tag_count, hb_tag_t *tags) const
++{
++  if (tag_count)
++  {
++    auto sub_features = features.as_array ().sub_array (start_offset, tag_count);
++    if (tags)
++    {
++      for (unsigned int i = 0; i < sub_features.length; i++)
++        tags[i] = sub_features[i].tag;
++    }
++  }
++
++  return features.length;
++}
+ 
+ #endif
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-map.hh b/src/java.desktop/share/native/libharfbuzz/hb-ot-map.hh
+index 110361552..68af97924 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-map.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-map.hh
+@@ -166,6 +166,9 @@ struct hb_ot_map_t
+                           const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const;
+   HB_INTERNAL void substitute (const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const;
+   HB_INTERNAL void position (const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const;
++  HB_INTERNAL unsigned int get_feature_tags (unsigned int  start_offset,
++                                             unsigned int *tag_count, /* IN/OUT */
++                                             hb_tag_t     *tags /* OUT */) const;
+ 
+   public:
+   hb_tag_t chosen_script[2];
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-math-table.hh b/src/java.desktop/share/native/libharfbuzz/hb-ot-math-table.hh
+index 63bcd132c..c1b2a27b2 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-math-table.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-math-table.hh
+@@ -333,6 +333,7 @@ struct MathKern
+   {
+     TRACE_SANITIZE (this);
+     return_trace (c->check_struct (this) &&
++                  hb_barrier () &&
+                   c->check_array (mathValueRecordsZ.arrayZ, 2 * heightCount + 1) &&
+                   sanitize_math_value_records (c));
+   }
+@@ -343,27 +344,20 @@ struct MathKern
+     const MathValueRecord* kernValue = mathValueRecordsZ.arrayZ + heightCount;
+     int sign = font->y_scale < 0 ? -1 : +1;
+ 
+-    /* The description of the MathKern table is a ambiguous, but interpreting
+-     * "between the two heights found at those indexes" for 0 < i < len as
+-     *
+-     *   correctionHeight[i-1] < correction_height <= correctionHeight[i]
+-     *
+-     * makes the result consistent with the limit cases and we can just use the
+-     * binary search algorithm of std::upper_bound:
++    /* According to OpenType spec (v1.9), except for the boundary cases, the index
++     * chosen for kern value should be i such that
++     *    correctionHeight[i-1] <= correction_height < correctionHeight[i]
++     * We can use the binary search algorithm of std::upper_bound(). Or, we can
++     * use the internal hb_bsearch_impl.
+      */
+-    unsigned int i = 0;
+-    unsigned int count = heightCount;
+-    while (count > 0)
+-    {
+-      unsigned int half = count / 2;
+-      hb_position_t height = correctionHeight[i + half].get_y_value (font, this);
+-      if (sign * height < sign * correction_height)
+-      {
+-        i += half + 1;
+-        count -= half + 1;
+-      } else
+-        count = half;
+-    }
++    unsigned int pos;
++    auto cmp = +[](const void* key, const void* p,
++                   int sign, hb_font_t* font, const MathKern* mathKern) -> int {
++      return sign * *(hb_position_t*)key - sign * ((MathValueRecord*)p)->get_y_value(font, mathKern);
++    };
++    unsigned int i = hb_bsearch_impl(&pos, correction_height, correctionHeight,
++                                     heightCount, MathValueRecord::static_size,
++                                     cmp, sign, font, this) ? pos + 1 : pos;
+     return kernValue[i].get_x_value (font, this);
+   }
+ 
+@@ -984,6 +978,7 @@ struct MathVariants
+     return_trace (c->check_struct (this) &&
+                   vertGlyphCoverage.sanitize (c, this) &&
+                   horizGlyphCoverage.sanitize (c, this) &&
++                  hb_barrier () &&
+                   c->check_array (glyphConstruction.arrayZ, vertGlyphCount + horizGlyphCount) &&
+                   sanitize_offsets (c));
+   }
+@@ -1103,6 +1098,7 @@ struct MATH
+     TRACE_SANITIZE (this);
+     return_trace (version.sanitize (c) &&
+                   likely (version.major == 1) &&
++                  hb_barrier () &&
+                   mathConstants.sanitize (c, this) &&
+                   mathGlyphInfo.sanitize (c, this) &&
+                   mathVariants.sanitize (c, this));
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-maxp-table.hh b/src/java.desktop/share/native/libharfbuzz/hb-ot-maxp-table.hh
+index f7f2e860e..f6eeda40e 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-maxp-table.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-maxp-table.hh
+@@ -85,7 +85,7 @@ struct maxp
+     TRACE_SANITIZE (this);
+     if (unlikely (!c->check_struct (this)))
+       return_trace (false);
+-
++    hb_barrier ();
+     if (version.major == 1)
+     {
+       const maxpV1Tail &v1 = StructAfter (*this);
+@@ -103,6 +103,7 @@ struct maxp
+     maxp_prime->numGlyphs = hb_min (c->plan->num_output_glyphs (), 0xFFFFu);
+     if (maxp_prime->version.major == 1)
+     {
++      hb_barrier ();
+       const maxpV1Tail *src_v1 = &StructAfter (*this);
+       maxpV1Tail *dest_v1 = c->serializer->embed (src_v1);
+       if (unlikely (!dest_v1)) return_trace (false);
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-meta-table.hh b/src/java.desktop/share/native/libharfbuzz/hb-ot-meta-table.hh
+index 1f0118828..20c62b83e 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-meta-table.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-meta-table.hh
+@@ -51,6 +51,7 @@ struct DataMap
+   {
+     TRACE_SANITIZE (this);
+     return_trace (likely (c->check_struct (this) &&
++                          hb_barrier () &&
+                           dataZ.sanitize (c, base, dataLength)));
+   }
+ 
+@@ -101,6 +102,7 @@ struct meta
+   {
+     TRACE_SANITIZE (this);
+     return_trace (likely (c->check_struct (this) &&
++                          hb_barrier () &&
+                           version == 1 &&
+                           dataMaps.sanitize (c, this)));
+   }
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-os2-table.hh b/src/java.desktop/share/native/libharfbuzz/hb-ot-os2-table.hh
+index 30ae335d7..24e9c9703 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-os2-table.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-os2-table.hh
+@@ -209,6 +209,23 @@ struct OS2
+     return ret;
+   }
+ 
++  static unsigned calc_avg_char_width (const hb_hashmap_t>& hmtx_map)
++  {
++    unsigned num = 0;
++    unsigned total_width = 0;
++    for (const auto& _ : hmtx_map.values_ref ())
++    {
++      unsigned width = _.first;
++      if (width)
++      {
++        total_width += width;
++        num++;
++      }
++    }
++
++    return num ? (unsigned) roundf ((double) total_width / (double) num) : 0;
++  }
++
+   bool subset (hb_subset_context_t *c) const
+   {
+     TRACE_SUBSET (this);
+@@ -239,17 +256,23 @@ struct OS2
+ 
+       if (os2_prime->version >= 2)
+       {
++        hb_barrier ();
+         auto *table = & const_cast (os2_prime->v2 ());
+         HB_ADD_MVAR_VAR (HB_OT_METRICS_TAG_X_HEIGHT,                   sxHeight);
+         HB_ADD_MVAR_VAR (HB_OT_METRICS_TAG_CAP_HEIGHT,                 sCapHeight);
+       }
++
++      unsigned avg_char_width = calc_avg_char_width (c->plan->hmtx_map);
++      if (!c->serializer->check_assign (os2_prime->xAvgCharWidth, avg_char_width,
++                                        HB_SERIALIZE_ERROR_INT_OVERFLOW))
++        return_trace (false);
+     }
+ #endif
+ 
+     Triple *axis_range;
+     if (c->plan->user_axes_location.has (HB_TAG ('w','g','h','t'), &axis_range))
+     {
+-      unsigned weight_class = static_cast (roundf (hb_clamp (axis_range->middle, 1.0f, 1000.0f)));
++      unsigned weight_class = static_cast (roundf (hb_clamp (axis_range->middle, 1.0, 1000.0)));
+       if (os2_prime->usWeightClass != weight_class)
+         os2_prime->usWeightClass = weight_class;
+     }
+@@ -261,12 +284,12 @@ struct OS2
+         os2_prime->usWidthClass = width_class;
+     }
+ 
++    os2_prime->usFirstCharIndex = hb_min (0xFFFFu, c->plan->os2_info.min_cmap_codepoint);
++    os2_prime->usLastCharIndex  = hb_min (0xFFFFu, c->plan->os2_info.max_cmap_codepoint);
++
+     if (c->plan->flags & HB_SUBSET_FLAGS_NO_PRUNE_UNICODE_RANGES)
+       return_trace (true);
+ 
+-    os2_prime->usFirstCharIndex = hb_min (0xFFFFu, c->plan->unicodes.get_min ());
+-    os2_prime->usLastCharIndex  = hb_min (0xFFFFu, c->plan->unicodes.get_max ());
+-
+     _update_unicode_ranges (&c->plan->unicodes, os2_prime->ulUnicodeRange);
+ 
+     return_trace (true);
+@@ -334,6 +357,7 @@ struct OS2
+   {
+     TRACE_SANITIZE (this);
+     if (unlikely (!c->check_struct (this))) return_trace (false);
++    hb_barrier ();
+     if (unlikely (version >= 1 && !v1X.sanitize (c))) return_trace (false);
+     if (unlikely (version >= 2 && !v2X.sanitize (c))) return_trace (false);
+     if (unlikely (version >= 5 && !v5X.sanitize (c))) return_trace (false);
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-post-table-v2subset.hh b/src/java.desktop/share/native/libharfbuzz/hb-ot-post-table-v2subset.hh
+index d44233610..67d1b6aa7 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-post-table-v2subset.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-post-table-v2subset.hh
+@@ -84,9 +84,9 @@ HB_INTERNAL bool postV2Tail::subset (hb_subset_context_t *c) const
+   old_gid_new_index_map.alloc (num_glyphs);
+   glyph_name_to_new_index.alloc (num_glyphs);
+ 
+-  for (hb_codepoint_t new_gid = 0; new_gid < num_glyphs; new_gid++)
++  for (auto _ : c->plan->new_to_old_gid_list)
+   {
+-    hb_codepoint_t old_gid = reverse_glyph_map.get (new_gid);
++    hb_codepoint_t old_gid = _.second;
+     unsigned old_index = glyphNameIndex[old_gid];
+ 
+     unsigned new_index;
+@@ -125,13 +125,22 @@ HB_INTERNAL bool postV2Tail::subset (hb_subset_context_t *c) const
+     old_gid_new_index_map.set (old_gid, new_index);
+   }
+ 
++  if (old_gid_new_index_map.in_error())
++    return_trace (false);
++
+   auto index_iter =
+   + hb_range (num_glyphs)
+-  | hb_map (reverse_glyph_map)
+-  | hb_map_retains_sorting ([&](hb_codepoint_t old_gid)
++  | hb_map_retains_sorting ([&](hb_codepoint_t new_gid)
+                             {
+-                              unsigned new_index = old_gid_new_index_map.get (old_gid);
+-                              return hb_pair_t (old_gid, new_index);
++                              hb_codepoint_t *old_gid;
++                              /* use 0 for retain-gid holes, which refers to the name .notdef,
++                               * as the glyphNameIndex entry for that glyph ID."*/
++                              unsigned new_index = 0;
++                              if (reverse_glyph_map.has (new_gid, &old_gid)) {
++                                new_index = old_gid_new_index_map.get (*old_gid);
++                                return hb_pair_t (*old_gid, new_index);
++                              }
++                              return hb_pair_t (new_gid, new_index);
+                             })
+   ;
+ 
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-post-table.hh b/src/java.desktop/share/native/libharfbuzz/hb-ot-post-table.hh
+index d41c86f8b..83d310e16 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-post-table.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-post-table.hh
+@@ -116,13 +116,16 @@ struct post
+     Triple *axis_range;
+     if (c->plan->user_axes_location.has (HB_TAG ('s','l','n','t'), &axis_range))
+     {
+-      float italic_angle = hb_max (-90.f, hb_min (axis_range->middle, 90.f));
++      float italic_angle = hb_max (-90.0, hb_min (axis_range->middle, 90.0));
+       if (post_prime->italicAngle.to_float () != italic_angle)
+         post_prime->italicAngle.set_float (italic_angle);
+     }
+ 
+     if (glyph_names && version.major == 2)
++    {
++      hb_barrier ();
+       return_trace (v2X.subset (c));
++    }
+ 
+     return_trace (true);
+   }
+@@ -138,6 +141,7 @@ struct post
+ 
+       version = table->version.to_int ();
+       if (version != 0x00020000) return;
++      hb_barrier ();
+ 
+       const postV2Tail &v2 = table->v2X;
+ 
+@@ -217,10 +221,16 @@ struct post
+     unsigned int get_glyph_count () const
+     {
+       if (version == 0x00010000)
++      {
++        hb_barrier ();
+         return format1_names_length;
++      }
+ 
+       if (version == 0x00020000)
++      {
++        hb_barrier ();
+         return glyphNameIndex->len;
++      }
+ 
+       return 0;
+     }
+@@ -245,13 +255,18 @@ struct post
+     {
+       if (version == 0x00010000)
+       {
++        hb_barrier ();
+         if (glyph >= format1_names_length)
+           return hb_bytes_t ();
+ 
+         return format1_names (glyph);
+       }
+ 
+-      if (version != 0x00020000 || glyph >= glyphNameIndex->len)
++      if (version != 0x00020000)
++        return hb_bytes_t ();
++      hb_barrier ();
++
++      if (glyph >= glyphNameIndex->len)
+         return hb_bytes_t ();
+ 
+       unsigned int index = glyphNameIndex->arrayZ[glyph];
+@@ -284,8 +299,9 @@ struct post
+   {
+     TRACE_SANITIZE (this);
+     return_trace (c->check_struct (this) &&
++                  hb_barrier () &&
+                   (version.to_int () == 0x00010000 ||
+-                   (version.to_int () == 0x00020000 && v2X.sanitize (c)) ||
++                   (version.to_int () == 0x00020000 && hb_barrier () && v2X.sanitize (c)) ||
+                    version.to_int () == 0x00030000));
+   }
+ 
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-shape-normalize.cc b/src/java.desktop/share/native/libharfbuzz/hb-ot-shape-normalize.cc
+index b1acc7e7d..cb941bc7f 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-shape-normalize.cc
++++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-shape-normalize.cc
+@@ -74,23 +74,6 @@
+  *     Indic shaper may want to disallow recomposing of two matras.
+  */
+ 
+-static bool
+-decompose_unicode (const hb_ot_shape_normalize_context_t *c,
+-                   hb_codepoint_t  ab,
+-                   hb_codepoint_t *a,
+-                   hb_codepoint_t *b)
+-{
+-  return (bool) c->unicode->decompose (ab, a, b);
+-}
+-
+-static bool
+-compose_unicode (const hb_ot_shape_normalize_context_t *c,
+-                 hb_codepoint_t  a,
+-                 hb_codepoint_t  b,
+-                 hb_codepoint_t *ab)
+-{
+-  return (bool) c->unicode->compose (a, b, ab);
+-}
+ 
+ static inline void
+ set_glyph (hb_glyph_info_t &info, hb_font_t *font)
+@@ -170,7 +153,7 @@ decompose_current_character (const hb_ot_shape_normalize_context_t *c, bool shor
+   hb_codepoint_t u = buffer->cur().codepoint;
+   hb_codepoint_t glyph = 0;
+ 
+-  if (shortest && c->font->get_nominal_glyph (u, &glyph, c->not_found))
++  if (shortest && c->font->get_nominal_glyph (u, &glyph, buffer->not_found))
+   {
+     next_char (buffer, glyph);
+     return;
+@@ -182,7 +165,7 @@ decompose_current_character (const hb_ot_shape_normalize_context_t *c, bool shor
+     return;
+   }
+ 
+-  if (!shortest && c->font->get_nominal_glyph (u, &glyph, c->not_found))
++  if (!shortest && c->font->get_nominal_glyph (u, &glyph, buffer->not_found))
+   {
+     next_char (buffer, glyph);
+     return;
+@@ -237,6 +220,12 @@ handle_variation_selector_cluster (const hb_ot_shape_normalize_context_t *c,
+         /* Just pass on the two characters separately, let GSUB do its magic. */
+         set_glyph (buffer->cur(), font);
+         (void) buffer->next_glyph ();
++
++        buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_VARIATION_SELECTOR_FALLBACK;
++        _hb_glyph_info_set_variation_selector (&buffer->cur(), true);
++        if (buffer->not_found_variation_selector != HB_CODEPOINT_INVALID)
++          _hb_glyph_info_clear_default_ignorable (&buffer->cur());
++
+         set_glyph (buffer->cur(), font);
+         (void) buffer->next_glyph ();
+       }
+@@ -307,15 +296,15 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan,
+       mode = HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS;
+   }
+ 
+-  const hb_ot_shape_normalize_context_t c = {
++  hb_ot_shape_normalize_context_t c = {
+     plan,
+     buffer,
+     font,
+     buffer->unicode,
+-    buffer->not_found,
+-    plan->shaper->decompose ? plan->shaper->decompose : decompose_unicode,
+-    plan->shaper->compose   ? plan->shaper->compose   : compose_unicode
++    plan->shaper->decompose ? plan->shaper->decompose : hb_ot_shape_normalize_context_t::decompose_unicode,
++    plan->shaper->compose   ? plan->shaper->compose   : hb_ot_shape_normalize_context_t::compose_unicode
+   };
++  c.override_decompose_and_compose (plan->shaper->decompose, plan->shaper->compose);
+ 
+   bool always_short_circuit = mode == HB_OT_SHAPE_NORMALIZATION_MODE_NONE;
+   bool might_short_circuit = always_short_circuit ||
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-shape-normalize.hh b/src/java.desktop/share/native/libharfbuzz/hb-ot-shape-normalize.hh
+index afd62dd40..9f17bdbb2 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-shape-normalize.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-shape-normalize.hh
+@@ -28,6 +28,7 @@
+ #define HB_OT_SHAPE_NORMALIZE_HH
+ 
+ #include "hb.hh"
++#include "hb-unicode.hh"
+ 
+ 
+ /* buffer var allocations, used during the normalization process */
+@@ -52,11 +53,42 @@ HB_INTERNAL void _hb_ot_shape_normalize (const hb_ot_shape_plan_t *shaper,
+ 
+ struct hb_ot_shape_normalize_context_t
+ {
++  static bool
++  decompose_unicode (const hb_ot_shape_normalize_context_t *c,
++                     hb_codepoint_t  ab,
++                     hb_codepoint_t *a,
++                     hb_codepoint_t *b)
++  {
++    return (bool) c->unicode->decompose (ab, a, b);
++  }
++
++  static bool
++  compose_unicode (const hb_ot_shape_normalize_context_t *c,
++                   hb_codepoint_t  a,
++                   hb_codepoint_t  b,
++                   hb_codepoint_t *ab)
++  {
++    return (bool) c->unicode->compose (a, b, ab);
++  }
++
++  void
++  override_decompose_and_compose (bool (*decompose) (const hb_ot_shape_normalize_context_t *c,
++                                                      hb_codepoint_t  ab,
++                                                      hb_codepoint_t *a,
++                                                      hb_codepoint_t *b),
++                                  bool (*compose) (const hb_ot_shape_normalize_context_t *c,
++                                                   hb_codepoint_t  a,
++                                                   hb_codepoint_t  b,
++                                                   hb_codepoint_t *ab))
++  {
++    this->decompose = decompose ? decompose : decompose_unicode;
++    this->compose = compose ? compose : compose_unicode;
++  }
++
+   const hb_ot_shape_plan_t *plan;
+   hb_buffer_t *buffer;
+   hb_font_t *font;
+   hb_unicode_funcs_t *unicode;
+-  const hb_codepoint_t not_found;
+   bool (*decompose) (const hb_ot_shape_normalize_context_t *c,
+                      hb_codepoint_t  ab,
+                      hb_codepoint_t *a,
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-shape.cc b/src/java.desktop/share/native/libharfbuzz/hb-ot-shape.cc
+index f936ac45f..6265f0eb1 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-shape.cc
++++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-shape.cc
+@@ -46,6 +46,8 @@
+ #include "hb-set.hh"
+ 
+ #include "hb-aat-layout.hh"
++#include "hb-ot-stat-table.hh"
++
+ 
+ static inline bool
+ _hb_codepoint_is_regional_indicator (hb_codepoint_t u)
+@@ -85,7 +87,7 @@ hb_ot_shape_planner_t::hb_ot_shape_planner_t (hb_face_t                     *fac
+                                                 , apply_morx (_hb_apply_morx (face, props))
+ #endif
+ {
+-  shaper = hb_ot_shaper_categorize (this);
++  shaper = hb_ot_shaper_categorize (props.script, props.direction, map.chosen_script[0]);
+ 
+   script_zero_marks = shaper->zero_width_marks != HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE;
+   script_fallback_mark_positioning = shaper->fallback_position;
+@@ -121,10 +123,6 @@ hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t           &plan,
+   plan.kern_mask = plan.map.get_mask (kern_tag);
+   plan.requested_kerning = !!plan.kern_mask;
+ #endif
+-#ifndef HB_NO_AAT_SHAPE
+-  plan.trak_mask = plan.map.get_mask (HB_TAG ('t','r','a','k'));
+-  plan.requested_tracking = !!plan.trak_mask;
+-#endif
+ 
+   bool has_gpos_kern = plan.map.get_feature_index (1, kern_tag) != HB_OT_LAYOUT_NO_FEATURE_INDEX;
+   bool disable_gpos = plan.shaper->gpos_tag &&
+@@ -155,7 +153,7 @@ hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t           &plan,
+ #endif
+   bool has_gpos = !disable_gpos && hb_ot_layout_has_positioning (face);
+   if (false)
+-    ;
++    {}
+ #ifndef HB_NO_AAT_SHAPE
+   /* Prefer GPOS over kerx if GSUB is present;
+    * https://github.com/harfbuzz/harfbuzz/issues/3008 */
+@@ -167,15 +165,16 @@ hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t           &plan,
+ 
+   if (!plan.apply_kerx && (!has_gpos_kern || !plan.apply_gpos))
+   {
++    if (false) {}
+ #ifndef HB_NO_AAT_SHAPE
+-    if (has_kerx)
++    else if (has_kerx)
+       plan.apply_kerx = true;
+-    else
+ #endif
+ #ifndef HB_NO_OT_KERN
+-    if (hb_ot_layout_has_kerning (face))
++    else if (hb_ot_layout_has_kerning (face))
+       plan.apply_kern = true;
+ #endif
++    else {}
+   }
+ 
+   plan.apply_fallback_kern = !(plan.apply_gpos || plan.apply_kerx || plan.apply_kern);
+@@ -206,9 +205,6 @@ hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t           &plan,
+      https://github.com/harfbuzz/harfbuzz/issues/2967. */
+   if (plan.apply_morx)
+     plan.adjust_mark_positioning_when_zeroing = false;
+-
+-  /* Currently we always apply trak. */
+-  plan.apply_trak = plan.requested_tracking && hb_aat_layout_has_tracking (face);
+ #endif
+ }
+ 
+@@ -273,11 +269,6 @@ hb_ot_shape_plan_t::position (hb_font_t   *font,
+ #endif
+   else if (this->apply_fallback_kern)
+     _hb_ot_shape_fallback_kern (this, font, buffer);
+-
+-#ifndef HB_NO_AAT_SHAPE
+-  if (this->apply_trak)
+-    hb_aat_layout_track (this, font, buffer);
+-#endif
+ }
+ 
+ 
+@@ -345,13 +336,6 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner,
+   /* Random! */
+   map->enable_feature (HB_TAG ('r','a','n','d'), F_RANDOM, HB_OT_MAP_MAX_VALUE);
+ 
+-#ifndef HB_NO_AAT_SHAPE
+-  /* Tracking.  We enable dummy feature here just to allow disabling
+-   * AAT 'trak' table using features.
+-   * https://github.com/harfbuzz/harfbuzz/issues/1303 */
+-  map->enable_feature (HB_TAG ('t','r','a','k'), F_HAS_FALLBACK);
+-#endif
+-
+   map->enable_feature (HB_TAG ('H','a','r','f')); /* Considered required. */
+   map->enable_feature (HB_TAG ('H','A','R','F')); /* Considered discretionary. */
+ 
+@@ -836,6 +820,28 @@ hb_ot_zero_width_default_ignorables (const hb_buffer_t *buffer)
+       pos[i].x_advance = pos[i].y_advance = pos[i].x_offset = pos[i].y_offset = 0;
+ }
+ 
++static void
++hb_ot_deal_with_variation_selectors (hb_buffer_t *buffer)
++{
++  if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_VARIATION_SELECTOR_FALLBACK) ||
++        buffer->not_found_variation_selector == HB_CODEPOINT_INVALID)
++    return;
++
++  unsigned int count = buffer->len;
++  hb_glyph_info_t *info = buffer->info;
++  hb_glyph_position_t *pos = buffer->pos;
++
++  for (unsigned int i = 0; i < count; i++)
++  {
++    if (_hb_glyph_info_is_variation_selector (&info[i]))
++    {
++      info[i].codepoint = buffer->not_found_variation_selector;
++      pos[i].x_advance = pos[i].y_advance = pos[i].x_offset = pos[i].y_offset = 0;
++      _hb_glyph_info_set_variation_selector (&info[i], false);
++    }
++  }
++}
++
+ static void
+ hb_ot_hide_default_ignorables (hb_buffer_t *buffer,
+                                hb_font_t   *font)
+@@ -965,6 +971,7 @@ hb_ot_substitute_post (const hb_ot_shape_context_t *c)
+     hb_aat_layout_remove_deleted_glyphs (c->buffer);
+ #endif
+ 
++  hb_ot_deal_with_variation_selectors (c->buffer);
+   hb_ot_hide_default_ignorables (c->buffer, c->font);
+ 
+   if (c->plan->shaper->postprocess_glyphs &&
+@@ -1253,6 +1260,36 @@ hb_ot_shape_plan_collect_lookups (hb_shape_plan_t *shape_plan,
+ }
+ 
+ 
++/**
++ * hb_ot_shape_plan_get_feature_tags:
++ * @shape_plan: A shaping plan
++ * @start_offset: The index of first feature to retrieve
++ * @tag_count: (inout): Input = the maximum number of features to return;
++ *                      Output = the actual number of features returned (may be zero)
++ * @tags: (out) (array length=tag_count): The array of enabled feature
++ *
++ * Fetches the list of OpenType feature tags enabled for a shaping plan, if possible.
++ *
++ * Return value: Total number of feature tagss.
++ *
++ * Since: 10.3.0
++ */
++unsigned int
++hb_ot_shape_plan_get_feature_tags (hb_shape_plan_t *shape_plan,
++                                   unsigned int     start_offset,
++                                   unsigned int    *tag_count, /* IN/OUT */
++                                   hb_tag_t        *tags /* OUT */)
++{
++#ifndef HB_NO_OT_SHAPE
++  return shape_plan->ot.map.get_feature_tags (start_offset, tag_count, tags);
++#else
++  if (tag_count)
++        *tag_count = 0;
++  return 0;
++#endif
++}
++
++
+ /* TODO Move this to hb-ot-shape-normalize, make it do decompose, and make it public. */
+ static void
+ add_char (hb_font_t          *font,
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-shape.h b/src/java.desktop/share/native/libharfbuzz/hb-ot-shape.h
+index 545e2c3f1..1732831b1 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-shape.h
++++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-shape.h
+@@ -48,6 +48,12 @@ hb_ot_shape_plan_collect_lookups (hb_shape_plan_t *shape_plan,
+                                   hb_tag_t         table_tag,
+                                   hb_set_t        *lookup_indexes /* OUT */);
+ 
++HB_EXTERN unsigned int
++hb_ot_shape_plan_get_feature_tags (hb_shape_plan_t *shape_plan,
++                                   unsigned int     start_offset,
++                                   unsigned int    *tag_count, /* IN/OUT */
++                                   hb_tag_t        *tags /* OUT */);
++
+ HB_END_DECLS
+ 
+ #endif /* HB_OT_SHAPE_H */
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-shape.hh b/src/java.desktop/share/native/libharfbuzz/hb-ot-shape.hh
+index 2fa121ced..d5ee82d4c 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-shape.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-shape.hh
+@@ -51,7 +51,8 @@ struct hb_ot_shape_plan_key_t
+ 
+   bool equal (const hb_ot_shape_plan_key_t *other)
+   {
+-    return 0 == hb_memcmp (this, other, sizeof (*this));
++    return variations_index[0] == other->variations_index[0] &&
++           variations_index[1] == other->variations_index[1];
+   }
+ };
+ 
+@@ -79,22 +80,12 @@ struct hb_ot_shape_plan_t
+ #else
+   static constexpr hb_mask_t kern_mask = 0;
+ #endif
+-#ifndef HB_NO_AAT_SHAPE
+-  hb_mask_t trak_mask;
+-#else
+-  static constexpr hb_mask_t trak_mask = 0;
+-#endif
+ 
+ #ifndef HB_NO_OT_KERN
+   bool requested_kerning : 1;
+ #else
+   static constexpr bool requested_kerning = false;
+ #endif
+-#ifndef HB_NO_AAT_SHAPE
+-  bool requested_tracking : 1;
+-#else
+-  static constexpr bool requested_tracking = false;
+-#endif
+ #ifndef HB_NO_OT_SHAPE_FRACTIONS
+   bool has_frac : 1;
+ #else
+@@ -117,11 +108,9 @@ struct hb_ot_shape_plan_t
+ #ifndef HB_NO_AAT_SHAPE
+   bool apply_kerx : 1;
+   bool apply_morx : 1;
+-  bool apply_trak : 1;
+ #else
+   static constexpr bool apply_kerx = false;
+   static constexpr bool apply_morx = false;
+-  static constexpr bool apply_trak = false;
+ #endif
+ 
+   void collect_lookups (hb_tag_t table_tag, hb_set_t *lookups) const
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-arabic-fallback.hh b/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-arabic-fallback.hh
+index 858a98727..ff0b2aced 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-arabic-fallback.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-arabic-fallback.hh
+@@ -355,6 +355,8 @@ arabic_fallback_plan_destroy (arabic_fallback_plan_t *fallback_plan)
+   for (unsigned int i = 0; i < fallback_plan->num_lookups; i++)
+     if (fallback_plan->lookup_array[i])
+     {
++      if (fallback_plan->accel_array[i])
++        fallback_plan->accel_array[i]->fini ();
+       hb_free (fallback_plan->accel_array[i]);
+       if (fallback_plan->free_lookups)
+         hb_free (fallback_plan->lookup_array[i]);
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-arabic-joining-list.hh b/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-arabic-joining-list.hh
+index a5a7b84af..e38686e3e 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-arabic-joining-list.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-arabic-joining-list.hh
+@@ -6,10 +6,10 @@
+  *
+  * on files with these headers:
+  *
+- * # ArabicShaping-15.1.0.txt
+- * # Date: 2023-01-05
+- * # Scripts-15.1.0.txt
+- * # Date: 2023-07-28, 16:01:07 GMT
++ * # ArabicShaping-16.0.0.txt
++ * # Date: 2024-07-30
++ * # Scripts-16.0.0.txt
++ * # Date: 2024-04-30, 21:48:40 GMT
+  */
+ 
+ #ifndef HB_OT_SHAPER_ARABIC_JOINING_LIST_HH
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-arabic-table.hh b/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-arabic-table.hh
+index 8c2504438..19bd72d42 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-arabic-table.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-arabic-table.hh
+@@ -6,10 +6,10 @@
+  *
+  * on files with these headers:
+  *
+- * # ArabicShaping-15.1.0.txt
+- * # Date: 2023-01-05
+- * # Blocks-15.1.0.txt
+- * # Date: 2023-07-28, 15:47:20 GMT
++ * # ArabicShaping-16.0.0.txt
++ * # Date: 2024-07-30
++ * # Blocks-16.0.0.txt
++ * # Date: 2024-02-02
+  * UnicodeData.txt does not have a header.
+  */
+ 
+@@ -136,7 +136,13 @@ static const uint8_t joining_table[] =
+   /* 10D00 */ L,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,
+   /* 10D20 */ D,D,R,D,
+ 
+-#define joining_offset_0x10f30u 1182
++#define joining_offset_0x10ec2u 1182
++
++  /* Arabic Extended-C */
++
++  /* 10EC0 */     R,D,D,
++
++#define joining_offset_0x10f30u 1185
+ 
+   /* Sogdian */
+ 
+@@ -155,14 +161,14 @@ static const uint8_t joining_table[] =
+   /* 10FA0 */                                 D,U,D,D,R,R,R,U,D,R,R,D,D,R,D,D,
+   /* 10FC0 */ U,D,R,R,D,U,U,U,U,R,D,L,
+ 
+-#define joining_offset_0x110bdu 1338
++#define joining_offset_0x110bdu 1341
+ 
+   /* Kaithi */
+ 
+   /* 110A0 */                                                           U,X,X,
+   /* 110C0 */ X,X,X,X,X,X,X,X,X,X,X,X,X,U,
+ 
+-#define joining_offset_0x1e900u 1355
++#define joining_offset_0x1e900u 1358
+ 
+   /* Adlam */
+ 
+@@ -170,7 +176,7 @@ static const uint8_t joining_table[] =
+   /* 1E920 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,
+   /* 1E940 */ D,D,D,D,X,X,X,X,X,X,X,T,
+ 
+-}; /* Table items: 1431; occupancy: 57% */
++}; /* Table items: 1434; occupancy: 57% */
+ 
+ 
+ static unsigned int
+@@ -198,6 +204,7 @@ joining_type (hb_codepoint_t u)
+       if (hb_in_range (u, 0x10AC0u, 0x10AEFu)) return joining_table[u - 0x10AC0u + joining_offset_0x10ac0u];
+       if (hb_in_range (u, 0x10B80u, 0x10BAFu)) return joining_table[u - 0x10B80u + joining_offset_0x10b80u];
+       if (hb_in_range (u, 0x10D00u, 0x10D23u)) return joining_table[u - 0x10D00u + joining_offset_0x10d00u];
++      if (hb_in_range (u, 0x10EC2u, 0x10EC4u)) return joining_table[u - 0x10EC2u + joining_offset_0x10ec2u];
+       if (hb_in_range (u, 0x10F30u, 0x10FCBu)) return joining_table[u - 0x10F30u + joining_offset_0x10f30u];
+       break;
+ 
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-arabic.cc b/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-arabic.cc
+index 87d76e1a1..67db6cb26 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-arabic.cc
++++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-arabic.cc
+@@ -233,10 +233,7 @@ collect_features_arabic (hb_ot_shape_planner_t *plan)
+    map->enable_feature (HB_TAG('c','a','l','t'), F_MANUAL_ZWJ);
+    /* https://github.com/harfbuzz/harfbuzz/issues/1573 */
+    if (!map->has_feature (HB_TAG('r','c','l','t')))
+-   {
+      map->add_gsub_pause (nullptr);
+-     map->enable_feature (HB_TAG('r','c','l','t'), F_MANUAL_ZWJ);
+-   }
+ 
+    map->enable_feature (HB_TAG('l','i','g','a'), F_MANUAL_ZWJ);
+    map->enable_feature (HB_TAG('c','l','i','g'), F_MANUAL_ZWJ);
+@@ -560,9 +557,9 @@ apply_stch (const hb_ot_shape_plan_t *plan HB_UNUSED,
+ 
+       DEBUG_MSG (ARABIC, nullptr, "%s stretch at (%u,%u,%u)",
+                  step == MEASURE ? "measuring" : "cutting", context, start, end);
+-      DEBUG_MSG (ARABIC, nullptr, "rest of word:    count=%u width %d", start - context, w_total);
+-      DEBUG_MSG (ARABIC, nullptr, "fixed tiles:     count=%d width=%d", n_fixed, w_fixed);
+-      DEBUG_MSG (ARABIC, nullptr, "repeating tiles: count=%d width=%d", n_repeating, w_repeating);
++      DEBUG_MSG (ARABIC, nullptr, "rest of word:    count=%u width %" PRId32, start - context, w_total);
++      DEBUG_MSG (ARABIC, nullptr, "fixed tiles:     count=%d width=%" PRId32, n_fixed, w_fixed);
++      DEBUG_MSG (ARABIC, nullptr, "repeating tiles: count=%d width=%" PRId32, n_repeating, w_repeating);
+ 
+       /* Number of additional times to repeat each repeating tile. */
+       int n_copies = 0;
+@@ -602,7 +599,7 @@ apply_stch (const hb_ot_shape_plan_t *plan HB_UNUSED,
+           if (info[k - 1].arabic_shaping_action() == STCH_REPEATING)
+             repeat += n_copies;
+ 
+-          DEBUG_MSG (ARABIC, nullptr, "appending %u copies of glyph %u; j=%u",
++          DEBUG_MSG (ARABIC, nullptr, "appending %u copies of glyph %" PRIu32 "; j=%u",
+                      repeat, info[k - 1].codepoint, j);
+           pos[k - 1].x_advance = 0;
+           for (unsigned int n = 0; n < repeat; n++)
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-hebrew.cc b/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-hebrew.cc
+index bb9950d02..0ad1cea95 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-hebrew.cc
++++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-hebrew.cc
+@@ -78,7 +78,7 @@ compose_hebrew (const hb_ot_shape_normalize_context_t *c,
+   return found;
+ #endif
+ 
+-  if (!found && !c->plan->has_gpos_mark)
++  if (!found && (c->plan && !c->plan->has_gpos_mark))
+   {
+       /* Special-case Hebrew presentation forms that are excluded from
+        * standard normalization, but wanted for old fonts. */
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-indic-machine.hh b/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-indic-machine.hh
+index 6a6db4484..25e6d85ef 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-indic-machine.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-indic-machine.hh
+@@ -68,6 +68,7 @@ enum indic_syllable_type_t {
+ #define indic_syllable_machine_ex_Ra 15u
+ #define indic_syllable_machine_ex_Repha 14u
+ #define indic_syllable_machine_ex_SM 8u
++#define indic_syllable_machine_ex_SMPst 57u
+ #define indic_syllable_machine_ex_Symbol 17u
+ #define indic_syllable_machine_ex_V 2u
+ #define indic_syllable_machine_ex_VD 9u
+@@ -76,251 +77,916 @@ enum indic_syllable_type_t {
+ #define indic_syllable_machine_ex_ZWNJ 5u
+ 
+ 
+-#line 80 "hb-ot-shaper-indic-machine.hh"
++#line 81 "hb-ot-shaper-indic-machine.hh"
+ static const unsigned char _indic_syllable_machine_trans_keys[] = {
+-        8u, 8u, 4u, 13u, 5u, 13u, 5u, 13u, 13u, 13u, 4u, 13u, 4u, 13u, 4u, 13u,
+-        8u, 8u, 5u, 13u, 5u, 13u, 13u, 13u, 4u, 13u, 4u, 13u, 4u, 13u, 4u, 13u,
+-        8u, 8u, 5u, 13u, 5u, 13u, 13u, 13u, 4u, 13u, 4u, 13u, 4u, 13u, 8u, 8u,
+-        5u, 13u, 5u, 13u, 13u, 13u, 4u, 13u, 4u, 13u, 5u, 13u, 8u, 8u, 1u, 18u,
+-        3u, 16u, 3u, 16u, 4u, 16u, 1u, 15u, 5u, 9u, 5u, 9u, 9u, 9u, 5u, 9u,
+-        1u, 15u, 1u, 15u, 1u, 15u, 3u, 13u, 4u, 13u, 5u, 13u, 5u, 13u, 4u, 13u,
+-        5u, 9u, 3u, 9u, 5u, 9u, 3u, 16u, 3u, 16u, 3u, 16u, 3u, 16u, 4u, 16u,
+-        1u, 15u, 3u, 16u, 3u, 16u, 4u, 16u, 1u, 15u, 5u, 9u, 9u, 9u, 5u, 9u,
+-        1u, 15u, 1u, 15u, 3u, 13u, 4u, 13u, 5u, 13u, 5u, 13u, 4u, 13u, 5u, 9u,
+-        5u, 9u, 3u, 9u, 5u, 9u, 3u, 16u, 3u, 16u, 4u, 13u, 3u, 16u, 3u, 16u,
+-        4u, 16u, 1u, 15u, 3u, 16u, 1u, 15u, 5u, 9u, 9u, 9u, 5u, 9u, 1u, 15u,
+-        1u, 15u, 3u, 13u, 4u, 13u, 5u, 13u, 5u, 13u, 3u, 16u, 4u, 13u, 5u, 9u,
+-        5u, 9u, 3u, 9u, 5u, 9u, 3u, 16u, 4u, 13u, 4u, 13u, 3u, 16u, 3u, 16u,
+-        4u, 16u, 1u, 15u, 3u, 16u, 1u, 15u, 5u, 9u, 9u, 9u, 5u, 9u, 1u, 15u,
+-        1u, 15u, 3u, 13u, 4u, 13u, 5u, 13u, 5u, 13u, 3u, 16u, 4u, 13u, 5u, 9u,
+-        5u, 9u, 3u, 9u, 5u, 9u, 1u, 16u, 3u, 16u, 1u, 16u, 4u, 13u, 5u, 13u,
+-        5u, 13u, 9u, 9u, 5u, 9u, 1u, 15u, 3u, 9u, 5u, 9u, 5u, 9u, 9u, 9u,
++        8u, 57u, 4u, 57u, 5u, 57u, 5u, 57u, 13u, 13u, 4u, 57u, 4u, 57u, 4u, 57u,
++        8u, 57u, 5u, 57u, 5u, 57u, 13u, 13u, 4u, 57u, 4u, 57u, 4u, 57u, 4u, 57u,
++        8u, 57u, 5u, 57u, 5u, 57u, 13u, 13u, 4u, 57u, 4u, 57u, 4u, 57u, 8u, 57u,
++        5u, 57u, 5u, 57u, 13u, 13u, 4u, 57u, 4u, 57u, 5u, 57u, 8u, 57u, 1u, 57u,
++        3u, 57u, 3u, 57u, 4u, 57u, 1u, 57u, 5u, 57u, 5u, 57u, 9u, 9u, 5u, 9u,
++        1u, 57u, 1u, 57u, 1u, 57u, 3u, 57u, 4u, 57u, 5u, 57u, 5u, 57u, 4u, 57u,
++        5u, 57u, 3u, 57u, 5u, 57u, 3u, 57u, 3u, 57u, 3u, 57u, 3u, 57u, 4u, 57u,
++        1u, 57u, 3u, 57u, 3u, 57u, 4u, 57u, 1u, 57u, 5u, 57u, 9u, 9u, 5u, 9u,
++        1u, 57u, 1u, 57u, 3u, 57u, 4u, 57u, 5u, 57u, 5u, 57u, 4u, 57u, 5u, 57u,
++        5u, 57u, 3u, 57u, 5u, 57u, 3u, 57u, 3u, 57u, 4u, 57u, 3u, 57u, 3u, 57u,
++        4u, 57u, 1u, 57u, 3u, 57u, 1u, 57u, 5u, 57u, 9u, 9u, 5u, 9u, 1u, 57u,
++        1u, 57u, 3u, 57u, 4u, 57u, 5u, 57u, 5u, 57u, 3u, 57u, 4u, 57u, 5u, 57u,
++        5u, 57u, 3u, 57u, 5u, 57u, 3u, 57u, 4u, 57u, 4u, 57u, 3u, 57u, 3u, 57u,
++        4u, 57u, 1u, 57u, 3u, 57u, 1u, 57u, 5u, 57u, 9u, 9u, 5u, 9u, 1u, 57u,
++        1u, 57u, 3u, 57u, 4u, 57u, 5u, 57u, 5u, 57u, 3u, 57u, 4u, 57u, 5u, 57u,
++        5u, 57u, 3u, 57u, 5u, 57u, 1u, 57u, 3u, 57u, 1u, 57u, 4u, 57u, 5u, 57u,
++        5u, 57u, 9u, 9u, 5u, 9u, 1u, 57u, 3u, 57u, 5u, 57u, 5u, 57u, 9u, 9u,
+         5u, 9u, 1u, 15u, 0
+ };
+ 
+ static const char _indic_syllable_machine_key_spans[] = {
+-        1, 10, 9, 9, 1, 10, 10, 10,
+-        1, 9, 9, 1, 10, 10, 10, 10,
+-        1, 9, 9, 1, 10, 10, 10, 1,
+-        9, 9, 1, 10, 10, 9, 1, 18,
+-        14, 14, 13, 15, 5, 5, 1, 5,
+-        15, 15, 15, 11, 10, 9, 9, 10,
+-        5, 7, 5, 14, 14, 14, 14, 13,
+-        15, 14, 14, 13, 15, 5, 1, 5,
+-        15, 15, 11, 10, 9, 9, 10, 5,
+-        5, 7, 5, 14, 14, 10, 14, 14,
+-        13, 15, 14, 15, 5, 1, 5, 15,
+-        15, 11, 10, 9, 9, 14, 10, 5,
+-        5, 7, 5, 14, 10, 10, 14, 14,
+-        13, 15, 14, 15, 5, 1, 5, 15,
+-        15, 11, 10, 9, 9, 14, 10, 5,
+-        5, 7, 5, 16, 14, 16, 10, 9,
+-        9, 1, 5, 15, 7, 5, 5, 1,
++        50, 54, 53, 53, 1, 54, 54, 54,
++        50, 53, 53, 1, 54, 54, 54, 54,
++        50, 53, 53, 1, 54, 54, 54, 50,
++        53, 53, 1, 54, 54, 53, 50, 57,
++        55, 55, 54, 57, 53, 53, 1, 5,
++        57, 57, 57, 55, 54, 53, 53, 54,
++        53, 55, 53, 55, 55, 55, 55, 54,
++        57, 55, 55, 54, 57, 53, 1, 5,
++        57, 57, 55, 54, 53, 53, 54, 53,
++        53, 55, 53, 55, 55, 54, 55, 55,
++        54, 57, 55, 57, 53, 1, 5, 57,
++        57, 55, 54, 53, 53, 55, 54, 53,
++        53, 55, 53, 55, 54, 54, 55, 55,
++        54, 57, 55, 57, 53, 1, 5, 57,
++        57, 55, 54, 53, 53, 55, 54, 53,
++        53, 55, 53, 57, 55, 57, 54, 53,
++        53, 1, 5, 57, 55, 53, 53, 1,
+         5, 15
+ };
+ 
+ static const short _indic_syllable_machine_index_offsets[] = {
+-        0, 2, 13, 23, 33, 35, 46, 57,
+-        68, 70, 80, 90, 92, 103, 114, 125,
+-        136, 138, 148, 158, 160, 171, 182, 193,
+-        195, 205, 215, 217, 228, 239, 249, 251,
+-        270, 285, 300, 314, 330, 336, 342, 344,
+-        350, 366, 382, 398, 410, 421, 431, 441,
+-        452, 458, 466, 472, 487, 502, 517, 532,
+-        546, 562, 577, 592, 606, 622, 628, 630,
+-        636, 652, 668, 680, 691, 701, 711, 722,
+-        728, 734, 742, 748, 763, 778, 789, 804,
+-        819, 833, 849, 864, 880, 886, 888, 894,
+-        910, 926, 938, 949, 959, 969, 984, 995,
+-        1001, 1007, 1015, 1021, 1036, 1047, 1058, 1073,
+-        1088, 1102, 1118, 1133, 1149, 1155, 1157, 1163,
+-        1179, 1195, 1207, 1218, 1228, 1238, 1253, 1264,
+-        1270, 1276, 1284, 1290, 1307, 1322, 1339, 1350,
+-        1360, 1370, 1372, 1378, 1394, 1402, 1408, 1414,
+-        1416, 1422
++        0, 51, 106, 160, 214, 216, 271, 326,
++        381, 432, 486, 540, 542, 597, 652, 707,
++        762, 813, 867, 921, 923, 978, 1033, 1088,
++        1139, 1193, 1247, 1249, 1304, 1359, 1413, 1464,
++        1522, 1578, 1634, 1689, 1747, 1801, 1855, 1857,
++        1863, 1921, 1979, 2037, 2093, 2148, 2202, 2256,
++        2311, 2365, 2421, 2475, 2531, 2587, 2643, 2699,
++        2754, 2812, 2868, 2924, 2979, 3037, 3091, 3093,
++        3099, 3157, 3215, 3271, 3326, 3380, 3434, 3489,
++        3543, 3597, 3653, 3707, 3763, 3819, 3874, 3930,
++        3986, 4041, 4099, 4155, 4213, 4267, 4269, 4275,
++        4333, 4391, 4447, 4502, 4556, 4610, 4666, 4721,
++        4775, 4829, 4885, 4939, 4995, 5050, 5105, 5161,
++        5217, 5272, 5330, 5386, 5444, 5498, 5500, 5506,
++        5564, 5622, 5678, 5733, 5787, 5841, 5897, 5952,
++        6006, 6060, 6116, 6170, 6228, 6284, 6342, 6397,
++        6451, 6505, 6507, 6513, 6571, 6627, 6681, 6735,
++        6737, 6743
+ };
+ 
+ static const unsigned char _indic_syllable_machine_indicies[] = {
+-        1, 0, 2, 3, 3, 4, 5, 0,
+-        0, 0, 0, 4, 0, 3, 3, 4,
+-        6, 0, 0, 0, 0, 4, 0, 3,
+-        3, 4, 5, 0, 0, 0, 0, 4,
+-        0, 4, 0, 7, 3, 3, 4, 5,
+-        0, 0, 0, 0, 4, 0, 2, 3,
+-        3, 4, 5, 0, 0, 0, 8, 4,
+-        0, 10, 11, 11, 12, 13, 9, 9,
+-        9, 9, 12, 9, 14, 9, 11, 11,
+-        12, 15, 9, 9, 9, 9, 12, 9,
+-        11, 11, 12, 13, 9, 9, 9, 9,
+-        12, 9, 12, 9, 16, 11, 11, 12,
+-        13, 9, 9, 9, 9, 12, 9, 10,
+-        11, 11, 12, 13, 9, 9, 9, 17,
+-        12, 9, 10, 11, 11, 12, 13, 9,
+-        9, 9, 18, 12, 9, 20, 21, 21,
+-        22, 23, 19, 19, 19, 24, 22, 19,
+-        25, 19, 21, 21, 22, 27, 26, 26,
+-        26, 26, 22, 26, 21, 21, 22, 23,
+-        19, 19, 19, 19, 22, 19, 22, 26,
+-        20, 21, 21, 22, 23, 19, 19, 19,
+-        19, 22, 19, 28, 21, 21, 22, 23,
+-        19, 19, 19, 19, 22, 19, 30, 31,
+-        31, 32, 33, 29, 29, 29, 34, 32,
++        1, 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, 0, 0, 0, 0, 0, 0, 0,
++        0, 1, 0, 2, 3, 3, 4, 5,
++        0, 0, 0, 0, 4, 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, 0, 0, 0,
++        5, 0, 3, 3, 4, 6, 0, 0,
++        0, 0, 4, 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, 0, 0, 0, 6, 0,
++        3, 3, 4, 5, 0, 0, 0, 0,
++        4, 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, 0, 0, 0, 5, 0, 4, 0,
++        7, 3, 3, 4, 5, 0, 0, 0,
++        0, 4, 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, 0, 0, 0, 5, 0, 2,
++        3, 3, 4, 5, 0, 0, 0, 8,
++        4, 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, 0, 0, 0, 5, 0, 10, 11,
++        11, 12, 13, 9, 9, 9, 9, 12,
++        9, 9, 9, 9, 9, 9, 9, 9,
++        9, 9, 9, 9, 9, 9, 9, 9,
++        9, 9, 9, 9, 9, 9, 9, 9,
++        9, 9, 9, 9, 9, 9, 9, 9,
++        9, 9, 9, 9, 9, 9, 9, 9,
++        9, 9, 9, 13, 9, 14, 9, 9,
++        9, 9, 9, 9, 9, 9, 9, 9,
++        9, 9, 9, 9, 9, 9, 9, 9,
++        9, 9, 9, 9, 9, 9, 9, 9,
++        9, 9, 9, 9, 9, 9, 9, 9,
++        9, 9, 9, 9, 9, 9, 9, 9,
++        9, 9, 9, 9, 9, 9, 14, 9,
++        11, 11, 12, 15, 9, 9, 9, 9,
++        12, 9, 9, 9, 9, 9, 9, 9,
++        9, 9, 9, 9, 9, 9, 9, 9,
++        9, 9, 9, 9, 9, 9, 9, 9,
++        9, 9, 9, 9, 9, 9, 9, 9,
++        9, 9, 9, 9, 9, 9, 9, 9,
++        9, 9, 9, 9, 15, 9, 11, 11,
++        12, 13, 9, 9, 9, 9, 12, 9,
++        9, 9, 9, 9, 9, 9, 9, 9,
++        9, 9, 9, 9, 9, 9, 9, 9,
++        9, 9, 9, 9, 9, 9, 9, 9,
++        9, 9, 9, 9, 9, 9, 9, 9,
++        9, 9, 9, 9, 9, 9, 9, 9,
++        9, 9, 13, 9, 12, 9, 16, 11,
++        11, 12, 13, 9, 9, 9, 9, 12,
++        9, 9, 9, 9, 9, 9, 9, 9,
++        9, 9, 9, 9, 9, 9, 9, 9,
++        9, 9, 9, 9, 9, 9, 9, 9,
++        9, 9, 9, 9, 9, 9, 9, 9,
++        9, 9, 9, 9, 9, 9, 9, 9,
++        9, 9, 9, 13, 9, 10, 11, 11,
++        12, 13, 9, 9, 9, 17, 12, 9,
++        9, 9, 9, 9, 9, 9, 9, 9,
++        9, 9, 9, 9, 9, 9, 9, 9,
++        9, 9, 9, 9, 9, 9, 9, 9,
++        9, 9, 9, 9, 9, 9, 9, 9,
++        9, 9, 9, 9, 9, 9, 9, 9,
++        9, 9, 13, 9, 10, 11, 11, 12,
++        13, 9, 9, 9, 18, 12, 9, 9,
++        9, 9, 9, 9, 9, 9, 9, 9,
++        9, 9, 9, 9, 9, 9, 9, 9,
++        9, 9, 9, 9, 9, 9, 9, 9,
++        9, 9, 9, 9, 9, 9, 9, 9,
++        9, 9, 9, 9, 9, 9, 9, 9,
++        9, 13, 9, 20, 21, 21, 22, 23,
++        19, 19, 19, 24, 22, 19, 19, 19,
++        19, 19, 19, 19, 19, 19, 19, 19,
++        19, 19, 19, 19, 19, 19, 19, 19,
++        19, 19, 19, 19, 19, 19, 19, 19,
++        19, 19, 19, 19, 19, 19, 19, 19,
++        19, 19, 19, 19, 19, 19, 19, 19,
++        23, 19, 25, 19, 19, 19, 19, 19,
++        19, 19, 19, 19, 19, 19, 19, 19,
++        19, 19, 19, 19, 19, 19, 19, 19,
++        19, 19, 19, 19, 19, 19, 19, 19,
++        19, 19, 19, 19, 19, 19, 19, 19,
++        19, 19, 19, 19, 19, 19, 19, 19,
++        19, 19, 19, 25, 19, 21, 21, 22,
++        27, 26, 26, 26, 26, 22, 26, 26,
++        26, 26, 26, 26, 26, 26, 26, 26,
++        26, 26, 26, 26, 26, 26, 26, 26,
++        26, 26, 26, 26, 26, 26, 26, 26,
++        26, 26, 26, 26, 26, 26, 26, 26,
++        26, 26, 26, 26, 26, 26, 26, 26,
++        26, 27, 26, 21, 21, 22, 23, 19,
++        19, 19, 19, 22, 19, 19, 19, 19,
++        19, 19, 19, 19, 19, 19, 19, 19,
++        19, 19, 19, 19, 19, 19, 19, 19,
++        19, 19, 19, 19, 19, 19, 19, 19,
++        19, 19, 19, 19, 19, 19, 19, 19,
++        19, 19, 19, 19, 19, 19, 19, 23,
++        19, 22, 26, 20, 21, 21, 22, 23,
++        19, 19, 19, 19, 22, 19, 19, 19,
++        19, 19, 19, 19, 19, 19, 19, 19,
++        19, 19, 19, 19, 19, 19, 19, 19,
++        19, 19, 19, 19, 19, 19, 19, 19,
++        19, 19, 19, 19, 19, 19, 19, 19,
++        19, 19, 19, 19, 19, 19, 19, 19,
++        23, 19, 28, 21, 21, 22, 23, 19,
++        19, 19, 19, 22, 19, 19, 19, 19,
++        19, 19, 19, 19, 19, 19, 19, 19,
++        19, 19, 19, 19, 19, 19, 19, 19,
++        19, 19, 19, 19, 19, 19, 19, 19,
++        19, 19, 19, 19, 19, 19, 19, 19,
++        19, 19, 19, 19, 19, 19, 19, 23,
++        19, 30, 31, 31, 32, 33, 29, 29,
++        29, 34, 32, 29, 29, 29, 29, 29,
++        29, 29, 29, 29, 29, 29, 29, 29,
++        29, 29, 29, 29, 29, 29, 29, 29,
++        29, 29, 29, 29, 29, 29, 29, 29,
++        29, 29, 29, 29, 29, 29, 29, 29,
++        29, 29, 29, 29, 29, 29, 33, 29,
++        35, 29, 29, 29, 29, 29, 29, 29,
++        29, 29, 29, 29, 29, 29, 29, 29,
++        29, 29, 29, 29, 29, 29, 29, 29,
++        29, 29, 29, 29, 29, 29, 29, 29,
++        29, 29, 29, 29, 29, 29, 29, 29,
++        29, 29, 29, 29, 29, 29, 29, 29,
+         29, 35, 29, 31, 31, 32, 36, 29,
+-        29, 29, 29, 32, 29, 31, 31, 32,
+-        33, 29, 29, 29, 29, 32, 29, 32,
++        29, 29, 29, 32, 29, 29, 29, 29,
++        29, 29, 29, 29, 29, 29, 29, 29,
++        29, 29, 29, 29, 29, 29, 29, 29,
++        29, 29, 29, 29, 29, 29, 29, 29,
++        29, 29, 29, 29, 29, 29, 29, 29,
++        29, 29, 29, 29, 29, 29, 29, 36,
++        29, 31, 31, 32, 33, 29, 29, 29,
++        29, 32, 29, 29, 29, 29, 29, 29,
++        29, 29, 29, 29, 29, 29, 29, 29,
++        29, 29, 29, 29, 29, 29, 29, 29,
++        29, 29, 29, 29, 29, 29, 29, 29,
++        29, 29, 29, 29, 29, 29, 29, 29,
++        29, 29, 29, 29, 29, 33, 29, 32,
+         29, 30, 31, 31, 32, 33, 29, 29,
+-        29, 29, 32, 29, 37, 31, 31, 32,
+-        33, 29, 29, 29, 29, 32, 29, 21,
++        29, 29, 32, 29, 29, 29, 29, 29,
++        29, 29, 29, 29, 29, 29, 29, 29,
++        29, 29, 29, 29, 29, 29, 29, 29,
++        29, 29, 29, 29, 29, 29, 29, 29,
++        29, 29, 29, 29, 29, 29, 29, 29,
++        29, 29, 29, 29, 29, 29, 33, 29,
++        37, 31, 31, 32, 33, 29, 29, 29,
++        29, 32, 29, 29, 29, 29, 29, 29,
++        29, 29, 29, 29, 29, 29, 29, 29,
++        29, 29, 29, 29, 29, 29, 29, 29,
++        29, 29, 29, 29, 29, 29, 29, 29,
++        29, 29, 29, 29, 29, 29, 29, 29,
++        29, 29, 29, 29, 29, 33, 29, 21,
+         21, 22, 38, 0, 0, 0, 0, 22,
+-        0, 40, 39, 42, 43, 44, 45, 46,
+-        47, 22, 23, 48, 49, 49, 24, 22,
+-        50, 51, 52, 53, 54, 41, 56, 57,
+-        58, 59, 4, 5, 60, 55, 55, 8,
+-        4, 55, 55, 61, 55, 62, 57, 63,
+-        63, 4, 5, 60, 55, 55, 55, 4,
+-        55, 55, 61, 55, 57, 63, 63, 4,
+-        5, 60, 55, 55, 55, 4, 55, 55,
+-        61, 55, 42, 55, 55, 55, 64, 65,
+-        55, 1, 60, 55, 55, 55, 55, 55,
+-        42, 55, 66, 66, 55, 1, 60, 55,
+-        60, 55, 55, 67, 60, 55, 60, 55,
+-        60, 55, 55, 55, 60, 55, 42, 55,
+-        68, 55, 66, 66, 55, 1, 60, 55,
+-        55, 55, 55, 55, 42, 55, 42, 55,
+-        55, 55, 66, 66, 55, 1, 60, 55,
+-        55, 55, 55, 55, 42, 55, 42, 55,
+-        55, 55, 66, 65, 55, 1, 60, 55,
+-        55, 55, 55, 55, 42, 55, 69, 70,
+-        71, 71, 4, 5, 60, 55, 55, 55,
+-        4, 55, 70, 71, 71, 4, 5, 60,
+-        55, 55, 55, 4, 55, 71, 71, 4,
+-        5, 60, 55, 55, 55, 4, 55, 60,
+-        55, 55, 67, 60, 55, 55, 55, 4,
+-        55, 72, 73, 73, 4, 5, 60, 55,
+-        55, 55, 4, 55, 64, 74, 55, 1,
+-        60, 55, 64, 55, 66, 66, 55, 1,
+-        60, 55, 66, 74, 55, 1, 60, 55,
+-        56, 57, 63, 63, 4, 5, 60, 55,
+-        55, 55, 4, 55, 55, 61, 55, 56,
+-        57, 58, 63, 4, 5, 60, 55, 55,
+-        8, 4, 55, 55, 61, 55, 76, 77,
+-        78, 79, 12, 13, 80, 75, 75, 18,
+-        12, 75, 75, 81, 75, 82, 77, 83,
+-        79, 12, 13, 80, 75, 75, 75, 12,
+-        75, 75, 81, 75, 77, 83, 79, 12,
+-        13, 80, 75, 75, 75, 12, 75, 75,
+-        81, 75, 84, 75, 75, 75, 85, 86,
+-        75, 14, 80, 75, 75, 75, 75, 75,
+-        84, 75, 87, 77, 88, 89, 12, 13,
+-        80, 75, 75, 17, 12, 75, 75, 81,
+-        75, 90, 77, 83, 83, 12, 13, 80,
+-        75, 75, 75, 12, 75, 75, 81, 75,
+-        77, 83, 83, 12, 13, 80, 75, 75,
+-        75, 12, 75, 75, 81, 75, 84, 75,
+-        75, 75, 91, 86, 75, 14, 80, 75,
+-        75, 75, 75, 75, 84, 75, 80, 75,
+-        75, 92, 80, 75, 80, 75, 80, 75,
+-        75, 75, 80, 75, 84, 75, 93, 75,
+-        91, 91, 75, 14, 80, 75, 75, 75,
+-        75, 75, 84, 75, 84, 75, 75, 75,
+-        91, 91, 75, 14, 80, 75, 75, 75,
+-        75, 75, 84, 75, 94, 95, 96, 96,
+-        12, 13, 80, 75, 75, 75, 12, 75,
+-        95, 96, 96, 12, 13, 80, 75, 75,
+-        75, 12, 75, 96, 96, 12, 13, 80,
+-        75, 75, 75, 12, 75, 80, 75, 75,
+-        92, 80, 75, 75, 75, 12, 75, 97,
+-        98, 98, 12, 13, 80, 75, 75, 75,
+-        12, 75, 85, 99, 75, 14, 80, 75,
+-        91, 91, 75, 14, 80, 75, 85, 75,
+-        91, 91, 75, 14, 80, 75, 91, 99,
+-        75, 14, 80, 75, 87, 77, 83, 83,
+-        12, 13, 80, 75, 75, 75, 12, 75,
+-        75, 81, 75, 87, 77, 88, 83, 12,
+-        13, 80, 75, 75, 17, 12, 75, 75,
+-        81, 75, 10, 11, 11, 12, 13, 75,
+-        75, 75, 75, 12, 75, 76, 77, 83,
+-        79, 12, 13, 80, 75, 75, 75, 12,
+-        75, 75, 81, 75, 101, 45, 102, 102,
+-        22, 23, 48, 100, 100, 100, 22, 100,
+-        100, 52, 100, 45, 102, 102, 22, 23,
+-        48, 100, 100, 100, 22, 100, 100, 52,
+-        100, 103, 100, 100, 100, 104, 105, 100,
+-        25, 48, 100, 100, 100, 100, 100, 103,
+-        100, 44, 45, 106, 107, 22, 23, 48,
+-        100, 100, 24, 22, 100, 100, 52, 100,
+-        103, 100, 100, 100, 108, 105, 100, 25,
+-        48, 100, 100, 100, 100, 100, 103, 100,
+-        48, 100, 100, 109, 48, 100, 48, 100,
+-        48, 100, 100, 100, 48, 100, 103, 100,
+-        110, 100, 108, 108, 100, 25, 48, 100,
+-        100, 100, 100, 100, 103, 100, 103, 100,
+-        100, 100, 108, 108, 100, 25, 48, 100,
+-        100, 100, 100, 100, 103, 100, 111, 112,
+-        113, 113, 22, 23, 48, 100, 100, 100,
+-        22, 100, 112, 113, 113, 22, 23, 48,
+-        100, 100, 100, 22, 100, 113, 113, 22,
+-        23, 48, 100, 100, 100, 22, 100, 48,
+-        100, 100, 109, 48, 100, 100, 100, 22,
+-        100, 44, 45, 102, 102, 22, 23, 48,
+-        100, 100, 100, 22, 100, 100, 52, 100,
+-        114, 115, 115, 22, 23, 48, 100, 100,
+-        100, 22, 100, 104, 116, 100, 25, 48,
+-        100, 108, 108, 100, 25, 48, 100, 104,
+-        100, 108, 108, 100, 25, 48, 100, 108,
+-        116, 100, 25, 48, 100, 44, 45, 106,
+-        102, 22, 23, 48, 100, 100, 24, 22,
+-        100, 100, 52, 100, 20, 21, 21, 22,
+-        23, 117, 117, 117, 24, 22, 117, 20,
+-        21, 21, 22, 23, 117, 117, 117, 117,
+-        22, 117, 119, 120, 121, 122, 32, 33,
+-        123, 118, 118, 34, 32, 118, 118, 124,
+-        118, 125, 120, 122, 122, 32, 33, 123,
+-        118, 118, 118, 32, 118, 118, 124, 118,
+-        120, 122, 122, 32, 33, 123, 118, 118,
+-        118, 32, 118, 118, 124, 118, 126, 118,
+-        118, 118, 127, 128, 118, 35, 123, 118,
+-        118, 118, 118, 118, 126, 118, 119, 120,
+-        121, 49, 32, 33, 123, 118, 118, 34,
+-        32, 118, 118, 124, 118, 126, 118, 118,
+-        118, 129, 128, 118, 35, 123, 118, 118,
+-        118, 118, 118, 126, 118, 123, 118, 118,
+-        130, 123, 118, 123, 118, 123, 118, 118,
+-        118, 123, 118, 126, 118, 131, 118, 129,
+-        129, 118, 35, 123, 118, 118, 118, 118,
+-        118, 126, 118, 126, 118, 118, 118, 129,
+-        129, 118, 35, 123, 118, 118, 118, 118,
+-        118, 126, 118, 132, 133, 134, 134, 32,
+-        33, 123, 118, 118, 118, 32, 118, 133,
+-        134, 134, 32, 33, 123, 118, 118, 118,
+-        32, 118, 134, 134, 32, 33, 123, 118,
+-        118, 118, 32, 118, 123, 118, 118, 130,
+-        123, 118, 118, 118, 32, 118, 119, 120,
+-        122, 122, 32, 33, 123, 118, 118, 118,
+-        32, 118, 118, 124, 118, 135, 136, 136,
+-        32, 33, 123, 118, 118, 118, 32, 118,
+-        127, 137, 118, 35, 123, 118, 129, 129,
+-        118, 35, 123, 118, 127, 118, 129, 129,
+-        118, 35, 123, 118, 129, 137, 118, 35,
+-        123, 118, 42, 43, 44, 45, 106, 102,
+-        22, 23, 48, 49, 49, 24, 22, 100,
+-        42, 52, 100, 56, 138, 58, 59, 4,
+-        5, 60, 55, 55, 8, 4, 55, 55,
+-        61, 55, 42, 43, 44, 45, 139, 140,
+-        22, 141, 142, 55, 49, 24, 22, 55,
+-        42, 52, 55, 20, 143, 143, 22, 141,
+-        60, 55, 55, 24, 22, 55, 60, 55,
+-        55, 67, 60, 55, 55, 55, 22, 55,
+-        142, 55, 55, 144, 142, 55, 55, 55,
+-        22, 55, 142, 55, 142, 55, 55, 55,
+-        142, 55, 42, 55, 68, 20, 143, 143,
+-        22, 141, 60, 55, 55, 55, 22, 55,
+-        42, 55, 146, 145, 147, 147, 145, 40,
+-        148, 145, 147, 147, 145, 40, 148, 145,
+-        148, 145, 145, 149, 148, 145, 148, 145,
+-        148, 145, 145, 145, 148, 145, 42, 117,
+-        117, 117, 117, 117, 117, 117, 117, 49,
+-        117, 117, 117, 117, 42, 117, 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, 0,
++        0, 0, 0, 38, 0, 40, 39, 39,
++        39, 39, 39, 39, 39, 39, 39, 39,
++        39, 39, 39, 39, 39, 39, 39, 39,
++        39, 39, 39, 39, 39, 39, 39, 39,
++        39, 39, 39, 39, 39, 39, 39, 39,
++        39, 39, 39, 39, 39, 39, 39, 39,
++        39, 39, 39, 39, 39, 39, 40, 39,
++        42, 43, 44, 45, 46, 47, 22, 23,
++        48, 49, 49, 24, 22, 50, 51, 52,
++        53, 54, 41, 41, 41, 41, 41, 41,
++        41, 41, 41, 41, 41, 41, 41, 41,
++        41, 41, 41, 41, 41, 41, 41, 41,
++        41, 41, 41, 41, 41, 41, 41, 41,
++        41, 41, 41, 41, 41, 41, 41, 41,
++        55, 41, 57, 58, 59, 60, 4, 5,
++        61, 56, 56, 8, 4, 56, 56, 62,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        5, 56, 63, 58, 64, 64, 4, 5,
++        61, 56, 56, 56, 4, 56, 56, 62,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        5, 56, 58, 64, 64, 4, 5, 61,
++        56, 56, 56, 4, 56, 56, 62, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 5,
++        56, 42, 56, 56, 56, 65, 66, 56,
++        1, 61, 56, 56, 56, 56, 56, 42,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 1, 56, 67, 67, 56, 1, 61,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 1,
++        56, 61, 56, 56, 68, 61, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 68, 56, 61,
++        56, 61, 56, 56, 56, 61, 56, 42,
++        56, 69, 56, 67, 67, 56, 1, 61,
++        56, 56, 56, 56, 56, 42, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 1,
++        56, 42, 56, 56, 56, 67, 67, 56,
++        1, 61, 56, 56, 56, 56, 56, 42,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 1, 56, 42, 56, 56, 56, 67,
++        66, 56, 1, 61, 56, 56, 56, 56,
++        56, 42, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 1, 56, 70, 71, 72,
++        72, 4, 5, 61, 56, 56, 56, 4,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 5, 56, 71, 72, 72,
++        4, 5, 61, 56, 56, 56, 4, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 5, 56, 72, 72, 4, 5,
++        61, 56, 56, 56, 4, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        5, 56, 61, 56, 56, 68, 61, 56,
++        56, 56, 4, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 68, 56,
++        73, 74, 74, 4, 5, 61, 56, 56,
++        56, 4, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 5, 56, 65,
++        75, 56, 1, 61, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 1, 56, 65, 56, 67,
++        67, 56, 1, 61, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 1, 56, 67, 75, 56,
++        1, 61, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 1, 56, 57, 58, 64, 64, 4,
++        5, 61, 56, 56, 56, 4, 56, 56,
++        62, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 5, 56, 57, 58, 59, 64, 4,
++        5, 61, 56, 56, 8, 4, 56, 56,
++        62, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 5, 56, 77, 78, 79, 80, 12,
++        13, 81, 76, 76, 18, 12, 76, 76,
++        82, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 13, 76, 83, 78, 84, 80, 12,
++        13, 81, 76, 76, 76, 12, 76, 76,
++        82, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 13, 76, 78, 84, 80, 12, 13,
++        81, 76, 76, 76, 12, 76, 76, 82,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        13, 76, 85, 76, 76, 76, 86, 87,
++        76, 14, 81, 76, 76, 76, 76, 76,
++        85, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 14, 76, 88, 78, 89, 90,
++        12, 13, 81, 76, 76, 17, 12, 76,
++        76, 82, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 13, 76, 91, 78, 84, 84,
++        12, 13, 81, 76, 76, 76, 12, 76,
++        76, 82, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 13, 76, 78, 84, 84, 12,
++        13, 81, 76, 76, 76, 12, 76, 76,
++        82, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 13, 76, 85, 76, 76, 76, 92,
++        87, 76, 14, 81, 76, 76, 76, 76,
++        76, 85, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 14, 76, 81, 76, 76,
++        93, 81, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 93, 76, 81, 76, 81, 76, 76,
++        76, 81, 76, 85, 76, 94, 76, 92,
++        92, 76, 14, 81, 76, 76, 76, 76,
++        76, 85, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 14, 76, 85, 76, 76,
++        76, 92, 92, 76, 14, 81, 76, 76,
++        76, 76, 76, 85, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 14, 76, 95,
++        96, 97, 97, 12, 13, 81, 76, 76,
++        76, 12, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 13, 76, 96,
++        97, 97, 12, 13, 81, 76, 76, 76,
++        12, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 13, 76, 97, 97,
++        12, 13, 81, 76, 76, 76, 12, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 13, 76, 81, 76, 76, 93,
++        81, 76, 76, 76, 12, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        93, 76, 98, 99, 99, 12, 13, 81,
++        76, 76, 76, 12, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 13,
++        76, 86, 100, 76, 14, 81, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 14, 76, 92,
++        92, 76, 14, 81, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 14, 76, 86, 76, 92,
++        92, 76, 14, 81, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 14, 76, 92, 100, 76,
++        14, 81, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 14, 76, 88, 78, 84, 84, 12,
++        13, 81, 76, 76, 76, 12, 76, 76,
++        82, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 13, 76, 88, 78, 89, 84, 12,
++        13, 81, 76, 76, 17, 12, 76, 76,
++        82, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 13, 76, 10, 11, 11, 12, 13,
++        76, 76, 76, 76, 12, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        13, 76, 77, 78, 84, 80, 12, 13,
++        81, 76, 76, 76, 12, 76, 76, 82,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        76, 76, 76, 76, 76, 76, 76, 76,
++        13, 76, 102, 45, 103, 103, 22, 23,
++        48, 101, 101, 101, 22, 101, 101, 52,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        23, 101, 45, 103, 103, 22, 23, 48,
++        101, 101, 101, 22, 101, 101, 52, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 23,
++        101, 104, 101, 101, 101, 105, 106, 101,
++        25, 48, 101, 101, 101, 101, 101, 104,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 25, 101, 44, 45, 107, 108, 22,
++        23, 48, 101, 101, 24, 22, 101, 101,
++        52, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 23, 101, 104, 101, 101, 101, 109,
++        106, 101, 25, 48, 101, 101, 101, 101,
++        101, 104, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 25, 101, 48, 101, 101,
++        110, 48, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 110, 101, 48, 101, 48, 101, 101,
++        101, 48, 101, 104, 101, 111, 101, 109,
++        109, 101, 25, 48, 101, 101, 101, 101,
++        101, 104, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 25, 101, 104, 101, 101,
++        101, 109, 109, 101, 25, 48, 101, 101,
++        101, 101, 101, 104, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 25, 101, 112,
++        113, 114, 114, 22, 23, 48, 101, 101,
++        101, 22, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 23, 101, 113,
++        114, 114, 22, 23, 48, 101, 101, 101,
++        22, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 23, 101, 114, 114,
++        22, 23, 48, 101, 101, 101, 22, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 23, 101, 48, 26, 26, 110,
++        48, 26, 26, 26, 22, 26, 26, 26,
++        26, 26, 26, 26, 26, 26, 26, 26,
++        26, 26, 26, 26, 26, 26, 26, 26,
++        26, 26, 26, 26, 26, 26, 26, 26,
++        26, 26, 26, 26, 26, 26, 26, 26,
++        26, 26, 26, 26, 26, 26, 26, 26,
++        110, 26, 44, 45, 103, 103, 22, 23,
++        48, 101, 101, 101, 22, 101, 101, 52,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        23, 101, 115, 116, 116, 22, 23, 48,
++        101, 101, 101, 22, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 23,
++        101, 105, 117, 101, 25, 48, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 25, 101, 109,
++        109, 101, 25, 48, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 25, 101, 105, 101, 109,
++        109, 101, 25, 48, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 25, 101, 109, 117, 101,
++        25, 48, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 25, 101, 44, 45, 107, 103, 22,
++        23, 48, 101, 101, 24, 22, 101, 101,
++        52, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 23, 101, 20, 21, 21, 22, 23,
++        118, 118, 118, 24, 22, 118, 118, 118,
++        118, 118, 118, 118, 118, 118, 118, 118,
++        118, 118, 118, 118, 118, 118, 118, 118,
++        118, 118, 118, 118, 118, 118, 118, 118,
++        118, 118, 118, 118, 118, 118, 118, 118,
++        118, 118, 118, 118, 118, 118, 118, 118,
++        23, 118, 20, 21, 21, 22, 23, 118,
++        118, 118, 118, 22, 118, 118, 118, 118,
++        118, 118, 118, 118, 118, 118, 118, 118,
++        118, 118, 118, 118, 118, 118, 118, 118,
++        118, 118, 118, 118, 118, 118, 118, 118,
++        118, 118, 118, 118, 118, 118, 118, 118,
++        118, 118, 118, 118, 118, 118, 118, 23,
++        118, 120, 121, 122, 123, 32, 33, 124,
++        119, 119, 34, 32, 119, 119, 125, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 33,
++        119, 126, 121, 123, 123, 32, 33, 124,
++        119, 119, 119, 32, 119, 119, 125, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 33,
++        119, 121, 123, 123, 32, 33, 124, 119,
++        119, 119, 32, 119, 119, 125, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 33, 119,
++        127, 119, 119, 119, 128, 129, 119, 35,
++        124, 119, 119, 119, 119, 119, 127, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        35, 119, 120, 121, 122, 49, 32, 33,
++        124, 119, 119, 34, 32, 119, 119, 125,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        33, 119, 127, 119, 119, 119, 130, 129,
++        119, 35, 124, 119, 119, 119, 119, 119,
++        127, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 35, 119, 124, 119, 119, 131,
++        124, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        131, 119, 124, 119, 124, 119, 119, 119,
++        124, 119, 127, 119, 132, 119, 130, 130,
++        119, 35, 124, 119, 119, 119, 119, 119,
++        127, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 35, 119, 127, 119, 119, 119,
++        130, 130, 119, 35, 124, 119, 119, 119,
++        119, 119, 127, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 35, 119, 133, 134,
++        135, 135, 32, 33, 124, 119, 119, 119,
++        32, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 33, 119, 134, 135,
++        135, 32, 33, 124, 119, 119, 119, 32,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 33, 119, 135, 135, 32,
++        33, 124, 119, 119, 119, 32, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 33, 119, 124, 119, 119, 131, 124,
++        119, 119, 119, 32, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 131,
++        119, 120, 121, 123, 123, 32, 33, 124,
++        119, 119, 119, 32, 119, 119, 125, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 33,
++        119, 136, 137, 137, 32, 33, 124, 119,
++        119, 119, 32, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 33, 119,
++        128, 138, 119, 35, 124, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 35, 119, 130, 130,
++        119, 35, 124, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 35, 119, 128, 119, 130, 130,
++        119, 35, 124, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 35, 119, 130, 138, 119, 35,
++        124, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        119, 119, 119, 119, 119, 119, 119, 119,
++        35, 119, 42, 43, 44, 45, 107, 103,
++        22, 23, 48, 49, 49, 24, 22, 101,
++        42, 52, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 101, 101, 101, 101, 101, 101,
++        101, 101, 23, 101, 57, 139, 59, 60,
++        4, 5, 61, 56, 56, 8, 4, 56,
++        56, 62, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 5, 56, 42, 43, 44, 45,
++        140, 141, 22, 142, 143, 56, 49, 24,
++        22, 56, 42, 52, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 142, 56, 20, 144,
++        144, 22, 142, 61, 56, 56, 24, 22,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 142, 56, 61, 56, 56,
++        68, 61, 56, 56, 56, 22, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 68, 56, 143, 56, 56, 145, 143,
++        56, 56, 56, 22, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 145,
++        56, 143, 56, 143, 56, 56, 56, 143,
++        56, 42, 56, 69, 20, 144, 144, 22,
++        142, 61, 56, 56, 56, 22, 56, 42,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 56, 56, 56, 56, 56, 56, 56,
++        56, 142, 56, 147, 146, 148, 148, 146,
++        40, 149, 146, 146, 146, 146, 146, 146,
++        146, 146, 146, 146, 146, 146, 146, 146,
++        146, 146, 146, 146, 146, 146, 146, 146,
++        146, 146, 146, 146, 146, 146, 146, 146,
++        146, 146, 146, 146, 146, 146, 146, 146,
++        146, 146, 146, 146, 146, 146, 146, 146,
++        146, 40, 146, 148, 148, 146, 40, 149,
++        146, 146, 146, 146, 146, 146, 146, 146,
++        146, 146, 146, 146, 146, 146, 146, 146,
++        146, 146, 146, 146, 146, 146, 146, 146,
++        146, 146, 146, 146, 146, 146, 146, 146,
++        146, 146, 146, 146, 146, 146, 146, 146,
++        146, 146, 146, 146, 146, 146, 146, 40,
++        146, 149, 146, 146, 150, 149, 146, 146,
++        146, 146, 146, 146, 146, 146, 146, 146,
++        146, 146, 146, 146, 146, 146, 146, 146,
++        146, 146, 146, 146, 146, 146, 146, 146,
++        146, 146, 146, 146, 146, 146, 146, 146,
++        146, 146, 146, 146, 146, 146, 146, 146,
++        146, 146, 146, 146, 146, 150, 146, 149,
++        146, 149, 146, 146, 146, 149, 146, 42,
++        118, 118, 118, 118, 118, 118, 118, 118,
++        49, 118, 118, 118, 118, 42, 118, 0
+ };
+ 
+ static const unsigned char _indic_syllable_machine_trans_targs[] = {
+@@ -330,41 +996,41 @@ static const unsigned char _indic_syllable_machine_trans_targs[] = {
+         93, 84, 31, 19, 98, 31, 107, 24,
+         113, 116, 117, 108, 26, 122, 127, 31,
+         134, 31, 32, 53, 79, 81, 100, 101,
+-        85, 102, 123, 124, 94, 132, 137, 31,
+-        33, 35, 6, 52, 38, 47, 34, 1,
+-        36, 40, 0, 39, 41, 44, 45, 3,
+-        48, 5, 49, 31, 54, 56, 14, 77,
+-        62, 70, 55, 7, 57, 72, 64, 58,
+-        13, 76, 59, 8, 63, 65, 67, 68,
+-        10, 71, 12, 73, 31, 80, 20, 82,
+-        96, 87, 15, 99, 16, 86, 88, 90,
+-        91, 18, 95, 21, 97, 31, 31, 103,
+-        105, 22, 27, 109, 118, 104, 106, 120,
+-        111, 23, 110, 112, 114, 115, 25, 119,
+-        28, 121, 125, 126, 131, 128, 129, 29,
+-        130, 31, 133, 30, 135, 136
++        85, 102, 123, 124, 94, 132, 137, 92,
++        31, 33, 35, 6, 52, 38, 47, 34,
++        1, 36, 40, 0, 39, 41, 44, 45,
++        3, 48, 5, 49, 31, 54, 56, 14,
++        77, 62, 70, 55, 7, 57, 72, 64,
++        58, 13, 76, 59, 8, 63, 65, 67,
++        68, 10, 71, 12, 73, 31, 80, 20,
++        82, 96, 87, 15, 99, 16, 86, 88,
++        90, 91, 18, 95, 21, 97, 31, 31,
++        103, 105, 22, 27, 109, 118, 104, 106,
++        120, 111, 23, 110, 112, 114, 115, 25,
++        119, 28, 121, 125, 126, 131, 128, 129,
++        29, 130, 31, 133, 30, 135, 136
+ };
+ 
+ static const char _indic_syllable_machine_trans_actions[] = {
+         1, 0, 2, 0, 2, 0, 0, 2,
+         2, 3, 2, 0, 2, 0, 0, 0,
+-        2, 2, 2, 4, 2, 0, 5, 0,
++        2, 2, 2, 4, 2, 0, 5, 5,
+         5, 0, 6, 0, 2, 7, 2, 0,
+         2, 0, 2, 0, 0, 2, 0, 8,
+         0, 11, 2, 2, 5, 0, 12, 12,
+         0, 2, 5, 2, 5, 2, 0, 13,
+-        2, 0, 0, 2, 0, 2, 2, 0,
+-        2, 2, 0, 0, 2, 2, 2, 0,
+-        0, 0, 2, 14, 2, 0, 0, 2,
+-        0, 2, 2, 0, 2, 2, 2, 2,
++        14, 2, 0, 0, 2, 0, 2, 2,
+         0, 2, 2, 0, 0, 2, 2, 2,
+-        0, 0, 0, 2, 15, 5, 0, 5,
+-        2, 2, 0, 5, 0, 0, 2, 5,
+-        5, 0, 0, 0, 2, 16, 17, 2,
+-        0, 0, 0, 0, 2, 2, 2, 2,
+-        2, 0, 0, 2, 2, 2, 0, 0,
+-        0, 2, 0, 18, 18, 0, 0, 0,
+-        0, 19, 2, 0, 0, 0
++        0, 0, 0, 2, 15, 2, 0, 0,
++        2, 0, 2, 2, 0, 2, 2, 2,
++        2, 0, 2, 2, 0, 0, 2, 2,
++        2, 0, 0, 0, 2, 16, 5, 0,
++        5, 2, 2, 0, 5, 0, 0, 2,
++        5, 5, 0, 0, 0, 2, 17, 18,
++        2, 0, 0, 0, 0, 2, 2, 2,
++        2, 2, 0, 0, 2, 2, 2, 0,
++        0, 0, 2, 0, 19, 19, 0, 0,
++        0, 0, 20, 2, 0, 0, 0
+ };
+ 
+ static const char _indic_syllable_machine_to_state_actions[] = {
+@@ -414,20 +1080,20 @@ static const short _indic_syllable_machine_eof_trans[] = {
+         10, 10, 10, 10, 10, 10, 10, 20,
+         20, 27, 20, 27, 20, 20, 30, 30,
+         30, 30, 30, 30, 30, 1, 40, 0,
+-        56, 56, 56, 56, 56, 56, 56, 56,
+-        56, 56, 56, 56, 56, 56, 56, 56,
+-        56, 56, 56, 56, 56, 76, 76, 76,
+-        76, 76, 76, 76, 76, 76, 76, 76,
+-        76, 76, 76, 76, 76, 76, 76, 76,
+-        76, 76, 76, 76, 76, 76, 76, 101,
+-        101, 101, 101, 101, 101, 101, 101, 101,
+-        101, 101, 101, 101, 101, 101, 101, 101,
+-        101, 101, 101, 101, 118, 118, 119, 119,
+-        119, 119, 119, 119, 119, 119, 119, 119,
+-        119, 119, 119, 119, 119, 119, 119, 119,
+-        119, 119, 119, 101, 56, 56, 56, 56,
+-        56, 56, 56, 56, 146, 146, 146, 146,
+-        146, 118
++        57, 57, 57, 57, 57, 57, 57, 57,
++        57, 57, 57, 57, 57, 57, 57, 57,
++        57, 57, 57, 57, 57, 77, 77, 77,
++        77, 77, 77, 77, 77, 77, 77, 77,
++        77, 77, 77, 77, 77, 77, 77, 77,
++        77, 77, 77, 77, 77, 77, 77, 102,
++        102, 102, 102, 102, 102, 102, 102, 102,
++        102, 102, 102, 102, 27, 102, 102, 102,
++        102, 102, 102, 102, 119, 119, 120, 120,
++        120, 120, 120, 120, 120, 120, 120, 120,
++        120, 120, 120, 120, 120, 120, 120, 120,
++        120, 120, 120, 102, 57, 57, 57, 57,
++        57, 57, 57, 57, 147, 147, 147, 147,
++        147, 119
+ };
+ 
+ static const int indic_syllable_machine_start = 31;
+@@ -441,7 +1107,7 @@ static const int indic_syllable_machine_en_main = 31;
+ 
+ 
+ 
+-#line 118 "hb-ot-shaper-indic-machine.rl"
++#line 121 "hb-ot-shaper-indic-machine.rl"
+ 
+ 
+ #define found_syllable(syllable_type) \
+@@ -460,7 +1126,7 @@ find_syllables_indic (hb_buffer_t *buffer)
+   int cs;
+   hb_glyph_info_t *info = buffer->info;
+ 
+-#line 464 "hb-ot-shaper-indic-machine.hh"
++#line 1130 "hb-ot-shaper-indic-machine.hh"
+         {
+         cs = indic_syllable_machine_start;
+         ts = 0;
+@@ -468,7 +1134,7 @@ find_syllables_indic (hb_buffer_t *buffer)
+         act = 0;
+         }
+ 
+-#line 138 "hb-ot-shaper-indic-machine.rl"
++#line 141 "hb-ot-shaper-indic-machine.rl"
+ 
+ 
+   p = 0;
+@@ -476,7 +1142,7 @@ find_syllables_indic (hb_buffer_t *buffer)
+ 
+   unsigned int syllable_serial = 1;
+ 
+-#line 480 "hb-ot-shaper-indic-machine.hh"
++#line 1146 "hb-ot-shaper-indic-machine.hh"
+         {
+         int _slen;
+         int _trans;
+@@ -490,7 +1156,7 @@ _resume:
+ #line 1 "NONE"
+         {ts = p;}
+         break;
+-#line 494 "hb-ot-shaper-indic-machine.hh"
++#line 1160 "hb-ot-shaper-indic-machine.hh"
+         }
+ 
+         _keys = _indic_syllable_machine_trans_keys + (cs<<1);
+@@ -513,51 +1179,51 @@ _eof_trans:
+         {te = p+1;}
+         break;
+         case 11:
+-#line 114 "hb-ot-shaper-indic-machine.rl"
++#line 117 "hb-ot-shaper-indic-machine.rl"
+         {te = p+1;{ found_syllable (indic_non_indic_cluster); }}
+         break;
+-        case 13:
+-#line 109 "hb-ot-shaper-indic-machine.rl"
++        case 14:
++#line 111 "hb-ot-shaper-indic-machine.rl"
+         {te = p;p--;{ found_syllable (indic_consonant_syllable); }}
+         break;
+-        case 14:
+-#line 110 "hb-ot-shaper-indic-machine.rl"
++        case 15:
++#line 112 "hb-ot-shaper-indic-machine.rl"
+         {te = p;p--;{ found_syllable (indic_vowel_syllable); }}
+         break;
+-        case 17:
+-#line 111 "hb-ot-shaper-indic-machine.rl"
++        case 18:
++#line 113 "hb-ot-shaper-indic-machine.rl"
+         {te = p;p--;{ found_syllable (indic_standalone_cluster); }}
+         break;
+-        case 19:
+-#line 112 "hb-ot-shaper-indic-machine.rl"
++        case 20:
++#line 114 "hb-ot-shaper-indic-machine.rl"
+         {te = p;p--;{ found_syllable (indic_symbol_cluster); }}
+         break;
+-        case 15:
+-#line 113 "hb-ot-shaper-indic-machine.rl"
++        case 16:
++#line 116 "hb-ot-shaper-indic-machine.rl"
+         {te = p;p--;{ found_syllable (indic_broken_cluster); buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE; }}
+         break;
+-        case 16:
+-#line 114 "hb-ot-shaper-indic-machine.rl"
++        case 17:
++#line 117 "hb-ot-shaper-indic-machine.rl"
+         {te = p;p--;{ found_syllable (indic_non_indic_cluster); }}
+         break;
+         case 1:
+-#line 109 "hb-ot-shaper-indic-machine.rl"
++#line 111 "hb-ot-shaper-indic-machine.rl"
+         {{p = ((te))-1;}{ found_syllable (indic_consonant_syllable); }}
+         break;
+         case 3:
+-#line 110 "hb-ot-shaper-indic-machine.rl"
++#line 112 "hb-ot-shaper-indic-machine.rl"
+         {{p = ((te))-1;}{ found_syllable (indic_vowel_syllable); }}
+         break;
+         case 7:
+-#line 111 "hb-ot-shaper-indic-machine.rl"
++#line 113 "hb-ot-shaper-indic-machine.rl"
+         {{p = ((te))-1;}{ found_syllable (indic_standalone_cluster); }}
+         break;
+         case 8:
+-#line 112 "hb-ot-shaper-indic-machine.rl"
++#line 114 "hb-ot-shaper-indic-machine.rl"
+         {{p = ((te))-1;}{ found_syllable (indic_symbol_cluster); }}
+         break;
+         case 4:
+-#line 113 "hb-ot-shaper-indic-machine.rl"
++#line 116 "hb-ot-shaper-indic-machine.rl"
+         {{p = ((te))-1;}{ found_syllable (indic_broken_cluster); buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE; }}
+         break;
+         case 6:
+@@ -567,33 +1233,42 @@ _eof_trans:
+         {{p = ((te))-1;} found_syllable (indic_consonant_syllable); }
+         break;
+         case 5:
+-        {{p = ((te))-1;} found_syllable (indic_broken_cluster); buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE; }
++        {{p = ((te))-1;} found_syllable (indic_non_indic_cluster); }
+         break;
+         case 6:
++        {{p = ((te))-1;} found_syllable (indic_broken_cluster); buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE; }
++        break;
++        case 7:
+         {{p = ((te))-1;} found_syllable (indic_non_indic_cluster); }
+         break;
+         }
+         }
+         break;
+-        case 18:
++        case 19:
+ #line 1 "NONE"
+         {te = p+1;}
+-#line 109 "hb-ot-shaper-indic-machine.rl"
++#line 111 "hb-ot-shaper-indic-machine.rl"
+         {act = 1;}
+         break;
+-        case 5:
++        case 13:
+ #line 1 "NONE"
+         {te = p+1;}
+-#line 113 "hb-ot-shaper-indic-machine.rl"
++#line 115 "hb-ot-shaper-indic-machine.rl"
+         {act = 5;}
+         break;
+-        case 12:
++        case 5:
+ #line 1 "NONE"
+         {te = p+1;}
+-#line 114 "hb-ot-shaper-indic-machine.rl"
++#line 116 "hb-ot-shaper-indic-machine.rl"
+         {act = 6;}
+         break;
+-#line 597 "hb-ot-shaper-indic-machine.hh"
++        case 12:
++#line 1 "NONE"
++        {te = p+1;}
++#line 117 "hb-ot-shaper-indic-machine.rl"
++        {act = 7;}
++        break;
++#line 1272 "hb-ot-shaper-indic-machine.hh"
+         }
+ 
+ _again:
+@@ -602,7 +1277,7 @@ _again:
+ #line 1 "NONE"
+         {ts = 0;}
+         break;
+-#line 606 "hb-ot-shaper-indic-machine.hh"
++#line 1281 "hb-ot-shaper-indic-machine.hh"
+         }
+ 
+         if ( ++p != pe )
+@@ -618,7 +1293,7 @@ _again:
+ 
+         }
+ 
+-#line 146 "hb-ot-shaper-indic-machine.rl"
++#line 149 "hb-ot-shaper-indic-machine.rl"
+ 
+ }
+ 
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-indic-table.cc b/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-indic-table.cc
+index d9899a633..b87c53085 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-indic-table.cc
++++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-indic-table.cc
+@@ -6,12 +6,12 @@
+  *
+  * on files with these headers:
+  *
+- * # IndicSyllabicCategory-15.1.0.txt
+- * # Date: 2023-01-05
+- * # IndicPositionalCategory-15.1.0.txt
+- * # Date: 2023-01-05
+- * # Blocks-15.1.0.txt
+- * # Date: 2023-07-28, 15:47:20 GMT
++ * # IndicSyllabicCategory-16.0.0.txt
++ * # Date: 2024-04-30, 21:48:21 GMT
++ * # IndicPositionalCategory-16.0.0.txt
++ * # Date: 2024-04-30, 21:48:21 GMT
++ * # Blocks-16.0.0.txt
++ * # Date: 2024-02-02
+  */
+ 
+ #include "hb.hh"
+@@ -48,6 +48,7 @@
+ #define OT_CM I_Cat(CM)
+ #define OT_Symbol I_Cat(Symbol)
+ #define OT_CS I_Cat(CS)
++#define OT_SMPst I_Cat(SMPst)
+ /* khmer */
+ #define OT_VAbv K_Cat(VAbv)
+ #define OT_VBlw K_Cat(VBlw)
+@@ -89,12 +90,13 @@ static_assert (OT_VPst == M_Cat(VPst), "");
+ #define _OT_MW   OT_MW           /*   2 chars; MW */
+ #define _OT_MY   OT_MY           /*   3 chars; MY */
+ #define _OT_N    OT_N            /*  17 chars; N */
+-#define _OT_GB   OT_PLACEHOLDER  /* 165 chars; PLACEHOLDER */
++#define _OT_GB   OT_PLACEHOLDER  /* 185 chars; PLACEHOLDER */
+ #define _OT_PT   OT_PT           /*   8 chars; PT */
+ #define _OT_R    OT_Ra           /*  14 chars; Ra */
+ #define _OT_Rf   OT_Repha        /*   1 chars; Repha */
+ #define _OT_Rt   OT_Robatic      /*   3 chars; Robatic */
+-#define _OT_SM   OT_SM           /*  56 chars; SM */
++#define _OT_SM   OT_SM           /*  50 chars; SM */
++#define _OT_SP   OT_SMPst        /*   6 chars; SMPst */
+ #define _OT_S    OT_Symbol       /*  22 chars; Symbol */
+ #define _OT_V    OT_V            /* 172 chars; V */
+ #define _OT_VA   OT_VAbv         /*  18 chars; VAbv */
+@@ -112,7 +114,7 @@ static_assert (OT_VPst == M_Cat(VPst), "");
+ #define _POS_A   POS_AFTER_MAIN  /*   3 chars; AFTER_MAIN */
+ #define _POS_AP  POS_AFTER_POST  /*  50 chars; AFTER_POST */
+ #define _POS_AS  POS_AFTER_SUB   /*  51 chars; AFTER_SUB */
+-#define _POS_C   POS_BASE_C      /* 833 chars; BASE_C */
++#define _POS_C   POS_BASE_C      /* 853 chars; BASE_C */
+ #define _POS_BS  POS_BEFORE_SUB  /*  25 chars; BEFORE_SUB */
+ #define _POS_B   POS_BELOW_C     /*  13 chars; BELOW_C */
+ #define _POS_X   POS_END         /*  71 chars; END */
+@@ -145,7 +147,7 @@ static const uint16_t indic_table[] = {
+ 
+   /* Latin-1 Supplement */
+ 
+-  /* 00B0 */  _(X,X),  _(X,X),_(SM,SM),_(SM,SM),  _(X,X),  _(X,X),  _(X,X),  _(X,X),
++  /* 00B0 */  _(X,X),  _(X,X),_(SP,SM),_(SP,SM),  _(X,X),  _(X,X),  _(X,X),  _(X,X),
+   /* 00B8 */  _(X,X),  _(X,X),  _(X,X),  _(X,X),  _(X,X),  _(X,X),  _(X,X),  _(X,X),
+   /* 00C0 */  _(X,X),  _(X,X),  _(X,X),  _(X,X),  _(X,X),  _(X,X),  _(X,X),  _(X,X),
+   /* 00C8 */  _(X,X),  _(X,X),  _(X,X),  _(X,X),  _(X,X),  _(X,X),  _(X,X),  _(X,X),
+@@ -398,9 +400,9 @@ static const uint16_t indic_table[] = {
+ 
+   /* Superscripts and Subscripts */
+ 
+-  /* 2070 */  _(X,X),  _(X,X),  _(X,X),  _(X,X),_(SM,SM),  _(X,X),  _(X,X),  _(X,X),
++  /* 2070 */  _(X,X),  _(X,X),  _(X,X),  _(X,X),_(SP,SM),  _(X,X),  _(X,X),  _(X,X),
+   /* 2078 */  _(X,X),  _(X,X),  _(X,X),  _(X,X),  _(X,X),  _(X,X),  _(X,X),  _(X,X),
+-  /* 2080 */  _(X,X),  _(X,X),_(SM,SM),_(SM,SM),_(SM,SM),  _(X,X),  _(X,X),  _(X,X),
++  /* 2080 */  _(X,X),  _(X,X),_(SP,SM),_(SP,SM),_(SP,SM),  _(X,X),  _(X,X),  _(X,X),
+ 
+ #define indic_offset_0x25f8u 1592
+ 
+@@ -458,7 +460,16 @@ static const uint16_t indic_table[] = {
+ 
+   /* 11338 */  _(X,X),  _(X,X),  _(X,X),  _(N,X),  _(N,X),  _(X,X),  _(X,X),  _(X,X),
+ 
+-}; /* Table items: 1728; occupancy: 71% */
++#define indic_offset_0x116d0u 1728
++
++
++  /* Myanmar Extended-C */
++
++  /* 116D0 */ _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C),
++  /* 116D8 */ _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C),
++  /* 116E0 */ _(GB,C), _(GB,C), _(GB,C), _(GB,C),  _(X,X),  _(X,X),  _(X,X),  _(X,X),
++
++}; /* Table items: 1752; occupancy: 71% */
+ 
+ uint16_t
+ hb_indic_get_categories (hb_codepoint_t u)
+@@ -498,6 +509,7 @@ hb_indic_get_categories (hb_codepoint_t u)
+     case 0x11u:
+       if (hb_in_range (u, 0x11300u, 0x11307u)) return indic_table[u - 0x11300u + indic_offset_0x11300u];
+       if (hb_in_range (u, 0x11338u, 0x1133Fu)) return indic_table[u - 0x11338u + indic_offset_0x11338u];
++      if (hb_in_range (u, 0x116D0u, 0x116E7u)) return indic_table[u - 0x116D0u + indic_offset_0x116d0u];
+       break;
+ 
+     default:
+@@ -530,6 +542,7 @@ hb_indic_get_categories (hb_codepoint_t u)
+ #undef _OT_Rf
+ #undef _OT_Rt
+ #undef _OT_SM
++#undef _OT_SP
+ #undef _OT_S
+ #undef _OT_V
+ #undef _OT_VA
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-myanmar-machine.hh b/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-myanmar-machine.hh
+index 3dcf61b93..64eb761b4 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-myanmar-machine.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-myanmar-machine.hh
+@@ -68,6 +68,7 @@ enum myanmar_syllable_type_t {
+ #define myanmar_syllable_machine_ex_PT 39u
+ #define myanmar_syllable_machine_ex_Ra 15u
+ #define myanmar_syllable_machine_ex_SM 8u
++#define myanmar_syllable_machine_ex_SMPst 57u
+ #define myanmar_syllable_machine_ex_VAbv 20u
+ #define myanmar_syllable_machine_ex_VBlw 21u
+ #define myanmar_syllable_machine_ex_VPre 22u
+@@ -77,35 +78,35 @@ enum myanmar_syllable_type_t {
+ #define myanmar_syllable_machine_ex_ZWNJ 5u
+ 
+ 
+-#line 81 "hb-ot-shaper-myanmar-machine.hh"
++#line 82 "hb-ot-shaper-myanmar-machine.hh"
+ static const unsigned char _myanmar_syllable_machine_trans_keys[] = {
+-        1u, 41u, 3u, 41u, 5u, 39u, 5u, 8u, 3u, 41u, 3u, 39u, 3u, 39u, 5u, 39u,
+-        5u, 39u, 3u, 39u, 3u, 39u, 3u, 41u, 5u, 39u, 1u, 15u, 3u, 39u, 3u, 39u,
+-        3u, 40u, 3u, 39u, 3u, 41u, 3u, 41u, 3u, 39u, 3u, 41u, 3u, 41u, 3u, 41u,
+-        3u, 41u, 3u, 41u, 5u, 39u, 5u, 8u, 3u, 41u, 3u, 39u, 3u, 39u, 5u, 39u,
+-        5u, 39u, 3u, 39u, 3u, 39u, 3u, 41u, 5u, 39u, 1u, 15u, 3u, 41u, 3u, 39u,
+-        3u, 39u, 3u, 40u, 3u, 39u, 3u, 41u, 3u, 41u, 3u, 39u, 3u, 41u, 3u, 41u,
+-        3u, 41u, 3u, 41u, 3u, 41u, 3u, 41u, 3u, 41u, 1u, 41u, 1u, 15u, 0
++        1u, 57u, 3u, 57u, 5u, 57u, 5u, 57u, 3u, 57u, 5u, 57u, 3u, 57u, 3u, 57u,
++        3u, 57u, 3u, 57u, 3u, 57u, 5u, 57u, 1u, 15u, 3u, 57u, 3u, 57u, 3u, 57u,
++        3u, 57u, 3u, 57u, 3u, 57u, 3u, 57u, 3u, 57u, 3u, 57u, 3u, 57u, 3u, 57u,
++        3u, 57u, 5u, 57u, 5u, 57u, 3u, 57u, 5u, 57u, 3u, 57u, 3u, 57u, 3u, 57u,
++        3u, 57u, 3u, 57u, 5u, 57u, 1u, 15u, 3u, 57u, 3u, 57u, 3u, 57u, 3u, 57u,
++        3u, 57u, 3u, 57u, 3u, 57u, 3u, 57u, 3u, 57u, 3u, 57u, 3u, 57u, 3u, 57u,
++        3u, 57u, 3u, 57u, 3u, 57u, 1u, 57u, 1u, 15u, 0
+ };
+ 
+ static const char _myanmar_syllable_machine_key_spans[] = {
+-        41, 39, 35, 4, 39, 37, 37, 35,
+-        35, 37, 37, 39, 35, 15, 37, 37,
+-        38, 37, 39, 39, 37, 39, 39, 39,
+-        39, 39, 35, 4, 39, 37, 37, 35,
+-        35, 37, 37, 39, 35, 15, 39, 37,
+-        37, 38, 37, 39, 39, 37, 39, 39,
+-        39, 39, 39, 39, 39, 41, 15
++        57, 55, 53, 53, 55, 53, 55, 55,
++        55, 55, 55, 53, 15, 55, 55, 55,
++        55, 55, 55, 55, 55, 55, 55, 55,
++        55, 53, 53, 55, 53, 55, 55, 55,
++        55, 55, 53, 15, 55, 55, 55, 55,
++        55, 55, 55, 55, 55, 55, 55, 55,
++        55, 55, 55, 57, 15
+ };
+ 
+ static const short _myanmar_syllable_machine_index_offsets[] = {
+-        0, 42, 82, 118, 123, 163, 201, 239,
+-        275, 311, 349, 387, 427, 463, 479, 517,
+-        555, 594, 632, 672, 712, 750, 790, 830,
+-        870, 910, 950, 986, 991, 1031, 1069, 1107,
+-        1143, 1179, 1217, 1255, 1295, 1331, 1347, 1387,
+-        1425, 1463, 1502, 1540, 1580, 1620, 1658, 1698,
+-        1738, 1778, 1818, 1858, 1898, 1938, 1980
++        0, 58, 114, 168, 222, 278, 332, 388,
++        444, 500, 556, 612, 666, 682, 738, 794,
++        850, 906, 962, 1018, 1074, 1130, 1186, 1242,
++        1298, 1354, 1408, 1462, 1518, 1572, 1628, 1684,
++        1740, 1796, 1852, 1906, 1922, 1978, 2034, 2090,
++        2146, 2202, 2258, 2314, 2370, 2426, 2482, 2538,
++        2594, 2650, 2706, 2762, 2820
+ };
+ 
+ static const char _myanmar_syllable_machine_indicies[] = {
+@@ -114,273 +115,378 @@ static const char _myanmar_syllable_machine_indicies[] = {
+         0, 8, 0, 9, 10, 11, 12, 0,
+         0, 0, 0, 0, 0, 0, 0, 13,
+         0, 0, 14, 15, 16, 17, 18, 19,
+-        20, 0, 22, 23, 24, 24, 21, 25,
+-        26, 21, 21, 21, 21, 21, 21, 21,
+-        21, 21, 21, 27, 28, 29, 30, 21,
+-        21, 21, 21, 21, 21, 21, 21, 31,
+-        21, 21, 32, 33, 34, 35, 36, 37,
+-        38, 21, 24, 24, 21, 25, 21, 21,
+-        21, 21, 21, 21, 21, 21, 21, 21,
+-        21, 21, 21, 21, 30, 21, 21, 21,
+-        21, 21, 21, 21, 21, 39, 21, 21,
+-        21, 21, 21, 21, 36, 21, 24, 24,
+-        21, 25, 21, 22, 21, 24, 24, 21,
+-        25, 26, 21, 21, 21, 21, 21, 21,
+-        21, 21, 21, 21, 40, 21, 21, 30,
+-        21, 21, 21, 21, 21, 21, 21, 21,
+-        41, 21, 21, 42, 21, 21, 21, 36,
+-        21, 41, 21, 22, 21, 24, 24, 21,
+-        25, 26, 21, 21, 21, 21, 21, 21,
+-        21, 21, 21, 21, 21, 21, 21, 30,
+-        21, 21, 21, 21, 21, 21, 21, 21,
+-        21, 21, 21, 21, 21, 21, 21, 36,
+-        21, 43, 21, 24, 24, 21, 25, 36,
+-        21, 21, 21, 21, 21, 21, 21, 21,
+-        21, 21, 21, 21, 21, 21, 21, 21,
+-        21, 21, 21, 21, 21, 21, 44, 21,
+-        21, 21, 21, 21, 21, 36, 21, 24,
+-        24, 21, 25, 21, 21, 21, 21, 21,
+-        21, 21, 21, 21, 21, 21, 21, 21,
+-        21, 21, 21, 21, 21, 21, 21, 21,
+-        21, 21, 44, 21, 21, 21, 21, 21,
+-        21, 36, 21, 24, 24, 21, 25, 21,
+-        21, 21, 21, 21, 21, 21, 21, 21,
+-        21, 21, 21, 21, 21, 21, 21, 21,
+-        21, 21, 21, 21, 21, 21, 21, 21,
+-        21, 21, 21, 21, 21, 36, 21, 22,
+-        21, 24, 24, 21, 25, 26, 21, 21,
+-        21, 21, 21, 21, 21, 21, 21, 21,
+-        40, 21, 21, 30, 21, 21, 21, 21,
+-        21, 21, 21, 21, 21, 21, 21, 21,
+-        21, 21, 21, 36, 21, 22, 21, 24,
+-        24, 21, 25, 26, 21, 21, 21, 21,
+-        21, 21, 21, 21, 21, 21, 40, 21,
+-        21, 30, 21, 21, 21, 21, 21, 21,
+-        21, 21, 41, 21, 21, 21, 21, 21,
+-        21, 36, 21, 22, 21, 24, 24, 21,
+-        25, 26, 21, 21, 21, 21, 21, 21,
+-        21, 21, 21, 21, 40, 21, 21, 30,
+-        21, 21, 21, 21, 21, 21, 21, 21,
+-        41, 21, 21, 21, 21, 21, 21, 36,
+-        21, 41, 21, 24, 24, 21, 25, 21,
+-        21, 21, 21, 21, 21, 21, 21, 21,
+-        21, 21, 21, 21, 21, 30, 21, 21,
+-        21, 21, 21, 21, 21, 21, 21, 21,
+-        21, 21, 21, 21, 21, 36, 21, 1,
+-        1, 21, 21, 21, 21, 21, 21, 21,
+-        21, 21, 21, 21, 21, 1, 21, 22,
+-        21, 24, 24, 21, 25, 26, 21, 21,
+-        21, 21, 21, 21, 21, 21, 21, 21,
+-        27, 28, 21, 30, 21, 21, 21, 21,
+-        21, 21, 21, 21, 21, 21, 21, 21,
+-        21, 21, 21, 36, 21, 22, 21, 24,
+-        24, 21, 25, 26, 21, 21, 21, 21,
+-        21, 21, 21, 21, 21, 21, 21, 28,
+-        21, 30, 21, 21, 21, 21, 21, 21,
+-        21, 21, 21, 21, 21, 21, 21, 21,
+-        21, 36, 21, 22, 21, 24, 24, 21,
+-        25, 26, 21, 21, 21, 21, 21, 21,
+-        21, 21, 21, 21, 27, 28, 29, 30,
+-        21, 21, 21, 21, 21, 21, 21, 21,
+-        21, 21, 21, 21, 21, 21, 21, 36,
+-        45, 21, 22, 21, 24, 24, 21, 25,
+-        26, 21, 21, 21, 21, 21, 21, 21,
+-        21, 21, 21, 27, 28, 29, 30, 21,
+-        21, 21, 21, 21, 21, 21, 21, 21,
+-        21, 21, 21, 21, 21, 21, 36, 21,
+-        22, 21, 24, 24, 21, 25, 26, 21,
+-        21, 21, 21, 21, 21, 21, 21, 21,
+-        21, 27, 28, 29, 30, 21, 21, 21,
+-        21, 21, 21, 21, 21, 31, 21, 21,
+-        32, 33, 34, 35, 36, 21, 38, 21,
+-        22, 21, 24, 24, 21, 25, 26, 21,
+-        21, 21, 21, 21, 21, 21, 21, 21,
+-        21, 27, 28, 29, 30, 21, 21, 21,
+-        21, 21, 21, 21, 21, 45, 21, 21,
+-        21, 21, 21, 21, 36, 21, 38, 21,
+-        22, 21, 24, 24, 21, 25, 26, 21,
+-        21, 21, 21, 21, 21, 21, 21, 21,
+-        21, 27, 28, 29, 30, 21, 21, 21,
+-        21, 21, 21, 21, 21, 45, 21, 21,
+-        21, 21, 21, 21, 36, 21, 22, 21,
+-        24, 24, 21, 25, 26, 21, 21, 21,
+-        21, 21, 21, 21, 21, 21, 21, 27,
+-        28, 29, 30, 21, 21, 21, 21, 21,
+-        21, 21, 21, 21, 21, 21, 32, 21,
+-        34, 21, 36, 21, 38, 21, 22, 21,
+-        24, 24, 21, 25, 26, 21, 21, 21,
+-        21, 21, 21, 21, 21, 21, 21, 27,
+-        28, 29, 30, 21, 21, 21, 21, 21,
+-        21, 21, 21, 45, 21, 21, 32, 21,
+-        21, 21, 36, 21, 38, 21, 22, 21,
+-        24, 24, 21, 25, 26, 21, 21, 21,
+-        21, 21, 21, 21, 21, 21, 21, 27,
+-        28, 29, 30, 21, 21, 21, 21, 21,
+-        21, 21, 21, 46, 21, 21, 32, 33,
+-        34, 21, 36, 21, 38, 21, 22, 21,
+-        24, 24, 21, 25, 26, 21, 21, 21,
+-        21, 21, 21, 21, 21, 21, 21, 27,
+-        28, 29, 30, 21, 21, 21, 21, 21,
+-        21, 21, 21, 21, 21, 21, 32, 33,
+-        34, 21, 36, 21, 38, 21, 22, 23,
+-        24, 24, 21, 25, 26, 21, 21, 21,
+-        21, 21, 21, 21, 21, 21, 21, 27,
+-        28, 29, 30, 21, 21, 21, 21, 21,
+-        21, 21, 21, 31, 21, 21, 32, 33,
+-        34, 35, 36, 21, 38, 21, 48, 48,
++        20, 0, 0, 0, 0, 0, 0, 0,
++        0, 0, 0, 0, 0, 0, 0, 0,
++        21, 0, 23, 24, 25, 25, 22, 26,
++        27, 22, 22, 22, 22, 22, 22, 22,
++        22, 22, 22, 28, 29, 30, 31, 22,
++        22, 22, 22, 22, 22, 22, 22, 32,
++        22, 22, 33, 34, 35, 36, 37, 38,
++        39, 22, 22, 22, 22, 22, 22, 22,
++        22, 22, 22, 22, 22, 22, 22, 22,
++        26, 22, 25, 25, 22, 26, 22, 22,
++        22, 22, 22, 22, 22, 22, 22, 22,
++        22, 22, 22, 22, 31, 22, 22, 22,
++        22, 22, 22, 22, 22, 40, 22, 22,
++        22, 22, 22, 22, 37, 22, 22, 22,
++        22, 22, 22, 22, 22, 22, 22, 22,
++        22, 22, 22, 22, 22, 22, 26, 22,
++        25, 25, 22, 26, 22, 22, 22, 22,
++        22, 22, 22, 22, 22, 22, 22, 22,
++        22, 22, 22, 22, 22, 22, 22, 22,
++        22, 22, 22, 22, 22, 22, 22, 22,
++        22, 22, 37, 22, 22, 22, 22, 22,
++        22, 22, 22, 22, 22, 22, 22, 22,
++        22, 22, 22, 22, 26, 22, 41, 22,
++        25, 25, 22, 26, 37, 22, 22, 22,
++        22, 22, 22, 22, 22, 22, 22, 22,
++        22, 22, 22, 22, 22, 22, 22, 22,
++        22, 22, 22, 26, 22, 22, 22, 22,
++        22, 22, 37, 22, 22, 22, 22, 22,
++        22, 22, 22, 22, 22, 22, 22, 22,
++        22, 22, 22, 22, 26, 22, 25, 25,
++        22, 26, 22, 22, 22, 22, 22, 22,
++        22, 22, 22, 22, 22, 22, 22, 22,
++        22, 22, 22, 22, 22, 22, 22, 22,
++        22, 26, 22, 22, 22, 22, 22, 22,
++        37, 22, 22, 22, 22, 22, 22, 22,
++        22, 22, 22, 22, 22, 22, 22, 22,
++        22, 22, 26, 22, 23, 22, 25, 25,
++        22, 26, 27, 22, 22, 22, 22, 22,
++        22, 22, 22, 22, 22, 42, 22, 22,
++        31, 22, 22, 22, 22, 22, 22, 22,
++        22, 43, 22, 22, 44, 22, 22, 22,
++        37, 22, 43, 22, 22, 22, 22, 22,
++        22, 22, 22, 22, 22, 22, 22, 22,
++        22, 22, 26, 22, 23, 22, 25, 25,
++        22, 26, 27, 22, 22, 22, 22, 22,
++        22, 22, 22, 22, 22, 22, 22, 22,
++        31, 22, 22, 22, 22, 22, 22, 22,
++        22, 22, 22, 22, 22, 22, 22, 22,
++        37, 22, 22, 22, 22, 22, 22, 22,
++        22, 22, 22, 22, 22, 22, 22, 22,
++        22, 22, 26, 22, 23, 22, 25, 25,
++        22, 26, 27, 22, 22, 22, 22, 22,
++        22, 22, 22, 22, 22, 42, 22, 22,
++        31, 22, 22, 22, 22, 22, 22, 22,
++        22, 22, 22, 22, 22, 22, 22, 22,
++        37, 22, 22, 22, 22, 22, 22, 22,
++        22, 22, 22, 22, 22, 22, 22, 22,
++        22, 22, 26, 22, 23, 22, 25, 25,
++        22, 26, 27, 22, 22, 22, 22, 22,
++        22, 22, 22, 22, 22, 42, 22, 22,
++        31, 22, 22, 22, 22, 22, 22, 22,
++        22, 43, 22, 22, 22, 22, 22, 22,
++        37, 22, 22, 22, 22, 22, 22, 22,
++        22, 22, 22, 22, 22, 22, 22, 22,
++        22, 22, 26, 22, 23, 22, 25, 25,
++        22, 26, 27, 22, 22, 22, 22, 22,
++        22, 22, 22, 22, 22, 42, 22, 22,
++        31, 22, 22, 22, 22, 22, 22, 22,
++        22, 43, 22, 22, 22, 22, 22, 22,
++        37, 22, 43, 22, 22, 22, 22, 22,
++        22, 22, 22, 22, 22, 22, 22, 22,
++        22, 22, 26, 22, 25, 25, 22, 26,
++        22, 22, 22, 22, 22, 22, 22, 22,
++        22, 22, 22, 22, 22, 22, 31, 22,
++        22, 22, 22, 22, 22, 22, 22, 22,
++        22, 22, 22, 22, 22, 22, 37, 22,
++        22, 22, 22, 22, 22, 22, 22, 22,
++        22, 22, 22, 22, 22, 22, 22, 22,
++        26, 22, 1, 1, 22, 22, 22, 22,
++        22, 22, 22, 22, 22, 22, 22, 22,
++        1, 22, 23, 22, 25, 25, 22, 26,
++        27, 22, 22, 22, 22, 22, 22, 22,
++        22, 22, 22, 28, 29, 22, 31, 22,
++        22, 22, 22, 22, 22, 22, 22, 22,
++        22, 22, 22, 22, 22, 22, 37, 22,
++        22, 22, 22, 22, 22, 22, 22, 22,
++        22, 22, 22, 22, 22, 22, 22, 22,
++        26, 22, 23, 22, 25, 25, 22, 26,
++        27, 22, 22, 22, 22, 22, 22, 22,
++        22, 22, 22, 22, 29, 22, 31, 22,
++        22, 22, 22, 22, 22, 22, 22, 22,
++        22, 22, 22, 22, 22, 22, 37, 22,
++        22, 22, 22, 22, 22, 22, 22, 22,
++        22, 22, 22, 22, 22, 22, 22, 22,
++        26, 22, 23, 22, 25, 25, 22, 26,
++        27, 22, 22, 22, 22, 22, 22, 22,
++        22, 22, 22, 28, 29, 30, 31, 22,
++        22, 22, 22, 22, 22, 22, 22, 22,
++        22, 22, 22, 22, 22, 22, 37, 45,
++        22, 22, 22, 22, 22, 22, 22, 22,
++        22, 22, 22, 22, 22, 22, 22, 22,
++        26, 22, 23, 22, 25, 25, 22, 26,
++        27, 22, 22, 22, 22, 22, 22, 22,
++        22, 22, 22, 28, 29, 30, 31, 22,
++        22, 22, 22, 22, 22, 22, 22, 22,
++        22, 22, 22, 22, 22, 22, 37, 22,
++        22, 22, 22, 22, 22, 22, 22, 22,
++        22, 22, 22, 22, 22, 22, 22, 22,
++        26, 22, 23, 22, 25, 25, 22, 26,
++        27, 22, 22, 22, 22, 22, 22, 22,
++        22, 22, 22, 28, 29, 30, 31, 22,
++        22, 22, 22, 22, 22, 22, 22, 32,
++        22, 22, 33, 34, 35, 36, 37, 22,
++        39, 22, 22, 22, 22, 22, 22, 22,
++        22, 22, 22, 22, 22, 22, 22, 22,
++        26, 22, 23, 22, 25, 25, 22, 26,
++        27, 22, 22, 22, 22, 22, 22, 22,
++        22, 22, 22, 28, 29, 30, 31, 22,
++        22, 22, 22, 22, 22, 22, 22, 45,
++        22, 22, 22, 22, 22, 22, 37, 22,
++        39, 22, 22, 22, 22, 22, 22, 22,
++        22, 22, 22, 22, 22, 22, 22, 22,
++        26, 22, 23, 22, 25, 25, 22, 26,
++        27, 22, 22, 22, 22, 22, 22, 22,
++        22, 22, 22, 28, 29, 30, 31, 22,
++        22, 22, 22, 22, 22, 22, 22, 45,
++        22, 22, 22, 22, 22, 22, 37, 22,
++        22, 22, 22, 22, 22, 22, 22, 22,
++        22, 22, 22, 22, 22, 22, 22, 22,
++        26, 22, 23, 22, 25, 25, 22, 26,
++        27, 22, 22, 22, 22, 22, 22, 22,
++        22, 22, 22, 28, 29, 30, 31, 22,
++        22, 22, 22, 22, 22, 22, 22, 22,
++        22, 22, 33, 22, 35, 22, 37, 22,
++        39, 22, 22, 22, 22, 22, 22, 22,
++        22, 22, 22, 22, 22, 22, 22, 22,
++        26, 22, 23, 22, 25, 25, 22, 26,
++        27, 22, 22, 22, 22, 22, 22, 22,
++        22, 22, 22, 28, 29, 30, 31, 22,
++        22, 22, 22, 22, 22, 22, 22, 45,
++        22, 22, 33, 22, 22, 22, 37, 22,
++        39, 22, 22, 22, 22, 22, 22, 22,
++        22, 22, 22, 22, 22, 22, 22, 22,
++        26, 22, 23, 22, 25, 25, 22, 26,
++        27, 22, 22, 22, 22, 22, 22, 22,
++        22, 22, 22, 28, 29, 30, 31, 22,
++        22, 22, 22, 22, 22, 22, 22, 46,
++        22, 22, 33, 34, 35, 22, 37, 22,
++        39, 22, 22, 22, 22, 22, 22, 22,
++        22, 22, 22, 22, 22, 22, 22, 22,
++        26, 22, 23, 22, 25, 25, 22, 26,
++        27, 22, 22, 22, 22, 22, 22, 22,
++        22, 22, 22, 28, 29, 30, 31, 22,
++        22, 22, 22, 22, 22, 22, 22, 22,
++        22, 22, 33, 34, 35, 22, 37, 22,
++        39, 22, 22, 22, 22, 22, 22, 22,
++        22, 22, 22, 22, 22, 22, 22, 22,
++        26, 22, 23, 24, 25, 25, 22, 26,
++        27, 22, 22, 22, 22, 22, 22, 22,
++        22, 22, 22, 28, 29, 30, 31, 22,
++        22, 22, 22, 22, 22, 22, 22, 32,
++        22, 22, 33, 34, 35, 36, 37, 22,
++        39, 22, 22, 22, 22, 22, 22, 22,
++        22, 22, 22, 22, 22, 22, 22, 22,
++        26, 22, 48, 48, 47, 5, 47, 47,
++        47, 47, 47, 47, 47, 47, 47, 47,
++        47, 47, 47, 47, 12, 47, 47, 47,
++        47, 47, 47, 47, 47, 49, 47, 47,
++        47, 47, 47, 47, 18, 47, 47, 47,
++        47, 47, 47, 47, 47, 47, 47, 47,
++        47, 47, 47, 47, 47, 47, 5, 47,
++        48, 48, 50, 5, 50, 50, 50, 50,
++        50, 50, 50, 50, 50, 50, 50, 50,
++        50, 50, 50, 50, 50, 50, 50, 50,
++        50, 50, 50, 50, 50, 50, 50, 50,
++        50, 50, 18, 50, 50, 50, 50, 50,
++        50, 50, 50, 50, 50, 50, 50, 50,
++        50, 50, 50, 50, 5, 50, 51, 47,
++        48, 48, 47, 5, 18, 47, 47, 47,
++        47, 47, 47, 47, 47, 47, 47, 47,
++        47, 47, 47, 47, 47, 47, 47, 47,
++        47, 47, 47, 5, 47, 47, 47, 47,
++        47, 47, 18, 47, 47, 47, 47, 47,
++        47, 47, 47, 47, 47, 47, 47, 47,
++        47, 47, 47, 47, 5, 47, 48, 48,
+         47, 5, 47, 47, 47, 47, 47, 47,
+         47, 47, 47, 47, 47, 47, 47, 47,
++        47, 47, 47, 47, 47, 47, 47, 47,
++        47, 5, 47, 47, 47, 47, 47, 47,
++        18, 47, 47, 47, 47, 47, 47, 47,
++        47, 47, 47, 47, 47, 47, 47, 47,
++        47, 47, 5, 47, 2, 47, 48, 48,
++        47, 5, 6, 47, 47, 47, 47, 47,
++        47, 47, 47, 47, 47, 52, 47, 47,
++        12, 47, 47, 47, 47, 47, 47, 47,
++        47, 53, 47, 47, 54, 47, 47, 47,
++        18, 47, 53, 47, 47, 47, 47, 47,
++        47, 47, 47, 47, 47, 47, 47, 47,
++        47, 47, 5, 47, 2, 47, 48, 48,
++        47, 5, 6, 47, 47, 47, 47, 47,
++        47, 47, 47, 47, 47, 47, 47, 47,
++        12, 47, 47, 47, 47, 47, 47, 47,
++        47, 47, 47, 47, 47, 47, 47, 47,
++        18, 47, 47, 47, 47, 47, 47, 47,
++        47, 47, 47, 47, 47, 47, 47, 47,
++        47, 47, 5, 47, 2, 47, 48, 48,
++        47, 5, 6, 47, 47, 47, 47, 47,
++        47, 47, 47, 47, 47, 52, 47, 47,
++        12, 47, 47, 47, 47, 47, 47, 47,
++        47, 47, 47, 47, 47, 47, 47, 47,
++        18, 47, 47, 47, 47, 47, 47, 47,
++        47, 47, 47, 47, 47, 47, 47, 47,
++        47, 47, 5, 47, 2, 47, 48, 48,
++        47, 5, 6, 47, 47, 47, 47, 47,
++        47, 47, 47, 47, 47, 52, 47, 47,
++        12, 47, 47, 47, 47, 47, 47, 47,
++        47, 53, 47, 47, 47, 47, 47, 47,
++        18, 47, 47, 47, 47, 47, 47, 47,
++        47, 47, 47, 47, 47, 47, 47, 47,
++        47, 47, 5, 47, 2, 47, 48, 48,
++        47, 5, 6, 47, 47, 47, 47, 47,
++        47, 47, 47, 47, 47, 52, 47, 47,
+         12, 47, 47, 47, 47, 47, 47, 47,
+-        47, 49, 47, 47, 47, 47, 47, 47,
+-        18, 47, 48, 48, 47, 5, 47, 2,
+-        47, 48, 48, 47, 5, 6, 47, 47,
++        47, 53, 47, 47, 47, 47, 47, 47,
++        18, 47, 53, 47, 47, 47, 47, 47,
+         47, 47, 47, 47, 47, 47, 47, 47,
+-        50, 47, 47, 12, 47, 47, 47, 47,
+-        47, 47, 47, 47, 51, 47, 47, 52,
+-        47, 47, 47, 18, 47, 51, 47, 2,
+-        47, 48, 48, 47, 5, 6, 47, 47,
++        47, 47, 5, 47, 48, 48, 47, 5,
+         47, 47, 47, 47, 47, 47, 47, 47,
+-        47, 47, 47, 12, 47, 47, 47, 47,
++        47, 47, 47, 47, 47, 47, 12, 47,
+         47, 47, 47, 47, 47, 47, 47, 47,
+-        47, 47, 47, 18, 47, 53, 47, 48,
+-        48, 47, 5, 18, 47, 47, 47, 47,
++        47, 47, 47, 47, 47, 47, 18, 47,
+         47, 47, 47, 47, 47, 47, 47, 47,
+         47, 47, 47, 47, 47, 47, 47, 47,
+-        47, 47, 54, 47, 47, 47, 47, 47,
+-        47, 18, 47, 48, 48, 47, 5, 47,
++        5, 47, 55, 55, 47, 47, 47, 47,
+         47, 47, 47, 47, 47, 47, 47, 47,
++        55, 47, 2, 3, 48, 48, 47, 5,
++        6, 47, 47, 47, 47, 47, 47, 47,
++        47, 47, 47, 9, 10, 11, 12, 47,
++        47, 47, 47, 47, 47, 47, 47, 13,
++        47, 47, 14, 15, 16, 17, 18, 19,
++        20, 47, 47, 47, 47, 47, 47, 47,
+         47, 47, 47, 47, 47, 47, 47, 47,
+-        47, 47, 47, 47, 47, 47, 54, 47,
+-        47, 47, 47, 47, 47, 18, 47, 48,
+-        48, 47, 5, 47, 47, 47, 47, 47,
++        5, 47, 2, 47, 48, 48, 47, 5,
++        6, 47, 47, 47, 47, 47, 47, 47,
++        47, 47, 47, 9, 10, 47, 12, 47,
+         47, 47, 47, 47, 47, 47, 47, 47,
++        47, 47, 47, 47, 47, 47, 18, 47,
+         47, 47, 47, 47, 47, 47, 47, 47,
+         47, 47, 47, 47, 47, 47, 47, 47,
+-        47, 18, 47, 2, 47, 48, 48, 47,
+-        5, 6, 47, 47, 47, 47, 47, 47,
+-        47, 47, 47, 47, 50, 47, 47, 12,
++        5, 47, 2, 47, 48, 48, 47, 5,
++        6, 47, 47, 47, 47, 47, 47, 47,
++        47, 47, 47, 47, 10, 47, 12, 47,
+         47, 47, 47, 47, 47, 47, 47, 47,
+-        47, 47, 47, 47, 47, 47, 47, 18,
+-        47, 2, 47, 48, 48, 47, 5, 6,
++        47, 47, 47, 47, 47, 47, 18, 47,
+         47, 47, 47, 47, 47, 47, 47, 47,
+-        47, 47, 50, 47, 47, 12, 47, 47,
+-        47, 47, 47, 47, 47, 47, 51, 47,
+-        47, 47, 47, 47, 47, 18, 47, 2,
+-        47, 48, 48, 47, 5, 6, 47, 47,
+         47, 47, 47, 47, 47, 47, 47, 47,
+-        50, 47, 47, 12, 47, 47, 47, 47,
+-        47, 47, 47, 47, 51, 47, 47, 47,
+-        47, 47, 47, 18, 47, 51, 47, 48,
+-        48, 47, 5, 47, 47, 47, 47, 47,
++        5, 47, 2, 47, 48, 48, 47, 5,
++        6, 47, 47, 47, 47, 47, 47, 47,
++        47, 47, 47, 9, 10, 11, 12, 47,
+         47, 47, 47, 47, 47, 47, 47, 47,
+-        47, 12, 47, 47, 47, 47, 47, 47,
++        47, 47, 47, 47, 47, 47, 18, 56,
+         47, 47, 47, 47, 47, 47, 47, 47,
+-        47, 18, 47, 55, 55, 47, 47, 47,
+         47, 47, 47, 47, 47, 47, 47, 47,
+-        47, 55, 47, 2, 3, 48, 48, 47,
+-        5, 6, 47, 47, 47, 47, 47, 47,
+-        47, 47, 47, 47, 9, 10, 11, 12,
++        5, 47, 2, 47, 48, 48, 47, 5,
++        6, 47, 47, 47, 47, 47, 47, 47,
++        47, 47, 47, 9, 10, 11, 12, 47,
+         47, 47, 47, 47, 47, 47, 47, 47,
+-        13, 47, 47, 14, 15, 16, 17, 18,
+-        19, 20, 47, 2, 47, 48, 48, 47,
+-        5, 6, 47, 47, 47, 47, 47, 47,
+-        47, 47, 47, 47, 9, 10, 47, 12,
++        47, 47, 47, 47, 47, 47, 18, 47,
+         47, 47, 47, 47, 47, 47, 47, 47,
+-        47, 47, 47, 47, 47, 47, 47, 18,
+-        47, 2, 47, 48, 48, 47, 5, 6,
+         47, 47, 47, 47, 47, 47, 47, 47,
+-        47, 47, 47, 10, 47, 12, 47, 47,
++        5, 47, 2, 47, 48, 48, 47, 5,
++        6, 47, 47, 47, 47, 47, 47, 47,
++        47, 47, 47, 9, 10, 11, 12, 47,
++        47, 47, 47, 47, 47, 47, 47, 13,
++        47, 47, 14, 15, 16, 17, 18, 47,
++        20, 47, 47, 47, 47, 47, 47, 47,
+         47, 47, 47, 47, 47, 47, 47, 47,
+-        47, 47, 47, 47, 47, 18, 47, 2,
+-        47, 48, 48, 47, 5, 6, 47, 47,
++        5, 47, 2, 47, 48, 48, 47, 5,
++        6, 47, 47, 47, 47, 47, 47, 47,
++        47, 47, 47, 9, 10, 11, 12, 47,
++        47, 47, 47, 47, 47, 47, 47, 56,
++        47, 47, 47, 47, 47, 47, 18, 47,
++        20, 47, 47, 47, 47, 47, 47, 47,
+         47, 47, 47, 47, 47, 47, 47, 47,
+-        9, 10, 11, 12, 47, 47, 47, 47,
++        5, 47, 2, 47, 48, 48, 47, 5,
++        6, 47, 47, 47, 47, 47, 47, 47,
++        47, 47, 47, 9, 10, 11, 12, 47,
++        47, 47, 47, 47, 47, 47, 47, 56,
++        47, 47, 47, 47, 47, 47, 18, 47,
+         47, 47, 47, 47, 47, 47, 47, 47,
+-        47, 47, 47, 18, 56, 47, 2, 47,
+-        48, 48, 47, 5, 6, 47, 47, 47,
+-        47, 47, 47, 47, 47, 47, 47, 9,
+-        10, 11, 12, 47, 47, 47, 47, 47,
+         47, 47, 47, 47, 47, 47, 47, 47,
+-        47, 47, 18, 47, 2, 47, 48, 48,
+-        47, 5, 6, 47, 47, 47, 47, 47,
+-        47, 47, 47, 47, 47, 9, 10, 11,
+-        12, 47, 47, 47, 47, 47, 47, 47,
+-        47, 13, 47, 47, 14, 15, 16, 17,
+-        18, 47, 20, 47, 2, 47, 48, 48,
+-        47, 5, 6, 47, 47, 47, 47, 47,
+-        47, 47, 47, 47, 47, 9, 10, 11,
+-        12, 47, 47, 47, 47, 47, 47, 47,
+-        47, 56, 47, 47, 47, 47, 47, 47,
+-        18, 47, 20, 47, 2, 47, 48, 48,
+-        47, 5, 6, 47, 47, 47, 47, 47,
+-        47, 47, 47, 47, 47, 9, 10, 11,
+-        12, 47, 47, 47, 47, 47, 47, 47,
+-        47, 56, 47, 47, 47, 47, 47, 47,
+-        18, 47, 2, 47, 48, 48, 47, 5,
++        5, 47, 2, 47, 48, 48, 47, 5,
+         6, 47, 47, 47, 47, 47, 47, 47,
+         47, 47, 47, 9, 10, 11, 12, 47,
+         47, 47, 47, 47, 47, 47, 47, 47,
+         47, 47, 14, 47, 16, 47, 18, 47,
+-        20, 47, 2, 47, 48, 48, 47, 5,
++        20, 47, 47, 47, 47, 47, 47, 47,
++        47, 47, 47, 47, 47, 47, 47, 47,
++        5, 47, 2, 47, 48, 48, 47, 5,
+         6, 47, 47, 47, 47, 47, 47, 47,
+         47, 47, 47, 9, 10, 11, 12, 47,
+         47, 47, 47, 47, 47, 47, 47, 56,
+         47, 47, 14, 47, 47, 47, 18, 47,
+-        20, 47, 2, 47, 48, 48, 47, 5,
++        20, 47, 47, 47, 47, 47, 47, 47,
++        47, 47, 47, 47, 47, 47, 47, 47,
++        5, 47, 2, 47, 48, 48, 47, 5,
+         6, 47, 47, 47, 47, 47, 47, 47,
+         47, 47, 47, 9, 10, 11, 12, 47,
+         47, 47, 47, 47, 47, 47, 47, 57,
+         47, 47, 14, 15, 16, 47, 18, 47,
+-        20, 47, 2, 47, 48, 48, 47, 5,
++        20, 47, 47, 47, 47, 47, 47, 47,
++        47, 47, 47, 47, 47, 47, 47, 47,
++        5, 47, 2, 47, 48, 48, 47, 5,
+         6, 47, 47, 47, 47, 47, 47, 47,
+         47, 47, 47, 9, 10, 11, 12, 47,
+         47, 47, 47, 47, 47, 47, 47, 47,
+         47, 47, 14, 15, 16, 47, 18, 47,
+-        20, 47, 2, 3, 48, 48, 47, 5,
++        20, 47, 47, 47, 47, 47, 47, 47,
++        47, 47, 47, 47, 47, 47, 47, 47,
++        5, 47, 2, 3, 48, 48, 47, 5,
+         6, 47, 47, 47, 47, 47, 47, 47,
+         47, 47, 47, 9, 10, 11, 12, 47,
+         47, 47, 47, 47, 47, 47, 47, 13,
+         47, 47, 14, 15, 16, 17, 18, 47,
+-        20, 47, 22, 23, 24, 24, 21, 25,
+-        26, 21, 21, 21, 21, 21, 21, 21,
+-        21, 21, 21, 27, 28, 29, 30, 21,
+-        21, 21, 21, 21, 21, 21, 21, 58,
+-        21, 21, 32, 33, 34, 35, 36, 37,
+-        38, 21, 22, 59, 24, 24, 21, 25,
+-        26, 21, 21, 21, 21, 21, 21, 21,
+-        21, 21, 21, 27, 28, 29, 30, 21,
+-        21, 21, 21, 21, 21, 21, 21, 31,
+-        21, 21, 32, 33, 34, 35, 36, 21,
+-        38, 21, 1, 1, 2, 3, 48, 48,
++        20, 47, 47, 47, 47, 47, 47, 47,
++        47, 47, 47, 47, 47, 47, 47, 47,
++        5, 47, 23, 24, 25, 25, 22, 26,
++        27, 22, 22, 22, 22, 22, 22, 22,
++        22, 22, 22, 28, 29, 30, 31, 22,
++        22, 22, 22, 22, 22, 22, 22, 58,
++        22, 22, 33, 34, 35, 36, 37, 38,
++        39, 22, 22, 22, 22, 22, 22, 22,
++        22, 22, 22, 22, 22, 22, 22, 22,
++        26, 22, 23, 59, 25, 25, 22, 26,
++        27, 22, 22, 22, 22, 22, 22, 22,
++        22, 22, 22, 28, 29, 30, 31, 22,
++        22, 22, 22, 22, 22, 22, 22, 32,
++        22, 22, 33, 34, 35, 36, 37, 22,
++        39, 22, 22, 22, 22, 22, 22, 22,
++        22, 22, 22, 22, 22, 22, 22, 22,
++        26, 22, 1, 1, 2, 3, 48, 48,
+         47, 5, 6, 1, 1, 47, 47, 47,
+         1, 47, 47, 47, 47, 9, 10, 11,
+         12, 47, 47, 47, 47, 47, 47, 47,
+         47, 13, 47, 47, 14, 15, 16, 17,
+-        18, 19, 20, 47, 1, 1, 60, 60,
++        18, 19, 20, 47, 47, 47, 47, 47,
++        47, 47, 47, 47, 47, 47, 47, 47,
++        47, 47, 5, 47, 1, 1, 60, 60,
+         60, 60, 60, 60, 60, 1, 1, 60,
+         60, 60, 1, 60, 0
+ };
+ 
+ static const char _myanmar_syllable_machine_trans_targs[] = {
+-        0, 1, 26, 37, 0, 27, 29, 51,
+-        54, 39, 40, 41, 28, 43, 44, 46,
+-        47, 48, 30, 50, 45, 0, 2, 13,
+-        0, 3, 5, 14, 15, 16, 4, 18,
+-        19, 21, 22, 23, 6, 25, 20, 12,
+-        9, 10, 11, 7, 8, 17, 24, 0,
+-        0, 36, 33, 34, 35, 31, 32, 38,
+-        42, 49, 52, 53, 0
++        0, 1, 25, 35, 0, 26, 30, 49,
++        52, 37, 38, 39, 29, 41, 42, 44,
++        45, 46, 27, 48, 43, 26, 0, 2,
++        12, 0, 3, 7, 13, 14, 15, 6,
++        17, 18, 20, 21, 22, 4, 24, 19,
++        11, 5, 8, 9, 10, 16, 23, 0,
++        0, 34, 0, 28, 31, 32, 33, 36,
++        40, 47, 50, 51, 0
+ };
+ 
+ static const char _myanmar_syllable_machine_trans_actions[] = {
+-        3, 0, 0, 0, 4, 0, 0, 0,
++        3, 0, 0, 0, 4, 5, 0, 0,
+         0, 0, 0, 0, 0, 0, 0, 0,
+-        0, 0, 0, 0, 0, 5, 0, 0,
+-        6, 0, 0, 0, 0, 0, 0, 0,
++        0, 0, 0, 0, 0, 6, 7, 0,
++        0, 8, 0, 0, 0, 0, 0, 0,
+         0, 0, 0, 0, 0, 0, 0, 0,
+-        0, 0, 0, 0, 0, 0, 0, 7,
+-        8, 0, 0, 0, 0, 0, 0, 0,
+-        0, 0, 0, 0, 9
++        0, 0, 0, 0, 0, 0, 0, 9,
++        10, 0, 11, 0, 0, 0, 0, 0,
++        0, 0, 0, 0, 12
+ };
+ 
+ static const char _myanmar_syllable_machine_to_state_actions[] = {
+@@ -390,7 +496,7 @@ static const char _myanmar_syllable_machine_to_state_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, 0, 0, 0, 0, 0, 0
++        0, 0, 0, 0, 0
+ };
+ 
+ static const char _myanmar_syllable_machine_from_state_actions[] = {
+@@ -400,17 +506,17 @@ static const char _myanmar_syllable_machine_from_state_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, 0, 0, 0, 0, 0, 0
++        0, 0, 0, 0, 0
+ };
+ 
+ static const short _myanmar_syllable_machine_eof_trans[] = {
+-        0, 22, 22, 22, 22, 22, 22, 22,
+-        22, 22, 22, 22, 22, 22, 22, 22,
+-        22, 22, 22, 22, 22, 22, 22, 22,
+-        22, 22, 48, 48, 48, 48, 48, 48,
++        0, 23, 23, 23, 23, 23, 23, 23,
++        23, 23, 23, 23, 23, 23, 23, 23,
++        23, 23, 23, 23, 23, 23, 23, 23,
++        23, 48, 51, 48, 48, 48, 48, 48,
+         48, 48, 48, 48, 48, 48, 48, 48,
+         48, 48, 48, 48, 48, 48, 48, 48,
+-        48, 48, 48, 22, 22, 48, 61
++        48, 23, 23, 48, 61
+ };
+ 
+ static const int myanmar_syllable_machine_start = 0;
+@@ -424,7 +530,7 @@ static const int myanmar_syllable_machine_en_main = 0;
+ 
+ 
+ 
+-#line 117 "hb-ot-shaper-myanmar-machine.rl"
++#line 118 "hb-ot-shaper-myanmar-machine.rl"
+ 
+ 
+ #define found_syllable(syllable_type) \
+@@ -443,7 +549,7 @@ find_syllables_myanmar (hb_buffer_t *buffer)
+   int cs;
+   hb_glyph_info_t *info = buffer->info;
+ 
+-#line 447 "hb-ot-shaper-myanmar-machine.hh"
++#line 553 "hb-ot-shaper-myanmar-machine.hh"
+         {
+         cs = myanmar_syllable_machine_start;
+         ts = 0;
+@@ -451,7 +557,7 @@ find_syllables_myanmar (hb_buffer_t *buffer)
+         act = 0;
+         }
+ 
+-#line 137 "hb-ot-shaper-myanmar-machine.rl"
++#line 138 "hb-ot-shaper-myanmar-machine.rl"
+ 
+ 
+   p = 0;
+@@ -459,7 +565,7 @@ find_syllables_myanmar (hb_buffer_t *buffer)
+ 
+   unsigned int syllable_serial = 1;
+ 
+-#line 463 "hb-ot-shaper-myanmar-machine.hh"
++#line 569 "hb-ot-shaper-myanmar-machine.hh"
+         {
+         int _slen;
+         int _trans;
+@@ -473,7 +579,7 @@ _resume:
+ #line 1 "NONE"
+         {ts = p;}
+         break;
+-#line 477 "hb-ot-shaper-myanmar-machine.hh"
++#line 583 "hb-ot-shaper-myanmar-machine.hh"
+         }
+ 
+         _keys = _myanmar_syllable_machine_trans_keys + (cs<<1);
+@@ -491,35 +597,59 @@ _eof_trans:
+                 goto _again;
+ 
+         switch ( _myanmar_syllable_machine_trans_actions[_trans] ) {
+-        case 6:
+-#line 110 "hb-ot-shaper-myanmar-machine.rl"
++        case 8:
++#line 111 "hb-ot-shaper-myanmar-machine.rl"
+         {te = p+1;{ found_syllable (myanmar_consonant_syllable); }}
+         break;
+         case 4:
+-#line 111 "hb-ot-shaper-myanmar-machine.rl"
++#line 112 "hb-ot-shaper-myanmar-machine.rl"
+         {te = p+1;{ found_syllable (myanmar_non_myanmar_cluster); }}
+         break;
+-        case 8:
+-#line 112 "hb-ot-shaper-myanmar-machine.rl"
++        case 10:
++#line 113 "hb-ot-shaper-myanmar-machine.rl"
+         {te = p+1;{ found_syllable (myanmar_broken_cluster); buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE; }}
+         break;
+         case 3:
+-#line 113 "hb-ot-shaper-myanmar-machine.rl"
++#line 114 "hb-ot-shaper-myanmar-machine.rl"
+         {te = p+1;{ found_syllable (myanmar_non_myanmar_cluster); }}
+         break;
+-        case 5:
+-#line 110 "hb-ot-shaper-myanmar-machine.rl"
+-        {te = p;p--;{ found_syllable (myanmar_consonant_syllable); }}
+-        break;
+         case 7:
+-#line 112 "hb-ot-shaper-myanmar-machine.rl"
+-        {te = p;p--;{ found_syllable (myanmar_broken_cluster); buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE; }}
++#line 111 "hb-ot-shaper-myanmar-machine.rl"
++        {te = p;p--;{ found_syllable (myanmar_consonant_syllable); }}
+         break;
+         case 9:
+ #line 113 "hb-ot-shaper-myanmar-machine.rl"
++        {te = p;p--;{ found_syllable (myanmar_broken_cluster); buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE; }}
++        break;
++        case 12:
++#line 114 "hb-ot-shaper-myanmar-machine.rl"
+         {te = p;p--;{ found_syllable (myanmar_non_myanmar_cluster); }}
+         break;
+-#line 523 "hb-ot-shaper-myanmar-machine.hh"
++        case 11:
++#line 1 "NONE"
++        {       switch( act ) {
++        case 2:
++        {{p = ((te))-1;} found_syllable (myanmar_non_myanmar_cluster); }
++        break;
++        case 3:
++        {{p = ((te))-1;} found_syllable (myanmar_broken_cluster); buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE; }
++        break;
++        }
++        }
++        break;
++        case 6:
++#line 1 "NONE"
++        {te = p+1;}
++#line 112 "hb-ot-shaper-myanmar-machine.rl"
++        {act = 2;}
++        break;
++        case 5:
++#line 1 "NONE"
++        {te = p+1;}
++#line 113 "hb-ot-shaper-myanmar-machine.rl"
++        {act = 3;}
++        break;
++#line 653 "hb-ot-shaper-myanmar-machine.hh"
+         }
+ 
+ _again:
+@@ -528,7 +658,7 @@ _again:
+ #line 1 "NONE"
+         {ts = 0;}
+         break;
+-#line 532 "hb-ot-shaper-myanmar-machine.hh"
++#line 662 "hb-ot-shaper-myanmar-machine.hh"
+         }
+ 
+         if ( ++p != pe )
+@@ -544,7 +674,7 @@ _again:
+ 
+         }
+ 
+-#line 145 "hb-ot-shaper-myanmar-machine.rl"
++#line 146 "hb-ot-shaper-myanmar-machine.rl"
+ 
+ }
+ 
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-use-machine.hh b/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-use-machine.hh
+index 47b0e6bbd..46f66f7d2 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-use-machine.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-use-machine.hh
+@@ -81,6 +81,7 @@ enum use_syllable_type_t {
+ #define use_syllable_machine_ex_N 4u
+ #define use_syllable_machine_ex_O 0u
+ #define use_syllable_machine_ex_R 18u
++#define use_syllable_machine_ex_RK 56u
+ #define use_syllable_machine_ex_SB 51u
+ #define use_syllable_machine_ex_SE 52u
+ #define use_syllable_machine_ex_SMAbv 41u
+@@ -99,62 +100,62 @@ enum use_syllable_type_t {
+ #define use_syllable_machine_ex_ZWNJ 14u
+ 
+ 
+-#line 103 "hb-ot-shaper-use-machine.hh"
++#line 104 "hb-ot-shaper-use-machine.hh"
+ static const unsigned char _use_syllable_machine_trans_keys[] = {
+-        49u, 51u, 0u, 53u, 11u, 53u, 11u, 53u, 1u, 53u, 14u, 48u, 14u, 47u, 14u, 47u,
++        49u, 51u, 0u, 56u, 11u, 56u, 11u, 56u, 1u, 53u, 14u, 48u, 14u, 47u, 14u, 47u,
+         14u, 47u, 14u, 46u, 14u, 46u, 14u, 14u, 14u, 48u, 14u, 48u, 14u, 48u, 1u, 14u,
+         14u, 48u, 14u, 53u, 14u, 53u, 14u, 53u, 14u, 53u, 12u, 53u, 14u, 53u, 12u, 53u,
+-        12u, 53u, 12u, 53u, 11u, 53u, 1u, 14u, 1u, 48u, 14u, 42u, 14u, 42u, 11u, 53u,
++        12u, 53u, 12u, 53u, 11u, 56u, 1u, 14u, 1u, 48u, 14u, 42u, 14u, 42u, 11u, 56u,
+         1u, 53u, 14u, 48u, 14u, 47u, 14u, 47u, 14u, 47u, 14u, 46u, 14u, 46u, 14u, 14u,
+         14u, 48u, 14u, 48u, 14u, 48u, 1u, 14u, 14u, 48u, 14u, 53u, 14u, 53u, 14u, 53u,
+-        14u, 53u, 12u, 53u, 14u, 53u, 12u, 53u, 12u, 53u, 12u, 53u, 11u, 53u, 1u, 14u,
+-        1u, 14u, 1u, 48u, 13u, 14u, 4u, 14u, 11u, 53u, 11u, 53u, 1u, 53u, 14u, 48u,
+-        14u, 47u, 14u, 47u, 14u, 47u, 14u, 46u, 14u, 46u, 14u, 14u, 14u, 48u, 14u, 48u,
+-        14u, 48u, 1u, 14u, 14u, 48u, 14u, 53u, 14u, 53u, 14u, 53u, 14u, 53u, 12u, 53u,
+-        14u, 53u, 12u, 53u, 12u, 53u, 12u, 53u, 11u, 53u, 1u, 14u, 1u, 14u, 1u, 48u,
+-        11u, 53u, 1u, 53u, 14u, 48u, 14u, 47u, 14u, 47u, 14u, 47u, 14u, 46u, 14u, 46u,
+-        14u, 14u, 14u, 48u, 14u, 48u, 14u, 48u, 1u, 14u, 14u, 48u, 14u, 53u, 14u, 53u,
+-        14u, 53u, 14u, 53u, 12u, 53u, 14u, 53u, 12u, 53u, 12u, 53u, 12u, 53u, 11u, 53u,
+-        1u, 14u, 1u, 48u, 4u, 14u, 13u, 14u, 1u, 53u, 14u, 42u, 14u, 42u, 1u, 5u,
+-        14u, 55u, 14u, 51u, 14u, 52u, 14u, 54u, 11u, 53u, 0
++        14u, 53u, 12u, 53u, 14u, 53u, 12u, 53u, 12u, 53u, 12u, 53u, 11u, 56u, 1u, 14u,
++        1u, 14u, 1u, 48u, 14u, 14u, 13u, 14u, 4u, 14u, 11u, 56u, 11u, 56u, 1u, 53u,
++        14u, 48u, 14u, 47u, 14u, 47u, 14u, 47u, 14u, 46u, 14u, 46u, 14u, 14u, 14u, 48u,
++        14u, 48u, 14u, 48u, 1u, 14u, 14u, 48u, 14u, 53u, 14u, 53u, 14u, 53u, 14u, 53u,
++        12u, 53u, 14u, 53u, 12u, 53u, 12u, 53u, 12u, 53u, 11u, 56u, 1u, 14u, 1u, 14u,
++        1u, 48u, 14u, 14u, 11u, 56u, 1u, 53u, 14u, 48u, 14u, 47u, 14u, 47u, 14u, 47u,
++        14u, 46u, 14u, 46u, 14u, 14u, 14u, 48u, 14u, 48u, 14u, 48u, 1u, 14u, 14u, 48u,
++        14u, 53u, 14u, 53u, 14u, 53u, 14u, 53u, 12u, 53u, 14u, 53u, 12u, 53u, 12u, 53u,
++        12u, 53u, 11u, 56u, 1u, 14u, 1u, 48u, 4u, 14u, 13u, 14u, 1u, 56u, 14u, 42u,
++        14u, 42u, 1u, 5u, 14u, 55u, 14u, 51u, 14u, 52u, 14u, 54u, 11u, 56u, 0
+ };
+ 
+ static const char _use_syllable_machine_key_spans[] = {
+-        3, 54, 43, 43, 53, 35, 34, 34,
++        3, 57, 46, 46, 53, 35, 34, 34,
+         34, 33, 33, 1, 35, 35, 35, 14,
+         35, 40, 40, 40, 40, 42, 40, 42,
+-        42, 42, 43, 14, 48, 29, 29, 43,
++        42, 42, 46, 14, 48, 29, 29, 46,
+         53, 35, 34, 34, 34, 33, 33, 1,
+         35, 35, 35, 14, 35, 40, 40, 40,
+-        40, 42, 40, 42, 42, 42, 43, 14,
+-        14, 48, 2, 11, 43, 43, 53, 35,
+-        34, 34, 34, 33, 33, 1, 35, 35,
+-        35, 14, 35, 40, 40, 40, 40, 42,
+-        40, 42, 42, 42, 43, 14, 14, 48,
+-        43, 53, 35, 34, 34, 34, 33, 33,
+-        1, 35, 35, 35, 14, 35, 40, 40,
+-        40, 40, 42, 40, 42, 42, 42, 43,
+-        14, 48, 11, 2, 53, 29, 29, 5,
+-        42, 38, 39, 41, 43
++        40, 42, 40, 42, 42, 42, 46, 14,
++        14, 48, 1, 2, 11, 46, 46, 53,
++        35, 34, 34, 34, 33, 33, 1, 35,
++        35, 35, 14, 35, 40, 40, 40, 40,
++        42, 40, 42, 42, 42, 46, 14, 14,
++        48, 1, 46, 53, 35, 34, 34, 34,
++        33, 33, 1, 35, 35, 35, 14, 35,
++        40, 40, 40, 40, 42, 40, 42, 42,
++        42, 46, 14, 48, 11, 2, 56, 29,
++        29, 5, 42, 38, 39, 41, 46
+ };
+ 
+ static const short _use_syllable_machine_index_offsets[] = {
+-        0, 4, 59, 103, 147, 201, 237, 272,
+-        307, 342, 376, 410, 412, 448, 484, 520,
+-        535, 571, 612, 653, 694, 735, 778, 819,
+-        862, 905, 948, 992, 1007, 1056, 1086, 1116,
+-        1160, 1214, 1250, 1285, 1320, 1355, 1389, 1423,
+-        1425, 1461, 1497, 1533, 1548, 1584, 1625, 1666,
+-        1707, 1748, 1791, 1832, 1875, 1918, 1961, 2005,
+-        2020, 2035, 2084, 2087, 2099, 2143, 2187, 2241,
+-        2277, 2312, 2347, 2382, 2416, 2450, 2452, 2488,
+-        2524, 2560, 2575, 2611, 2652, 2693, 2734, 2775,
+-        2818, 2859, 2902, 2945, 2988, 3032, 3047, 3062,
+-        3111, 3155, 3209, 3245, 3280, 3315, 3350, 3384,
+-        3418, 3420, 3456, 3492, 3528, 3543, 3579, 3620,
+-        3661, 3702, 3743, 3786, 3827, 3870, 3913, 3956,
+-        4000, 4015, 4064, 4076, 4079, 4133, 4163, 4193,
+-        4199, 4242, 4281, 4321, 4363
++        0, 4, 62, 109, 156, 210, 246, 281,
++        316, 351, 385, 419, 421, 457, 493, 529,
++        544, 580, 621, 662, 703, 744, 787, 828,
++        871, 914, 957, 1004, 1019, 1068, 1098, 1128,
++        1175, 1229, 1265, 1300, 1335, 1370, 1404, 1438,
++        1440, 1476, 1512, 1548, 1563, 1599, 1640, 1681,
++        1722, 1763, 1806, 1847, 1890, 1933, 1976, 2023,
++        2038, 2053, 2102, 2104, 2107, 2119, 2166, 2213,
++        2267, 2303, 2338, 2373, 2408, 2442, 2476, 2478,
++        2514, 2550, 2586, 2601, 2637, 2678, 2719, 2760,
++        2801, 2844, 2885, 2928, 2971, 3014, 3061, 3076,
++        3091, 3140, 3142, 3189, 3243, 3279, 3314, 3349,
++        3384, 3418, 3452, 3454, 3490, 3526, 3562, 3577,
++        3613, 3654, 3695, 3736, 3777, 3820, 3861, 3904,
++        3947, 3990, 4037, 4052, 4101, 4113, 4116, 4173,
++        4203, 4233, 4239, 4282, 4321, 4361, 4403
+ };
+ 
+ static const unsigned char _use_syllable_machine_indicies[] = {
+@@ -165,571 +166,578 @@ static const unsigned char _use_syllable_machine_indicies[] = {
+         19, 20, 21, 8, 22, 23, 24, 25,
+         5, 26, 27, 28, 5, 29, 30, 31,
+         32, 33, 34, 35, 32, 1, 5, 36,
+-        5, 37, 5, 39, 40, 38, 41, 38,
+-        38, 38, 38, 38, 38, 38, 42, 43,
+-        44, 45, 46, 47, 48, 49, 50, 39,
+-        51, 52, 53, 54, 38, 55, 56, 57,
+-        38, 58, 59, 38, 60, 61, 62, 63,
+-        60, 38, 38, 38, 38, 64, 38, 39,
+-        40, 38, 41, 38, 38, 38, 38, 38,
+-        38, 38, 42, 43, 44, 45, 46, 47,
+-        48, 49, 50, 39, 51, 52, 53, 54,
+-        38, 55, 56, 57, 38, 38, 38, 38,
+-        60, 61, 62, 63, 60, 38, 38, 38,
+-        38, 64, 38, 39, 38, 38, 38, 38,
+-        38, 38, 38, 38, 38, 38, 38, 38,
+-        41, 38, 38, 38, 38, 38, 38, 38,
+-        38, 43, 44, 45, 46, 38, 38, 38,
+-        38, 38, 38, 38, 38, 38, 38, 55,
+-        56, 57, 38, 38, 38, 38, 38, 61,
+-        62, 63, 65, 38, 38, 38, 38, 43,
+-        38, 41, 38, 38, 38, 38, 38, 38,
+-        38, 38, 43, 44, 45, 46, 38, 38,
+-        38, 38, 38, 38, 38, 38, 38, 38,
+-        55, 56, 57, 38, 38, 38, 38, 38,
+-        61, 62, 63, 65, 38, 41, 38, 38,
+-        38, 38, 38, 38, 38, 38, 38, 44,
+-        45, 46, 38, 38, 38, 38, 38, 38,
+-        38, 38, 38, 38, 38, 38, 38, 38,
+-        38, 38, 38, 38, 61, 62, 63, 38,
+-        41, 38, 38, 38, 38, 38, 38, 38,
+-        38, 38, 38, 45, 46, 38, 38, 38,
+-        38, 38, 38, 38, 38, 38, 38, 38,
+-        38, 38, 38, 38, 38, 38, 38, 61,
+-        62, 63, 38, 41, 38, 38, 38, 38,
+-        38, 38, 38, 38, 38, 38, 38, 46,
+-        38, 38, 38, 38, 38, 38, 38, 38,
+-        38, 38, 38, 38, 38, 38, 38, 38,
+-        38, 38, 61, 62, 63, 38, 41, 38,
+-        38, 38, 38, 38, 38, 38, 38, 38,
+-        38, 38, 38, 38, 38, 38, 38, 38,
+-        38, 38, 38, 38, 38, 38, 38, 38,
+-        38, 38, 38, 38, 38, 61, 62, 38,
+-        41, 38, 38, 38, 38, 38, 38, 38,
+-        38, 38, 38, 38, 38, 38, 38, 38,
+-        38, 38, 38, 38, 38, 38, 38, 38,
+-        38, 38, 38, 38, 38, 38, 38, 38,
+-        62, 38, 41, 38, 41, 38, 38, 38,
+-        38, 38, 38, 38, 38, 38, 44, 45,
+-        46, 38, 38, 38, 38, 38, 38, 38,
+-        38, 38, 38, 55, 56, 57, 38, 38,
+-        38, 38, 38, 61, 62, 63, 65, 38,
+-        41, 38, 38, 38, 38, 38, 38, 38,
+-        38, 38, 44, 45, 46, 38, 38, 38,
+-        38, 38, 38, 38, 38, 38, 38, 38,
+-        56, 57, 38, 38, 38, 38, 38, 61,
+-        62, 63, 65, 38, 41, 38, 38, 38,
+-        38, 38, 38, 38, 38, 38, 44, 45,
+-        46, 38, 38, 38, 38, 38, 38, 38,
+-        38, 38, 38, 38, 38, 57, 38, 38,
+-        38, 38, 38, 61, 62, 63, 65, 38,
+-        66, 38, 38, 38, 38, 38, 38, 38,
+-        38, 38, 38, 38, 38, 41, 38, 41,
+-        38, 38, 38, 38, 38, 38, 38, 38,
+-        38, 44, 45, 46, 38, 38, 38, 38,
+-        38, 38, 38, 38, 38, 38, 38, 38,
+-        38, 38, 38, 38, 38, 38, 61, 62,
+-        63, 65, 38, 41, 38, 38, 38, 38,
+-        38, 38, 38, 42, 43, 44, 45, 46,
+-        38, 38, 38, 38, 38, 38, 52, 53,
+-        54, 38, 55, 56, 57, 38, 38, 38,
+-        38, 38, 61, 62, 63, 65, 38, 38,
+-        38, 38, 43, 38, 41, 38, 38, 38,
+-        38, 38, 38, 38, 38, 43, 44, 45,
+-        46, 38, 38, 38, 38, 38, 38, 52,
+-        53, 54, 38, 55, 56, 57, 38, 38,
+-        38, 38, 38, 61, 62, 63, 65, 38,
+-        38, 38, 38, 43, 38, 41, 38, 38,
+-        38, 38, 38, 38, 38, 38, 43, 44,
+-        45, 46, 38, 38, 38, 38, 38, 38,
+-        38, 53, 54, 38, 55, 56, 57, 38,
+-        38, 38, 38, 38, 61, 62, 63, 65,
+-        38, 38, 38, 38, 43, 38, 41, 38,
+-        38, 38, 38, 38, 38, 38, 38, 43,
+-        44, 45, 46, 38, 38, 38, 38, 38,
+-        38, 38, 38, 54, 38, 55, 56, 57,
+-        38, 38, 38, 38, 38, 61, 62, 63,
+-        65, 38, 38, 38, 38, 43, 38, 67,
+-        38, 41, 38, 38, 38, 38, 38, 38,
+-        38, 42, 43, 44, 45, 46, 38, 48,
+-        49, 38, 38, 38, 52, 53, 54, 38,
+-        55, 56, 57, 38, 38, 38, 38, 38,
+-        61, 62, 63, 65, 38, 38, 38, 38,
+-        43, 38, 41, 38, 38, 38, 38, 38,
+-        38, 38, 38, 43, 44, 45, 46, 38,
+-        38, 38, 38, 38, 38, 38, 38, 38,
+-        38, 55, 56, 57, 38, 38, 38, 38,
+-        38, 61, 62, 63, 65, 38, 38, 38,
+-        38, 43, 38, 67, 38, 41, 38, 38,
+-        38, 38, 38, 38, 38, 42, 43, 44,
+-        45, 46, 38, 38, 49, 38, 38, 38,
+-        52, 53, 54, 38, 55, 56, 57, 38,
+-        38, 38, 38, 38, 61, 62, 63, 65,
+-        38, 38, 38, 38, 43, 38, 67, 38,
+-        41, 38, 38, 38, 38, 38, 38, 38,
+-        42, 43, 44, 45, 46, 38, 38, 38,
+-        38, 38, 38, 52, 53, 54, 38, 55,
+-        56, 57, 38, 38, 38, 38, 38, 61,
+-        62, 63, 65, 38, 38, 38, 38, 43,
+-        38, 67, 38, 41, 38, 38, 38, 38,
+-        38, 38, 38, 42, 43, 44, 45, 46,
+-        47, 48, 49, 38, 38, 38, 52, 53,
+-        54, 38, 55, 56, 57, 38, 38, 38,
+-        38, 38, 61, 62, 63, 65, 38, 38,
+-        38, 38, 43, 38, 39, 40, 38, 41,
+-        38, 38, 38, 38, 38, 38, 38, 42,
++        5, 37, 5, 5, 38, 5, 40, 41,
++        39, 42, 39, 39, 39, 39, 39, 39,
++        39, 43, 44, 45, 46, 47, 48, 49,
++        50, 51, 40, 52, 53, 54, 55, 39,
++        56, 57, 58, 39, 59, 60, 39, 61,
++        62, 63, 64, 61, 39, 39, 39, 39,
++        65, 39, 39, 64, 39, 40, 41, 39,
++        42, 39, 39, 39, 39, 39, 39, 39,
+         43, 44, 45, 46, 47, 48, 49, 50,
+-        38, 51, 52, 53, 54, 38, 55, 56,
+-        57, 38, 38, 38, 38, 60, 61, 62,
+-        63, 60, 38, 38, 38, 38, 64, 38,
+-        39, 38, 38, 38, 38, 38, 38, 38,
+-        38, 38, 38, 38, 38, 41, 38, 39,
+-        38, 38, 38, 38, 38, 38, 38, 38,
+-        38, 38, 38, 38, 41, 38, 38, 38,
+-        38, 38, 38, 38, 38, 43, 44, 45,
+-        46, 38, 38, 38, 38, 38, 38, 38,
+-        38, 38, 38, 55, 56, 57, 38, 38,
+-        38, 38, 38, 61, 62, 63, 65, 38,
+-        41, 38, 38, 38, 38, 38, 38, 38,
+-        38, 38, 38, 38, 38, 38, 38, 38,
+-        38, 38, 38, 38, 38, 38, 38, 38,
+-        38, 38, 38, 58, 59, 38, 41, 38,
+-        38, 38, 38, 38, 38, 38, 38, 38,
+-        38, 38, 38, 38, 38, 38, 38, 38,
+-        38, 38, 38, 38, 38, 38, 38, 38,
+-        38, 38, 59, 38, 4, 69, 68, 70,
+-        68, 68, 68, 68, 68, 68, 68, 71,
+-        72, 73, 74, 75, 76, 77, 78, 79,
+-        4, 80, 81, 82, 83, 68, 84, 85,
+-        86, 68, 68, 68, 68, 87, 88, 89,
+-        90, 91, 68, 68, 68, 68, 92, 68,
+-        4, 68, 68, 68, 68, 68, 68, 68,
+-        68, 68, 68, 68, 68, 70, 68, 68,
+-        68, 68, 68, 68, 68, 68, 72, 73,
+-        74, 75, 68, 68, 68, 68, 68, 68,
+-        68, 68, 68, 68, 84, 85, 86, 68,
+-        68, 68, 68, 68, 88, 89, 90, 93,
+-        68, 68, 68, 68, 72, 68, 70, 68,
+-        68, 68, 68, 68, 68, 68, 68, 72,
+-        73, 74, 75, 68, 68, 68, 68, 68,
+-        68, 68, 68, 68, 68, 84, 85, 86,
+-        68, 68, 68, 68, 68, 88, 89, 90,
+-        93, 68, 70, 68, 68, 68, 68, 68,
+-        68, 68, 68, 68, 73, 74, 75, 68,
+-        68, 68, 68, 68, 68, 68, 68, 68,
+-        68, 68, 68, 68, 68, 68, 68, 68,
+-        68, 88, 89, 90, 68, 70, 68, 68,
+-        68, 68, 68, 68, 68, 68, 68, 68,
+-        74, 75, 68, 68, 68, 68, 68, 68,
+-        68, 68, 68, 68, 68, 68, 68, 68,
+-        68, 68, 68, 68, 88, 89, 90, 68,
+-        70, 68, 68, 68, 68, 68, 68, 68,
+-        68, 68, 68, 68, 75, 68, 68, 68,
+-        68, 68, 68, 68, 68, 68, 68, 68,
+-        68, 68, 68, 68, 68, 68, 68, 88,
+-        89, 90, 68, 70, 68, 68, 68, 68,
+-        68, 68, 68, 68, 68, 68, 68, 68,
+-        68, 68, 68, 68, 68, 68, 68, 68,
+-        68, 68, 68, 68, 68, 68, 68, 68,
+-        68, 68, 88, 89, 68, 70, 68, 68,
+-        68, 68, 68, 68, 68, 68, 68, 68,
+-        68, 68, 68, 68, 68, 68, 68, 68,
+-        68, 68, 68, 68, 68, 68, 68, 68,
+-        68, 68, 68, 68, 68, 89, 68, 70,
+-        68, 70, 68, 68, 68, 68, 68, 68,
+-        68, 68, 68, 73, 74, 75, 68, 68,
+-        68, 68, 68, 68, 68, 68, 68, 68,
+-        84, 85, 86, 68, 68, 68, 68, 68,
+-        88, 89, 90, 93, 68, 70, 68, 68,
+-        68, 68, 68, 68, 68, 68, 68, 73,
+-        74, 75, 68, 68, 68, 68, 68, 68,
+-        68, 68, 68, 68, 68, 85, 86, 68,
+-        68, 68, 68, 68, 88, 89, 90, 93,
+-        68, 70, 68, 68, 68, 68, 68, 68,
+-        68, 68, 68, 73, 74, 75, 68, 68,
+-        68, 68, 68, 68, 68, 68, 68, 68,
+-        68, 68, 86, 68, 68, 68, 68, 68,
+-        88, 89, 90, 93, 68, 95, 94, 94,
+-        94, 94, 94, 94, 94, 94, 94, 94,
+-        94, 94, 96, 94, 70, 68, 68, 68,
+-        68, 68, 68, 68, 68, 68, 73, 74,
+-        75, 68, 68, 68, 68, 68, 68, 68,
+-        68, 68, 68, 68, 68, 68, 68, 68,
+-        68, 68, 68, 88, 89, 90, 93, 68,
+-        70, 68, 68, 68, 68, 68, 68, 68,
+-        71, 72, 73, 74, 75, 68, 68, 68,
+-        68, 68, 68, 81, 82, 83, 68, 84,
+-        85, 86, 68, 68, 68, 68, 68, 88,
+-        89, 90, 93, 68, 68, 68, 68, 72,
+-        68, 70, 68, 68, 68, 68, 68, 68,
+-        68, 68, 72, 73, 74, 75, 68, 68,
+-        68, 68, 68, 68, 81, 82, 83, 68,
+-        84, 85, 86, 68, 68, 68, 68, 68,
+-        88, 89, 90, 93, 68, 68, 68, 68,
+-        72, 68, 70, 68, 68, 68, 68, 68,
+-        68, 68, 68, 72, 73, 74, 75, 68,
+-        68, 68, 68, 68, 68, 68, 82, 83,
+-        68, 84, 85, 86, 68, 68, 68, 68,
+-        68, 88, 89, 90, 93, 68, 68, 68,
+-        68, 72, 68, 70, 68, 68, 68, 68,
+-        68, 68, 68, 68, 72, 73, 74, 75,
+-        68, 68, 68, 68, 68, 68, 68, 68,
+-        83, 68, 84, 85, 86, 68, 68, 68,
+-        68, 68, 88, 89, 90, 93, 68, 68,
+-        68, 68, 72, 68, 97, 68, 70, 68,
+-        68, 68, 68, 68, 68, 68, 71, 72,
+-        73, 74, 75, 68, 77, 78, 68, 68,
+-        68, 81, 82, 83, 68, 84, 85, 86,
+-        68, 68, 68, 68, 68, 88, 89, 90,
+-        93, 68, 68, 68, 68, 72, 68, 70,
+-        68, 68, 68, 68, 68, 68, 68, 68,
+-        72, 73, 74, 75, 68, 68, 68, 68,
+-        68, 68, 68, 68, 68, 68, 84, 85,
+-        86, 68, 68, 68, 68, 68, 88, 89,
+-        90, 93, 68, 68, 68, 68, 72, 68,
+-        97, 68, 70, 68, 68, 68, 68, 68,
+-        68, 68, 71, 72, 73, 74, 75, 68,
+-        68, 78, 68, 68, 68, 81, 82, 83,
+-        68, 84, 85, 86, 68, 68, 68, 68,
+-        68, 88, 89, 90, 93, 68, 68, 68,
+-        68, 72, 68, 97, 68, 70, 68, 68,
+-        68, 68, 68, 68, 68, 71, 72, 73,
+-        74, 75, 68, 68, 68, 68, 68, 68,
+-        81, 82, 83, 68, 84, 85, 86, 68,
+-        68, 68, 68, 68, 88, 89, 90, 93,
+-        68, 68, 68, 68, 72, 68, 97, 68,
+-        70, 68, 68, 68, 68, 68, 68, 68,
+-        71, 72, 73, 74, 75, 76, 77, 78,
+-        68, 68, 68, 81, 82, 83, 68, 84,
+-        85, 86, 68, 68, 68, 68, 68, 88,
+-        89, 90, 93, 68, 68, 68, 68, 72,
+-        68, 4, 69, 68, 70, 68, 68, 68,
+-        68, 68, 68, 68, 71, 72, 73, 74,
+-        75, 76, 77, 78, 79, 68, 80, 81,
+-        82, 83, 68, 84, 85, 86, 68, 68,
+-        68, 68, 87, 88, 89, 90, 91, 68,
+-        68, 68, 68, 92, 68, 4, 98, 98,
+-        98, 98, 98, 98, 98, 98, 98, 98,
+-        98, 98, 99, 98, 4, 94, 94, 94,
+-        94, 94, 94, 94, 94, 94, 94, 94,
+-        94, 96, 94, 4, 68, 68, 68, 68,
+-        68, 68, 68, 68, 68, 68, 68, 68,
+-        70, 68, 68, 68, 68, 68, 68, 68,
+-        68, 72, 73, 74, 75, 68, 68, 68,
+-        68, 68, 68, 68, 68, 68, 68, 84,
+-        85, 86, 68, 68, 68, 68, 68, 88,
+-        89, 90, 93, 68, 101, 102, 100, 6,
+-        103, 103, 103, 103, 103, 103, 103, 103,
+-        103, 104, 103, 105, 106, 68, 70, 68,
+-        68, 68, 68, 68, 68, 68, 107, 108,
+-        109, 110, 111, 112, 113, 114, 115, 105,
+-        116, 117, 118, 119, 68, 120, 121, 122,
+-        68, 58, 59, 68, 123, 124, 125, 126,
+-        127, 68, 68, 68, 68, 128, 68, 105,
+-        106, 68, 70, 68, 68, 68, 68, 68,
+-        68, 68, 107, 108, 109, 110, 111, 112,
+-        113, 114, 115, 105, 116, 117, 118, 119,
+-        68, 120, 121, 122, 68, 68, 68, 68,
+-        123, 124, 125, 126, 127, 68, 68, 68,
+-        68, 128, 68, 105, 68, 68, 68, 68,
+-        68, 68, 68, 68, 68, 68, 68, 68,
+-        70, 68, 68, 68, 68, 68, 68, 68,
+-        68, 108, 109, 110, 111, 68, 68, 68,
+-        68, 68, 68, 68, 68, 68, 68, 120,
+-        121, 122, 68, 68, 68, 68, 68, 124,
+-        125, 126, 129, 68, 68, 68, 68, 108,
+-        68, 70, 68, 68, 68, 68, 68, 68,
+-        68, 68, 108, 109, 110, 111, 68, 68,
+-        68, 68, 68, 68, 68, 68, 68, 68,
+-        120, 121, 122, 68, 68, 68, 68, 68,
+-        124, 125, 126, 129, 68, 70, 68, 68,
+-        68, 68, 68, 68, 68, 68, 68, 109,
+-        110, 111, 68, 68, 68, 68, 68, 68,
+-        68, 68, 68, 68, 68, 68, 68, 68,
+-        68, 68, 68, 68, 124, 125, 126, 68,
+-        70, 68, 68, 68, 68, 68, 68, 68,
+-        68, 68, 68, 110, 111, 68, 68, 68,
+-        68, 68, 68, 68, 68, 68, 68, 68,
+-        68, 68, 68, 68, 68, 68, 68, 124,
+-        125, 126, 68, 70, 68, 68, 68, 68,
+-        68, 68, 68, 68, 68, 68, 68, 111,
+-        68, 68, 68, 68, 68, 68, 68, 68,
+-        68, 68, 68, 68, 68, 68, 68, 68,
+-        68, 68, 124, 125, 126, 68, 70, 68,
+-        68, 68, 68, 68, 68, 68, 68, 68,
+-        68, 68, 68, 68, 68, 68, 68, 68,
+-        68, 68, 68, 68, 68, 68, 68, 68,
+-        68, 68, 68, 68, 68, 124, 125, 68,
+-        70, 68, 68, 68, 68, 68, 68, 68,
+-        68, 68, 68, 68, 68, 68, 68, 68,
+-        68, 68, 68, 68, 68, 68, 68, 68,
+-        68, 68, 68, 68, 68, 68, 68, 68,
+-        125, 68, 70, 68, 70, 68, 68, 68,
+-        68, 68, 68, 68, 68, 68, 109, 110,
+-        111, 68, 68, 68, 68, 68, 68, 68,
+-        68, 68, 68, 120, 121, 122, 68, 68,
+-        68, 68, 68, 124, 125, 126, 129, 68,
+-        70, 68, 68, 68, 68, 68, 68, 68,
+-        68, 68, 109, 110, 111, 68, 68, 68,
+-        68, 68, 68, 68, 68, 68, 68, 68,
+-        121, 122, 68, 68, 68, 68, 68, 124,
+-        125, 126, 129, 68, 70, 68, 68, 68,
+-        68, 68, 68, 68, 68, 68, 109, 110,
+-        111, 68, 68, 68, 68, 68, 68, 68,
+-        68, 68, 68, 68, 68, 122, 68, 68,
+-        68, 68, 68, 124, 125, 126, 129, 68,
+-        130, 94, 94, 94, 94, 94, 94, 94,
+-        94, 94, 94, 94, 94, 96, 94, 70,
+-        68, 68, 68, 68, 68, 68, 68, 68,
+-        68, 109, 110, 111, 68, 68, 68, 68,
+-        68, 68, 68, 68, 68, 68, 68, 68,
+-        68, 68, 68, 68, 68, 68, 124, 125,
+-        126, 129, 68, 70, 68, 68, 68, 68,
+-        68, 68, 68, 107, 108, 109, 110, 111,
+-        68, 68, 68, 68, 68, 68, 117, 118,
+-        119, 68, 120, 121, 122, 68, 68, 68,
+-        68, 68, 124, 125, 126, 129, 68, 68,
+-        68, 68, 108, 68, 70, 68, 68, 68,
+-        68, 68, 68, 68, 68, 108, 109, 110,
+-        111, 68, 68, 68, 68, 68, 68, 117,
+-        118, 119, 68, 120, 121, 122, 68, 68,
+-        68, 68, 68, 124, 125, 126, 129, 68,
+-        68, 68, 68, 108, 68, 70, 68, 68,
+-        68, 68, 68, 68, 68, 68, 108, 109,
+-        110, 111, 68, 68, 68, 68, 68, 68,
+-        68, 118, 119, 68, 120, 121, 122, 68,
+-        68, 68, 68, 68, 124, 125, 126, 129,
+-        68, 68, 68, 68, 108, 68, 70, 68,
+-        68, 68, 68, 68, 68, 68, 68, 108,
+-        109, 110, 111, 68, 68, 68, 68, 68,
+-        68, 68, 68, 119, 68, 120, 121, 122,
+-        68, 68, 68, 68, 68, 124, 125, 126,
+-        129, 68, 68, 68, 68, 108, 68, 131,
+-        68, 70, 68, 68, 68, 68, 68, 68,
+-        68, 107, 108, 109, 110, 111, 68, 113,
+-        114, 68, 68, 68, 117, 118, 119, 68,
+-        120, 121, 122, 68, 68, 68, 68, 68,
+-        124, 125, 126, 129, 68, 68, 68, 68,
+-        108, 68, 70, 68, 68, 68, 68, 68,
+-        68, 68, 68, 108, 109, 110, 111, 68,
+-        68, 68, 68, 68, 68, 68, 68, 68,
+-        68, 120, 121, 122, 68, 68, 68, 68,
+-        68, 124, 125, 126, 129, 68, 68, 68,
+-        68, 108, 68, 131, 68, 70, 68, 68,
+-        68, 68, 68, 68, 68, 107, 108, 109,
+-        110, 111, 68, 68, 114, 68, 68, 68,
+-        117, 118, 119, 68, 120, 121, 122, 68,
+-        68, 68, 68, 68, 124, 125, 126, 129,
+-        68, 68, 68, 68, 108, 68, 131, 68,
+-        70, 68, 68, 68, 68, 68, 68, 68,
+-        107, 108, 109, 110, 111, 68, 68, 68,
+-        68, 68, 68, 117, 118, 119, 68, 120,
+-        121, 122, 68, 68, 68, 68, 68, 124,
+-        125, 126, 129, 68, 68, 68, 68, 108,
+-        68, 131, 68, 70, 68, 68, 68, 68,
+-        68, 68, 68, 107, 108, 109, 110, 111,
+-        112, 113, 114, 68, 68, 68, 117, 118,
+-        119, 68, 120, 121, 122, 68, 68, 68,
+-        68, 68, 124, 125, 126, 129, 68, 68,
+-        68, 68, 108, 68, 105, 106, 68, 70,
+-        68, 68, 68, 68, 68, 68, 68, 107,
+-        108, 109, 110, 111, 112, 113, 114, 115,
+-        68, 116, 117, 118, 119, 68, 120, 121,
+-        122, 68, 68, 68, 68, 123, 124, 125,
+-        126, 127, 68, 68, 68, 68, 128, 68,
+-        105, 98, 98, 98, 98, 98, 98, 98,
+-        98, 98, 98, 98, 98, 99, 98, 105,
+-        94, 94, 94, 94, 94, 94, 94, 94,
+-        94, 94, 94, 94, 96, 94, 105, 68,
+-        68, 68, 68, 68, 68, 68, 68, 68,
+-        68, 68, 68, 70, 68, 68, 68, 68,
+-        68, 68, 68, 68, 108, 109, 110, 111,
+-        68, 68, 68, 68, 68, 68, 68, 68,
+-        68, 68, 120, 121, 122, 68, 68, 68,
+-        68, 68, 124, 125, 126, 129, 68, 8,
+-        9, 132, 11, 132, 132, 132, 132, 132,
+-        132, 132, 13, 14, 15, 16, 17, 18,
+-        19, 20, 21, 8, 22, 23, 24, 25,
+-        132, 26, 27, 28, 132, 132, 132, 132,
+-        32, 33, 34, 35, 32, 132, 132, 132,
+-        132, 37, 132, 8, 132, 132, 132, 132,
+-        132, 132, 132, 132, 132, 132, 132, 132,
+-        11, 132, 132, 132, 132, 132, 132, 132,
+-        132, 14, 15, 16, 17, 132, 132, 132,
+-        132, 132, 132, 132, 132, 132, 132, 26,
+-        27, 28, 132, 132, 132, 132, 132, 33,
+-        34, 35, 133, 132, 132, 132, 132, 14,
+-        132, 11, 132, 132, 132, 132, 132, 132,
+-        132, 132, 14, 15, 16, 17, 132, 132,
+-        132, 132, 132, 132, 132, 132, 132, 132,
+-        26, 27, 28, 132, 132, 132, 132, 132,
+-        33, 34, 35, 133, 132, 11, 132, 132,
+-        132, 132, 132, 132, 132, 132, 132, 15,
+-        16, 17, 132, 132, 132, 132, 132, 132,
+-        132, 132, 132, 132, 132, 132, 132, 132,
+-        132, 132, 132, 132, 33, 34, 35, 132,
+-        11, 132, 132, 132, 132, 132, 132, 132,
+-        132, 132, 132, 16, 17, 132, 132, 132,
+-        132, 132, 132, 132, 132, 132, 132, 132,
+-        132, 132, 132, 132, 132, 132, 132, 33,
+-        34, 35, 132, 11, 132, 132, 132, 132,
+-        132, 132, 132, 132, 132, 132, 132, 17,
+-        132, 132, 132, 132, 132, 132, 132, 132,
+-        132, 132, 132, 132, 132, 132, 132, 132,
+-        132, 132, 33, 34, 35, 132, 11, 132,
+-        132, 132, 132, 132, 132, 132, 132, 132,
+-        132, 132, 132, 132, 132, 132, 132, 132,
+-        132, 132, 132, 132, 132, 132, 132, 132,
+-        132, 132, 132, 132, 132, 33, 34, 132,
+-        11, 132, 132, 132, 132, 132, 132, 132,
+-        132, 132, 132, 132, 132, 132, 132, 132,
+-        132, 132, 132, 132, 132, 132, 132, 132,
+-        132, 132, 132, 132, 132, 132, 132, 132,
+-        34, 132, 11, 132, 11, 132, 132, 132,
+-        132, 132, 132, 132, 132, 132, 15, 16,
+-        17, 132, 132, 132, 132, 132, 132, 132,
+-        132, 132, 132, 26, 27, 28, 132, 132,
+-        132, 132, 132, 33, 34, 35, 133, 132,
+-        11, 132, 132, 132, 132, 132, 132, 132,
+-        132, 132, 15, 16, 17, 132, 132, 132,
+-        132, 132, 132, 132, 132, 132, 132, 132,
+-        27, 28, 132, 132, 132, 132, 132, 33,
+-        34, 35, 133, 132, 11, 132, 132, 132,
+-        132, 132, 132, 132, 132, 132, 15, 16,
+-        17, 132, 132, 132, 132, 132, 132, 132,
+-        132, 132, 132, 132, 132, 28, 132, 132,
+-        132, 132, 132, 33, 34, 35, 133, 132,
+-        134, 132, 132, 132, 132, 132, 132, 132,
+-        132, 132, 132, 132, 132, 11, 132, 11,
+-        132, 132, 132, 132, 132, 132, 132, 132,
+-        132, 15, 16, 17, 132, 132, 132, 132,
+-        132, 132, 132, 132, 132, 132, 132, 132,
+-        132, 132, 132, 132, 132, 132, 33, 34,
+-        35, 133, 132, 11, 132, 132, 132, 132,
+-        132, 132, 132, 13, 14, 15, 16, 17,
+-        132, 132, 132, 132, 132, 132, 23, 24,
+-        25, 132, 26, 27, 28, 132, 132, 132,
+-        132, 132, 33, 34, 35, 133, 132, 132,
+-        132, 132, 14, 132, 11, 132, 132, 132,
+-        132, 132, 132, 132, 132, 14, 15, 16,
+-        17, 132, 132, 132, 132, 132, 132, 23,
+-        24, 25, 132, 26, 27, 28, 132, 132,
+-        132, 132, 132, 33, 34, 35, 133, 132,
+-        132, 132, 132, 14, 132, 11, 132, 132,
+-        132, 132, 132, 132, 132, 132, 14, 15,
+-        16, 17, 132, 132, 132, 132, 132, 132,
+-        132, 24, 25, 132, 26, 27, 28, 132,
+-        132, 132, 132, 132, 33, 34, 35, 133,
+-        132, 132, 132, 132, 14, 132, 11, 132,
+-        132, 132, 132, 132, 132, 132, 132, 14,
+-        15, 16, 17, 132, 132, 132, 132, 132,
+-        132, 132, 132, 25, 132, 26, 27, 28,
+-        132, 132, 132, 132, 132, 33, 34, 35,
+-        133, 132, 132, 132, 132, 14, 132, 135,
+-        132, 11, 132, 132, 132, 132, 132, 132,
+-        132, 13, 14, 15, 16, 17, 132, 19,
+-        20, 132, 132, 132, 23, 24, 25, 132,
+-        26, 27, 28, 132, 132, 132, 132, 132,
+-        33, 34, 35, 133, 132, 132, 132, 132,
+-        14, 132, 11, 132, 132, 132, 132, 132,
+-        132, 132, 132, 14, 15, 16, 17, 132,
+-        132, 132, 132, 132, 132, 132, 132, 132,
+-        132, 26, 27, 28, 132, 132, 132, 132,
+-        132, 33, 34, 35, 133, 132, 132, 132,
+-        132, 14, 132, 135, 132, 11, 132, 132,
+-        132, 132, 132, 132, 132, 13, 14, 15,
+-        16, 17, 132, 132, 20, 132, 132, 132,
+-        23, 24, 25, 132, 26, 27, 28, 132,
+-        132, 132, 132, 132, 33, 34, 35, 133,
+-        132, 132, 132, 132, 14, 132, 135, 132,
+-        11, 132, 132, 132, 132, 132, 132, 132,
+-        13, 14, 15, 16, 17, 132, 132, 132,
+-        132, 132, 132, 23, 24, 25, 132, 26,
+-        27, 28, 132, 132, 132, 132, 132, 33,
+-        34, 35, 133, 132, 132, 132, 132, 14,
+-        132, 135, 132, 11, 132, 132, 132, 132,
+-        132, 132, 132, 13, 14, 15, 16, 17,
+-        18, 19, 20, 132, 132, 132, 23, 24,
+-        25, 132, 26, 27, 28, 132, 132, 132,
+-        132, 132, 33, 34, 35, 133, 132, 132,
+-        132, 132, 14, 132, 8, 9, 132, 11,
+-        132, 132, 132, 132, 132, 132, 132, 13,
+-        14, 15, 16, 17, 18, 19, 20, 21,
+-        132, 22, 23, 24, 25, 132, 26, 27,
+-        28, 132, 132, 132, 132, 32, 33, 34,
+-        35, 32, 132, 132, 132, 132, 37, 132,
+-        8, 132, 132, 132, 132, 132, 132, 132,
+-        132, 132, 132, 132, 132, 11, 132, 8,
+-        132, 132, 132, 132, 132, 132, 132, 132,
+-        132, 132, 132, 132, 11, 132, 132, 132,
+-        132, 132, 132, 132, 132, 14, 15, 16,
+-        17, 132, 132, 132, 132, 132, 132, 132,
+-        132, 132, 132, 26, 27, 28, 132, 132,
+-        132, 132, 132, 33, 34, 35, 133, 132,
+-        136, 132, 132, 132, 132, 132, 132, 132,
+-        132, 132, 11, 132, 10, 11, 132, 4,
+-        132, 132, 132, 4, 132, 132, 132, 132,
+-        132, 8, 9, 10, 11, 132, 132, 132,
+-        132, 132, 132, 132, 13, 14, 15, 16,
+-        17, 18, 19, 20, 21, 8, 22, 23,
+-        24, 25, 132, 26, 27, 28, 132, 29,
+-        30, 132, 32, 33, 34, 35, 32, 132,
+-        132, 132, 132, 37, 132, 11, 132, 132,
+-        132, 132, 132, 132, 132, 132, 132, 132,
+-        132, 132, 132, 132, 132, 132, 132, 132,
+-        132, 132, 132, 132, 132, 132, 132, 132,
+-        29, 30, 132, 11, 132, 132, 132, 132,
+-        132, 132, 132, 132, 132, 132, 132, 132,
+-        132, 132, 132, 132, 132, 132, 132, 132,
+-        132, 132, 132, 132, 132, 132, 132, 30,
+-        132, 4, 137, 137, 137, 4, 137, 139,
+-        138, 138, 138, 138, 138, 138, 138, 138,
+-        138, 138, 138, 138, 138, 138, 138, 138,
+-        138, 138, 138, 138, 138, 138, 138, 138,
+-        138, 138, 138, 138, 138, 138, 138, 138,
+-        138, 138, 138, 140, 138, 141, 138, 141,
+-        142, 138, 139, 138, 138, 138, 138, 138,
+-        138, 138, 138, 138, 138, 138, 138, 138,
+-        138, 138, 138, 138, 138, 138, 138, 138,
+-        138, 138, 138, 138, 138, 138, 138, 138,
+-        138, 138, 138, 138, 138, 1, 140, 140,
+-        138, 139, 138, 138, 138, 138, 138, 138,
+-        138, 138, 138, 138, 138, 138, 138, 138,
+-        138, 138, 138, 138, 138, 138, 138, 138,
+-        138, 138, 138, 138, 138, 138, 138, 138,
+-        138, 138, 138, 138, 138, 140, 138, 141,
+-        138, 139, 138, 138, 138, 138, 138, 138,
+-        138, 138, 138, 138, 138, 138, 138, 138,
+-        138, 138, 138, 138, 138, 138, 138, 138,
+-        138, 138, 138, 138, 138, 138, 138, 138,
+-        138, 138, 138, 138, 138, 140, 138, 141,
+-        138, 141, 138, 39, 40, 38, 41, 38,
+-        38, 38, 38, 38, 38, 38, 42, 43,
+-        44, 45, 46, 47, 48, 49, 50, 39,
+-        51, 52, 53, 54, 38, 55, 56, 57,
+-        38, 58, 59, 38, 60, 61, 62, 63,
+-        60, 1, 38, 2, 38, 64, 38, 0
++        51, 40, 52, 53, 54, 55, 39, 56,
++        57, 58, 39, 39, 39, 39, 61, 62,
++        63, 64, 61, 39, 39, 39, 39, 65,
++        39, 39, 64, 39, 40, 39, 39, 39,
++        39, 39, 39, 39, 39, 39, 39, 39,
++        39, 42, 39, 39, 39, 39, 39, 39,
++        39, 39, 44, 45, 46, 47, 39, 39,
++        39, 39, 39, 39, 39, 39, 39, 39,
++        56, 57, 58, 39, 39, 39, 39, 39,
++        62, 63, 64, 66, 39, 39, 39, 39,
++        44, 39, 42, 39, 39, 39, 39, 39,
++        39, 39, 39, 44, 45, 46, 47, 39,
++        39, 39, 39, 39, 39, 39, 39, 39,
++        39, 56, 57, 58, 39, 39, 39, 39,
++        39, 62, 63, 64, 66, 39, 42, 39,
++        39, 39, 39, 39, 39, 39, 39, 39,
++        45, 46, 47, 39, 39, 39, 39, 39,
++        39, 39, 39, 39, 39, 39, 39, 39,
++        39, 39, 39, 39, 39, 62, 63, 64,
++        39, 42, 39, 39, 39, 39, 39, 39,
++        39, 39, 39, 39, 46, 47, 39, 39,
++        39, 39, 39, 39, 39, 39, 39, 39,
++        39, 39, 39, 39, 39, 39, 39, 39,
++        62, 63, 64, 39, 42, 39, 39, 39,
++        39, 39, 39, 39, 39, 39, 39, 39,
++        47, 39, 39, 39, 39, 39, 39, 39,
++        39, 39, 39, 39, 39, 39, 39, 39,
++        39, 39, 39, 62, 63, 64, 39, 42,
++        39, 39, 39, 39, 39, 39, 39, 39,
++        39, 39, 39, 39, 39, 39, 39, 39,
++        39, 39, 39, 39, 39, 39, 39, 39,
++        39, 39, 39, 39, 39, 39, 62, 63,
++        39, 42, 39, 39, 39, 39, 39, 39,
++        39, 39, 39, 39, 39, 39, 39, 39,
++        39, 39, 39, 39, 39, 39, 39, 39,
++        39, 39, 39, 39, 39, 39, 39, 39,
++        39, 63, 39, 42, 39, 42, 39, 39,
++        39, 39, 39, 39, 39, 39, 39, 45,
++        46, 47, 39, 39, 39, 39, 39, 39,
++        39, 39, 39, 39, 56, 57, 58, 39,
++        39, 39, 39, 39, 62, 63, 64, 66,
++        39, 42, 39, 39, 39, 39, 39, 39,
++        39, 39, 39, 45, 46, 47, 39, 39,
++        39, 39, 39, 39, 39, 39, 39, 39,
++        39, 57, 58, 39, 39, 39, 39, 39,
++        62, 63, 64, 66, 39, 42, 39, 39,
++        39, 39, 39, 39, 39, 39, 39, 45,
++        46, 47, 39, 39, 39, 39, 39, 39,
++        39, 39, 39, 39, 39, 39, 58, 39,
++        39, 39, 39, 39, 62, 63, 64, 66,
++        39, 67, 39, 39, 39, 39, 39, 39,
++        39, 39, 39, 39, 39, 39, 42, 39,
++        42, 39, 39, 39, 39, 39, 39, 39,
++        39, 39, 45, 46, 47, 39, 39, 39,
++        39, 39, 39, 39, 39, 39, 39, 39,
++        39, 39, 39, 39, 39, 39, 39, 62,
++        63, 64, 66, 39, 42, 39, 39, 39,
++        39, 39, 39, 39, 43, 44, 45, 46,
++        47, 39, 39, 39, 39, 39, 39, 53,
++        54, 55, 39, 56, 57, 58, 39, 39,
++        39, 39, 39, 62, 63, 64, 66, 39,
++        39, 39, 39, 44, 39, 42, 39, 39,
++        39, 39, 39, 39, 39, 39, 44, 45,
++        46, 47, 39, 39, 39, 39, 39, 39,
++        53, 54, 55, 39, 56, 57, 58, 39,
++        39, 39, 39, 39, 62, 63, 64, 66,
++        39, 39, 39, 39, 44, 39, 42, 39,
++        39, 39, 39, 39, 39, 39, 39, 44,
++        45, 46, 47, 39, 39, 39, 39, 39,
++        39, 39, 54, 55, 39, 56, 57, 58,
++        39, 39, 39, 39, 39, 62, 63, 64,
++        66, 39, 39, 39, 39, 44, 39, 42,
++        39, 39, 39, 39, 39, 39, 39, 39,
++        44, 45, 46, 47, 39, 39, 39, 39,
++        39, 39, 39, 39, 55, 39, 56, 57,
++        58, 39, 39, 39, 39, 39, 62, 63,
++        64, 66, 39, 39, 39, 39, 44, 39,
++        68, 39, 42, 39, 39, 39, 39, 39,
++        39, 39, 43, 44, 45, 46, 47, 39,
++        49, 50, 39, 39, 39, 53, 54, 55,
++        39, 56, 57, 58, 39, 39, 39, 39,
++        39, 62, 63, 64, 66, 39, 39, 39,
++        39, 44, 39, 42, 39, 39, 39, 39,
++        39, 39, 39, 39, 44, 45, 46, 47,
++        39, 39, 39, 39, 39, 39, 39, 39,
++        39, 39, 56, 57, 58, 39, 39, 39,
++        39, 39, 62, 63, 64, 66, 39, 39,
++        39, 39, 44, 39, 68, 39, 42, 39,
++        39, 39, 39, 39, 39, 39, 43, 44,
++        45, 46, 47, 39, 39, 50, 39, 39,
++        39, 53, 54, 55, 39, 56, 57, 58,
++        39, 39, 39, 39, 39, 62, 63, 64,
++        66, 39, 39, 39, 39, 44, 39, 68,
++        39, 42, 39, 39, 39, 39, 39, 39,
++        39, 43, 44, 45, 46, 47, 39, 39,
++        39, 39, 39, 39, 53, 54, 55, 39,
++        56, 57, 58, 39, 39, 39, 39, 39,
++        62, 63, 64, 66, 39, 39, 39, 39,
++        44, 39, 68, 39, 42, 39, 39, 39,
++        39, 39, 39, 39, 43, 44, 45, 46,
++        47, 48, 49, 50, 39, 39, 39, 53,
++        54, 55, 39, 56, 57, 58, 39, 39,
++        39, 39, 39, 62, 63, 64, 66, 39,
++        39, 39, 39, 44, 39, 40, 41, 39,
++        42, 39, 39, 39, 39, 39, 39, 39,
++        43, 44, 45, 46, 47, 48, 49, 50,
++        51, 39, 52, 53, 54, 55, 39, 56,
++        57, 58, 39, 39, 39, 39, 61, 62,
++        63, 64, 61, 39, 39, 39, 39, 65,
++        39, 39, 64, 39, 40, 39, 39, 39,
++        39, 39, 39, 39, 39, 39, 39, 39,
++        39, 42, 39, 40, 39, 39, 39, 39,
++        39, 39, 39, 39, 39, 39, 39, 39,
++        42, 39, 39, 39, 39, 39, 39, 39,
++        39, 44, 45, 46, 47, 39, 39, 39,
++        39, 39, 39, 39, 39, 39, 39, 56,
++        57, 58, 39, 39, 39, 39, 39, 62,
++        63, 64, 66, 39, 42, 39, 39, 39,
++        39, 39, 39, 39, 39, 39, 39, 39,
++        39, 39, 39, 39, 39, 39, 39, 39,
++        39, 39, 39, 39, 39, 39, 39, 59,
++        60, 39, 42, 39, 39, 39, 39, 39,
++        39, 39, 39, 39, 39, 39, 39, 39,
++        39, 39, 39, 39, 39, 39, 39, 39,
++        39, 39, 39, 39, 39, 39, 60, 39,
++        4, 70, 69, 71, 69, 69, 69, 69,
++        69, 69, 69, 72, 73, 74, 75, 76,
++        77, 78, 79, 80, 4, 81, 82, 83,
++        84, 69, 85, 86, 87, 69, 69, 69,
++        69, 88, 89, 90, 91, 92, 69, 69,
++        69, 69, 93, 69, 69, 94, 69, 4,
++        69, 69, 69, 69, 69, 69, 69, 69,
++        69, 69, 69, 69, 71, 69, 69, 69,
++        69, 69, 69, 69, 69, 73, 74, 75,
++        76, 69, 69, 69, 69, 69, 69, 69,
++        69, 69, 69, 85, 86, 87, 69, 69,
++        69, 69, 69, 89, 90, 91, 95, 69,
++        69, 69, 69, 73, 69, 71, 69, 69,
++        69, 69, 69, 69, 69, 69, 73, 74,
++        75, 76, 69, 69, 69, 69, 69, 69,
++        69, 69, 69, 69, 85, 86, 87, 69,
++        69, 69, 69, 69, 89, 90, 91, 95,
++        69, 71, 69, 69, 69, 69, 69, 69,
++        69, 69, 69, 74, 75, 76, 69, 69,
++        69, 69, 69, 69, 69, 69, 69, 69,
++        69, 69, 69, 69, 69, 69, 69, 69,
++        89, 90, 91, 69, 71, 69, 69, 69,
++        69, 69, 69, 69, 69, 69, 69, 75,
++        76, 69, 69, 69, 69, 69, 69, 69,
++        69, 69, 69, 69, 69, 69, 69, 69,
++        69, 69, 69, 89, 90, 91, 69, 71,
++        69, 69, 69, 69, 69, 69, 69, 69,
++        69, 69, 69, 76, 69, 69, 69, 69,
++        69, 69, 69, 69, 69, 69, 69, 69,
++        69, 69, 69, 69, 69, 69, 89, 90,
++        91, 69, 71, 69, 69, 69, 69, 69,
++        69, 69, 69, 69, 69, 69, 69, 69,
++        69, 69, 69, 69, 69, 69, 69, 69,
++        69, 69, 69, 69, 69, 69, 69, 69,
++        69, 89, 90, 69, 71, 69, 69, 69,
++        69, 69, 69, 69, 69, 69, 69, 69,
++        69, 69, 69, 69, 69, 69, 69, 69,
++        69, 69, 69, 69, 69, 69, 69, 69,
++        69, 69, 69, 69, 90, 69, 71, 69,
++        71, 69, 69, 69, 69, 69, 69, 69,
++        69, 69, 74, 75, 76, 69, 69, 69,
++        69, 69, 69, 69, 69, 69, 69, 85,
++        86, 87, 69, 69, 69, 69, 69, 89,
++        90, 91, 95, 69, 71, 69, 69, 69,
++        69, 69, 69, 69, 69, 69, 74, 75,
++        76, 69, 69, 69, 69, 69, 69, 69,
++        69, 69, 69, 69, 86, 87, 69, 69,
++        69, 69, 69, 89, 90, 91, 95, 69,
++        71, 69, 69, 69, 69, 69, 69, 69,
++        69, 69, 74, 75, 76, 69, 69, 69,
++        69, 69, 69, 69, 69, 69, 69, 69,
++        69, 87, 69, 69, 69, 69, 69, 89,
++        90, 91, 95, 69, 97, 96, 96, 96,
++        96, 96, 96, 96, 96, 96, 96, 96,
++        96, 98, 96, 71, 69, 69, 69, 69,
++        69, 69, 69, 69, 69, 74, 75, 76,
++        69, 69, 69, 69, 69, 69, 69, 69,
++        69, 69, 69, 69, 69, 69, 69, 69,
++        69, 69, 89, 90, 91, 95, 69, 71,
++        69, 69, 69, 69, 69, 69, 69, 72,
++        73, 74, 75, 76, 69, 69, 69, 69,
++        69, 69, 82, 83, 84, 69, 85, 86,
++        87, 69, 69, 69, 69, 69, 89, 90,
++        91, 95, 69, 69, 69, 69, 73, 69,
++        71, 69, 69, 69, 69, 69, 69, 69,
++        69, 73, 74, 75, 76, 69, 69, 69,
++        69, 69, 69, 82, 83, 84, 69, 85,
++        86, 87, 69, 69, 69, 69, 69, 89,
++        90, 91, 95, 69, 69, 69, 69, 73,
++        69, 71, 69, 69, 69, 69, 69, 69,
++        69, 69, 73, 74, 75, 76, 69, 69,
++        69, 69, 69, 69, 69, 83, 84, 69,
++        85, 86, 87, 69, 69, 69, 69, 69,
++        89, 90, 91, 95, 69, 69, 69, 69,
++        73, 69, 71, 69, 69, 69, 69, 69,
++        69, 69, 69, 73, 74, 75, 76, 69,
++        69, 69, 69, 69, 69, 69, 69, 84,
++        69, 85, 86, 87, 69, 69, 69, 69,
++        69, 89, 90, 91, 95, 69, 69, 69,
++        69, 73, 69, 99, 69, 71, 69, 69,
++        69, 69, 69, 69, 69, 72, 73, 74,
++        75, 76, 69, 78, 79, 69, 69, 69,
++        82, 83, 84, 69, 85, 86, 87, 69,
++        69, 69, 69, 69, 89, 90, 91, 95,
++        69, 69, 69, 69, 73, 69, 71, 69,
++        69, 69, 69, 69, 69, 69, 69, 73,
++        74, 75, 76, 69, 69, 69, 69, 69,
++        69, 69, 69, 69, 69, 85, 86, 87,
++        69, 69, 69, 69, 69, 89, 90, 91,
++        95, 69, 69, 69, 69, 73, 69, 99,
++        69, 71, 69, 69, 69, 69, 69, 69,
++        69, 72, 73, 74, 75, 76, 69, 69,
++        79, 69, 69, 69, 82, 83, 84, 69,
++        85, 86, 87, 69, 69, 69, 69, 69,
++        89, 90, 91, 95, 69, 69, 69, 69,
++        73, 69, 99, 69, 71, 69, 69, 69,
++        69, 69, 69, 69, 72, 73, 74, 75,
++        76, 69, 69, 69, 69, 69, 69, 82,
++        83, 84, 69, 85, 86, 87, 69, 69,
++        69, 69, 69, 89, 90, 91, 95, 69,
++        69, 69, 69, 73, 69, 99, 69, 71,
++        69, 69, 69, 69, 69, 69, 69, 72,
++        73, 74, 75, 76, 77, 78, 79, 69,
++        69, 69, 82, 83, 84, 69, 85, 86,
++        87, 69, 69, 69, 69, 69, 89, 90,
++        91, 95, 69, 69, 69, 69, 73, 69,
++        4, 70, 69, 71, 69, 69, 69, 69,
++        69, 69, 69, 72, 73, 74, 75, 76,
++        77, 78, 79, 80, 69, 81, 82, 83,
++        84, 69, 85, 86, 87, 69, 69, 69,
++        69, 88, 89, 90, 91, 92, 69, 69,
++        69, 69, 93, 69, 69, 94, 69, 4,
++        100, 100, 100, 100, 100, 100, 100, 100,
++        100, 100, 100, 100, 101, 100, 4, 96,
++        96, 96, 96, 96, 96, 96, 96, 96,
++        96, 96, 96, 98, 96, 4, 69, 69,
++        69, 69, 69, 69, 69, 69, 69, 69,
++        69, 69, 71, 69, 69, 69, 69, 69,
++        69, 69, 69, 73, 74, 75, 76, 69,
++        69, 69, 69, 69, 69, 69, 69, 69,
++        69, 85, 86, 87, 69, 69, 69, 69,
++        69, 89, 90, 91, 95, 69, 101, 100,
++        103, 104, 102, 6, 105, 105, 105, 105,
++        105, 105, 105, 105, 105, 106, 105, 107,
++        108, 69, 71, 69, 69, 69, 69, 69,
++        69, 69, 109, 110, 111, 112, 113, 114,
++        115, 116, 117, 107, 118, 119, 120, 121,
++        69, 122, 123, 124, 69, 59, 60, 69,
++        125, 126, 127, 128, 129, 69, 69, 69,
++        69, 130, 69, 69, 131, 69, 107, 108,
++        69, 71, 69, 69, 69, 69, 69, 69,
++        69, 109, 110, 111, 112, 113, 114, 115,
++        116, 117, 107, 118, 119, 120, 121, 69,
++        122, 123, 124, 69, 69, 69, 69, 125,
++        126, 127, 128, 129, 69, 69, 69, 69,
++        130, 69, 69, 131, 69, 107, 69, 69,
++        69, 69, 69, 69, 69, 69, 69, 69,
++        69, 69, 71, 69, 69, 69, 69, 69,
++        69, 69, 69, 110, 111, 112, 113, 69,
++        69, 69, 69, 69, 69, 69, 69, 69,
++        69, 122, 123, 124, 69, 69, 69, 69,
++        69, 126, 127, 128, 132, 69, 69, 69,
++        69, 110, 69, 71, 69, 69, 69, 69,
++        69, 69, 69, 69, 110, 111, 112, 113,
++        69, 69, 69, 69, 69, 69, 69, 69,
++        69, 69, 122, 123, 124, 69, 69, 69,
++        69, 69, 126, 127, 128, 132, 69, 71,
++        69, 69, 69, 69, 69, 69, 69, 69,
++        69, 111, 112, 113, 69, 69, 69, 69,
++        69, 69, 69, 69, 69, 69, 69, 69,
++        69, 69, 69, 69, 69, 69, 126, 127,
++        128, 69, 71, 69, 69, 69, 69, 69,
++        69, 69, 69, 69, 69, 112, 113, 69,
++        69, 69, 69, 69, 69, 69, 69, 69,
++        69, 69, 69, 69, 69, 69, 69, 69,
++        69, 126, 127, 128, 69, 71, 69, 69,
++        69, 69, 69, 69, 69, 69, 69, 69,
++        69, 113, 69, 69, 69, 69, 69, 69,
++        69, 69, 69, 69, 69, 69, 69, 69,
++        69, 69, 69, 69, 126, 127, 128, 69,
++        71, 69, 69, 69, 69, 69, 69, 69,
++        69, 69, 69, 69, 69, 69, 69, 69,
++        69, 69, 69, 69, 69, 69, 69, 69,
++        69, 69, 69, 69, 69, 69, 69, 126,
++        127, 69, 71, 69, 69, 69, 69, 69,
++        69, 69, 69, 69, 69, 69, 69, 69,
++        69, 69, 69, 69, 69, 69, 69, 69,
++        69, 69, 69, 69, 69, 69, 69, 69,
++        69, 69, 127, 69, 71, 69, 71, 69,
++        69, 69, 69, 69, 69, 69, 69, 69,
++        111, 112, 113, 69, 69, 69, 69, 69,
++        69, 69, 69, 69, 69, 122, 123, 124,
++        69, 69, 69, 69, 69, 126, 127, 128,
++        132, 69, 71, 69, 69, 69, 69, 69,
++        69, 69, 69, 69, 111, 112, 113, 69,
++        69, 69, 69, 69, 69, 69, 69, 69,
++        69, 69, 123, 124, 69, 69, 69, 69,
++        69, 126, 127, 128, 132, 69, 71, 69,
++        69, 69, 69, 69, 69, 69, 69, 69,
++        111, 112, 113, 69, 69, 69, 69, 69,
++        69, 69, 69, 69, 69, 69, 69, 124,
++        69, 69, 69, 69, 69, 126, 127, 128,
++        132, 69, 133, 96, 96, 96, 96, 96,
++        96, 96, 96, 96, 96, 96, 96, 98,
++        96, 71, 69, 69, 69, 69, 69, 69,
++        69, 69, 69, 111, 112, 113, 69, 69,
++        69, 69, 69, 69, 69, 69, 69, 69,
++        69, 69, 69, 69, 69, 69, 69, 69,
++        126, 127, 128, 132, 69, 71, 69, 69,
++        69, 69, 69, 69, 69, 109, 110, 111,
++        112, 113, 69, 69, 69, 69, 69, 69,
++        119, 120, 121, 69, 122, 123, 124, 69,
++        69, 69, 69, 69, 126, 127, 128, 132,
++        69, 69, 69, 69, 110, 69, 71, 69,
++        69, 69, 69, 69, 69, 69, 69, 110,
++        111, 112, 113, 69, 69, 69, 69, 69,
++        69, 119, 120, 121, 69, 122, 123, 124,
++        69, 69, 69, 69, 69, 126, 127, 128,
++        132, 69, 69, 69, 69, 110, 69, 71,
++        69, 69, 69, 69, 69, 69, 69, 69,
++        110, 111, 112, 113, 69, 69, 69, 69,
++        69, 69, 69, 120, 121, 69, 122, 123,
++        124, 69, 69, 69, 69, 69, 126, 127,
++        128, 132, 69, 69, 69, 69, 110, 69,
++        71, 69, 69, 69, 69, 69, 69, 69,
++        69, 110, 111, 112, 113, 69, 69, 69,
++        69, 69, 69, 69, 69, 121, 69, 122,
++        123, 124, 69, 69, 69, 69, 69, 126,
++        127, 128, 132, 69, 69, 69, 69, 110,
++        69, 134, 69, 71, 69, 69, 69, 69,
++        69, 69, 69, 109, 110, 111, 112, 113,
++        69, 115, 116, 69, 69, 69, 119, 120,
++        121, 69, 122, 123, 124, 69, 69, 69,
++        69, 69, 126, 127, 128, 132, 69, 69,
++        69, 69, 110, 69, 71, 69, 69, 69,
++        69, 69, 69, 69, 69, 110, 111, 112,
++        113, 69, 69, 69, 69, 69, 69, 69,
++        69, 69, 69, 122, 123, 124, 69, 69,
++        69, 69, 69, 126, 127, 128, 132, 69,
++        69, 69, 69, 110, 69, 134, 69, 71,
++        69, 69, 69, 69, 69, 69, 69, 109,
++        110, 111, 112, 113, 69, 69, 116, 69,
++        69, 69, 119, 120, 121, 69, 122, 123,
++        124, 69, 69, 69, 69, 69, 126, 127,
++        128, 132, 69, 69, 69, 69, 110, 69,
++        134, 69, 71, 69, 69, 69, 69, 69,
++        69, 69, 109, 110, 111, 112, 113, 69,
++        69, 69, 69, 69, 69, 119, 120, 121,
++        69, 122, 123, 124, 69, 69, 69, 69,
++        69, 126, 127, 128, 132, 69, 69, 69,
++        69, 110, 69, 134, 69, 71, 69, 69,
++        69, 69, 69, 69, 69, 109, 110, 111,
++        112, 113, 114, 115, 116, 69, 69, 69,
++        119, 120, 121, 69, 122, 123, 124, 69,
++        69, 69, 69, 69, 126, 127, 128, 132,
++        69, 69, 69, 69, 110, 69, 107, 108,
++        69, 71, 69, 69, 69, 69, 69, 69,
++        69, 109, 110, 111, 112, 113, 114, 115,
++        116, 117, 69, 118, 119, 120, 121, 69,
++        122, 123, 124, 69, 69, 69, 69, 125,
++        126, 127, 128, 129, 69, 69, 69, 69,
++        130, 69, 69, 131, 69, 107, 100, 100,
++        100, 100, 100, 100, 100, 100, 100, 100,
++        100, 100, 101, 100, 107, 96, 96, 96,
++        96, 96, 96, 96, 96, 96, 96, 96,
++        96, 98, 96, 107, 69, 69, 69, 69,
++        69, 69, 69, 69, 69, 69, 69, 69,
++        71, 69, 69, 69, 69, 69, 69, 69,
++        69, 110, 111, 112, 113, 69, 69, 69,
++        69, 69, 69, 69, 69, 69, 69, 122,
++        123, 124, 69, 69, 69, 69, 69, 126,
++        127, 128, 132, 69, 101, 100, 8, 9,
++        135, 11, 135, 135, 135, 135, 135, 135,
++        135, 13, 14, 15, 16, 17, 18, 19,
++        20, 21, 8, 22, 23, 24, 25, 135,
++        26, 27, 28, 135, 135, 135, 135, 32,
++        33, 34, 38, 32, 135, 135, 135, 135,
++        37, 135, 135, 38, 135, 8, 135, 135,
++        135, 135, 135, 135, 135, 135, 135, 135,
++        135, 135, 11, 135, 135, 135, 135, 135,
++        135, 135, 135, 14, 15, 16, 17, 135,
++        135, 135, 135, 135, 135, 135, 135, 135,
++        135, 26, 27, 28, 135, 135, 135, 135,
++        135, 33, 34, 38, 136, 135, 135, 135,
++        135, 14, 135, 11, 135, 135, 135, 135,
++        135, 135, 135, 135, 14, 15, 16, 17,
++        135, 135, 135, 135, 135, 135, 135, 135,
++        135, 135, 26, 27, 28, 135, 135, 135,
++        135, 135, 33, 34, 38, 136, 135, 11,
++        135, 135, 135, 135, 135, 135, 135, 135,
++        135, 15, 16, 17, 135, 135, 135, 135,
++        135, 135, 135, 135, 135, 135, 135, 135,
++        135, 135, 135, 135, 135, 135, 33, 34,
++        38, 135, 11, 135, 135, 135, 135, 135,
++        135, 135, 135, 135, 135, 16, 17, 135,
++        135, 135, 135, 135, 135, 135, 135, 135,
++        135, 135, 135, 135, 135, 135, 135, 135,
++        135, 33, 34, 38, 135, 11, 135, 135,
++        135, 135, 135, 135, 135, 135, 135, 135,
++        135, 17, 135, 135, 135, 135, 135, 135,
++        135, 135, 135, 135, 135, 135, 135, 135,
++        135, 135, 135, 135, 33, 34, 38, 135,
++        11, 135, 135, 135, 135, 135, 135, 135,
++        135, 135, 135, 135, 135, 135, 135, 135,
++        135, 135, 135, 135, 135, 135, 135, 135,
++        135, 135, 135, 135, 135, 135, 135, 33,
++        34, 135, 11, 135, 135, 135, 135, 135,
++        135, 135, 135, 135, 135, 135, 135, 135,
++        135, 135, 135, 135, 135, 135, 135, 135,
++        135, 135, 135, 135, 135, 135, 135, 135,
++        135, 135, 34, 135, 11, 137, 11, 135,
++        135, 135, 135, 135, 135, 135, 135, 135,
++        15, 16, 17, 135, 135, 135, 135, 135,
++        135, 135, 135, 135, 135, 26, 27, 28,
++        135, 135, 135, 135, 135, 33, 34, 38,
++        136, 135, 11, 135, 135, 135, 135, 135,
++        135, 135, 135, 135, 15, 16, 17, 135,
++        135, 135, 135, 135, 135, 135, 135, 135,
++        135, 135, 27, 28, 135, 135, 135, 135,
++        135, 33, 34, 38, 136, 135, 11, 135,
++        135, 135, 135, 135, 135, 135, 135, 135,
++        15, 16, 17, 135, 135, 135, 135, 135,
++        135, 135, 135, 135, 135, 135, 135, 28,
++        135, 135, 135, 135, 135, 33, 34, 38,
++        136, 135, 138, 135, 135, 135, 135, 135,
++        135, 135, 135, 135, 135, 135, 135, 11,
++        135, 11, 135, 135, 135, 135, 135, 135,
++        135, 135, 135, 15, 16, 17, 135, 135,
++        135, 135, 135, 135, 135, 135, 135, 135,
++        135, 135, 135, 135, 135, 135, 135, 135,
++        33, 34, 38, 136, 135, 11, 135, 135,
++        135, 135, 135, 135, 135, 13, 14, 15,
++        16, 17, 135, 135, 135, 135, 135, 135,
++        23, 24, 25, 135, 26, 27, 28, 135,
++        135, 135, 135, 135, 33, 34, 38, 136,
++        135, 135, 135, 135, 14, 135, 11, 135,
++        135, 135, 135, 135, 135, 135, 135, 14,
++        15, 16, 17, 135, 135, 135, 135, 135,
++        135, 23, 24, 25, 135, 26, 27, 28,
++        135, 135, 135, 135, 135, 33, 34, 38,
++        136, 135, 135, 135, 135, 14, 135, 11,
++        135, 135, 135, 135, 135, 135, 135, 135,
++        14, 15, 16, 17, 135, 135, 135, 135,
++        135, 135, 135, 24, 25, 135, 26, 27,
++        28, 135, 135, 135, 135, 135, 33, 34,
++        38, 136, 135, 135, 135, 135, 14, 135,
++        11, 135, 135, 135, 135, 135, 135, 135,
++        135, 14, 15, 16, 17, 135, 135, 135,
++        135, 135, 135, 135, 135, 25, 135, 26,
++        27, 28, 135, 135, 135, 135, 135, 33,
++        34, 38, 136, 135, 135, 135, 135, 14,
++        135, 139, 135, 11, 135, 135, 135, 135,
++        135, 135, 135, 13, 14, 15, 16, 17,
++        135, 19, 20, 135, 135, 135, 23, 24,
++        25, 135, 26, 27, 28, 135, 135, 135,
++        135, 135, 33, 34, 38, 136, 135, 135,
++        135, 135, 14, 135, 11, 135, 135, 135,
++        135, 135, 135, 135, 135, 14, 15, 16,
++        17, 135, 135, 135, 135, 135, 135, 135,
++        135, 135, 135, 26, 27, 28, 135, 135,
++        135, 135, 135, 33, 34, 38, 136, 135,
++        135, 135, 135, 14, 135, 139, 135, 11,
++        135, 135, 135, 135, 135, 135, 135, 13,
++        14, 15, 16, 17, 135, 135, 20, 135,
++        135, 135, 23, 24, 25, 135, 26, 27,
++        28, 135, 135, 135, 135, 135, 33, 34,
++        38, 136, 135, 135, 135, 135, 14, 135,
++        139, 135, 11, 135, 135, 135, 135, 135,
++        135, 135, 13, 14, 15, 16, 17, 135,
++        135, 135, 135, 135, 135, 23, 24, 25,
++        135, 26, 27, 28, 135, 135, 135, 135,
++        135, 33, 34, 38, 136, 135, 135, 135,
++        135, 14, 135, 139, 135, 11, 135, 135,
++        135, 135, 135, 135, 135, 13, 14, 15,
++        16, 17, 18, 19, 20, 135, 135, 135,
++        23, 24, 25, 135, 26, 27, 28, 135,
++        135, 135, 135, 135, 33, 34, 38, 136,
++        135, 135, 135, 135, 14, 135, 8, 9,
++        135, 11, 135, 135, 135, 135, 135, 135,
++        135, 13, 14, 15, 16, 17, 18, 19,
++        20, 21, 135, 22, 23, 24, 25, 135,
++        26, 27, 28, 135, 135, 135, 135, 32,
++        33, 34, 38, 32, 135, 135, 135, 135,
++        37, 135, 135, 38, 135, 8, 135, 135,
++        135, 135, 135, 135, 135, 135, 135, 135,
++        135, 135, 11, 135, 8, 135, 135, 135,
++        135, 135, 135, 135, 135, 135, 135, 135,
++        135, 11, 135, 135, 135, 135, 135, 135,
++        135, 135, 14, 15, 16, 17, 135, 135,
++        135, 135, 135, 135, 135, 135, 135, 135,
++        26, 27, 28, 135, 135, 135, 135, 135,
++        33, 34, 38, 136, 135, 140, 135, 135,
++        135, 135, 135, 135, 135, 135, 135, 11,
++        135, 10, 11, 135, 4, 135, 135, 135,
++        4, 135, 135, 135, 135, 135, 8, 9,
++        10, 11, 135, 135, 135, 135, 135, 135,
++        135, 13, 14, 15, 16, 17, 18, 19,
++        20, 21, 8, 22, 23, 24, 25, 135,
++        26, 27, 28, 135, 29, 30, 135, 32,
++        33, 34, 38, 32, 135, 135, 135, 135,
++        37, 135, 135, 38, 135, 11, 135, 135,
++        135, 135, 135, 135, 135, 135, 135, 135,
++        135, 135, 135, 135, 135, 135, 135, 135,
++        135, 135, 135, 135, 135, 135, 135, 135,
++        29, 30, 135, 11, 135, 135, 135, 135,
++        135, 135, 135, 135, 135, 135, 135, 135,
++        135, 135, 135, 135, 135, 135, 135, 135,
++        135, 135, 135, 135, 135, 135, 135, 30,
++        135, 4, 141, 141, 141, 4, 141, 143,
++        142, 142, 142, 142, 142, 142, 142, 142,
++        142, 142, 142, 142, 142, 142, 142, 142,
++        142, 142, 142, 142, 142, 142, 142, 142,
++        142, 142, 142, 142, 142, 142, 142, 142,
++        142, 142, 142, 144, 142, 145, 142, 145,
++        146, 142, 143, 142, 142, 142, 142, 142,
++        142, 142, 142, 142, 142, 142, 142, 142,
++        142, 142, 142, 142, 142, 142, 142, 142,
++        142, 142, 142, 142, 142, 142, 142, 142,
++        142, 142, 142, 142, 142, 1, 144, 144,
++        142, 143, 142, 142, 142, 142, 142, 142,
++        142, 142, 142, 142, 142, 142, 142, 142,
++        142, 142, 142, 142, 142, 142, 142, 142,
++        142, 142, 142, 142, 142, 142, 142, 142,
++        142, 142, 142, 142, 142, 144, 142, 145,
++        142, 143, 142, 142, 142, 142, 142, 142,
++        142, 142, 142, 142, 142, 142, 142, 142,
++        142, 142, 142, 142, 142, 142, 142, 142,
++        142, 142, 142, 142, 142, 142, 142, 142,
++        142, 142, 142, 142, 142, 144, 142, 145,
++        142, 145, 142, 40, 41, 39, 42, 39,
++        39, 39, 39, 39, 39, 39, 43, 44,
++        45, 46, 47, 48, 49, 50, 51, 40,
++        52, 53, 54, 55, 39, 56, 57, 58,
++        39, 59, 60, 39, 61, 62, 63, 64,
++        61, 1, 39, 2, 39, 65, 39, 39,
++        64, 39, 0
+ };
+ 
+ static const char _use_syllable_machine_trans_targs[] = {
+-        1, 120, 0, 2, 31, 1, 58, 60,
+-        88, 89, 114, 1, 116, 102, 90, 91,
+-        92, 93, 106, 108, 109, 110, 111, 103,
+-        104, 105, 97, 98, 99, 117, 118, 119,
+-        112, 94, 95, 96, 124, 113, 1, 3,
+-        4, 1, 17, 5, 6, 7, 8, 21,
+-        23, 24, 25, 26, 18, 19, 20, 12,
+-        13, 14, 29, 30, 27, 9, 10, 11,
+-        28, 15, 16, 22, 1, 32, 1, 45,
+-        33, 34, 35, 36, 49, 51, 52, 53,
+-        54, 46, 47, 48, 40, 41, 42, 55,
+-        37, 38, 39, 56, 57, 43, 1, 44,
+-        1, 50, 1, 1, 1, 59, 1, 1,
+-        1, 61, 62, 75, 63, 64, 65, 66,
+-        79, 81, 82, 83, 84, 76, 77, 78,
+-        70, 71, 72, 85, 67, 68, 69, 86,
+-        87, 73, 74, 80, 1, 100, 101, 107,
+-        115, 1, 1, 1, 121, 122, 123
++        1, 122, 0, 2, 31, 1, 59, 61,
++        90, 91, 116, 1, 118, 104, 92, 93,
++        94, 95, 108, 110, 111, 112, 113, 105,
++        106, 107, 99, 100, 101, 119, 120, 121,
++        114, 96, 97, 98, 126, 115, 98, 1,
++        3, 4, 1, 17, 5, 6, 7, 8,
++        21, 23, 24, 25, 26, 18, 19, 20,
++        12, 13, 14, 29, 30, 27, 9, 10,
++        11, 28, 15, 16, 22, 1, 32, 1,
++        45, 33, 34, 35, 36, 49, 51, 52,
++        53, 54, 46, 47, 48, 40, 41, 42,
++        55, 37, 38, 39, 56, 57, 58, 43,
++        1, 44, 1, 50, 1, 1, 1, 60,
++        1, 1, 1, 62, 63, 76, 64, 65,
++        66, 67, 80, 82, 83, 84, 85, 77,
++        78, 79, 71, 72, 73, 86, 68, 69,
++        70, 87, 88, 89, 74, 75, 81, 1,
++        102, 1, 103, 109, 117, 1, 1, 1,
++        123, 124, 125
+ };
+ 
+ static const char _use_syllable_machine_trans_actions[] = {
+@@ -737,20 +745,21 @@ static const char _use_syllable_machine_trans_actions[] = {
+         0, 0, 0, 5, 0, 0, 0, 0,
+         0, 0, 0, 0, 0, 0, 0, 0,
+         0, 0, 0, 0, 0, 0, 0, 0,
+-        0, 0, 0, 0, 6, 0, 7, 0,
+-        0, 8, 0, 0, 0, 0, 0, 0,
++        0, 0, 0, 6, 7, 0, 8, 9,
++        0, 0, 10, 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, 9, 0, 10, 0,
++        0, 0, 0, 0, 0, 11, 0, 12,
+         0, 0, 0, 0, 0, 0, 0, 0,
+         0, 0, 0, 0, 0, 0, 0, 0,
+-        0, 0, 0, 0, 0, 0, 11, 0,
+-        12, 0, 13, 14, 15, 0, 16, 17,
+-        18, 0, 0, 0, 0, 0, 0, 0,
+         0, 0, 0, 0, 0, 0, 0, 0,
++        13, 0, 14, 0, 15, 16, 17, 0,
++        18, 19, 20, 0, 0, 0, 0, 0,
+         0, 0, 0, 0, 0, 0, 0, 0,
+-        0, 0, 0, 0, 19, 0, 0, 0,
+-        0, 20, 21, 22, 0, 0, 0
++        0, 0, 0, 0, 0, 0, 0, 0,
++        0, 0, 0, 0, 0, 0, 0, 21,
++        0, 22, 0, 0, 0, 23, 24, 25,
++        0, 0, 0
+ };
+ 
+ static const char _use_syllable_machine_to_state_actions[] = {
+@@ -769,7 +778,7 @@ static const char _use_syllable_machine_to_state_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, 0, 0, 0, 0
++        0, 0, 0, 0, 0, 0, 0
+ };
+ 
+ static const char _use_syllable_machine_from_state_actions[] = {
+@@ -788,26 +797,26 @@ static const char _use_syllable_machine_from_state_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, 0, 0, 0, 0
++        0, 0, 0, 0, 0, 0, 0
+ };
+ 
+ static const short _use_syllable_machine_eof_trans[] = {
+-        1, 0, 39, 39, 39, 39, 39, 39,
+-        39, 39, 39, 39, 39, 39, 39, 39,
+-        39, 39, 39, 39, 39, 39, 39, 39,
+-        39, 39, 39, 39, 39, 39, 39, 69,
+-        69, 69, 69, 69, 69, 69, 69, 69,
+-        69, 69, 69, 95, 69, 69, 69, 69,
+-        69, 69, 69, 69, 69, 69, 69, 99,
+-        95, 69, 101, 104, 69, 69, 69, 69,
+-        69, 69, 69, 69, 69, 69, 69, 69,
+-        69, 95, 69, 69, 69, 69, 69, 69,
+-        69, 69, 69, 69, 69, 99, 95, 69,
+-        133, 133, 133, 133, 133, 133, 133, 133,
+-        133, 133, 133, 133, 133, 133, 133, 133,
+-        133, 133, 133, 133, 133, 133, 133, 133,
+-        133, 133, 133, 133, 133, 133, 133, 138,
+-        139, 139, 139, 139, 39
++        1, 0, 40, 40, 40, 40, 40, 40,
++        40, 40, 40, 40, 40, 40, 40, 40,
++        40, 40, 40, 40, 40, 40, 40, 40,
++        40, 40, 40, 40, 40, 40, 40, 70,
++        70, 70, 70, 70, 70, 70, 70, 70,
++        70, 70, 70, 97, 70, 70, 70, 70,
++        70, 70, 70, 70, 70, 70, 70, 101,
++        97, 70, 101, 103, 106, 70, 70, 70,
++        70, 70, 70, 70, 70, 70, 70, 70,
++        70, 70, 97, 70, 70, 70, 70, 70,
++        70, 70, 70, 70, 70, 70, 101, 97,
++        70, 101, 136, 136, 136, 136, 136, 136,
++        136, 136, 138, 136, 136, 136, 136, 136,
++        136, 136, 136, 136, 136, 136, 136, 136,
++        136, 136, 136, 136, 136, 136, 136, 136,
++        136, 142, 143, 143, 143, 143, 40
+ };
+ 
+ static const int use_syllable_machine_start = 1;
+@@ -821,7 +830,7 @@ static const int use_syllable_machine_en_main = 1;
+ 
+ 
+ 
+-#line 184 "hb-ot-shaper-use-machine.rl"
++#line 186 "hb-ot-shaper-use-machine.rl"
+ 
+ 
+ #define found_syllable(syllable_type) \
+@@ -920,7 +929,7 @@ find_syllables_use (hb_buffer_t *buffer)
+   unsigned int act HB_UNUSED;
+   int cs;
+ 
+-#line 924 "hb-ot-shaper-use-machine.hh"
++#line 933 "hb-ot-shaper-use-machine.hh"
+         {
+         cs = use_syllable_machine_start;
+         ts = 0;
+@@ -928,12 +937,12 @@ find_syllables_use (hb_buffer_t *buffer)
+         act = 0;
+         }
+ 
+-#line 284 "hb-ot-shaper-use-machine.rl"
++#line 286 "hb-ot-shaper-use-machine.rl"
+ 
+ 
+   unsigned int syllable_serial = 1;
+ 
+-#line 937 "hb-ot-shaper-use-machine.hh"
++#line 946 "hb-ot-shaper-use-machine.hh"
+         {
+         int _slen;
+         int _trans;
+@@ -947,7 +956,7 @@ _resume:
+ #line 1 "NONE"
+         {ts = p;}
+         break;
+-#line 951 "hb-ot-shaper-use-machine.hh"
++#line 960 "hb-ot-shaper-use-machine.hh"
+         }
+ 
+         _keys = _use_syllable_machine_trans_keys + (cs<<1);
+@@ -965,87 +974,111 @@ _eof_trans:
+                 goto _again;
+ 
+         switch ( _use_syllable_machine_trans_actions[_trans] ) {
+-        case 6:
++        case 7:
+ #line 1 "NONE"
+         {te = p+1;}
+         break;
+-        case 14:
+-#line 172 "hb-ot-shaper-use-machine.rl"
++        case 16:
++#line 173 "hb-ot-shaper-use-machine.rl"
+         {te = p+1;{ found_syllable (use_virama_terminated_cluster); }}
+         break;
+-        case 12:
+-#line 173 "hb-ot-shaper-use-machine.rl"
++        case 14:
++#line 174 "hb-ot-shaper-use-machine.rl"
+         {te = p+1;{ found_syllable (use_sakot_terminated_cluster); }}
+         break;
+-        case 10:
+-#line 174 "hb-ot-shaper-use-machine.rl"
++        case 12:
++#line 175 "hb-ot-shaper-use-machine.rl"
+         {te = p+1;{ found_syllable (use_standard_cluster); }}
+         break;
+-        case 18:
+-#line 175 "hb-ot-shaper-use-machine.rl"
++        case 20:
++#line 176 "hb-ot-shaper-use-machine.rl"
+         {te = p+1;{ found_syllable (use_number_joiner_terminated_cluster); }}
+         break;
+-        case 16:
+-#line 176 "hb-ot-shaper-use-machine.rl"
++        case 18:
++#line 177 "hb-ot-shaper-use-machine.rl"
+         {te = p+1;{ found_syllable (use_numeral_cluster); }}
+         break;
+-        case 8:
+-#line 177 "hb-ot-shaper-use-machine.rl"
++        case 10:
++#line 178 "hb-ot-shaper-use-machine.rl"
+         {te = p+1;{ found_syllable (use_symbol_cluster); }}
+         break;
+-        case 22:
+-#line 178 "hb-ot-shaper-use-machine.rl"
++        case 25:
++#line 179 "hb-ot-shaper-use-machine.rl"
+         {te = p+1;{ found_syllable (use_hieroglyph_cluster); }}
+         break;
+         case 5:
+-#line 179 "hb-ot-shaper-use-machine.rl"
++#line 181 "hb-ot-shaper-use-machine.rl"
+         {te = p+1;{ found_syllable (use_broken_cluster); buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE; }}
+         break;
+         case 4:
+-#line 180 "hb-ot-shaper-use-machine.rl"
++#line 182 "hb-ot-shaper-use-machine.rl"
+         {te = p+1;{ found_syllable (use_non_cluster); }}
+         break;
+-        case 13:
+-#line 172 "hb-ot-shaper-use-machine.rl"
++        case 15:
++#line 173 "hb-ot-shaper-use-machine.rl"
+         {te = p;p--;{ found_syllable (use_virama_terminated_cluster); }}
+         break;
+-        case 11:
+-#line 173 "hb-ot-shaper-use-machine.rl"
++        case 13:
++#line 174 "hb-ot-shaper-use-machine.rl"
+         {te = p;p--;{ found_syllable (use_sakot_terminated_cluster); }}
+         break;
+-        case 9:
+-#line 174 "hb-ot-shaper-use-machine.rl"
++        case 11:
++#line 175 "hb-ot-shaper-use-machine.rl"
+         {te = p;p--;{ found_syllable (use_standard_cluster); }}
+         break;
+-        case 17:
+-#line 175 "hb-ot-shaper-use-machine.rl"
++        case 19:
++#line 176 "hb-ot-shaper-use-machine.rl"
+         {te = p;p--;{ found_syllable (use_number_joiner_terminated_cluster); }}
+         break;
+-        case 15:
+-#line 176 "hb-ot-shaper-use-machine.rl"
++        case 17:
++#line 177 "hb-ot-shaper-use-machine.rl"
+         {te = p;p--;{ found_syllable (use_numeral_cluster); }}
+         break;
+-        case 7:
+-#line 177 "hb-ot-shaper-use-machine.rl"
++        case 9:
++#line 178 "hb-ot-shaper-use-machine.rl"
+         {te = p;p--;{ found_syllable (use_symbol_cluster); }}
+         break;
+-        case 21:
+-#line 178 "hb-ot-shaper-use-machine.rl"
++        case 24:
++#line 179 "hb-ot-shaper-use-machine.rl"
+         {te = p;p--;{ found_syllable (use_hieroglyph_cluster); }}
+         break;
+-        case 19:
+-#line 179 "hb-ot-shaper-use-machine.rl"
++        case 21:
++#line 181 "hb-ot-shaper-use-machine.rl"
+         {te = p;p--;{ found_syllable (use_broken_cluster); buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE; }}
+         break;
+-        case 20:
+-#line 180 "hb-ot-shaper-use-machine.rl"
++        case 23:
++#line 182 "hb-ot-shaper-use-machine.rl"
+         {te = p;p--;{ found_syllable (use_non_cluster); }}
+         break;
+         case 1:
+-#line 177 "hb-ot-shaper-use-machine.rl"
++#line 178 "hb-ot-shaper-use-machine.rl"
+         {{p = ((te))-1;}{ found_syllable (use_symbol_cluster); }}
+         break;
+-#line 1049 "hb-ot-shaper-use-machine.hh"
++        case 22:
++#line 1 "NONE"
++        {       switch( act ) {
++        case 8:
++        {{p = ((te))-1;} found_syllable (use_non_cluster); }
++        break;
++        case 9:
++        {{p = ((te))-1;} found_syllable (use_broken_cluster); buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE; }
++        break;
++        }
++        }
++        break;
++        case 6:
++#line 1 "NONE"
++        {te = p+1;}
++#line 180 "hb-ot-shaper-use-machine.rl"
++        {act = 8;}
++        break;
++        case 8:
++#line 1 "NONE"
++        {te = p+1;}
++#line 181 "hb-ot-shaper-use-machine.rl"
++        {act = 9;}
++        break;
++#line 1082 "hb-ot-shaper-use-machine.hh"
+         }
+ 
+ _again:
+@@ -1054,7 +1087,7 @@ _again:
+ #line 1 "NONE"
+         {ts = 0;}
+         break;
+-#line 1058 "hb-ot-shaper-use-machine.hh"
++#line 1091 "hb-ot-shaper-use-machine.hh"
+         }
+ 
+         if ( ++p != pe )
+@@ -1070,7 +1103,7 @@ _again:
+ 
+         }
+ 
+-#line 289 "hb-ot-shaper-use-machine.rl"
++#line 291 "hb-ot-shaper-use-machine.rl"
+ 
+ }
+ 
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-use-table.hh b/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-use-table.hh
+index 491b2f940..d3c49949a 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-use-table.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-use-table.hh
+@@ -6,18 +6,18 @@
+  *
+  * on files with these headers:
+  *
+- * # IndicSyllabicCategory-15.1.0.txt
+- * # Date: 2023-01-05
+- * # IndicPositionalCategory-15.1.0.txt
+- * # Date: 2023-01-05
+- * # ArabicShaping-15.1.0.txt
+- * # Date: 2023-01-05
+- * # DerivedCoreProperties-15.1.0.txt
+- * # Date: 2023-08-07, 15:21:24 GMT
+- * # Blocks-15.1.0.txt
+- * # Date: 2023-07-28, 15:47:20 GMT
+- * # Scripts-15.1.0.txt
+- * # Date: 2023-07-28, 16:01:07 GMT
++ * # IndicSyllabicCategory-16.0.0.txt
++ * # Date: 2024-04-30, 21:48:21 GMT
++ * # IndicPositionalCategory-16.0.0.txt
++ * # Date: 2024-04-30, 21:48:21 GMT
++ * # ArabicShaping-16.0.0.txt
++ * # Date: 2024-07-30
++ * # DerivedCoreProperties-16.0.0.txt
++ * # Date: 2024-05-31, 18:09:32 GMT
++ * # Blocks-16.0.0.txt
++ * # Date: 2024-02-02
++ * # Scripts-16.0.0.txt
++ * # Date: 2024-04-30, 21:48:40 GMT
+  * # Override values For Indic_Syllabic_Category
+  * # Not derivable
+  * # Initial version based on Unicode 7.0 by Andrew Glass 2014-03-17
+@@ -27,6 +27,7 @@
+  * # Updated for Unicode 14.0 by Andrew Glass 2021-09-25
+  * # Updated for Unicode 15.0 by Andrew Glass 2022-09-16
+  * # Updated for Unicode 15.1 by Andrew Glass 2023-09-14
++ * # Updated for Unicode 16.0 by Andrew Glass 2024-09-11
+  * # Override values For Indic_Positional_Category
+  * # Not derivable
+  * # Initial version based on Unicode 7.0 by Andrew Glass 2014-03-17
+@@ -38,6 +39,7 @@
+  * # Updated for Unicode 14.0 by Andrew Glass 2021-09-28
+  * # Updated for Unicode 15.0 by Andrew Glass 2022-09-16
+  * # Updated for Unicode 15.1 by Andrew Glass 2023-09-14
++ * # Updated for Unicode 16.0 by Andrew Glass 2024-09-11
+  * UnicodeData.txt does not have a header.
+  */
+ 
+@@ -65,6 +67,7 @@
+ #define N       USE(N)  /* BASE_NUM */
+ #define O       USE(O)  /* OTHER */
+ #define R       USE(R)  /* REPHA */
++#define RK      USE(RK) /* REORDERING_KILLER */
+ #define SB      USE(SB) /* HIEROGLYPH_SEGMENT_BEGIN */
+ #define SE      USE(SE) /* HIEROGLYPH_SEGMENT_END */
+ #define SUB     USE(SUB)        /* CONS_SUB */
+@@ -99,16 +102,16 @@
+ #ifndef HB_OPTIMIZE_SIZE
+ 
+ static const uint8_t
+-hb_use_u8[3187] =
++hb_use_u8[3345] =
+ {
+-     16,   50,   51,   51,   51,   52,   51,   83,  118,  131,   51,   57,   58,  179,  195,   61,
++     16,   50,   51,   51,   51,   52,   51,   83,  118,  131,   57,   58,   59,  195,  211,   62,
+      51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
+      51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
+      51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
+      51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
+      51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
+      51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
+-     14,    0,    1,    2,    2,    2,    2,    3,    2,    2,    2,    2,    2,    4,    2,    2,
++     15,    0,    1,    2,    2,    2,    2,    3,    2,    2,    2,    2,    2,    4,    2,    2,
+       5,    6,    2,    7,    8,    9,   10,   11,   12,   13,   14,   15,   16,    2,    2,   17,
+      18,   19,   20,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,   21,
+      22,   23,   24,   25,   26,   27,   28,   29,   30,   31,   32,    2,   33,    2,    2,    2,
+@@ -121,24 +124,26 @@ hb_use_u8[3187] =
+       2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,
+       2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,   47,   48,    2,
+      49,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,   50,   51,    2,    2,    2,
+-      2,    2,    2,    2,    2,   52,   53,    2,   54,    2,    2,   55,    2,    2,   56,   57,
+-     58,   59,   60,   61,   62,   63,   64,   65,    2,   66,   67,    2,   68,   69,   70,   71,
+-      2,   72,    2,   73,   74,   75,   76,    2,    2,   77,   78,   79,   80,    2,   81,   82,
+-      2,   83,   83,   83,   83,   83,   83,   83,   83,   84,    2,    2,    2,    2,    2,    2,
++      2,    2,    2,    2,    2,   52,   53,    2,   54,    2,    2,   55,   56,    2,   57,   58,
++     59,   60,   61,   62,   63,   64,   65,   66,   67,   68,   69,    2,   70,   71,   72,   73,
++      2,   74,    2,   75,   76,   77,   78,    2,    2,   79,   80,   81,   82,    2,   83,   84,
++      2,   85,   85,   85,   85,   85,   85,   85,   85,   86,   85,   85,   85,   85,   85,   85,
++     85,   85,   85,   85,   85,   85,   85,   85,   85,   85,   85,   85,   85,   85,   85,   85,
++     85,   85,   85,   85,   85,   85,   85,   85,   87,    2,    2,    2,    2,    2,    2,    2,
+       2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,
++      2,    2,    2,   88,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,
++      2,    2,    2,    2,    2,    2,   89,   90,    2,    2,    2,   91,    2,    2,    2,   92,
++     93,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,
++      2,    2,    2,    2,    2,    2,    2,   94,   94,   94,   95,    2,    2,    2,    2,    2,
+       2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,
+-      2,    2,    2,    2,    2,    2,   85,   86,    2,    2,    2,    2,    2,    2,    2,   87,
+-     88,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,
+-      2,    2,    2,    2,    2,    2,    2,   89,   89,   89,   90,    2,    2,    2,    2,    2,
++      2,    2,    2,    2,    2,    2,    2,    2,    2,   96,   97,    2,    2,    2,    2,    2,
++      2,    2,    2,   98,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,
+       2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,
+-      2,    2,    2,    2,    2,    2,    2,    2,    2,   91,   92,    2,    2,    2,    2,    2,
+-      2,    2,    2,   93,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,
+-      2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,
+-      2,    2,    2,   94,    2,    2,   95,    2,    2,    2,   96,    2,    2,    2,    2,    2,
+-      2,    2,    2,   97,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,
+-      2,   98,   98,   99,  100,   98,   98,   98,   98,   98,   98,   98,   98,   98,   98,   98,
+-     98,   98,   98,   98,   98,   98,   98,   98,   98,   98,   98,   98,   98,   98,   98,   98,
+-     98,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    1,
++      2,    2,    2,   99,    2,    2,  100,    2,    2,    2,  101,    2,  102,    2,    2,    2,
++      2,    2,    2,  103,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,
++      2,  104,  104,  105,  106,  104,  104,  104,  104,  104,  104,  104,  104,  104,  104,  104,
++    104,  104,  104,  104,  104,  104,  104,  104,  104,  104,  104,  104,  104,  104,  104,  104,
++    104,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    1,
+       0,    2,    2,    2,    2,    2,    0,    0,    0,    0,    0,    0,    0,    0,    3,    4,
+       0,    5,    0,    0,    0,    0,    0,    6,    0,    0,    7,    0,    0,    0,    0,    0,
+       0,    0,    0,    0,    1,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+@@ -167,7 +172,7 @@ hb_use_u8[3187] =
+       0,    0,    0,   27,   31,    2,    9,    0,    0,   10,   29,   30,    2,    2,    2,    9,
+       2,    2,    2,   30,    2,    2,    0,   17,   45,    0,    0,   35,   47,    0,    0,    0,
+       9,   50,   51,    0,    0,    0,    0,    0,    0,   11,   29,    2,    2,    2,    2,    9,
+-      2,    2,    2,    2,    2,    2,   52,   53,   23,   23,   19,   31,   48,   33,   48,   34,
++      2,    2,    2,    2,    2,    2,   52,   53,   23,   19,   20,   31,   48,   33,   48,   34,
+      54,    0,    0,    0,   35,    0,    0,    0,   30,   12,   29,   30,    2,    2,    2,    2,
+       2,    2,    2,    2,    9,    0,    2,    2,    2,    2,   30,    2,    2,    2,    2,   30,
+       0,    2,    2,    2,    9,    0,   55,    0,   35,   23,   22,   31,   31,   18,   48,   48,
+@@ -195,9 +200,9 @@ hb_use_u8[3187] =
+       0,    2,    2,  100,  101,  102,  103,   61,   63,  104,   16,   45,   22,   59,   21,   80,
+      48,   48,   76,   11,   11,   11,  105,   46,   40,   11,  106,   74,    2,    2,    2,    2,
+       2,    2,    2,  107,   22,   20,   20,   22,   48,   48,   22,  108,    2,    2,    2,    9,
+-      0,    0,    0,    0,    0,    0,  109,  110,  111,  111,  111,    0,    0,    0,    0,    0,
+-      0,  106,   74,    2,    2,    2,    2,    2,    2,   60,   61,   59,   25,   22,  112,   61,
+-      2,    2,    2,    2,  107,   22,   23,   45,   45,  102,   14,    0,    0,    0,    0,    0,
++      0,    0,    0,    0,    0,    0,  109,  110,  110,  110,  110,    0,    0,    0,    0,    0,
++      0,  106,   74,    2,    2,    2,    2,    2,    2,   60,   61,   59,   25,   22,  111,   61,
++      2,    2,    2,    2,  107,   22,   23,   45,   45,  102,  112,    0,    0,    0,    0,    0,
+       0,    2,    2,   61,   18,   48,   23,  113,  102,  102,  102,  114,  115,    0,    0,    0,
+       0,    2,    2,    2,    2,    2,    0,   30,    2,   11,   46,  116,  116,  116,   11,  116,
+     116,   15,  116,  116,  116,   26,    0,   40,    0,    0,    0,  117,   51,   11,    5,    0,
+@@ -226,6 +231,7 @@ hb_use_u8[3187] =
+     146,    2,    2,   30,    2,   30,    2,    2,    2,    2,    2,    2,    0,   14,   37,    0,
+     147,    2,    2,   13,   37,    0,   30,    2,    2,    2,    0,    0,    0,    0,    0,    0,
+       0,    0,    0,    0,    0,   30,    2,    2,    9,    2,    2,   11,   41,    0,    0,    0,
++      0,    2,    2,    2,    0,   27,   22,   22,   30,    2,    2,    2,    0,    0,    0,    0,
+       0,    2,    2,    2,    2,    2,   27,   38,    0,    2,    2,    2,  116,  116,  116,  116,
+     116,  148,    2,    9,    0,    0,    0,    0,    0,    2,   14,   14,    0,    0,    0,    0,
+       0,    9,    2,    2,    9,    2,    2,    2,    2,   30,    2,    9,    0,   30,    2,    0,
+@@ -244,39 +250,45 @@ hb_use_u8[3187] =
+       0,   11,   11,   30,    2,    2,    2,    9,   30,    9,    2,   30,    2,    2,   58,   17,
+      23,   16,   23,   47,   32,   33,   32,   34,    0,    0,    0,    0,   35,    0,    0,    0,
+       2,    2,   23,    0,   11,   11,   11,   46,    0,   11,   11,   46,    0,    0,    0,    0,
+-      0,    2,    2,   65,   25,   20,   20,   20,   22,   23,  126,   15,   17,    0,    0,    0,
+-      0,    2,    2,    2,    2,    2,    0,    0,  163,  164,    0,    0,    0,    0,    0,    0,
+-      0,   18,   19,   20,   20,   66,   99,   25,  160,   11,  165,    9,    0,    0,    0,    0,
+-      0,    2,    2,    2,    2,    2,    2,    2,   65,   25,   20,   20,    0,   48,   48,   11,
+-    166,   37,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    2,    2,   20,
+-      0,   23,   19,   20,   20,   21,   16,   82,  166,   38,    0,    0,    0,    0,    0,    0,
+-      0,    2,    2,    2,    2,    2,   10,  167,   25,   20,   22,   22,  165,    9,    0,    0,
+-      0,    2,    2,    2,    2,    2,    9,   43,  136,   23,   22,   20,   76,   21,   22,    0,
+-      0,    2,    2,    2,    9,    0,    0,    0,    0,    2,    2,    2,    2,    2,    2,   18,
+-     19,   20,   21,   22,  105,  166,   37,    0,    0,    2,    2,    2,    9,   30,    0,    2,
+-      2,    2,    2,   30,    9,    2,    2,    2,    2,   23,   23,   18,   32,   33,   12,  168,
+-    169,  170,  171,    0,    0,    0,    0,    0,    0,    2,    2,    2,    2,    0,    2,    2,
+-      2,   65,   25,   20,   20,    0,   22,   23,   29,  108,    0,   33,    0,    0,    0,    0,
+-      0,   52,   20,   22,   22,   22,  140,    2,    2,    2,  172,  173,   11,   15,  174,   72,
+-    175,    0,    0,    1,  147,    0,    0,    0,    0,   52,   20,   22,   16,   19,   20,    2,
+-      2,    2,    2,  158,  158,  158,  176,  176,  176,  176,  176,  176,   15,  177,    0,   30,
+-      0,   22,   20,   20,   31,   22,   22,   11,  166,    0,   61,   61,   61,   61,   61,   61,
+-     61,   66,   21,   82,   46,    0,    0,    0,    0,    2,    2,    2,    9,    2,   30,    2,
+-      2,   52,   22,   22,   31,    0,   38,   22,   27,   11,  159,  178,  174,    0,    0,    0,
+-      0,    2,    2,    2,   30,    9,    2,    2,    2,    2,    2,    2,    2,    2,   23,   23,
+-     47,   22,   35,   82,   68,    0,    0,    0,    0,    2,  179,   66,   47,    0,    0,    0,
+-      0,   11,  180,    2,    2,    2,    2,    2,    2,    2,    2,   23,   22,   20,   31,    0,
+-     48,   16,  143,    0,    0,    0,    0,    0,    0,  181,  181,  181,  181,  181,  181,  181,
+-    181,  182,  182,  182,  183,  184,  182,  181,  181,  185,  181,  181,  186,  187,  187,  187,
+-    187,  187,  187,  187,    0,    0,    0,    0,    0,   11,   11,   11,   46,    0,    0,    0,
+-      0,    2,    2,    2,    2,    2,    9,    0,   58,  188,   20,   20,   20,   20,   20,   20,
+-     20,   20,   20,   20,   20,   20,   20,   20,   20,   20,   20,   20,   20,    0,    0,    0,
+-     40,  116,   26,    0,    0,    0,    0,    0,    0,    0,    0,    9,    0,    0,    0,    0,
+-      0,    2,    2,    2,    0,    0,    0,    0,    0,    2,    2,    2,    2,    2,    0,   58,
+-     37,    0,    6,  120,  120,  120,  121,    0,    0,   11,   11,   11,   49,    2,    2,    2,
+-      0,    2,    2,    2,    2,    2,    0,    0,    2,    2,    2,    2,    2,    2,    2,    2,
+-     46,    2,    2,    2,    2,    2,    2,   11,   11,    2,    2,    2,    2,    2,    2,   22,
+-     22,    2,    2,   44,   44,   44,   92,    0,    0,    O,    O,    O,   GB,    B,    B,    O,
++      0,    2,    2,    2,    2,    2,   30,    0,    9,    2,    2,    2,   30,   45,   59,   20,
++     20,   31,   33,   32,   32,   25,  163,   29,  164,  165,   37,    0,    0,    0,    0,    0,
++      0,   12,   26,    0,    0,    0,    0,    0,    0,    2,    2,   65,   25,   20,   20,   20,
++     22,   23,  126,   15,   17,    0,    0,    0,    0,    2,    2,    2,    2,    2,    0,    0,
++    166,  167,    0,    0,    0,    0,    0,    0,    0,   18,   19,   20,   20,   66,   99,   25,
++    160,   11,  168,    9,    0,    0,    0,    0,    0,    2,    2,    2,    2,    2,    2,    2,
++     65,   25,   20,   20,    0,   48,   48,   11,  169,   37,    0,    0,    0,    0,    0,    0,
++      0,    0,    0,    0,    0,    2,    2,   20,    0,   23,   19,   20,   20,   21,   16,   82,
++    169,   38,    0,    0,    0,    0,    0,    0,    0,    2,    2,    2,    2,    2,   10,  170,
++     25,   20,   22,   22,  168,    9,    0,    0,    0,    2,    2,    2,    2,    2,    9,   43,
++    136,   23,   22,   20,   76,   21,   22,    0,    0,    2,    2,    2,    9,    0,    0,    0,
++      0,    2,    2,    2,    2,    2,    2,   18,   19,   20,   21,   22,  105,  169,   37,    0,
++      0,    2,    2,    2,    9,   30,    0,    2,    2,    2,    2,   30,    9,    2,    2,    2,
++      2,   23,   23,   18,   32,   33,   12,  171,  165,  172,  173,    0,    0,    0,    0,    0,
++      0,    2,    2,    2,    2,    0,    2,    2,    2,   65,   25,   20,   20,    0,   22,   23,
++     29,  108,    0,   33,    0,    0,    0,    0,    0,   52,   20,   22,   22,   22,  140,    2,
++      2,    2,  174,  175,   11,   15,  176,   61,  177,    0,    0,    1,  147,    0,    0,    0,
++      0,   52,   20,   22,   16,   19,   20,    2,    2,    2,    2,  158,  158,  158,  178,  178,
++    178,  178,  178,  178,   15,  179,    0,   30,    0,   22,   20,   20,   31,   22,   22,   11,
++    169,    0,   61,   61,   61,   61,   61,   61,   61,   66,   21,   82,   46,    0,    0,    0,
++      0,    2,    2,    2,    9,    2,   30,    2,    2,   52,   22,   22,   31,    0,   38,   22,
++     27,   11,  159,  180,  181,    0,    0,    0,    0,    2,    2,    2,   30,    9,    2,    2,
++      2,    2,    2,    2,    2,    2,   23,   23,   47,   22,   35,   82,   68,    0,    0,    0,
++      0,    2,  182,   66,   47,    0,    0,    0,    0,   11,  183,    2,    2,    2,    2,    2,
++      2,    2,    2,   23,   22,   20,   31,    0,   48,   16,  143,    0,    0,    0,    0,    0,
++      0,    2,    2,    2,    2,    2,  156,    0,    0,  184,  184,  184,  184,  184,  184,  184,
++    184,  185,  185,  185,  186,  187,  185,  184,  184,  188,  184,  184,  189,  190,  190,  190,
++    190,  190,  190,  190,    0,    0,    0,    0,    0,  184,  184,  184,  184,  184,  191,    0,
++      0,    2,    2,    2,    2,    2,    2,    2,   22,   22,   22,   22,   22,   22,  192,  193,
++    194,   11,   11,   11,   46,    0,    0,    0,    0,   29,   74,    2,    2,    2,    2,    2,
++      2,    2,    2,    2,    2,    2,   65,   47,    0,    2,    2,    2,    2,    2,    9,    0,
++     58,  195,   20,   20,   20,   20,   20,   20,   20,   20,   20,   20,   20,   20,   20,   20,
++     20,   20,   20,   20,   20,    0,    0,    0,   40,  116,   26,    0,    0,    0,    0,    0,
++      0,    0,    0,    9,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
++     30,    2,    2,    2,    2,    2,    0,   58,   37,    0,    6,  120,  120,  120,  121,    0,
++      0,   11,   11,   11,   49,    2,    2,    2,    0,    2,    2,    2,    2,    2,    0,    0,
++      2,    2,    2,    2,    2,    2,    2,    2,   46,    2,    2,    2,    2,    2,    2,   11,
++     11,    2,    2,    2,    2,    2,    2,   22,   22,    2,    2,    2,    2,    2,    2,    2,
++     20,    2,    2,   44,   44,   44,   92,    0,    0,    O,    O,    O,   GB,    B,    B,    O,
+      SB,    O,   SE,   GB,    O,    O,   WJ,FMPst,FMPst,    O,  CGJ,    B,    O,    B,VMAbv,VMAbv,
+   VMAbv,    O,VMAbv,    B,CMBlw,CMBlw,CMBlw,VMAbv,VMPst, VAbv, VPst,CMBlw,    B, VPst, VPre, VPst,
+    VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, VAbv, VPst, VPst, VPst,    H, VPre, VPst,VMBlw,    O,    O,
+@@ -290,20 +302,21 @@ hb_use_u8[3187] =
+   FMAbv, FAbv,CMAbv,FMAbv,VMAbv,FMAbv, VAbv,   IS,FMAbv,    B,FMAbv,    B,  CGJ,   WJ,  CGJ,   GB,
+   CMAbv,CMAbv,    B,   GB,    B, VAbv,  SUB, FPst, FPst,VMBlw, FPst, FPst, FBlw,VMAbv,FMBlw, VAbv,
+    VPre,    B, MPre, MBlw,  SUB, FAbv, FAbv, MAbv,  SUB,   Sk, VPst, VAbv,VMAbv,VMAbv, FAbv,CMAbv,
+-   VPst,    H,    B,    O,SMAbv,SMBlw,SMAbv,SMAbv,SMAbv, VPst,   IS, VBlw, FAbv,VMPre,VMPre,FMAbv,
++   VPst,    H,    B,    O,SMAbv,SMAbv,SMAbv, VPst,   IS,   RK,   RK, VBlw, FAbv,VMPre,VMPre,FMAbv,
+   CMBlw,VMBlw,VMBlw,VMAbv,   CS,    O,FMAbv, ZWNJ,  CGJ,   WJ,   WJ,   WJ,    O,FMPst,    O,   SB,
+      SE,    O,    H, MPst, VPst,    H,VMAbv, VAbv,VMBlw,    B, VBlw, FPst, VPst, FAbv,VMPst,    B,
+   CMAbv, VAbv, MBlw, MPst, MBlw,    H,    O, VBlw, MPst, MPre, MAbv, MBlw,    O,    B, FAbv, FAbv,
+    FPst, VBlw,    B,    B, VPre,    O,VMPst,   IS,    O,VMPst, VBlw, VPst,VMBlw,VMBlw,VMAbv,    O,
+      IS,VMBlw,    B,VMPst,VMAbv,VMPst,   CS,   CS,    B,    N,    N,    O,   HN, VPre, VBlw, VAbv,
+-     IS,CMAbv,    O, VPst,    B,    R,    R,CMBlw, VAbv, VPre,VMAbv,VMAbv,    H, VAbv,CMBlw,FMAbv,
+-      B,   CS,   CS,    H,CMBlw,VMPst,    H,VMPst, VAbv,VMAbv, VPst,   IS,    R, MPst,    R, MPst,
+-  CMBlw,    B,FMBlw, VBlw,VMAbv,    R, MBlw, MBlw,   GB, FBlw, FBlw,CMAbv,   IS, VBlw,   IS,   GB,
+-   VAbv,    R,VMPst,    G,    G,    J,    J,    J,   SB,   SE,    J,   HR,    G,    G,   HM,   HM,
+-     HM,    O, VBlw,
++     IS,CMAbv,    O, VPst,    B,    R,    R,CMBlw, VAbv, VPre,VMAbv,VMAbv,    H, VAbv,CMBlw,VMPst,
++      O,VMAbv,CMBlw,   IS,    R,FMAbv,    B,   CS,   CS,    H,CMBlw,VMPst,    H,VMPst, VAbv,VMAbv,
++   VPst, MPst,    R, MPst,CMBlw,    B,FMBlw, VBlw,VMAbv,   CS,  SUB,  SUB,   GB, FBlw, FBlw,CMAbv,
++     IS, VBlw,   IS,    R, MBlw,   GB, VAbv,    R,VMPst,    G,    G,    J,    J,    J,   SB,   SE,
++      J,   HR,    G,    G,   HM,   HM,   HM,    G,    O, MPre, MPre, MPst,VMAbv, MBlw, VBlw,    O,
++   VBlw,
+ };
+ static const uint16_t
+-hb_use_u16[808] =
++hb_use_u16[856] =
+ {
+     0,  0,  1,  2,  0,  3,  0,  3,  0,  0,  4,  5,  0,  6,  0,  0,
+     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  7,  0,  0,  0,
+@@ -332,28 +345,31 @@ hb_use_u16[808] =
+     0,  0,  0,  0,  0,  0,  0,164,  0,  0,  0,  0,  0,  0,  0,165,
+     0,  0,  0,  0,  0,  0,  0,166,166,167, 34,168,  0,  0,  0,  0,
+   169,170, 10,171, 95,  0,  0,  0,  0,  0,  0,  0, 70, 10,172,  0,
+-   10,173,174,  0,  0,  0,  0,  0, 10, 10,175,  2,  0,  0,  0,  0,
+-   10, 10,176,173,  0,  0,  0,  0,  0,  0,  0, 10,177,178,  0, 10,
+-  179,  0,  0,180,181,  0,  0,  0,182, 10, 10,183,184,185,186,187,
+-  188, 10, 10,189,190,  0,  0,  0,191, 10,192,193,194, 10, 10,195,
+-  188, 10, 10,196,197,106,198,103, 10, 34,199,200,201,  0,  0,  0,
+-  202,203, 95, 10, 10,204,205,  2,206, 21, 22,207,208,209,210,211,
+-   10, 10, 10,212,213,214,215,  0,198, 10, 10,216,217,  2,  0,  0,
+-   10, 10,218,219,220,221,  0,  0, 10, 10, 10,222,223,  2,  0,  0,
+-   10, 10,224,225,  2,  0,  0,  0, 10,226,227,104,228,  0,  0,  0,
+-   10, 10,229,230,  0,  0,  0,  0,231,232, 10,233,234,  2,  0,  0,
+-    0,  0,235, 10, 10,236,237,  0,238, 10, 10,239,240,241, 10, 10,
+-  242,243,  0,  0,  0,  0,  0,  0, 22, 10,218,244,  8, 10, 71, 19,
+-   10,245, 74,246,  0,  0,  0,  0,247, 10, 10,248,249,  2,250, 10,
+-  251,252,  2,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 10,253,
+-  254, 49, 10,255,256,  2,  0,  0,257,257,257,257,257,257,257,257,
+-  257,257,257,258,259,260,  0,  0,  0,  0,  0,  0,  2,  0,  0,  0,
+-   10, 10, 10,261,  0,  0,  0,  0, 10, 10, 10, 10,262,263,264,264,
+-  265,266,  0,  0,  0,  0,267,  0, 10, 10, 10, 10, 10, 10, 10, 10,
+-   10, 10, 10, 10, 10,268,  0,  0, 10, 10, 10, 10, 10, 10,106, 71,
+-   95,269,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,270,
+-   10, 10, 71,271,272,  0,  0,  0,  0, 10,273,  0, 10, 10,274,  2,
+-    0,  0,  0,  0,  0, 10,275,  2, 10, 10, 10, 10,276,  2,  0,  0,
++   10,173,174,  0,  0,  0,  0,  0, 10, 10,175,  2,  9, 10,176, 10,
++  177,  0,  0,  0,  0,  0,  0,  0, 10, 10,178,173,  0,  0,  0,  0,
++    0,  0,  0, 10,179,180,  0, 10,181,  0,  0,182,183,  0,  0,  0,
++  184, 10, 10,185,186,187,188,189,190, 10, 10,191,192,  0,  0,  0,
++  193, 10,194,195,196, 10, 10,197,190, 10, 10,198,199,106,200,103,
++   10, 34,201,202,203,  0,  0,  0,204,205, 95, 10, 10,206,207,  2,
++  208, 21, 22,209,210,211,212,213,214, 10, 10,215,216,217,218,  0,
++   10, 10, 10,219,220,221,222,  0,200, 10, 10,223,224,  2,  0,  0,
++   10, 10,225,226,227,228,  0,  0, 10, 10, 10,229,230,  2,  0,  0,
++   10, 10,231,232,  2, 10,141,  0, 10,233,234,104,235,  0,  0,  0,
++   10, 10,236,237,  0,  0,  0,  0,238,239, 10,240,241,  2,  0,  0,
++    0,  0,242, 10, 10,243,244,  0,245, 10, 10,246,247,248, 10, 10,
++  249,250,  0,  0,  0,  0,  0,  0, 22, 10,225,251,  8, 10, 71, 19,
++   10,252, 74,253,  0,  0,  0,  0,254, 10, 10,255,256,  2,257, 10,
++  258,259,  2,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 10,260,
++  261, 49, 10,262,263,264,  0,  0,265,265,265,265,265,265,265,265,
++  265,265,265,266,267,268,265,265,265,265,265,265,265,265,265,269,
++   10,270,271,  2,  0,  0,  0,  0,  0,  0,  0,  0,  2,  0,  0,  0,
++   10, 10, 10,272,  0,  0,  0,  0,  0,  0,  0,  0,273, 10,274,  2,
++   10, 10, 10, 10,275,276,277,277,278,279,  0,  0,  0,  0,280,  0,
++   10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,177,  0,281,
++   10, 10, 10, 10, 10, 10,106, 71, 95,282,  0,  0,  0,  0,  0,  0,
++    0,  0,  0,  0,  0,  0,  0,283, 10, 10, 71,284,285,  0,  0,  0,
++    0, 10,286,  0, 10, 10,287,  2,  0,  0,  0,  0,  0, 10,288,  2,
++    0,  0,  0,  0,  0, 10,289,106, 10, 10, 10, 10,290,  2,  0,  0,
+   130,130,130,130,130,130,130,130,163,163,163,163,163,163,163,163,
+   163,163,163,163,163,163,163,130,
+ };
+@@ -366,23 +382,23 @@ hb_use_b4 (const uint8_t* a, unsigned i)
+ static inline uint_fast8_t
+ hb_use_get_category (unsigned u)
+ {
+-  return u<921600u?hb_use_u8[2809+(((hb_use_u8[593+(((hb_use_u16[((hb_use_u8[113+(((hb_use_b4(hb_use_u8,u>>1>>3>>3>>5))<<5)+((u>>1>>3>>3)&31u))])<<3)+((u>>1>>3)&7u)])<<3)+((u>>1)&7u))])<<1)+((u)&1u))]:O;
++  return u<921600u?hb_use_u8[2953+(((hb_use_u8[625+(((hb_use_u16[((hb_use_u8[113+(((hb_use_b4(hb_use_u8,u>>1>>3>>3>>5))<<5)+((u>>1>>3>>3)&31u))])<<3)+((u>>1>>3)&7u)])<<3)+((u>>1)&7u))])<<1)+((u)&1u))]:O;
+ }
+ 
+ 
+ #else
+ 
+ static const uint8_t
+-hb_use_u8[3483] =
++hb_use_u8[3657] =
+ {
+-     16,   50,   51,   51,   51,   52,   51,   83,  118,  131,   51,   57,   58,  179,  195,   61,
++     16,   50,   51,   51,   51,   52,   51,   83,  118,  131,   57,   58,   59,  195,  211,   62,
+      51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
+      51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
+      51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
+      51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
+      51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
+      51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,   51,
+-     14,    0,    1,    1,    2,    1,    1,    3,    4,    5,    6,    7,    8,    9,   10,    1,
++     15,    0,    1,    1,    2,    1,    1,    3,    4,    5,    6,    7,    8,    9,   10,    1,
+      11,   12,    1,    1,    1,    1,    1,    1,   13,   14,   15,   16,   17,   18,   19,    1,
+       1,   20,    1,    1,    1,    1,   21,    1,   22,    1,    1,    1,    1,    1,   23,   24,
+       1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+@@ -390,14 +406,15 @@ hb_use_u8[3483] =
+       1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,   29,
+      30,    1,    1,    1,    1,    1,   31,    1,    1,    1,    1,   32,   33,    1,   34,   35,
+      36,   37,   38,   39,   40,   41,   42,   43,   44,   45,   46,   47,    1,   48,   49,   50,
+-     51,   52,   52,   52,   52,   53,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+-      1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,   54,   55,    1,    1,    1,
+-     56,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,   57,   58,    1,    1,
+-      1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,   59,    1,    1,
+-      1,    1,   60,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+-      1,    1,   61,   62,    1,   63,    1,    1,    1,    1,   64,    1,    1,    1,    1,    1,
+-      1,   65,   66,   65,   65,   65,   65,   65,   65,   65,   65,   65,   65,   65,   65,   65,
+-     65,    0,    1,    2,    2,    0,    3,    4,    0,    0,    0,    0,    0,    0,    0,    0,
++     51,   52,   52,   52,   52,   53,   52,   52,   52,   52,   52,   52,   52,   52,   52,   52,
++     52,   52,   52,   52,   54,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
++      1,    1,   55,    1,    1,    1,    1,    1,    1,    1,    1,   56,   57,    1,   58,    1,
++     59,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,   60,   61,    1,    1,
++      1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,   62,    1,    1,
++      1,    1,   63,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
++      1,    1,   64,   65,    1,   66,   67,    1,    1,    1,   68,    1,    1,    1,    1,    1,
++      1,   69,   70,   69,   69,   69,   69,   69,   69,   69,   69,   69,   69,   69,   69,   69,
++     69,    0,    1,    2,    2,    0,    3,    4,    0,    0,    0,    0,    0,    0,    0,    0,
+       0,    0,    0,    5,    0,    0,    0,    0,    0,    0,    0,    6,    0,    0,    0,    0,
+       0,    0,    0,    0,    0,    0,    0,    7,    8,    0,    0,    9,    0,    0,    0,    0,
+       0,   10,   11,   12,   13,   14,   15,   16,   17,   18,   19,   20,   21,   22,   23,   24,
+@@ -414,23 +431,25 @@ hb_use_u8[3483] =
+     122,    0,    0,    0,    0,    0,    0,   56,  123,  124,    0,    0,    0,    0,    0,    0,
+     125,    0,    0,    0,    0,    0,    0,    0,  126,    0,    0,    0,  127,  128,  129,    0,
+       0,  130,  131,  132,    0,    0,    0,   51,  133,    0,    0,    0,    0,  134,  135,    0,
+-      0,   56,  136,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,   56,  137,    0,
+-      0,    0,  101,  138,  101,  139,  140,  141,    0,  142,  143,  144,  145,  146,  147,  148,
+-      0,  149,  150,  151,  152,  146,  153,  154,  155,  156,  157,  158,    0,  159,  160,  161,
+-    162,  163,  164,  165,  166,    0,    0,    0,    0,   56,  167,  168,  169,  170,  171,  172,
+-      0,    0,    0,    0,    0,   56,  173,  174,    0,   56,  175,  176,    0,   56,  177,   67,
+-      0,  178,  179,  180,    0,    0,    0,    0,    0,   56,  181,    0,    0,    0,    0,    0,
+-      0,  182,  183,  184,    0,    0,  185,  186,  187,  188,  189,  190,   56,  191,    0,    0,
+-      0,  192,  193,  194,  195,  196,  197,    0,    0,  198,  199,  200,  201,  202,   67,    0,
+-      0,    0,    0,    0,    0,    0,    0,    0,  203,  204,  205,  206,    0,    0,    0,    0,
+-      0,  207,  207,  207,  207,  207,  207,  207,  207,  207,  208,  209,    0,    0,    0,    0,
+-      0,    0,    0,    0,    0,    0,    0,   67,    0,   56,  210,    0,    0,    0,    0,    0,
+-      0,   56,   56,  211,  212,  213,    0,    0,  214,   56,   56,   56,   56,   56,   56,   56,
+-     56,   56,   56,   56,   56,   56,   56,  215,    0,   56,   56,   56,  216,  217,    0,    0,
+-      0,    0,    0,    0,  218,    0,    0,    0,    0,   56,  219,  220,    0,    0,    0,    0,
+-      0,    0,    0,    0,    0,  101,  221,   56,  222,    0,    0,    0,    0,    0,    0,  101,
+-    223,   56,   56,  224,    0,    0,    0,    0,    0,  225,  225,  225,  225,  225,  225,  225,
+-    225,  226,  226,  226,  226,  226,  226,  226,  227,    0,    0,    0,    0,    0,    0,    0,
++      0,   56,  136,    7,  137,  138,    0,    0,    0,    0,    0,    0,    0,   56,  139,    0,
++      0,    0,  101,  140,  101,  141,  142,  143,    0,  144,  145,  146,  147,  148,  149,  150,
++      0,  151,  152,  153,  154,  148,  155,  156,  157,  158,  159,  160,    0,  161,  162,  163,
++    164,  165,  166,  167,  168,  169,  170,  171,  172,   56,  173,  174,  175,  176,  177,  178,
++      0,    0,    0,    0,    0,   56,  179,  180,    0,   56,  181,  182,    0,   56,  183,  184,
++    185,  186,  187,  188,    0,    0,    0,    0,    0,   56,  189,    0,    0,    0,    0,    0,
++      0,  190,  191,  192,    0,    0,  193,  194,  195,  196,  197,  198,   56,  199,    0,    0,
++      0,  200,  201,  202,  203,  204,  205,    0,    0,  206,  207,  208,  209,  210,   67,    0,
++      0,    0,    0,    0,    0,    0,    0,    0,  211,  212,  213,  214,    0,    0,    0,    0,
++      0,  215,  215,  215,  215,  215,  215,  215,  215,  215,  216,  217,  215,  215,  215,  215,
++    215,  215,  215,  215,  215,  215,  215,  215,  218,  219,  220,    0,    0,    0,    0,    0,
++      0,    0,    0,    0,    0,    0,    0,   67,    0,   56,  221,    0,    0,    0,    0,    0,
++      0,    0,    0,  222,  223,    0,    0,    0,    0,   56,   56,  224,  225,  226,    0,    0,
++    227,   56,   56,   56,   56,   56,   56,   56,   56,   56,   56,   56,   56,   56,   56,  228,
++    229,   56,   56,   56,  230,  231,    0,    0,    0,    0,    0,    0,  232,    0,    0,    0,
++      0,   56,  233,  234,    0,    0,    0,    0,    0,    0,    0,    0,    0,  101,  235,   56,
++    236,    0,    0,    0,    0,    0,    0,  101,  237,    0,    0,    0,    0,    0,    0,  101,
++    238,   56,   56,  239,    0,    0,    0,    0,    0,  240,  240,  240,  240,  240,  240,  240,
++    240,  241,  241,  241,  241,  241,  241,  241,  242,    0,    0,    0,    0,    0,    0,    0,
+       0,    0,    0,    0,    0,    0,    0,    1,    0,    2,    2,    2,    2,    2,    0,    0,
+       0,    0,    0,    0,    0,    0,    3,    4,    0,    5,    0,    0,    0,    0,    0,    6,
+       0,    0,    7,    0,    0,    0,    0,    0,    0,    0,    0,    0,    1,    0,    0,    0,
+@@ -460,7 +479,7 @@ hb_use_u8[3483] =
+       0,   10,   29,   30,    2,    2,    2,    9,    2,    2,    2,   30,    2,    2,    0,   17,
+      45,    0,    0,   35,   47,    0,    0,    0,    9,   50,   51,    0,    0,    0,    0,    0,
+       0,   11,   29,    2,    2,    2,    2,    9,    2,    2,    2,    2,    2,    2,   52,   53,
+-     23,   23,   19,   31,   48,   33,   48,   34,   54,    0,    0,    0,   35,    0,    0,    0,
++     23,   19,   20,   31,   48,   33,   48,   34,   54,    0,    0,    0,   35,    0,    0,    0,
+      30,   12,   29,   30,    2,    2,    2,    2,    2,    2,    2,    2,    9,    0,    2,    2,
+       2,    2,   30,    2,    2,    2,    2,   30,    0,    2,    2,    2,    9,    0,   55,    0,
+      35,   23,   22,   31,   31,   18,   48,   48,   25,    0,   23,    0,    0,    0,    0,    0,
+@@ -488,9 +507,9 @@ hb_use_u8[3483] =
+      63,  104,   16,   45,   22,   59,   21,   80,   48,   48,   76,   11,   11,   11,  105,   46,
+      40,   11,  106,   74,    2,    2,    2,    2,    2,    2,    2,  107,   22,   20,   20,   22,
+      48,   48,   22,  108,    2,    2,    2,    9,    0,    0,    0,    0,    0,    0,  109,  110,
+-    111,  111,  111,    0,    0,    0,    0,    0,    0,  106,   74,    2,    2,    2,    2,    2,
+-      2,   60,   61,   59,   25,   22,  112,   61,    2,    2,    2,    2,  107,   22,   23,   45,
+-     45,  102,   14,    0,    0,    0,    0,    0,    0,    2,    2,   61,   18,   48,   23,  113,
++    110,  110,  110,    0,    0,    0,    0,    0,    0,  106,   74,    2,    2,    2,    2,    2,
++      2,   60,   61,   59,   25,   22,  111,   61,    2,    2,    2,    2,  107,   22,   23,   45,
++     45,  102,  112,    0,    0,    0,    0,    0,    0,    2,    2,   61,   18,   48,   23,  113,
+     102,  102,  102,  114,  115,    0,    0,    0,    0,    2,    2,    2,    2,    2,    0,   30,
+       2,   11,   46,  116,  116,  116,   11,  116,  116,   15,  116,  116,  116,   26,    0,   40,
+       0,    0,    0,  117,   51,   11,    5,    0,    0,    0,    0,    0,    0,    0,  118,    0,
+@@ -518,7 +537,8 @@ hb_use_u8[3483] =
+       0,  128,   20,   27,   31,    0,    0,  145,  146,    2,    2,   30,    2,   30,    2,    2,
+       2,    2,    2,    2,    0,   14,   37,    0,  147,    2,    2,   13,   37,    0,   30,    2,
+       2,    2,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,   30,    2,    2,
+-      9,    2,    2,   11,   41,    0,    0,    0,    0,    2,    2,    2,    2,    2,   27,   38,
++      9,    2,    2,   11,   41,    0,    0,    0,    0,    2,    2,    2,    0,   27,   22,   22,
++     30,    2,    2,    2,    0,    0,    0,    0,    0,    2,    2,    2,    2,    2,   27,   38,
+       0,    2,    2,    2,  116,  116,  116,  116,  116,  148,    2,    9,    0,    0,    0,    0,
+       0,    2,   14,   14,    0,    0,    0,    0,    0,    9,    2,    2,    9,    2,    2,    2,
+       2,   30,    2,    9,    0,   30,    2,    0,    0,  149,  150,  151,    2,    2,    2,    2,
+@@ -536,39 +556,45 @@ hb_use_u8[3483] =
+      10,   18,   19,   21,   22,  162,   31,    0,    0,   11,   11,   30,    2,    2,    2,    9,
+      30,    9,    2,   30,    2,    2,   58,   17,   23,   16,   23,   47,   32,   33,   32,   34,
+       0,    0,    0,    0,   35,    0,    0,    0,    2,    2,   23,    0,   11,   11,   11,   46,
+-      0,   11,   11,   46,    0,    0,    0,    0,    0,    2,    2,   65,   25,   20,   20,   20,
+-     22,   23,  126,   15,   17,    0,    0,    0,    0,    2,    2,    2,    2,    2,    0,    0,
+-    163,  164,    0,    0,    0,    0,    0,    0,    0,   18,   19,   20,   20,   66,   99,   25,
+-    160,   11,  165,    9,    0,    0,    0,    0,    0,    2,    2,    2,    2,    2,    2,    2,
+-     65,   25,   20,   20,    0,   48,   48,   11,  166,   37,    0,    0,    0,    0,    0,    0,
+-      0,    0,    0,    0,    0,    2,    2,   20,    0,   23,   19,   20,   20,   21,   16,   82,
+-    166,   38,    0,    0,    0,    0,    0,    0,    0,    2,    2,    2,    2,    2,   10,  167,
+-     25,   20,   22,   22,  165,    9,    0,    0,    0,    2,    2,    2,    2,    2,    9,   43,
+-    136,   23,   22,   20,   76,   21,   22,    0,    0,    2,    2,    2,    9,    0,    0,    0,
+-      0,    2,    2,    2,    2,    2,    2,   18,   19,   20,   21,   22,  105,  166,   37,    0,
+-      0,    2,    2,    2,    9,   30,    0,    2,    2,    2,    2,   30,    9,    2,    2,    2,
+-      2,   23,   23,   18,   32,   33,   12,  168,  169,  170,  171,    0,    0,    0,    0,    0,
+-      0,    2,    2,    2,    2,    0,    2,    2,    2,   65,   25,   20,   20,    0,   22,   23,
+-     29,  108,    0,   33,    0,    0,    0,    0,    0,   52,   20,   22,   22,   22,  140,    2,
+-      2,    2,  172,  173,   11,   15,  174,   72,  175,    0,    0,    1,  147,    0,    0,    0,
+-      0,   52,   20,   22,   16,   19,   20,    2,    2,    2,    2,  158,  158,  158,  176,  176,
+-    176,  176,  176,  176,   15,  177,    0,   30,    0,   22,   20,   20,   31,   22,   22,   11,
+-    166,    0,   61,   61,   61,   61,   61,   61,   61,   66,   21,   82,   46,    0,    0,    0,
+-      0,    2,    2,    2,    9,    2,   30,    2,    2,   52,   22,   22,   31,    0,   38,   22,
+-     27,   11,  159,  178,  174,    0,    0,    0,    0,    2,    2,    2,   30,    9,    2,    2,
+-      2,    2,    2,    2,    2,    2,   23,   23,   47,   22,   35,   82,   68,    0,    0,    0,
+-      0,    2,  179,   66,   47,    0,    0,    0,    0,   11,  180,    2,    2,    2,    2,    2,
+-      2,    2,    2,   23,   22,   20,   31,    0,   48,   16,  143,    0,    0,    0,    0,    0,
+-      0,  181,  181,  181,  181,  181,  181,  181,  181,  182,  182,  182,  183,  184,  182,  181,
+-    181,  185,  181,  181,  186,  187,  187,  187,  187,  187,  187,  187,    0,    0,    0,    0,
+-      0,   11,   11,   11,   46,    0,    0,    0,    0,    2,    2,    2,    2,    2,    9,    0,
+-     58,  188,   20,   20,   20,   20,   20,   20,   20,   20,   20,   20,   20,   20,   20,   20,
+-     20,   20,   20,   20,   20,    0,    0,    0,   40,  116,   26,    0,    0,    0,    0,    0,
+-      0,    0,    0,    9,    0,    0,    0,    0,    0,    2,    2,    2,    0,    0,    0,    0,
+-      0,    2,    2,    2,    2,    2,    0,   58,   37,    0,    6,  120,  120,  120,  121,    0,
+-      0,   11,   11,   11,   49,    2,    2,    2,    0,    2,    2,    2,    2,    2,    0,    0,
+-      2,    2,    2,    2,    2,    2,    2,    2,   46,    2,    2,    2,    2,    2,    2,   11,
+-     11,    2,    2,    2,    2,    2,    2,   22,   22,    2,    2,   44,   44,   44,   92,    0,
++      0,   11,   11,   46,    0,    0,    0,    0,    0,    2,    2,    2,    2,    2,   30,    0,
++      9,    2,    2,    2,   30,   45,   59,   20,   20,   31,   33,   32,   32,   25,  163,   29,
++    164,  165,   37,    0,    0,    0,    0,    0,    0,   12,   26,    0,    0,    0,    0,    0,
++      0,    2,    2,   65,   25,   20,   20,   20,   22,   23,  126,   15,   17,    0,    0,    0,
++      0,    2,    2,    2,    2,    2,    0,    0,  166,  167,    0,    0,    0,    0,    0,    0,
++      0,   18,   19,   20,   20,   66,   99,   25,  160,   11,  168,    9,    0,    0,    0,    0,
++      0,    2,    2,    2,    2,    2,    2,    2,   65,   25,   20,   20,    0,   48,   48,   11,
++    169,   37,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    2,    2,   20,
++      0,   23,   19,   20,   20,   21,   16,   82,  169,   38,    0,    0,    0,    0,    0,    0,
++      0,    2,    2,    2,    2,    2,   10,  170,   25,   20,   22,   22,  168,    9,    0,    0,
++      0,    2,    2,    2,    2,    2,    9,   43,  136,   23,   22,   20,   76,   21,   22,    0,
++      0,    2,    2,    2,    9,    0,    0,    0,    0,    2,    2,    2,    2,    2,    2,   18,
++     19,   20,   21,   22,  105,  169,   37,    0,    0,    2,    2,    2,    9,   30,    0,    2,
++      2,    2,    2,   30,    9,    2,    2,    2,    2,   23,   23,   18,   32,   33,   12,  171,
++    165,  172,  173,    0,    0,    0,    0,    0,    0,    2,    2,    2,    2,    0,    2,    2,
++      2,   65,   25,   20,   20,    0,   22,   23,   29,  108,    0,   33,    0,    0,    0,    0,
++      0,   52,   20,   22,   22,   22,  140,    2,    2,    2,  174,  175,   11,   15,  176,   61,
++    177,    0,    0,    1,  147,    0,    0,    0,    0,   52,   20,   22,   16,   19,   20,    2,
++      2,    2,    2,  158,  158,  158,  178,  178,  178,  178,  178,  178,   15,  179,    0,   30,
++      0,   22,   20,   20,   31,   22,   22,   11,  169,    0,   61,   61,   61,   61,   61,   61,
++     61,   66,   21,   82,   46,    0,    0,    0,    0,    2,    2,    2,    9,    2,   30,    2,
++      2,   52,   22,   22,   31,    0,   38,   22,   27,   11,  159,  180,  181,    0,    0,    0,
++      0,    2,    2,    2,   30,    9,    2,    2,    2,    2,    2,    2,    2,    2,   23,   23,
++     47,   22,   35,   82,   68,    0,    0,    0,    0,    2,  182,   66,   47,    0,    0,    0,
++      0,   11,  183,    2,    2,    2,    2,    2,    2,    2,    2,   23,   22,   20,   31,    0,
++     48,   16,  143,    0,    0,    0,    0,    0,    0,    2,    2,    2,    2,    2,  156,    0,
++      0,  184,  184,  184,  184,  184,  184,  184,  184,  185,  185,  185,  186,  187,  185,  184,
++    184,  188,  184,  184,  189,  190,  190,  190,  190,  190,  190,  190,    0,    0,    0,    0,
++      0,  184,  184,  184,  184,  184,  191,    0,    0,    2,    2,    2,    2,    2,    2,    2,
++     22,   22,   22,   22,   22,   22,  192,  193,  194,   11,   11,   11,   46,    0,    0,    0,
++      0,   29,   74,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,   65,   47,
++      0,    2,    2,    2,    2,    2,    9,    0,   58,  195,   20,   20,   20,   20,   20,   20,
++     20,   20,   20,   20,   20,   20,   20,   20,   20,   20,   20,   20,   20,    0,    0,    0,
++     40,  116,   26,    0,    0,    0,    0,    0,    0,    0,    0,    9,    0,    0,    0,    0,
++      0,    0,    0,    0,    0,    0,    0,    0,   30,    2,    2,    2,    2,    2,    0,   58,
++     37,    0,    6,  120,  120,  120,  121,    0,    0,   11,   11,   11,   49,    2,    2,    2,
++      0,    2,    2,    2,    2,    2,    0,    0,    2,    2,    2,    2,    2,    2,    2,    2,
++     46,    2,    2,    2,    2,    2,    2,   11,   11,    2,    2,    2,    2,    2,    2,   22,
++     22,    2,    2,    2,    2,    2,    2,    2,   20,    2,    2,   44,   44,   44,   92,    0,
+       0,    O,    O,    O,   GB,    B,    B,    O,   SB,    O,   SE,   GB,    O,    O,   WJ,FMPst,
+   FMPst,    O,  CGJ,    B,    O,    B,VMAbv,VMAbv,VMAbv,    O,VMAbv,    B,CMBlw,CMBlw,CMBlw,VMAbv,
+   VMPst, VAbv, VPst,CMBlw,    B, VPst, VPre, VPst, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, VAbv, VPst,
+@@ -582,20 +608,21 @@ hb_use_u8[3483] =
+   VMPst, VBlw, VPst,  CGJ,  CGJ, VPst,VMAbv,VMAbv,FMAbv, FAbv,CMAbv,FMAbv,VMAbv,FMAbv, VAbv,   IS,
+   FMAbv,    B,FMAbv,    B,  CGJ,   WJ,  CGJ,   GB,CMAbv,CMAbv,    B,   GB,    B, VAbv,  SUB, FPst,
+    FPst,VMBlw, FPst, FPst, FBlw,VMAbv,FMBlw, VAbv, VPre,    B, MPre, MBlw,  SUB, FAbv, FAbv, MAbv,
+-    SUB,   Sk, VPst, VAbv,VMAbv,VMAbv, FAbv,CMAbv, VPst,    H,    B,    O,SMAbv,SMBlw,SMAbv,SMAbv,
+-  SMAbv, VPst,   IS, VBlw, FAbv,VMPre,VMPre,FMAbv,CMBlw,VMBlw,VMBlw,VMAbv,   CS,    O,FMAbv, ZWNJ,
++    SUB,   Sk, VPst, VAbv,VMAbv,VMAbv, FAbv,CMAbv, VPst,    H,    B,    O,SMAbv,SMAbv,SMAbv, VPst,
++     IS,   RK,   RK, VBlw, FAbv,VMPre,VMPre,FMAbv,CMBlw,VMBlw,VMBlw,VMAbv,   CS,    O,FMAbv, ZWNJ,
+     CGJ,   WJ,   WJ,   WJ,    O,FMPst,    O,   SB,   SE,    O,    H, MPst, VPst,    H,VMAbv, VAbv,
+   VMBlw,    B, VBlw, FPst, VPst, FAbv,VMPst,    B,CMAbv, VAbv, MBlw, MPst, MBlw,    H,    O, VBlw,
+    MPst, MPre, MAbv, MBlw,    O,    B, FAbv, FAbv, FPst, VBlw,    B,    B, VPre,    O,VMPst,   IS,
+       O,VMPst, VBlw, VPst,VMBlw,VMBlw,VMAbv,    O,   IS,VMBlw,    B,VMPst,VMAbv,VMPst,   CS,   CS,
+       B,    N,    N,    O,   HN, VPre, VBlw, VAbv,   IS,CMAbv,    O, VPst,    B,    R,    R,CMBlw,
+-   VAbv, VPre,VMAbv,VMAbv,    H, VAbv,CMBlw,FMAbv,    B,   CS,   CS,    H,CMBlw,VMPst,    H,VMPst,
+-   VAbv,VMAbv, VPst,   IS,    R, MPst,    R, MPst,CMBlw,    B,FMBlw, VBlw,VMAbv,    R, MBlw, MBlw,
+-     GB, FBlw, FBlw,CMAbv,   IS, VBlw,   IS,   GB, VAbv,    R,VMPst,    G,    G,    J,    J,    J,
+-     SB,   SE,    J,   HR,    G,    G,   HM,   HM,   HM,    O, VBlw,
++   VAbv, VPre,VMAbv,VMAbv,    H, VAbv,CMBlw,VMPst,    O,VMAbv,CMBlw,   IS,    R,FMAbv,    B,   CS,
++     CS,    H,CMBlw,VMPst,    H,VMPst, VAbv,VMAbv, VPst, MPst,    R, MPst,CMBlw,    B,FMBlw, VBlw,
++  VMAbv,   CS,  SUB,  SUB,   GB, FBlw, FBlw,CMAbv,   IS, VBlw,   IS,    R, MBlw,   GB, VAbv,    R,
++  VMPst,    G,    G,    J,    J,    J,   SB,   SE,    J,   HR,    G,    G,   HM,   HM,   HM,    G,
++      O, MPre, MPre, MPst,VMAbv, MBlw, VBlw,    O, VBlw,
+ };
+ static const uint16_t
+-hb_use_u16[456] =
++hb_use_u16[486] =
+ {
+     0,  0,  1,  2,  0,  3,  4,  5,  0,  6,  7,  0,  8,  0,  9, 10,
+    11, 12, 10, 13, 14, 10, 10, 15, 16, 17, 18, 19, 20, 21, 22, 23,
+@@ -614,18 +641,20 @@ hb_use_u16[456] =
+   148,149,150, 10, 10,151,152,  2,153, 99,154,155,156,  2, 10,157,
+    10,158,159,  0,160,161,162,  2,163,  0,  0,164,  0,165,  0,166,
+   166,167, 34,168,169,170, 10,171, 95,  0,172,  0, 10,173,174,  0,
+-  175,  2,176,173,177,178,179,  0,  0,180,181,  0,182, 10, 10,183,
+-  184,185,186,187,188, 10, 10,189,190,  0,191, 10,192,193,194, 10,
+-   10,195, 10,196,197,106,198,103, 10, 34,199,200,201,  0,202,203,
+-   95, 10, 10,204,205,  2,206, 21, 22,207,208,209,210,211, 10,212,
+-  213,214,215,  0,198, 10, 10,216,217,  2,218,219,220,221, 10,222,
+-  223,  2,224,225, 10,226,227,104,228,  0,229,230,231,232, 10,233,
+-  234,  2,235, 10, 10,236,237,  0,238, 10, 10,239,240,241,242,243,
+-   22, 10,218,244,  8, 10, 71, 19, 10,245, 74,246,247, 10, 10,248,
+-  249,  2,250, 10,251,252, 10,253,254, 49, 10,255,256,  2,257,257,
+-  257,258,259,260, 10,261,262,263,264,264,265,266,267,  0, 10,268,
+-  106, 71, 95,269,  0,270, 71,271,272,  0,273,  0,274,  2,275,  2,
+-  276,  2,130,130,163,163,163,130,
++  175,  2,176, 10,177,  0,178,173,179,180,181,  0,  0,182,183,  0,
++  184, 10, 10,185,186,187,188,189,190, 10, 10,191,192,  0,193, 10,
++  194,195,196, 10, 10,197, 10,198,199,106,200,103, 10, 34,201,202,
++  203,  0,204,205, 95, 10, 10,206,207,  2,208, 21, 22,209,210,211,
++  212,213,214, 10, 10,215,216,217,218,  0, 10,219,220,221,222,  0,
++  200, 10, 10,223,224,  2,225,226,227,228, 10,229,230,  2,231,232,
++    2, 10,141,  0, 10,233,234,104,235,  0,236,237,238,239, 10,240,
++  241,  2,242, 10, 10,243,244,  0,245, 10, 10,246,247,248,249,250,
++   22, 10,225,251,  8, 10, 71, 19, 10,252, 74,253,254, 10, 10,255,
++  256,  2,257, 10,258,259, 10,260,261, 49, 10,262,263,264,265,265,
++  265,266,267,268,265,269, 10,270,271,  2, 10,272,273, 10,274,  2,
++  275,276,277,277,278,279,280,  0, 10,177,  0,281,106, 71, 95,282,
++    0,283, 71,284,285,  0,286,  0,287,  2,288,  2,289,106,290,  2,
++  130,130,163,163,163,130,
+ };
+ 
+ static inline unsigned
+@@ -636,7 +665,7 @@ hb_use_b4 (const uint8_t* a, unsigned i)
+ static inline uint_fast8_t
+ hb_use_get_category (unsigned u)
+ {
+-  return u<921600u?hb_use_u8[3105+(((hb_use_u8[889+(((hb_use_u16[((hb_use_u8[353+(((hb_use_u8[113+(((hb_use_b4(hb_use_u8,u>>1>>3>>1>>3>>4))<<4)+((u>>1>>3>>1>>3)&15u))])<<3)+((u>>1>>3>>1)&7u))])<<1)+((u>>1>>3)&1u)])<<3)+((u>>1)&7u))])<<1)+((u)&1u))]:O;
++  return u<921600u?hb_use_u8[3265+(((hb_use_u8[937+(((hb_use_u16[((hb_use_u8[369+(((hb_use_u8[113+(((hb_use_b4(hb_use_u8,u>>1>>3>>1>>3>>4))<<4)+((u>>1>>3>>1>>3)&15u))])<<3)+((u>>1>>3>>1)&7u))])<<1)+((u>>1>>3)&1u)])<<3)+((u>>1)&7u))])<<1)+((u)&1u))]:O;
+ }
+ 
+ #endif
+@@ -656,6 +685,7 @@ hb_use_get_category (unsigned u)
+ #undef N
+ #undef O
+ #undef R
++#undef RK
+ #undef SB
+ #undef SE
+ #undef SUB
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-vowel-constraints.cc b/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-vowel-constraints.cc
+index 35693254e..4a112e1c2 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-vowel-constraints.cc
++++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper-vowel-constraints.cc
+@@ -10,8 +10,8 @@
+  * # Date: 2015-03-12, 21:17:00 GMT [AG]
+  * # Date: 2019-11-08, 23:22:00 GMT [AG]
+  *
+- * # Scripts-15.1.0.txt
+- * # Date: 2023-07-28, 16:01:07 GMT
++ * # Scripts-16.0.0.txt
++ * # Date: 2024-04-30, 21:48:40 GMT
+  */
+ 
+ #include "hb.hh"
+@@ -24,7 +24,7 @@ static void
+ _output_dotted_circle (hb_buffer_t *buffer)
+ {
+   (void) buffer->output_glyph (0x25CCu);
+-  _hb_glyph_info_reset_continuation (&buffer->prev());
++  _hb_glyph_info_clear_continuation (&buffer->prev());
+ }
+ 
+ static void
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper.hh b/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper.hh
+index 39a04ec23..48cd5296f 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-shaper.hh
+@@ -174,9 +174,11 @@ HB_OT_SHAPERS_IMPLEMENT_SHAPERS
+ 
+ 
+ static inline const hb_ot_shaper_t *
+-hb_ot_shaper_categorize (const hb_ot_shape_planner_t *planner)
++hb_ot_shaper_categorize (hb_script_t script,
++                         hb_direction_t direction,
++                         hb_tag_t gsub_script)
+ {
+-  switch ((hb_tag_t) planner->props.script)
++  switch ((hb_tag_t) script)
+   {
+     default:
+       return &_hb_ot_shaper_default;
+@@ -192,9 +194,8 @@ hb_ot_shaper_categorize (const hb_ot_shape_planner_t *planner)
+        * This is because we do fallback shaping for Arabic script (and not others).
+        * But note that Arabic shaping is applicable only to horizontal layout; for
+        * vertical text, just use the generic shaper instead. */
+-      if ((planner->map.chosen_script[0] != HB_OT_TAG_DEFAULT_SCRIPT ||
+-           planner->props.script == HB_SCRIPT_ARABIC) &&
+-          HB_DIRECTION_IS_HORIZONTAL(planner->props.direction))
++      if ((gsub_script != HB_OT_TAG_DEFAULT_SCRIPT || script == HB_SCRIPT_ARABIC) &&
++          HB_DIRECTION_IS_HORIZONTAL (direction))
+         return &_hb_ot_shaper_arabic;
+       else
+         return &_hb_ot_shaper_default;
+@@ -235,10 +236,10 @@ hb_ot_shaper_categorize (const hb_ot_shape_planner_t *planner)
+        * Otherwise, use the specific shaper.
+        *
+        * If it's indy3 tag, send to USE. */
+-      if (planner->map.chosen_script[0] == HB_TAG ('D','F','L','T') ||
+-          planner->map.chosen_script[0] == HB_TAG ('l','a','t','n'))
++      if (gsub_script == HB_TAG ('D','F','L','T') ||
++          gsub_script == HB_TAG ('l','a','t','n'))
+         return &_hb_ot_shaper_default;
+-      else if ((planner->map.chosen_script[0] & 0x000000FF) == '3')
++      else if ((gsub_script & 0x000000FF) == '3')
+         return &_hb_ot_shaper_use;
+       else
+         return &_hb_ot_shaper_indic;
+@@ -254,9 +255,9 @@ hb_ot_shaper_categorize (const hb_ot_shape_planner_t *planner)
+        * If designer designed for 'mymr' tag, also send to default
+        * shaper.  That's tag used from before Myanmar shaping spec
+        * was developed.  The shaping spec uses 'mym2' tag. */
+-      if (planner->map.chosen_script[0] == HB_TAG ('D','F','L','T') ||
+-          planner->map.chosen_script[0] == HB_TAG ('l','a','t','n') ||
+-          planner->map.chosen_script[0] == HB_TAG ('m','y','m','r'))
++      if (gsub_script == HB_TAG ('D','F','L','T') ||
++          gsub_script == HB_TAG ('l','a','t','n') ||
++          gsub_script == HB_TAG ('m','y','m','r'))
+         return &_hb_ot_shaper_default;
+       else
+         return &_hb_ot_shaper_myanmar;
+@@ -386,13 +387,22 @@ hb_ot_shaper_categorize (const hb_ot_shape_planner_t *planner)
+     case HB_SCRIPT_KAWI:
+     case HB_SCRIPT_NAG_MUNDARI:
+ 
++    /* Unicode-16.0 additions */
++    case HB_SCRIPT_GARAY:
++    case HB_SCRIPT_GURUNG_KHEMA:
++    case HB_SCRIPT_KIRAT_RAI:
++    case HB_SCRIPT_OL_ONAL:
++    case HB_SCRIPT_SUNUWAR:
++    case HB_SCRIPT_TODHRI:
++    case HB_SCRIPT_TULU_TIGALARI:
++
+       /* If the designer designed the font for the 'DFLT' script,
+        * (or we ended up arbitrarily pick 'latn'), use the default shaper.
+        * Otherwise, use the specific shaper.
+        * Note that for some simple scripts, there may not be *any*
+        * GSUB/GPOS needed, so there may be no scripts found! */
+-      if (planner->map.chosen_script[0] == HB_TAG ('D','F','L','T') ||
+-          planner->map.chosen_script[0] == HB_TAG ('l','a','t','n'))
++      if (gsub_script == HB_TAG ('D','F','L','T') ||
++          gsub_script == HB_TAG ('l','a','t','n'))
+         return &_hb_ot_shaper_default;
+       else
+         return &_hb_ot_shaper_use;
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-stat-table.hh b/src/java.desktop/share/native/libharfbuzz/hb-ot-stat-table.hh
+index 7f6b52d79..10165f57b 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-stat-table.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-stat-table.hh
+@@ -63,8 +63,9 @@ static bool axis_value_is_outside_axis_range (hb_tag_t axis_tag, float axis_valu
+   if (!user_axes_location->has (axis_tag))
+     return false;
+ 
++  double axis_value_double = static_cast(axis_value);
+   Triple axis_range = user_axes_location->get (axis_tag);
+-  return (axis_value < axis_range.minimum || axis_value > axis_range.maximum);
++  return (axis_value_double < axis_range.minimum || axis_value_double > axis_range.maximum);
+ }
+ 
+ struct StatAxisRecord
+@@ -327,6 +328,7 @@ struct AxisValueFormat4
+   {
+     TRACE_SANITIZE (this);
+     return_trace (likely (c->check_struct (this) &&
++                          hb_barrier () &&
+                           axisValues.sanitize (c, axisCount)));
+   }
+ 
+@@ -348,15 +350,15 @@ struct AxisValueFormat4
+ 
+ struct AxisValue
+ {
+-  bool get_value (unsigned int axis_index) const
++  float get_value (unsigned int axis_index) const
+   {
+     switch (u.format)
+     {
+-    case 1: return u.format1.get_value ();
+-    case 2: return u.format2.get_value ();
+-    case 3: return u.format3.get_value ();
+-    case 4: return u.format4.get_axis_record (axis_index).get_value ();
+-    default:return 0;
++    case 1: hb_barrier (); return u.format1.get_value ();
++    case 2: hb_barrier (); return u.format2.get_value ();
++    case 3: hb_barrier (); return u.format3.get_value ();
++    case 4: hb_barrier (); return u.format4.get_axis_record (axis_index).get_value ();
++    default:return 0.f;
+     }
+   }
+ 
+@@ -364,9 +366,9 @@ struct AxisValue
+   {
+     switch (u.format)
+     {
+-    case 1: return u.format1.get_axis_index ();
+-    case 2: return u.format2.get_axis_index ();
+-    case 3: return u.format3.get_axis_index ();
++    case 1: hb_barrier (); return u.format1.get_axis_index ();
++    case 2: hb_barrier (); return u.format2.get_axis_index ();
++    case 3: hb_barrier (); return u.format3.get_axis_index ();
+     /* case 4: Makes more sense for variable fonts which are handled by fvar in hb-style */
+     default:return -1;
+     }
+@@ -376,10 +378,10 @@ struct AxisValue
+   {
+     switch (u.format)
+     {
+-    case 1: return u.format1.get_value_name_id ();
+-    case 2: return u.format2.get_value_name_id ();
+-    case 3: return u.format3.get_value_name_id ();
+-    case 4: return u.format4.get_value_name_id ();
++    case 1: hb_barrier (); return u.format1.get_value_name_id ();
++    case 2: hb_barrier (); return u.format2.get_value_name_id ();
++    case 3: hb_barrier (); return u.format3.get_value_name_id ();
++    case 4: hb_barrier (); return u.format4.get_value_name_id ();
+     default:return HB_OT_NAME_ID_INVALID;
+     }
+   }
+@@ -390,10 +392,10 @@ struct AxisValue
+     if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
+     TRACE_DISPATCH (this, u.format);
+     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)...));
+-    case 3: return_trace (c->dispatch (u.format3, std::forward (ds)...));
+-    case 4: return_trace (c->dispatch (u.format4, std::forward (ds)...));
++    case 1: hb_barrier (); return_trace (c->dispatch (u.format1, std::forward (ds)...));
++    case 2: hb_barrier (); return_trace (c->dispatch (u.format2, std::forward (ds)...));
++    case 3: hb_barrier (); return_trace (c->dispatch (u.format3, std::forward (ds)...));
++    case 4: hb_barrier (); return_trace (c->dispatch (u.format4, std::forward (ds)...));
+     default:return_trace (c->default_return_value ());
+     }
+   }
+@@ -403,10 +405,10 @@ struct AxisValue
+   {
+     switch (u.format)
+     {
+-    case 1: return u.format1.keep_axis_value (axis_records, user_axes_location);
+-    case 2: return u.format2.keep_axis_value (axis_records, user_axes_location);
+-    case 3: return u.format3.keep_axis_value (axis_records, user_axes_location);
+-    case 4: return u.format4.keep_axis_value (axis_records, user_axes_location);
++    case 1: hb_barrier (); return u.format1.keep_axis_value (axis_records, user_axes_location);
++    case 2: hb_barrier (); return u.format2.keep_axis_value (axis_records, user_axes_location);
++    case 3: hb_barrier (); return u.format3.keep_axis_value (axis_records, user_axes_location);
++    case 4: hb_barrier (); return u.format4.keep_axis_value (axis_records, user_axes_location);
+     default:return false;
+     }
+   }
+@@ -416,13 +418,14 @@ struct AxisValue
+     TRACE_SANITIZE (this);
+     if (unlikely (!c->check_struct (this)))
+       return_trace (false);
++    hb_barrier ();
+ 
+     switch (u.format)
+     {
+-    case 1: return_trace (u.format1.sanitize (c));
+-    case 2: return_trace (u.format2.sanitize (c));
+-    case 3: return_trace (u.format3.sanitize (c));
+-    case 4: return_trace (u.format4.sanitize (c));
++    case 1: hb_barrier (); return_trace (u.format1.sanitize (c));
++    case 2: hb_barrier (); return_trace (u.format2.sanitize (c));
++    case 3: hb_barrier (); return_trace (u.format3.sanitize (c));
++    case 4: hb_barrier (); return_trace (u.format4.sanitize (c));
+     default:return_trace (true);
+     }
+   }
+@@ -483,7 +486,7 @@ struct STAT
+     hb_array_t> axis_values = get_axis_value_offsets ();
+     for (unsigned int i = 0; i < axis_values.length; i++)
+     {
+-      const AxisValue& axis_value = this+axis_values[i];
++      const AxisValue& axis_value = this+offsetToAxisValueOffsets+axis_values[i];
+       if (axis_value.get_axis_index () == axis_index)
+       {
+         if (value)
+@@ -560,6 +563,7 @@ struct STAT
+   {
+     TRACE_SANITIZE (this);
+     return_trace (likely (c->check_struct (this) &&
++                          hb_barrier () &&
+                           version.major == 1 &&
+                           version.minor > 0 &&
+                           designAxesOffset.sanitize (c, this, designAxisCount) &&
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-tag-table.hh b/src/java.desktop/share/native/libharfbuzz/hb-ot-tag-table.hh
+index 8ee42e638..50ddf5f69 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-tag-table.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-tag-table.hh
+@@ -6,8 +6,8 @@
+  *
+  * on files with these headers:
+  *
+- * 
+- * File-Date: 2023-08-02
++ * 
++ * File-Date: 2025-01-21
+  */
+ 
+ #ifndef HB_OT_TAG_TABLE_HH
+@@ -26,12 +26,12 @@ static const LangTag ot_languages2[] = {
+   {HB_TAG('a','y',' ',' '),     HB_TAG('A','Y','M',' ')},       /* Aymara [macrolanguage] */
+   {HB_TAG('a','z',' ',' '),     HB_TAG('A','Z','E',' ')},       /* Azerbaijani [macrolanguage] */
+   {HB_TAG('b','a',' ',' '),     HB_TAG('B','S','H',' ')},       /* Bashkir */
+-  {HB_TAG('b','e',' ',' '),     HB_TAG('B','E','L',' ')},       /* Belarusian -> Belarussian */
++  {HB_TAG('b','e',' ',' '),     HB_TAG('B','E','L',' ')},       /* Belarusian */
+   {HB_TAG('b','g',' ',' '),     HB_TAG('B','G','R',' ')},       /* Bulgarian */
+   {HB_TAG('b','i',' ',' '),     HB_TAG('B','I','S',' ')},       /* Bislama */
+   {HB_TAG('b','i',' ',' '),     HB_TAG('C','P','P',' ')},       /* Bislama -> Creoles */
+   {HB_TAG('b','m',' ',' '),     HB_TAG('B','M','B',' ')},       /* Bambara (Bamanankan) */
+-  {HB_TAG('b','n',' ',' '),     HB_TAG('B','E','N',' ')},       /* Bengali */
++  {HB_TAG('b','n',' ',' '),     HB_TAG('B','E','N',' ')},       /* Bangla */
+   {HB_TAG('b','o',' ',' '),     HB_TAG('T','I','B',' ')},       /* Tibetan */
+   {HB_TAG('b','r',' ',' '),     HB_TAG('B','R','E',' ')},       /* Breton */
+   {HB_TAG('b','s',' ',' '),     HB_TAG('B','O','S',' ')},       /* Bosnian */
+@@ -64,7 +64,8 @@ static const LangTag ot_languages2[] = {
+   {HB_TAG('f','r',' ',' '),     HB_TAG('F','R','A',' ')},       /* French */
+   {HB_TAG('f','y',' ',' '),     HB_TAG('F','R','I',' ')},       /* Western Frisian -> Frisian */
+   {HB_TAG('g','a',' ',' '),     HB_TAG('I','R','I',' ')},       /* Irish */
+-  {HB_TAG('g','d',' ',' '),     HB_TAG('G','A','E',' ')},       /* Scottish Gaelic (Gaelic) */
++  {HB_TAG('g','a',' ',' '),     HB_TAG('I','R','T',' ')},       /* Irish -> Irish Traditional */
++  {HB_TAG('g','d',' ',' '),     HB_TAG('G','A','E',' ')},       /* Scottish Gaelic */
+   {HB_TAG('g','l',' ',' '),     HB_TAG('G','A','L',' ')},       /* Galician */
+   {HB_TAG('g','n',' ',' '),     HB_TAG('G','U','A',' ')},       /* Guarani [macrolanguage] */
+   {HB_TAG('g','u',' ',' '),     HB_TAG('G','U','J',' ')},       /* Gujarati */
+@@ -153,7 +154,7 @@ static const LangTag ot_languages2[] = {
+   {HB_TAG('o','c',' ',' '),     HB_TAG('O','C','I',' ')},       /* Occitan (post 1500) */
+   {HB_TAG('o','j',' ',' '),     HB_TAG('O','J','B',' ')},       /* Ojibwa [macrolanguage] -> Ojibway */
+   {HB_TAG('o','m',' ',' '),     HB_TAG('O','R','O',' ')},       /* Oromo [macrolanguage] */
+-  {HB_TAG('o','r',' ',' '),     HB_TAG('O','R','I',' ')},       /* Odia (formerly Oriya) [macrolanguage] */
++  {HB_TAG('o','r',' ',' '),     HB_TAG('O','R','I',' ')},       /* Odia [macrolanguage] */
+   {HB_TAG('o','s',' ',' '),     HB_TAG('O','S','S',' ')},       /* Ossetian */
+   {HB_TAG('p','a',' ',' '),     HB_TAG('P','A','N',' ')},       /* Punjabi */
+   {HB_TAG('p','i',' ',' '),     HB_TAG('P','A','L',' ')},       /* Pali */
+@@ -166,7 +167,7 @@ static const LangTag ot_languages2[] = {
+   {HB_TAG('r','o',' ',' '),     HB_TAG('R','O','M',' ')},       /* Romanian */
+   {HB_TAG('r','u',' ',' '),     HB_TAG('R','U','S',' ')},       /* Russian */
+   {HB_TAG('r','w',' ',' '),     HB_TAG('R','U','A',' ')},       /* Kinyarwanda */
+-  {HB_TAG('s','a',' ',' '),     HB_TAG('S','A','N',' ')},       /* Sanskrit */
++  {HB_TAG('s','a',' ',' '),     HB_TAG('S','A','N',' ')},       /* Sanskrit [macrolanguage] */
+   {HB_TAG('s','c',' ',' '),     HB_TAG('S','R','D',' ')},       /* Sardinian [macrolanguage] */
+   {HB_TAG('s','d',' ',' '),     HB_TAG('S','N','D',' ')},       /* Sindhi */
+   {HB_TAG('s','e',' ',' '),     HB_TAG('N','S','M',' ')},       /* Northern Sami */
+@@ -223,6 +224,7 @@ static const LangTag ot_languages2[] = {
+ static const LangTag ot_languages3[] = {
+   {HB_TAG('a','a','e',' '),     HB_TAG('S','Q','I',' ')},       /* Arbëreshë Albanian -> Albanian */
+   {HB_TAG('a','a','o',' '),     HB_TAG('A','R','A',' ')},       /* Algerian Saharan Arabic -> Arabic */
++/*{HB_TAG('a','a','q',' '),     HB_TAG('A','A','Q',' ')},*/     /* Eastern Abnaki -> Eastern Abenaki */
+   {HB_TAG('a','a','t',' '),     HB_TAG('S','Q','I',' ')},       /* Arvanitika Albanian -> Albanian */
+   {HB_TAG('a','b','a',' '),     HB_TAG_NONE            },       /* Abé != Abaza */
+   {HB_TAG('a','b','h',' '),     HB_TAG('A','R','A',' ')},       /* Tajiki Arabic -> Arabic */
+@@ -238,6 +240,7 @@ static const LangTag ot_languages3[] = {
+   {HB_TAG('a','c','r',' '),     HB_TAG('M','Y','N',' ')},       /* Achi -> Mayan */
+   {HB_TAG('a','c','w',' '),     HB_TAG('A','R','A',' ')},       /* Hijazi Arabic -> Arabic */
+   {HB_TAG('a','c','x',' '),     HB_TAG('A','R','A',' ')},       /* Omani Arabic -> Arabic */
++  {HB_TAG('a','c','y',' '),     HB_TAG('A','C','Y',' ')},       /* Cypriot Arabic */
+   {HB_TAG('a','c','y',' '),     HB_TAG('A','R','A',' ')},       /* Cypriot Arabic -> Arabic */
+   {HB_TAG('a','d','a',' '),     HB_TAG('D','N','G',' ')},       /* Adangme -> Dangme */
+   {HB_TAG('a','d','f',' '),     HB_TAG('A','R','A',' ')},       /* Dhofari Arabic -> Arabic */
+@@ -288,6 +291,7 @@ static const LangTag ot_languages3[] = {
+ /*{HB_TAG('a','s','t',' '),     HB_TAG('A','S','T',' ')},*/     /* Asturian */
+ /*{HB_TAG('a','t','h',' '),     HB_TAG('A','T','H',' ')},*/     /* Athapascan [collection] -> Athapaskan */
+   {HB_TAG('a','t','j',' '),     HB_TAG('R','C','R',' ')},       /* Atikamekw -> R-Cree */
++/*{HB_TAG('a','t','s',' '),     HB_TAG('A','T','S',' ')},*/     /* Gros Ventre (Atsina) */
+   {HB_TAG('a','t','v',' '),     HB_TAG('A','L','T',' ')},       /* Northern Altai -> Altai */
+   {HB_TAG('a','u','j',' '),     HB_TAG('B','B','R',' ')},       /* Awjilah -> Berber */
+   {HB_TAG('a','u','z',' '),     HB_TAG('A','R','A',' ')},       /* Uzbeki Arabic -> Arabic */
+@@ -326,6 +330,7 @@ static const LangTag ot_languages3[] = {
+   {HB_TAG('b','c','l',' '),     HB_TAG('B','I','K',' ')},       /* Central Bikol -> Bikol */
+   {HB_TAG('b','c','q',' '),     HB_TAG('B','C','H',' ')},       /* Bench */
+   {HB_TAG('b','c','r',' '),     HB_TAG('A','T','H',' ')},       /* Babine -> Athapaskan */
++/*{HB_TAG('b','d','c',' '),     HB_TAG('B','D','C',' ')},*/     /* Emberá-Baudó */
+ /*{HB_TAG('b','d','y',' '),     HB_TAG('B','D','Y',' ')},*/     /* Bandjalang */
+   {HB_TAG('b','e','a',' '),     HB_TAG('A','T','H',' ')},       /* Beaver -> Athapaskan */
+   {HB_TAG('b','e','b',' '),     HB_TAG('B','T','I',' ')},       /* Bebele -> Beti */
+@@ -421,6 +426,8 @@ static const LangTag ot_languages3[] = {
+   {HB_TAG('c','a','f',' '),     HB_TAG('A','T','H',' ')},       /* Southern Carrier -> Athapaskan */
+   {HB_TAG('c','a','k',' '),     HB_TAG('C','A','K',' ')},       /* Kaqchikel */
+   {HB_TAG('c','a','k',' '),     HB_TAG('M','Y','N',' ')},       /* Kaqchikel -> Mayan */
++/*{HB_TAG('c','a','y',' '),     HB_TAG('C','A','Y',' ')},*/     /* Cayuga */
++/*{HB_TAG('c','b','g',' '),     HB_TAG('C','B','G',' ')},*/     /* Chimila */
+   {HB_TAG('c','b','k',' '),     HB_TAG('C','B','K',' ')},       /* Chavacano -> Zamboanga Chavacano */
+   {HB_TAG('c','b','k',' '),     HB_TAG('C','P','P',' ')},       /* Chavacano -> Creoles */
+   {HB_TAG('c','b','l',' '),     HB_TAG('Q','I','N',' ')},       /* Bualkhaw Chin -> Chin */
+@@ -465,7 +472,9 @@ static const LangTag ot_languages3[] = {
+   {HB_TAG('c','l','d',' '),     HB_TAG('S','Y','R',' ')},       /* Chaldean Neo-Aramaic -> Syriac */
+   {HB_TAG('c','l','e',' '),     HB_TAG('C','C','H','N')},       /* Lealao Chinantec -> Chinantec */
+   {HB_TAG('c','l','j',' '),     HB_TAG('Q','I','N',' ')},       /* Laitu Chin -> Chin */
++  {HB_TAG('c','l','s',' '),     HB_TAG('S','A','N',' ')},       /* Classical Sanskrit -> Sanskrit */
+   {HB_TAG('c','l','t',' '),     HB_TAG('Q','I','N',' ')},       /* Lautu Chin -> Chin */
++/*{HB_TAG('c','m','i',' '),     HB_TAG('C','M','I',' ')},*/     /* Emberá-Chamí */
+   {HB_TAG('c','m','n',' '),     HB_TAG('Z','H','S',' ')},       /* Mandarin Chinese -> Chinese, Simplified */
+   {HB_TAG('c','m','r',' '),     HB_TAG('Q','I','N',' ')},       /* Mro-Khimi Chin -> Chin */
+   {HB_TAG('c','n','b',' '),     HB_TAG('Q','I','N',' ')},       /* Chinbon Chin -> Chin */
+@@ -479,6 +488,7 @@ static const LangTag ot_languages3[] = {
+   {HB_TAG('c','n','w',' '),     HB_TAG('Q','I','N',' ')},       /* Ngawn Chin -> Chin */
+   {HB_TAG('c','o','a',' '),     HB_TAG('M','L','Y',' ')},       /* Cocos Islands Malay -> Malay */
+   {HB_TAG('c','o','b',' '),     HB_TAG('M','Y','N',' ')},       /* Chicomuceltec -> Mayan */
++/*{HB_TAG('c','o','o',' '),     HB_TAG('C','O','O',' ')},*/     /* Comox */
+ /*{HB_TAG('c','o','p',' '),     HB_TAG('C','O','P',' ')},*/     /* Coptic */
+   {HB_TAG('c','o','q',' '),     HB_TAG('A','T','H',' ')},       /* Coquille -> Athapaskan */
+   {HB_TAG('c','p','a',' '),     HB_TAG('C','C','H','N')},       /* Palantla Chinantec -> Chinantec */
+@@ -528,6 +538,7 @@ static const LangTag ot_languages3[] = {
+ /*{HB_TAG('c','t','g',' '),     HB_TAG('C','T','G',' ')},*/     /* Chittagonian */
+   {HB_TAG('c','t','h',' '),     HB_TAG('Q','I','N',' ')},       /* Thaiphum Chin -> Chin */
+   {HB_TAG('c','t','l',' '),     HB_TAG('C','C','H','N')},       /* Tlacoatzintepec Chinantec -> Chinantec */
++/*{HB_TAG('c','t','o',' '),     HB_TAG('C','T','O',' ')},*/     /* Emberá-Catío */
+   {HB_TAG('c','t','s',' '),     HB_TAG('B','I','K',' ')},       /* Northern Catanduanes Bikol -> Bikol */
+ /*{HB_TAG('c','t','t',' '),     HB_TAG('C','T','T',' ')},*/     /* Wayanad Chetti */
+   {HB_TAG('c','t','u',' '),     HB_TAG('M','Y','N',' ')},       /* Chol -> Mayan */
+@@ -551,7 +562,7 @@ static const LangTag ot_languages3[] = {
+   {HB_TAG('d','e','p',' '),     HB_TAG('C','P','P',' ')},       /* Pidgin Delaware -> Creoles */
+   {HB_TAG('d','g','o',' '),     HB_TAG('D','G','O',' ')},       /* Dogri (individual language) */
+   {HB_TAG('d','g','o',' '),     HB_TAG('D','G','R',' ')},       /* Dogri (macrolanguage) */
+-  {HB_TAG('d','g','r',' '),     HB_TAG('A','T','H',' ')},       /* Dogrib -> Athapaskan */
++  {HB_TAG('d','g','r',' '),     HB_TAG('A','T','H',' ')},       /* Tlicho -> Athapaskan */
+   {HB_TAG('d','h','d',' '),     HB_TAG('M','A','W',' ')},       /* Dhundari -> Marwari */
+ /*{HB_TAG('d','h','g',' '),     HB_TAG('D','H','G',' ')},*/     /* Dhangu */
+   {HB_TAG('d','h','v',' '),     HB_TAG_NONE            },       /* Dehu != Divehi (Dhivehi, Maldivian) (deprecated) */
+@@ -590,6 +601,7 @@ static const LangTag ot_languages3[] = {
+   {HB_TAG('e','k','y',' '),     HB_TAG('K','R','N',' ')},       /* Eastern Kayah -> Karen */
+   {HB_TAG('e','m','k',' '),     HB_TAG('E','M','K',' ')},       /* Eastern Maninkakan */
+   {HB_TAG('e','m','k',' '),     HB_TAG('M','N','K',' ')},       /* Eastern Maninkakan -> Maninka */
++/*{HB_TAG('e','m','p',' '),     HB_TAG('E','M','P',' ')},*/     /* Northern Emberá */
+   {HB_TAG('e','m','y',' '),     HB_TAG('M','Y','N',' ')},       /* Epigraphic Mayan -> Mayan */
+   {HB_TAG('e','n','b',' '),     HB_TAG('K','A','L',' ')},       /* Markweeta -> Kalenjin */
+   {HB_TAG('e','n','f',' '),     HB_TAG('F','N','E',' ')},       /* Forest Enets */
+@@ -637,7 +649,7 @@ static const LangTag ot_languages3[] = {
+   {HB_TAG('g','a','a',' '),     HB_TAG('G','A','D',' ')},       /* Ga */
+   {HB_TAG('g','a','c',' '),     HB_TAG('C','P','P',' ')},       /* Mixed Great Andamanese -> Creoles */
+   {HB_TAG('g','a','d',' '),     HB_TAG_NONE            },       /* Gaddang != Ga */
+-  {HB_TAG('g','a','e',' '),     HB_TAG_NONE            },       /* Guarequena != Scottish Gaelic (Gaelic) */
++  {HB_TAG('g','a','e',' '),     HB_TAG_NONE            },       /* Guarequena != Scottish Gaelic */
+ /*{HB_TAG('g','a','g',' '),     HB_TAG('G','A','G',' ')},*/     /* Gagauz */
+   {HB_TAG('g','a','l',' '),     HB_TAG_NONE            },       /* Galolen != Galician */
+   {HB_TAG('g','a','n',' '),     HB_TAG('Z','H','S',' ')},       /* Gan Chinese -> Chinese, Simplified */
+@@ -654,6 +666,7 @@ static const LangTag ot_languages3[] = {
+ /*{HB_TAG('g','e','z',' '),     HB_TAG('G','E','Z',' ')},*/     /* Geez */
+   {HB_TAG('g','g','o',' '),     HB_TAG('G','O','N',' ')},       /* Southern Gondi (retired code) -> Gondi */
+   {HB_TAG('g','h','a',' '),     HB_TAG('B','B','R',' ')},       /* Ghadamès -> Berber */
++  {HB_TAG('g','h','c',' '),     HB_TAG('I','R','T',' ')},       /* Hiberno-Scottish Gaelic -> Irish Traditional */
+   {HB_TAG('g','h','k',' '),     HB_TAG('K','R','N',' ')},       /* Geko Karen -> Karen */
+   {HB_TAG('g','h','o',' '),     HB_TAG('B','B','R',' ')},       /* Ghomara -> Berber */
+   {HB_TAG('g','i','b',' '),     HB_TAG('C','P','P',' ')},       /* Gibanawa -> Creoles */
+@@ -732,6 +745,7 @@ static const LangTag ot_languages3[] = {
+ /*{HB_TAG('h','n','d',' '),     HB_TAG('H','N','D',' ')},*/     /* Southern Hindko -> Hindko */
+   {HB_TAG('h','n','e',' '),     HB_TAG('C','H','H',' ')},       /* Chhattisgarhi -> Chattisgarhi */
+   {HB_TAG('h','n','j',' '),     HB_TAG('H','M','N',' ')},       /* Hmong Njua -> Hmong */
++  {HB_TAG('h','n','m',' '),     HB_TAG('Z','H','S',' ')},       /* Hainanese -> Chinese, Simplified */
+   {HB_TAG('h','n','o',' '),     HB_TAG('H','N','D',' ')},       /* Northern Hindko -> Hindko */
+   {HB_TAG('h','o','c',' '),     HB_TAG('H','O',' ',' ')},       /* Ho */
+   {HB_TAG('h','o','i',' '),     HB_TAG('A','T','H',' ')},       /* Holikachuk -> Athapaskan */
+@@ -743,6 +757,7 @@ static const LangTag ot_languages3[] = {
+   {HB_TAG('h','s','n',' '),     HB_TAG('Z','H','S',' ')},       /* Xiang Chinese -> Chinese, Simplified */
+   {HB_TAG('h','u','j',' '),     HB_TAG('H','M','N',' ')},       /* Northern Guiyang Hmong -> Hmong */
+   {HB_TAG('h','u','p',' '),     HB_TAG('A','T','H',' ')},       /* Hupa -> Athapaskan */
++/*{HB_TAG('h','u','r',' '),     HB_TAG('H','U','R',' ')},*/     /* Halkomelem */
+   {HB_TAG('h','u','s',' '),     HB_TAG('M','Y','N',' ')},       /* Huastec -> Mayan */
+   {HB_TAG('h','w','c',' '),     HB_TAG('C','P','P',' ')},       /* Hawai'i Creole English -> Creoles */
+   {HB_TAG('h','y','w',' '),     HB_TAG('H','Y','E',' ')},       /* Western Armenian -> Armenian */
+@@ -780,6 +795,7 @@ static const LangTag ot_languages3[] = {
+   {HB_TAG('j','b','n',' '),     HB_TAG('B','B','R',' ')},       /* Nafusi -> Berber */
+ /*{HB_TAG('j','b','o',' '),     HB_TAG('J','B','O',' ')},*/     /* Lojban */
+ /*{HB_TAG('j','c','t',' '),     HB_TAG('J','C','T',' ')},*/     /* Krymchak */
++/*{HB_TAG('j','d','t',' '),     HB_TAG('J','D','T',' ')},*/     /* Judeo-Tat */
+   {HB_TAG('j','g','o',' '),     HB_TAG('B','M','L',' ')},       /* Ngomba -> Bamileke */
+   {HB_TAG('j','i','i',' '),     HB_TAG_NONE            },       /* Jiiddu != Yiddish */
+   {HB_TAG('j','k','m',' '),     HB_TAG('K','R','N',' ')},       /* Mobwa Karen -> Karen */
+@@ -794,6 +810,7 @@ static const LangTag ot_languages3[] = {
+   {HB_TAG('k','a','m',' '),     HB_TAG('K','M','B',' ')},       /* Kamba (Kenya) */
+   {HB_TAG('k','a','r',' '),     HB_TAG('K','R','N',' ')},       /* Karen [collection] */
+ /*{HB_TAG('k','a','w',' '),     HB_TAG('K','A','W',' ')},*/     /* Kawi (Old Javanese) */
++/*{HB_TAG('k','b','c',' '),     HB_TAG('K','B','C',' ')},*/     /* Kadiwéu */
+   {HB_TAG('k','b','d',' '),     HB_TAG('K','A','B',' ')},       /* Kabardian */
+   {HB_TAG('k','b','y',' '),     HB_TAG('K','N','R',' ')},       /* Manga Kanuri -> Kanuri */
+   {HB_TAG('k','c','a',' '),     HB_TAG('K','H','K',' ')},       /* Khanty -> Khanty-Kazim */
+@@ -814,6 +831,7 @@ static const LangTag ot_languages3[] = {
+   {HB_TAG('k','f','x',' '),     HB_TAG('K','U','L',' ')},       /* Kullu Pahari -> Kulvi */
+   {HB_TAG('k','f','y',' '),     HB_TAG('K','M','N',' ')},       /* Kumaoni */
+   {HB_TAG('k','g','e',' '),     HB_TAG_NONE            },       /* Komering != Khutsuri Georgian */
++/*{HB_TAG('k','g','f',' '),     HB_TAG('K','G','F',' ')},*/     /* Kube */
+   {HB_TAG('k','h','a',' '),     HB_TAG('K','S','I',' ')},       /* Khasi */
+   {HB_TAG('k','h','b',' '),     HB_TAG('X','B','D',' ')},       /* Lü */
+   {HB_TAG('k','h','k',' '),     HB_TAG('M','N','G',' ')},       /* Halh Mongolian -> Mongolian */
+@@ -829,6 +847,7 @@ static const LangTag ot_languages3[] = {
+   {HB_TAG('k','j','b',' '),     HB_TAG('M','Y','N',' ')},       /* Q'anjob'al -> Mayan */
+ /*{HB_TAG('k','j','d',' '),     HB_TAG('K','J','D',' ')},*/     /* Southern Kiwai */
+   {HB_TAG('k','j','h',' '),     HB_TAG('K','H','A',' ')},       /* Khakas -> Khakass */
++/*{HB_TAG('k','j','j',' '),     HB_TAG('K','J','J',' ')},*/     /* Khinalugh -> Khinalug */
+   {HB_TAG('k','j','p',' '),     HB_TAG('K','J','P',' ')},       /* Pwo Eastern Karen -> Eastern Pwo Karen */
+   {HB_TAG('k','j','p',' '),     HB_TAG('K','R','N',' ')},       /* Pwo Eastern Karen -> Karen */
+   {HB_TAG('k','j','t',' '),     HB_TAG('K','R','N',' ')},       /* Phrae Pwo Karen -> Karen */
+@@ -838,6 +857,7 @@ static const LangTag ot_languages3[] = {
+   {HB_TAG('k','l','m',' '),     HB_TAG_NONE            },       /* Migum != Kalmyk */
+   {HB_TAG('k','l','n',' '),     HB_TAG('K','A','L',' ')},       /* Kalenjin [macrolanguage] */
+   {HB_TAG('k','m','b',' '),     HB_TAG('M','B','N',' ')},       /* Kimbundu -> Mbundu */
++/*{HB_TAG('k','m','g',' '),     HB_TAG('K','M','G',' ')},*/     /* Kâte */
+   {HB_TAG('k','m','n',' '),     HB_TAG_NONE            },       /* Awtuw != Kumaoni */
+   {HB_TAG('k','m','o',' '),     HB_TAG_NONE            },       /* Kwoma != Komo */
+   {HB_TAG('k','m','r',' '),     HB_TAG('K','U','R',' ')},       /* Northern Kurdish -> Kurdish */
+@@ -881,6 +901,7 @@ static const LangTag ot_languages3[] = {
+   {HB_TAG('k','s','i',' '),     HB_TAG_NONE            },       /* Krisa != Khasi */
+   {HB_TAG('k','s','m',' '),     HB_TAG_NONE            },       /* Kumba != Kildin Sami */
+   {HB_TAG('k','s','s',' '),     HB_TAG('K','I','S',' ')},       /* Southern Kisi -> Kisii */
++/*{HB_TAG('k','s','u',' '),     HB_TAG('K','S','U',' ')},*/     /* Khamyang */
+   {HB_TAG('k','s','w',' '),     HB_TAG('K','S','W',' ')},       /* S’gaw Karen */
+   {HB_TAG('k','s','w',' '),     HB_TAG('K','R','N',' ')},       /* S'gaw Karen -> Karen */
+   {HB_TAG('k','t','b',' '),     HB_TAG('K','E','B',' ')},       /* Kambaata -> Kebena */
+@@ -894,6 +915,7 @@ static const LangTag ot_languages3[] = {
+   {HB_TAG('k','u','y',' '),     HB_TAG_NONE            },       /* Kuuku-Ya'u != Kuy */
+   {HB_TAG('k','v','b',' '),     HB_TAG('M','L','Y',' ')},       /* Kubu -> Malay */
+   {HB_TAG('k','v','l',' '),     HB_TAG('K','R','N',' ')},       /* Kayaw -> Karen */
++  {HB_TAG('k','v','q',' '),     HB_TAG('K','V','Q',' ')},       /* Geba Karen */
+   {HB_TAG('k','v','q',' '),     HB_TAG('K','R','N',' ')},       /* Geba Karen -> Karen */
+   {HB_TAG('k','v','r',' '),     HB_TAG('M','L','Y',' ')},       /* Kerinci -> Malay */
+   {HB_TAG('k','v','t',' '),     HB_TAG('K','R','N',' ')},       /* Lahta Karen -> Karen */
+@@ -930,6 +952,7 @@ static const LangTag ot_languages3[] = {
+ /*{HB_TAG('l','i','j',' '),     HB_TAG('L','I','J',' ')},*/     /* Ligurian */
+   {HB_TAG('l','i','r',' '),     HB_TAG('C','P','P',' ')},       /* Liberian English -> Creoles */
+ /*{HB_TAG('l','i','s',' '),     HB_TAG('L','I','S',' ')},*/     /* Lisu */
++/*{HB_TAG('l','i','v',' '),     HB_TAG('L','I','V',' ')},*/     /* Liv */
+   {HB_TAG('l','i','w',' '),     HB_TAG('M','L','Y',' ')},       /* Col -> Malay */
+   {HB_TAG('l','i','y',' '),     HB_TAG('B','A','D','0')},       /* Banda-Bambari -> Banda */
+ /*{HB_TAG('l','j','p',' '),     HB_TAG('L','J','P',' ')},*/     /* Lampung Api -> Lampung */
+@@ -959,9 +982,11 @@ static const LangTag ot_languages3[] = {
+   {HB_TAG('l','t','o',' '),     HB_TAG('L','U','H',' ')},       /* Tsotso -> Luyia */
+   {HB_TAG('l','t','s',' '),     HB_TAG('L','U','H',' ')},       /* Tachoni -> Luyia */
+ /*{HB_TAG('l','u','a',' '),     HB_TAG('L','U','A',' ')},*/     /* Luba-Lulua */
++  {HB_TAG('l','u','h',' '),     HB_TAG('Z','H','S',' ')},       /* Leizhou Chinese -> Chinese, Simplified */
+ /*{HB_TAG('l','u','o',' '),     HB_TAG('L','U','O',' ')},*/     /* Luo (Kenya and Tanzania) */
+   {HB_TAG('l','u','s',' '),     HB_TAG('M','I','Z',' ')},       /* Lushai -> Mizo */
+   {HB_TAG('l','u','s',' '),     HB_TAG('Q','I','N',' ')},       /* Lushai -> Chin */
++/*{HB_TAG('l','u','t',' '),     HB_TAG('L','U','T',' ')},*/     /* Lushootseed */
+   {HB_TAG('l','u','y',' '),     HB_TAG('L','U','H',' ')},       /* Luyia [macrolanguage] */
+   {HB_TAG('l','u','z',' '),     HB_TAG('L','R','C',' ')},       /* Southern Luri -> Luri */
+   {HB_TAG('l','v','i',' '),     HB_TAG_NONE            },       /* Lavi != Latvian */
+@@ -995,12 +1020,14 @@ static const LangTag ot_languages3[] = {
+   {HB_TAG('m','e','n',' '),     HB_TAG('M','D','E',' ')},       /* Mende (Sierra Leone) */
+   {HB_TAG('m','e','o',' '),     HB_TAG('M','L','Y',' ')},       /* Kedah Malay -> Malay */
+ /*{HB_TAG('m','e','r',' '),     HB_TAG('M','E','R',' ')},*/     /* Meru */
++/*{HB_TAG('m','e','v',' '),     HB_TAG('M','E','V',' ')},*/     /* Mano */
+   {HB_TAG('m','f','a',' '),     HB_TAG('M','F','A',' ')},       /* Pattani Malay */
+   {HB_TAG('m','f','a',' '),     HB_TAG('M','L','Y',' ')},       /* Pattani Malay -> Malay */
+   {HB_TAG('m','f','b',' '),     HB_TAG('M','L','Y',' ')},       /* Bangka -> Malay */
+   {HB_TAG('m','f','e',' '),     HB_TAG('M','F','E',' ')},       /* Morisyen */
+   {HB_TAG('m','f','e',' '),     HB_TAG('C','P','P',' ')},       /* Morisyen -> Creoles */
+   {HB_TAG('m','f','p',' '),     HB_TAG('C','P','P',' ')},       /* Makassar Malay -> Creoles */
++  {HB_TAG('m','g','a',' '),     HB_TAG('S','G','A',' ')},       /* Middle Irish (900-1200) -> Old Irish */
+   {HB_TAG('m','h','c',' '),     HB_TAG('M','Y','N',' ')},       /* Mocho -> Mayan */
+   {HB_TAG('m','h','r',' '),     HB_TAG('L','M','A',' ')},       /* Eastern Mari -> Low Mari */
+   {HB_TAG('m','h','v',' '),     HB_TAG('A','R','K',' ')},       /* Arakanese (retired code) -> Rakhine */
+@@ -1126,6 +1153,7 @@ static const LangTag ot_languages3[] = {
+   {HB_TAG('n','o','d',' '),     HB_TAG('N','T','A',' ')},       /* Northern Thai -> Northern Tai */
+ /*{HB_TAG('n','o','e',' '),     HB_TAG('N','O','E',' ')},*/     /* Nimadi */
+ /*{HB_TAG('n','o','g',' '),     HB_TAG('N','O','G',' ')},*/     /* Nogai */
++/*{HB_TAG('n','o','p',' '),     HB_TAG('N','O','P',' ')},*/     /* Numanggang */
+ /*{HB_TAG('n','o','v',' '),     HB_TAG('N','O','V',' ')},*/     /* Novial */
+   {HB_TAG('n','p','i',' '),     HB_TAG('N','E','P',' ')},       /* Nepali */
+   {HB_TAG('n','p','l',' '),     HB_TAG('N','A','H',' ')},       /* Southeastern Puebla Nahuatl -> Nahuatl */
+@@ -1136,6 +1164,7 @@ static const LangTag ot_languages3[] = {
+   {HB_TAG('n','s','u',' '),     HB_TAG('N','A','H',' ')},       /* Sierra Negra Nahuatl -> Nahuatl */
+   {HB_TAG('n','t','o',' '),     HB_TAG_NONE            },       /* Ntomba != Esperanto */
+   {HB_TAG('n','u','e',' '),     HB_TAG('B','A','D','0')},       /* Ngundu -> Banda */
++/*{HB_TAG('n','u','k',' '),     HB_TAG('N','U','K',' ')},*/     /* Nuu-chah-nulth */
+   {HB_TAG('n','u','u',' '),     HB_TAG('B','A','D','0')},       /* Ngbundu -> Banda */
+   {HB_TAG('n','u','z',' '),     HB_TAG('N','A','H',' ')},       /* Tlamacazapa Nahuatl -> Nahuatl */
+   {HB_TAG('n','w','e',' '),     HB_TAG('B','M','L',' ')},       /* Ngwe -> Bamileke */
+@@ -1153,6 +1182,8 @@ static const LangTag ot_languages3[] = {
+   {HB_TAG('o','k','i',' '),     HB_TAG('K','A','L',' ')},       /* Okiek -> Kalenjin */
+   {HB_TAG('o','k','m',' '),     HB_TAG('K','O','H',' ')},       /* Middle Korean (10th-16th cent.) -> Korean Old Hangul */
+   {HB_TAG('o','k','r',' '),     HB_TAG('I','J','O',' ')},       /* Kirike -> Ijo */
++/*{HB_TAG('o','n','e',' '),     HB_TAG('O','N','E',' ')},*/     /* Oneida */
++/*{HB_TAG('o','n','o',' '),     HB_TAG('O','N','O',' ')},*/     /* Onondaga */
+   {HB_TAG('o','n','x',' '),     HB_TAG('C','P','P',' ')},       /* Onin Based Pidgin -> Creoles */
+   {HB_TAG('o','o','r',' '),     HB_TAG('C','P','P',' ')},       /* Oorlams -> Creoles */
+   {HB_TAG('o','r','c',' '),     HB_TAG('O','R','O',' ')},       /* Orma -> Oromo */
+@@ -1160,7 +1191,7 @@ static const LangTag ot_languages3[] = {
+   {HB_TAG('o','r','o',' '),     HB_TAG_NONE            },       /* Orokolo != Oromo */
+   {HB_TAG('o','r','r',' '),     HB_TAG('I','J','O',' ')},       /* Oruma -> Ijo */
+   {HB_TAG('o','r','s',' '),     HB_TAG('M','L','Y',' ')},       /* Orang Seletar -> Malay */
+-  {HB_TAG('o','r','y',' '),     HB_TAG('O','R','I',' ')},       /* Odia (formerly Oriya) */
++  {HB_TAG('o','r','y',' '),     HB_TAG('O','R','I',' ')},       /* Odia */
+   {HB_TAG('o','t','w',' '),     HB_TAG('O','J','B',' ')},       /* Ottawa -> Ojibway */
+   {HB_TAG('o','u','a',' '),     HB_TAG('B','B','R',' ')},       /* Tagargrent -> Berber */
+   {HB_TAG('p','a','a',' '),     HB_TAG_NONE            },       /* Papuan [collection] != Palestinian Aramaic */
+@@ -1193,7 +1224,7 @@ static const LangTag ot_languages3[] = {
+   {HB_TAG('p','i','s',' '),     HB_TAG('C','P','P',' ')},       /* Pijin -> Creoles */
+   {HB_TAG('p','k','h',' '),     HB_TAG('Q','I','N',' ')},       /* Pankhu -> Chin */
+   {HB_TAG('p','k','o',' '),     HB_TAG('K','A','L',' ')},       /* Pökoot -> Kalenjin */
+-  {HB_TAG('p','l','g',' '),     HB_TAG_NONE            },       /* Pilagá != Palaung */
++  {HB_TAG('p','l','g',' '),     HB_TAG('P','L','G','0')},       /* Pilagá */
+   {HB_TAG('p','l','k',' '),     HB_TAG_NONE            },       /* Kohistani Shina != Polish */
+   {HB_TAG('p','l','l',' '),     HB_TAG('P','L','G',' ')},       /* Shwe Palaung -> Palaung */
+   {HB_TAG('p','l','n',' '),     HB_TAG('C','P','P',' ')},       /* Palenquero -> Creoles */
+@@ -1353,6 +1384,7 @@ static const LangTag ot_languages3[] = {
+   {HB_TAG('s','d','h',' '),     HB_TAG('K','U','R',' ')},       /* Southern Kurdish -> Kurdish */
+   {HB_TAG('s','d','n',' '),     HB_TAG('S','R','D',' ')},       /* Gallurese Sardinian -> Sardinian */
+   {HB_TAG('s','d','s',' '),     HB_TAG('B','B','R',' ')},       /* Sened -> Berber */
++/*{HB_TAG('s','e','e',' '),     HB_TAG('S','E','E',' ')},*/     /* Seneca */
+   {HB_TAG('s','e','h',' '),     HB_TAG('S','N','A',' ')},       /* Sena */
+   {HB_TAG('s','e','k',' '),     HB_TAG('A','T','H',' ')},       /* Sekani -> Athapaskan */
+ /*{HB_TAG('s','e','l',' '),     HB_TAG('S','E','L',' ')},*/     /* Selkup */
+@@ -1374,9 +1406,13 @@ static const LangTag ot_languages3[] = {
+ /*{HB_TAG('s','i','d',' '),     HB_TAG('S','I','D',' ')},*/     /* Sidamo */
+   {HB_TAG('s','i','g',' '),     HB_TAG_NONE            },       /* Paasaal != Silte Gurage */
+   {HB_TAG('s','i','z',' '),     HB_TAG('B','B','R',' ')},       /* Siwi -> Berber */
++/*{HB_TAG('s','j','a',' '),     HB_TAG('S','J','A',' ')},*/     /* Epena */
++  {HB_TAG('s','j','c',' '),     HB_TAG('Z','H','S',' ')},       /* Shaojiang Chinese -> Chinese, Simplified */
+   {HB_TAG('s','j','d',' '),     HB_TAG('K','S','M',' ')},       /* Kildin Sami */
++/*{HB_TAG('s','j','e',' '),     HB_TAG('S','J','E',' ')},*/     /* Pite Sami */
+   {HB_TAG('s','j','o',' '),     HB_TAG('S','I','B',' ')},       /* Xibe -> Sibe */
+   {HB_TAG('s','j','s',' '),     HB_TAG('B','B','R',' ')},       /* Senhaja De Srair -> Berber */
++/*{HB_TAG('s','j','u',' '),     HB_TAG('S','J','U',' ')},*/     /* Ume Sami */
+   {HB_TAG('s','k','g',' '),     HB_TAG('M','L','G',' ')},       /* Sakalava Malagasy -> Malagasy */
+   {HB_TAG('s','k','r',' '),     HB_TAG('S','R','K',' ')},       /* Saraiki */
+   {HB_TAG('s','k','s',' '),     HB_TAG_NONE            },       /* Maia != Skolt Sami */
+@@ -1395,7 +1431,7 @@ static const LangTag ot_languages3[] = {
+ /*{HB_TAG('s','n','k',' '),     HB_TAG('S','N','K',' ')},*/     /* Soninke */
+   {HB_TAG('s','o','g',' '),     HB_TAG_NONE            },       /* Sogdian != Sodo Gurage */
+ /*{HB_TAG('s','o','p',' '),     HB_TAG('S','O','P',' ')},*/     /* Songe */
+-  {HB_TAG('s','p','v',' '),     HB_TAG('O','R','I',' ')},       /* Sambalpuri -> Odia (formerly Oriya) */
++  {HB_TAG('s','p','v',' '),     HB_TAG('O','R','I',' ')},       /* Sambalpuri -> Odia */
+   {HB_TAG('s','p','y',' '),     HB_TAG('K','A','L',' ')},       /* Sabaot -> Kalenjin */
+   {HB_TAG('s','r','b',' '),     HB_TAG_NONE            },       /* Sora != Serbian */
+   {HB_TAG('s','r','c',' '),     HB_TAG('S','R','D',' ')},       /* Logudorese Sardinian -> Sardinian */
+@@ -1410,6 +1446,7 @@ static const LangTag ot_languages3[] = {
+   {HB_TAG('s','s','m',' '),     HB_TAG_NONE            },       /* Semnam != Southern Sami */
+   {HB_TAG('s','t','a',' '),     HB_TAG('C','P','P',' ')},       /* Settla -> Creoles */
+ /*{HB_TAG('s','t','q',' '),     HB_TAG('S','T','Q',' ')},*/     /* Saterfriesisch -> Saterland Frisian */
++/*{HB_TAG('s','t','r',' '),     HB_TAG('S','T','R',' ')},*/     /* Straits Salish */
+   {HB_TAG('s','t','v',' '),     HB_TAG('S','I','G',' ')},       /* Silt'e -> Silte Gurage */
+ /*{HB_TAG('s','u','k',' '),     HB_TAG('S','U','K',' ')},*/     /* Sukuma */
+   {HB_TAG('s','u','q',' '),     HB_TAG('S','U','R',' ')},       /* Suri */
+@@ -1431,10 +1468,12 @@ static const LangTag ot_languages3[] = {
+   {HB_TAG('t','a','a',' '),     HB_TAG('A','T','H',' ')},       /* Lower Tanana -> Athapaskan */
+ /*{HB_TAG('t','a','b',' '),     HB_TAG('T','A','B',' ')},*/     /* Tabassaran -> Tabasaran */
+   {HB_TAG('t','a','j',' '),     HB_TAG_NONE            },       /* Eastern Tamang != Tajiki */
++  {HB_TAG('t','a','q',' '),     HB_TAG('T','A','Q',' ')},       /* Tamasheq */
+   {HB_TAG('t','a','q',' '),     HB_TAG('T','M','H',' ')},       /* Tamasheq -> Tamashek */
+   {HB_TAG('t','a','q',' '),     HB_TAG('B','B','R',' ')},       /* Tamasheq -> Berber */
+   {HB_TAG('t','a','s',' '),     HB_TAG('C','P','P',' ')},       /* Tay Boi -> Creoles */
+   {HB_TAG('t','a','u',' '),     HB_TAG('A','T','H',' ')},       /* Upper Tanana -> Athapaskan */
++/*{HB_TAG('t','b','v',' '),     HB_TAG('T','B','V',' ')},*/     /* Tobo */
+   {HB_TAG('t','c','b',' '),     HB_TAG('A','T','H',' ')},       /* Tanacross -> Athapaskan */
+   {HB_TAG('t','c','e',' '),     HB_TAG('A','T','H',' ')},       /* Southern Tutchone -> Athapaskan */
+   {HB_TAG('t','c','h',' '),     HB_TAG('C','P','P',' ')},       /* Turks And Caicos Creole English -> Creoles */
+@@ -1442,6 +1481,7 @@ static const LangTag ot_languages3[] = {
+   {HB_TAG('t','c','s',' '),     HB_TAG('C','P','P',' ')},       /* Torres Strait Creole -> Creoles */
+   {HB_TAG('t','c','y',' '),     HB_TAG('T','U','L',' ')},       /* Tulu */
+   {HB_TAG('t','c','z',' '),     HB_TAG('Q','I','N',' ')},       /* Thado Chin -> Chin */
++/*{HB_TAG('t','d','c',' '),     HB_TAG('T','D','C',' ')},*/     /* Emberá-Tadó */
+ /*{HB_TAG('t','d','d',' '),     HB_TAG('T','D','D',' ')},*/     /* Tai Nüa -> Dehong Dai */
+   {HB_TAG('t','d','x',' '),     HB_TAG('M','L','G',' ')},       /* Tandroy-Mahafaly Malagasy -> Malagasy */
+   {HB_TAG('t','e','c',' '),     HB_TAG('K','A','L',' ')},       /* Terik -> Kalenjin */
+@@ -1455,9 +1495,12 @@ static const LangTag ot_languages3[] = {
+   {HB_TAG('t','g','r',' '),     HB_TAG_NONE            },       /* Tareng != Tigre */
+   {HB_TAG('t','g','x',' '),     HB_TAG('A','T','H',' ')},       /* Tagish -> Athapaskan */
+   {HB_TAG('t','g','y',' '),     HB_TAG_NONE            },       /* Togoyo != Tigrinya */
++/*{HB_TAG('t','h','p',' '),     HB_TAG('T','H','P',' ')},*/     /* Thompson */
+   {HB_TAG('t','h','t',' '),     HB_TAG('A','T','H',' ')},       /* Tahltan -> Athapaskan */
++  {HB_TAG('t','h','v',' '),     HB_TAG('T','H','V',' ')},       /* Tahaggart Tamahaq */
+   {HB_TAG('t','h','v',' '),     HB_TAG('T','M','H',' ')},       /* Tahaggart Tamahaq -> Tamashek */
+   {HB_TAG('t','h','v',' '),     HB_TAG('B','B','R',' ')},       /* Tahaggart Tamahaq -> Berber */
++  {HB_TAG('t','h','z',' '),     HB_TAG('T','H','Z',' ')},       /* Tayart Tamajeq */
+   {HB_TAG('t','h','z',' '),     HB_TAG('T','M','H',' ')},       /* Tayart Tamajeq -> Tamashek */
+   {HB_TAG('t','h','z',' '),     HB_TAG('B','B','R',' ')},       /* Tayart Tamajeq -> Berber */
+   {HB_TAG('t','i','a',' '),     HB_TAG('B','B','R',' ')},       /* Tidikelt Tamazight -> Berber */
+@@ -1468,6 +1511,7 @@ static const LangTag ot_languages3[] = {
+   {HB_TAG('t','k','g',' '),     HB_TAG('M','L','G',' ')},       /* Tesaka Malagasy -> Malagasy */
+   {HB_TAG('t','k','m',' '),     HB_TAG_NONE            },       /* Takelma != Turkmen */
+ /*{HB_TAG('t','l','i',' '),     HB_TAG('T','L','I',' ')},*/     /* Tlingit */
++/*{HB_TAG('t','l','y',' '),     HB_TAG('T','L','Y',' ')},*/     /* Talysh */
+   {HB_TAG('t','m','g',' '),     HB_TAG('C','P','P',' ')},       /* Ternateño -> Creoles */
+   {HB_TAG('t','m','h',' '),     HB_TAG('T','M','H',' ')},       /* Tamashek [macrolanguage] */
+   {HB_TAG('t','m','h',' '),     HB_TAG('B','B','R',' ')},       /* Tamashek [macrolanguage] -> Berber */
+@@ -1493,11 +1537,13 @@ static const LangTag ot_languages3[] = {
+ /*{HB_TAG('t','s','j',' '),     HB_TAG('T','S','J',' ')},*/     /* Tshangla */
+   {HB_TAG('t','t','c',' '),     HB_TAG('M','Y','N',' ')},       /* Tektiteko -> Mayan */
+   {HB_TAG('t','t','m',' '),     HB_TAG('A','T','H',' ')},       /* Northern Tutchone -> Athapaskan */
++  {HB_TAG('t','t','q',' '),     HB_TAG('T','T','Q',' ')},       /* Tawallammat Tamajaq */
+   {HB_TAG('t','t','q',' '),     HB_TAG('T','M','H',' ')},       /* Tawallammat Tamajaq -> Tamashek */
+   {HB_TAG('t','t','q',' '),     HB_TAG('B','B','R',' ')},       /* Tawallammat Tamajaq -> Berber */
+   {HB_TAG('t','u','a',' '),     HB_TAG_NONE            },       /* Wiarumus != Turoyo Aramaic */
+   {HB_TAG('t','u','l',' '),     HB_TAG_NONE            },       /* Tula != Tulu */
+ /*{HB_TAG('t','u','m',' '),     HB_TAG('T','U','M',' ')},*/     /* Tumbuka */
++/*{HB_TAG('t','u','s',' '),     HB_TAG('T','U','S',' ')},*/     /* Tuscarora */
+   {HB_TAG('t','u','u',' '),     HB_TAG('A','T','H',' ')},       /* Tututni -> Athapaskan */
+   {HB_TAG('t','u','v',' '),     HB_TAG_NONE            },       /* Turkana != Tuvin */
+   {HB_TAG('t','u','y',' '),     HB_TAG('K','A','L',' ')},       /* Tugen -> Kalenjin */
+@@ -1514,6 +1560,7 @@ static const LangTag ot_languages3[] = {
+   {HB_TAG('t','z','o',' '),     HB_TAG('T','Z','O',' ')},       /* Tzotzil */
+   {HB_TAG('t','z','o',' '),     HB_TAG('M','Y','N',' ')},       /* Tzotzil -> Mayan */
+   {HB_TAG('u','b','l',' '),     HB_TAG('B','I','K',' ')},       /* Buhi'non Bikol -> Bikol */
++/*{HB_TAG('u','d','i',' '),     HB_TAG('U','D','I',' ')},*/     /* Udi */
+ /*{HB_TAG('u','d','m',' '),     HB_TAG('U','D','M',' ')},*/     /* Udmurt */
+   {HB_TAG('u','k','i',' '),     HB_TAG('K','U','I',' ')},       /* Kui (India) */
+   {HB_TAG('u','l','n',' '),     HB_TAG('C','P','P',' ')},       /* Unserdeutsch -> Creoles */
+@@ -1532,13 +1579,17 @@ static const LangTag ot_languages3[] = {
+   {HB_TAG('v','k','t',' '),     HB_TAG('M','L','Y',' ')},       /* Tenggarong Kutai Malay -> Malay */
+   {HB_TAG('v','l','s',' '),     HB_TAG('F','L','E',' ')},       /* Vlaams -> Dutch (Flemish) */
+   {HB_TAG('v','m','w',' '),     HB_TAG('M','A','K',' ')},       /* Makhuwa */
+-/*{HB_TAG('v','r','o',' '),     HB_TAG('V','R','O',' ')},*/     /* Võro */
++  {HB_TAG('v','r','o',' '),     HB_TAG('V','R','O',' ')},       /* Võro */
++  {HB_TAG('v','r','o',' '),     HB_TAG('E','T','I',' ')},       /* Võro -> Estonian */
++  {HB_TAG('v','s','n',' '),     HB_TAG('S','A','N',' ')},       /* Vedic Sanskrit -> Sanskrit */
+   {HB_TAG('w','a','g',' '),     HB_TAG_NONE            },       /* Wa'ema != Wagdi */
+ /*{HB_TAG('w','a','r',' '),     HB_TAG('W','A','R',' ')},*/     /* Waray (Philippines) -> Waray-Waray */
++/*{HB_TAG('w','b','l',' '),     HB_TAG('W','B','L',' ')},*/     /* Wakhi */
+   {HB_TAG('w','b','m',' '),     HB_TAG('W','A',' ',' ')},       /* Wa */
+   {HB_TAG('w','b','r',' '),     HB_TAG('W','A','G',' ')},       /* Wagdi */
+   {HB_TAG('w','b','r',' '),     HB_TAG('R','A','J',' ')},       /* Wagdi -> Rajasthani */
+ /*{HB_TAG('w','c','i',' '),     HB_TAG('W','C','I',' ')},*/     /* Waci Gbe */
++/*{HB_TAG('w','d','t',' '),     HB_TAG('W','D','T',' ')},*/     /* Wendat */
+   {HB_TAG('w','e','a',' '),     HB_TAG('K','R','N',' ')},       /* Wewaw -> Karen */
+   {HB_TAG('w','e','s',' '),     HB_TAG('C','P','P',' ')},       /* Cameroon Pidgin -> Creoles */
+   {HB_TAG('w','e','u',' '),     HB_TAG('Q','I','N',' ')},       /* Rawngtu Chin -> Chin */
+@@ -1550,6 +1601,9 @@ static const LangTag ot_languages3[] = {
+   {HB_TAG('w','s','g',' '),     HB_TAG('G','O','N',' ')},       /* Adilabad Gondi -> Gondi */
+ /*{HB_TAG('w','t','m',' '),     HB_TAG('W','T','M',' ')},*/     /* Mewati */
+   {HB_TAG('w','u','u',' '),     HB_TAG('Z','H','S',' ')},       /* Wu Chinese -> Chinese, Simplified */
++  {HB_TAG('w','y','a',' '),     HB_TAG('W','D','T',' ')},       /* Wyandot (retired code) -> Wendat */
++  {HB_TAG('w','y','a',' '),     HB_TAG('W','Y','N',' ')},       /* Wyandot (retired code) */
++/*{HB_TAG('w','y','n',' '),     HB_TAG('W','Y','N',' ')},*/     /* Wyandot */
+   {HB_TAG('x','a','l',' '),     HB_TAG('K','L','M',' ')},       /* Kalmyk */
+   {HB_TAG('x','a','l',' '),     HB_TAG('T','O','D',' ')},       /* Kalmyk -> Todo */
+   {HB_TAG('x','a','n',' '),     HB_TAG('S','E','K',' ')},       /* Xamtanga -> Sekota */
+@@ -1582,7 +1636,7 @@ static const LangTag ot_languages3[] = {
+   {HB_TAG('y','b','a',' '),     HB_TAG_NONE            },       /* Yala != Yoruba */
+   {HB_TAG('y','b','b',' '),     HB_TAG('B','M','L',' ')},       /* Yemba -> Bamileke */
+   {HB_TAG('y','b','d',' '),     HB_TAG('A','R','K',' ')},       /* Yangbye (retired code) -> Rakhine */
+-  {HB_TAG('y','c','r',' '),     HB_TAG_NONE            },       /* Yilan Creole != Y-Cree */
++  {HB_TAG('y','c','r',' '),     HB_TAG('C','P','P',' ')},       /* Yilan Creole -> Creoles */
+   {HB_TAG('y','d','d',' '),     HB_TAG('J','I','I',' ')},       /* Eastern Yiddish -> Yiddish */
+ /*{HB_TAG('y','g','p',' '),     HB_TAG('Y','G','P',' ')},*/     /* Gepo */
+   {HB_TAG('y','i','h',' '),     HB_TAG('J','I','I',' ')},       /* Western Yiddish -> Yiddish */
+@@ -1591,6 +1645,7 @@ static const LangTag ot_languages3[] = {
+   {HB_TAG('y','o','s',' '),     HB_TAG('Q','I','N',' ')},       /* Yos (retired code) -> Chin */
+   {HB_TAG('y','u','a',' '),     HB_TAG('M','Y','N',' ')},       /* Yucateco -> Mayan */
+   {HB_TAG('y','u','e',' '),     HB_TAG('Z','H','H',' ')},       /* Yue Chinese -> Chinese, Traditional, Hong Kong SAR */
++/*{HB_TAG('y','u','f',' '),     HB_TAG('Y','U','F',' ')},*/     /* Havasupai-Walapai-Yavapai */
+ /*{HB_TAG('y','w','q',' '),     HB_TAG('Y','W','Q',' ')},*/     /* Wuding-Luquan Yi */
+   {HB_TAG('z','c','h',' '),     HB_TAG('Z','H','A',' ')},       /* Central Hongshuihe Zhuang -> Zhuang */
+   {HB_TAG('z','d','j',' '),     HB_TAG('C','M','R',' ')},       /* Ngazidja Comorian -> Comorian */
+@@ -2335,6 +2390,26 @@ out:
+       *count = i;
+       return true;
+     }
++    if (lang_matches (&lang_str[1], limit, "nm-hant-hk", 10))
++    {
++      /* Hainanese; Han (Traditional variant); Hong Kong */
++      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Traditional, Hong Kong SAR */
++      *count = 1;
++      return true;
++    }
++    if (lang_matches (&lang_str[1], limit, "nm-hant-mo", 10))
++    {
++      /* Hainanese; Han (Traditional variant); Macao */
++      unsigned int i;
++      hb_tag_t possible_tags[] = {
++        HB_TAG('Z','H','T','M'),  /* Chinese, Traditional, Macao SAR */
++        HB_TAG('Z','H','H',' '),  /* Chinese, Traditional, Hong Kong SAR */
++      };
++      for (i = 0; i < 2 && i < *count; i++)
++        tags[i] = possible_tags[i];
++      *count = i;
++      return true;
++    }
+     if (lang_matches (&lang_str[1], limit, "sn-hant-hk", 10))
+     {
+       /* Xiang Chinese; Han (Traditional variant); Hong Kong */
+@@ -2369,6 +2444,20 @@ out:
+       *count = 1;
+       return true;
+     }
++    if (lang_matches (&lang_str[1], limit, "nm-hans", 7))
++    {
++      /* Hainanese; Han (Simplified variant) */
++      tags[0] = HB_TAG('Z','H','S',' ');  /* Chinese, Simplified */
++      *count = 1;
++      return true;
++    }
++    if (lang_matches (&lang_str[1], limit, "nm-hant", 7))
++    {
++      /* Hainanese; Han (Traditional variant) */
++      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese, Traditional */
++      *count = 1;
++      return true;
++    }
+     if (lang_matches (&lang_str[1], limit, "sn-hans", 7))
+     {
+       /* Xiang Chinese; Han (Simplified variant) */
+@@ -2413,6 +2502,36 @@ out:
+       *count = 1;
+       return true;
+     }
++    if (0 == strncmp (&lang_str[1], "nm-", 3)
++        && subtag_matches (lang_str, limit, "-hk", 3))
++    {
++      /* Hainanese; Hong Kong */
++      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Traditional, Hong Kong SAR */
++      *count = 1;
++      return true;
++    }
++    if (0 == strncmp (&lang_str[1], "nm-", 3)
++        && subtag_matches (lang_str, limit, "-mo", 3))
++    {
++      /* Hainanese; Macao */
++      unsigned int i;
++      hb_tag_t possible_tags[] = {
++        HB_TAG('Z','H','T','M'),  /* Chinese, Traditional, Macao SAR */
++        HB_TAG('Z','H','H',' '),  /* Chinese, Traditional, Hong Kong SAR */
++      };
++      for (i = 0; i < 2 && i < *count; i++)
++        tags[i] = possible_tags[i];
++      *count = i;
++      return true;
++    }
++    if (0 == strncmp (&lang_str[1], "nm-", 3)
++        && subtag_matches (lang_str, limit, "-tw", 3))
++    {
++      /* Hainanese; Taiwan, Province of China */
++      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese, Traditional */
++      *count = 1;
++      return true;
++    }
+     if (0 == strncmp (&lang_str[1], "sn-", 3)
+         && subtag_matches (lang_str, limit, "-hk", 3))
+     {
+@@ -2474,6 +2593,40 @@ out:
+     }
+     break;
+   case 'l':
++    if (lang_matches (&lang_str[1], limit, "uh-hant-hk", 10))
++    {
++      /* Leizhou Chinese; Han (Traditional variant); Hong Kong */
++      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Traditional, Hong Kong SAR */
++      *count = 1;
++      return true;
++    }
++    if (lang_matches (&lang_str[1], limit, "uh-hant-mo", 10))
++    {
++      /* Leizhou Chinese; Han (Traditional variant); Macao */
++      unsigned int i;
++      hb_tag_t possible_tags[] = {
++        HB_TAG('Z','H','T','M'),  /* Chinese, Traditional, Macao SAR */
++        HB_TAG('Z','H','H',' '),  /* Chinese, Traditional, Hong Kong SAR */
++      };
++      for (i = 0; i < 2 && i < *count; i++)
++        tags[i] = possible_tags[i];
++      *count = i;
++      return true;
++    }
++    if (lang_matches (&lang_str[1], limit, "uh-hans", 7))
++    {
++      /* Leizhou Chinese; Han (Simplified variant) */
++      tags[0] = HB_TAG('Z','H','S',' ');  /* Chinese, Simplified */
++      *count = 1;
++      return true;
++    }
++    if (lang_matches (&lang_str[1], limit, "uh-hant", 7))
++    {
++      /* Leizhou Chinese; Han (Traditional variant) */
++      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese, Traditional */
++      *count = 1;
++      return true;
++    }
+     if (lang_matches (&lang_str[1], limit, "zh-hans", 7))
+     {
+       /* Literary Chinese; Han (Simplified variant) */
+@@ -2481,6 +2634,36 @@ out:
+       *count = 1;
+       return true;
+     }
++    if (0 == strncmp (&lang_str[1], "uh-", 3)
++        && subtag_matches (lang_str, limit, "-hk", 3))
++    {
++      /* Leizhou Chinese; Hong Kong */
++      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Traditional, Hong Kong SAR */
++      *count = 1;
++      return true;
++    }
++    if (0 == strncmp (&lang_str[1], "uh-", 3)
++        && subtag_matches (lang_str, limit, "-mo", 3))
++    {
++      /* Leizhou Chinese; Macao */
++      unsigned int i;
++      hb_tag_t possible_tags[] = {
++        HB_TAG('Z','H','T','M'),  /* Chinese, Traditional, Macao SAR */
++        HB_TAG('Z','H','H',' '),  /* Chinese, Traditional, Hong Kong SAR */
++      };
++      for (i = 0; i < 2 && i < *count; i++)
++        tags[i] = possible_tags[i];
++      *count = i;
++      return true;
++    }
++    if (0 == strncmp (&lang_str[1], "uh-", 3)
++        && subtag_matches (lang_str, limit, "-tw", 3))
++    {
++      /* Leizhou Chinese; Taiwan, Province of China */
++      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese, Traditional */
++      *count = 1;
++      return true;
++    }
+     break;
+   case 'm':
+     if (lang_matches (&lang_str[1], limit, "np-hant-hk", 10))
+@@ -2652,6 +2835,72 @@ out:
+       return true;
+     }
+     break;
++  case 's':
++    if (lang_matches (&lang_str[1], limit, "jc-hant-hk", 10))
++    {
++      /* Shaojiang Chinese; Han (Traditional variant); Hong Kong */
++      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Traditional, Hong Kong SAR */
++      *count = 1;
++      return true;
++    }
++    if (lang_matches (&lang_str[1], limit, "jc-hant-mo", 10))
++    {
++      /* Shaojiang Chinese; Han (Traditional variant); Macao */
++      unsigned int i;
++      hb_tag_t possible_tags[] = {
++        HB_TAG('Z','H','T','M'),  /* Chinese, Traditional, Macao SAR */
++        HB_TAG('Z','H','H',' '),  /* Chinese, Traditional, Hong Kong SAR */
++      };
++      for (i = 0; i < 2 && i < *count; i++)
++        tags[i] = possible_tags[i];
++      *count = i;
++      return true;
++    }
++    if (lang_matches (&lang_str[1], limit, "jc-hans", 7))
++    {
++      /* Shaojiang Chinese; Han (Simplified variant) */
++      tags[0] = HB_TAG('Z','H','S',' ');  /* Chinese, Simplified */
++      *count = 1;
++      return true;
++    }
++    if (lang_matches (&lang_str[1], limit, "jc-hant", 7))
++    {
++      /* Shaojiang Chinese; Han (Traditional variant) */
++      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese, Traditional */
++      *count = 1;
++      return true;
++    }
++    if (0 == strncmp (&lang_str[1], "jc-", 3)
++        && subtag_matches (lang_str, limit, "-hk", 3))
++    {
++      /* Shaojiang Chinese; Hong Kong */
++      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Traditional, Hong Kong SAR */
++      *count = 1;
++      return true;
++    }
++    if (0 == strncmp (&lang_str[1], "jc-", 3)
++        && subtag_matches (lang_str, limit, "-mo", 3))
++    {
++      /* Shaojiang Chinese; Macao */
++      unsigned int i;
++      hb_tag_t possible_tags[] = {
++        HB_TAG('Z','H','T','M'),  /* Chinese, Traditional, Macao SAR */
++        HB_TAG('Z','H','H',' '),  /* Chinese, Traditional, Hong Kong SAR */
++      };
++      for (i = 0; i < 2 && i < *count; i++)
++        tags[i] = possible_tags[i];
++      *count = i;
++      return true;
++    }
++    if (0 == strncmp (&lang_str[1], "jc-", 3)
++        && subtag_matches (lang_str, limit, "-tw", 3))
++    {
++      /* Shaojiang Chinese; Taiwan, Province of China */
++      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese, Traditional */
++      *count = 1;
++      return true;
++    }
++    break;
+   case 'w':
+     if (lang_matches (&lang_str[1], limit, "uu-hant-hk", 10))
+     {
+@@ -2816,9 +3065,10 @@ out:
+  * @tag: A language tag.
+  *
+  * Converts @tag to a BCP 47 language tag if it is ambiguous (it corresponds to
+- * many language tags) and the best tag is not the alphabetically first, or if
+- * the best tag consists of multiple subtags, or if the best tag does not appear
+- * in #ot_languages.
++ * many language tags) and the best tag is not the first (sorted alphabetically,
++ * with two-letter tags having priority over all three-letter tags), or if the
++ * best tag consists of multiple subtags, or if the best tag does not appear in
++ * #ot_languages2 or #ot_languages3.
+  *
+  * Return value: The #hb_language_t corresponding to the BCP 47 language tag,
+  * or #HB_LANGUAGE_INVALID if @tag is not ambiguous.
+@@ -2832,8 +3082,6 @@ hb_ot_ambiguous_tag_to_language (hb_tag_t tag)
+     return hb_language_from_string ("alt", -1);  /* Southern Altai */
+   case HB_TAG('A','P','P','H'):  /* Phonetic transcription—Americanist conventions */
+     return hb_language_from_string ("und-fonnapa", -1);  /* Undetermined; North American Phonetic Alphabet */
+-  case HB_TAG('A','R','A',' '):  /* Arabic */
+-    return hb_language_from_string ("ar", -1);  /* Arabic [macrolanguage] */
+   case HB_TAG('A','R','K',' '):  /* Rakhine */
+     return hb_language_from_string ("rki", -1);  /* Rakhine */
+   case HB_TAG('A','T','H',' '):  /* Athapaskan */
+@@ -2854,12 +3102,6 @@ hb_ot_ambiguous_tag_to_language (hb_tag_t tag)
+     return hb_language_from_string ("din", -1);  /* Dinka [macrolanguage] */
+   case HB_TAG('D','R','I',' '):  /* Dari */
+     return hb_language_from_string ("prs", -1);  /* Dari */
+-  case HB_TAG('D','Z','N',' '):  /* Dzongkha */
+-    return hb_language_from_string ("dz", -1);  /* Dzongkha */
+-  case HB_TAG('E','T','I',' '):  /* Estonian */
+-    return hb_language_from_string ("et", -1);  /* Estonian [macrolanguage] */
+-  case HB_TAG('F','A','R',' '):  /* Persian */
+-    return hb_language_from_string ("fa", -1);  /* Persian [macrolanguage] */
+   case HB_TAG('G','O','N',' '):  /* Gondi */
+     return hb_language_from_string ("gon", -1);  /* Gondi [macrolanguage] */
+   case HB_TAG('H','M','A',' '):  /* High Mari */
+@@ -2874,50 +3116,34 @@ hb_ot_ambiguous_tag_to_language (hb_tag_t tag)
+     return hb_language_from_string ("iba", -1);  /* Iban */
+   case HB_TAG('I','J','O',' '):  /* Ijo */
+     return hb_language_from_string ("ijo", -1);  /* Ijo [collection] */
+-  case HB_TAG('I','N','U',' '):  /* Inuktitut */
+-    return hb_language_from_string ("iu", -1);  /* Inuktitut [macrolanguage] */
+-  case HB_TAG('I','P','K',' '):  /* Inupiat */
+-    return hb_language_from_string ("ik", -1);  /* Inupiaq [macrolanguage] */
+   case HB_TAG('I','P','P','H'):  /* Phonetic transcription—IPA conventions */
+     return hb_language_from_string ("und-fonipa", -1);  /* Undetermined; International Phonetic Alphabet */
+   case HB_TAG('I','R','T',' '):  /* Irish Traditional */
+-    return hb_language_from_string ("ga-Latg", -1);  /* Irish; Latin (Gaelic variant) */
++    return hb_language_from_string ("ghc", -1);  /* Hiberno-Scottish Gaelic */
+   case HB_TAG('J','I','I',' '):  /* Yiddish */
+     return hb_language_from_string ("yi", -1);  /* Yiddish [macrolanguage] */
+   case HB_TAG('K','A','L',' '):  /* Kalenjin */
+     return hb_language_from_string ("kln", -1);  /* Kalenjin [macrolanguage] */
+   case HB_TAG('K','G','E',' '):  /* Khutsuri Georgian */
+     return hb_language_from_string ("und-Geok", -1);  /* Undetermined; Khutsuri (Asomtavruli and Nuskhuri) */
+-  case HB_TAG('K','N','R',' '):  /* Kanuri */
+-    return hb_language_from_string ("kr", -1);  /* Kanuri [macrolanguage] */
+   case HB_TAG('K','O','H',' '):  /* Korean Old Hangul */
+     return hb_language_from_string ("okm", -1);  /* Middle Korean (10th-16th cent.) */
+   case HB_TAG('K','O','K',' '):  /* Konkani */
+     return hb_language_from_string ("kok", -1);  /* Konkani [macrolanguage] */
+-  case HB_TAG('K','O','M',' '):  /* Komi */
+-    return hb_language_from_string ("kv", -1);  /* Komi [macrolanguage] */
+   case HB_TAG('K','P','L',' '):  /* Kpelle */
+     return hb_language_from_string ("kpe", -1);  /* Kpelle [macrolanguage] */
+   case HB_TAG('K','R','N',' '):  /* Karen */
+     return hb_language_from_string ("kar", -1);  /* Karen [collection] */
+   case HB_TAG('K','U','I',' '):  /* Kui */
+     return hb_language_from_string ("uki", -1);  /* Kui (India) */
+-  case HB_TAG('K','U','R',' '):  /* Kurdish */
+-    return hb_language_from_string ("ku", -1);  /* Kurdish [macrolanguage] */
+   case HB_TAG('L','M','A',' '):  /* Low Mari */
+     return hb_language_from_string ("mhr", -1);  /* Eastern Mari */
+   case HB_TAG('L','U','H',' '):  /* Luyia */
+     return hb_language_from_string ("luy", -1);  /* Luyia [macrolanguage] */
+-  case HB_TAG('L','V','I',' '):  /* Latvian */
+-    return hb_language_from_string ("lv", -1);  /* Latvian [macrolanguage] */
+   case HB_TAG('M','A','W',' '):  /* Marwari */
+     return hb_language_from_string ("mwr", -1);  /* Marwari [macrolanguage] */
+-  case HB_TAG('M','L','G',' '):  /* Malagasy */
+-    return hb_language_from_string ("mg", -1);  /* Malagasy [macrolanguage] */
+   case HB_TAG('M','L','Y',' '):  /* Malay */
+     return hb_language_from_string ("ms", -1);  /* Malay [macrolanguage] */
+-  case HB_TAG('M','N','G',' '):  /* Mongolian */
+-    return hb_language_from_string ("mn", -1);  /* Mongolian [macrolanguage] */
+   case HB_TAG('M','N','K',' '):  /* Maninka */
+     return hb_language_from_string ("man", -1);  /* Mandingo [macrolanguage] */
+   case HB_TAG('M','O','L',' '):  /* Moldavian */
+@@ -2928,26 +3154,16 @@ hb_ot_ambiguous_tag_to_language (hb_tag_t tag)
+     return hb_language_from_string ("myn", -1);  /* Mayan [collection] */
+   case HB_TAG('N','A','H',' '):  /* Nahuatl */
+     return hb_language_from_string ("nah", -1);  /* Nahuatl [collection] */
+-  case HB_TAG('N','E','P',' '):  /* Nepali */
+-    return hb_language_from_string ("ne", -1);  /* Nepali [macrolanguage] */
+   case HB_TAG('N','I','S',' '):  /* Nisi */
+     return hb_language_from_string ("njz", -1);  /* Nyishi */
+   case HB_TAG('N','O','R',' '):  /* Norwegian */
+     return hb_language_from_string ("no", -1);  /* Norwegian [macrolanguage] */
+-  case HB_TAG('O','J','B',' '):  /* Ojibway */
+-    return hb_language_from_string ("oj", -1);  /* Ojibwa [macrolanguage] */
+-  case HB_TAG('O','R','O',' '):  /* Oromo */
+-    return hb_language_from_string ("om", -1);  /* Oromo [macrolanguage] */
+-  case HB_TAG('P','A','S',' '):  /* Pashto */
+-    return hb_language_from_string ("ps", -1);  /* Pashto [macrolanguage] */
+   case HB_TAG('P','G','R',' '):  /* Polytonic Greek */
+     return hb_language_from_string ("el-polyton", -1);  /* Modern Greek (1453-); Polytonic Greek */
+   case HB_TAG('P','R','O',' '):  /* Provençal / Old Provençal */
+     return hb_language_from_string ("pro", -1);  /* Old Provençal (to 1500) */
+   case HB_TAG('Q','U','H',' '):  /* Quechua (Bolivia) */
+     return hb_language_from_string ("quh", -1);  /* South Bolivian Quechua */
+-  case HB_TAG('Q','U','Z',' '):  /* Quechua */
+-    return hb_language_from_string ("qu", -1);  /* Quechua [macrolanguage] */
+   case HB_TAG('Q','V','I',' '):  /* Quechua (Ecuador) */
+     return hb_language_from_string ("qvi", -1);  /* Imbabura Highland Quichua */
+   case HB_TAG('Q','W','H',' '):  /* Quechua (Peru) */
+@@ -2958,8 +3174,8 @@ hb_ot_ambiguous_tag_to_language (hb_tag_t tag)
+     return hb_language_from_string ("ro", -1);  /* Romanian */
+   case HB_TAG('R','O','Y',' '):  /* Romany */
+     return hb_language_from_string ("rom", -1);  /* Romany [macrolanguage] */
+-  case HB_TAG('S','Q','I',' '):  /* Albanian */
+-    return hb_language_from_string ("sq", -1);  /* Albanian [macrolanguage] */
++  case HB_TAG('S','G','A',' '):  /* Old Irish */
++    return hb_language_from_string ("sga", -1);  /* Old Irish (to 900) */
+   case HB_TAG('S','R','B',' '):  /* Serbian */
+     return hb_language_from_string ("sr", -1);  /* Serbian */
+   case HB_TAG('S','X','T',' '):  /* Sutu */
+@@ -2976,6 +3192,10 @@ hb_ot_ambiguous_tag_to_language (hb_tag_t tag)
+     return hb_language_from_string ("tmh", -1);  /* Tamashek [macrolanguage] */
+   case HB_TAG('T','O','D',' '):  /* Todo */
+     return hb_language_from_string ("xwo", -1);  /* Written Oirat */
++  case HB_TAG('W','D','T',' '):  /* Wendat */
++    return hb_language_from_string ("wdt", -1);  /* Wendat */
++  case HB_TAG('W','Y','N',' '):  /* Wyandot */
++    return hb_language_from_string ("wyn", -1);  /* Wyandot */
+   case HB_TAG('Z','H','H',' '):  /* Chinese, Traditional, Hong Kong SAR */
+     return hb_language_from_string ("zh-HK", -1);  /* Chinese [macrolanguage]; Hong Kong */
+   case HB_TAG('Z','H','S',' '):  /* Chinese, Simplified */
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-tag.cc b/src/java.desktop/share/native/libharfbuzz/hb-ot-tag.cc
+index 9f0ae3b4d..3cdb70320 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-tag.cc
++++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-tag.cc
+@@ -547,7 +547,7 @@ hb_ot_tag_to_language (hb_tag_t tag)
+       buf[3] = '-';
+       str += 4;
+     }
+-    snprintf (str, 16, "x-hbot-%08x", tag);
++    snprintf (str, 16, "x-hbot-%08" PRIx32, tag);
+     return hb_language_from_string (&*buf, -1);
+   }
+ }
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-var-avar-table.hh b/src/java.desktop/share/native/libharfbuzz/hb-ot-var-avar-table.hh
+index 0aaf68adb..e26687c34 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-var-avar-table.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-var-avar-table.hh
+@@ -57,7 +57,7 @@ struct avarV2Tail
+ 
+   protected:
+   Offset32To  varIdxMap;      /* Offset from the beginning of 'avar' table. */
+-  Offset32To    varStore;       /* Offset from the beginning of 'avar' table. */
++  Offset32To        varStore;       /* Offset from the beginning of 'avar' table. */
+ 
+   public:
+   DEFINE_SIZE_STATIC (8);
+@@ -80,7 +80,7 @@ struct AxisValueMap
+ 
+   bool is_outside_axis_range (const Triple& axis_range) const
+   {
+-    float from_coord = coords[0].to_float ();
++    double from_coord = (double) coords[0].to_float ();
+     return !axis_range.contains (from_coord);
+   }
+ 
+@@ -100,8 +100,8 @@ struct AxisValueMap
+     float from_coord = coords[0].to_float ();
+     float to_coord = coords[1].to_float ();
+ 
+-    from_coord = renormalizeValue (from_coord, unmapped_range, triple_distances);
+-    to_coord = renormalizeValue (to_coord, axis_range, triple_distances);
++    from_coord = renormalizeValue ((double) from_coord, unmapped_range, triple_distances);
++    to_coord = renormalizeValue ((double) to_coord, axis_range, triple_distances);
+ 
+     coords[0].set_float (from_coord);
+     coords[1].set_float (to_coord);
+@@ -197,7 +197,7 @@ struct SegmentMaps : Array16Of
+     unmapped_val.set_int (unmap (val.to_int ()));
+     float unmapped_max = unmapped_val.to_float ();
+ 
+-    return Triple{unmapped_min, unmapped_middle, unmapped_max};
++    return Triple{(double) unmapped_min, (double) unmapped_middle, (double) unmapped_max};
+   }
+ 
+   bool subset (hb_subset_context_t *c, hb_tag_t axis_tag) const
+@@ -230,7 +230,7 @@ struct SegmentMaps : Array16Of
+        * duplicates here */
+       if (mapping.must_include ())
+         continue;
+-      value_mappings.push (std::move (mapping));
++      value_mappings.push (mapping);
+     }
+ 
+     AxisValueMap m;
+@@ -273,6 +273,7 @@ struct avar
+   {
+     TRACE_SANITIZE (this);
+     if (!(version.sanitize (c) &&
++          hb_barrier () &&
+           (version.major == 1
+ #ifndef HB_NO_AVAR2
+            || version.major == 2
+@@ -293,6 +294,7 @@ struct avar
+ #ifndef HB_NO_AVAR2
+     if (version.major < 2)
+       return_trace (true);
++    hb_barrier ();
+ 
+     const auto &v2 = * (const avarV2Tail *) map;
+     if (unlikely (!v2.sanitize (c, this)))
+@@ -316,6 +318,7 @@ struct avar
+ #ifndef HB_NO_AVAR2
+     if (version.major < 2)
+       return;
++    hb_barrier ();
+ 
+     for (; count < axisCount; count++)
+       map = &StructAfter (*map);
+@@ -340,7 +343,7 @@ struct avar
+     for (unsigned i = 0; i < coords_length; i++)
+       coords[i] = out[i];
+ 
+-    OT::VariationStore::destroy_cache (var_store_cache);
++    OT::ItemVariationStore::destroy_cache (var_store_cache);
+ #endif
+   }
+ 
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-var-common.hh b/src/java.desktop/share/native/libharfbuzz/hb-ot-var-common.hh
+index 271250f91..72deddef2 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-var-common.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-var-common.hh
+@@ -28,215 +28,11 @@
+ 
+ #include "hb-ot-layout-common.hh"
+ #include "hb-priority-queue.hh"
++#include "hb-subset-instancer-iup.hh"
+ 
+ 
+ namespace OT {
+ 
+-template 
+-struct DeltaSetIndexMapFormat01
+-{
+-  friend struct DeltaSetIndexMap;
+-
+-  unsigned get_size () const
+-  { return min_size + mapCount * get_width (); }
+-
+-  private:
+-  DeltaSetIndexMapFormat01* copy (hb_serialize_context_t *c) const
+-  {
+-    TRACE_SERIALIZE (this);
+-    return_trace (c->embed (this));
+-  }
+-
+-  template 
+-  bool serialize (hb_serialize_context_t *c, const T &plan)
+-  {
+-    unsigned int width = plan.get_width ();
+-    unsigned int inner_bit_count = plan.get_inner_bit_count ();
+-    const hb_array_t output_map = plan.get_output_map ();
+-
+-    TRACE_SERIALIZE (this);
+-    if (unlikely (output_map.length && ((((inner_bit_count-1)&~0xF)!=0) || (((width-1)&~0x3)!=0))))
+-      return_trace (false);
+-    if (unlikely (!c->extend_min (this))) return_trace (false);
+-
+-    entryFormat = ((width-1)<<4)|(inner_bit_count-1);
+-    mapCount = output_map.length;
+-    HBUINT8 *p = c->allocate_size (width * output_map.length);
+-    if (unlikely (!p)) return_trace (false);
+-    for (unsigned int i = 0; i < output_map.length; i++)
+-    {
+-      unsigned int v = output_map.arrayZ[i];
+-      if (v)
+-      {
+-        unsigned int outer = v >> 16;
+-        unsigned int inner = v & 0xFFFF;
+-        unsigned int u = (outer << inner_bit_count) | inner;
+-        for (unsigned int w = width; w > 0;)
+-        {
+-          p[--w] = u;
+-          u >>= 8;
+-        }
+-      }
+-      p += width;
+-    }
+-    return_trace (true);
+-  }
+-
+-  uint32_t map (unsigned int v) const /* Returns 16.16 outer.inner. */
+-  {
+-    /* If count is zero, pass value unchanged.  This takes
+-     * care of direct mapping for advance map. */
+-    if (!mapCount)
+-      return v;
+-
+-    if (v >= mapCount)
+-      v = mapCount - 1;
+-
+-    unsigned int u = 0;
+-    { /* Fetch it. */
+-      unsigned int w = get_width ();
+-      const HBUINT8 *p = mapDataZ.arrayZ + w * v;
+-      for (; w; w--)
+-        u = (u << 8) + *p++;
+-    }
+-
+-    { /* Repack it. */
+-      unsigned int n = get_inner_bit_count ();
+-      unsigned int outer = u >> n;
+-      unsigned int inner = u & ((1 << n) - 1);
+-      u = (outer<<16) | inner;
+-    }
+-
+-    return u;
+-  }
+-
+-  unsigned get_map_count () const       { return mapCount; }
+-  unsigned get_width () const           { return ((entryFormat >> 4) & 3) + 1; }
+-  unsigned get_inner_bit_count () const { return (entryFormat & 0xF) + 1; }
+-
+-
+-  bool sanitize (hb_sanitize_context_t *c) const
+-  {
+-    TRACE_SANITIZE (this);
+-    return_trace (c->check_struct (this) &&
+-                  c->check_range (mapDataZ.arrayZ,
+-                                  mapCount,
+-                                  get_width ()));
+-  }
+-
+-  protected:
+-  HBUINT8       format;         /* Format identifier--format = 0 */
+-  HBUINT8       entryFormat;    /* A packed field that describes the compressed
+-                                 * representation of delta-set indices. */
+-  MapCountT     mapCount;       /* The number of mapping entries. */
+-  UnsizedArrayOf
+-                mapDataZ;       /* The delta-set index mapping data. */
+-
+-  public:
+-  DEFINE_SIZE_ARRAY (2+MapCountT::static_size, mapDataZ);
+-};
+-
+-struct DeltaSetIndexMap
+-{
+-  template 
+-  bool serialize (hb_serialize_context_t *c, const T &plan)
+-  {
+-    TRACE_SERIALIZE (this);
+-    unsigned length = plan.get_output_map ().length;
+-    u.format = length <= 0xFFFF ? 0 : 1;
+-    switch (u.format) {
+-    case 0: return_trace (u.format0.serialize (c, plan));
+-    case 1: return_trace (u.format1.serialize (c, plan));
+-    default:return_trace (false);
+-    }
+-  }
+-
+-  uint32_t map (unsigned v) const
+-  {
+-    switch (u.format) {
+-    case 0: return (u.format0.map (v));
+-    case 1: return (u.format1.map (v));
+-    default:return v;
+-    }
+-  }
+-
+-  unsigned get_map_count () const
+-  {
+-    switch (u.format) {
+-    case 0: return u.format0.get_map_count ();
+-    case 1: return u.format1.get_map_count ();
+-    default:return 0;
+-    }
+-  }
+-
+-  unsigned get_width () const
+-  {
+-    switch (u.format) {
+-    case 0: return u.format0.get_width ();
+-    case 1: return u.format1.get_width ();
+-    default:return 0;
+-    }
+-  }
+-
+-  unsigned get_inner_bit_count () const
+-  {
+-    switch (u.format) {
+-    case 0: return u.format0.get_inner_bit_count ();
+-    case 1: return u.format1.get_inner_bit_count ();
+-    default:return 0;
+-    }
+-  }
+-
+-  bool sanitize (hb_sanitize_context_t *c) const
+-  {
+-    TRACE_SANITIZE (this);
+-    if (!u.format.sanitize (c)) return_trace (false);
+-    switch (u.format) {
+-    case 0: return_trace (u.format0.sanitize (c));
+-    case 1: return_trace (u.format1.sanitize (c));
+-    default:return_trace (true);
+-    }
+-  }
+-
+-  DeltaSetIndexMap* copy (hb_serialize_context_t *c) const
+-  {
+-    TRACE_SERIALIZE (this);
+-    switch (u.format) {
+-    case 0: return_trace (reinterpret_cast (u.format0.copy (c)));
+-    case 1: return_trace (reinterpret_cast (u.format1.copy (c)));
+-    default:return_trace (nullptr);
+-    }
+-  }
+-
+-  protected:
+-  union {
+-  HBUINT8                            format;         /* Format identifier */
+-  DeltaSetIndexMapFormat01 format0;
+-  DeltaSetIndexMapFormat01 format1;
+-  } u;
+-  public:
+-  DEFINE_SIZE_UNION (1, format);
+-};
+-
+-
+-struct VarStoreInstancer
+-{
+-  VarStoreInstancer (const VariationStore *varStore,
+-                     const DeltaSetIndexMap *varIdxMap,
+-                     hb_array_t coords) :
+-    varStore (varStore), varIdxMap (varIdxMap), coords (coords) {}
+-
+-  operator bool () const { return varStore && bool (coords); }
+-
+-  /* according to the spec, if colr table has varStore but does not have
+-   * varIdxMap, then an implicit identity mapping is used */
+-  float operator() (uint32_t varIdx, unsigned short offset = 0) const
+-  { return coords ? varStore->get_delta (varIdxMap ? varIdxMap->map (VarIdx::add (varIdx, offset)) : varIdx + offset, coords) : 0; }
+-
+-  const VariationStore *varStore;
+-  const DeltaSetIndexMap *varIdxMap;
+-  hb_array_t coords;
+-};
+ 
+ /* https://docs.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#tuplevariationheader */
+ struct TupleVariationHeader
+@@ -296,15 +92,15 @@ struct TupleVariationHeader
+         start = hb_min (peak, 0.f);
+         end = hb_max (peak, 0.f);
+       }
+-      axis_tuples.set (*axis_tag, Triple (start, peak, end));
++      axis_tuples.set (*axis_tag, Triple ((double) start, (double) peak, (double) end));
+     }
+ 
+     return true;
+   }
+ 
+-  float calculate_scalar (hb_array_t coords, unsigned int coord_count,
+-                          const hb_array_t shared_tuples,
+-                          const hb_vector_t> *shared_tuple_active_idx = nullptr) const
++  double calculate_scalar (hb_array_t coords, unsigned int coord_count,
++                           const hb_array_t shared_tuples,
++                           const hb_vector_t> *shared_tuple_active_idx = nullptr) const
+   {
+     const F2DOT14 *peak_tuple;
+ 
+@@ -318,13 +114,13 @@ struct TupleVariationHeader
+     {
+       unsigned int index = get_index ();
+       if (unlikely ((index + 1) * coord_count > shared_tuples.length))
+-        return 0.f;
++        return 0.0;
+       peak_tuple = shared_tuples.sub_array (coord_count * index, coord_count).arrayZ;
+ 
+       if (shared_tuple_active_idx)
+       {
+         if (unlikely (index >= shared_tuple_active_idx->length))
+-          return 0.f;
++          return 0.0;
+         auto _ = (*shared_tuple_active_idx).arrayZ[index];
+         if (_.second != -1)
+         {
+@@ -349,7 +145,7 @@ struct TupleVariationHeader
+       end_tuple = get_end_tuple (coord_count).arrayZ;
+     }
+ 
+-    float scalar = 1.f;
++    double scalar = 1.0;
+     for (unsigned int i = start_idx; i < end_idx; i += step)
+     {
+       int peak = peak_tuple[i].to_int ();
+@@ -364,15 +160,15 @@ struct TupleVariationHeader
+         int end = end_tuple[i].to_int ();
+         if (unlikely (start > peak || peak > end ||
+                       (start < 0 && end > 0 && peak))) continue;
+-        if (v < start || v > end) return 0.f;
++        if (v < start || v > end) return 0.0;
+         if (v < peak)
+-        { if (peak != start) scalar *= (float) (v - start) / (peak - start); }
++        { if (peak != start) scalar *= (double) (v - start) / (peak - start); }
+         else
+-        { if (peak != end) scalar *= (float) (end - v) / (end - peak); }
++        { if (peak != end) scalar *= (double) (end - v) / (end - peak); }
+       }
+-      else if (!v || v < hb_min (0, peak) || v > hb_max (0, peak)) return 0.f;
++      else if (!v || v < hb_min (0, peak) || v > hb_max (0, peak)) return 0.0;
+       else
+-        scalar *= (float) v / peak;
++        scalar *= (double) v / peak;
+     }
+     return scalar;
+   }
+@@ -425,15 +221,10 @@ struct TupleVariationHeader
+   DEFINE_SIZE_MIN (4);
+ };
+ 
+-enum packed_delta_flag_t
+-{
+-  DELTAS_ARE_ZERO      = 0x80,
+-  DELTAS_ARE_WORDS     = 0x40,
+-  DELTA_RUN_COUNT_MASK = 0x3F
+-};
+-
+ struct tuple_delta_t
+ {
++  static constexpr bool realloc_move = true;  // Watch out when adding new members!
++
+   public:
+   hb_hashmap_t axis_tuples;
+ 
+@@ -447,8 +238,8 @@ struct tuple_delta_t
+   /* compiled data: header and deltas
+    * compiled point data is saved in a hashmap within tuple_variations_t cause
+    * some point sets might be reused by different tuple variations */
+-  hb_vector_t compiled_tuple_header;
+-  hb_vector_t compiled_deltas;
++  hb_vector_t compiled_tuple_header;
++  hb_vector_t compiled_deltas;
+ 
+   /* compiled peak coords, empty for non-gvar tuples */
+   hb_vector_t compiled_peak_coords;
+@@ -456,7 +247,7 @@ struct tuple_delta_t
+   tuple_delta_t () = default;
+   tuple_delta_t (const tuple_delta_t& o) = default;
+ 
+-  friend void swap (tuple_delta_t& a, tuple_delta_t& b)
++  friend void swap (tuple_delta_t& a, tuple_delta_t& b) noexcept
+   {
+     hb_swap (a.axis_tuples, b.axis_tuples);
+     hb_swap (a.indices, b.indices);
+@@ -467,10 +258,10 @@ struct tuple_delta_t
+     hb_swap (a.compiled_peak_coords, b.compiled_peak_coords);
+   }
+ 
+-  tuple_delta_t (tuple_delta_t&& o) : tuple_delta_t ()
++  tuple_delta_t (tuple_delta_t&& o)  noexcept : tuple_delta_t ()
+   { hb_swap (*this, o); }
+ 
+-  tuple_delta_t& operator = (tuple_delta_t&& o)
++  tuple_delta_t& operator = (tuple_delta_t&& o) noexcept
+   {
+     hb_swap (*this, o);
+     return *this;
+@@ -514,14 +305,19 @@ struct tuple_delta_t
+       return *this;
+ 
+     unsigned num = indices.length;
+-    for (unsigned i = 0; i < num; i++)
+-    {
+-      if (!indices.arrayZ[i]) continue;
+-
+-      deltas_x[i] *= scalar;
+-      if (deltas_y)
++    if (deltas_y)
++      for (unsigned i = 0; i < num; i++)
++      {
++        if (!indices.arrayZ[i]) continue;
++        deltas_x[i] *= scalar;
+         deltas_y[i] *= scalar;
+-    }
++      }
++    else
++      for (unsigned i = 0; i < num; i++)
++      {
++        if (!indices.arrayZ[i]) continue;
++        deltas_x[i] *= scalar;
++      }
+     return *this;
+   }
+ 
+@@ -536,18 +332,18 @@ struct tuple_delta_t
+       return out;
+     }
+ 
+-    if ((tent->minimum < 0.f && tent->maximum > 0.f) ||
++    if ((tent->minimum < 0.0 && tent->maximum > 0.0) ||
+         !(tent->minimum <= tent->middle && tent->middle <= tent->maximum))
+       return out;
+ 
+-    if (tent->middle == 0.f)
++    if (tent->middle == 0.0)
+     {
+       out.push (*this);
+       return out;
+     }
+ 
+-    result_t solutions = rebase_tent (*tent, axis_limit, axis_triple_distances);
+-    for (auto t : solutions)
++    rebase_tent_result_t solutions = rebase_tent (*tent, axis_limit, axis_triple_distances);
++    for (auto &t : solutions)
+     {
+       tuple_delta_t new_var = *this;
+       if (t.second == Triple ())
+@@ -600,7 +396,9 @@ struct tuple_delta_t
+                                  const hb_map_t& axes_old_index_tag_map,
+                                  const hb_hashmap_t*, unsigned>* shared_tuples_idx_map)
+   {
+-    if (!compiled_deltas) return false;
++    /* compiled_deltas could be empty after iup delta optimization, we can skip
++     * compiling this tuple and return true */
++    if (!compiled_deltas) return true;
+ 
+     unsigned cur_axis_count = axes_index_map.get_population ();
+     /* allocate enough memory: 1 peak + 2 intermediate coords + fixed header size */
+@@ -714,37 +512,42 @@ struct tuple_delta_t
+   }
+ 
+   bool compile_deltas ()
++  { return compile_deltas (indices, deltas_x, deltas_y, compiled_deltas); }
++
++  static bool compile_deltas (hb_array_t point_indices,
++                              hb_array_t x_deltas,
++                              hb_array_t y_deltas,
++                              hb_vector_t &compiled_deltas /* OUT */)
+   {
+     hb_vector_t rounded_deltas;
+-    if (unlikely (!rounded_deltas.alloc (indices.length)))
++    if (unlikely (!rounded_deltas.alloc (point_indices.length)))
+       return false;
+ 
+-    for (unsigned i = 0; i < indices.length; i++)
++    for (unsigned i = 0; i < point_indices.length; i++)
+     {
+-      if (!indices[i]) continue;
+-      int rounded_delta = (int) roundf (deltas_x[i]);
++      if (!point_indices[i]) continue;
++      int rounded_delta = (int) roundf (x_deltas.arrayZ[i]);
+       rounded_deltas.push (rounded_delta);
+     }
+ 
+-    if (!rounded_deltas) return false;
+-    /* allocate enough memories 3 * num_deltas */
+-    unsigned alloc_len = 3 * rounded_deltas.length;
+-    if (deltas_y)
++    if (!rounded_deltas) return true;
++    /* allocate enough memories 5 * num_deltas */
++    unsigned alloc_len = 5 * rounded_deltas.length;
++    if (y_deltas)
+       alloc_len *= 2;
+ 
+     if (unlikely (!compiled_deltas.resize (alloc_len))) return false;
+ 
+-    unsigned i = 0;
+-    unsigned encoded_len = encode_delta_run (i, compiled_deltas.as_array (), rounded_deltas);
++    unsigned encoded_len = compile_deltas (compiled_deltas, rounded_deltas);
+ 
+-    if (deltas_y)
++    if (y_deltas)
+     {
+-      /* reuse the rounded_deltas vector, check that deltas_y have the same num of deltas as deltas_x */
++      /* reuse the rounded_deltas vector, check that y_deltas have the same num of deltas as x_deltas */
+       unsigned j = 0;
+-      for (unsigned idx = 0; idx < indices.length; idx++)
++      for (unsigned idx = 0; idx < point_indices.length; idx++)
+       {
+-        if (!indices[idx]) continue;
+-        int rounded_delta = (int) roundf (deltas_y[idx]);
++        if (!point_indices[idx]) continue;
++        int rounded_delta = (int) roundf (y_deltas.arrayZ[idx]);
+ 
+         if (j >= rounded_deltas.length) return false;
+ 
+@@ -752,174 +555,15 @@ struct tuple_delta_t
+       }
+ 
+       if (j != rounded_deltas.length) return false;
+-      /* reset i because we reuse rounded_deltas for deltas_y */
+-      i = 0;
+-      encoded_len += encode_delta_run (i, compiled_deltas.as_array ().sub_array (encoded_len), rounded_deltas);
++      encoded_len += compile_deltas (compiled_deltas.as_array ().sub_array (encoded_len), rounded_deltas);
+     }
+     return compiled_deltas.resize (encoded_len);
+   }
+ 
+-  unsigned encode_delta_run (unsigned& i,
+-                             hb_array_t encoded_bytes,
+-                             const hb_vector_t& deltas) const
+-  {
+-    unsigned num_deltas = deltas.length;
+-    unsigned encoded_len = 0;
+-    while (i < num_deltas)
+-    {
+-      int val = deltas[i];
+-      if (val == 0)
+-        encoded_len += encode_delta_run_as_zeroes (i, encoded_bytes.sub_array (encoded_len), deltas);
+-      else if (val >= -128 && val <= 127)
+-        encoded_len += encode_delta_run_as_bytes (i, encoded_bytes.sub_array (encoded_len), deltas);
+-      else
+-        encoded_len += encode_delta_run_as_words (i, encoded_bytes.sub_array (encoded_len), deltas);
+-    }
+-    return encoded_len;
+-  }
+-
+-  unsigned encode_delta_run_as_zeroes (unsigned& i,
+-                                       hb_array_t encoded_bytes,
+-                                       const hb_vector_t& deltas) const
+-  {
+-    unsigned num_deltas = deltas.length;
+-    unsigned run_length = 0;
+-    auto it = encoded_bytes.iter ();
+-    unsigned encoded_len = 0;
+-    while (i < num_deltas && deltas[i] == 0)
+-    {
+-      i++;
+-      run_length++;
+-    }
+-
+-    while (run_length >= 64)
+-    {
+-      *it++ = char (DELTAS_ARE_ZERO | 63);
+-      run_length -= 64;
+-      encoded_len++;
+-    }
+-
+-    if (run_length)
+-    {
+-      *it++ = char (DELTAS_ARE_ZERO | (run_length - 1));
+-      encoded_len++;
+-    }
+-    return encoded_len;
+-  }
+-
+-  unsigned encode_delta_run_as_bytes (unsigned &i,
+-                                      hb_array_t encoded_bytes,
+-                                      const hb_vector_t& deltas) const
+-  {
+-    unsigned start = i;
+-    unsigned num_deltas = deltas.length;
+-    while (i < num_deltas)
+-    {
+-      int val = deltas[i];
+-      if (val > 127 || val < -128)
+-        break;
+-
+-      /* from fonttools: if there're 2 or more zeros in a sequence,
+-       * it is better to start a new run to save bytes. */
+-      if (val == 0 && i + 1 < num_deltas && deltas[i+1] == 0)
+-        break;
+-
+-      i++;
+-    }
+-    unsigned run_length = i - start;
+-
+-    unsigned encoded_len = 0;
+-    auto it = encoded_bytes.iter ();
+-
+-    while (run_length >= 64)
+-    {
+-      *it++ = 63;
+-      encoded_len++;
+-
+-      for (unsigned j = 0; j < 64; j++)
+-      {
+-        *it++ = static_cast (deltas[start + j]);
+-        encoded_len++;
+-      }
+-
+-      start += 64;
+-      run_length -= 64;
+-    }
+-
+-    if (run_length)
+-    {
+-      *it++ = run_length - 1;
+-      encoded_len++;
+-
+-      while (start < i)
+-      {
+-        *it++ = static_cast (deltas[start++]);
+-        encoded_len++;
+-      }
+-    }
+-
+-    return encoded_len;
+-  }
+-
+-  unsigned encode_delta_run_as_words (unsigned &i,
+-                                      hb_array_t encoded_bytes,
+-                                      const hb_vector_t& deltas) const
++  static unsigned compile_deltas (hb_array_t encoded_bytes,
++                                  hb_array_t deltas)
+   {
+-    unsigned start = i;
+-    unsigned num_deltas = deltas.length;
+-    while (i < num_deltas)
+-    {
+-      int val = deltas[i];
+-
+-      /* start a new run for a single zero value*/
+-      if (val == 0) break;
+-
+-      /* from fonttools: continue word-encoded run if there's only one
+-       * single value in the range [-128, 127] because it is more compact.
+-       * Only start a new run when there're 2 continuous such values. */
+-      if (val >= -128 && val <= 127 &&
+-          i + 1 < num_deltas &&
+-          deltas[i+1] >= -128 && deltas[i+1] <= 127)
+-        break;
+-
+-      i++;
+-    }
+-
+-    unsigned run_length = i - start;
+-    auto it = encoded_bytes.iter ();
+-    unsigned encoded_len = 0;
+-    while (run_length >= 64)
+-    {
+-      *it++ = (DELTAS_ARE_WORDS | 63);
+-      encoded_len++;
+-
+-      for (unsigned j = 0; j < 64; j++)
+-      {
+-        int16_t delta_val = deltas[start + j];
+-        *it++ = static_cast (delta_val >> 8);
+-        *it++ = static_cast (delta_val & 0xFF);
+-
+-        encoded_len += 2;
+-      }
+-
+-      start += 64;
+-      run_length -= 64;
+-    }
+-
+-    if (run_length)
+-    {
+-      *it++ = (DELTAS_ARE_WORDS | (run_length - 1));
+-      encoded_len++;
+-      while (start < i)
+-      {
+-        int16_t delta_val = deltas[start++];
+-        *it++ = static_cast (delta_val >> 8);
+-        *it++ = static_cast (delta_val & 0xFF);
+-
+-        encoded_len += 2;
+-      }
+-    }
+-    return encoded_len;
++    return TupleValues::compile (deltas, encoded_bytes);
+   }
+ 
+   bool calc_inferred_deltas (const contour_point_vector_t& orig_points)
+@@ -982,10 +626,14 @@ struct tuple_delta_t
+         {
+           i = next_index (i, start_point, end_point);
+           if (i == next) break;
+-          deltas_x.arrayZ[i] = infer_delta (orig_points.arrayZ[i].x, orig_points.arrayZ[prev].x, orig_points.arrayZ[next].x,
+-                                            deltas_x.arrayZ[prev], deltas_x.arrayZ[next]);
+-          deltas_y.arrayZ[i] = infer_delta (orig_points.arrayZ[i].y, orig_points.arrayZ[prev].y, orig_points.arrayZ[next].y,
+-                                            deltas_y.arrayZ[prev], deltas_y.arrayZ[next]);
++          deltas_x.arrayZ[i] = infer_delta ((double) orig_points.arrayZ[i].x,
++                                            (double) orig_points.arrayZ[prev].x,
++                                            (double) orig_points.arrayZ[next].x,
++                                            (double) deltas_x.arrayZ[prev], (double) deltas_x.arrayZ[next]);
++          deltas_y.arrayZ[i] = infer_delta ((double) orig_points.arrayZ[i].y,
++                                            (double) orig_points.arrayZ[prev].y,
++                                            (double) orig_points.arrayZ[next].y,
++                                            (double) deltas_y.arrayZ[prev], (double) deltas_y.arrayZ[next]);
+           inferred_idxes.add (i);
+           if (--unref_count == 0) goto no_more_gaps;
+         }
+@@ -1002,8 +650,8 @@ struct tuple_delta_t
+       {
+         if (!inferred_idxes.has (i))
+         {
+-          deltas_x.arrayZ[i] = 0.f;
+-          deltas_y.arrayZ[i] = 0.f;
++          deltas_x.arrayZ[i] = 0.0;
++          deltas_y.arrayZ[i] = 0.0;
+         }
+         indices[i] = true;
+       }
+@@ -1011,16 +659,181 @@ struct tuple_delta_t
+     return true;
+   }
+ 
+-  static float infer_delta (float target_val, float prev_val, float next_val, float prev_delta, float next_delta)
++  bool optimize (const contour_point_vector_t& contour_points,
++                 bool is_composite,
++                 double tolerance = 0.5 + 1e-10)
++  {
++    unsigned count = contour_points.length;
++    if (deltas_x.length != count ||
++        deltas_y.length != count)
++      return false;
++
++    hb_vector_t opt_indices;
++    hb_vector_t rounded_x_deltas, rounded_y_deltas;
++
++    if (unlikely (!rounded_x_deltas.alloc (count) ||
++                  !rounded_y_deltas.alloc (count)))
++      return false;
++
++    for (unsigned i = 0; i < count; i++)
++    {
++      int rounded_x_delta = (int) roundf (deltas_x.arrayZ[i]);
++      int rounded_y_delta = (int) roundf (deltas_y.arrayZ[i]);
++      rounded_x_deltas.push (rounded_x_delta);
++      rounded_y_deltas.push (rounded_y_delta);
++    }
++
++    if (!iup_delta_optimize (contour_points, rounded_x_deltas, rounded_y_deltas, opt_indices, tolerance))
++      return false;
++
++    unsigned ref_count = 0;
++    for (bool ref_flag : opt_indices)
++       ref_count += ref_flag;
++
++    if (ref_count == count) return true;
++
++    hb_vector_t opt_deltas_x, opt_deltas_y;
++    bool is_comp_glyph_wo_deltas = (is_composite && ref_count == 0);
++    if (is_comp_glyph_wo_deltas)
++    {
++      if (unlikely (!opt_deltas_x.resize (count) ||
++                    !opt_deltas_y.resize (count)))
++        return false;
++
++      opt_indices.arrayZ[0] = true;
++      for (unsigned i = 1; i < count; i++)
++        opt_indices.arrayZ[i] = false;
++    }
++
++    hb_vector_t opt_point_data;
++    if (!compile_point_set (opt_indices, opt_point_data))
++      return false;
++    hb_vector_t opt_deltas_data;
++    if (!compile_deltas (opt_indices,
++                         is_comp_glyph_wo_deltas ? opt_deltas_x : deltas_x,
++                         is_comp_glyph_wo_deltas ? opt_deltas_y : deltas_y,
++                         opt_deltas_data))
++      return false;
++
++    hb_vector_t point_data;
++    if (!compile_point_set (indices, point_data))
++      return false;
++    hb_vector_t deltas_data;
++    if (!compile_deltas (indices, deltas_x, deltas_y, deltas_data))
++      return false;
++
++    if (opt_point_data.length + opt_deltas_data.length < point_data.length + deltas_data.length)
++    {
++      indices.fini ();
++      indices = std::move (opt_indices);
++
++      if (is_comp_glyph_wo_deltas)
++      {
++        deltas_x.fini ();
++        deltas_x = std::move (opt_deltas_x);
++
++        deltas_y.fini ();
++        deltas_y = std::move (opt_deltas_y);
++      }
++    }
++    return !indices.in_error () && !deltas_x.in_error () && !deltas_y.in_error ();
++  }
++
++  static bool compile_point_set (const hb_vector_t &point_indices,
++                                 hb_vector_t& compiled_points /* OUT */)
++  {
++    unsigned num_points = 0;
++    for (bool i : point_indices)
++      if (i) num_points++;
++
++    /* when iup optimization is enabled, num of referenced points could be 0 */
++    if (!num_points) return true;
++
++    unsigned indices_length = point_indices.length;
++    /* If the points set consists of all points in the glyph, it's encoded with a
++     * single zero byte */
++    if (num_points == indices_length)
++      return compiled_points.resize (1);
++
++    /* allocate enough memories: 2 bytes for count + 3 bytes for each point */
++    unsigned num_bytes = 2 + 3 *num_points;
++    if (unlikely (!compiled_points.resize (num_bytes, false)))
++      return false;
++
++    unsigned pos = 0;
++    /* binary data starts with the total number of reference points */
++    if (num_points < 0x80)
++      compiled_points.arrayZ[pos++] = num_points;
++    else
++    {
++      compiled_points.arrayZ[pos++] = ((num_points >> 8) | 0x80);
++      compiled_points.arrayZ[pos++] = num_points & 0xFF;
++    }
++
++    const unsigned max_run_length = 0x7F;
++    unsigned i = 0;
++    unsigned last_value = 0;
++    unsigned num_encoded = 0;
++    while (i < indices_length && num_encoded < num_points)
++    {
++      unsigned run_length = 0;
++      unsigned header_pos = pos;
++      compiled_points.arrayZ[pos++] = 0;
++
++      bool use_byte_encoding = false;
++      bool new_run = true;
++      while (i < indices_length && num_encoded < num_points &&
++             run_length <= max_run_length)
++      {
++        // find out next referenced point index
++        while (i < indices_length && !point_indices[i])
++          i++;
++
++        if (i >= indices_length) break;
++
++        unsigned cur_value = i;
++        unsigned delta = cur_value - last_value;
++
++        if (new_run)
++        {
++          use_byte_encoding = (delta <= 0xFF);
++          new_run = false;
++        }
++
++        if (use_byte_encoding && delta > 0xFF)
++          break;
++
++        if (use_byte_encoding)
++          compiled_points.arrayZ[pos++] = delta;
++        else
++        {
++          compiled_points.arrayZ[pos++] = delta >> 8;
++          compiled_points.arrayZ[pos++] = delta & 0xFF;
++        }
++        i++;
++        last_value = cur_value;
++        run_length++;
++        num_encoded++;
++      }
++
++      if (use_byte_encoding)
++        compiled_points.arrayZ[header_pos] = run_length - 1;
++      else
++        compiled_points.arrayZ[header_pos] = (run_length - 1) | 0x80;
++    }
++    return compiled_points.resize (pos, false);
++  }
++
++  static double infer_delta (double target_val, double prev_val, double next_val, double prev_delta, double next_delta)
+   {
+     if (prev_val == next_val)
+-      return (prev_delta == next_delta) ? prev_delta : 0.f;
++      return (prev_delta == next_delta) ? prev_delta : 0.0;
+     else if (target_val <= hb_min (prev_val, next_val))
+       return (prev_val < next_val) ? prev_delta : next_delta;
+     else if (target_val >= hb_max (prev_val, next_val))
+       return (prev_val > next_val) ? prev_delta : next_delta;
+ 
+-    float r = (target_val - prev_val) / (next_val - prev_val);
++    double r = (target_val - prev_val) / (next_val - prev_val);
+     return prev_delta + r * (next_delta - prev_delta);
+   }
+ 
+@@ -1028,6 +841,7 @@ struct tuple_delta_t
+   { return (i >= end) ? start : (i + 1); }
+ };
+ 
++template 
+ struct TupleVariationData
+ {
+   bool sanitize (hb_sanitize_context_t *c) const
+@@ -1062,19 +876,22 @@ struct TupleVariationData
+ 
+     private:
+     /* referenced point set->compiled point data map */
+-    hb_hashmap_t*, hb_bytes_t> point_data_map;
++    hb_hashmap_t*, hb_vector_t> point_data_map;
+     /* referenced point set-> count map, used in finding shared points */
+     hb_hashmap_t*, unsigned> point_set_count_map;
+ 
+     /* empty for non-gvar tuples.
+-     * shared_points_bytes is just a copy of some value in the point_data_map,
++     * shared_points_bytes is a pointer to some value in the point_data_map,
+      * which will be freed during map destruction. Save it for serialization, so
+      * no need to do find_shared_points () again */
+-    hb_bytes_t shared_points_bytes;
++    hb_vector_t *shared_points_bytes = nullptr;
+ 
+-    /* total compiled byte size as TupleVariationData format, initialized to its
+-     * min_size: 4 */
+-    unsigned compiled_byte_size = 4;
++    /* total compiled byte size as TupleVariationData format, initialized to 0 */
++    unsigned compiled_byte_size = 0;
++    bool needs_padding = false;
++
++    /* for gvar iup delta optimization: whether this is a composite glyph */
++    bool is_composite = false;
+ 
+     public:
+     tuple_variations_t () = default;
+@@ -1082,21 +899,18 @@ struct TupleVariationData
+     tuple_variations_t& operator=(const tuple_variations_t&) = delete;
+     tuple_variations_t (tuple_variations_t&&) = default;
+     tuple_variations_t& operator=(tuple_variations_t&&) = default;
+-    ~tuple_variations_t () { fini (); }
+-    void fini ()
+-    {
+-      for (auto _ : point_data_map.values ())
+-        _.fini ();
+-
+-      point_set_count_map.fini ();
+-      tuple_vars.fini ();
+-    }
++    ~tuple_variations_t () = default;
+ 
+     explicit operator bool () const { return bool (tuple_vars); }
+     unsigned get_var_count () const
+     {
+-      unsigned count = tuple_vars.length;
+-      if (shared_points_bytes.length)
++      unsigned count = 0;
++      /* when iup delta opt is enabled, compiled_deltas could be empty and we
++       * should skip this tuple */
++      for (auto& tuple: tuple_vars)
++        if (tuple.compiled_deltas) count++;
++
++      if (shared_points_bytes && shared_points_bytes->length)
+         count |= TupleVarCount::SharedPointNumbers;
+       return count;
+     }
+@@ -1110,26 +924,27 @@ struct TupleVariationData
+                                      bool is_gvar,
+                                      const hb_map_t *axes_old_index_tag_map,
+                                      const hb_vector_t &shared_indices,
+-                                     const hb_array_t shared_tuples)
++                                     const hb_array_t shared_tuples,
++                                     bool is_composite_glyph)
+     {
+       do
+       {
+         const HBUINT8 *p = iterator.get_serialized_data ();
+         unsigned int length = iterator.current_tuple->get_data_size ();
+         if (unlikely (!iterator.var_data_bytes.check_range (p, length)))
+-        { fini (); return false; }
++          return false;
+ 
+         hb_hashmap_t axis_tuples;
+         if (!iterator.current_tuple->unpack_axis_tuples (iterator.get_axis_count (), shared_tuples, axes_old_index_tag_map, axis_tuples)
+             || axis_tuples.is_empty ())
+-        { fini (); return false; }
++          return false;
+ 
+         hb_vector_t private_indices;
+         bool has_private_points = iterator.current_tuple->has_private_points ();
+         const HBUINT8 *end = p + length;
+         if (has_private_points &&
+-            !TupleVariationData::unpack_points (p, private_indices, end))
+-        { fini (); return false; }
++            !TupleVariationData::decompile_points (p, private_indices, end))
++          return false;
+ 
+         const hb_vector_t &indices = has_private_points ? private_indices : shared_indices;
+         bool apply_to_all = (indices.length == 0);
+@@ -1138,43 +953,46 @@ struct TupleVariationData
+         hb_vector_t deltas_x;
+ 
+         if (unlikely (!deltas_x.resize (num_deltas, false) ||
+-                      !TupleVariationData::unpack_deltas (p, deltas_x, end)))
+-        { fini (); return false; }
++                      !TupleVariationData::decompile_deltas (p, deltas_x, end)))
++          return false;
+ 
+         hb_vector_t deltas_y;
+         if (is_gvar)
+         {
+           if (unlikely (!deltas_y.resize (num_deltas, false) ||
+-                        !TupleVariationData::unpack_deltas (p, deltas_y, end)))
+-          { fini (); return false; }
++                        !TupleVariationData::decompile_deltas (p, deltas_y, end)))
++            return false;
+         }
+ 
+         tuple_delta_t var;
+         var.axis_tuples = std::move (axis_tuples);
+         if (unlikely (!var.indices.resize (point_count) ||
+                       !var.deltas_x.resize (point_count, false)))
+-        { fini (); return false; }
++          return false;
+ 
+         if (is_gvar && unlikely (!var.deltas_y.resize (point_count, false)))
+-        { fini (); return false; }
++          return false;
+ 
+         for (unsigned i = 0; i < num_deltas; i++)
+         {
+           unsigned idx = apply_to_all ? i : indices[i];
+           if (idx >= point_count) continue;
+           var.indices[idx] = true;
+-          var.deltas_x[idx] = static_cast (deltas_x[i]);
++          var.deltas_x[idx] = deltas_x[i];
+           if (is_gvar)
+-            var.deltas_y[idx] = static_cast (deltas_y[i]);
++            var.deltas_y[idx] = deltas_y[i];
+         }
+         tuple_vars.push (std::move (var));
+       } while (iterator.move_to_next ());
++
++      is_composite = is_composite_glyph;
+       return true;
+     }
+ 
+     bool create_from_item_var_data (const VarData &var_data,
+                                     const hb_vector_t>& regions,
+                                     const hb_map_t& axes_old_index_tag_map,
++                                    unsigned& item_count,
+                                     const hb_inc_bimap_t* inner_map = nullptr)
+     {
+       /* NULL offset, to keep original varidx valid, just return */
+@@ -1184,7 +1002,8 @@ struct TupleVariationData
+       unsigned num_regions = var_data.get_region_index_count ();
+       if (!tuple_vars.alloc (num_regions)) return false;
+ 
+-      unsigned item_count = inner_map ? inner_map->get_population () : var_data.get_item_count ();
++      item_count = inner_map ? inner_map->get_population () : var_data.get_item_count ();
++      if (!item_count) return true;
+       unsigned row_size = var_data.get_row_size ();
+       const HBUINT8 *delta_bytes = var_data.get_delta_bytes ();
+ 
+@@ -1237,7 +1056,7 @@ struct TupleVariationData
+         Triple *axis_limit;
+         if (!normalized_axes_location.has (axis_tag, &axis_limit))
+           return false;
+-        TripleDistances axis_triple_distances{1.f, 1.f};
++        TripleDistances axis_triple_distances{1.0, 1.0};
+         if (axes_triple_distances.has (axis_tag))
+           axis_triple_distances = axes_triple_distances.get (axis_tag);
+ 
+@@ -1250,7 +1069,7 @@ struct TupleVariationData
+           unsigned new_len = new_vars.length + out.length;
+ 
+           if (unlikely (!new_vars.alloc (new_len, false)))
+-          { fini (); return false;}
++            return false;
+ 
+           for (unsigned i = 0; i < out.length; i++)
+             new_vars.push (std::move (out[i]));
+@@ -1261,8 +1080,9 @@ struct TupleVariationData
+       return true;
+     }
+ 
+-    /* merge tuple variations with overlapping tents */
+-    void merge_tuple_variations ()
++    /* merge tuple variations with overlapping tents, if iup delta optimization
++     * is enabled, add default deltas to contour_points */
++    bool merge_tuple_variations (contour_point_vector_t* contour_points = nullptr)
+     {
+       hb_vector_t new_vars;
+       hb_hashmap_t*, unsigned> m;
+@@ -1270,7 +1090,15 @@ struct TupleVariationData
+       for (const tuple_delta_t& var : tuple_vars)
+       {
+         /* if all axes are pinned, drop the tuple variation */
+-        if (var.axis_tuples.is_empty ()) continue;
++        if (var.axis_tuples.is_empty ())
++        {
++          /* if iup_delta_optimize is enabled, add deltas to contour coords */
++          if (contour_points && !contour_points->add_deltas (var.deltas_x,
++                                                             var.deltas_y,
++                                                             var.indices))
++            return false;
++          continue;
++        }
+ 
+         unsigned *idx;
+         if (m.has (&(var.axis_tuples), &idx))
+@@ -1280,98 +1108,14 @@ struct TupleVariationData
+         else
+         {
+           new_vars.push (var);
+-          m.set (&(var.axis_tuples), i);
++          if (!m.set (&(var.axis_tuples), i))
++            return false;
+           i++;
+         }
+       }
+       tuple_vars.fini ();
+       tuple_vars = std::move (new_vars);
+-    }
+-
+-    hb_bytes_t compile_point_set (const hb_vector_t &point_indices)
+-    {
+-      unsigned num_points = 0;
+-      for (bool i : point_indices)
+-        if (i) num_points++;
+-
+-      unsigned indices_length = point_indices.length;
+-      /* If the points set consists of all points in the glyph, it's encoded with a
+-       * single zero byte */
+-      if (num_points == indices_length)
+-      {
+-        char *p = (char *) hb_calloc (1, sizeof (char));
+-        if (unlikely (!p)) return hb_bytes_t ();
+-
+-        return hb_bytes_t (p, 1);
+-      }
+-
+-      /* allocate enough memories: 2 bytes for count + 3 bytes for each point */
+-      unsigned num_bytes = 2 + 3 *num_points;
+-      char *p = (char *) hb_calloc (num_bytes, sizeof (char));
+-      if (unlikely (!p)) return hb_bytes_t ();
+-
+-      unsigned pos = 0;
+-      /* binary data starts with the total number of reference points */
+-      if (num_points < 0x80)
+-        p[pos++] = num_points;
+-      else
+-      {
+-        p[pos++] = ((num_points >> 8) | 0x80);
+-        p[pos++] = num_points & 0xFF;
+-      }
+-
+-      const unsigned max_run_length = 0x7F;
+-      unsigned i = 0;
+-      unsigned last_value = 0;
+-      unsigned num_encoded = 0;
+-      while (i < indices_length && num_encoded < num_points)
+-      {
+-        unsigned run_length = 0;
+-        unsigned header_pos = pos;
+-        p[pos++] = 0;
+-
+-        bool use_byte_encoding = false;
+-        bool new_run = true;
+-        while (i < indices_length && num_encoded < num_points &&
+-               run_length <= max_run_length)
+-        {
+-          // find out next referenced point index
+-          while (i < indices_length && !point_indices[i])
+-            i++;
+-
+-          if (i >= indices_length) break;
+-
+-          unsigned cur_value = i;
+-          unsigned delta = cur_value - last_value;
+-
+-          if (new_run)
+-          {
+-            use_byte_encoding = (delta <= 0xFF);
+-            new_run = false;
+-          }
+-
+-          if (use_byte_encoding && delta > 0xFF)
+-            break;
+-
+-          if (use_byte_encoding)
+-            p[pos++] = delta;
+-          else
+-          {
+-            p[pos++] = delta >> 8;
+-            p[pos++] = delta & 0xFF;
+-          }
+-          i++;
+-          last_value = cur_value;
+-          run_length++;
+-          num_encoded++;
+-        }
+-
+-        if (use_byte_encoding)
+-          p[header_pos] = run_length - 1;
+-        else
+-          p[header_pos] = (run_length - 1) | 0x80;
+-      }
+-      return hb_bytes_t (p, pos);
++      return true;
+     }
+ 
+     /* compile all point set and store byte data in a point_set->hb_bytes_t hashmap,
+@@ -1391,11 +1135,11 @@ struct TupleVariationData
+           continue;
+         }
+ 
+-        hb_bytes_t compiled_data = compile_point_set (*points_set);
+-        if (unlikely (compiled_data == hb_bytes_t ()))
++        hb_vector_t compiled_point_data;
++        if (!tuple_delta_t::compile_point_set (*points_set, compiled_point_data))
+           return false;
+ 
+-        if (!point_data_map.set (points_set, compiled_data) ||
++        if (!point_data_map.set (points_set, std::move (compiled_point_data)) ||
+             !point_set_count_map.set (points_set, 1))
+           return false;
+       }
+@@ -1403,31 +1147,33 @@ struct TupleVariationData
+     }
+ 
+     /* find shared points set which saves most bytes */
+-    hb_bytes_t find_shared_points ()
++    void find_shared_points ()
+     {
+       unsigned max_saved_bytes = 0;
+-      hb_bytes_t res{};
+ 
+-      for (const auto& _ : point_data_map.iter ())
++      for (const auto& _ : point_data_map.iter_ref ())
+       {
+         const hb_vector_t* points_set = _.first;
+         unsigned data_length = _.second.length;
++        if (!data_length) continue;
+         unsigned *count;
+         if (unlikely (!point_set_count_map.has (points_set, &count) ||
+                       *count <= 1))
+-          return hb_bytes_t ();
++        {
++          shared_points_bytes = nullptr;
++          return;
++        }
+ 
+         unsigned saved_bytes = data_length * ((*count) -1);
+         if (saved_bytes > max_saved_bytes)
+         {
+           max_saved_bytes = saved_bytes;
+-          res = _.second;
++          shared_points_bytes = &(_.second);
+         }
+       }
+-      return res;
+     }
+ 
+-    bool calc_inferred_deltas (contour_point_vector_t& contour_points)
++    bool calc_inferred_deltas (const contour_point_vector_t& contour_points)
+     {
+       for (tuple_delta_t& var : tuple_vars)
+         if (!var.calc_inferred_deltas (contour_points))
+@@ -1436,10 +1182,21 @@ struct TupleVariationData
+       return true;
+     }
+ 
++    bool iup_optimize (const contour_point_vector_t& contour_points)
++    {
++      for (tuple_delta_t& var : tuple_vars)
++      {
++        if (!var.optimize (contour_points, is_composite))
++          return false;
++      }
++      return true;
++    }
++
+     public:
+     bool instantiate (const hb_hashmap_t& normalized_axes_location,
+                       const hb_hashmap_t& axes_triple_distances,
+-                      contour_point_vector_t* contour_points = nullptr)
++                      contour_point_vector_t* contour_points = nullptr,
++                      bool optimize = false)
+     {
+       if (!tuple_vars) return true;
+       if (!change_tuple_variations_axis_limits (normalized_axes_location, axes_triple_distances))
+@@ -1449,41 +1206,70 @@ struct TupleVariationData
+         if (!calc_inferred_deltas (*contour_points))
+           return false;
+ 
+-      merge_tuple_variations ();
++      /* if iup delta opt is on, contour_points can't be null */
++      if (optimize && !contour_points)
++        return false;
++
++      if (!merge_tuple_variations (optimize ? contour_points : nullptr))
++        return false;
++
++      if (optimize && !iup_optimize (*contour_points)) return false;
+       return !tuple_vars.in_error ();
+     }
+ 
+     bool compile_bytes (const hb_map_t& axes_index_map,
+                         const hb_map_t& axes_old_index_tag_map,
+                         bool use_shared_points,
++                        bool is_gvar = false,
+                         const hb_hashmap_t*, unsigned>* shared_tuples_idx_map = nullptr)
+     {
++      // return true for empty glyph
++      if (!tuple_vars)
++        return true;
++
+       // compile points set and store data in hashmap
+       if (!compile_all_point_sets ())
+         return false;
+ 
++      /* total compiled byte size as TupleVariationData format, initialized to its
++       * min_size: 4 */
++      compiled_byte_size += 4;
++
+       if (use_shared_points)
+       {
+-        shared_points_bytes = find_shared_points ();
+-        compiled_byte_size += shared_points_bytes.length;
++        find_shared_points ();
++        if (shared_points_bytes)
++          compiled_byte_size += shared_points_bytes->length;
+       }
+       // compile delta and tuple var header for each tuple variation
+       for (auto& tuple: tuple_vars)
+       {
+         const hb_vector_t* points_set = &(tuple.indices);
+-        hb_bytes_t *points_data;
++        hb_vector_t *points_data;
+         if (unlikely (!point_data_map.has (points_set, &points_data)))
+           return false;
+ 
++        /* when iup optimization is enabled, num of referenced points could be 0
++         * and thus the compiled points bytes is empty, we should skip compiling
++         * this tuple */
++        if (!points_data->length)
++          continue;
+         if (!tuple.compile_deltas ())
+           return false;
+ 
+-        unsigned points_data_length = (*points_data != shared_points_bytes) ? points_data->length : 0;
++        unsigned points_data_length = (points_data != shared_points_bytes) ? points_data->length : 0;
+         if (!tuple.compile_tuple_var_header (axes_index_map, points_data_length, axes_old_index_tag_map,
+                                              shared_tuples_idx_map))
+           return false;
+         compiled_byte_size += tuple.compiled_tuple_header.length + points_data_length + tuple.compiled_deltas.length;
+       }
++
++      if (is_gvar && (compiled_byte_size % 2))
++      {
++        needs_padding = true;
++        compiled_byte_size += 1;
++      }
++
+       return true;
+     }
+ 
+@@ -1502,25 +1288,31 @@ struct TupleVariationData
+     bool serialize_var_data (hb_serialize_context_t *c, bool is_gvar) const
+     {
+       TRACE_SERIALIZE (this);
+-      if (is_gvar)
+-        shared_points_bytes.copy (c);
++      if (is_gvar && shared_points_bytes)
++      {
++        hb_ubytes_t s (shared_points_bytes->arrayZ, shared_points_bytes->length);
++        s.copy (c);
++      }
+ 
+       for (const auto& tuple: tuple_vars)
+       {
+         const hb_vector_t* points_set = &(tuple.indices);
+-        hb_bytes_t *point_data;
++        hb_vector_t *point_data;
+         if (!point_data_map.has (points_set, &point_data))
+           return_trace (false);
+ 
+-        if (!is_gvar || *point_data != shared_points_bytes)
+-          point_data->copy (c);
++        if (!is_gvar || point_data != shared_points_bytes)
++        {
++          hb_ubytes_t s (point_data->arrayZ, point_data->length);
++          s.copy (c);
++        }
+ 
+         tuple.compiled_deltas.as_array ().copy (c);
+         if (c->in_error ()) return_trace (false);
+       }
+ 
+       /* padding for gvar */
+-      if (is_gvar && (compiled_byte_size % 2))
++      if (is_gvar && needs_padding)
+       {
+         HBUINT8 pad;
+         pad = 0;
+@@ -1551,7 +1343,7 @@ struct TupleVariationData
+       {
+         const HBUINT8 *base = &(table_base+var_data->data);
+         const HBUINT8 *p = base;
+-        if (!unpack_points (p, shared_indices, (const HBUINT8 *) (var_data_bytes.arrayZ + var_data_bytes.length))) return false;
++        if (!decompile_points (p, shared_indices, (const HBUINT8 *) (var_data_bytes.arrayZ + var_data_bytes.length))) return false;
+         data_offset = p - base;
+       }
+       return true;
+@@ -1601,9 +1393,9 @@ struct TupleVariationData
+ 
+   bool has_shared_point_numbers () const { return tupleVarCount.has_shared_point_numbers (); }
+ 
+-  static bool unpack_points (const HBUINT8 *&p /* IN/OUT */,
+-                             hb_vector_t &points /* OUT */,
+-                             const HBUINT8 *end)
++  static bool decompile_points (const HBUINT8 *&p /* IN/OUT */,
++                                hb_vector_t &points /* OUT */,
++                                const HBUINT8 *end)
+   {
+     enum packed_point_flag_t
+     {
+@@ -1653,43 +1445,13 @@ struct TupleVariationData
+     return true;
+   }
+ 
+-  static bool unpack_deltas (const HBUINT8 *&p /* IN/OUT */,
+-                             hb_vector_t &deltas /* IN/OUT */,
+-                             const HBUINT8 *end)
++  template 
++  static bool decompile_deltas (const HBUINT8 *&p /* IN/OUT */,
++                                hb_vector_t &deltas /* IN/OUT */,
++                                const HBUINT8 *end,
++                                bool consume_all = false)
+   {
+-    unsigned i = 0;
+-    unsigned count = deltas.length;
+-    while (i < count)
+-    {
+-      if (unlikely (p + 1 > end)) return false;
+-      unsigned control = *p++;
+-      unsigned run_count = (control & DELTA_RUN_COUNT_MASK) + 1;
+-      unsigned stop = i + run_count;
+-      if (unlikely (stop > count)) return false;
+-      if (control & DELTAS_ARE_ZERO)
+-      {
+-        for (; i < stop; i++)
+-          deltas.arrayZ[i] = 0;
+-      }
+-      else if (control & DELTAS_ARE_WORDS)
+-      {
+-        if (unlikely (p + run_count * HBUINT16::static_size > end)) return false;
+-        for (; i < stop; i++)
+-        {
+-          deltas.arrayZ[i] = * (const HBINT16 *) p;
+-          p += HBUINT16::static_size;
+-        }
+-      }
+-      else
+-      {
+-        if (unlikely (p + run_count > end)) return false;
+-        for (; i < stop; i++)
+-        {
+-          deltas.arrayZ[i] = * (const HBINT8 *) p++;
+-        }
+-      }
+-    }
+-    return true;
++    return TupleValues::decompile (p, deltas, end, consume_all);
+   }
+ 
+   bool has_data () const { return tupleVarCount; }
+@@ -1700,13 +1462,15 @@ struct TupleVariationData
+                                    const hb_map_t *axes_old_index_tag_map,
+                                    const hb_vector_t &shared_indices,
+                                    const hb_array_t shared_tuples,
+-                                   tuple_variations_t& tuple_variations /* OUT */) const
++                                   tuple_variations_t& tuple_variations, /* OUT */
++                                   bool is_composite_glyph = false) const
+   {
+     return tuple_variations.create_from_tuple_var_data (iterator, tupleVarCount,
+                                                         point_count, is_gvar,
+                                                         axes_old_index_tag_map,
+                                                         shared_indices,
+-                                                        shared_tuples);
++                                                        shared_tuples,
++                                                        is_composite_glyph);
+   }
+ 
+   bool serialize (hb_serialize_context_t *c,
+@@ -1758,15 +1522,16 @@ struct TupleVariationData
+                                  * low 12 bits are the number of tuple variation tables
+                                  * for this glyph. The number of tuple variation tables
+                                  * can be any number between 1 and 4095. */
+-  Offset16To
++  OffsetTo
+                 data;           /* Offset from the start of the base table
+                                  * to the serialized data. */
+   /* TupleVariationHeader tupleVariationHeaders[] *//* Array of tuple variation headers. */
+   public:
+-  DEFINE_SIZE_MIN (4);
++  DEFINE_SIZE_MIN (2 + OffType::static_size);
+ };
+ 
+-using tuple_variations_t = TupleVariationData::tuple_variations_t;
++// TODO: Move tuple_variations_t to outside of TupleVariationData
++using tuple_variations_t = TupleVariationData::tuple_variations_t;
+ struct item_variations_t
+ {
+   using region_t = const hb_hashmap_t*;
+@@ -1775,6 +1540,14 @@ struct item_variations_t
+    * have the same num of deltas (rows) */
+   hb_vector_t vars;
+ 
++  /* num of retained rows for each subtable, there're 2 cases when var_data is empty:
++   * 1. retained item_count is zero
++   * 2. regions is empty and item_count is non-zero.
++   * when converting to tuples, both will be dropped because the tuple is empty,
++   * however, we need to retain 2. as all-zero rows to keep original varidx
++   * valid, so we need a way to remember the num of rows for each subtable */
++  hb_vector_t var_data_num_rows;
++
+   /* original region list, decompiled from item varstore, used when rebuilding
+    * region list after instantiation */
+   hb_vector_t> orig_region_list;
+@@ -1812,7 +1585,7 @@ struct item_variations_t
+   const hb_map_t& get_varidx_map () const
+   { return varidx_map; }
+ 
+-  bool instantiate (const VariationStore& varStore,
++  bool instantiate (const ItemVariationStore& varStore,
+                     const hb_subset_plan_t *plan,
+                     bool optimize=true,
+                     bool use_no_variation_idx=true,
+@@ -1826,7 +1599,7 @@ struct item_variations_t
+   }
+ 
+   /* keep below APIs public only for unit test: test-item-varstore */
+-  bool create_from_item_varstore (const VariationStore& varStore,
++  bool create_from_item_varstore (const ItemVariationStore& varStore,
+                                   const hb_map_t& axes_old_index_tag_map,
+                                   const hb_array_t  inner_maps = hb_array_t ())
+   {
+@@ -1836,22 +1609,26 @@ struct item_variations_t
+ 
+     unsigned num_var_data = varStore.get_sub_table_count ();
+     if (inner_maps && inner_maps.length != num_var_data) return false;
+-    if (!vars.alloc (num_var_data)) return false;
++    if (!vars.alloc (num_var_data) ||
++        !var_data_num_rows.alloc (num_var_data)) return false;
+ 
+     for (unsigned i = 0; i < num_var_data; i++)
+     {
+       if (inner_maps && !inner_maps.arrayZ[i].get_population ())
+           continue;
+       tuple_variations_t var_data_tuples;
++      unsigned item_count = 0;
+       if (!var_data_tuples.create_from_item_var_data (varStore.get_sub_table (i),
+                                                       orig_region_list,
+                                                       axes_old_index_tag_map,
++                                                      item_count,
+                                                       inner_maps ? &(inner_maps.arrayZ[i]) : nullptr))
+         return false;
+ 
++      var_data_num_rows.push (item_count);
+       vars.push (std::move (var_data_tuples));
+     }
+-    return !vars.in_error ();
++    return !vars.in_error () && !var_data_num_rows.in_error () && vars.length == var_data_num_rows.length;
+   }
+ 
+   bool instantiate_tuple_vars (const hb_hashmap_t& normalized_axes_location,
+@@ -1904,7 +1681,9 @@ struct item_variations_t
+       }
+     }
+ 
+-    if (!all_regions || !all_unique_regions) return false;
++    /* regions are empty means no variation data, return true */
++    if (!all_regions || !all_unique_regions) return true;
++
+     if (!region_list.alloc (all_regions.get_population ()))
+       return false;
+ 
+@@ -1969,16 +1748,13 @@ struct item_variations_t
+ 
+   bool as_item_varstore (bool optimize=true, bool use_no_variation_idx=true)
+   {
+-    if (!region_list) return false;
++    /* return true if no variation data */
++    if (!region_list) return true;
+     unsigned num_cols = region_list.length;
+     /* pre-alloc a 2D vector for all sub_table's VarData rows */
+     unsigned total_rows = 0;
+-    for (unsigned major = 0; major < vars.length; major++)
+-    {
+-      const tuple_variations_t& tuples = vars[major];
+-      /* all tuples in each sub_table should have same num of deltas(num rows) */
+-      total_rows += tuples.tuple_vars[0].deltas_x.length;
+-    }
++    for (unsigned major = 0; major < var_data_num_rows.length; major++)
++      total_rows += var_data_num_rows[major];
+ 
+     if (!delta_rows.resize (total_rows)) return false;
+     /* init all rows to [0]*num_cols */
+@@ -1998,7 +1774,7 @@ struct item_variations_t
+       /* deltas are stored in tuples(column based), convert them back into items
+        * (row based) delta */
+       const tuple_variations_t& tuples = vars[major];
+-      unsigned num_rows = tuples.tuple_vars[0].deltas_x.length;
++      unsigned num_rows = var_data_num_rows[major];
+       for (const tuple_delta_t& tuple: tuples.tuple_vars)
+       {
+         if (tuple.deltas_x.length != num_rows)
+@@ -2223,6 +1999,7 @@ struct item_variations_t
+   }
+ };
+ 
++
+ } /* namespace OT */
+ 
+ 
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-var-cvar-table.hh b/src/java.desktop/share/native/libharfbuzz/hb-ot-var-cvar-table.hh
+index a44a8e999..3dc4ebaeb 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-var-cvar-table.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-var-cvar-table.hh
+@@ -45,11 +45,12 @@ struct cvar
+   {
+     TRACE_SANITIZE (this);
+     return_trace (c->check_struct (this) &&
+-                  version.sanitize (c) && likely (version.major == 1) &&
++                  hb_barrier () &&
++                  likely (version.major == 1) &&
+                   tupleVariationData.sanitize (c));
+   }
+ 
+-  const TupleVariationData* get_tuple_var_data (void) const
++  const TupleVariationData<>* get_tuple_var_data (void) const
+   { return &tupleVariationData; }
+ 
+   bool decompile_tuple_variations (unsigned axis_count,
+@@ -57,12 +58,12 @@ struct cvar
+                                    hb_blob_t *blob,
+                                    bool is_gvar,
+                                    const hb_map_t *axes_old_index_tag_map,
+-                                   TupleVariationData::tuple_variations_t& tuple_variations /* OUT */) const
++                                   TupleVariationData<>::tuple_variations_t& tuple_variations /* OUT */) const
+   {
+     hb_vector_t shared_indices;
+-    TupleVariationData::tuple_iterator_t iterator;
++    TupleVariationData<>::tuple_iterator_t iterator;
+     hb_bytes_t var_data_bytes = blob->as_bytes ().sub_array (4);
+-    if (!TupleVariationData::get_tuple_iterator (var_data_bytes, axis_count, this,
++    if (!TupleVariationData<>::get_tuple_iterator (var_data_bytes, axis_count, this,
+                                                  shared_indices, &iterator))
+       return false;
+ 
+@@ -76,16 +77,16 @@ struct cvar
+   static bool calculate_cvt_deltas (unsigned axis_count,
+                                     hb_array_t coords,
+                                     unsigned num_cvt_item,
+-                                    const TupleVariationData *tuple_var_data,
++                                    const TupleVariationData<> *tuple_var_data,
+                                     const void *base,
+                                     hb_vector_t& cvt_deltas /* OUT */)
+   {
+     if (!coords) return true;
+     hb_vector_t shared_indices;
+-    TupleVariationData::tuple_iterator_t iterator;
++    TupleVariationData<>::tuple_iterator_t iterator;
+     unsigned var_data_length = tuple_var_data->get_size (axis_count);
+     hb_bytes_t var_data_bytes = hb_bytes_t (reinterpret_cast (tuple_var_data), var_data_length);
+-    if (!TupleVariationData::get_tuple_iterator (var_data_bytes, axis_count, base,
++    if (!TupleVariationData<>::get_tuple_iterator (var_data_bytes, axis_count, base,
+                                                  shared_indices, &iterator))
+       return true; /* isn't applied at all */
+ 
+@@ -106,14 +107,14 @@ struct cvar
+ 
+       bool has_private_points = iterator.current_tuple->has_private_points ();
+       if (has_private_points &&
+-          !TupleVariationData::unpack_points (p, private_indices, end))
++          !TupleVariationData<>::decompile_points (p, private_indices, end))
+         return false;
+       const hb_vector_t &indices = has_private_points ? private_indices : shared_indices;
+ 
+       bool apply_to_all = (indices.length == 0);
+       unsigned num_deltas = apply_to_all ? num_cvt_item : indices.length;
+       if (unlikely (!unpacked_deltas.resize (num_deltas, false))) return false;
+-      if (unlikely (!TupleVariationData::unpack_deltas (p, unpacked_deltas, end))) return false;
++      if (unlikely (!TupleVariationData<>::decompile_deltas (p, unpacked_deltas, end))) return false;
+ 
+       for (unsigned int i = 0; i < num_deltas; i++)
+       {
+@@ -128,7 +129,7 @@ struct cvar
+   }
+ 
+   bool serialize (hb_serialize_context_t *c,
+-                  TupleVariationData::tuple_variations_t& tuple_variations) const
++                  TupleVariationData<>::tuple_variations_t& tuple_variations) const
+   {
+     TRACE_SERIALIZE (this);
+     if (!tuple_variations) return_trace (false);
+@@ -143,7 +144,7 @@ struct cvar
+     if (c->plan->all_axes_pinned)
+       return_trace (false);
+ 
+-    OT::TupleVariationData::tuple_variations_t tuple_variations;
++    OT::TupleVariationData<>::tuple_variations_t tuple_variations;
+     unsigned axis_count = c->plan->axes_old_index_tag_map.get_population ();
+ 
+     const hb_tag_t cvt = HB_TAG('c','v','t',' ');
+@@ -168,7 +169,7 @@ struct cvar
+   }
+ 
+   static bool add_cvt_and_apply_deltas (hb_subset_plan_t *plan,
+-                                        const TupleVariationData *tuple_var_data,
++                                        const TupleVariationData<> *tuple_var_data,
+                                         const void *base)
+   {
+     const hb_tag_t cvt = HB_TAG('c','v','t',' ');
+@@ -208,7 +209,7 @@ struct cvar
+   protected:
+   FixedVersion<>version;                /* Version of the CVT variation table
+                                          * initially set to 0x00010000u */
+-  TupleVariationData tupleVariationData; /* TupleVariationDate for cvar table */
++  TupleVariationData<> tupleVariationData; /* TupleVariationDate for cvar table */
+   public:
+   DEFINE_SIZE_MIN (8);
+ };
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-var-fvar-table.hh b/src/java.desktop/share/native/libharfbuzz/hb-ot-var-fvar-table.hh
+index d60c3dbcf..f2725eaa2 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-var-fvar-table.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-var-fvar-table.hh
+@@ -43,7 +43,7 @@ static bool axis_coord_pinned_or_within_axis_range (const hb_array_t(coords[axis_index].to_float ());
+   if (axis_limit.is_point ())
+   {
+     if (axis_limit.minimum != axis_coord)
+@@ -131,6 +131,7 @@ struct InstanceRecord
+   {
+     TRACE_SANITIZE (this);
+     return_trace (c->check_struct (this) &&
++                  hb_barrier () &&
+                   c->check_array (coordinatesZ.arrayZ, axis_count));
+   }
+ 
+@@ -232,7 +233,10 @@ struct AxisRecord
+   {
+     float min, default_, max;
+     get_coordinates (min, default_, max);
+-    return TripleDistances (min, default_, max);
++    return TripleDistances (
++      static_cast(min),
++      static_cast(default_),
++      static_cast(max));
+   }
+ 
+   bool subset (hb_subset_context_t *c) const
+@@ -277,8 +281,10 @@ struct fvar
+   {
+     TRACE_SANITIZE (this);
+     return_trace (version.sanitize (c) &&
++                  hb_barrier () &&
+                   likely (version.major == 1) &&
+                   c->check_struct (this) &&
++                  hb_barrier () &&
+                   axisSize == 20 && /* Assumed in our code. */
+                   instanceSize >= axisCount * 4 + 4 &&
+                   get_axes ().sanitize (c) &&
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-var-gvar-table.hh b/src/java.desktop/share/native/libharfbuzz/hb-ot-var-gvar-table.hh
+index fd32ef03f..c3040187f 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-var-gvar-table.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-var-gvar-table.hh
+@@ -28,6 +28,7 @@
+ #ifndef HB_OT_VAR_GVAR_TABLE_HH
+ #define HB_OT_VAR_GVAR_TABLE_HH
+ 
++#include "hb-decycler.hh"
+ #include "hb-open-type.hh"
+ #include "hb-ot-var-common.hh"
+ 
+@@ -36,15 +37,37 @@
+  * https://docs.microsoft.com/en-us/typography/opentype/spec/gvar
+  */
+ #define HB_OT_TAG_gvar HB_TAG('g','v','a','r')
++#define HB_OT_TAG_GVAR HB_TAG('G','V','A','R')
+ 
+-namespace OT {
++struct hb_glyf_scratch_t
++{
++  // glyf
++  contour_point_vector_t all_points;
++  contour_point_vector_t comp_points;
++  hb_decycler_t decycler;
++
++  // gvar
++  contour_point_vector_t orig_points;
++  hb_vector_t x_deltas;
++  hb_vector_t y_deltas;
++  contour_point_vector_t deltas;
++  hb_vector_t shared_indices;
++  hb_vector_t private_indices;
++
++  // VARC
++  hb_vector_t axisIndices;
++  hb_vector_t axisValues;
++};
+ 
+-struct GlyphVariationData : TupleVariationData
+-{};
++namespace OT {
+ 
++template 
+ struct glyph_variations_t
+ {
+-  using tuple_variations_t = TupleVariationData::tuple_variations_t;
++  // TODO: Move tuple_variations_t to outside of TupleVariationData
++  using tuple_variations_t = typename TupleVariationData::tuple_variations_t;
++  using GlyphVariationData = TupleVariationData;
++
+   hb_vector_t glyph_variations;
+ 
+   hb_vector_t compiled_shared_tuples;
+@@ -72,7 +95,7 @@ struct glyph_variations_t
+                                     const hb_subset_plan_t *plan,
+                                     const hb_hashmap_t& new_gid_var_data_map)
+   {
+-    if (unlikely (!glyph_variations.alloc (plan->new_to_old_gid_list.length, true)))
++    if (unlikely (!glyph_variations.alloc_exact (plan->new_to_old_gid_list.length)))
+       return false;
+ 
+     auto it = hb_iter (plan->new_to_old_gid_list);
+@@ -86,10 +109,11 @@ struct glyph_variations_t
+       hb_bytes_t var_data = new_gid_var_data_map.get (new_gid);
+ 
+       const GlyphVariationData* p = reinterpret_cast (var_data.arrayZ);
+-      hb_vector_t shared_indices;
+-      GlyphVariationData::tuple_iterator_t iterator;
++      typename GlyphVariationData::tuple_iterator_t iterator;
+       tuple_variations_t tuple_vars;
+ 
++      hb_vector_t shared_indices;
++
+       /* in case variation data is empty, push an empty struct into the vector,
+        * keep the vector in sync with the new_to_old_gid_list */
+       if (!var_data || ! p->has_data () || !all_contour_points->length ||
+@@ -101,10 +125,14 @@ struct glyph_variations_t
+         continue;
+       }
+ 
++      bool is_composite_glyph = false;
++      is_composite_glyph = plan->composite_new_gids.has (new_gid);
++
+       if (!p->decompile_tuple_variations (all_contour_points->length, true /* is_gvar */,
+                                           iterator, &(plan->axes_old_index_tag_map),
+                                           shared_indices, shared_tuples,
+-                                          tuple_vars /* OUT */))
++                                          tuple_vars, /* OUT */
++                                          is_composite_glyph))
+         return false;
+       glyph_variations.push (std::move (tuple_vars));
+     }
+@@ -114,13 +142,15 @@ struct glyph_variations_t
+   bool instantiate (const hb_subset_plan_t *plan)
+   {
+     unsigned count = plan->new_to_old_gid_list.length;
++    bool iup_optimize = false;
++    iup_optimize = plan->flags & HB_SUBSET_FLAGS_OPTIMIZE_IUP_DELTAS;
+     for (unsigned i = 0; i < count; i++)
+     {
+       hb_codepoint_t new_gid = plan->new_to_old_gid_list[i].first;
+       contour_point_vector_t *all_points;
+       if (!plan->new_gid_contour_points_map.has (new_gid, &all_points))
+         return false;
+-      if (!glyph_variations[i].instantiate (plan->axes_location, plan->axes_triple_distances, all_points))
++      if (!glyph_variations[i].instantiate (plan->axes_location, plan->axes_triple_distances, all_points, iup_optimize))
+         return false;
+     }
+     return true;
+@@ -134,6 +164,7 @@ struct glyph_variations_t
+     for (tuple_variations_t& vars: glyph_variations)
+       if (!vars.compile_bytes (axes_index_map, axes_old_index_tag_map,
+                                true, /* use shared points*/
++                               true,
+                                &shared_tuples_idx_map))
+         return false;
+ 
+@@ -252,7 +283,7 @@ struct glyph_variations_t
+     hb_codepoint_t last_gid = 0;
+     unsigned idx = 0;
+ 
+-    TupleVariationData* cur_glyph = c->start_embed ();
++    GlyphVariationData* cur_glyph = c->start_embed ();
+     if (!cur_glyph) return_trace (false);
+     for (auto &_ : it)
+     {
+@@ -266,7 +297,7 @@ struct glyph_variations_t
+ 
+       if (idx >= glyph_variations.length) return_trace (false);
+       if (!cur_glyph->serialize (c, true, glyph_variations[idx])) return_trace (false);
+-      TupleVariationData* next_glyph = c->start_embed ();
++      GlyphVariationData* next_glyph = c->start_embed ();
+       glyph_offset += (char *) next_glyph - (char *) cur_glyph;
+ 
+       if (long_offset)
+@@ -289,14 +320,21 @@ struct glyph_variations_t
+   }
+ };
+ 
+-struct gvar
++template 
++struct gvar_GVAR
+ {
+-  static constexpr hb_tag_t tableTag = HB_OT_TAG_gvar;
++  static constexpr hb_tag_t tableTag = TableTag;
++
++  using GlyphVariationData = TupleVariationData;
++
++  bool has_data () const { return version.to_int () != 0; }
+ 
+   bool sanitize_shallow (hb_sanitize_context_t *c) const
+   {
+     TRACE_SANITIZE (this);
+-    return_trace (c->check_struct (this) && (version.major == 1) &&
++    return_trace (c->check_struct (this) &&
++                  hb_barrier () &&
++                  (version.major == 1) &&
+                   sharedTuples.sanitize (c, this, axisCount * sharedTupleCount) &&
+                   (is_long_offset () ?
+                      c->check_array (get_long_offset_array (), c->get_num_glyphs () + 1) :
+@@ -308,7 +346,7 @@ struct gvar
+   { return sanitize_shallow (c); }
+ 
+   bool decompile_glyph_variations (hb_subset_context_t *c,
+-                                   glyph_variations_t& glyph_vars /* OUT */) const
++                                   glyph_variations_t& glyph_vars /* OUT */) const
+   {
+     hb_hashmap_t new_gid_var_data_map;
+     auto it = hb_iter (c->plan->new_to_old_gid_list);
+@@ -335,13 +373,14 @@ struct gvar
+   template
+   bool serialize (hb_serialize_context_t *c,
+-                  const glyph_variations_t& glyph_vars,
++                  const glyph_variations_t& glyph_vars,
+                   Iterator it,
+                   unsigned axis_count,
+-                  unsigned num_glyphs) const
++                  unsigned num_glyphs,
++                  bool force_long_offsets) const
+   {
+     TRACE_SERIALIZE (this);
+-    gvar *out = c->allocate_min ();
++    gvar_GVAR *out = c->allocate_min ();
+     if (unlikely (!out)) return_trace (false);
+ 
+     out->version.major = 1;
+@@ -350,7 +389,10 @@ struct gvar
+     out->glyphCountX = hb_min (0xFFFFu, num_glyphs);
+ 
+     unsigned glyph_var_data_size = glyph_vars.compiled_byte_size ();
+-    bool long_offset = glyph_var_data_size & ~0xFFFFu;
++    /* According to the spec: If the short format (Offset16) is used for offsets,
++     * the value stored is the offset divided by 2, so the maximum data size should
++     * be 2 * 0xFFFFu, which is 0x1FFFEu */
++    bool long_offset = glyph_var_data_size > 0x1FFFEu || force_long_offsets;
+     out->flags = long_offset ? 1 : 0;
+ 
+     HBUINT8 *glyph_var_data_offsets = c->allocate_size ((long_offset ? 4 : 2) * (num_glyphs + 1), false);
+@@ -380,7 +422,7 @@ struct gvar
+   bool instantiate (hb_subset_context_t *c) const
+   {
+     TRACE_SUBSET (this);
+-    glyph_variations_t glyph_vars;
++    glyph_variations_t glyph_vars;
+     if (!decompile_glyph_variations (c, glyph_vars))
+       return_trace (false);
+ 
+@@ -391,7 +433,12 @@ struct gvar
+     unsigned axis_count = c->plan->axes_index_map.get_population ();
+     unsigned num_glyphs = c->plan->num_output_glyphs ();
+     auto it = hb_iter (c->plan->new_to_old_gid_list);
+-    return_trace (serialize (c->serializer, glyph_vars, it, axis_count, num_glyphs));
++
++    bool force_long_offsets = false;
++#ifdef HB_EXPERIMENTAL_API
++    force_long_offsets = c->plan->flags & HB_SUBSET_FLAGS_IFTB_REQUIREMENTS;
++#endif
++    return_trace (serialize (c->serializer, glyph_vars, it, axis_count, num_glyphs, force_long_offsets));
+   }
+ 
+   bool subset (hb_subset_context_t *c) const
+@@ -405,7 +452,7 @@ struct gvar
+ 
+     unsigned glyph_count = version.to_int () ? c->plan->source->get_num_glyphs () : 0;
+ 
+-    gvar *out = c->serializer->allocate_min ();
++    gvar_GVAR *out = c->serializer->allocate_min ();
+     if (unlikely (!out)) return_trace (false);
+ 
+     out->version.major = 1;
+@@ -426,7 +473,13 @@ struct gvar
+       subset_data_size += get_glyph_var_data_bytes (c->source_blob, glyph_count, old_gid).length;
+     }
+ 
+-    bool long_offset = subset_data_size & ~0xFFFFu;
++    /* According to the spec: If the short format (Offset16) is used for offsets,
++     * the value stored is the offset divided by 2, so the maximum data size should
++     * be 2 * 0xFFFFu, which is 0x1FFFEu */
++    bool long_offset = subset_data_size > 0x1FFFEu;
++#ifdef HB_EXPERIMENTAL_API
++    long_offset = long_offset || (c->plan->flags & HB_SUBSET_FLAGS_IFTB_REQUIREMENTS);
++#endif
+     out->flags = long_offset ? 1 : 0;
+ 
+     HBUINT8 *subset_offsets = c->serializer->allocate_size ((long_offset ? 4 : 2) * (num_glyphs + 1), false);
+@@ -444,6 +497,8 @@ struct gvar
+       hb_memcpy (tuples, this+sharedTuples, shared_tuple_size);
+     }
+ 
++    /* This ordering relative to the shared tuples array, which puts the glyphVariationData
++       last in the table, is required when HB_SUBSET_FLAGS_IFTB_REQUIREMENTS is set */
+     char *subset_data = c->serializer->allocate_size (subset_data_size, false);
+     if (!subset_data) return_trace (false);
+     out->dataZ = subset_data - (char *) out;
+@@ -521,7 +576,7 @@ struct gvar
+   unsigned get_offset (unsigned glyph_count, unsigned i) const
+   {
+     if (unlikely (i > glyph_count)) return 0;
+-    _hb_compiler_memory_r_barrier ();
++    hb_barrier ();
+     return is_long_offset () ? get_long_offset_array ()[i] : get_short_offset_array ()[i] * 2;
+   }
+ 
+@@ -531,9 +586,11 @@ struct gvar
+   public:
+   struct accelerator_t
+   {
++    bool has_data () const { return table->has_data (); }
++
+     accelerator_t (hb_face_t *face)
+     {
+-      table = hb_sanitize_context_t ().reference_table (face);
++      table = hb_sanitize_context_t ().reference_table (face);
+       /* If sanitize failed, set glyphCount to 0. */
+       glyphCount = table->version.to_int () ? face->get_num_glyphs () : 0;
+ 
+@@ -599,37 +656,42 @@ struct gvar
+ 
+     public:
+     bool apply_deltas_to_points (hb_codepoint_t glyph,
+-                                 hb_array_t coords,
++                                 hb_array_t coords,
+                                  const hb_array_t points,
++                                 hb_glyf_scratch_t &scratch,
+                                  bool phantom_only = false) const
+     {
+       if (unlikely (glyph >= glyphCount)) return true;
+ 
+       hb_bytes_t var_data_bytes = table->get_glyph_var_data_bytes (table.get_blob (), glyphCount, glyph);
+       if (!var_data_bytes.as ()->has_data ()) return true;
+-      hb_vector_t shared_indices;
+-      GlyphVariationData::tuple_iterator_t iterator;
++
++      auto &shared_indices = scratch.shared_indices;
++      shared_indices.clear ();
++
++      typename GlyphVariationData::tuple_iterator_t iterator;
+       if (!GlyphVariationData::get_tuple_iterator (var_data_bytes, table->axisCount,
+                                                    var_data_bytes.arrayZ,
+                                                    shared_indices, &iterator))
+         return true; /* so isn't applied at all */
+ 
+       /* Save original points for inferred delta calculation */
+-      contour_point_vector_t orig_points_vec; // Populated lazily
++      auto &orig_points_vec = scratch.orig_points;
++      orig_points_vec.clear (); // Populated lazily
+       auto orig_points = orig_points_vec.as_array ();
+ 
+       /* flag is used to indicate referenced point */
+-      contour_point_vector_t deltas_vec; // Populated lazily
++      auto &deltas_vec = scratch.deltas;
++      deltas_vec.clear (); // Populated lazily
+       auto deltas = deltas_vec.as_array ();
+ 
+-      hb_vector_t end_points; // Populated lazily
+-
+       unsigned num_coords = table->axisCount;
+       hb_array_t shared_tuples = (table+table->sharedTuples).as_array (table->sharedTupleCount * num_coords);
+ 
+-      hb_vector_t private_indices;
+-      hb_vector_t x_deltas;
+-      hb_vector_t y_deltas;
++      auto &private_indices = scratch.private_indices;
++      auto &x_deltas = scratch.x_deltas;
++      auto &y_deltas = scratch.y_deltas;
++
+       unsigned count = points.length;
+       bool flush = false;
+       do
+@@ -654,16 +716,16 @@ struct gvar
+ 
+         bool has_private_points = iterator.current_tuple->has_private_points ();
+         if (has_private_points &&
+-            !GlyphVariationData::unpack_points (p, private_indices, end))
++            !GlyphVariationData::decompile_points (p, private_indices, end))
+           return false;
+         const hb_array_t &indices = has_private_points ? private_indices : shared_indices;
+ 
+         bool apply_to_all = (indices.length == 0);
+         unsigned int num_deltas = apply_to_all ? points.length : indices.length;
+         if (unlikely (!x_deltas.resize (num_deltas, false))) return false;
+-        if (unlikely (!GlyphVariationData::unpack_deltas (p, x_deltas, end))) return false;
++        if (unlikely (!GlyphVariationData::decompile_deltas (p, x_deltas, end))) return false;
+         if (unlikely (!y_deltas.resize (num_deltas, false))) return false;
+-        if (unlikely (!GlyphVariationData::unpack_deltas (p, y_deltas, end))) return false;
++        if (unlikely (!GlyphVariationData::decompile_deltas (p, y_deltas, end))) return false;
+ 
+         if (!apply_to_all)
+         {
+@@ -700,8 +762,8 @@ struct gvar
+             if (phantom_only && pt_index < count - 4) continue;
+             auto &delta = deltas.arrayZ[pt_index];
+             delta.flag = 1;     /* this point is referenced, i.e., explicit deltas specified */
+-            delta.x += x_deltas.arrayZ[i] * scalar;
+-            delta.y += y_deltas.arrayZ[i] * scalar;
++            delta.add_delta (x_deltas.arrayZ[i] * scalar,
++                             y_deltas.arrayZ[i] * scalar);
+           }
+         }
+         else
+@@ -712,10 +774,9 @@ struct gvar
+             if (apply_to_all)
+               for (unsigned int i = phantom_only ? count - 4 : 0; i < count; i++)
+               {
+-                unsigned int pt_index = i;
+-                auto &delta = deltas.arrayZ[pt_index];
+-                delta.x += x_deltas.arrayZ[i] * scalar;
+-                delta.y += y_deltas.arrayZ[i] * scalar;
++                auto &delta = deltas.arrayZ[i];
++                delta.add_delta (x_deltas.arrayZ[i] * scalar,
++                                 y_deltas.arrayZ[i] * scalar);
+               }
+             else
+               for (unsigned int i = 0; i < num_deltas; i++)
+@@ -725,8 +786,8 @@ struct gvar
+                 if (phantom_only && pt_index < count - 4) continue;
+                 auto &delta = deltas.arrayZ[pt_index];
+                 delta.flag = 1; /* this point is referenced, i.e., explicit deltas specified */
+-                delta.x += x_deltas.arrayZ[i] * scalar;
+-                delta.y += y_deltas.arrayZ[i] * scalar;
++                delta.add_delta (x_deltas.arrayZ[i] * scalar,
++                                 y_deltas.arrayZ[i] * scalar);
+               }
+           }
+           else
+@@ -734,10 +795,9 @@ struct gvar
+             if (apply_to_all)
+               for (unsigned int i = phantom_only ? count - 4 : 0; i < count; i++)
+               {
+-                unsigned int pt_index = i;
+-                auto &delta = deltas.arrayZ[pt_index];
+-                delta.x += x_deltas.arrayZ[i];
+-                delta.y += y_deltas.arrayZ[i];
++                auto &delta = deltas.arrayZ[i];
++                delta.add_delta (x_deltas.arrayZ[i],
++                                 y_deltas.arrayZ[i]);
+               }
+             else
+               for (unsigned int i = 0; i < num_deltas; i++)
+@@ -747,8 +807,8 @@ struct gvar
+                 if (phantom_only && pt_index < count - 4) continue;
+                 auto &delta = deltas.arrayZ[pt_index];
+                 delta.flag = 1; /* this point is referenced, i.e., explicit deltas specified */
+-                delta.x += x_deltas.arrayZ[i];
+-                delta.y += y_deltas.arrayZ[i];
++                delta.add_delta (x_deltas.arrayZ[i],
++                                 y_deltas.arrayZ[i]);
+               }
+           }
+         }
+@@ -756,17 +816,14 @@ struct gvar
+         /* infer deltas for unreferenced points */
+         if (!apply_to_all && !phantom_only)
+         {
+-          if (!end_points)
+-          {
+-            for (unsigned i = 0; i < count; ++i)
+-              if (points.arrayZ[i].is_end_point)
+-                end_points.push (i);
+-            if (unlikely (end_points.in_error ())) return false;
+-          }
+-
+           unsigned start_point = 0;
+-          for (unsigned end_point : end_points)
++          unsigned end_point = 0;
++          while (true)
+           {
++            while (end_point < count && !points.arrayZ[end_point].is_end_point)
++              end_point++;
++            if (unlikely (end_point == count)) break;
++
+             /* Check the number of unreferenced points in a contour. If no unref points or no ref points, nothing to do. */
+             unsigned unref_count = 0;
+             for (unsigned i = start_point; i < end_point + 1; i++)
+@@ -809,7 +866,7 @@ struct gvar
+               }
+             }
+           no_more_gaps:
+-            start_point = end_point + 1;
++            start_point = end_point = end_point + 1;
+           }
+         }
+ 
+@@ -829,7 +886,7 @@ struct gvar
+     unsigned int get_axis_count () const { return table->axisCount; }
+ 
+     private:
+-    hb_blob_ptr_t table;
++    hb_blob_ptr_t table;
+     unsigned glyphCount;
+     hb_vector_t> shared_tuple_active_idx;
+   };
+@@ -847,7 +904,7 @@ struct gvar
+   NNOffset32To>
+                 sharedTuples;   /* Offset from the start of this table to the shared tuple records.
+                                  * Array of tuple records shared across all glyph variation data tables. */
+-  HBUINT16      glyphCountX;    /* The number of glyphs in this font. This must match the number of
++  GidOffsetType glyphCountX;    /* The number of glyphs in this font. This must match the number of
+                                  * glyphs stored elsewhere in the font. */
+   HBUINT16      flags;          /* Bit-field that gives the format of the offset array that follows.
+                                  * If bit 0 is clear, the offsets are uint16; if bit 0 is set, the
+@@ -862,9 +919,15 @@ struct gvar
+   DEFINE_SIZE_ARRAY (20, offsetZ);
+ };
+ 
++using gvar = gvar_GVAR;
++using GVAR = gvar_GVAR;
++
+ struct gvar_accelerator_t : gvar::accelerator_t {
+   gvar_accelerator_t (hb_face_t *face) : gvar::accelerator_t (face) {}
+ };
++struct GVAR_accelerator_t : GVAR::accelerator_t {
++  GVAR_accelerator_t (hb_face_t *face) : GVAR::accelerator_t (face) {}
++};
+ 
+ } /* namespace OT */
+ 
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-var-hvar-table.hh b/src/java.desktop/share/native/libharfbuzz/hb-ot-var-hvar-table.hh
+index c1b40dcb4..40a85a62b 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-var-hvar-table.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-var-hvar-table.hh
+@@ -188,7 +188,7 @@ struct hvarvvar_subset_plan_t
+   ~hvarvvar_subset_plan_t() { fini (); }
+ 
+   void init (const hb_array_t &index_maps,
+-             const VariationStore &_var_store,
++             const ItemVariationStore &_var_store,
+              const hb_subset_plan_t *plan)
+   {
+     index_map_plans.resize (index_maps.length);
+@@ -263,7 +263,7 @@ struct hvarvvar_subset_plan_t
+   hb_inc_bimap_t outer_map;
+   hb_vector_t inner_maps;
+   hb_vector_t index_map_plans;
+-  const VariationStore *var_store;
++  const ItemVariationStore *var_store;
+ 
+   protected:
+   hb_vector_t inner_sets;
+@@ -288,6 +288,7 @@ struct HVARVVAR
+   {
+     TRACE_SANITIZE (this);
+     return_trace (version.sanitize (c) &&
++                  hb_barrier () &&
+                   likely (version.major == 1) &&
+                   varStore.sanitize (c, this) &&
+                   advMap.sanitize (c, this) &&
+@@ -295,7 +296,7 @@ struct HVARVVAR
+                   rsbMap.sanitize (c, this));
+   }
+ 
+-  const VariationStore& get_var_store () const
++  const ItemVariationStore& get_var_store () const
+   { return this+varStore; }
+ 
+   void listup_index_maps (hb_vector_t &index_maps) const
+@@ -383,7 +384,7 @@ struct HVARVVAR
+ 
+   float get_advance_delta_unscaled (hb_codepoint_t  glyph,
+                                     const int *coords, unsigned int coord_count,
+-                                    VariationStore::cache_t *store_cache = nullptr) const
++                                    ItemVariationStore::cache_t *store_cache = nullptr) const
+   {
+     uint32_t varidx = (this+advMap).map (glyph);
+     return (this+varStore).get_delta (varidx,
+@@ -404,7 +405,7 @@ struct HVARVVAR
+   public:
+   FixedVersion<>version;        /* Version of the metrics variation table
+                                  * initially set to 0x00010000u */
+-  Offset32To
++  Offset32To
+                 varStore;       /* Offset to item variation store table. */
+   Offset32To
+                 advMap;         /* Offset to advance var-idx mapping. */
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-var-mvar-table.hh b/src/java.desktop/share/native/libharfbuzz/hb-ot-var-mvar-table.hh
+index ced04d89d..c5a58d6f6 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-var-mvar-table.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-var-mvar-table.hh
+@@ -56,7 +56,7 @@ struct VariationValueRecord
+ 
+   public:
+   Tag           valueTag;       /* Four-byte tag identifying a font-wide measure. */
+-  VarIdx        varIdx;         /* Outer/inner index into VariationStore item. */
++  VarIdx        varIdx;         /* Outer/inner index into ItemVariationStore item. */
+ 
+   public:
+   DEFINE_SIZE_STATIC (8);
+@@ -77,8 +77,10 @@ struct MVAR
+   {
+     TRACE_SANITIZE (this);
+     return_trace (version.sanitize (c) &&
++                  hb_barrier () &&
+                   likely (version.major == 1) &&
+                   c->check_struct (this) &&
++                  hb_barrier () &&
+                   valueRecordSize >= VariationValueRecord::static_size &&
+                   varStore.sanitize (c, this) &&
+                   c->check_range (valuesZ.arrayZ,
+@@ -104,7 +106,7 @@ struct MVAR
+     out->valueRecordCount = valueRecordCount;
+ 
+     item_variations_t item_vars;
+-    const VariationStore& src_var_store = this+varStore;
++    const ItemVariationStore& src_var_store = this+varStore;
+ 
+     if (!item_vars.instantiate (src_var_store, c->plan))
+       return_trace (false);
+@@ -157,7 +159,7 @@ protected:
+   HBUINT16      valueRecordSize;/* The size in bytes of each value record —
+                                  * must be greater than zero. */
+   HBUINT16      valueRecordCount;/* The number of value records — may be zero. */
+-  Offset16To
++  Offset16To
+                 varStore;       /* Offset to item variation store table. */
+   UnsizedArrayOf
+                 valuesZ;        /* Array of value records. The records must be
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-var-varc-table.hh b/src/java.desktop/share/native/libharfbuzz/hb-ot-var-varc-table.hh
+new file mode 100644
+index 000000000..603aeb258
+--- /dev/null
++++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-var-varc-table.hh
+@@ -0,0 +1,32 @@
++/*
++ * Copyright © 2024  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_OT_VAR_VARC_TABLE_HH
++#define HB_OT_VAR_VARC_TABLE_HH
++
++#include "OT/Var/VARC/VARC.hh"
++
++#endif /* HB_OT_VAR_VARC_TABLE_HH */
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ot-vorg-table.hh b/src/java.desktop/share/native/libharfbuzz/hb-ot-vorg-table.hh
+index dd3039924..b2300a327 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-ot-vorg-table.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-ot-vorg-table.hh
+@@ -117,6 +117,7 @@ struct VORG
+   {
+     TRACE_SANITIZE (this);
+     return_trace (c->check_struct (this) &&
++                  hb_barrier () &&
+                   version.major == 1 &&
+                   vertYOrigins.sanitize (c));
+   }
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-paint-extents.hh b/src/java.desktop/share/native/libharfbuzz/hb-paint-extents.hh
+index 518228c41..18aa638c7 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-paint-extents.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-paint-extents.hh
+@@ -28,169 +28,8 @@
+ #include "hb.hh"
+ #include "hb-paint.h"
+ 
++#include "hb-geometry.hh"
+ 
+-typedef struct hb_extents_t
+-{
+-  hb_extents_t () {}
+-  hb_extents_t (float xmin, float ymin, float xmax, float ymax) :
+-    xmin (xmin), ymin (ymin), xmax (xmax), ymax (ymax) {}
+-
+-  bool is_empty () const { return xmin >= xmax || ymin >= ymax; }
+-  bool is_void () const { return xmin > xmax; }
+-
+-  void union_ (const hb_extents_t &o)
+-  {
+-    xmin = hb_min (xmin, o.xmin);
+-    ymin = hb_min (ymin, o.ymin);
+-    xmax = hb_max (xmax, o.xmax);
+-    ymax = hb_max (ymax, o.ymax);
+-  }
+-
+-  void intersect (const hb_extents_t &o)
+-  {
+-    xmin = hb_max (xmin, o.xmin);
+-    ymin = hb_max (ymin, o.ymin);
+-    xmax = hb_min (xmax, o.xmax);
+-    ymax = hb_min (ymax, o.ymax);
+-  }
+-
+-  void
+-  add_point (float x, float y)
+-  {
+-    if (unlikely (is_void ()))
+-    {
+-      xmin = xmax = x;
+-      ymin = ymax = y;
+-    }
+-    else
+-    {
+-      xmin = hb_min (xmin, x);
+-      ymin = hb_min (ymin, y);
+-      xmax = hb_max (xmax, x);
+-      ymax = hb_max (ymax, y);
+-    }
+-  }
+-
+-  float xmin = 0.f;
+-  float ymin = 0.f;
+-  float xmax = -1.f;
+-  float ymax = -1.f;
+-} hb_extents_t;
+-
+-typedef struct hb_transform_t
+-{
+-  hb_transform_t () {}
+-  hb_transform_t (float xx, float yx,
+-                  float xy, float yy,
+-                  float x0, float y0) :
+-    xx (xx), yx (yx), xy (xy), yy (yy), x0 (x0), y0 (y0) {}
+-
+-  void multiply (const hb_transform_t &o)
+-  {
+-    /* Copied from cairo, with "o" being "a" there and "this" being "b" there. */
+-    hb_transform_t r;
+-
+-    r.xx = o.xx * xx + o.yx * xy;
+-    r.yx = o.xx * yx + o.yx * yy;
+-
+-    r.xy = o.xy * xx + o.yy * xy;
+-    r.yy = o.xy * yx + o.yy * yy;
+-
+-    r.x0 = o.x0 * xx + o.y0 * xy + x0;
+-    r.y0 = o.x0 * yx + o.y0 * yy + y0;
+-
+-    *this = r;
+-  }
+-
+-  void transform_distance (float &dx, float &dy) const
+-  {
+-    float new_x = xx * dx + xy * dy;
+-    float new_y = yx * dx + yy * dy;
+-    dx = new_x;
+-    dy = new_y;
+-  }
+-
+-  void transform_point (float &x, float &y) const
+-  {
+-    transform_distance (x, y);
+-    x += x0;
+-    y += y0;
+-  }
+-
+-  void transform_extents (hb_extents_t &extents) const
+-  {
+-    float quad_x[4], quad_y[4];
+-
+-    quad_x[0] = extents.xmin;
+-    quad_y[0] = extents.ymin;
+-    quad_x[1] = extents.xmin;
+-    quad_y[1] = extents.ymax;
+-    quad_x[2] = extents.xmax;
+-    quad_y[2] = extents.ymin;
+-    quad_x[3] = extents.xmax;
+-    quad_y[3] = extents.ymax;
+-
+-    extents = hb_extents_t {};
+-    for (unsigned i = 0; i < 4; i++)
+-    {
+-      transform_point (quad_x[i], quad_y[i]);
+-      extents.add_point (quad_x[i], quad_y[i]);
+-    }
+-  }
+-
+-  float xx = 1.f;
+-  float yx = 0.f;
+-  float xy = 0.f;
+-  float yy = 1.f;
+-  float x0 = 0.f;
+-  float y0 = 0.f;
+-} hb_transform_t;
+-
+-typedef struct hb_bounds_t
+-{
+-  enum status_t {
+-    UNBOUNDED,
+-    BOUNDED,
+-    EMPTY,
+-  };
+-
+-  hb_bounds_t (status_t status) : status (status) {}
+-  hb_bounds_t (const hb_extents_t &extents) :
+-    status (extents.is_empty () ? EMPTY : BOUNDED), extents (extents) {}
+-
+-  void union_ (const hb_bounds_t &o)
+-  {
+-    if (o.status == UNBOUNDED)
+-      status = UNBOUNDED;
+-    else if (o.status == BOUNDED)
+-    {
+-      if (status == EMPTY)
+-        *this = o;
+-      else if (status == BOUNDED)
+-        extents.union_ (o.extents);
+-    }
+-  }
+-
+-  void intersect (const hb_bounds_t &o)
+-  {
+-    if (o.status == EMPTY)
+-      status = EMPTY;
+-    else if (o.status == BOUNDED)
+-    {
+-      if (status == UNBOUNDED)
+-        *this = o;
+-      else if (status == BOUNDED)
+-      {
+-        extents.intersect (o.extents);
+-        if (extents.is_empty ())
+-          status = EMPTY;
+-      }
+-    }
+-  }
+-
+-  status_t status;
+-  hb_extents_t extents;
+-} hb_bounds_t;
+ 
+ typedef struct  hb_paint_extents_context_t hb_paint_extents_context_t;
+ 
+@@ -231,7 +70,10 @@ struct hb_paint_extents_context_t
+     const hb_transform_t &t = transforms.tail ();
+     t.transform_extents (extents);
+ 
+-    clips.push (hb_bounds_t {extents});
++    auto bounds = hb_bounds_t {extents};
++    bounds.intersect (clips.tail ());
++
++    clips.push (bounds);
+   }
+ 
+   void pop_clip ()
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-paint.h b/src/java.desktop/share/native/libharfbuzz/hb-paint.h
+index 6215488e2..f0d943850 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-paint.h
++++ b/src/java.desktop/share/native/libharfbuzz/hb-paint.h
+@@ -146,7 +146,7 @@ typedef void (*hb_paint_pop_transform_func_t) (hb_paint_funcs_t *funcs,
+  *
+  * A virtual method for the #hb_paint_funcs_t to render a color glyph by glyph index.
+  *
+- * Return value: %true if the glyph was painted, %false otherwise.
++ * Return value: `true` if the glyph was painted, `false` otherwise.
+  *
+  * Since: 8.2.0
+  */
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-priority-queue.hh b/src/java.desktop/share/native/libharfbuzz/hb-priority-queue.hh
+index 2c8ccbfb6..274d5df4c 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-priority-queue.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-priority-queue.hh
+@@ -55,6 +55,9 @@ struct hb_priority_queue_t
+ 
+   bool in_error () const { return heap.in_error (); }
+ 
++  bool alloc (unsigned size)
++  { return heap.alloc (size); }
++
+ #ifndef HB_OPTIMIZE_SIZE
+   HB_ALWAYS_INLINE
+ #endif
+@@ -160,7 +163,7 @@ struct hb_priority_queue_t
+     goto repeat;
+   }
+ 
+-  void swap (unsigned a, unsigned b)
++  void swap (unsigned a, unsigned b) noexcept
+   {
+     assert (a < heap.length);
+     assert (b < heap.length);
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-repacker.hh b/src/java.desktop/share/native/libharfbuzz/hb-repacker.hh
+index e9cd376ad..cb4fdeead 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-repacker.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-repacker.hh
+@@ -238,6 +238,54 @@ bool _try_isolating_subgraphs (const hb_vector_t& over
+   return true;
+ }
+ 
++static inline
++bool _resolve_shared_overflow(const hb_vector_t& overflows,
++                              int overflow_index,
++                              graph_t& sorted_graph)
++{
++  const graph::overflow_record_t& r = overflows[overflow_index];
++
++  // Find all of the parents in overflowing links that link to this
++  // same child node. We will then try duplicating the child node and
++  // re-assigning all of these parents to the duplicate.
++  hb_set_t parents;
++  parents.add(r.parent);
++  for (int i = overflow_index - 1; i >= 0; i--) {
++    const graph::overflow_record_t& r2 = overflows[i];
++    if (r2.child == r.child) {
++      parents.add(r2.parent);
++    }
++  }
++
++  unsigned result = sorted_graph.duplicate(&parents, r.child);
++  if (result == (unsigned) -1 && parents.get_population() > 2) {
++    // All links to the child are overflowing, so we can't include all
++    // in the duplication. Remove one parent from the duplication.
++    // Remove the lowest index parent, which will be the closest to the child.
++    parents.del(parents.get_min());
++    result = sorted_graph.duplicate(&parents, r.child);
++  }
++
++  if (result == (unsigned) -1) return result;
++
++  if (parents.get_population() > 1) {
++    // If the duplicated node has more than one parent pre-emptively raise it's priority to the maximum.
++    // This will place it close to the parents. Node's with only one parent, don't need this as normal overflow
++    // resolution will raise priority if needed.
++    //
++    // Reasoning: most of the parents to this child are likely at the same layer in the graph. Duplicating
++    // the child will theoretically allow it to be placed closer to it's parents. However, due to the shortest
++    // distance sort by default it's placement will remain in the same layer, thus it will remain in roughly the
++    // same position (and distance from parents) as the original child node. The overflow resolution will attempt
++    // to move nodes closer, but only for non-shared nodes. Since this node is shared, it will simply be given
++    // further duplication which defeats the attempt to duplicate with multiple parents. To fix this we
++    // pre-emptively raise priority now which allows the duplicated node to pack into the same layer as it's parents.
++    sorted_graph.vertices_[result].give_max_priority();
++  }
++
++  return result;
++}
++
+ static inline
+ bool _process_overflows (const hb_vector_t& overflows,
+                          hb_set_t& priority_bumped_parents,
+@@ -254,7 +302,7 @@ bool _process_overflows (const hb_vector_t& overflows,
+     {
+       // The child object is shared, we may be able to eliminate the overflow
+       // by duplicating it.
+-      if (sorted_graph.duplicate (r.parent, r.child) == (unsigned) -1) continue;
++      if (!_resolve_shared_overflow(overflows, i, sorted_graph)) continue;
+       return true;
+     }
+ 
+@@ -289,9 +337,10 @@ bool _process_overflows (const hb_vector_t& overflows,
+ inline bool
+ hb_resolve_graph_overflows (hb_tag_t table_tag,
+                             unsigned max_rounds ,
+-                            bool recalculate_extensions,
++                            bool always_recalculate_extensions,
+                             graph_t& sorted_graph /* IN/OUT */)
+ {
++  DEBUG_MSG (SUBSET_REPACK, nullptr, "Repacking %c%c%c%c.", HB_UNTAG(table_tag));
+   sorted_graph.sort_shortest_distance ();
+   if (sorted_graph.in_error ())
+   {
+@@ -303,12 +352,12 @@ hb_resolve_graph_overflows (hb_tag_t table_tag,
+   if (!will_overflow)
+     return true;
+ 
++  bool is_gsub_or_gpos = (table_tag == HB_OT_TAG_GPOS ||  table_tag == HB_OT_TAG_GSUB);
+   graph::gsubgpos_graph_context_t ext_context (table_tag, sorted_graph);
+-  if ((table_tag == HB_OT_TAG_GPOS
+-       ||  table_tag == HB_OT_TAG_GSUB)
+-      && will_overflow)
++  if (is_gsub_or_gpos && will_overflow)
+   {
+-    if (recalculate_extensions)
++    DEBUG_MSG (SUBSET_REPACK, nullptr, "Applying GSUB/GPOS repacking specializations.");
++    if (always_recalculate_extensions)
+     {
+       DEBUG_MSG (SUBSET_REPACK, nullptr, "Splitting subtables if needed.");
+       if (!_presplit_subtables_if_needed (ext_context)) {
+@@ -364,6 +413,13 @@ hb_resolve_graph_overflows (hb_tag_t table_tag,
+ 
+   if (graph::will_overflow (sorted_graph))
+   {
++    if (is_gsub_or_gpos && !always_recalculate_extensions) {
++      // If this a GSUB/GPOS table and we didn't try to extension promotion and table splitting then
++      // as a last ditch effort, re-run the repacker with it enabled.
++      DEBUG_MSG (SUBSET_REPACK, nullptr, "Failed to find a resolution. Re-running with extension promotion and table splitting enabled.");
++      return hb_resolve_graph_overflows (table_tag, max_rounds, true, sorted_graph);
++    }
++
+     DEBUG_MSG (SUBSET_REPACK, nullptr, "Offset overflow resolution failed.");
+     return false;
+   }
+@@ -388,7 +444,7 @@ template
+ inline hb_blob_t*
+ hb_resolve_overflows (const T& packed,
+                       hb_tag_t table_tag,
+-                      unsigned max_rounds = 20,
++                      unsigned max_rounds = 32,
+                       bool recalculate_extensions = false) {
+   graph_t sorted_graph (packed);
+   if (sorted_graph.in_error ())
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-sanitize.hh b/src/java.desktop/share/native/libharfbuzz/hb-sanitize.hh
+index 3a6ec4fed..1f8ba32ba 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-sanitize.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-sanitize.hh
+@@ -72,8 +72,8 @@
+  *
+  * === The sanitize() contract ===
+  *
+- * The sanitize() method of each object type shall return true if it's safe to
+- * call other methods of the object, and %false otherwise.
++ * The sanitize() method of each object type shall return `true` if it's safe to
++ * call other methods of the object, and `false` otherwise.
+  *
+  * Note that what sanitize() checks for might align with what the specification
+  * describes as valid table data, but does not have to be.  In particular, we
+@@ -134,7 +134,10 @@ struct hb_sanitize_context_t :
+   const char *get_name () { return "SANITIZE"; }
+   template 
+   bool may_dispatch (const T *obj HB_UNUSED, const F *format)
+-  { return format->sanitize (this); }
++  {
++    return format->sanitize (this) &&
++           hb_barrier ();
++  }
+   static return_t default_return_value () { return true; }
+   static return_t no_dispatch_return_value () { return false; }
+   bool stop_sublookup_iteration (const return_t r) const { return !r; }
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-serialize.hh b/src/java.desktop/share/native/libharfbuzz/hb-serialize.hh
+index 675eb03ca..704d0ffd1 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-serialize.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-serialize.hh
+@@ -36,9 +36,7 @@
+ #include "hb-map.hh"
+ #include "hb-pool.hh"
+ 
+-#ifdef HB_EXPERIMENTAL_API
+-#include "hb-subset-repacker.h"
+-#endif
++#include "hb-subset-serialize.h"
+ 
+ /*
+  * Serialize
+@@ -75,23 +73,41 @@ struct hb_serialize_context_t
+ 
+     object_t () = default;
+ 
+-#ifdef HB_EXPERIMENTAL_API
+-    object_t (const hb_object_t &o)
++    object_t (const hb_subset_serialize_object_t &o)
+     {
+       head = o.head;
+       tail = o.tail;
+       next = nullptr;
+-      real_links.alloc (o.num_real_links, true);
++      real_links.alloc_exact (o.num_real_links);
+       for (unsigned i = 0 ; i < o.num_real_links; i++)
+         real_links.push (o.real_links[i]);
+ 
+-      virtual_links.alloc (o.num_virtual_links, true);
++      virtual_links.alloc_exact (o.num_virtual_links);
+       for (unsigned i = 0; i < o.num_virtual_links; i++)
+         virtual_links.push (o.virtual_links[i]);
+     }
+-#endif
+ 
+-    friend void swap (object_t& a, object_t& b)
++    bool add_virtual_link (objidx_t objidx)
++    {
++      if (!objidx)
++        return false;
++
++      auto& link = *virtual_links.push ();
++      if (virtual_links.in_error ())
++        return false;
++
++      link.objidx = objidx;
++      // Remaining fields were previously zero'd by push():
++      // link.width = 0;
++      // link.is_signed = 0;
++      // link.whence = 0;
++      // link.position = 0;
++      // link.bias = 0;
++
++      return true;
++    }
++
++    friend void swap (object_t& a, object_t& b) noexcept
+     {
+       hb_swap (a.head, b.head);
+       hb_swap (a.tail, b.tail);
+@@ -128,8 +144,7 @@ struct hb_serialize_context_t
+ 
+       link_t () = default;
+ 
+-#ifdef HB_EXPERIMENTAL_API
+-      link_t (const hb_link_t &o)
++      link_t (const hb_subset_serialize_link_t &o)
+       {
+         width = o.width;
+         is_signed = 0;
+@@ -138,7 +153,6 @@ struct hb_serialize_context_t
+         bias = 0;
+         objidx = o.objidx;
+       }
+-#endif
+ 
+       HB_INTERNAL static int cmp (const void* a, const void* b)
+       {
+@@ -156,9 +170,9 @@ struct hb_serialize_context_t
+     object_t *next;
+ 
+     auto all_links () const HB_AUTO_RETURN
+-        (( hb_concat (this->real_links, this->virtual_links) ));
++        (( hb_concat (real_links, virtual_links) ));
+     auto all_links_writer () HB_AUTO_RETURN
+-        (( hb_concat (this->real_links.writer (), this->virtual_links.writer ()) ));
++        (( hb_concat (real_links.writer (), virtual_links.writer ()) ));
+   };
+ 
+   struct snapshot_t
+@@ -380,6 +394,7 @@ struct hb_serialize_context_t
+       {
+         merge_virtual_links (obj, objidx);
+         obj->fini ();
++        object_pool.release (obj);
+         return objidx;
+       }
+     }
+@@ -443,9 +458,11 @@ struct hb_serialize_context_t
+     while (packed.length > 1 &&
+            packed.tail ()->head < tail)
+     {
+-      packed_map.del (packed.tail ());
+-      assert (!packed.tail ()->next);
+-      packed.tail ()->fini ();
++      object_t *obj = packed.tail ();
++      packed_map.del (obj);
++      assert (!obj->next);
++      obj->fini ();
++      object_pool.release (obj);
+       packed.pop ();
+     }
+     if (packed.length > 1)
+@@ -469,16 +486,40 @@ struct hb_serialize_context_t
+ 
+     assert (current);
+ 
+-    auto& link = *current->virtual_links.push ();
+-    if (current->virtual_links.in_error ())
++    if (!current->add_virtual_link(objidx))
+       err (HB_SERIALIZE_ERROR_OTHER);
++  }
+ 
+-    link.width = 0;
+-    link.objidx = objidx;
+-    link.is_signed = 0;
+-    link.whence = 0;
+-    link.position = 0;
+-    link.bias = 0;
++  objidx_t last_added_child_index() const {
++    if (unlikely (in_error ())) return (objidx_t) -1;
++
++    assert (current);
++    if (!bool(current->real_links)) {
++      return (objidx_t) -1;
++    }
++
++    return current->real_links[current->real_links.length - 1].objidx;
++  }
++
++  // For the current object ensure that the sub-table bytes for child objidx are always placed
++  // after the subtable bytes for any other existing children. This only ensures that the
++  // repacker will not move the target subtable before the other children
++  // (by adding virtual links). It is up to the caller to ensure the initial serialization
++  // order is correct.
++  void repack_last(objidx_t objidx) {
++    if (unlikely (in_error ())) return;
++
++    if (!objidx)
++      return;
++
++    assert (current);
++    for (auto& l : current->real_links) {
++      if (l.objidx == objidx) {
++        continue;
++      }
++
++      packed[l.objidx]->add_virtual_link(objidx);
++    }
+   }
+ 
+   template 
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-set-digest.hh b/src/java.desktop/share/native/libharfbuzz/hb-set-digest.hh
+index c1e107b4c..7bd14a281 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-set-digest.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-set-digest.hh
+@@ -56,7 +56,7 @@
+  *   - For each glyph, if it doesn't match the subtable digest,
+  *     skip it.
+  *
+- * The main filter we use is a combination of three bits-pattern
++ * The main filter we use is a combination of four bits-pattern
+  * filters. A bits-pattern filter checks a number of bits (5 or 6)
+  * of the input number (glyph-id in this case) and checks whether
+  * its pattern is amongst the patterns of any of the accepted values.
+@@ -64,43 +64,60 @@
+  * check is done using four bitwise operations only.
+  */
+ 
+-template 
+-struct hb_set_digest_bits_pattern_t
++static constexpr unsigned hb_set_digest_shifts[] = {4, 0, 6};
++
++struct hb_set_digest_t
+ {
++  // No science in these. Intuition and testing only.
++  using mask_t = uint64_t;
++
++  static constexpr unsigned n = ARRAY_LENGTH_CONST (hb_set_digest_shifts);
+   static constexpr unsigned mask_bytes = sizeof (mask_t);
+   static constexpr unsigned mask_bits = sizeof (mask_t) * 8;
+-  static constexpr unsigned num_bits = 0
+-                                     + (mask_bytes >= 1 ? 3 : 0)
+-                                     + (mask_bytes >= 2 ? 1 : 0)
+-                                     + (mask_bytes >= 4 ? 1 : 0)
+-                                     + (mask_bytes >= 8 ? 1 : 0)
+-                                     + (mask_bytes >= 16? 1 : 0)
+-                                     + 0;
++  static constexpr hb_codepoint_t mb1 = mask_bits - 1;
++  static constexpr mask_t one = 1;
++  static constexpr mask_t all = (mask_t) -1;
+ 
+-  static_assert ((shift < sizeof (hb_codepoint_t) * 8), "");
+-  static_assert ((shift + num_bits <= sizeof (hb_codepoint_t) * 8), "");
++  void init ()
++  { for (unsigned i = 0; i < n; i++) masks[i] = 0; }
+ 
+-  void init () { mask = 0; }
++  void clear () { init (); }
+ 
+-  void add (const hb_set_digest_bits_pattern_t &o) { mask |= o.mask; }
++  static hb_set_digest_t full ()
++  {
++    hb_set_digest_t d;
++    for (unsigned i = 0; i < n; i++) d.masks[i] = all;
++    return d;
++  }
+ 
+-  void add (hb_codepoint_t g) { mask |= mask_for (g); }
++  void union_ (const hb_set_digest_t &o)
++  { for (unsigned i = 0; i < n; i++) masks[i] |= o.masks[i]; }
+ 
+   bool add_range (hb_codepoint_t a, hb_codepoint_t b)
+   {
+-    if (mask == (mask_t) -1) return false;
+-    if ((b >> shift) - (a >> shift) >= mask_bits - 1)
+-    {
+-      mask = (mask_t) -1;
+-      return false;
+-    }
+-    else
++    bool ret;
++
++    ret = false;
++    for (unsigned i = 0; i < n; i++)
++      if (masks[i] != all)
++        ret = true;
++    if (!ret) return false;
++
++    ret = false;
++    for (unsigned i = 0; i < n; i++)
+     {
+-      mask_t ma = mask_for (a);
+-      mask_t mb = mask_for (b);
+-      mask |= mb + (mb - ma) - (mb < ma);
+-      return true;
++      mask_t shift = hb_set_digest_shifts[i];
++      if ((b >> shift) - (a >> shift) >= mb1)
++        masks[i] = all;
++      else
++      {
++        mask_t ma = one << ((a >> shift) & mb1);
++        mask_t mb = one << ((b >> shift) & mb1);
++        masks[i] |= mb + (mb - ma) - (mb < ma);
++        ret = true;
++      }
+     }
++    return ret;
+   }
+ 
+   template 
+@@ -123,95 +140,37 @@ struct hb_set_digest_bits_pattern_t
+   template 
+   bool add_sorted_array (const hb_sorted_array_t& arr) { return add_sorted_array (&arr, arr.len ()); }
+ 
+-  bool may_have (const hb_set_digest_bits_pattern_t &o) const
+-  { return mask & o.mask; }
+-
+-  bool may_have (hb_codepoint_t g) const
+-  { return mask & mask_for (g); }
+-
+-  private:
+-
+-  static mask_t mask_for (hb_codepoint_t g)
+-  { return ((mask_t) 1) << ((g >> shift) & (mask_bits - 1)); }
+-  mask_t mask;
+-};
+-
+-template 
+-struct hb_set_digest_combiner_t
+-{
+-  void init ()
+-  {
+-    head.init ();
+-    tail.init ();
+-  }
++  bool operator [] (hb_codepoint_t g) const
++  { return may_have (g); }
+ 
+-  void add (const hb_set_digest_combiner_t &o)
+-  {
+-    head.add (o.head);
+-    tail.add (o.tail);
+-  }
+ 
+   void add (hb_codepoint_t g)
+   {
+-    head.add (g);
+-    tail.add (g);
+-  }
+-
+-  bool add_range (hb_codepoint_t a, hb_codepoint_t b)
+-  {
+-    return (int) head.add_range (a, b) | (int) tail.add_range (a, b);
+-  }
+-  template 
+-  void add_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
+-  {
+-    head.add_array (array, count, stride);
+-    tail.add_array (array, count, stride);
+-  }
+-  template 
+-  void add_array (const hb_array_t& arr) { add_array (&arr, arr.len ()); }
+-  template 
+-  bool add_sorted_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
+-  {
+-    return head.add_sorted_array (array, count, stride) &&
+-           tail.add_sorted_array (array, count, stride);
++    for (unsigned i = 0; i < n; i++)
++      masks[i] |= one << ((g >> hb_set_digest_shifts[i]) & mb1);
+   }
+-  template 
+-  bool add_sorted_array (const hb_sorted_array_t& arr) { return add_sorted_array (&arr, arr.len ()); }
+ 
+-  bool may_have (const hb_set_digest_combiner_t &o) const
++  HB_ALWAYS_INLINE
++  bool may_have (hb_codepoint_t g) const
+   {
+-    return head.may_have (o.head) && tail.may_have (o.tail);
++    for (unsigned i = 0; i < n; i++)
++      if (!(masks[i] & (one << ((g >> hb_set_digest_shifts[i]) & mb1))))
++        return false;
++    return true;
+   }
+ 
+-  bool may_have (hb_codepoint_t g) const
++  bool may_intersect (const hb_set_digest_t &o) const
+   {
+-    return head.may_have (g) && tail.may_have (g);
++    for (unsigned i = 0; i < n; i++)
++      if (!(masks[i] & o.masks[i]))
++        return false;
++    return true;
+   }
+ 
+   private:
+-  head_t head;
+-  tail_t tail;
+-};
+-
+ 
+-/*
+- * hb_set_digest_t
+- *
+- * This is a combination of digests that performs "best".
+- * There is not much science to this: it's a result of intuition
+- * and testing.
+- */
+-using hb_set_digest_t =
+-  hb_set_digest_combiner_t
+-  <
+-    hb_set_digest_bits_pattern_t,
+-    hb_set_digest_combiner_t
+-    <
+-      hb_set_digest_bits_pattern_t,
+-      hb_set_digest_bits_pattern_t
+-    >
+-  >
+-;
++  mask_t masks[n] = {};
++};
+ 
+ 
+ #endif /* HB_SET_DIGEST_HH */
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-set.hh b/src/java.desktop/share/native/libharfbuzz/hb-set.hh
+index 4aa682616..eaa892ab9 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-set.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-set.hh
+@@ -35,6 +35,8 @@
+ template 
+ struct hb_sparseset_t
+ {
++  static constexpr bool realloc_move = true;
++
+   hb_object_header_t header;
+   impl_t s;
+ 
+@@ -42,10 +44,10 @@ struct hb_sparseset_t
+   ~hb_sparseset_t () { fini (); }
+ 
+   hb_sparseset_t (const hb_sparseset_t& other) : hb_sparseset_t () { set (other); }
+-  hb_sparseset_t (hb_sparseset_t&& other) : hb_sparseset_t () { s = std::move (other.s); }
++  hb_sparseset_t (hb_sparseset_t&& other)  noexcept : hb_sparseset_t () { s = std::move (other.s); }
+   hb_sparseset_t& operator = (const hb_sparseset_t& other) { set (other); return *this; }
+-  hb_sparseset_t& operator = (hb_sparseset_t&& other) { s = std::move (other.s); return *this; }
+-  friend void swap (hb_sparseset_t& a, hb_sparseset_t& b) { hb_swap (a.s, b.s); }
++  hb_sparseset_t& operator = (hb_sparseset_t&& other)  noexcept { s = std::move (other.s); return *this; }
++  friend void swap (hb_sparseset_t& a, hb_sparseset_t& b)  noexcept { hb_swap (a.s, b.s); }
+ 
+   hb_sparseset_t (std::initializer_list lst) : hb_sparseset_t ()
+   {
+@@ -84,7 +86,7 @@ struct hb_sparseset_t
+   uint32_t hash () const { return s.hash (); }
+ 
+   void add (hb_codepoint_t g) { s.add (g); }
+-  bool add_range (hb_codepoint_t a, hb_codepoint_t b) { return s.add_range (a, b); }
++  bool add_range (hb_codepoint_t first, hb_codepoint_t last) { return s.add_range (first, last); }
+ 
+   template 
+   void add_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
+@@ -104,6 +106,7 @@ struct hb_sparseset_t
+   void del_range (hb_codepoint_t a, hb_codepoint_t b) { s.del_range (a, b); }
+ 
+   bool get (hb_codepoint_t g) const { return s.get (g); }
++  bool may_have (hb_codepoint_t g) const { return get (g); }
+ 
+   /* Has interface. */
+   bool operator [] (hb_codepoint_t k) const { return get (k); }
+@@ -118,6 +121,9 @@ struct hb_sparseset_t
+   hb_sparseset_t& operator << (const hb_codepoint_pair_t& range)
+   { add_range (range.first, range.second); return *this; }
+ 
++  bool may_intersect (const hb_sparseset_t &other) const
++  { return s.may_intersect (other.s); }
++
+   bool intersects (hb_codepoint_t first, hb_codepoint_t last) const
+   { return s.intersects (first, last); }
+ 
+@@ -164,7 +170,7 @@ struct hb_set_t : hb_sparseset_t
+   ~hb_set_t () = default;
+   hb_set_t () : sparseset () {};
+   hb_set_t (const hb_set_t &o) : sparseset ((sparseset &) o) {};
+-  hb_set_t (hb_set_t&& o) : sparseset (std::move ((sparseset &) o)) {}
++  hb_set_t (hb_set_t&& o)  noexcept : sparseset (std::move ((sparseset &) o)) {}
+   hb_set_t& operator = (const hb_set_t&) = default;
+   hb_set_t& operator = (hb_set_t&&) = default;
+   hb_set_t (std::initializer_list lst) : sparseset (lst) {}
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-shape-plan.cc b/src/java.desktop/share/native/libharfbuzz/hb-shape-plan.cc
+index 970aaa0b4..19188f800 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-shape-plan.cc
++++ b/src/java.desktop/share/native/libharfbuzz/hb-shape-plan.cc
+@@ -233,7 +233,7 @@ hb_shape_plan_create2 (hb_face_t                     *face,
+                   num_coords,
+                   shaper_list);
+ 
+-  if (unlikely (props->direction == HB_DIRECTION_INVALID))
++  if (unlikely (!HB_DIRECTION_IS_VALID (props->direction)))
+     return hb_shape_plan_get_empty ();
+ 
+   hb_shape_plan_t *shape_plan;
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-shape.h b/src/java.desktop/share/native/libharfbuzz/hb-shape.h
+index bf7eafd2b..294105d3c 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-shape.h
++++ b/src/java.desktop/share/native/libharfbuzz/hb-shape.h
+@@ -53,6 +53,7 @@ hb_shape_full (hb_font_t          *font,
+                unsigned int        num_features,
+                const char * const *shaper_list);
+ 
++#ifdef HB_EXPERIMENTAL_API
+ HB_EXTERN hb_bool_t
+ hb_shape_justify (hb_font_t          *font,
+                   hb_buffer_t        *buffer,
+@@ -64,6 +65,7 @@ hb_shape_justify (hb_font_t          *font,
+                   float              *advance, /* IN/OUT */
+                   hb_tag_t           *var_tag, /* OUT */
+                   float              *var_value /* OUT */);
++#endif
+ 
+ HB_EXTERN const char **
+ hb_shape_list_shapers (void);
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-style.cc b/src/java.desktop/share/native/libharfbuzz/hb-style.cc
+index 20d4696b9..7378a8895 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-style.cc
++++ b/src/java.desktop/share/native/libharfbuzz/hb-style.cc
+@@ -61,8 +61,8 @@ _hb_ratio_to_angle (float r)
+  * @style_tag: a style tag.
+  *
+  * Searches variation axes of a #hb_font_t object for a specific axis first,
+- * if not set, then tries to get default style values from different
+- * tables of the font.
++ * if not set, first tries to get default style values in `STAT` table
++ * then tries to polyfill from different tables of the font.
+  *
+  * Returns: Corresponding axis or default value to a style tag.
+  *
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-subset-cff-common.hh b/src/java.desktop/share/native/libharfbuzz/hb-subset-cff-common.hh
+index 4213f7e71..62206e0f5 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-subset-cff-common.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-subset-cff-common.hh
+@@ -115,7 +115,7 @@ struct str_encoder_t
+       encode_byte (OpCode_BCD);
+ 
+       // Based on:
+-      // https://github.com/fonttools/fonttools/blob/97ed3a61cde03e17b8be36f866192fbd56f1d1a7/Lib/fontTools/misc/psCharStrings.py#L265-L294
++      // https://github.com/fonttools/fonttools/blob/0738c41dfbcbc213ab9263f486ef0cccc6eb5ce5/Lib/fontTools/misc/psCharStrings.py#L267-L316
+ 
+       char buf[16];
+       /* FontTools has the following comment:
+@@ -133,6 +133,10 @@ struct str_encoder_t
+       (void) hb_uselocale (((void) freelocale (clocale), oldlocale));
+ 
+       char *s = buf;
++      size_t len;
++      char *comma = strchr (s, ',');
++      if (comma) // Comma for some European locales in case no uselocale available.
++        *comma = '.';
+       if (s[0] == '0' && s[1] == '.')
+         s++;
+       else if (s[0] == '-' && s[1] == '0' && s[2] == '.')
+@@ -140,6 +144,45 @@ struct str_encoder_t
+         s[1] = '-';
+         s++;
+       }
++      else if ((len = strlen (s)) > 3 && !strcmp (s + len - 3, "000"))
++      {
++        unsigned exponent = len - 3;
++        char *s2 = s + exponent - 1;
++        while (*s2 == '0' && exponent > 1)
++        {
++          s2--;
++          exponent++;
++        }
++        snprintf (s2 + 1, sizeof (buf) - (s2 + 1 - buf), "E%u", exponent);
++      }
++      else
++      {
++        char *dot = strchr (s, '.');
++        char *e = strchr (s, 'E');
++        if (dot && e)
++        {
++          memmove (dot, dot + 1, e - (dot + 1));
++          int exponent = atoi (e + 1);
++          int new_exponent = exponent - (e - (dot + 1));
++          if (new_exponent == 1)
++          {
++            e[-1] = '0';
++            e[0] = '\0';
++          }
++          else
++            snprintf (e - 1, sizeof (buf) - (e - 1 - buf), "E%d", new_exponent);
++        }
++      }
++      if ((s[0] == '.' && s[1] == '0') || (s[0] == '-' && s[1] == '.' && s[2] == '0'))
++      {
++        int sign = s[0] == '-';
++        char *s2 = s + sign + 1;
++        while (*s2 == '0')
++          s2++;
++        len = strlen (s2);
++        memmove (s + sign, s2, len);
++        snprintf (s + sign + len, sizeof (buf) - (s + sign + len - buf), "E-%u", (unsigned) (strlen (s + sign) - 1));
++      }
+       hb_vector_t nibbles;
+       while (*s)
+       {
+@@ -155,20 +198,22 @@ struct str_encoder_t
+             {
+               s++;
+               nibbles.push (0x0C); // E-
+-              continue;
++            } else {
++              if (c2 == '+')
++                s++;
++              nibbles.push (0x0B); // E
+             }
+-            if (c2 == '+')
++            if (*s == '0')
+               s++;
+-            nibbles.push (0x0B); // E
+             continue;
+           }
+ 
+-          case '.': case ',': // Comma for some European locales in case no uselocale available.
++          case '.':
+             nibbles.push (0x0A); // .
+             continue;
+ 
+           case '-':
+-            nibbles.push (0x0E); // .
++            nibbles.push (0x0E); // -
+             continue;
+         }
+ 
+@@ -1083,7 +1128,7 @@ struct subr_subsetter_t
+       if (opstr.op == OpCode_callsubr || opstr.op == OpCode_callgsubr)
+         size += 3;
+     }
+-    if (!buff.alloc (buff.length + size, true))
++    if (!buff.alloc_exact (buff.length + size))
+       return false;
+ 
+     for (auto &opstr : str.values)
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-subset-cff1.cc b/src/java.desktop/share/native/libharfbuzz/hb-subset-cff1.cc
+index 780bf34ef..4938c048d 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-subset-cff1.cc
++++ b/src/java.desktop/share/native/libharfbuzz/hb-subset-cff1.cc
+@@ -45,7 +45,7 @@ struct remap_sid_t
+   void alloc (unsigned size)
+   {
+     map.alloc (size);
+-    vector.alloc (size, true);
++    vector.alloc_exact (size);
+   }
+ 
+   bool in_error () const
+@@ -620,6 +620,12 @@ struct cff1_subset_plan
+     drop_hints = plan->flags & HB_SUBSET_FLAGS_NO_HINTING;
+     desubroutinize = plan->flags & HB_SUBSET_FLAGS_DESUBROUTINIZE;
+ 
++ #ifdef HB_EXPERIMENTAL_API
++    min_charstrings_off_size = (plan->flags & HB_SUBSET_FLAGS_IFTB_REQUIREMENTS) ? 4 : 0;
++ #else
++    min_charstrings_off_size = 0;
++ #endif
++
+     subset_charset = !acc.is_predef_charset ();
+     if (!subset_charset)
+       /* check whether the subset renumbers any glyph IDs */
+@@ -778,13 +784,43 @@ struct cff1_subset_plan
+   unsigned int  topDictModSIDs[name_dict_values_t::ValCount];
+ 
+   bool          desubroutinize = false;
++
++  unsigned      min_charstrings_off_size = 0;
+ };
+ } // namespace OT
+ 
++static bool _serialize_cff1_charstrings (hb_serialize_context_t *c,
++                                         struct OT::cff1_subset_plan &plan,
++                                         const OT::cff1::accelerator_subset_t  &acc)
++{
++  c->push ();
++
++  unsigned data_size = 0;
++  unsigned total_size = CFF1CharStrings::total_size (plan.subset_charstrings, &data_size, plan.min_charstrings_off_size);
++  if (unlikely (!c->start_zerocopy (total_size)))
++    return false;
++
++  auto *cs = c->start_embed ();
++  if (unlikely (!cs->serialize (c, plan.subset_charstrings, &data_size, plan.min_charstrings_off_size))) {
++    c->pop_discard ();
++    return false;
++  }
++
++  plan.info.char_strings_link = c->pop_pack (false);
++  return true;
++}
++
+ bool
+ OT::cff1::accelerator_subset_t::serialize (hb_serialize_context_t *c,
+                                            struct OT::cff1_subset_plan &plan) const
+ {
++  /* push charstrings onto the object stack first which will ensure it packs as the last
++     object in the table. Keeping the chastrings last satisfies the requirements for patching
++     via IFTB. If this ordering needs to be changed in the future, charstrings should be left
++     at the end whenever HB_SUBSET_FLAGS_ITFB_REQUIREMENTS is enabled. */
++  if (!_serialize_cff1_charstrings(c, plan, *this))
++    return false;
++
+   /* private dicts & local subrs */
+   for (int i = (int) privateDicts.length; --i >= 0 ;)
+   {
+@@ -823,25 +859,6 @@ OT::cff1::accelerator_subset_t::serialize (hb_serialize_context_t *c,
+   if (!is_CID ())
+     plan.info.privateDictInfo = plan.fontdicts_mod[0].privateDictInfo;
+ 
+-  /* CharStrings */
+-  {
+-    c->push ();
+-
+-    unsigned data_size = 0;
+-    unsigned total_size = CFF1CharStrings::total_size (plan.subset_charstrings, &data_size);
+-    if (unlikely (!c->start_zerocopy (total_size)))
+-       return false;
+-
+-    auto *cs = c->start_embed ();
+-    if (likely (cs->serialize (c, plan.subset_charstrings, &data_size)))
+-      plan.info.char_strings_link = c->pop_pack (false);
+-    else
+-    {
+-      c->pop_discard ();
+-      return false;
+-    }
+-  }
+-
+   /* FDArray (FD Index) */
+   if (fdArray != &Null (CFF1FDArray))
+   {
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-subset-cff2.cc b/src/java.desktop/share/native/libharfbuzz/hb-subset-cff2.cc
+index 1f9bc209e..1074d2403 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-subset-cff2.cc
++++ b/src/java.desktop/share/native/libharfbuzz/hb-subset-cff2.cc
+@@ -248,7 +248,7 @@ struct cff2_subr_subsetter_t : subr_subsetter_t normalized_coords) :
+     c (c), varStore (varStore), normalized_coords (normalized_coords) {}
+ 
+@@ -284,7 +284,7 @@ struct cff2_private_blend_encoder_param_t
+   unsigned ivs = 0;
+   unsigned region_count = 0;
+   hb_vector_t scalars;
+-  const  CFF2VariationStore *varStore = nullptr;
++  const  CFF2ItemVariationStore *varStore = nullptr;
+   hb_array_t normalized_coords;
+ };
+ 
+@@ -378,7 +378,7 @@ struct cff2_private_dict_blend_opset_t : dict_opset_t
+ struct cff2_private_dict_op_serializer_t : op_serializer_t
+ {
+   cff2_private_dict_op_serializer_t (bool desubroutinize_, bool drop_hints_, bool pinned_,
+-                                     const CFF::CFF2VariationStore* varStore_,
++                                     const CFF::CFF2ItemVariationStore* varStore_,
+                                      hb_array_t normalized_coords_)
+     : desubroutinize (desubroutinize_), drop_hints (drop_hints_), pinned (pinned_),
+       varStore (varStore_), normalized_coords (normalized_coords_) {}
+@@ -416,7 +416,7 @@ struct cff2_private_dict_op_serializer_t : op_serializer_t
+   const bool desubroutinize;
+   const bool drop_hints;
+   const bool pinned;
+-  const CFF::CFF2VariationStore* varStore;
++  const CFF::CFF2ItemVariationStore* varStore;
+   hb_array_t normalized_coords;
+ };
+ 
+@@ -439,6 +439,12 @@ struct cff2_subset_plan
+     desubroutinize = plan->flags & HB_SUBSET_FLAGS_DESUBROUTINIZE ||
+                      pinned; // For instancing we need this path
+ 
++ #ifdef HB_EXPERIMENTAL_API
++    min_charstrings_off_size = (plan->flags & HB_SUBSET_FLAGS_IFTB_REQUIREMENTS) ? 4 : 0;
++ #else
++    min_charstrings_off_size = 0;
++ #endif
++
+     if (desubroutinize)
+     {
+       /* Flatten global & local subrs */
+@@ -510,14 +516,45 @@ struct cff2_subset_plan
+ 
+   bool      drop_hints = false;
+   bool      desubroutinize = false;
++
++  unsigned  min_charstrings_off_size = 0;
+ };
+ } // namespace OT
+ 
++static bool _serialize_cff2_charstrings (hb_serialize_context_t *c,
++                             cff2_subset_plan &plan,
++                             const OT::cff2::accelerator_subset_t  &acc)
++{
++  c->push ();
++
++  unsigned data_size = 0;
++  unsigned total_size = CFF2CharStrings::total_size (plan.subset_charstrings, &data_size, plan.min_charstrings_off_size);
++  if (unlikely (!c->start_zerocopy (total_size)))
++    return false;
++
++  auto *cs = c->start_embed ();
++  if (unlikely (!cs->serialize (c, plan.subset_charstrings, &data_size, plan.min_charstrings_off_size)))
++  {
++    c->pop_discard ();
++    return false;
++  }
++
++  plan.info.char_strings_link = c->pop_pack (false);
++  return true;
++}
++
+ bool
+ OT::cff2::accelerator_subset_t::serialize (hb_serialize_context_t *c,
+                                            struct cff2_subset_plan &plan,
+                                            hb_array_t normalized_coords) const
+ {
++  /* push charstrings onto the object stack first which will ensure it packs as the last
++     object in the table. Keeping the chastrings last satisfies the requirements for patching
++     via IFTB. If this ordering needs to be changed in the future, charstrings should be left
++     at the end whenever HB_SUBSET_FLAGS_ITFB_REQUIREMENTS is enabled. */
++  if (!_serialize_cff2_charstrings(c, plan, *this))
++    return false;
++
+   /* private dicts & local subrs */
+   hb_vector_t  private_dict_infos;
+   if (unlikely (!private_dict_infos.resize (plan.subset_fdcount))) return false;
+@@ -556,25 +593,6 @@ OT::cff2::accelerator_subset_t::serialize (hb_serialize_context_t *c,
+     }
+   }
+ 
+-  /* CharStrings */
+-  {
+-    c->push ();
+-
+-    unsigned data_size = 0;
+-    unsigned total_size = CFF2CharStrings::total_size (plan.subset_charstrings, &data_size);
+-    if (unlikely (!c->start_zerocopy (total_size)))
+-       return false;
+-
+-    auto *cs = c->start_embed ();
+-    if (likely (cs->serialize (c, plan.subset_charstrings, &data_size)))
+-      plan.info.char_strings_link = c->pop_pack (false);
+-    else
+-    {
+-      c->pop_discard ();
+-      return false;
+-    }
+-  }
+-
+   /* FDSelect */
+   if (fdSelect != &Null (CFF2FDSelect))
+   {
+@@ -610,10 +628,10 @@ OT::cff2::accelerator_subset_t::serialize (hb_serialize_context_t *c,
+   }
+ 
+   /* variation store */
+-  if (varStore != &Null (CFF2VariationStore) &&
++  if (varStore != &Null (CFF2ItemVariationStore) &&
+       !plan.pinned)
+   {
+-    auto *dest = c->push ();
++    auto *dest = c->push ();
+     if (unlikely (!dest->serialize (c, varStore)))
+     {
+       c->pop_discard ();
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-subset-input.cc b/src/java.desktop/share/native/libharfbuzz/hb-subset-input.cc
+index 8c67f7f23..bbe50b1fb 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-subset-input.cc
++++ b/src/java.desktop/share/native/libharfbuzz/hb-subset-input.cc
+@@ -24,6 +24,7 @@
+  * Google Author(s): Garret Rieger, Rod Sheeter, Behdad Esfahbod
+  */
+ 
++#include "hb-subset-instancer-solver.hh"
+ #include "hb-subset.hh"
+ #include "hb-set.hh"
+ #include "hb-utf.hh"
+@@ -50,7 +51,6 @@ hb_subset_input_t::hb_subset_input_t ()
+     HB_TAG ('k', 'e', 'r', 'n'),
+ 
+     // Copied from fontTools:
+-    HB_TAG ('B', 'A', 'S', 'E'),
+     HB_TAG ('J', 'S', 'T', 'F'),
+     HB_TAG ('D', 'S', 'I', 'G'),
+     HB_TAG ('E', 'B', 'D', 'T'),
+@@ -123,6 +123,12 @@ hb_subset_input_t::hb_subset_input_t ()
+     //justify
+     HB_TAG ('j', 'a', 'l', 't'), // HarfBuzz doesn't use; others might
+ 
++    //East Asian spacing
++    HB_TAG ('c', 'h', 'w', 's'),
++    HB_TAG ('v', 'c', 'h', 'w'),
++    HB_TAG ('h', 'a', 'l', 't'),
++    HB_TAG ('v', 'h', 'a', 'l'),
++
+     //private
+     HB_TAG ('H', 'a', 'r', 'f'),
+     HB_TAG ('H', 'A', 'R', 'F'),
+@@ -406,11 +412,52 @@ hb_subset_input_keep_everything (hb_subset_input_t *input)
+   hb_subset_input_set_flags (input,
+                              HB_SUBSET_FLAGS_NOTDEF_OUTLINE |
+                              HB_SUBSET_FLAGS_GLYPH_NAMES |
++                             HB_SUBSET_FLAGS_NAME_LEGACY |
+                              HB_SUBSET_FLAGS_NO_PRUNE_UNICODE_RANGES |
+                              HB_SUBSET_FLAGS_PASSTHROUGH_UNRECOGNIZED);
+ }
+ 
+ #ifndef HB_NO_VAR
++/**
++ * hb_subset_input_pin_all_axes_to_default: (skip)
++ * @input: a #hb_subset_input_t object.
++ * @face: a #hb_face_t object.
++ *
++ * Pin all axes to default locations in the given subset input object.
++ *
++ * All axes in a font must be pinned. Additionally, `CFF2` table, if present,
++ * will be de-subroutinized.
++ *
++ * Return value: `true` if success, `false` otherwise
++ *
++ * Since: 8.3.1
++ **/
++HB_EXTERN hb_bool_t
++hb_subset_input_pin_all_axes_to_default (hb_subset_input_t  *input,
++                                         hb_face_t          *face)
++{
++  unsigned axis_count = hb_ot_var_get_axis_count (face);
++  if (!axis_count) return false;
++
++  hb_ot_var_axis_info_t *axis_infos = (hb_ot_var_axis_info_t *) hb_calloc (axis_count, sizeof (hb_ot_var_axis_info_t));
++  if (unlikely (!axis_infos)) return false;
++
++  (void) hb_ot_var_get_axis_infos (face, 0, &axis_count, axis_infos);
++
++  for (unsigned i = 0; i < axis_count; i++)
++  {
++    hb_tag_t axis_tag = axis_infos[i].tag;
++    double default_val = (double) axis_infos[i].default_value;
++    if (!input->axes_location.set (axis_tag, Triple (default_val, default_val, default_val)))
++    {
++      hb_free (axis_infos);
++      return false;
++    }
++  }
++  hb_free (axis_infos);
++  return true;
++}
++
+ /**
+  * hb_subset_input_pin_axis_to_default: (skip)
+  * @input: a #hb_subset_input_t object.
+@@ -435,7 +482,7 @@ hb_subset_input_pin_axis_to_default (hb_subset_input_t  *input,
+   if (!hb_ot_var_find_axis_info (face, axis_tag, &axis_info))
+     return false;
+ 
+-  float default_val = axis_info.default_value;
++  double default_val = (double) axis_info.default_value;
+   return input->axes_location.set (axis_tag, Triple (default_val, default_val, default_val));
+ }
+ 
+@@ -465,37 +512,32 @@ hb_subset_input_pin_axis_location (hb_subset_input_t  *input,
+   if (!hb_ot_var_find_axis_info (face, axis_tag, &axis_info))
+     return false;
+ 
+-  float val = hb_clamp(axis_value, axis_info.min_value, axis_info.max_value);
++  double val = hb_clamp((double) axis_value, (double) axis_info.min_value, (double) axis_info.max_value);
+   return input->axes_location.set (axis_tag, Triple (val, val, val));
+ }
+ 
+-#ifdef HB_EXPERIMENTAL_API
+ /**
+  * hb_subset_input_set_axis_range: (skip)
+  * @input: a #hb_subset_input_t object.
+  * @face: a #hb_face_t object.
+  * @axis_tag: Tag of the axis
+- * @axis_min_value: Minimum value of the axis variation range to set
+- * @axis_max_value: Maximum value of the axis variation range to set
+- * @axis_def_value: Default value of the axis variation range to set, in case of
+- * null, it'll be determined automatically
++ * @axis_min_value: Minimum value of the axis variation range to set, if NaN the existing min will be used.
++ * @axis_max_value: Maximum value of the axis variation range to set  if NaN the existing max will be used.
++ * @axis_def_value: Default value of the axis variation range to set, if NaN the existing default will be used.
+  *
+  * Restricting the range of variation on an axis in the given subset input object.
+  * New min/default/max values will be clamped if they're not within the fvar axis range.
+- * If the new default value is null:
+- * If the fvar axis default value is within the new range, then new default
+- * value is the same as original default value.
++ *
+  * If the fvar axis default value is not within the new range, the new default
+  * value will be changed to the new min or max value, whichever is closer to the fvar
+  * axis default.
+  *
+  * Note: input min value can not be bigger than input max value. If the input
+  * default value is not within the new min/max range, it'll be clamped.
+- * Note: currently it supports gvar and cvar tables only.
+  *
+  * Return value: `true` if success, `false` otherwise
+  *
+- * XSince: EXPERIMENTAL
++ * Since: 8.5.0
+  **/
+ HB_EXTERN hb_bool_t
+ hb_subset_input_set_axis_range (hb_subset_input_t  *input,
+@@ -503,22 +545,195 @@ hb_subset_input_set_axis_range (hb_subset_input_t  *input,
+                                 hb_tag_t            axis_tag,
+                                 float               axis_min_value,
+                                 float               axis_max_value,
+-                                float              *axis_def_value /* IN, maybe NULL */)
++                                float               axis_def_value)
+ {
+-  if (axis_min_value > axis_max_value)
+-    return false;
+-
+   hb_ot_var_axis_info_t axis_info;
+   if (!hb_ot_var_find_axis_info (face, axis_tag, &axis_info))
+     return false;
+ 
+-  float new_min_val = hb_clamp(axis_min_value, axis_info.min_value, axis_info.max_value);
+-  float new_max_val = hb_clamp(axis_max_value, axis_info.min_value, axis_info.max_value);
+-  float new_default_val = axis_def_value ? *axis_def_value : axis_info.default_value;
+-  new_default_val = hb_clamp(new_default_val, new_min_val, new_max_val);
+-  return input->axes_location.set (axis_tag, Triple (new_min_val, new_default_val, new_max_val));
++  float min = !std::isnan(axis_min_value) ? axis_min_value : axis_info.min_value;
++  float max = !std::isnan(axis_max_value) ? axis_max_value : axis_info.max_value;
++  float def = !std::isnan(axis_def_value) ? axis_def_value : axis_info.default_value;
++
++  if (min > max)
++    return false;
++
++  float new_min_val = hb_clamp(min, axis_info.min_value, axis_info.max_value);
++  float new_max_val = hb_clamp(max, axis_info.min_value, axis_info.max_value);
++  float new_default_val = hb_clamp(def, new_min_val, new_max_val);
++  return input->axes_location.set (axis_tag, Triple ((double) new_min_val, (double) new_default_val, (double) new_max_val));
++}
++
++/**
++ * hb_subset_input_get_axis_range: (skip)
++ * @input: a #hb_subset_input_t object.
++ * @axis_tag: Tag of the axis
++ * @axis_min_value: Set to the previously configured minimum value of the axis variation range.
++ * @axis_max_value: Set to the previously configured maximum value of the axis variation range.
++ * @axis_def_value: Set to the previously configured default value of the axis variation range.
++ *
++ * Gets the axis range assigned by previous calls to hb_subset_input_set_axis_range.
++ *
++ * Return value: `true` if a range has been set for this axis tag, `false` otherwise.
++ *
++ * Since: 8.5.0
++ **/
++HB_EXTERN hb_bool_t
++hb_subset_input_get_axis_range (hb_subset_input_t  *input,
++                                hb_tag_t            axis_tag,
++                                float              *axis_min_value,
++                                float              *axis_max_value,
++                                float              *axis_def_value)
++
++{
++  Triple* triple;
++  if (!input->axes_location.has(axis_tag, &triple)) {
++    return false;
++  }
++
++  *axis_min_value = triple->minimum;
++  *axis_def_value = triple->middle;
++  *axis_max_value = triple->maximum;
++  return true;
++}
++
++/**
++ * hb_subset_axis_range_from_string:
++ * @str: a string to parse
++ * @len: length of @str, or -1 if str is NULL terminated
++ * @axis_min_value: (out): the axis min value to initialize with the parsed value
++ * @axis_max_value: (out): the axis max value to initialize with the parsed value
++ * @axis_def_value: (out): the axis default value to initialize with the parse
++ * value
++ *
++ * Parses a string into a subset axis range(min, def, max).
++ * Axis positions string is in the format of min:def:max or min:max
++ * When parsing axis positions, empty values as meaning the existing value for that part
++ * E.g: :300:500
++ * Specifies min = existing, def = 300, max = 500
++ * In the output axis_range, if a value should be set to it's default value,
++ * then it will be set to NaN
++ *
++ * Return value:
++ * `true` if @str is successfully parsed, `false` otherwise
++ *
++ * Since: 10.2.0
++ */
++HB_EXTERN hb_bool_t
++hb_subset_axis_range_from_string (const char *str, int len,
++                                  float *axis_min_value,
++                                  float *axis_max_value,
++                                  float *axis_def_value)
++{
++  if (len < 0)
++    len = strlen (str);
++
++  const char *end = str + len;
++  const char* part = strpbrk (str, ":");
++  if (!part)
++  {
++    // Single value.
++    if (strcmp (str, "drop") == 0)
++    {
++      *axis_min_value = NAN;
++      *axis_def_value = NAN;
++      *axis_max_value = NAN;
++      return true;
++    }
++
++    double v;
++    if (!hb_parse_double (&str, end, &v)) return false;
++
++    *axis_min_value = v;
++    *axis_def_value = v;
++    *axis_max_value = v;
++    return true;
++  }
++
++  float values[3];
++  int count = 0;
++  for (int i = 0; i < 3; i++) {
++    count++;
++    if (!*str || part == str)
++    {
++      values[i] = NAN;
++
++      if (part == NULL) break;
++      str = part + 1;
++      part = strpbrk (str, ":");
++      continue;
++    }
++
++    double v;
++    if (!hb_parse_double (&str, part, &v)) return false;
++    values[i] = v;
++
++    if (part == NULL) break;
++    str = part + 1;
++    part = strpbrk (str, ":");
++  }
++
++  if (count == 2)
++  {
++    *axis_min_value = values[0];
++    *axis_def_value = NAN;
++    *axis_max_value = values[1];
++    return true;
++  }
++  else if (count == 3)
++  {
++    *axis_min_value = values[0];
++    *axis_def_value = values[1];
++    *axis_max_value = values[2];
++    return true;
++  }
++  return false;
++}
++
++/**
++ * hb_subset_axis_range_to_string:
++ * @input: a #hb_subset_input_t object.
++ * @axis_tag: an axis to convert
++ * @buf: (array length=size) (out caller-allocates): output string
++ * @size: the allocated size of @buf
++ *
++ * Converts an axis range into a `NULL`-terminated string in the format
++ * understood by hb_subset_axis_range_from_string(). The client in responsible for
++ * allocating big enough size for @buf, 128 bytes is more than enough.
++ *
++ * Since: 10.2.0
++ */
++HB_EXTERN void
++hb_subset_axis_range_to_string (hb_subset_input_t *input,
++                                hb_tag_t axis_tag,
++                                char *buf, unsigned size)
++{
++  if (unlikely (!size)) return;
++  Triple* triple;
++  if (!input->axes_location.has(axis_tag, &triple)) {
++    return;
++  }
++
++  char s[128];
++  unsigned len = 0;
++
++  hb_locale_t clocale HB_UNUSED;
++  hb_locale_t oldlocale HB_UNUSED;
++  oldlocale = hb_uselocale (clocale = newlocale (LC_ALL_MASK, "C", NULL));
++  len += hb_max (0, snprintf (s, ARRAY_LENGTH (s) - len, "%g", (double) triple->minimum));
++  s[len++] = ':';
++
++  len += hb_max (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%g", (double) triple->middle));
++  s[len++] = ':';
++
++  len += hb_max (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%g", (double) triple->maximum));
++  (void) hb_uselocale (((void) freelocale (clocale), oldlocale));
++
++  assert (len < ARRAY_LENGTH (s));
++  len = hb_min (len, size - 1);
++  hb_memcpy (buf, s, len);
++  buf[len] = '\0';
+ }
+-#endif
+ #endif
+ 
+ /**
+@@ -653,7 +868,7 @@ hb_subset_input_override_name_table (hb_subset_input_t  *input,
+         src = hb_utf8_t::next (src, src_end, &unicode, replacement);
+         if (unicode >= 0x0080u)
+         {
+-          printf ("Non-ascii character detected, ignored...This API supports acsii characters only for mac platform\n");
++          printf ("Non-ascii character detected, ignored...This API supports ascii characters only for mac platform\n");
+           return false;
+         }
+       }
+@@ -667,5 +882,4 @@ hb_subset_input_override_name_table (hb_subset_input_t  *input,
+   input->name_table_overrides.set (hb_ot_name_record_ids_t (platform_id, encoding_id, language_id, name_id), name_bytes);
+   return true;
+ }
+-
+ #endif
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-subset-instancer-iup.hh b/src/java.desktop/share/native/libharfbuzz/hb-subset-instancer-iup.hh
+new file mode 100644
+index 000000000..01987bd25
+--- /dev/null
++++ b/src/java.desktop/share/native/libharfbuzz/hb-subset-instancer-iup.hh
+@@ -0,0 +1,37 @@
++/*
++ * Copyright © 2024  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_SUBSET_INSTANCER_IUP_HH
++#define HB_SUBSET_INSTANCER_IUP_HH
++
++#include "hb-subset-plan.hh"
++/* given contour points and deltas, optimize a set of referenced points within error
++ * tolerance. Returns optimized referenced point indices */
++HB_INTERNAL bool iup_delta_optimize (const contour_point_vector_t& contour_points,
++                                     const hb_vector_t& x_deltas,
++                                     const hb_vector_t& y_deltas,
++                                     hb_vector_t& opt_indices, /* OUT */
++                                     double tolerance = 0.0);
++
++#endif /* HB_SUBSET_INSTANCER_IUP_HH */
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-subset-instancer-solver.cc b/src/java.desktop/share/native/libharfbuzz/hb-subset-instancer-solver.cc
+index 8ec36e3e8..c67fee421 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-subset-instancer-solver.cc
++++ b/src/java.desktop/share/native/libharfbuzz/hb-subset-instancer-solver.cc
+@@ -32,17 +32,17 @@
+  * This should be safe.
+  */
+ 
+-constexpr static float EPSILON = 1.f / (1 << 14);
+-constexpr static float MAX_F2DOT14 = float (0x7FFF) / (1 << 14);
++constexpr static double EPSILON = 1.0 / (1 << 14);
++constexpr static double MAX_F2DOT14 = double (0x7FFF) / (1 << 14);
+ 
+ static inline Triple _reverse_negate(const Triple &v)
+ { return {-v.maximum, -v.middle, -v.minimum}; }
+ 
+ 
+-static inline float supportScalar (float coord, const Triple &tent)
++static inline double supportScalar (double coord, const Triple &tent)
+ {
+   /* Copied from VarRegionAxis::evaluate() */
+-  float start = tent.minimum, peak = tent.middle, end = tent.maximum;
++  double start = tent.minimum, peak = tent.middle, end = tent.maximum;
+ 
+   if (unlikely (start > peak || peak > end))
+     return 1.;
+@@ -62,20 +62,20 @@ static inline float supportScalar (float coord, const Triple &tent)
+     return  (end - coord) / (end - peak);
+ }
+ 
+-static inline result_t
++static inline rebase_tent_result_t
+ _solve (Triple tent, Triple axisLimit, bool negative = false)
+ {
+-  float axisMin = axisLimit.minimum;
+-  float axisDef = axisLimit.middle;
+-  float axisMax = axisLimit.maximum;
+-  float lower = tent.minimum;
+-  float peak  = tent.middle;
+-  float upper = tent.maximum;
++  double axisMin = axisLimit.minimum;
++  double axisDef = axisLimit.middle;
++  double axisMax = axisLimit.maximum;
++  double lower = tent.minimum;
++  double peak  = tent.middle;
++  double upper = tent.maximum;
+ 
+   // Mirror the problem such that axisDef <= peak
+   if (axisDef > peak)
+   {
+-    result_t vec = _solve (_reverse_negate (tent),
++    rebase_tent_result_t vec = _solve (_reverse_negate (tent),
+                            _reverse_negate (axisLimit),
+                            !negative);
+ 
+@@ -98,7 +98,7 @@ _solve (Triple tent, Triple axisLimit, bool negative = false)
+    *    axisMin     axisDef    axisMax   lower     upper
+    */
+   if (axisMax <= lower && axisMax < peak)
+-      return result_t{};  // No overlap
++      return rebase_tent_result_t{};  // No overlap
+ 
+   /* case 2: Only the peak and outermost bound fall outside the new limit;
+    * we keep the deltaset, update peak and outermost bound and scale deltas
+@@ -130,10 +130,10 @@ _solve (Triple tent, Triple axisLimit, bool negative = false)
+    */
+   if (axisMax < peak)
+   {
+-    float mult = supportScalar (axisMax, tent);
++    double mult = supportScalar (axisMax, tent);
+     tent = Triple{lower, axisMax, axisMax};
+ 
+-    result_t vec = _solve (tent, axisLimit);
++    rebase_tent_result_t vec = _solve (tent, axisLimit);
+ 
+     for (auto &p : vec)
+       p = hb_pair (p.first * mult, p.second);
+@@ -143,13 +143,13 @@ _solve (Triple tent, Triple axisLimit, bool negative = false)
+ 
+   // lower <= axisDef <= peak <= axisMax
+ 
+-  float gain = supportScalar (axisDef, tent);
+-  result_t out {hb_pair (gain, Triple{})};
++  double gain = supportScalar (axisDef, tent);
++  rebase_tent_result_t out {hb_pair (gain, Triple{})};
+ 
+   // First, the positive side
+ 
+   // outGain is the scalar of axisMax at the tent.
+-  float outGain = supportScalar (axisMax, tent);
++  double outGain = supportScalar (axisMax, tent);
+ 
+   /* Case 3a: Gain is more than outGain. The tent down-slope crosses
+    * the axis into negative. We have to split it into multiples.
+@@ -168,13 +168,15 @@ _solve (Triple tent, Triple axisLimit, bool negative = false)
+    *                           |
+    *                      crossing
+    */
+-  if (gain > outGain)
++  if (gain >= outGain)
+   {
++    // Note that this is the branch taken if both gain and outGain are 0.
++
+     // Crossing point on the axis.
+-    float crossing = peak + (1 - gain) * (upper - peak);
++    double crossing = peak + (1 - gain) * (upper - peak);
+ 
+-    Triple loc{axisDef, peak, crossing};
+-    float scalar = 1.f;
++    Triple loc{hb_max (lower, axisDef), peak, crossing};
++    double scalar = 1.0;
+ 
+     // The part before the crossing point.
+     out.push (hb_pair (scalar - gain, loc));
+@@ -189,7 +191,7 @@ _solve (Triple tent, Triple axisLimit, bool negative = false)
+     if (upper >= axisMax)
+     {
+       Triple loc {crossing, axisMax, axisMax};
+-      float scalar = outGain;
++      double scalar = outGain;
+ 
+       out.push (hb_pair (scalar - gain, loc));
+     }
+@@ -219,11 +221,11 @@ _solve (Triple tent, Triple axisLimit, bool negative = false)
+ 
+       // Downslope.
+       Triple loc1 {crossing, upper, axisMax};
+-      float scalar1 = 0.f;
++      double scalar1 = 0.0;
+ 
+       // Eternity justify.
+       Triple loc2 {upper, axisMax, axisMax};
+-      float scalar2 = 0.f;
++      double scalar2 = 0.0;
+ 
+       out.push (hb_pair (scalar1 - gain, loc1));
+       out.push (hb_pair (scalar2 - gain, loc2));
+@@ -252,9 +254,12 @@ _solve (Triple tent, Triple axisLimit, bool negative = false)
+      *                    |      |  newUpper
+      *              axisDef      axisMax
+      */
+-    float newUpper = peak + (1 - gain) * (upper - peak);
+-    assert (axisMax <= newUpper);  // Because outGain >= gain
+-    if (newUpper <= axisDef + (axisMax - axisDef) * 2)
++    double newUpper = peak + (1 - gain) * (upper - peak);
++    assert (axisMax <= newUpper);  // Because outGain > gain
++    /* Disabled because ots doesn't like us:
++     * https://github.com/fonttools/fonttools/issues/3350 */
++
++    if (false && (newUpper <= axisDef + (axisMax - axisDef) * 2))
+     {
+       upper = newUpper;
+       if (!negative && axisDef + (axisMax - axisDef) * MAX_F2DOT14 < upper)
+@@ -265,7 +270,7 @@ _solve (Triple tent, Triple axisLimit, bool negative = false)
+       }
+ 
+       Triple loc {hb_max (axisDef, lower), peak, upper};
+-      float scalar = 1.f;
++      double scalar = 1.0;
+ 
+       out.push (hb_pair (scalar - gain, loc));
+     }
+@@ -289,10 +294,10 @@ _solve (Triple tent, Triple axisLimit, bool negative = false)
+     else
+     {
+       Triple loc1 {hb_max (axisDef, lower), peak, axisMax};
+-      float scalar1 = 1.f;
++      double scalar1 = 1.0;
+ 
+       Triple loc2 {peak, axisMax, axisMax};
+-      float scalar2 = outGain;
++      double scalar2 = outGain;
+ 
+       out.push (hb_pair (scalar1 - gain, loc1));
+       // Don't add a dirac delta!
+@@ -320,7 +325,7 @@ _solve (Triple tent, Triple axisLimit, bool negative = false)
+   if (lower <= axisMin)
+   {
+     Triple loc {axisMin, axisMin, axisDef};
+-    float scalar = supportScalar (axisMin, tent);
++    double scalar = supportScalar (axisMin, tent);
+ 
+     out.push (hb_pair (scalar - gain, loc));
+   }
+@@ -348,11 +353,11 @@ _solve (Triple tent, Triple axisLimit, bool negative = false)
+ 
+     // Downslope.
+     Triple loc1 {axisMin, lower, axisDef};
+-    float scalar1 = 0.f;
++    double scalar1 = 0.0;
+ 
+     // Eternity justify.
+     Triple loc2 {axisMin, axisMin, lower};
+-    float scalar2 = 0.f;
++    double scalar2 = 0.0;
+ 
+     out.push (hb_pair (scalar1 - gain, loc1));
+     out.push (hb_pair (scalar2 - gain, loc2));
+@@ -364,19 +369,19 @@ _solve (Triple tent, Triple axisLimit, bool negative = false)
+ static inline TripleDistances _reverse_triple_distances (const TripleDistances &v)
+ { return TripleDistances (v.positive, v.negative); }
+ 
+-float renormalizeValue (float v, const Triple &triple,
+-                        const TripleDistances &triple_distances, bool extrapolate)
++double renormalizeValue (double v, const Triple &triple,
++                         const TripleDistances &triple_distances, bool extrapolate)
+ {
+-  float lower = triple.minimum, def = triple.middle, upper = triple.maximum;
++  double lower = triple.minimum, def = triple.middle, upper = triple.maximum;
+   assert (lower <= def && def <= upper);
+ 
+   if (!extrapolate)
+-      v = hb_max (hb_min (v, upper), lower);
++    v = hb_clamp (v, lower, upper);
+ 
+   if (v == def)
+-    return 0.f;
++    return 0.0;
+ 
+-  if (def < 0.f)
++  if (def < 0.0)
+     return -renormalizeValue (-v, _reverse_negate (triple),
+                               _reverse_triple_distances (triple_distances), extrapolate);
+ 
+@@ -385,14 +390,14 @@ float renormalizeValue (float v, const Triple &triple,
+     return (v - def) / (upper - def);
+ 
+   /* v < def */
+-  if (lower >= 0.f)
++  if (lower >= 0.0)
+     return (v - def) / (def - lower);
+ 
+   /* lower < 0 and v < default */
+-  float total_distance = triple_distances.negative * (-lower) + triple_distances.positive * def;
++  double total_distance = triple_distances.negative * (-lower) + triple_distances.positive * def;
+ 
+-  float v_distance;
+-  if (v >= 0.f)
++  double v_distance;
++  if (v >= 0.0)
+     v_distance = (def - v) * triple_distances.positive;
+   else
+     v_distance = (-v) * triple_distances.negative + triple_distances.positive * def;
+@@ -400,18 +405,18 @@ float renormalizeValue (float v, const Triple &triple,
+   return (-v_distance) /total_distance;
+ }
+ 
+-result_t
++rebase_tent_result_t
+ rebase_tent (Triple tent, Triple axisLimit, TripleDistances axis_triple_distances)
+ {
+-  assert (-1.f <= axisLimit.minimum && axisLimit.minimum <= axisLimit.middle && axisLimit.middle <= axisLimit.maximum && axisLimit.maximum <= +1.f);
+-  assert (-2.f <= tent.minimum && tent.minimum <= tent.middle && tent.middle <= tent.maximum && tent.maximum <= +2.f);
+-  assert (tent.middle != 0.f);
++  assert (-1.0 <= axisLimit.minimum && axisLimit.minimum <= axisLimit.middle && axisLimit.middle <= axisLimit.maximum && axisLimit.maximum <= +1.0);
++  assert (-2.0 <= tent.minimum && tent.minimum <= tent.middle && tent.middle <= tent.maximum && tent.maximum <= +2.0);
++  assert (tent.middle != 0.0);
+ 
+-  result_t sols = _solve (tent, axisLimit);
++  rebase_tent_result_t sols = _solve (tent, axisLimit);
+ 
+-  auto n = [&axisLimit, &axis_triple_distances] (float v) { return renormalizeValue (v, axisLimit, axis_triple_distances); };
++  auto n = [&axisLimit, &axis_triple_distances] (double v) { return renormalizeValue (v, axisLimit, axis_triple_distances); };
+ 
+-  result_t out;
++  rebase_tent_result_t out;
+   for (auto &p : sols)
+   {
+     if (!p.first) continue;
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-subset-instancer-solver.hh b/src/java.desktop/share/native/libharfbuzz/hb-subset-instancer-solver.hh
+index e8ca1dc4e..9764dcc17 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-subset-instancer-solver.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-subset-instancer-solver.hh
+@@ -30,24 +30,24 @@
+ /* pre-normalized distances */
+ struct TripleDistances
+ {
+-  TripleDistances (): negative (1.f), positive (1.f) {}
+-  TripleDistances (float neg_, float pos_): negative (neg_), positive (pos_) {}
+-  TripleDistances (float min, float default_, float max)
++  TripleDistances (): negative (1.0), positive (1.0) {}
++  TripleDistances (double neg_, double pos_): negative (neg_), positive (pos_) {}
++  TripleDistances (double min, double default_, double max)
+   {
+     negative = default_ - min;
+     positive = max - default_;
+   }
+ 
+-  float negative;
+-  float positive;
++  double negative;
++  double positive;
+ };
+ 
+ struct Triple {
+ 
+   Triple () :
+-    minimum (0.f), middle (0.f), maximum (0.f) {}
++    minimum (0.0), middle (0.0), maximum (0.0) {}
+ 
+-  Triple (float minimum_, float middle_, float maximum_) :
++  Triple (double minimum_, double middle_, double maximum_) :
+     minimum (minimum_), middle (middle_), maximum (maximum_) {}
+ 
+   bool operator == (const Triple &o) const
+@@ -63,7 +63,7 @@ struct Triple {
+   bool is_point () const
+   { return minimum == middle && middle == maximum; }
+ 
+-  bool contains (float point) const
++  bool contains (double point) const
+   { return minimum <= point && point <= maximum; }
+ 
+   /* from hb_array_t hash ()*/
+@@ -82,18 +82,18 @@ struct Triple {
+   }
+ 
+ 
+-  float minimum;
+-  float middle;
+-  float maximum;
++  double minimum;
++  double middle;
++  double maximum;
+ };
+ 
+-using result_item_t = hb_pair_t;
+-using result_t = hb_vector_t;
++using rebase_tent_result_item_t = hb_pair_t;
++using rebase_tent_result_t = hb_vector_t;
+ 
+ /* renormalize a normalized value v to the range of an axis,
+  * considering the prenormalized distances as well as the new axis limits.
+  * Ported from fonttools */
+-HB_INTERNAL float renormalizeValue (float v, const Triple &triple,
++HB_INTERNAL double renormalizeValue (double v, const Triple &triple,
+                                     const TripleDistances &triple_distances,
+                                     bool extrapolate = true);
+ /* Given a tuple (lower,peak,upper) "tent" and new axis limits
+@@ -107,6 +107,8 @@ HB_INTERNAL float renormalizeValue (float v, const Triple &triple,
+  * If tent value is Triple{}, that is a special deltaset that should
+  * be always-enabled (called "gain").
+  */
+-HB_INTERNAL result_t rebase_tent (Triple tent, Triple axisLimit, TripleDistances axis_triple_distances);
++HB_INTERNAL rebase_tent_result_t rebase_tent (Triple tent,
++                                              Triple axisLimit,
++                                              TripleDistances axis_triple_distances);
+ 
+ #endif /* HB_SUBSET_INSTANCER_SOLVER_HH */
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-subset-plan-member-list.hh b/src/java.desktop/share/native/libharfbuzz/hb-subset-plan-member-list.hh
+index 8bc1fcb56..ade8278c4 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-subset-plan-member-list.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-subset-plan-member-list.hh
+@@ -70,6 +70,9 @@ HB_SUBSET_PLAN_MEMBER (hb_set_t, _glyphset_colred)
+ HB_SUBSET_PLAN_MEMBER (hb_map_t, gsub_lookups)
+ HB_SUBSET_PLAN_MEMBER (hb_map_t, gpos_lookups)
+ 
++//use_mark_sets mapping: old->new
++HB_SUBSET_PLAN_MEMBER (hb_map_t, used_mark_sets_map)
++
+ //active langsys we'd like to retain
+ HB_SUBSET_PLAN_MEMBER (hb_hashmap_t E(>), gsub_langsys)
+ HB_SUBSET_PLAN_MEMBER (hb_hashmap_t E(>), gpos_langsys)
+@@ -87,9 +90,24 @@ HB_SUBSET_PLAN_MEMBER (hb_hashmap_t E(>), gpo
+ HB_SUBSET_PLAN_MEMBER (hb_hashmap_t E(), gsub_feature_substitutes_map)
+ HB_SUBSET_PLAN_MEMBER (hb_hashmap_t E(), gpos_feature_substitutes_map)
+ 
++// old feature_indexes set, used to reinstate the old features
++HB_SUBSET_PLAN_MEMBER (hb_set_t, gsub_old_features)
++HB_SUBSET_PLAN_MEMBER (hb_set_t, gpos_old_features)
++
++//feature_index->pair of (address of old feature, feature tag), used for inserting a catch all record
++//if necessary
++HB_SUBSET_PLAN_MEMBER (hb_hashmap_t E()>), gsub_old_feature_idx_tag_map)
++HB_SUBSET_PLAN_MEMBER (hb_hashmap_t E()>), gpos_old_feature_idx_tag_map)
++
+ //active layers/palettes we'd like to retain
+ HB_SUBSET_PLAN_MEMBER (hb_map_t, colrv1_layers)
+ HB_SUBSET_PLAN_MEMBER (hb_map_t, colr_palettes)
++//colrv1 varstore retained varidx mapping
++HB_SUBSET_PLAN_MEMBER (hb_vector_t, colrv1_varstore_inner_maps)
++//colrv1 retained varidx -> (new varidx, delta) mapping
++HB_SUBSET_PLAN_MEMBER (mutable hb_hashmap_t E()>), colrv1_variation_idx_delta_map)
++//colrv1 retained new delta set index -> new varidx mapping
++HB_SUBSET_PLAN_MEMBER (hb_map_t, colrv1_new_deltaset_idx_varidx_map)
+ 
+ //Old layout item variation index -> (New varidx, delta) mapping
+ HB_SUBSET_PLAN_MEMBER (mutable hb_hashmap_t E()>), layout_variation_idx_delta_map)
+@@ -128,6 +146,15 @@ HB_SUBSET_PLAN_MEMBER (mutable hb_vector_t, bounds_height_vec)
+ //map: new_gid -> contour points vector
+ HB_SUBSET_PLAN_MEMBER (mutable hb_hashmap_t E(), new_gid_contour_points_map)
+ 
++//new gids set for composite glyphs
++HB_SUBSET_PLAN_MEMBER (hb_set_t, composite_new_gids)
++
++//Old BASE item variation index -> (New varidx, 0) mapping
++HB_SUBSET_PLAN_MEMBER (mutable hb_hashmap_t E()>), base_variation_idx_map)
++
++//BASE table varstore retained varidx mapping
++HB_SUBSET_PLAN_MEMBER (hb_vector_t, base_varstore_inner_maps)
++
+ #ifdef HB_EXPERIMENTAL_API
+ // name table overrides map: hb_ot_name_record_ids_t-> name string new value or
+ // None to indicate should remove
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-subset-plan.cc b/src/java.desktop/share/native/libharfbuzz/hb-subset-plan.cc
+index b9cc4fd0b..fb5282916 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-subset-plan.cc
++++ b/src/java.desktop/share/native/libharfbuzz/hb-subset-plan.cc
+@@ -32,6 +32,7 @@
+ 
+ #include "hb-ot-cmap-table.hh"
+ #include "hb-ot-glyf-table.hh"
++#include "hb-ot-layout-base-table.hh"
+ #include "hb-ot-layout-gdef-table.hh"
+ #include "hb-ot-layout-gpos-table.hh"
+ #include "hb-ot-layout-gsub-table.hh"
+@@ -150,7 +151,8 @@ static void _collect_layout_indices (hb_subset_plan_t     *plan,
+                                      hb_set_t             *feature_indices, /* OUT */
+                                      hb_hashmap_t> *feature_record_cond_idx_map, /* OUT */
+                                      hb_hashmap_t *feature_substitutes_map, /* OUT */
+-                                     bool& insert_catch_all_feature_variation_record)
++                                     hb_set_t& catch_all_record_feature_idxes, /* OUT */
++                                     hb_hashmap_t>& catch_all_record_idx_feature_map /* OUT */)
+ {
+   unsigned num_features = table.get_feature_count ();
+   hb_vector_t features;
+@@ -186,7 +188,7 @@ static void _collect_layout_indices (hb_subset_plan_t     *plan,
+       &plan->axes_location,
+       feature_record_cond_idx_map,
+       feature_substitutes_map,
+-      insert_catch_all_feature_variation_record,
++      catch_all_record_feature_idxes,
+       feature_indices,
+       false,
+       false,
+@@ -208,17 +210,25 @@ static void _collect_layout_indices (hb_subset_plan_t     *plan,
+     f->add_lookup_indexes_to (lookup_indices);
+   }
+ 
++#ifndef HB_NO_VAR
++  if (catch_all_record_feature_idxes)
++  {
++    for (unsigned feature_index : catch_all_record_feature_idxes)
++    {
++      const OT::Feature& f = table.get_feature (feature_index);
++      f.add_lookup_indexes_to (lookup_indices);
++      const void *tag = reinterpret_cast (&(table.get_feature_list ().get_tag (feature_index)));
++      catch_all_record_idx_feature_map.set (feature_index, hb_pair (&f, tag));
++    }
++  }
++
+   // If all axes are pinned then all feature variations will be dropped so there's no need
+   // to collect lookups from them.
+   if (!plan->all_axes_pinned)
+-  {
+-    // TODO(qxliu76): this collection doesn't work correctly for feature variations that are dropped
+-    //                but not applied. The collection will collect and retain the lookup indices
+-    //                associated with those dropped but not activated rules. Since partial instancing
+-    //                isn't yet supported this isn't an issue yet but will need to be fixed for
+-    //                partial instancing.
+-    table.feature_variation_collect_lookups (feature_indices, feature_substitutes_map, lookup_indices);
+-  }
++    table.feature_variation_collect_lookups (feature_indices,
++                                             plan->user_axes_location.is_empty () ? nullptr: feature_record_cond_idx_map,
++                                             lookup_indices);
++#endif
+ }
+ 
+ 
+@@ -302,7 +312,8 @@ _closure_glyphs_lookups_features (hb_subset_plan_t   *plan,
+                                   script_langsys_map *langsys_map,
+                                   hb_hashmap_t> *feature_record_cond_idx_map,
+                                   hb_hashmap_t *feature_substitutes_map,
+-                                  bool& insert_catch_all_feature_variation_record)
++                                  hb_set_t &catch_all_record_feature_idxes,
++                                  hb_hashmap_t>& catch_all_record_idx_feature_map)
+ {
+   hb_blob_ptr_t table = plan->source_table ();
+   hb_tag_t table_tag = table->tableTag;
+@@ -313,7 +324,8 @@ _closure_glyphs_lookups_features (hb_subset_plan_t   *plan,
+                               &feature_indices,
+                               feature_record_cond_idx_map,
+                               feature_substitutes_map,
+-                              insert_catch_all_feature_variation_record);
++                              catch_all_record_feature_idxes,
++                              catch_all_record_idx_feature_map);
+ 
+   if (table_tag == HB_OT_TAG_GSUB && !(plan->flags & HB_SUBSET_FLAGS_NO_LAYOUT_CLOSURE))
+     hb_ot_layout_lookups_substitute_closure (plan->source,
+@@ -386,13 +398,56 @@ _get_hb_font_with_variations (const hb_subset_plan_t *plan)
+   return font;
+ }
+ 
++static inline void
++_remap_variation_indices (const OT::ItemVariationStore &var_store,
++                          const hb_set_t &variation_indices,
++                          const hb_vector_t& normalized_coords,
++                          bool calculate_delta, /* not pinned at default */
++                          bool no_variations, /* all axes pinned */
++                          hb_hashmap_t> &variation_idx_delta_map /* OUT */)
++{
++  if (&var_store == &Null (OT::ItemVariationStore)) return;
++  unsigned subtable_count = var_store.get_sub_table_count ();
++  float *store_cache = var_store.create_cache ();
++
++  unsigned new_major = 0, new_minor = 0;
++  unsigned last_major = (variation_indices.get_min ()) >> 16;
++  for (unsigned idx : variation_indices)
++  {
++    int delta = 0;
++    if (calculate_delta)
++      delta = roundf (var_store.get_delta (idx, normalized_coords.arrayZ,
++                                           normalized_coords.length, store_cache));
++
++    if (no_variations)
++    {
++      variation_idx_delta_map.set (idx, hb_pair_t (HB_OT_LAYOUT_NO_VARIATIONS_INDEX, delta));
++      continue;
++    }
++
++    uint16_t major = idx >> 16;
++    if (major >= subtable_count) break;
++    if (major != last_major)
++    {
++      new_minor = 0;
++      ++new_major;
++    }
++
++    unsigned new_idx = (new_major << 16) + new_minor;
++    variation_idx_delta_map.set (idx, hb_pair_t (new_idx, delta));
++    ++new_minor;
++    last_major = major;
++  }
++  var_store.destroy_cache (store_cache);
++}
++
+ static inline void
+ _collect_layout_variation_indices (hb_subset_plan_t* plan)
+ {
+   hb_blob_ptr_t gdef = plan->source_table ();
+   hb_blob_ptr_t gpos = plan->source_table ();
+ 
+-  if (!gdef->has_data ())
++  if (!gdef->has_data () || !gdef->has_var_store ())
+   {
+     gdef.destroy ();
+     gpos.destroy ();
+@@ -408,18 +463,47 @@ _collect_layout_variation_indices (hb_subset_plan_t* plan)
+   if (hb_ot_layout_has_positioning (plan->source))
+     gpos->collect_variation_indices (&c);
+ 
+-  gdef->remap_layout_variation_indices (&varidx_set,
+-                                        plan->normalized_coords,
+-                                        !plan->pinned_at_default,
+-                                        plan->all_axes_pinned,
+-                                        &plan->layout_variation_idx_delta_map);
++  _remap_variation_indices (gdef->get_var_store (),
++                            varidx_set, plan->normalized_coords,
++                            !plan->pinned_at_default,
++                            plan->all_axes_pinned,
++                            plan->layout_variation_idx_delta_map);
+ 
+-  unsigned subtable_count = gdef->has_var_store () ? gdef->get_var_store ().get_sub_table_count () : 0;
++  unsigned subtable_count = gdef->get_var_store ().get_sub_table_count ();
+   _generate_varstore_inner_maps (varidx_set, subtable_count, plan->gdef_varstore_inner_maps);
+ 
+   gdef.destroy ();
+   gpos.destroy ();
+ }
++
++#ifndef HB_NO_BASE
++static inline void
++_collect_base_variation_indices (hb_subset_plan_t* plan)
++{
++  hb_blob_ptr_t base = plan->source_table ();
++  if (!base->has_var_store ())
++  {
++    base.destroy ();
++    return;
++  }
++
++  hb_set_t varidx_set;
++  base->collect_variation_indices (plan, varidx_set);
++  const OT::ItemVariationStore &var_store = base->get_var_store ();
++  unsigned subtable_count = var_store.get_sub_table_count ();
++
++
++  _remap_variation_indices (var_store, varidx_set,
++                            plan->normalized_coords,
++                            !plan->pinned_at_default,
++                            plan->all_axes_pinned,
++                            plan->base_variation_idx_map);
++  _generate_varstore_inner_maps (varidx_set, subtable_count, plan->base_varstore_inner_maps);
++
++  base.destroy ();
++}
++
++#endif
+ #endif
+ 
+ static inline void
+@@ -431,12 +515,45 @@ _cmap_closure (hb_face_t           *face,
+   cmap.table->closure_glyphs (unicodes, glyphset);
+ }
+ 
+-static void _colr_closure (hb_face_t *face,
+-                           hb_map_t *layers_map,
+-                           hb_map_t *palettes_map,
++#ifndef HB_NO_VAR
++static void
++_remap_colrv1_delta_set_index_indices (const OT::DeltaSetIndexMap &index_map,
++                                       const hb_set_t &delta_set_idxes,
++                                       hb_hashmap_t> &variation_idx_delta_map, /* IN/OUT */
++                                       hb_map_t &new_deltaset_idx_varidx_map /* OUT */)
++{
++  if (!index_map.get_map_count ())
++    return;
++
++  hb_hashmap_t> delta_set_idx_delta_map;
++  unsigned new_delta_set_idx = 0;
++  for (unsigned delta_set_idx : delta_set_idxes)
++  {
++    unsigned var_idx = index_map.map (delta_set_idx);
++    unsigned new_varidx = HB_OT_LAYOUT_NO_VARIATIONS_INDEX;
++    int delta = 0;
++
++    if (var_idx != HB_OT_LAYOUT_NO_VARIATIONS_INDEX)
++    {
++      hb_pair_t *new_varidx_delta;
++      if (!variation_idx_delta_map.has (var_idx, &new_varidx_delta)) continue;
++
++      new_varidx = hb_first (*new_varidx_delta);
++      delta = hb_second (*new_varidx_delta);
++    }
++
++    new_deltaset_idx_varidx_map.set (new_delta_set_idx, new_varidx);
++    delta_set_idx_delta_map.set (delta_set_idx, hb_pair_t (new_delta_set_idx, delta));
++    new_delta_set_idx++;
++  }
++  variation_idx_delta_map = std::move (delta_set_idx_delta_map);
++}
++#endif
++
++static void _colr_closure (hb_subset_plan_t* plan,
+                            hb_set_t *glyphs_colred)
+ {
+-  OT::COLR::accelerator_t colr (face);
++  OT::COLR::accelerator_t colr (plan->source);
+   if (!colr.is_valid ()) return;
+ 
+   hb_set_t palette_indices, layer_indices;
+@@ -448,11 +565,45 @@ static void _colr_closure (hb_face_t *face,
+   glyphs_colred->union_ (glyphset_colrv0);
+ 
+   //closure for COLRv1
+-  colr.closure_forV1 (glyphs_colred, &layer_indices, &palette_indices);
++  hb_set_t variation_indices, delta_set_indices;
++  colr.closure_forV1 (glyphs_colred, &layer_indices, &palette_indices, &variation_indices, &delta_set_indices);
+ 
+   colr.closure_V0palette_indices (glyphs_colred, &palette_indices);
+-  _remap_indexes (&layer_indices, layers_map);
+-  _remap_palette_indexes (&palette_indices, palettes_map);
++  _remap_indexes (&layer_indices, &plan->colrv1_layers);
++  _remap_palette_indexes (&palette_indices, &plan->colr_palettes);
++
++#ifndef HB_NO_VAR
++  if (!colr.has_var_store () || !variation_indices) return;
++
++  const OT::ItemVariationStore &var_store = colr.get_var_store ();
++  // generated inner_maps is used by ItemVariationStore serialize(), which is subset only
++  unsigned subtable_count = var_store.get_sub_table_count ();
++  _generate_varstore_inner_maps (variation_indices, subtable_count, plan->colrv1_varstore_inner_maps);
++
++  /* colr variation indices mapping during planning phase:
++   * generate colrv1_variation_idx_delta_map. When delta set index map is not
++   * included, it's a mapping from varIdx-> (new varIdx,delta). Otherwise, it's
++   * a mapping from old delta set idx-> (new delta set idx, delta). Mapping
++   * delta set indices is the same as gid mapping.
++   * Besides, we need to generate a delta set idx-> new var_idx map for updating
++   * delta set index map if exists. This map will be updated again after
++   * instancing. */
++  if (!plan->all_axes_pinned)
++  {
++    _remap_variation_indices (var_store,
++                              variation_indices,
++                              plan->normalized_coords,
++                              false, /* no need to calculate delta for COLR during planning */
++                              plan->all_axes_pinned,
++                              plan->colrv1_variation_idx_delta_map);
++
++    if (colr.has_delta_set_index_map ())
++      _remap_colrv1_delta_set_index_indices (colr.get_delta_set_index_map (),
++                                             delta_set_indices,
++                                             plan->colrv1_variation_idx_delta_map,
++                                             plan->colrv1_new_deltaset_idx_varidx_map);
++  }
++#endif
+ }
+ 
+ static inline void
+@@ -465,6 +616,24 @@ _math_closure (hb_subset_plan_t *plan,
+   math.destroy ();
+ }
+ 
++static inline void
++_remap_used_mark_sets (hb_subset_plan_t *plan,
++                       hb_map_t& used_mark_sets_map)
++{
++  hb_blob_ptr_t gdef = plan->source_table ();
++
++  if (!gdef->has_data () || !gdef->has_mark_glyph_sets ())
++  {
++    gdef.destroy ();
++    return;
++  }
++
++  hb_set_t used_mark_sets;
++  gdef->get_mark_glyph_sets ().collect_used_mark_sets (plan->_glyphset_gsub, used_mark_sets);
++  gdef.destroy ();
++
++  _remap_indexes (&used_mark_sets, &used_mark_sets_map);
++}
+ 
+ static inline void
+ _remove_invalid_gids (hb_set_t *glyphs,
+@@ -473,6 +642,36 @@ _remove_invalid_gids (hb_set_t *glyphs,
+   glyphs->del_range (num_glyphs, HB_SET_VALUE_INVALID);
+ }
+ 
++template
++static void
++_fill_unicode_and_glyph_map(hb_subset_plan_t *plan,
++                            I unicode_iterator,
++                            F unicode_to_gid_for_iterator,
++                            G unicode_to_gid_general)
++{
++  for (hb_codepoint_t cp : unicode_iterator)
++  {
++    hb_codepoint_t gid = unicode_to_gid_for_iterator(cp);
++    if (!GID_ALWAYS_EXISTS && gid == HB_MAP_VALUE_INVALID)
++    {
++      DEBUG_MSG(SUBSET, nullptr, "Drop U+%04X; no gid", cp);
++      continue;
++    }
++
++    plan->codepoint_to_glyph->set (cp, gid);
++    plan->unicode_to_new_gid_list.push (hb_pair (cp, gid));
++  }
++}
++
++template
++static void
++_fill_unicode_and_glyph_map(hb_subset_plan_t *plan,
++                            I unicode_iterator,
++                            F unicode_to_gid_for_iterator)
++{
++  _fill_unicode_and_glyph_map(plan, unicode_iterator, unicode_to_gid_for_iterator, unicode_to_gid_for_iterator);
++}
++
+ static void
+ _populate_unicodes_to_retain (const hb_set_t *unicodes,
+                               const hb_set_t *glyphs,
+@@ -480,6 +679,7 @@ _populate_unicodes_to_retain (const hb_set_t *unicodes,
+ {
+   OT::cmap::accelerator_t cmap (plan->source);
+   unsigned size_threshold = plan->source->get_num_glyphs ();
++
+   if (glyphs->is_empty () && unicodes->get_population () < size_threshold)
+   {
+ 
+@@ -492,35 +692,21 @@ _populate_unicodes_to_retain (const hb_set_t *unicodes,
+     // not excessively large (eg. an inverted set).
+     plan->unicode_to_new_gid_list.alloc (unicodes->get_population ());
+     if (!unicode_to_gid) {
+-      for (hb_codepoint_t cp : *unicodes)
+-      {
++      _fill_unicode_and_glyph_map(plan, unicodes->iter(), [&] (hb_codepoint_t cp) {
+         hb_codepoint_t gid;
+-        if (!cmap.get_nominal_glyph (cp, &gid))
+-        {
+-          DEBUG_MSG(SUBSET, nullptr, "Drop U+%04X; no gid", cp);
+-          continue;
++        if (!cmap.get_nominal_glyph (cp, &gid)) {
++          return HB_MAP_VALUE_INVALID;
+         }
+-
+-        plan->codepoint_to_glyph->set (cp, gid);
+-        plan->unicode_to_new_gid_list.push (hb_pair (cp, gid));
+-      }
++        return gid;
++      });
+     } else {
+       // Use in memory unicode to gid map it's faster then looking up from
+       // the map. This code is mostly duplicated from above to avoid doing
+       // conditionals on the presence of the unicode_to_gid map each
+       // iteration.
+-      for (hb_codepoint_t cp : *unicodes)
+-      {
+-        hb_codepoint_t gid = unicode_to_gid->get (cp);
+-        if (gid == HB_MAP_VALUE_INVALID)
+-        {
+-          DEBUG_MSG(SUBSET, nullptr, "Drop U+%04X; no gid", cp);
+-          continue;
+-        }
+-
+-        plan->codepoint_to_glyph->set (cp, gid);
+-        plan->unicode_to_new_gid_list.push (hb_pair (cp, gid));
+-      }
++      _fill_unicode_and_glyph_map(plan, unicodes->iter(), [&] (hb_codepoint_t cp) {
++        return unicode_to_gid->get (cp);
++      });
+     }
+   }
+   else
+@@ -550,42 +736,46 @@ _populate_unicodes_to_retain (const hb_set_t *unicodes,
+       plan->codepoint_to_glyph->alloc (unicodes->get_population () + glyphs->get_population ());
+ 
+       auto &gid_to_unicodes = plan->accelerator->gid_to_unicodes;
++
+       for (hb_codepoint_t gid : *glyphs)
+       {
+         auto unicodes = gid_to_unicodes.get (gid);
+-
+-        for (hb_codepoint_t cp : unicodes)
+-        {
+-          plan->codepoint_to_glyph->set (cp, gid);
+-          plan->unicode_to_new_gid_list.push (hb_pair (cp, gid));
+-        }
++        _fill_unicode_and_glyph_map(plan, unicodes, [&] (hb_codepoint_t cp) {
++          return gid;
++        },
++        [&] (hb_codepoint_t cp) {
++          return unicode_glyphid_map->get(cp);
++        });
+       }
+-      for (hb_codepoint_t cp : *unicodes)
+-      {
+-        /* Don't double-add entry. */
++
++      _fill_unicode_and_glyph_map(plan, unicodes->iter(), [&] (hb_codepoint_t cp) {
++          /* Don't double-add entry. */
+         if (plan->codepoint_to_glyph->has (cp))
+-          continue;
++          return HB_MAP_VALUE_INVALID;
+ 
+-        hb_codepoint_t *gid;
+-        if (!unicode_glyphid_map->has(cp, &gid))
+-          continue;
++        return unicode_glyphid_map->get(cp);
++      },
++      [&] (hb_codepoint_t cp) {
++          return unicode_glyphid_map->get(cp);
++      });
+ 
+-        plan->codepoint_to_glyph->set (cp, *gid);
+-        plan->unicode_to_new_gid_list.push (hb_pair (cp, *gid));
+-      }
+       plan->unicode_to_new_gid_list.qsort ();
+     }
+     else
+     {
+       plan->codepoint_to_glyph->alloc (cmap_unicodes->get_population ());
+-      for (hb_codepoint_t cp : *cmap_unicodes)
++      hb_codepoint_t first = HB_SET_VALUE_INVALID, last = HB_SET_VALUE_INVALID;
++      for (; cmap_unicodes->next_range (&first, &last); )
+       {
+-        hb_codepoint_t gid = (*unicode_glyphid_map)[cp];
+-        if (!unicodes->has (cp) && !glyphs->has (gid))
+-          continue;
+-
+-        plan->codepoint_to_glyph->set (cp, gid);
+-        plan->unicode_to_new_gid_list.push (hb_pair (cp, gid));
++        _fill_unicode_and_glyph_map(plan, hb_range(first, last + 1), [&] (hb_codepoint_t cp) {
++          hb_codepoint_t gid = (*unicode_glyphid_map)[cp];
++          if (!unicodes->has (cp) && !glyphs->has (gid))
++            return HB_MAP_VALUE_INVALID;
++          return gid;
++        },
++        [&] (hb_codepoint_t cp) {
++          return unicode_glyphid_map->get(cp);
++        });
+       }
+     }
+ 
+@@ -608,11 +798,22 @@ _populate_unicodes_to_retain (const hb_set_t *unicodes,
+     plan->unicodes.add_sorted_array (&arr.arrayZ->first, arr.length, sizeof (*arr.arrayZ));
+     plan->_glyphset_gsub.add_array (&arr.arrayZ->second, arr.length, sizeof (*arr.arrayZ));
+   }
+-}
+ 
+-#ifndef HB_COMPOSITE_OPERATIONS_PER_GLYPH
+-#define HB_COMPOSITE_OPERATIONS_PER_GLYPH 64
+-#endif
++  // Variation selectors don't have glyphs associated with them in the cmap so they will have been filtered out above
++  // but should still be retained. Add them back here.
++
++  // However, the min and max codepoints for OS/2 should be calculated without considering variation selectors,
++  // so record those first.
++  plan->os2_info.min_cmap_codepoint = plan->unicodes.get_min();
++  plan->os2_info.max_cmap_codepoint = plan->unicodes.get_max();
++
++  hb_set_t variation_selectors_to_retain;
++  cmap.collect_variation_selectors(&variation_selectors_to_retain);
++  + variation_selectors_to_retain.iter()
++  | hb_filter(unicodes)
++  | hb_sink(&plan->unicodes)
++  ;
++}
+ 
+ static unsigned
+ _glyf_add_gid_and_children (const OT::glyf_accelerator_t &glyf,
+@@ -639,18 +840,6 @@ _glyf_add_gid_and_children (const OT::glyf_accelerator_t &glyf,
+                                   operation_count,
+                                   depth);
+ 
+-#ifndef HB_NO_VAR_COMPOSITES
+-  for (auto &item : glyph.get_var_composite_iterator ())
+-   {
+-    operation_count =
+-      _glyf_add_gid_and_children (glyf,
+-                                  item.get_gid (),
+-                                  gids_to_retain,
+-                                  operation_count,
+-                                  depth);
+-   }
+-#endif
+-
+   return operation_count;
+ }
+ 
+@@ -714,7 +903,8 @@ _populate_gids_to_retain (hb_subset_plan_t* plan,
+         &plan->gsub_langsys,
+         &plan->gsub_feature_record_cond_idx_map,
+         &plan->gsub_feature_substitutes_map,
+-        plan->gsub_insert_catch_all_feature_variation_rec);
++        plan->gsub_old_features,
++        plan->gsub_old_feature_idx_tag_map);
+ 
+   if (!drop_tables->has (HB_OT_TAG_GPOS))
+     _closure_glyphs_lookups_features (
+@@ -725,7 +915,8 @@ _populate_gids_to_retain (hb_subset_plan_t* plan,
+         &plan->gpos_langsys,
+         &plan->gpos_feature_record_cond_idx_map,
+         &plan->gpos_feature_substitutes_map,
+-        plan->gpos_insert_catch_all_feature_variation_rec);
++        plan->gpos_old_features,
++        plan->gpos_old_feature_idx_tag_map);
+ #endif
+   _remove_invalid_gids (&plan->_glyphset_gsub, plan->source->get_num_glyphs ());
+ 
+@@ -739,19 +930,21 @@ _populate_gids_to_retain (hb_subset_plan_t* plan,
+   hb_set_t cur_glyphset = plan->_glyphset_mathed;
+   if (!drop_tables->has (HB_OT_TAG_COLR))
+   {
+-    _colr_closure (plan->source, &plan->colrv1_layers, &plan->colr_palettes, &cur_glyphset);
++    _colr_closure (plan, &cur_glyphset);
+     _remove_invalid_gids (&cur_glyphset, plan->source->get_num_glyphs ());
+   }
+ 
+   plan->_glyphset_colred = cur_glyphset;
+ 
++  // XXX TODO VARC closure / subset
++
+   _nameid_closure (plan, drop_tables);
+   /* Populate a full set of glyphs to retain by adding all referenced
+    * composite glyphs. */
+   if (glyf.has_data ())
+     for (hb_codepoint_t gid : cur_glyphset)
+       _glyf_add_gid_and_children (glyf, gid, &plan->_glyphset,
+-                                  cur_glyphset.get_population () * HB_COMPOSITE_OPERATIONS_PER_GLYPH);
++                                  cur_glyphset.get_population () * HB_MAX_COMPOSITE_OPERATIONS_PER_GLYPH);
+   else
+     plan->_glyphset.union_ (cur_glyphset);
+ #ifndef HB_NO_SUBSET_CFF
+@@ -871,9 +1064,11 @@ _create_old_gid_to_new_gid_map (const hb_face_t *face,
+     *num_glyphs = max_glyph + 1;
+   }
+ 
++  reverse_glyph_map->alloc (reverse_glyph_map->get_population () + new_to_old_gid_list->length);
+   + hb_iter (new_to_old_gid_list)
+   | hb_sink (reverse_glyph_map)
+   ;
++  glyph_map->alloc (glyph_map->get_population () + new_to_old_gid_list->length);
+   + hb_iter (new_to_old_gid_list)
+   | hb_map (&hb_codepoint_pair_t::reverse)
+   | hb_sink (glyph_map)
+@@ -932,9 +1127,9 @@ _normalize_axes_location (hb_face_t *face, hb_subset_plan_t *plan)
+         normalized_default = seg_maps->map (normalized_default);
+         normalized_max = seg_maps->map (normalized_max);
+       }
+-      plan->axes_location.set (axis_tag, Triple (static_cast (normalized_min / 16384.f),
+-                                                 static_cast (normalized_default / 16384.f),
+-                                                 static_cast (normalized_max / 16384.f)));
++      plan->axes_location.set (axis_tag, Triple (static_cast (normalized_min / 16384.0),
++                                                 static_cast (normalized_default / 16384.0),
++                                                 static_cast (normalized_max / 16384.0)));
+ 
+       if (normalized_default != 0)
+         plan->pinned_at_default = false;
+@@ -957,8 +1152,8 @@ _update_instance_metrics_map_from_cff2 (hb_subset_plan_t *plan)
+   OT::cff2::accelerator_t cff2 (plan->source);
+   if (!cff2.is_valid ()) return;
+ 
+-  hb_font_t *font = nullptr;
+-  if (unlikely (!plan->check_success (font = _get_hb_font_with_variations (plan))))
++  hb_font_t *font = _get_hb_font_with_variations (plan);
++  if (unlikely (!plan->check_success (font != nullptr)))
+   {
+     hb_font_destroy (font);
+     return;
+@@ -1036,8 +1231,8 @@ _update_instance_metrics_map_from_cff2 (hb_subset_plan_t *plan)
+ static bool
+ _get_instance_glyphs_contour_points (hb_subset_plan_t *plan)
+ {
+-  /* contour_points vector only needed for updating gvar table (infer delta)
+-   * during partial instancing */
++  /* contour_points vector only needed for updating gvar table (infer delta and
++   * iup delta optimization) during partial instancing */
+   if (plan->user_axes_location.is_empty () || plan->all_axes_pinned)
+     return true;
+ 
+@@ -1055,10 +1250,15 @@ _get_instance_glyphs_contour_points (hb_subset_plan_t *plan)
+     }
+ 
+     hb_codepoint_t old_gid = _.second;
+-    if (unlikely (!glyf.glyph_for_gid (old_gid).get_all_points_without_var (plan->source, all_points)))
++    auto glyph = glyf.glyph_for_gid (old_gid);
++    if (unlikely (!glyph.get_all_points_without_var (plan->source, all_points)))
+       return false;
+     if (unlikely (!plan->new_gid_contour_points_map.set (new_gid, all_points)))
+       return false;
++
++    /* composite new gids are only needed by iup delta optimization */
++    if ((plan->flags & HB_SUBSET_FLAGS_OPTIMIZE_IUP_DELTAS) && glyph.is_composite ())
++      plan->composite_new_gids.add (new_gid);
+   }
+   return true;
+ }
+@@ -1093,6 +1293,7 @@ hb_subset_plan_t::hb_subset_plan_t (hb_face_t *face,
+   user_axes_location = input->axes_location;
+   all_axes_pinned = false;
+   pinned_at_default = true;
++  has_gdef_varstore = false;
+ 
+ #ifdef HB_EXPERIMENTAL_API
+   for (auto _ : input->name_table_overrides)
+@@ -1112,6 +1313,10 @@ hb_subset_plan_t::hb_subset_plan_t (hb_face_t *face,
+ 
+   attach_accelerator_data = input->attach_accelerator_data;
+   force_long_loca = input->force_long_loca;
++#ifdef HB_EXPERIMENTAL_API
++  force_long_loca = force_long_loca || (flags & HB_SUBSET_FLAGS_IFTB_REQUIREMENTS);
++#endif
++
+   if (accel)
+     accelerator = (hb_subset_accelerator_t*) accel;
+ 
+@@ -1160,6 +1365,16 @@ hb_subset_plan_t::hb_subset_plan_t (hb_face_t *face,
+   for (auto &v : bounds_height_vec)
+     v = 0xFFFFFFFF;
+ 
++  if (!drop_tables.has (HB_OT_TAG_GDEF))
++    _remap_used_mark_sets (this, used_mark_sets_map);
++
++#ifndef HB_NO_VAR
++#ifndef HB_NO_BASE
++  if (!drop_tables.has (HB_OT_TAG_BASE))
++    _collect_base_variation_indices (this);
++#endif
++#endif
++
+   if (unlikely (in_error ()))
+     return;
+ 
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-subset-plan.hh b/src/java.desktop/share/native/libharfbuzz/hb-subset-plan.hh
+index 40a6ff112..a6bae2396 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-subset-plan.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-subset-plan.hh
+@@ -41,6 +41,13 @@ namespace OT {
+ struct Feature;
+ }
+ 
++struct os2_info_t {
++  hb_codepoint_t min_cmap_codepoint;
++  hb_codepoint_t max_cmap_codepoint;
++};
++
++typedef struct os2_info_t os2_info_t;
++
+ struct head_maxp_info_t
+ {
+   head_maxp_info_t ()
+@@ -78,10 +85,16 @@ struct contour_point_t
+           y  = x * matrix[1] + y * matrix[3];
+     x  = x_;
+   }
++
++  void add_delta (float delta_x, float delta_y)
++  {
++    x += delta_x;
++    y += delta_y;
++  }
++
+   HB_ALWAYS_INLINE
+   void translate (const contour_point_t &p) { x += p.x; y += p.y; }
+ 
+-
+   float x;
+   float y;
+   uint8_t flag;
+@@ -90,14 +103,20 @@ struct contour_point_t
+ 
+ struct contour_point_vector_t : hb_vector_t
+ {
+-  void extend (const hb_array_t &a)
++  bool add_deltas (hb_array_t deltas_x,
++                   hb_array_t deltas_y,
++                   hb_array_t indices)
+   {
+-    unsigned int old_len = length;
+-    if (unlikely (!resize (old_len + a.length, false)))
+-      return;
+-    auto arrayZ = this->arrayZ + old_len;
+-    unsigned count = a.length;
+-    hb_memcpy (arrayZ, a.arrayZ, count * sizeof (arrayZ[0]));
++    if (indices.length != deltas_x.length ||
++        indices.length != deltas_y.length)
++      return false;
++
++    for (unsigned i = 0; i < indices.length; i++)
++    {
++      if (!indices.arrayZ[i]) continue;
++      arrayZ[i].add_delta (deltas_x.arrayZ[i], deltas_y.arrayZ[i]);
++    }
++    return true;
+   }
+ };
+ 
+@@ -147,6 +166,9 @@ struct hb_subset_plan_t
+   bool gsub_insert_catch_all_feature_variation_rec;
+   bool gpos_insert_catch_all_feature_variation_rec;
+ 
++  // whether GDEF ItemVariationStore is retained
++  mutable bool has_gdef_varstore;
++
+ #define HB_SUBSET_PLAN_MEMBER(Type, Name) Type Name;
+ #include "hb-subset-plan-member-list.hh"
+ #undef HB_SUBSET_PLAN_MEMBER
+@@ -154,6 +176,8 @@ struct hb_subset_plan_t
+   //recalculated head/maxp table info after instancing
+   mutable head_maxp_info_t head_maxp_info;
+ 
++  os2_info_t os2_info;
++
+   const hb_subset_accelerator_t* accelerator;
+   hb_subset_accelerator_t* inprogress_accelerator;
+ 
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-subset-serialize.h b/src/java.desktop/share/native/libharfbuzz/hb-subset-serialize.h
+new file mode 100644
+index 000000000..9035d4ced
+--- /dev/null
++++ b/src/java.desktop/share/native/libharfbuzz/hb-subset-serialize.h
+@@ -0,0 +1,83 @@
++/*
++ * 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.
++ *
++ */
++
++#ifndef HB_SUBSET_SERIALIZE_H
++#define HB_SUBSET_SERIALIZE_H
++
++#include "hb.h"
++
++HB_BEGIN_DECLS
++
++/**
++ * hb_subset_serialize_link_t:
++ * @width: offsetSize in bytes
++ * @position: position of the offset field in bytes from
++ *            beginning of subtable
++ * @objidx: index of subtable
++ *
++ * Represents a link between two objects in the object graph
++ * to be serialized.
++ *
++ * Since: 10.2.0
++ */
++typedef struct hb_subset_serialize_link_t {
++  unsigned int width;
++  unsigned int position;
++  unsigned int objidx;
++} hb_subset_serialize_link_t;
++
++/**
++ * hb_subset_serialize_object_t:
++ * @head: start of object data
++ * @tail: end of object data
++ * @num_real_links: number of offset field in the object
++ * @real_links: array of offset info
++ * @num_virtual_links: number of objects that must be packed
++ *                     after current object in the final
++ *                     serialized order
++ * @virtual_links: array of virtual link info
++ *
++ * Represents an object in the object graph to be serialized.
++ *
++ * Since: 10.2.0
++ */
++typedef struct hb_subset_serialize_object_t {
++  char *head;
++  char *tail;
++  unsigned int num_real_links;
++  hb_subset_serialize_link_t *real_links;
++  unsigned int num_virtual_links;
++  hb_subset_serialize_link_t *virtual_links;
++} hb_subset_serialize_object_t;
++
++HB_EXTERN hb_blob_t *
++hb_subset_serialize_or_fail (hb_tag_t                      table_tag,
++                             hb_subset_serialize_object_t *hb_objects,
++                             unsigned                      num_hb_objs);
++
++
++HB_END_DECLS
++
++#endif /* HB_SUBSET_SERIALIZE_H */
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-subset.cc b/src/java.desktop/share/native/libharfbuzz/hb-subset.cc
+index c125a435b..595cafc28 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-subset.cc
++++ b/src/java.desktop/share/native/libharfbuzz/hb-subset.cc
+@@ -48,6 +48,7 @@
+ #include "hb-ot-cff2-table.hh"
+ #include "hb-ot-vorg-table.hh"
+ #include "hb-ot-name-table.hh"
++#include "hb-ot-layout-base-table.hh"
+ #include "hb-ot-layout-gsub-table.hh"
+ #include "hb-ot-layout-gpos-table.hh"
+ #include "hb-ot-var-avar-table.hh"
+@@ -294,8 +295,8 @@ _try_subset (const TableType *table,
+   DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c ran out of room; reallocating to %u bytes.",
+              HB_UNTAG (c->table_tag), buf_size);
+ 
+-  if (unlikely (buf_size > c->source_blob->length * 16 ||
+-                !buf->alloc (buf_size, true)))
++  if (unlikely (buf_size > c->source_blob->length * 256 ||
++                !buf->alloc_exact (buf_size)))
+   {
+     DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c failed to reallocate %u bytes.",
+                HB_UNTAG (c->table_tag), buf_size);
+@@ -460,9 +461,10 @@ _dependencies_satisfied (hb_subset_plan_t *plan, hb_tag_t tag,
+   case HB_OT_TAG_hmtx:
+   case HB_OT_TAG_vmtx:
+   case HB_OT_TAG_maxp:
++  case HB_OT_TAG_OS2:
+     return !plan->normalized_coords || !pending_subset_tags.has (HB_OT_TAG_glyf);
+   case HB_OT_TAG_GPOS:
+-    return !plan->normalized_coords || plan->all_axes_pinned || !pending_subset_tags.has (HB_OT_TAG_GDEF);
++    return plan->all_axes_pinned || !pending_subset_tags.has (HB_OT_TAG_GDEF);
+   default:
+     return true;
+   }
+@@ -502,6 +504,7 @@ _subset_table (hb_subset_plan_t *plan,
+   case HB_OT_TAG_CBLC: return _subset (plan, buf);
+   case HB_OT_TAG_CBDT: return true; /* skip CBDT, handled by CBLC */
+   case HB_OT_TAG_MATH: return _subset (plan, buf);
++  case HB_OT_TAG_BASE: return _subset (plan, buf);
+ 
+ #ifndef HB_NO_SUBSET_CFF
+   case HB_OT_TAG_CFF1: return _subset (plan, buf);
+@@ -547,6 +550,7 @@ _subset_table (hb_subset_plan_t *plan,
+     }
+ #endif
+     return _passthrough (plan, tag);
++
+   default:
+     if (plan->flags & HB_SUBSET_FLAGS_PASSTHROUGH_UNRECOGNIZED)
+       return _passthrough (plan, tag);
+@@ -590,14 +594,20 @@ static void _attach_accelerator_data (hb_subset_plan_t* plan,
+  * @input: input to use for the subsetting.
+  *
+  * Subsets a font according to provided input. Returns nullptr
+- * if the subset operation fails.
++ * if the subset operation fails or the face has no glyphs.
+  *
+  * Since: 2.9.0
+  **/
+ hb_face_t *
+ hb_subset_or_fail (hb_face_t *source, const hb_subset_input_t *input)
+ {
+-  if (unlikely (!input || !source)) return hb_face_get_empty ();
++  if (unlikely (!input || !source)) return nullptr;
++
++  if (unlikely (!source->get_num_glyphs ()))
++  {
++    DEBUG_MSG (SUBSET, nullptr, "No glyphs in source font.");
++    return nullptr;
++  }
+ 
+   hb_subset_plan_t *plan = hb_subset_plan_create_or_fail (source, input);
+   if (unlikely (!plan)) {
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-subset.h b/src/java.desktop/share/native/libharfbuzz/hb-subset.h
+index 8ea24da41..13fcd5332 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-subset.h
++++ b/src/java.desktop/share/native/libharfbuzz/hb-subset.h
+@@ -73,6 +73,11 @@ typedef struct hb_subset_plan_t hb_subset_plan_t;
+  * OS/2 will not be recalculated.
+  * @HB_SUBSET_FLAGS_NO_LAYOUT_CLOSURE: If set don't perform glyph closure on layout
+  * substitution rules (GSUB). Since: 7.2.0.
++ * @HB_SUBSET_FLAGS_OPTIMIZE_IUP_DELTAS: If set perform IUP delta optimization on the
++ * remaining gvar table's deltas. Since: 8.5.0
++ * @HB_SUBSET_FLAGS_IFTB_REQUIREMENTS: If set enforce requirements on the output subset
++ * to allow it to be used with incremental font transfer IFTB patches. Primarily,
++ * this forces all outline data to use long (32 bit) offsets. Since: EXPERIMENTAL
+  *
+  * List of boolean properties that can be configured on the subset input.
+  *
+@@ -90,6 +95,10 @@ typedef enum { /*< flags >*/
+   HB_SUBSET_FLAGS_GLYPH_NAMES =              0x00000080u,
+   HB_SUBSET_FLAGS_NO_PRUNE_UNICODE_RANGES =  0x00000100u,
+   HB_SUBSET_FLAGS_NO_LAYOUT_CLOSURE =        0x00000200u,
++  HB_SUBSET_FLAGS_OPTIMIZE_IUP_DELTAS     =  0x00000400u,
++#ifdef HB_EXPERIMENTAL_API
++  HB_SUBSET_FLAGS_IFTB_REQUIREMENTS       =  0x00000800u,
++#endif
+ } hb_subset_flags_t;
+ 
+ /**
+@@ -164,6 +173,10 @@ HB_EXTERN void
+ hb_subset_input_set_flags (hb_subset_input_t *input,
+                            unsigned value);
+ 
++HB_EXTERN hb_bool_t
++hb_subset_input_pin_all_axes_to_default (hb_subset_input_t  *input,
++                                         hb_face_t          *face);
++
+ HB_EXTERN hb_bool_t
+ hb_subset_input_pin_axis_to_default (hb_subset_input_t  *input,
+                                      hb_face_t          *face,
+@@ -175,15 +188,34 @@ hb_subset_input_pin_axis_location (hb_subset_input_t  *input,
+                                    hb_tag_t            axis_tag,
+                                    float               axis_value);
+ 
+-#ifdef HB_EXPERIMENTAL_API
++HB_EXTERN hb_bool_t
++hb_subset_input_get_axis_range (hb_subset_input_t  *input,
++                                hb_tag_t            axis_tag,
++                                float              *axis_min_value,
++                                float              *axis_max_value,
++                                float              *axis_def_value);
++
+ HB_EXTERN hb_bool_t
+ hb_subset_input_set_axis_range (hb_subset_input_t  *input,
+                                 hb_face_t          *face,
+                                 hb_tag_t            axis_tag,
+                                 float               axis_min_value,
+                                 float               axis_max_value,
+-                                float              *axis_def_value);
++                                float               axis_def_value);
++
++HB_EXTERN hb_bool_t
++hb_subset_axis_range_from_string (const char *str, int len,
++                                  float *axis_min_value,
++                                  float *axis_max_value,
++                                  float *axis_def_value);
+ 
++HB_EXTERN void
++hb_subset_axis_range_to_string (hb_subset_input_t *input,
++                                hb_tag_t axis_tag,
++                                char *buf,
++                                unsigned size);
++
++#ifdef HB_EXPERIMENTAL_API
+ HB_EXTERN hb_bool_t
+ hb_subset_input_override_name_table (hb_subset_input_t  *input,
+                                      hb_ot_name_id_t     name_id,
+@@ -192,7 +224,6 @@ hb_subset_input_override_name_table (hb_subset_input_t  *input,
+                                      unsigned            language_id,
+                                      const char         *name_str,
+                                      int                 str_len);
+-
+ #endif
+ 
+ HB_EXTERN hb_face_t *
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-ucd-table.hh b/src/java.desktop/share/native/libharfbuzz/hb-ucd-table.hh
+index 8d3807a80..8731a0bcf 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-ucd-table.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-ucd-table.hh
+@@ -4,7 +4,7 @@
+  *
+  *   ./gen-ucd-table.py ucd.nounihan.grouped.xml
+  *
+- * on file with this description: Unicode 15.1.0
++ * on file with this description: Unicode 16.0.0
+  */
+ 
+ #ifndef HB_UCD_TABLE_HH
+@@ -13,7 +13,7 @@
+ #include "hb.hh"
+ 
+ static const hb_script_t
+-_hb_ucd_sc_map[165] =
++_hb_ucd_sc_map[172] =
+ {
+                    HB_SCRIPT_COMMON,              HB_SCRIPT_INHERITED,
+                   HB_SCRIPT_UNKNOWN,                 HB_SCRIPT_ARABIC,
+@@ -97,7 +97,10 @@ _hb_ucd_sc_map[165] =
+                HB_SCRIPT_OLD_UYGHUR,                 HB_SCRIPT_TANGSA,
+                      HB_SCRIPT_TOTO,               HB_SCRIPT_VITHKUQI,
+                      HB_SCRIPT_MATH,                   HB_SCRIPT_KAWI,
+-              HB_SCRIPT_NAG_MUNDARI,
++              HB_SCRIPT_NAG_MUNDARI,                  HB_SCRIPT_GARAY,
++             HB_SCRIPT_GURUNG_KHEMA,              HB_SCRIPT_KIRAT_RAI,
++                  HB_SCRIPT_OL_ONAL,                HB_SCRIPT_SUNUWAR,
++                   HB_SCRIPT_TODHRI,          HB_SCRIPT_TULU_TIGALARI,
+ };
+ static const uint16_t
+ _hb_ucd_dm1_p0_map[825] =
+@@ -868,7 +871,7 @@ _hb_ucd_dm2_u32_map[638] =
+    HB_CODEPOINT_ENCODE3_11_7_14 (0x04E9u, 0x0308u, 0x04EBu),
+ };
+ static const uint64_t
+-_hb_ucd_dm2_u64_map[388] =
++_hb_ucd_dm2_u64_map[408] =
+ {
+      HB_CODEPOINT_ENCODE3 (0x05D0u, 0x05B7u, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x05D0u, 0x05B8u, 0x0000u),
+      HB_CODEPOINT_ENCODE3 (0x05D0u, 0x05BCu, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x05D1u, 0x05BCu, 0x0000u),
+@@ -1051,13 +1054,23 @@ _hb_ucd_dm2_u64_map[388] =
+      HB_CODEPOINT_ENCODE3 (0x30F0u, 0x3099u, 0x30F8u),   HB_CODEPOINT_ENCODE3 (0x30F1u, 0x3099u, 0x30F9u),
+      HB_CODEPOINT_ENCODE3 (0x30F2u, 0x3099u, 0x30FAu),   HB_CODEPOINT_ENCODE3 (0x30FDu, 0x3099u, 0x30FEu),
+      HB_CODEPOINT_ENCODE3 (0xFB49u, 0x05C1u, 0x0000u),   HB_CODEPOINT_ENCODE3 (0xFB49u, 0x05C2u, 0x0000u),
++   HB_CODEPOINT_ENCODE3 (0x105D2u, 0x0307u, 0x105C9u), HB_CODEPOINT_ENCODE3 (0x105DAu, 0x0307u, 0x105E4u),
+   HB_CODEPOINT_ENCODE3 (0x11099u, 0x110BAu, 0x1109Au),HB_CODEPOINT_ENCODE3 (0x1109Bu, 0x110BAu, 0x1109Cu),
+   HB_CODEPOINT_ENCODE3 (0x110A5u, 0x110BAu, 0x110ABu),HB_CODEPOINT_ENCODE3 (0x11131u, 0x11127u, 0x1112Eu),
+   HB_CODEPOINT_ENCODE3 (0x11132u, 0x11127u, 0x1112Fu),HB_CODEPOINT_ENCODE3 (0x11347u, 0x1133Eu, 0x1134Bu),
+-  HB_CODEPOINT_ENCODE3 (0x11347u, 0x11357u, 0x1134Cu),HB_CODEPOINT_ENCODE3 (0x114B9u, 0x114B0u, 0x114BCu),
+-  HB_CODEPOINT_ENCODE3 (0x114B9u, 0x114BAu, 0x114BBu),HB_CODEPOINT_ENCODE3 (0x114B9u, 0x114BDu, 0x114BEu),
+-  HB_CODEPOINT_ENCODE3 (0x115B8u, 0x115AFu, 0x115BAu),HB_CODEPOINT_ENCODE3 (0x115B9u, 0x115AFu, 0x115BBu),
+-  HB_CODEPOINT_ENCODE3 (0x11935u, 0x11930u, 0x11938u), HB_CODEPOINT_ENCODE3 (0x1D157u, 0x1D165u, 0x0000u),
++  HB_CODEPOINT_ENCODE3 (0x11347u, 0x11357u, 0x1134Cu),HB_CODEPOINT_ENCODE3 (0x11382u, 0x113C9u, 0x11383u),
++  HB_CODEPOINT_ENCODE3 (0x11384u, 0x113BBu, 0x11385u),HB_CODEPOINT_ENCODE3 (0x1138Bu, 0x113C2u, 0x1138Eu),
++  HB_CODEPOINT_ENCODE3 (0x11390u, 0x113C9u, 0x11391u),HB_CODEPOINT_ENCODE3 (0x113C2u, 0x113B8u, 0x113C7u),
++  HB_CODEPOINT_ENCODE3 (0x113C2u, 0x113C2u, 0x113C5u),HB_CODEPOINT_ENCODE3 (0x113C2u, 0x113C9u, 0x113C8u),
++  HB_CODEPOINT_ENCODE3 (0x114B9u, 0x114B0u, 0x114BCu),HB_CODEPOINT_ENCODE3 (0x114B9u, 0x114BAu, 0x114BBu),
++  HB_CODEPOINT_ENCODE3 (0x114B9u, 0x114BDu, 0x114BEu),HB_CODEPOINT_ENCODE3 (0x115B8u, 0x115AFu, 0x115BAu),
++  HB_CODEPOINT_ENCODE3 (0x115B9u, 0x115AFu, 0x115BBu),HB_CODEPOINT_ENCODE3 (0x11935u, 0x11930u, 0x11938u),
++  HB_CODEPOINT_ENCODE3 (0x1611Eu, 0x1611Eu, 0x16121u),HB_CODEPOINT_ENCODE3 (0x1611Eu, 0x1611Fu, 0x16123u),
++  HB_CODEPOINT_ENCODE3 (0x1611Eu, 0x16120u, 0x16125u),HB_CODEPOINT_ENCODE3 (0x1611Eu, 0x16129u, 0x16122u),
++  HB_CODEPOINT_ENCODE3 (0x16121u, 0x1611Fu, 0x16126u),HB_CODEPOINT_ENCODE3 (0x16121u, 0x16120u, 0x16128u),
++  HB_CODEPOINT_ENCODE3 (0x16122u, 0x1611Fu, 0x16127u),HB_CODEPOINT_ENCODE3 (0x16129u, 0x1611Fu, 0x16124u),
++  HB_CODEPOINT_ENCODE3 (0x16D63u, 0x16D67u, 0x16D69u),HB_CODEPOINT_ENCODE3 (0x16D67u, 0x16D67u, 0x16D68u),
++  HB_CODEPOINT_ENCODE3 (0x16D69u, 0x16D67u, 0x16D6Au), HB_CODEPOINT_ENCODE3 (0x1D157u, 0x1D165u, 0x0000u),
+    HB_CODEPOINT_ENCODE3 (0x1D158u, 0x1D165u, 0x0000u), HB_CODEPOINT_ENCODE3 (0x1D15Fu, 0x1D16Eu, 0x0000u),
+    HB_CODEPOINT_ENCODE3 (0x1D15Fu, 0x1D16Fu, 0x0000u), HB_CODEPOINT_ENCODE3 (0x1D15Fu, 0x1D170u, 0x0000u),
+    HB_CODEPOINT_ENCODE3 (0x1D15Fu, 0x1D171u, 0x0000u), HB_CODEPOINT_ENCODE3 (0x1D15Fu, 0x1D172u, 0x0000u),
+@@ -1069,90 +1082,59 @@ _hb_ucd_dm2_u64_map[388] =
+ #ifndef HB_OPTIMIZE_SIZE
+ 
+ static const uint8_t
+-_hb_ucd_u8[17884] =
++_hb_ucd_u8[17612] =
+ {
+-    0,  1,  2,  3,  4,  5,  6,  7,  7,  8,  7,  7,  7,  7,  7,  7,
+-    7,  7,  7,  7,  9, 10,  7,  7,  7,  7, 11, 12, 13, 13, 13, 14,
+-   15, 16, 17, 18, 19, 20, 21, 22, 23, 22, 22, 22, 22, 24,  7,  7,
+-   25, 26, 22, 22, 22, 27, 28, 29, 22, 30, 31, 32, 33, 34, 35, 36,
+-    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
+-    7,  7,  7,  7, 37,  7, 38, 39,  7, 40,  7,  7,  7, 41, 22, 42,
+-    7,  7, 43,  7, 44, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+-   45, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 46,
+-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 47,
++    0,  1,  2,  3,  4,  5,  5,  5,  5,  5,  6,  5,  5,  7,  8,  9,
++   10, 11, 12, 13, 14, 15, 16,  5, 17, 15, 18, 19, 20, 21, 22, 23,
++    5,  5,  5,  5,  5,  5,  5,  5,  5,  5, 24, 25, 26,  5, 27, 28,
++    5, 29, 30, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
++   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
++   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
++   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
++   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
++   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
++   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
++   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
++   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
++   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
++   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
++   31, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
++    8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8, 32,
++    8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8, 33,
+     0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
+-   16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+-   32, 33, 34, 34, 35, 36, 37, 38, 39, 34, 34, 34, 40, 41, 42, 43,
+-   44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+-   60, 61, 62, 63, 64, 64, 65, 66, 67, 68, 69, 70, 71, 69, 72, 73,
+-   69, 69, 64, 74, 64, 64, 75, 76, 77, 78, 79, 80, 81, 82, 69, 83,
+-   84, 85, 86, 87, 88, 89, 69, 69, 34, 34, 34, 34, 34, 34, 34, 34,
+-   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
+-   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 90, 34, 34, 34, 34,
+-   91, 34, 34, 34, 34, 34, 34, 34, 34, 92, 34, 34, 93, 94, 95, 96,
+-   97, 98, 99,100,101,102,103,104, 34, 34, 34, 34, 34, 34, 34, 34,
+-   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,105,
+-  106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,
+-  107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,
+-  107,107, 34, 34,108,109,110,111, 34, 34,112,113,114,115,116,117,
+-  118,119,120,121,122,123,124,125,126,127,128,129, 34, 34,130,131,
+-  132,133,134,135,136,137,138,139,140,141,142,122,143,144,145,146,
+-  147,148,149,150,151,152,153,122,154,155,122,156,157,158,159,122,
+-  160,161,162,163,164,165,166,122,167,168,169,170,122,171,172,173,
+-   34, 34, 34, 34, 34, 34, 34,174,175, 34,176,122,122,122,122,122,
+-  122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,177,
+-   34, 34, 34, 34, 34, 34, 34, 34,178,122,122,122,122,122,122,122,
+-  122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,
+-  122,122,122,122,122,122,122,122, 34, 34, 34, 34,179,122,122,122,
+-   34, 34, 34, 34,180,181,182,183,122,122,122,122,184,185,186,187,
+-   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,188,
+-   34, 34, 34, 34, 34, 34, 34, 34, 34,189,190,122,122,122,122,122,
+-  122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,191,
+-   34, 34,192, 34, 34,193,122,122,122,122,122,122,122,122,122,122,
+-  122,122,122,122,122,122,122,122,194,195,122,122,122,122,122,122,
+-  122,122,122,122,122,122,122,122,122,122,122,122,122,122,196,197,
+-   69,198,199,200,201,202,203,122,204,205,206,207,208,209,210,211,
+-   69, 69, 69, 69,212,213,122,122,122,122,122,122,122,122,214,122,
+-  215,216,217,122,122,218,122,122,122,219,122,122,122,122,122,220,
+-   34,221,222,122,122,122,122,122,223,224,225,122,226,227,122,122,
+-  228,229,230,231,232,122, 69,233, 69, 69, 69, 69, 69,234,235,236,
+-  237,238, 69, 69,239,240, 69,241,122,122,122,122,122,122,122,122,
+-   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,242, 34, 34,
+-   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,243, 34,
+-  244, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
+-   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,245, 34, 34,
+-   34, 34, 34, 34, 34, 34, 34,246, 34, 34, 34, 34,247,122,122,122,
+-   34, 34, 34, 34,248,122,122,122,122,122,122,122,122,122,122,122,
+-   34, 34, 34, 34, 34, 34,249, 34, 34, 34, 34, 34, 34, 34, 34, 34,
+-   34, 34, 34, 34, 34, 34, 34,250,122,122,122,122,122,122,122,122,
+-  251,122,252,253,122,122,122,122,122,122,122,122,122,122,122,122,
+-  107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,254,
+-  107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,255,
++   16, 17, 18, 19, 20, 17, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
++   31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 33, 41, 42, 43, 44, 45,
++   46, 47, 48, 39, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
++   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 49, 17, 17,
++   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
++   50, 17, 17, 17, 51, 17, 52, 53, 54, 55, 56, 57, 17, 17, 17, 17,
++   17, 17, 17, 17, 17, 17, 17, 58, 59, 59, 59, 59, 59, 59, 59, 59,
++   60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,
++   60, 60, 60, 60, 60, 60, 60, 60, 60, 17, 61, 62, 17, 63, 64, 65,
++   66, 67, 68, 69, 70, 71, 17, 72, 73, 74, 75, 76, 77, 78, 79, 80,
++   81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96,
++   17, 17, 17, 97, 98, 99,100,100,100,100,100,100,100,100,100,101,
++   17, 17, 17, 17,102, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
++   17, 17, 17,103, 17, 17,104,100,100,100,100,100,100,100,100,100,
++  100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
++  100,105,100,100,100,100,100,100, 17, 17,106,107,100,108,109,110,
++   17, 17, 17, 17, 17, 17, 17,111, 17, 17, 17, 17,112,113,100,100,
++  100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,114,
++   17,115,116,100,100,100,100,100,100,100,100,100,117,100,100,100,
++  100,100,100,100,100,100,100,100,100,100,100,100,118, 39,119,120,
++  121,122,123,124,125,126,127,128, 39, 39,129,100,100,100,100,130,
++  131,132,133,100,134,135,100,136,137,138,100,100,139,140,141,100,
++  142,143,144,145, 39, 39,146,147,148, 39,149,150,100,100,100,100,
++   17, 17, 17, 17, 17, 17,151, 17, 17, 17, 17, 17, 17, 17, 17, 17,
++   17, 17, 17, 17, 17, 17, 17,152,153, 17, 17, 17, 17, 17, 17, 17,
++   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,154, 17,
++   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,155, 17, 17,156,100,
++  100,100,100,100,100,100,100,100, 17, 17,157,100,100,100,100,100,
++   17, 17, 17,158, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
++   17, 17, 17,159,100,100,100,100,100,100,100,100,100,100,100,100,
++  160,161,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
++   60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,162,
++   60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,163,
+     0,  0,  0,  0,  0,  0,  0,  0,  1,  2,  3,  2,  4,  5,  6,  2,
+     7,  7,  7,  7,  7,  2,  8,  9, 10, 11, 11, 11, 11, 11, 11, 11,
+    11, 11, 11, 11, 11, 12, 13, 14, 15, 16, 16, 16, 16, 16, 16, 16,
+@@ -1189,7 +1171,7 @@ _hb_ucd_u8[17884] =
+    43, 43, 40, 21,  2, 81, 57, 20, 36, 36, 36, 43, 43, 75, 43, 43,
+    43, 43, 75, 43, 75, 43, 43, 44,  2,  2,  2,  2,  2,  2,  2, 64,
+    36, 36, 36, 36, 70, 43, 44, 64, 36, 36, 36, 36, 36, 61, 44, 44,
+-   36, 36, 36, 36, 82, 36, 36, 61, 65, 44, 44, 44, 43, 43, 43, 43,
++   36, 36, 36, 36, 82, 36, 36, 61, 65, 44, 44, 57, 43, 43, 43, 43,
+    36, 36, 36, 36, 83, 43, 43, 43, 43, 84, 43, 43, 43, 43, 43, 43,
+    43, 85, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 85, 71, 86,
+    87, 43, 43, 43, 85, 86, 87, 86, 70, 43, 43, 43, 36, 36, 36, 36,
+@@ -1262,13 +1244,13 @@ _hb_ucd_u8[17884] =
+    85, 85, 87, 43, 43, 43, 85, 86, 86, 87, 43, 43, 43, 43, 80, 57,
+     2,  2,  2, 88,  2,  2,  2, 44, 43, 43, 43, 43, 43, 43, 43,109,
+    43, 43, 43, 43, 43, 43, 43, 80, 43, 43, 98, 36, 36, 36, 36, 36,
+-   36, 36, 85, 43, 43, 85, 85, 86, 86, 85, 98, 36, 36, 36, 61, 44,
+-   97, 67, 67, 67, 67, 50, 43, 43, 43, 43, 67, 67, 67, 67, 21, 64,
++   36, 36, 85, 43, 43, 85, 85, 86, 86, 85, 98, 36, 36, 36, 61,  2,
++   97, 67, 67, 67, 67, 50, 43, 43, 43, 43, 67, 67, 67, 67, 21,  2,
+    43, 98, 36, 36, 36, 36, 36, 36, 94, 43, 43, 86, 43, 87, 43, 36,
+    36, 36, 36, 85, 43, 86, 87, 87, 43, 86, 44, 44, 44, 44,  2,  2,
+    36, 36, 86, 86, 86, 86, 43, 43, 43, 43, 86, 43, 44, 93,  2,  2,
+     7,  7,  7,  7,  7, 44, 62, 36, 36, 36, 36, 36, 40, 40, 40,  2,
+-   16, 16, 16, 16,110, 44, 44, 44, 11, 11, 11, 11, 11, 47, 48, 11,
++   16, 16, 16, 16, 34,110, 44, 44, 11, 11, 11, 11, 11, 47, 48, 11,
+     2,  2,  2,  2, 44, 44, 44, 44, 43, 60, 43, 43, 43, 43, 43, 43,
+    85, 43, 43, 43, 71, 36, 70, 36, 36, 36, 71, 94, 43, 61, 44, 44,
+    16, 16, 16, 16, 16, 16, 40, 40, 40, 40, 40, 40, 40, 45, 16, 16,
+@@ -1296,33 +1278,33 @@ _hb_ucd_u8[17884] =
+    67, 67, 67, 67,  4,  4, 67, 67,  8, 67, 67, 67,145,146, 67, 67,
+    67, 67, 67, 67, 67, 67,144, 67, 67, 67, 67, 67, 67, 26,  8,  8,
+     8,  8, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,  8,  8,
+-    8, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 92, 44, 44, 44, 44,
+-   67, 67, 67, 67, 67, 92, 44, 44, 27, 27, 27, 27, 27, 27, 67, 67,
+-   67, 67, 67, 67, 67, 27, 27, 27, 67, 67, 67, 26, 67, 67, 67, 67,
+-   26, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,  8,  8,  8,  8,
+-   67, 67, 67, 67, 67, 67, 67, 26, 67, 67, 67, 67,  4,  4,  4,  4,
+-    4,  4,  4, 27, 27, 27, 27, 27, 27, 27, 67, 67, 67, 67, 67, 67,
+-    8,  8,129,147,  8,  8,  8,  8,  8,  8,  8,  4,  4,  4,  4,  4,
+-    8,129,148,148,148,148,148,148,148,148,148,148,147,  8,  8,  8,
+-    8,  8,  8,  8,  4,  4,  8,  8,  8,  8,  8,  8,  8,  8,  4,  8,
+-    8,  8,144, 26,  8,  8,144, 67, 67, 67, 44, 67, 67, 67, 67, 67,
+-   67, 67, 67, 55, 67, 67, 67, 67, 32, 11, 32, 34, 34, 34, 34, 11,
+-   32, 32, 34, 16, 16, 16, 40, 11, 32, 32,140, 67, 67,138, 34,149,
+-   43, 32, 44, 44, 93,  2, 99,  2, 16, 16, 16,150, 44, 44,150, 44,
+-   36, 36, 36, 36, 44, 44, 44, 52, 64, 44, 44, 44, 44, 44, 44, 57,
+-   36, 36, 36, 61, 44, 44, 44, 44, 36, 36, 36, 61, 36, 36, 36, 61,
+-    2,121,121,  2,125,126,121,  2,  2,  2,  2,  6,  2,108,121,  2,
+-  121,  4,  4,  4,  4,  2,  2, 88,  2,  2,  2,  2,  2,120,  2,  2,
+-  108,151,  2,  2,  2,  2,  2,  2, 67,  2,152,148,148,148,153, 44,
+-   67, 67, 67, 67, 67, 55, 67, 67, 67, 67, 44, 44, 44, 44, 44, 44,
+-   67, 67, 67, 44, 44, 44, 44, 44,  1,  2,154,155,  4,  4,  4,  4,
+-    4, 67,  4,  4,  4,  4,156,157,158,105,105,105,105, 43, 43, 86,
+-  159, 40, 40, 67,105,160, 63, 67, 36, 36, 36, 61, 57,161,162, 69,
+-   36, 36, 36, 36, 36, 63, 40, 69, 44, 44, 62, 36, 36, 36, 36, 36,
+-   67, 27, 27, 67, 67, 67, 67, 67, 67, 67, 44, 44, 44, 44, 44, 55,
+-   67, 67, 67, 67, 67, 67, 67, 92, 27, 27, 27, 27, 27, 67, 67, 67,
+-   67, 67, 67, 67, 27, 27, 27, 27,163, 27, 27, 27, 27, 27, 27, 27,
+-   36, 36, 83, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,164,  2,
++    8, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 92, 44, 44,
++   27, 27, 27, 27, 27, 27, 67, 67, 67, 67, 67, 67, 67, 27, 27, 27,
++   67, 67, 67, 26, 67, 67, 67, 67, 26, 67, 67, 67, 67, 67, 67, 67,
++   67, 67, 67, 67,  8,  8,  8,  8, 67, 67, 67, 67, 67, 67, 67, 26,
++   67, 67, 67, 67,  4,  4,  4,  4,  4,  4,  4, 27, 27, 27, 27, 27,
++   27, 27, 67, 67, 67, 67, 67, 67,  8,  8,129,147,  8,  8,  8,  8,
++    8,  8,  8,  4,  4,  4,  4,  4,  8,129,148,148,148,148,148,148,
++  148,148,148,148,147,  8,  8,  8,  8,  8,  8,  8,  4,  4,  8,  8,
++    8,  8,  8,  8,  8,  8,  4,  8,  8,  8,144, 26,  8,  8,144, 67,
++   67, 67, 44, 67, 67, 67, 67, 67, 67, 67, 67, 55, 67, 67, 67, 67,
++   32, 11, 32, 34, 34, 34, 34, 11, 32, 32, 34, 16, 16, 16, 40, 11,
++   32, 32,140, 67, 67,138, 34,149, 43, 32, 44, 44, 93,  2, 99,  2,
++   16, 16, 16,150, 44, 44,150, 44, 36, 36, 36, 36, 44, 44, 44, 52,
++   64, 44, 44, 44, 44, 44, 44, 57, 36, 36, 36, 61, 44, 44, 44, 44,
++   36, 36, 36, 61, 36, 36, 36, 61,  2,121,121,  2,125,126,121,  2,
++    2,  2,  2,  6,  2,108,121,  2,121,  4,  4,  4,  4,  2,  2, 88,
++    2,  2,  2,  2,  2,120,  2,  2,108,151,  2,  2,  2,  2,  2,  2,
++   67,  2,152,148,148,148,153, 44, 67, 67, 67, 67, 67, 55, 67, 67,
++   67, 67, 44, 44, 44, 44, 44, 44, 67, 67, 67, 44, 44, 44, 44, 44,
++    1,  2,154,155,  4,  4,  4,  4,  4, 67,  4,  4,  4,  4,156,157,
++  158,105,105,105,105, 43, 43, 86,159, 40, 40, 67,105,160, 63, 67,
++   36, 36, 36, 61, 57,161,162, 69, 36, 36, 36, 36, 36, 63, 40, 69,
++   44, 44, 62, 36, 36, 36, 36, 36, 67, 27, 27, 67, 67, 67, 67, 67,
++   67, 67, 67, 44, 44, 44, 44, 55, 67, 67, 67, 67, 67, 67, 67, 92,
++   27, 27, 27, 27, 27, 67, 67, 67, 67, 67, 67, 67, 27, 27, 27, 27,
++  163, 27, 27, 27, 27, 27, 27, 27, 36, 36, 83, 36, 36, 36, 36, 36,
++   67, 67, 67, 92, 44, 44, 44, 44, 36, 36, 36, 36, 36, 36,164,  2,
+     7,  7,  7,  7,  7, 36, 44, 44, 32, 32, 32, 32, 32, 32, 32, 70,
+    51,165, 43, 43, 43, 43, 43, 88, 32, 32, 32, 32, 32, 32, 40, 43,
+    36, 36, 36,105,105,105,105,105, 43,  2,  2,  2, 44, 44, 44, 44,
+@@ -1330,7 +1312,7 @@ _hb_ucd_u8[17884] =
+    16, 32, 32, 32, 32, 32, 32, 32, 45, 16, 16, 16, 34, 34, 34, 32,
+    32, 32, 32, 32, 42,166, 34, 35, 32, 32, 16, 32, 32, 32, 32, 32,
+    32, 32, 32, 32, 32, 11, 11, 32, 11, 11, 32, 32, 32, 32, 32, 32,
+-   32, 32, 11, 11, 34,110, 44, 44, 32,150,150, 32, 32, 44, 44, 44,
++   32, 32, 11, 11, 34, 34, 32, 44, 32,150,150, 32, 32, 32, 47, 44,
+    44, 40,167, 35, 40, 35, 36, 36, 36, 71, 36, 71, 36, 70, 36, 36,
+    36, 94, 87, 85, 67, 67, 80, 44, 27, 27, 27, 67,168, 44, 44, 44,
+    36, 36,  2,  2, 44, 44, 44, 44, 86, 36, 36, 36, 36, 36, 36, 36,
+@@ -1391,8 +1373,10 @@ _hb_ucd_u8[17884] =
+    36, 61, 44, 44, 27, 27, 27, 27, 36, 44, 44, 44, 93,  2, 64, 44,
+    44, 44, 44, 44,179, 27, 27, 27, 11, 47, 44, 44, 44, 44, 44, 44,
+    16,110, 44, 44, 44, 27, 27, 27, 36, 36, 43, 43, 44, 44, 44, 44,
+-   27, 27, 27, 27, 27, 27, 27,100, 36, 36, 36, 36, 36, 57,184, 44,
+-   36, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 57, 43,
++    7,  7,  7,  7,  7, 36, 36, 69, 11, 11, 11, 44, 57, 43, 43,159,
++   16, 16, 16, 44, 44, 44, 44,  8, 27, 27, 27, 27, 27, 27, 27,100,
++   36, 36, 36, 36, 36, 57,184, 44, 36, 44, 44, 44, 44, 44, 44, 44,
++   44, 36, 61, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 43, 43,
+    27, 27, 27, 95, 44, 44, 44, 44,180, 27, 30,  2,  2, 44, 44, 44,
+    36, 43, 43,  2,  2, 44, 44, 44, 36, 36,183, 27, 27, 27, 44, 44,
+    87, 98, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 43, 43, 43, 43,
+@@ -1410,14 +1394,18 @@ _hb_ucd_u8[17884] =
+    86, 87, 43, 43, 43, 80, 44, 44, 43, 86, 62, 36, 36, 36, 61, 62,
+    61, 36, 62, 36, 36, 57, 71, 86, 85, 86, 90, 89, 90, 89, 86, 44,
+    61, 44, 44, 89, 44, 44, 62, 36, 36, 86, 44, 43, 43, 43, 80, 44,
+-   43, 43, 80, 44, 44, 44, 44, 44, 36, 36, 94, 86, 43, 43, 43, 43,
+-   86, 43, 85, 71, 36, 63,  2,  2,  7,  7,  7,  7,  7,  2, 93, 71,
+-   86, 87, 43, 43, 85, 85, 86, 87, 85, 43, 36, 72, 44, 44, 44, 44,
+-   36, 36, 36, 36, 36, 36, 36, 94, 86, 43, 43, 44, 86, 86, 43, 87,
+-   60,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 36, 36, 43, 44,
+-   86, 87, 43, 43, 43, 85, 87, 87, 60,  2, 61, 44, 44, 44, 44, 44,
+-    2,  2,  2,  2,  2,  2, 64, 44, 36, 36, 36, 36, 36, 70, 87, 86,
+-   43, 43, 43, 87, 63, 44, 44, 44, 86, 43, 43, 87, 43, 43, 44, 44,
++   43, 43, 80, 44, 44, 44, 44, 44, 36, 36, 36, 36, 36, 62, 44, 61,
++   36, 36, 36, 62, 86, 87, 43, 43, 80, 90, 89, 89, 86, 90, 86, 85,
++   71, 71,  2, 93, 64, 44, 44, 44, 57, 80, 44, 44, 44, 44, 44, 44,
++   36, 36, 94, 86, 43, 43, 43, 43, 86, 43, 85, 71, 36, 63,  2,  2,
++    7,  7,  7,  7,  7,  2, 93, 71, 86, 87, 43, 43, 85, 85, 86, 87,
++   85, 43, 36, 72, 44, 44, 44, 44, 36, 36, 36, 36, 36, 36, 36, 94,
++   86, 43, 43, 44, 86, 86, 43, 87, 60,  2,  2,  2,  2,  2,  2,  2,
++    2,  2,  2,  2, 36, 36, 43, 44, 86, 87, 43, 43, 43, 85, 87, 87,
++   60,  2, 61, 44, 44, 44, 44, 44,  2,  2,  2,  2,  2,  2, 64, 44,
++   36, 36, 36, 36, 36, 70, 87, 86, 43, 43, 43, 87, 63, 44, 44, 44,
++    7,  7,  7,  7,  7,  7,  7,  7,  7,  7, 44, 44, 44, 44, 44, 44,
++   36, 36, 36, 36, 36, 61, 57, 87, 86, 43, 43, 87, 43, 43, 44, 44,
+     7,  7,  7,  7,  7, 27,  2, 97, 43, 43, 43, 43, 87, 60, 44, 44,
+    27,100, 44, 44, 44, 44, 44, 62, 36, 36, 36, 61, 62, 44, 36, 36,
+    36, 36, 62, 61, 36, 36, 36, 36, 86, 86, 86, 89, 90, 57, 85, 71,
+@@ -1427,49 +1415,52 @@ _hb_ucd_u8[17884] =
+     2,  2,  2, 59, 44, 44, 44, 44, 70, 43, 43, 85, 87, 43, 36, 36,
+    36, 36, 36, 36, 36, 43, 43, 43, 43, 43, 43, 85, 43,  2, 72,  2,
+     2, 64, 44, 44, 44, 44, 44, 44,  2,  2,  2,  2,  2, 44, 44, 44,
+-   43, 43, 43, 80, 43, 43, 43, 87, 63,  2,  2, 44, 44, 44, 44, 44,
+-    2, 36, 36, 36, 36, 36, 36, 36, 44, 43, 43, 43, 43, 43, 43, 43,
+-   43, 43, 43, 43, 89, 43, 43, 43, 85, 43, 87, 80, 44, 44, 44, 44,
+-   36, 36, 36, 61, 36, 62, 36, 36, 70, 43, 43, 80, 44, 80, 43, 57,
+-   43, 43, 43, 70, 44, 44, 44, 44, 36, 36, 36, 62, 61, 36, 36, 36,
+-   36, 36, 36, 36, 36, 86, 86, 90, 43, 89, 87, 87, 61, 44, 44, 44,
+-   36, 70, 85,107, 64, 44, 44, 44, 43, 94, 36, 36, 36, 36, 36, 36,
+-   36, 36, 86, 43, 43, 80, 44, 86, 85, 60,  2,  2,  2,  2,  2,  2,
++   63, 44, 44, 44, 44, 44, 44, 44, 43, 43, 43, 80, 43, 43, 43, 87,
++   63,  2,  2, 44, 44, 44, 44, 44,  2, 36, 36, 36, 36, 36, 36, 36,
++   44, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 89, 43, 43, 43,
++   85, 43, 87, 80, 44, 44, 44, 44, 36, 36, 36, 61, 36, 62, 36, 36,
++   70, 43, 43, 80, 44, 80, 43, 57, 43, 43, 43, 70, 44, 44, 44, 44,
++   36, 36, 36, 62, 61, 36, 36, 36, 36, 36, 36, 36, 36, 86, 86, 90,
++   43, 89, 87, 87, 61, 44, 44, 44, 36, 70, 85,107, 64, 44, 44, 44,
++   43, 94, 36, 36, 36, 36, 36, 36, 36, 36, 86, 43, 43, 80, 44, 86,
++   85, 60,  2,  2,  2,  2,  2,  2,  7,  7,  7,  7,  7, 80, 44, 44,
+    27, 27, 91, 67, 67, 67, 56, 20,168, 67, 67, 67, 67, 67, 67, 67,
+    67, 44, 44, 44, 44, 44, 44, 93,105,105,105,105,105,105,105,181,
+     2,  2, 64, 44, 44, 44, 44, 44, 63, 64, 44, 44, 44, 44, 44, 44,
+    65, 65, 65, 65, 65, 65, 65, 65, 71, 36, 36, 70, 43, 43, 43, 43,
+-   43, 43, 43, 44, 44, 44, 44, 44, 43, 43, 60, 44, 44, 44, 44, 44,
++   43, 43, 43, 44, 44, 44, 44, 44, 36, 36, 36, 36, 36, 36, 36, 43,
++   43, 43, 43, 43, 43, 86, 87, 43, 43, 43, 60, 44, 44, 44, 44, 44,
+    43, 43, 43, 60,  2,  2, 67, 67, 40, 40, 97, 44, 44, 44, 44, 44,
+     7,  7,  7,  7,  7,179, 27, 27, 27, 62, 36, 36, 36, 36, 36, 36,
+-   36, 36, 36, 36, 44, 44, 62, 36, 27, 27, 27, 30,  2, 64, 44, 44,
++   36, 36, 36, 36, 44, 44, 62, 36, 40, 69, 36, 36, 36, 36, 36, 36,
++   36, 36, 36, 36, 36, 83,164,  2, 27, 27, 27, 30,  2, 64, 44, 44,
+    36, 36, 36, 36, 36, 61, 44, 57, 94, 86, 86, 86, 86, 86, 86, 86,
+    86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 44, 44, 44, 57,
+    43, 74, 40, 40, 40, 40, 40, 40, 40, 88, 80, 44, 44, 44, 44, 44,
+-   86, 44, 44, 44, 44, 44, 44, 44, 40, 40, 52, 40, 40, 40, 52, 81,
+-   36, 61, 44, 44, 44, 44, 44, 44, 44, 61, 44, 44, 44, 44, 44, 44,
+-   36, 61, 62, 44, 44, 44, 44, 44, 44, 44, 36, 36, 44, 44, 44, 44,
+-   36, 36, 36, 36, 36, 44, 50, 60, 65, 65, 44, 44, 44, 44, 44, 44,
+-   43, 43, 43, 43, 43, 43, 43, 44, 43, 43, 43, 80, 44, 44, 44, 44,
+-   67, 67, 67, 92, 55, 67, 67, 67, 67, 67,186, 87, 43, 67,186, 86,
+-   86,187, 65, 65, 65, 84, 43, 43, 43, 76, 50, 43, 43, 43, 67, 67,
+-   67, 67, 67, 67, 67, 43, 43, 67, 67, 43, 76, 44, 44, 44, 44, 44,
+-   27, 27, 44, 44, 44, 44, 44, 44, 11, 11, 11, 11, 11, 16, 16, 16,
+-   16, 16, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 16,
+-   16, 16,110, 16, 16, 16, 16, 16, 11, 16, 16, 16, 16, 16, 16, 16,
+-   16, 16, 16, 16, 16, 16, 47, 11, 44, 47, 48, 47, 48, 11, 47, 11,
+-   11, 11, 11, 16, 16,150,150, 16, 16, 16,150, 16, 16, 16, 16, 16,
+-   16, 16, 11, 48, 11, 47, 48, 11, 11, 11, 47, 11, 11, 11, 47, 16,
+-   16, 16, 16, 16, 11, 48, 11, 47, 11, 11, 47, 47, 44, 11, 11, 11,
+-   47, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 11, 11,
+-   11, 11, 11, 16, 16, 16, 16, 16, 16, 16, 16, 44, 11, 11, 11, 11,
+-   31, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 33, 16, 16,
+-   16, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 31, 16, 16,
+-   16, 16, 33, 16, 16, 16, 11, 11, 11, 11, 31, 16, 16, 16, 16, 16,
+-   16, 16, 16, 16, 16, 16, 16, 33, 16, 16, 16, 11, 11, 11, 11, 11,
+-   11, 11, 11, 11, 11, 11, 11, 31, 16, 16, 16, 16, 33, 16, 16, 16,
+-   11, 11, 11, 11, 31, 16, 16, 16, 16, 33, 16, 16, 16, 32, 44,  7,
+-    7,  7,  7,  7,  7,  7,  7,  7, 43, 43, 43, 76, 67, 50, 43, 43,
++   86, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 62,
++   40, 40, 52, 40, 40, 40, 52, 81, 36, 61, 44, 44, 44, 44, 44, 44,
++   44, 61, 44, 44, 44, 44, 44, 44, 36, 61, 62, 44, 44, 44, 44, 44,
++   44, 44, 36, 36, 44, 44, 44, 44, 36, 36, 36, 36, 36, 44, 50, 60,
++   65, 65, 44, 44, 44, 44, 44, 44, 43, 43, 43, 43, 43, 43, 43, 44,
++   43, 43, 43, 80, 44, 44, 44, 44, 67, 67, 67, 92, 55, 67, 67, 67,
++   67, 67,186, 87, 43, 67,186, 86, 86,187, 65, 65, 65, 84, 43, 43,
++   43, 76, 50, 43, 43, 43, 67, 67, 67, 67, 67, 67, 67, 43, 43, 67,
++   67, 43, 76, 44, 44, 44, 44, 44, 27, 27, 44, 44, 44, 44, 44, 44,
++   11, 11, 11, 11, 11, 16, 16, 16, 16, 16, 11, 11, 11, 11, 11, 11,
++   11, 11, 11, 11, 11, 11, 11, 16, 16, 16,110, 16, 16, 16, 16, 16,
++   11, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 47, 11,
++   44, 47, 48, 47, 48, 11, 47, 11, 11, 11, 11, 16, 16,150,150, 16,
++   16, 16,150, 16, 16, 16, 16, 16, 16, 16, 11, 48, 11, 47, 48, 11,
++   11, 11, 47, 11, 11, 11, 47, 16, 16, 16, 16, 16, 11, 48, 11, 47,
++   11, 11, 47, 47, 44, 11, 11, 11, 47, 16, 16, 16, 16, 16, 16, 16,
++   16, 16, 16, 16, 16, 16, 11, 11, 11, 11, 11, 16, 16, 16, 16, 16,
++   16, 16, 16, 44, 11, 11, 11, 11, 31, 16, 16, 16, 16, 16, 16, 16,
++   16, 16, 16, 16, 16, 33, 16, 16, 16, 11, 11, 11, 11, 11, 11, 11,
++   11, 11, 11, 11, 11, 31, 16, 16, 16, 16, 33, 16, 16, 16, 11, 11,
++   11, 11, 31, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 33,
++   16, 16, 16, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 31,
++   16, 16, 16, 16, 33, 16, 16, 16, 11, 11, 11, 11, 31, 16, 16, 16,
++   16, 33, 16, 16, 16, 32, 44,  7, 43, 43, 43, 76, 67, 50, 43, 43,
+    43, 43, 43, 43, 43, 43, 76, 67, 67, 67, 50, 67, 67, 67, 67, 67,
+    67, 67, 76, 21,  2,  2, 44, 44, 44, 44, 44, 44, 44, 57, 43, 43,
+    16, 16, 16, 16, 16, 39, 16, 16, 16, 16, 16, 16, 16, 16, 16,110,
+@@ -1479,22 +1470,23 @@ _hb_ucd_u8[17884] =
+    43, 43, 43, 74, 40, 40, 40, 44,  7,  7,  7,  7,  7, 44, 44, 77,
+    36, 36, 36, 36, 36, 36, 36, 80, 36, 36, 36, 36, 36, 36, 43, 43,
+     7,  7,  7,  7,  7, 44, 44, 96, 36, 36, 36, 36, 36, 83, 43, 43,
+-   36, 36, 36, 61, 36, 36, 62, 61, 36, 36, 61,179, 27, 27, 27, 27,
+-   16, 16, 43, 43, 43, 74, 44, 44, 27, 27, 27, 27, 27, 27,163, 27,
+-  188, 27,100, 44, 44, 44, 44, 44, 27, 27, 27, 27, 27, 27, 27,163,
+-   27, 27, 27, 27, 27, 27, 27, 44, 36, 36, 62, 36, 36, 36, 36, 36,
+-   62, 61, 61, 62, 62, 36, 36, 36, 36, 61, 36, 36, 62, 62, 44, 44,
+-   44, 61, 44, 62, 62, 62, 62, 36, 62, 61, 61, 62, 62, 62, 62, 62,
+-   62, 61, 61, 62, 36, 61, 36, 36, 36, 61, 36, 36, 62, 36, 61, 61,
+-   36, 36, 36, 36, 36, 62, 36, 36, 62, 36, 62, 36, 36, 62, 36, 36,
+-    8, 44, 44, 44, 44, 44, 44, 44, 67, 67, 67, 67, 67, 67, 44, 44,
+-   55, 67, 67, 67, 67, 67, 67, 67, 27, 27, 27, 27, 27, 27, 91, 67,
+-   67, 67, 67, 67, 67, 67, 67, 44, 44, 44, 44, 67, 67, 67, 67, 67,
+-   67, 92, 44, 44, 44, 44, 44, 44, 67, 67, 67, 67, 92, 44, 44, 44,
+-   67, 44, 44, 44, 44, 44, 44, 44, 67, 67, 67, 67, 67, 25, 41, 41,
+-   67, 67, 67, 67, 44, 44, 67, 67, 67, 67, 67, 92, 44, 55, 67, 67,
+-   67, 67, 67, 67, 44, 44, 44, 44, 67, 67, 67, 67, 67, 67, 67, 55,
+-   67, 67, 67, 44, 44, 44, 44, 67, 67, 92, 67, 67, 67, 67, 67, 67,
++  188,  7,  7,  7,  7,189, 44, 93, 36, 36, 36, 61, 36, 36, 62, 61,
++   36, 36, 61,179, 27, 27, 27, 27, 16, 16, 43, 43, 43, 74, 44, 44,
++   27, 27, 27, 27, 27, 27,163, 27,190, 27,100, 44, 44, 44, 44, 44,
++   27, 27, 27, 27, 27, 27, 27,163, 27, 27, 27, 27, 27, 27, 27, 44,
++   36, 36, 62, 36, 36, 36, 36, 36, 62, 61, 61, 62, 62, 36, 36, 36,
++   36, 61, 36, 36, 62, 62, 44, 44, 44, 61, 44, 62, 62, 62, 62, 36,
++   62, 61, 61, 62, 62, 62, 62, 62, 62, 61, 61, 62, 36, 61, 36, 36,
++   36, 61, 36, 36, 62, 36, 61, 61, 36, 36, 36, 36, 36, 62, 36, 36,
++   62, 36, 62, 36, 36, 62, 36, 36,  8, 44, 44, 44, 44, 44, 44, 44,
++   67, 67, 67, 67, 67, 67, 44, 44, 55, 67, 67, 67, 67, 67, 67, 67,
++   27, 27, 27, 27, 27, 27, 91, 67, 67, 67, 67, 67, 67, 67, 67, 44,
++   44, 44, 44, 67, 67, 67, 67, 67, 67, 92, 44, 44, 44, 44, 44, 44,
++   67, 67, 67, 67, 92, 44, 44, 44, 67, 44, 44, 44, 44, 44, 44, 44,
++   67, 67, 67, 67, 67, 25, 41, 41, 67, 67, 67, 67, 44, 44, 67, 67,
++   67, 67, 67, 92, 44, 55, 67, 67, 67, 67, 67, 67, 44, 44, 44, 44,
++   67, 67, 67, 67, 67, 44, 44, 55, 67, 67, 67, 92, 44, 44, 44, 67,
++   67, 67, 67, 67, 67, 67, 92, 55, 67, 92, 67, 67, 67, 67, 67, 67,
+    79, 44, 44, 44, 44, 44, 44, 44,171,171,171,171,171,171,171, 44,
+   171,171,171,171,171,171,171,  0,  0,  0, 29, 21, 21, 21, 23, 21,
+    22, 18, 21, 25, 21, 17, 13, 13, 25, 25, 25, 21, 21,  9,  9,  9,
+@@ -1520,366 +1512,350 @@ _hb_ucd_u8[17884] =
+     6, 21, 11, 21, 24,  9,  6,  9, 23, 26,  6, 10,  4,  4,  3,  3,
+     7, 25, 17, 16, 16, 22, 16, 16, 25, 17, 25,  2, 25, 24,  2, 15,
+    12, 15, 14,  2, 21, 14,  7, 15, 12, 17, 21,  1, 26, 10, 10,  1,
+-   23, 15,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  0, 10, 11, 12,
+-   13,  0, 14,  0,  0,  0,  0,  0, 15,  0, 16,  0,  0,  0,  0,  0,
++    7, 13, 13,  2, 23, 15,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9,
++    0, 10, 11, 12, 13,  0, 14,  0,  0,  0,  0,  0, 15,  0, 16,  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,  0,  0,  0,  0,  0,  0,  0,  0,  0,
++    0,  0,  0,  0,  0,  0,  0,  0,  0, 17, 18, 19,  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, 17, 18, 19,  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, 20,
+-    0, 21, 22, 23,  0,  0,  0, 24, 25, 26, 27, 28, 29, 30, 31, 32,
+-   33, 34,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
++    0,  0,  0, 20,  0, 21, 22, 23,  0,  0,  0, 24, 25, 26, 27, 28,
++   29, 30, 31, 32, 33, 34,  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, 35,  0, 36,  0,  0,  0,  0,  0,  0,
++    0,  0,  0,  0,  0,  0, 35,  0,  0,  0,  0, 36,  0, 37,  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,
+-   37,  0,  0,  0,  0,  0,  0,  0,  0,  0, 38, 39,  0,  0,  0,  0,
+-    0,  0, 40, 41, 42,  0, 43,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+-    0,  0,  0,  0,  1,  2,  0,  0,  0,  0,  3,  0,  0,  0,  4,  5,
+-    6,  7,  0,  8,  9, 10,  0, 11, 12, 13, 14, 15, 16, 17, 16, 18,
+-   16, 19, 16, 19, 16, 19,  0, 19, 16, 20, 16, 19, 21, 19,  0, 22,
+-   23, 24, 25, 26, 27, 28, 29, 30, 31,  0, 32,  0,  0,  0,  0,  0,
+-    0,  0,  0,  0,  0, 33,  0,  0,  0,  0,  0,  0, 34,  0,  0, 35,
+-    0,  0, 36,  0, 37,  0,  0,  0, 38, 39, 40, 41, 42, 43, 44, 45,
+-   46,  0,  0, 47,  0,  0,  0, 48,  0,  0,  0, 49,  0,  0,  0,  0,
+-    0,  0,  0, 50,  0, 51,  0, 52, 53,  0, 54,  0,  0,  0,  0,  0,
+-    0, 55, 56, 57,  0,  0,  0,  0, 58,  0,  0, 59, 60, 61, 62, 63,
+-    0,  0, 64, 65,  0,  0,  0, 66,  0,  0,  0,  0, 67,  0,  0,  0,
+-   68,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 69,
+-    0,  0,  0, 70,  0, 71,  0,  0, 72,  0,  0, 73,  0,  0,  0,  0,
+-    0,  0,  0,  0, 74,  0,  0,  0,  0,  0, 75, 76,  0, 77, 78,  0,
+-    0, 79, 80,  0, 81, 62,  0, 82, 83,  0,  0, 84, 85, 86,  0,  0,
+-    0, 87,  0, 88,  0,  0, 51, 89, 51,  0, 90,  0, 91,  0,  0,  0,
+-   80,  0,  0,  0, 92, 93,  0, 94, 95, 96, 97,  0,  0,  0,  0,  0,
+-   51,  0,  0,  0,  0, 98, 99,  0,  0,  0,  0,  0,  0,100,  0,  0,
+-    0,  0,  0,101,102,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,103,
+-    0,  0,104,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,105,106,  0,
+-    0,107,  0,  0,  0,  0,  0,  0,108,  0,109,  0,102,  0,  0,  0,
+-    0,  0,110,111,  0,  0,  0,  0,  0,  0,  0,112,  0,  0,  0,  0,
+-    0,  0,  0,113,  0,114,  0,  0,  0,  0,  0,  0,  1,  2,  3,  4,
+-    5,  6,  7,  0,  8,  0,  0,  0,  0,  9, 10, 11, 12,  0,  0,  0,
+-    0, 13,  0,  0, 14, 15,  0, 16,  0, 17, 18,  0,  0, 19,  0, 20,
+-   21,  0,  0,  0,  0,  0, 22, 23,  0, 24, 25,  0,  0, 26,  0,  0,
+-    0, 27,  0,  0, 28, 29, 30, 31,  0,  0,  0, 32, 33, 34,  0,  0,
+-   33,  0,  0, 35, 33,  0,  0,  0, 33, 36,  0,  0,  0,  0,  0, 37,
+-   38,  0,  0,  0,  0,  0,  0, 39, 40,  0,  0,  0,  0,  0,  0, 41,
+-   42,  0,  0,  0,  0, 43,  0, 44,  0,  0,  0, 45, 46,  0,  0,  0,
+-   47,  0,  0,  0,  0,  0,  0, 48, 49,  0,  0,  0,  0, 50,  0,  0,
+-    0, 51,  0, 52,  0, 53,  0,  0,  0,  0, 54,  0,  0,  0,  0, 55,
+-    0, 56,  0,  0,  0,  0, 57, 58,  0,  0,  0, 59, 60,  0,  0,  0,
+-    0,  0,  0, 61, 52,  0, 62, 63,  0,  0, 64,  0,  0,  0, 65, 66,
+-    0,  0,  0, 67,  0, 68, 69, 70, 71, 72,  1, 73,  0, 74, 75, 76,
+-    0,  0, 77, 78,  0,  0,  0, 79,  0,  0,  1,  1,  0,  0, 80,  0,
+-    0, 81,  0,  0,  0,  0, 77, 82,  0, 83,  0,  0,  0,  0,  0, 78,
+-   84,  0, 85,  0, 52,  0,  1, 78,  0,  0, 86,  0,  0, 87,  0,  0,
+-    0,  0,  0, 88, 57,  0,  0,  0,  0,  0,  0, 89, 90,  0,  0, 84,
+-    0,  0, 33,  0,  0, 91,  0,  0,  0,  0, 92,  0,  0,  0,  0, 49,
+-    0,  0, 93,  0,  0,  0,  0, 94, 95,  0,  0, 96,  0,  0, 97,  0,
+-    0,  0, 98,  0,  0,  0, 99,  0,  0,  0,  0,100,101, 93,  0,  0,
+-  102,  0,  0,  0, 84,  0,  0,103,  0,  0,  0,104,105,  0,  0,106,
+-  107,  0,  0,  0,  0,  0,  0,108,  0,  0,109,  0,  0,  0,  0,110,
+-   33,  0,111,112,113, 35,  0,  0,114,  0,  0,  0,115,  0,  0,  0,
+-    0,  0,  0,116,  0,  0,117,  0,  0,  0,  0,118, 88,  0,  0,  0,
+-    0,  0, 57,  0,  0,  0,  0, 52,119,  0,  0,  0,  0,120,  0,  0,
+-  121,  0,  0,  0,  0,119,  0,  0,122,  0,  0,  0,  0,  0,  0,123,
+-    0,  0,  0,124,  0,  0,  0,125,  0,126,  0,  0,  0,  0,127,128,
+-  129,  0,130,  0,131,  0,  0,  0,132,133,134,  0, 77,  0,  0,  0,
+-    0,  0, 35,  0,  0,  0,135,  0,  0,  0,136,  0,  0,137,  0,  0,
+-  138,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1,  2,  3,  4,
+-    5,  6,  7,  4,  4,  8,  9, 10,  1, 11, 12, 13, 14, 15, 16, 17,
+-   18,  1,  1,  1, 19,  1,  0,  0, 20, 21, 22,  1, 23,  4, 21, 24,
+-   25, 26, 27, 28, 29, 30,  0,  0,  1,  1, 31,  0,  0,  0, 32, 33,
+-   34, 35,  1, 36, 37,  0,  0,  0,  0, 38,  1, 39, 14, 39, 40, 41,
+-   42,  0,  0,  0, 43, 36, 44, 45, 21, 45, 46,  0,  0,  0, 19,  1,
+-   21,  0,  0, 47,  0, 38, 48,  1,  1, 49, 49, 50,  0,  0, 51,  0,
+-    0,  0, 52,  1,  0,  0, 38, 14,  4,  1,  1,  1, 53, 21, 43, 52,
+-   54, 21, 35,  1,  0,  0,  0, 55,  0,  0,  0, 56, 57, 58,  0,  0,
+-    0,  0,  0, 59,  0, 60,  0,  0,  0,  0, 61, 62,  0,  0, 63,  0,
+-    0,  0, 64,  0,  0,  0, 65,  0,  0,  0, 66,  0,  0,  0, 67,  0,
+-    0,  0, 68,  0,  0, 69, 70,  0, 71, 72, 73, 74, 75, 76,  0,  0,
+-    0, 77,  0,  0,  0, 78, 79,  0,  0,  0,  0, 47,  0,  0,  0, 49,
+-    0, 80,  0,  0,  0, 62,  0,  0, 63,  0,  0, 81,  0,  0, 82,  0,
+-    0,  0, 83,  0,  0, 19, 84,  0, 62,  0,  0,  0,  0, 49,  1, 85,
+-    1, 52, 15, 86, 36, 10, 21, 87,  0, 55,  0,  0,  0,  0, 19, 10,
+-    1,  0,  0,  0,  0,  0, 88,  0,  0, 89,  0,  0, 88,  0,  0,  0,
+-    0, 78,  0,  0, 87,  9, 12,  4, 90,  8, 91, 47,  0, 58, 50,  0,
+-   21,  1, 21, 92, 93,  1,  1,  1,  1, 94, 95, 96, 97,  1, 98, 58,
+-   81, 99,100,  4, 58,  0,  0,  0,  0,  0,  0, 19, 50,  0,  0,  0,
+-    0,  0,  0, 61,  0,  0,101,102,  0,  0,103,  0,  0,  1,  1, 50,
+-    0,  0,  0, 38,  0, 63,  0,  0,  0,  0,  0, 62,  0,  0,104, 68,
+-   61,  0,  0,  0, 78,  0,  0,  0,105,106, 58, 38, 81,  0,  0,  0,
+-    0,  0,  0,107,  1, 14,  4, 12, 84,  0,  0,  0,  0, 38, 87,  0,
+-    0,  0,  0,108,  0,  0,109, 61,  0,110,  0,  0,  0,  1,  0,  0,
++    0,  0,  0,  0, 38,  0,  0,  0,  0,  0,  0,  0,  0,  0, 39, 40,
++    0,  0,  0,  0,  0,  0, 41, 42, 43,  0, 44,  0,  0,  0,  0,  0,
++    0,  0,  0,  0,  0,  0,  0,  0,  1,  2,  0,  0,  0,  0,  3,  0,
++    0,  0,  4,  5,  6,  7,  0,  8,  9, 10,  0, 11, 12, 13, 14, 15,
++   16, 17, 16, 18, 16, 19, 16, 19, 16, 19,  0, 19, 16, 20, 16, 19,
++   21, 19,  0, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,  0, 32,  0,
++    0,  0,  0,  0,  0,  0,  0,  0,  0, 33,  0,  0,  0,  0,  0,  0,
++   34,  0,  0, 35,  0,  0, 36,  0, 37,  0,  0,  0, 38, 39, 40, 41,
++   42, 43, 44, 45, 46,  0,  0, 47,  0,  0,  0, 48,  0,  0,  0, 49,
++    0,  0,  0,  0,  0,  0,  0, 50,  0, 51,  0, 52, 53,  0, 54,  0,
++    0,  0,  0,  0,  0, 55, 56, 57,  0,  0,  0,  0, 58,  0,  0, 59,
++   60, 61, 62, 63,  0,  0, 64, 65,  0,  0,  0, 66,  0,  0,  0,  0,
++   67,  0,  0,  0, 68,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
++    0,  0,  0, 69,  0,  0,  0, 70,  0, 71,  0,  0, 72,  0,  0, 73,
++    0,  0,  0,  0,  0,  0,  0,  0, 74, 75,  0,  0,  0,  0, 76, 77,
++    0, 78, 79,  0,  0, 80, 81,  0, 82, 62,  0, 83, 84,  0,  0, 85,
++   86, 87,  0, 88,  0, 89,  0, 90,  0,  0, 51, 91, 51,  0, 92,  0,
++   93,  0,  0,  0, 81,  0,  0,  0, 94, 95,  0, 96, 97, 98, 99,  0,
++    0,  0,  0,  0, 51,  0,  0,  0,  0,100,101,  0,  0,  0,  0,  0,
++    0,102,  0,  0,  0,  0,  0,  0,103,  0,  0,  0,  0,  0,  0,104,
++  105,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,106,  0,  0,107,  0,
++    0,  0,  0,  0,  0,  0,  0,  0,  0,108,109,  0,  0,110,  0,  0,
++    0,  0,  0,  0,111,  0,112,  0,105,  0,  0,  0,  0,  0,113,114,
++    0,  0,  0,  0,  0,  0,  0,115,  0,  0,  0,116,  0,  0,  0,117,
++    0,118,  0,  0,  0,  0,  0,  0,  1,  2,  3,  4,  5,  6,  7,  0,
++    8,  0,  0,  0,  0,  9, 10, 11, 12,  0,  0,  0,  0, 13,  0,  0,
++   14, 15,  0, 16,  0, 17, 18,  0,  0, 19,  0, 20, 21,  0,  0,  0,
++    0,  0, 22, 23,  0, 24, 25,  0,  0, 26,  0,  0,  0, 27,  0,  0,
++   28, 29, 30, 31,  0,  0,  0, 32, 33, 34,  0,  0, 33,  0,  0, 35,
++   33,  0,  0,  0, 33, 36,  0,  0,  0,  0,  0, 37, 38,  0,  0,  0,
++    0,  0,  0, 39, 40,  0,  0,  0,  0,  0,  0, 41, 42,  0,  0,  0,
++    0, 43,  0, 44,  0,  0,  0, 45, 46,  0,  0,  0, 47,  0,  0,  0,
++    0,  0,  0, 48, 49,  0,  0,  0,  0, 50,  0,  0,  0, 51,  0, 52,
++    0, 53,  0,  0,  0,  0, 54,  0,  0,  0,  0, 55,  0, 56,  0,  0,
++    0,  0, 57, 58,  0,  0,  0, 59, 60,  0,  0,  0,  0,  0,  0, 61,
++   52,  0, 62, 63,  0,  0, 64,  0,  0,  0, 65, 66,  0,  0,  0, 67,
++    0, 68, 69, 70, 71, 72,  1, 73,  0, 74, 75, 76,  0,  0, 77, 78,
++    0,  0,  0, 79,  0,  0,  1,  1,  0,  0, 80,  0,  0, 81,  0,  0,
++    0,  0, 77, 82,  0, 83,  0,  0,  0,  0,  0, 78, 84,  0, 85,  0,
++   52,  0,  1, 78,  0,  0, 86,  0,  0, 87,  0,  0,  0,  0,  0, 88,
++   57,  0,  0,  0,  0,  0,  0, 89, 90,  0,  0, 84,  0,  0, 33,  0,
++    0, 91,  0,  0,  0,  0, 92,  0,  0,  0,  0, 49,  0,  0, 93,  0,
++    0,  0,  0, 94, 95,  0,  0, 96,  0,  0, 97,  0,  0,  0, 98,  0,
++    0,  0, 99,  0,  0,  0,100,  0,  0,  0,  0,101,102, 93,  0,  0,
++  103,  0,  0,  0, 84,  0,  0,104,  0,  0,  0,105,106,  0,  0,107,
++  108,  0,  0,  0,  0,  0,  0,109,  0,  0,110,  0,  0,  0,  0,111,
++   33,  0,112,113,114, 57,  0,  0,115, 35,  0,  0,116,  0,  0,  0,
++  117,  0,  0,  0,  0,  0,  0,118,  0,  0,119,  0,  0,  0,  0,120,
++   88,  0,  0,  0,  0,  0, 57,  0,  0,  0,  0, 52,121,  0,  0,  0,
++    0,122,  0,  0,123,  0,  0,  0,  0,121,  0,  0,124,  0,  0,  0,
++    0,  0, 79,  0,  0,  0,  0,125,  0,  0,  0,126,  0,  0,  0,127,
++    0,128,  0,  0,  0,  0,129,130,131,  0,132,  0,133,  0,  0,  0,
++  134,135,136,  0, 77,  0,  0,  0,  0,  0, 35,  0,  0,  0,137,  0,
++    0,  0,138,  0,  0,  0,139,  0,  0,140,  0,  0,141,  0,  0,  0,
++    0,  0,  0,  0,  1,  1,  1,  1,  1,  2,  3,  4,  5,  6,  7,  4,
++    4,  8,  9, 10,  1, 11, 12, 13, 14, 15, 16, 17, 18,  1,  1,  1,
++   19,  1,  0,  0, 20, 21, 22,  1, 23,  4, 21, 24, 25, 26, 27, 28,
++   29, 30,  0,  0,  1,  1, 31,  0,  0,  0, 32, 33, 34, 35,  1, 36,
++   37,  0,  0,  0,  0, 38,  1, 39, 14, 39, 40, 41, 42,  0,  0,  0,
++   43, 36, 44, 45, 21, 45, 46,  0,  0,  0, 19,  1, 21,  0,  0, 47,
++    0, 38, 48,  1,  1, 49, 49, 50,  0,  0, 51,  0,  0, 19, 52,  1,
++    0,  0, 38, 14,  4,  1,  1,  1, 53, 21, 43, 52, 54, 21, 35,  1,
++    0,  0,  0, 55,  0,  0,  0, 56, 57, 58,  0,  0,  0,  0,  0, 59,
++    0, 60,  0,  0,  0,  0, 61, 62,  0,  0, 63,  0,  0,  0, 64,  0,
++    0,  0, 65,  0,  0,  0, 66,  0,  0,  0, 67,  0,  0,  0, 68,  0,
++    0, 69, 70,  0, 71, 72, 73, 74, 75, 76,  0,  0,  0, 77,  0,  0,
++    0, 78, 79,  0,  0,  0,  0, 47,  0,  0,  0, 49,  0, 80,  0,  0,
++    0, 62,  0,  0, 63,  0,  0, 81,  0,  0, 82,  0,  0,  0, 83,  0,
++    0, 19, 84,  0, 62,  0,  0,  0,  0, 49,  1, 85,  1, 52, 15, 86,
++   36, 10, 21, 87,  0, 55,  0,  0,  0,  0, 19, 10,  1,  0,  0,  0,
++    0,  0, 88,  0,  0, 89,  0,  0, 88,  0,  0,  0,  0, 78,  0,  0,
++   87,  9, 12,  4, 90,  8, 91, 47,  0, 58, 50,  0, 21,  1, 21, 92,
++   93,  1,  1,  1,  1, 94, 95, 96, 97,  1, 98, 58, 81, 99,100,  4,
++   58,  0,  0,  0,  0,  0,  0, 19, 50,  0,  0,  0,  0,  0,  0, 61,
++    0,  0,101,102,  0,  0,103,  0,  0,  1,  1, 50,  0,  0,  0, 38,
++    0, 63,  0,  0,  0,  0,  0, 62,  0,  0,104, 68, 61,  0,  0,  0,
++   78,  0,  0,  0,105,106, 58, 38, 81,  0,  0,  0,  0,  0,  0,107,
++    1, 14,  4, 12, 84,  0,  0,  0,  0, 38, 87,  0,  0,  0,  0,108,
++    0,  0,109, 61,  0,110,  0,  0,  0,  1,  0,  0,  0,  0, 49, 50,
+     0,  0, 19, 58,  0,  0,  0, 51,  0,111, 14, 52,112, 41,  0,  0,
+    62,  0,  0, 61,  0,  0,113,  0, 87,  0,  0,  0, 61, 62,  0,  0,
+    62,  0, 89,  0,  0,113,  0,  0,  0,  0,114,  0,  0,  0, 78, 55,
+-    0, 38,  1, 58,  1, 58,  0,  0, 63, 89,  0,  0,115,  0,  0,  0,
+-   55,  0,  0,  0,  0,115,  0,  0,  0,  0, 61,  0,  0,  0,  0, 79,
+-    0, 61,  0,  0,  0,  0, 56,  0, 89, 80,  0,  0, 79,  0,  0,  0,
+-    8, 91,  0,  0,  1, 87,  0,  0,116,  0,  0,  0,  0,  0,  0,117,
+-    0,118,119,120,121,  0,104,  4,122, 49, 23,  0,  0,  0, 38, 50,
+-   38, 58,  0,  0,  1, 87,  1,  1,  1,  1, 39,  1, 48,105, 87,  0,
+-    0,  0,  0,  1,  0,  0,  0,123,  4,122,  0,  0,  0,  1,124,  0,
+-    0,  0,  0,  0,230,230,230,230,230,232,220,220,220,220,232,216,
+-  220,220,220,220,220,202,202,220,220,220,220,202,202,220,220,220,
+-    1,  1,  1,  1,  1,220,220,220,220,230,230,230,230,240,230,220,
+-  220,220,230,230,230,220,220,  0,230,230,230,220,220,220,220,230,
+-  232,220,220,230,233,234,234,233,234,234,233,230,  0,  0,  0,230,
+-    0,220,230,230,230,230,220,230,230,230,222,220,230,230,220,220,
+-  230,222,228,230, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20,
+-   21, 22,  0, 23,  0, 24, 25,  0,230,220,  0, 18, 30, 31, 32,  0,
+-    0,  0,  0, 27, 28, 29, 30, 31, 32, 33, 34,230,230,220,220,230,
+-  220,230,230,220, 35,  0,  0,  0,  0,  0,230,230,230,  0,  0,230,
+-  230,  0,220,230,230,220,  0,  0,  0, 36,  0,  0,230,220,230,230,
+-  220,220,230,220,220,230,220,230,220,230,230,  0,  0,220,  0,  0,
+-  230,230,  0,230,  0,230,230,230,230,230,  0,  0,  0,220,220,220,
+-  230,220,220,220,230,230,  0,220, 27, 28, 29,230,  7,  0,  0,  0,
+-    0,  9,  0,  0,  0,230,220,230,230,  0,  0,  0,  0,  0,230,  0,
+-    0, 84, 91,  0,  0,  0,  0,  9,  9,  0,  0,  0,  0,  0,  9,  0,
+-  103,103,  9,  0,107,107,107,107,118,118,  9,  0,122,122,122,122,
+-  220,220,  0,  0,  0,220,  0,220,  0,216,  0,  0,  0,129,130,  0,
+-  132,  0,  0,  0,  0,  0,130,130,130,130,  0,  0,130,  0,230,230,
+-    9,  0,230,230,  0,  0,220,  0,  0,  0,  0,  7,  0,  9,  9,  0,
+-    9,  9,  0,  0,  0,230,  0,  0,  0,228,  0,  0,  0,222,230,220,
+-  220,  0,  0,  0,230,  0,  0,220,230,220,  0,220,230,230,230,  0,
+-    0,  0,  9,  9,  0,  0,  7,  0,230,  0,  1,  1,  1,  0,  0,  0,
+-  230,234,214,220,202,230,230,230,230,230,232,228,228,220,218,230,
+-  233,220,230,220,230,230,  1,  1,  1,  1,  1,230,  0,  1,  1,230,
+-  220,230,  1,  1,  0,  0,218,228,232,222,224,224,  0,  8,  8,  0,
+-    0,  0,  0,220,230,  0,230,230,220,  0,  0,230,  0,  0, 26,  0,
+-    0,220,  0,230,230,  1,220,  0,  0,230,220,  0,  0,  0,220,220,
+-    0,  0,230,220,  0,  9,  7,  0,  0,  7,  9,  0,  0,  0,  9,  7,
+-    6,  6,  0,  0,  0,  0,  1,  0,  0,216,216,  1,  1,  1,  0,  0,
+-    0,226,216,216,216,216,216,  0,220,220,220,  0,232,232,220,230,
+-  230,230,  7,  0, 16, 17, 17, 17, 17, 17, 17, 33, 17, 17, 17, 19,
+-   17, 17, 17, 17, 20,101, 17,113,129,169, 17, 27, 28, 17, 17, 17,
++    0, 38,  1, 58,  1, 58,  0,  0,  0,  0,  0, 88, 63, 89,  0,  0,
++  115,  0,  0,  0, 55,  0,  0,  0,  0,115,  0,  0,  0,  0, 61,  0,
++    0,  0,  0, 79,  0, 61,  0,  0,  0,  0, 56,  0, 89, 80,  0,  0,
++   79,  0,  0,  0,  8, 91,  0,  0,  1, 87,  0,  0,116,  0,  0,  0,
++    0,  0,  0,117,  0,118,119,120,121,  0,104,  4,122, 49, 23,  0,
++    0,  0, 38, 50, 38, 58,  0,  0,  1, 87,  1,  1,  1,  1, 39,  1,
++   48,105, 87,  0,  0,  0,  0,  1,  0,  0,  0,123,  0,  0,  0,112,
++    4,122,  0,  0,  0,  1,124,  0,  0,  0,  0,  0,230,230,230,230,
++  230,232,220,220,220,220,232,216,220,220,220,220,220,202,202,220,
++  220,220,220,202,202,220,220,220,  1,  1,  1,  1,  1,220,220,220,
++  220,230,230,230,230,240,230,220,220,220,230,230,230,220,220,  0,
++  230,230,230,220,220,220,220,230,232,220,220,230,233,234,234,233,
++  234,234,233,230,  0,  0,  0,230,  0,220,230,230,230,230,220,230,
++  230,230,222,220,230,230,220,220,230,222,228,230, 10, 11, 12, 13,
++   14, 15, 16, 17, 18, 19, 19, 20, 21, 22,  0, 23,  0, 24, 25,  0,
++  230,220,  0, 18, 30, 31, 32,  0,  0,  0,  0, 27, 28, 29, 30, 31,
++   32, 33, 34,230,230,220,220,230,220,230,230,220, 35,  0,  0,  0,
++    0,  0,230,230,230,  0,  0,230,230,  0,220,230,230,220,  0,  0,
++    0, 36,  0,  0,230,220,230,230,220,220,230,220,220,230,220,230,
++  220,230,230,  0,  0,220,  0,  0,230,230,  0,230,  0,230,230,230,
++  230,230,  0,  0,  0,220,220,220,230,220,220,220,230,230,  0,220,
++   27, 28, 29,230,  7,  0,  0,  0,  0,  9,  0,  0,  0,230,220,230,
++  230,  0,  0,  0,  0,  0,230,  0,  0, 84, 91,  0,  0,  0,  0,  9,
++    9,  0,  0,  0,  0,  0,  9,  0,103,103,  9,  0,107,107,107,107,
++  118,118,  9,  0,122,122,122,122,220,220,  0,  0,  0,220,  0,220,
++    0,216,  0,  0,  0,129,130,  0,132,  0,  0,  0,  0,  0,130,130,
++  130,130,  0,  0,130,  0,230,230,  9,  0,230,230,  0,  0,220,  0,
++    0,  0,  0,  7,  0,  9,  9,  0,  9,  9,  0,  0,  0,230,  0,  0,
++    0,228,  0,  0,  0,222,230,220,220,  0,  0,  0,230,  0,  0,220,
++  230,220,  0,220,230,230,230,  0,  0,  0,  9,  9,  0,  0,  7,  0,
++  230,  0,  1,  1,  1,  0,  0,  0,230,234,214,220,202,230,230,230,
++  230,230,232,228,228,220,218,230,233,220,230,220,230,230,  1,  1,
++    1,  1,  1,230,  0,  1,  1,230,220,230,  1,  1,  0,  0,218,228,
++  232,222,224,224,  0,  8,  8,  0,  0,  0,  0,220,230,  0,230,230,
++  220,  0,  0,230,  0,  0, 26,  0,  0,220,  0,230,230,  1,220,  0,
++    0,230,220,  0,  0,  0,220,220,  0,  0,230,220,  0,  9,  7,  0,
++    0,  7,  9,  0,  0,  0,  9,  7,  6,  6,  0,  0,  0,  0,  1,  0,
++    0,216,216,  1,  1,  1,  0,  0,  0,226,216,216,216,216,216,  0,
++  220,220,220,  0,232,232,220,230,230,230,  7,  0, 16, 17, 17, 17,
++   17, 17, 17, 33, 17, 17, 17, 19, 17, 17, 17, 17, 20,101, 17,113,
++  129,169, 17, 27, 28, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+    17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+    17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+    17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+    17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+    17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+-   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+-   17, 17, 17,237,  0,  1,  2,  2,  0,  3,  0,  0,  0,  0,  0,  0,
+-    0,  0,  0,  0,  0,  4,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+-    5,  0,  0,  0,  0,  6,  7,  8,  9,  0,  0,  0, 10, 11, 12, 13,
+-   14, 15, 16, 17, 18, 19,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20,
+-    0,  0, 21, 22,  0,  0,  0,  0, 23, 24, 25, 26,  0, 27,  0, 28,
+-   29, 30, 31, 32,  0,  0,  0,  0,  0,  0,  0, 33, 34, 35, 36,  0,
+-    0,  0,  0,  0, 37,  0,  0,  0,  0,  0,  0,  0,  0,  0, 38, 39,
+-    0,  0,  0,  0,  1,  2, 40, 41,  0,  1,  2,  2,  0,  0,  0,  0,
+-    0,  0,  0,  0,  0,  0,  1,  0,  0,  0,  0,  2,  0,  0,  0,  0,
+-    0,  0,  3,  4,  0,  0,  5,  0,  0,  0,  6,  0,  0,  0,  0,  0,
+-    0,  0,  7,  1,  0,  0,  0,  0,  0,  0,  8,  9,  0,  0,  0,  0,
+-    0,  0, 10,  0,  0, 10,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+-    0,  0,  0, 10,  0,  0,  0, 10,  0,  0,  0,  0,  0,  0, 11, 12,
+-    0, 13,  0, 14, 15, 16,  0,  0,  0,  0,  0,  1, 17, 18,  0, 19,
+-    7,  1,  0,  0,  0, 20, 20,  7, 20, 20, 20, 20, 20, 20, 20,  8,
+-   21,  0, 22,  0,  7, 23, 24,  0, 20, 20, 25,  0,  0,  0, 26, 27,
+-    1,  7, 20, 20, 20, 20, 20,  1, 28, 29, 30, 31,  0,  0, 20,  0,
+-    0,  0,  0,  0,  0,  0, 10,  0,  0,  0,  0,  0,  0,  0, 20, 20,
+-   20,  1,  0,  0,  8, 21, 32,  4,  0, 10,  0, 33,  7, 20, 20, 20,
+-    0,  0,  0,  0,  8, 34, 34, 35, 36, 34, 37,  0, 38,  1, 20, 20,
+-    0,  0, 39,  0,  1,  1,  0,  8, 21,  1, 20,  0,  0,  0,  1,  0,
+-    0, 40,  1,  1,  0,  0,  8, 21,  0,  1,  0,  1,  0,  1,  0,  0,
+-    0,  0, 26, 34, 34, 34, 34, 34, 34, 34, 34, 34, 21,  7, 20, 41,
+-   34, 34, 34, 34, 34, 34, 34, 34, 34, 21,  0, 42, 43, 44,  0, 45,
+-    0,  8, 21,  0,  0,  0,  0,  0,  0,  0,  0, 46,  7,  1, 10,  1,
+-    0,  0,  0,  1, 20, 20,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+-    0, 26, 34,  9,  0,  0, 20, 20,  1, 20, 20,  0,  0,  0,  0,  0,
+-    0,  0, 26, 21,  0,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+-    0,  0,  3, 47, 48,  0,  0,  0,  0,  0,  0,  0,  0,  1,  2,  3,
+-    4,  5,  6,  7,  7,  8,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
+-    9, 10, 11, 11, 11, 11, 12, 13, 13, 13, 13, 14, 15, 16, 17, 18,
+-   19, 20, 21, 13, 22, 13, 13, 13, 13, 23, 24, 24, 25, 26, 13, 13,
+-   13, 27, 28, 29, 13, 30, 31, 32, 33, 34, 35, 36,  7,  7,  7,  7,
+-    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
+-   37,  7, 38, 39,  7, 40,  7,  7,  7, 41, 13, 42,  7,  7, 43,  7,
+-   44, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
++   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,237,  0,  1,  2,  2,
++    0,  3,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  4,  0,  0,
++    0,  0,  0,  0,  0,  0,  0,  0,  5,  0,  0,  0,  0,  6,  7,  8,
++    9,  0,  0,  0, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,  0,  0,
++    0,  0,  0,  0,  0,  0,  0, 20,  0,  0, 21, 22,  0,  0,  0,  0,
++   23, 24, 25, 26,  0, 27,  0, 28, 29, 30, 31, 32,  0,  0,  0,  0,
++    0,  0,  0, 33, 34, 35, 36,  0,  0,  0,  0,  0, 37,  0,  0,  0,
++    0,  0,  0,  0,  0,  0, 38, 39,  0,  0,  0,  0,  1,  2, 40, 41,
++    0,  1,  2,  2,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,
++    0,  0,  0,  2,  0,  0,  0,  0,  0,  0,  3,  4,  0,  0,  5,  0,
++    0,  0,  6,  0,  0,  0,  0,  0,  0,  0,  7,  1,  0,  0,  0,  0,
++    0,  0,  8,  9,  0,  0,  0,  0,  0,  0, 10,  0,  0, 10,  0,  0,
++    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 10,  0,  0,  0, 10,
++    0,  0,  0,  0,  0,  0, 11, 12,  0, 13,  0, 14, 15, 16,  0,  0,
++    0,  0,  0,  1, 17, 18,  0, 19,  7,  1,  0,  0,  0, 20, 20,  7,
++   20, 20, 20, 20, 20, 20, 20,  8, 21,  0, 22,  0,  7, 23, 24,  0,
++   20, 20, 25,  0,  0,  0, 26, 27,  1,  7, 20, 20, 20, 20, 20,  1,
++   28, 29, 30, 31,  0,  0, 20,  0,  0,  0,  0,  0,  0,  0, 10,  0,
++    0,  0,  0,  0,  0,  0, 20, 20, 20,  1,  0,  0,  8, 21, 32,  4,
++    0, 10,  0, 33,  7, 20, 20, 20,  0,  0,  0,  0,  8, 34, 34, 35,
++   36, 34, 37,  0, 38,  1, 20, 20,  0,  0, 39,  0,  1,  1,  0,  8,
++   21,  1, 20,  0,  0,  0,  1,  0,  0, 40,  1,  1,  0,  0,  8, 21,
++    0,  1,  0,  1,  0,  1,  0,  0,  0,  0, 26, 34, 34, 34, 34, 34,
++   34, 34, 34, 34, 21,  7, 20, 41, 34, 34, 34, 34, 34, 34, 34, 34,
++   34, 21,  0, 42, 43, 44,  0, 45,  0,  8, 21,  0,  0,  0,  0,  0,
++    0,  0,  0, 46,  7,  1, 10,  1,  0,  0,  0,  1, 20, 20,  1,  0,
++    0,  0,  0,  0,  0,  0,  0,  0,  0, 26, 34,  9,  0,  0, 20, 20,
++    1, 20, 20,  0,  0,  0,  0,  0,  0,  0, 26, 21,  0,  1,  0,  0,
++    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  3, 47, 48,  0,  0,  0,
++    0,  0,  0,  0,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11,
++   12, 13, 13, 13, 13, 13, 13, 14, 13, 13, 13, 13, 13, 13, 13, 13,
++   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 15, 16, 17, 18,
++   18, 18, 18, 18, 18, 18, 18, 18, 18, 19, 20, 20, 20, 20, 20, 20,
++   20, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 20, 33,
++   34, 35, 34, 34, 36, 37, 20, 20, 20, 20, 20, 20, 38, 20, 39, 40,
++   41, 41, 41, 41, 41, 42, 43, 44, 20, 20, 20, 20, 20, 20, 20, 45,
++   46, 20, 20, 47, 20, 20, 20, 48, 49, 50, 51, 52, 53, 54, 55, 56,
++   57, 58, 59, 20, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 45,  0,  0,  1,
+-    2,  2,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
+-   16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+-   32, 32, 33, 34, 35, 36, 37, 37, 37, 37, 37, 38, 39, 40, 41, 42,
+-   43, 44, 45, 46, 47, 48, 49, 50, 51, 52,  2,  2, 53, 54, 55, 56,
+-   57, 58, 59, 59, 59, 59, 60, 59, 59, 59, 59, 59, 59, 59, 61, 61,
+-   59, 59, 59, 59, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
+-   74, 75, 76, 77, 78, 59, 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, 79, 70, 70, 70, 70, 80, 80,
+-   80, 80, 80, 80, 80, 80, 80, 81, 82, 82, 83, 84, 85, 86, 87, 88,
+-   89, 90, 91, 92, 93, 94, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+-   32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+-   32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 95, 96, 96,
+-   96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
+-   70, 70, 97, 98, 99,100,101,101,102,103,104,105,106,107,108,109,
+-  110,111, 96,112,113,114,115,116,117,118,119,119,120,121,122,123,
+-  124,125,126,127,128,129,130,131,132, 96,133,134,135,136,137,138,
+-  139,140,141,142,143, 96,144,145, 96,146,147,148,149, 96,150,151,
+-  152,153,154,155,156, 96,157,158,159,160, 96,161,162,163,164,164,
+-  164,164,164,164,164,165,166,164,167, 96, 96, 96, 96, 96, 96, 96,
+-   96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,168,169,169,
+-  169,169,169,169,169,169,170, 96, 96, 96, 96, 96, 96, 96, 96, 96,
+-   96, 96, 96, 96, 96, 96,171,171,171,171,172, 96, 96, 96,173,173,
+-  173,173,174,175,176,177, 96, 96, 96, 96,178,179,180,181,182,182,
+-  182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,
+-  182,182,182,182,182,182,182,182,182,182,182,182,182,183,182,182,
+-  182,182,182,182,184,184,184,185,186, 96, 96, 96, 96, 96, 96, 96,
+-   96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,187,188,189,
+-  190,191,191,192, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
+-   96, 96, 96, 96, 96, 96,193,194, 96, 96, 96, 96, 96, 96, 96, 96,
+-   96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,195,196, 59,197,
+-  198,199,200,201,202, 96,203,204,205, 59, 59,206, 59,207,208,208,
+-  208,208,208,209, 96, 96, 96, 96, 96, 96, 96, 96,210, 96,211,212,
+-  213, 96, 96,214, 96, 96, 96,215, 96, 96, 96, 96, 96,216,217,218,
+-  219, 96, 96, 96, 96, 96,220,221,222, 96,223,224, 96, 96,225,226,
+-   59,227,228, 96, 59, 59, 59, 59, 59, 59, 59,229,230,231,232,233,
+-   59, 59,234,235, 59,236, 96, 96, 96, 96, 96, 96, 96, 96, 70, 70,
+-   70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,237, 70, 70, 70, 70,
+-   70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,238, 70,239, 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,240, 70, 70, 70, 70,
+-   70, 70, 70, 70, 70,241, 70, 70, 70, 70,242, 96, 96, 96, 70, 70,
+-   70, 70,243, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 70, 70,
+-   70, 70, 70, 70,244, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+-   70, 70, 70, 70, 70,245, 96, 96, 96, 96, 96, 96, 96, 96,246, 96,
+-  247,248,  0,  1,  2,  2,  0,  1,  2,  2,  2,  3,  4,  5,  0,  0,
+-    0,  0,  0,  0,  0,  0,  0, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+-   19, 19, 19, 19, 19, 19, 19, 19, 19,  0,  0,  0,  0,  0,  0,  0,
+-   19,  0,  0,  0,  0,  0, 19, 19, 19, 19, 19, 19, 19,  0, 19,  0,
+-    0,  0,  0,  0,  0,  0, 19, 19, 19, 19, 19,  0,  0,  0,  0,  0,
+-   26, 26,  0,  0,  0,  0,  1,  1,  1,  1,  1,  1,  1,  1,  9,  9,
+-    9,  9,  0,  9,  9,  9,  2,  2,  9,  9,  9,  9,  0,  9,  2,  2,
+-    2,  2,  9,  0,  9,  0,  9,  9,  9,  2,  9,  2,  9,  9,  9,  9,
+-    9,  9,  9,  9,  9,  9,  9,  9,  2,  9,  9,  9,  9,  9,  9,  9,
+-   55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,  6,  6,
+-    6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  1,  1,  6,  2,  4,
+-    4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,
+-    4,  4,  4,  4,  4,  2,  4,  4,  4,  2,  2,  4,  4,  4,  2, 14,
+-   14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,  2,  2,
+-    2,  2,  2,  2,  2,  2, 14, 14, 14,  2,  2,  2,  2, 14, 14, 14,
+-   14, 14, 14,  2,  2,  2,  3,  3,  3,  3,  3,  0,  3,  3,  3,  3,
+-    3,  3,  0,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,
+-    3,  0,  3,  3,  3,  0,  0,  3,  3,  3,  3,  3,  3,  3,  3,  3,
+-    3,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  3,  3,  1,  3,
+-    3,  3,  3,  3,  3,  3, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
+-   37, 37, 37, 37,  2, 37, 37, 37, 37,  2,  2, 37, 37, 37, 38, 38,
+-   38, 38, 38, 38, 38, 38, 38, 38,  2,  2,  2,  2,  2,  2, 64, 64,
+-   64, 64, 64, 64, 64, 64, 64, 64, 64,  2,  2, 64, 64, 64, 90, 90,
+-   90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90,  2,  2, 90, 90,
+-   90, 90, 90, 90, 90,  2, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,
+-   95, 95,  2,  2, 95,  2, 37, 37, 37,  2,  2,  2,  2,  2,  3,  3,
+-    3,  3,  3,  3,  3,  2,  3,  3,  2,  2,  2,  2,  2,  2,  3,  3,
+-    0,  3,  3,  3,  3,  3,  7,  7,  7,  7,  7,  7,  7,  7,  7,  1,
+-    1,  1,  1,  7,  7,  7,  7,  7,  7,  7,  0,  0,  7,  7,  5,  5,
+-    5,  5,  2,  5,  5,  5,  5,  5,  5,  5,  5,  2,  2,  5,  5,  2,
+-    2,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  2,
+-    5,  5,  5,  5,  5,  5,  5,  2,  5,  2,  2,  2,  5,  5,  5,  5,
+-    2,  2,  5,  5,  5,  5,  5,  2,  2,  5,  5,  5,  5,  2,  2,  2,
+-    2,  2,  2,  2,  2,  5,  2,  2,  2,  2,  5,  5,  2,  5,  5,  5,
+-    5,  5,  2,  2,  5,  5,  5,  5,  5,  5,  5,  5,  5,  2,  2, 11,
+-   11, 11,  2, 11, 11, 11, 11, 11, 11,  2,  2,  2,  2, 11, 11,  2,
+-    2, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,  2,
+-   11, 11, 11, 11, 11, 11, 11,  2, 11, 11,  2, 11, 11,  2, 11, 11,
+-    2,  2, 11,  2, 11, 11, 11,  2,  2, 11, 11, 11,  2,  2,  2, 11,
+-    2,  2,  2,  2,  2,  2,  2, 11, 11, 11, 11,  2, 11,  2,  2,  2,
+-    2,  2,  2,  2, 11, 11, 11, 11, 11, 11, 11, 11, 11,  2,  2, 10,
+-   10, 10,  2, 10, 10, 10, 10, 10, 10, 10, 10, 10,  2, 10, 10, 10,
+-    2, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,  2,
+-   10, 10, 10, 10, 10, 10, 10,  2, 10, 10,  2, 10, 10, 10, 10, 10,
+-    2,  2, 10, 10, 10, 10, 10, 10,  2, 10, 10, 10,  2,  2, 10,  2,
+-    2,  2,  2,  2,  2,  2, 10, 10, 10, 10,  2,  2, 10, 10, 10, 10,
+-    2,  2,  2,  2,  2,  2,  2, 10, 10, 10, 10, 10, 10, 10,  2, 21,
+-   21, 21,  2, 21, 21, 21, 21, 21, 21, 21, 21,  2,  2, 21, 21,  2,
+-    2, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,  2,
+-   21, 21, 21, 21, 21, 21, 21,  2, 21, 21,  2, 21, 21, 21, 21, 21,
+-    2,  2, 21, 21, 21, 21, 21,  2,  2, 21, 21, 21,  2,  2,  2,  2,
+-    2,  2,  2, 21, 21, 21,  2,  2,  2,  2, 21, 21,  2, 21, 21, 21,
+-   21, 21,  2,  2, 21, 21,  2,  2, 22, 22,  2, 22, 22, 22, 22, 22,
+-   22,  2,  2,  2, 22, 22, 22,  2, 22, 22, 22, 22,  2,  2,  2, 22,
+-   22,  2, 22,  2, 22, 22,  2,  2,  2, 22, 22,  2,  2,  2, 22, 22,
+-   22, 22, 22, 22, 22, 22, 22, 22,  2,  2,  2,  2, 22, 22, 22,  2,
+-    2,  2,  2,  2,  2, 22,  2,  2,  2,  2,  2,  2, 22, 22, 22, 22,
+-   22,  2,  2,  2,  2,  2, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+-   23, 23, 23,  2, 23, 23, 23,  2, 23, 23, 23, 23, 23, 23, 23, 23,
+-    2,  2, 23, 23, 23, 23, 23,  2, 23, 23, 23, 23,  2,  2,  2,  2,
+-    2,  2,  2, 23, 23,  2, 23, 23, 23,  2,  2, 23,  2,  2, 23, 23,
+-   23, 23,  2,  2, 23, 23,  2,  2,  2,  2,  2,  2,  2, 23, 16, 16,
+-   16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,  2, 16, 16, 16,  2,
+-   16, 16, 16, 16, 16, 16, 16, 16, 16, 16,  2, 16, 16, 16, 16, 16,
+-    2,  2, 16, 16, 16, 16, 16,  2, 16, 16, 16, 16,  2,  2,  2,  2,
+-    2,  2,  2, 16, 16,  2, 16, 16, 16, 16,  2,  2, 16, 16,  2, 16,
+-   16, 16,  2,  2,  2,  2, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+-   20, 20, 20,  2, 20, 20, 20,  2, 20, 20, 20, 20, 20, 20,  2,  2,
+-    2,  2, 20, 20, 20, 20, 20, 20, 20, 20,  2,  2, 20, 20,  2, 36,
+-   36, 36,  2, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
+-   36, 36, 36, 36, 36,  2,  2,  2, 36, 36, 36, 36, 36, 36, 36, 36,
+-    2, 36, 36, 36, 36, 36, 36, 36, 36, 36,  2, 36,  2,  2,  2,  2,
+-   36,  2,  2,  2,  2, 36, 36, 36, 36, 36, 36,  2, 36,  2,  2,  2,
+-    2,  2,  2,  2, 36, 36,  2,  2, 36, 36, 36,  2,  2,  2,  2, 24,
+-   24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+-   24,  2,  2,  2,  2,  0, 24, 24, 24, 24,  2,  2,  2,  2,  2, 18,
+-   18,  2, 18,  2, 18, 18, 18, 18, 18,  2, 18, 18, 18, 18, 18, 18,
+-   18, 18, 18, 18, 18, 18, 18, 18, 18, 18,  2, 18,  2, 18, 18, 18,
+-   18, 18, 18, 18,  2,  2, 18, 18, 18, 18, 18,  2, 18,  2, 18, 18,
+-   18, 18, 18, 18, 18,  2, 18, 18,  2,  2, 18, 18, 18, 18, 25, 25,
+-   25, 25, 25, 25, 25, 25,  2, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+-   25, 25, 25,  2,  2,  2, 25, 25, 25, 25, 25,  2, 25, 25, 25, 25,
+-   25, 25, 25,  0,  0,  0,  0, 25, 25,  2,  2,  2,  2,  2, 33, 33,
+-   33, 33, 33, 33, 33, 33,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
+-    8,  8,  8,  8,  2,  8,  2,  2,  2,  2,  2,  8,  2,  2,  8,  8,
+-    8,  0,  8,  8,  8,  8, 12, 12, 12, 12, 12, 12, 12, 12, 30, 30,
+-   30, 30, 30, 30, 30, 30, 30,  2, 30, 30, 30, 30,  2,  2, 30, 30,
+-   30, 30, 30, 30, 30,  2, 30, 30, 30,  2,  2, 30, 30, 30, 30, 30,
+-   30, 30, 30,  2,  2,  2, 30, 30,  2,  2,  2,  2,  2,  2, 29, 29,
+-   29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,  2,  2, 28, 28,
+-   28, 28, 28, 28, 28, 28, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
+-   34, 34, 34,  2,  2,  2, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
+-   35,  0,  0,  0, 35, 35, 35,  2,  2,  2,  2,  2,  2,  2, 45, 45,
+-   45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,  2,  2,  2,  2,
+-    2,  2,  2,  2,  2, 45, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44,
+-   44, 44, 44,  0,  0,  2, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+-   43, 43,  2,  2,  2,  2, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46,
+-   46, 46, 46,  2, 46, 46, 46,  2, 46, 46,  2,  2,  2,  2, 31, 31,
+-   31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,  2,  2, 31, 31,
+-    2,  2,  2,  2,  2,  2, 32, 32,  0,  0, 32,  0, 32, 32, 32, 32,
+-   32, 32, 32, 32, 32, 32, 32, 32,  2,  2,  2,  2,  2,  2, 32,  2,
+-    2,  2,  2,  2,  2,  2, 32, 32, 32,  2,  2,  2,  2,  2, 28, 28,
+-   28, 28, 28, 28,  2,  2, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
+-   48, 48, 48, 48, 48,  2, 48, 48, 48, 48,  2,  2,  2,  2, 48,  2,
+-    2,  2, 48, 48, 48, 48, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
+-   52, 52, 52, 52,  2,  2, 52, 52, 52, 52, 52,  2,  2,  2, 58, 58,
+-   58, 58, 58, 58, 58, 58, 58, 58, 58, 58,  2,  2,  2,  2, 58, 58,
+-    2,  2,  2,  2,  2,  2, 58, 58, 58,  2,  2,  2, 58, 58, 54, 54,
+-   54, 54, 54, 54, 54, 54, 54, 54, 54, 54,  2,  2, 54, 54, 91, 91,
+-   91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,  2, 91, 91,
+-   91, 91, 91,  2,  2, 91, 91, 91,  2,  2,  2,  2,  2,  2, 91, 91,
+-   91, 91, 91, 91,  2,  2,  1,  1,  1,  1,  1,  1,  1,  2, 62, 62,
+-   62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,  2,  2,  2, 62, 62,
+-   62, 62, 62, 62, 62,  2, 76, 76, 76, 76, 76, 76, 76, 76, 93, 93,
++   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 60, 13, 13,
++   13, 61, 62, 13, 13, 13, 13, 63, 13, 13, 13, 13, 13, 13, 64, 65,
++   20, 20, 66, 20, 13, 13, 13, 13, 67, 13, 13, 13, 68, 20, 20, 20,
++   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
++   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
++   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
++   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
++   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
++   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
++   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
++   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
++   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
++   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
++   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
++   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
++   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
++   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
++   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
++   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
++   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
++   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
++   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
++   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
++   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
++   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
++   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
++   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
++   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
++   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
++   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
++   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
++   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
++   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
++   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
++   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
++   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
++   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
++   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
++   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
++   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
++   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
++   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
++   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
++   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
++   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
++   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
++   20, 20, 20, 20, 69,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 19,
++   19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
++   19,  0,  0,  0,  0,  0,  0,  0, 19,  0,  0,  0,  0,  0, 19, 19,
++   19, 19, 19, 19, 19,  0, 19,  0,  0,  0,  0,  0,  0,  0, 19, 19,
++   19, 19, 19,  0,  0,  0,  0,  0, 26, 26,  0,  0,  0,  0,  1,  1,
++    1,  1,  1,  1,  1,  1,  9,  9,  9,  9,  0,  9,  9,  9,  2,  2,
++    9,  9,  9,  9,  0,  9,  2,  2,  2,  2,  9,  0,  9,  0,  9,  9,
++    9,  2,  9,  2,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
++    2,  9,  9,  9,  9,  9,  9,  9, 55, 55, 55, 55, 55, 55, 55, 55,
++   55, 55, 55, 55, 55, 55,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,
++    6,  6,  6,  1,  1,  6,  2,  4,  4,  4,  4,  4,  4,  4,  4,  4,
++    4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  2,  4,  4,
++    4,  2,  2,  4,  4,  4,  2, 14, 14, 14, 14, 14, 14, 14, 14, 14,
++   14, 14, 14, 14, 14, 14,  2,  2,  2,  2,  2,  2,  2,  2, 14, 14,
++   14,  2,  2,  2,  2, 14, 14, 14, 14, 14, 14,  2,  2,  2,  3,  3,
++    3,  3,  3,  0,  3,  3,  3,  3,  3,  3,  0,  3,  3,  3,  3,  3,
++    3,  3,  3,  3,  3,  3,  3,  3,  3,  0,  3,  3,  3,  0,  0,  3,
++    3,  3,  3,  3,  3,  3,  3,  3,  3,  1,  1,  1,  1,  1,  1,  1,
++    1,  1,  1,  1,  3,  3,  1,  3,  3,  3,  3,  3,  3,  3, 37, 37,
++   37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,  2, 37, 37, 37,
++   37,  2,  2, 37, 37, 37, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
++    2,  2,  2,  2,  2,  2, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
++   64,  2,  2, 64, 64, 64, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90,
++   90, 90, 90, 90,  2,  2, 90, 90, 90, 90, 90, 90, 90,  2, 95, 95,
++   95, 95, 95, 95, 95, 95, 95, 95, 95, 95,  2,  2, 95,  2, 37, 37,
++   37,  2,  2,  2,  2,  2,  3,  3,  3,  3,  3,  3,  3,  2,  3,  3,
++    2,  2,  2,  2,  2,  3,  3,  3,  0,  3,  3,  3,  3,  3,  7,  7,
++    7,  7,  7,  7,  7,  7,  7,  1,  1,  1,  1,  7,  7,  7,  7,  7,
++    7,  7,  0,  0,  7,  7,  5,  5,  5,  5,  2,  5,  5,  5,  5,  5,
++    5,  5,  5,  2,  2,  5,  5,  2,  2,  5,  5,  5,  5,  5,  5,  5,
++    5,  5,  5,  5,  5,  5,  5,  2,  5,  5,  5,  5,  5,  5,  5,  2,
++    5,  2,  2,  2,  5,  5,  5,  5,  2,  2,  5,  5,  5,  5,  5,  2,
++    2,  5,  5,  5,  5,  2,  2,  2,  2,  2,  2,  2,  2,  5,  2,  2,
++    2,  2,  5,  5,  2,  5,  5,  5,  5,  5,  2,  2,  5,  5,  5,  5,
++    5,  5,  5,  5,  5,  2,  2, 11, 11, 11,  2, 11, 11, 11, 11, 11,
++   11,  2,  2,  2,  2, 11, 11,  2,  2, 11, 11, 11, 11, 11, 11, 11,
++   11, 11, 11, 11, 11, 11, 11,  2, 11, 11, 11, 11, 11, 11, 11,  2,
++   11, 11,  2, 11, 11,  2, 11, 11,  2,  2, 11,  2, 11, 11, 11,  2,
++    2, 11, 11, 11,  2,  2,  2, 11,  2,  2,  2,  2,  2,  2,  2, 11,
++   11, 11, 11,  2, 11,  2,  2,  2,  2,  2,  2,  2, 11, 11, 11, 11,
++   11, 11, 11, 11, 11,  2,  2, 10, 10, 10,  2, 10, 10, 10, 10, 10,
++   10, 10, 10, 10,  2, 10, 10, 10,  2, 10, 10, 10, 10, 10, 10, 10,
++   10, 10, 10, 10, 10, 10, 10,  2, 10, 10, 10, 10, 10, 10, 10,  2,
++   10, 10,  2, 10, 10, 10, 10, 10,  2,  2, 10, 10, 10, 10, 10, 10,
++    2, 10, 10, 10,  2,  2, 10,  2,  2,  2,  2,  2,  2,  2, 10, 10,
++   10, 10,  2,  2, 10, 10, 10, 10,  2,  2,  2,  2,  2,  2,  2, 10,
++   10, 10, 10, 10, 10, 10,  2, 21, 21, 21,  2, 21, 21, 21, 21, 21,
++   21, 21, 21,  2,  2, 21, 21,  2,  2, 21, 21, 21, 21, 21, 21, 21,
++   21, 21, 21, 21, 21, 21, 21,  2, 21, 21, 21, 21, 21, 21, 21,  2,
++   21, 21,  2, 21, 21, 21, 21, 21,  2,  2, 21, 21, 21, 21, 21,  2,
++    2, 21, 21, 21,  2,  2,  2,  2,  2,  2,  2, 21, 21, 21,  2,  2,
++    2,  2, 21, 21,  2, 21, 21, 21, 21, 21,  2,  2, 21, 21,  2,  2,
++   22, 22,  2, 22, 22, 22, 22, 22, 22,  2,  2,  2, 22, 22, 22,  2,
++   22, 22, 22, 22,  2,  2,  2, 22, 22,  2, 22,  2, 22, 22,  2,  2,
++    2, 22, 22,  2,  2,  2, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
++    2,  2,  2,  2, 22, 22, 22,  2,  2,  2,  2,  2,  2, 22,  2,  2,
++    2,  2,  2,  2, 22, 22, 22, 22, 22,  2,  2,  2,  2,  2, 23, 23,
++   23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,  2, 23, 23, 23,  2,
++   23, 23, 23, 23, 23, 23, 23, 23,  2,  2, 23, 23, 23, 23, 23,  2,
++   23, 23, 23, 23,  2,  2,  2,  2,  2,  2,  2, 23, 23,  2, 23, 23,
++   23,  2,  2, 23,  2,  2, 23, 23, 23, 23,  2,  2, 23, 23,  2,  2,
++    2,  2,  2,  2,  2, 23, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
++   16, 16, 16,  2, 16, 16, 16,  2, 16, 16, 16, 16, 16, 16, 16, 16,
++   16, 16,  2, 16, 16, 16, 16, 16,  2,  2, 16, 16, 16, 16, 16,  2,
++   16, 16, 16, 16,  2,  2,  2,  2,  2,  2,  2, 16, 16,  2, 16, 16,
++   16, 16,  2,  2, 16, 16,  2, 16, 16, 16,  2,  2,  2,  2, 20, 20,
++   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  2, 20, 20, 20,  2,
++   20, 20, 20, 20, 20, 20,  2,  2,  2,  2, 20, 20, 20, 20, 20, 20,
++   20, 20,  2,  2, 20, 20,  2, 36, 36, 36,  2, 36, 36, 36, 36, 36,
++   36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,  2,  2,  2,
++   36, 36, 36, 36, 36, 36, 36, 36,  2, 36, 36, 36, 36, 36, 36, 36,
++   36, 36,  2, 36,  2,  2,  2,  2, 36,  2,  2,  2,  2, 36, 36, 36,
++   36, 36, 36,  2, 36,  2,  2,  2,  2,  2,  2,  2, 36, 36,  2,  2,
++   36, 36, 36,  2,  2,  2,  2, 24, 24, 24, 24, 24, 24, 24, 24, 24,
++   24, 24, 24, 24, 24, 24, 24, 24, 24,  2,  2,  2,  2,  0, 24, 24,
++   24, 24,  2,  2,  2,  2,  2, 18, 18,  2, 18,  2, 18, 18, 18, 18,
++   18,  2, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
++   18, 18,  2, 18,  2, 18, 18, 18, 18, 18, 18, 18,  2,  2, 18, 18,
++   18, 18, 18,  2, 18,  2, 18, 18, 18, 18, 18, 18, 18,  2, 18, 18,
++    2,  2, 18, 18, 18, 18, 25, 25, 25, 25, 25, 25, 25, 25,  2, 25,
++   25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,  2,  2,  2, 25, 25,
++   25, 25, 25,  2, 25, 25, 25, 25, 25, 25, 25,  0,  0,  0,  0, 25,
++   25,  2,  2,  2,  2,  2, 33, 33, 33, 33, 33, 33, 33, 33,  8,  8,
++    8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  2,  8,  2,  2,
++    2,  2,  2,  8,  2,  2,  8,  8,  8,  0,  8,  8,  8,  8, 12, 12,
++   12, 12, 12, 12, 12, 12, 30, 30, 30, 30, 30, 30, 30, 30, 30,  2,
++   30, 30, 30, 30,  2,  2, 30, 30, 30, 30, 30, 30, 30,  2, 30, 30,
++   30,  2,  2, 30, 30, 30, 30, 30, 30, 30, 30,  2,  2,  2, 30, 30,
++    2,  2,  2,  2,  2,  2, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
++   29, 29, 29, 29,  2,  2, 28, 28, 28, 28, 28, 28, 28, 28, 34, 34,
++   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,  2,  2,  2, 35, 35,
++   35, 35, 35, 35, 35, 35, 35, 35, 35,  0,  0,  0, 35, 35, 35,  2,
++    2,  2,  2,  2,  2,  2, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
++   45, 45, 45, 45,  2,  2,  2,  2,  2,  2,  2,  2,  2, 45, 44, 44,
++   44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44,  0,  0,  2, 43, 43,
++   43, 43, 43, 43, 43, 43, 43, 43, 43, 43,  2,  2,  2,  2, 46, 46,
++   46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46,  2, 46, 46, 46,  2,
++   46, 46,  2,  2,  2,  2, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
++   31, 31, 31, 31,  2,  2, 31, 31,  2,  2,  2,  2,  2,  2, 32, 32,
++    0,  0, 32,  0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
++    2,  2,  2,  2,  2,  2, 32,  2,  2,  2,  2,  2,  2,  2, 32, 32,
++   32,  2,  2,  2,  2,  2, 28, 28, 28, 28, 28, 28,  2,  2, 48, 48,
++   48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,  2, 48, 48,
++   48, 48,  2,  2,  2,  2, 48,  2,  2,  2, 48, 48, 48, 48, 52, 52,
++   52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,  2,  2, 52, 52,
++   52, 52, 52,  2,  2,  2, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
++   58, 58,  2,  2,  2,  2, 58, 58,  2,  2,  2,  2,  2,  2, 58, 58,
++   58,  2,  2,  2, 58, 58, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
++   54, 54,  2,  2, 54, 54, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
++   91, 91, 91, 91, 91,  2, 91, 91, 91, 91, 91,  2,  2, 91, 91, 91,
++    2,  2,  2,  2,  2,  2, 91, 91, 91, 91, 91, 91,  2,  2,  1,  1,
++    1,  1,  1,  1,  1,  2, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
++   62, 62, 62,  2, 62, 62, 76, 76, 76, 76, 76, 76, 76, 76, 93, 93,
+    93, 93, 93, 93, 93, 93, 93, 93, 93, 93,  2,  2,  2,  2,  2,  2,
+     2,  2, 93, 93, 93, 93, 70, 70, 70, 70, 70, 70, 70, 70,  2,  2,
+     2, 70, 70, 70, 70, 70, 70, 70,  2,  2,  2, 70, 70, 70, 73, 73,
+-   73, 73, 73, 73, 73, 73,  6,  2,  2,  2,  2,  2,  2,  2,  8,  8,
++   73, 73, 73, 73, 73, 73,  6,  6,  6,  2,  2,  2,  2,  2,  8,  8,
+     8,  2,  2,  8,  8,  8,  1,  1,  1,  0,  1,  1,  1,  1,  1,  0,
+     1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  1,  0,  0,  0,  0,
+     0,  0,  1,  0,  0,  0,  1,  1,  0,  2,  2,  2,  2,  2, 19, 19,
+@@ -1896,31 +1872,30 @@ _hb_ucd_u8[17884] =
+     2,  2,  2,  2,  2,  2,  1,  2,  2,  2,  2,  2,  2,  2,  0,  0,
+     0,  0,  0,  0,  9,  0,  0,  0, 19, 19,  0,  0,  0,  0,  0,  0,
+     0,  0,  0,  0, 19,  0, 19,  0,  0,  0,  2,  2,  2,  2,  0,  0,
+-    0,  2,  2,  2,  2,  2, 27, 27, 27, 27, 27, 27, 27, 27,  0,  0,
+-    0,  0,  2,  2,  0,  0,  0,  0,  0,  0,  0,  0,  2,  0, 56, 56,
+-   56, 56, 56, 56, 56, 56, 55, 55, 55, 55,  2,  2,  2,  2,  2, 55,
+-   55, 55, 55, 55, 55, 55, 61, 61, 61, 61, 61, 61, 61, 61,  2,  2,
+-    2,  2,  2,  2,  2, 61, 61,  2,  2,  2,  2,  2,  2,  2,  0,  0,
+-    0,  0,  0,  0,  2,  2, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+-    2, 13, 13, 13, 13, 13, 13, 13, 13, 13,  2,  2,  2,  2, 13, 13,
+-   13, 13, 13, 13,  2,  2,  0,  0,  0,  0,  0, 13,  0, 13,  0, 13,
+-   13, 13, 13, 13, 13, 13, 13, 13,  1,  1,  1,  1, 12, 12, 13, 13,
+-   13, 13,  0,  0,  0,  0,  2, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+-   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,  2,  2,  1,
+-    1,  0,  0, 15, 15, 15,  0, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+-   17, 17, 17, 17, 17, 17, 17, 17, 17,  0,  0, 17, 17, 17,  2,  2,
+-    2,  2,  2, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,  2, 12,
+-   12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,  2,  0,  0,
+-    0,  0,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  0, 12, 12,
++    2,  2,  2,  2,  2,  2,  0,  0,  0,  2,  2,  2,  2,  2, 27, 27,
++   27, 27, 27, 27, 27, 27,  0,  0,  0,  0,  2,  2,  0,  0,  0,  0,
++    0,  0,  0,  0,  2,  0, 56, 56, 56, 56, 56, 56, 56, 56, 55, 55,
++   55, 55,  2,  2,  2,  2,  2, 55, 55, 55, 55, 55, 55, 55, 61, 61,
++   61, 61, 61, 61, 61, 61,  2,  2,  2,  2,  2,  2,  2, 61, 61,  2,
++    2,  2,  2,  2,  2,  2,  0,  0,  0,  0,  0,  0,  2,  2, 13, 13,
++   13, 13, 13, 13, 13, 13, 13, 13,  2, 13, 13, 13, 13, 13, 13, 13,
++   13, 13,  2,  2,  2,  2, 13, 13, 13, 13, 13, 13,  2,  2,  0,  0,
++    0,  0,  0, 13,  0, 13,  0, 13, 13, 13, 13, 13, 13, 13, 13, 13,
++    1,  1,  1,  1, 12, 12, 13, 13, 13, 13,  0,  0,  0,  0,  2, 15,
++   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
++   15, 15, 15, 15, 15,  2,  2,  1,  1,  0,  0, 15, 15, 15,  0, 17,
++   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
++   17,  0,  0, 17, 17, 17,  2,  2,  2,  2,  2, 26, 26, 26, 26, 26,
++   26, 26, 26, 26, 26, 26,  2, 12, 12, 12, 12, 12, 12, 12, 12, 12,
++   12, 12, 12, 12, 12,  2,  2,  2,  2,  2,  2,  2,  2,  0, 12, 12,
+    12, 12, 12, 12, 12,  0, 17, 17, 17, 17, 17, 17, 17,  0, 39, 39,
+    39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,  2,  2,  2, 39, 39,
+    39, 39, 39, 39, 39,  2, 86, 86, 86, 86, 86, 86, 86, 86, 77, 77,
+    77, 77, 77, 77, 77, 77, 77, 77, 77, 77,  2,  2,  2,  2, 79, 79,
+    79, 79, 79, 79, 79, 79,  0,  0, 19, 19, 19, 19, 19, 19,  0,  0,
+-    0, 19, 19, 19, 19, 19, 19, 19, 19,  2,  2,  2,  2,  2, 19, 19,
+-    2, 19,  2, 19, 19, 19, 19, 19,  2,  2,  2,  2,  2,  2,  2,  2,
+-   19, 19, 19, 19, 19, 19, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,
+-   60, 60, 60,  2,  2,  2,  0,  0,  2,  2,  2,  2,  2,  2, 65, 65,
++    0, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,  2,  2, 19, 19,
++    2, 19,  2, 19, 19, 19,  2,  2, 19, 19, 19, 19, 19, 19, 60, 60,
++   60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,  2,  2,  2, 65, 65,
+    65, 65, 65, 65, 65, 65, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75,
+    75, 75, 75, 75,  2,  2,  2,  2,  2,  2,  2,  2, 75, 75, 75, 75,
+     2,  2,  2,  2,  2,  2, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69,
+@@ -1943,36 +1918,38 @@ _hb_ucd_u8[17884] =
+     2, 14, 14,  2, 14, 14,  3,  3,  3,  2,  2,  2,  2,  2,  2,  2,
+     2,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  0,  0,  2,  2,
+     3,  3,  3,  3,  3,  3,  2,  2,  2,  2,  2,  2,  2,  3,  1,  1,
+-    1,  1,  1,  1,  6,  6,  0,  0,  0,  2,  0,  0,  0,  0,  3,  3,
+-    3,  3,  3,  2,  3,  3,  3,  3,  3,  3,  3,  2,  2,  0,  2,  0,
+-    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 17, 17, 17, 17,
+-   17, 17, 17, 17,  0,  0,  2,  2, 12, 12, 12, 12, 12, 12,  2,  2,
+-   12, 12, 12,  2,  2,  2,  2,  0,  0,  0,  0,  0,  2,  2, 49, 49,
+-   49, 49, 49, 49, 49, 49, 49, 49, 49, 49,  2, 49, 49, 49, 49, 49,
+-   49, 49, 49, 49, 49,  2, 49, 49, 49,  2, 49, 49,  2, 49, 49, 49,
+-   49, 49, 49, 49,  2,  2, 49, 49, 49,  2,  2,  2,  2,  2,  0,  0,
+-    0,  2,  2,  2,  2,  0,  0,  0,  0,  0,  2,  2,  2,  0,  0,  0,
+-    0,  0,  0,  2,  2,  2,  9,  2,  2,  2,  2,  2,  2,  2,  0,  0,
+-    0,  0,  0,  1,  2,  2, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
+-   71, 71, 71,  2,  2,  2, 67, 67, 67, 67, 67, 67, 67, 67, 67,  2,
+-    2,  2,  2,  2,  2,  2,  1,  0,  0,  0,  0,  0,  0,  0, 42, 42,
+-   42, 42, 42, 42, 42, 42, 42, 42, 42, 42,  2,  2,  2,  2,  2,  2,
+-    2,  2,  2, 42, 42, 42, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
+-   41,  2,  2,  2,  2,  2,118,118,118,118,118,118,118,118,118,118,
+-  118,  2,  2,  2,  2,  2, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
+-   53, 53, 53, 53,  2, 53, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+-   59, 59,  2,  2,  2,  2, 59, 59, 59, 59, 59, 59,  2,  2, 40, 40,
+-   40, 40, 40, 40, 40, 40, 51, 51, 51, 51, 51, 51, 51, 51, 50, 50,
+-   50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,  2,  2, 50, 50,
+-    2,  2,  2,  2,  2,  2,135,135,135,135,135,135,135,135,135,135,
+-  135,135,  2,  2,  2,  2,106,106,106,106,106,106,106,106,104,104,
+-  104,104,104,104,104,104,104,104,104,104,  2,  2,  2,  2,  2,  2,
+-    2,  2,  2,  2,  2,104,161,161,161,161,161,161,161,161,161,161,
+-  161,  2,161,161,161,161,161,161,161,  2,161,161,  2,161,161,161,
+-    2,161,161,161,161,161,161,161,  2,161,161,  2,  2,  2,110,110,
+-  110,110,110,110,110,110,110,110,110,110,110,110,110,  2,110,110,
+-  110,110,110,110,  2,  2, 19, 19, 19, 19, 19, 19,  2, 19, 19,  2,
+-   19, 19, 19, 19, 19, 19, 47, 47, 47, 47, 47, 47,  2,  2, 47,  2,
++    1,  1,  1,  1,  6,  6,  0,  0,  0,  2,  0,  0,  0,  0,  0,  0,
++    0,  0,  2,  2,  2,  2,  3,  3,  3,  3,  3,  2,  3,  3,  3,  3,
++    3,  3,  3,  2,  2,  0,  2,  0,  0,  0,  0,  0,  0,  0,  0,  0,
++    0,  0,  0,  0, 17, 17, 17, 17, 17, 17, 17, 17,  0,  0,  2,  2,
++   12, 12, 12, 12, 12, 12,  2,  2, 12, 12, 12,  2,  2,  2,  2,  0,
++    0,  0,  0,  0,  2,  2, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
++   49, 49,  2, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,  2, 49, 49,
++   49,  2, 49, 49,  2, 49, 49, 49, 49, 49, 49, 49,  2,  2, 49, 49,
++   49,  2,  2,  2,  2,  2,  0,  0,  0,  2,  2,  2,  2,  0,  0,  0,
++    0,  0,  2,  2,  2,  0,  0,  0,  0,  0,  0,  2,  2,  2,  9,  2,
++    2,  2,  2,  2,  2,  2,  0,  0,  0,  0,  0,  1,  2,  2, 71, 71,
++   71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,  2,  2,  2, 67, 67,
++   67, 67, 67, 67, 67, 67, 67,  2,  2,  2,  2,  2,  2,  2,  1,  0,
++    0,  0,  0,  0,  0,  0, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
++   42, 42,  2,  2,  2,  2,  2,  2,  2,  2,  2, 42, 42, 42, 41, 41,
++   41, 41, 41, 41, 41, 41, 41, 41, 41,  2,  2,  2,  2,  2,118,118,
++  118,118,118,118,118,118,118,118,118,  2,  2,  2,  2,  2, 53, 53,
++   53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,  2, 53, 59, 59,
++   59, 59, 59, 59, 59, 59, 59, 59, 59, 59,  2,  2,  2,  2, 59, 59,
++   59, 59, 59, 59,  2,  2, 40, 40, 40, 40, 40, 40, 40, 40, 51, 51,
++   51, 51, 51, 51, 51, 51, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
++   50, 50, 50, 50,  2,  2, 50, 50,  2,  2,  2,  2,  2,  2,135,135,
++  135,135,135,135,135,135,135,135,135,135,  2,  2,  2,  2,106,106,
++  106,106,106,106,106,106,104,104,104,104,104,104,104,104,104,104,
++  104,104,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,104,161,161,
++  161,161,161,161,161,161,161,161,161,  2,161,161,161,161,161,161,
++  161,  2,161,161,  2,161,161,161,  2,161,161,161,161,161,161,161,
++    2,161,161,  2,  2,  2,170,170,170,170,170,170,170,170,170,170,
++  170,170,  2,  2,  2,  2,110,110,110,110,110,110,110,110,110,110,
++  110,110,110,110,110,  2,110,110,110,110,110,110,  2,  2, 19, 19,
++   19, 19, 19, 19,  2, 19, 19,  2, 19, 19, 19, 19, 19, 19, 19, 19,
++   19,  2,  2,  2,  2,  2, 47, 47, 47, 47, 47, 47,  2,  2, 47,  2,
+    47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+    47, 47, 47, 47,  2, 47, 47,  2,  2,  2, 47,  2,  2, 47, 81, 81,
+    81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,  2, 81,120,120,
+@@ -1998,122 +1975,135 @@ _hb_ucd_u8[17884] =
+   122,122,122,122,122,122, 89, 89, 89, 89, 89, 89, 89, 89, 89,  2,
+     2,  2,  2,  2,  2,  2,130,130,130,130,130,130,130,130,130,130,
+   130,  2,  2,  2,  2,  2,  2,  2,130,130,130,130,130,130,144,144,
+-  144,144,144,144,144,144,144,144,  2,  2,  2,  2,  2,  2,156,156,
++  144,144,144,144,144,144,144,144,  2,  2,  2,  2,  2,  2,165,165,
++  165,165,165,165,165,165,165,165,165,165,165,165,  2,  2,  2,165,
++  165,165,165,165,165,165,  2,  2,  2,  2,  2,  2,165,165,156,156,
+   156,156,156,156,156,156,156,156,  2,156,156,156,  2,  2,156,156,
+-    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  3,  3,  3,147,147,
+-  147,147,147,147,147,147,148,148,148,148,148,148,148,148,148,148,
+-    2,  2,  2,  2,  2,  2,158,158,158,158,158,158,158,158,158,158,
+-    2,  2,  2,  2,  2,  2,153,153,153,153,153,153,153,153,153,153,
+-  153,153,  2,  2,  2,  2,149,149,149,149,149,149,149,149,149,149,
+-  149,149,149,149,149,  2, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
+-   94, 94, 94, 94,  2,  2,  2,  2, 94, 94, 94, 94, 94, 94,  2,  2,
+-    2,  2,  2,  2,  2, 94, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
+-   85,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 85,  2,  2,101,101,
+-  101,101,101,101,101,101,101,  2,  2,  2,  2,  2,  2,  2,101,101,
+-    2,  2,  2,  2,  2,  2, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
+-   96, 96, 96,  2, 96, 96,111,111,111,111,111,111,111,111,111,111,
+-  111,111,111,111,111,  2,100,100,100,100,100,100,100,100,  2, 36,
+-   36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,  2,  2,  2,108,108,
+-  108,108,108,108,108,108,108,108,  2,108,108,108,108,108,108,108,
+-    2,  2,  2,  2,  2,  2,129,129,129,129,129,129,129,  2,129,  2,
+-  129,129,129,129,  2,129,129,129,129,129,129,129,129,129,129,129,
+-  129,129,129,129,  2,129,129,129,  2,  2,  2,  2,  2,  2,109,109,
+-  109,109,109,109,109,109,109,109,109,  2,  2,  2,  2,  2,109,109,
+-    2,  2,  2,  2,  2,  2,107,107,107,107,  2,107,107,107,107,107,
+-  107,107,107,  2,  2,107,107,  2,  2,107,107,107,107,107,107,107,
+-  107,107,107,107,107,107,107,  2,107,107,107,107,107,107,107,  2,
+-  107,107,  2,107,107,107,107,107,  2,  1,107,107,107,107,107,  2,
+-    2,107,107,107,  2,  2,107,  2,  2,  2,  2,  2,  2,107,  2,  2,
+-    2,  2,  2,107,107,107,107,107,107,107,  2,  2,107,107,107,107,
+-  107,107,107,  2,  2,  2,137,137,137,137,137,137,137,137,137,137,
++    2,  2,  2,  2,  2,  2,  2,  2,  3,  3,  3,  2,  2,  2,  2,  2,
++    2,  2,  3,  3,  3,  3,147,147,147,147,147,147,147,147,148,148,
++  148,148,148,148,148,148,148,148,  2,  2,  2,  2,  2,  2,158,158,
++  158,158,158,158,158,158,158,158,  2,  2,  2,  2,  2,  2,153,153,
++  153,153,153,153,153,153,153,153,153,153,  2,  2,  2,  2,149,149,
++  149,149,149,149,149,149,149,149,149,149,149,149,149,  2, 94, 94,
++   94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,  2,  2,  2,  2,
++   94, 94, 94, 94, 94, 94,  2,  2,  2,  2,  2,  2,  2, 94, 85, 85,
++   85, 85, 85, 85, 85, 85, 85, 85, 85,  2,  2,  2,  2,  2,  2,  2,
++    2,  2,  2, 85,  2,  2,101,101,101,101,101,101,101,101,101,  2,
++    2,  2,  2,  2,  2,  2,101,101,  2,  2,  2,  2,  2,  2, 96, 96,
++   96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,  2, 96, 96,111,111,
++  111,111,111,111,111,111,111,111,111,111,111,111,111,  2,100,100,
++  100,100,100,100,100,100,  2, 36, 36, 36, 36, 36, 36, 36, 36, 36,
++   36, 36, 36,  2,  2,  2,108,108,108,108,108,108,108,108,108,108,
++    2,108,108,108,108,108,108,108,  2,  2,  2,  2,  2,  2,129,129,
++  129,129,129,129,129,  2,129,  2,129,129,129,129,  2,129,129,129,
++  129,129,129,129,129,129,129,129,129,129,129,129,  2,129,129,129,
++    2,  2,  2,  2,  2,  2,109,109,109,109,109,109,109,109,109,109,
++  109,  2,  2,  2,  2,  2,109,109,  2,  2,  2,  2,  2,  2,107,107,
++  107,107,  2,107,107,107,107,107,107,107,107,  2,  2,107,107,  2,
++    2,107,107,107,107,107,107,107,107,107,107,107,107,107,107,  2,
++  107,107,107,107,107,107,107,  2,107,107,  2,107,107,107,107,107,
++    2,  1,107,107,107,107,107,  2,  2,107,107,107,  2,  2,107,  2,
++    2,  2,  2,  2,  2,107,  2,  2,  2,  2,  2,107,107,107,107,107,
++  107,107,  2,  2,107,107,107,107,107,107,107,  2,  2,  2,171,171,
++  171,171,171,171,171,171,171,171,  2,171,  2,  2,171,  2,171,171,
++  171,171,171,171,  2,171,171,  2,171,  2,  2,171,  2,171,171,171,
++  171,  2,171,171,171,171,171,  2,  2,  2,  2,  2,  2,  2,  2,171,
++  171,  2,  2,  2,  2,  2,137,137,137,137,137,137,137,137,137,137,
+   137,137,  2,137,137,137,137,137,  2,  2,  2,  2,  2,  2,124,124,
+   124,124,124,124,124,124,124,124,  2,  2,  2,  2,  2,  2,123,123,
+   123,123,123,123,123,123,123,123,123,123,123,123,  2,  2,114,114,
+   114,114,114,114,114,114,114,114,114,114,114,  2,  2,  2,114,114,
+     2,  2,  2,  2,  2,  2, 32, 32, 32, 32, 32,  2,  2,  2,102,102,
+-  102,102,102,102,102,102,102,102,  2,  2,  2,  2,  2,  2,126,126,
+-  126,126,126,126,126,126,126,126,126,  2,  2,126,126,126,126,126,
+-  126,126,  2,  2,  2,  2,126,126,126,126,126,126,126,  2,142,142,
+-  142,142,142,142,142,142,142,142,142,142,  2,  2,  2,  2,125,125,
+-  125,125,125,125,125,125,125,125,125,  2,  2,  2,  2,  2,  2,  2,
+-    2,  2,  2,  2,  2,125,154,154,154,154,154,154,154,  2,  2,154,
+-    2,  2,154,154,154,154,154,154,154,154,  2,154,154,  2,154,154,
+-  154,154,154,154,154,154,154,154,154,154,154,154,  2,154,154,  2,
+-    2,154,154,154,154,154,154,154,  2,  2,  2,  2,  2,  2,150,150,
+-  150,150,150,150,150,150,  2,  2,150,150,150,150,150,150,150,150,
+-  150,150,150,  2,  2,  2,141,141,141,141,141,141,141,141,140,140,
+-  140,140,140,140,140,140,140,140,140,  2,  2,  2,  2,  2,121,121,
+-  121,121,121,121,121,121,121,  2,  2,  2,  2,  2,  2,  2,  7,  7,
+-    2,  2,  2,  2,  2,  2,133,133,133,133,133,133,133,133,133,  2,
+-  133,133,133,133,133,133,133,133,133,133,133,133,133,  2,133,133,
+-  133,133,133,133,  2,  2,133,133,133,133,133,  2,  2,  2,134,134,
+-  134,134,134,134,134,134,  2,  2,134,134,134,134,134,134,  2,134,
+-  134,134,134,134,134,134,134,134,134,134,134,134,134,  2,138,138,
+-  138,138,138,138,138,  2,138,138,  2,138,138,138,138,138,138,138,
+-  138,138,138,138,138,138,  2,  2,138,  2,138,138,  2,138,138,138,
+-    2,  2,  2,  2,  2,  2,143,143,143,143,143,143,  2,143,143,  2,
+-  143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,
+-  143,143,143,143,143,  2,143,143,  2,143,143,143,143,143,143,  2,
+-    2,  2,  2,  2,  2,  2,143,143,  2,  2,  2,  2,  2,  2,145,145,
+-  145,145,145,145,145,145,145,  2,  2,  2,  2,  2,  2,  2,163,163,
+-  163,163,163,163,163,163,163,  2,163,163,163,163,163,163,163,163,
+-  163,  2,  2,  2,163,163,163,163,  2,  2,  2,  2,  2,  2, 86,  2,
+-    2,  2,  2,  2,  2,  2, 22, 22,  2,  2,  2,  2,  2,  2,  2,  2,
+-    2,  2,  2,  2,  2, 22, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63,
+-    2,  2,  2,  2,  2,  2, 63, 63, 63, 63, 63, 63, 63,  2, 63, 63,
+-   63, 63, 63,  2,  2,  2, 63, 63, 63, 63,  2,  2,  2,  2,157,157,
+-  157,157,157,157,157,157,157,157,157,  2,  2,  2,  2,  2, 80, 80,
+-   80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,  2,  2,127,127,
+-  127,127,127,127,127,127,127,127,127,127,127,127,127,  2, 79,  2,
++  102,102,102,102,102,102,102,102,  2,  2,  2,  2,  2,  2, 33, 33,
++   33, 33,  2,  2,  2,  2,126,126,126,126,126,126,126,126,126,126,
++  126,  2,  2,126,126,126,126,126,126,126,  2,  2,  2,  2,126,126,
++  126,126,126,126,126,  2,142,142,142,142,142,142,142,142,142,142,
++  142,142,  2,  2,  2,  2,125,125,125,125,125,125,125,125,125,125,
++  125,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,125,154,154,
++  154,154,154,154,154,  2,  2,154,  2,  2,154,154,154,154,154,154,
++  154,154,  2,154,154,  2,154,154,154,154,154,154,154,154,154,154,
++  154,154,154,154,  2,154,154,  2,  2,154,154,154,154,154,154,154,
++    2,  2,  2,  2,  2,  2,150,150,150,150,150,150,150,150,  2,  2,
++  150,150,150,150,150,150,150,150,150,150,150,  2,  2,  2,141,141,
++  141,141,141,141,141,141,140,140,140,140,140,140,140,140,140,140,
++  140,  2,  2,  2,  2,  2,121,121,121,121,121,121,121,121,121,  2,
++    2,  2,  2,  2,  2,  2,  7,  7,  2,  2,  2,  2,  2,  2,169,169,
++  169,169,169,169,169,169,169,169,  2,  2,  2,  2,  2,  2,133,133,
++  133,133,133,133,133,133,133,  2,133,133,133,133,133,133,133,133,
++  133,133,133,133,133,  2,133,133,133,133,133,133,  2,  2,133,133,
++  133,133,133,  2,  2,  2,134,134,134,134,134,134,134,134,  2,  2,
++  134,134,134,134,134,134,  2,134,134,134,134,134,134,134,134,134,
++  134,134,134,134,134,  2,138,138,138,138,138,138,138,  2,138,138,
++    2,138,138,138,138,138,138,138,138,138,138,138,138,138,  2,  2,
++  138,  2,138,138,  2,138,138,138,  2,  2,  2,  2,  2,  2,143,143,
++  143,143,143,143,  2,143,143,  2,143,143,143,143,143,143,143,143,
++  143,143,143,143,143,143,143,143,143,143,143,143,143,  2,143,143,
++    2,143,143,143,143,143,143,  2,  2,  2,  2,  2,  2,  2,143,143,
++    2,  2,  2,  2,  2,  2,145,145,145,145,145,145,145,145,145,  2,
++    2,  2,  2,  2,  2,  2,163,163,163,163,163,163,163,163,163,  2,
++  163,163,163,163,163,163,163,163,163,  2,  2,  2,163,163,163,163,
++  163,  2,  2,  2,  2,  2, 86,  2,  2,  2,  2,  2,  2,  2, 22, 22,
++    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 22, 63, 63,
++   63, 63, 63, 63, 63, 63, 63, 63,  2,  2,  2,  2,  2,  2, 63, 63,
++   63, 63, 63, 63, 63,  2, 63, 63, 63, 63, 63,  2,  2,  2, 63, 63,
++   63, 63,  2,  2,  2,  2,157,157,157,157,157,157,157,157,157,157,
++  157,  2,  2,  2,  2,  2, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
++   80, 80, 80, 80,  2,  2, 80, 80, 80,  2,  2,  2,  2,  2,127,127,
++  127,127,127,127,127,127,127,127,127,127,127,127,127,  2,166,166,
++  166,166,166,166,166,166,166,166,  2,  2,  2,  2,  2,  2, 79,  2,
+     2,  2,  2,  2,  2,  2,115,115,115,115,115,115,115,115,115,115,
+   115,115,115,115,115,  2,115,115,  2,  2,  2,  2,115,115,159,159,
+   159,159,159,159,159,159,159,159,159,159,159,159,159,  2,159,159,
+     2,  2,  2,  2,  2,  2,103,103,103,103,103,103,103,103,103,103,
+   103,103,103,103,  2,  2,119,119,119,119,119,119,119,119,119,119,
+   119,119,119,119,  2,  2,119,119,  2,119,119,119,119,119,  2,  2,
+-    2,  2,  2,119,119,119,146,146,146,146,146,146,146,146,146,146,
++    2,  2,  2,119,119,119,167,167,167,167,167,167,167,167,167,167,
++    2,  2,  2,  2,  2,  2,146,146,146,146,146,146,146,146,146,146,
+   146,  2,  2,  2,  2,  2, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
+    99,  2,  2,  2,  2, 99,  2,  2,  2,  2,  2,  2,  2, 99,136,139,
+    13, 13,155,  2,  2,  2,136,136,136,136,136,136,136,136,155,155,
+-  155,155,155,155,155,155,155,155,155,155,155,155,  2,  2,136,  2,
+-    2,  2,  2,  2,  2,  2, 17, 17, 17, 17,  2, 17, 17, 17, 17, 17,
+-   17, 17,  2, 17, 17,  2, 17, 15, 15, 15, 15, 15, 15, 15, 17, 17,
+-   17,  2,  2,  2,  2,  2,  2,  2, 15,  2,  2,  2,  2,  2, 15, 15,
+-   15,  2,  2, 17,  2,  2,  2,  2,  2,  2, 17, 17, 17, 17,139,139,
+-  139,139,139,139,139,139,139,139,139,139,  2,  2,  2,  2,105,105,
+-  105,105,105,105,105,105,105,105,105,  2,  2,  2,  2,  2,105,105,
+-  105,105,105,  2,  2,  2,105,  2,  2,  2,  2,  2,  2,  2,105,105,
+-    2,  2,105,105,105,105,  1,  1,  1,  1,  1,  1,  2,  2,  0,  0,
+-    0,  0,  0,  0,  0,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,
+-    0,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  1,  1,  1,  1,  1,
+-    1,  1,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  0,  0,  2,  2,
+-    0,  2,  2,  0,  0,  2,  2,  0,  0,  0,  0,  2,  0,  0,  0,  0,
+-    2,  0,  2,  0,  0,  0,  0,  0,  0,  0,  2,  0,  0,  0,  0,  0,
+-    0,  2,  2,  0,  0,  0,  0,  0,  2,  0,  0,  0,  0,  2,  0,  0,
+-    0,  0,  0,  2,  0,  2,  2,  2,  0,  0,  0,  0,  0,  0,  0,  2,
+-    0,  0,  0,  0,  0,  0,131,131,131,131,131,131,131,131,131,131,
+-  131,131,  2,  2,  2,  2,  2,  2,  2,131,131,131,131,131,  2,131,
+-  131,131,131,131,131,131,  2,  2,  2,  2,  2, 19, 19, 19, 56, 56,
+-   56, 56, 56, 56, 56,  2, 56,  2,  2, 56, 56, 56, 56, 56, 56, 56,
+-    2, 56, 56,  2, 56, 56, 56, 56, 56,  2,  2,  2,  2,  2,  6,  6,
+-    6,  6,  6,  6,  2,  2,  2,  2,  2,  2,  2,  2,  2,  6,151,151,
+-  151,151,151,151,151,151,151,151,151,151,151,  2,  2,  2,151,151,
+-  151,151,151,151,  2,  2,151,151,  2,  2,  2,  2,151,151,160,160,
+-  160,160,160,160,160,160,160,160,160,160,160,160,160,  2,152,152,
+-  152,152,152,152,152,152,152,152,  2,  2,  2,  2,  2,152,164,164,
+-  164,164,164,164,164,164,164,164,  2,  2,  2,  2,  2,  2, 30, 30,
+-   30, 30,  2, 30, 30,  2,113,113,113,113,113,113,113,113,113,113,
+-  113,113,113,  2,  2,113,113,113,113,113,113,113,113,  2,132,132,
+-  132,132,132,132,132,132,132,132,132,132,  2,  2,  2,  2,132,132,
+-    2,  2,  2,  2,132,132,  3,  3,  3,  3,  2,  3,  3,  3,  2,  3,
+-    3,  2,  3,  2,  2,  3,  2,  3,  3,  3,  3,  3,  3,  3,  3,  3,
+-    3,  2,  3,  3,  3,  3,  2,  3,  2,  3,  2,  2,  2,  2,  2,  2,
+-    3,  2,  2,  2,  2,  3,  2,  3,  2,  3,  2,  3,  3,  3,  2,  3,
+-    2,  3,  2,  3,  2,  3,  2,  3,  3,  3,  3,  2,  3,  2,  3,  3,
+-    2,  3,  3,  3,  3,  3,  3,  3,  3,  3,  2,  2,  2,  2,  2,  3,
+-    3,  3,  2,  3,  3,  3,  2,  2,  2,  2,  2,  2,  0,  0, 15,  0,
++  155,155,155,155,155,155,155,155,155,155,155,155,  2,  2,  2,  2,
++    2,  2,  2,  2,  2,155,136,  2,  2,  2,  2,  2,  2,  2, 17, 17,
++   17, 17,  2, 17, 17, 17, 17, 17, 17, 17,  2, 17, 17,  2, 17, 15,
++   15, 15, 15, 15, 15, 15, 17, 17, 17,  2,  2,  2,  2,  2,  2,  2,
++   15,  2,  2,  2,  2,  2, 15, 15, 15,  2,  2, 17,  2,  2,  2,  2,
++    2,  2, 17, 17, 17, 17,139,139,139,139,139,139,139,139,139,139,
++  139,139,  2,  2,  2,  2,105,105,105,105,105,105,105,105,105,105,
++  105,  2,  2,  2,  2,  2,105,105,105,105,105,  2,  2,  2,105,  2,
++    2,  2,  2,  2,  2,  2,105,105,  2,  2,105,105,105,105,  1,  1,
++    1,  1,  1,  1,  2,  2,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,
++    0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1,  1,  1,
++    1,  0,  0,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,
++    1,  1,  1,  1,  0,  0,  2,  2,  0,  2,  2,  0,  0,  2,  2,  0,
++    0,  0,  0,  2,  0,  0,  0,  0,  2,  0,  2,  0,  0,  0,  0,  0,
++    0,  0,  2,  0,  0,  0,  0,  0,  0,  2,  2,  0,  0,  0,  0,  0,
++    2,  0,  0,  0,  0,  2,  0,  0,  0,  0,  0,  2,  0,  2,  2,  2,
++    0,  0,  0,  0,  0,  0,  0,  2,  0,  0,  0,  0,  0,  0,131,131,
++  131,131,131,131,131,131,131,131,131,131,  2,  2,  2,  2,  2,  2,
++    2,131,131,131,131,131,  2,131,131,131,131,131,131,131,  2,  2,
++    2,  2,  2, 19, 19, 19, 56, 56, 56, 56, 56, 56, 56,  2, 56,  2,
++    2, 56, 56, 56, 56, 56, 56, 56,  2, 56, 56,  2, 56, 56, 56, 56,
++   56,  2,  2,  2,  2,  2,  6,  6,  6,  6,  6,  6,  2,  2,  2,  2,
++    2,  2,  2,  2,  2,  6,151,151,151,151,151,151,151,151,151,151,
++  151,151,151,  2,  2,  2,151,151,151,151,151,151,  2,  2,151,151,
++    2,  2,  2,  2,151,151,160,160,160,160,160,160,160,160,160,160,
++  160,160,160,160,160,  2,152,152,152,152,152,152,152,152,152,152,
++    2,  2,  2,  2,  2,152,164,164,164,164,164,164,164,164,164,164,
++    2,  2,  2,  2,  2,  2,168,168,168,168,168,168,168,168,168,168,
++  168,  2,  2,  2,  2,168, 30, 30, 30, 30,  2, 30, 30,  2,113,113,
++  113,113,113,113,113,113,113,113,113,113,113,  2,  2,113,113,113,
++  113,113,113,113,113,  2,132,132,132,132,132,132,132,132,132,132,
++  132,132,  2,  2,  2,  2,132,132,  2,  2,  2,  2,132,132,  3,  3,
++    3,  3,  2,  3,  3,  3,  2,  3,  3,  2,  3,  2,  2,  3,  2,  3,
++    3,  3,  3,  3,  3,  3,  3,  3,  3,  2,  3,  3,  3,  3,  2,  3,
++    2,  3,  2,  2,  2,  2,  2,  2,  3,  2,  2,  2,  2,  3,  2,  3,
++    2,  3,  2,  3,  3,  3,  2,  3,  2,  3,  2,  3,  2,  3,  2,  3,
++    3,  3,  3,  2,  3,  2,  3,  3,  2,  3,  3,  3,  3,  3,  3,  3,
++    3,  3,  2,  2,  2,  2,  2,  3,  3,  3,  2,  3,  3,  3,  3,  3,
++    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  0,  0, 15,  0,
+     0,  2,  2,  2,  2,  2,  2,  2,  2,  2,  0,  0,  0,  0,  2,  2,
+-    2,  0,  0,  0,  0,  0, 13,  2,  2,  2,  2,  2,  2,  2, 13, 13,
++    2,  0,  0,  0,  0,  0,  0,  0,  2,  2,  2,  2,  2,  0,  0,  0,
++    0,  0,  0,  2,  2,  0, 13,  2,  2,  2,  2,  2,  2,  2, 13, 13,
+    13,  2,  2,  2,  2,  2,  2,  0,  2,  2,  2,  2,  2,  2,  0,  1,
+     2,  3,  4,  5,  6,  7,  8,  9,  9,  9,  9, 10,  9, 11, 12, 13,
+     9,  9,  9, 14,  9,  9, 15,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+@@ -2123,13 +2113,14 @@ _hb_ucd_u8[17884] =
+     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+     9,  9,  9,  9,  9,  9,  9,  9,  9,  9, 16, 17,  9,  9,  9,  9,
+-    9,  9,  9,  9,  9,  9, 18, 19, 20,  9, 21,  9,  9,  9,  9,  9,
+-    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
++   18,  9,  9,  9,  9,  9, 19, 20, 21,  9, 22,  9,  9,  9,  9,  9,
+     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
++    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9, 23,  9,
++    9,  9,  9,  9, 24,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
++    9,  9,  9,  9,  9,  9, 25,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+-    9,  9,  9,  9,  9,  9, 22,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+@@ -2137,8 +2128,7 @@ _hb_ucd_u8[17884] =
+     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+-    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+-    9,  9,  9,  9,  9,  9,  9,  9,  9,  9, 23, 24,  0,  0,  0,  0,
++    9,  9,  9,  9,  9,  9,  9,  9,  9,  9, 26, 27,  0,  0,  0,  0,
+     0,  0,  0,  0,  0,  0,  0,  0,  1,  2,  3,  4,  5,  6,  7,  8,
+     9, 10, 11, 12,  0,  0, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
+     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+@@ -2175,23 +2165,29 @@ _hb_ucd_u8[17884] =
+   132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,
+   148,149,150,151,152,153,154,155,156,157,  0,  0,  0,158,159,160,
+   161,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+-    0,  0,  0,  0,  0,162,163,  0,  0,  0,  0,  0,  0,  0,164,  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,162,  0,163,  0,  0,  0,  0,  0,
++    0,  0,  0,  0,  0,164,165,  0,  0,  0,  0,  0,  0,  0,166,  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,
++  167,  0,  0,  0,168,169,  0,  0,170,  0,  0,  0,  0,  0,  0,  0,
++    0,  0,  0,  0,  0,  0,  0,171,  0,  0,  0,  0,  0,  0,  0,  0,
++    0,  0,  0,  0,  0,  0,  0,172,  0,  0,  0,  0,  0,  0,  0,  0,
++    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,173,
++    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,174,  0,
+     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+-  165,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+-    0,  0,  0,  0,  0,  0,  0,166,  0,  0,  0,  0,  0,  0,  0,  0,
+-    0,  0,  0,  0,  0,  0,  0,167,  0,  0,  0,  0,  0,  0,  0,  0,
+-    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,168,
+     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
++    0,  0,175,  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,169,170,  0,  0,  0,  0,171,172,  0,  0,  0,173,174,175,176,
+-  177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,
+-  193,194,195,196,197,198,199,200,201,202,203,204,205,206,  0,  0,
++    0,176,177,  0,  0,  0,  0,178,179,  0,  0,  0,180,181,182,183,
++  184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,
++  200,201,202,203,204,205,206,207,208,209,210,211,212,213,  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,  1,  2,  3,  4,
+ };
+ static const uint16_t
+-_hb_ucd_u16[9344] =
++_hb_ucd_u16[10400] =
+ {
+      0,   0,   1,   2,   3,   4,   5,   6,   0,   0,   7,   8,   9,  10,  11,  12,
+     13,  13,  13,  14,  15,  13,  13,  16,  17,  18,  19,  20,  21,  22,  13,  23,
+@@ -2210,9 +2206,10 @@ _hb_ucd_u16[9344] =
+    136,  48,  48, 137, 138, 139, 140, 140, 141,  48, 142, 143, 144, 145, 140, 140,
+    146, 147, 148, 149, 150,  48, 151, 152, 153, 154,  32, 155, 156, 157, 140, 140,
+     48,  48, 158, 159, 160, 161, 162, 163, 164, 165,   9,   9, 166,  11,  11, 167,
+-    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 168, 169,  48,  48,
+-   168,  48,  48, 170, 171, 172,  48,  48,  48, 171,  48,  48,  48, 173, 174, 175,
+-    48, 176,   9,   9,   9,   9,   9, 177, 178,  48,  48,  48,  48,  48,  48,  48,
++    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
++    48,  48,  48,  48, 168, 169,  48,  48, 168,  48,  48, 170, 171, 172,  48,  48,
++    48, 171,  48,  48,  48, 173, 174, 175,  48, 176,   9,   9,   9,   9,   9, 177,
++   178,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
+     48,  48,  48,  48,  48,  48, 179,  48, 180, 181,  48,  48,  48,  48, 182, 183,
+     48, 184,  48, 185,  48, 186, 187, 188,  48,  48,  48, 189, 190, 191, 192, 193,
+    194, 192,  48,  48, 195,  48,  48, 196, 197,  48, 198,  48,  48,  48,  48, 199,
+@@ -2225,28 +2222,34 @@ _hb_ucd_u16[9344] =
+    241, 242, 241, 241, 242, 243, 241, 244, 245, 245, 245, 246, 247, 248, 249, 250,
+    251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 261, 262, 263, 264, 265,
+    266, 267, 268, 269, 270, 271, 272, 272, 273, 274, 275, 209, 276, 277, 209, 278,
+-   279, 279, 279, 279, 279, 279, 279, 279, 280, 209, 281, 209, 209, 209, 209, 282,
+-   209, 283, 279, 284, 209, 285, 286, 209, 209, 209, 287, 140, 288, 140, 271, 271,
+-   271, 289, 209, 209, 209, 209, 290, 271, 209, 209, 209, 209, 209, 209, 209, 209,
+-   209, 209, 209, 291, 292, 209, 209, 293, 209, 209, 209, 209, 209, 209, 294, 209,
+-   209, 209, 209, 209, 209, 209, 295, 296, 271, 297, 209, 209, 298, 279, 299, 279,
+-   300, 301, 279, 279, 279, 302, 279, 303, 209, 209, 209, 279, 304, 209, 209, 305,
+-   209, 306, 209, 209, 209, 209, 209, 209,   9,   9,   9,  11,  11,  11, 307, 308,
+-    13,  13,  13,  13,  13,  13, 309, 310,  11,  11, 311,  48,  48,  48, 312, 313,
+-    48, 314, 315, 315, 315, 315,  32,  32, 316, 317, 318, 319, 320, 321, 140, 140,
+-   209, 322, 209, 209, 209, 209, 209, 323, 209, 209, 209, 209, 209, 324, 140, 209,
+-   325, 326, 327, 328, 136,  48,  48,  48,  48, 329, 178,  48,  48,  48,  48, 330,
+-   331,  48,  48, 136,  48,  48,  48,  48, 200, 332,  48,  48, 209, 209, 333,  48,
+-   209, 334, 335, 209, 336, 337, 209, 209, 335, 209, 209, 337, 209, 209, 209, 209,
+-    48,  48,  48,  48, 209, 209, 209, 209,  48, 338,  48,  48,  48,  48,  48,  48,
+-   151, 209, 209, 209, 287,  48,  48, 229, 339,  48, 340, 140,  13,  13, 341, 342,
+-    13, 343,  48,  48,  48,  48, 344, 345,  31, 346, 347, 348,  13,  13,  13, 349,
+-   350, 351, 352, 353, 354, 355, 140, 356, 357,  48, 358, 359,  48,  48,  48, 360,
+-   361,  48,  48, 362, 363, 192,  32, 364,  64,  48, 365,  48, 366, 367,  48, 151,
+-    76,  48,  48, 368, 369, 370, 371, 372,  48,  48, 373, 374, 375, 376,  48, 377,
+-    48,  48,  48, 378, 379, 380, 381, 382, 383, 384, 315,  11,  11, 385, 386,  11,
+-    11,  11,  11,  11,  48,  48, 387, 192,  48,  48, 388,  48, 389,  48,  48, 206,
+-   390, 390, 390, 390, 390, 390, 390, 390, 391, 391, 391, 391, 391, 391, 391, 391,
++   279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279,
++   280, 209, 281, 209, 209, 209, 209, 282, 209, 283, 279, 284, 209, 285, 286, 209,
++   209, 209, 176, 140, 287, 140, 271, 271, 271, 288, 209, 209, 209, 209, 289, 271,
++   209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 290, 291, 209, 209, 292,
++   209, 209, 209, 209, 209, 209, 293, 209, 209, 209, 209, 209, 209, 209, 209, 209,
++   209, 209, 209, 209, 209, 209, 294, 295, 271, 296, 209, 209, 297, 279, 298, 279,
++   209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209,
++   279, 279, 279, 279, 279, 279, 279, 279, 299, 300, 279, 279, 279, 301, 279, 302,
++   209, 209, 209, 279, 303, 209, 209, 304, 209, 305, 209, 209, 209, 209, 209, 209,
++     9,   9,   9,  11,  11,  11, 306, 307,  13,  13,  13,  13,  13,  13, 308, 309,
++    11,  11, 310,  48,  48,  48, 311, 312,  48, 313, 314, 314, 314, 314,  32,  32,
++   315, 316, 317, 318, 319, 320, 140, 140, 209, 321, 209, 209, 209, 209, 209, 322,
++   209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 323, 140, 209,
++   324, 325, 326, 327, 136,  48,  48,  48,  48, 328, 178,  48,  48,  48,  48, 329,
++   330,  48,  48, 136,  48,  48,  48,  48, 200, 331,  48,  48, 209, 209, 332,  48,
++   209, 333, 334, 209, 335, 336, 209, 209, 334, 209, 209, 336, 209, 209, 209, 209,
++    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 209, 209, 209, 209,
++    48, 337,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
++    48,  48,  48,  48,  48,  48,  48,  48, 151, 209, 209, 209, 338,  48,  48, 229,
++   339,  48, 340, 140,  13,  13, 341, 342,  13, 343,  48,  48,  48,  48, 344, 345,
++    31, 346, 347, 348,  13,  13,  13, 349, 350, 351, 352, 353, 354, 355, 140, 356,
++   357,  48, 358, 359,  48,  48,  48, 360, 361,  48,  48, 362, 363, 192,  32, 364,
++    64,  48, 365,  48, 366, 367,  48, 151,  76,  48,  48, 368, 369, 370, 371, 372,
++    48,  48, 373, 374, 375, 376,  48, 377,  48,  48,  48, 378, 379, 380, 381, 382,
++   383, 384, 314,  11,  11, 385, 386,  11,  11,  11,  11,  11,  48,  48, 387, 192,
++    48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 388,  48, 389,  48,  48, 206,
++   390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390,
++   391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391,
+     48,  48,  48,  48,  48,  48, 204,  48,  48,  48,  48,  48,  48, 207, 140, 140,
+    392, 393, 394, 395, 396,  48,  48,  48,  48,  48,  48, 397, 398, 399,  48,  48,
+     48,  48,  48, 400, 209,  48,  48,  48,  48, 401,  48,  48, 402, 140, 140, 403,
+@@ -2257,108 +2260,204 @@ _hb_ucd_u16[9344] =
+    140, 140, 140, 140, 140, 140, 140, 140,  48, 151,  48,  48,  48, 100, 429, 430,
+     48,  48, 431,  48, 432,  48,  48, 433,  48, 434,  48,  48, 435, 436, 140, 140,
+      9,   9, 437,  11,  11,  48,  48,  48,  48, 204, 192,   9,   9, 438,  11, 439,
+-    48,  48, 440,  48,  48,  48, 441, 442, 442, 443, 444, 445, 140, 140, 140, 140,
+-    48,  48,  48, 314,  48, 199, 440, 140, 446,  27,  27, 447, 140, 140, 140, 140,
++    48,  48, 440,  48,  48,  48, 441, 442, 442, 443, 444, 445,  48,  48,  48, 388,
++    48,  48,  48, 313,  48, 199, 440, 140, 446,  27,  27, 447, 140, 140, 140, 140,
+    448,  48,  48, 449,  48, 450,  48, 451,  48, 200, 452, 140, 140, 140,  48, 453,
+     48, 454,  48, 455, 140, 140, 140, 140,  48,  48,  48, 456, 271, 457, 271, 271,
+    458, 459,  48, 460, 461, 462,  48, 463,  48, 464, 140, 140, 465,  48, 466, 467,
+     48,  48,  48, 468,  48, 469,  48, 470,  48, 471, 472, 140, 140, 140, 140, 140,
+     48,  48,  48,  48, 196, 140, 140, 140,   9,   9,   9, 473,  11,  11,  11, 474,
+-    48,  48, 475, 192, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 271, 476,
+-    48,  48, 477, 478, 140, 140, 140, 479,  48, 464, 480,  48,  62, 481, 140,  48,
+-   482, 140, 140,  48, 483, 140,  48, 314, 484,  48,  48, 485, 486, 457, 487, 488,
+-   222,  48,  48, 489, 490,  48, 196, 192, 491,  48, 492, 493, 494,  48,  48, 495,
+-   222,  48,  48, 496, 497, 498, 499, 500,  48,  97, 501, 502, 503, 140, 140, 140,
+-   504, 505, 506,  48,  48, 507, 508, 192, 509,  83,  84, 510, 511, 512, 513, 514,
+-    48,  48,  48, 515, 516, 517, 478, 140,  48,  48,  48, 518, 519, 192, 140, 140,
+-    48,  48, 520, 521, 522, 523, 140, 140,  48,  48,  48, 524, 525, 192, 526, 140,
+-    48,  48, 527, 528, 192, 140, 140, 140,  48, 173, 529, 530, 314, 140, 140, 140,
+-    48,  48, 501, 531, 140, 140, 140, 140, 140, 140,   9,   9,  11,  11, 148, 532,
+-   533, 534,  48, 535, 536, 192, 140, 140, 140, 140, 537,  48,  48, 538, 539, 140,
+-   540,  48,  48, 541, 542, 543,  48,  48, 544, 545, 546,  48,  48,  48,  48, 196,
+-   547, 140, 140, 140, 140, 140, 140, 140,  84,  48, 520, 548, 549, 148, 175, 550,
+-    48, 551, 552, 553, 140, 140, 140, 140, 554,  48,  48, 555, 556, 192, 557,  48,
+-   558, 559, 192, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,  48, 560,
+-   561, 115,  48, 562, 563, 192, 140, 140, 140, 140, 140, 100, 271, 564, 565, 566,
+-    48, 207, 140, 140, 140, 140, 140, 140, 272, 272, 272, 272, 272, 272, 567, 568,
+-    48,  48,  48,  48, 388, 140, 140, 140, 140,  48,  48,  48,  48,  48,  48, 569,
+-    48,  48,  48, 570, 571, 572, 140, 140,  48,  48,  48,  48, 314, 140, 140, 140,
+-    48,  48,  48, 196,  48, 200, 370,  48,  48,  48,  48, 200, 192,  48, 204, 573,
+-    48,  48,  48, 574, 575, 576, 577, 578,  48, 140, 140, 140, 140, 140, 140, 140,
+-   140, 140, 140, 140,   9,   9,  11,  11, 271, 579, 140, 140, 140, 140, 140, 140,
+-    48,  48,  48,  48, 580, 581, 582, 582, 583, 584, 140, 140, 140, 140, 585, 586,
+-    48,  48,  48,  48,  48,  48,  48, 440,  48,  48,  48,  48,  48, 199, 140, 140,
+-   196, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 587,
+-    48,  48, 588, 589, 140, 590, 591,  48,  48,  48,  48,  48,  48,  48,  48, 206,
+-    48,  48,  48,  48,  48,  48,  71, 151, 196, 592, 593, 140, 140, 140, 140, 140,
+-    32,  32, 594,  32, 595, 209, 209, 209, 209, 209, 209, 209, 323, 140, 140, 140,
+-   209, 209, 209, 209, 209, 209, 209, 324, 209, 209, 596, 209, 209, 209, 597, 598,
+-   599, 209, 600, 209, 209, 209, 288, 140, 209, 209, 209, 209, 601, 140, 140, 140,
+-   140, 140, 140, 140, 271, 602, 271, 602, 209, 209, 209, 209, 209, 287, 271, 461,
+-     9, 603,  11, 604, 605, 606, 241,   9, 607, 608, 609, 610, 611,   9, 603,  11,
+-   612, 613,  11, 614, 615, 616, 617,   9, 618,  11,   9, 603,  11, 604, 605,  11,
+-   241,   9, 607, 617,   9, 618,  11,   9, 603,  11, 619,   9, 620, 621, 622, 623,
+-    11, 624,   9, 625, 626, 627, 628,  11, 629,   9, 630,  11, 631, 632, 632, 632,
+-    32,  32,  32, 633,  32,  32, 634, 635, 636, 637,  45, 140, 140, 140, 140, 140,
+-   638, 639, 640, 140, 140, 140, 140, 140, 641, 642, 643,  27,  27,  27, 644, 140,
+-   645, 140, 140, 140, 140, 140, 140, 140,  48,  48, 151, 646, 647, 140, 140, 140,
+-   140,  48, 648, 140,  48,  48, 649, 650, 140, 140, 140, 140, 140,  48, 651, 192,
+-   140, 140, 140, 140, 140, 140, 652, 200,  48,  48,  48,  48, 653, 595, 140, 140,
+-     9,   9, 607,  11, 654, 370, 140, 140, 140, 140, 140, 140, 140, 140, 140, 499,
+-   271, 271, 655, 656, 140, 140, 140, 140, 499, 271, 657, 658, 140, 140, 140, 140,
+-   659,  48, 660, 661, 662, 663, 664, 665, 666, 206, 667, 206, 140, 140, 140, 668,
+-   209, 209, 669, 209, 209, 209, 209, 209, 209, 323, 334, 670, 670, 670, 209, 324,
+-   671, 209, 209, 209, 209, 209, 209, 209, 209, 209, 672, 140, 140, 140, 673, 209,
+-   674, 209, 209, 669, 675, 676, 324, 140, 209, 209, 209, 209, 209, 209, 209, 677,
+-   209, 209, 209, 209, 209, 678, 426, 426, 209, 209, 209, 209, 209, 209, 209, 679,
+-   209, 209, 209, 209, 209, 176, 669, 427, 669, 209, 209, 209, 680, 176, 209, 209,
+-   680, 209, 672, 676, 140, 140, 140, 140, 209, 209, 209, 209, 209, 323, 672, 426,
+-   675, 209, 209, 681, 682, 669, 675, 675, 209, 683, 209, 209, 288, 140, 140, 192,
+-    48,  48,  48,  48,  48,  48, 140, 140,  48,  48,  48, 207,  48,  48,  48,  48,
+-    48, 204,  48,  48,  48,  48,  48,  48,  48,  48, 478,  48,  48,  48,  48,  48,
+-    48,  48,  48,  48,  48,  48, 100,  48,  48,  48,  48,  48,  48, 204, 140, 140,
+-    48, 204, 140, 140, 140, 140, 140, 140,  48,  48,  48,  48,  71,  48,  48,  48,
+-    48,  48,  48, 140, 140, 140, 140, 140, 684, 140, 570, 570, 570, 570, 570, 570,
++    48,  48, 475, 192, 476,   9, 477,  11, 478, 140, 140, 140, 140, 140, 140, 140,
++   140, 140, 140, 140, 140, 140, 271, 479,  48,  48, 480, 481, 482, 140, 140, 483,
++    48, 464, 484,  48,  62, 485, 140,  48, 486, 140, 140,  48, 487, 140,  48, 313,
++   488,  48,  48, 489, 490, 457, 491, 492, 222,  48,  48, 493, 494,  48, 196, 192,
++   495,  48, 496, 497, 498,  48,  48, 499, 222,  48,  48, 500, 501, 502, 503, 504,
++    48,  97, 505, 506, 507, 140, 140, 140, 508, 509, 510,  48,  48, 511, 512, 192,
++   513,  83,  84, 514, 515, 516, 517, 518, 519,  48,  48, 520, 521, 522, 523, 140,
++    48,  48,  48, 524, 525, 526, 481, 140,  48,  48,  48, 527, 528, 192, 140, 140,
++   140, 140, 140, 140, 140, 140, 140, 140,  48,  48, 529, 530, 531, 532, 140, 140,
++    48,  48,  48, 533, 534, 192, 535, 140,  48,  48, 536, 537, 192, 538, 539, 140,
++    48, 540, 541, 542, 313, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
++    48,  48, 505, 543, 140, 140, 140, 140, 140, 140,   9,   9,  11,  11, 148, 544,
++   545, 546,  48, 547, 548, 192, 140, 140, 140, 140, 549,  48,  48, 550, 551, 140,
++   552,  48,  48, 553, 554, 555,  48,  48, 556, 557, 558,  48,  48,  48,  48, 196,
++   559, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,  48,  48, 560, 192,
++    84,  48, 529, 561, 562, 148, 175, 563,  48, 564, 565, 566, 140, 140, 140, 140,
++   567,  48,  48, 568, 569, 192, 570,  48, 571, 572, 192, 140, 140, 140, 140, 140,
++   140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,  48, 573,
++   574, 115,  48, 575, 576, 577, 140, 140, 140, 140, 140, 100, 271, 578, 579, 580,
++    48,  48,  48,  48,  48,  48,  48,  48,  48, 207, 140, 140, 140, 140, 140, 140,
++   272, 272, 272, 272, 272, 272, 581, 582,  48,  48,  48,  48,  48,  48,  48,  48,
++    48,  48,  48,  48, 388, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
++   140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
++   140, 140, 140, 140, 140, 140, 140, 140, 140,  48,  48,  48,  48,  48,  48, 583,
++    48,  48,  48, 584, 585, 586,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
++    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  71,
++    48,  48,  48,  48, 313, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
++    48, 587, 588, 192, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
++    48,  48,  48, 196,  48, 200, 370,  48,  48,  48,  48, 200, 192,  48, 204, 589,
++    48,  48,  48, 590, 591, 592, 593, 594,  48, 140, 140, 140, 140, 140, 140, 140,
++   140, 140, 140, 140, 595,  48, 596, 192, 140, 140, 140, 140, 140, 140, 140, 140,
++   140, 140, 140, 140,   9,   9,  11,  11, 271, 597, 140, 140, 140, 140, 140, 140,
++    48,  48,  48,  48, 598, 599, 600, 600, 601, 602, 140, 140, 140, 140, 603, 604,
++    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 440,
++    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 199, 140, 605,
++   196, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
++   140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 606,
++    48,  48, 607, 608, 140, 609, 610,  48,  48,  48,  48,  48,  48,  48,  48,  48,
++    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 206,
++    48,  48,  48,  48,  48,  48,  71, 151, 196, 611, 612, 140, 140, 140, 140, 140,
++   209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 192,
++   209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 322, 140, 140, 140, 140,
++    32,  32, 613,  32, 614, 209, 209, 209, 209, 209, 209, 209, 322, 140, 140, 140,
++   209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 323,
++   209, 209, 615, 209, 209, 209, 616, 617, 618, 209, 619, 209, 209, 209, 287, 140,
++   209, 209, 209, 209, 620, 140, 140, 140, 140, 140, 140, 140, 271, 621, 271, 621,
++   209, 209, 209, 209, 209, 338, 271, 461, 140, 140, 140, 140, 140, 140, 140, 140,
++     9, 622,  11, 623, 624, 625, 241,   9, 626, 627, 628, 629, 630,   9, 622,  11,
++   631, 632,  11, 633, 634, 635, 636,   9, 637,  11,   9, 622,  11, 623, 624,  11,
++   241,   9, 626, 636,   9, 637,  11,   9, 622,  11, 638,   9, 639, 640, 641, 642,
++    11, 643,   9, 644, 645, 646, 647,  11, 648,   9, 649,  11, 650, 538, 538, 538,
++    32,  32,  32, 651,  32,  32, 652, 653, 654, 655,  45, 140, 140, 140, 140, 140,
++   656, 657, 658, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
++   659, 660, 661,  27,  27,  27, 662, 140, 663, 140, 140, 140, 140, 140, 140, 140,
++    48,  48, 151, 664, 665, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
++   140, 140, 140, 140, 140, 140, 140, 140, 140,  48, 666, 140,  48,  48, 667, 668,
++   140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,  48, 669, 192,
++   140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,  48, 587, 670,
++   140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 671, 200,
++    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 672, 614, 140, 140,
++     9,   9, 626,  11, 673, 370, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
++   140, 140, 140, 140, 140, 140, 140, 503, 271, 271, 674, 675, 140, 140, 140, 140,
++   503, 271, 676, 677, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
++   678,  48, 679, 680, 681, 682, 683, 684, 685, 206, 686, 206, 140, 140, 140, 687,
++   209, 209, 688, 209, 209, 209, 209, 209, 209, 322, 333, 689, 689, 689, 209, 323,
++   690, 209, 209, 209, 209, 209, 209, 209, 209, 209, 691, 140, 140, 140, 692, 209,
++   693, 209, 209, 688, 694, 695, 323, 140, 140, 140, 140, 140, 140, 140, 140, 140,
++   209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 696,
++   209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 697, 426, 426,
++   209, 209, 209, 209, 209, 209, 209, 698, 209, 209, 209, 209, 209, 176, 688, 427,
++   688, 209, 209, 209, 699, 176, 209, 209, 699, 209, 691, 688, 695, 140, 140, 140,
++   209, 209, 209, 209, 209, 322, 691, 426, 700, 209, 209, 209, 701, 702, 176, 694,
++   209, 209, 209, 209, 209, 209, 209, 209, 209, 703, 209, 209, 209, 209, 209, 192,
++    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 140, 140,
++    48,  48,  48, 207,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
++    48, 204,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
++    48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 481,  48,  48,  48,  48,  48,
++    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 100,  48,
++    48,  48,  48,  48,  48, 204, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
++    48, 204, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
++    48,  48,  48,  48,  71,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
++    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 140, 140, 140, 140, 140,
++   704, 140, 584, 584, 584, 584, 584, 584, 140, 140, 140, 140, 140, 140, 140, 140,
+     32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32, 140,
+-   391, 391, 391, 391, 391, 391, 391, 685, 391, 391, 391, 391, 391, 391, 391, 686,
++   391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 705,
++   391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 706,
++     0,   1,   2,   3,   4,   4,   4,   4,   4,   4,   5,   6,   7,   8,   9,  10,
++    11,  11,  12,  11,  13,  14,  15,  16,  17,  18,  19,  20,  21,  22,  23,  24,
++    25,  26,  27,  28,  29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,
++    41,  42,  43,  44,  45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,  56,
++    57,  57,  58,  59,  60,  60,  60,  60,  61,  62,  63,  64,  65,  66,  67,  68,
++    69,  69,  69,  69,  69,  69,  69,  69,  69,  69,  70,  71,  72,  73,  74,  75,
++    76,  77,  78,  79,  80,  81,  82,  83,  84,  85,  86,  87,  88,  89,  90,  91,
++    92,  93,  94,  95,  96,  97,  98,   7,   4,   4,   4,   4,  99, 100, 101, 102,
++   103, 104, 105, 106, 107, 108, 109,   0,   0,   0,   0,   0,   0,   0,   0,   0,
++   110, 111,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
++   112, 112, 112, 112,   0,   0,   0,   0,   0,   0,   0,   0,   0, 113, 114,   0,
++   115, 116, 117, 118, 119, 120, 121, 122,   0, 123, 124, 125, 126, 126, 126, 127,
++   128, 129, 130, 131, 132,  60, 133, 134, 135, 136,   0, 137, 138, 139,   0,   0,
++   126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126,
++   126, 126, 126, 126, 126, 126, 126,   0, 126, 126, 126, 126, 126, 126, 126, 126,
++   140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
++   140, 140, 141, 142, 143, 143, 143, 143, 144,  11, 145, 146, 147,   4, 148, 149,
++   150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165,
++    60,  60,  60,  60,  60,  60,  60,  60,  60,  60,  60,  60,  60,  60,  60,  60,
++    60,  60,  60,  60,  60,  60,  60,  60,  60,  60,  60,  60,  60,  60, 166, 167,
++   168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168,
++   168, 168, 168, 168, 126, 126, 126, 126, 126, 169, 126, 170, 171, 172,  19, 173,
++    19,  19,  19,  19, 174,  19, 175, 176, 177, 178,  19, 179, 180, 181, 182, 183,
++   184, 185, 186, 187, 188, 189, 190, 191, 168, 168, 192, 193, 194, 195, 196, 197,
++   198, 199, 200, 201, 202, 203, 204, 205, 206, 206, 206, 206, 207, 208, 209, 168,
++   210, 211, 212, 213, 214, 168, 215, 216, 217, 218, 219, 220, 221, 222, 223, 168,
++   224, 225, 226, 227, 228, 229, 230, 168, 168, 231, 232, 233, 234, 235, 236, 237,
++   238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253,
++   254, 255, 256, 257, 168, 168, 258, 259, 260, 261, 262, 263, 264, 265, 168, 168,
++   266, 168, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 168, 168, 278,
++   279, 280, 281, 168, 282, 283, 284, 168, 168, 168, 168, 285, 286, 287, 288, 289,
++   290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 291, 168,
++   290, 292, 290, 290, 290, 293, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168,
++   168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 294, 295,
++   296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296,
++   296, 297, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296,
++   296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, 298,
++   299, 299, 299, 299, 299, 299, 299, 299, 299, 300, 168, 168, 168, 168, 168, 168,
++   168, 168, 168, 168, 301, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168,
++   302, 302, 302, 302, 302, 302, 302, 302, 303, 304, 305, 306, 307, 308, 309, 168,
++   168, 168, 168, 168, 168, 310, 168, 168, 168, 311, 312, 168, 313, 314, 315, 316,
++   317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317,
++   317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 318,
++   317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 317, 319, 319, 319, 319,
++   319, 319, 319, 320, 321, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168,
++   168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 322,
++   323, 324, 324, 324, 325, 326, 327, 327, 327, 327, 327, 328, 168, 168, 168, 168,
++   329, 330, 331, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168,
++     0,   0,   0, 332,   0,   0,   0,   0,   0,   0, 333, 168, 334, 335,   0, 336,
++     0,   0,   0, 337, 338, 339, 340, 341, 189, 342, 168, 343,   0, 344, 168, 168,
++     0, 345, 346, 347, 348, 349,   0,   0,   0,   0, 350,   0,   0,   0,   0, 351,
++   352, 352, 352, 352, 352, 352, 352, 352, 352, 352, 353, 168, 168, 168, 168, 168,
++   168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 354, 168, 168, 168,
++   355, 356, 357, 168, 358, 359, 168, 168, 168, 168, 360, 361, 168, 168, 168, 168,
++   168, 168, 168, 362, 168, 168, 168, 363, 168, 168, 168, 168, 168, 168, 168, 364,
++   365, 365, 365, 366, 367, 368, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168,
++   168, 369, 370, 168, 371, 168, 168, 168, 372, 373, 374, 375, 168, 168, 168, 168,
++   376,   0, 377, 378,   0,   0, 379, 380, 381, 382, 168, 168,   0,   0,   0,   0,
++     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 383,   0, 384,   0, 385,
++   386, 387, 388, 389,   0,   0,   0,   0,   0, 390, 391, 392,   0,   0, 393, 332,
++   126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 394, 126, 126, 126, 126,
++   126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 395, 126, 126, 126,
++   396, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126,
++   126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 397, 126, 126, 126, 126, 126,
++   126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 398,
++   126, 126, 126, 126, 126, 126, 126, 126, 126, 399, 168, 168, 168, 168, 168, 168,
++   126, 126, 126, 126, 126, 126, 126, 126, 399, 168, 168, 168, 168, 168, 168, 168,
++   126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 400, 126, 126,
++   126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 401, 168,
++   402,   0, 168, 168,   7,   7,   7, 403,   0,   1,   2,   3,   4,   4,   4,   4,
+      0,   0,   0,   0,   0,   0,   0,   0,   1,   2,   2,   3,   1,   2,   2,   3,
+      0,   0,   0,   0,   0,   4,   0,   4,   2,   2,   5,   2,   2,   2,   5,   2,
+-     2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,
+-     2,   2,   2,   2,   2,   2,   2,   6,   0,   0,   0,   0,   7,   8,   0,   0,
+-     9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,  10,  11,
+-    12,  13,  14,  14,  15,  14,  14,  14,  14,  14,  14,  14,  16,  17,  14,  14,
+-    18,  18,  18,  18,  18,  18,  18,  18,  18,  18,  18,  18,  18,  18,  18,  18,
+-    19,  18,  18,  18,  18,  18,  18,  18,  18,  18,  18,  18,  18,  18,  18,  18,
+-    18,  18,  18,  18,  18,  18,  20,  21,  21,  21,  22,  20,  21,  21,  21,  21,
+-    21,  23,  24,  25,  25,  25,  25,  25,  25,  26,  25,  25,  25,  27,  28,  26,
+-    29,  30,  31,  32,  31,  31,  31,  31,  33,  34,  35,  31,  31,  31,  36,  31,
+-    31,  31,  31,  31,  31,  31,  31,  31,  31,  31,  31,  29,  31,  31,  31,  31,
+-    37,  38,  37,  37,  37,  37,  37,  37,  37,  39,  31,  31,  31,  31,  31,  31,
+-    40,  40,  40,  40,  40,  40,  41,  26,  42,  42,  42,  42,  42,  42,  42,  43,
+-    44,  44,  44,  44,  44,  45,  44,  46,  47,  47,  47,  48,  37,  49,  31,  31,
+-    31,  50,  51,  31,  31,  31,  31,  31,  31,  31,  31,  31,  52,  31,  31,  31,
+-    53,  53,  53,  53,  53,  53,  53,  53,  53,  53,  54,  53,  55,  53,  53,  53,
+-    56,  57,  58,  59,  59,  60,  61,  62,  57,  63,  64,  65,  66,  59,  59,  67,
+-    68,  69,  70,  71,  71,  72,  73,  74,  69,  75,  76,  77,  78,  71,  79,  26,
+-    80,  81,  82,  83,  83,  84,  85,  86,  81,  87,  88,  26,  89,  83,  90,  91,
+-    92,  93,  94,  95,  95,  96,  97,  98,  93,  99, 100, 101, 102,  95,  95,  26,
+-   103, 104, 105, 106, 107, 104, 108, 109, 104, 105, 110,  26, 111, 108, 108, 112,
+-   113, 114, 115, 113, 113, 115, 113, 116, 114, 117, 118, 119, 120, 113, 121, 113,
+-   122, 123, 124, 122, 122, 124, 125, 126, 123, 127, 128, 128, 129, 122, 130,  26,
+-   131, 132, 133, 131, 131, 131, 131, 131, 132, 133, 134, 131, 135, 131, 131, 131,
+-   136, 137, 138, 139, 137, 137, 140, 141, 138, 142, 143, 137, 144, 137, 145,  26,
+-   146, 147, 147, 147, 147, 147, 147, 148, 147, 147, 147, 149,  26,  26,  26,  26,
+-   150, 151, 152, 152, 153, 152, 152, 154, 155, 156, 152, 157,  26,  26,  26,  26,
+-   158, 158, 158, 158, 158, 158, 158, 158, 158, 159, 158, 158, 158, 160, 159, 158,
+-   158, 158, 158, 159, 158, 158, 158, 161, 158, 161, 162, 163,  26,  26,  26,  26,
+-   164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164,
++     2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   6,
++     0,   0,   0,   0,   7,   8,   0,   0,   9,   9,   9,   9,   9,   9,   9,   9,
++     9,   9,   9,   9,   9,   9,  10,  11,  12,  13,  14,  14,  15,  14,  14,  14,
++    14,  14,  14,  14,  16,  17,  14,  14,  18,  18,  18,  18,  18,  18,  18,  18,
++    19,  18,  18,  18,  18,  18,  18,  18,  18,  18,  18,  18,  18,  18,  20,  21,
++    21,  21,  22,  20,  21,  21,  21,  21,  21,  23,  24,  25,  25,  25,  25,  25,
++    25,  26,  25,  25,  25,  27,  28,  26,  29,  30,  31,  32,  31,  31,  31,  31,
++    33,  34,  35,  31,  31,  31,  36,  31,  31,  31,  31,  31,  31,  31,  31,  31,
++    31,  31,  31,  29,  31,  31,  31,  31,  37,  38,  37,  37,  37,  37,  37,  37,
++    37,  39,  31,  31,  31,  31,  31,  31,  40,  40,  40,  40,  40,  40,  41,  26,
++    42,  42,  42,  42,  42,  42,  42,  43,  44,  44,  44,  44,  44,  45,  44,  46,
++    47,  47,  47,  48,  37,  49,  31,  31,  31,  50,  51,  31,  31,  31,  31,  31,
++    31,  31,  31,  31,  52,  31,  31,  31,  53,  53,  53,  53,  53,  53,  53,  53,
++    53,  53,  54,  53,  55,  53,  53,  53,  56,  57,  58,  59,  59,  60,  61,  62,
++    57,  63,  64,  65,  66,  59,  59,  67,  68,  69,  70,  71,  71,  72,  73,  74,
++    69,  75,  76,  77,  78,  71,  79,  26,  80,  81,  82,  83,  83,  84,  85,  86,
++    81,  87,  88,  26,  89,  83,  90,  91,  92,  93,  94,  95,  95,  96,  97,  98,
++    93,  99, 100, 101, 102,  95,  95,  26, 103, 104, 105, 106, 107, 104, 108, 109,
++   104, 105, 110,  26, 111, 108, 108, 112, 113, 114, 115, 113, 113, 115, 113, 116,
++   114, 117, 118, 119, 120, 113, 121, 113, 122, 123, 124, 122, 122, 124, 125, 126,
++   123, 127, 128, 128, 129, 122, 130,  26, 131, 132, 133, 131, 131, 131, 131, 131,
++   132, 133, 134, 131, 135, 131, 131, 131, 136, 137, 138, 139, 137, 137, 140, 141,
++   138, 142, 143, 137, 144, 137, 145,  26, 146, 147, 147, 147, 147, 147, 147, 148,
++   147, 147, 147, 149,  26,  26,  26,  26, 150, 151, 152, 152, 153, 152, 152, 154,
++   155, 156, 152, 157,  26,  26,  26,  26, 158, 158, 158, 158, 158, 158, 158, 158,
++   158, 159, 158, 158, 158, 160, 159, 158, 158, 158, 158, 159, 158, 158, 158, 161,
++   158, 161, 162, 163,  26,  26,  26,  26, 164, 164, 164, 164, 164, 164, 164, 164,
+    164, 164, 164, 164, 165, 165, 165, 165, 166, 167, 165, 165, 165, 165, 165, 168,
+-   169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169,
+-   170, 170, 170, 170, 170, 170, 170, 170, 170, 171, 172, 171, 170, 170, 170, 170,
+-   170, 171, 170, 170, 170, 170, 171, 172, 171, 170, 172, 170, 170, 170, 170, 170,
+-   170, 170, 171, 170, 170, 170, 170, 170, 170, 170, 170, 173, 170, 170, 170, 174,
+-   170, 170, 170, 175, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 177, 177,
+-   178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178,
++   169, 169, 169, 169, 169, 169, 169, 169, 170, 170, 170, 170, 170, 170, 170, 170,
++   170, 171, 172, 171, 170, 170, 170, 170, 170, 171, 170, 170, 170, 170, 171, 172,
++   171, 170, 172, 170, 170, 170, 170, 170, 170, 170, 171, 170, 170, 170, 170, 170,
++   170, 170, 170, 173, 170, 170, 170, 174, 170, 170, 170, 175, 176, 176, 176, 176,
++   176, 176, 176, 176, 176, 176, 177, 177, 178, 178, 178, 178, 178, 178, 178, 178,
+    179, 179, 179, 180, 181, 181, 181, 181, 181, 181, 181, 181, 181, 182, 181, 183,
+    184, 184, 185, 186, 187, 187, 188,  26, 189, 189, 190,  26, 191, 192, 193,  26,
+    194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 195, 194, 196, 194, 196,
+@@ -2368,208 +2467,164 @@ _hb_ucd_u16[9344] =
+    210, 210, 210, 210, 210, 211, 210, 210, 210, 212, 210, 213, 194, 194, 194, 194,
+    214, 214, 214, 215, 216, 216, 216, 216, 216, 216, 216, 217, 216, 216, 216, 218,
+    216, 219, 216, 219, 216, 220,   9,   9,   9, 221,  26,  26,  26,  26,  26,  26,
+-   222, 222, 222, 222, 222, 222, 222, 222, 222, 223, 222, 222, 222, 222, 222, 224,
+-   225, 225, 225, 225, 225, 225, 225, 225, 226, 226, 226, 226, 226, 226, 227, 228,
+-   229, 229, 229, 229, 229, 229, 229, 230, 229, 231, 232, 232, 232, 232, 232, 232,
+-    18, 233, 165, 165, 165, 165, 165, 234, 225,  26, 235,   9, 236, 237, 238, 239,
+-     2,   2,   2,   2, 240, 241,   2,   2,   2,   2,   2, 242, 243, 244,   2, 245,
+-     2,   2,   2,   2,   2,   2,   2, 246,   9,   9,   9,   9,   9,   9,   9,   9,
+-    14,  14, 247, 247,  14,  14,  14,  14, 247, 247,  14, 248,  14,  14,  14, 247,
+-    14,  14,  14,  14,  14,  14, 249,  14, 249,  14, 250, 251,  14,  14, 252, 253,
+-     0, 254,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 255,   0, 256, 257,
+-     0, 258,   2, 259,   0,   0,   0,   0, 260,  26,   9,   9,   9,   9, 261,  26,
+-     0,   0,   0,   0, 262, 263,   4,   0,   0, 264,   0,   0,   2,   2,   2,   2,
+-     2, 265,   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, 258,  26,  26,  26,   0, 266,  26,  26,   0,   0,   0,   0,
+-   267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267, 267,
+-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 268,   0,
+-     0,   0, 269,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+-   270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270,   2,   2,   2,   2,
+-    17,  17,  17,  17,  17,  17,  17,  17,  17,  17,  17,  17,  17,  17, 271, 272,
+-   165, 165, 165, 165, 166, 167, 273, 273, 273, 273, 273, 273, 273, 274, 275, 274,
+-   170, 170, 172,  26, 172, 172, 172, 172, 172, 172, 172, 172,  18,  18,  18,  18,
+-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 276,  26,  26,  26,  26,
++   222, 222, 222, 222, 222, 222, 222, 222, 222, 223, 222, 222, 222, 222, 222, 222,
++   224, 224, 224, 224, 224, 224, 224, 224, 225, 225, 225, 225, 225, 225, 226, 227,
++   228, 228, 228, 228, 228, 228, 228, 229, 228, 230, 231, 231, 231, 231, 231, 231,
++    18, 232, 165, 165, 165, 165, 165, 233, 224,  26, 234,   9, 235, 236, 237, 238,
++     2,   2,   2,   2, 239, 240,   2,   2,   2,   2,   2, 241, 242, 243,   2, 244,
++     2,   2,   2,   2,   2,   2,   2, 245,  14,  14, 246, 246,  14,  14,  14,  14,
++   246, 246,  14, 247,  14,  14,  14, 246,  14,  14,  14,  14,  14,  14, 248,  14,
++   248,  14, 249, 250,  14,  14, 251, 252,   0, 253,   0,   0,   0,   0,   0,   0,
++     0,   0,   0,   0, 254,   0, 255, 256,   0, 257,   2, 258,   0,   0,   0,   0,
++   259,  26,   9,   9,   9,   9, 260,  26,   0,   0,   0,   0, 261, 262,   4,   0,
++     0, 263,   0,   0,   2,   2,   2,   2,   2, 264,   0,   0,   0,   0,   0,   0,
++     0,   0,   0,   0,   0, 265,  26,  26,   0, 266,  26,  26,   0,   0,   0,   0,
++   267, 267, 267, 267, 267, 267, 267, 267,   0,   0,   0,   0,   0,   0, 268,   0,
++     0,   0, 269,   0,   0,   0,   0,   0, 270, 270, 270, 270, 270, 270, 270, 270,
++   270, 270, 270, 270,   2,   2,   2,   2,  17,  17,  17,  17,  17,  17,  17,  17,
++    17,  17,  17,  17,  17,  17, 271, 272, 165, 165, 165, 165, 166, 167, 273, 273,
++   273, 273, 273, 273, 273, 274, 275, 274, 170, 170, 172,  26, 172, 172, 172, 172,
++   172, 172, 172, 172,  18,  18,  18,  18,   0,   0,   0, 276,  26,  26,  26,  26,
+    277, 277, 277, 278, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 279,  26,
+-   277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
+    277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 280,  26,  26,  26,   0,   0,
+    281,   0,   0,   0, 282, 283,   0, 284, 285, 286, 286, 286, 286, 286, 286, 286,
+    286, 286, 287, 288, 289, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 291,
+-   292, 293, 293, 293, 293, 293, 294, 169, 169, 169, 169, 169, 169, 169, 169, 169,
+-   169, 295,   0,   0, 293, 293, 293, 293,   0,   0,   0,   0, 296, 297, 290, 290,
+-   169, 169, 169, 295,   0,   0,   0,   0,   0,   0,   0,   0, 169, 169, 169, 298,
+-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 290, 290, 290, 290, 290, 299,
++   292, 293, 293, 293, 293, 293, 294, 169, 169, 295,   0,   0, 293, 293, 293, 293,
++     0,   0,   0,   0, 276, 296, 290, 290, 169, 169, 169, 295,   0,   0,   0,   0,
++     0,   0,   0,   0, 169, 169, 169, 297,   0,   0, 290, 290, 290, 290, 290, 298,
+    290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290,   0,   0,   0,   0,   0,
+-   277, 277, 277, 277, 277, 277, 277, 277,   0,   0,   0,   0,   0,   0,   0,   0,
+-   300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300,
+-   300, 301, 300, 300, 300, 300, 300, 300, 302,  26, 303, 303, 303, 303, 303, 303,
+-   304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304,
+-   304, 304, 304, 304, 304, 305,  26,  26,  18,  18,  18,  18,  18,  18,  18,  18,
+-    18,  18,  18,  18, 306, 306, 306, 306, 306, 306, 306, 306, 306, 306, 306,  26,
+-     0,   0,   0,   0, 307,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,
+-     2, 308,   2,   2,   2,   2,   2,   2,   2, 309, 310, 311,  26,  26, 312,   2,
+-   313, 313, 313, 313, 313, 314,   0, 315, 316, 316, 316, 316, 316, 316, 316,  26,
+-   317, 317, 317, 317, 317, 317, 317, 317, 318, 319, 317, 320,  53,  53,  53,  53,
+-   321, 321, 321, 321, 321, 322, 323, 323, 323, 323, 324, 325, 169, 169, 169, 326,
+-   327, 327, 327, 327, 327, 327, 327, 327, 327, 328, 327, 329, 164, 164, 164, 330,
+-   331, 331, 331, 331, 331, 331, 332,  26, 331, 333, 331, 334, 164, 164, 164, 164,
+-   335, 335, 335, 335, 335, 335, 335, 335, 336,  26,  26, 337, 338, 338, 339,  26,
+-   340, 340, 340,  26, 172, 172,   2,   2,   2,   2,   2, 341, 342, 343, 176, 176,
+-   176, 176, 176, 176, 176, 176, 176, 176, 338, 338, 338, 338, 338, 344, 338, 345,
+-   169, 169, 169, 169, 346,  26, 169, 169, 295, 347, 169, 169, 169, 169, 169, 346,
+-    26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
+-   277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 280, 277, 277,
+-   277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 348,  26,  26,  26,  26,
+-   349,  26, 350, 351,  25,  25, 352, 353, 354,  25,  31,  31,  31,  31,  31,  31,
+-    31,  31,  31,  31,  31,  31,  31,  31, 355,  26, 356,  31,  31,  31,  31,  31,
+-    31,  31,  31,  31,  31,  31,  31,  31,  31,  31,  31,  31,  31,  31,  31,  31,
+-    31,  31,  31,  31,  31,  31,  31, 357,  31,  31,  31,  31,  31,  31,  31,  31,
+-    31,  31, 358,  31,  31,  31,  31,  31,  31, 359,  26,  26,  26,  26,  31,  31,
+-     9,   9,   0, 315,   9, 360,   0,   0,   0,   0, 361,   0, 258, 296, 362,  31,
+-    31,  31,  31,  31,  31,  31,  31,  31,  31,  31,  31,  31,  31,  31,  31, 363,
+-   364,   0,   0,   0,   1,   2,   2,   3,   1,   2,   2,   3, 365, 290, 289, 290,
+-   290, 290, 290, 366, 169, 169, 169, 295, 367, 367, 367, 368, 258, 258,  26, 369,
+-   370, 371, 370, 370, 372, 370, 370, 373, 370, 374, 370, 374,  26,  26,  26,  26,
+-   370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, 375,
+-   376,   0,   0,   0,   0,   0, 377,   0,  14,  14,  14,  14,  14,  14,  14,  14,
+-    14, 253,   0, 378, 379,  26,  26,  26,  26,  26,   0,   0,   0,   0,   0, 380,
+-   381, 381, 381, 382, 383, 383, 383, 383, 383, 383, 384,  26, 385,   0,   0, 296,
+-   386, 386, 386, 386, 387, 388, 389, 389, 389, 390, 391, 391, 391, 391, 391, 392,
+-   393, 393, 393, 394, 395, 395, 395, 395, 396, 395, 397,  26,  26,  26,  26,  26,
+-   398, 398, 398, 398, 398, 398, 398, 398, 398, 398, 399, 399, 399, 399, 399, 399,
+-   400, 400, 400, 401, 400, 402, 403, 403, 403, 403, 404, 403, 403, 403, 403, 404,
+-   405, 405, 405, 405, 405,  26, 406, 406, 406, 406, 406, 406, 407, 408, 409, 410,
+-   409, 410, 411, 409, 412, 409, 412, 413,  26,  26,  26,  26,  26,  26,  26,  26,
+-   414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414,
+-   414, 414, 414, 414, 414, 414, 415,  26, 414, 414, 416,  26, 414,  26,  26,  26,
+-   417,   2,   2,   2,   2,   2, 418, 309,  26,  26,  26,  26,  26,  26,  26,  26,
+-   419, 420, 421, 421, 421, 421, 422, 423, 424, 424, 425, 424, 426, 426, 426, 426,
+-   427, 427, 427, 428, 429, 427,  26,  26,  26,  26,  26,  26, 430, 430, 431, 432,
+-   433, 433, 433, 434, 435, 435, 435, 436,  26,  26,  26,  26,  26,  26,  26,  26,
+-   437, 437, 437, 437, 438, 438, 438, 439, 438, 438, 440, 438, 438, 438, 438, 438,
+-   441, 442, 443, 444, 445, 445, 446, 447, 445, 448, 445, 448, 449, 449, 449, 449,
+-   450, 450, 450, 450,  26,  26,  26,  26, 451, 451, 451, 451, 452, 453, 452,  26,
+-   454, 454, 454, 454, 454, 454, 455, 456, 457, 457, 458, 457, 459, 459, 460, 459,
+-   461, 461, 462, 463,  26, 464,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
+-   465, 465, 465, 465, 465, 465, 465, 465, 465, 466,  26,  26,  26,  26,  26,  26,
+-   467, 467, 467, 467, 467, 467, 468,  26, 467, 467, 467, 467, 467, 467, 468, 469,
+-   470, 470, 470, 470, 470,  26, 470, 471,  26,  26,  26,  26,  26,  26,  26,  26,
+-    26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  31,  31,  31,  50,
+-   472, 472, 472, 472, 472, 473, 474,  26,  26,  26,  26,  26,  26,  26,  26, 475,
+-   476, 476, 476, 476, 476,  26, 477, 477, 477, 477, 477, 478,  26,  26, 479, 479,
+-   479, 480,  26,  26,  26,  26, 481, 481, 481, 482,  26,  26, 483, 483, 484,  26,
+-   485, 485, 485, 485, 485, 485, 485, 485, 485, 486, 487, 485, 485, 485, 486, 488,
+-   489, 489, 489, 489, 489, 489, 489, 489, 490, 491, 492, 492, 492, 493, 492, 494,
+-   495, 495, 495, 495, 495, 495, 496, 495, 495,  26, 497, 497, 497, 497, 498,  26,
+-   499, 499, 499, 499, 499, 499, 499, 499, 499, 499, 499, 499, 500, 137, 501,  26,
+-   502, 502, 503, 502, 502, 502, 502, 502, 504,  26,  26,  26,  26,  26,  26,  26,
+-   505, 506, 507, 508, 507, 509, 510, 510, 510, 510, 510, 510, 510, 511, 510, 512,
+-   513, 514, 515, 516, 516, 517, 518, 519, 514, 520, 521, 522, 523, 524, 524,  26,
+-   525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 526, 527,  26,  26,  26,
+-   528, 528, 528, 528, 528, 528, 528, 528, 528,  26, 528, 529,  26,  26,  26,  26,
+-   530, 530, 530, 530, 530, 530, 531, 530, 530, 530, 530, 531,  26,  26,  26,  26,
+-   532, 532, 532, 532, 532, 532, 532, 532, 533,  26, 532, 534, 198, 535,  26,  26,
+-   536, 536, 536, 536, 536, 536, 536, 537, 536, 537,  26,  26,  26,  26,  26,  26,
+-   538, 538, 538, 539, 538, 540, 538, 538, 541,  26,  26,  26,  26,  26,  26,  26,
+-   542, 542, 542, 542, 542, 542, 542, 543,  26,  26,  26,  26,  26,  26,  26,  26,
+-    26,  26,  26,  26, 544, 544, 544, 544, 544, 544, 544, 544, 544, 544, 545, 546,
+-   547, 548, 549, 550, 550, 550, 551, 552, 547,  26, 550, 553,  26,  26,  26,  26,
+-    26,  26,  26,  26, 554, 555, 554, 554, 554, 554, 554, 555, 556,  26,  26,  26,
+-   557, 557, 557, 557, 557, 557, 557, 557, 557,  26, 558, 558, 558, 558, 558, 558,
+-   558, 558, 558, 558, 559,  26, 178, 178, 560, 560, 560, 560, 560, 560, 560, 561,
+-    53, 562,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
+-   563, 564, 563, 563, 563, 563, 565, 563, 566,  26, 563, 563, 563, 567, 568, 568,
+-   568, 568, 569, 568, 568, 570, 571,  26,  26,  26,  26,  26,  26,  26,  26,  26,
+-   572, 573, 574, 574, 574, 574, 572, 575, 574,  26, 574, 576, 577, 578, 579, 579,
+-   579, 580, 581, 582, 579, 583,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
+-    26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26, 584, 584, 584, 585,
+-   586, 586, 587, 586, 586, 586, 586, 588, 586, 586, 586, 589,  26,  26,  26,  26,
+-    26,  26,  26,  26,  26,  26, 590,  26, 108, 108, 108, 108, 108, 108, 591, 592,
+-   593, 593, 593, 593, 593, 593, 593, 593, 593, 593, 593, 593, 593, 593, 593, 593,
+-   593, 593, 593, 594,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
+-   593, 593, 593, 593, 593, 593, 593, 593, 593, 593, 593, 593, 593, 595, 596,  26,
+-   593, 593, 593, 593, 593, 593, 593, 593, 597,  26,  26,  26,  26,  26,  26,  26,
+-    26,  26, 598, 598, 598, 598, 598, 598, 598, 598, 598, 598, 598, 598, 599,  26,
+-   600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600,
+-   600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 601,  26,  26,  26,  26,  26,
+-   602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602,
+-   602, 602, 602, 602, 602, 602, 602, 602, 603,  26,  26,  26,  26,  26,  26,  26,
+-   306, 306, 306, 306, 306, 306, 306, 306, 306, 306, 306, 306, 306, 306, 306, 306,
+-   306, 306, 306, 306, 306, 306, 306, 604, 605, 605, 605, 606, 605, 607, 608, 608,
+-   608, 608, 608, 608, 608, 608, 608, 609, 608, 610, 611, 611, 611, 612, 612,  26,
+-   613, 613, 613, 613, 613, 613, 613, 613, 614,  26, 613, 615, 615, 613, 613, 616,
+-   613, 613,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
+-    26,  26,  26,  26,  26,  26,  26,  26, 617, 617, 617, 617, 617, 617, 617, 617,
+-   617, 617, 617, 618,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
+-   619, 619, 619, 619, 619, 619, 619, 619, 619, 620, 619, 619, 619, 619, 619, 619,
+-   619, 621, 619, 619,  26,  26,  26,  26,  26,  26,  26,  26, 622,  26, 348,  26,
+-   623, 623, 623, 623, 623, 623, 623, 623, 623, 623, 623, 623, 623, 623, 623, 623,
+-   623, 623, 623, 623, 623, 623, 623, 623, 623, 623, 623, 623, 623, 623, 623,  26,
+-   624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 624,
+-   624, 624, 624, 624, 624, 624, 624, 624, 624, 624, 625,  26,  26,  26,  26,  26,
+-   623, 626,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
+-    26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26, 627, 628,
+-   629, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286,
+-   286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286,
+-   286, 286, 286, 286, 630,  26, 631,  26,  26,  26, 632,  26, 633,  26, 634, 634,
+-   634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634,
+-   634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 634, 635,
+-   636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 637, 636, 638,
+-   636, 639, 636, 640, 296,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
+-     9,   9,   9,   9,   9, 641,   9,   9, 221,  26,   0,   0,   0,   0,   0,   0,
+-     0,   0,   0,   0,   0,   0,   0,   0, 296,  26,  26,  26,  26,  26,  26,  26,
+-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 276,  26,
+-     0,   0,   0,   0, 258, 364,   0,   0,   0,   0,   0,   0, 642, 643,   0, 644,
+-   645, 646,   0,   0,   0, 647,   0,   0,   0,   0,   0,   0,   0, 266,  26,  26,
+-    14,  14,  14,  14,  14,  14,  14,  14, 247,  26,  26,  26,  26,  26,  26,  26,
+-    26,  26,  26,  26,  26,  26,  26,  26,   0,   0, 296,  26,   0,   0, 296,  26,
+-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 258,  26,   0,   0,   0, 260,
+-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 255,   0,   0,   0,   0,   0,
+-     0,   0,   0, 255, 648, 649,   0, 650, 651,   0,   0,   0,   0,   0,   0,   0,
+-   269, 652, 255, 255,   0,   0,   0, 653, 654, 655, 656,   0,   0,   0,   0,   0,
+-     0,   0,   0,   0, 276,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+-     0,   0,   0,   0,   0,   0,   0,   0,   0, 268,   0,   0,   0,   0,   0,   0,
+-   657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657, 657,
+-   657, 658,  26, 659, 660, 657,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
+-     2,   2,   2, 349, 661, 309,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
+-   662, 270, 270, 663, 664, 665,  18,  18,  18,  18,  18,  18,  18, 666,  26,  26,
+-    26, 667,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
+-   668, 668, 668, 668, 668, 669, 668, 670, 668, 671,  26,  26,  26,  26,  26,  26,
+-    26,  26, 672, 672, 672, 673,  26,  26, 674, 674, 674, 674, 674, 674, 674, 675,
+-    26,  26,  26,  26,  26,  26,  26,  26,  26,  26, 676, 676, 676, 676, 676, 677,
+-    26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26, 172, 678, 170, 172,
+-   679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679,
+-   679, 679, 679, 679, 679, 679, 679, 679, 680, 679, 681,  26,  26,  26,  26,  26,
+-   682, 682, 682, 682, 682, 682, 682, 682, 682, 683, 682, 684,  26,  26,  26,  26,
+-    26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26, 364,   0,
+-     0,   0,   0,   0,   0,   0, 378,  26,  26,  26,  26,  26,  26,  26,  26,  26,
+-   364,   0,   0,   0,   0,   0,   0, 276,  26,  26,  26,  26,  26,  26,  26,  26,
+-   685,  31,  31,  31, 686, 687, 688, 689, 690, 691, 686, 692, 686, 688, 688, 693,
+-    31, 694,  31, 695, 696, 694,  31, 695,  26,  26,  26,  26,  26,  26,  51,  26,
+-     0,   0,   0,   0,   0, 296,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+-     0,   0, 296,  26,   0, 258, 364,   0, 364,   0, 364,   0,   0,   0, 276,  26,
+-     0,   0,   0,   0,   0, 276,  26,  26,  26,  26,  26,  26, 697,   0,   0,   0,
+-   698,  26,   0,   0,   0,   0,   0, 296,   0, 260, 315,  26, 276,  26,  26,  26,
+-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 699,   0, 378,   0, 378,
+-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 258, 700,
+-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 315,   0, 296, 260,  26,
+-     0, 296,   0,   0,   0,   0,   0,   0,   0,  26,   0, 315,   0,   0,   0,   0,
+-     0,  26,   0,   0,   0, 276, 315,  26,  26,  26,  26,  26,  26,  26,  26,  26,
+-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 296,  26,   0, 276,   0, 378,
+-     0, 260,   0,   0,   0,   0,   0, 269, 276, 697,   0, 296,   0, 260,   0, 260,
+-     0,   0, 361,   0,   0,   0,   0,   0,   0, 266,  26,  26,  26,  26,   0, 315,
+-   277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,  26,  26,  26,  26,
+-   277, 277, 277, 277, 277, 277, 277, 348, 277, 277, 277, 277, 277, 277, 277, 277,
+-   277, 277, 277, 280, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
+-   277, 277, 277, 277, 348,  26, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
+-   277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 701,  26, 277, 277,
+-   277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 280,  26,  26,  26,  26,
+-   277, 277, 277, 280,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
+-   277, 277, 277, 277, 277, 277, 277, 277, 277, 702, 277, 277, 277, 277, 277, 277,
+-   277, 277, 277, 277, 277, 277,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
+-   703,  26,  26,  26,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+-     9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,
+-     9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   0,   0,
++   299, 299, 299, 299, 299, 299, 299, 299, 299, 300, 299, 299, 299, 299, 299, 299,
++   301,  26, 302, 302, 302, 302, 302, 302, 303, 303, 303, 303, 303, 303, 303, 303,
++   303, 303, 303, 303, 303, 304,  26,  26,  18,  18,  18,  18, 305, 305, 305, 305,
++   305, 305, 305, 305, 305, 305, 305,  26,   0,   0,   0,   0, 306,   2,   2,   2,
++     2, 307,   2,   2,   2,   2,   2,   2,   2, 308, 309, 258,  26,  26, 310,   2,
++   311, 311, 311, 311, 311, 312,   0, 265, 313, 313, 313, 313, 313, 313, 313,  26,
++   314, 314, 314, 314, 314, 314, 314, 314, 315, 316, 314, 317,  53,  53,  53,  53,
++   318, 318, 318, 318, 318, 319, 320, 320, 320, 320, 321, 322, 169, 169, 169, 323,
++   324, 324, 324, 324, 324, 324, 324, 324, 324, 325, 324, 326, 164, 164, 164, 327,
++   328, 328, 328, 328, 328, 328, 329,  26, 328, 330, 328, 331, 164, 164, 164, 164,
++   332, 332, 332, 332, 332, 332, 332, 332, 333,  26,  26, 334, 335, 335, 336,  26,
++   337, 337, 337,  26, 172, 172,   2,   2,   2,   2,   2, 338, 339, 340, 176, 176,
++   176, 176, 176, 176, 176, 176, 176, 176, 335, 335, 335, 335, 335, 341, 335, 342,
++   169, 169, 169, 169, 343,  26, 169, 169, 295, 344, 169, 169, 169, 169, 169, 343,
++    26,  26,  26,  26,  26,  26,  26,  26, 277, 277, 277, 277, 277, 280, 277, 277,
++   277, 277, 277, 345,  26,  26,  26,  26, 346,  26, 347, 348,  25,  25, 349, 350,
++   351,  25,  31,  31,  31,  31,  31,  31, 352,  26, 353,  31,  31,  31,  31,  31,
++    31,  31,  31,  31,  31,  31,  31, 354,  31,  31, 355,  31,  31,  31,  31,  31,
++    31, 356,  26,  26,  26,  26,  31,  31,   9,   9,   0, 265,   9, 357,   0,   0,
++     0,   0, 358,   0, 257, 359, 360,  31,  31,  31,  31,  31,  31,  31,  31, 361,
++   362,   0,   0,   0,   1,   2,   2,   3,   1,   2,   2,   3, 363, 290, 289, 290,
++   290, 290, 290, 364, 169, 169, 169, 295, 365, 365, 365, 366, 257, 257,  26, 367,
++   368, 369, 368, 368, 370, 368, 368, 371, 368, 372, 368, 372,  26,  26,  26,  26,
++   368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 373,
++   374,   0,   0,   0,   0,   0, 375,   0,  14,  14,  14,  14,  14,  14,  14,  14,
++    14, 252,   0, 376, 377,  26,  26,  26,  26,  26,   0,   0,   0,   0,   0, 378,
++   379, 379, 379, 380, 381, 381, 381, 381, 381, 381, 382,  26, 383,   0,   0, 359,
++   384, 384, 384, 384, 385, 386, 387, 387, 387, 388, 389, 389, 389, 389, 389, 390,
++   391, 391, 391, 392, 393, 393, 393, 393, 394, 393, 395,  26,  26,  26,  26,  26,
++   396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 397, 397, 397, 397, 397, 397,
++   398, 398, 398, 399, 398, 400, 401, 401, 401, 401, 402, 401, 401, 401, 401, 402,
++   403, 403, 403, 403, 403,  26, 404, 404, 404, 404, 404, 404, 405, 406, 407, 408,
++   407, 408, 409, 407, 410, 407, 410, 411, 412, 412, 412, 412, 412, 412, 413,  26,
++   414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, 415,  26,
++   414, 414, 416,  26, 414,  26,  26,  26, 417,   2,   2,   2,   2,   2, 418, 419,
++   420, 421, 422, 422, 422, 422, 423, 424, 425, 425, 426, 425, 427, 427, 427, 427,
++   428, 428, 428, 429, 430, 428,  26,  26,  26,  26,  26,  26, 431, 431, 432, 433,
++   434, 434, 434, 435, 436, 436, 436, 437, 438, 438, 438, 438, 439, 439, 439, 440,
++   439, 439, 441, 439, 439, 439, 439, 439, 442, 443, 444, 445, 446, 446, 447, 448,
++   446, 449, 446, 449, 450, 450, 450, 450, 451, 451, 451, 451,  26,  26,  26,  26,
++   452, 452, 452, 452, 453, 454, 453,  26, 455, 455, 455, 455, 455, 455, 456, 457,
++   458, 458, 459, 458, 460, 460, 461, 460, 462, 462, 463, 464,  26, 465,  26,  26,
++   466, 466, 466, 466, 466, 466, 466, 466, 466, 467,  26,  26,  26,  26,  26,  26,
++   468, 468, 468, 468, 468, 468, 469,  26, 468, 468, 468, 468, 468, 468, 469, 470,
++   471, 471, 471, 471, 471,  26, 471, 472, 473, 473, 473, 473, 474, 475, 473, 473,
++   474, 476,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  31,  31,  31,  50,
++   477, 477, 477, 477, 477, 478, 479,  26, 480,  26,  26,  26,  26,  26,  26, 481,
++   482, 482, 482, 482, 482,  26, 483, 483, 483, 483, 483, 484,  26,  26, 485, 485,
++   485, 486,  26,  26,  26,  26, 487, 487, 487, 488,  26,  26, 489, 489, 490,  26,
++   491, 491, 491, 491, 491, 491, 491, 491, 491, 492, 493, 491, 491, 491, 492, 494,
++   495, 495, 495, 495, 495, 495, 495, 495, 496, 497, 498, 498, 498, 499, 498, 500,
++   501, 501, 501, 501, 501, 501, 502, 501, 501,  26, 503, 503, 503, 503, 504,  26,
++   505, 505, 505, 505, 505, 505, 505, 505, 505, 505, 505, 505, 506, 137, 507,  26,
++   508, 508, 509, 508, 508, 508, 508, 508, 510,  26,  26,  26,  26,  26,  26,  26,
++   511, 512, 513, 514, 513, 515, 516, 516, 516, 516, 516, 516, 516, 517, 516, 518,
++   519, 520, 521, 522, 522, 523, 524, 525, 520, 526, 527, 528, 529, 530, 530,  26,
++   531, 532, 531, 531, 531, 531, 533, 531, 534, 535, 533, 536, 537,  26,  26,  26,
++   538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 538, 539, 540,  26,  26,  26,
++   541, 541, 541, 541, 541, 541, 541, 541, 541,  26, 541, 542,  26,  26,  26,  26,
++   543, 543, 543, 543, 543, 543, 544, 543, 543, 543, 543, 544,  26,  26,  26,  26,
++   545, 545, 545, 545, 545, 545, 545, 545, 546,  26, 545, 547, 198, 548,  26,  26,
++   549, 549, 549, 549, 549, 549, 549, 550, 549, 550, 164, 164, 551,  26,  26,  26,
++   552, 552, 552, 553, 552, 554, 552, 552, 555,  26,  26,  26,  26,  26,  26,  26,
++   556, 556, 556, 556, 556, 556, 556, 557,  26,  26,  26,  26, 558, 558, 558, 558,
++   558, 558, 558, 558, 558, 558, 559, 560, 561, 562, 563, 564, 564, 564, 565, 566,
++   561,  26, 564, 567,  26,  26,  26,  26,  26,  26,  26,  26, 568, 569, 568, 568,
++   568, 568, 568, 569, 570,  26,  26,  26, 571, 571, 571, 571, 571, 571, 571, 571,
++   571,  26, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 573,  26, 178, 178,
++   574, 574, 574, 574, 574, 574, 574, 575,  53, 576,  26,  26,  26,  26,  26,  26,
++   577, 577, 577, 577, 578,  26, 577, 578, 579, 580, 579, 579, 579, 579, 581, 579,
++   582,  26, 579, 579, 579, 583, 584, 584, 584, 584, 585, 584, 584, 586, 587,  26,
++   588, 589, 590, 590, 590, 590, 588, 591, 590,  26, 590, 592, 593, 594, 595, 595,
++   595, 596, 597, 598, 595, 599,  26,  26,  26,  26,  26,  26, 600, 600, 600, 601,
++   602, 602, 603, 602, 602, 602, 602, 604, 602, 602, 602, 605,  26,  26,  26,  26,
++    26,  26,  26,  26,  26,  26, 606,  26, 108, 108, 108, 108, 108, 108, 607, 608,
++   609, 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, 610,  26,  26,  26,  26,
++   609, 609, 609, 609, 609, 611, 612,  26, 613,  26,  26,  26,  26,  26,  26,  26,
++    26,  26, 614, 614, 614, 614, 614, 614, 614, 614, 614, 614, 614, 614, 615,  26,
++   616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 617,  26, 616, 616, 616, 616,
++   616, 616, 616, 616, 616, 616, 616, 618, 619, 619, 619, 619, 619, 619, 619, 619,
++   620,  26,  26,  26,  26,  26,  26,  26, 621, 621, 621, 621, 621, 621, 621, 622,
++   305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, 623,
++   624, 624, 624, 625, 624, 626, 627, 627, 627, 627, 627, 627, 627, 627, 627, 628,
++   627, 629, 630, 630, 630, 631, 631,  26, 632, 632, 632, 632, 632, 632, 632, 632,
++   633,  26, 632, 634, 634, 632, 632, 635, 632, 632,  26,  26,  26,  26,  26,  26,
++   636, 636, 636, 636, 636, 636, 636, 637, 638, 638, 638, 638, 638, 638, 638, 638,
++   638, 638, 638, 639,  26,  26,  26,  26, 640, 640, 640, 640, 640, 640, 640, 640,
++   640, 641, 640, 640, 640, 640, 640, 640, 640, 642, 640, 640,  26,  26,  26,  26,
++    26,  26,  26,  26, 643,  26, 345,  26, 644, 644, 644, 644, 644, 644, 644, 644,
++   644, 644, 644, 644, 644, 644, 644,  26, 645, 645, 645, 645, 645, 645, 645, 645,
++   645, 645, 646,  26,  26,  26,  26, 647, 644, 648,  26,  26,  26,  26,  26,  26,
++    26,  26,  26,  26,  26,  26, 649, 650, 651, 286, 286, 286, 286, 286, 286, 286,
++   286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 652,  26, 653,  26,
++    26,  26, 654,  26, 655,  26, 656, 656, 656, 656, 656, 656, 656, 656, 656, 656,
++   656, 656, 656, 656, 656, 656, 656, 657, 658, 658, 658, 658, 658, 658, 658, 658,
++   658, 658, 658, 658, 658, 659, 658, 660, 658, 661, 658, 662, 359,  26,  26,  26,
++     0,   0,   0,   0,   0,   0,   0, 265,   0,   0,   0,   0,   0,   0, 359,  26,
++     9,   9,   9,   9,   9, 663,   9,   9, 221,  26,   0,   0,   0,   0,   0,   0,
++   359,  26,  26,  26,  26,  26,  26,  26,   0,   0,   0,   0,   0,   0, 276,  26,
++     0,   0,   0,   0, 257, 362,   0,   0,   0,   0,   0,   0, 664, 665,   0, 666,
++   667, 668,   0,   0,   0, 669,   0,   0,   0,   0,   0,   0,   0, 266,  26,  26,
++   246,  26,  26,  26,  26,  26,  26,  26,   0,   0, 359,  26,   0,   0, 359,  26,
++     0,   0, 257,  26,   0,   0,   0, 259,   0,   0, 254,   0,   0,   0,   0,   0,
++     0,   0,   0, 254, 670, 671,   0, 672, 673,   0,   0,   0,   0,   0,   0,   0,
++   269, 674, 254, 254,   0,   0,   0, 675, 676, 677, 678,   0,   0,   0,   0,   0,
++     0,   0,   0,   0, 276,   0,   0,   0,   0, 268,   0,   0,   0,   0,   0,   0,
++   679, 679, 679, 679, 679, 679, 679, 679, 679, 680,  26, 681, 682, 679,  26,  26,
++     2,   2,   2, 346, 683, 419,  26,  26, 684, 270, 270, 685, 686, 687,  18,  18,
++    18,  18,  18,  18,  18, 688,  26,  26,  26, 689,  26,  26,  26,  26,  26,  26,
++   690, 690, 690, 690, 690, 691, 690, 692, 690, 693,  26,  26,  26,  26,  26,  26,
++    26,  26, 694, 694, 694, 695,  26,  26, 696, 696, 696, 696, 696, 696, 696, 697,
++    26,  26, 698, 698, 698, 698, 698, 699,  26,  26, 700, 700, 700, 700, 700, 701,
++    26,  26,  26,  26, 172, 702, 170, 172, 703, 703, 703, 703, 703, 703, 703, 703,
++   704, 703, 705,  26,  26,  26,  26,  26, 706, 706, 706, 706, 706, 706, 706, 706,
++   706, 707, 706, 708,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26, 362,   0,
++     0,   0,   0,   0,   0,   0, 376,  26, 362,   0,   0,   0,   0,   0,   0, 276,
++   709,  31,  31,  31, 710, 711, 712, 713, 714, 715, 710, 716, 710, 712, 712, 717,
++    31, 718,  31, 719, 720, 718,  31, 719,  26,  26,  26,  26,  26,  26, 721,  26,
++     0,   0,   0,   0,   0, 359,   0,   0,   0,   0, 359,  26,   0, 257, 362,   0,
++   362,   0, 362,   0,   0,   0, 276,  26,   0,   0,   0,   0,   0, 276,  26,  26,
++    26,  26,  26,  26, 722,   0,   0,   0, 723,  26,   0,   0,   0,   0,   0, 359,
++     0, 259, 265,  26, 276,  26,  26,  26,   0,   0,   0, 724,   0, 376,   0, 376,
++     0,   0,   0,   0,   0,   0, 257, 725,   0,   0,   0, 265,   0, 359, 259,  26,
++     0, 359,   0,   0,   0,   0,   0,   0,   0,  26,   0, 265,   0,   0,   0,   0,
++     0,  26,   0,   0,   0, 276,   0, 359, 265,  26,  26,  26,  26,  26,  26,  26,
++     0,   0, 359,  26,   0, 276,   0, 376,   0, 726,   0,   0,   0,   0,   0,   0,
++   257, 722,   0, 727,   0, 265,   0, 259,   0,   0, 358,   0,   0,   0,   0,   0,
++   277, 277, 277, 277,  26,  26,  26,  26, 277, 277, 277, 277, 277, 277, 277, 345,
++   277, 277, 277, 280, 277, 277, 277, 277, 277, 277, 277, 277, 345,  26, 277, 277,
++   277, 277, 277, 277, 728,  26, 277, 277, 277, 277, 277, 280,  26,  26,  26,  26,
++   277, 729, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,  26,  26,
++   730,  26,  26,  26,   0,   0,   0,   0,   9,   9,   9,   9,   9,   9,   0,   0,
+      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+    939, 940, 941, 942, 946, 948,   0, 962, 969, 970, 971, 976,1001,1002,1003,1008,
+      0,1033,1040,1041,1042,1043,1047,   0,   0,1080,1081,1082,1086,1110,   0,   0,
+@@ -2732,17 +2787,24 @@ _hb_ucd_u16[9344] =
+      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1602,1603,1934,1935,1574,1575,
+   1576,1577,1579,1580,1581,1583,1584,   0,1585,1587,1588,1589,1591,   0,1592,   0,
+   1593,1594,   0,1595,1596,   0,1598,1599,1600,1601,1604,1582,1578,1590,1597,   0,
+-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1936,   0,1937,   0,   0,   0,
+-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1938,   0,   0,   0,   0,
+-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1939,1940,
+-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1941,1942,   0,   0,   0,
+-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1944,1943,   0,1945,   0,
+-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1946,1947,   0,   0,   0,   0,
+-     0,   0,   0,   0,   0,   0,   0,   0,1948,   0,   0,   0,   0,   0,   0,   0,
+-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1949,1950,
+-  1951,1952,1953,1954,1955,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1956,1957,1958,1960,1959,
+-  1961,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
++     0,   0,   0,   0,   0,   0,   0,   0,   0,1936,   0,   0,   0,   0,   0,   0,
++     0,   0,   0,   0,1937,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
++     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1938,   0,1939,   0,   0,   0,
++     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1940,   0,   0,   0,   0,
++     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1941,1942,
++     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1943,1944,   0,   0,   0,
++     0,   0,   0,1945,   0,1946,   0,   0,   0,   0,   0,   0,   0,   0,1947,   0,
++     0,1948,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
++     0,   0,   0,   0,   0,1950,   0,1949,1951,   0,   0,   0,   0,   0,   0,   0,
++     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1953,1952,   0,1954,   0,
++     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1955,1956,   0,   0,   0,   0,
++     0,   0,   0,   0,   0,   0,   0,   0,1957,   0,   0,   0,   0,   0,   0,   0,
++     0,1958,1961,1959,1965,1960,1962,1964,1963,   0,   0,   0,   0,   0,   0,   0,
++     0,   0,   0,   0,   0,   0,   0,   0,1967,1966,1968,   0,   0,   0,   0,   0,
++     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1969,1970,
++  1971,1972,1973,1974,1975,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
++     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1976,1977,1978,1980,1979,
++  1981,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+    106, 104, 107, 826, 114, 118, 119, 121, 123, 124, 127, 125,  34, 830, 130, 131,
+    132, 137, 827,  35, 133, 139, 829, 142, 143, 112, 144, 145, 924, 151, 152,  37,
+    157, 158, 159, 160,  38, 165, 166, 169, 171, 172, 173, 174, 176, 177, 178, 179,
+@@ -2799,12 +2861,12 @@ _hb_ucd_i16[196] =
+ static inline uint_fast8_t
+ _hb_ucd_gc (unsigned u)
+ {
+-  return u<1114110u?_hb_ucd_u8[6808+(((_hb_ucd_u8[1312+(((_hb_ucd_u16[((_hb_ucd_u8[544+(((_hb_ucd_u8[u>>1>>3>>3>>4])<<4)+((u>>1>>3>>3)&15u))])<<3)+((u>>1>>3)&7u)])<<3)+((u>>1)&7u))])<<1)+((u)&1u))]:2;
++  return u<1114110u?_hb_ucd_u8[6472+(((_hb_ucd_u8[816+(((_hb_ucd_u16[((_hb_ucd_u8[272+(((_hb_ucd_u8[u>>1>>3>>4>>4])<<4)+((u>>1>>3>>4)&15u))])<<4)+((u>>1>>3)&15u)])<<3)+((u>>1)&7u))])<<1)+((u)&1u))]:2;
+ }
+ static inline uint_fast8_t
+ _hb_ucd_ccc (unsigned u)
+ {
+-  return u<125259u?_hb_ucd_u8[8800+(((_hb_ucd_u8[8244+(((_hb_ucd_u8[7784+(((_hb_ucd_u8[7432+(((_hb_ucd_u8[7186+(u>>2>>2>>2>>3)])<<3)+((u>>2>>2>>2)&7u))])<<2)+((u>>2>>2)&3u))])<<2)+((u>>2)&3u))])<<2)+((u)&3u))]:0;
++  return u<125259u?_hb_ucd_u8[8504+(((_hb_ucd_u8[7936+(((_hb_ucd_u8[7460+(((_hb_ucd_u8[7100+(((_hb_ucd_u8[6854+(u>>2>>2>>2>>3)])<<3)+((u>>2>>2>>2)&7u))])<<2)+((u>>2>>2)&3u))])<<2)+((u>>2)&3u))])<<2)+((u)&3u))]:0;
+ }
+ static inline unsigned
+ _hb_ucd_b4 (const uint8_t* a, unsigned i)
+@@ -2814,107 +2876,76 @@ _hb_ucd_b4 (const uint8_t* a, unsigned i)
+ static inline int_fast16_t
+ _hb_ucd_bmg (unsigned u)
+ {
+-  return u<65380u?_hb_ucd_i16[((_hb_ucd_u8[9548+(((_hb_ucd_u8[9428+(((_hb_ucd_b4(9300+_hb_ucd_u8,u>>2>>3>>3))<<3)+((u>>2>>3)&7u))])<<3)+((u>>2)&7u))])<<2)+((u)&3u)]:0;
++  return u<65380u?_hb_ucd_i16[((_hb_ucd_u8[9252+(((_hb_ucd_u8[9132+(((_hb_ucd_b4(9004+_hb_ucd_u8,u>>2>>3>>3))<<3)+((u>>2>>3)&7u))])<<3)+((u>>2)&7u))])<<2)+((u)&3u)]:0;
+ }
+ static inline uint_fast8_t
+ _hb_ucd_sc (unsigned u)
+ {
+-  return u<918000u?_hb_ucd_u8[11070+(((_hb_ucd_u16[2048+(((_hb_ucd_u8[10334+(((_hb_ucd_u8[9884+(u>>3>>4>>4)])<<4)+((u>>3>>4)&15u))])<<4)+((u>>3)&15u))])<<3)+((u)&7u))]:2;
++  return u<918000u?_hb_ucd_u8[10486+(((_hb_ucd_u16[3744+(((_hb_ucd_u16[2624+(((_hb_ucd_u8[9588+(u>>3>>3>>4)])<<4)+((u>>3>>3)&15u))])<<3)+((u>>3)&7u))])<<3)+((u)&7u))]:2;
+ }
+ static inline uint_fast16_t
+ _hb_ucd_dm (unsigned u)
+ {
+-  return u<195102u?_hb_ucd_u16[6032+(((_hb_ucd_u8[17084+(((_hb_ucd_u8[16702+(u>>4>>5)])<<5)+((u>>4)&31u))])<<4)+((u)&15u))]:0;
++  return u<195102u?_hb_ucd_u16[6976+(((_hb_ucd_u8[16716+(((_hb_ucd_u8[16334+(u>>4>>5)])<<5)+((u>>4)&31u))])<<4)+((u)&15u))]:0;
+ }
+ 
+ 
+ #elif !defined(HB_NO_UCD_UNASSIGNED)
+ 
+ static const uint8_t
+-_hb_ucd_u8[14752] =
++_hb_ucd_u8[17524] =
+ {
+-    0,  1,  2,  3,  4,  5,  6,  7,  7,  8,  7,  7,  7,  7,  7,  7,
+-    7,  7,  7,  7,  9, 10,  7,  7,  7,  7, 11, 12, 13, 13, 13, 14,
+-   15, 16, 17, 18, 19, 20, 21, 22, 23, 22, 22, 22, 22, 24,  7,  7,
+-   25, 26, 22, 22, 22, 27, 28, 29, 22, 30, 31, 32, 33, 34, 35, 36,
+-    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
+-    7,  7,  7,  7, 37,  7, 38, 39,  7, 40,  7,  7,  7, 41, 22, 42,
+-    7,  7, 43,  7, 44, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+-   45, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+-   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 46,
+-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 47,
++    0,  1,  2,  3,  4,  5,  5,  5,  5,  5,  6,  5,  5,  7,  8,  9,
++   10, 11, 12, 13, 14, 15, 16,  5, 17, 15, 18, 19, 20, 21, 22, 23,
++    5,  5,  5,  5,  5,  5,  5,  5,  5,  5, 24, 25, 26,  5, 27, 28,
++    5, 29, 30, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
++   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
++   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
++   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
++   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
++   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
++   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
++   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
++   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
++   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
++   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
++   31, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
++    8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8, 32,
++    8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8, 33,
+     0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
+-   16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+-   32, 33, 34, 34, 35, 36, 37, 38, 39, 34, 34, 34, 40, 41, 42, 43,
+-   44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+-   60, 61, 62, 63, 64, 64, 65, 66, 67, 68, 69, 70, 71, 69, 72, 73,
+-   69, 69, 64, 74, 64, 64, 75, 76, 77, 78, 79, 80, 81, 82, 69, 83,
+-   84, 85, 86, 87, 88, 89, 69, 69, 34, 34, 34, 34, 34, 34, 34, 34,
+-   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
+-   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 90, 34, 34, 34, 34,
+-   91, 34, 34, 34, 34, 34, 34, 34, 34, 92, 34, 34, 93, 94, 95, 96,
+-   97, 98, 99,100,101,102,103,104, 34, 34, 34, 34, 34, 34, 34, 34,
+-   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,105,
+-  106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,
+-  107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,
+-  107,107, 34, 34,108,109,110,111, 34, 34,112,113,114,115,116,117,
+-  118,119,120,121,122,123,124,125,126,127,128,129, 34, 34,130,131,
+-  132,133,134,135,136,137,138,139,140,141,142,122,143,144,145,146,
+-  147,148,149,150,151,152,153,122,154,155,122,156,157,158,159,122,
+-  160,161,162,163,164,165,166,122,167,168,169,170,122,171,172,173,
+-   34, 34, 34, 34, 34, 34, 34,174,175, 34,176,122,122,122,122,122,
+-  122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,177,
+-   34, 34, 34, 34, 34, 34, 34, 34,178,122,122,122,122,122,122,122,
+-  122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,
+-  122,122,122,122,122,122,122,122, 34, 34, 34, 34,179,122,122,122,
+-   34, 34, 34, 34,180,181,182,183,122,122,122,122,184,185,186,187,
+-   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,188,
+-   34, 34, 34, 34, 34, 34, 34, 34, 34,189,190,122,122,122,122,122,
+-  122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,191,
+-   34, 34,192, 34, 34,193,122,122,122,122,122,122,122,122,122,122,
+-  122,122,122,122,122,122,122,122,194,195,122,122,122,122,122,122,
+-  122,122,122,122,122,122,122,122,122,122,122,122,122,122,196,197,
+-   69,198,199,200,201,202,203,122,204,205,206,207,208,209,210,211,
+-   69, 69, 69, 69,212,213,122,122,122,122,122,122,122,122,214,122,
+-  215,216,217,122,122,218,122,122,122,219,122,122,122,122,122,220,
+-   34,221,222,122,122,122,122,122,223,224,225,122,226,227,122,122,
+-  228,229,230,231,232,122, 69,233, 69, 69, 69, 69, 69,234,235,236,
+-  237,238, 69, 69,239,240, 69,241,122,122,122,122,122,122,122,122,
+-   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,242, 34, 34,
+-   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,243, 34,
+-  244, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
+-   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,245, 34, 34,
+-   34, 34, 34, 34, 34, 34, 34,246, 34, 34, 34, 34,247,122,122,122,
+-   34, 34, 34, 34,248,122,122,122,122,122,122,122,122,122,122,122,
+-   34, 34, 34, 34, 34, 34,249, 34, 34, 34, 34, 34, 34, 34, 34, 34,
+-   34, 34, 34, 34, 34, 34, 34,250,122,122,122,122,122,122,122,122,
+-  251,122,252,253,122,122,122,122,122,122,122,122,122,122,122,122,
+-  107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,254,
+-  107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,255,
++   16, 17, 18, 19, 20, 17, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
++   31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 33, 41, 42, 43, 44, 45,
++   46, 47, 48, 39, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
++   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 49, 17, 17,
++   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
++   50, 17, 17, 17, 51, 17, 52, 53, 54, 55, 56, 57, 17, 17, 17, 17,
++   17, 17, 17, 17, 17, 17, 17, 58, 59, 59, 59, 59, 59, 59, 59, 59,
++   60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,
++   60, 60, 60, 60, 60, 60, 60, 60, 60, 17, 61, 62, 17, 63, 64, 65,
++   66, 67, 68, 69, 70, 71, 17, 72, 73, 74, 75, 76, 77, 78, 79, 80,
++   81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96,
++   17, 17, 17, 97, 98, 99,100,100,100,100,100,100,100,100,100,101,
++   17, 17, 17, 17,102, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
++   17, 17, 17,103, 17, 17,104,100,100,100,100,100,100,100,100,100,
++  100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
++  100,105,100,100,100,100,100,100, 17, 17,106,107,100,108,109,110,
++   17, 17, 17, 17, 17, 17, 17,111, 17, 17, 17, 17,112,113,100,100,
++  100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,114,
++   17,115,116,100,100,100,100,100,100,100,100,100,117,100,100,100,
++  100,100,100,100,100,100,100,100,100,100,100,100,118, 39,119,120,
++  121,122,123,124,125,126,127,128, 39, 39,129,100,100,100,100,130,
++  131,132,133,100,134,135,100,136,137,138,100,100,139,140,141,100,
++  142,143,144,145, 39, 39,146,147,148, 39,149,150,100,100,100,100,
++   17, 17, 17, 17, 17, 17,151, 17, 17, 17, 17, 17, 17, 17, 17, 17,
++   17, 17, 17, 17, 17, 17, 17,152,153, 17, 17, 17, 17, 17, 17, 17,
++   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,154, 17,
++   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,155, 17, 17,156,100,
++  100,100,100,100,100,100,100,100, 17, 17,157,100,100,100,100,100,
++   17, 17, 17,158, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
++   17, 17, 17,159,100,100,100,100,100,100,100,100,100,100,100,100,
++  160,161,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
++   60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,162,
++   60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,163,
+     0,  0,  0,  0,  0,  0,  0,  0,  1,  2,  3,  2,  4,  5,  6,  2,
+     7,  7,  7,  7,  7,  2,  8,  9, 10, 11, 11, 11, 11, 11, 11, 11,
+    11, 11, 11, 11, 11, 12, 13, 14, 15, 16, 16, 16, 16, 16, 16, 16,
+@@ -2951,7 +2982,7 @@ _hb_ucd_u8[14752] =
+    43, 43, 40, 21,  2, 81, 57, 20, 36, 36, 36, 43, 43, 75, 43, 43,
+    43, 43, 75, 43, 75, 43, 43, 44,  2,  2,  2,  2,  2,  2,  2, 64,
+    36, 36, 36, 36, 70, 43, 44, 64, 36, 36, 36, 36, 36, 61, 44, 44,
+-   36, 36, 36, 36, 82, 36, 36, 61, 65, 44, 44, 44, 43, 43, 43, 43,
++   36, 36, 36, 36, 82, 36, 36, 61, 65, 44, 44, 57, 43, 43, 43, 43,
+    36, 36, 36, 36, 83, 43, 43, 43, 43, 84, 43, 43, 43, 43, 43, 43,
+    43, 85, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 85, 71, 86,
+    87, 43, 43, 43, 85, 86, 87, 86, 70, 43, 43, 43, 36, 36, 36, 36,
+@@ -3024,13 +3055,13 @@ _hb_ucd_u8[14752] =
+    85, 85, 87, 43, 43, 43, 85, 86, 86, 87, 43, 43, 43, 43, 80, 57,
+     2,  2,  2, 88,  2,  2,  2, 44, 43, 43, 43, 43, 43, 43, 43,109,
+    43, 43, 43, 43, 43, 43, 43, 80, 43, 43, 98, 36, 36, 36, 36, 36,
+-   36, 36, 85, 43, 43, 85, 85, 86, 86, 85, 98, 36, 36, 36, 61, 44,
+-   97, 67, 67, 67, 67, 50, 43, 43, 43, 43, 67, 67, 67, 67, 21, 64,
++   36, 36, 85, 43, 43, 85, 85, 86, 86, 85, 98, 36, 36, 36, 61,  2,
++   97, 67, 67, 67, 67, 50, 43, 43, 43, 43, 67, 67, 67, 67, 21,  2,
+    43, 98, 36, 36, 36, 36, 36, 36, 94, 43, 43, 86, 43, 87, 43, 36,
+    36, 36, 36, 85, 43, 86, 87, 87, 43, 86, 44, 44, 44, 44,  2,  2,
+    36, 36, 86, 86, 86, 86, 43, 43, 43, 43, 86, 43, 44, 93,  2,  2,
+     7,  7,  7,  7,  7, 44, 62, 36, 36, 36, 36, 36, 40, 40, 40,  2,
+-   16, 16, 16, 16,110, 44, 44, 44, 11, 11, 11, 11, 11, 47, 48, 11,
++   16, 16, 16, 16, 34,110, 44, 44, 11, 11, 11, 11, 11, 47, 48, 11,
+     2,  2,  2,  2, 44, 44, 44, 44, 43, 60, 43, 43, 43, 43, 43, 43,
+    85, 43, 43, 43, 71, 36, 70, 36, 36, 36, 71, 94, 43, 61, 44, 44,
+    16, 16, 16, 16, 16, 16, 40, 40, 40, 40, 40, 40, 40, 45, 16, 16,
+@@ -3058,33 +3089,33 @@ _hb_ucd_u8[14752] =
+    67, 67, 67, 67,  4,  4, 67, 67,  8, 67, 67, 67,145,146, 67, 67,
+    67, 67, 67, 67, 67, 67,144, 67, 67, 67, 67, 67, 67, 26,  8,  8,
+     8,  8, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,  8,  8,
+-    8, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 92, 44, 44, 44, 44,
+-   67, 67, 67, 67, 67, 92, 44, 44, 27, 27, 27, 27, 27, 27, 67, 67,
+-   67, 67, 67, 67, 67, 27, 27, 27, 67, 67, 67, 26, 67, 67, 67, 67,
+-   26, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,  8,  8,  8,  8,
+-   67, 67, 67, 67, 67, 67, 67, 26, 67, 67, 67, 67,  4,  4,  4,  4,
+-    4,  4,  4, 27, 27, 27, 27, 27, 27, 27, 67, 67, 67, 67, 67, 67,
+-    8,  8,129,147,  8,  8,  8,  8,  8,  8,  8,  4,  4,  4,  4,  4,
+-    8,129,148,148,148,148,148,148,148,148,148,148,147,  8,  8,  8,
+-    8,  8,  8,  8,  4,  4,  8,  8,  8,  8,  8,  8,  8,  8,  4,  8,
+-    8,  8,144, 26,  8,  8,144, 67, 67, 67, 44, 67, 67, 67, 67, 67,
+-   67, 67, 67, 55, 67, 67, 67, 67, 32, 11, 32, 34, 34, 34, 34, 11,
+-   32, 32, 34, 16, 16, 16, 40, 11, 32, 32,140, 67, 67,138, 34,149,
+-   43, 32, 44, 44, 93,  2, 99,  2, 16, 16, 16,150, 44, 44,150, 44,
+-   36, 36, 36, 36, 44, 44, 44, 52, 64, 44, 44, 44, 44, 44, 44, 57,
+-   36, 36, 36, 61, 44, 44, 44, 44, 36, 36, 36, 61, 36, 36, 36, 61,
+-    2,121,121,  2,125,126,121,  2,  2,  2,  2,  6,  2,108,121,  2,
+-  121,  4,  4,  4,  4,  2,  2, 88,  2,  2,  2,  2,  2,120,  2,  2,
+-  108,151,  2,  2,  2,  2,  2,  2, 67,  2,152,148,148,148,153, 44,
+-   67, 67, 67, 67, 67, 55, 67, 67, 67, 67, 44, 44, 44, 44, 44, 44,
+-   67, 67, 67, 44, 44, 44, 44, 44,  1,  2,154,155,  4,  4,  4,  4,
+-    4, 67,  4,  4,  4,  4,156,157,158,105,105,105,105, 43, 43, 86,
+-  159, 40, 40, 67,105,160, 63, 67, 36, 36, 36, 61, 57,161,162, 69,
+-   36, 36, 36, 36, 36, 63, 40, 69, 44, 44, 62, 36, 36, 36, 36, 36,
+-   67, 27, 27, 67, 67, 67, 67, 67, 67, 67, 44, 44, 44, 44, 44, 55,
+-   67, 67, 67, 67, 67, 67, 67, 92, 27, 27, 27, 27, 27, 67, 67, 67,
+-   67, 67, 67, 67, 27, 27, 27, 27,163, 27, 27, 27, 27, 27, 27, 27,
+-   36, 36, 83, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,164,  2,
++    8, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 92, 44, 44,
++   27, 27, 27, 27, 27, 27, 67, 67, 67, 67, 67, 67, 67, 27, 27, 27,
++   67, 67, 67, 26, 67, 67, 67, 67, 26, 67, 67, 67, 67, 67, 67, 67,
++   67, 67, 67, 67,  8,  8,  8,  8, 67, 67, 67, 67, 67, 67, 67, 26,
++   67, 67, 67, 67,  4,  4,  4,  4,  4,  4,  4, 27, 27, 27, 27, 27,
++   27, 27, 67, 67, 67, 67, 67, 67,  8,  8,129,147,  8,  8,  8,  8,
++    8,  8,  8,  4,  4,  4,  4,  4,  8,129,148,148,148,148,148,148,
++  148,148,148,148,147,  8,  8,  8,  8,  8,  8,  8,  4,  4,  8,  8,
++    8,  8,  8,  8,  8,  8,  4,  8,  8,  8,144, 26,  8,  8,144, 67,
++   67, 67, 44, 67, 67, 67, 67, 67, 67, 67, 67, 55, 67, 67, 67, 67,
++   32, 11, 32, 34, 34, 34, 34, 11, 32, 32, 34, 16, 16, 16, 40, 11,
++   32, 32,140, 67, 67,138, 34,149, 43, 32, 44, 44, 93,  2, 99,  2,
++   16, 16, 16,150, 44, 44,150, 44, 36, 36, 36, 36, 44, 44, 44, 52,
++   64, 44, 44, 44, 44, 44, 44, 57, 36, 36, 36, 61, 44, 44, 44, 44,
++   36, 36, 36, 61, 36, 36, 36, 61,  2,121,121,  2,125,126,121,  2,
++    2,  2,  2,  6,  2,108,121,  2,121,  4,  4,  4,  4,  2,  2, 88,
++    2,  2,  2,  2,  2,120,  2,  2,108,151,  2,  2,  2,  2,  2,  2,
++   67,  2,152,148,148,148,153, 44, 67, 67, 67, 67, 67, 55, 67, 67,
++   67, 67, 44, 44, 44, 44, 44, 44, 67, 67, 67, 44, 44, 44, 44, 44,
++    1,  2,154,155,  4,  4,  4,  4,  4, 67,  4,  4,  4,  4,156,157,
++  158,105,105,105,105, 43, 43, 86,159, 40, 40, 67,105,160, 63, 67,
++   36, 36, 36, 61, 57,161,162, 69, 36, 36, 36, 36, 36, 63, 40, 69,
++   44, 44, 62, 36, 36, 36, 36, 36, 67, 27, 27, 67, 67, 67, 67, 67,
++   67, 67, 67, 44, 44, 44, 44, 55, 67, 67, 67, 67, 67, 67, 67, 92,
++   27, 27, 27, 27, 27, 67, 67, 67, 67, 67, 67, 67, 27, 27, 27, 27,
++  163, 27, 27, 27, 27, 27, 27, 27, 36, 36, 83, 36, 36, 36, 36, 36,
++   67, 67, 67, 92, 44, 44, 44, 44, 36, 36, 36, 36, 36, 36,164,  2,
+     7,  7,  7,  7,  7, 36, 44, 44, 32, 32, 32, 32, 32, 32, 32, 70,
+    51,165, 43, 43, 43, 43, 43, 88, 32, 32, 32, 32, 32, 32, 40, 43,
+    36, 36, 36,105,105,105,105,105, 43,  2,  2,  2, 44, 44, 44, 44,
+@@ -3092,7 +3123,7 @@ _hb_ucd_u8[14752] =
+    16, 32, 32, 32, 32, 32, 32, 32, 45, 16, 16, 16, 34, 34, 34, 32,
+    32, 32, 32, 32, 42,166, 34, 35, 32, 32, 16, 32, 32, 32, 32, 32,
+    32, 32, 32, 32, 32, 11, 11, 32, 11, 11, 32, 32, 32, 32, 32, 32,
+-   32, 32, 11, 11, 34,110, 44, 44, 32,150,150, 32, 32, 44, 44, 44,
++   32, 32, 11, 11, 34, 34, 32, 44, 32,150,150, 32, 32, 32, 47, 44,
+    44, 40,167, 35, 40, 35, 36, 36, 36, 71, 36, 71, 36, 70, 36, 36,
+    36, 94, 87, 85, 67, 67, 80, 44, 27, 27, 27, 67,168, 44, 44, 44,
+    36, 36,  2,  2, 44, 44, 44, 44, 86, 36, 36, 36, 36, 36, 36, 36,
+@@ -3153,8 +3184,10 @@ _hb_ucd_u8[14752] =
+    36, 61, 44, 44, 27, 27, 27, 27, 36, 44, 44, 44, 93,  2, 64, 44,
+    44, 44, 44, 44,179, 27, 27, 27, 11, 47, 44, 44, 44, 44, 44, 44,
+    16,110, 44, 44, 44, 27, 27, 27, 36, 36, 43, 43, 44, 44, 44, 44,
+-   27, 27, 27, 27, 27, 27, 27,100, 36, 36, 36, 36, 36, 57,184, 44,
+-   36, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 57, 43,
++    7,  7,  7,  7,  7, 36, 36, 69, 11, 11, 11, 44, 57, 43, 43,159,
++   16, 16, 16, 44, 44, 44, 44,  8, 27, 27, 27, 27, 27, 27, 27,100,
++   36, 36, 36, 36, 36, 57,184, 44, 36, 44, 44, 44, 44, 44, 44, 44,
++   44, 36, 61, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 43, 43,
+    27, 27, 27, 95, 44, 44, 44, 44,180, 27, 30,  2,  2, 44, 44, 44,
+    36, 43, 43,  2,  2, 44, 44, 44, 36, 36,183, 27, 27, 27, 44, 44,
+    87, 98, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 43, 43, 43, 43,
+@@ -3172,14 +3205,18 @@ _hb_ucd_u8[14752] =
+    86, 87, 43, 43, 43, 80, 44, 44, 43, 86, 62, 36, 36, 36, 61, 62,
+    61, 36, 62, 36, 36, 57, 71, 86, 85, 86, 90, 89, 90, 89, 86, 44,
+    61, 44, 44, 89, 44, 44, 62, 36, 36, 86, 44, 43, 43, 43, 80, 44,
+-   43, 43, 80, 44, 44, 44, 44, 44, 36, 36, 94, 86, 43, 43, 43, 43,
+-   86, 43, 85, 71, 36, 63,  2,  2,  7,  7,  7,  7,  7,  2, 93, 71,
+-   86, 87, 43, 43, 85, 85, 86, 87, 85, 43, 36, 72, 44, 44, 44, 44,
+-   36, 36, 36, 36, 36, 36, 36, 94, 86, 43, 43, 44, 86, 86, 43, 87,
+-   60,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 36, 36, 43, 44,
+-   86, 87, 43, 43, 43, 85, 87, 87, 60,  2, 61, 44, 44, 44, 44, 44,
+-    2,  2,  2,  2,  2,  2, 64, 44, 36, 36, 36, 36, 36, 70, 87, 86,
+-   43, 43, 43, 87, 63, 44, 44, 44, 86, 43, 43, 87, 43, 43, 44, 44,
++   43, 43, 80, 44, 44, 44, 44, 44, 36, 36, 36, 36, 36, 62, 44, 61,
++   36, 36, 36, 62, 86, 87, 43, 43, 80, 90, 89, 89, 86, 90, 86, 85,
++   71, 71,  2, 93, 64, 44, 44, 44, 57, 80, 44, 44, 44, 44, 44, 44,
++   36, 36, 94, 86, 43, 43, 43, 43, 86, 43, 85, 71, 36, 63,  2,  2,
++    7,  7,  7,  7,  7,  2, 93, 71, 86, 87, 43, 43, 85, 85, 86, 87,
++   85, 43, 36, 72, 44, 44, 44, 44, 36, 36, 36, 36, 36, 36, 36, 94,
++   86, 43, 43, 44, 86, 86, 43, 87, 60,  2,  2,  2,  2,  2,  2,  2,
++    2,  2,  2,  2, 36, 36, 43, 44, 86, 87, 43, 43, 43, 85, 87, 87,
++   60,  2, 61, 44, 44, 44, 44, 44,  2,  2,  2,  2,  2,  2, 64, 44,
++   36, 36, 36, 36, 36, 70, 87, 86, 43, 43, 43, 87, 63, 44, 44, 44,
++    7,  7,  7,  7,  7,  7,  7,  7,  7,  7, 44, 44, 44, 44, 44, 44,
++   36, 36, 36, 36, 36, 61, 57, 87, 86, 43, 43, 87, 43, 43, 44, 44,
+     7,  7,  7,  7,  7, 27,  2, 97, 43, 43, 43, 43, 87, 60, 44, 44,
+    27,100, 44, 44, 44, 44, 44, 62, 36, 36, 36, 61, 62, 44, 36, 36,
+    36, 36, 62, 61, 36, 36, 36, 36, 86, 86, 86, 89, 90, 57, 85, 71,
+@@ -3189,49 +3226,52 @@ _hb_ucd_u8[14752] =
+     2,  2,  2, 59, 44, 44, 44, 44, 70, 43, 43, 85, 87, 43, 36, 36,
+    36, 36, 36, 36, 36, 43, 43, 43, 43, 43, 43, 85, 43,  2, 72,  2,
+     2, 64, 44, 44, 44, 44, 44, 44,  2,  2,  2,  2,  2, 44, 44, 44,
+-   43, 43, 43, 80, 43, 43, 43, 87, 63,  2,  2, 44, 44, 44, 44, 44,
+-    2, 36, 36, 36, 36, 36, 36, 36, 44, 43, 43, 43, 43, 43, 43, 43,
+-   43, 43, 43, 43, 89, 43, 43, 43, 85, 43, 87, 80, 44, 44, 44, 44,
+-   36, 36, 36, 61, 36, 62, 36, 36, 70, 43, 43, 80, 44, 80, 43, 57,
+-   43, 43, 43, 70, 44, 44, 44, 44, 36, 36, 36, 62, 61, 36, 36, 36,
+-   36, 36, 36, 36, 36, 86, 86, 90, 43, 89, 87, 87, 61, 44, 44, 44,
+-   36, 70, 85,107, 64, 44, 44, 44, 43, 94, 36, 36, 36, 36, 36, 36,
+-   36, 36, 86, 43, 43, 80, 44, 86, 85, 60,  2,  2,  2,  2,  2,  2,
++   63, 44, 44, 44, 44, 44, 44, 44, 43, 43, 43, 80, 43, 43, 43, 87,
++   63,  2,  2, 44, 44, 44, 44, 44,  2, 36, 36, 36, 36, 36, 36, 36,
++   44, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 89, 43, 43, 43,
++   85, 43, 87, 80, 44, 44, 44, 44, 36, 36, 36, 61, 36, 62, 36, 36,
++   70, 43, 43, 80, 44, 80, 43, 57, 43, 43, 43, 70, 44, 44, 44, 44,
++   36, 36, 36, 62, 61, 36, 36, 36, 36, 36, 36, 36, 36, 86, 86, 90,
++   43, 89, 87, 87, 61, 44, 44, 44, 36, 70, 85,107, 64, 44, 44, 44,
++   43, 94, 36, 36, 36, 36, 36, 36, 36, 36, 86, 43, 43, 80, 44, 86,
++   85, 60,  2,  2,  2,  2,  2,  2,  7,  7,  7,  7,  7, 80, 44, 44,
+    27, 27, 91, 67, 67, 67, 56, 20,168, 67, 67, 67, 67, 67, 67, 67,
+    67, 44, 44, 44, 44, 44, 44, 93,105,105,105,105,105,105,105,181,
+     2,  2, 64, 44, 44, 44, 44, 44, 63, 64, 44, 44, 44, 44, 44, 44,
+    65, 65, 65, 65, 65, 65, 65, 65, 71, 36, 36, 70, 43, 43, 43, 43,
+-   43, 43, 43, 44, 44, 44, 44, 44, 43, 43, 60, 44, 44, 44, 44, 44,
++   43, 43, 43, 44, 44, 44, 44, 44, 36, 36, 36, 36, 36, 36, 36, 43,
++   43, 43, 43, 43, 43, 86, 87, 43, 43, 43, 60, 44, 44, 44, 44, 44,
+    43, 43, 43, 60,  2,  2, 67, 67, 40, 40, 97, 44, 44, 44, 44, 44,
+     7,  7,  7,  7,  7,179, 27, 27, 27, 62, 36, 36, 36, 36, 36, 36,
+-   36, 36, 36, 36, 44, 44, 62, 36, 27, 27, 27, 30,  2, 64, 44, 44,
++   36, 36, 36, 36, 44, 44, 62, 36, 40, 69, 36, 36, 36, 36, 36, 36,
++   36, 36, 36, 36, 36, 83,164,  2, 27, 27, 27, 30,  2, 64, 44, 44,
+    36, 36, 36, 36, 36, 61, 44, 57, 94, 86, 86, 86, 86, 86, 86, 86,
+    86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 44, 44, 44, 57,
+    43, 74, 40, 40, 40, 40, 40, 40, 40, 88, 80, 44, 44, 44, 44, 44,
+-   86, 44, 44, 44, 44, 44, 44, 44, 40, 40, 52, 40, 40, 40, 52, 81,
+-   36, 61, 44, 44, 44, 44, 44, 44, 44, 61, 44, 44, 44, 44, 44, 44,
+-   36, 61, 62, 44, 44, 44, 44, 44, 44, 44, 36, 36, 44, 44, 44, 44,
+-   36, 36, 36, 36, 36, 44, 50, 60, 65, 65, 44, 44, 44, 44, 44, 44,
+-   43, 43, 43, 43, 43, 43, 43, 44, 43, 43, 43, 80, 44, 44, 44, 44,
+-   67, 67, 67, 92, 55, 67, 67, 67, 67, 67,186, 87, 43, 67,186, 86,
+-   86,187, 65, 65, 65, 84, 43, 43, 43, 76, 50, 43, 43, 43, 67, 67,
+-   67, 67, 67, 67, 67, 43, 43, 67, 67, 43, 76, 44, 44, 44, 44, 44,
+-   27, 27, 44, 44, 44, 44, 44, 44, 11, 11, 11, 11, 11, 16, 16, 16,
+-   16, 16, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 16,
+-   16, 16,110, 16, 16, 16, 16, 16, 11, 16, 16, 16, 16, 16, 16, 16,
+-   16, 16, 16, 16, 16, 16, 47, 11, 44, 47, 48, 47, 48, 11, 47, 11,
+-   11, 11, 11, 16, 16,150,150, 16, 16, 16,150, 16, 16, 16, 16, 16,
+-   16, 16, 11, 48, 11, 47, 48, 11, 11, 11, 47, 11, 11, 11, 47, 16,
+-   16, 16, 16, 16, 11, 48, 11, 47, 11, 11, 47, 47, 44, 11, 11, 11,
+-   47, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 11, 11,
+-   11, 11, 11, 16, 16, 16, 16, 16, 16, 16, 16, 44, 11, 11, 11, 11,
+-   31, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 33, 16, 16,
+-   16, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 31, 16, 16,
+-   16, 16, 33, 16, 16, 16, 11, 11, 11, 11, 31, 16, 16, 16, 16, 16,
+-   16, 16, 16, 16, 16, 16, 16, 33, 16, 16, 16, 11, 11, 11, 11, 11,
+-   11, 11, 11, 11, 11, 11, 11, 31, 16, 16, 16, 16, 33, 16, 16, 16,
+-   11, 11, 11, 11, 31, 16, 16, 16, 16, 33, 16, 16, 16, 32, 44,  7,
+-    7,  7,  7,  7,  7,  7,  7,  7, 43, 43, 43, 76, 67, 50, 43, 43,
++   86, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 62,
++   40, 40, 52, 40, 40, 40, 52, 81, 36, 61, 44, 44, 44, 44, 44, 44,
++   44, 61, 44, 44, 44, 44, 44, 44, 36, 61, 62, 44, 44, 44, 44, 44,
++   44, 44, 36, 36, 44, 44, 44, 44, 36, 36, 36, 36, 36, 44, 50, 60,
++   65, 65, 44, 44, 44, 44, 44, 44, 43, 43, 43, 43, 43, 43, 43, 44,
++   43, 43, 43, 80, 44, 44, 44, 44, 67, 67, 67, 92, 55, 67, 67, 67,
++   67, 67,186, 87, 43, 67,186, 86, 86,187, 65, 65, 65, 84, 43, 43,
++   43, 76, 50, 43, 43, 43, 67, 67, 67, 67, 67, 67, 67, 43, 43, 67,
++   67, 43, 76, 44, 44, 44, 44, 44, 27, 27, 44, 44, 44, 44, 44, 44,
++   11, 11, 11, 11, 11, 16, 16, 16, 16, 16, 11, 11, 11, 11, 11, 11,
++   11, 11, 11, 11, 11, 11, 11, 16, 16, 16,110, 16, 16, 16, 16, 16,
++   11, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 47, 11,
++   44, 47, 48, 47, 48, 11, 47, 11, 11, 11, 11, 16, 16,150,150, 16,
++   16, 16,150, 16, 16, 16, 16, 16, 16, 16, 11, 48, 11, 47, 48, 11,
++   11, 11, 47, 11, 11, 11, 47, 16, 16, 16, 16, 16, 11, 48, 11, 47,
++   11, 11, 47, 47, 44, 11, 11, 11, 47, 16, 16, 16, 16, 16, 16, 16,
++   16, 16, 16, 16, 16, 16, 11, 11, 11, 11, 11, 16, 16, 16, 16, 16,
++   16, 16, 16, 44, 11, 11, 11, 11, 31, 16, 16, 16, 16, 16, 16, 16,
++   16, 16, 16, 16, 16, 33, 16, 16, 16, 11, 11, 11, 11, 11, 11, 11,
++   11, 11, 11, 11, 11, 31, 16, 16, 16, 16, 33, 16, 16, 16, 11, 11,
++   11, 11, 31, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 33,
++   16, 16, 16, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 31,
++   16, 16, 16, 16, 33, 16, 16, 16, 11, 11, 11, 11, 31, 16, 16, 16,
++   16, 33, 16, 16, 16, 32, 44,  7, 43, 43, 43, 76, 67, 50, 43, 43,
+    43, 43, 43, 43, 43, 43, 76, 67, 67, 67, 50, 67, 67, 67, 67, 67,
+    67, 67, 76, 21,  2,  2, 44, 44, 44, 44, 44, 44, 44, 57, 43, 43,
+    16, 16, 16, 16, 16, 39, 16, 16, 16, 16, 16, 16, 16, 16, 16,110,
+@@ -3241,22 +3281,23 @@ _hb_ucd_u8[14752] =
+    43, 43, 43, 74, 40, 40, 40, 44,  7,  7,  7,  7,  7, 44, 44, 77,
+    36, 36, 36, 36, 36, 36, 36, 80, 36, 36, 36, 36, 36, 36, 43, 43,
+     7,  7,  7,  7,  7, 44, 44, 96, 36, 36, 36, 36, 36, 83, 43, 43,
+-   36, 36, 36, 61, 36, 36, 62, 61, 36, 36, 61,179, 27, 27, 27, 27,
+-   16, 16, 43, 43, 43, 74, 44, 44, 27, 27, 27, 27, 27, 27,163, 27,
+-  188, 27,100, 44, 44, 44, 44, 44, 27, 27, 27, 27, 27, 27, 27,163,
+-   27, 27, 27, 27, 27, 27, 27, 44, 36, 36, 62, 36, 36, 36, 36, 36,
+-   62, 61, 61, 62, 62, 36, 36, 36, 36, 61, 36, 36, 62, 62, 44, 44,
+-   44, 61, 44, 62, 62, 62, 62, 36, 62, 61, 61, 62, 62, 62, 62, 62,
+-   62, 61, 61, 62, 36, 61, 36, 36, 36, 61, 36, 36, 62, 36, 61, 61,
+-   36, 36, 36, 36, 36, 62, 36, 36, 62, 36, 62, 36, 36, 62, 36, 36,
+-    8, 44, 44, 44, 44, 44, 44, 44, 67, 67, 67, 67, 67, 67, 44, 44,
+-   55, 67, 67, 67, 67, 67, 67, 67, 27, 27, 27, 27, 27, 27, 91, 67,
+-   67, 67, 67, 67, 67, 67, 67, 44, 44, 44, 44, 67, 67, 67, 67, 67,
+-   67, 92, 44, 44, 44, 44, 44, 44, 67, 67, 67, 67, 92, 44, 44, 44,
+-   67, 44, 44, 44, 44, 44, 44, 44, 67, 67, 67, 67, 67, 25, 41, 41,
+-   67, 67, 67, 67, 44, 44, 67, 67, 67, 67, 67, 92, 44, 55, 67, 67,
+-   67, 67, 67, 67, 44, 44, 44, 44, 67, 67, 67, 67, 67, 67, 67, 55,
+-   67, 67, 67, 44, 44, 44, 44, 67, 67, 92, 67, 67, 67, 67, 67, 67,
++  188,  7,  7,  7,  7,189, 44, 93, 36, 36, 36, 61, 36, 36, 62, 61,
++   36, 36, 61,179, 27, 27, 27, 27, 16, 16, 43, 43, 43, 74, 44, 44,
++   27, 27, 27, 27, 27, 27,163, 27,190, 27,100, 44, 44, 44, 44, 44,
++   27, 27, 27, 27, 27, 27, 27,163, 27, 27, 27, 27, 27, 27, 27, 44,
++   36, 36, 62, 36, 36, 36, 36, 36, 62, 61, 61, 62, 62, 36, 36, 36,
++   36, 61, 36, 36, 62, 62, 44, 44, 44, 61, 44, 62, 62, 62, 62, 36,
++   62, 61, 61, 62, 62, 62, 62, 62, 62, 61, 61, 62, 36, 61, 36, 36,
++   36, 61, 36, 36, 62, 36, 61, 61, 36, 36, 36, 36, 36, 62, 36, 36,
++   62, 36, 62, 36, 36, 62, 36, 36,  8, 44, 44, 44, 44, 44, 44, 44,
++   67, 67, 67, 67, 67, 67, 44, 44, 55, 67, 67, 67, 67, 67, 67, 67,
++   27, 27, 27, 27, 27, 27, 91, 67, 67, 67, 67, 67, 67, 67, 67, 44,
++   44, 44, 44, 67, 67, 67, 67, 67, 67, 92, 44, 44, 44, 44, 44, 44,
++   67, 67, 67, 67, 92, 44, 44, 44, 67, 44, 44, 44, 44, 44, 44, 44,
++   67, 67, 67, 67, 67, 25, 41, 41, 67, 67, 67, 67, 44, 44, 67, 67,
++   67, 67, 67, 92, 44, 55, 67, 67, 67, 67, 67, 67, 44, 44, 44, 44,
++   67, 67, 67, 67, 67, 44, 44, 55, 67, 67, 67, 92, 44, 44, 44, 67,
++   67, 67, 67, 67, 67, 67, 92, 55, 67, 92, 67, 67, 67, 67, 67, 67,
+    79, 44, 44, 44, 44, 44, 44, 44,171,171,171,171,171,171,171, 44,
+   171,171,171,171,171,171,171,  0,  0,  0, 29, 21, 21, 21, 23, 21,
+    22, 18, 21, 25, 21, 17, 13, 13, 25, 25, 25, 21, 21,  9,  9,  9,
+@@ -3282,420 +3323,609 @@ _hb_ucd_u8[14752] =
+     6, 21, 11, 21, 24,  9,  6,  9, 23, 26,  6, 10,  4,  4,  3,  3,
+     7, 25, 17, 16, 16, 22, 16, 16, 25, 17, 25,  2, 25, 24,  2, 15,
+    12, 15, 14,  2, 21, 14,  7, 15, 12, 17, 21,  1, 26, 10, 10,  1,
+-   23, 15,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  0, 10, 11, 12,
+-   13,  0, 14,  0,  0,  0,  0,  0, 15,  0, 16,  0,  0,  0,  0,  0,
++    7, 13, 13,  2, 23, 15,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9,
++    0, 10, 11, 12, 13,  0, 14,  0,  0,  0,  0,  0, 15,  0, 16,  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,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+-    0,  0,  0,  0,  0, 17, 18, 19,  0,  0,  0,  0,  0,  0,  0,  0,
++    0,  0,  0,  0,  0,  0,  0,  0,  0, 17, 18, 19,  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, 20,
+-    0, 21, 22, 23,  0,  0,  0, 24, 25, 26, 27, 28, 29, 30, 31, 32,
+-   33, 34,  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, 35,  0, 36,  0,  0,  0,  0,  0,  0,
++    0,  0,  0, 20,  0, 21, 22, 23,  0,  0,  0, 24, 25, 26, 27, 28,
++   29, 30, 31, 32, 33, 34,  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, 35,  0,  0,  0,  0, 36,  0, 37,  0,  0,
+     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+-   37,  0,  0,  0,  0,  0,  0,  0,  0,  0, 38, 39,  0,  0,  0,  0,
+-    0,  0, 40, 41, 42,  0, 43,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+-    0,  0,  0,  0,  1,  2,  0,  0,  0,  0,  3,  0,  0,  0,  4,  5,
+-    6,  7,  0,  8,  9, 10,  0, 11, 12, 13, 14, 15, 16, 17, 16, 18,
+-   16, 19, 16, 19, 16, 19,  0, 19, 16, 20, 16, 19, 21, 19,  0, 22,
+-   23, 24, 25, 26, 27, 28, 29, 30, 31,  0, 32,  0,  0,  0,  0,  0,
+-    0,  0,  0,  0,  0, 33,  0,  0,  0,  0,  0,  0, 34,  0,  0, 35,
+-    0,  0, 36,  0, 37,  0,  0,  0, 38, 39, 40, 41, 42, 43, 44, 45,
+-   46,  0,  0, 47,  0,  0,  0, 48,  0,  0,  0, 49,  0,  0,  0,  0,
+-    0,  0,  0, 50,  0, 51,  0, 52, 53,  0, 54,  0,  0,  0,  0,  0,
+-    0, 55, 56, 57,  0,  0,  0,  0, 58,  0,  0, 59, 60, 61, 62, 63,
+-    0,  0, 64, 65,  0,  0,  0, 66,  0,  0,  0,  0, 67,  0,  0,  0,
+-   68,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 69,
+-    0,  0,  0, 70,  0, 71,  0,  0, 72,  0,  0, 73,  0,  0,  0,  0,
+-    0,  0,  0,  0, 74,  0,  0,  0,  0,  0, 75, 76,  0, 77, 78,  0,
+-    0, 79, 80,  0, 81, 62,  0, 82, 83,  0,  0, 84, 85, 86,  0,  0,
+-    0, 87,  0, 88,  0,  0, 51, 89, 51,  0, 90,  0, 91,  0,  0,  0,
+-   80,  0,  0,  0, 92, 93,  0, 94, 95, 96, 97,  0,  0,  0,  0,  0,
+-   51,  0,  0,  0,  0, 98, 99,  0,  0,  0,  0,  0,  0,100,  0,  0,
+-    0,  0,  0,101,102,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,103,
+-    0,  0,104,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,105,106,  0,
+-    0,107,  0,  0,  0,  0,  0,  0,108,  0,109,  0,102,  0,  0,  0,
+-    0,  0,110,111,  0,  0,  0,  0,  0,  0,  0,112,  0,  0,  0,  0,
+-    0,  0,  0,113,  0,114,  0,  0,  0,  0,  0,  0,  1,  2,  3,  4,
+-    5,  6,  7,  0,  8,  0,  0,  0,  0,  9, 10, 11, 12,  0,  0,  0,
+-    0, 13,  0,  0, 14, 15,  0, 16,  0, 17, 18,  0,  0, 19,  0, 20,
+-   21,  0,  0,  0,  0,  0, 22, 23,  0, 24, 25,  0,  0, 26,  0,  0,
+-    0, 27,  0,  0, 28, 29, 30, 31,  0,  0,  0, 32, 33, 34,  0,  0,
+-   33,  0,  0, 35, 33,  0,  0,  0, 33, 36,  0,  0,  0,  0,  0, 37,
+-   38,  0,  0,  0,  0,  0,  0, 39, 40,  0,  0,  0,  0,  0,  0, 41,
+-   42,  0,  0,  0,  0, 43,  0, 44,  0,  0,  0, 45, 46,  0,  0,  0,
+-   47,  0,  0,  0,  0,  0,  0, 48, 49,  0,  0,  0,  0, 50,  0,  0,
+-    0, 51,  0, 52,  0, 53,  0,  0,  0,  0, 54,  0,  0,  0,  0, 55,
+-    0, 56,  0,  0,  0,  0, 57, 58,  0,  0,  0, 59, 60,  0,  0,  0,
+-    0,  0,  0, 61, 52,  0, 62, 63,  0,  0, 64,  0,  0,  0, 65, 66,
+-    0,  0,  0, 67,  0, 68, 69, 70, 71, 72,  1, 73,  0, 74, 75, 76,
+-    0,  0, 77, 78,  0,  0,  0, 79,  0,  0,  1,  1,  0,  0, 80,  0,
+-    0, 81,  0,  0,  0,  0, 77, 82,  0, 83,  0,  0,  0,  0,  0, 78,
+-   84,  0, 85,  0, 52,  0,  1, 78,  0,  0, 86,  0,  0, 87,  0,  0,
+-    0,  0,  0, 88, 57,  0,  0,  0,  0,  0,  0, 89, 90,  0,  0, 84,
+-    0,  0, 33,  0,  0, 91,  0,  0,  0,  0, 92,  0,  0,  0,  0, 49,
+-    0,  0, 93,  0,  0,  0,  0, 94, 95,  0,  0, 96,  0,  0, 97,  0,
+-    0,  0, 98,  0,  0,  0, 99,  0,  0,  0,  0,100,101, 93,  0,  0,
+-  102,  0,  0,  0, 84,  0,  0,103,  0,  0,  0,104,105,  0,  0,106,
+-  107,  0,  0,  0,  0,  0,  0,108,  0,  0,109,  0,  0,  0,  0,110,
+-   33,  0,111,112,113, 35,  0,  0,114,  0,  0,  0,115,  0,  0,  0,
+-    0,  0,  0,116,  0,  0,117,  0,  0,  0,  0,118, 88,  0,  0,  0,
+-    0,  0, 57,  0,  0,  0,  0, 52,119,  0,  0,  0,  0,120,  0,  0,
+-  121,  0,  0,  0,  0,119,  0,  0,122,  0,  0,  0,  0,  0,  0,123,
+-    0,  0,  0,124,  0,  0,  0,125,  0,126,  0,  0,  0,  0,127,128,
+-  129,  0,130,  0,131,  0,  0,  0,132,133,134,  0, 77,  0,  0,  0,
+-    0,  0, 35,  0,  0,  0,135,  0,  0,  0,136,  0,  0,137,  0,  0,
+-  138,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1,  2,  3,  4,
+-    5,  6,  7,  4,  4,  8,  9, 10,  1, 11, 12, 13, 14, 15, 16, 17,
+-   18,  1,  1,  1, 19,  1,  0,  0, 20, 21, 22,  1, 23,  4, 21, 24,
+-   25, 26, 27, 28, 29, 30,  0,  0,  1,  1, 31,  0,  0,  0, 32, 33,
+-   34, 35,  1, 36, 37,  0,  0,  0,  0, 38,  1, 39, 14, 39, 40, 41,
+-   42,  0,  0,  0, 43, 36, 44, 45, 21, 45, 46,  0,  0,  0, 19,  1,
+-   21,  0,  0, 47,  0, 38, 48,  1,  1, 49, 49, 50,  0,  0, 51,  0,
+-    0,  0, 52,  1,  0,  0, 38, 14,  4,  1,  1,  1, 53, 21, 43, 52,
+-   54, 21, 35,  1,  0,  0,  0, 55,  0,  0,  0, 56, 57, 58,  0,  0,
+-    0,  0,  0, 59,  0, 60,  0,  0,  0,  0, 61, 62,  0,  0, 63,  0,
+-    0,  0, 64,  0,  0,  0, 65,  0,  0,  0, 66,  0,  0,  0, 67,  0,
+-    0,  0, 68,  0,  0, 69, 70,  0, 71, 72, 73, 74, 75, 76,  0,  0,
+-    0, 77,  0,  0,  0, 78, 79,  0,  0,  0,  0, 47,  0,  0,  0, 49,
+-    0, 80,  0,  0,  0, 62,  0,  0, 63,  0,  0, 81,  0,  0, 82,  0,
+-    0,  0, 83,  0,  0, 19, 84,  0, 62,  0,  0,  0,  0, 49,  1, 85,
+-    1, 52, 15, 86, 36, 10, 21, 87,  0, 55,  0,  0,  0,  0, 19, 10,
+-    1,  0,  0,  0,  0,  0, 88,  0,  0, 89,  0,  0, 88,  0,  0,  0,
+-    0, 78,  0,  0, 87,  9, 12,  4, 90,  8, 91, 47,  0, 58, 50,  0,
+-   21,  1, 21, 92, 93,  1,  1,  1,  1, 94, 95, 96, 97,  1, 98, 58,
+-   81, 99,100,  4, 58,  0,  0,  0,  0,  0,  0, 19, 50,  0,  0,  0,
+-    0,  0,  0, 61,  0,  0,101,102,  0,  0,103,  0,  0,  1,  1, 50,
+-    0,  0,  0, 38,  0, 63,  0,  0,  0,  0,  0, 62,  0,  0,104, 68,
+-   61,  0,  0,  0, 78,  0,  0,  0,105,106, 58, 38, 81,  0,  0,  0,
+-    0,  0,  0,107,  1, 14,  4, 12, 84,  0,  0,  0,  0, 38, 87,  0,
+-    0,  0,  0,108,  0,  0,109, 61,  0,110,  0,  0,  0,  1,  0,  0,
++    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
++    0,  0,  0,  0, 38,  0,  0,  0,  0,  0,  0,  0,  0,  0, 39, 40,
++    0,  0,  0,  0,  0,  0, 41, 42, 43,  0, 44,  0,  0,  0,  0,  0,
++    0,  0,  0,  0,  0,  0,  0,  0,  1,  2,  0,  0,  0,  0,  3,  0,
++    0,  0,  4,  5,  6,  7,  0,  8,  9, 10,  0, 11, 12, 13, 14, 15,
++   16, 17, 16, 18, 16, 19, 16, 19, 16, 19,  0, 19, 16, 20, 16, 19,
++   21, 19,  0, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,  0, 32,  0,
++    0,  0,  0,  0,  0,  0,  0,  0,  0, 33,  0,  0,  0,  0,  0,  0,
++   34,  0,  0, 35,  0,  0, 36,  0, 37,  0,  0,  0, 38, 39, 40, 41,
++   42, 43, 44, 45, 46,  0,  0, 47,  0,  0,  0, 48,  0,  0,  0, 49,
++    0,  0,  0,  0,  0,  0,  0, 50,  0, 51,  0, 52, 53,  0, 54,  0,
++    0,  0,  0,  0,  0, 55, 56, 57,  0,  0,  0,  0, 58,  0,  0, 59,
++   60, 61, 62, 63,  0,  0, 64, 65,  0,  0,  0, 66,  0,  0,  0,  0,
++   67,  0,  0,  0, 68,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
++    0,  0,  0, 69,  0,  0,  0, 70,  0, 71,  0,  0, 72,  0,  0, 73,
++    0,  0,  0,  0,  0,  0,  0,  0, 74, 75,  0,  0,  0,  0, 76, 77,
++    0, 78, 79,  0,  0, 80, 81,  0, 82, 62,  0, 83, 84,  0,  0, 85,
++   86, 87,  0, 88,  0, 89,  0, 90,  0,  0, 51, 91, 51,  0, 92,  0,
++   93,  0,  0,  0, 81,  0,  0,  0, 94, 95,  0, 96, 97, 98, 99,  0,
++    0,  0,  0,  0, 51,  0,  0,  0,  0,100,101,  0,  0,  0,  0,  0,
++    0,102,  0,  0,  0,  0,  0,  0,103,  0,  0,  0,  0,  0,  0,104,
++  105,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,106,  0,  0,107,  0,
++    0,  0,  0,  0,  0,  0,  0,  0,  0,108,109,  0,  0,110,  0,  0,
++    0,  0,  0,  0,111,  0,112,  0,105,  0,  0,  0,  0,  0,113,114,
++    0,  0,  0,  0,  0,  0,  0,115,  0,  0,  0,116,  0,  0,  0,117,
++    0,118,  0,  0,  0,  0,  0,  0,  1,  2,  3,  4,  5,  6,  7,  0,
++    8,  0,  0,  0,  0,  9, 10, 11, 12,  0,  0,  0,  0, 13,  0,  0,
++   14, 15,  0, 16,  0, 17, 18,  0,  0, 19,  0, 20, 21,  0,  0,  0,
++    0,  0, 22, 23,  0, 24, 25,  0,  0, 26,  0,  0,  0, 27,  0,  0,
++   28, 29, 30, 31,  0,  0,  0, 32, 33, 34,  0,  0, 33,  0,  0, 35,
++   33,  0,  0,  0, 33, 36,  0,  0,  0,  0,  0, 37, 38,  0,  0,  0,
++    0,  0,  0, 39, 40,  0,  0,  0,  0,  0,  0, 41, 42,  0,  0,  0,
++    0, 43,  0, 44,  0,  0,  0, 45, 46,  0,  0,  0, 47,  0,  0,  0,
++    0,  0,  0, 48, 49,  0,  0,  0,  0, 50,  0,  0,  0, 51,  0, 52,
++    0, 53,  0,  0,  0,  0, 54,  0,  0,  0,  0, 55,  0, 56,  0,  0,
++    0,  0, 57, 58,  0,  0,  0, 59, 60,  0,  0,  0,  0,  0,  0, 61,
++   52,  0, 62, 63,  0,  0, 64,  0,  0,  0, 65, 66,  0,  0,  0, 67,
++    0, 68, 69, 70, 71, 72,  1, 73,  0, 74, 75, 76,  0,  0, 77, 78,
++    0,  0,  0, 79,  0,  0,  1,  1,  0,  0, 80,  0,  0, 81,  0,  0,
++    0,  0, 77, 82,  0, 83,  0,  0,  0,  0,  0, 78, 84,  0, 85,  0,
++   52,  0,  1, 78,  0,  0, 86,  0,  0, 87,  0,  0,  0,  0,  0, 88,
++   57,  0,  0,  0,  0,  0,  0, 89, 90,  0,  0, 84,  0,  0, 33,  0,
++    0, 91,  0,  0,  0,  0, 92,  0,  0,  0,  0, 49,  0,  0, 93,  0,
++    0,  0,  0, 94, 95,  0,  0, 96,  0,  0, 97,  0,  0,  0, 98,  0,
++    0,  0, 99,  0,  0,  0,100,  0,  0,  0,  0,101,102, 93,  0,  0,
++  103,  0,  0,  0, 84,  0,  0,104,  0,  0,  0,105,106,  0,  0,107,
++  108,  0,  0,  0,  0,  0,  0,109,  0,  0,110,  0,  0,  0,  0,111,
++   33,  0,112,113,114, 57,  0,  0,115, 35,  0,  0,116,  0,  0,  0,
++  117,  0,  0,  0,  0,  0,  0,118,  0,  0,119,  0,  0,  0,  0,120,
++   88,  0,  0,  0,  0,  0, 57,  0,  0,  0,  0, 52,121,  0,  0,  0,
++    0,122,  0,  0,123,  0,  0,  0,  0,121,  0,  0,124,  0,  0,  0,
++    0,  0, 79,  0,  0,  0,  0,125,  0,  0,  0,126,  0,  0,  0,127,
++    0,128,  0,  0,  0,  0,129,130,131,  0,132,  0,133,  0,  0,  0,
++  134,135,136,  0, 77,  0,  0,  0,  0,  0, 35,  0,  0,  0,137,  0,
++    0,  0,138,  0,  0,  0,139,  0,  0,140,  0,  0,141,  0,  0,  0,
++    0,  0,  0,  0,  1,  1,  1,  1,  1,  2,  3,  4,  5,  6,  7,  4,
++    4,  8,  9, 10,  1, 11, 12, 13, 14, 15, 16, 17, 18,  1,  1,  1,
++   19,  1,  0,  0, 20, 21, 22,  1, 23,  4, 21, 24, 25, 26, 27, 28,
++   29, 30,  0,  0,  1,  1, 31,  0,  0,  0, 32, 33, 34, 35,  1, 36,
++   37,  0,  0,  0,  0, 38,  1, 39, 14, 39, 40, 41, 42,  0,  0,  0,
++   43, 36, 44, 45, 21, 45, 46,  0,  0,  0, 19,  1, 21,  0,  0, 47,
++    0, 38, 48,  1,  1, 49, 49, 50,  0,  0, 51,  0,  0, 19, 52,  1,
++    0,  0, 38, 14,  4,  1,  1,  1, 53, 21, 43, 52, 54, 21, 35,  1,
++    0,  0,  0, 55,  0,  0,  0, 56, 57, 58,  0,  0,  0,  0,  0, 59,
++    0, 60,  0,  0,  0,  0, 61, 62,  0,  0, 63,  0,  0,  0, 64,  0,
++    0,  0, 65,  0,  0,  0, 66,  0,  0,  0, 67,  0,  0,  0, 68,  0,
++    0, 69, 70,  0, 71, 72, 73, 74, 75, 76,  0,  0,  0, 77,  0,  0,
++    0, 78, 79,  0,  0,  0,  0, 47,  0,  0,  0, 49,  0, 80,  0,  0,
++    0, 62,  0,  0, 63,  0,  0, 81,  0,  0, 82,  0,  0,  0, 83,  0,
++    0, 19, 84,  0, 62,  0,  0,  0,  0, 49,  1, 85,  1, 52, 15, 86,
++   36, 10, 21, 87,  0, 55,  0,  0,  0,  0, 19, 10,  1,  0,  0,  0,
++    0,  0, 88,  0,  0, 89,  0,  0, 88,  0,  0,  0,  0, 78,  0,  0,
++   87,  9, 12,  4, 90,  8, 91, 47,  0, 58, 50,  0, 21,  1, 21, 92,
++   93,  1,  1,  1,  1, 94, 95, 96, 97,  1, 98, 58, 81, 99,100,  4,
++   58,  0,  0,  0,  0,  0,  0, 19, 50,  0,  0,  0,  0,  0,  0, 61,
++    0,  0,101,102,  0,  0,103,  0,  0,  1,  1, 50,  0,  0,  0, 38,
++    0, 63,  0,  0,  0,  0,  0, 62,  0,  0,104, 68, 61,  0,  0,  0,
++   78,  0,  0,  0,105,106, 58, 38, 81,  0,  0,  0,  0,  0,  0,107,
++    1, 14,  4, 12, 84,  0,  0,  0,  0, 38, 87,  0,  0,  0,  0,108,
++    0,  0,109, 61,  0,110,  0,  0,  0,  1,  0,  0,  0,  0, 49, 50,
+     0,  0, 19, 58,  0,  0,  0, 51,  0,111, 14, 52,112, 41,  0,  0,
+    62,  0,  0, 61,  0,  0,113,  0, 87,  0,  0,  0, 61, 62,  0,  0,
+    62,  0, 89,  0,  0,113,  0,  0,  0,  0,114,  0,  0,  0, 78, 55,
+-    0, 38,  1, 58,  1, 58,  0,  0, 63, 89,  0,  0,115,  0,  0,  0,
+-   55,  0,  0,  0,  0,115,  0,  0,  0,  0, 61,  0,  0,  0,  0, 79,
+-    0, 61,  0,  0,  0,  0, 56,  0, 89, 80,  0,  0, 79,  0,  0,  0,
+-    8, 91,  0,  0,  1, 87,  0,  0,116,  0,  0,  0,  0,  0,  0,117,
+-    0,118,119,120,121,  0,104,  4,122, 49, 23,  0,  0,  0, 38, 50,
+-   38, 58,  0,  0,  1, 87,  1,  1,  1,  1, 39,  1, 48,105, 87,  0,
+-    0,  0,  0,  1,  0,  0,  0,123,  4,122,  0,  0,  0,  1,124,  0,
+-    0,  0,  0,  0,230,230,230,230,230,232,220,220,220,220,232,216,
+-  220,220,220,220,220,202,202,220,220,220,220,202,202,220,220,220,
+-    1,  1,  1,  1,  1,220,220,220,220,230,230,230,230,240,230,220,
+-  220,220,230,230,230,220,220,  0,230,230,230,220,220,220,220,230,
+-  232,220,220,230,233,234,234,233,234,234,233,230,  0,  0,  0,230,
+-    0,220,230,230,230,230,220,230,230,230,222,220,230,230,220,220,
+-  230,222,228,230, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20,
+-   21, 22,  0, 23,  0, 24, 25,  0,230,220,  0, 18, 30, 31, 32,  0,
+-    0,  0,  0, 27, 28, 29, 30, 31, 32, 33, 34,230,230,220,220,230,
+-  220,230,230,220, 35,  0,  0,  0,  0,  0,230,230,230,  0,  0,230,
+-  230,  0,220,230,230,220,  0,  0,  0, 36,  0,  0,230,220,230,230,
+-  220,220,230,220,220,230,220,230,220,230,230,  0,  0,220,  0,  0,
+-  230,230,  0,230,  0,230,230,230,230,230,  0,  0,  0,220,220,220,
+-  230,220,220,220,230,230,  0,220, 27, 28, 29,230,  7,  0,  0,  0,
+-    0,  9,  0,  0,  0,230,220,230,230,  0,  0,  0,  0,  0,230,  0,
+-    0, 84, 91,  0,  0,  0,  0,  9,  9,  0,  0,  0,  0,  0,  9,  0,
+-  103,103,  9,  0,107,107,107,107,118,118,  9,  0,122,122,122,122,
+-  220,220,  0,  0,  0,220,  0,220,  0,216,  0,  0,  0,129,130,  0,
+-  132,  0,  0,  0,  0,  0,130,130,130,130,  0,  0,130,  0,230,230,
+-    9,  0,230,230,  0,  0,220,  0,  0,  0,  0,  7,  0,  9,  9,  0,
+-    9,  9,  0,  0,  0,230,  0,  0,  0,228,  0,  0,  0,222,230,220,
+-  220,  0,  0,  0,230,  0,  0,220,230,220,  0,220,230,230,230,  0,
+-    0,  0,  9,  9,  0,  0,  7,  0,230,  0,  1,  1,  1,  0,  0,  0,
+-  230,234,214,220,202,230,230,230,230,230,232,228,228,220,218,230,
+-  233,220,230,220,230,230,  1,  1,  1,  1,  1,230,  0,  1,  1,230,
+-  220,230,  1,  1,  0,  0,218,228,232,222,224,224,  0,  8,  8,  0,
+-    0,  0,  0,220,230,  0,230,230,220,  0,  0,230,  0,  0, 26,  0,
+-    0,220,  0,230,230,  1,220,  0,  0,230,220,  0,  0,  0,220,220,
+-    0,  0,230,220,  0,  9,  7,  0,  0,  7,  9,  0,  0,  0,  9,  7,
+-    6,  6,  0,  0,  0,  0,  1,  0,  0,216,216,  1,  1,  1,  0,  0,
+-    0,226,216,216,216,216,216,  0,220,220,220,  0,232,232,220,230,
+-  230,230,  7,  0, 16, 17, 17, 33, 17, 49, 17, 17, 84, 97,135,145,
+-   26, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
++    0, 38,  1, 58,  1, 58,  0,  0,  0,  0,  0, 88, 63, 89,  0,  0,
++  115,  0,  0,  0, 55,  0,  0,  0,  0,115,  0,  0,  0,  0, 61,  0,
++    0,  0,  0, 79,  0, 61,  0,  0,  0,  0, 56,  0, 89, 80,  0,  0,
++   79,  0,  0,  0,  8, 91,  0,  0,  1, 87,  0,  0,116,  0,  0,  0,
++    0,  0,  0,117,  0,118,119,120,121,  0,104,  4,122, 49, 23,  0,
++    0,  0, 38, 50, 38, 58,  0,  0,  1, 87,  1,  1,  1,  1, 39,  1,
++   48,105, 87,  0,  0,  0,  0,  1,  0,  0,  0,123,  0,  0,  0,112,
++    4,122,  0,  0,  0,  1,124,  0,  0,  0,  0,  0,230,230,230,230,
++  230,232,220,220,220,220,232,216,220,220,220,220,220,202,202,220,
++  220,220,220,202,202,220,220,220,  1,  1,  1,  1,  1,220,220,220,
++  220,230,230,230,230,240,230,220,220,220,230,230,230,220,220,  0,
++  230,230,230,220,220,220,220,230,232,220,220,230,233,234,234,233,
++  234,234,233,230,  0,  0,  0,230,  0,220,230,230,230,230,220,230,
++  230,230,222,220,230,230,220,220,230,222,228,230, 10, 11, 12, 13,
++   14, 15, 16, 17, 18, 19, 19, 20, 21, 22,  0, 23,  0, 24, 25,  0,
++  230,220,  0, 18, 30, 31, 32,  0,  0,  0,  0, 27, 28, 29, 30, 31,
++   32, 33, 34,230,230,220,220,230,220,230,230,220, 35,  0,  0,  0,
++    0,  0,230,230,230,  0,  0,230,230,  0,220,230,230,220,  0,  0,
++    0, 36,  0,  0,230,220,230,230,220,220,230,220,220,230,220,230,
++  220,230,230,  0,  0,220,  0,  0,230,230,  0,230,  0,230,230,230,
++  230,230,  0,  0,  0,220,220,220,230,220,220,220,230,230,  0,220,
++   27, 28, 29,230,  7,  0,  0,  0,  0,  9,  0,  0,  0,230,220,230,
++  230,  0,  0,  0,  0,  0,230,  0,  0, 84, 91,  0,  0,  0,  0,  9,
++    9,  0,  0,  0,  0,  0,  9,  0,103,103,  9,  0,107,107,107,107,
++  118,118,  9,  0,122,122,122,122,220,220,  0,  0,  0,220,  0,220,
++    0,216,  0,  0,  0,129,130,  0,132,  0,  0,  0,  0,  0,130,130,
++  130,130,  0,  0,130,  0,230,230,  9,  0,230,230,  0,  0,220,  0,
++    0,  0,  0,  7,  0,  9,  9,  0,  9,  9,  0,  0,  0,230,  0,  0,
++    0,228,  0,  0,  0,222,230,220,220,  0,  0,  0,230,  0,  0,220,
++  230,220,  0,220,230,230,230,  0,  0,  0,  9,  9,  0,  0,  7,  0,
++  230,  0,  1,  1,  1,  0,  0,  0,230,234,214,220,202,230,230,230,
++  230,230,232,228,228,220,218,230,233,220,230,220,230,230,  1,  1,
++    1,  1,  1,230,  0,  1,  1,230,220,230,  1,  1,  0,  0,218,228,
++  232,222,224,224,  0,  8,  8,  0,  0,  0,  0,220,230,  0,230,230,
++  220,  0,  0,230,  0,  0, 26,  0,  0,220,  0,230,230,  1,220,  0,
++    0,230,220,  0,  0,  0,220,220,  0,  0,230,220,  0,  9,  7,  0,
++    0,  7,  9,  0,  0,  0,  9,  7,  6,  6,  0,  0,  0,  0,  1,  0,
++    0,216,216,  1,  1,  1,  0,  0,  0,226,216,216,216,216,216,  0,
++  220,220,220,  0,232,232,220,230,230,230,  7,  0, 16, 17, 17, 33,
++   17, 49, 17, 17, 84, 97,135,145, 26, 17, 17, 17, 17, 17, 17, 17,
+    17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+    17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+-   17, 17, 17,177,  0,  1,  2,  3,  3,  3,  3,  3,  3,  3,  3,  3,
+-    3,  3,  3,  3,  3,  3,  3,  3,  4,  3,  3,  3,  3,  3,  5,  3,
+-    3,  3,  3,  3,  6,  7,  8,  3,  3,  3,  3,  3,  9, 10, 11, 12,
+-   13,  3,  3,  3,  3,  3,  3,  3,  3, 14,  3, 15,  3,  3,  3,  3,
+-    3,  3, 16, 17, 18, 19, 20, 21,  3,  3,  3, 22, 23, 24,  3,  3,
+-    3,  3,  3,  3, 25,  3,  3,  3,  3,  3,  3,  3,  3, 26,  3,  3,
+-   27, 28,  0,  1,  0,  0,  0,  0,  0,  1,  0,  2,  0,  0,  0,  3,
+-    0,  0,  0,  3,  0,  0,  0,  0,  0,  4,  0,  5,  0,  0,  0,  0,
+-    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  6,  0,  0,  0,  7,
+-    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  8,  9,  0,  0,  0,
+-    0,  0,  0,  9,  0,  9,  0,  0,  0,  0,  0,  0,  0, 10, 11, 12,
+-   13,  0,  0, 14, 15, 16,  6,  0, 17, 18, 19, 19, 19, 20, 21, 22,
+-   23, 24, 19, 25,  0, 26, 27, 19, 19, 28, 29, 30,  0, 31,  0,  0,
+-    0,  8,  0,  0,  0,  0,  0,  0,  0, 19, 28,  0, 32, 33,  9, 34,
+-   35, 19,  0,  0, 36, 37, 38, 39, 40, 19,  0, 41, 42, 43, 44, 31,
+-    0,  1, 45, 42,  0,  0,  0,  0,  0, 32, 14, 14,  0,  0,  0,  0,
+-   14,  0,  0, 46, 47, 47, 47, 47, 48, 49, 47, 47, 47, 47, 50, 51,
+-   52, 53, 43, 21,  0,  0,  0,  0,  0,  0,  0, 54,  6, 55,  0, 14,
+-   19,  1,  0,  0,  0,  0, 56, 57,  0,  0,  0,  0,  0, 19, 58, 31,
+-    0,  0,  0,  0,  0,  0,  0, 59, 14,  0,  0,  0,  0,  1,  0,  2,
+-    0,  0,  0,  3,  0,  0,  0, 60, 61,  0,  0,  0,  0,  0,  0,  0,
+-    1,  0,  0,  0,  0,  0,  2,  3,  0,  4,  5,  0,  0,  6,  0,  0,
+-    0,  7,  0,  0,  0,  1,  1,  0,  0,  8,  9,  0,  8,  9,  0,  0,
+-    0,  0,  8,  9, 10, 11, 12,  0,  0,  0, 13,  0,  0,  0,  0, 14,
+-   15, 16, 17,  0,  0,  0,  1,  0,  0, 18, 19,  0,  0,  0, 20,  0,
+-    0,  0,  1,  1,  1,  1,  0,  1,  1,  1,  1,  1,  1,  1,  0,  8,
+-   21,  9,  0,  0, 22,  0,  0,  0,  0,  1,  0, 23, 24, 25,  0,  0,
+-   26,  0,  0,  0,  8, 21, 27,  0,  1,  0,  0,  1,  1,  1,  1,  0,
+-    1, 28, 29, 30,  0, 31, 32, 20,  1,  1,  0,  0,  0,  8, 21,  9,
+-    1,  4,  5,  0,  0,  0, 33,  9,  0,  1,  1,  1,  0,  8, 21, 21,
+-   21, 21, 34,  1, 35, 21, 21, 21,  9, 36,  0,  0, 37, 38,  1,  0,
+-   39,  0,  0,  0,  1,  0,  1,  0,  0,  0,  0,  8, 21,  9,  1,  0,
+-    0,  0, 40,  0,  8, 21, 21, 21, 21, 21, 21, 21, 21,  9,  0,  1,
+-    1,  1,  1,  8, 21, 21, 21,  9,  0,  0,  0, 41,  0, 42, 43,  0,
+-    0,  0,  1, 44,  0,  0,  0, 45,  8,  9,  1,  0,  0,  0,  8, 21,
+-   21, 21,  9,  0,  1,  0,  1,  1,  8, 21, 21,  9,  0,  4,  5,  8,
+-    9,  1,  0,  0,  0,  1,  2,  3,  4,  5,  6,  7,  7,  8,  7,  7,
+-    7,  7,  7,  7,  7,  7,  7,  7,  9, 10, 11, 11, 11, 11, 12, 13,
+-   13, 13, 13, 14, 15, 16, 17, 18, 19, 20, 21, 13, 22, 13, 13, 13,
+-   13, 23, 24, 24, 25, 26, 13, 13, 13, 27, 28, 29, 13, 30, 31, 32,
+-   33, 34, 35, 36,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
+-    7,  7,  7,  7,  7,  7,  7,  7, 37,  7, 38, 39,  7, 40,  7,  7,
+-    7, 41, 13, 42,  7,  7, 43,  7, 44, 13, 13, 13, 13, 13, 13, 13,
+-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+-   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+-   13, 13, 13, 13, 45,  0,  0,  1,  2,  2,  2,  3,  4,  5,  6,  7,
+-    8,  9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
+-   24, 25, 26, 27, 28, 29, 30, 31, 32, 32, 33, 34, 35, 36, 37, 37,
+-   37, 37, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
+-   51, 52,  2,  2, 53, 54, 55, 56, 57, 58, 59, 59, 59, 59, 60, 59,
+-   59, 59, 59, 59, 59, 59, 61, 61, 59, 59, 59, 59, 62, 63, 64, 65,
+-   66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 59, 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, 79, 70, 70, 70, 70, 80, 80, 80, 80, 80, 80, 80, 80, 80, 81,
+-   82, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 32, 32,
+-   32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+-   32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+-   32, 32, 32, 32, 32, 95, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
+-   96, 96, 96, 96, 96, 96, 96, 96, 70, 70, 97, 98, 99,100,101,101,
+-  102,103,104,105,106,107,108,109,110,111, 96,112,113,114,115,116,
+-  117,118,119,119,120,121,122,123,124,125,126,127,128,129,130,131,
+-  132, 96,133,134,135,136,137,138,139,140,141,142,143, 96,144,145,
+-   96,146,147,148,149, 96,150,151,152,153,154,155,156, 96,157,158,
+-  159,160, 96,161,162,163,164,164,164,164,164,164,164,165,166,164,
+-  167, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
+-   96, 96, 96, 96, 96,168,169,169,169,169,169,169,169,169,170, 96,
+-   96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,171,171,
+-  171,171,172, 96, 96, 96,173,173,173,173,174,175,176,177, 96, 96,
+-   96, 96,178,179,180,181,182,182,182,182,182,182,182,182,182,182,
+-  182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,
+-  182,182,182,182,182,183,182,182,182,182,182,182,184,184,184,185,
+-  186, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
+-   96, 96, 96, 96, 96,187,188,189,190,191,191,192, 96, 96, 96, 96,
+-   96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,193,194,
+-   96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
+-   96, 96, 96, 96,195,196, 59,197,198,199,200,201,202, 96,203,204,
+-  205, 59, 59,206, 59,207,208,208,208,208,208,209, 96, 96, 96, 96,
+-   96, 96, 96, 96,210, 96,211,212,213, 96, 96,214, 96, 96, 96,215,
+-   96, 96, 96, 96, 96,216,217,218,219, 96, 96, 96, 96, 96,220,221,
+-  222, 96,223,224, 96, 96,225,226, 59,227,228, 96, 59, 59, 59, 59,
+-   59, 59, 59,229,230,231,232,233, 59, 59,234,235, 59,236, 96, 96,
+-   96, 96, 96, 96, 96, 96, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+-   70, 70, 70,237, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+-   70, 70, 70, 70,238, 70,239, 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,240, 70, 70, 70, 70, 70, 70, 70, 70, 70,241, 70, 70,
+-   70, 70,242, 96, 96, 96, 70, 70, 70, 70,243, 96, 96, 96, 96, 96,
+-   96, 96, 96, 96, 96, 96, 70, 70, 70, 70, 70, 70,244, 70, 70, 70,
+-   70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,245, 96, 96,
+-   96, 96, 96, 96, 96, 96,246, 96,247,248,  0,  1,  2,  2,  0,  1,
+-    2,  2,  2,  3,  4,  5,  0,  0,  0,  0,  0, 19, 19, 19, 19, 19,
+-   19, 19, 19, 19, 19,  0,  0,  0, 19,  0, 19,  0,  0,  0,  0,  0,
+-   26, 26,  1,  1,  1,  1,  9,  9,  9,  9,  0,  9,  9,  9,  2,  2,
+-    9,  9,  9,  9,  0,  9,  2,  2,  2,  2,  9,  0,  9,  0,  9,  9,
+-    9,  2,  9,  2,  9,  9,  9,  9,  2,  9,  9,  9, 55, 55, 55, 55,
+-   55, 55,  6,  6,  6,  6,  6,  1,  1,  6,  2,  4,  4,  4,  4,  4,
+-    4,  4,  4,  4,  4,  2,  2, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+-   14,  2,  2,  2,  2, 14, 14,  2,  2,  2,  3,  3,  3,  3,  3,  0,
+-    3,  3,  0,  3,  3,  3,  3,  3,  3,  0,  3,  3,  3,  1,  1,  1,
+-    3,  3,  1,  3,  3,  3, 37, 37, 37, 37, 37, 37,  2, 37, 37, 37,
+-   37,  2,  2, 37, 37, 37, 38, 38, 38, 38, 38, 38,  2,  2, 64, 64,
+-   64, 64, 64, 64, 64,  2,  2, 64, 64, 64, 90, 90, 90, 90, 90, 90,
+-    2,  2, 90, 90, 90,  2, 95, 95, 95, 95,  2,  2, 95,  2,  3,  3,
+-    3,  2,  3,  3,  2,  2,  3,  3,  0,  3,  7,  7,  7,  7,  7,  1,
+-    1,  1,  1,  7,  7,  7,  0,  0,  7,  7,  5,  5,  5,  5,  2,  5,
+-    5,  5,  5,  2,  2,  5,  5,  2,  5,  5,  5,  2,  5,  2,  2,  2,
+-    5,  5,  5,  5,  2,  2,  5,  5,  5,  2,  2,  2,  2,  5,  5,  5,
+-    2,  5,  2, 11, 11, 11, 11, 11, 11,  2,  2,  2,  2, 11, 11,  2,
+-    2, 11, 11, 11, 11, 11, 11,  2, 11, 11,  2, 11, 11,  2, 11, 11,
+-    2,  2,  2, 11,  2,  2, 11,  2, 11,  2,  2,  2, 11, 11,  2, 10,
+-   10, 10, 10, 10, 10, 10, 10, 10,  2, 10, 10,  2, 10, 10, 10, 10,
+-    2,  2, 10,  2,  2,  2,  2,  2, 10, 10,  2, 21, 21, 21, 21, 21,
+-   21, 21, 21,  2,  2, 21, 21,  2, 21, 21, 21, 21,  2,  2, 21, 21,
+-    2, 21,  2,  2, 21, 21,  2,  2, 22, 22,  2, 22, 22, 22, 22, 22,
+-   22,  2, 22,  2, 22, 22, 22, 22,  2,  2,  2, 22, 22,  2,  2,  2,
+-    2, 22, 22,  2,  2,  2, 22, 22, 22, 22, 23, 23, 23, 23, 23,  2,
+-   23, 23, 23, 23,  2,  2,  2, 23, 23,  2, 23, 23, 23,  2,  2, 23,
+-    2,  2,  2,  2, 23, 23,  2,  2,  2, 23, 16, 16, 16, 16, 16,  2,
+-   16, 16,  2, 16, 16, 16, 16, 16,  2,  2,  2, 16, 16,  2,  2,  2,
+-   16, 16, 20, 20, 20, 20, 20,  2, 20, 20,  2,  2, 20, 20,  2, 36,
+-   36, 36, 36, 36, 36, 36, 36, 36, 36,  2,  2,  2, 36, 36, 36, 36,
+-    2, 36,  2, 36,  2,  2,  2,  2, 36,  2,  2,  2,  2, 36, 36,  2,
+-   36,  2, 36,  2,  2,  2,  2, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+-   24,  2,  2,  2,  2,  0,  2, 18, 18,  2, 18,  2, 18, 18, 18, 18,
+-   18,  2, 18, 18, 18, 18,  2, 18,  2, 18, 18, 18,  2,  2, 18,  2,
+-   18,  2, 25, 25, 25, 25,  2, 25, 25, 25, 25,  2,  2,  2, 25,  2,
+-   25, 25, 25,  0,  0,  0,  0, 25, 25,  2, 33, 33, 33, 33,  8,  8,
+-    8,  8,  8,  8,  2,  8,  2,  8,  2,  2,  8,  8,  8,  0, 12, 12,
+-   12, 12, 30, 30, 30, 30, 30,  2, 30, 30, 30, 30,  2,  2, 30, 30,
+-   30,  2,  2, 30, 30, 30, 30,  2,  2,  2, 29, 29, 29, 29, 29, 29,
+-    2,  2, 28, 28, 28, 28, 34, 34, 34, 34, 34,  2,  2,  2, 35, 35,
+-   35, 35, 35, 35, 35,  0,  0,  0, 35, 35, 35,  2,  2,  2, 45, 45,
+-   45, 45, 45, 45,  2,  2,  2,  2,  2, 45, 44, 44, 44, 44, 44,  0,
+-    0,  2, 43, 43, 43, 43, 46, 46, 46, 46, 46,  2, 46, 46, 31, 31,
+-   31, 31, 31, 31,  2,  2, 32, 32,  0,  0, 32,  0, 32, 32, 32, 32,
+-   32, 32, 32, 32,  2,  2, 32,  2,  2,  2, 32, 32, 32,  2, 28, 28,
+-    2,  2, 48, 48, 48, 48, 48, 48, 48,  2, 48,  2,  2,  2, 52, 52,
+-   52, 52, 52, 52,  2,  2, 52,  2,  2,  2, 58, 58, 58, 58, 58, 58,
+-    2,  2, 58, 58, 58,  2,  2,  2, 58, 58, 54, 54, 54, 54,  2,  2,
+-   54, 54, 91, 91, 91, 91, 91, 91, 91,  2, 91,  2,  2, 91, 91, 91,
+-    2,  2,  1,  1,  1,  2, 62, 62, 62, 62, 62,  2,  2,  2, 62, 62,
+-   62,  2, 76, 76, 76, 76, 93, 93, 93, 93, 70, 70, 70, 70,  2,  2,
+-    2, 70, 70, 70,  2,  2,  2, 70, 70, 70, 73, 73, 73, 73,  6,  2,
+-    2,  2,  8,  8,  8,  2,  2,  8,  8,  8,  1,  1,  1,  0,  1,  0,
+-    1,  1,  1,  0,  0,  0,  0,  1,  0,  0,  1,  1,  0,  2, 19, 19,
+-    9,  9,  9,  9,  9,  6, 19,  9,  9,  9,  9,  9, 19, 19,  9,  9,
+-    9, 19,  6, 19, 19, 19, 19, 19, 19,  9,  9,  9,  2,  2,  2,  9,
+-    2,  9,  2,  9,  9,  9,  1,  1,  0,  0,  0,  2,  0,  0,  0, 19,
+-    2,  2,  0,  0,  0, 19,  0,  0,  0,  2, 19,  2,  2,  2,  0,  2,
+-    2,  2,  1,  2,  2,  2,  0,  0,  9,  0,  0,  0, 19, 19, 27, 27,
+-   27, 27,  2,  2,  0,  0,  0,  0,  2,  0, 56, 56, 56, 56,  2, 55,
+-   55, 55, 61, 61, 61, 61,  2,  2,  2, 61, 61,  2,  2,  2,  0,  0,
+-    2,  2, 13, 13, 13, 13, 13, 13,  2, 13, 13, 13,  2,  2,  0, 13,
+-    0, 13,  0, 13, 13, 13, 13, 13,  1,  1,  1,  1, 12, 12,  2, 15,
+-   15, 15, 15, 15, 15, 15, 15, 15, 15,  2,  2,  1,  1,  0,  0, 15,
+-   15, 15,  0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,  0,  2, 26,
+-   26, 26, 26, 26, 26, 26,  2, 12, 12, 12, 12, 12, 12,  2, 12, 12,
+-   12,  0, 39, 39, 39, 39, 39,  2,  2,  2, 39, 39, 39,  2, 86, 86,
+-   86, 86, 77, 77, 77, 77, 79, 79, 79, 79, 19, 19, 19,  2, 19, 19,
+-    2, 19,  2, 19, 19, 19, 19, 19,  2,  2,  2,  2, 19, 19, 60, 60,
+-   60, 60, 60,  2,  2,  2, 65, 65, 65, 65, 75, 75, 75, 75, 75, 75,
+-    2,  2,  2,  2, 75, 75, 69, 69, 69, 69, 69, 69,  0, 69, 74, 74,
+-   74, 74,  2,  2,  2, 74, 12,  2,  2,  2, 84, 84, 84, 84, 84, 84,
+-    2,  0, 84, 84,  2,  2,  2,  2, 84, 84, 33, 33, 33,  2, 68, 68,
+-   68, 68, 68, 68, 68,  2, 68, 68,  2,  2, 92, 92, 92, 92, 92, 92,
+-   92,  2,  2,  2,  2, 92, 87, 87, 87, 87, 87, 87, 87,  2, 19,  9,
+-   19, 19, 19, 19,  0,  0, 87, 87,  2,  2,  2,  2,  2, 12,  2,  2,
+-    2,  4, 14,  2, 14,  2, 14, 14,  2, 14, 14,  2, 14, 14,  2,  2,
+-    2,  3,  3,  3,  0,  0,  2,  2,  3,  3,  1,  1,  6,  6,  3,  2,
+-    3,  3,  3,  2,  2,  0,  2,  0,  0,  0,  0,  0, 17, 17, 17, 17,
+-    0,  0,  2,  2, 12, 12, 49, 49, 49, 49,  2, 49, 49, 49, 49, 49,
+-   49,  2, 49, 49,  2, 49, 49, 49,  2,  2,  9,  2,  2,  2,  0,  1,
+-    2,  2, 71, 71, 71, 71, 71,  2,  2,  2, 67, 67, 67, 67, 67,  2,
+-    2,  2, 42, 42, 42, 42,  2, 42, 42, 42, 41, 41, 41, 41, 41, 41,
+-   41,  2,118,118,118,118,118,118,118,  2, 53, 53, 53, 53, 53, 53,
+-    2, 53, 59, 59, 59, 59, 59, 59,  2,  2, 40, 40, 40, 40, 51, 51,
+-   51, 51, 50, 50, 50, 50, 50, 50,  2,  2,135,135,135,135,106,106,
+-  106,106,104,104,104,104,  2,  2,  2,104,161,161,161,161,161,161,
+-  161,  2,161,161,  2,161,161,  2,  2,  2,110,110,110,110,110,110,
+-  110,  2,110,110,  2,  2, 19,  2, 19, 19, 47, 47, 47, 47, 47, 47,
+-    2,  2, 47,  2, 47, 47, 47, 47,  2, 47, 47,  2,  2,  2, 47,  2,
+-    2, 47, 81, 81, 81, 81, 81, 81,  2, 81,120,120,120,120,116,116,
+-  116,116,116,116,116,  2,  2,  2,  2,116,128,128,128,128,128,128,
+-  128,  2,128,128,  2,  2,  2,  2,  2,128, 66, 66, 66, 66,  2,  2,
+-    2, 66, 72, 72, 72, 72, 72, 72,  2,  2,  2,  2,  2, 72, 98, 98,
+-   98, 98, 97, 97, 97, 97,  2,  2, 97, 97, 57, 57, 57, 57,  2, 57,
+-   57,  2,  2, 57, 57, 57, 57, 57,  2,  2, 57, 57, 57,  2,  2,  2,
+-    2, 57, 57,  2,  2,  2, 88, 88, 88, 88,117,117,117,117,112,112,
+-  112,112,112,112,112,  2,  2,  2,  2,112, 78, 78, 78, 78, 78, 78,
+-    2,  2,  2, 78, 78, 78, 83, 83, 83, 83, 83, 83,  2,  2, 82, 82,
+-   82, 82, 82, 82, 82,  2,122,122,122,122,122,122,  2,  2,  2,122,
+-  122,122,122,  2,  2,  2, 89, 89, 89, 89, 89,  2,  2,  2,130,130,
+-  130,130,130,130,130,  2,  2,  2,130,130,144,144,144,144,144,144,
+-    2,  2,156,156,156,156,156,156,  2,156,156,156,  2,  2,  2,  3,
+-    3,  3,147,147,147,147,148,148,148,148,148,148,  2,  2,158,158,
+-  158,158,158,158,  2,  2,153,153,153,153,149,149,149,149,149,149,
+-  149,  2, 94, 94, 94, 94, 94, 94,  2,  2,  2,  2, 94, 94,  2,  2,
+-    2, 94, 85, 85, 85, 85, 85, 85, 85,  2,  2, 85,  2,  2,101,101,
+-  101,101,101,  2,  2,  2,101,101,  2,  2, 96, 96, 96, 96, 96,  2,
+-   96, 96,111,111,111,111,111,111,111,  2,100,100,100,100,108,108,
+-  108,108,108,108,  2,108,108,108,  2,  2,129,129,129,129,129,129,
+-  129,  2,129,  2,129,129,129,129,  2,129,129,129,  2,  2,109,109,
+-  109,109,109,109,109,  2,109,109,  2,  2,107,107,107,107,  2,107,
+-  107,107,107,  2,  2,107,107,  2,107,107,107,107,  2,  1,107,107,
+-    2,  2,107,  2,  2,  2,  2,  2,  2,107,  2,  2,107,107,137,137,
+-  137,137,  2,137,137,137,137,137,  2,  2,124,124,124,124,124,124,
+-    2,  2,123,123,123,123,123,123,  2,  2,114,114,114,114,114,  2,
+-    2,  2,114,114,  2,  2,102,102,102,102,102,102,  2,  2,126,126,
+-  126,126,126,126,126,  2,  2,126,126,126,142,142,142,142,125,125,
+-  125,125,125,125,125,  2,  2,  2,  2,125,154,154,154,154,154,154,
+-  154,  2,  2,154,  2,  2,  2,154,154,  2,154,154,  2,154,154,  2,
+-    2,154,154,154,  2,  2,150,150,150,150,  2,  2,150,150,150,  2,
+-    2,  2,141,141,141,141,140,140,140,140,140,140,140,  2,121,121,
+-  121,121,121,  2,  2,  2,  7,  7,  2,  2,133,133,133,133,133,  2,
+-  133,133,133,133,133,  2,133,133,  2,  2,133,  2,  2,  2,134,134,
+-  134,134,  2,  2,134,134,  2,134,134,134,134,134,134,  2,138,138,
+-  138,138,138,138,138,  2,138,138,  2,138,  2,  2,138,  2,138,138,
+-    2,  2,143,143,143,143,143,143,  2,143,143,  2,143,143,143,143,
+-  143,  2,143,  2,  2,  2,143,143,  2,  2,145,145,145,145,145,  2,
+-    2,  2,163,163,163,163,163,  2,163,163,163,163,163,  2,  2,  2,
+-  163,163,163,163,  2,  2, 86,  2,  2,  2, 63, 63, 63, 63, 63, 63,
+-    2,  2, 63, 63, 63,  2, 63,  2,  2,  2,157,157,157,157,157,157,
+-  157,  2, 80, 80, 80, 80, 80, 80,  2,  2,127,127,127,127,127,127,
+-  127,  2, 79,  2,  2,  2,115,115,115,115,115,115,115,  2,115,115,
+-    2,  2,  2,  2,115,115,159,159,159,159,159,159,159,  2,159,159,
+-    2,  2,103,103,103,103,103,103,  2,  2,119,119,119,119,119,119,
+-    2,  2,119,119,  2,119,  2,119,119,119,146,146,146,146,146,146,
+-  146,  2, 99, 99, 99, 99, 99, 99, 99,  2,  2,  2,  2, 99,136,139,
+-   13, 13,155,  2,  2,  2,136,136,136,136,155,155,155,155,155,155,
+-    2,  2,136,  2,  2,  2,  2, 17, 17, 17,  2, 17, 17,  2, 17, 15,
+-   15, 15, 17, 17, 17,  2,  2,  2, 15,  2,  2, 17,  2,  2,139,139,
+-  139,139,105,105,105,105,105,105,105,  2,105,  2,  2,  2,105,105,
+-    2,  2,  1,  1,  2,  2,  0,  0,  0,  1,  0,  1,  1,  1,  0,  0,
+-    1,  1,  2,  2,  0,  2,  2,  0,  0,  2,  0,  2,  0,  2,131,131,
+-  131,131,  2,  2,  2,131,  2,131,131,131, 56, 56, 56,  2, 56,  2,
+-    2, 56, 56, 56,  2, 56, 56,  2, 56, 56,  6,  6,  2,  2,  2,  2,
+-    2,  6,151,151,151,151,151,  2,  2,  2,151,151,  2,  2,  2,  2,
+-  151,151,160,160,160,160,160,160,160,  2,152,152,152,152,152,152,
+-    2,  2,  2,  2,  2,152,164,164,164,164,164,164,  2,  2,  2, 30,
+-   30,  2,113,113,113,113,113,  2,  2,113,113,113,113,  2,132,132,
+-  132,132,132,132,  2,  2,  2,  2,132,132,  2,  3,  3,  2,  3,  2,
+-    2,  3,  2,  3,  2,  3,  2,  2,  3,  2,  3,  2,  3,  2,  3,  3,
+-    2,  3, 15,  0,  0,  2, 13,  2,  2,  2, 13, 13, 13,  2,  2,  0,
+-    2,  2,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  9,  9,  9, 10,
+-    9, 11, 12, 13,  9,  9,  9, 14,  9,  9, 15,  9,  9,  9,  9,  9,
++   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,177,  0,  1,  2,  3,
++    3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,
++    4,  3,  3,  3,  3,  3,  5,  3,  3,  3,  3,  3,  6,  7,  8,  3,
++    3,  3,  3,  3,  9, 10, 11, 12, 13,  3,  3,  3,  3,  3,  3,  3,
++    3, 14,  3, 15,  3,  3,  3,  3,  3,  3, 16, 17, 18, 19, 20, 21,
++    3,  3,  3, 22, 23, 24,  3,  3,  3,  3,  3,  3, 25,  3,  3,  3,
++    3,  3,  3,  3,  3, 26,  3,  3, 27, 28,  0,  1,  0,  0,  0,  0,
++    0,  1,  0,  2,  0,  0,  0,  3,  0,  0,  0,  3,  0,  0,  0,  0,
++    0,  4,  0,  5,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
++    0,  0,  0,  6,  0,  0,  0,  7,  0,  0,  0,  0,  0,  0,  0,  0,
++    0,  0,  0,  8,  9,  0,  0,  0,  0,  0,  0,  9,  0,  9,  0,  0,
++    0,  0,  0,  0,  0, 10, 11, 12, 13,  0,  0, 14, 15, 16,  6,  0,
++   17, 18, 19, 19, 19, 20, 21, 22, 23, 24, 19, 25,  0, 26, 27, 19,
++   19, 28, 29, 30,  0, 31,  0,  0,  0,  8,  0,  0,  0,  0,  0,  0,
++    0, 19, 28,  0, 32, 33,  9, 34, 35, 19,  0,  0, 36, 37, 38, 39,
++   40, 19,  0, 41, 42, 43, 44, 31,  0,  1, 45, 42,  0,  0,  0,  0,
++    0, 32, 14, 14,  0,  0,  0,  0, 14,  0,  0, 46, 47, 47, 47, 47,
++   48, 49, 47, 47, 47, 47, 50, 51, 52, 53, 43, 21,  0,  0,  0,  0,
++    0,  0,  0, 54,  6, 55,  0, 14, 19,  1,  0,  0,  0,  0, 56, 57,
++    0,  0,  0,  0,  0, 19, 58, 31,  0,  0,  0,  0,  0,  0,  0, 59,
++   14,  0,  0,  0,  0,  1,  0,  2,  0,  0,  0,  3,  0,  0,  0, 60,
++   61,  0,  0,  0,  0,  0,  0,  0,  1,  0,  0,  0,  0,  0,  2,  3,
++    0,  4,  5,  0,  0,  6,  0,  0,  0,  7,  0,  0,  0,  1,  1,  0,
++    0,  8,  9,  0,  8,  9,  0,  0,  0,  0,  8,  9, 10, 11, 12,  0,
++    0,  0, 13,  0,  0,  0,  0, 14, 15, 16, 17,  0,  0,  0,  1,  0,
++    0, 18, 19,  0,  0,  0, 20,  0,  0,  0,  1,  1,  1,  1,  0,  1,
++    1,  1,  1,  1,  1,  1,  0,  8, 21,  9,  0,  0, 22,  0,  0,  0,
++    0,  1,  0, 23, 24, 25,  0,  0, 26,  0,  0,  0,  8, 21, 27,  0,
++    1,  0,  0,  1,  1,  1,  1,  0,  1, 28, 29, 30,  0, 31, 32, 20,
++    1,  1,  0,  0,  0,  8, 21,  9,  1,  4,  5,  0,  0,  0, 33,  9,
++    0,  1,  1,  1,  0,  8, 21, 21, 21, 21, 34,  1, 35, 21, 21, 21,
++    9, 36,  0,  0, 37, 38,  1,  0, 39,  0,  0,  0,  1,  0,  1,  0,
++    0,  0,  0,  8, 21,  9,  1,  0,  0,  0, 40,  0,  8, 21, 21, 21,
++   21, 21, 21, 21, 21,  9,  0,  1,  1,  1,  1,  8, 21, 21, 21,  9,
++    0,  0,  0, 41,  0, 42, 43,  0,  0,  0,  1, 44,  0,  0,  0, 45,
++    8,  9,  1,  0,  0,  0,  8, 21, 21, 21,  9,  0,  1,  0,  1,  1,
++    8, 21, 21,  9,  0,  4,  5,  8,  9,  1,  0,  0,  0,  1,  2,  3,
++    4,  5,  5,  5,  5,  5,  6,  7,  7,  8,  9, 10, 11, 12, 13, 14,
++   15,  9, 16, 17, 18,  9, 19, 20, 21, 22, 23, 24,  5,  5,  5,  5,
++    5,  5,  5,  5,  5,  5, 25, 26, 27,  5, 28, 29,  5, 30, 31,  9,
++    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
++    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
++    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
++    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
++    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
++    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
++    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
++    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
++    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
++    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
++    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9, 32,  0,  0,  1,
++    2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17,
++   18, 19, 20, 20, 21, 22, 23, 24, 25, 26, 27, 28,  1, 29, 30, 31,
++   32, 32, 33, 32, 32, 32, 34, 32, 32, 35, 36, 37, 38, 39, 40, 41,
++   42, 43, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44,
++   44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 45, 44, 44, 44, 44,
++   44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 46, 46,
++   46, 46, 47, 48, 49, 50, 51, 52, 53, 54, 17, 17, 17, 17, 17, 17,
++   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
++   17, 17, 17, 17, 17, 55, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
++   56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
++   56, 56, 56, 56, 56, 56, 56, 44, 57, 58, 59, 60, 61, 62, 63, 64,
++   65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
++   81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 95,
++   95, 96, 97, 98, 56, 56, 56, 56, 56, 56, 56, 56, 56, 99,100,100,
++  100,100,101,100,100,100,100,100,100,100,100,100,100,100,100,100,
++  100,102,103,103,104, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,105,
++   56, 56, 56, 56, 56, 56,106,106,107,108, 56,109,110,111,112,112,
++  112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
++  112,112,112,112,112,113,112,112,112,114,115,116, 56, 56, 56, 56,
++   56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,117,118,119,
++  120, 56, 56, 56, 56, 56, 56, 56, 56, 56,121, 56, 56, 56, 56, 56,
++   56, 56, 56, 56, 56, 56, 56, 56, 56, 56,122, 32,123,124,125,126,
++  127,128,129,130,131,132,133,133,134, 56, 56, 56, 56,135,136,137,
++  138, 56,139,140, 56,141,142,143, 56, 56,144,145,146, 56,147,148,
++  149, 32, 32, 32,150,151,152, 32,153,154, 56, 56, 56, 56, 44, 44,
++   44, 44, 44, 44,155, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44,
++   44, 44, 44, 44, 44,156,157, 44, 44, 44, 44, 44, 44, 44, 44, 44,
++   44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44,158, 44, 44, 44,
++   44, 44, 44, 44, 44, 44, 44, 44, 44,159, 44, 44,160, 56, 56, 56,
++   56, 56, 56, 56, 56, 56, 44, 44,161, 56, 56, 56, 56, 56, 44, 44,
++   44,162, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44,
++   44,163, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,164,165,
++    0,  1,  0,  1,  2,  3,  0,  1,  2,  3,  4,  5,  6,  7,  0,  0,
++    0,  0,  0,  0,  0,  0,  0, 19, 19, 19, 19, 19, 19, 19, 19, 19,
++   19, 19, 19, 19, 19, 19, 19, 19, 19,  0,  0,  0,  0,  0,  0,  0,
++   19,  0,  0,  0,  0,  0, 19, 19, 19, 19, 19, 19, 19,  0, 19,  0,
++    0,  0,  0,  0,  0,  0, 19, 19, 19, 19, 19,  0,  0,  0,  0,  0,
++   26, 26,  0,  0,  0,  0,  1,  1,  1,  1,  1,  1,  1,  1,  9,  9,
++    9,  9,  0,  9,  9,  9,  2,  2,  9,  9,  9,  9,  0,  9,  2,  2,
++    2,  2,  9,  0,  9,  0,  9,  9,  9,  2,  9,  2,  9,  9,  9,  9,
++    9,  9,  9,  9,  9,  9,  9,  9,  2,  9,  9,  9,  9,  9,  9,  9,
++   55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,  6,  6,
++    6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  1,  1,  6,  2,  4,
++    4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,
++    4,  4,  4,  4,  4,  2,  4,  4,  4,  2,  2,  4,  4,  4,  2, 14,
++   14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,  2,  2,
++    2,  2,  2,  2,  2,  2, 14, 14, 14,  2,  2,  2,  2, 14, 14, 14,
++   14, 14, 14,  2,  2,  2,  3,  3,  3,  3,  3,  0,  3,  3,  3,  3,
++    3,  3,  0,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,
++    3,  0,  3,  3,  3,  0,  0,  3,  3,  3,  3,  3,  3,  3,  3,  3,
++    3,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  3,  3,  1,  3,
++    3,  3,  3,  3,  3,  3, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
++   37, 37, 37, 37,  2, 37, 37, 37, 37,  2,  2, 37, 37, 37, 38, 38,
++   38, 38, 38, 38, 38, 38, 38, 38,  2,  2,  2,  2,  2,  2, 64, 64,
++   64, 64, 64, 64, 64, 64, 64, 64, 64,  2,  2, 64, 64, 64, 90, 90,
++   90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90,  2,  2, 90, 90,
++   90, 90, 90, 90, 90,  2, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,
++   95, 95,  2,  2, 95,  2, 37, 37, 37,  2,  2,  2,  2,  2,  3,  3,
++    3,  3,  3,  3,  3,  2,  3,  3,  2,  2,  2,  2,  2,  3,  3,  3,
++    0,  3,  3,  3,  3,  3,  7,  7,  7,  7,  7,  7,  7,  7,  7,  1,
++    1,  1,  1,  7,  7,  7,  7,  7,  7,  7,  0,  0,  7,  7,  5,  5,
++    5,  5,  2,  5,  5,  5,  5,  5,  5,  5,  5,  2,  2,  5,  5,  2,
++    2,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  2,
++    5,  5,  5,  5,  5,  5,  5,  2,  5,  2,  2,  2,  5,  5,  5,  5,
++    2,  2,  5,  5,  5,  5,  5,  2,  2,  5,  5,  5,  5,  2,  2,  2,
++    2,  2,  2,  2,  2,  5,  2,  2,  2,  2,  5,  5,  2,  5,  5,  5,
++    5,  5,  2,  2,  5,  5,  5,  5,  5,  5,  5,  5,  5,  2,  2, 11,
++   11, 11,  2, 11, 11, 11, 11, 11, 11,  2,  2,  2,  2, 11, 11,  2,
++    2, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,  2,
++   11, 11, 11, 11, 11, 11, 11,  2, 11, 11,  2, 11, 11,  2, 11, 11,
++    2,  2, 11,  2, 11, 11, 11,  2,  2, 11, 11, 11,  2,  2,  2, 11,
++    2,  2,  2,  2,  2,  2,  2, 11, 11, 11, 11,  2, 11,  2,  2,  2,
++    2,  2,  2,  2, 11, 11, 11, 11, 11, 11, 11, 11, 11,  2,  2, 10,
++   10, 10,  2, 10, 10, 10, 10, 10, 10, 10, 10, 10,  2, 10, 10, 10,
++    2, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,  2,
++   10, 10, 10, 10, 10, 10, 10,  2, 10, 10,  2, 10, 10, 10, 10, 10,
++    2,  2, 10, 10, 10, 10, 10, 10,  2, 10, 10, 10,  2,  2, 10,  2,
++    2,  2,  2,  2,  2,  2, 10, 10, 10, 10,  2,  2, 10, 10, 10, 10,
++    2,  2,  2,  2,  2,  2,  2, 10, 10, 10, 10, 10, 10, 10,  2, 21,
++   21, 21,  2, 21, 21, 21, 21, 21, 21, 21, 21,  2,  2, 21, 21,  2,
++    2, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,  2,
++   21, 21, 21, 21, 21, 21, 21,  2, 21, 21,  2, 21, 21, 21, 21, 21,
++    2,  2, 21, 21, 21, 21, 21,  2,  2, 21, 21, 21,  2,  2,  2,  2,
++    2,  2,  2, 21, 21, 21,  2,  2,  2,  2, 21, 21,  2, 21, 21, 21,
++   21, 21,  2,  2, 21, 21,  2,  2, 22, 22,  2, 22, 22, 22, 22, 22,
++   22,  2,  2,  2, 22, 22, 22,  2, 22, 22, 22, 22,  2,  2,  2, 22,
++   22,  2, 22,  2, 22, 22,  2,  2,  2, 22, 22,  2,  2,  2, 22, 22,
++   22, 22, 22, 22, 22, 22, 22, 22,  2,  2,  2,  2, 22, 22, 22,  2,
++    2,  2,  2,  2,  2, 22,  2,  2,  2,  2,  2,  2, 22, 22, 22, 22,
++   22,  2,  2,  2,  2,  2, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
++   23, 23, 23,  2, 23, 23, 23,  2, 23, 23, 23, 23, 23, 23, 23, 23,
++    2,  2, 23, 23, 23, 23, 23,  2, 23, 23, 23, 23,  2,  2,  2,  2,
++    2,  2,  2, 23, 23,  2, 23, 23, 23,  2,  2, 23,  2,  2, 23, 23,
++   23, 23,  2,  2, 23, 23,  2,  2,  2,  2,  2,  2,  2, 23, 16, 16,
++   16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,  2, 16, 16, 16,  2,
++   16, 16, 16, 16, 16, 16, 16, 16, 16, 16,  2, 16, 16, 16, 16, 16,
++    2,  2, 16, 16, 16, 16, 16,  2, 16, 16, 16, 16,  2,  2,  2,  2,
++    2,  2,  2, 16, 16,  2, 16, 16, 16, 16,  2,  2, 16, 16,  2, 16,
++   16, 16,  2,  2,  2,  2, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
++   20, 20, 20,  2, 20, 20, 20,  2, 20, 20, 20, 20, 20, 20,  2,  2,
++    2,  2, 20, 20, 20, 20, 20, 20, 20, 20,  2,  2, 20, 20,  2, 36,
++   36, 36,  2, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
++   36, 36, 36, 36, 36,  2,  2,  2, 36, 36, 36, 36, 36, 36, 36, 36,
++    2, 36, 36, 36, 36, 36, 36, 36, 36, 36,  2, 36,  2,  2,  2,  2,
++   36,  2,  2,  2,  2, 36, 36, 36, 36, 36, 36,  2, 36,  2,  2,  2,
++    2,  2,  2,  2, 36, 36,  2,  2, 36, 36, 36,  2,  2,  2,  2, 24,
++   24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
++   24,  2,  2,  2,  2,  0, 24, 24, 24, 24,  2,  2,  2,  2,  2, 18,
++   18,  2, 18,  2, 18, 18, 18, 18, 18,  2, 18, 18, 18, 18, 18, 18,
++   18, 18, 18, 18, 18, 18, 18, 18, 18, 18,  2, 18,  2, 18, 18, 18,
++   18, 18, 18, 18,  2,  2, 18, 18, 18, 18, 18,  2, 18,  2, 18, 18,
++   18, 18, 18, 18, 18,  2, 18, 18,  2,  2, 18, 18, 18, 18, 25, 25,
++   25, 25, 25, 25, 25, 25,  2, 25, 25, 25, 25, 25, 25, 25, 25, 25,
++   25, 25, 25,  2,  2,  2, 25, 25, 25, 25, 25,  2, 25, 25, 25, 25,
++   25, 25, 25,  0,  0,  0,  0, 25, 25,  2,  2,  2,  2,  2, 33, 33,
++   33, 33, 33, 33, 33, 33,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
++    8,  8,  8,  8,  2,  8,  2,  2,  2,  2,  2,  8,  2,  2,  8,  8,
++    8,  0,  8,  8,  8,  8, 12, 12, 12, 12, 12, 12, 12, 12, 30, 30,
++   30, 30, 30, 30, 30, 30, 30,  2, 30, 30, 30, 30,  2,  2, 30, 30,
++   30, 30, 30, 30, 30,  2, 30, 30, 30,  2,  2, 30, 30, 30, 30, 30,
++   30, 30, 30,  2,  2,  2, 30, 30,  2,  2,  2,  2,  2,  2, 29, 29,
++   29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,  2,  2, 28, 28,
++   28, 28, 28, 28, 28, 28, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
++   34, 34, 34,  2,  2,  2, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
++   35,  0,  0,  0, 35, 35, 35,  2,  2,  2,  2,  2,  2,  2, 45, 45,
++   45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,  2,  2,  2,  2,
++    2,  2,  2,  2,  2, 45, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44,
++   44, 44, 44,  0,  0,  2, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43,
++   43, 43,  2,  2,  2,  2, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46,
++   46, 46, 46,  2, 46, 46, 46,  2, 46, 46,  2,  2,  2,  2, 31, 31,
++   31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,  2,  2, 31, 31,
++    2,  2,  2,  2,  2,  2, 32, 32,  0,  0, 32,  0, 32, 32, 32, 32,
++   32, 32, 32, 32, 32, 32, 32, 32,  2,  2,  2,  2,  2,  2, 32,  2,
++    2,  2,  2,  2,  2,  2, 32, 32, 32,  2,  2,  2,  2,  2, 28, 28,
++   28, 28, 28, 28,  2,  2, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
++   48, 48, 48, 48, 48,  2, 48, 48, 48, 48,  2,  2,  2,  2, 48,  2,
++    2,  2, 48, 48, 48, 48, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
++   52, 52, 52, 52,  2,  2, 52, 52, 52, 52, 52,  2,  2,  2, 58, 58,
++   58, 58, 58, 58, 58, 58, 58, 58, 58, 58,  2,  2,  2,  2, 58, 58,
++    2,  2,  2,  2,  2,  2, 58, 58, 58,  2,  2,  2, 58, 58, 54, 54,
++   54, 54, 54, 54, 54, 54, 54, 54, 54, 54,  2,  2, 54, 54, 91, 91,
++   91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,  2, 91, 91,
++   91, 91, 91,  2,  2, 91, 91, 91,  2,  2,  2,  2,  2,  2, 91, 91,
++   91, 91, 91, 91,  2,  2,  1,  1,  1,  1,  1,  1,  1,  2, 62, 62,
++   62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,  2, 62, 62, 76, 76,
++   76, 76, 76, 76, 76, 76, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
++   93, 93,  2,  2,  2,  2,  2,  2,  2,  2, 93, 93, 93, 93, 70, 70,
++   70, 70, 70, 70, 70, 70,  2,  2,  2, 70, 70, 70, 70, 70, 70, 70,
++    2,  2,  2, 70, 70, 70, 73, 73, 73, 73, 73, 73, 73, 73,  6,  6,
++    6,  2,  2,  2,  2,  2,  8,  8,  8,  2,  2,  8,  8,  8,  1,  1,
++    1,  0,  1,  1,  1,  1,  1,  0,  1,  1,  1,  1,  1,  1,  1,  0,
++    0,  0,  0,  1,  0,  0,  0,  0,  0,  0,  1,  0,  0,  0,  1,  1,
++    0,  2,  2,  2,  2,  2, 19, 19, 19, 19, 19, 19,  9,  9,  9,  9,
++    9,  6, 19, 19, 19, 19, 19, 19, 19, 19, 19,  9,  9,  9,  9,  9,
++   19, 19, 19, 19,  9,  9,  9,  9,  9, 19, 19, 19, 19, 19,  6, 19,
++   19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,  9,  9,  9,
++    9,  9,  9,  9,  2,  2,  2,  9,  2,  9,  2,  9,  2,  9,  9,  9,
++    9,  9,  9,  2,  9,  9,  9,  9,  9,  9,  2,  2,  9,  9,  9,  9,
++    9,  9,  2,  9,  9,  9,  2,  2,  9,  9,  9,  2,  9,  9,  9,  9,
++    9,  9,  9,  9,  9,  2,  0,  0,  0,  0,  1,  1,  0,  0,  0,  0,
++    0,  0,  0,  2,  0,  0,  0, 19,  2,  2,  0,  0,  0,  0,  0,  0,
++    0,  0,  0,  0,  0, 19,  0,  0,  0,  0,  0,  0,  0,  2, 19, 19,
++   19, 19, 19,  2,  2,  2,  0,  2,  2,  2,  2,  2,  2,  2,  1,  2,
++    2,  2,  2,  2,  2,  2,  0,  0,  0,  0,  0,  0,  9,  0,  0,  0,
++   19, 19,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 19,  0, 19,  0,
++    0,  0,  2,  2,  2,  2,  0,  0,  2,  2,  2,  2,  2,  2,  0,  0,
++    0,  2,  2,  2,  2,  2, 27, 27, 27, 27, 27, 27, 27, 27,  0,  0,
++    0,  0,  2,  2,  0,  0,  0,  0,  0,  0,  0,  0,  2,  0, 56, 56,
++   56, 56, 56, 56, 56, 56, 55, 55, 55, 55,  2,  2,  2,  2,  2, 55,
++   55, 55, 55, 55, 55, 55, 61, 61, 61, 61, 61, 61, 61, 61,  2,  2,
++    2,  2,  2,  2,  2, 61, 61,  2,  2,  2,  2,  2,  2,  2,  0,  0,
++    0,  0,  0,  0,  2,  2, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
++    2, 13, 13, 13, 13, 13, 13, 13, 13, 13,  2,  2,  2,  2, 13, 13,
++   13, 13, 13, 13,  2,  2,  0,  0,  0,  0,  0, 13,  0, 13,  0, 13,
++   13, 13, 13, 13, 13, 13, 13, 13,  1,  1,  1,  1, 12, 12, 13, 13,
++   13, 13,  0,  0,  0,  0,  2, 15, 15, 15, 15, 15, 15, 15, 15, 15,
++   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,  2,  2,  1,
++    1,  0,  0, 15, 15, 15,  0, 17, 17, 17, 17, 17, 17, 17, 17, 17,
++   17, 17, 17, 17, 17, 17, 17, 17, 17,  0,  0, 17, 17, 17,  2,  2,
++    2,  2,  2, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,  2, 12,
++   12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,  2,  2,  2,
++    2,  2,  2,  2,  2,  0, 12, 12, 12, 12, 12, 12, 12,  0, 17, 17,
++   17, 17, 17, 17, 17,  0, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
++   39, 39, 39,  2,  2,  2, 39, 39, 39, 39, 39, 39, 39,  2, 86, 86,
++   86, 86, 86, 86, 86, 86, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
++   77, 77,  2,  2,  2,  2, 79, 79, 79, 79, 79, 79, 79, 79,  0,  0,
++   19, 19, 19, 19, 19, 19,  0,  0,  0, 19, 19, 19, 19, 19, 19, 19,
++   19, 19, 19, 19,  2,  2, 19, 19,  2, 19,  2, 19, 19, 19,  2,  2,
++   19, 19, 19, 19, 19, 19, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,
++   60, 60, 60,  2,  2,  2, 65, 65, 65, 65, 65, 65, 65, 65, 75, 75,
++   75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75,  2,  2,  2,  2,
++    2,  2,  2,  2, 75, 75, 75, 75,  2,  2,  2,  2,  2,  2, 69, 69,
++   69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69,  0, 69, 74, 74,
++   74, 74, 74, 74, 74, 74, 74, 74, 74, 74,  2,  2,  2,  2,  2,  2,
++    2,  2,  2,  2,  2, 74, 12, 12, 12, 12, 12,  2,  2,  2, 84, 84,
++   84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84,  2,  0, 84, 84,
++    2,  2,  2,  2, 84, 84, 33, 33, 33, 33, 33, 33, 33,  2, 68, 68,
++   68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,  2, 68, 68,
++   68, 68, 68, 68,  2,  2, 68, 68,  2,  2, 68, 68, 68, 68, 92, 92,
++   92, 92, 92, 92, 92, 92, 92, 92, 92,  2,  2,  2,  2,  2,  2,  2,
++    2, 92, 92, 92, 92, 92, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
++   87, 87, 87, 87, 87,  2,  2, 30, 30, 30, 30, 30, 30,  2, 19, 19,
++   19,  0, 19, 19, 19, 19, 19, 19, 19, 19, 19,  9, 19, 19, 19, 19,
++    0,  0,  2,  2,  2,  2, 87, 87, 87, 87, 87, 87,  2,  2, 87, 87,
++    2,  2,  2,  2,  2,  2, 12, 12, 12, 12,  2,  2,  2,  2,  2,  2,
++    2, 12, 12, 12, 12, 12, 13, 13,  2,  2,  2,  2,  2,  2, 19, 19,
++   19, 19, 19, 19, 19,  2,  2,  2,  2,  4,  4,  4,  4,  4,  2,  2,
++    2,  2,  2, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,  2, 14, 14,
++   14, 14, 14,  2, 14,  2, 14, 14,  2, 14, 14,  2, 14, 14,  3,  3,
++    3,  2,  2,  2,  2,  2,  2,  2,  2,  3,  3,  3,  3,  3,  3,  3,
++    3,  3,  3,  3,  0,  0,  2,  2,  3,  3,  3,  3,  3,  3,  2,  2,
++    2,  2,  2,  2,  2,  3,  1,  1,  1,  1,  1,  1,  6,  6,  0,  0,
++    0,  2,  0,  0,  0,  0,  0,  0,  0,  0,  2,  2,  2,  2,  3,  3,
++    3,  3,  3,  2,  3,  3,  3,  3,  3,  3,  3,  2,  2,  0,  2,  0,
++    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 17, 17, 17, 17,
++   17, 17, 17, 17,  0,  0,  2,  2, 12, 12, 12, 12, 12, 12,  2,  2,
++   12, 12, 12,  2,  2,  2,  2,  0,  0,  0,  0,  0,  2,  2, 49, 49,
++   49, 49, 49, 49, 49, 49, 49, 49, 49, 49,  2, 49, 49, 49, 49, 49,
++   49, 49, 49, 49, 49,  2, 49, 49, 49,  2, 49, 49,  2, 49, 49, 49,
++   49, 49, 49, 49,  2,  2, 49, 49, 49,  2,  2,  2,  2,  2,  0,  0,
++    0,  2,  2,  2,  2,  0,  0,  0,  0,  0,  2,  2,  2,  0,  0,  0,
++    0,  0,  0,  2,  2,  2,  9,  2,  2,  2,  2,  2,  2,  2,  0,  0,
++    0,  0,  0,  1,  2,  2, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
++   71, 71, 71,  2,  2,  2, 67, 67, 67, 67, 67, 67, 67, 67, 67,  2,
++    2,  2,  2,  2,  2,  2,  1,  0,  0,  0,  0,  0,  0,  0, 42, 42,
++   42, 42, 42, 42, 42, 42, 42, 42, 42, 42,  2,  2,  2,  2,  2,  2,
++    2,  2,  2, 42, 42, 42, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
++   41,  2,  2,  2,  2,  2,118,118,118,118,118,118,118,118,118,118,
++  118,  2,  2,  2,  2,  2, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
++   53, 53, 53, 53,  2, 53, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
++   59, 59,  2,  2,  2,  2, 59, 59, 59, 59, 59, 59,  2,  2, 40, 40,
++   40, 40, 40, 40, 40, 40, 51, 51, 51, 51, 51, 51, 51, 51, 50, 50,
++   50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,  2,  2, 50, 50,
++    2,  2,  2,  2,  2,  2,135,135,135,135,135,135,135,135,135,135,
++  135,135,  2,  2,  2,  2,106,106,106,106,106,106,106,106,104,104,
++  104,104,104,104,104,104,104,104,104,104,  2,  2,  2,  2,  2,  2,
++    2,  2,  2,  2,  2,104,161,161,161,161,161,161,161,161,161,161,
++  161,  2,161,161,161,161,161,161,161,  2,161,161,  2,161,161,161,
++    2,161,161,161,161,161,161,161,  2,161,161,  2,  2,  2,170,170,
++  170,170,170,170,170,170,170,170,170,170,  2,  2,  2,  2,110,110,
++  110,110,110,110,110,110,110,110,110,110,110,110,110,  2,110,110,
++  110,110,110,110,  2,  2, 19, 19, 19, 19, 19, 19,  2, 19, 19,  2,
++   19, 19, 19, 19, 19, 19, 19, 19, 19,  2,  2,  2,  2,  2, 47, 47,
++   47, 47, 47, 47,  2,  2, 47,  2, 47, 47, 47, 47, 47, 47, 47, 47,
++   47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,  2, 47, 47,  2,
++    2,  2, 47,  2,  2, 47, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
++   81, 81, 81, 81,  2, 81,120,120,120,120,120,120,120,120,116,116,
++  116,116,116,116,116,116,116,116,116,116,116,116,116,  2,  2,  2,
++    2,  2,  2,  2,  2,116,128,128,128,128,128,128,128,128,128,128,
++  128,  2,128,128,  2,  2,  2,  2,  2,128,128,128,128,128, 66, 66,
++   66, 66, 66, 66, 66, 66, 66, 66, 66, 66,  2,  2,  2, 66, 72, 72,
++   72, 72, 72, 72, 72, 72, 72, 72,  2,  2,  2,  2,  2, 72, 98, 98,
++   98, 98, 98, 98, 98, 98, 97, 97, 97, 97, 97, 97, 97, 97,  2,  2,
++    2,  2, 97, 97, 97, 97,  2,  2, 97, 97, 97, 97, 97, 97, 57, 57,
++   57, 57,  2, 57, 57,  2,  2,  2,  2,  2, 57, 57, 57, 57, 57, 57,
++   57, 57,  2, 57, 57, 57,  2, 57, 57, 57, 57, 57, 57, 57, 57, 57,
++   57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57,  2,  2, 57, 57,
++   57,  2,  2,  2,  2, 57, 57,  2,  2,  2,  2,  2,  2,  2, 88, 88,
++   88, 88, 88, 88, 88, 88,117,117,117,117,117,117,117,117,112,112,
++  112,112,112,112,112,112,112,112,112,112,112,112,112,  2,  2,  2,
++    2,112,112,112,112,112, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78,
++   78, 78, 78, 78,  2,  2,  2, 78, 78, 78, 78, 78, 78, 78, 83, 83,
++   83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83,  2,  2, 82, 82,
++   82, 82, 82, 82, 82, 82, 82, 82, 82,  2,  2,  2,  2,  2,122,122,
++  122,122,122,122,122,122,122,122,  2,  2,  2,  2,  2,  2,  2,122,
++  122,122,122,  2,  2,  2,  2,122,122,122,122,122,122,122, 89, 89,
++   89, 89, 89, 89, 89, 89, 89,  2,  2,  2,  2,  2,  2,  2,130,130,
++  130,130,130,130,130,130,130,130,130,  2,  2,  2,  2,  2,  2,  2,
++  130,130,130,130,130,130,144,144,144,144,144,144,144,144,144,144,
++    2,  2,  2,  2,  2,  2,165,165,165,165,165,165,165,165,165,165,
++  165,165,165,165,  2,  2,  2,165,165,165,165,165,165,165,  2,  2,
++    2,  2,  2,  2,165,165,156,156,156,156,156,156,156,156,156,156,
++    2,156,156,156,  2,  2,156,156,  2,  2,  2,  2,  2,  2,  2,  2,
++    3,  3,  3,  2,  2,  2,  2,  2,  2,  2,  3,  3,  3,  3,147,147,
++  147,147,147,147,147,147,148,148,148,148,148,148,148,148,148,148,
++    2,  2,  2,  2,  2,  2,158,158,158,158,158,158,158,158,158,158,
++    2,  2,  2,  2,  2,  2,153,153,153,153,153,153,153,153,153,153,
++  153,153,  2,  2,  2,  2,149,149,149,149,149,149,149,149,149,149,
++  149,149,149,149,149,  2, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
++   94, 94, 94, 94,  2,  2,  2,  2, 94, 94, 94, 94, 94, 94,  2,  2,
++    2,  2,  2,  2,  2, 94, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
++   85,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 85,  2,  2,101,101,
++  101,101,101,101,101,101,101,  2,  2,  2,  2,  2,  2,  2,101,101,
++    2,  2,  2,  2,  2,  2, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
++   96, 96, 96,  2, 96, 96,111,111,111,111,111,111,111,111,111,111,
++  111,111,111,111,111,  2,100,100,100,100,100,100,100,100,  2, 36,
++   36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,  2,  2,  2,108,108,
++  108,108,108,108,108,108,108,108,  2,108,108,108,108,108,108,108,
++    2,  2,  2,  2,  2,  2,129,129,129,129,129,129,129,  2,129,  2,
++  129,129,129,129,  2,129,129,129,129,129,129,129,129,129,129,129,
++  129,129,129,129,  2,129,129,129,  2,  2,  2,  2,  2,  2,109,109,
++  109,109,109,109,109,109,109,109,109,  2,  2,  2,  2,  2,109,109,
++    2,  2,  2,  2,  2,  2,107,107,107,107,  2,107,107,107,107,107,
++  107,107,107,  2,  2,107,107,  2,  2,107,107,107,107,107,107,107,
++  107,107,107,107,107,107,107,  2,107,107,107,107,107,107,107,  2,
++  107,107,  2,107,107,107,107,107,  2,  1,107,107,107,107,107,  2,
++    2,107,107,107,  2,  2,107,  2,  2,  2,  2,  2,  2,107,  2,  2,
++    2,  2,  2,107,107,107,107,107,107,107,  2,  2,107,107,107,107,
++  107,107,107,  2,  2,  2,171,171,171,171,171,171,171,171,171,171,
++    2,171,  2,  2,171,  2,171,171,171,171,171,171,  2,171,171,  2,
++  171,  2,  2,171,  2,171,171,171,171,  2,171,171,171,171,171,  2,
++    2,  2,  2,  2,  2,  2,  2,171,171,  2,  2,  2,  2,  2,137,137,
++  137,137,137,137,137,137,137,137,137,137,  2,137,137,137,137,137,
++    2,  2,  2,  2,  2,  2,124,124,124,124,124,124,124,124,124,124,
++    2,  2,  2,  2,  2,  2,123,123,123,123,123,123,123,123,123,123,
++  123,123,123,123,  2,  2,114,114,114,114,114,114,114,114,114,114,
++  114,114,114,  2,  2,  2,114,114,  2,  2,  2,  2,  2,  2, 32, 32,
++   32, 32, 32,  2,  2,  2,102,102,102,102,102,102,102,102,102,102,
++    2,  2,  2,  2,  2,  2, 33, 33, 33, 33,  2,  2,  2,  2,126,126,
++  126,126,126,126,126,126,126,126,126,  2,  2,126,126,126,126,126,
++  126,126,  2,  2,  2,  2,126,126,126,126,126,126,126,  2,142,142,
++  142,142,142,142,142,142,142,142,142,142,  2,  2,  2,  2,125,125,
++  125,125,125,125,125,125,125,125,125,  2,  2,  2,  2,  2,  2,  2,
++    2,  2,  2,  2,  2,125,154,154,154,154,154,154,154,  2,  2,154,
++    2,  2,154,154,154,154,154,154,154,154,  2,154,154,  2,154,154,
++  154,154,154,154,154,154,154,154,154,154,154,154,  2,154,154,  2,
++    2,154,154,154,154,154,154,154,  2,  2,  2,  2,  2,  2,150,150,
++  150,150,150,150,150,150,  2,  2,150,150,150,150,150,150,150,150,
++  150,150,150,  2,  2,  2,141,141,141,141,141,141,141,141,140,140,
++  140,140,140,140,140,140,140,140,140,  2,  2,  2,  2,  2,121,121,
++  121,121,121,121,121,121,121,  2,  2,  2,  2,  2,  2,  2,  7,  7,
++    2,  2,  2,  2,  2,  2,169,169,169,169,169,169,169,169,169,169,
++    2,  2,  2,  2,  2,  2,133,133,133,133,133,133,133,133,133,  2,
++  133,133,133,133,133,133,133,133,133,133,133,133,133,  2,133,133,
++  133,133,133,133,  2,  2,133,133,133,133,133,  2,  2,  2,134,134,
++  134,134,134,134,134,134,  2,  2,134,134,134,134,134,134,  2,134,
++  134,134,134,134,134,134,134,134,134,134,134,134,134,  2,138,138,
++  138,138,138,138,138,  2,138,138,  2,138,138,138,138,138,138,138,
++  138,138,138,138,138,138,  2,  2,138,  2,138,138,  2,138,138,138,
++    2,  2,  2,  2,  2,  2,143,143,143,143,143,143,  2,143,143,  2,
++  143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,
++  143,143,143,143,143,  2,143,143,  2,143,143,143,143,143,143,  2,
++    2,  2,  2,  2,  2,  2,143,143,  2,  2,  2,  2,  2,  2,145,145,
++  145,145,145,145,145,145,145,  2,  2,  2,  2,  2,  2,  2,163,163,
++  163,163,163,163,163,163,163,  2,163,163,163,163,163,163,163,163,
++  163,  2,  2,  2,163,163,163,163,163,  2,  2,  2,  2,  2, 86,  2,
++    2,  2,  2,  2,  2,  2, 22, 22,  2,  2,  2,  2,  2,  2,  2,  2,
++    2,  2,  2,  2,  2, 22, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63,
++    2,  2,  2,  2,  2,  2, 63, 63, 63, 63, 63, 63, 63,  2, 63, 63,
++   63, 63, 63,  2,  2,  2, 63, 63, 63, 63,  2,  2,  2,  2,157,157,
++  157,157,157,157,157,157,157,157,157,  2,  2,  2,  2,  2, 80, 80,
++   80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,  2,  2, 80, 80,
++   80,  2,  2,  2,  2,  2,127,127,127,127,127,127,127,127,127,127,
++  127,127,127,127,127,  2,166,166,166,166,166,166,166,166,166,166,
++    2,  2,  2,  2,  2,  2, 79,  2,  2,  2,  2,  2,  2,  2,115,115,
++  115,115,115,115,115,115,115,115,115,115,115,115,115,  2,115,115,
++    2,  2,  2,  2,115,115,159,159,159,159,159,159,159,159,159,159,
++  159,159,159,159,159,  2,159,159,  2,  2,  2,  2,  2,  2,103,103,
++  103,103,103,103,103,103,103,103,103,103,103,103,  2,  2,119,119,
++  119,119,119,119,119,119,119,119,119,119,119,119,  2,  2,119,119,
++    2,119,119,119,119,119,  2,  2,  2,  2,  2,119,119,119,167,167,
++  167,167,167,167,167,167,167,167,  2,  2,  2,  2,  2,  2,146,146,
++  146,146,146,146,146,146,146,146,146,  2,  2,  2,  2,  2, 99, 99,
++   99, 99, 99, 99, 99, 99, 99, 99, 99,  2,  2,  2,  2, 99,  2,  2,
++    2,  2,  2,  2,  2, 99,136,139, 13, 13,155,  2,  2,  2,136,136,
++  136,136,136,136,136,136,155,155,155,155,155,155,155,155,155,155,
++  155,155,155,155,  2,  2,  2,  2,  2,  2,  2,  2,  2,155,136,  2,
++    2,  2,  2,  2,  2,  2, 17, 17, 17, 17,  2, 17, 17, 17, 17, 17,
++   17, 17,  2, 17, 17,  2, 17, 15, 15, 15, 15, 15, 15, 15, 17, 17,
++   17,  2,  2,  2,  2,  2,  2,  2, 15,  2,  2,  2,  2,  2, 15, 15,
++   15,  2,  2, 17,  2,  2,  2,  2,  2,  2, 17, 17, 17, 17,139,139,
++  139,139,139,139,139,139,139,139,139,139,  2,  2,  2,  2,105,105,
++  105,105,105,105,105,105,105,105,105,  2,  2,  2,  2,  2,105,105,
++  105,105,105,  2,  2,  2,105,  2,  2,  2,  2,  2,  2,  2,105,105,
++    2,  2,105,105,105,105,  1,  1,  1,  1,  1,  1,  2,  2,  0,  0,
++    0,  0,  0,  0,  0,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,
++    0,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  1,  1,  1,  1,  1,
++    1,  1,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  0,  0,  2,  2,
++    0,  2,  2,  0,  0,  2,  2,  0,  0,  0,  0,  2,  0,  0,  0,  0,
++    2,  0,  2,  0,  0,  0,  0,  0,  0,  0,  2,  0,  0,  0,  0,  0,
++    0,  2,  2,  0,  0,  0,  0,  0,  2,  0,  0,  0,  0,  2,  0,  0,
++    0,  0,  0,  2,  0,  2,  2,  2,  0,  0,  0,  0,  0,  0,  0,  2,
++    0,  0,  0,  0,  0,  0,131,131,131,131,131,131,131,131,131,131,
++  131,131,  2,  2,  2,  2,  2,  2,  2,131,131,131,131,131,  2,131,
++  131,131,131,131,131,131,  2,  2,  2,  2,  2, 19, 19, 19, 56, 56,
++   56, 56, 56, 56, 56,  2, 56,  2,  2, 56, 56, 56, 56, 56, 56, 56,
++    2, 56, 56,  2, 56, 56, 56, 56, 56,  2,  2,  2,  2,  2,  6,  6,
++    6,  6,  6,  6,  2,  2,  2,  2,  2,  2,  2,  2,  2,  6,151,151,
++  151,151,151,151,151,151,151,151,151,151,151,  2,  2,  2,151,151,
++  151,151,151,151,  2,  2,151,151,  2,  2,  2,  2,151,151,160,160,
++  160,160,160,160,160,160,160,160,160,160,160,160,160,  2,152,152,
++  152,152,152,152,152,152,152,152,  2,  2,  2,  2,  2,152,164,164,
++  164,164,164,164,164,164,164,164,  2,  2,  2,  2,  2,  2,168,168,
++  168,168,168,168,168,168,168,168,168,  2,  2,  2,  2,168, 30, 30,
++   30, 30,  2, 30, 30,  2,113,113,113,113,113,113,113,113,113,113,
++  113,113,113,  2,  2,113,113,113,113,113,113,113,113,  2,132,132,
++  132,132,132,132,132,132,132,132,132,132,  2,  2,  2,  2,132,132,
++    2,  2,  2,  2,132,132,  3,  3,  3,  3,  2,  3,  3,  3,  2,  3,
++    3,  2,  3,  2,  2,  3,  2,  3,  3,  3,  3,  3,  3,  3,  3,  3,
++    3,  2,  3,  3,  3,  3,  2,  3,  2,  3,  2,  2,  2,  2,  2,  2,
++    3,  2,  2,  2,  2,  3,  2,  3,  2,  3,  2,  3,  3,  3,  2,  3,
++    2,  3,  2,  3,  2,  3,  2,  3,  3,  3,  3,  2,  3,  2,  3,  3,
++    2,  3,  3,  3,  3,  3,  3,  3,  3,  3,  2,  2,  2,  2,  2,  3,
++    3,  3,  2,  3,  3,  3,  3,  3,  2,  2,  2,  2,  2,  2,  2,  2,
++    2,  2,  2,  2,  0,  0, 15,  0,  0,  2,  2,  2,  2,  2,  2,  2,
++    2,  2,  0,  0,  0,  0,  2,  2,  2,  0,  0,  0,  0,  0,  0,  0,
++    2,  2,  2,  2,  2,  0,  0,  0,  0,  0,  0,  2,  2,  0, 13,  2,
++    2,  2,  2,  2,  2,  2, 13, 13, 13,  2,  2,  2,  2,  2,  2,  0,
++    2,  2,  2,  2,  2,  2,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9,
++    9,  9,  9, 10,  9, 11, 12, 13,  9,  9,  9, 14,  9,  9, 15,  9,
+     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+-    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9, 16, 17,
+-    9,  9,  9,  9,  9,  9,  9,  9,  9,  9, 18, 19, 20,  9, 21,  9,
+     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
++    9,  9, 16, 17,  9,  9,  9,  9, 18,  9,  9,  9,  9,  9, 19, 20,
++   21,  9, 22,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
++    9,  9,  9,  9,  9,  9, 23,  9,  9,  9,  9,  9, 24,  9,  9,  9,
+     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
++    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9, 25,  9,
+     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+-    9,  9,  9,  9,  9,  9,  9,  9,  9,  9, 22,  9,  9,  9,  9,  9,
+     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+@@ -3704,60 +3934,66 @@ _hb_ucd_u8[14752] =
+     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+-    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9, 23, 24,
+-    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  2,  3,  4,
+-    5,  6,  7,  8,  9, 10, 11, 12,  0,  0, 13, 14, 15, 16, 17, 18,
+-   19, 20, 21, 22,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+-    0,  0,  0,  0, 23,  0,  0, 24, 25, 26, 27, 28, 29, 30,  0,  0,
+-   31, 32,  0, 33,  0, 34,  0, 35,  0,  0,  0,  0, 36, 37, 38, 39,
++    9,  9, 26, 27,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
++    1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12,  0,  0, 13, 14,
++   15, 16, 17, 18, 19, 20, 21, 22,  0,  0,  0,  0,  0,  0,  0,  0,
++    0,  0,  0,  0,  0,  0,  0,  0, 23,  0,  0, 24, 25, 26, 27, 28,
++   29, 30,  0,  0, 31, 32,  0, 33,  0, 34,  0, 35,  0,  0,  0,  0,
++   36, 37, 38, 39,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
++    0,  0,  0,  0,  0,  0, 40,  0,  0,  0,  0,  0,  0,  0,  0,  0,
++   41, 42,  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, 40,  0,  0,  0,  0,  0,  0,  0,  0,  0, 41, 42,  0,  0,
++    0,  0,  0,  0,  0,  0, 43, 44,  0, 45,  0,  0,  0,  0,  0,  0,
++   46, 47,  0,  0,  0,  0,  0, 48,  0, 49,  0,  0,  0,  0,  0,  0,
++    0,  0,  0,  0,  0,  0,  0,  0, 50, 51,  0,  0,  0, 52,  0,  0,
++   53,  0,  0,  0,  0,  0,  0,  0, 54,  0,  0,  0,  0,  0,  0,  0,
++   55,  0,  0,  0,  0,  0,  0,  0, 56,  0,  0,  0,  0,  0,  0,  0,
++    0, 57,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
++    0,  0,  0,  0,  0,  0,  0,  0, 58, 59, 60, 61, 62, 63, 64, 65,
++    0,  0,  0,  0,  0,  0, 66,  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,  0,
+-    0,  0, 43, 44,  0, 45,  0,  0,  0,  0,  0,  0, 46, 47,  0,  0,
+-    0,  0,  0, 48,  0, 49,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+-    0,  0,  0,  0, 50, 51,  0,  0,  0, 52,  0,  0, 53,  0,  0,  0,
+-    0,  0,  0,  0, 54,  0,  0,  0,  0,  0,  0,  0, 55,  0,  0,  0,
+-    0,  0,  0,  0, 56,  0,  0,  0,  0,  0,  0,  0,  0, 57,  0,  0,
+     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+-    0,  0,  0,  0, 58, 59, 60, 61, 62, 63, 64, 65,  0,  0,  0,  0,
+-    0,  0, 66,  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, 67, 68,  0, 69, 70,  0,  0,  0,  0,  0,  0,  0,
++    0,  0,  0,  0, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82,
++   83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98,
++   99,100,101,102,103,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
++    0,  0,  0,  0,  0,  0,104,  0,  0,  0,  0,  0,  0,105,106,  0,
++  107,  0,  0,  0,108,  0,109,  0,110,  0,111,112,113,  0,114,  0,
++    0,  0,115,  0,  0,  0,116,  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,117,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
++    0,  0,  0,  0,  0,  0,  0,  0,118,119,120,121,  0,122,123,124,
++  125,126,  0,127,  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,128,129,130,131,132,133,134,135,136,137,138,139,
++  140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,
++  156,157,  0,  0,  0,158,159,160,161,  0,  0,  0,  0,  0,  0,  0,
+     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+-   67, 68,  0, 69, 70,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+-   71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86,
+-   87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,100,101,102,
+-  103,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+-    0,  0,104,  0,  0,  0,  0,  0,  0,105,106,  0,107,  0,  0,  0,
+-  108,  0,109,  0,110,  0,111,112,113,  0,114,  0,  0,  0,115,  0,
+-    0,  0,116,  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,117,  0,  0,
+     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+-    0,  0,  0,  0,118,119,120,121,  0,122,123,124,125,126,  0,127,
++  162,  0,163,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,164,165,  0,
++    0,  0,  0,  0,  0,  0,166,  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,167,  0,  0,  0,168,169,  0,  0,
++  170,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,171,
++    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,172,
+     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+-  128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+-  144,145,146,147,148,149,150,151,152,153,154,155,156,157,  0,  0,
+-    0,158,159,160,161,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+-    0,  0,  0,  0,  0,  0,  0,  0,  0,162,163,  0,  0,  0,  0,  0,
+-    0,  0,164,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
++    0,  0,  0,  0,  0,  0,  0,173,  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,165,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+-    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,166,  0,  0,  0,  0,
+-    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,167,  0,  0,  0,  0,
++    0,  0,  0,  0,  0,  0,174,  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,168,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
++    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,175,  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,169,170,  0,  0,  0,  0,171,172,  0,  0,  0,
+-  173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,
+-  189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,
+-  205,206,  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,  1,  2,  3,  4,
++    0,  0,  0,  0,  0,  0,  0,  0,  0,176,177,  0,  0,  0,  0,178,
++  179,  0,  0,  0,180,181,182,183,184,185,186,187,188,189,190,191,
++  192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
++  208,209,210,211,212,213,  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,
++    1,  2,  3,  4,
+ };
+ static const uint16_t
+-_hb_ucd_u16[10060] =
++_hb_ucd_u16[9668] =
+ {
+      0,   0,   1,   2,   3,   4,   5,   6,   0,   0,   7,   8,   9,  10,  11,  12,
+     13,  13,  13,  14,  15,  13,  13,  16,  17,  18,  19,  20,  21,  22,  13,  23,
+@@ -3776,9 +4012,10 @@ _hb_ucd_u16[10060] =
+    136,  48,  48, 137, 138, 139, 140, 140, 141,  48, 142, 143, 144, 145, 140, 140,
+    146, 147, 148, 149, 150,  48, 151, 152, 153, 154,  32, 155, 156, 157, 140, 140,
+     48,  48, 158, 159, 160, 161, 162, 163, 164, 165,   9,   9, 166,  11,  11, 167,
+-    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 168, 169,  48,  48,
+-   168,  48,  48, 170, 171, 172,  48,  48,  48, 171,  48,  48,  48, 173, 174, 175,
+-    48, 176,   9,   9,   9,   9,   9, 177, 178,  48,  48,  48,  48,  48,  48,  48,
++    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
++    48,  48,  48,  48, 168, 169,  48,  48, 168,  48,  48, 170, 171, 172,  48,  48,
++    48, 171,  48,  48,  48, 173, 174, 175,  48, 176,   9,   9,   9,   9,   9, 177,
++   178,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
+     48,  48,  48,  48,  48,  48, 179,  48, 180, 181,  48,  48,  48,  48, 182, 183,
+     48, 184,  48, 185,  48, 186, 187, 188,  48,  48,  48, 189, 190, 191, 192, 193,
+    194, 192,  48,  48, 195,  48,  48, 196, 197,  48, 198,  48,  48,  48,  48, 199,
+@@ -3791,28 +4028,34 @@ _hb_ucd_u16[10060] =
+    241, 242, 241, 241, 242, 243, 241, 244, 245, 245, 245, 246, 247, 248, 249, 250,
+    251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 261, 262, 263, 264, 265,
+    266, 267, 268, 269, 270, 271, 272, 272, 273, 274, 275, 209, 276, 277, 209, 278,
+-   279, 279, 279, 279, 279, 279, 279, 279, 280, 209, 281, 209, 209, 209, 209, 282,
+-   209, 283, 279, 284, 209, 285, 286, 209, 209, 209, 287, 140, 288, 140, 271, 271,
+-   271, 289, 209, 209, 209, 209, 290, 271, 209, 209, 209, 209, 209, 209, 209, 209,
+-   209, 209, 209, 291, 292, 209, 209, 293, 209, 209, 209, 209, 209, 209, 294, 209,
+-   209, 209, 209, 209, 209, 209, 295, 296, 271, 297, 209, 209, 298, 279, 299, 279,
+-   300, 301, 279, 279, 279, 302, 279, 303, 209, 209, 209, 279, 304, 209, 209, 305,
+-   209, 306, 209, 209, 209, 209, 209, 209,   9,   9,   9,  11,  11,  11, 307, 308,
+-    13,  13,  13,  13,  13,  13, 309, 310,  11,  11, 311,  48,  48,  48, 312, 313,
+-    48, 314, 315, 315, 315, 315,  32,  32, 316, 317, 318, 319, 320, 321, 140, 140,
+-   209, 322, 209, 209, 209, 209, 209, 323, 209, 209, 209, 209, 209, 324, 140, 209,
+-   325, 326, 327, 328, 136,  48,  48,  48,  48, 329, 178,  48,  48,  48,  48, 330,
+-   331,  48,  48, 136,  48,  48,  48,  48, 200, 332,  48,  48, 209, 209, 333,  48,
+-   209, 334, 335, 209, 336, 337, 209, 209, 335, 209, 209, 337, 209, 209, 209, 209,
+-    48,  48,  48,  48, 209, 209, 209, 209,  48, 338,  48,  48,  48,  48,  48,  48,
+-   151, 209, 209, 209, 287,  48,  48, 229, 339,  48, 340, 140,  13,  13, 341, 342,
+-    13, 343,  48,  48,  48,  48, 344, 345,  31, 346, 347, 348,  13,  13,  13, 349,
+-   350, 351, 352, 353, 354, 355, 140, 356, 357,  48, 358, 359,  48,  48,  48, 360,
+-   361,  48,  48, 362, 363, 192,  32, 364,  64,  48, 365,  48, 366, 367,  48, 151,
+-    76,  48,  48, 368, 369, 370, 371, 372,  48,  48, 373, 374, 375, 376,  48, 377,
+-    48,  48,  48, 378, 379, 380, 381, 382, 383, 384, 315,  11,  11, 385, 386,  11,
+-    11,  11,  11,  11,  48,  48, 387, 192,  48,  48, 388,  48, 389,  48,  48, 206,
+-   390, 390, 390, 390, 390, 390, 390, 390, 391, 391, 391, 391, 391, 391, 391, 391,
++   279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279,
++   280, 209, 281, 209, 209, 209, 209, 282, 209, 283, 279, 284, 209, 285, 286, 209,
++   209, 209, 176, 140, 287, 140, 271, 271, 271, 288, 209, 209, 209, 209, 289, 271,
++   209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 290, 291, 209, 209, 292,
++   209, 209, 209, 209, 209, 209, 293, 209, 209, 209, 209, 209, 209, 209, 209, 209,
++   209, 209, 209, 209, 209, 209, 294, 295, 271, 296, 209, 209, 297, 279, 298, 279,
++   209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209,
++   279, 279, 279, 279, 279, 279, 279, 279, 299, 300, 279, 279, 279, 301, 279, 302,
++   209, 209, 209, 279, 303, 209, 209, 304, 209, 305, 209, 209, 209, 209, 209, 209,
++     9,   9,   9,  11,  11,  11, 306, 307,  13,  13,  13,  13,  13,  13, 308, 309,
++    11,  11, 310,  48,  48,  48, 311, 312,  48, 313, 314, 314, 314, 314,  32,  32,
++   315, 316, 317, 318, 319, 320, 140, 140, 209, 321, 209, 209, 209, 209, 209, 322,
++   209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 323, 140, 209,
++   324, 325, 326, 327, 136,  48,  48,  48,  48, 328, 178,  48,  48,  48,  48, 329,
++   330,  48,  48, 136,  48,  48,  48,  48, 200, 331,  48,  48, 209, 209, 332,  48,
++   209, 333, 334, 209, 335, 336, 209, 209, 334, 209, 209, 336, 209, 209, 209, 209,
++    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 209, 209, 209, 209,
++    48, 337,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
++    48,  48,  48,  48,  48,  48,  48,  48, 151, 209, 209, 209, 338,  48,  48, 229,
++   339,  48, 340, 140,  13,  13, 341, 342,  13, 343,  48,  48,  48,  48, 344, 345,
++    31, 346, 347, 348,  13,  13,  13, 349, 350, 351, 352, 353, 354, 355, 140, 356,
++   357,  48, 358, 359,  48,  48,  48, 360, 361,  48,  48, 362, 363, 192,  32, 364,
++    64,  48, 365,  48, 366, 367,  48, 151,  76,  48,  48, 368, 369, 370, 371, 372,
++    48,  48, 373, 374, 375, 376,  48, 377,  48,  48,  48, 378, 379, 380, 381, 382,
++   383, 384, 314,  11,  11, 385, 386,  11,  11,  11,  11,  11,  48,  48, 387, 192,
++    48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 388,  48, 389,  48,  48, 206,
++   390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390,
++   391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391,
+     48,  48,  48,  48,  48,  48, 204,  48,  48,  48,  48,  48,  48, 207, 140, 140,
+    392, 393, 394, 395, 396,  48,  48,  48,  48,  48,  48, 397, 398, 399,  48,  48,
+     48,  48,  48, 400, 209,  48,  48,  48,  48, 401,  48,  48, 402, 140, 140, 403,
+@@ -3823,571 +4066,540 @@ _hb_ucd_u16[10060] =
+    140, 140, 140, 140, 140, 140, 140, 140,  48, 151,  48,  48,  48, 100, 429, 430,
+     48,  48, 431,  48, 432,  48,  48, 433,  48, 434,  48,  48, 435, 436, 140, 140,
+      9,   9, 437,  11,  11,  48,  48,  48,  48, 204, 192,   9,   9, 438,  11, 439,
+-    48,  48, 440,  48,  48,  48, 441, 442, 442, 443, 444, 445, 140, 140, 140, 140,
+-    48,  48,  48, 314,  48, 199, 440, 140, 446,  27,  27, 447, 140, 140, 140, 140,
++    48,  48, 440,  48,  48,  48, 441, 442, 442, 443, 444, 445,  48,  48,  48, 388,
++    48,  48,  48, 313,  48, 199, 440, 140, 446,  27,  27, 447, 140, 140, 140, 140,
+    448,  48,  48, 449,  48, 450,  48, 451,  48, 200, 452, 140, 140, 140,  48, 453,
+     48, 454,  48, 455, 140, 140, 140, 140,  48,  48,  48, 456, 271, 457, 271, 271,
+    458, 459,  48, 460, 461, 462,  48, 463,  48, 464, 140, 140, 465,  48, 466, 467,
+     48,  48,  48, 468,  48, 469,  48, 470,  48, 471, 472, 140, 140, 140, 140, 140,
+     48,  48,  48,  48, 196, 140, 140, 140,   9,   9,   9, 473,  11,  11,  11, 474,
+-    48,  48, 475, 192, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 271, 476,
+-    48,  48, 477, 478, 140, 140, 140, 479,  48, 464, 480,  48,  62, 481, 140,  48,
+-   482, 140, 140,  48, 483, 140,  48, 314, 484,  48,  48, 485, 486, 457, 487, 488,
+-   222,  48,  48, 489, 490,  48, 196, 192, 491,  48, 492, 493, 494,  48,  48, 495,
+-   222,  48,  48, 496, 497, 498, 499, 500,  48,  97, 501, 502, 503, 140, 140, 140,
+-   504, 505, 506,  48,  48, 507, 508, 192, 509,  83,  84, 510, 511, 512, 513, 514,
+-    48,  48,  48, 515, 516, 517, 478, 140,  48,  48,  48, 518, 519, 192, 140, 140,
+-    48,  48, 520, 521, 522, 523, 140, 140,  48,  48,  48, 524, 525, 192, 526, 140,
+-    48,  48, 527, 528, 192, 140, 140, 140,  48, 173, 529, 530, 314, 140, 140, 140,
+-    48,  48, 501, 531, 140, 140, 140, 140, 140, 140,   9,   9,  11,  11, 148, 532,
+-   533, 534,  48, 535, 536, 192, 140, 140, 140, 140, 537,  48,  48, 538, 539, 140,
+-   540,  48,  48, 541, 542, 543,  48,  48, 544, 545, 546,  48,  48,  48,  48, 196,
+-   547, 140, 140, 140, 140, 140, 140, 140,  84,  48, 520, 548, 549, 148, 175, 550,
+-    48, 551, 552, 553, 140, 140, 140, 140, 554,  48,  48, 555, 556, 192, 557,  48,
+-   558, 559, 192, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,  48, 560,
+-   561, 115,  48, 562, 563, 192, 140, 140, 140, 140, 140, 100, 271, 564, 565, 566,
+-    48, 207, 140, 140, 140, 140, 140, 140, 272, 272, 272, 272, 272, 272, 567, 568,
+-    48,  48,  48,  48, 388, 140, 140, 140, 140,  48,  48,  48,  48,  48,  48, 569,
+-    48,  48,  48, 570, 571, 572, 140, 140,  48,  48,  48,  48, 314, 140, 140, 140,
+-    48,  48,  48, 196,  48, 200, 370,  48,  48,  48,  48, 200, 192,  48, 204, 573,
+-    48,  48,  48, 574, 575, 576, 577, 578,  48, 140, 140, 140, 140, 140, 140, 140,
+-   140, 140, 140, 140,   9,   9,  11,  11, 271, 579, 140, 140, 140, 140, 140, 140,
+-    48,  48,  48,  48, 580, 581, 582, 582, 583, 584, 140, 140, 140, 140, 585, 586,
+-    48,  48,  48,  48,  48,  48,  48, 440,  48,  48,  48,  48,  48, 199, 140, 140,
+-   196, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 587,
+-    48,  48, 588, 589, 140, 590, 591,  48,  48,  48,  48,  48,  48,  48,  48, 206,
+-    48,  48,  48,  48,  48,  48,  71, 151, 196, 592, 593, 140, 140, 140, 140, 140,
+-    32,  32, 594,  32, 595, 209, 209, 209, 209, 209, 209, 209, 323, 140, 140, 140,
+-   209, 209, 209, 209, 209, 209, 209, 324, 209, 209, 596, 209, 209, 209, 597, 598,
+-   599, 209, 600, 209, 209, 209, 288, 140, 209, 209, 209, 209, 601, 140, 140, 140,
+-   140, 140, 140, 140, 271, 602, 271, 602, 209, 209, 209, 209, 209, 287, 271, 461,
+-     9, 603,  11, 604, 605, 606, 241,   9, 607, 608, 609, 610, 611,   9, 603,  11,
+-   612, 613,  11, 614, 615, 616, 617,   9, 618,  11,   9, 603,  11, 604, 605,  11,
+-   241,   9, 607, 617,   9, 618,  11,   9, 603,  11, 619,   9, 620, 621, 622, 623,
+-    11, 624,   9, 625, 626, 627, 628,  11, 629,   9, 630,  11, 631, 632, 632, 632,
+-    32,  32,  32, 633,  32,  32, 634, 635, 636, 637,  45, 140, 140, 140, 140, 140,
+-   638, 639, 640, 140, 140, 140, 140, 140, 641, 642, 643,  27,  27,  27, 644, 140,
+-   645, 140, 140, 140, 140, 140, 140, 140,  48,  48, 151, 646, 647, 140, 140, 140,
+-   140,  48, 648, 140,  48,  48, 649, 650, 140, 140, 140, 140, 140,  48, 651, 192,
+-   140, 140, 140, 140, 140, 140, 652, 200,  48,  48,  48,  48, 653, 595, 140, 140,
+-     9,   9, 607,  11, 654, 370, 140, 140, 140, 140, 140, 140, 140, 140, 140, 499,
+-   271, 271, 655, 656, 140, 140, 140, 140, 499, 271, 657, 658, 140, 140, 140, 140,
+-   659,  48, 660, 661, 662, 663, 664, 665, 666, 206, 667, 206, 140, 140, 140, 668,
+-   209, 209, 669, 209, 209, 209, 209, 209, 209, 323, 334, 670, 670, 670, 209, 324,
+-   671, 209, 209, 209, 209, 209, 209, 209, 209, 209, 672, 140, 140, 140, 673, 209,
+-   674, 209, 209, 669, 675, 676, 324, 140, 209, 209, 209, 209, 209, 209, 209, 677,
+-   209, 209, 209, 209, 209, 678, 426, 426, 209, 209, 209, 209, 209, 209, 209, 679,
+-   209, 209, 209, 209, 209, 176, 669, 427, 669, 209, 209, 209, 680, 176, 209, 209,
+-   680, 209, 672, 676, 140, 140, 140, 140, 209, 209, 209, 209, 209, 323, 672, 426,
+-   675, 209, 209, 681, 682, 669, 675, 675, 209, 683, 209, 209, 288, 140, 140, 192,
+-    48,  48,  48,  48,  48,  48, 140, 140,  48,  48,  48, 207,  48,  48,  48,  48,
+-    48, 204,  48,  48,  48,  48,  48,  48,  48,  48, 478,  48,  48,  48,  48,  48,
+-    48,  48,  48,  48,  48,  48, 100,  48,  48,  48,  48,  48,  48, 204, 140, 140,
+-    48, 204, 140, 140, 140, 140, 140, 140,  48,  48,  48,  48,  71,  48,  48,  48,
+-    48,  48,  48, 140, 140, 140, 140, 140, 684, 140, 570, 570, 570, 570, 570, 570,
++    48,  48, 475, 192, 476,   9, 477,  11, 478, 140, 140, 140, 140, 140, 140, 140,
++   140, 140, 140, 140, 140, 140, 271, 479,  48,  48, 480, 481, 482, 140, 140, 483,
++    48, 464, 484,  48,  62, 485, 140,  48, 486, 140, 140,  48, 487, 140,  48, 313,
++   488,  48,  48, 489, 490, 457, 491, 492, 222,  48,  48, 493, 494,  48, 196, 192,
++   495,  48, 496, 497, 498,  48,  48, 499, 222,  48,  48, 500, 501, 502, 503, 504,
++    48,  97, 505, 506, 507, 140, 140, 140, 508, 509, 510,  48,  48, 511, 512, 192,
++   513,  83,  84, 514, 515, 516, 517, 518, 519,  48,  48, 520, 521, 522, 523, 140,
++    48,  48,  48, 524, 525, 526, 481, 140,  48,  48,  48, 527, 528, 192, 140, 140,
++   140, 140, 140, 140, 140, 140, 140, 140,  48,  48, 529, 530, 531, 532, 140, 140,
++    48,  48,  48, 533, 534, 192, 535, 140,  48,  48, 536, 537, 192, 538, 539, 140,
++    48, 540, 541, 542, 313, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
++    48,  48, 505, 543, 140, 140, 140, 140, 140, 140,   9,   9,  11,  11, 148, 544,
++   545, 546,  48, 547, 548, 192, 140, 140, 140, 140, 549,  48,  48, 550, 551, 140,
++   552,  48,  48, 553, 554, 555,  48,  48, 556, 557, 558,  48,  48,  48,  48, 196,
++   559, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,  48,  48, 560, 192,
++    84,  48, 529, 561, 562, 148, 175, 563,  48, 564, 565, 566, 140, 140, 140, 140,
++   567,  48,  48, 568, 569, 192, 570,  48, 571, 572, 192, 140, 140, 140, 140, 140,
++   140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,  48, 573,
++   574, 115,  48, 575, 576, 577, 140, 140, 140, 140, 140, 100, 271, 578, 579, 580,
++    48,  48,  48,  48,  48,  48,  48,  48,  48, 207, 140, 140, 140, 140, 140, 140,
++   272, 272, 272, 272, 272, 272, 581, 582,  48,  48,  48,  48,  48,  48,  48,  48,
++    48,  48,  48,  48, 388, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
++   140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
++   140, 140, 140, 140, 140, 140, 140, 140, 140,  48,  48,  48,  48,  48,  48, 583,
++    48,  48,  48, 584, 585, 586,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
++    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  71,
++    48,  48,  48,  48, 313, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
++    48, 587, 588, 192, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
++    48,  48,  48, 196,  48, 200, 370,  48,  48,  48,  48, 200, 192,  48, 204, 589,
++    48,  48,  48, 590, 591, 592, 593, 594,  48, 140, 140, 140, 140, 140, 140, 140,
++   140, 140, 140, 140, 595,  48, 596, 192, 140, 140, 140, 140, 140, 140, 140, 140,
++   140, 140, 140, 140,   9,   9,  11,  11, 271, 597, 140, 140, 140, 140, 140, 140,
++    48,  48,  48,  48, 598, 599, 600, 600, 601, 602, 140, 140, 140, 140, 603, 604,
++    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 440,
++    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 199, 140, 605,
++   196, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
++   140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 606,
++    48,  48, 607, 608, 140, 609, 610,  48,  48,  48,  48,  48,  48,  48,  48,  48,
++    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 206,
++    48,  48,  48,  48,  48,  48,  71, 151, 196, 611, 612, 140, 140, 140, 140, 140,
++   209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 192,
++   209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 322, 140, 140, 140, 140,
++    32,  32, 613,  32, 614, 209, 209, 209, 209, 209, 209, 209, 322, 140, 140, 140,
++   209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 323,
++   209, 209, 615, 209, 209, 209, 616, 617, 618, 209, 619, 209, 209, 209, 287, 140,
++   209, 209, 209, 209, 620, 140, 140, 140, 140, 140, 140, 140, 271, 621, 271, 621,
++   209, 209, 209, 209, 209, 338, 271, 461, 140, 140, 140, 140, 140, 140, 140, 140,
++     9, 622,  11, 623, 624, 625, 241,   9, 626, 627, 628, 629, 630,   9, 622,  11,
++   631, 632,  11, 633, 634, 635, 636,   9, 637,  11,   9, 622,  11, 623, 624,  11,
++   241,   9, 626, 636,   9, 637,  11,   9, 622,  11, 638,   9, 639, 640, 641, 642,
++    11, 643,   9, 644, 645, 646, 647,  11, 648,   9, 649,  11, 650, 538, 538, 538,
++    32,  32,  32, 651,  32,  32, 652, 653, 654, 655,  45, 140, 140, 140, 140, 140,
++   656, 657, 658, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
++   659, 660, 661,  27,  27,  27, 662, 140, 663, 140, 140, 140, 140, 140, 140, 140,
++    48,  48, 151, 664, 665, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
++   140, 140, 140, 140, 140, 140, 140, 140, 140,  48, 666, 140,  48,  48, 667, 668,
++   140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,  48, 669, 192,
++   140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,  48, 587, 670,
++   140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 671, 200,
++    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 672, 614, 140, 140,
++     9,   9, 626,  11, 673, 370, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
++   140, 140, 140, 140, 140, 140, 140, 503, 271, 271, 674, 675, 140, 140, 140, 140,
++   503, 271, 676, 677, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
++   678,  48, 679, 680, 681, 682, 683, 684, 685, 206, 686, 206, 140, 140, 140, 687,
++   209, 209, 688, 209, 209, 209, 209, 209, 209, 322, 333, 689, 689, 689, 209, 323,
++   690, 209, 209, 209, 209, 209, 209, 209, 209, 209, 691, 140, 140, 140, 692, 209,
++   693, 209, 209, 688, 694, 695, 323, 140, 140, 140, 140, 140, 140, 140, 140, 140,
++   209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 696,
++   209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 697, 426, 426,
++   209, 209, 209, 209, 209, 209, 209, 698, 209, 209, 209, 209, 209, 176, 688, 427,
++   688, 209, 209, 209, 699, 176, 209, 209, 699, 209, 691, 688, 695, 140, 140, 140,
++   209, 209, 209, 209, 209, 322, 691, 426, 700, 209, 209, 209, 701, 702, 176, 694,
++   209, 209, 209, 209, 209, 209, 209, 209, 209, 703, 209, 209, 209, 209, 209, 192,
++    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 140, 140,
++    48,  48,  48, 207,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
++    48, 204,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
++    48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 481,  48,  48,  48,  48,  48,
++    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 100,  48,
++    48,  48,  48,  48,  48, 204, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
++    48, 204, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
++    48,  48,  48,  48,  71,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
++    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 140, 140, 140, 140, 140,
++   704, 140, 584, 584, 584, 584, 584, 584, 140, 140, 140, 140, 140, 140, 140, 140,
+     32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32, 140,
+-   391, 391, 391, 391, 391, 391, 391, 685, 391, 391, 391, 391, 391, 391, 391, 686,
+-     0,   0,   0,   0,   1,   2,   1,   2,   0,   0,   3,   3,   4,   5,   4,   5,
+-     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   6,   0,   0,   7,   0,
+-     8,   8,   8,   8,   8,   8,   8,   9,  10,  11,  12,  11,  11,  11,  13,  11,
+-    14,  14,  14,  14,  14,  14,  14,  14,  15,  14,  14,  14,  14,  14,  14,  14,
+-    14,  14,  14,  16,  17,  18,  17,  17,  19,  20,  21,  21,  22,  21,  23,  24,
+-    25,  26,  27,  27,  28,  29,  27,  30,  27,  27,  27,  27,  27,  31,  27,  27,
+-    32,  33,  33,  33,  34,  27,  27,  27,  35,  35,  35,  36,  37,  37,  37,  38,
+-    39,  39,  40,  41,  42,  43,  44,  27,  45,  46,  27,  27,  27,  27,  47,  27,
+-    48,  48,  48,  48,  48,  49,  50,  48,  51,  52,  53,  54,  55,  56,  57,  58,
+-    59,  60,  61,  62,  63,  64,  65,  66,  67,  68,  69,  70,  71,  72,  73,  74,
+-    75,  76,  77,  78,  79,  80,  81,  82,  83,  84,  85,  86,  87,  88,  89,  90,
+-    91,  92,  93,  94,  95,  96,  97,  98,  99, 100, 101, 102, 103, 104, 105, 106,
+-   107, 108, 109, 109, 110, 111, 112, 109, 113, 114, 115, 116, 117, 118, 119, 120,
+-   121, 122, 122, 123, 122, 124, 125, 125, 126, 127, 128, 129, 130, 131, 125, 125,
+-   132, 132, 132, 132, 133, 132, 134, 135, 132, 133, 132, 136, 136, 137, 125, 125,
+-   138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 139, 140, 139, 139, 141,
+-   142, 142, 142, 142, 142, 142, 142, 142, 143, 143, 143, 143, 144, 145, 143, 143,
+-   144, 143, 143, 146, 147, 148, 143, 143, 143, 147, 143, 143, 143, 149, 143, 150,
+-   143, 151, 152, 152, 152, 152, 152, 153, 154, 154, 154, 154, 154, 154, 154, 154,
+-   155, 156, 157, 157, 157, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167,
+-   168, 168, 168, 168, 168, 169, 170, 170, 171, 172, 173, 173, 173, 173, 173, 174,
+-   173, 173, 175, 154, 154, 154, 154, 176, 177, 178, 179, 179, 180, 181, 182, 183,
+-   184, 184, 185, 184, 186, 187, 168, 168, 188, 189, 190, 190, 190, 191, 190, 192,
+-   193, 193, 194,   8, 195, 125, 125, 125, 196, 196, 196, 196, 197, 196, 196, 198,
+-   199, 199, 199, 199, 200, 200, 200, 201, 202, 202, 202, 203, 204, 205, 205, 205,
+-   206, 139, 139, 207, 208, 209, 210, 211,   4,   4, 212,   4,   4, 213, 214, 215,
+-     4,   4,   4, 216,   8,   8,   8,   8,  11, 217,  11,  11, 217, 218,  11, 219,
+-    11,  11,  11, 220, 220, 221,  11, 222, 223,   0,   0,   0,   0,   0, 224, 225,
+-   226, 227,   0,   0, 228,   8,   8, 229,   0,   0, 230, 231, 232,   0,   4,   4,
+-   233,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+-     0,   0, 234, 125, 235, 125,   0,   0, 236, 236, 236, 236, 236, 236, 236, 236,
+-     0,   0,   0,   0,   0,   0,   0, 237,   0, 238,   0,   0,   0,   0,   0,   0,
+-   239, 239, 239, 239, 239, 239,   4,   4, 240, 240, 240, 240, 240, 240, 240, 241,
+-   139, 139, 140, 242, 242, 242, 243, 244, 143, 245, 246, 246, 246, 246,  14,  14,
+-     0,   0,   0,   0,   0, 247, 125, 125, 248, 249, 248, 248, 248, 248, 248, 250,
+-   248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 251, 125,   0,
+-   252,   0, 253, 254, 255, 256, 256, 256, 256, 257, 258, 259, 259, 259, 259, 260,
+-   261, 262, 262, 263, 142, 142, 142, 142, 264,   0, 262, 262,   0,   0, 265, 259,
+-   142, 264,   0,   0,   0,   0, 142, 266,   0,   0,   0,   0,   0, 259, 259, 267,
+-   259, 259, 259, 259, 259, 268,   0,   0, 248, 248, 248, 248,   0,   0,   0,   0,
+-   269, 269, 269, 269, 269, 269, 269, 269, 270, 269, 269, 269, 271, 272, 272, 272,
+-   273, 273, 273, 273, 273, 273, 273, 273, 273, 273, 274, 125,  14,  14,  14,  14,
+-    14,  14, 275, 275, 275, 275, 275, 276,   0,   0, 277,   4,   4,   4,   4,   4,
+-   278,   4,   4,   4, 279, 280, 125, 281, 282, 282, 283, 284, 285, 285, 285, 286,
+-   287, 287, 287, 287, 288, 289,  48,  48, 290, 290, 291, 292, 292, 293, 142, 294,
+-   295, 295, 295, 295, 296, 297, 138, 298, 299, 299, 299, 300, 301, 302, 138, 138,
+-   303, 303, 303, 303, 304, 305, 306, 307, 308, 309, 246,   4,   4, 310, 311, 152,
+-   152, 152, 152, 152, 306, 306, 312, 313, 142, 142, 314, 142, 315, 142, 142, 316,
+-   125, 125, 125, 125, 125, 125, 125, 125, 248, 248, 248, 248, 248, 248, 317, 248,
+-   248, 248, 248, 248, 248, 318, 125, 125, 319, 320,  21, 321, 322,  27,  27,  27,
+-    27,  27,  27,  27, 323, 324,  27,  27,  27,  27,  27,  27,  27,  27,  27,  27,
+-    27,  27,  27, 325,  27,  27,  27,  27,  27, 326,  27,  27, 327, 125, 125,  27,
+-     8, 284, 328,   0,   0, 329, 330, 331,  27,  27,  27,  27,  27,  27,  27, 332,
+-   333,   0,   1,   2,   1,   2, 334, 258, 259, 335, 142, 264, 336, 337, 338, 339,
+-   340, 341, 342, 343, 344, 344, 125, 125, 341, 341, 341, 341, 341, 341, 341, 345,
+-   346,   0,   0, 347,  11,  11,  11,  11, 348, 349, 350, 125, 125,   0,   0, 351,
+-   352, 353, 354, 354, 354, 355, 356, 357, 358, 358, 359, 360, 361, 362, 362, 363,
+-   364, 365, 366, 366, 367, 368, 125, 125, 369, 369, 369, 369, 369, 370, 370, 370,
+-   371, 372, 373, 374, 374, 375, 374, 376, 377, 377, 378, 379, 379, 379, 380, 381,
+-   381, 382, 383, 384, 125, 125, 125, 125, 385, 385, 385, 385, 385, 385, 385, 385,
+-   385, 385, 385, 386, 385, 387, 388, 125, 389,   4,   4, 390, 125, 125, 125, 125,
+-   391, 392, 392, 393, 394, 395, 396, 396, 397, 398, 399, 125, 125, 125, 400, 401,
+-   402, 403, 404, 405, 125, 125, 125, 125, 406, 406, 407, 408, 407, 409, 407, 407,
+-   410, 411, 412, 413, 414, 414, 415, 415, 416, 416, 125, 125, 417, 417, 418, 419,
+-   420, 420, 420, 421, 422, 423, 424, 425, 426, 427, 428, 125, 125, 125, 125, 125,
+-   429, 429, 429, 429, 430, 125, 125, 125, 431, 431, 431, 432, 431, 431, 431, 433,
+-   434, 434, 435, 436, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,  27,  45,
+-   437, 437, 438, 439, 125, 125, 125, 440, 441, 441, 442, 443, 443, 444, 125, 445,
+-   446, 125, 125, 447, 448, 125, 449, 450, 451, 451, 451, 451, 452, 453, 451, 454,
+-   455, 455, 455, 455, 456, 457, 458, 459, 460, 460, 460, 461, 462, 463, 463, 464,
+-   465, 465, 465, 465, 465, 465, 466, 467, 468, 469, 468, 468, 470, 125, 125, 125,
+-   471, 472, 473, 474, 474, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484,
+-   485, 485, 485, 485, 485, 486, 487, 125, 488, 488, 488, 488, 489, 490, 125, 125,
+-   491, 491, 491, 492, 491, 493, 125, 125, 494, 494, 494, 494, 495, 496, 497, 125,
+-   498, 498, 498, 499, 499, 125, 125, 125, 500, 501, 502, 500, 503, 125, 125, 125,
+-   504, 504, 504, 505, 125, 125, 125, 125, 125, 125, 506, 506, 506, 506, 506, 507,
+-   508, 509, 510, 511, 512, 513, 125, 125, 125, 125, 514, 515, 515, 514, 516, 125,
+-   517, 517, 517, 517, 518, 519, 519, 519, 519, 519, 520, 154, 521, 521, 521, 522,
+-   523, 125, 125, 125, 125, 125, 125, 125, 524, 525, 525, 526, 527, 525, 528, 529,
+-   529, 530, 531, 532, 125, 125, 125, 125, 533, 534, 534, 535, 536, 537, 538, 539,
+-   540, 541, 542, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 543, 544,
+-   545, 546, 545, 547, 545, 548, 125, 125, 125, 125, 125, 549, 550, 550, 550, 551,
+-   552, 552, 552, 552, 552, 552, 552, 552, 552, 553, 125, 125, 125, 125, 125, 125,
+-   552, 552, 552, 552, 552, 552, 554, 555, 552, 552, 552, 552, 556, 125, 125, 125,
+-   125, 557, 557, 557, 557, 557, 557, 558, 559, 559, 559, 559, 559, 559, 559, 559,
+-   559, 559, 559, 559, 559, 560, 125, 125, 561, 561, 561, 561, 561, 561, 561, 561,
+-   561, 561, 561, 561, 562, 125, 125, 125, 275, 275, 275, 275, 275, 275, 275, 275,
+-   275, 275, 275, 563, 564, 565, 566, 567, 567, 567, 567, 568, 569, 570, 571, 572,
+-   573, 573, 573, 573, 574, 575, 576, 577, 573, 125, 125, 125, 125, 125, 125, 125,
+-   125, 125, 125, 125, 578, 578, 578, 578, 578, 579, 125, 125, 125, 125, 125, 125,
+-   580, 580, 580, 580, 581, 580, 580, 580, 582, 580, 125, 125, 125, 125, 583, 584,
+-   585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 586,
+-   587, 587, 587, 587, 587, 587, 587, 587, 587, 587, 587, 587, 587, 588, 125, 125,
+-   589, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 590,
+-   591, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
+-   256, 256, 592, 593, 125, 594, 595, 596, 596, 596, 596, 596, 596, 596, 596, 596,
+-   596, 596, 596, 596, 596, 596, 596, 597, 598, 598, 598, 598, 598, 598, 599, 600,
+-   601, 602, 603, 125, 125, 125, 125, 125,   8,   8, 604,   8, 605,   0,   0,   0,
+-     0,   0,   0,   0, 603, 125, 125, 125,   0,   0,   0,   0,   0,   0,   0, 606,
+-     0,   0, 607,   0,   0,   0, 608, 609, 610,   0, 611,   0,   0,   0, 235, 125,
+-    11,  11,  11,  11, 612, 125, 125, 125, 125, 125, 125, 125,   0, 603,   0, 603,
+-     0,   0,   0,   0,   0, 234,   0, 613,   0,   0,   0,   0,   0, 224,   0,   0,
+-     0, 614, 615, 616, 617,   0,   0,   0, 618, 619,   0, 620, 621, 622,   0,   0,
+-     0,   0, 623,   0,   0,   0,   0,   0,   0,   0,   0,   0, 624,   0,   0,   0,
+-   625, 625, 625, 625, 625, 625, 625, 625, 626, 627, 628, 125, 125, 125, 125, 125,
+-     4, 629, 630, 125, 125, 125, 125, 125, 631, 632, 633,  14,  14,  14, 634, 125,
+-   635, 125, 125, 125, 125, 125, 125, 125, 636, 636, 637, 638, 639, 125, 125, 125,
+-   125, 640, 641, 125, 642, 642, 642, 643, 125, 125, 125, 125, 125, 644, 644, 645,
+-   125, 125, 125, 125, 125, 125, 646, 647, 648, 648, 648, 648, 648, 648, 648, 648,
+-   648, 648, 648, 648, 649, 650, 125, 125, 651, 651, 651, 651, 652, 653, 125, 125,
+-   125, 125, 125, 125, 125, 125, 125, 333,   0,   0,   0, 654, 125, 125, 125, 125,
+-   333,   0,   0, 247, 125, 125, 125, 125, 655,  27, 656, 657, 658, 659, 660, 661,
+-   662, 663, 664, 663, 125, 125, 125, 665,   0,   0, 357,   0,   0,   0,   0,   0,
+-     0, 603, 226, 333, 333, 333,   0, 606,   0,   0, 247, 125, 125, 125, 666,   0,
+-   667,   0,   0, 357, 613, 668, 606, 125,   0,   0,   0,   0,   0, 669, 349, 349,
+-     0,   0,   0,   0,   0,   0,   0, 670,   0,   0,   0,   0,   0, 284, 357, 228,
+-   357,   0,   0,   0, 671, 284,   0,   0, 671,   0, 247, 668, 125, 125, 125, 125,
+-     0,   0,   0,   0,   0, 603, 247, 349, 613,   0,   0, 672, 673, 357, 613, 613,
+-     0, 329,   0,   0, 235, 125, 125, 284, 248, 248, 248, 248, 248, 248, 125, 125,
+-   248, 248, 248, 318, 248, 248, 248, 248, 248, 317, 248, 248, 248, 248, 248, 248,
+-   248, 248, 584, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 674, 248,
+-   248, 248, 248, 248, 248, 317, 125, 125, 248, 317, 125, 125, 125, 125, 125, 125,
+-   248, 248, 248, 248, 675, 248, 248, 248, 248, 248, 248, 125, 125, 125, 125, 125,
+-   676, 125,   0,   0,   0,   0,   0,   0,   8,   8,   8,   8,   8,   8,   8,   8,
+-     8,   8,   8,   8,   8,   8,   8,   0,   0,   0,   0,   0,   1,   2,   2,   2,
+-     2,   2,   3,   0,   0,   0,   4,   0,   2,   2,   2,   2,   2,   3,   2,   2,
+-     2,   2,   5,   0,   2,   5,   6,   0,   7,   7,   7,   7,   8,   9,  10,  11,
+-    12,  13,  14,  15,   8,   8,   8,   8,  16,   8,   8,   8,  17,  18,  18,  18,
+-    19,  19,  19,  19,  19,  20,  19,  19,  21,  22,  22,  22,  22,  22,  22,  22,
+-    22,  23,  21,  22,  22,  22,  23,  21,  24,  25,  25,  25,  25,  25,  25,  25,
+-    25,  25,  12,  12,  25,  25,  26,  27,  25,  28,  12,  12,  29,  30,  29,  31,
+-    29,  29,  32,  32,  29,  29,  29,  29,  31,  29,  33,   7,   7,  34,  29,  29,
+-    35,  29,  29,  29,  29,  29,  29,  30,  36,  36,  36,  37,  36,  36,  36,  36,
+-    36,  36,  38,  39,  40,  40,  40,  40,  41,  12,  12,  12,  42,  42,  42,  42,
+-    42,  42,  43,  44,  45,  45,  45,  45,  45,  45,  45,  46,  45,  45,  45,  47,
+-    48,  48,  48,  48,  48,  48,  48,  49,  36,  36,  38,  12,  29,  29,  29,  50,
+-    51,  12,  29,  29,  52,  29,  29,  29,  53,  53,  53,  53,  54,  55,  53,  53,
+-    53,  56,  53,  53,  57,  58,  57,  59,  59,  57,  57,  57,  57,  57,  60,  57,
+-    61,  62,  63,  57,  57,  59,  59,  64,  12,  65,  12,  66,  57,  62,  57,  57,
+-    57,  57,  57,  64,  67,  67,  68,  69,  70,  71,  71,  71,  71,  71,  72,  71,
+-    72,  73,  74,  72,  68,  69,  70,  74,  75,  12,  67,  76,  12,  77,  71,  71,
+-    71,  68,  12,  12,  78,  78,  79,  80,  80,  79,  79,  79,  79,  79,  81,  79,
+-    81,  78,  82,  79,  79,  80,  80,  82,  83,  12,  12,  12,  79,  84,  79,  79,
+-    82,  12,  78,  79,  85,  85,  86,  87,  87,  86,  86,  86,  86,  86,  88,  86,
+-    88,  85,  89,  86,  86,  87,  87,  89,  12,  85,  12,  90,  86,  91,  86,  86,
+-    86,  86,  12,  12,  92,  93,  94,  92,  95,  96,  97,  95,  98,  99,  94,  92,
+-   100, 100,  96,  92,  94,  92,  95,  96,  99,  98,  12,  12,  12,  92, 100, 100,
+-   100, 100,  94,  12, 101, 101, 101, 102, 102, 101, 101, 101, 101, 101, 102, 101,
+-   101, 101, 103, 101, 101, 102, 102, 103,  12, 104, 105, 106, 101, 107, 101, 101,
+-    12, 108, 101, 101, 109, 109, 109, 110, 110, 109, 109, 109, 109, 109, 110, 109,
+-   109, 111, 112, 109, 109, 110, 110, 112,  12, 113,  12, 113, 109, 114, 109, 109,
+-   111,  12,  12,  12, 115, 115, 115, 116, 116, 115, 115, 115, 115, 115, 115, 115,
+-   115, 116, 116, 115,  12, 115, 115, 115, 115, 117, 115, 115, 118, 118, 119, 119,
+-   119, 120, 121, 119, 119, 119, 119, 119, 122, 119, 119, 123, 119, 120, 124, 125,
+-   119, 126, 119, 119,  12, 121, 119, 119, 121, 127,  12,  12, 128, 129, 129, 129,
+-   129, 129, 129, 129, 129, 129, 130, 131, 129, 129, 129,  12,  12,  12,  12,  12,
+-   132, 133, 134, 135, 135, 135, 135, 135, 135, 136, 135, 135, 135, 135, 135, 137,
+-   135, 138, 135, 134, 135, 135, 137, 135, 139, 139, 139, 139, 139, 139, 140, 139,
+-   139, 139, 139, 141, 140, 139, 139, 139, 139, 139, 139, 142, 139, 143, 144,  12,
+-   145, 145, 145, 145, 146, 146, 146, 146, 146, 147,  12, 148, 146, 146, 149, 146,
+-   150, 150, 150, 150, 151, 151, 151, 151, 151, 151, 152, 153, 151, 154, 152, 153,
+-   152, 153, 151, 154, 152, 153, 151, 151, 151, 154, 151, 151, 151, 151, 154, 155,
+-   151, 151, 151, 156, 151, 151, 153,  12, 157, 157, 157, 157, 157, 158, 157, 158,
+-   159, 159, 159, 159, 160, 160, 160, 160, 160, 160, 160, 161, 162, 162, 162, 162,
+-   162, 162, 163, 164, 162, 162, 165,  12, 166, 166, 166, 166, 166, 167,  12, 168,
+-   169, 169, 169, 169, 169, 170,  12,  12, 171, 171, 171, 171, 171,  12,  12,  12,
+-   172, 172, 172, 173, 173,  12,  12,  12, 174, 174, 174, 174, 174, 174, 174, 175,
+-   174, 174, 175,  12, 176, 177, 178, 178, 178, 178, 179,  12, 178, 178, 178, 178,
+-   178, 178, 180,  12, 178, 178, 181,  12, 159, 182,  12,  12, 183, 183, 183, 183,
+-   183, 183, 183, 184, 183, 183, 183,  12, 185, 183, 183, 183, 186, 186, 186, 186,
+-   186, 186, 186, 187, 186, 188,  12,  12, 189, 189, 189, 189, 189, 189, 189,  12,
+-   189, 189, 190,  12, 189, 189, 191, 192, 193, 193, 193, 193, 193, 193, 193, 194,
+-   195, 195, 195, 195, 195, 195, 195, 196, 195, 195, 195, 197, 195, 195, 198,  12,
+-   195, 195, 195, 198,   7,   7,   7, 199, 200, 200, 200, 200, 200, 200, 200, 201,
+-   200, 200, 200, 202, 203, 203, 203, 203, 204, 204, 204, 204, 204,  12,  12, 204,
+-   205, 205, 205, 205, 205, 205, 206, 205, 205, 205, 207, 208, 209, 209, 209, 209,
+-    19,  19, 210,  12, 146, 146, 211, 212, 203, 203,  12,  12, 213,   7,   7,   7,
+-   214,   7, 215, 216,   0, 215, 217,  12,   2, 218, 219,   2,   2,   2,   2, 220,
+-   221, 218, 222,   2,   2,   2, 223,   2,   2,   2,   2, 224,   8, 225,   8, 225,
+-     8,   8, 226, 226,   8,   8,   8, 225,   8,  15,   8,   8,   8,  10,   8, 227,
+-    10,  15,   8,  14,   0,   0,   0, 228,   0, 229,   0,   0, 230,   0,   0, 231,
+-     0,   0,   0, 232,   2,   2,   2, 233, 234,  12,  12,  12, 235,  12,  12,  12,
+-     0, 236, 237,   0,   4,   0,   0,   0,   0,   0,   0,   4,   2,   2,   5,  12,
+-     0, 232,  12,  12,   0,   0, 232,  12, 238, 238, 238, 238,   0, 239,   0,   0,
+-     0, 240,   0,   0, 241, 241, 241, 241,  18,  18,  18,  18,  18,  12, 242,  18,
+-   243, 243, 243, 243, 243, 243,  12, 244, 245,  12,  12, 244, 151, 154,  12,  12,
+-   151, 154, 151, 154,   0,   0,   0, 246, 247, 247, 247, 247, 247, 247, 248, 247,
+-   247,  12,  12,  12, 247, 249,  12,  12,   0, 250,   0,   0, 251, 247, 252, 253,
+-     0,   0, 247,   0, 254, 255, 255, 255, 255, 255, 255, 255, 255, 256, 257, 258,
+-   259, 260, 260, 260, 260, 260, 260, 260, 260, 260, 261, 259,  12, 262, 263, 263,
+-   263, 263, 263, 263, 264, 150, 150, 150, 150, 150, 150, 265,   0,  12,  12, 131,
+-   150, 150, 150, 266, 260, 260, 260, 261, 260, 260,   0,   0, 267, 267, 267, 267,
+-   267, 267, 267, 268, 267, 269,  12,  12, 270, 270, 270, 270, 271, 271, 271, 271,
+-   271, 271, 271,  12, 272, 272, 272, 272, 272, 272,  12,  12, 237,   2,   2,   2,
+-     2,   2, 231,   2,   2,   2, 273,  12, 274, 275, 276,  12, 277,   2,   2,   2,
+-   278, 278, 278, 278, 278, 278, 278, 279,   0,   0, 246,  12, 280, 280, 280, 280,
+-   280, 280,  12,  12, 281, 281, 281, 281, 281, 282,  12, 283, 281, 281, 282,  12,
+-   284, 284, 284, 284, 284, 284, 284, 285, 286, 286, 286, 286, 286,  12,  12, 287,
+-   150, 150, 150, 288, 289, 289, 289, 289, 289, 289, 289, 290, 289, 289, 291, 292,
+-   145, 145, 145, 293, 294, 294, 294, 294, 294, 295,  12,  12, 294, 294, 294, 296,
+-   294, 294, 296, 294, 297, 297, 297, 297, 298,  12,  12,  12,  12,  12, 299, 297,
+-   300, 300, 300, 300, 300, 301,  12,  12, 155, 154, 155, 154, 155, 154,  12,  12,
+-     2,   2,   3,   2,   2, 302, 303,  12, 300, 300, 300, 304, 300, 300, 304,  12,
+-   150,  12,  12,  12, 150, 265, 305, 150, 150, 150, 150,  12, 247, 247, 247, 249,
+-   247, 247, 249,  12,   2, 273,  12,  12, 306,  22,  12,  24,  25,  26,  25, 307,
+-   308, 309,  25,  25,  50,  12,  12,  12, 310,  29,  29,  29,  29,  29,  29, 311,
+-   312,  29,  29,  29,  29,  29,  12, 310,   7,   7,   7, 313, 232,   0,   0,   0,
+-     0, 232,   0,  12,  29, 314,  29,  29,  29,  29,  29, 315, 316,   0,   0,   0,
+-     0, 317, 260, 260, 260, 260, 260, 318, 319, 150, 319, 150, 319, 150, 319, 288,
+-     0, 232,   0, 232,  12,  12, 316, 246, 320, 320, 320, 321, 320, 320, 320, 320,
+-   320, 322, 320, 320, 320, 320, 322, 323, 320, 320, 320, 324, 320, 320, 322,  12,
+-   232, 131,   0,   0,   0, 131,   0,   0,   8,   8,   8,  14,   0,   0,   0, 234,
+-   325,  12,  12,  12,   0,   0,   0, 326, 327, 327, 327, 327, 327, 327, 327, 328,
+-   329, 329, 329, 329, 330,  12,  12,  12, 215,   0,   0,   0,   0,   0,   0,  12,
+-   331, 331, 331, 331, 331,  12,  12, 332, 333, 333, 333, 333, 333, 333, 334,  12,
+-   335, 335, 335, 335, 335, 335, 336,  12, 337, 337, 337, 337, 337, 337, 337, 338,
+-   339, 339, 339, 339, 339,  12, 339, 339, 339, 340,  12,  12, 341, 341, 341, 341,
+-   342, 342, 342, 342, 343, 343, 343, 343, 343, 343, 343, 344, 343, 343, 344,  12,
+-   345, 345, 345, 345, 345,  12, 345, 345, 345, 345, 345,  12, 346, 346, 346, 346,
+-   346, 346,  12,  12, 347, 347, 347, 347, 347,  12,  12, 348, 349, 349, 350, 349,
+-   350, 351, 349, 349, 351, 349, 349, 349, 351, 349, 351, 352, 353, 353, 353, 353,
+-   353, 354,  12,  12, 353, 355,  12,  12, 353, 353,  12,  12,   2, 274,   2,   2,
+-   356,   2, 273,  12, 357, 358, 359, 357, 357, 357, 357, 357, 357, 360, 361, 362,
+-   363, 363, 363, 363, 363, 364, 363, 363, 365, 365, 365, 365, 366, 366, 366, 366,
+-   366, 366, 366, 367,  12, 368, 366, 366, 369, 369, 369, 369, 370, 371, 372, 369,
+-   373, 373, 373, 373, 373, 373, 373, 374, 375, 375, 375, 375, 375, 375, 376, 377,
+-   378, 378, 378, 378, 379, 379, 379, 379, 379, 379,  12, 379, 380, 379, 379, 379,
+-   381, 382,  12, 381, 381, 383, 383, 381, 381, 381, 381, 381, 381, 384, 385, 386,
+-   381, 381, 387,  12, 388, 388, 388, 388, 389, 389, 389, 389, 390, 390, 390, 390,
+-   390, 391, 392, 390, 390, 391,  12,  12, 393, 393, 393, 393, 393, 394, 395, 393,
+-   396, 396, 396, 396, 396, 397, 396, 396, 398, 398, 398, 398, 399,  12, 398, 398,
+-   400, 400, 400, 400, 401,  12, 402, 403,  12,  12, 402, 400, 404, 404, 404, 404,
+-   404, 404, 405,  12, 406, 406, 406, 406, 407,  12,  12,  12, 407,  12, 408, 406,
+-   409, 409, 409, 409, 409, 409,  12,  12, 409, 409, 410,  12, 411, 411, 411, 411,
+-   411, 411, 412, 413, 413,  12,  12,  12,  12,  12,  12, 414, 415, 415, 415, 415,
+-   415, 415,  12,  12, 416, 416, 416, 416, 416, 416, 417,  12, 418, 418, 418, 418,
+-   418, 418, 419,  12, 420, 420, 420, 420, 420, 420, 420,  12, 421, 421, 421, 421,
+-   421, 422,  12,  12, 423, 423, 423, 423, 423, 423, 423, 424, 425, 423, 423, 423,
+-   423, 424,  12, 426, 427, 427, 427, 427, 428,  12,  12, 429, 430, 430, 430, 430,
+-   430, 430, 431,  12, 430, 430, 432,  12, 433, 433, 433, 433, 433, 434, 433, 433,
+-   433, 433,  12,  12, 435, 435, 435, 435, 435, 436,  12,  12, 437, 437, 437, 437,
+-   118, 119, 119, 119, 119, 127,  12,  12, 438, 438, 438, 438, 439, 438, 438, 438,
+-   440,  12,  12,  12, 441, 442, 443, 444, 441, 441, 441, 444, 441, 441, 445,  12,
+-   446, 446, 446, 446, 446, 446, 447,  12, 446, 446, 448,  12, 449, 450, 449, 451,
+-   451, 449, 449, 449, 449, 449, 452, 449, 452, 450, 453, 449, 449, 451, 451, 454,
+-   455, 456,  12, 450, 449, 457, 449, 455, 449, 455,  12,  12, 458, 458, 458, 458,
+-   458, 458, 458, 459, 460,  12,  12,  12, 461, 461, 461, 461, 461, 461,  12,  12,
+-   461, 461, 462,  12, 463, 463, 463, 463, 463, 464, 463, 463, 463, 463, 463, 464,
+-   465, 465, 465, 465, 465, 466,  12,  12, 465, 465, 467,  12, 178, 178, 178, 180,
+-   468, 468, 468, 468, 468, 468, 469,  12, 470, 470, 470, 470, 470, 470, 471, 472,
+-   470, 470, 470,  12, 470, 471,  12,  12, 473, 473, 473, 473, 473, 473, 473,  12,
+-   474, 474, 474, 474, 475,  12,  12, 476, 477, 478, 479, 477, 477, 480, 477, 477,
+-   477, 477, 477, 477, 477, 481, 482, 477, 477, 478,  12,  12, 477, 477, 483,  12,
+-   484, 484, 485, 484, 484, 484, 484, 484, 484, 486,  12,  12, 487, 487, 487, 487,
+-   487, 487,  12,  12, 488, 488, 488, 488, 489,  12,  12,  12, 490, 490, 490, 490,
+-   490, 490, 491,  12,  53,  53, 492,  12, 493, 493, 494, 493, 493, 493, 493, 493,
+-   493, 495, 493, 493, 493, 496,  12,  12, 493, 493, 493, 497, 498, 498, 498, 498,
+-   499, 498, 498, 498, 498, 498, 500, 498, 498, 501,  12,  12, 502, 503, 504, 502,
+-   502, 502, 502, 502, 502, 503, 505, 504, 502, 502,  12,  12, 502, 502, 506,  12,
+-   507, 508, 509, 507, 507, 507, 507, 507, 507, 507, 507, 510, 508, 507, 511,  12,
+-   507, 507, 512,  12, 513, 513, 513, 513, 513, 513, 514,  12, 515, 515, 515, 515,
+-   516, 515, 515, 515, 515, 515, 517, 518, 515, 515, 519,  12, 520,  12,  12,  12,
+-   100, 100, 100, 100,  96,  12,  12,  98, 521, 521, 521, 521, 521, 521, 522,  12,
+-   521, 521, 521, 523, 521, 524,  12,  12, 521,  12,  12,  12, 525, 525, 525, 525,
+-   526,  12,  12,  12, 527, 527, 527, 527, 527, 528,  12,  12, 529, 529, 529, 529,
+-   529, 530,  12,  12, 272, 272, 531,  12, 532, 532, 532, 532, 532, 532, 532, 533,
+-   532, 532, 534, 535, 536, 536, 536, 536, 536, 536, 536, 537, 536, 536, 538,  12,
+-   539, 539, 539, 539, 539, 539, 539, 540, 539, 540,  12,  12, 541, 541, 541, 541,
+-   541, 542,  12,  12, 541, 541, 543, 541, 543, 541, 541, 541, 541, 541,  12, 544,
+-   545, 545, 545, 545, 545, 545, 546,  12, 547, 547, 547, 547, 547, 547, 548, 549,
+-   547, 547,  12, 549, 550, 551,  12,  12, 249,  12,  12,  12, 552, 552, 552, 552,
+-   552, 552,  12,  12, 553, 553, 553, 553, 553, 554,  12,  12, 552, 552, 555,  12,
+-   260, 556, 260, 557, 558, 255, 255, 255, 559,  12,  12,  12, 560,  12,  12,  12,
+-   256, 561,  12,  12,  12, 260,  12,  12, 562, 562, 562, 562, 562, 562, 562,  12,
+-   563, 563, 563, 563, 563, 563, 564,  12, 563, 563, 563, 565, 563, 563, 565,  12,
+-   563, 563, 566, 563,   0,  12,  12,  12,   7,   7,   7, 567,   7, 199,  12,  12,
+-     0, 246,  12,  12,   0, 232, 316,   0,   0, 568, 228,   0,   0,   0, 568,   7,
+-   213, 569,   7,   0,   0,   0, 570, 228,   8, 225,  12,  12,   0,   0, 234,  12,
+-     0,   0,   0, 229, 571, 572, 316, 229,   0,   0, 240, 316,   0, 316,   0,   0,
+-     0, 240, 232, 316,   0, 229,   0, 229,   0,   0, 240, 232,   0, 573, 239,   0,
+-   229,   0,   0,   0,   0, 246,   0,   0,   0,   0,   0, 239, 574, 574, 574, 574,
+-   574, 574, 574,  12,  12,  12, 575, 574, 576, 574, 574, 574,   2,   2,   2, 273,
+-    12, 275, 273,  12, 241, 577, 241, 241, 241, 241, 578, 241, 579, 580, 577,  12,
+-    19,  19,  19, 581,  12,  12,  12, 582, 583, 583, 583, 583, 583, 583, 583, 584,
+-   583, 583, 583, 585, 583, 583, 585, 586, 587, 587, 587, 587, 587, 587, 587, 588,
+-   589, 589, 589, 589, 589, 589, 590, 591, 592, 592, 592, 592, 592, 592, 593,  12,
+-   151, 154, 151, 594, 151, 151, 151, 154, 595, 595, 595, 595, 595, 596, 595, 595,
+-   595, 597,  12,  12, 598, 598, 598, 598, 598, 598, 598,  12, 598, 598, 599, 600,
+-     0, 234,  12,  12,  29, 414,  29,  29, 601, 602, 414,  29,  50,  29, 603,  12,
+-   604, 310, 603, 414, 601, 602, 603, 603, 601, 602,  50,  29,  50,  29, 414, 605,
+-    29,  29, 606,  29,  29,  29,  29,  12, 414, 414, 606,  29,  51,  12,  12,  12,
+-    12, 239,   0,   0, 607,  12,  12,  12, 246,  12,  12,  12,   0,   0,  12,   0,
+-     0, 232, 131,   0,   0,   0,  12,  12,   0,   0,   0, 240,   0, 246,  12, 239,
+-   608,  12,  12,  12, 247, 247, 609,  12, 610,  12,  12,  12,   0,   0,   0,   0,
+-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 939, 940, 941, 942,
+-   946, 948,   0, 962, 969, 970, 971, 976,1001,1002,1003,1008,   0,1033,1040,1041,
+-  1042,1043,1047,   0,   0,1080,1081,1082,1086,1110,   0,   0,1124,1125,1126,1127,
+-  1131,1133,   0,1147,1154,1155,1156,1161,1187,1188,1189,1193,   0,1219,1226,1227,
+-  1228,1229,1233,   0,   0,1267,1268,1269,1273,1298,   0,1303, 943,1128, 944,1129,
+-   954,1139, 958,1143, 959,1144, 960,1145, 961,1146, 964,1149,   0,   0, 973,1158,
+-   974,1159, 975,1160, 983,1168, 978,1163, 988,1173, 990,1175, 991,1176, 993,1178,
+-   994,1179,   0,   0,1004,1190,1005,1191,1006,1192,1014,1199,1007,   0,   0,   0,
+-  1016,1201,1020,1206,   0,1022,1208,1025,1211,1023,1209,   0,   0,   0,   0,1032,
+-  1218,1037,1223,1035,1221,   0,   0,   0,1044,1230,1045,1231,1049,1235,   0,   0,
+-  1058,1244,1064,1250,1060,1246,1066,1252,1067,1253,1072,1258,1069,1255,1077,1264,
+-  1074,1261,   0,   0,1083,1270,1084,1271,1085,1272,1088,1275,1089,1276,1096,1283,
+-  1103,1290,1111,1299,1115,1118,1307,1120,1309,1121,1310,   0,1053,1239,   0,   0,
+-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1093,1280,   0,   0,   0,
++   391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 705,
++   391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 706,
++     0,   0,   1,   1,   0,   2,   3,   3,   4,   4,   4,   4,   4,   4,   4,   4,
++     4,   4,   4,   4,   4,   5,   0,   6,   7,   7,   7,   8,   9,  10,  11,  12,
++    13,  13,  13,  13,  14,  13,  13,  13,  13,  15,  16,  17,  18,  19,  20,  21,
++    22,  23,  24,  25,  23,  23,  26,  23,  27,  28,  29,  23,  30,  31,  32,  33,
++    34,  35,  36,  37,  38,  23,  23,  39,  40,  40,  41,  42,  43,  44,  45,  46,
++    47,  48,  49,  50,  51,  52,  53,  54,  55,  56,  57,  58,  59,  60,  61,  62,
++    63,  64,  65,  66,  67,  68,  69,  70,  71,  72,  73,  74,  75,  76,  77,  78,
++    79,  80,  81,  82,  83,  84,  85,  82,  86,  86,  87,  88,  89,  90,  91,  82,
++    92,  92,  92,  92,  92,  93,  94,  95,  96,  96,  96,  96,  96,  96,  96,  96,
++    97,  97,  98,  97,  99, 100, 101,  97, 102,  97, 103, 104, 105, 106, 106, 107,
++   108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 109, 110, 110, 111,
++   112, 113, 114, 115, 116, 116, 117, 118, 119, 120, 120, 121, 120, 122, 108, 123,
++   124, 125, 126, 127, 128, 129, 130, 116, 131, 132, 133, 134, 135, 136, 137,  82,
++   138, 138, 139, 138, 140, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150,
++     4, 151, 152, 153,   4, 154,   7,   7, 155,  11, 156, 157,  11, 158, 159, 160,
++   161,   0,   0, 162, 163,   0, 164, 165,   0, 166, 167,   4, 168,   0,   0,   0,
++     0,   0,   0,   0,   0,   0,   0,   0,   0, 169, 170,   0,   0,   0,   0,   0,
++   171, 171, 171, 171, 171, 171, 171, 171,   0,   0,   0, 172, 173,   0,   0,   0,
++   174, 174, 174,   4, 175, 175, 175, 176,  93, 177, 178, 179, 180, 181, 181,  13,
++     0,   0, 182,  82, 183, 184, 184, 185, 184, 184, 184, 184, 184, 184, 186, 187,
++   188, 189, 190, 191, 192, 193, 194, 195, 196, 197,  96,  96, 198, 199,   0, 200,
++   201,   0,   0, 202,   0,   0, 203, 204, 194, 194, 205,   0,   0,   0,   0,   0,
++   184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184,   0,   0,
++   206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, 207, 206, 208, 209,
++   210, 210, 210, 210, 210, 210, 210, 210, 210, 211,  13,  13,  13, 212, 212, 213,
++     0, 214,   4,   4, 215,   4, 216, 217, 218, 219, 220, 221, 222, 222, 223,  40,
++   224, 225, 226, 227, 228, 228, 229, 230, 231, 232, 233,  92, 234, 234, 235, 236,
++   237, 238, 239, 240, 106, 106, 241, 242,  96,  96,  96,  96,  96, 243, 244, 245,
++    82,  82,  82,  82,  82,  82,  82,  82, 184, 184, 184, 246, 184, 184, 247,  82,
++   248, 249, 250,  23,  23,  23, 251,  23,  23,  23,  23,  23,  23,  23,  23,  23,
++    23, 252,  23,  23, 253,  23, 254, 255, 256, 257, 258, 259,  23,  23,  23, 260,
++   261,   1,   1, 262, 263, 201, 264, 265, 266, 267, 268,  82, 269, 269, 269, 270,
++   271, 272,  11,  11, 273, 274, 187, 275,  82,  82,  82,  82, 276, 277, 278, 279,
++   280, 281, 282, 283, 284, 285, 286,  82, 287, 287, 288, 289, 290, 291, 292, 293,
++   294, 295, 296, 297, 298, 299, 300, 301, 302, 302, 302, 302, 302, 302, 302, 302,
++   302, 303, 304, 305, 306, 307,  82,  82, 308, 309, 310, 311, 312, 313,  82, 314,
++   315, 316,  82,  82, 317, 318, 319, 320, 321, 322, 323, 324, 325,  82, 326, 327,
++   328, 329, 330, 331, 332, 333,  82,  82, 334, 334, 335,  82, 336, 337, 336, 338,
++   339, 340, 341, 342, 343,  82,  82,  82,  82,  82,  82, 344, 345, 346, 347, 348,
++   349, 350, 351, 352, 353, 354, 355, 356, 357, 357, 358, 359, 360, 360, 361, 362,
++   363, 364, 365, 366, 367, 367, 367, 368, 369, 370, 371,  82, 372, 373, 374, 375,
++   376, 377, 378, 379, 380, 381, 382, 383, 384, 384, 385, 386, 387, 387, 388,  82,
++    82,  82,  82,  82, 389, 390, 391,  82, 392, 392, 393, 394, 395, 396, 397, 398,
++   399, 400, 401,  82,  82,  82,  82,  82, 402, 403,  82,  82,  82, 404, 404, 405,
++   406, 407, 408,  82,  82, 409, 410, 411, 412, 412, 413, 414, 414, 415, 416, 417,
++   418,  82,  82,  82,  82,  82, 419, 420, 421, 422, 423, 424, 425, 426,  82,  82,
++   427, 428, 429, 430, 431, 432,  82,  82,  82,  82,  82,  82,  82,  82,  82, 433,
++   434, 435, 436,  82,  82, 437, 438, 439, 440, 440, 440, 440, 440, 440, 440, 440,
++   440, 440, 440, 440, 441,  82,  82,  82, 440, 440, 440, 442, 440, 440, 440, 440,
++   440, 440, 443,  82,  82,  82,  82,  82,  82,  82,  82,  82, 444, 445, 445, 446,
++   447, 447, 447, 447, 447, 447, 447, 447, 447, 447, 448, 447, 447, 447, 447, 447,
++   447, 447, 447, 447, 447, 447, 447, 449, 450, 450, 450, 450, 450, 450, 450, 450,
++   450, 450, 451,  82,  82,  82,  82,  82, 452, 453,  82,  82,  82,  82,  82,  82,
++   212, 212, 212, 212, 212, 212, 212, 212, 212, 454, 455, 456, 457, 458, 459, 460,
++   461, 461, 462, 463, 464,  82,  82,  82,  82,  82, 465, 466,  82,  82,  82,  82,
++    82,  82, 467, 467, 468,  82,  82,  82, 469, 469, 470, 469, 471,  82,  82, 472,
++   473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 473, 474,
++   475, 475, 475, 475, 475, 475, 475, 475, 475, 475, 475, 475, 475, 475, 476, 477,
++   478,  82,  82,  82,  82,  82,  82,  82,  82,  82,  82,  82,  82,  82,  82, 479,
++   480, 191, 191, 191, 191, 191, 191, 191, 191, 481, 482, 483, 484, 484, 484, 484,
++   484, 484, 484, 484, 484, 484, 484, 485, 486, 486, 486, 487, 488, 489,  82,  82,
++     0,   0,   0,   0,   0,   0,   0, 490,   0,   0,   0,   0,   0, 491,  82,  82,
++     7, 492, 493,   0,   0,   0, 489,  82,   0,   0,   0,   0,   0,   0,   0, 494,
++     0, 495,   0, 496, 497, 498,   0, 170,  11,  11, 499,  82,  82,  82, 491, 491,
++     0,   0, 500, 501,  82,  82,  82,  82,   0,   0, 502,   0, 503, 504, 505,   0,
++   506, 507, 508,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 509,   0,   0,
++     0,   0,   0,   0,   0,   0, 510,   0, 511, 511, 511, 511, 511, 511, 511, 511,
++   511, 511, 511, 511, 512, 513,  82,  82, 514, 515,  82,  82,  82,  82,  82,  82,
++   516, 517,  13, 518, 519,  82,  82,  82, 520, 521, 522,  82,  82,  82,  82,  82,
++    82,  82,  82,  82, 523, 524, 525, 526,  82,  82,  82,  82,  82,  82, 527, 528,
++    82,  82,  82,  82,  82,  82, 529, 530,  82,  82,  82,  82,  82,  82,  82, 531,
++   532, 532, 532, 532, 532, 532, 533,  82, 534, 534, 535,  82,  82,  82,  82,  82,
++    82,  82,  82, 536,   0, 537,  82,  82, 261, 182,  82,  82,  82,  82,  82,  82,
++   538, 539, 540, 541, 542, 543,  82, 544,   0, 545,   0,   0, 491, 546, 547, 494,
++     0,   0,   0,   0,   0, 548,  82, 549, 550, 551, 552, 553,  82,  82,  82,  82,
++     0,   0,   0,   0,   0,   0, 554, 555,   0,   0,   0, 556,   0,   0, 490, 557,
++   545,   0, 558,   0, 559, 560, 561,  82,   0,   0, 491, 562, 563,   0, 564, 565,
++     0,   0,   0,   0, 258,   0,   0, 490, 184, 184, 184, 184, 184, 184, 184,  82,
++   184, 247, 184, 184, 184, 184, 184, 184, 566, 184, 184, 184, 184, 184, 184, 184,
++   184, 184, 184, 184, 184, 567, 184, 184, 184, 184, 184, 184, 184, 184, 184, 568,
++   184, 184, 566,  82,  82,  82,  82,  82, 566,  82,  82,  82,  82,  82,  82,  82,
++   184, 184, 569, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 570,  82,  82,
++   571,   0,   0,   0,  82,  82,  82,  82,   7,   7,   7,   7,   7,   7,   7, 572,
++     0,   0,   0,   0,   1,   2,   2,   3,   0,   4,   0,   4,   2,   2,   5,   2,
++     2,   2,   2,   2,   2,   2,   2,   6,   7,   8,   0,   0,   9,   9,   9,   9,
++     9,   9,  10,  11,  12,  13,  14,  14,  15,  14,  14,  14,  14,  14,  14,  14,
++    16,  17,  14,  14,  18,  18,  18,  18,  19,  18,  18,  18,  18,  18,  20,  21,
++    21,  21,  22,  20,  21,  21,  21,  21,  21,  23,  24,  25,  25,  25,  25,  25,
++    25,  26,  25,  25,  25,  27,  28,  26,  29,  30,  31,  32,  31,  31,  31,  31,
++    33,  34,  35,  31,  31,  31,  36,  31,  31,  31,  31,  29,  37,  38,  37,  37,
++    37,  37,  37,  37,  37,  39,  31,  31,  40,  40,  40,  40,  40,  40,  41,  26,
++    42,  42,  42,  42,  42,  42,  42,  43,  44,  44,  44,  44,  44,  45,  44,  46,
++    47,  47,  47,  48,  37,  49,  31,  31,  31,  50,  51,  31,  52,  31,  31,  31,
++    53,  53,  53,  53,  53,  53,  54,  53,  55,  53,  53,  53,  56,  57,  58,  59,
++    59,  60,  61,  62,  57,  63,  64,  65,  66,  59,  59,  67,  68,  69,  70,  71,
++    71,  72,  73,  74,  69,  75,  76,  77,  78,  71,  79,  26,  80,  81,  82,  83,
++    83,  84,  85,  86,  81,  87,  88,  26,  89,  83,  90,  91,  92,  93,  94,  95,
++    95,  96,  97,  98,  93,  99, 100, 101, 102,  95,  95,  26, 103, 104, 105, 106,
++   107, 104, 108, 109, 104, 105, 110,  26, 111, 108, 108, 112, 113, 114, 115, 113,
++   113, 115, 113, 116, 114, 117, 118, 119, 120, 113, 121, 113, 122, 123, 124, 122,
++   122, 124, 125, 126, 123, 127, 128, 128, 129, 122, 130,  26, 131, 132, 133, 131,
++   131, 131, 131, 131, 132, 133, 134, 131, 135, 131, 131, 131, 136, 137, 138, 139,
++   137, 137, 140, 141, 138, 142, 143, 137, 144, 137, 145,  26, 146, 147, 147, 147,
++   147, 147, 147, 148, 147, 147, 147, 149,  26,  26,  26,  26, 150, 151, 152, 152,
++   153, 152, 152, 154, 155, 156, 152, 157, 158, 158, 158, 158, 158, 159, 158, 158,
++   158, 160, 159, 158, 158, 158, 158, 159, 158, 158, 158, 161, 158, 161, 162, 163,
++   164, 164, 164, 164, 165, 165, 165, 165, 166, 167, 165, 165, 165, 165, 165, 168,
++   169, 169, 169, 169, 170, 170, 170, 170, 170, 171, 172, 171, 170, 171, 170, 170,
++   170, 170, 171, 172, 171, 170, 172, 170, 170, 170, 171, 170, 170, 170, 170, 173,
++   170, 170, 170, 174, 170, 170, 170, 175, 176, 176, 176, 176, 176, 176, 177, 177,
++   178, 178, 178, 178, 179, 179, 179, 180, 181, 181, 181, 181, 181, 182, 181, 183,
++   184, 184, 185, 186, 187, 187, 188,  26, 189, 189, 190,  26, 191, 192, 193,  26,
++   194, 194, 194, 194, 194, 194, 194, 195, 194, 196, 194, 196, 197, 198, 198, 199,
++   198, 198, 198, 198, 198, 198, 198, 200, 198, 201, 178, 178, 178, 178, 202,  26,
++   203, 203, 203, 204, 203, 205, 203, 205, 206, 203, 207, 207, 207, 208, 209,  26,
++   210, 210, 210, 210, 210, 211, 210, 210, 210, 212, 210, 213, 214, 214, 214, 215,
++   216, 216, 216, 216, 216, 216, 216, 217, 216, 216, 216, 218, 216, 219, 216, 219,
++   216, 220,   9,   9,   9, 221,  26,  26, 222, 222, 222, 222, 222, 223, 222, 222,
++   224, 224, 224, 224, 225, 225, 225, 225, 225, 225, 226, 227, 228, 228, 228, 228,
++   228, 228, 228, 229, 228, 230, 231, 231, 231, 231, 231, 231,  18, 232, 165, 165,
++   165, 165, 165, 233, 224,  26, 234,   9, 235, 236, 237, 238, 239, 240,   2,   2,
++     2,   2,   2, 241, 242, 243,   2, 244,   2,   2,   2, 245,  14,  14, 246, 246,
++   246, 246,  14, 247,  14,  14,  14, 246,  14,  14, 248,  14, 248,  14, 249, 250,
++    14,  14, 251, 252,   0, 253,   0,   0, 254,   0, 255, 256,   0, 257,   2, 258,
++   259,  26,   9,   9,   9,   9, 260,  26, 261, 262,   4,   0,   0, 263,   0,   0,
++     2, 264,   0,   0,   0, 265,  26,  26,   0, 266,  26,  26, 267, 267, 267, 267,
++     0,   0, 268,   0,   0,   0, 269,   0, 270, 270, 270, 270,  17,  17,  17,  17,
++    17,  17, 271, 272, 166, 167, 273, 273, 273, 273, 273, 273, 273, 274, 275, 274,
++   170, 170, 172,  26, 172, 172, 172, 172,   0,   0,   0, 276, 277, 277, 277, 278,
++   277, 277, 277, 277, 277, 277, 279,  26, 277, 277, 280,  26,  26,  26,   0,   0,
++   281,   0,   0,   0, 282, 283,   0, 284, 285, 286, 286, 286, 286, 286, 286, 286,
++   286, 286, 287, 288, 289, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 291,
++   292, 293, 293, 293, 293, 293, 294, 169, 169, 295,   0,   0, 293, 293, 293, 293,
++   276, 296, 290, 290, 169, 169, 169, 295, 169, 169, 169, 297,   0,   0, 290, 290,
++   290, 290, 290, 298, 290, 290, 290,   0, 299, 299, 299, 299, 299, 300, 299, 299,
++   301,  26, 302, 302, 302, 302, 302, 302, 303, 303, 303, 303, 303, 304,  26,  26,
++   305, 305, 305, 305, 305, 305, 305,  26, 306,   2,   2,   2,   2, 307,   2,   2,
++     2, 308, 309, 258,  26,  26, 310,   2, 311, 311, 311, 311, 311, 312,   0, 265,
++   313, 313, 313, 313, 313, 313, 313,  26, 314, 314, 314, 314, 315, 316, 314, 317,
++   318, 318, 318, 318, 318, 319, 320, 320, 320, 320, 321, 322, 169, 169, 169, 323,
++   324, 324, 324, 324, 324, 325, 324, 326, 164, 164, 164, 327, 328, 328, 328, 328,
++   328, 328, 329,  26, 328, 330, 328, 331, 332, 332, 332, 332, 333,  26,  26, 334,
++   335, 335, 336,  26, 337, 337, 337,  26, 172, 172,   2,   2,   2,   2,   2, 338,
++   339, 340, 176, 176, 335, 335, 335, 335, 335, 341, 335, 342, 343,  26, 169, 169,
++   295, 344, 169, 169, 169, 169, 169, 343, 277, 280, 277, 277, 277, 277, 277, 345,
++   346,  26, 347, 348,  25,  25, 349, 350, 351,  25,  31,  31, 352,  26, 353,  31,
++    31,  31,  31, 354,  31,  31, 355,  31,  31, 356,  26,  26,  26,  26,  31,  31,
++     9,   9,   0, 265,   9, 357,   0,   0,   0,   0, 358,   0, 257, 359, 360,  31,
++    31,  31,  31, 361, 362,   0,   0,   0, 363, 290, 289, 290, 290, 290, 290, 364,
++   365, 365, 365, 366, 257, 257,  26, 367, 368, 369, 368, 368, 370, 368, 368, 371,
++   368, 372, 368, 372, 368, 368, 368, 368, 368, 368, 368, 373, 374,   0,   0,   0,
++     0,   0, 375,   0,  14, 252,   0, 376, 377,  26,  26,  26,   0,   0,   0, 378,
++   379, 379, 379, 380, 381, 381, 381, 381, 381, 381, 382,  26, 383,   0,   0, 359,
++   384, 384, 384, 384, 385, 386, 387, 387, 387, 388, 389, 389, 389, 389, 389, 390,
++   391, 391, 391, 392, 393, 393, 393, 393, 394, 393, 395,  26, 396, 396, 396, 396,
++   396, 396, 397, 397, 397, 397, 397, 397, 398, 398, 398, 399, 398, 400, 401, 401,
++   401, 401, 402, 401, 401, 401, 401, 402, 403, 403, 403, 403, 403,  26, 404, 404,
++   404, 404, 404, 404, 405, 406, 407, 408, 407, 408, 409, 407, 410, 407, 410, 411,
++   412, 412, 412, 412, 412, 412, 413,  26, 414, 414, 414, 414, 414, 414, 415,  26,
++   414, 414, 416,  26, 414,  26,  26,  26, 417,   2,   2,   2,   2,   2, 418, 419,
++   420, 421, 422, 422, 422, 422, 423, 424, 425, 425, 426, 425, 427, 427, 427, 427,
++   428, 428, 428, 429, 430, 428,  26,  26, 431, 431, 432, 433, 434, 434, 434, 435,
++   436, 436, 436, 437, 438, 438, 438, 438, 439, 439, 439, 440, 439, 439, 441, 439,
++   439, 439, 439, 439, 442, 443, 444, 445, 446, 446, 447, 448, 446, 449, 446, 449,
++   450, 450, 450, 450, 451, 451, 451, 451, 452, 452, 452, 452, 453, 454, 453,  26,
++   455, 455, 455, 455, 455, 455, 456, 457, 458, 458, 459, 458, 460, 460, 461, 460,
++   462, 462, 463, 464,  26, 465,  26,  26, 466, 466, 466, 466, 466, 467,  26,  26,
++   468, 468, 468, 468, 468, 468, 469,  26, 468, 468, 469, 470, 471, 471, 471, 471,
++   471,  26, 471, 472, 473, 473, 473, 473, 474, 475, 473, 473, 474, 476,  26,  26,
++    31,  31,  31,  50, 477, 477, 477, 477, 477, 478, 479,  26, 480,  26,  26,  26,
++    26,  26,  26, 481, 482, 482, 482, 482, 482,  26, 483, 483, 483, 483, 483, 484,
++    26,  26, 485, 485, 485, 486,  26,  26,  26,  26, 487, 487, 487, 488,  26,  26,
++   489, 489, 490,  26, 491, 491, 491, 491, 491, 492, 493, 491, 491, 491, 492, 494,
++   495, 495, 495, 495, 496, 497, 498, 498, 498, 499, 498, 500, 501, 501, 501, 501,
++   501, 501, 502, 501, 501,  26, 503, 503, 503, 503, 504,  26, 505, 505, 505, 505,
++   506, 137, 507,  26, 508, 508, 509, 508, 508, 508, 508, 508, 510,  26,  26,  26,
++   511, 512, 513, 514, 513, 515, 516, 516, 516, 516, 516, 516, 516, 517, 516, 518,
++   519, 520, 521, 522, 522, 523, 524, 525, 520, 526, 527, 528, 529, 530, 530,  26,
++   531, 532, 531, 531, 531, 531, 533, 531, 534, 535, 533, 536, 537,  26,  26,  26,
++   538, 538, 538, 538, 538, 538, 538, 539, 540,  26,  26,  26, 541, 541, 541, 541,
++   541,  26, 541, 542, 543, 543, 543, 543, 543, 543, 544, 543, 543, 543, 543, 544,
++   545, 545, 545, 545, 546,  26, 545, 547, 198, 548,  26,  26, 549, 549, 549, 549,
++   549, 549, 549, 550, 549, 550, 164, 164, 551,  26,  26,  26, 552, 552, 552, 553,
++   552, 554, 552, 552, 555,  26,  26,  26, 556, 556, 556, 556, 556, 556, 556, 557,
++   558, 558, 558, 558, 558, 558, 559, 560, 561, 562, 563, 564, 564, 564, 565, 566,
++   561,  26, 564, 567, 568, 569, 568, 568, 568, 568, 568, 569, 570,  26,  26,  26,
++   571, 571, 571, 571, 571,  26, 572, 572, 572, 572, 572, 572, 573,  26, 178, 178,
++   574, 574, 574, 574, 574, 574, 574, 575,  53, 576,  26,  26, 577, 577, 577, 577,
++   578,  26, 577, 578, 579, 580, 579, 579, 579, 579, 581, 579, 582,  26, 579, 579,
++   579, 583, 584, 584, 584, 584, 585, 584, 584, 586, 587,  26, 588, 589, 590, 590,
++   590, 590, 588, 591, 590,  26, 590, 592, 593, 594, 595, 595, 595, 596, 597, 598,
++   595, 599,  26,  26, 600, 600, 600, 601, 602, 602, 603, 602, 602, 602, 602, 604,
++   602, 602, 602, 605,  26,  26, 606,  26, 108, 108, 108, 108, 108, 108, 607, 608,
++   609, 609, 609, 609, 609, 609, 609, 610, 609, 611, 612,  26, 613,  26,  26,  26,
++    26,  26, 614, 614, 614, 614, 614, 614, 614, 614, 615,  26, 616, 616, 616, 616,
++   616, 616, 617,  26, 616, 616, 616, 618, 619, 619, 619, 619, 620,  26,  26,  26,
++   621, 621, 621, 621, 621, 621, 621, 622, 305, 305, 305, 623, 624, 624, 624, 625,
++   624, 626, 627, 627, 627, 627, 627, 627, 627, 627, 627, 628, 627, 629, 630, 630,
++   630, 631, 631,  26, 632, 632, 632, 632, 633,  26, 632, 634, 634, 632, 632, 635,
++   632, 632,  26,  26, 636, 636, 636, 636, 636, 636, 636, 637, 638, 638, 638, 638,
++   638, 638, 638, 639, 640, 640, 640, 640, 640, 641, 640, 640, 640, 642, 640, 640,
++   643,  26, 345,  26, 644, 644, 644, 644, 644, 644, 644,  26, 645, 645, 645, 645,
++   645, 645, 646,  26,  26,  26,  26, 647, 644, 648,  26,  26,  26,  26, 649, 650,
++   651, 286, 286, 286, 652,  26, 653,  26,  26,  26, 654,  26, 655,  26, 656, 656,
++   656, 656, 656, 656, 656, 656, 656, 657, 658, 658, 658, 658, 658, 659, 658, 660,
++   658, 661, 658, 662, 359,  26,  26,  26,   0,   0,   0, 265,   0,   0, 359,  26,
++     9, 663,   9,   9, 221,  26,   0,   0,   0,   0, 276,  26, 257, 362,   0,   0,
++   664, 665,   0, 666, 667, 668,   0,   0,   0, 669,   0,   0, 246,  26,  26,  26,
++     0,   0, 257,  26,   0,   0,   0, 259,   0,   0, 254,   0,   0,   0,   0, 254,
++   670, 671,   0, 672, 673,   0,   0,   0, 269, 674, 254, 254,   0,   0,   0, 675,
++   676, 677, 678,   0, 276,   0,   0,   0,   0, 268,   0,   0, 679, 679, 679, 679,
++   679, 680,  26, 681, 682, 679,  26,  26,   2,   2,   2, 346, 683, 419,  26,  26,
++   684, 270, 270, 685, 686, 687,  18,  18,  18, 688,  26,  26,  26, 689,  26,  26,
++   690, 690, 690, 690, 690, 691, 690, 692, 690, 693,  26,  26,  26,  26, 694, 694,
++   694, 695,  26,  26, 696, 696, 696, 696, 696, 696, 696, 697,  26,  26, 698, 698,
++   698, 698, 698, 699,  26,  26, 700, 700, 700, 700, 700, 701, 172, 702, 170, 172,
++   703, 703, 703, 703, 704, 703, 705,  26, 706, 706, 706, 706, 706, 707, 706, 708,
++    26,  26, 362,   0,   0,   0, 376,  26, 709,  31,  31,  31, 710, 711, 712, 713,
++   714, 715, 710, 716, 710, 712, 712, 717,  31, 718,  31, 719, 720, 718,  31, 719,
++    26,  26, 721,  26,   0, 359,   0,   0,   0, 257, 362,   0, 362,   0, 362,   0,
++     0, 276,  26,  26, 722,   0,   0,   0, 723,  26,   0,   0,   0,   0,   0, 359,
++     0, 259, 265,  26, 276,  26,  26,  26,   0,   0,   0, 724,   0, 376,   0, 376,
++     0,   0, 257, 725,   0, 359, 259,  26,   0,  26,   0, 265,   0,  26,   0,   0,
++     0, 276,   0, 359, 265,  26,  26,  26,   0, 276,   0, 376,   0, 726,   0,   0,
++   257, 722,   0, 727,   0, 265,   0, 259, 277, 277, 277, 280, 345,  26, 277, 277,
++   728,  26, 277, 277, 277, 729, 277, 277, 277, 277,  26,  26, 730,  26,  26,  26,
++     9,   9,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
++     0,   0,   0,   0, 939, 940, 941, 942, 946, 948,   0, 962, 969, 970, 971, 976,
++  1001,1002,1003,1008,   0,1033,1040,1041,1042,1043,1047,   0,   0,1080,1081,1082,
++  1086,1110,   0,   0,1124,1125,1126,1127,1131,1133,   0,1147,1154,1155,1156,1161,
++  1187,1188,1189,1193,   0,1219,1226,1227,1228,1229,1233,   0,   0,1267,1268,1269,
++  1273,1298,   0,1303, 943,1128, 944,1129, 954,1139, 958,1143, 959,1144, 960,1145,
++   961,1146, 964,1149,   0,   0, 973,1158, 974,1159, 975,1160, 983,1168, 978,1163,
++   988,1173, 990,1175, 991,1176, 993,1178, 994,1179,   0,   0,1004,1190,1005,1191,
++  1006,1192,1014,1199,1007,   0,   0,   0,1016,1201,1020,1206,   0,1022,1208,1025,
++  1211,1023,1209,   0,   0,   0,   0,1032,1218,1037,1223,1035,1221,   0,   0,   0,
++  1044,1230,1045,1231,1049,1235,   0,   0,1058,1244,1064,1250,1060,1246,1066,1252,
++  1067,1253,1072,1258,1069,1255,1077,1264,1074,1261,   0,   0,1083,1270,1084,1271,
++  1085,1272,1088,1275,1089,1276,1096,1283,1103,1290,1111,1299,1115,1118,1307,1120,
++  1309,1121,1310,   0,1053,1239,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
++     0,   0,   0,1093,1280,   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, 949,1134,1010,1195,1050,1236,1090,
+-  1277,1341,1368,1340,1367,1342,1369,1339,1366,   0,1320,1347,1418,1419,1323,1350,
+-     0,   0, 992,1177,1018,1204,1055,1241,1416,1417,1415,1424,1202,   0,   0,   0,
+-   987,1172,   0,   0,1031,1217,1321,1348,1322,1349,1338,1365, 950,1135, 951,1136,
+-   979,1164, 980,1165,1011,1196,1012,1197,1051,1237,1052,1238,1061,1247,1062,1248,
+-  1091,1278,1092,1279,1071,1257,1076,1263,   0,   0, 997,1182,   0,   0,   0,   0,
+-     0,   0, 945,1130, 982,1167,1337,1364,1335,1362,1046,1232,1422,1423,1113,1301,
+-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   8,   9,   0,  10,
+-  1425,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+-     7,   0,   0,   0,   0,   0,   0,   0,   0,   0,   1,   0,   0,   0,   0,   0,
+-     0,1314,1427,   5,1434,1438,1443,   0,1450,   0,1455,1461,1514,   0,   0,   0,
++     0, 949,1134,1010,1195,1050,1236,1090,1277,1341,1368,1340,1367,1342,1369,1339,
++  1366,   0,1320,1347,1418,1419,1323,1350,   0,   0, 992,1177,1018,1204,1055,1241,
++  1416,1417,1415,1424,1202,   0,   0,   0, 987,1172,   0,   0,1031,1217,1321,1348,
++  1322,1349,1338,1365, 950,1135, 951,1136, 979,1164, 980,1165,1011,1196,1012,1197,
++  1051,1237,1052,1238,1061,1247,1062,1248,1091,1278,1092,1279,1071,1257,1076,1263,
++     0,   0, 997,1182,   0,   0,   0,   0,   0,   0, 945,1130, 982,1167,1337,1364,
++  1335,1362,1046,1232,1422,1423,1113,1301,   0,   0,   0,   0,   0,   0,   0,   0,
++     0,   0,   0,   0,   8,   9,   0,  10,1425,   0,   0,   0,   0,   0,   0,   0,
++     0,   0,   0,   0,   0,   0,   0,   0,   7,   0,   0,   0,   0,   0,   0,   0,
++     0,   0,   1,   0,   0,   0,   0,   0,   0,1314,1427,   5,1434,1438,1443,   0,
++  1450,   0,1455,1461,1514,   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,1446,1458,
++  1468,1476,1480,1486,1517,   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,1489,1503,
++  1494,1500,1508,   0,   0,   0,   0,1520,1521,   0,   0,   0,   0,   0,   0,   0,
++     0,   0,   0,   0,1526,1528,   0,1525,   0,   0,   0,1522,   0,   0,   0,   0,
++  1536,1532,1539,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1534,   0,   0,
++     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1556,   0,   0,
++     0,   0,   0,   0,1548,1550,   0,1547,   0,   0,   0,1567,   0,   0,   0,   0,
++  1558,1554,1561,   0,   0,   0,   0,   0,   0,   0,1568,1569,   0,   0,   0,   0,
++     0,   0,   0,   0,   0,1529,1551,   0,   0,   0,   0,   0,   0,   0,   0,   0,
++     0,   0,   0,   0,1523,1545,1524,1546,   0,   0,1527,1549,   0,   0,1570,1571,
++  1530,1552,1531,1553,   0,   0,1533,1555,1535,1557,1537,1559,   0,   0,1572,1573,
++  1544,1566,1538,1560,1540,1562,1541,1563,1542,1564,   0,   0,1543,1565,   0,   0,
++     0,   0,   0,   0,   0,   0,1606,1607,1609,1608,1610,   0,   0,   0,   0,   0,
++     0,   0,   0,   0,1613,   0,1611,   0,   0,   0,   0,   0,   0,   0,   0,   0,
++     0,   0,   0,   0,   0,   0,   0,1612,   0,   0,   0,   0,   0,   0,   0,   0,
++     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1620,   0,   0,
++     0,   0,   0,   0,   0,1623,   0,   0,1624,   0,   0,   0,   0,   0,   0,   0,
++     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1614,1615,1616,1617,
++  1618,1619,1621,1622,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1628,
++  1629,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
++  1625,1626,   0,1627,   0,   0,   0,1634,   0,   0,1635,   0,   0,   0,   0,   0,
++     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1630,1631,1632,
++     0,   0,1633,   0,   0,   0,   0,   0,   0,   0,   0,   0,1639,   0,   0,1638,
++  1640,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
++  1636,1637,   0,   0,   0,   0,   0,   0,1641,   0,   0,   0,   0,   0,   0,   0,
++     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1642,1644,
++  1643,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1645,   0,   0,   0,
++     0,   0,   0,   0,1646,   0,   0,   0,   0,   0,   0,1648,1649,   0,1647,1650,
++     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1651,1653,
++  1652,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1654,   0,
++  1655,1657,1656,   0,   0,   0,   0,1659,   0,   0,   0,   0,   0,   0,   0,   0,
++     0,1660,   0,   0,   0,   0,1661,   0,   0,   0,   0,1662,   0,   0,   0,   0,
++  1663,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1658,   0,   0,
++     0,   0,   0,   0,   0,   0,   0,1664,   0,1665,1673,   0,1674,   0,   0,   0,
++     0,   0,   0,   0,   0,1666,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
++     0,   0,   0,   0,   0,   0,   0,1668,   0,   0,   0,   0,   0,   0,   0,   0,
++     0,1669,   0,   0,   0,   0,1670,   0,   0,   0,   0,1671,   0,   0,   0,   0,
++  1672,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1667,   0,   0,
++     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1675,   0,   0,   0,   0,   0,
++     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1676,   0,1677,   0,1678,   0,
++  1679,   0,1680,   0,   0,   0,1681,   0,   0,   0,   0,   0,   0,   0,   0,   0,
++     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1682,
++     0,1683,   0,   0,1684,1685,   0,1686,   0,   0,   0,   0,   0,   0,   0,   0,
++     0,   0,   0,   0, 953,1138, 955,1140, 956,1141, 957,1142,1324,1351, 963,1148,
++   965,1150, 968,1153, 966,1151, 967,1152,1378,1380,1379,1381, 984,1169, 985,1170,
++  1420,1421, 986,1171, 989,1174, 995,1180, 998,1183, 996,1181, 999,1184,1000,1185,
++  1015,1200,1329,1356,1017,1203,1019,1205,1021,1207,1024,1210,1687,1688,1027,1213,
++  1026,1212,1028,1214,1029,1215,1030,1216,1034,1220,1036,1222,1039,1225,1038,1224,
++  1334,1361,1336,1363,1382,1384,1383,1385,1056,1242,1057,1243,1059,1245,1063,1249,
++  1689,1690,1065,1251,1068,1254,1070,1256,1386,1387,1388,1389,1691,1692,1073,1259,
++  1075,1262,1079,1266,1078,1265,1095,1282,1098,1285,1097,1284,1390,1391,1392,1393,
++  1099,1286,1100,1287,1101,1288,1102,1289,1105,1292,1104,1291,1106,1294,1107,1295,
++  1108,1296,1114,1302,1119,1308,1122,1311,1123,1312,1186,1260,1293,1305,   0,1394,
++     0,   0,   0,   0, 952,1137, 947,1132,1317,1344,1316,1343,1319,1346,1318,1345,
++  1693,1695,1371,1375,1370,1374,1373,1377,1372,1376,1694,1696, 981,1166, 977,1162,
++   972,1157,1326,1353,1325,1352,1328,1355,1327,1354,1697,1698,1009,1194,1013,1198,
++  1054,1240,1048,1234,1331,1358,1330,1357,1333,1360,1332,1359,1699,1700,1396,1401,
++  1395,1400,1398,1403,1397,1402,1399,1404,1094,1281,1087,1274,1406,1411,1405,1410,
++  1408,1413,1407,1412,1409,1414,1109,1297,1117,1306,1116,1304,1112,1300,   0,   0,
++     0,   0,   0,   0,1471,1472,1701,1705,1702,1706,1703,1707,1430,1431,1715,1719,
++  1716,1720,1717,1721,1477,1478,1729,1731,1730,1732,   0,   0,1435,1436,1733,1735,
++  1734,1736,   0,   0,1481,1482,1737,1741,1738,1742,1739,1743,1439,1440,1751,1755,
++  1752,1756,1753,1757,1490,1491,1765,1768,1766,1769,1767,1770,1447,1448,1771,1774,
++  1772,1775,1773,1776,1495,1496,1777,1779,1778,1780,   0,   0,1451,1452,1781,1783,
++  1782,1784,   0,   0,1504,1505,1785,1788,1786,1789,1787,1790,   0,1459,   0,1791,
++     0,1792,   0,1793,1509,1510,1794,1798,1795,1799,1796,1800,1462,1463,1808,1812,
++  1809,1813,1810,1814,1467,  21,1475,  22,1479,  23,1485,  24,1493,  27,1499,  28,
++  1507,  29,   0,   0,1704,1708,1709,1710,1711,1712,1713,1714,1718,1722,1723,1724,
++  1725,1726,1727,1728,1740,1744,1745,1746,1747,1748,1749,1750,1754,1758,1759,1760,
++  1761,1762,1763,1764,1797,1801,1802,1803,1804,1805,1806,1807,1811,1815,1816,1817,
++  1818,1819,1820,1821,1470,1469,1822,1474,1465,   0,1473,1825,1429,1428,1426,  12,
++  1432,   0,  26,   0,   0,1315,1823,1484,1466,   0,1483,1829,1433,  13,1437,  14,
++  1441,1826,1827,1828,1488,1487,1513,  19,   0,   0,1492,1515,1445,1444,1442,  15,
++     0,1831,1832,1833,1502,1501,1516,  25,1497,1498,1506,1518,1457,1456,1454,  17,
++  1453,1313,  11,   3,   0,   0,1824,1512,1519,   0,1511,1830,1449,  16,1460,  18,
++  1464,   4,   0,   0,  30,  31,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
++     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  20,   0,   0,   0,   2,   6,
++     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1834,1835,
+      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+-     0,   0,   0,   0,   0,   0,1446,1458,1468,1476,1480,1486,1517,   0,   0,   0,
++     0,   0,1836,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
++     0,1837,1839,1838,   0,   0,   0,   0,1840,   0,   0,   0,   0,1841,   0,   0,
++  1842,   0,   0,   0,   0,   0,   0,   0,1843,   0,1844,   0,   0,   0,   0,   0,
++     0,   0,   0,   0,   0,1845,   0,   0,1846,   0,   0,1847,   0,1848,   0,   0,
++     0,   0,   0,   0, 937,   0,1850,   0,   0,   0,   0,   0,   0,   0,   0,   0,
++     0,1849, 936, 938,1851,1852,   0,   0,1853,1854,   0,   0,1855,1856,   0,   0,
++     0,   0,   0,   0,1857,1858,   0,   0,1861,1862,   0,   0,1863,1864,   0,   0,
+      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+-     0,   0,   0,   0,   0,   0,1489,1503,1494,1500,1508,   0,   0,   0,   0,1520,
+-  1521,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1526,1528,   0,1525,
+-     0,   0,   0,1522,   0,   0,   0,   0,1536,1532,1539,   0,   0,   0,   0,   0,
+-     0,   0,   0,   0,   0,1534,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+-     0,   0,   0,   0,   0,1556,   0,   0,   0,   0,   0,   0,1548,1550,   0,1547,
+-     0,   0,   0,1567,   0,   0,   0,   0,1558,1554,1561,   0,   0,   0,   0,   0,
+-     0,   0,1568,1569,   0,   0,   0,   0,   0,   0,   0,   0,   0,1529,1551,   0,
+-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1523,1545,1524,1546,
+-     0,   0,1527,1549,   0,   0,1570,1571,1530,1552,1531,1553,   0,   0,1533,1555,
+-  1535,1557,1537,1559,   0,   0,1572,1573,1544,1566,1538,1560,1540,1562,1541,1563,
+-  1542,1564,   0,   0,1543,1565,   0,   0,   0,   0,   0,   0,   0,   0,1606,1607,
+-  1609,1608,1610,   0,   0,   0,   0,   0,   0,   0,   0,   0,1613,   0,1611,   0,
+-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1612,
++  1867,1868,1869,1870,1859,1860,1865,1866,   0,   0,   0,   0,   0,   0,1871,1872,
++  1873,1874,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  32,  33,   0,
+      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+-     0,   0,   0,   0,   0,1620,   0,   0,   0,   0,   0,   0,   0,1623,   0,   0,
+-  1624,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+-     0,   0,   0,   0,1614,1615,1616,1617,1618,1619,1621,1622,   0,   0,   0,   0,
+-     0,   0,   0,   0,   0,   0,   0,1628,1629,   0,   0,   0,   0,   0,   0,   0,
+-     0,   0,   0,   0,   0,   0,   0,   0,1625,1626,   0,1627,   0,   0,   0,1634,
+-     0,   0,1635,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+-     0,   0,   0,   0,   0,1630,1631,1632,   0,   0,1633,   0,   0,   0,   0,   0,
+-     0,   0,   0,   0,1639,   0,   0,1638,1640,   0,   0,   0,   0,   0,   0,   0,
+-     0,   0,   0,   0,   0,   0,   0,   0,1636,1637,   0,   0,   0,   0,   0,   0,
+-  1641,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+-     0,   0,   0,   0,   0,   0,1642,1644,1643,   0,   0,   0,   0,   0,   0,   0,
+-     0,   0,   0,   0,1645,   0,   0,   0,   0,   0,   0,   0,1646,   0,   0,   0,
+-     0,   0,   0,1648,1649,   0,1647,1650,   0,   0,   0,   0,   0,   0,   0,   0,
+-     0,   0,   0,   0,   0,   0,1651,1653,1652,   0,   0,   0,   0,   0,   0,   0,
+-     0,   0,   0,   0,   0,   0,1654,   0,1655,1657,1656,   0,   0,   0,   0,1659,
+-     0,   0,   0,   0,   0,   0,   0,   0,   0,1660,   0,   0,   0,   0,1661,   0,
+-     0,   0,   0,1662,   0,   0,   0,   0,1663,   0,   0,   0,   0,   0,   0,   0,
+-     0,   0,   0,   0,   0,1658,   0,   0,   0,   0,   0,   0,   0,   0,   0,1664,
+-     0,1665,1673,   0,1674,   0,   0,   0,   0,   0,   0,   0,   0,1666,   0,   0,
+-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1668,
+-     0,   0,   0,   0,   0,   0,   0,   0,   0,1669,   0,   0,   0,   0,1670,   0,
+-     0,   0,   0,1671,   0,   0,   0,   0,1672,   0,   0,   0,   0,   0,   0,   0,
+-     0,   0,   0,   0,   0,1667,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+-     0,   0,1675,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+-     0,   0,1676,   0,1677,   0,1678,   0,1679,   0,1680,   0,   0,   0,1681,   0,
++  1875,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
++  1877,   0,1878,   0,1879,   0,1880,   0,1881,   0,1882,   0,1883,   0,1884,   0,
++  1885,   0,1886,   0,1887,   0,1888,   0,   0,1889,   0,1890,   0,1891,   0,   0,
++     0,   0,   0,   0,1892,1893,   0,1894,1895,   0,1896,1897,   0,1898,1899,   0,
++  1900,1901,   0,   0,   0,   0,   0,   0,1876,   0,   0,   0,   0,   0,   0,   0,
++     0,   0,1902,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
++  1904,   0,1905,   0,1906,   0,1907,   0,1908,   0,1909,   0,1910,   0,1911,   0,
++  1912,   0,1913,   0,1914,   0,1915,   0,   0,1916,   0,1917,   0,1918,   0,   0,
++     0,   0,   0,   0,1919,1920,   0,1921,1922,   0,1923,1924,   0,1925,1926,   0,
++  1927,1928,   0,   0,   0,   0,   0,   0,1903,   0,   0,1929,1930,1931,1932,   0,
++     0,   0,1933,   0, 710, 385, 724, 715, 455, 103, 186, 825, 825, 242, 751, 205,
++   241, 336, 524, 601, 663, 676, 688, 738, 411, 434, 474, 500, 649, 746, 799, 108,
++   180, 416, 482, 662, 810, 275, 462, 658, 692, 344, 618, 679, 293, 388, 440, 492,
++   740, 116, 146, 168, 368, 414, 481, 527, 606, 660, 665, 722, 781, 803, 809, 538,
++   553, 588, 642, 758, 811, 701, 233, 299, 573, 612, 487, 540, 714, 779, 232, 267,
++   412, 445, 457, 585, 594, 766, 167, 613, 149, 148, 560, 589, 648, 768, 708, 345,
++   411, 704, 105, 259, 313, 496, 518, 174, 542, 120, 307, 101, 430, 372, 584, 183,
++   228, 529, 650, 697, 424, 732, 428, 349, 632, 355, 517, 110, 135, 147, 403, 580,
++   624, 700, 750, 170, 193, 245, 297, 374, 463, 543, 763, 801, 812, 815, 162, 384,
++   420, 730, 287, 330, 337, 366, 459, 476, 509, 558, 591, 610, 726, 652, 734, 759,
++   154, 163, 198, 473, 683, 697, 292, 311, 353, 423, 572, 494, 113, 217, 259, 280,
++   314, 499, 506, 603, 608, 752, 778, 782, 788, 117, 557, 748, 774, 320, 109, 126,
++   260, 265, 373, 411, 479, 523, 655, 737, 823, 380, 765, 161, 395, 398, 438, 451,
++   502, 516, 537, 583, 791, 136, 340, 769, 122, 273, 446, 727, 305, 322, 400, 496,
++   771, 155, 190, 269, 377, 391, 406, 432, 501, 519, 599, 684, 687, 749, 776, 175,
++   452, 191, 480, 510, 659, 772, 805, 813, 397, 444, 619, 566, 568, 575, 491, 471,
++   707, 111, 636, 156, 153, 288, 346, 578, 256, 435, 383, 729, 680, 767, 694, 295,
++   128, 210,   0,   0, 227,   0, 379,   0,   0, 150, 493, 525, 544, 551, 552, 556,
++   783, 576, 604,   0, 661,   0, 703,   0,   0, 735, 743,   0,   0,   0, 793, 794,
++   795, 808, 741, 773, 118, 127, 130, 166, 169, 177, 207, 213, 215, 226, 229, 268,
++   270, 317, 327, 329, 335, 369, 375, 381, 404, 441, 448, 458, 477, 484, 503, 539,
++   545, 547, 546, 548, 549, 550, 554, 555, 561, 564, 569, 591, 593, 595, 598, 607,
++   620, 625, 625, 651, 690, 695, 705, 706, 716, 717, 733, 735, 777, 786, 790, 315,
++   869, 623,   0,   0, 102, 145, 134, 115, 129, 138, 165, 171, 207, 202, 206, 212,
++   227, 231, 240, 243, 250, 254, 294, 296, 303, 308, 319, 325, 321, 329, 326, 335,
++   341, 357, 360, 362, 370, 379, 388, 389, 393, 421, 424, 438, 456, 454, 458, 465,
++   477, 535, 485, 490, 493, 507, 512, 514, 521, 522, 525, 526, 528, 533, 532, 541,
++   565, 569, 574, 586, 591, 597, 607, 637, 647, 674, 691, 693, 695, 698, 703, 699,
++   705, 704, 702, 706, 709, 717, 728, 736, 747, 754, 770, 777, 783, 784, 786, 787,
++   790, 802, 825, 848, 847, 857,  55,  65,  66, 883, 892, 916, 822, 824,   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,1682,   0,1683,   0,   0,1684,1685,   0,1686,
+-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 953,1138, 955,1140,
+-   956,1141, 957,1142,1324,1351, 963,1148, 965,1150, 968,1153, 966,1151, 967,1152,
+-  1378,1380,1379,1381, 984,1169, 985,1170,1420,1421, 986,1171, 989,1174, 995,1180,
+-   998,1183, 996,1181, 999,1184,1000,1185,1015,1200,1329,1356,1017,1203,1019,1205,
+-  1021,1207,1024,1210,1687,1688,1027,1213,1026,1212,1028,1214,1029,1215,1030,1216,
+-  1034,1220,1036,1222,1039,1225,1038,1224,1334,1361,1336,1363,1382,1384,1383,1385,
+-  1056,1242,1057,1243,1059,1245,1063,1249,1689,1690,1065,1251,1068,1254,1070,1256,
+-  1386,1387,1388,1389,1691,1692,1073,1259,1075,1262,1079,1266,1078,1265,1095,1282,
+-  1098,1285,1097,1284,1390,1391,1392,1393,1099,1286,1100,1287,1101,1288,1102,1289,
+-  1105,1292,1104,1291,1106,1294,1107,1295,1108,1296,1114,1302,1119,1308,1122,1311,
+-  1123,1312,1186,1260,1293,1305,   0,1394,   0,   0,   0,   0, 952,1137, 947,1132,
+-  1317,1344,1316,1343,1319,1346,1318,1345,1693,1695,1371,1375,1370,1374,1373,1377,
+-  1372,1376,1694,1696, 981,1166, 977,1162, 972,1157,1326,1353,1325,1352,1328,1355,
+-  1327,1354,1697,1698,1009,1194,1013,1198,1054,1240,1048,1234,1331,1358,1330,1357,
+-  1333,1360,1332,1359,1699,1700,1396,1401,1395,1400,1398,1403,1397,1402,1399,1404,
+-  1094,1281,1087,1274,1406,1411,1405,1410,1408,1413,1407,1412,1409,1414,1109,1297,
+-  1117,1306,1116,1304,1112,1300,   0,   0,   0,   0,   0,   0,1471,1472,1701,1705,
+-  1702,1706,1703,1707,1430,1431,1715,1719,1716,1720,1717,1721,1477,1478,1729,1731,
+-  1730,1732,   0,   0,1435,1436,1733,1735,1734,1736,   0,   0,1481,1482,1737,1741,
+-  1738,1742,1739,1743,1439,1440,1751,1755,1752,1756,1753,1757,1490,1491,1765,1768,
+-  1766,1769,1767,1770,1447,1448,1771,1774,1772,1775,1773,1776,1495,1496,1777,1779,
+-  1778,1780,   0,   0,1451,1452,1781,1783,1782,1784,   0,   0,1504,1505,1785,1788,
+-  1786,1789,1787,1790,   0,1459,   0,1791,   0,1792,   0,1793,1509,1510,1794,1798,
+-  1795,1799,1796,1800,1462,1463,1808,1812,1809,1813,1810,1814,1467,  21,1475,  22,
+-  1479,  23,1485,  24,1493,  27,1499,  28,1507,  29,   0,   0,1704,1708,1709,1710,
+-  1711,1712,1713,1714,1718,1722,1723,1724,1725,1726,1727,1728,1740,1744,1745,1746,
+-  1747,1748,1749,1750,1754,1758,1759,1760,1761,1762,1763,1764,1797,1801,1802,1803,
+-  1804,1805,1806,1807,1811,1815,1816,1817,1818,1819,1820,1821,1470,1469,1822,1474,
+-  1465,   0,1473,1825,1429,1428,1426,  12,1432,   0,  26,   0,   0,1315,1823,1484,
+-  1466,   0,1483,1829,1433,  13,1437,  14,1441,1826,1827,1828,1488,1487,1513,  19,
+-     0,   0,1492,1515,1445,1444,1442,  15,   0,1831,1832,1833,1502,1501,1516,  25,
+-  1497,1498,1506,1518,1457,1456,1454,  17,1453,1313,  11,   3,   0,   0,1824,1512,
+-  1519,   0,1511,1830,1449,  16,1460,  18,1464,   4,   0,   0,  30,  31,   0,   0,
++     0,1586,   0,1605,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1602,1603,
++  1934,1935,1574,1575,1576,1577,1579,1580,1581,1583,1584,   0,1585,1587,1588,1589,
++  1591,   0,1592,   0,1593,1594,   0,1595,1596,   0,1598,1599,1600,1601,1604,1582,
++  1578,1590,1597,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1936,   0,   0,
++     0,   0,   0,   0,   0,   0,   0,   0,1937,   0,   0,   0,   0,   0,   0,   0,
++     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1938,   0,
++  1939,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1940,
+      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+-     0,   0,  20,   0,   0,   0,   2,   6,   0,   0,   0,   0,   0,   0,   0,   0,
+-     0,   0,   0,   0,   0,   0,1834,1835,   0,   0,   0,   0,   0,   0,   0,   0,
+-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1836,   0,   0,   0,   0,   0,
+-     0,   0,   0,   0,   0,   0,   0,   0,   0,1837,1839,1838,   0,   0,   0,   0,
+-  1840,   0,   0,   0,   0,1841,   0,   0,1842,   0,   0,   0,   0,   0,   0,   0,
+-  1843,   0,1844,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1845,   0,   0,
+-  1846,   0,   0,1847,   0,1848,   0,   0,   0,   0,   0,   0, 937,   0,1850,   0,
+-     0,   0,   0,   0,   0,   0,   0,   0,   0,1849, 936, 938,1851,1852,   0,   0,
+-  1853,1854,   0,   0,1855,1856,   0,   0,   0,   0,   0,   0,1857,1858,   0,   0,
+-  1861,1862,   0,   0,1863,1864,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+-     0,   0,   0,   0,   0,   0,   0,   0,1867,1868,1869,1870,1859,1860,1865,1866,
+-     0,   0,   0,   0,   0,   0,1871,1872,1873,1874,   0,   0,   0,   0,   0,   0,
+-     0,   0,   0,   0,   0,  32,  33,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+-     0,   0,   0,   0,   0,   0,   0,   0,1875,   0,   0,   0,   0,   0,   0,   0,
+-     0,   0,   0,   0,   0,   0,   0,   0,1877,   0,1878,   0,1879,   0,1880,   0,
+-  1881,   0,1882,   0,1883,   0,1884,   0,1885,   0,1886,   0,1887,   0,1888,   0,
+-     0,1889,   0,1890,   0,1891,   0,   0,   0,   0,   0,   0,1892,1893,   0,1894,
+-  1895,   0,1896,1897,   0,1898,1899,   0,1900,1901,   0,   0,   0,   0,   0,   0,
+-  1876,   0,   0,   0,   0,   0,   0,   0,   0,   0,1902,   0,   0,   0,   0,   0,
+-     0,   0,   0,   0,   0,   0,   0,   0,1904,   0,1905,   0,1906,   0,1907,   0,
+-  1908,   0,1909,   0,1910,   0,1911,   0,1912,   0,1913,   0,1914,   0,1915,   0,
+-     0,1916,   0,1917,   0,1918,   0,   0,   0,   0,   0,   0,1919,1920,   0,1921,
+-  1922,   0,1923,1924,   0,1925,1926,   0,1927,1928,   0,   0,   0,   0,   0,   0,
+-  1903,   0,   0,1929,1930,1931,1932,   0,   0,   0,1933,   0, 710, 385, 724, 715,
+-   455, 103, 186, 825, 825, 242, 751, 205, 241, 336, 524, 601, 663, 676, 688, 738,
+-   411, 434, 474, 500, 649, 746, 799, 108, 180, 416, 482, 662, 810, 275, 462, 658,
+-   692, 344, 618, 679, 293, 388, 440, 492, 740, 116, 146, 168, 368, 414, 481, 527,
+-   606, 660, 665, 722, 781, 803, 809, 538, 553, 588, 642, 758, 811, 701, 233, 299,
+-   573, 612, 487, 540, 714, 779, 232, 267, 412, 445, 457, 585, 594, 766, 167, 613,
+-   149, 148, 560, 589, 648, 768, 708, 345, 411, 704, 105, 259, 313, 496, 518, 174,
+-   542, 120, 307, 101, 430, 372, 584, 183, 228, 529, 650, 697, 424, 732, 428, 349,
+-   632, 355, 517, 110, 135, 147, 403, 580, 624, 700, 750, 170, 193, 245, 297, 374,
+-   463, 543, 763, 801, 812, 815, 162, 384, 420, 730, 287, 330, 337, 366, 459, 476,
+-   509, 558, 591, 610, 726, 652, 734, 759, 154, 163, 198, 473, 683, 697, 292, 311,
+-   353, 423, 572, 494, 113, 217, 259, 280, 314, 499, 506, 603, 608, 752, 778, 782,
+-   788, 117, 557, 748, 774, 320, 109, 126, 260, 265, 373, 411, 479, 523, 655, 737,
+-   823, 380, 765, 161, 395, 398, 438, 451, 502, 516, 537, 583, 791, 136, 340, 769,
+-   122, 273, 446, 727, 305, 322, 400, 496, 771, 155, 190, 269, 377, 391, 406, 432,
+-   501, 519, 599, 684, 687, 749, 776, 175, 452, 191, 480, 510, 659, 772, 805, 813,
+-   397, 444, 619, 566, 568, 575, 491, 471, 707, 111, 636, 156, 153, 288, 346, 578,
+-   256, 435, 383, 729, 680, 767, 694, 295, 128, 210,   0,   0, 227,   0, 379,   0,
+-     0, 150, 493, 525, 544, 551, 552, 556, 783, 576, 604,   0, 661,   0, 703,   0,
+-     0, 735, 743,   0,   0,   0, 793, 794, 795, 808, 741, 773, 118, 127, 130, 166,
+-   169, 177, 207, 213, 215, 226, 229, 268, 270, 317, 327, 329, 335, 369, 375, 381,
+-   404, 441, 448, 458, 477, 484, 503, 539, 545, 547, 546, 548, 549, 550, 554, 555,
+-   561, 564, 569, 591, 593, 595, 598, 607, 620, 625, 625, 651, 690, 695, 705, 706,
+-   716, 717, 733, 735, 777, 786, 790, 315, 869, 623,   0,   0, 102, 145, 134, 115,
+-   129, 138, 165, 171, 207, 202, 206, 212, 227, 231, 240, 243, 250, 254, 294, 296,
+-   303, 308, 319, 325, 321, 329, 326, 335, 341, 357, 360, 362, 370, 379, 388, 389,
+-   393, 421, 424, 438, 456, 454, 458, 465, 477, 535, 485, 490, 493, 507, 512, 514,
+-   521, 522, 525, 526, 528, 533, 532, 541, 565, 569, 574, 586, 591, 597, 607, 637,
+-   647, 674, 691, 693, 695, 698, 703, 699, 705, 704, 702, 706, 709, 717, 728, 736,
+-   747, 754, 770, 777, 783, 784, 786, 787, 790, 802, 825, 848, 847, 857,  55,  65,
+-    66, 883, 892, 916, 822, 824,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+-     0,   0,   0,   0,   0,   0,   0,   0,   0,1586,   0,1605,   0,   0,   0,   0,
+-     0,   0,   0,   0,   0,   0,1602,1603,1934,1935,1574,1575,1576,1577,1579,1580,
+-  1581,1583,1584,   0,1585,1587,1588,1589,1591,   0,1592,   0,1593,1594,   0,1595,
+-  1596,   0,1598,1599,1600,1601,1604,1582,1578,1590,1597,   0,   0,   0,   0,   0,
+-     0,   0,   0,   0,   0,   0,1936,   0,1937,   0,   0,   0,   0,   0,   0,   0,
+-     0,   0,   0,   0,   0,   0,   0,1938,   0,   0,   0,   0,   0,   0,   0,   0,
+-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1939,1940,   0,   0,   0,   0,
+-     0,   0,   0,   0,   0,   0,   0,1941,1942,   0,   0,   0,   0,   0,   0,   0,
+-     0,   0,   0,   0,   0,   0,   0,1944,1943,   0,1945,   0,   0,   0,   0,   0,
+-     0,   0,   0,   0,   0,   0,1946,1947,   0,   0,   0,   0,   0,   0,   0,   0,
+-     0,   0,   0,   0,1948,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1949,1950,1951,1952,1953,1954,
+-  1955,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+-     0,   0,   0,   0,   0,   0,   0,1956,1957,1958,1960,1959,1961,   0,   0,   0,
+-     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 106, 104, 107, 826,
+-   114, 118, 119, 121, 123, 124, 127, 125,  34, 830, 130, 131, 132, 137, 827,  35,
+-   133, 139, 829, 142, 143, 112, 144, 145, 924, 151, 152,  37, 157, 158, 159, 160,
+-    38, 165, 166, 169, 171, 172, 173, 174, 176, 177, 178, 179, 181, 182, 182, 182,
+-   833, 468, 184, 185, 834, 187, 188, 189, 196, 192, 194, 195, 197, 199, 200, 201,
+-   203, 204, 204, 206, 208, 209, 211, 218, 213, 219, 214, 216, 153, 234, 221, 222,
+-   223, 220, 225, 224, 230, 835, 235, 236, 237, 238, 239, 244, 836, 837, 247, 248,
+-   249, 246, 251,  39,  40, 253, 255, 255, 838, 257, 258, 259, 261, 839, 262, 263,
+-   301, 264,  41, 266, 270, 272, 271, 841, 274, 842, 277, 276, 278, 281, 282,  42,
+-   283, 284, 285, 286,  43, 843,  44, 289, 290, 291, 293, 934, 298, 845, 845, 621,
+-   300, 300,  45, 852, 894, 302, 304,  46, 306, 309, 310, 312, 316,  48,  47, 317,
+-   846, 318, 323, 324, 325, 324, 328, 329, 333, 331, 332, 334, 335, 336, 338, 339,
+-   342, 343, 347, 351, 849, 350, 348, 352, 354, 359, 850, 361, 358, 356,  49, 363,
+-   365, 367, 364,  50, 369, 371, 851, 376, 386, 378,  53, 381,  52,  51, 140, 141,
+-   387, 382, 614,  78, 388, 389, 390, 394, 392, 856,  54, 399, 396, 402, 404, 858,
+-   405, 401, 407,  55, 408, 409, 410, 413, 859, 415,  56, 417, 860, 418,  57, 419,
+-   422, 424, 425, 861, 840, 862, 426, 863, 429, 431, 427, 433, 437, 441, 438, 439,
+-   442, 443, 864, 436, 449, 450,  58, 454, 453, 865, 447, 460, 866, 867, 461, 466,
+-   465, 464,  59, 467, 470, 469, 472, 828, 475, 868, 478, 870, 483, 485, 486, 871,
+-   488, 489, 872, 873, 495, 497,  60, 498,  61,  61, 504, 505, 507, 508, 511,  62,
+-   513, 874, 515, 875, 518, 844, 520, 876, 877, 878,  63,  64, 528, 880, 879, 881,
+-   882, 530, 531, 531, 533,  66, 534,  67,  68, 884, 536, 538, 541,  69, 885, 549,
+-   886, 887, 556, 559,  70, 561, 562, 563, 888, 889, 889, 567,  71, 890, 570, 571,
+-    72, 891, 577,  73, 581, 579, 582, 893, 587,  74, 590, 592, 596,  75, 895, 896,
+-    76, 897, 600, 898, 602, 605, 607, 899, 900, 609, 901, 611, 853,  77, 615, 616,
+-    79, 617, 252, 902, 903, 854, 855, 621, 622, 731,  80, 627, 626, 628, 164, 629,
+-   630, 631, 633, 904, 632, 634, 639, 640, 635, 641, 646, 651, 638, 643, 644, 645,
+-   905, 907, 906,  81, 653, 654, 656, 911, 657, 908,  82,  83, 909, 910,  84, 664,
+-   665, 666, 667, 669, 668, 671, 670, 674, 672, 673, 675,  85, 677, 678,  86, 681,
+-   682, 912, 685, 686,  87, 689,  36, 913, 914,  88,  89, 696, 702, 709, 711, 915,
+-   712, 713, 718, 719, 917, 831, 721, 720, 723, 832, 725, 728, 918, 919, 739, 742,
+-   744, 920, 745, 753, 756, 757, 755, 760, 761, 921, 762,  90, 764, 922,  91, 775,
+-   279, 780, 923, 925,  92,  93, 785, 926,  94, 927, 787, 787, 789, 928, 792,  95,
+-   796, 797, 798, 800,  96, 929, 802, 804, 806,  97,  98, 807, 930,  99, 931, 932,
+-   933, 814, 100, 816, 817, 818, 819, 820, 821, 935,   0,   0,
++     0,   0,1941,1942,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1943,
++  1944,   0,   0,   0,   0,   0,   0,1945,   0,1946,   0,   0,   0,   0,   0,   0,
++     0,   0,1947,   0,   0,1948,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
++     0,   0,   0,   0,   0,   0,   0,   0,   0,1950,   0,1949,1951,   0,   0,   0,
++     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1953,
++  1952,   0,1954,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1955,1956,
++     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1957,   0,   0,   0,
++     0,   0,   0,   0,   0,1958,1961,1959,1965,1960,1962,1964,1963,   0,   0,   0,
++     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1967,1966,1968,   0,
++     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
++     0,   0,1969,1970,1971,1972,1973,1974,1975,   0,   0,   0,   0,   0,   0,   0,
++     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1976,
++  1977,1978,1980,1979,1981,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
++     0,   0,   0,   0, 106, 104, 107, 826, 114, 118, 119, 121, 123, 124, 127, 125,
++    34, 830, 130, 131, 132, 137, 827,  35, 133, 139, 829, 142, 143, 112, 144, 145,
++   924, 151, 152,  37, 157, 158, 159, 160,  38, 165, 166, 169, 171, 172, 173, 174,
++   176, 177, 178, 179, 181, 182, 182, 182, 833, 468, 184, 185, 834, 187, 188, 189,
++   196, 192, 194, 195, 197, 199, 200, 201, 203, 204, 204, 206, 208, 209, 211, 218,
++   213, 219, 214, 216, 153, 234, 221, 222, 223, 220, 225, 224, 230, 835, 235, 236,
++   237, 238, 239, 244, 836, 837, 247, 248, 249, 246, 251,  39,  40, 253, 255, 255,
++   838, 257, 258, 259, 261, 839, 262, 263, 301, 264,  41, 266, 270, 272, 271, 841,
++   274, 842, 277, 276, 278, 281, 282,  42, 283, 284, 285, 286,  43, 843,  44, 289,
++   290, 291, 293, 934, 298, 845, 845, 621, 300, 300,  45, 852, 894, 302, 304,  46,
++   306, 309, 310, 312, 316,  48,  47, 317, 846, 318, 323, 324, 325, 324, 328, 329,
++   333, 331, 332, 334, 335, 336, 338, 339, 342, 343, 347, 351, 849, 350, 348, 352,
++   354, 359, 850, 361, 358, 356,  49, 363, 365, 367, 364,  50, 369, 371, 851, 376,
++   386, 378,  53, 381,  52,  51, 140, 141, 387, 382, 614,  78, 388, 389, 390, 394,
++   392, 856,  54, 399, 396, 402, 404, 858, 405, 401, 407,  55, 408, 409, 410, 413,
++   859, 415,  56, 417, 860, 418,  57, 419, 422, 424, 425, 861, 840, 862, 426, 863,
++   429, 431, 427, 433, 437, 441, 438, 439, 442, 443, 864, 436, 449, 450,  58, 454,
++   453, 865, 447, 460, 866, 867, 461, 466, 465, 464,  59, 467, 470, 469, 472, 828,
++   475, 868, 478, 870, 483, 485, 486, 871, 488, 489, 872, 873, 495, 497,  60, 498,
++    61,  61, 504, 505, 507, 508, 511,  62, 513, 874, 515, 875, 518, 844, 520, 876,
++   877, 878,  63,  64, 528, 880, 879, 881, 882, 530, 531, 531, 533,  66, 534,  67,
++    68, 884, 536, 538, 541,  69, 885, 549, 886, 887, 556, 559,  70, 561, 562, 563,
++   888, 889, 889, 567,  71, 890, 570, 571,  72, 891, 577,  73, 581, 579, 582, 893,
++   587,  74, 590, 592, 596,  75, 895, 896,  76, 897, 600, 898, 602, 605, 607, 899,
++   900, 609, 901, 611, 853,  77, 615, 616,  79, 617, 252, 902, 903, 854, 855, 621,
++   622, 731,  80, 627, 626, 628, 164, 629, 630, 631, 633, 904, 632, 634, 639, 640,
++   635, 641, 646, 651, 638, 643, 644, 645, 905, 907, 906,  81, 653, 654, 656, 911,
++   657, 908,  82,  83, 909, 910,  84, 664, 665, 666, 667, 669, 668, 671, 670, 674,
++   672, 673, 675,  85, 677, 678,  86, 681, 682, 912, 685, 686,  87, 689,  36, 913,
++   914,  88,  89, 696, 702, 709, 711, 915, 712, 713, 718, 719, 917, 831, 721, 720,
++   723, 832, 725, 728, 918, 919, 739, 742, 744, 920, 745, 753, 756, 757, 755, 760,
++   761, 921, 762,  90, 764, 922,  91, 775, 279, 780, 923, 925,  92,  93, 785, 926,
++    94, 927, 787, 787, 789, 928, 792,  95, 796, 797, 798, 800,  96, 929, 802, 804,
++   806,  97,  98, 807, 930,  99, 931, 932, 933, 814, 100, 816, 817, 818, 819, 820,
++   821, 935,   0,   0,
+ };
+ static const int16_t
+ _hb_ucd_i16[92] =
+@@ -4403,12 +4615,12 @@ _hb_ucd_i16[92] =
+ static inline uint_fast8_t
+ _hb_ucd_gc (unsigned u)
+ {
+-  return u<1114110u?_hb_ucd_u8[6808+(((_hb_ucd_u8[1312+(((_hb_ucd_u16[((_hb_ucd_u8[544+(((_hb_ucd_u8[u>>1>>3>>3>>4])<<4)+((u>>1>>3>>3)&15u))])<<3)+((u>>1>>3)&7u)])<<3)+((u>>1)&7u))])<<1)+((u)&1u))]:2;
++  return u<1114110u?_hb_ucd_u8[6472+(((_hb_ucd_u8[816+(((_hb_ucd_u16[((_hb_ucd_u8[272+(((_hb_ucd_u8[u>>1>>3>>4>>4])<<4)+((u>>1>>3>>4)&15u))])<<4)+((u>>1>>3)&15u)])<<3)+((u>>1)&7u))])<<1)+((u)&1u))]:2;
+ }
+ static inline uint_fast8_t
+ _hb_ucd_ccc (unsigned u)
+ {
+-  return u<125259u?_hb_ucd_u8[8800+(((_hb_ucd_u8[8244+(((_hb_ucd_u8[7784+(((_hb_ucd_u8[7432+(((_hb_ucd_u8[7186+(u>>2>>2>>2>>3)])<<3)+((u>>2>>2>>2)&7u))])<<2)+((u>>2>>2)&3u))])<<2)+((u>>2)&3u))])<<2)+((u)&3u))]:0;
++  return u<125259u?_hb_ucd_u8[8504+(((_hb_ucd_u8[7936+(((_hb_ucd_u8[7460+(((_hb_ucd_u8[7100+(((_hb_ucd_u8[6854+(u>>2>>2>>2>>3)])<<3)+((u>>2>>2>>2)&7u))])<<2)+((u>>2>>2)&3u))])<<2)+((u>>2)&3u))])<<2)+((u)&3u))]:0;
+ }
+ static inline unsigned
+ _hb_ucd_b4 (const uint8_t* a, unsigned i)
+@@ -4418,55 +4630,55 @@ _hb_ucd_b4 (const uint8_t* a, unsigned i)
+ static inline int_fast16_t
+ _hb_ucd_bmg (unsigned u)
+ {
+-  return u<65380u?_hb_ucd_i16[((_hb_ucd_u8[9692+(((_hb_ucd_u8[9460+(((_hb_ucd_u8[9364+(((_hb_ucd_b4(9300+_hb_ucd_u8,u>>1>>2>>3>>3))<<3)+((u>>1>>2>>3)&7u))])<<3)+((u>>1>>2)&7u))])<<2)+((u>>1)&3u))])<<1)+((u)&1u)]:0;
++  return u<65380u?_hb_ucd_i16[((_hb_ucd_u8[9396+(((_hb_ucd_u8[9164+(((_hb_ucd_u8[9068+(((_hb_ucd_b4(9004+_hb_ucd_u8,u>>1>>2>>3>>3))<<3)+((u>>1>>2>>3)&7u))])<<3)+((u>>1>>2)&7u))])<<2)+((u>>1)&3u))])<<1)+((u)&1u)]:0;
+ }
+ static inline uint_fast8_t
+ _hb_ucd_sc (unsigned u)
+ {
+-  return u<918000u?_hb_ucd_u8[11126+(((_hb_ucd_u16[4040+(((_hb_ucd_u16[2048+(((_hb_ucd_u8[10390+(((_hb_ucd_u8[9940+(u>>2>>2>>3>>4)])<<4)+((u>>2>>2>>3)&15u))])<<3)+((u>>2>>2)&7u))])<<2)+((u>>2)&3u))])<<2)+((u)&3u))]:2;
++  return u<918000u?_hb_ucd_u8[10398+(((_hb_ucd_u16[3952+(((_hb_ucd_u16[2624+(((_hb_ucd_u8[9870+(((_hb_ucd_u8[9644+(u>>3>>2>>3>>4)])<<4)+((u>>3>>2>>3)&15u))])<<3)+((u>>3>>2)&7u))])<<2)+((u>>3)&3u))])<<3)+((u)&7u))]:2;
+ }
+ static inline uint_fast16_t
+ _hb_ucd_dm (unsigned u)
+ {
+-  return u<195102u?_hb_ucd_u16[6748+(((_hb_ucd_u8[13952+(((_hb_ucd_u8[13570+(u>>4>>5)])<<5)+((u>>4)&31u))])<<4)+((u)&15u))]:0;
++  return u<195102u?_hb_ucd_u16[6244+(((_hb_ucd_u8[16628+(((_hb_ucd_u8[16246+(u>>4>>5)])<<5)+((u>>4)&31u))])<<4)+((u)&15u))]:0;
+ }
+ 
+ 
+ #else
+ 
+ static const uint8_t
+-_hb_ucd_u8[13386] =
++_hb_ucd_u8[13730] =
+ {
+     0,  1,  2,  3,  4,  5,  6,  7,  7,  8,  7,  7,  7,  7,  7,  7,
+     7,  7,  7,  7,  9, 10,  7,  7,  7,  7,  7, 11, 12, 12, 12, 13,
+-   14, 15, 16, 17, 18, 19, 20, 21, 22, 21, 21, 21, 21, 23,  7,  7,
+-    7, 24, 21, 21, 21, 25, 26, 27, 21, 28, 29, 30, 31, 32, 33, 34,
++   14, 15, 16, 17, 18, 19, 20,  7, 21, 22, 22, 22, 23, 24,  7,  7,
++    7, 25, 22, 22, 22, 26, 27, 28, 22, 29, 30, 31, 32, 33, 34, 35,
+     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
+-    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7, 35, 21, 36,
+-    7,  7,  7,  7, 37, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+-   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+-   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+-   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+-   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+-   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+-   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+-   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+-   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+-   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+-   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+-   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+-   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+-   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+-   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+-   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+-   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+-   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+-   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+-   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+-   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+-   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+-   38, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+-   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
++    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7, 21, 22, 36,
++    7,  7,  7,  7, 37, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
++   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
++   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
++   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
++   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
++   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
++   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
++   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
++   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
++   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
++   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
++   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
++   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
++   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
++   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
++   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
++   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
++   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
++   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
++   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
++   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
++   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
++   38, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
++   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+    12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+    12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+    12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+@@ -4486,30 +4698,30 @@ _hb_ucd_u8[13386] =
+   100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
+   100,100, 34, 34, 34, 34,101,102, 34, 34,103,104,105,106,107,108,
+    34, 34,109,110,111,112,113,114,115,116,117,118, 34, 34, 34,119,
+-  120,121,122,123,124,125,126,127, 34,128,129,111,130,131,132,133,
+-  134,135,136,137,138,139,140,111,141,142,111,143,144,145,146,111,
+-  147,148,149,150,151,152,153,111,154,155,156,157,111,158,159,160,
+-   34, 34, 34, 34, 34, 34, 34, 34,161, 34, 34,111,111,111,111,111,
+-  111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,162,
+-   34, 34, 34, 34, 34, 34, 34, 34,163,111,111,111,111,111,111,111,
++  120,121,122,123,124,125,126,127, 34,128,129,130,131,132,133,134,
++  135,136,137,138,139,140,141,142,143,144,111,145,146,147,148,111,
++  149,150,151,152,153,154,155,156,157,158,159,160,111,161,162,163,
++   34, 34, 34, 34, 34, 34, 34, 34,164, 34, 34,111,111,111,111,111,
++  111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,165,
++   34, 34, 34, 34, 34, 34, 34, 34,166, 34, 34, 34, 34, 34, 34, 34,
++   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,111,111,111,
+   111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,
+-  111,111,111,111,111,111,111,111, 34, 34, 34, 34, 34,111,111,111,
+-   34, 34, 34, 34,164,165,166, 34,111,111,111,111,167,168,169,170,
++  111,111,167,111,111,111,111,111,111,111,111,111,111,111,111,111,
++   34, 34, 34, 34,168,169,170, 34,111,111,171,111,172,173,174,175,
+    34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,111,111,111,111,111,
+   111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,119,
+    34, 34, 34, 34, 34, 34,111,111,111,111,111,111,111,111,111,111,
+-  111,111,111,111,111,111,111,111, 34,171,111,111,111,111,111,111,
+-  111,111,111,111,111,111,111,111,111,111,111,111,111,111,172, 67,
+-   67, 67,173,174,175,130, 65,111,176,177,178,179,180,181,182,183,
+-   67, 67, 67, 67,184,185,111,111,111,111,111,111,111,111,186,111,
+-  187,188,189,111,111,190,111,111,111,191,111,111,111,111,111, 34,
+-   34,192,193,111,111,111,111,111,130,194,195,111, 34,196,111,111,
+-   67, 67,197, 67, 67,111, 67,198, 67, 67, 67, 67, 67, 67, 67, 67,
+-   67, 67, 67, 67, 67, 67, 67,199,111,111,111,111,111,111,111,111,
+-   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,111,111,111,
++  111,111,111,111,111,111,111,111, 34,176,111,111,111,111,111,111,
++  111,111,111,111,111,111,111,111, 67,177, 67, 67, 67, 67,178, 67,
++   67, 67,179,180,181,131, 65,111,182,183,184,185,186,187,188,189,
++   67, 67, 67, 67,190,191,111,111,111,111,111,111,111,111,192,111,
++  193,194,195,111,111,196,111,111,111,197,111,198,111,111,111, 34,
++   34,199,200,111,111,111,111,111,131,201,202,111, 34,203,111,111,
++   67, 67,204, 67, 67,111, 67,205, 67, 67, 67, 67, 67, 67, 67, 67,
++   67, 67, 67, 67, 67, 67, 67,177,111,111,111,111,111,111,111,111,
+    34, 34, 34, 34, 34,111,111,111,111,111,111,111,111,111,111,111,
+    34, 34, 34, 34, 34, 34, 34, 34,111,111,111,111,111,111,111,111,
+-  200,111,188,188,111,111,111,111,111,111,111,111,111,111,111,111,
++  206,111,194,194,111,111,111,111,111,111,111,111,111,111,111,111,
+     0,  0,  0,  0,  0,  0,  0,  0,  1,  2,  3,  2,  4,  5,  6,  2,
+     7,  7,  7,  7,  7,  2,  8,  9, 10, 11, 11, 11, 11, 11, 11, 11,
+    11, 11, 11, 11, 11, 12, 13, 14, 15, 16, 16, 16, 16, 16, 16, 16,
+@@ -4544,8 +4756,8 @@ _hb_ucd_u8[13386] =
+    36, 36, 36, 36, 36, 64, 43, 43, 43, 43, 40, 21,  2, 40, 69, 20,
+    36, 36, 36, 43, 43, 69, 43, 43, 43, 43, 69, 43, 69, 43, 43, 43,
+     2,  2,  2,  2,  2,  2,  2,  2, 36, 36, 36, 36, 64, 43, 43,  2,
+-   36, 36, 36, 36, 74, 36, 36, 36, 59, 59, 59, 59, 43, 43, 43, 43,
+-   36, 36, 36, 36, 75, 43, 43, 43, 43, 76, 43, 43, 43, 43, 43, 43,
++   36, 36, 36, 36, 74, 36, 36, 36, 59, 59, 59, 75, 43, 43, 43, 43,
++   36, 36, 36, 36, 76, 43, 43, 43, 43, 75, 43, 43, 43, 43, 43, 43,
+    43, 77, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 77, 65, 78,
+    79, 43, 43, 43, 77, 78, 79, 78, 64, 43, 43, 43, 36, 36, 36, 36,
+    36, 43,  2,  7,  7,  7,  7,  7, 80, 36, 36, 36, 36, 36, 36, 36,
+@@ -4590,130 +4802,135 @@ _hb_ucd_u8[13386] =
+    36, 43, 77, 78, 78, 78, 78, 81, 36, 43, 97,  2,  2,  2,  2,  2,
+    36, 43, 43, 43, 43, 43, 43, 43, 36, 36, 43, 79, 43, 43, 43, 78,
+    78, 78, 78, 77, 79, 43, 43, 43, 43, 43,  2, 80,  2, 60, 64, 43,
+-    7,  7,  7,  7,  7,  7,  7,  7,  2,  2,  2, 98,  2, 56, 43, 76,
+-   36, 75, 36, 36, 36, 36, 36, 36, 36, 36, 64, 65, 36, 36, 36, 36,
++    7,  7,  7,  7,  7,  7,  7,  7,  2,  2,  2, 98,  2, 56, 43, 75,
++   36, 76, 36, 36, 36, 36, 36, 36, 36, 36, 64, 65, 36, 36, 36, 36,
+    36, 36, 36, 36, 64, 36, 36, 36, 43, 77, 78, 79, 77, 78, 78, 78,
+    78, 77, 78, 78, 79, 43, 43, 43, 61, 61,  2,  7,  7,  7,  7,  7,
+     7,  7,  7,  7,  7, 27, 27, 61, 36, 36, 36, 64, 77, 79, 43,  2,
+    36, 36, 82, 77, 43, 43, 43, 43, 77, 77, 79, 43, 43, 43, 77, 78,
+    78, 79, 43, 43, 43, 43, 43, 43,  2,  2,  2, 80,  2,  2,  2,  2,
+    43, 43, 43, 43, 43, 43, 43, 99, 43, 43, 81, 36, 36, 36, 36, 36,
+-   36, 36, 77, 43, 43, 77, 77, 78, 78, 77, 81, 36, 36, 36, 36, 36,
++   36, 36, 77, 43, 43, 77, 77, 78, 78, 77, 81, 36, 36, 36, 36,  2,
+    89, 61, 61, 61, 61, 47, 43, 43, 43, 43, 61, 61, 61, 61, 21,  2,
+    43, 81, 36, 36, 36, 36, 36, 36, 82, 43, 43, 78, 43, 79, 43, 36,
+    36, 36, 36, 77, 43, 78, 79, 79, 43, 78, 78, 78, 78, 78,  2,  2,
+    36, 36, 78, 78, 78, 78, 43, 43, 43, 43, 78, 43, 43, 57,  2,  2,
+     7,  7,  7,  7,  7,  7, 86, 36, 36, 36, 36, 36, 40, 40, 40,  2,
+-   43, 57, 43, 43, 43, 43, 43, 43, 77, 43, 43, 43, 65, 36, 64, 36,
+-   36, 36, 65, 82, 43, 36, 36, 36, 16, 16, 16, 16, 16, 16, 40, 40,
+-   40, 40, 40, 40, 40, 44, 16, 16, 16, 16, 16, 16, 44, 16, 16, 16,
+-   16, 16, 16, 16, 16,100, 40, 40, 32, 32, 32, 16, 16, 16, 16, 32,
+-   16, 16, 16, 16, 11, 11, 11, 11, 16, 16, 16, 16, 34, 11, 11, 11,
+-   16, 16, 16, 16,101,101,101,101, 16, 16, 16, 16, 11, 11,102,103,
+-   41, 16, 16, 16, 11, 11,102, 41, 16, 16, 16, 16, 11, 11,104, 41,
+-  105,105,105,105,105,106, 59, 59, 51, 51, 51,  2,107,108,107,108,
+-    2,  2,  2,  2,109, 59, 59,110,  2,  2,  2,  2,111,112,  2,113,
+-  114,  2,115,116,  2,  2,  2,  2,  2,  9,114,  2,  2,  2,  2,117,
+-   59, 59, 59, 59, 59, 59, 59, 59,118, 40, 27, 27, 27,  8,115,119,
+-   27, 27, 27, 27, 27,  8,115, 94, 20, 20, 20, 20, 20, 20, 20, 20,
+-   43, 43, 43, 43, 43, 43,120, 48, 99, 48, 99, 43, 43, 43, 43, 43,
+-   61,121, 61,122, 61, 34, 11, 16, 11, 32,122, 61, 46, 11, 11, 61,
+-   61, 61,121,121,121, 11, 11,123, 11, 11, 35, 36, 39, 61, 16, 11,
+-    8,  8, 46, 16, 16, 26, 61,124, 95, 95, 95, 95, 95, 95, 95, 95,
+-   95,125,126, 95,127, 61, 61, 61,  8,  8,128, 61, 61,  8, 61, 61,
+-  128, 26, 61,128, 61, 61, 61,128, 61, 61, 61, 61, 61, 61, 61,  8,
+-   61,128,128, 61, 61, 61, 61, 61, 61, 61,  8,  8,  8,  8,  8,  8,
+-    8,  8,  8,  8,  8,  8,  8,  8, 61, 61, 61, 61,  4,  4, 61, 61,
+-    8, 61, 61, 61,129,130, 61, 61, 61, 61, 61, 61, 61, 61,128, 61,
+-   61, 61, 61, 61, 61, 26,  8,  8,  8,  8, 61, 61, 61, 61, 61, 61,
+-   61, 61, 61, 61, 61, 61,  8,  8,  8, 61, 61, 61, 61, 61, 61, 61,
+-   27, 27, 27, 27, 27, 27, 61, 61, 61, 61, 61, 61, 61, 27, 27, 27,
+-   61, 61, 61, 26, 61, 61, 61, 61, 26, 61, 61, 61, 61, 61, 61, 61,
+-   61, 61, 61, 61,  8,  8,  8,  8, 61, 61, 61, 61, 61, 61, 61, 26,
+-   61, 61, 61, 61,  4,  4,  4,  4,  4,  4,  4, 27, 27, 27, 27, 27,
+-   27, 27, 61, 61, 61, 61, 61, 61,  8,  8,115,131,  8,  8,  8,  8,
+-    8,  8,  8,  4,  4,  4,  4,  4,  8,115,132,132,132,132,132,132,
+-  132,132,132,132,131,  8,  8,  8,  8,  8,  8,  8,  4,  4,  8,  8,
+-    8,  8,  8,  8,  8,  8,  4,  8,  8,  8,128, 26,  8,  8,128, 61,
+-   32, 11, 32, 34, 34, 34, 34, 11, 32, 32, 34, 16, 16, 16, 40, 11,
+-   32, 32,124, 61, 61,122, 34,133, 43, 32, 16, 16, 50,  2, 90,  2,
+-   36, 36, 36, 36, 36, 36, 36, 75,  2,  2,  2,  2,  2,  2,  2, 56,
+-    2,107,107,  2,111,112,107,  2,  2,  2,  2,  6,  2, 98,107,  2,
+-  107,  4,  4,  4,  4,  2,  2, 80,  2,  2,  2,  2,  2, 51,  2,  2,
+-   98,134,  2,  2,  2,  2,  2,  2, 61,  2,135,132,132,132,136, 51,
+-   51, 51, 51, 51, 51, 51, 51, 51,  1,  2,137,138,  4,  4,  4,  4,
+-    4, 61,  4,  4,  4,  4,139, 94,140, 95, 95, 95, 95, 43, 43, 78,
+-  141, 40, 40, 61, 95,142, 58, 61, 72, 36, 36, 36, 36, 36, 36, 36,
+-   36, 36, 36, 36, 64,143,144, 63, 36, 36, 36, 36, 36, 58, 40, 63,
+-   61, 27, 27, 61, 61, 61, 61, 61, 27, 27, 27, 27, 27, 61, 61, 61,
+-   61, 61, 61, 61, 27, 27, 27, 27,145, 27, 27, 27, 27, 27, 27, 27,
+-   36, 36, 75, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,146,  2,
+-   32, 32, 32, 32, 32, 32, 32, 64, 48,147, 43, 43, 43, 43, 43, 80,
+-   32, 32, 32, 32, 32, 32, 40, 43, 36, 36, 36, 95, 95, 95, 95, 95,
+-   43,  2,  2,  2,  2,  2,  2,  2, 41, 41, 41,144, 40, 40, 40, 40,
+-   41, 32, 32, 32, 32, 32, 32, 32, 16, 32, 32, 32, 32, 32, 32, 32,
+-   44, 16, 16, 16, 34, 34, 34, 32, 32, 32, 32, 32, 42,148, 34, 35,
+-   32, 32, 16, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 11, 11, 32,
+-   11, 11, 32, 32, 32, 32, 32, 32, 32, 32, 11, 11, 34, 16, 16, 16,
+-   32, 16, 16, 32, 32, 16, 16, 16, 16, 40,149, 35, 40, 35, 36, 36,
+-   36, 65, 36, 65, 36, 64, 36, 36, 36, 82, 79, 77, 61, 61, 43, 43,
+-   27, 27, 27, 61,150, 61, 61, 61, 36, 36,  2,  2,  2,  2,  2,  2,
+-   78, 36, 36, 36, 36, 36, 36, 36, 36, 36, 78, 78, 78, 78, 78, 78,
+-   78, 78, 43, 43, 43, 43, 43,  2, 43, 36, 36, 36,  2, 66, 66, 64,
+-   36, 36, 36, 43, 43, 43, 43,  2, 36, 36, 36, 64, 43, 43, 43, 43,
+-   43, 78, 78, 78, 78, 78, 78, 97, 36, 64, 78, 43, 43, 78, 43, 78,
+-   97,  2,  2,  2,  2,  2,  2, 80,  7,  7,  7,  7,  7,  7,  7,  2,
+-   36, 36, 64, 63, 36, 36, 36, 36, 36, 36, 36, 36, 64, 43, 43, 77,
+-   79, 77, 79, 43, 43, 43, 43, 43, 36, 64, 36, 36, 36, 36, 77, 78,
+-    7,  7,  7,  7,  7,  7,  2,  2, 63, 36, 36, 71, 61, 82, 77, 36,
+-   65, 43, 65, 64, 65, 36, 36, 43, 36, 36, 36, 36, 36, 36, 75,  2,
+-   36, 36, 36, 36, 36, 82, 43, 78,  2, 75,151, 43, 43, 43, 43, 43,
+-   16, 16, 16, 16, 16,103, 40, 40, 16, 16, 16, 16,100, 41, 41, 41,
+-   36, 82, 79, 78, 77, 97, 79, 43,152,152,152,152,152,152,152,152,
+-  153,153,153,153,153,153,153,153, 16, 16, 16, 16, 16, 16, 35, 65,
+-   36, 36, 36, 36,154, 36, 36, 36, 36, 41, 41, 41, 41, 41, 41, 41,
+-   41, 74, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,132,
+-   36, 36, 36, 36, 36, 36, 36, 71, 36, 36, 36, 36, 36, 36,150, 61,
+-    2,  2,  2,135,116,  2,  2,  2,  6,155,156,132,132,132,132,132,
+-  132,132,116,135,116,  2,113,157,  2,  2,  2,  2,139,132,132,116,
+-    2,158,  8,  8, 60,  2,  2,  2, 36, 36, 36, 36, 36, 36, 36,159,
+-    2,  2,  3,  2,  4,  5,  6,  2, 16, 16, 16, 16, 16, 17, 18,115,
+-  116,  4,  2, 36, 36, 36, 36, 36, 63, 36, 36, 36, 36, 36, 36, 36,
+-   36, 36, 36, 36, 36, 36, 36, 40, 20,160, 53, 20, 26,  8,128, 61,
+-   61, 61, 61, 61,161, 59, 61, 61,  2,  2,  2, 90, 27, 27, 27, 27,
+-   27, 27, 27, 84, 61, 61, 61, 61, 95, 95,127, 27, 84, 61, 61, 61,
+-   61, 61, 61, 61, 61, 27, 61, 61, 61, 61, 61, 61, 61, 61, 47, 43,
+-  162,162,162,162,162,162,162,162,163, 27, 27, 27, 27, 27, 27, 27,
+-   27, 27, 27, 27, 27, 27, 87, 36,138, 36, 36, 36, 36, 95, 95, 95,
+-   36, 36, 36, 36, 36, 36, 36, 58,164, 95, 95, 95, 95, 95, 95, 95,
+-   11, 11, 11, 32, 16, 16, 16, 16, 36, 36, 36, 58, 27, 27, 27, 27,
+-   36, 36, 36, 71,145, 27, 27, 27, 36, 36, 36,165, 27, 27, 27, 27,
+-   36, 36, 36, 36, 36,165, 27, 27, 36, 36, 36, 27, 27, 27, 27, 30,
+-   36, 36, 36, 36, 36, 36, 27, 36, 64, 43, 43, 43, 43, 43, 43, 43,
+-   36, 36, 36, 36, 43, 43, 43, 43, 36, 36, 36, 36, 36, 36,165, 30,
+-   36, 36, 36, 36, 36, 36,165, 27, 36, 36, 36, 36, 72, 36, 36, 36,
+-   36, 36, 64, 43, 43,163, 27, 27, 36, 36, 36, 36, 58,  2,  2,  2,
+-   36, 36, 36, 36, 27, 27, 27, 27, 16, 16, 16, 16, 16, 27, 27, 27,
+-   36, 36, 43, 43, 43, 43, 43, 43, 36, 36, 36, 36, 36, 64,166, 51,
+-   27, 27, 27, 87, 36, 36, 36, 36,163, 27, 30,  2,  2,  2,  2,  2,
+-   36, 43, 43,  2,  2,  2,  2,  2, 36, 36,165, 27, 27, 27, 27, 27,
+-   79, 81, 36, 36, 36, 36, 36, 36, 43, 43, 43, 57,  2,  2,  2,  2,
+-    2, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,  7,  7,  7,  7,  7,
+-   65, 64, 65, 36, 36, 36, 36, 64, 78, 79, 43, 77, 79, 57, 73,  2,
+-    2, 43, 43, 43, 43, 43, 67, 59, 36, 36, 36, 64, 43, 43, 79, 43,
+-   43, 43, 43,  7,  7,  7,  7,  7,  2,  2, 82, 81, 36, 36, 36, 36,
+-   36, 64,  2, 36, 36, 36, 36, 36, 36, 82, 78, 43, 43, 43, 43, 77,
+-   81, 36, 58,  2, 56, 43, 57, 79,  7,  7,  7,  7,  7, 58, 58,  2,
+-   90, 27, 27, 27, 27, 27, 27, 27, 36, 36, 36, 36, 36, 36, 78, 79,
+-   43, 78, 77, 43,  2,  2,  2, 65, 36, 36, 36, 36, 36, 36, 36, 64,
+-   77, 78, 78, 78, 78, 78, 78, 78, 36, 36, 36, 82, 78, 78, 81, 36,
+-   36, 78, 78, 43, 43, 43, 43, 43, 36, 36, 82, 78, 43, 43, 43, 43,
+-   78, 43, 77, 65, 36, 58,  2,  2,  7,  7,  7,  7,  7,  2,  2, 65,
+-   78, 79, 43, 43, 77, 77, 78, 79, 77, 43, 36, 66, 36, 36, 36, 36,
+-   36, 36, 36, 36, 36, 36, 36, 82, 78, 43, 43, 43, 78, 78, 43, 79,
+-   57,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 36, 36, 43, 43,
+-   78, 79, 43, 43, 43, 77, 79, 79, 57,  2, 36, 36, 36, 36, 36, 36,
+-   36, 36, 36, 36, 36, 64, 79, 78, 43, 43, 43, 79, 58,  2,  2,  2,
++   16, 16, 16, 16, 34, 16, 16, 16, 43, 57, 43, 43, 43, 43, 43, 43,
++   77, 43, 43, 43, 65, 36, 64, 36, 36, 36, 65, 82, 43, 36, 36, 36,
++   16, 16, 16, 16, 16, 16, 40, 40, 40, 40, 40, 40, 40, 44, 16, 16,
++   16, 16, 16, 16, 44, 16, 16, 16, 16, 16, 16, 16, 16,100, 40, 40,
++   32, 32, 32, 16, 16, 16, 16, 32, 16, 16, 16, 16, 11, 11, 11, 11,
++   16, 16, 16, 16, 34, 11, 11, 11, 16, 16, 16, 16,101,101,101,101,
++   16, 16, 16, 16, 11, 11,102,103, 41, 16, 16, 16, 11, 11,102, 41,
++   16, 16, 16, 16, 11, 11,104, 41,105,105,105,105,105,106, 59, 59,
++   51, 51, 51,  2,107,108,107,108,  2,  2,  2,  2,109, 59, 59,110,
++    2,  2,  2,  2,111,112,  2,113,114,  2,115,116,  2,  2,  2,  2,
++    2,  9,114,  2,  2,  2,  2,117, 59, 59, 59, 59, 59, 59, 59, 59,
++  118, 40, 27, 27, 27,  8,115,119, 27, 27, 27, 27, 27,  8,115, 94,
++   20, 20, 20, 20, 20, 20, 20, 20, 43, 43, 43, 43, 43, 43,120, 48,
++   99, 48, 99, 43, 43, 43, 43, 43, 61,121, 61,122, 61, 34, 11, 16,
++   11, 32,122, 61, 46, 11, 11, 61, 61, 61,121,121,121, 11, 11,123,
++   11, 11, 35, 36, 39, 61, 16, 11,  8,  8, 46, 16, 16, 26, 61,124,
++   95, 95, 95, 95, 95, 95, 95, 95, 95,125,126, 95,127, 61, 61, 61,
++    8,  8,128, 61, 61,  8, 61, 61,128, 26, 61,128, 61, 61, 61,128,
++   61, 61, 61, 61, 61, 61, 61,  8, 61,128,128, 61, 61, 61, 61, 61,
++   61, 61,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
++   61, 61, 61, 61,  4,  4, 61, 61,  8, 61, 61, 61,129,130, 61, 61,
++   61, 61, 61, 61, 61, 61,128, 61, 61, 61, 61, 61, 61, 26,  8,  8,
++    8,  8, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61,  8,  8,
++    8, 61, 61, 61, 61, 61, 61, 61, 27, 27, 27, 27, 27, 27, 61, 61,
++   61, 61, 61, 61, 61, 27, 27, 27, 61, 61, 61, 26, 61, 61, 61, 61,
++   26, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61,  8,  8,  8,  8,
++   61, 61, 61, 61, 61, 61, 61, 26, 61, 61, 61, 61,  4,  4,  4,  4,
++    4,  4,  4, 27, 27, 27, 27, 27, 27, 27, 61, 61, 61, 61, 61, 61,
++    8,  8,115,131,  8,  8,  8,  8,  8,  8,  8,  4,  4,  4,  4,  4,
++    8,115,132,132,132,132,132,132,132,132,132,132,131,  8,  8,  8,
++    8,  8,  8,  8,  4,  4,  8,  8,  8,  8,  8,  8,  8,  8,  4,  8,
++    8,  8,128, 26,  8,  8,128, 61, 32, 11, 32, 34, 34, 34, 34, 11,
++   32, 32, 34, 16, 16, 16, 40, 11, 32, 32,124, 61, 61,122, 34,133,
++   43, 32, 16, 16, 50,  2, 90,  2, 36, 36, 36, 36, 36, 36, 36, 76,
++    2,  2,  2,  2,  2,  2,  2, 56,  2,107,107,  2,111,112,107,  2,
++    2,  2,  2,  6,  2, 98,107,  2,107,  4,  4,  4,  4,  2,  2, 80,
++    2,  2,  2,  2,  2, 51,  2,  2, 98,134,  2,  2,  2,  2,  2,  2,
++   61,  2,135,132,132,132,136, 51, 51, 51, 51, 51, 51, 51, 51, 51,
++    1,  2,137,138,  4,  4,  4,  4,  4, 61,  4,  4,  4,  4,139, 94,
++  140, 95, 95, 95, 95, 43, 43, 78,141, 40, 40, 61, 95,142, 58, 61,
++   72, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 64,143,144, 63,
++   36, 36, 36, 36, 36, 58, 40, 63, 61, 27, 27, 61, 61, 61, 61, 61,
++   27, 27, 27, 27, 27, 61, 61, 61, 61, 61, 61, 61, 27, 27, 27, 27,
++  145, 27, 27, 27, 27, 27, 27, 27, 36, 36, 76, 36, 36, 36, 36, 36,
++   36, 36, 36, 36, 36, 36,146,  2, 32, 32, 32, 32, 32, 32, 32, 64,
++   48,147, 43, 43, 43, 43, 43, 80, 32, 32, 32, 32, 32, 32, 40, 43,
++   36, 36, 36, 95, 95, 95, 95, 95, 43,  2,  2,  2,  2,  2,  2,  2,
++   41, 41, 41,144, 40, 40, 40, 40, 41, 32, 32, 32, 32, 32, 32, 32,
++   16, 32, 32, 32, 32, 32, 32, 32, 44, 16, 16, 16, 34, 34, 34, 32,
++   32, 32, 32, 32, 42,148, 34, 35, 32, 32, 16, 32, 32, 32, 32, 32,
++   32, 32, 32, 32, 32, 11, 11, 32, 11, 11, 32, 32, 32, 32, 32, 32,
++   32, 32, 11, 11, 34, 34, 32, 16, 32, 16, 16, 32, 32, 32, 11, 11,
++   11, 40,149, 35, 40, 35, 36, 36, 36, 65, 36, 65, 36, 64, 36, 36,
++   36, 82, 79, 77, 61, 61, 43, 43, 27, 27, 27, 61,150, 61, 61, 61,
++   36, 36,  2,  2,  2,  2,  2,  2, 78, 36, 36, 36, 36, 36, 36, 36,
++   36, 36, 78, 78, 78, 78, 78, 78, 78, 78, 43, 43, 43, 43, 43,  2,
++   43, 36, 36, 36,  2, 66, 66, 64, 36, 36, 36, 43, 43, 43, 43,  2,
++   36, 36, 36, 64, 43, 43, 43, 43, 43, 78, 78, 78, 78, 78, 78, 97,
++   36, 64, 78, 43, 43, 78, 43, 78, 97,  2,  2,  2,  2,  2,  2, 80,
++    7,  7,  7,  7,  7,  7,  7,  2, 36, 36, 64, 63, 36, 36, 36, 36,
++   36, 36, 36, 36, 64, 43, 43, 77, 79, 77, 79, 43, 43, 43, 43, 43,
++   36, 64, 36, 36, 36, 36, 77, 78,  7,  7,  7,  7,  7,  7,  2,  2,
++   63, 36, 36, 71, 61, 82, 77, 36, 65, 43, 65, 64, 65, 36, 36, 43,
++   36, 36, 36, 36, 36, 36, 76,  2, 36, 36, 36, 36, 36, 82, 43, 78,
++    2, 76,151, 43, 43, 43, 43, 43, 16, 16, 16, 16, 16,103, 40, 40,
++   16, 16, 16, 16,100, 41, 41, 41, 36, 82, 79, 78, 77, 97, 79, 43,
++  152,152,152,152,152,152,152,152,153,153,153,153,153,153,153,153,
++   16, 16, 16, 16, 16, 16, 35, 65, 36, 36, 36, 36,154, 36, 36, 36,
++   36, 41, 41, 41, 41, 41, 41, 41, 41, 74, 36, 36, 36, 36, 36, 36,
++   36, 36, 36, 36, 36, 36, 36,132, 36, 36, 36, 36, 36, 36, 36, 71,
++   36, 36, 36, 36, 36, 36,150, 61,  2,  2,  2,135,116,  2,  2,  2,
++    6,155,156,132,132,132,132,132,132,132,116,135,116,  2,113,157,
++    2,  2,  2,  2,139,132,132,116,  2,158,  8,  8, 60,  2,  2,  2,
++   36, 36, 36, 36, 36, 36, 36,159,  2,  2,  3,  2,  4,  5,  6,  2,
++   16, 16, 16, 16, 16, 17, 18,115,116,  4,  2, 36, 36, 36, 36, 36,
++   63, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 40,
++   20,160, 53, 20, 26,  8,128, 61, 61, 61, 61, 61,161, 59, 61, 61,
++    2,  2,  2, 90, 27, 27, 27, 27, 27, 27, 27, 84, 61, 61, 61, 61,
++   95, 95,127, 27, 84, 61, 61, 61, 61, 61, 61, 61, 61, 27, 61, 61,
++   61, 61, 61, 61, 61, 61, 47, 43,162,162,162,162,162,162,162,162,
++  163, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 87, 36,
++  138, 36, 36, 36, 36, 95, 95, 95, 36, 36, 36, 36, 36, 36, 36, 58,
++  164, 95, 95, 95, 95, 95, 95, 95, 11, 11, 11, 32, 16, 16, 16, 16,
++   36, 36, 36, 58, 27, 27, 27, 27, 36, 36, 36, 71,145, 27, 27, 27,
++   36, 36, 36,165, 27, 27, 27, 27, 36, 36, 36, 36, 36,165, 27, 27,
++   36, 36, 36, 27, 27, 27, 27, 30, 36, 36, 36, 36, 36, 36, 27, 36,
++   64, 43, 43, 43, 43, 43, 43, 43, 36, 36, 36, 36, 43, 43, 43, 43,
++   36, 36, 36, 36, 36, 36,165, 30, 36, 36, 36, 36, 36, 36,165, 27,
++   36, 36, 36, 36, 72, 36, 36, 36, 36, 36, 64, 43, 43,163, 27, 27,
++   36, 36, 36, 36, 58,  2,  2,  2, 36, 36, 36, 36, 27, 27, 27, 27,
++   16, 16, 16, 16, 16, 27, 27, 27, 36, 36, 43, 43, 43, 43, 43, 43,
++    7,  7,  7,  7,  7, 36, 36, 63, 11, 11, 11, 11,166, 43, 43,141,
++   16, 16, 16, 16, 16, 16, 16,  8, 36, 36, 36, 36, 36, 64,167, 51,
++   36, 36, 36, 36, 36, 36, 43, 43, 27, 27, 27, 87, 36, 36, 36, 36,
++  163, 27, 30,  2,  2,  2,  2,  2, 36, 43, 43,  2,  2,  2,  2,  2,
++   36, 36,165, 27, 27, 27, 27, 27, 79, 81, 36, 36, 36, 36, 36, 36,
++   43, 43, 43, 57,  2,  2,  2,  2,  2, 27, 27, 27, 27, 27, 27, 27,
++   27, 27, 27,  7,  7,  7,  7,  7, 65, 64, 65, 36, 36, 36, 36, 64,
++   78, 79, 43, 77, 79, 57, 73,  2,  2, 43, 43, 43, 43, 43, 67, 59,
++   36, 36, 36, 64, 43, 43, 79, 43, 43, 43, 43,  7,  7,  7,  7,  7,
++    2,  2, 82, 81, 36, 36, 36, 36, 36, 64,  2, 36, 36, 36, 36, 36,
++   36, 82, 78, 43, 43, 43, 43, 77, 81, 36, 58,  2, 56, 43, 57, 79,
++    7,  7,  7,  7,  7, 58, 58,  2, 90, 27, 27, 27, 27, 27, 27, 27,
++   36, 36, 36, 36, 36, 36, 78, 79, 43, 78, 77, 43,  2,  2,  2, 65,
++   36, 36, 36, 36, 36, 36, 36, 64, 77, 78, 78, 78, 78, 78, 78, 78,
++   36, 36, 36, 82, 78, 78, 81, 36, 36, 78, 78, 43, 43, 43, 43, 43,
++   36, 36, 36, 36, 78, 79, 43, 43, 43, 78, 78, 78, 78, 78, 78, 77,
++   65, 65,  2,  2,  2,  2,  2,  2, 56, 43, 43, 43, 43, 43, 43, 43,
++   36, 36, 82, 78, 43, 43, 43, 43, 78, 43, 77, 65, 36, 58,  2,  2,
++    7,  7,  7,  7,  7,  2,  2, 65, 78, 79, 43, 43, 77, 77, 78, 79,
++   77, 43, 36, 66, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 82,
++   78, 43, 43, 43, 78, 78, 43, 79, 57,  2,  2,  2,  2,  2,  2,  2,
++    2,  2,  2,  2, 36, 36, 43, 43, 78, 79, 43, 43, 43, 77, 79, 79,
++   57,  2, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 64, 79, 78,
++   43, 43, 43, 79, 58,  2,  2,  2, 36, 36, 36, 36, 36, 36, 64, 79,
+    78, 43, 43, 79, 43, 43, 43, 43,  7,  7,  7,  7,  7, 27,  2, 89,
+    43, 43, 43, 43, 79, 57,  2,  2, 27, 27, 27, 27, 27, 27, 27, 87,
+    78, 78, 78, 78, 78, 79, 77, 65, 81, 79,  2,  2,  2,  2,  2,  2,
+@@ -4721,39 +4938,41 @@ _hb_ucd_u8[13386] =
+    78, 78, 78, 78, 78, 78, 78, 78, 64, 43, 43, 43, 43, 65, 36, 36,
+    36, 64, 43, 43, 77, 64, 43, 57,  2,  2,  2, 56, 43, 43, 43, 43,
+    64, 43, 43, 77, 79, 43, 36, 36, 36, 36, 36, 36, 36, 43, 43, 43,
+-   43, 43, 43, 77, 43,  2, 66,  2, 43, 43, 43, 43, 43, 43, 43, 79,
+-   58,  2,  2,  2,  2,  2,  2,  2,  2, 36, 36, 36, 36, 36, 36, 36,
++   43, 43, 43, 77, 43,  2, 66,  2, 58,  2,  2,  2,  2,  2,  2,  2,
++   43, 43, 43, 43, 43, 43, 43, 79,  2, 36, 36, 36, 36, 36, 36, 36,
+    43, 43, 43, 43, 77, 43, 43, 43, 77, 43, 79, 43, 43, 43, 43, 43,
+    43, 43, 43, 64, 43, 43, 43, 43, 36, 36, 36, 36, 36, 78, 78, 78,
+    43, 77, 79, 79, 36, 36, 36, 36, 36, 64, 77, 97,  2,  2,  2,  2,
+    43, 82, 36, 36, 36, 36, 36, 36, 36, 36, 78, 43, 43, 43, 43, 78,
+-   77, 57,  2,  2,  2,  2,  2,  2, 27, 27, 84, 61, 61, 61, 53, 20,
+-  150, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 21,
+-   65, 36, 36, 64, 43, 43, 43, 43, 43, 43, 57,  2,  2,  2,  2,  2,
+-   43, 43, 43, 57,  2,  2, 61, 61, 40, 40, 89, 61, 61, 61, 61, 61,
+-    7,  7,  7,  7,  7,167, 27, 27, 27, 87, 36, 36, 36, 36, 36, 36,
+-   27, 27, 27, 30,  2,  2,  2,  2, 82, 78, 78, 78, 78, 78, 78, 78,
+-   78, 78, 78, 78, 78, 78, 78, 79, 43, 68, 40, 40, 40, 40, 40, 40,
+-   40, 80, 43, 43, 43, 43, 43, 43, 36, 36, 36, 36, 36, 36, 47, 57,
+-   61, 61,168, 79, 43, 61,168, 78, 78,169, 59, 59, 59, 76, 43, 43,
+-   43, 70, 47, 43, 43, 43, 61, 61, 61, 61, 61, 61, 61, 43, 43, 61,
+-   61, 43, 70, 61, 61, 61, 61, 61, 11, 11, 11, 11, 11, 16, 16, 16,
+-   16, 16, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 16,
+-   11, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 11, 11,
+-   11, 11, 11, 16, 16, 16, 16, 16, 31, 16, 16, 16, 16, 16, 16, 16,
+-   16, 16, 16, 16, 16, 33, 16, 16, 16, 11, 11, 11, 11, 11, 11, 11,
+-   11, 11, 11, 11, 11, 31, 16, 16, 16, 16, 33, 16, 16, 16, 11, 11,
+-   11, 11, 31, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 33,
+-   16, 16, 16, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 31,
+-   16, 16, 16, 16, 33, 16, 16, 16, 11, 11, 11, 11, 31, 16, 16, 16,
+-   16, 33, 16, 16, 16, 32, 16,  7, 43, 43, 43, 70, 61, 47, 43, 43,
+-   43, 43, 43, 43, 43, 43, 70, 61, 61, 61, 47, 61, 61, 61, 61, 61,
+-   61, 61, 70, 21,  2,  2,  2,  2,  2,  2,  2,  2,  2, 56, 43, 43,
+-   16, 16, 16, 16, 16, 39, 16, 16, 43, 43, 43, 68, 40, 40, 40, 40,
+-    7,  7,  7,  7,  7,  7,  7, 71, 36, 36, 36, 36, 36, 36, 36, 43,
+-   36, 36, 36, 36, 36, 36, 43, 43,  7,  7,  7,  7,  7,  7,  7,170,
+-   36, 36, 36, 36, 36, 75, 43, 43, 16, 16, 43, 43, 43, 68, 40, 40,
+-   27, 27, 27, 27, 27, 27,145, 27,171, 27, 27, 27, 27, 27, 27, 27,
++   77, 57,  2,  2,  2,  2,  2,  2,  7,  7,  7,  7,  7, 43, 43, 43,
++   27, 27, 84, 61, 61, 61, 53, 20,150, 61, 61, 61, 61, 61, 61, 61,
++   61, 61, 61, 61, 61, 61, 61, 21, 65, 36, 36, 64, 43, 43, 43, 43,
++   36, 36, 36, 36, 36, 36, 36, 43, 43, 43, 43, 43, 43, 78, 79, 43,
++   43, 43, 57,  2,  2,  2,  2,  2, 43, 43, 43, 57,  2,  2, 61, 61,
++   40, 40, 89, 61, 61, 61, 61, 61,  7,  7,  7,  7,  7,168, 27, 27,
++   27, 87, 36, 36, 36, 36, 36, 36, 40, 63, 36, 36, 36, 36, 36, 36,
++   36, 36, 36, 36, 36, 76,146,  2, 27, 27, 27, 30,  2,  2,  2,  2,
++   82, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 79,
++   43, 68, 40, 40, 40, 40, 40, 40, 40, 80, 43, 43, 43, 43, 43, 43,
++   36, 36, 36, 36, 36, 36, 47, 57, 61, 61,169, 79, 43, 61,169, 78,
++   78,170, 59, 59, 59, 75, 43, 43, 43, 70, 47, 43, 43, 43, 61, 61,
++   61, 61, 61, 61, 61, 43, 43, 61, 61, 43, 70, 61, 61, 61, 61, 61,
++   11, 11, 11, 11, 11, 16, 16, 16, 16, 16, 11, 11, 11, 11, 11, 11,
++   11, 11, 11, 11, 11, 11, 11, 16, 11, 16, 16, 16, 16, 16, 16, 16,
++   16, 16, 16, 16, 16, 16, 11, 11, 11, 11, 11, 16, 16, 16, 16, 16,
++   31, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 33, 16, 16,
++   16, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 31, 16, 16,
++   16, 16, 33, 16, 16, 16, 11, 11, 11, 11, 31, 16, 16, 16, 16, 16,
++   16, 16, 16, 16, 16, 16, 16, 33, 16, 16, 16, 11, 11, 11, 11, 11,
++   11, 11, 11, 11, 11, 11, 11, 31, 16, 16, 16, 16, 33, 16, 16, 16,
++   11, 11, 11, 11, 31, 16, 16, 16, 16, 33, 16, 16, 16, 32, 16,  7,
++   43, 43, 43, 70, 61, 47, 43, 43, 43, 43, 43, 43, 43, 43, 70, 61,
++   61, 61, 47, 61, 61, 61, 61, 61, 61, 61, 70, 21,  2,  2,  2,  2,
++    2,  2,  2,  2,  2, 56, 43, 43, 16, 16, 16, 16, 16, 39, 16, 16,
++   43, 43, 43, 68, 40, 40, 40, 40,  7,  7,  7,  7,  7,  7,  7, 71,
++    7,  7,  7,  7,  7,  7,  7,171, 36, 36, 36, 36, 36, 76, 43, 43,
++  172,  7,  7,  7,  7,  7,  7, 85, 16, 16, 43, 43, 43, 68, 40, 40,
++   27, 27, 27, 27, 27, 27,145, 27,173, 27, 27, 27, 27, 27, 27, 27,
+    27, 27, 27, 27, 27, 27, 27,145, 27, 27, 27, 27, 27, 27, 84, 61,
+    61, 61, 61, 61, 61, 25, 41, 41,  0,  0, 29, 21, 21, 21, 23, 21,
+    22, 18, 21, 25, 21, 17, 13, 13, 25, 25, 25, 21, 21,  9,  9,  9,
+@@ -4764,8 +4983,8 @@ _hb_ucd_u8[13386] =
+     6,  5,  9, 21, 25,  9, 26, 12, 11, 11,  9,  6,  5, 21, 17, 17,
+    17, 26, 26, 23, 23, 12, 17, 12, 21, 12, 12, 21,  7, 21,  1,  1,
+    21, 23, 26, 26,  1, 21,  6,  7,  7, 12, 12,  7, 21,  7, 12,  1,
+-   12,  6,  6, 12, 12, 26,  7, 26, 26,  7, 21,  1, 24,  7,  7,  6,
+-    1, 12, 12, 10, 10, 10, 10, 12, 21,  6, 10,  7,  7, 10, 23,  7,
++   12,  6,  6, 12, 12, 26,  7, 26, 26,  7, 21,  1, 24,  7,  1, 12,
++    7,  6, 12, 10, 10, 10, 10, 12, 21,  6, 10,  7,  7, 10, 23,  7,
+    15, 26, 13, 21, 13,  7, 15,  7, 12, 23, 21, 26, 21, 15, 17,  7,
+    29,  7,  7, 22, 18, 18, 14, 14, 14,  7, 10, 21, 17, 21, 11, 12,
+     5,  6,  8,  8,  8, 24,  5, 24,  9, 24, 29, 29, 29,  1, 20, 19,
+@@ -4776,247 +4995,250 @@ _hb_ucd_u8[13386] =
+    26, 14, 17,  6, 14,  6, 12, 24, 24,  6, 26, 15,  6, 21, 11, 21,
+    24,  9,  6,  9, 23, 26,  6, 10,  4,  4,  3,  3,  7, 25, 17, 16,
+    16, 22, 16, 16, 25, 17,  7,  1, 25, 24, 26,  1,  2,  2, 12, 15,
+-   21, 14,  7, 15, 12, 17, 13, 15, 26, 10, 10,  1, 13, 23, 23, 15,
+-    0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  0, 10, 11, 12, 13,  0,
+-   14,  0,  0,  0,  0,  0, 15,  0, 16,  0,  0,  0,  0,  0,  0,  0,
++   21, 14,  7, 15,  9, 12, 12, 17, 13, 15, 26, 10, 10,  1, 13, 23,
++    7, 13, 23, 15,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  0, 10,
++   11, 12, 13,  0, 14,  0,  0,  0,  0,  0, 15,  0, 16,  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,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
++    0,  0,  0,  0,  0,  0,  0, 17, 18, 19,  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, 17, 18, 19,  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, 20,  0, 21,
+-   22, 23,  0,  0,  0, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
++    0, 20,  0, 21, 22, 23,  0,  0,  0, 24, 25, 26, 27, 28, 29, 30,
++   31, 32, 33, 34,  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, 35,  0,  0,  0,  0, 36,  0, 37,  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, 35,  0, 36,  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, 37,  0,
+-    0,  0,  0,  0,  0,  0,  0,  0, 38, 39,  0,  0,  0,  0,  0,  0,
+-   40, 41, 42,  0, 43,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+-    0,  0,  1,  2,  0,  0,  0,  0,  3,  0,  0,  0,  4,  5,  6,  7,
+-    0,  8,  9, 10,  0, 11, 12, 13, 14, 15, 16, 17, 16, 18, 16, 19,
+-   16, 19, 16, 19,  0, 19, 16, 20, 16, 19, 21, 19,  0, 22, 23, 24,
+-   25, 26, 27, 28, 29, 30, 31,  0, 32,  0,  0,  0,  0,  0,  0,  0,
+-    0,  0,  0, 33,  0,  0,  0,  0,  0,  0, 34,  0,  0, 35,  0,  0,
+-   36,  0, 37,  0,  0,  0, 38, 39, 40, 41, 42, 43, 44, 45, 46,  0,
+-    0, 47,  0,  0,  0, 48,  0,  0,  0, 49,  0,  0,  0,  0,  0,  0,
+-    0, 50,  0, 51,  0, 52, 53,  0, 54,  0,  0,  0,  0,  0,  0, 55,
+-   56, 57,  0,  0,  0,  0, 58,  0,  0, 59, 60, 61, 62, 63,  0,  0,
+-   64, 65,  0,  0,  0, 66,  0,  0,  0,  0, 67,  0,  0,  0, 68,  0,
+-    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 69,  0,  0,
+-    0, 70,  0, 71,  0,  0, 72,  0,  0, 73,  0,  0,  0,  0,  0,  0,
+-    0,  0, 74,  0,  0,  0,  0,  0, 75, 76,  0, 77, 78,  0,  0, 79,
+-   80,  0, 81, 62,  0, 82, 83,  0,  0, 84, 85, 86,  0,  0,  0, 87,
+-    0, 88,  0,  0, 51, 89, 51,  0, 90,  0, 91,  0,  0,  0, 80,  0,
+-    0,  0, 92, 93,  0, 94, 95, 96, 97,  0,  0,  0,  0,  0, 51,  0,
+-    0,  0,  0, 98, 99,  0,  0,  0,  0,  0,  0,100,  0,  0,  0,  0,
+-    0,101,102,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,103,  0,  0,
+-  104,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,105,106,  0,  0,107,
+-    0,  0,  0,  0,  0,  0,108,  0,109,  0,102,  0,  0,  0,  0,  0,
+-  110,111,  0,  0,  0,  0,  0,  0,  0,112,  0,  0,  0,  0,  0,  0,
+-    0,113,  0,114,  0,  0,  0,  0,  0,  0,  1,  2,  3,  4,  5,  6,
+-    7,  0,  8,  0,  0,  0,  0,  9, 10, 11, 12,  0,  0,  0,  0, 13,
+-    0,  0, 14, 15,  0, 16,  0, 17, 18,  0,  0, 19,  0, 20, 21,  0,
+-    0,  0,  0,  0, 22, 23,  0, 24, 25,  0,  0, 26,  0,  0,  0, 27,
+-    0,  0, 28, 29, 30, 31,  0,  0,  0, 32, 33, 34,  0,  0, 33,  0,
+-    0, 35, 33,  0,  0,  0, 33, 36,  0,  0,  0,  0,  0, 37, 38,  0,
+-    0,  0,  0,  0,  0, 39, 40,  0,  0,  0,  0,  0,  0, 41, 42,  0,
+-    0,  0,  0, 43,  0, 44,  0,  0,  0, 45, 46,  0,  0,  0, 47,  0,
+-    0,  0,  0,  0,  0, 48, 49,  0,  0,  0,  0, 50,  0,  0,  0, 51,
+-    0, 52,  0, 53,  0,  0,  0,  0, 54,  0,  0,  0,  0, 55,  0, 56,
+-    0,  0,  0,  0, 57, 58,  0,  0,  0, 59, 60,  0,  0,  0,  0,  0,
+-    0, 61, 52,  0, 62, 63,  0,  0, 64,  0,  0,  0, 65, 66,  0,  0,
+-    0, 67,  0, 68, 69, 70, 71, 72,  1, 73,  0, 74, 75, 76,  0,  0,
+-   77, 78,  0,  0,  0, 79,  0,  0,  1,  1,  0,  0, 80,  0,  0, 81,
+-    0,  0,  0,  0, 77, 82,  0, 83,  0,  0,  0,  0,  0, 78, 84,  0,
+-   85,  0, 52,  0,  1, 78,  0,  0, 86,  0,  0, 87,  0,  0,  0,  0,
+-    0, 88, 57,  0,  0,  0,  0,  0,  0, 89, 90,  0,  0, 84,  0,  0,
+-   33,  0,  0, 91,  0,  0,  0,  0, 92,  0,  0,  0,  0, 49,  0,  0,
+-   93,  0,  0,  0,  0, 94, 95,  0,  0, 96,  0,  0, 97,  0,  0,  0,
+-   98,  0,  0,  0, 99,  0,  0,  0,  0,100,101, 93,  0,  0,102,  0,
+-    0,  0, 84,  0,  0,103,  0,  0,  0,104,105,  0,  0,106,107,  0,
+-    0,  0,  0,  0,  0,108,  0,  0,109,  0,  0,  0,  0,110, 33,  0,
+-  111,112,113, 35,  0,  0,114,  0,  0,  0,115,  0,  0,  0,  0,  0,
+-    0,116,  0,  0,117,  0,  0,  0,  0,118, 88,  0,  0,  0,  0,  0,
+-   57,  0,  0,  0,  0, 52,119,  0,  0,  0,  0,120,  0,  0,121,  0,
+-    0,  0,  0,119,  0,  0,122,  0,  0,  0,  0,  0,  0,123,  0,  0,
+-    0,124,  0,  0,  0,125,  0,126,  0,  0,  0,  0,127,128,129,  0,
+-  130,  0,131,  0,  0,  0,132,133,134,  0, 77,  0,  0,  0,  0,  0,
+-   35,  0,  0,  0,135,  0,  0,  0,136,  0,  0,137,  0,  0,138,  0,
+-    0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1,  2,  3,  4,  5,  6,
+-    7,  4,  4,  8,  9, 10,  1, 11, 12, 13, 14, 15, 16, 17, 18,  1,
+-    1,  1, 19,  1,  0,  0, 20, 21, 22,  1, 23,  4, 21, 24, 25, 26,
+-   27, 28, 29, 30,  0,  0,  1,  1, 31,  0,  0,  0, 32, 33, 34, 35,
+-    1, 36, 37,  0,  0,  0,  0, 38,  1, 39, 14, 39, 40, 41, 42,  0,
+-    0,  0, 43, 36, 44, 45, 21, 45, 46,  0,  0,  0, 19,  1, 21,  0,
+-    0, 47,  0, 38, 48,  1,  1, 49, 49, 50,  0,  0, 51,  0,  0,  0,
+-   52,  1,  0,  0, 38, 14,  4,  1,  1,  1, 53, 21, 43, 52, 54, 21,
+-   35,  1,  0,  0,  0, 55,  0,  0,  0, 56, 57, 58,  0,  0,  0,  0,
+-    0, 59,  0, 60,  0,  0,  0,  0, 61, 62,  0,  0, 63,  0,  0,  0,
+-   64,  0,  0,  0, 65,  0,  0,  0, 66,  0,  0,  0, 67,  0,  0,  0,
+-   68,  0,  0, 69, 70,  0, 71, 72, 73, 74, 75, 76,  0,  0,  0, 77,
+-    0,  0,  0, 78, 79,  0,  0,  0,  0, 47,  0,  0,  0, 49,  0, 80,
+-    0,  0,  0, 62,  0,  0, 63,  0,  0, 81,  0,  0, 82,  0,  0,  0,
+-   83,  0,  0, 19, 84,  0, 62,  0,  0,  0,  0, 49,  1, 85,  1, 52,
+-   15, 86, 36, 10, 21, 87,  0, 55,  0,  0,  0,  0, 19, 10,  1,  0,
+-    0,  0,  0,  0, 88,  0,  0, 89,  0,  0, 88,  0,  0,  0,  0, 78,
+-    0,  0, 87,  9, 12,  4, 90,  8, 91, 47,  0, 58, 50,  0, 21,  1,
+-   21, 92, 93,  1,  1,  1,  1, 94, 95, 96, 97,  1, 98, 58, 81, 99,
+-  100,  4, 58,  0,  0,  0,  0,  0,  0, 19, 50,  0,  0,  0,  0,  0,
+-    0, 61,  0,  0,101,102,  0,  0,103,  0,  0,  1,  1, 50,  0,  0,
+-    0, 38,  0, 63,  0,  0,  0,  0,  0, 62,  0,  0,104, 68, 61,  0,
+-    0,  0, 78,  0,  0,  0,105,106, 58, 38, 81,  0,  0,  0,  0,  0,
+-    0,107,  1, 14,  4, 12, 84,  0,  0,  0,  0, 38, 87,  0,  0,  0,
+-    0,108,  0,  0,109, 61,  0,110,  0,  0,  0,  1,  0,  0,  0,  0,
++    0,  0, 38,  0,  0,  0,  0,  0,  0,  0,  0,  0, 39, 40,  0,  0,
++    0,  0,  0,  0, 41, 42, 43,  0, 44,  0,  0,  0,  0,  0,  0,  0,
++    0,  0,  0,  0,  0,  0,  1,  2,  0,  0,  0,  0,  3,  0,  0,  0,
++    4,  5,  6,  7,  0,  8,  9, 10,  0, 11, 12, 13, 14, 15, 16, 17,
++   16, 18, 16, 19, 16, 19, 16, 19,  0, 19, 16, 20, 16, 19, 21, 19,
++    0, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,  0, 32,  0,  0,  0,
++    0,  0,  0,  0,  0,  0,  0, 33,  0,  0,  0,  0,  0,  0, 34,  0,
++    0, 35,  0,  0, 36,  0, 37,  0,  0,  0, 38, 39, 40, 41, 42, 43,
++   44, 45, 46,  0,  0, 47,  0,  0,  0, 48,  0,  0,  0, 49,  0,  0,
++    0,  0,  0,  0,  0, 50,  0, 51,  0, 52, 53,  0, 54,  0,  0,  0,
++    0,  0,  0, 55, 56, 57,  0,  0,  0,  0, 58,  0,  0, 59, 60, 61,
++   62, 63,  0,  0, 64, 65,  0,  0,  0, 66,  0,  0,  0,  0, 67,  0,
++    0,  0, 68,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
++    0, 69,  0,  0,  0, 70,  0, 71,  0,  0, 72,  0,  0, 73,  0,  0,
++    0,  0,  0,  0,  0,  0, 74, 75,  0,  0,  0,  0, 76, 77,  0, 78,
++   79,  0,  0, 80, 81,  0, 82, 62,  0, 83, 84,  0,  0, 85, 86, 87,
++    0, 88,  0, 89,  0, 90,  0,  0, 51, 91, 51,  0, 92,  0, 93,  0,
++    0,  0, 81,  0,  0,  0, 94, 95,  0, 96, 97, 98, 99,  0,  0,  0,
++    0,  0, 51,  0,  0,  0,  0,100,101,  0,  0,  0,  0,  0,  0,102,
++    0,  0,  0,  0,  0,  0,103,  0,  0,  0,  0,  0,  0,104,105,  0,
++    0,  0,  0,  0,  0,  0,  0,  0,  0,106,  0,  0,107,  0,  0,  0,
++    0,  0,  0,  0,  0,  0,  0,108,109,  0,  0,110,  0,  0,  0,  0,
++    0,  0,111,  0,112,  0,105,  0,  0,  0,  0,  0,113,114,  0,  0,
++    0,  0,  0,  0,  0,115,  0,  0,  0,116,  0,  0,  0,117,  0,118,
++    0,  0,  0,  0,  0,  0,  1,  2,  3,  4,  5,  6,  7,  0,  8,  0,
++    0,  0,  0,  9, 10, 11, 12,  0,  0,  0,  0, 13,  0,  0, 14, 15,
++    0, 16,  0, 17, 18,  0,  0, 19,  0, 20, 21,  0,  0,  0,  0,  0,
++   22, 23,  0, 24, 25,  0,  0, 26,  0,  0,  0, 27,  0,  0, 28, 29,
++   30, 31,  0,  0,  0, 32, 33, 34,  0,  0, 33,  0,  0, 35, 33,  0,
++    0,  0, 33, 36,  0,  0,  0,  0,  0, 37, 38,  0,  0,  0,  0,  0,
++    0, 39, 40,  0,  0,  0,  0,  0,  0, 41, 42,  0,  0,  0,  0, 43,
++    0, 44,  0,  0,  0, 45, 46,  0,  0,  0, 47,  0,  0,  0,  0,  0,
++    0, 48, 49,  0,  0,  0,  0, 50,  0,  0,  0, 51,  0, 52,  0, 53,
++    0,  0,  0,  0, 54,  0,  0,  0,  0, 55,  0, 56,  0,  0,  0,  0,
++   57, 58,  0,  0,  0, 59, 60,  0,  0,  0,  0,  0,  0, 61, 52,  0,
++   62, 63,  0,  0, 64,  0,  0,  0, 65, 66,  0,  0,  0, 67,  0, 68,
++   69, 70, 71, 72,  1, 73,  0, 74, 75, 76,  0,  0, 77, 78,  0,  0,
++    0, 79,  0,  0,  1,  1,  0,  0, 80,  0,  0, 81,  0,  0,  0,  0,
++   77, 82,  0, 83,  0,  0,  0,  0,  0, 78, 84,  0, 85,  0, 52,  0,
++    1, 78,  0,  0, 86,  0,  0, 87,  0,  0,  0,  0,  0, 88, 57,  0,
++    0,  0,  0,  0,  0, 89, 90,  0,  0, 84,  0,  0, 33,  0,  0, 91,
++    0,  0,  0,  0, 92,  0,  0,  0,  0, 49,  0,  0, 93,  0,  0,  0,
++    0, 94, 95,  0,  0, 96,  0,  0, 97,  0,  0,  0, 98,  0,  0,  0,
++   99,  0,  0,  0,100,  0,  0,  0,  0,101,102, 93,  0,  0,103,  0,
++    0,  0, 84,  0,  0,104,  0,  0,  0,105,106,  0,  0,107,108,  0,
++    0,  0,  0,  0,  0,109,  0,  0,110,  0,  0,  0,  0,111, 33,  0,
++  112,113,114, 57,  0,  0,115, 35,  0,  0,116,  0,  0,  0,117,  0,
++    0,  0,  0,  0,  0,118,  0,  0,119,  0,  0,  0,  0,120, 88,  0,
++    0,  0,  0,  0, 57,  0,  0,  0,  0, 52,121,  0,  0,  0,  0,122,
++    0,  0,123,  0,  0,  0,  0,121,  0,  0,124,  0,  0,  0,  0,  0,
++   79,  0,  0,  0,  0,125,  0,  0,  0,126,  0,  0,  0,127,  0,128,
++    0,  0,  0,  0,129,130,131,  0,132,  0,133,  0,  0,  0,134,135,
++  136,  0, 77,  0,  0,  0,  0,  0, 35,  0,  0,  0,137,  0,  0,  0,
++  138,  0,  0,  0,139,  0,  0,140,  0,  0,141,  0,  0,  0,  0,  0,
++    0,  0,  1,  1,  1,  1,  1,  2,  3,  4,  5,  6,  7,  4,  4,  8,
++    9, 10,  1, 11, 12, 13, 14, 15, 16, 17, 18,  1,  1,  1, 19,  1,
++    0,  0, 20, 21, 22,  1, 23,  4, 21, 24, 25, 26, 27, 28, 29, 30,
++    0,  0,  1,  1, 31,  0,  0,  0, 32, 33, 34, 35,  1, 36, 37,  0,
++    0,  0,  0, 38,  1, 39, 14, 39, 40, 41, 42,  0,  0,  0, 43, 36,
++   44, 45, 21, 45, 46,  0,  0,  0, 19,  1, 21,  0,  0, 47,  0, 38,
++   48,  1,  1, 49, 49, 50,  0,  0, 51,  0,  0, 19, 52,  1,  0,  0,
++   38, 14,  4,  1,  1,  1, 53, 21, 43, 52, 54, 21, 35,  1,  0,  0,
++    0, 55,  0,  0,  0, 56, 57, 58,  0,  0,  0,  0,  0, 59,  0, 60,
++    0,  0,  0,  0, 61, 62,  0,  0, 63,  0,  0,  0, 64,  0,  0,  0,
++   65,  0,  0,  0, 66,  0,  0,  0, 67,  0,  0,  0, 68,  0,  0, 69,
++   70,  0, 71, 72, 73, 74, 75, 76,  0,  0,  0, 77,  0,  0,  0, 78,
++   79,  0,  0,  0,  0, 47,  0,  0,  0, 49,  0, 80,  0,  0,  0, 62,
++    0,  0, 63,  0,  0, 81,  0,  0, 82,  0,  0,  0, 83,  0,  0, 19,
++   84,  0, 62,  0,  0,  0,  0, 49,  1, 85,  1, 52, 15, 86, 36, 10,
++   21, 87,  0, 55,  0,  0,  0,  0, 19, 10,  1,  0,  0,  0,  0,  0,
++   88,  0,  0, 89,  0,  0, 88,  0,  0,  0,  0, 78,  0,  0, 87,  9,
++   12,  4, 90,  8, 91, 47,  0, 58, 50,  0, 21,  1, 21, 92, 93,  1,
++    1,  1,  1, 94, 95, 96, 97,  1, 98, 58, 81, 99,100,  4, 58,  0,
++    0,  0,  0,  0,  0, 19, 50,  0,  0,  0,  0,  0,  0, 61,  0,  0,
++  101,102,  0,  0,103,  0,  0,  1,  1, 50,  0,  0,  0, 38,  0, 63,
++    0,  0,  0,  0,  0, 62,  0,  0,104, 68, 61,  0,  0,  0, 78,  0,
++    0,  0,105,106, 58, 38, 81,  0,  0,  0,  0,  0,  0,107,  1, 14,
++    4, 12, 84,  0,  0,  0,  0, 38, 87,  0,  0,  0,  0,108,  0,  0,
++  109, 61,  0,110,  0,  0,  0,  1,  0,  0,  0,  0, 49, 50,  0,  0,
+    19, 58,  0,  0,  0, 51,  0,111, 14, 52,112, 41,  0,  0, 62,  0,
+     0, 61,  0,  0,113,  0, 87,  0,  0,  0, 61, 62,  0,  0, 62,  0,
+    89,  0,  0,113,  0,  0,  0,  0,114,  0,  0,  0, 78, 55,  0, 38,
+-    1, 58,  1, 58,  0,  0, 63, 89,  0,  0,115,  0,  0,  0, 55,  0,
+-    0,  0,  0,115,  0,  0,  0,  0, 61,  0,  0,  0,  0, 79,  0, 61,
+-    0,  0,  0,  0, 56,  0, 89, 80,  0,  0, 79,  0,  0,  0,  8, 91,
+-    0,  0,  1, 87,  0,  0,116,  0,  0,  0,  0,  0,  0,117,  0,118,
+-  119,120,121,  0,104,  4,122, 49, 23,  0,  0,  0, 38, 50, 38, 58,
+-    0,  0,  1, 87,  1,  1,  1,  1, 39,  1, 48,105, 87,  0,  0,  0,
+-    0,  1,  0,  0,  0,123,  4,122,  0,  0,  0,  1,124,  0,  0,  0,
+-    0,  0,230,230,230,230,230,232,220,220,220,220,232,216,220,220,
+-  220,220,220,202,202,220,220,220,220,202,202,220,220,220,  1,  1,
+-    1,  1,  1,220,220,220,220,230,230,230,230,240,230,220,220,220,
+-  230,230,230,220,220,  0,230,230,230,220,220,220,220,230,232,220,
+-  220,230,233,234,234,233,234,234,233,230,  0,  0,  0,230,  0,220,
+-  230,230,230,230,220,230,230,230,222,220,230,230,220,220,230,222,
+-  228,230, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22,
+-    0, 23,  0, 24, 25,  0,230,220,  0, 18, 30, 31, 32,  0,  0,  0,
+-    0, 27, 28, 29, 30, 31, 32, 33, 34,230,230,220,220,230,220,230,
+-  230,220, 35,  0,  0,  0,  0,  0,230,230,230,  0,  0,230,230,  0,
+-  220,230,230,220,  0,  0,  0, 36,  0,  0,230,220,230,230,220,220,
+-  230,220,220,230,220,230,220,230,230,  0,  0,220,  0,  0,230,230,
+-    0,230,  0,230,230,230,230,230,  0,  0,  0,220,220,220,230,220,
+-  220,220,230,230,  0,220, 27, 28, 29,230,  7,  0,  0,  0,  0,  9,
+-    0,  0,  0,230,220,230,230,  0,  0,  0,  0,  0,230,  0,  0, 84,
+-   91,  0,  0,  0,  0,  9,  9,  0,  0,  0,  0,  0,  9,  0,103,103,
+-    9,  0,107,107,107,107,118,118,  9,  0,122,122,122,122,220,220,
+-    0,  0,  0,220,  0,220,  0,216,  0,  0,  0,129,130,  0,132,  0,
+-    0,  0,  0,  0,130,130,130,130,  0,  0,130,  0,230,230,  9,  0,
+-  230,230,  0,  0,220,  0,  0,  0,  0,  7,  0,  9,  9,  0,  9,  9,
+-    0,  0,  0,230,  0,  0,  0,228,  0,  0,  0,222,230,220,220,  0,
+-    0,  0,230,  0,  0,220,230,220,  0,220,230,230,230,  0,  0,  0,
+-    9,  9,  0,  0,  7,  0,230,  0,  1,  1,  1,  0,  0,  0,230,234,
+-  214,220,202,230,230,230,230,230,232,228,228,220,218,230,233,220,
+-  230,220,230,230,  1,  1,  1,  1,  1,230,  0,  1,  1,230,220,230,
+-    1,  1,  0,  0,218,228,232,222,224,224,  0,  8,  8,  0,  0,  0,
+-    0,220,230,  0,230,230,220,  0,  0,230,  0,  0, 26,  0,  0,220,
+-    0,230,230,  1,220,  0,  0,230,220,  0,  0,  0,220,220,  0,  0,
+-  230,220,  0,  9,  7,  0,  0,  7,  9,  0,  0,  0,  9,  7,  6,  6,
+-    0,  0,  0,  0,  1,  0,  0,216,216,  1,  1,  1,  0,  0,  0,226,
+-  216,216,216,216,216,  0,220,220,220,  0,232,232,220,230,230,230,
+-    7,  0, 16, 17, 17, 33, 17, 49, 17, 17, 84, 97,135,145, 26, 17,
++    1, 58,  1, 58,  0,  0,  0,  0,  0, 88, 63, 89,  0,  0,115,  0,
++    0,  0, 55,  0,  0,  0,  0,115,  0,  0,  0,  0, 61,  0,  0,  0,
++    0, 79,  0, 61,  0,  0,  0,  0, 56,  0, 89, 80,  0,  0, 79,  0,
++    0,  0,  8, 91,  0,  0,  1, 87,  0,  0,116,  0,  0,  0,  0,  0,
++    0,117,  0,118,119,120,121,  0,104,  4,122, 49, 23,  0,  0,  0,
++   38, 50, 38, 58,  0,  0,  1, 87,  1,  1,  1,  1, 39,  1, 48,105,
++   87,  0,  0,  0,  0,  1,  0,  0,  0,123,  0,  0,  0,112,  4,122,
++    0,  0,  0,  1,124,  0,  0,  0,  0,  0,230,230,230,230,230,232,
++  220,220,220,220,232,216,220,220,220,220,220,202,202,220,220,220,
++  220,202,202,220,220,220,  1,  1,  1,  1,  1,220,220,220,220,230,
++  230,230,230,240,230,220,220,220,230,230,230,220,220,  0,230,230,
++  230,220,220,220,220,230,232,220,220,230,233,234,234,233,234,234,
++  233,230,  0,  0,  0,230,  0,220,230,230,230,230,220,230,230,230,
++  222,220,230,230,220,220,230,222,228,230, 10, 11, 12, 13, 14, 15,
++   16, 17, 18, 19, 19, 20, 21, 22,  0, 23,  0, 24, 25,  0,230,220,
++    0, 18, 30, 31, 32,  0,  0,  0,  0, 27, 28, 29, 30, 31, 32, 33,
++   34,230,230,220,220,230,220,230,230,220, 35,  0,  0,  0,  0,  0,
++  230,230,230,  0,  0,230,230,  0,220,230,230,220,  0,  0,  0, 36,
++    0,  0,230,220,230,230,220,220,230,220,220,230,220,230,220,230,
++  230,  0,  0,220,  0,  0,230,230,  0,230,  0,230,230,230,230,230,
++    0,  0,  0,220,220,220,230,220,220,220,230,230,  0,220, 27, 28,
++   29,230,  7,  0,  0,  0,  0,  9,  0,  0,  0,230,220,230,230,  0,
++    0,  0,  0,  0,230,  0,  0, 84, 91,  0,  0,  0,  0,  9,  9,  0,
++    0,  0,  0,  0,  9,  0,103,103,  9,  0,107,107,107,107,118,118,
++    9,  0,122,122,122,122,220,220,  0,  0,  0,220,  0,220,  0,216,
++    0,  0,  0,129,130,  0,132,  0,  0,  0,  0,  0,130,130,130,130,
++    0,  0,130,  0,230,230,  9,  0,230,230,  0,  0,220,  0,  0,  0,
++    0,  7,  0,  9,  9,  0,  9,  9,  0,  0,  0,230,  0,  0,  0,228,
++    0,  0,  0,222,230,220,220,  0,  0,  0,230,  0,  0,220,230,220,
++    0,220,230,230,230,  0,  0,  0,  9,  9,  0,  0,  7,  0,230,  0,
++    1,  1,  1,  0,  0,  0,230,234,214,220,202,230,230,230,230,230,
++  232,228,228,220,218,230,233,220,230,220,230,230,  1,  1,  1,  1,
++    1,230,  0,  1,  1,230,220,230,  1,  1,  0,  0,218,228,232,222,
++  224,224,  0,  8,  8,  0,  0,  0,  0,220,230,  0,230,230,220,  0,
++    0,230,  0,  0, 26,  0,  0,220,  0,230,230,  1,220,  0,  0,230,
++  220,  0,  0,  0,220,220,  0,  0,230,220,  0,  9,  7,  0,  0,  7,
++    9,  0,  0,  0,  9,  7,  6,  6,  0,  0,  0,  0,  1,  0,  0,216,
++  216,  1,  1,  1,  0,  0,  0,226,216,216,216,216,216,  0,220,220,
++  220,  0,232,232,220,230,230,230,  7,  0, 16, 17, 17, 33, 17, 49,
++   17, 17, 84, 97,135,145, 26, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+    17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+    17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
++   17, 17, 17, 17, 17, 17, 17, 17, 17,177,  0,  1,  2,  3,  3,  3,
++    3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  4,  3,
++    3,  3,  3,  3,  5,  3,  3,  3,  3,  3,  6,  7,  8,  3,  3,  3,
++    3,  3,  9, 10, 11, 12, 13,  3,  3,  3,  3,  3,  3,  3,  3, 14,
++    3, 15,  3,  3,  3,  3,  3,  3, 16, 17, 18, 19, 20, 21,  3,  3,
++    3, 22, 23, 24,  3,  3,  3,  3,  3,  3, 25,  3,  3,  3,  3,  3,
++    3,  3,  3, 26,  3,  3, 27, 28,  0,  1,  0,  0,  0,  0,  0,  1,
++    0,  2,  0,  0,  0,  3,  0,  0,  0,  3,  0,  0,  0,  0,  0,  4,
++    0,  5,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
++    0,  6,  0,  0,  0,  7,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
++    0,  8,  9,  0,  0,  0,  0,  0,  0,  9,  0,  9,  0,  0,  0,  0,
++    0,  0,  0, 10, 11, 12, 13,  0,  0, 14, 15, 16,  6,  0, 17, 18,
++   19, 19, 19, 20, 21, 22, 23, 24, 19, 25,  0, 26, 27, 19, 19, 28,
++   29, 30,  0, 31,  0,  0,  0,  8,  0,  0,  0,  0,  0,  0,  0, 19,
++   28,  0, 32, 33,  9, 34, 35, 19,  0,  0, 36, 37, 38, 39, 40, 19,
++    0, 41, 42, 43, 44, 31,  0,  1, 45, 42,  0,  0,  0,  0,  0, 32,
++   14, 14,  0,  0,  0,  0, 14,  0,  0, 46, 47, 47, 47, 47, 48, 49,
++   47, 47, 47, 47, 50, 51, 52, 53, 43, 21,  0,  0,  0,  0,  0,  0,
++    0, 54,  6, 55,  0, 14, 19,  1,  0,  0,  0,  0, 56, 57,  0,  0,
++    0,  0,  0, 19, 58, 31,  0,  0,  0,  0,  0,  0,  0, 59, 14,  0,
++    0,  0,  0,  1,  0,  2,  0,  0,  0,  3,  0,  0,  0, 60, 61,  0,
++    0,  0,  0,  0,  0,  0,  1,  0,  0,  0,  0,  0,  2,  3,  0,  4,
++    5,  0,  0,  6,  0,  0,  0,  7,  0,  0,  0,  1,  1,  0,  0,  8,
++    9,  0,  8,  9,  0,  0,  0,  0,  8,  9, 10, 11, 12,  0,  0,  0,
++   13,  0,  0,  0,  0, 14, 15, 16, 17,  0,  0,  0,  1,  0,  0, 18,
++   19,  0,  0,  0, 20,  0,  0,  0,  1,  1,  1,  1,  0,  1,  1,  1,
++    1,  1,  1,  1,  0,  8, 21,  9,  0,  0, 22,  0,  0,  0,  0,  1,
++    0, 23, 24, 25,  0,  0, 26,  0,  0,  0,  8, 21, 27,  0,  1,  0,
++    0,  1,  1,  1,  1,  0,  1, 28, 29, 30,  0, 31, 32, 20,  1,  1,
++    0,  0,  0,  8, 21,  9,  1,  4,  5,  0,  0,  0, 33,  9,  0,  1,
++    1,  1,  0,  8, 21, 21, 21, 21, 34,  1, 35, 21, 21, 21,  9, 36,
++    0,  0, 37, 38,  1,  0, 39,  0,  0,  0,  1,  0,  1,  0,  0,  0,
++    0,  8, 21,  9,  1,  0,  0,  0, 40,  0,  8, 21, 21, 21, 21, 21,
++   21, 21, 21,  9,  0,  1,  1,  1,  1,  8, 21, 21, 21,  9,  0,  0,
++    0, 41,  0, 42, 43,  0,  0,  0,  1, 44,  0,  0,  0, 45,  8,  9,
++    1,  0,  0,  0,  8, 21, 21, 21,  9,  0,  1,  0,  1,  1,  8, 21,
++   21,  9,  0,  4,  5,  8,  9,  1,  0,  0,  0,  1,  2,  3,  3,  4,
++    5,  6,  7,  8,  9, 10, 11, 12, 13, 14,  3,  3,  3,  3,  3,  3,
++    3, 15,  3, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+    17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+-   17,177,  0,  1,  2,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,
+-    3,  3,  3,  3,  3,  3,  4,  3,  3,  3,  3,  3,  5,  3,  3,  3,
+-    3,  3,  6,  7,  8,  3,  3,  3,  3,  3,  9, 10, 11, 12, 13,  3,
+-    3,  3,  3,  3,  3,  3,  3, 14,  3, 15,  3,  3,  3,  3,  3,  3,
+-   16, 17, 18, 19, 20, 21,  3,  3,  3, 22, 23, 24,  3,  3,  3,  3,
+-    3,  3, 25,  3,  3,  3,  3,  3,  3,  3,  3, 26,  3,  3, 27, 28,
+-    0,  1,  0,  0,  0,  0,  0,  1,  0,  2,  0,  0,  0,  3,  0,  0,
+-    0,  3,  0,  0,  0,  0,  0,  4,  0,  5,  0,  0,  0,  0,  0,  0,
+-    0,  0,  0,  0,  0,  0,  0,  0,  0,  6,  0,  0,  0,  7,  0,  0,
+-    0,  0,  0,  0,  0,  0,  0,  0,  0,  8,  9,  0,  0,  0,  0,  0,
+-    0,  9,  0,  9,  0,  0,  0,  0,  0,  0,  0, 10, 11, 12, 13,  0,
+-    0, 14, 15, 16,  6,  0, 17, 18, 19, 19, 19, 20, 21, 22, 23, 24,
+-   19, 25,  0, 26, 27, 19, 19, 28, 29, 30,  0, 31,  0,  0,  0,  8,
+-    0,  0,  0,  0,  0,  0,  0, 19, 28,  0, 32, 33,  9, 34, 35, 19,
+-    0,  0, 36, 37, 38, 39, 40, 19,  0, 41, 42, 43, 44, 31,  0,  1,
+-   45, 42,  0,  0,  0,  0,  0, 32, 14, 14,  0,  0,  0,  0, 14,  0,
+-    0, 46, 47, 47, 47, 47, 48, 49, 47, 47, 47, 47, 50, 51, 52, 53,
+-   43, 21,  0,  0,  0,  0,  0,  0,  0, 54,  6, 55,  0, 14, 19,  1,
+-    0,  0,  0,  0, 56, 57,  0,  0,  0,  0,  0, 19, 58, 31,  0,  0,
+-    0,  0,  0,  0,  0, 59, 14,  0,  0,  0,  0,  1,  0,  2,  0,  0,
+-    0,  3,  0,  0,  0, 60, 61,  0,  0,  0,  0,  0,  0,  0,  1,  0,
+-    0,  0,  0,  0,  2,  3,  0,  4,  5,  0,  0,  6,  0,  0,  0,  7,
+-    0,  0,  0,  1,  1,  0,  0,  8,  9,  0,  8,  9,  0,  0,  0,  0,
+-    8,  9, 10, 11, 12,  0,  0,  0, 13,  0,  0,  0,  0, 14, 15, 16,
+-   17,  0,  0,  0,  1,  0,  0, 18, 19,  0,  0,  0, 20,  0,  0,  0,
+-    1,  1,  1,  1,  0,  1,  1,  1,  1,  1,  1,  1,  0,  8, 21,  9,
+-    0,  0, 22,  0,  0,  0,  0,  1,  0, 23, 24, 25,  0,  0, 26,  0,
+-    0,  0,  8, 21, 27,  0,  1,  0,  0,  1,  1,  1,  1,  0,  1, 28,
+-   29, 30,  0, 31, 32, 20,  1,  1,  0,  0,  0,  8, 21,  9,  1,  4,
+-    5,  0,  0,  0, 33,  9,  0,  1,  1,  1,  0,  8, 21, 21, 21, 21,
+-   34,  1, 35, 21, 21, 21,  9, 36,  0,  0, 37, 38,  1,  0, 39,  0,
+-    0,  0,  1,  0,  1,  0,  0,  0,  0,  8, 21,  9,  1,  0,  0,  0,
+-   40,  0,  8, 21, 21, 21, 21, 21, 21, 21, 21,  9,  0,  1,  1,  1,
+-    1,  8, 21, 21, 21,  9,  0,  0,  0, 41,  0, 42, 43,  0,  0,  0,
+-    1, 44,  0,  0,  0, 45,  8,  9,  1,  0,  0,  0,  8, 21, 21, 21,
+-    9,  0,  1,  0,  1,  1,  8, 21, 21,  9,  0,  4,  5,  8,  9,  1,
+-    0,  0,  0,  1,  2,  3,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12,
+-   13, 14,  3,  3,  3,  3,  3,  3,  3, 15,  3, 16, 17, 17, 17, 17,
+    17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+    17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+    17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+-   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+-   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+-   17, 17, 18,  0,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11,
+-   12, 13, 14, 15, 16, 17, 17, 17, 18, 17, 19, 20, 21, 22, 23, 23,
+-   23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 24, 23, 23, 23, 23, 23,
+-   23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+-   23, 23, 23, 23, 25, 25, 26, 27, 28, 29, 30, 30, 30, 30, 30, 30,
+-   30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
++   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 18,  0,  0,  1,  2,  3,
++    4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17, 17, 17,
++   18, 17, 19, 20, 21, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
++   23, 23, 24, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
++   23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 25, 25, 26, 27,
++   28, 29, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
++   30, 30, 30, 30, 30, 30, 30, 30, 31, 31, 31, 31, 31, 31, 31, 31,
++   31, 31, 31, 31, 31, 31, 31, 31, 32, 33, 34, 35, 36, 37, 38, 39,
++   40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 52, 53, 31,
++   31, 31, 31, 54, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 56, 57,
++   31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 58, 31, 31, 31,
++   59, 60, 61, 62, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63,
++   63, 64, 65, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
++   31, 31, 31, 66, 67, 68, 31, 31, 31, 31, 69, 31, 31, 31, 31, 31,
++   31, 31, 17, 70, 71, 72, 17, 17, 73, 74, 31, 75, 76, 77, 78, 79,
++   80, 31, 81, 82, 17, 83, 17, 17, 17, 17, 31, 31, 23, 23, 23, 23,
++   23, 23, 23, 84, 31, 31, 31, 31, 23, 84, 31, 31, 23, 23, 31, 31,
+    31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
+-   32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+-   48, 49, 50, 51, 52, 52, 53, 31, 31, 31, 31, 54, 55, 55, 56, 31,
+-   31, 31, 31, 31, 31, 31, 57, 58, 31, 31, 31, 31, 31, 31, 31, 31,
+-   31, 31, 31, 31, 31, 31, 31, 31, 59, 60, 31, 61, 62, 62, 62, 62,
+-   62, 62, 62, 62, 62, 62, 62, 62, 62, 63, 64, 31, 31, 31, 31, 31,
+-   31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 65, 66, 67, 31, 31,
+-   31, 31, 68, 31, 31, 31, 31, 31, 31, 31, 31, 69, 70, 71, 17, 17,
+-   72, 73, 31, 74, 75, 76, 77, 78, 79, 31, 80, 81, 17, 82, 17, 17,
+-   17, 17, 31, 31, 23, 23, 23, 23, 23, 23, 23, 83, 31, 31, 31, 31,
+-   23, 83, 31, 31, 23, 23, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
+-   31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
+-   31, 31, 31, 31, 84,  0,  0,  1,  0,  1,  2,  3,  0,  1,  2,  3,
+-    4,  5,  6,  7,  0,  1,  2,  3,  4,  4,  4,  4,  4,  4,  5,  6,
+-    7,  8,  9, 10, 11, 11, 12, 11, 13, 14, 15, 16, 17, 18, 19, 20,
+-   21, 22, 23, 24, 25, 26, 19, 27, 28, 29, 30, 30, 31, 31, 32, 32,
+-   33, 33, 34, 34, 35, 35, 36, 36, 37, 37, 38, 38, 39, 40, 41, 41,
+-   42, 42, 42, 43, 44, 44, 45, 46, 47, 47, 47, 47, 48, 48, 48, 48,
+-   48, 48, 49, 50, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 52, 53,
+-   54, 55, 56, 56, 57, 58, 59, 51, 60, 61, 62, 63, 64, 65, 66,  7,
+-   67, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76,  7,  4,  4,  4,  4,
+-   77, 77, 77, 77, 78, 79, 80, 81, 82, 83, 84,  0,  0,  0,  0,  0,
+-    0,  0,  0,  0, 85, 85, 85, 85,  0,  0,  0,  0, 86, 87, 88, 88,
+-   89, 90, 48, 91,  0,  0, 92, 92, 92, 92, 92, 93, 94, 95, 96, 97,
+-   98, 47, 99,100,101,102,  0,103,104,105,  0,  0, 92, 92, 92, 92,
+-   92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,  0,106,106,106,106,
+-  106,106,106,106,106,106,106,107,108,108,108,108,108, 11,109,110,
+-  111,  4,112,  4,113,114,115,116,117,118,119,120,121,122,123,124,
+-  125,126, 50,127, 47, 47, 47, 47, 47, 47, 47, 47,128,128,128,128,
+-  128,128,128,128,128,128,128,128, 92, 92, 92, 92, 92, 92, 92, 92,
+-  129,130, 19, 19, 19, 19, 19, 19,131, 19, 19, 19,132,133, 19,134,
+-  135,136,137,101,138,138,138,138,  0, 77,139,140,128,128,141,142,
+-  143,144,145,146,147,148,149,150,151,152,153,153,154,154,154,154,
+-  154,154,  4,  4,155,156,157,158,159,160,161,162,163,164,165,166,
+-  167,168,169,169,170,170,171,171,172,172,128,128, 19, 19,173,174,
+-  175,176,177,178,179,179,180,181,182,183,184,185,186,186,187,188,
+-  189,190,128,128,191,191,192,192,128,128,193,193,194,195,196,196,
+-  197,197,128,128,198,198,199,199,200,200,201,201,202,203,204,205,
+-   28, 28,128,128,206,207,208,208,209,210,211,211,128,128,212,212,
+-  213,213,214, 34,215,215,215,215,215,215,215,215,215,215,215,215,
+-  215,215,128,128,128,128,128,128,128,128,216,216,217,217,217,217,
+-  217,217,217,217,217,217,128,128,128,128,128,128,218,218,218,218,
+-  218,218,218,218,218,218,128,128,128,128,128,128,110,110,110,110,
+-  110,110,110,110,110,219,220,221,222,222,222,222,223,223,223,223,
+-  224,224,224,225,226,226,226,226,226,226,226,226,226,226,226,226,
+-  227,227,227,227,227,227,227,227,226,226,128,128,128,128,128,128,
+-  128,128,104,104,228,229,229,229,230,231,232,232,232,232,232,232,
+-  128,128,128,128,233,233,234,  0,128,128,128,128,128,128,128,128,
+-    7,235,  0,  0,  0,  0,  0,  0,  0,236,237,  0, 77, 77,  0,  0,
+-    0,  0,128,128,238,238,238,238,238,238,238,238,238,238,238,238,
+-  128,128,128,128,128,128,128,128,  4,  4,128,128,239, 11, 11, 11,
+-  240,240,128,128,128,128,241,242,128,128,128,128,128,128,243,243,
+-  128,128,128,128,128,128,128,128,128,128, 48, 48,244,244,244,244,
+-  245,245,128,128,  0,  0,  0,  0,  0,  0,128,128, 19, 19, 19, 19,
+-  128,128,128,128,246,  0,128,128,  0,  0,  0,  0, 92, 92,128,128,
++   31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 85,  0,  0,  1,
++    0,  1,  2,  3,  0,  1,  2,  3,  4,  5,  6,  7,  0,  1,  2,  3,
++    4,  4,  4,  4,  4,  4,  5,  6,  7,  8,  9, 10, 11, 11, 12, 11,
++   13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 19, 27,
++   28, 29, 30, 30, 31, 31, 32, 32, 33, 33, 34, 34, 35, 35, 36, 36,
++   37, 37, 38, 38, 39, 40, 41, 41, 42, 42, 42, 43, 44, 44, 45, 46,
++   47, 47, 47, 47, 48, 48, 48, 48, 48, 48, 49, 50, 51, 51, 51, 51,
++   51, 51, 51, 51, 51, 51, 52, 53, 54, 55, 56, 56, 57, 58, 59, 51,
++   60, 61, 62, 63, 64, 65, 66,  7, 67, 67, 68, 69, 70, 71, 72, 73,
++   74, 75, 76,  7,  4,  4,  4,  4, 77, 77, 77, 77, 78, 79, 80, 81,
++   82, 83, 84,  0,  0,  0,  0,  0,  0,  0,  0,  0, 85, 85, 85, 85,
++    0,  0,  0,  0, 86, 87, 88, 88, 89, 90, 48, 91,  0,  0, 92, 92,
++   92, 92, 92, 93, 94, 95, 96, 97, 98, 47, 99,100,101,102,  0,103,
++  104,105,  0,  0, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
++   92, 92, 92,  0,106,106,106,106,106,106,106,106,106,106,106,107,
++  108,108,108,108,108, 11,109,110,111,  4,112,  4,113,114,115,116,
++  117,118,119,120,121,122,123,124,125,126, 50,127, 47, 47, 47, 47,
++   47, 47, 47, 47,128,128,128,128,128,128,128,128,128,128,128,128,
++   92, 92, 92, 92, 92, 92, 92, 92,129,130, 19, 19, 19, 19, 19, 19,
++  131, 19, 19, 19,132,133, 19,134,135,136,137,101,138,138,138,138,
++    0, 77,139,140,128,128,141,142,143,144,145,146,147,148,149,150,
++  151,152,153,154,155,155,155,155,155,155,  4,  4,156,157,158,159,
++  160,161,162,163,164,165,166,167,168,169,170,170,171,171,172,172,
++  173,174,174,174, 19, 19,175,176,177,178,179,180,181,181,182,183,
++  184,185,186,187,188,188,189,190,191,192,193,193,194,194,195,195,
++  128,128,196,196,197,198,199,200,201,201,128,128,202,202,203,203,
++  204,204,205,205,206,207,208,209, 28, 28,210,210,211,212,213,213,
++  214,215,216,216,128,128,217,217,218,218,219, 34,220,220,220,220,
++  220,220,220,220,220,220,220,220,220,220,128,128,128,128,128,128,
++  128,128,221,221,222,222,222,222,222,222,222,222,223,223,223,223,
++  223,223,223,223,223,223,128,128,128,128,128,128,128,128,128,128,
++  224,224,128,128,110,110,110,110,110,110,110,110,110,225,226,227,
++  228,228,228,228,128,128,128,128,229,229,128,128,230,230,230,230,
++  231,231,231,232,233,233,233,233,233,233,233,233,233,233,233,233,
++  234,234,234,234,234,234,234,234,233,233,128,128,128,128,128,128,
++  128,128,104,104,235,236,236,236,237,238,239,239,239,239,239,239,
++  128,128,128,128,240,240,241,  0,128,128,128,128,  0,  0,  0,  0,
++    7,242,  0,  0,  0,  0,  0,  0,  0,243,244,  0, 77, 77,  0,  0,
++    0,  0,128,128,245,245,245,245,245,245,245,245,245,245,245,245,
++  128,128,128,128,128,128,128,128,  4,  4,128,128,246, 11, 11, 11,
++  247,247,128,128,128,128,248,249,128,128,128,128,128,128,250,250,
++  128,128,251,251,128,128,128,128,128,128, 48, 48,252,252,252,252,
++  253,253,128,128,  0,  0,  0,  0,  0,  0,128,128, 19, 19, 19, 19,
++  128,128,128,128,254,  0,128,128,  0,  0,  0,  0, 92, 92,128,128,
+   128,128,128,128,  0,  0,128,128,  7,  7,  7,  7,  0,  0,  0,  0,
+     1,  2,  1,  2,  0,  0,  3,  3,  4,  5,  4,  5,  4,  4,  4,  4,
+     4,  4,  4,  6,  0,  0,  7,  0,  8,  8,  8,  8,  8,  8,  8,  9,
+@@ -5056,30 +5278,32 @@ _hb_ucd_u8[13386] =
+   137,137,138,138,138,138,139,  0,140,140,140,141,141,142,142,142,
+   143,143,144,144,144,144,144,144,145,145,145,145,145,146,146,146,
+   147,147,147,148,148,148,148,148,149,149,149,150,150,150,150,151,
+-  151,151,151,151,152,152,152,152,153,153,153,153,154,154,155,155,
+-  156,156,156,156,156,156,157,157,158,158,159,159,159,159,159,159,
+-  160,160,161,161,161,161,161,161,162,162,162,162,162,162,163,163,
+-  164,164,164,164,165,165,165,165,166,166,166,166,167,167,168,168,
+-  169,169,169,169,170,170,170,170,171,171,171,171,172,172,172,172,
+-  173,173,173,173,173,173,173,174,175,175,175,176,176,176,176,177,
+-  177,177,177,178,178,178,179,179,180,180,180,180,181,181,181,181,
+-  181,182,182,182,183,183,183,183,183,184,184,184,185,185,185,185,
+-  185,185,186, 43,187,187,187,187,188,188,188,189,189,189,189,189,
+-  190,190,190,191,190,190,190,190,192,192,192,192,193,193,193,193,
+-  194,194,194,194,195,195,195,195,195,195, 66, 66,196,196,196,196,
+-  197,197,197,197,198,198,198,198,199,199,199,199,200,200,200,200,
+-  201,201,201,201,202,202,202,202,202,203,203,203,203,203,203, 55,
+-  204,204,204,204,205,205,205,205,205,205,205,206,206,206,206,206,
+-  207,207,207,207,207,207,208,208,208,208,208,208,209,209,209,209,
+-  210,210,210,210,110,110,110,110,211,211,211,211,212,212,212,212,
+-  213,213,213,213,214,214,214,214,215,215,215,216,216,216,216,216,
+-  216,217,217,217,218,218,218,218,219,219,219,219,220,220,220,220,
+-  220,220,221, 94,222,222,222,222,223,223,223,223,224, 99, 99, 99,
+-   99, 99, 99, 99, 99, 99,102,225, 99,226,102,227,227,227,227,227,
+-  228,228,228,228,228,228,  0,  0,  8,  0,  0,  0,  0,  0,229,230,
+-  231,  0,232,  0,233,233,233,233, 91, 91, 91, 13,234,234,234,234,
+-  235,235,235,235,236,236,236,236,237,237,237,237,238,238,238,238,
+-  239,239,239,239,240,  0,  0,  0,  0,  0,  0,  0,  1,  2,  2,  2,
++  151,151,151,151,152,152,152,152,153,153,153,153,154,154,154,154,
++  155,155,156,156,157,157,157,157,157,157,158,158,159,159,160,160,
++  160,160,160,160,161,161,162,162,162,162,162,162,163,163,163,163,
++  163,163,164,164,165,165,165,165,166,166,166,166,167,167,167,167,
++  168,168,169,169,170,170,170,170,171,171,171,171,172,172,172,172,
++  173,173,173,173,174,174,174,174,175,175,175,175,176, 21, 21, 21,
++  177,177,177,178,178,178,178,179,179,179,179,180,180,180,181,181,
++  182,182,182,182,183,183,183,183,183,184,184,184,185,185,185,185,
++  185,186,186,186,187,187,187,187,187,187,188, 43,189,189,189,189,
++  190,190,190,191,191,191,191,191,192,192,192,193,192,192,192,192,
++  194,194,194,194,195,195,195,195,196,196,196,196,197,197,197,197,
++  198,198,198,198,198,198, 66, 66,199,199,199,199,199, 49, 49, 49,
++  200,200,200,200,201,201,201,201,202,202,202,202,203,203,203,203,
++  204,204,204,204,205,205,205,205,205,206,206,206,206,206,206, 55,
++  207,207,207,207,208,208,208,208,209,209,209,209,209,209,209,210,
++  210,210,210,210,211,211,211,211,211,211,212,212,212,212,212,212,
++  213,213,213,213,214,214,214,214,110,110,110,110,215,215,215,215,
++  216,216,216,216,217,217,217,217,218,218,218,218,219,219,219,219,
++  220,220,220,221,221,221,221,221,221,222,222,222,223,223,223,223,
++  224,224,224,224,225,225,225,225,226,226,226,226,226,226,227, 94,
++  228,228,228,228,229,229,229,229,230, 99, 99, 99, 99, 99, 99, 99,
++   99, 99,102,231, 99,232,102,233,233,233,233,233,234,234,234,234,
++  234,234,  0,  0,  8,  0,  0,  0,  0,  0,235,236,237,  0,238,  0,
++  239,239,239,239, 91, 91, 91, 13,240,240,240,240,241,241,241,241,
++  242,242,242,242,243,243,243,243,244,244,244,244,245,245,245,245,
++  246,246,246,246,247,  0,  0,  0,  0,  0,  0,  0,  1,  2,  2,  2,
+     2,  2,  3,  0,  0,  0,  4,  0,  2,  2,  2,  2,  2,  3,  2,  2,
+     2,  2,  5,  0,  2,  5,  6,  0,  7,  7,  7,  7,  8,  9,  8, 10,
+     8, 11,  8,  8,  8,  8,  8,  8, 12, 13, 13, 13, 14, 14, 14, 14,
+@@ -5123,98 +5347,102 @@ _hb_ucd_u8[13386] =
+   163,163,163,163,164,164,164,164,165,165,165,165,166,166,166,166,
+   167,167,167,167,168,168,168,168,169,169,169,169,170,170,170,170,
+   171,171,171,171,172,172,172,172,173,173,173,173,174,174,174,174,
+-  174,174,174,175,176,176,176,176,177,177,177,177,178,178,178,178,
++  175,175,175,175,176,176,176,176,177, 20, 20, 20,178,178,178,178,
+   179,179,179,179,180,180,180,180,181,181,181,181,182,182,182,182,
+   183,183,183,183,184,184,184,184,185,185,185,185,186,186,186,186,
+-  187, 45, 45, 45,188,188,188,188,189,189,189,189,190,190,190,190,
+-  191,191,191,191,191,191,192,191,193,193,193,193,194,194,194,194,
++  187,187,187,187,188,188,188,188,189, 45, 45, 45,190,190,190,190,
++  191,191,191,191,192,192,192,192,193,193,193,193,193,193,194,193,
+   195,195,195,195,196,196,196,196,197,197,197,197,198,198,198,198,
+   199,199,199,199,200,200,200,200,201,201,201,201,202,202,202,202,
+   203,203,203,203,204,204,204,204,205,205,205,205,206,206,206,206,
+   207,207,207,207,208,208,208,208,209,209,209,209,210,210,210,210,
+   211,211,211,211,212,212,212,212,213,213,213,213,214,214,214,214,
+   215,215,215,215,216,216,216,216,217,217,217,217,218,218,218,218,
+-  219,219,219,219,220,220,220,220,221,221,221,221,222,223,223,223,
+-  224,224,224,224,223,223,223,223,225,106,106,106,226,106,106,106,
+-  106,227,109,109,228,228,228,228,229,229,229,229,  0,230, 86,  0,
+-    0,  0,230,  7, 82,138,  7,  0,  0,  0,231, 86,232,232,232,232,
+-  233,233,233,233,234,234,234,234,235,235,235,235,236,236,236,236,
+-  237,237,237,237,238,238,238,238,239,  0,  0,  0,  0,  0,  0,  0,
+-    0, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,  0,  0,  0, 19,  0,
+-   19,  0,  0,  0,  0,  0, 26, 26,  1,  1,  1,  1,  9,  9,  9,  9,
+-    0,  9,  9,  9,  9,  9,  0,  9,  9,  0,  9,  0,  9,  9, 55, 55,
+-   55, 55, 55, 55,  6,  6,  6,  6,  6,  1,  1,  6,  6,  4,  4,  4,
+-    4,  4,  4,  4,  4, 14, 14, 14, 14, 14, 14, 14,  3,  3,  3,  3,
+-    3,  0,  3,  3,  0,  3,  3,  3,  3,  3,  3,  0,  3,  3,  3,  1,
+-    1,  1,  3,  3,  1,  3,  3,  3, 37, 37, 37, 37, 38, 38, 38, 38,
+-   64, 64, 64, 64, 90, 90, 90, 90, 95, 95, 95, 95,  3,  3,  0,  3,
+-    7,  7,  7,  7,  7,  1,  1,  1,  1,  7,  7,  7,  0,  0,  7,  7,
+-    5,  5,  5,  5, 11, 11, 11, 11, 10, 10, 10, 10, 21, 21, 21, 21,
+-   22, 22, 22, 22, 23, 23, 23, 23, 16, 16, 16, 16, 20, 20, 20, 20,
+-   36, 36, 36, 36, 24, 24, 24, 24, 24, 24, 24,  0, 18, 18, 18, 18,
+-   25, 25, 25, 25, 25,  0,  0,  0,  0, 25, 25, 25, 33, 33, 33, 33,
+-    8,  8,  8,  8,  8,  8,  8,  0, 12, 12, 12, 12, 30, 30, 30, 30,
+-   29, 29, 29, 29, 28, 28, 28, 28, 34, 34, 34, 34, 35, 35, 35, 35,
+-   35, 35, 35,  0,  0,  0, 35, 35, 45, 45, 45, 45, 44, 44, 44, 44,
+-   44,  0,  0,  0, 43, 43, 43, 43, 46, 46, 46, 46, 31, 31, 31, 31,
+-   32, 32,  0,  0, 32,  0, 32, 32, 32, 32, 32, 32, 48, 48, 48, 48,
+-   52, 52, 52, 52, 58, 58, 58, 58, 54, 54, 54, 54, 91, 91, 91, 91,
+-   62, 62, 62, 62, 76, 76, 76, 76, 93, 93, 93, 93, 70, 70, 70, 70,
+-   73, 73, 73, 73,  1,  1,  1,  0,  1,  0,  1,  1,  1,  0,  0,  0,
+-    0,  1,  0,  0,  1,  1,  0,  0, 19, 19,  9,  9,  9,  9,  9,  6,
+-   19,  9,  9,  9,  9,  9, 19, 19,  9,  9,  9, 19,  6, 19, 19, 19,
+-   19, 19, 19,  9,  0,  0,  0, 19,  0,  0,  9,  0,  0,  0, 19, 19,
+-   27, 27, 27, 27, 56, 56, 56, 56, 61, 61, 61, 61, 13, 13, 13, 13,
+-    0, 13,  0, 13,  0, 13, 13, 13, 13, 13,  1,  1,  1,  1, 12, 12,
+-    0, 15, 15, 15, 15, 15, 15, 15, 15,  1,  1,  0,  0, 17, 17, 17,
+-   17, 17, 17, 17, 17, 17, 17,  0, 26, 26, 26, 26, 26, 12, 12, 12,
+-   12, 12, 12,  0, 39, 39, 39, 39, 86, 86, 86, 86, 77, 77, 77, 77,
+-   79, 79, 79, 79, 60, 60, 60, 60, 65, 65, 65, 65, 75, 75, 75, 75,
+-   69, 69, 69, 69, 69, 69,  0, 69, 74, 74, 74, 74, 84, 84, 84, 84,
+-   84, 84, 84,  0, 68, 68, 68, 68, 92, 92, 92, 92, 87, 87, 87, 87,
+-   19,  9, 19, 19, 19, 19,  0,  0,  2,  2,  2,  2, 19, 19, 19,  4,
+-    3,  3,  0,  0,  1,  1,  6,  6,  0,  0, 17, 17, 17, 17,  0,  0,
+-   49, 49, 49, 49,  0,  1,  1,  1, 71, 71, 71, 71, 67, 67, 67, 67,
+-   42, 42, 42, 42, 41, 41, 41, 41,118,118,118,118, 53, 53, 53, 53,
+-   59, 59, 59, 59, 40, 40, 40, 40, 51, 51, 51, 51, 50, 50, 50, 50,
+-  135,135,135,135,106,106,106,106,104,104,104,104,161,161,161,161,
++  219,219,219,219,220,220,220,220,221,221,221,221,222,222,222,222,
++  223,223,223,223,224,224,224,224,225,225,225,225,226,226,226,226,
++  227,227,227,227,228,229,229,229,230,230,230,230,229,229,229,229,
++  231,106,106,106,232,106,106,106,106,233,109,109,234,234,234,234,
++  235,235,235,235,  0,236, 86,  0,  0,  0,236,  7, 82,138,  7,  0,
++    0,  0,237, 86,238,238,238,238,239,239,239,239,240,240,240,240,
++  241,241,241,241,242,242,242,242,243,243,243,243,244,244,244,244,
++  245,245,245,245,246,  0,  0,  0,  0,  0,  0,  0,  0, 19, 19, 19,
++   19, 19, 19, 19, 19, 19, 19,  0,  0,  0, 19,  0, 19,  0,  0,  0,
++    0,  0, 26, 26,  1,  1,  1,  1,  9,  9,  9,  9,  0,  9,  9,  9,
++    9,  9,  0,  9,  9,  0,  9,  0,  9,  9, 55, 55, 55, 55, 55, 55,
++    6,  6,  6,  6,  6,  1,  1,  6,  6,  4,  4,  4,  4,  4,  4,  4,
++    4, 14, 14, 14, 14, 14, 14, 14,  3,  3,  3,  3,  3,  0,  3,  3,
++    0,  3,  3,  3,  3,  3,  3,  0,  3,  3,  3,  1,  1,  1,  3,  3,
++    1,  3,  3,  3, 37, 37, 37, 37, 38, 38, 38, 38, 64, 64, 64, 64,
++   90, 90, 90, 90, 95, 95, 95, 95,  3,  3,  0,  3,  7,  7,  7,  7,
++    7,  1,  1,  1,  1,  7,  7,  7,  0,  0,  7,  7,  5,  5,  5,  5,
++   11, 11, 11, 11, 10, 10, 10, 10, 21, 21, 21, 21, 22, 22, 22, 22,
++   23, 23, 23, 23, 16, 16, 16, 16, 20, 20, 20, 20, 36, 36, 36, 36,
++   24, 24, 24, 24, 24, 24, 24,  0, 18, 18, 18, 18, 25, 25, 25, 25,
++   25,  0,  0,  0,  0, 25, 25, 25, 33, 33, 33, 33,  8,  8,  8,  8,
++    8,  8,  8,  0, 12, 12, 12, 12, 30, 30, 30, 30, 29, 29, 29, 29,
++   28, 28, 28, 28, 34, 34, 34, 34, 35, 35, 35, 35, 35, 35, 35,  0,
++    0,  0, 35, 35, 45, 45, 45, 45, 44, 44, 44, 44, 44,  0,  0,  0,
++   43, 43, 43, 43, 46, 46, 46, 46, 31, 31, 31, 31, 32, 32,  0,  0,
++   32,  0, 32, 32, 32, 32, 32, 32, 48, 48, 48, 48, 52, 52, 52, 52,
++   58, 58, 58, 58, 54, 54, 54, 54, 91, 91, 91, 91, 62, 62, 62, 62,
++   76, 76, 76, 76, 93, 93, 93, 93, 70, 70, 70, 70, 73, 73, 73, 73,
++    1,  1,  1,  0,  1,  0,  1,  1,  1,  0,  0,  0,  0,  1,  0,  0,
++    1,  1,  0,  0, 19, 19,  9,  9,  9,  9,  9,  6, 19,  9,  9,  9,
++    9,  9, 19, 19,  9,  9,  9, 19,  6, 19, 19, 19, 19, 19, 19,  9,
++    0,  0,  0, 19,  0,  0,  9,  0,  0,  0, 19, 19, 27, 27, 27, 27,
++   56, 56, 56, 56, 61, 61, 61, 61, 13, 13, 13, 13,  0, 13,  0, 13,
++    0, 13, 13, 13, 13, 13,  1,  1,  1,  1, 12, 12,  0, 15, 15, 15,
++   15, 15, 15, 15, 15,  1,  1,  0,  0, 17, 17, 17, 17, 17, 17, 17,
++   17, 17, 17,  0, 26, 26, 26, 26, 26, 12, 12, 12, 12, 12, 12,  0,
++   39, 39, 39, 39, 86, 86, 86, 86, 77, 77, 77, 77, 79, 79, 79, 79,
++   60, 60, 60, 60, 65, 65, 65, 65, 75, 75, 75, 75, 69, 69, 69, 69,
++   69, 69,  0, 69, 74, 74, 74, 74, 84, 84, 84, 84, 84, 84, 84,  0,
++   68, 68, 68, 68, 92, 92, 92, 92, 87, 87, 87, 87, 19,  9, 19, 19,
++   19, 19,  0,  0,  2,  2,  2,  2, 19, 19, 19,  4,  3,  3,  0,  0,
++    1,  1,  6,  6,  0,  0, 17, 17, 17, 17,  0,  0, 49, 49, 49, 49,
++    0,  1,  1,  1, 71, 71, 71, 71, 67, 67, 67, 67, 42, 42, 42, 42,
++   41, 41, 41, 41,118,118,118,118, 53, 53, 53, 53, 59, 59, 59, 59,
++   40, 40, 40, 40, 51, 51, 51, 51, 50, 50, 50, 50,135,135,135,135,
++  106,106,106,106,104,104,104,104,161,161,161,161,170,170,170,170,
+   110,110,110,110, 47, 47, 47, 47, 81, 81, 81, 81,120,120,120,120,
+   116,116,116,116,128,128,128,128, 66, 66, 66, 66, 72, 72, 72, 72,
+    98, 98, 98, 98, 97, 97, 97, 97, 57, 57, 57, 57, 88, 88, 88, 88,
+   117,117,117,117,112,112,112,112, 78, 78, 78, 78, 83, 83, 83, 83,
+    82, 82, 82, 82,122,122,122,122, 89, 89, 89, 89,130,130,130,130,
+-  144,144,144,144,156,156,156,156,156,  3,  3,  3,147,147,147,147,
+-  148,148,148,148,158,158,158,158,153,153,153,153,149,149,149,149,
+-   94, 94, 94, 94, 85, 85, 85, 85,101,101,101,101, 96, 96, 96, 96,
+-  111,111,111,111,100,100,100,100,100, 36, 36, 36,108,108,108,108,
+-  129,129,129,129,109,109,109,109,107,107,107,107,107,107,107,  1,
+-  137,137,137,137,124,124,124,124,123,123,123,123,114,114,114,114,
+-  102,102,102,102,126,126,126,126,142,142,142,142,125,125,125,125,
+-  154,154,154,154,150,150,150,150,141,141,141,141,140,140,140,140,
+-  121,121,121,121,133,133,133,133,134,134,134,134,138,138,138,138,
+-  143,143,143,143,145,145,145,145,163,163,163,163, 63, 63, 63, 63,
+-  157,157,157,157, 80, 80, 80, 80,127,127,127,127,115,115,115,115,
+-  159,159,159,159,103,103,103,103,119,119,119,119,146,146,146,146,
+-   99, 99, 99, 99,136,139, 13, 13,155,155,155,155,136,136,136,136,
+-   17, 15, 15, 15, 17, 17, 15, 15, 15, 17, 17, 17,139,139,139,139,
+-  105,105,105,105,  0,  0,  0,  1,  0,  0,  1,  1,131,131,131,131,
+-  151,151,151,151,160,160,160,160,152,152,152,152,164,164,164,164,
+-  113,113,113,113,132,132,132,132, 15,  0,  0,  0,  0,  1,  2,  3,
+-    4,  5,  6,  7,  8,  9,  9,  9,  9, 10,  9, 11, 12, 13,  9,  9,
+-    9, 14,  9,  9, 15,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
++  144,144,144,144,165,165,165,165,156,156,156,156,156,156,  3,  3,
++  147,147,147,147,148,148,148,148,158,158,158,158,153,153,153,153,
++  149,149,149,149, 94, 94, 94, 94, 85, 85, 85, 85,101,101,101,101,
++   96, 96, 96, 96,111,111,111,111,100,100,100,100,100, 36, 36, 36,
++  108,108,108,108,129,129,129,129,109,109,109,109,107,107,107,107,
++  107,107,107,  1,171,171,171,171,137,137,137,137,124,124,124,124,
++  123,123,123,123,114,114,114,114,102,102,102,102,126,126,126,126,
++  142,142,142,142,125,125,125,125,154,154,154,154,150,150,150,150,
++  141,141,141,141,140,140,140,140,121,121,121,121,169,169,169,169,
++  133,133,133,133,134,134,134,134,138,138,138,138,143,143,143,143,
++  145,145,145,145,163,163,163,163, 63, 63, 63, 63,157,157,157,157,
++   80, 80, 80, 80,127,127,127,127,166,166,166,166,115,115,115,115,
++  159,159,159,159,103,103,103,103,119,119,119,119,167,167,167,167,
++  146,146,146,146, 99, 99, 99, 99,136,139, 13, 13,155,155,155,155,
++  136,136,136,136, 17, 15, 15, 15, 17, 17, 15, 15, 15, 17, 17, 17,
++  139,139,139,139,105,105,105,105,  0,  0,  0,  1,  0,  0,  1,  1,
++  131,131,131,131,151,151,151,151,160,160,160,160,152,152,152,152,
++  164,164,164,164,168,168,168,168,113,113,113,113,132,132,132,132,
++   15,  0,  0,  0,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  9,  9,
++    9, 10,  9, 11, 12, 13,  9,  9,  9, 14,  9,  9, 15,  9,  9,  9,
+     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+-    9,  9,  9,  9,  9,  9,  9,  9, 16, 17,  9,  9,  9,  9,  9,  9,
+-    9,  9,  9,  9, 18, 19, 20,  9, 21,  9,  9,  9,  9,  9,  9,  9,
+     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
++   16, 17,  9,  9,  9,  9, 18,  9,  9,  9,  9,  9, 19, 20, 21,  9,
++   22,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
++    9,  9,  9,  9, 23,  9,  9,  9,  9,  9, 24,  9,  9,  9,  9,  9,
+     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
++    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9, 25,  9,  9,  9,
+     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+-    9,  9,  9,  9, 22,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+@@ -5223,60 +5451,66 @@ _hb_ucd_u8[13386] =
+     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+-    9,  9,  9,  9,  9,  9,  9,  9, 23, 24,  0,  0,  0,  0,  0,  0,
+-    0,  0,  0,  0,  0,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10,
+-   11, 12,  0,  0, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,  0,  0,
+-    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 23,  0,
+-    0, 24, 25, 26, 27, 28, 29, 30,  0,  0, 31, 32,  0, 33,  0, 34,
+-    0, 35,  0,  0,  0,  0, 36, 37, 38, 39,  0,  0,  0,  0,  0,  0,
+-    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 40,  0,  0,  0,
+-    0,  0,  0,  0,  0,  0, 41, 42,  0,  0,  0,  0,  0,  0,  0,  0,
++   26, 27,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  2,
++    3,  4,  5,  6,  7,  8,  9, 10, 11, 12,  0,  0, 13, 14, 15, 16,
++   17, 18, 19, 20, 21, 22,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
++    0,  0,  0,  0,  0,  0, 23,  0,  0, 24, 25, 26, 27, 28, 29, 30,
++    0,  0, 31, 32,  0, 33,  0, 34,  0, 35,  0,  0,  0,  0, 36, 37,
++   38, 39,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
++    0,  0,  0,  0, 40,  0,  0,  0,  0,  0,  0,  0,  0,  0, 41, 42,
+     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, 43, 44,  0, 45,
+-    0,  0,  0,  0,  0,  0, 46, 47,  0,  0,  0,  0,  0, 48,  0, 49,
+-    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 50, 51,
+-    0,  0,  0, 52,  0,  0, 53,  0,  0,  0,  0,  0,  0,  0, 54,  0,
+-    0,  0,  0,  0,  0,  0, 55,  0,  0,  0,  0,  0,  0,  0, 56,  0,
+-    0,  0,  0,  0,  0,  0,  0, 57,  0,  0,  0,  0,  0,  0,  0,  0,
+-    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 58, 59,
+-   60, 61, 62, 63, 64, 65,  0,  0,  0,  0,  0,  0, 66,  0,  0,  0,
+     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
++    0,  0,  0,  0, 43, 44,  0, 45,  0,  0,  0,  0,  0,  0, 46, 47,
++    0,  0,  0,  0,  0, 48,  0, 49,  0,  0,  0,  0,  0,  0,  0,  0,
++    0,  0,  0,  0,  0,  0, 50, 51,  0,  0,  0, 52,  0,  0, 53,  0,
++    0,  0,  0,  0,  0,  0, 54,  0,  0,  0,  0,  0,  0,  0, 55,  0,
++    0,  0,  0,  0,  0,  0, 56,  0,  0,  0,  0,  0,  0,  0,  0, 57,
+     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
++    0,  0,  0,  0,  0,  0, 58, 59, 60, 61, 62, 63, 64, 65,  0,  0,
++    0,  0,  0,  0, 66,  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,  0,  0,  0,
+-    0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 67, 68,  0, 69, 70,  0,
+-    0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 71, 72, 73, 74, 75, 76,
+-   77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92,
+-   93, 94, 95, 96, 97, 98, 99,100,101,102,103,  0,  0,  0,  0,  0,
+-    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,104,  0,  0,  0,
+-    0,  0,  0,105,106,  0,107,  0,  0,  0,108,  0,109,  0,110,  0,
+-  111,112,113,  0,114,  0,  0,  0,115,  0,  0,  0,116,  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,117,  0,  0,  0,  0,  0,  0,  0,  0,
+-    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,118,119,
+-  120,121,  0,122,123,124,125,126,  0,127,  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,128,129,130,131,132,133,
+-  134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,
+-  150,151,152,153,154,155,156,157,  0,  0,  0,158,159,160,161,  0,
++    0,  0, 67, 68,  0, 69, 70,  0,  0,  0,  0,  0,  0,  0,  0,  0,
++    0,  0, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
++   85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,100,
++  101,102,103,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
++    0,  0,  0,  0,104,  0,  0,  0,  0,  0,  0,105,106,  0,107,  0,
++    0,  0,108,  0,109,  0,110,  0,111,112,113,  0,114,  0,  0,  0,
++  115,  0,  0,  0,116,  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,117,
+     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+-    0,  0,  0,162,163,  0,  0,  0,  0,  0,  0,  0,164,  0,  0,  0,
++    0,  0,  0,  0,  0,  0,118,119,120,121,  0,122,123,124,125,126,
++    0,127,  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,  0,  0,  0,  0,165,  0,
++    0,  0,128,129,130,131,132,133,134,135,136,137,138,139,140,141,
++  142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,
++    0,  0,  0,158,159,160,161,  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,166,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+-    0,  0,  0,  0,  0,167,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+-    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,168,  0,  0,
++    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,162,  0,
++  163,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,164,165,  0,  0,  0,
++    0,  0,  0,  0,166,  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,  0,  0,169,
+-  170,  0,  0,  0,  0,171,172,  0,  0,  0,173,174,175,176,177,178,
+-  179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,
+-  195,196,197,198,199,200,201,202,203,204,205,206,  0,  0,  0,  0,
++    0,  0,  0,  0,  0,  0,167,  0,  0,  0,168,169,  0,  0,170,  0,
++    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,171,  0,  0,
++    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,172,  0,  0,
+     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+-    0,  0,  0,  0,  0,  0,  1,  2,  3,  4,
++    0,  0,  0,  0,  0,173,  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,174,  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,175,  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,176,177,  0,  0,  0,  0,178,179,  0,
++    0,  0,180,181,182,183,184,185,186,187,188,189,190,191,192,193,
++  194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,
++  210,211,212,213,  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,  1,  2,
++    3,  4,
+ };
+ static const uint16_t
+-_hb_ucd_u16[4920] =
++_hb_ucd_u16[5080] =
+ {
+      0,   0,   1,   2,   3,   4,   5,   6,   0,   0,   7,   8,   9,  10,  11,  12,
+     13,  13,  13,  14,  15,  13,  13,  16,  17,  18,  19,  20,  21,  22,  13,  23,
+@@ -5303,82 +5537,85 @@ _hb_ucd_u16[4920] =
+     47,  47, 165, 166, 167,  47,  47,  47,  47,  47,  47,  47,  47, 168, 146, 146,
+     47, 169,  47,  47,  47, 170, 171, 172, 160, 160, 173, 174,  32,  32,  32,  32,
+    175,  47,  47, 176, 177, 122, 178, 179, 180,  47, 181,  61,  47,  47, 182, 183,
+-    47,  47, 184, 185, 186,  61,  47, 187,  11,   9,   9,   9,  66, 188, 189, 190,
+-    11,  11, 191,  27,  27,  27, 192, 193,  11, 194,  27,  27,  32,  32,  32,  32,
+-    13,  13,  13,  13,  13,  13,  13,  13,  13, 195,  13,  13,  13,  13,  13,  13,
+-   196, 196, 196, 196, 196, 197, 196,  11, 198, 198, 198, 199, 200, 201, 201, 200,
+-   202, 203, 204, 205, 206, 207, 208, 209, 210,  27, 211, 211, 211, 212, 213,  32,
+-   214, 215, 216, 217, 218, 145, 219, 219, 220, 221, 222, 146, 223, 224, 146, 225,
+-   226, 226, 226, 226, 226, 226, 226, 226, 227, 146, 228, 146, 146, 146, 146, 229,
+-   146, 230, 226, 231, 146, 232, 233, 146, 146, 146, 146, 146, 146, 146, 145, 145,
+-   145, 234, 146, 146, 146, 146, 235, 145, 146, 146, 146, 146, 146, 146, 146, 146,
+-   146, 146, 146, 236, 237, 146, 146, 238, 146, 146, 146, 146, 146, 146, 239, 146,
+-   146, 146, 146, 146, 146, 146, 240, 241, 145, 242, 146, 146, 243, 226, 244, 226,
+-   245, 246, 226, 226, 226, 247, 226, 248, 146, 146, 146, 226, 249, 146, 146, 146,
+-     9,   9,   9,  11,  11,  11, 250, 251,  13,  13,  13,  13,  13,  13, 252, 253,
+-    11,  11,  11,  47,  47,  47, 254, 255,  47,  47,  47,  47,  47,  47,  32,  32,
+-   256, 257, 258, 259, 260, 261, 262, 262, 263, 264, 265, 266, 267,  47,  47,  47,
+-    47, 268, 148,  47,  47,  47,  47, 269,  47, 270,  47,  47, 146, 146, 146,  47,
+-   146, 146, 271, 146, 272, 273, 146, 146, 271, 146, 146, 273, 146, 146, 146, 146,
+-    47,  47,  47,  47, 146, 146, 146, 146,  47, 274,  47,  47,  47,  47,  47,  47,
+-    47, 146, 146, 146, 146,  47,  47, 187, 275,  47,  61,  47,  13,  13, 276, 277,
+-    13, 278,  47,  47,  47,  47, 279, 280,  31, 281, 282, 283,  13,  13,  13, 284,
+-   285, 286, 287, 288, 289, 290,  11, 291, 292,  47, 293, 294,  47,  47,  47, 295,
+-   296,  47,  47, 297, 298, 160,  32, 299,  61,  47, 300,  47, 301, 302,  47,  47,
+-    72,  47,  47, 303, 304, 305, 306,  61,  47,  47, 307, 308, 309, 310,  47, 311,
+-    47,  47,  47, 312,  58, 313, 314, 315,  47,  47,  47,  11,  11, 316, 317,  11,
+-    11,  11,  11,  11,  47,  47, 318, 160, 319, 319, 319, 319, 319, 319, 319, 319,
+-   320, 320, 320, 320, 320, 320, 320, 320,  11, 321, 322,  47,  47,  47,  47,  47,
+-    47,  47,  47, 323,  31, 324,  47,  47,  47,  47,  47, 325, 146,  47,  47,  47,
+-    47,  47,  47,  47, 326, 146, 146, 327,  32, 328,  32, 329, 330, 331, 332,  47,
+-    47,  47,  47,  47,  47,  47,  47, 333, 334,   2,   3,   4,   5, 335, 336, 337,
+-    47, 338,  47,  47,  47,  47, 339, 340, 341, 145, 145, 342, 219, 219, 219, 343,
+-   344, 146, 146, 146, 146, 146, 146, 345, 346, 346, 346, 346, 346, 346, 346, 346,
+-    47,  47,  47,  47,  47,  47, 347, 145,  47,  47, 348,  47, 349,  47,  47,  60,
+-    47, 350,  47,  47,  47, 351, 219, 219,   9,   9, 147,  11,  11,  47,  47,  47,
+-    47,  47, 160,   9,   9, 147,  11,  11,  47,  47,  47,  47,  47,  47, 350,   9,
+-     9, 352,  11,  11,  11,  11,  11,  11,  27,  27,  27,  27,  27,  27,  27,  27,
+-    47,  47,  47,  47,  47, 353,  47, 354,  47,  47, 355, 145, 145, 145,  47, 356,
+-    47, 357,  47, 350,  66,  66,  66,  66,  47,  47,  47, 358, 145, 145, 145, 145,
+-   359,  47,  47, 360, 145,  66,  47, 361,  47, 362, 145, 145, 363,  47, 364,  66,
+-    47,  47,  47, 365,  47, 366,  47, 366,  47, 365, 144, 145, 145, 145, 145, 145,
+-     9,   9,   9,   9,  11,  11,  11, 367,  47,  47, 368, 160, 160, 160, 160, 160,
+-   145, 145, 145, 145, 145, 145, 145, 145,  47,  47, 369,  47,  47,  47,  47, 143,
+-    47, 362, 370,  47,  60, 371,  66,  47, 372,  66,  66,  47, 373, 145,  47,  47,
+-   374,  47,  47, 360, 375, 376, 377, 378, 180,  47,  47, 379, 380,  47,  47, 160,
+-    97,  47, 381, 382, 383,  47,  47, 384, 180,  47,  47, 385, 386, 387, 388, 145,
+-    47,  47, 389, 390, 359,  32,  32,  32,  47,  47, 365,  47,  47, 391, 172, 160,
+-    92,  47,  47, 113, 392, 393, 394,  32,  47,  47,  47, 395, 396, 397,  47,  47,
+-    47,  47,  47, 398, 399, 160, 160, 160,  47,  47, 400, 401, 402, 403,  32,  32,
+-    47,  47,  47, 404, 405, 160,  66,  66,  47,  47, 406, 407, 160, 160, 160, 160,
+-    47, 143, 408, 409,  47,  47,  47,  47,  47,  47, 389, 410,  66,  66,  66,  66,
+-     9,   9,   9,   9,  11,  11, 128, 411,  47,  47,  47, 412, 413, 160, 160, 160,
+-    47,  47,  47,  47,  47, 414, 415, 416, 417,  47,  47, 418, 419, 420,  47,  47,
+-   421, 422,  66,  47,  47,  47,  47,  47,  66,  66,  66,  66,  66,  66,  66,  66,
+-    47,  47, 400, 423, 424, 128, 145, 425,  47, 156, 426, 427,  32,  32,  32,  32,
+-    47,  47,  47, 359, 428, 160,  47,  47, 429, 430, 160, 160, 160, 160, 160, 160,
+-    47,  47,  47,  47,  47,  47,  47, 431, 432,  47,  47, 433, 434, 160, 160, 160,
+-    47,  47,  47,  47, 145, 435, 436, 437, 219, 219, 219, 219, 219, 219, 219,  66,
+-    47,  47,  47,  47,  47,  47,  47, 424,  47,  47,  47, 208, 438,  32,  32,  32,
+-    47,  47,  47,  47,  47,  47, 305,  47,  47,  47,  47,  47, 160,  47,  47, 439,
+-    47,  47,  47, 440, 441, 442, 443,  47,   9,   9,   9,   9,   9,   9,  11,  11,
+-   145, 444,  66,  66,  66,  66,  66,  66,  47,  47,  47,  47, 391, 445, 416, 416,
+-   446, 447,  27,  27,  27,  27, 448, 416,  47, 449, 208, 208, 208, 208, 208, 208,
+-    32,  32,  32,  32,  32, 146, 146, 146, 146, 146, 146, 146, 146, 146, 450, 451,
+-   452, 146, 453, 146, 146, 146, 146, 146, 146, 146, 146, 146, 454, 146, 146, 146,
+-     9, 455,  11, 456, 457,  11, 196,   9, 458, 459,   9, 460,  11,   9, 455,  11,
+-   456, 457,  11, 196,   9, 458, 459,   9, 460,  11,   9, 455,  11, 456, 457,  11,
+-   196,   9, 458, 459,   9, 460,  11,   9, 455,  11, 196,   9, 461, 462, 463, 464,
+-    11, 465,   9, 466, 467, 468, 469,  11, 470,   9, 471,  11, 472, 160, 160, 160,
+-    32,  32,  32, 473,  32,  32, 474, 475, 476, 477,  32,  32,  32,  32,  32,  32,
+-   478,  11,  11,  11,  11,  11,  11,  11,  32,  32,  32,  27,  27,  27,  27,  27,
+-    32,  32,  32,  32,  32,  32,  32,  32,  47,  47,  47, 479, 480, 146, 146, 146,
+-    47,  47, 481,  32,  47,  47, 482, 483,  47,  47,  47,  47,  47,  47, 484, 160,
+-    47,  47,  47,  47, 355,  32,  32,  32,   9,   9, 458,  11, 485, 305,  66,  66,
+-   145, 145, 486, 487, 145, 145, 145, 145, 145, 145, 488, 145, 145, 145, 145, 145,
+-    47,  47,  47,  47,  47,  47,  47, 226, 489, 146, 146, 146, 146, 146, 146, 146,
+-   146, 146, 146, 146, 146, 146, 146, 490, 146, 146, 146, 146, 146, 146, 146, 160,
+-   208, 208, 208, 208, 208, 208, 208, 208,   0,   0,   0,   0,   0,   0,   0,   0,
++    47,  47, 184, 185, 186,  61,  47, 187, 188,   9,   9,   9,  66, 189, 190, 191,
++    11,  11, 192,  27,  27,  27, 193, 194,  11, 195,  27,  27,  32,  32,  32,  32,
++    13,  13,  13,  13,  13,  13,  13,  13,  13, 196,  13,  13,  13,  13,  13,  13,
++   197, 197, 197, 197, 197, 198, 197,  11, 199, 199, 199, 200, 201, 202, 202, 201,
++   203, 204, 205, 206, 207, 208, 209, 210, 211,  27, 212, 212, 212, 213, 214,  32,
++   215, 216, 217, 218, 219, 145, 220, 220, 221, 222, 223, 146, 224, 225, 146, 226,
++   227, 227, 227, 227, 227, 227, 227, 227, 228, 146, 229, 146, 146, 146, 146, 230,
++   146, 231, 227, 232, 146, 233, 234, 146, 146, 146, 146, 146, 146, 146, 145, 145,
++   145, 235, 146, 146, 146, 146, 236, 145, 146, 146, 146, 146, 146, 146, 146, 146,
++   146, 146, 146, 237, 238, 146, 146, 239, 146, 146, 146, 146, 146, 146, 240, 146,
++   146, 146, 146, 146, 146, 146, 241, 242, 145, 243, 146, 146, 244, 227, 245, 227,
++   246, 247, 227, 227, 227, 248, 227, 249, 146, 146, 146, 227, 250, 146, 146, 146,
++     9,   9,   9,  11,  11,  11, 251, 252,  13,  13,  13,  13,  13,  13, 253, 254,
++    11,  11,  11,  47,  47,  47, 255, 256,  47,  47,  47,  47,  47,  47,  32,  32,
++   257, 258, 259, 260, 261, 262, 263, 263, 264, 265, 266, 267, 268,  47,  47,  47,
++    47, 269, 148,  47,  47,  47,  47, 270,  47, 271,  47,  47, 146, 146, 146,  47,
++   146, 146, 272, 146, 273, 274, 146, 146, 272, 146, 146, 274, 146, 146, 146, 146,
++    47,  47,  47,  47, 146, 146, 146, 146,  47, 275,  47,  47,  47,  47,  47,  47,
++    47, 146, 146, 146, 146,  47,  47, 187, 276,  47,  61,  47,  13,  13, 277, 278,
++    13, 279,  47,  47,  47,  47, 280, 281,  31, 282, 283, 284,  13,  13,  13, 285,
++   286, 287, 288, 289, 290, 291,   9, 292, 293,  47, 294, 295,  47,  47,  47, 296,
++   297,  47,  47, 298, 299, 160,  32, 300,  61,  47, 301,  47, 302, 303,  47,  47,
++    72,  47,  47, 304, 305, 306, 307,  61,  47,  47, 308, 309, 310, 311,  47, 312,
++    47,  47,  47, 313,  58, 314, 315, 316,  47,  47,  47,  11,  11, 317, 318,  11,
++    11,  11,  11,  11,  47,  47, 319, 160, 320, 320, 320, 320, 320, 320, 320, 320,
++   321, 321, 321, 321, 321, 321, 321, 321,  11, 322, 323,  47,  47,  47,  47,  47,
++    47,  47,  47, 324,  31, 325,  47,  47,  47,  47,  47, 326, 146,  47,  47,  47,
++    47,  47,  47,  47, 327, 146, 146, 328,  32, 329,  32, 330, 331, 332, 333,  47,
++    47,  47,  47,  47,  47,  47,  47, 334, 335,   2,   3,   4,   5, 336, 337, 338,
++    47, 339,  47,  47,  47,  47, 340, 341, 342, 145, 145, 343, 220, 220, 220, 344,
++   345, 146, 146, 146, 146, 146, 146, 346, 347, 347, 347, 347, 347, 347, 347, 347,
++    47,  47,  47,  47,  47,  47, 348, 145,  47,  47, 349,  47, 350,  47,  47,  60,
++    47, 351,  47,  47,  47, 352, 220, 220,   9,   9, 147,  11,  11,  47,  47,  47,
++    47,  47, 160,   9,   9, 147,  11,  11,  47,  47,  47,  47,  47,  47, 351,   9,
++     9, 353,  11,  11,  47,  47,  47,  47,  27,  27,  27,  27,  27,  27,  27,  27,
++    47,  47,  47,  47,  47, 354,  47, 355,  47,  47, 356, 145, 145, 145,  47, 357,
++    47, 358,  47, 351,  66,  66,  66,  66,  47,  47,  47, 359, 145, 145, 145, 145,
++   360,  47,  47, 361, 145,  66,  47, 362,  47, 363, 145, 145, 364,  47, 365,  66,
++    47,  47,  47, 366,  47, 367,  47, 367,  47, 366, 144, 145, 145, 145, 145, 145,
++     9,   9,   9,   9,  11,  11,  11, 368,  47,  47, 369, 160, 370,   9, 371,  11,
++   372, 227, 227, 227, 227, 227, 227, 227, 145, 145, 145, 145, 145, 145, 145, 145,
++    47,  47, 373,  47,  47,  47,  47, 374,  47, 363, 375,  47,  60, 376,  66,  47,
++   377,  66,  66,  47, 378, 145,  47,  47, 379,  47,  47, 361, 380, 381, 382, 383,
++   180,  47,  47, 384, 385,  47,  47, 160,  97,  47, 386, 387, 388,  47,  47, 389,
++   180,  47,  47, 390, 391, 392, 393, 145,  47,  47, 394, 395, 360,  32,  32,  32,
++    47,  47, 366,  47,  47, 396, 172, 160,  92,  47,  47, 113, 397, 398, 399,  32,
++    47,  47,  47, 400, 401, 402, 403,  32,  47,  47,  47, 404, 405, 406,  47,  47,
++    47,  47,  47, 407, 408, 160, 160, 160,  47,  47, 409, 410, 411, 412,  32,  32,
++    47,  47,  47, 413, 414, 160,  66,  66,  47,  47, 415, 416, 160, 160, 160, 160,
++    47, 417, 418, 419,  47,  47,  47,  47,  47,  47, 394, 420,  66,  66,  66,  66,
++     9,   9,   9,   9,  11,  11, 128, 421,  47,  47,  47, 422, 423, 160, 160, 160,
++    47,  47,  47,  47,  47, 424, 425, 426, 427,  47,  47, 428, 429, 430,  47,  47,
++   431, 432,  66,  47,  47,  47,  47,  47,  66,  66,  66,  66,  66,  66,  66,  66,
++    47,  47,  47,  47,  47,  47, 433, 160,  47,  47, 409, 434, 433, 128, 145, 435,
++    47, 156, 436, 437,  32,  32,  32,  32,  47,  47,  47, 360, 438, 160,  47,  47,
++   439, 440, 160, 160, 160, 160, 160, 160,  47,  47,  47,  47,  47,  47,  47, 441,
++   442,  47,  47, 443, 444, 445,  32,  32,  47,  47,  47,  47, 145, 446, 447, 448,
++   220, 220, 220, 220, 220, 220, 220,  66,  47,  47,  47,  47,  47,  47,  47, 433,
++    47,  47,  47, 209, 449,  32,  47,  47,  47, 450, 451, 160, 160, 160, 160, 160,
++    47,  47,  47,  47,  47,  47, 306,  47,  47,  47,  47,  47, 160,  47,  47, 452,
++    47,  47,  47, 453, 454, 455, 456,  47,  27,  27,  27,  27, 457,  47, 458, 160,
++     9,   9,   9,   9,   9,   9,  11,  11, 145, 459,  66,  66,  66,  66,  66,  66,
++    47,  47,  47,  47, 396, 460, 426, 426, 461, 462,  27,  27,  27,  27, 463, 426,
++    47, 464, 209, 209, 209, 209, 209, 209, 146, 146, 146, 146, 146, 146, 146, 160,
++    32,  32,  32,  32,  32, 146, 146, 146, 146, 146, 146, 146, 146, 146, 465, 466,
++   467, 146, 468, 146, 146, 146, 146, 146, 146, 146, 146, 146, 469, 146, 146, 146,
++     9, 470,  11, 471, 472,  11, 197,   9, 473, 474,   9, 475,  11,   9, 470,  11,
++   471, 472,  11, 197,   9, 473, 474,   9, 475,  11,   9, 470,  11, 471, 472,  11,
++   197,   9, 473, 474,   9, 475,  11,   9, 470,  11, 197,   9, 476, 477, 478, 479,
++    11, 480,   9, 481, 482, 483, 484,  11, 485,   9, 486,  11, 487, 160, 160, 160,
++    32,  32,  32, 488,  32,  32, 489, 490, 491, 492,  32,  32,  32,  32,  32,  32,
++   493,  11,  11,  11,  11,  11,  11,  11,  32,  32,  32,  27,  27,  27,  27,  27,
++    32,  32,  32,  32,  32,  32,  32,  32,  47,  47,  47, 494, 495, 146, 146, 146,
++    47,  47, 450,  32,  47,  47, 374, 496,  47,  47,  47,  47,  47,  47, 497, 160,
++    47,  47,  47,  47,  47,  47, 450, 498,  47,  47,  47,  47, 356,  32,  32,  32,
++     9,   9, 473,  11, 499, 306,  66,  66, 145, 145, 500, 501, 145, 145, 145, 145,
++   145, 145, 502, 145, 145, 145, 145, 145,  47,  47,  47,  47,  47,  47,  47, 227,
++   503, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 504,
++   209, 209, 209, 209, 209, 209, 209, 209,   0,   0,   0,   0,   0,   0,   0,   0,
+      0,   0,   0,   0,   0,   0,   0,   0, 939, 940, 941, 942, 946, 948,   0, 962,
+    969, 970, 971, 976,1001,1002,1003,1008,   0,1033,1040,1041,1042,1043,1047,   0,
+      0,1080,1081,1082,1086,1110,   0,   0,1124,1125,1126,1127,1131,1133,   0,1147,
+@@ -5541,16 +5778,23 @@ _hb_ucd_u16[4920] =
+      0,   0,1602,1603,1934,1935,1574,1575,1576,1577,1579,1580,1581,1583,1584,   0,
+   1585,1587,1588,1589,1591,   0,1592,   0,1593,1594,   0,1595,1596,   0,1598,1599,
+   1600,1601,1604,1582,1578,1590,1597,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+-     0,   0,1936,   0,1937,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+-     0,   0,   0,1938,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+-     0,   0,   0,   0,   0,   0,1939,1940,   0,   0,   0,   0,   0,   0,   0,   0,
+-     0,   0,   0,1941,1942,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+-     0,   0,   0,1944,1943,   0,1945,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+-     0,   0,1946,1947,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+-  1948,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+-     0,   0,   0,   0,   0,   0,1949,1950,1951,1952,1953,1954,1955,   0,   0,   0,
++     0,1936,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1937,   0,   0,   0,
++     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
++     0,   0,1938,   0,1939,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
++     0,   0,   0,1940,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
++     0,   0,   0,   0,   0,   0,1941,1942,   0,   0,   0,   0,   0,   0,   0,   0,
++     0,   0,   0,1943,1944,   0,   0,   0,   0,   0,   0,1945,   0,1946,   0,   0,
++     0,   0,   0,   0,   0,   0,1947,   0,   0,1948,   0,   0,   0,   0,   0,   0,
++     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1950,   0,1949,
++  1951,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
++     0,   0,   0,1953,1952,   0,1954,   0,   0,   0,   0,   0,   0,   0,   0,   0,
++     0,   0,1955,1956,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
++  1957,   0,   0,   0,   0,   0,   0,   0,   0,1958,1961,1959,1965,1960,1962,1964,
++  1963,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
++  1967,1966,1968,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
++     0,   0,   0,   0,   0,   0,1969,1970,1971,1972,1973,1974,1975,   0,   0,   0,
+      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+-     0,   0,   0,1956,1957,1958,1960,1959,1961,   0,   0,   0,   0,   0,   0,   0,
++     0,   0,   0,1976,1977,1978,1980,1979,1981,   0,   0,   0,   0,   0,   0,   0,
+      0,   0,   0,   0,   0,   0,   0,   0, 106, 104, 107, 826, 114, 118, 119, 121,
+    123, 124, 127, 125,  34, 830, 130, 131, 132, 137, 827,  35, 133, 139, 829, 142,
+    143, 112, 144, 145, 924, 151, 152,  37, 157, 158, 159, 160,  38, 165, 166, 169,
+@@ -5601,12 +5845,12 @@ _hb_ucd_i16[92] =
+ static inline uint_fast8_t
+ _hb_ucd_gc (unsigned u)
+ {
+-  return u<1114112u?_hb_ucd_u8[5096+(((_hb_ucd_u8[1168+(((_hb_ucd_u16[((_hb_ucd_u8[544+(((_hb_ucd_u8[u>>1>>3>>3>>4])<<4)+((u>>1>>3>>3)&15u))])<<3)+((u>>1>>3)&7u)])<<3)+((u>>1)&7u))])<<1)+((u)&1u))]:2;
++  return u<1114112u?_hb_ucd_u8[5208+(((_hb_ucd_u8[1168+(((_hb_ucd_u16[((_hb_ucd_u8[544+(((_hb_ucd_u8[u>>1>>3>>3>>4])<<4)+((u>>1>>3>>3)&15u))])<<3)+((u>>1>>3)&7u)])<<3)+((u>>1)&7u))])<<1)+((u)&1u))]:2;
+ }
+ static inline uint_fast8_t
+ _hb_ucd_ccc (unsigned u)
+ {
+-  return u<125259u?_hb_ucd_u8[7054+(((_hb_ucd_u8[6498+(((_hb_ucd_u8[6038+(((_hb_ucd_u8[5686+(((_hb_ucd_u8[5440+(u>>2>>2>>2>>3)])<<3)+((u>>2>>2>>2)&7u))])<<2)+((u>>2>>2)&3u))])<<2)+((u>>2)&3u))])<<2)+((u)&3u))]:0;
++  return u<125259u?_hb_ucd_u8[7206+(((_hb_ucd_u8[6638+(((_hb_ucd_u8[6162+(((_hb_ucd_u8[5802+(((_hb_ucd_u8[5556+(u>>2>>2>>2>>3)])<<3)+((u>>2>>2>>2)&7u))])<<2)+((u>>2>>2)&3u))])<<2)+((u>>2)&3u))])<<2)+((u)&3u))]:0;
+ }
+ static inline unsigned
+ _hb_ucd_b4 (const uint8_t* a, unsigned i)
+@@ -5616,17 +5860,17 @@ _hb_ucd_b4 (const uint8_t* a, unsigned i)
+ static inline int_fast16_t
+ _hb_ucd_bmg (unsigned u)
+ {
+-  return u<65380u?_hb_ucd_i16[((_hb_ucd_u8[7946+(((_hb_ucd_u8[7714+(((_hb_ucd_u8[7618+(((_hb_ucd_b4(7554+_hb_ucd_u8,u>>1>>2>>3>>3))<<3)+((u>>1>>2>>3)&7u))])<<3)+((u>>1>>2)&7u))])<<2)+((u>>1)&3u))])<<1)+((u)&1u)]:0;
++  return u<65380u?_hb_ucd_i16[((_hb_ucd_u8[8098+(((_hb_ucd_u8[7866+(((_hb_ucd_u8[7770+(((_hb_ucd_b4(7706+_hb_ucd_u8,u>>1>>2>>3>>3))<<3)+((u>>1>>2>>3)&7u))])<<3)+((u>>1>>2)&7u))])<<2)+((u>>1)&3u))])<<1)+((u)&1u)]:0;
+ }
+ static inline uint_fast8_t
+ _hb_ucd_sc (unsigned u)
+ {
+-  return u<918016u?_hb_ucd_u8[11244+(((_hb_ucd_u8[10280+(((_hb_ucd_u8[9292+(((_hb_ucd_u8[8612+(((_hb_ucd_u8[8308+(((_hb_ucd_u8[8194+(u>>2>>2>>2>>3>>4)])<<4)+((u>>2>>2>>2>>3)&15u))])<<3)+((u>>2>>2>>2)&7u))])<<2)+((u>>2>>2)&3u))])<<2)+((u>>2)&3u))])<<2)+((u)&3u))]:2;
++  return u<918016u?_hb_ucd_u8[11464+(((_hb_ucd_u8[10472+(((_hb_ucd_u8[9452+(((_hb_ucd_u8[8764+(((_hb_ucd_u8[8460+(((_hb_ucd_u8[8346+(u>>2>>2>>2>>3>>4)])<<4)+((u>>2>>2>>2>>3)&15u))])<<3)+((u>>2>>2>>2)&7u))])<<2)+((u>>2>>2)&3u))])<<2)+((u>>2)&3u))])<<2)+((u)&3u))]:2;
+ }
+ static inline uint_fast16_t
+ _hb_ucd_dm (unsigned u)
+ {
+-  return u<195102u?_hb_ucd_u16[1608+(((_hb_ucd_u8[12586+(((_hb_ucd_u8[12204+(u>>4>>5)])<<5)+((u>>4)&31u))])<<4)+((u)&15u))]:0;
++  return u<195102u?_hb_ucd_u16[1656+(((_hb_ucd_u8[12834+(((_hb_ucd_u8[12452+(u>>4>>5)])<<5)+((u>>4)&31u))])<<4)+((u)&15u))]:0;
+ }
+ 
+ #endif
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-unicode-emoji-table.hh b/src/java.desktop/share/native/libharfbuzz/hb-unicode-emoji-table.hh
+index e607e8ca8..4bc8d64c2 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-unicode-emoji-table.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-unicode-emoji-table.hh
+@@ -7,13 +7,13 @@
+  * on file with this header:
+  *
+  * # emoji-data.txt
+- * # Date: 2023-02-01, 02:22:54 GMT
+- * # © 2023 Unicode®, Inc.
++ * # Date: 2024-05-01, 21:25:24 GMT
++ * # © 2024 Unicode®, Inc.
+  * # Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries.
+- * # For terms of use, see https://www.unicode.org/terms_of_use.html
++ * # For terms of use and license, see https://www.unicode.org/terms_of_use.html
+  * #
+  * # Emoji Data for UTS #51
+- * # Used with Emoji Version 15.1 and subsequent minor revisions (if any)
++ * # Used with Emoji Version 16.0 and subsequent minor revisions (if any)
+  * #
+  * # For documentation and usage, see https://www.unicode.org/reports/tr51
+  */
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-utf.hh b/src/java.desktop/share/native/libharfbuzz/hb-utf.hh
+index 9175df265..7fd3bf882 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-utf.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-utf.hh
+@@ -458,19 +458,21 @@ struct hb_ascii_t
+ template 
+ static inline const typename utf_t::codepoint_t *
+ hb_utf_offset_to_pointer (const typename utf_t::codepoint_t *start,
++                          const typename utf_t::codepoint_t *text,
++                          unsigned text_len,
+                           signed offset)
+ {
+   hb_codepoint_t unicode;
+ 
+   while (offset-- > 0)
+     start = utf_t::next (start,
+-                         start + utf_t::max_len,
++                         text + text_len,
+                          &unicode,
+                          HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT);
+ 
+   while (offset++ < 0)
+     start = utf_t::prev (start,
+-                         start - utf_t::max_len,
++                         text,
+                          &unicode,
+                          HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT);
+ 
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-vector.hh b/src/java.desktop/share/native/libharfbuzz/hb-vector.hh
+index 001789a30..7e755818d 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-vector.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb-vector.hh
+@@ -37,6 +37,8 @@ template 
+ struct hb_vector_t
+ {
++  static constexpr bool realloc_move = true;
++
+   typedef Type item_t;
+   static constexpr unsigned item_size = hb_static_size (Type);
+   using array_t = typename std::conditional, hb_array_t>::type;
+@@ -51,32 +53,29 @@ struct hb_vector_t
+   }
+   template 
+-  hb_vector_t (const Iterable &o) : hb_vector_t ()
++  explicit hb_vector_t (const Iterable &o) : hb_vector_t ()
+   {
+-    auto iter = hb_iter (o);
+-    if (iter.is_random_access_iterator || iter.has_fast_len)
+-      alloc (hb_len (iter), true);
+-    hb_copy (iter, *this);
++    extend (o);
+   }
+   hb_vector_t (const hb_vector_t &o) : hb_vector_t ()
+   {
+-    alloc (o.length, true);
++    alloc_exact (o.length);
+     if (unlikely (in_error ())) return;
+     copy_array (o.as_array ());
+   }
+   hb_vector_t (array_t o) : hb_vector_t ()
+   {
+-    alloc (o.length, true);
++    alloc_exact (o.length);
+     if (unlikely (in_error ())) return;
+     copy_array (o);
+   }
+   hb_vector_t (c_array_t o) : hb_vector_t ()
+   {
+-    alloc (o.length, true);
++    alloc_exact (o.length);
+     if (unlikely (in_error ())) return;
+     copy_array (o);
+   }
+-  hb_vector_t (hb_vector_t &&o)
++  hb_vector_t (hb_vector_t &&o) noexcept
+   {
+     allocated = o.allocated;
+     length = o.length;
+@@ -85,6 +84,35 @@ struct hb_vector_t
+   }
+   ~hb_vector_t () { fini (); }
+ 
++  template 
++  void extend (const Iterable &o)
++  {
++    auto iter = hb_iter (o);
++    if (iter.is_random_access_iterator || iter.has_fast_len)
++      alloc (hb_len (iter), true);
++    while (iter)
++    {
++      if (unlikely (!alloc (length + 1)))
++        return;
++      unsigned room = allocated - length;
++      for (unsigned i = 0; i < room && iter; i++)
++        push_has_room (*iter++);
++    }
++  }
++  void extend (array_t o)
++  {
++    alloc (length + o.length);
++    if (unlikely (in_error ())) return;
++    copy_array (o);
++  }
++  void extend (c_array_t o)
++  {
++    alloc (length + o.length);
++    if (unlikely (in_error ())) return;
++    copy_array (o);
++  }
++
+   public:
+   int allocated = 0; /* < 0 means allocation failed. */
+   unsigned int length = 0;
+@@ -120,7 +148,7 @@ struct hb_vector_t
+     resize (0);
+   }
+ 
+-  friend void swap (hb_vector_t& a, hb_vector_t& b)
++  friend void swap (hb_vector_t& a, hb_vector_t& b) noexcept
+   {
+     hb_swap (a.allocated, b.allocated);
+     hb_swap (a.length, b.length);
+@@ -130,14 +158,15 @@ struct hb_vector_t
+   hb_vector_t& operator = (const hb_vector_t &o)
+   {
+     reset ();
+-    alloc (o.length, true);
++    alloc_exact (o.length);
+     if (unlikely (in_error ())) return *this;
+ 
++    length = 0;
+     copy_array (o.as_array ());
+ 
+     return *this;
+   }
+-  hb_vector_t& operator = (hb_vector_t &&o)
++  hb_vector_t& operator = (hb_vector_t &&o) noexcept
+   {
+     hb_swap (*this, o);
+     return *this;
+@@ -216,6 +245,10 @@ struct hb_vector_t
+       // reference to it.
+       return std::addressof (Crap (Type));
+ 
++    return push_has_room (std::forward (args)...);
++  }
++  template  Type *push_has_room (Args&&... args)
++  {
+     /* Emplace. */
+     Type *p = std::addressof (arrayZ[length++]);
+     return new (p) Type (std::forward (args)...);
+@@ -268,10 +301,9 @@ struct hb_vector_t
+     }
+     return new_array;
+   }
+-  /* Specialization for hb_vector_t> to speed up. */
++  /* Specialization for types that can be moved using realloc(). */
+   template ) ||
+-                          hb_is_same (T, hb_array_t ))>
++            hb_enable_if (T::realloc_move)>
+   Type *
+   realloc_vector (unsigned new_allocated, hb_priority<1>)
+   {
+@@ -310,18 +342,23 @@ struct hb_vector_t
+     length = size;
+   }
+ 
++  template 
++  void
++  copy_array (hb_array_t other)
++  {
++    assert ((int) (length + other.length) <= allocated);
++    hb_memcpy ((void *) (arrayZ + length), (const void *) other.arrayZ, other.length * item_size);
++    length += other.length;
++  }
+   template 
+   void
+   copy_array (hb_array_t other)
+   {
+-    length = other.length;
+-    if (!HB_OPTIMIZE_SIZE_VAL && sizeof (T) >= sizeof (long long))
+-      /* This runs faster because of alignment. */
+-      for (unsigned i = 0; i < length; i++)
+-        arrayZ[i] = other.arrayZ[i];
+-    else
+-       hb_memcpy ((void *) arrayZ, (const void *) other.arrayZ, length * item_size);
++    assert ((int) (length + other.length) <= allocated);
++    hb_memcpy ((void *) (arrayZ + length), (const void *) other.arrayZ, other.length * item_size);
++    length += other.length;
+   }
+   template  other)
+   {
+-    length = 0;
+-    while (length < other.length)
+-    {
+-      length++;
+-      new (std::addressof (arrayZ[length - 1])) Type (other.arrayZ[length - 1]);
+-    }
++    assert ((int) (length + other.length) <= allocated);
++    for (unsigned i = 0; i < other.length; i++)
++      new (std::addressof (arrayZ[length + i])) Type (other.arrayZ[i]);
++    length += other.length;
+   }
+   template  other)
+   {
+-    length = 0;
+-    while (length < other.length)
++    assert ((int) (length + other.length) <= allocated);
++    for (unsigned i = 0; i < other.length; i++)
+     {
+-      length++;
+-      new (std::addressof (arrayZ[length - 1])) Type ();
+-      arrayZ[length - 1] = other.arrayZ[length - 1];
++      new (std::addressof (arrayZ[length + i])) Type ();
++      arrayZ[length + i] = other.arrayZ[i];
+     }
++    length += other.length;
+   }
+ 
+   void
+@@ -431,6 +466,15 @@ struct hb_vector_t
+ 
+     return true;
+   }
++  bool alloc_exact (unsigned int size)
++  {
++    return alloc (size, true);
++  }
++
++  void clear ()
++  {
++    resize (0);
++  }
+ 
+   bool resize (int size_, bool initialize = true, bool exact = false)
+   {
+@@ -496,7 +540,7 @@ struct hb_vector_t
+     shrink_vector (size);
+ 
+     if (shrink_memory)
+-      alloc (size, true); /* To force shrinking memory if needed. */
++      alloc_exact (size); /* To force shrinking memory if needed. */
+   }
+ 
+ 
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb-version.h b/src/java.desktop/share/native/libharfbuzz/hb-version.h
+index 3627da3bf..01edf1743 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb-version.h
++++ b/src/java.desktop/share/native/libharfbuzz/hb-version.h
+@@ -41,26 +41,26 @@ HB_BEGIN_DECLS
+  *
+  * The major component of the library version available at compile-time.
+  */
+-#define HB_VERSION_MAJOR 8
++#define HB_VERSION_MAJOR 10
+ /**
+  * HB_VERSION_MINOR:
+  *
+  * The minor component of the library version available at compile-time.
+  */
+-#define HB_VERSION_MINOR 2
++#define HB_VERSION_MINOR 4
+ /**
+  * HB_VERSION_MICRO:
+  *
+  * The micro component of the library version available at compile-time.
+  */
+-#define HB_VERSION_MICRO 2
++#define HB_VERSION_MICRO 0
+ 
+ /**
+  * HB_VERSION_STRING:
+  *
+  * A string literal containing the library version available at compile-time.
+  */
+-#define HB_VERSION_STRING "8.2.2"
++#define HB_VERSION_STRING "10.4.0"
+ 
+ /**
+  * HB_VERSION_ATLEAST:
+diff --git a/src/java.desktop/share/native/libharfbuzz/hb.hh b/src/java.desktop/share/native/libharfbuzz/hb.hh
+index 65d2dd58a..fee1c9cd6 100644
+--- a/src/java.desktop/share/native/libharfbuzz/hb.hh
++++ b/src/java.desktop/share/native/libharfbuzz/hb.hh
+@@ -64,6 +64,7 @@
+ #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   "-Wcast-function-type-strict"
+ #pragma GCC diagnostic error   "-Wconstant-conversion"
+ #pragma GCC diagnostic error   "-Wcomma"
+ #pragma GCC diagnostic error   "-Wdelete-non-virtual-dtor"
+@@ -83,6 +84,7 @@
+ #pragma GCC diagnostic error   "-Wredundant-decls"
+ #pragma GCC diagnostic error   "-Wreorder"
+ #pragma GCC diagnostic error   "-Wsign-compare"
++#pragma GCC diagnostic error   "-Wstrict-flex-arrays"
+ #pragma GCC diagnostic error   "-Wstrict-prototypes"
+ #pragma GCC diagnostic error   "-Wstring-conversion"
+ #pragma GCC diagnostic error   "-Wswitch-enum"
+@@ -129,6 +131,7 @@
+ #pragma GCC diagnostic ignored "-Wclass-memaccess"
+ #pragma GCC diagnostic ignored "-Wcast-function-type-strict" // https://github.com/harfbuzz/harfbuzz/pull/3859#issuecomment-1295409126
+ #pragma GCC diagnostic ignored "-Wdangling-reference" // https://github.com/harfbuzz/harfbuzz/issues/4043
++#pragma GCC diagnostic ignored "-Wdangling-pointer" // Trigerred by hb_decycler_node_t().
+ #pragma GCC diagnostic ignored "-Wformat-nonliteral"
+ #pragma GCC diagnostic ignored "-Wformat-zero-length"
+ #pragma GCC diagnostic ignored "-Wmissing-field-initializers"
+@@ -177,6 +180,11 @@
+ #define HB_EXTERN __declspec (dllexport) extern
+ #endif
+ 
++// https://github.com/harfbuzz/harfbuzz/pull/4619
++#ifndef __STDC_FORMAT_MACROS
++#define __STDC_FORMAT_MACROS 1
++#endif
++
+ #include "hb.h"
+ #define HB_H_IN
+ #include "hb-ot.h"
+@@ -212,6 +220,12 @@
+ #include 
+ #endif
+ 
++#ifndef PRId32
++# define PRId32 "d"
++# define PRIu32 "u"
++# define PRIx32 "x"
++#endif
++
+ #define HB_PASTE1(a,b) a##b
+ #define HB_PASTE(a,b) HB_PASTE1(a,b)
+ 
+@@ -268,7 +282,9 @@ extern "C" void  hb_free_impl(void *ptr);
+ #define __attribute__(x)
+ #endif
+ 
+-#if defined(__GNUC__) && (__GNUC__ >= 3)
++#if defined(__MINGW32__) && (__GNUC__ >= 3)
++#define HB_PRINTF_FUNC(format_idx, arg_idx) __attribute__((__format__ (gnu_printf, format_idx, arg_idx)))
++#elif defined(__GNUC__) && (__GNUC__ >= 3)
+ #define HB_PRINTF_FUNC(format_idx, arg_idx) __attribute__((__format__ (__printf__, format_idx, arg_idx)))
+ #else
+ #define HB_PRINTF_FUNC(format_idx, arg_idx)
+diff --git a/src/java.desktop/share/native/liblcms/cmsalpha.c b/src/java.desktop/share/native/liblcms/cmsalpha.c
+index 78d3ca6b6..2e50b65be 100644
+--- a/src/java.desktop/share/native/liblcms/cmsalpha.c
++++ b/src/java.desktop/share/native/liblcms/cmsalpha.c
+@@ -30,7 +30,7 @@
+ //---------------------------------------------------------------------------------
+ //
+ //  Little Color Management System
+-//  Copyright (c) 1998-2023 Marti Maria Saguer
++//  Copyright (c) 1998-2024 Marti Maria Saguer
+ //
+ // Permission is hereby granted, free of charge, to any person obtaining
+ // a copy of this software and associated documentation files (the "Software"),
+@@ -612,8 +612,8 @@ void _cmsHandleExtraChannels(_cmsTRANSFORM* p, const void* in,
+         cmsUInt8Number* SourcePtr;
+         cmsUInt8Number* DestPtr;
+ 
+-        cmsUInt32Number SourceStrideIncrement = 0;
+-        cmsUInt32Number DestStrideIncrement = 0;
++        size_t SourceStrideIncrement = 0;
++        size_t DestStrideIncrement = 0;
+ 
+         // The loop itself
+         for (i = 0; i < LineCount; i++) {
+@@ -640,8 +640,8 @@ void _cmsHandleExtraChannels(_cmsTRANSFORM* p, const void* in,
+         cmsUInt8Number* SourcePtr[cmsMAXCHANNELS];
+         cmsUInt8Number* DestPtr[cmsMAXCHANNELS];
+ 
+-        cmsUInt32Number SourceStrideIncrements[cmsMAXCHANNELS];
+-        cmsUInt32Number DestStrideIncrements[cmsMAXCHANNELS];
++        size_t SourceStrideIncrements[cmsMAXCHANNELS];
++        size_t DestStrideIncrements[cmsMAXCHANNELS];
+ 
+         memset(SourceStrideIncrements, 0, sizeof(SourceStrideIncrements));
+         memset(DestStrideIncrements, 0, sizeof(DestStrideIncrements));
+diff --git a/src/java.desktop/share/native/liblcms/cmscam02.c b/src/java.desktop/share/native/liblcms/cmscam02.c
+index 71a48d43d..45ef4eef9 100644
+--- a/src/java.desktop/share/native/liblcms/cmscam02.c
++++ b/src/java.desktop/share/native/liblcms/cmscam02.c
+@@ -30,7 +30,7 @@
+ //---------------------------------------------------------------------------------
+ //
+ //  Little Color Management System
+-//  Copyright (c) 1998-2023 Marti Maria Saguer
++//  Copyright (c) 1998-2024 Marti Maria Saguer
+ //
+ // Permission is hereby granted, free of charge, to any person obtaining
+ // a copy of this software and associated documentation files (the "Software"),
+@@ -117,17 +117,16 @@ cmsFloat64Number computeFL(cmsCIECAM02* pMod)
+     return FL;
+ }
+ 
+-static
+-cmsFloat64Number computeD(cmsCIECAM02* pMod)
++static cmsFloat64Number computeD(cmsCIECAM02* pMod)
+ {
+-    cmsFloat64Number D;
++    cmsFloat64Number D, temp;
+ 
+-    D = pMod->F - (1.0/3.6)*(exp(((-pMod ->LA-42) / 92.0)));
++    temp = 1.0 - ((1.0 / 3.6) * exp((-pMod->LA - 42) / 92.0));
+ 
++    D = pMod->F * temp;
+     return D;
+ }
+ 
+-
+ static
+ CAM02COLOR XYZtoCAT02(CAM02COLOR clr)
+ {
+diff --git a/src/java.desktop/share/native/liblcms/cmscgats.c b/src/java.desktop/share/native/liblcms/cmscgats.c
+index 57725ae47..3e62d064c 100644
+--- a/src/java.desktop/share/native/liblcms/cmscgats.c
++++ b/src/java.desktop/share/native/liblcms/cmscgats.c
+@@ -30,7 +30,7 @@
+ //---------------------------------------------------------------------------------
+ //
+ //  Little Color Management System
+-//  Copyright (c) 1998-2023 Marti Maria Saguer
++//  Copyright (c) 1998-2024 Marti Maria Saguer
+ //
+ // Permission is hereby granted, free of charge, to any person obtaining
+ // a copy of this software and associated documentation files (the "Software"),
+@@ -444,10 +444,11 @@ static
+ void StringClear(string* s)
+ {
+     s->len = 0;
++    s->begin[0] = 0;
+ }
+ 
+ static
+-void StringAppend(string* s, char c)
++cmsBool StringAppend(string* s, char c)
+ {
+     if (s->len + 1 >= s->max)
+     {
+@@ -455,6 +456,8 @@ void StringAppend(string* s, char c)
+ 
+         s->max *= 10;
+         new_ptr = (char*) AllocChunk(s->it8, s->max);
++        if (new_ptr == NULL) return FALSE;
++
+         if (new_ptr != NULL && s->begin != NULL)
+             memcpy(new_ptr, s->begin, s->len);
+ 
+@@ -466,6 +469,8 @@ void StringAppend(string* s, char c)
+         s->begin[s->len++] = c;
+         s->begin[s->len] = 0;
+     }
++
++    return TRUE;
+ }
+ 
+ static
+@@ -475,13 +480,15 @@ char* StringPtr(string* s)
+ }
+ 
+ static
+-void StringCat(string* s, const char* c)
++cmsBool StringCat(string* s, const char* c)
+ {
+     while (*c)
+     {
+-        StringAppend(s, *c);
++        if (!StringAppend(s, *c)) return FALSE;
+         c++;
+     }
++
++    return TRUE;
+ }
+ 
+ 
+@@ -830,7 +837,12 @@ void InStringSymbol(cmsIT8* it8)
+ 
+             if (it8->ch == '\n' || it8->ch == '\r' || it8->ch == 0) break;
+             else {
+-                StringAppend(it8->str, (char)it8->ch);
++                if (!StringAppend(it8->str, (char)it8->ch)) {
++
++                    SynError(it8, "Out of memory");
++                    return;
++                }
++
+                 NextCh(it8);
+             }
+         }
+@@ -860,7 +872,11 @@ void InSymbol(cmsIT8* it8)
+ 
+             do {
+ 
+-                StringAppend(it8->id, (char) it8->ch);
++                if (!StringAppend(it8->id, (char)it8->ch)) {
++
++                    SynError(it8, "Out of memory");
++                    return;
++                }
+ 
+                 NextCh(it8);
+ 
+@@ -904,7 +920,6 @@ void InSymbol(cmsIT8* it8)
+                             if ((cmsFloat64Number) it8->inum * 16.0 + (cmsFloat64Number) j > (cmsFloat64Number)+2147483647.0)
+                             {
+                                 SynError(it8, "Invalid hexadecimal number");
+-                                it8->sy = SEOF;
+                                 return;
+                             }
+ 
+@@ -926,7 +941,6 @@ void InSymbol(cmsIT8* it8)
+                             if ((cmsFloat64Number) it8->inum * 2.0 + j > (cmsFloat64Number)+2147483647.0)
+                             {
+                                 SynError(it8, "Invalid binary number");
+-                                it8->sy = SEOF;
+                                 return;
+                             }
+ 
+@@ -979,11 +993,19 @@ void InSymbol(cmsIT8* it8)
+                     }
+ 
+                     StringClear(it8->id);
+-                    StringCat(it8->id, buffer);
++                    if (!StringCat(it8->id, buffer)) {
++
++                        SynError(it8, "Out of memory");
++                        return;
++                    }
+ 
+                     do {
+ 
+-                        StringAppend(it8->id, (char) it8->ch);
++                        if (!StringAppend(it8->id, (char)it8->ch)) {
++
++                            SynError(it8, "Out of memory");
++                            return;
++                        }
+ 
+                         NextCh(it8);
+ 
+@@ -1038,7 +1060,6 @@ void InSymbol(cmsIT8* it8)
+ 
+         default:
+             SynError(it8, "Unrecognized character: 0x%x", it8 ->ch);
+-            it8->sy = SEOF;
+             return;
+             }
+ 
+@@ -1053,24 +1074,21 @@ void InSymbol(cmsIT8* it8)
+                 if(it8 -> IncludeSP >= (MAXINCLUDE-1)) {
+ 
+                     SynError(it8, "Too many recursion levels");
+-                    it8->sy = SEOF;
+                     return;
+                 }
+ 
+                 InStringSymbol(it8);
+                 if (!Check(it8, SSTRING, "Filename expected"))
+-                {
+-                    it8->sy = SEOF;
+                     return;
+-                }
++
+ 
+                 FileNest = it8 -> FileStack[it8 -> IncludeSP + 1];
+                 if(FileNest == NULL) {
+ 
+                     FileNest = it8 ->FileStack[it8 -> IncludeSP + 1] = (FILECTX*)AllocChunk(it8, sizeof(FILECTX));
+                     if (FileNest == NULL) {
++
+                         SynError(it8, "Out of memory");
+-                        it8->sy = SEOF;
+                         return;
+                     }
+                 }
+@@ -1078,8 +1096,8 @@ void InSymbol(cmsIT8* it8)
+                 if (BuildAbsolutePath(StringPtr(it8->str),
+                                       it8->FileStack[it8->IncludeSP]->FileName,
+                                       FileNest->FileName, cmsMAX_PATH-1) == FALSE) {
++
+                     SynError(it8, "File path too long");
+-                    it8->sy = SEOF;
+                     return;
+                 }
+ 
+@@ -1087,7 +1105,6 @@ void InSymbol(cmsIT8* it8)
+                 if (FileNest->Stream == NULL) {
+ 
+                         SynError(it8, "File %s not found", FileNest->FileName);
+-                        it8->sy = SEOF;
+                         return;
+                 }
+                 it8->IncludeSP++;
+@@ -1102,10 +1119,10 @@ void InSymbol(cmsIT8* it8)
+ static
+ cmsBool CheckEOLN(cmsIT8* it8)
+ {
+-        if (!Check(it8, SEOLN, "Expected separator")) return FALSE;
+-        while (it8 -> sy == SEOLN)
+-                        InSymbol(it8);
+-        return TRUE;
++    if (!Check(it8, SEOLN, "Expected separator")) return FALSE;
++    while (it8->sy == SEOLN)
++        InSymbol(it8);
++    return TRUE;
+ 
+ }
+ 
+@@ -1114,8 +1131,8 @@ cmsBool CheckEOLN(cmsIT8* it8)
+ static
+ void Skip(cmsIT8* it8, SYMBOL sy)
+ {
+-        if (it8->sy == sy && it8->sy != SEOF)
+-                        InSymbol(it8);
++    if (it8->sy == sy && it8->sy != SEOF && it8->sy != SSYNERROR)
++        InSymbol(it8);
+ }
+ 
+ 
+@@ -1124,7 +1141,7 @@ static
+ void SkipEOLN(cmsIT8* it8)
+ {
+     while (it8->sy == SEOLN) {
+-             InSymbol(it8);
++        InSymbol(it8);
+     }
+ }
+ 
+@@ -1235,9 +1252,12 @@ void* AllocChunk(cmsIT8* it8, cmsUInt32Number size)
+     cmsUInt8Number* ptr;
+ 
+     size = _cmsALIGNMEM(size);
++    if (size == 0) return NULL;
+ 
+     if (size > Free) {
+ 
++        cmsUInt8Number* new_block;
++
+         if (it8 -> Allocator.BlockSize == 0)
+ 
+                 it8 -> Allocator.BlockSize = 20*1024;
+@@ -1248,7 +1268,11 @@ void* AllocChunk(cmsIT8* it8, cmsUInt32Number size)
+                 it8 ->Allocator.BlockSize = size;
+ 
+         it8 ->Allocator.Used = 0;
+-        it8 ->Allocator.Block = (cmsUInt8Number*) AllocBigBlock(it8, it8 ->Allocator.BlockSize);
++        new_block = (cmsUInt8Number*)AllocBigBlock(it8, it8->Allocator.BlockSize);
++        if (new_block == NULL)
++            return NULL;
++
++        it8->Allocator.Block = new_block;
+     }
+ 
+     if (it8->Allocator.Block == NULL)
+@@ -1258,7 +1282,6 @@ void* AllocChunk(cmsIT8* it8, cmsUInt32Number size)
+     it8 ->Allocator.Used += size;
+ 
+     return (void*) ptr;
+-
+ }
+ 
+ 
+@@ -1266,9 +1289,12 @@ void* AllocChunk(cmsIT8* it8, cmsUInt32Number size)
+ static
+ char *AllocString(cmsIT8* it8, const char* str)
+ {
+-    cmsUInt32Number Size = (cmsUInt32Number) strlen(str)+1;
++    cmsUInt32Number Size;
+     char *ptr;
+ 
++    if (str == NULL) return NULL;
++
++    Size = (cmsUInt32Number)strlen(str) + 1;
+ 
+     ptr = (char *) AllocChunk(it8, Size);
+     if (ptr) memcpy(ptr, str, Size-1);
+@@ -1404,10 +1430,13 @@ KEYVALUE* AddAvailableSampleID(cmsIT8* it8, const char* Key)
+ 
+ 
+ static
+-void AllocTable(cmsIT8* it8)
++cmsBool AllocTable(cmsIT8* it8)
+ {
+     TABLE* t;
+ 
++    if (it8->TablesCount >= (MAXTABLES-1))
++        return FALSE;
++
+     t = it8 ->Tab + it8 ->TablesCount;
+ 
+     t->HeaderList = NULL;
+@@ -1415,6 +1444,7 @@ void AllocTable(cmsIT8* it8)
+     t->Data       = NULL;
+ 
+     it8 ->TablesCount++;
++    return TRUE;
+ }
+ 
+ 
+@@ -1426,7 +1456,10 @@ cmsInt32Number CMSEXPORT cmsIT8SetTable(cmsHANDLE  IT8, cmsUInt32Number nTable)
+ 
+          if (nTable == it8 ->TablesCount) {
+ 
+-             AllocTable(it8);
++             if (!AllocTable(it8)) {
++                 SynError(it8, "Too many tables");
++                 return -1;
++             }
+          }
+          else {
+              SynError(it8, "Table %d is out of sequence", nTable);
+@@ -1610,8 +1643,8 @@ cmsInt32Number satoi(const char* b)
+     if (b == NULL) return 0;
+ 
+     n = atoi(b);
+-    if (n > 0x7fffffffL) return 0x7fffffffL;
+-    if (n < -0x7ffffffeL) return -0x7ffffffeL;
++    if (n > 0x7ffffff0L) return 0x7ffffff0L;
++    if (n < -0x7ffffff0L) return -0x7ffffff0L;
+ 
+     return (cmsInt32Number)n;
+ }
+@@ -1620,22 +1653,26 @@ cmsInt32Number satoi(const char* b)
+ static
+ cmsBool AllocateDataFormat(cmsIT8* it8)
+ {
++    cmsUInt32Number size;
++
+     TABLE* t = GetTable(it8);
+ 
+-    if (t -> DataFormat) return TRUE;    // Already allocated
++    if (t->DataFormat) return TRUE;    // Already allocated
+ 
+-    t -> nSamples  = satoi(cmsIT8GetProperty(it8, "NUMBER_OF_FIELDS"));
++    t->nSamples = satoi(cmsIT8GetProperty(it8, "NUMBER_OF_FIELDS"));
+ 
+-    if (t -> nSamples <= 0) {
++    if (t->nSamples <= 0 || t->nSamples > 0x7ffe) {
+ 
+-        SynError(it8, "AllocateDataFormat: Unknown NUMBER_OF_FIELDS");
++        SynError(it8, "Wrong NUMBER_OF_FIELDS");
+         return FALSE;
+-        }
++    }
++
++    size = ((cmsUInt32Number)t->nSamples + 1) * sizeof(char*);
+ 
+-    t -> DataFormat = (char**) AllocChunk (it8, ((cmsUInt32Number) t->nSamples + 1) * sizeof(char *));
++    t->DataFormat = (char**)AllocChunk(it8, size);
+     if (t->DataFormat == NULL) {
+ 
+-        SynError(it8, "AllocateDataFormat: Unable to allocate dataFormat array");
++        SynError(it8, "Unable to allocate dataFormat array");
+         return FALSE;
+     }
+ 
+@@ -1664,7 +1701,7 @@ cmsBool SetDataFormat(cmsIT8* it8, int n, const char *label)
+             return FALSE;
+     }
+ 
+-    if (n > t -> nSamples) {
++    if (n >= t -> nSamples) {
+         SynError(it8, "More than NUMBER_OF_FIELDS fields.");
+         return FALSE;
+     }
+@@ -1713,13 +1750,14 @@ cmsBool AllocateDataSet(cmsIT8* it8)
+     t-> nSamples   = satoi(cmsIT8GetProperty(it8, "NUMBER_OF_FIELDS"));
+     t-> nPatches   = satoi(cmsIT8GetProperty(it8, "NUMBER_OF_SETS"));
+ 
+-    if (t -> nSamples < 0 || t->nSamples > 0x7ffe || t->nPatches < 0 || t->nPatches > 0x7ffe)
++    if (t -> nSamples < 0 || t->nSamples > 0x7ffe || t->nPatches < 0 || t->nPatches > 0x7ffe ||
++        (t->nPatches * t->nSamples) > 200000)
+     {
+         SynError(it8, "AllocateDataSet: too much data");
+         return FALSE;
+     }
+     else {
+-        // Some dumb analizers warns of possible overflow here, just take a look couple of lines above.
++        // Some dumb analyzers warns of possible overflow here, just take a look couple of lines above.
+         t->Data = (char**)AllocChunk(it8, ((cmsUInt32Number)t->nSamples + 1) * ((cmsUInt32Number)t->nPatches + 1) * sizeof(char*));
+         if (t->Data == NULL) {
+ 
+@@ -1748,8 +1786,11 @@ char* GetData(cmsIT8* it8, int nSet, int nField)
+ static
+ cmsBool SetData(cmsIT8* it8, int nSet, int nField, const char *Val)
+ {
++    char* ptr;
++
+     TABLE* t = GetTable(it8);
+ 
++
+     if (!t->Data) {
+         if (!AllocateDataSet(it8)) return FALSE;
+     }
+@@ -1766,7 +1807,11 @@ cmsBool SetData(cmsIT8* it8, int nSet, int nField, const char *Val)
+ 
+     }
+ 
+-    t->Data [nSet * t -> nSamples + nField] = AllocString(it8, Val);
++    ptr = AllocString(it8, Val);
++    if (ptr == NULL)
++        return FALSE;
++
++    t->Data [nSet * t -> nSamples + nField] = ptr;
+     return TRUE;
+ }
+ 
+@@ -2121,7 +2166,7 @@ cmsBool DataSection (cmsIT8* it8)
+         if (!AllocateDataSet(it8)) return FALSE;
+     }
+ 
+-    while (it8->sy != SEND_DATA && it8->sy != SEOF)
++    while (it8->sy != SEND_DATA && it8->sy != SEOF && it8->sy != SSYNERROR)
+     {
+         if (iField >= t -> nSamples) {
+             iField = 0;
+@@ -2129,7 +2174,7 @@ cmsBool DataSection (cmsIT8* it8)
+ 
+         }
+ 
+-        if (it8->sy != SEND_DATA && it8->sy != SEOF) {
++        if (it8->sy != SEND_DATA && it8->sy != SEOF && it8->sy != SSYNERROR) {
+ 
+             switch (it8->sy)
+             {
+@@ -2225,8 +2270,8 @@ cmsBool HeaderSection(cmsIT8* it8)
+             if (!GetVal(it8, Buffer, MAXSTR - 1, "Property data expected")) return FALSE;
+ 
+             if (Key->WriteAs != WRITE_PAIR) {
+-                AddToList(it8, &GetTable(it8)->HeaderList, VarName, NULL, Buffer,
+-                    (it8->sy == SSTRING) ? WRITE_STRINGIFY : WRITE_UNCOOKED);
++                if (AddToList(it8, &GetTable(it8)->HeaderList, VarName, NULL, Buffer,
++                    (it8->sy == SSTRING) ? WRITE_STRINGIFY : WRITE_UNCOOKED) == NULL) return FALSE;
+             }
+             else {
+                 const char *Subkey;
+@@ -2332,9 +2377,10 @@ cmsBool ParseIT8(cmsIT8* it8, cmsBool nosheet)
+ 
+                     if (!DataSection(it8)) return FALSE;
+ 
+-                    if (it8 -> sy != SEOF) {
++                    if (it8 -> sy != SEOF && it8->sy != SSYNERROR) {
++
++                            if (!AllocTable(it8)) return FALSE;
+ 
+-                            AllocTable(it8);
+                             it8 ->nTable = it8 ->TablesCount - 1;
+ 
+                             // Read sheet type if present. We only support identifier and string.
+@@ -3064,7 +3110,8 @@ cmsBool ParseCube(cmsIT8* cube, cmsStage** Shaper, cmsStage** CLUT, char title[]
+ 
+     InSymbol(cube);
+ 
+-    while (cube->sy != SEOF) {
++    while (cube->sy != SEOF && cube->sy != SSYNERROR) {
++
+         switch (cube->sy)
+         {
+         // Set profile description
+diff --git a/src/java.desktop/share/native/liblcms/cmscnvrt.c b/src/java.desktop/share/native/liblcms/cmscnvrt.c
+index d18865b15..9f8619cb9 100644
+--- a/src/java.desktop/share/native/liblcms/cmscnvrt.c
++++ b/src/java.desktop/share/native/liblcms/cmscnvrt.c
+@@ -30,7 +30,7 @@
+ //---------------------------------------------------------------------------------
+ //
+ //  Little Color Management System
+-//  Copyright (c) 1998-2023 Marti Maria Saguer
++//  Copyright (c) 1998-2024 Marti Maria Saguer
+ //
+ // Permission is hereby granted, free of charge, to any person obtaining
+ // a copy of this software and associated documentation files (the "Software"),
+@@ -750,7 +750,6 @@ static
+ cmsBool is_cmyk_devicelink(cmsHPROFILE hProfile)
+ {
+     return cmsGetDeviceClass(hProfile) == cmsSigLinkClass &&
+-            cmsGetColorSpace(hProfile) == cmsSigCmykData &&
+             cmsGetColorSpace(hProfile) == cmsSigCmykData;
+ }
+ 
+diff --git a/src/java.desktop/share/native/liblcms/cmserr.c b/src/java.desktop/share/native/liblcms/cmserr.c
+index 9fb7db89c..d421c550d 100644
+--- a/src/java.desktop/share/native/liblcms/cmserr.c
++++ b/src/java.desktop/share/native/liblcms/cmserr.c
+@@ -30,7 +30,7 @@
+ //---------------------------------------------------------------------------------
+ //
+ //  Little Color Management System
+-//  Copyright (c) 1998-2023 Marti Maria Saguer
++//  Copyright (c) 1998-2024 Marti Maria Saguer
+ //
+ // Permission is hereby granted, free of charge, to any person obtaining
+ // a copy of this software and associated documentation files (the "Software"),
+diff --git a/src/java.desktop/share/native/liblcms/cmsgamma.c b/src/java.desktop/share/native/liblcms/cmsgamma.c
+index 8e489a43c..773858b0c 100644
+--- a/src/java.desktop/share/native/liblcms/cmsgamma.c
++++ b/src/java.desktop/share/native/liblcms/cmsgamma.c
+@@ -30,7 +30,7 @@
+ //---------------------------------------------------------------------------------
+ //
+ //  Little Color Management System
+-//  Copyright (c) 1998-2023 Marti Maria Saguer
++//  Copyright (c) 1998-2024 Marti Maria Saguer
+ //
+ // Permission is hereby granted, free of charge, to any person obtaining
+ // a copy of this software and associated documentation files (the "Software"),
+diff --git a/src/java.desktop/share/native/liblcms/cmsgmt.c b/src/java.desktop/share/native/liblcms/cmsgmt.c
+index e9ee73b52..03ac70202 100644
+--- a/src/java.desktop/share/native/liblcms/cmsgmt.c
++++ b/src/java.desktop/share/native/liblcms/cmsgmt.c
+@@ -30,7 +30,7 @@
+ //---------------------------------------------------------------------------------
+ //
+ //  Little Color Management System
+-//  Copyright (c) 1998-2021 Marti Maria Saguer
++//  Copyright (c) 1998-2024 Marti Maria Saguer
+ //
+ // Permission is hereby granted, free of charge, to any person obtaining
+ // a copy of this software and associated documentation files (the "Software"),
+@@ -327,8 +327,9 @@ cmsPipeline* _cmsCreateGamutCheckPipeline(cmsContext ContextID,
+     cmsUInt32Number dwFormat;
+     GAMUTCHAIN Chain;
+     cmsUInt32Number nGridpoints;
+-    cmsInt32Number nChannels;
++    cmsInt32Number nChannels, nInputChannels;
+     cmsColorSpaceSignature ColorSpace;
++    cmsColorSpaceSignature InputColorSpace;
+     cmsUInt32Number i;
+     cmsHPROFILE ProfileList[256];
+     cmsBool     BPCList[256];
+@@ -374,11 +375,13 @@ cmsPipeline* _cmsCreateGamutCheckPipeline(cmsContext ContextID,
+     AdaptationList[nGamutPCSposition] = 1.0;
+     IntentList[nGamutPCSposition] = INTENT_RELATIVE_COLORIMETRIC;
+ 
+-
+     ColorSpace  = cmsGetColorSpace(hGamut);
+     nChannels   = cmsChannelsOfColorSpace(ColorSpace);
+     nGridpoints = _cmsReasonableGridpointsByColorspace(ColorSpace, cmsFLAGS_HIGHRESPRECALC);
+-    dwFormat    = (CHANNELS_SH(nChannels)|BYTES_SH(2));
++
++    InputColorSpace = cmsGetColorSpace(ProfileList[0]);
++    nInputChannels  = cmsChannelsOfColorSpace(InputColorSpace);
++    dwFormat        = (CHANNELS_SH(nInputChannels)|BYTES_SH(2));
+ 
+     // 16 bits to Lab double
+     Chain.hInput = cmsCreateExtendedTransform(ContextID,
+diff --git a/src/java.desktop/share/native/liblcms/cmshalf.c b/src/java.desktop/share/native/liblcms/cmshalf.c
+index 5babb063e..7e5f7a3c7 100644
+--- a/src/java.desktop/share/native/liblcms/cmshalf.c
++++ b/src/java.desktop/share/native/liblcms/cmshalf.c
+@@ -30,7 +30,7 @@
+ //---------------------------------------------------------------------------------
+ //
+ //  Little Color Management System
+-//  Copyright (c) 1998-2023 Marti Maria Saguer
++//  Copyright (c) 1998-2024 Marti Maria Saguer
+ //
+ // Permission is hereby granted, free of charge, to any person obtaining
+ // a copy of this software and associated documentation files (the "Software"),
+diff --git a/src/java.desktop/share/native/liblcms/cmsintrp.c b/src/java.desktop/share/native/liblcms/cmsintrp.c
+index 9837454df..43c47429c 100644
+--- a/src/java.desktop/share/native/liblcms/cmsintrp.c
++++ b/src/java.desktop/share/native/liblcms/cmsintrp.c
+@@ -30,7 +30,7 @@
+ //---------------------------------------------------------------------------------
+ //
+ //  Little Color Management System
+-//  Copyright (c) 1998-2023 Marti Maria Saguer
++//  Copyright (c) 1998-2024 Marti Maria Saguer
+ //
+ // Permission is hereby granted, free of charge, to any person obtaining
+ // a copy of this software and associated documentation files (the "Software"),
+@@ -524,7 +524,7 @@ void TrilinearInterpFloat(const cmsFloat32Number Input[],
+     py = fclamp(Input[1]) * p->Domain[1];
+     pz = fclamp(Input[2]) * p->Domain[2];
+ 
+-    x0 = (int) floor(px); fx = px - (cmsFloat32Number) x0;  // We need full floor funcionality here
++    x0 = (int) floor(px); fx = px - (cmsFloat32Number) x0;  // We need full floor functionality here
+     y0 = (int) floor(py); fy = py - (cmsFloat32Number) y0;
+     z0 = (int) floor(pz); fz = pz - (cmsFloat32Number) z0;
+ 
+diff --git a/src/java.desktop/share/native/liblcms/cmsio0.c b/src/java.desktop/share/native/liblcms/cmsio0.c
+index 05baa9392..5258b7939 100644
+--- a/src/java.desktop/share/native/liblcms/cmsio0.c
++++ b/src/java.desktop/share/native/liblcms/cmsio0.c
+@@ -30,7 +30,7 @@
+ //---------------------------------------------------------------------------------
+ //
+ //  Little Color Management System
+-//  Copyright (c) 1998-2023 Marti Maria Saguer
++//  Copyright (c) 1998-2024 Marti Maria Saguer
+ //
+ // Permission is hereby granted, free of charge, to any person obtaining
+ // a copy of this software and associated documentation files (the "Software"),
+@@ -306,6 +306,11 @@ cmsIOHANDLER* CMSEXPORT cmsOpenIOhandlerFromMem(cmsContext ContextID, void *Buff
+         fm = (FILEMEM*) _cmsMallocZero(ContextID, sizeof(FILEMEM));
+         if (fm == NULL) goto Error;
+ 
++        if (Buffer == NULL) {
++            cmsSignalError(ContextID, cmsERROR_WRITE, "Couldn't write profile to NULL pointer");
++            goto Error;
++        }
++
+         fm ->Block = (cmsUInt8Number*) Buffer;
+         fm ->FreeBlockOnClose = FALSE;
+         fm ->Size    = size;
+diff --git a/src/java.desktop/share/native/liblcms/cmsio1.c b/src/java.desktop/share/native/liblcms/cmsio1.c
+index e42d4d389..48772c7cb 100644
+--- a/src/java.desktop/share/native/liblcms/cmsio1.c
++++ b/src/java.desktop/share/native/liblcms/cmsio1.c
+@@ -30,7 +30,7 @@
+ //---------------------------------------------------------------------------------
+ //
+ //  Little Color Management System
+-//  Copyright (c) 1998-2023 Marti Maria Saguer
++//  Copyright (c) 1998-2024 Marti Maria Saguer
+ //
+ // Permission is hereby granted, free of charge, to any person obtaining
+ // a copy of this software and associated documentation files (the "Software"),
+diff --git a/src/java.desktop/share/native/liblcms/cmslut.c b/src/java.desktop/share/native/liblcms/cmslut.c
+index b544c9486..3cf4e8cac 100644
+--- a/src/java.desktop/share/native/liblcms/cmslut.c
++++ b/src/java.desktop/share/native/liblcms/cmslut.c
+@@ -30,7 +30,7 @@
+ //---------------------------------------------------------------------------------
+ //
+ //  Little Color Management System
+-//  Copyright (c) 1998-2023 Marti Maria Saguer
++//  Copyright (c) 1998-2024 Marti Maria Saguer
+ //
+ // Permission is hereby granted, free of charge, to any person obtaining
+ // a copy of this software and associated documentation files (the "Software"),
+@@ -1109,7 +1109,7 @@ cmsStage* _cmsStageNormalizeFromLabFloat(cmsContext ContextID)
+     return mpe;
+ }
+ 
+-// Fom XYZ to floating point PCS
++// From XYZ to floating point PCS
+ cmsStage* _cmsStageNormalizeFromXyzFloat(cmsContext ContextID)
+ {
+ #define n (32768.0/65535.0)
+diff --git a/src/java.desktop/share/native/liblcms/cmsmd5.c b/src/java.desktop/share/native/liblcms/cmsmd5.c
+index 01aa44de8..d9b9a4e52 100644
+--- a/src/java.desktop/share/native/liblcms/cmsmd5.c
++++ b/src/java.desktop/share/native/liblcms/cmsmd5.c
+@@ -30,7 +30,7 @@
+ //---------------------------------------------------------------------------------
+ //
+ //  Little Color Management System
+-//  Copyright (c) 1998-2023 Marti Maria Saguer
++//  Copyright (c) 1998-2024 Marti Maria Saguer
+ //
+ // Permission is hereby granted, free of charge, to any person obtaining
+ // a copy of this software and associated documentation files (the "Software"),
+@@ -280,8 +280,8 @@ void CMSEXPORT cmsMD5finish(cmsProfileID* ProfileID,  cmsHANDLE Handle)
+ 
+ 
+ // Assuming io points to an ICC profile, compute and store MD5 checksum
+-// In the header, rendering intentent, attributes and ID should be set to zero
+-// before computing MD5 checksum (per 6.1.13 in ICC spec)
++// In the header, rendering intentent, flags and ID should be set to zero
++// before computing MD5 checksum (per 7.2.18 of ICC spec 4.4)
+ 
+ cmsBool CMSEXPORT cmsMD5computeID(cmsHPROFILE hProfile)
+ {
+@@ -299,8 +299,8 @@ cmsBool CMSEXPORT cmsMD5computeID(cmsHPROFILE hProfile)
+     // Save a copy of the profile header
+     memmove(&Keep, Icc, sizeof(_cmsICCPROFILE));
+ 
+-    // Set RI, attributes and ID
+-    memset(&Icc ->attributes, 0, sizeof(Icc ->attributes));
++    // Set RI, flags and ID
++    Icc ->flags = 0;
+     Icc ->RenderingIntent = 0;
+     memset(&Icc ->ProfileID, 0, sizeof(Icc ->ProfileID));
+ 
+diff --git a/src/java.desktop/share/native/liblcms/cmsmtrx.c b/src/java.desktop/share/native/liblcms/cmsmtrx.c
+index 599c290bd..841da662a 100644
+--- a/src/java.desktop/share/native/liblcms/cmsmtrx.c
++++ b/src/java.desktop/share/native/liblcms/cmsmtrx.c
+@@ -30,7 +30,7 @@
+ //---------------------------------------------------------------------------------
+ //
+ //  Little Color Management System
+-//  Copyright (c) 1998-2023 Marti Maria Saguer
++//  Copyright (c) 1998-2024 Marti Maria Saguer
+ //
+ // Permission is hereby granted, free of charge, to any person obtaining
+ // a copy of this software and associated documentation files (the "Software"),
+diff --git a/src/java.desktop/share/native/liblcms/cmsnamed.c b/src/java.desktop/share/native/liblcms/cmsnamed.c
+index d3cd97d4a..451bfe9f3 100644
+--- a/src/java.desktop/share/native/liblcms/cmsnamed.c
++++ b/src/java.desktop/share/native/liblcms/cmsnamed.c
+@@ -30,7 +30,7 @@
+ //---------------------------------------------------------------------------------
+ //
+ //  Little Color Management System
+-//  Copyright (c) 1998-2023 Marti Maria Saguer
++//  Copyright (c) 1998-2024 Marti Maria Saguer
+ //
+ // Permission is hereby granted, free of charge, to any person obtaining
+ // a copy of this software and associated documentation files (the "Software"),
+@@ -598,7 +598,7 @@ cmsUInt32Number CMSEXPORT cmsMLUgetASCII(const cmsMLU* mlu,
+     if (BufferSize < ASCIIlen + 1)
+         ASCIIlen = BufferSize - 1;
+ 
+-    // Precess each character
++    // Process each character
+     for (i=0; i < ASCIIlen; i++) {
+ 
+         wchar_t wc = Wide[i];
+diff --git a/src/java.desktop/share/native/liblcms/cmsopt.c b/src/java.desktop/share/native/liblcms/cmsopt.c
+index 421a4f4a7..767008e68 100644
+--- a/src/java.desktop/share/native/liblcms/cmsopt.c
++++ b/src/java.desktop/share/native/liblcms/cmsopt.c
+@@ -30,7 +30,7 @@
+ //---------------------------------------------------------------------------------
+ //
+ //  Little Color Management System
+-//  Copyright (c) 1998-2023 Marti Maria Saguer
++//  Copyright (c) 1998-2024 Marti Maria Saguer
+ //
+ // Permission is hereby granted, free of charge, to any person obtaining
+ // a copy of this software and associated documentation files (the "Software"),
+diff --git a/src/java.desktop/share/native/liblcms/cmspack.c b/src/java.desktop/share/native/liblcms/cmspack.c
+index fc875995a..d430e7305 100644
+--- a/src/java.desktop/share/native/liblcms/cmspack.c
++++ b/src/java.desktop/share/native/liblcms/cmspack.c
+@@ -30,7 +30,7 @@
+ //---------------------------------------------------------------------------------
+ //
+ //  Little Color Management System
+-//  Copyright (c) 1998-2023 Marti Maria Saguer
++//  Copyright (c) 1998-2024 Marti Maria Saguer
+ //
+ // Permission is hereby granted, free of charge, to any person obtaining
+ // a copy of this software and associated documentation files (the "Software"),
+@@ -217,7 +217,7 @@ cmsUInt8Number* UnrollPlanarBytes(CMSREGISTER _cmsTRANSFORM* info,
+     else
+     {
+         if (Premul && Extra)
+-            alpha_factor = _cmsToFixedDomain(FROM_8_TO_16(accum[(nChan) * Stride]));
++            alpha_factor = _cmsToFixedDomain(FROM_8_TO_16(accum[nChan * Stride]));
+     }
+ 
+     for (i=0; i < nChan; i++) {
+@@ -606,8 +606,8 @@ cmsUInt8Number* UnrollAnyWordsPremul(CMSREGISTER _cmsTRANSFORM* info,
+    cmsUInt32Number ExtraFirst  = DoSwap ^ SwapFirst;
+    cmsUInt32Number i;
+ 
+-   cmsUInt16Number alpha = (ExtraFirst ? accum[0] : accum[nChan - 1]);
+-   cmsUInt32Number alpha_factor = _cmsToFixedDomain(FROM_8_TO_16(alpha));
++   cmsUInt16Number alpha = (ExtraFirst ? ((cmsUInt16Number*)accum)[0] : ((cmsUInt16Number*)accum)[nChan]);
++   cmsUInt32Number alpha_factor = _cmsToFixedDomain(alpha);
+ 
+     if (ExtraFirst) {
+         accum += sizeof(cmsUInt16Number);
+@@ -691,8 +691,8 @@ cmsUInt8Number* UnrollPlanarWordsPremul(CMSREGISTER _cmsTRANSFORM* info,
+     cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
+     cmsUInt8Number* Init = accum;
+ 
+-    cmsUInt16Number  alpha = (ExtraFirst ? accum[0] : accum[(nChan - 1) * Stride]);
+-    cmsUInt32Number alpha_factor = _cmsToFixedDomain(FROM_8_TO_16(alpha));
++    cmsUInt16Number alpha = (ExtraFirst ? ((cmsUInt16Number*)accum)[0] : ((cmsUInt16Number*)accum)[nChan * Stride / 2]);
++    cmsUInt32Number alpha_factor = _cmsToFixedDomain(alpha);
+ 
+     if (ExtraFirst) {
+         accum += Stride;
+@@ -1107,8 +1107,7 @@ cmsINLINE cmsBool IsInkSpace(cmsUInt32Number Type)
+ }
+ 
+ // Return the size in bytes of a given formatter
+-static
+-cmsUInt32Number PixelSize(cmsUInt32Number Format)
++cmsINLINE cmsUInt32Number PixelSize(cmsUInt32Number Format)
+ {
+     cmsUInt32Number fmt_bytes = T_BYTES(Format);
+ 
+@@ -1454,7 +1453,7 @@ cmsUInt8Number* UnrollDoublesToFloat(_cmsTRANSFORM* info,
+     if (Premul && Extra)
+     {
+         if (Planar)
+-            alpha_factor = (ExtraFirst ? ptr[0] : ptr[(nChan) * Stride]) / maximum;
++            alpha_factor = (ExtraFirst ? ptr[0] : ptr[nChan * Stride]) / maximum;
+         else
+             alpha_factor = (ExtraFirst ? ptr[0] : ptr[nChan]) / maximum;
+     }
+@@ -3052,6 +3051,7 @@ cmsUInt8Number* PackWordsFromFloat(_cmsTRANSFORM* info,
+     if (ExtraFirst)
+         start = Extra;
+ 
++    Stride /= 2;
+     for (i = 0; i < nChan; i++) {
+ 
+         cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
+@@ -3115,7 +3115,7 @@ cmsUInt8Number* PackFloatsFromFloat(_cmsTRANSFORM* info,
+                      v = maximum - v;
+ 
+               if (Planar)
+-                     ((cmsFloat32Number*)output)[(i + start)* Stride] = (cmsFloat32Number)v;
++                     ((cmsFloat32Number*)output)[(i + start) * Stride] = (cmsFloat32Number)v;
+               else
+                      ((cmsFloat32Number*)output)[i + start] = (cmsFloat32Number)v;
+        }
+@@ -3455,7 +3455,7 @@ cmsUInt8Number* UnrollHalfToFloat(_cmsTRANSFORM* info,
+     cmsUInt32Number i, start = 0;
+     cmsFloat32Number maximum = IsInkSpace(info ->InputFormat) ? 100.0F : 1.0F;
+ 
+-    Stride /= PixelSize(info->OutputFormat);
++    Stride /= PixelSize(info->InputFormat);
+ 
+     if (ExtraFirst)
+             start = Extra;
+@@ -4062,6 +4062,9 @@ cmsUInt32Number CMSEXPORT cmsFormatterForColorspaceOfProfile(cmsHPROFILE hProfil
+     // Unsupported color space?
+     if (nOutputChans < 0) return 0;
+ 
++    // Fix float spaces
++    nBytes &= 7;
++
+     // Create a fake formatter for result
+     return FLOAT_SH(Float) | COLORSPACE_SH(ColorSpaceBits) | BYTES_SH(nBytes) | CHANNELS_SH(nOutputChans);
+ }
+@@ -4079,6 +4082,9 @@ cmsUInt32Number CMSEXPORT cmsFormatterForPCSOfProfile(cmsHPROFILE hProfile, cmsU
+     // Unsupported color space?
+     if (nOutputChans < 0) return 0;
+ 
++    // Fix float spaces
++    nBytes &= 7;
++
+     // Create a fake formatter for result
+     return FLOAT_SH(Float) | COLORSPACE_SH(ColorSpaceBits) | BYTES_SH(nBytes) | CHANNELS_SH(nOutputChans);
+ }
+diff --git a/src/java.desktop/share/native/liblcms/cmspcs.c b/src/java.desktop/share/native/liblcms/cmspcs.c
+index c47398400..5f1b1f0d8 100644
+--- a/src/java.desktop/share/native/liblcms/cmspcs.c
++++ b/src/java.desktop/share/native/liblcms/cmspcs.c
+@@ -30,7 +30,7 @@
+ //---------------------------------------------------------------------------------
+ //
+ //  Little Color Management System
+-//  Copyright (c) 1998-2023 Marti Maria Saguer
++//  Copyright (c) 1998-2024 Marti Maria Saguer
+ //
+ // Permission is hereby granted, free of charge, to any person obtaining
+ // a copy of this software and associated documentation files (the "Software"),
+diff --git a/src/java.desktop/share/native/liblcms/cmsplugin.c b/src/java.desktop/share/native/liblcms/cmsplugin.c
+index f84e0172c..aaad39f52 100644
+--- a/src/java.desktop/share/native/liblcms/cmsplugin.c
++++ b/src/java.desktop/share/native/liblcms/cmsplugin.c
+@@ -30,7 +30,7 @@
+ //---------------------------------------------------------------------------------
+ //
+ //  Little Color Management System
+-//  Copyright (c) 1998-2023 Marti Maria Saguer
++//  Copyright (c) 1998-2024 Marti Maria Saguer
+ //
+ // Permission is hereby granted, free of charge, to any person obtaining
+ // a copy of this software and associated documentation files (the "Software"),
+@@ -935,7 +935,10 @@ cmsContext CMSEXPORT cmsDupContext(cmsContext ContextID, void* NewUserData)
+     if (!InitContextMutex()) return NULL;
+ 
+     // Setup default memory allocators
+-    memcpy(&ctx->DefaultMemoryManager, &src->DefaultMemoryManager, sizeof(ctx->DefaultMemoryManager));
++    if (ContextID == NULL)
++        _cmsInstallAllocFunctions(NULL, &ctx->DefaultMemoryManager);
++    else
++        memcpy(&ctx->DefaultMemoryManager, &src->DefaultMemoryManager, sizeof(ctx->DefaultMemoryManager));
+ 
+     // Maintain the linked list
+     _cmsEnterCriticalSectionPrimitive(&_cmsContextPoolHeadMutex);
+diff --git a/src/java.desktop/share/native/liblcms/cmsps2.c b/src/java.desktop/share/native/liblcms/cmsps2.c
+index 9a2ab464f..476817e9c 100644
+--- a/src/java.desktop/share/native/liblcms/cmsps2.c
++++ b/src/java.desktop/share/native/liblcms/cmsps2.c
+@@ -30,7 +30,7 @@
+ //---------------------------------------------------------------------------------
+ //
+ //  Little Color Management System
+-//  Copyright (c) 1998-2023 Marti Maria Saguer
++//  Copyright (c) 1998-2024 Marti Maria Saguer
+ //
+ // Permission is hereby granted, free of charge, to any person obtaining
+ // a copy of this software and associated documentation files (the "Software"),
+@@ -494,7 +494,7 @@ void Emit1Gamma(cmsIOHANDLER* m, cmsToneCurve* Table)
+     // Bounds check
+     EmitRangeCheck(m);
+ 
+-    // Emit intepolation code
++    // Emit interpolation code
+ 
+     // PostScript code                      Stack
+     // ===============                      ========================
+@@ -618,7 +618,7 @@ int OutputValueSampler(CMSREGISTER const cmsUInt16Number In[], CMSREGISTER cmsUI
+     }
+ 
+ 
+-    // Hadle the parenthesis on rows
++    // Handle the parenthesis on rows
+ 
+     if (In[0] != sc ->FirstComponent) {
+ 
+@@ -694,8 +694,10 @@ void WriteCLUT(cmsIOHANDLER* m, cmsStage* mpe, const char* PreMaj,
+ 
+         _cmsIOPrintf(m, "[");
+ 
+-        for (i = 0; i < sc.Pipeline->Params->nInputs; i++)
+-            _cmsIOPrintf(m, " %d ", sc.Pipeline->Params->nSamples[i]);
++        for (i = 0; i < sc.Pipeline->Params->nInputs; i++) {
++            if (i < MAX_INPUT_DIMENSIONS)
++                _cmsIOPrintf(m, " %d ", sc.Pipeline->Params->nSamples[i]);
++        }
+ 
+         _cmsIOPrintf(m, " [\n");
+ 
+@@ -869,13 +871,13 @@ cmsToneCurve* ExtractGray2Y(cmsContext ContextID, cmsHPROFILE hProfile, cmsUInt3
+ // a more perceptually uniform space... I do choose Lab.
+ 
+ static
+-int WriteInputLUT(cmsIOHANDLER* m, cmsHPROFILE hProfile, cmsUInt32Number Intent, cmsUInt32Number dwFlags)
++cmsBool WriteInputLUT(cmsIOHANDLER* m, cmsHPROFILE hProfile, cmsUInt32Number Intent, cmsUInt32Number dwFlags)
+ {
+     cmsHPROFILE hLab;
+     cmsHTRANSFORM xform;
+     cmsUInt32Number nChannels;
+     cmsUInt32Number InputFormat;
+-    int rc;
++
+     cmsHPROFILE Profiles[2];
+     cmsCIEXYZ BlackPointAdaptedToD50;
+ 
+@@ -900,7 +902,7 @@ int WriteInputLUT(cmsIOHANDLER* m, cmsHPROFILE hProfile, cmsUInt32Number Intent,
+     if (xform == NULL) {
+ 
+         cmsSignalError(m ->ContextID, cmsERROR_COLORSPACE_CHECK, "Cannot create transform Profile -> Lab");
+-        return 0;
++        return FALSE;
+     }
+ 
+     // Only 1, 3 and 4 channels are allowed
+@@ -919,29 +921,35 @@ int WriteInputLUT(cmsIOHANDLER* m, cmsHPROFILE hProfile, cmsUInt32Number Intent,
+             cmsUInt32Number OutFrm = TYPE_Lab_16;
+             cmsPipeline* DeviceLink;
+             _cmsTRANSFORM* v = (_cmsTRANSFORM*) xform;
++            cmsBool rc;
+ 
+             DeviceLink = cmsPipelineDup(v ->Lut);
+-            if (DeviceLink == NULL) return 0;
++            if (DeviceLink == NULL) {
++                cmsDeleteTransform(xform);
++                return FALSE;
++            }
+ 
+             dwFlags |= cmsFLAGS_FORCE_CLUT;
+             _cmsOptimizePipeline(m->ContextID, &DeviceLink, Intent, &InputFormat, &OutFrm, &dwFlags);
+ 
+             rc = EmitCIEBasedDEF(m, DeviceLink, Intent, &BlackPointAdaptedToD50);
+             cmsPipelineFree(DeviceLink);
+-            if (rc == 0) return 0;
++            if (!rc) {
++                cmsDeleteTransform(xform);
++                return FALSE;
++            }
+             }
+             break;
+ 
+     default:
+ 
++        cmsDeleteTransform(xform);
+         cmsSignalError(m ->ContextID, cmsERROR_COLORSPACE_CHECK, "Only 3, 4 channels are supported for CSA. This profile has %d channels.", nChannels);
+-        return 0;
++        return FALSE;
+     }
+ 
+-
+     cmsDeleteTransform(xform);
+-
+-    return 1;
++    return TRUE;
+ }
+ 
+ static
+@@ -1284,7 +1292,7 @@ void EmitXYZ2Lab(cmsIOHANDLER* m)
+ // 8 bits.
+ 
+ static
+-int WriteOutputLUT(cmsIOHANDLER* m, cmsHPROFILE hProfile, cmsUInt32Number Intent, cmsUInt32Number dwFlags)
++cmsBool WriteOutputLUT(cmsIOHANDLER* m, cmsHPROFILE hProfile, cmsUInt32Number Intent, cmsUInt32Number dwFlags)
+ {
+     cmsHPROFILE hLab;
+     cmsHTRANSFORM xform;
+@@ -1302,7 +1310,7 @@ int WriteOutputLUT(cmsIOHANDLER* m, cmsHPROFILE hProfile, cmsUInt32Number Intent
+     cmsStage* first;
+ 
+     hLab = cmsCreateLab4ProfileTHR(m ->ContextID, NULL);
+-    if (hLab == NULL) return 0;
++    if (hLab == NULL) return FALSE;
+ 
+     OutputFormat = cmsFormatterForColorspaceOfProfile(hProfile, 2, FALSE);
+     nChannels    = T_CHANNELS(OutputFormat);
+@@ -1327,7 +1335,7 @@ int WriteOutputLUT(cmsIOHANDLER* m, cmsHPROFILE hProfile, cmsUInt32Number Intent
+ 
+     if (xform == NULL) {
+         cmsSignalError(m ->ContextID, cmsERROR_COLORSPACE_CHECK, "Cannot create transform Lab -> Profile in CRD creation");
+-        return 0;
++        return FALSE;
+     }
+ 
+     // Get a copy of the internal devicelink
+@@ -1335,17 +1343,22 @@ int WriteOutputLUT(cmsIOHANDLER* m, cmsHPROFILE hProfile, cmsUInt32Number Intent
+     DeviceLink = cmsPipelineDup(v ->Lut);
+     if (DeviceLink == NULL) {
+         cmsDeleteTransform(xform);
+-        return 0;
++        cmsSignalError(m->ContextID, cmsERROR_CORRUPTION_DETECTED, "Cannot access link for CRD");
++        return FALSE;
+     }
+ 
+      // We need a CLUT
+     dwFlags |= cmsFLAGS_FORCE_CLUT;
+-    _cmsOptimizePipeline(m->ContextID, &DeviceLink, RelativeEncodingIntent, &InFrm, &OutputFormat, &dwFlags);
++    if (!_cmsOptimizePipeline(m->ContextID, &DeviceLink, RelativeEncodingIntent, &InFrm, &OutputFormat, &dwFlags)) {
++        cmsPipelineFree(DeviceLink);
++        cmsDeleteTransform(xform);
++        cmsSignalError(m->ContextID, cmsERROR_CORRUPTION_DETECTED, "Cannot create CLUT table for CRD");
++        return FALSE;
++    }
+ 
+     _cmsIOPrintf(m, "<<\n");
+     _cmsIOPrintf(m, "/ColorRenderingType 1\n");
+ 
+-
+     cmsDetectBlackPoint(&BlackPointAdaptedToD50, hProfile, Intent, 0);
+ 
+     // Emit headers, etc.
+@@ -1367,6 +1380,13 @@ int WriteOutputLUT(cmsIOHANDLER* m, cmsHPROFILE hProfile, cmsUInt32Number Intent
+ 
+     first = cmsPipelineGetPtrToFirstStage(DeviceLink);
+     if (first != NULL) {
++        if (first->Type != cmsSigCLutElemType) {
++            cmsPipelineFree(DeviceLink);
++            cmsDeleteTransform(xform);
++            cmsSignalError(m->ContextID, cmsERROR_CORRUPTION_DETECTED, "Cannot create CLUT, revise your flags!");
++            return FALSE;
++        }
++
+         WriteCLUT(m, first, "<", ">\n", "", "", lFixWhite, ColorSpace);
+     }
+ 
+@@ -1389,7 +1409,7 @@ int WriteOutputLUT(cmsIOHANDLER* m, cmsHPROFILE hProfile, cmsUInt32Number Intent
+     cmsPipelineFree(DeviceLink);
+     cmsDeleteTransform(xform);
+ 
+-    return 1;
++    return TRUE;
+ }
+ 
+ 
+diff --git a/src/java.desktop/share/native/liblcms/cmssamp.c b/src/java.desktop/share/native/liblcms/cmssamp.c
+index 74f5f4bff..ca5c4a9d6 100644
+--- a/src/java.desktop/share/native/liblcms/cmssamp.c
++++ b/src/java.desktop/share/native/liblcms/cmssamp.c
+@@ -30,7 +30,7 @@
+ //---------------------------------------------------------------------------------
+ //
+ //  Little Color Management System
+-//  Copyright (c) 1998-2023 Marti Maria Saguer
++//  Copyright (c) 1998-2024 Marti Maria Saguer
+ //
+ // Permission is hereby granted, free of charge, to any person obtaining
+ // a copy of this software and associated documentation files (the "Software"),
+diff --git a/src/java.desktop/share/native/liblcms/cmssm.c b/src/java.desktop/share/native/liblcms/cmssm.c
+index 3e1486ae3..e2a810a26 100644
+--- a/src/java.desktop/share/native/liblcms/cmssm.c
++++ b/src/java.desktop/share/native/liblcms/cmssm.c
+@@ -30,7 +30,7 @@
+ //---------------------------------------------------------------------------------
+ //
+ //  Little Color Management System
+-//  Copyright (c) 1998-2023 Marti Maria Saguer
++//  Copyright (c) 1998-2024 Marti Maria Saguer
+ //
+ // Permission is hereby granted, free of charge, to any person obtaining
+ // a copy of this software and associated documentation files (the "Software"),
+diff --git a/src/java.desktop/share/native/liblcms/cmstypes.c b/src/java.desktop/share/native/liblcms/cmstypes.c
+index 862f39349..22514f882 100644
+--- a/src/java.desktop/share/native/liblcms/cmstypes.c
++++ b/src/java.desktop/share/native/liblcms/cmstypes.c
+@@ -30,7 +30,7 @@
+ //---------------------------------------------------------------------------------
+ //
+ //  Little Color Management System
+-//  Copyright (c) 1998-2023 Marti Maria Saguer
++//  Copyright (c) 1998-2024 Marti Maria Saguer
+ //
+ // Permission is hereby granted, free of charge, to any person obtaining
+ // a copy of this software and associated documentation files (the "Software"),
+@@ -599,6 +599,178 @@ void Type_ColorantOrderType_Free(struct _cms_typehandler_struct* self, void* Ptr
+     _cmsFree(self ->ContextID, Ptr);
+ }
+ 
++// ********************************************************************************
++// Type cmsSigUInt8ArrayType
++// ********************************************************************************
++// This type represents an array of generic 1-byte/8-bit quantity.
++
++static
++void* Type_UInt8_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
++{
++    cmsUInt8Number* array;
++    cmsUInt32Number i, n;
++
++    *nItems = 0;
++    n = SizeOfTag / sizeof(cmsUInt8Number);
++    array = (cmsUInt8Number*)_cmsCalloc(self->ContextID, n, sizeof(cmsUInt8Number));
++    if (array == NULL) return NULL;
++
++    for (i = 0; i < n; i++) {
++
++        if (!_cmsReadUInt8Number(io, &array[i])) {
++
++            _cmsFree(self->ContextID, array);
++            return NULL;
++        }
++    }
++
++    *nItems = n;
++    return (void*)array;
++}
++
++static
++cmsBool Type_UInt8_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
++{
++    cmsUInt8Number* Value = (cmsUInt8Number*)Ptr;
++    cmsUInt32Number i;
++
++    for (i = 0; i < nItems; i++) {
++
++        if (!_cmsWriteUInt8Number(io, Value[i])) return FALSE;
++    }
++
++    return TRUE;
++
++    cmsUNUSED_PARAMETER(self);
++}
++
++static
++void* Type_UInt8_Dup(struct _cms_typehandler_struct* self, const void* Ptr, cmsUInt32Number n)
++{
++    return _cmsDupMem(self->ContextID, Ptr, n * sizeof(cmsUInt8Number));
++}
++
++
++static
++void Type_UInt8_Free(struct _cms_typehandler_struct* self, void* Ptr)
++{
++    _cmsFree(self->ContextID, Ptr);
++}
++
++// ********************************************************************************
++// Type cmsSigUInt32ArrayType
++// ********************************************************************************
++// This type represents an array of generic 4-byte/32-bit quantity.
++static
++void* Type_UInt32_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
++{
++    cmsUInt32Number* array;
++    cmsUInt32Number i, n;
++
++    *nItems = 0;
++    n = SizeOfTag / sizeof(cmsUInt32Number);
++    array = (cmsUInt32Number*)_cmsCalloc(self->ContextID, n, sizeof(cmsUInt32Number));
++    if (array == NULL) return NULL;
++
++    for (i = 0; i < n; i++) {
++
++        if (!_cmsReadUInt32Number(io, &array[i])) {
++
++            _cmsFree(self->ContextID, array);
++            return NULL;
++        }
++    }
++
++    *nItems = n;
++    return (void*)array;
++}
++
++static
++cmsBool Type_UInt32_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
++{
++    cmsUInt32Number* Value = (cmsUInt32Number*)Ptr;
++    cmsUInt32Number i;
++
++    for (i = 0; i < nItems; i++) {
++
++        if (!_cmsWriteUInt32Number(io, Value[i])) return FALSE;
++    }
++
++    return TRUE;
++
++    cmsUNUSED_PARAMETER(self);
++}
++
++static
++void* Type_UInt32_Dup(struct _cms_typehandler_struct* self, const void* Ptr, cmsUInt32Number n)
++{
++    return _cmsDupMem(self->ContextID, Ptr, n * sizeof(cmsUInt32Number));
++}
++
++
++static
++void Type_UInt32_Free(struct _cms_typehandler_struct* self, void* Ptr)
++{
++    _cmsFree(self->ContextID, Ptr);
++}
++
++// ********************************************************************************
++// Type cmsSigUInt64ArrayType
++// ********************************************************************************
++// This type represents an array of generic 8-byte/64-bit quantity.
++static
++void* Type_UInt64_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
++{
++    cmsUInt64Number* array;
++    cmsUInt32Number i, n;
++
++    *nItems = 0;
++    n = SizeOfTag / sizeof(cmsUInt64Number);
++    array = (cmsUInt64Number*)_cmsCalloc(self->ContextID, n, sizeof(cmsUInt64Number));
++    if (array == NULL) return NULL;
++
++    for (i = 0; i < n; i++) {
++
++        if (!_cmsReadUInt64Number(io, &array[i])) {
++
++            _cmsFree(self->ContextID, array);
++            return NULL;
++        }
++    }
++
++    *nItems = n;
++    return (void*)array;
++}
++
++static
++cmsBool Type_UInt64_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
++{
++    cmsUInt64Number* Value = (cmsUInt64Number*)Ptr;
++    cmsUInt32Number i;
++
++    for (i = 0; i < nItems; i++) {
++
++        if (!_cmsWriteUInt64Number(io, &Value[i])) return FALSE;
++    }
++
++    return TRUE;
++
++    cmsUNUSED_PARAMETER(self);
++}
++
++static
++void* Type_UInt64_Dup(struct _cms_typehandler_struct* self, const void* Ptr, cmsUInt32Number n)
++{
++    return _cmsDupMem(self->ContextID, Ptr, n * sizeof(cmsUInt64Number));
++}
++
++
++static
++void Type_UInt64_Free(struct _cms_typehandler_struct* self, void* Ptr)
++{
++    _cmsFree(self->ContextID, Ptr);
++}
++
+ // ********************************************************************************
+ // Type cmsSigS15Fixed16ArrayType
+ // ********************************************************************************
+@@ -968,6 +1140,8 @@ void *Type_Text_Description_Read(struct _cms_typehandler_struct* self, cmsIOHAND
+ 
+     // Read len of ASCII
+     if (!_cmsReadUInt32Number(io, &AsciiCount)) return NULL;
++    if (AsciiCount > 0x7ffff) return NULL;
++
+     SizeOfTag -= sizeof(cmsUInt32Number);
+ 
+     // Check for size
+@@ -999,7 +1173,8 @@ void *Type_Text_Description_Read(struct _cms_typehandler_struct* self, cmsIOHAND
+     if (!_cmsReadUInt32Number(io, &UnicodeCount)) goto Done;
+     SizeOfTag -= 2* sizeof(cmsUInt32Number);
+ 
+-    if (UnicodeCount == 0 || SizeOfTag < UnicodeCount*sizeof(cmsUInt16Number)) goto Done;
++    if (UnicodeCount == 0 || UnicodeCount > 0x7ffff ||
++        SizeOfTag < UnicodeCount*sizeof(cmsUInt16Number)) goto Done;
+ 
+     UnicodeString = (wchar_t*)_cmsMallocZero(self->ContextID, (UnicodeCount + 1) * sizeof(wchar_t));
+     if (UnicodeString == NULL) goto Done;
+@@ -1129,7 +1304,7 @@ cmsBool  Type_Text_Description_Write(struct _cms_typehandler_struct* self, cmsIO
+     if (!io ->Write(io, 67, Filler)) goto Error;
+ 
+     // possibly add pad at the end of tag
+-    if(len_aligned - len_tag_requirement > 0)
++    if (len_aligned > len_tag_requirement)
+       if (!io ->Write(io, len_aligned - len_tag_requirement, Filler)) goto Error;
+ 
+     rc = TRUE;
+@@ -5191,7 +5366,7 @@ cmsBool ReadOneWChar(cmsIOHANDLER* io,  _cmsDICelem* e, cmsUInt32Number i, wchar
+       if (!io -> Seek(io, e -> Offsets[i])) return FALSE;
+ 
+       nChars = e ->Sizes[i] / sizeof(cmsUInt16Number);
+-
++      if (nChars > 0x7ffff) return FALSE;
+ 
+       *wcstr = (wchar_t*) _cmsMallocZero(e ->ContextID, (nChars + 1) * sizeof(wchar_t));
+       if (*wcstr == NULL) return FALSE;
+@@ -5772,7 +5947,10 @@ static const _cmsTagTypeLinkedList SupportedTagTypes[] = {
+ {TYPE_HANDLER(cmsSigDictType,                  Dictionary),         (_cmsTagTypeLinkedList*) &SupportedTagTypes[30] },
+ {TYPE_HANDLER(cmsSigcicpType,                  VideoSignal),        (_cmsTagTypeLinkedList*) &SupportedTagTypes[31] },
+ {TYPE_HANDLER(cmsSigVcgtType,                  vcgt),               (_cmsTagTypeLinkedList*) &SupportedTagTypes[32] },
+-{TYPE_HANDLER(cmsSigMHC2Type,                  MHC2),                NULL }
++{TYPE_HANDLER(cmsSigMHC2Type,                  MHC2),               (_cmsTagTypeLinkedList*) &SupportedTagTypes[33] },
++{TYPE_HANDLER(cmsSigUInt8ArrayType,            UInt8),              (_cmsTagTypeLinkedList*) &SupportedTagTypes[34] },
++{TYPE_HANDLER(cmsSigUInt32ArrayType,           UInt32),             (_cmsTagTypeLinkedList*) &SupportedTagTypes[35] },
++{TYPE_HANDLER(cmsSigUInt64ArrayType,           UInt64),             NULL }
+ };
+ 
+ 
+diff --git a/src/java.desktop/share/native/liblcms/cmsvirt.c b/src/java.desktop/share/native/liblcms/cmsvirt.c
+index e8d18d4ca..1ef86dae0 100644
+--- a/src/java.desktop/share/native/liblcms/cmsvirt.c
++++ b/src/java.desktop/share/native/liblcms/cmsvirt.c
+@@ -30,7 +30,7 @@
+ //---------------------------------------------------------------------------------
+ //
+ //  Little Color Management System
+-//  Copyright (c) 1998-2023 Marti Maria Saguer
++//  Copyright (c) 1998-2024 Marti Maria Saguer
+ //
+ // Permission is hereby granted, free of charge, to any person obtaining
+ // a copy of this software and associated documentation files (the "Software"),
+@@ -412,7 +412,7 @@ int InkLimitingSampler(CMSREGISTER const cmsUInt16Number In[], CMSREGISTER cmsUI
+     Out[1] = _cmsQuickSaturateWord(In[1] * Ratio);     // M
+     Out[2] = _cmsQuickSaturateWord(In[2] * Ratio);     // Y
+ 
+-    Out[3] = In[3];                                 // K (untouched)
++    Out[3] = In[3];                                    // K (untouched)
+ 
+     return TRUE;
+ }
+@@ -433,7 +433,7 @@ cmsHPROFILE CMSEXPORT cmsCreateInkLimitingDeviceLinkTHR(cmsContext ContextID,
+         return NULL;
+     }
+ 
+-    if (Limit < 0.0 || Limit > 400) {
++    if (Limit < 1.0 || Limit > 400) {
+ 
+         cmsSignalError(ContextID, cmsERROR_RANGE, "InkLimiting: Limit should be between 1..400");
+         if (Limit < 1) Limit = 1;
+@@ -705,7 +705,7 @@ cmsHPROFILE CMSEXPORT cmsCreate_sRGBProfile(void)
+ *
+ * This virtual profile cannot be saved as an ICC file
+ */
+-cmsHPROFILE cmsCreate_OkLabProfile(cmsContext ctx)
++cmsHPROFILE CMSEXPORT cmsCreate_OkLabProfile(cmsContext ctx)
+ {
+     cmsStage* XYZPCS = _cmsStageNormalizeFromXyzFloat(ctx);
+     cmsStage* PCSXYZ = _cmsStageNormalizeToXyzFloat(ctx);
+@@ -774,6 +774,8 @@ cmsHPROFILE cmsCreate_OkLabProfile(cmsContext ctx)
+     cmsPipeline* BToA = cmsPipelineAlloc(ctx, 3, 3);
+ 
+     cmsHPROFILE hProfile = cmsCreateProfilePlaceholder(ctx);
++    if (!hProfile)            // can't allocate
++        goto error;
+ 
+     cmsSetProfileVersion(hProfile, 4.4);
+ 
+diff --git a/src/java.desktop/share/native/liblcms/cmswtpnt.c b/src/java.desktop/share/native/liblcms/cmswtpnt.c
+index 27d718035..ebba2cd6a 100644
+--- a/src/java.desktop/share/native/liblcms/cmswtpnt.c
++++ b/src/java.desktop/share/native/liblcms/cmswtpnt.c
+@@ -30,7 +30,7 @@
+ //---------------------------------------------------------------------------------
+ //
+ //  Little Color Management System
+-//  Copyright (c) 1998-2023 Marti Maria Saguer
++//  Copyright (c) 1998-2024 Marti Maria Saguer
+ //
+ // Permission is hereby granted, free of charge, to any person obtaining
+ // a copy of this software and associated documentation files (the "Software"),
+diff --git a/src/java.desktop/share/native/liblcms/cmsxform.c b/src/java.desktop/share/native/liblcms/cmsxform.c
+index 86afd7202..1eb3eecbf 100644
+--- a/src/java.desktop/share/native/liblcms/cmsxform.c
++++ b/src/java.desktop/share/native/liblcms/cmsxform.c
+@@ -30,7 +30,7 @@
+ //---------------------------------------------------------------------------------
+ //
+ //  Little Color Management System
+-//  Copyright (c) 1998-2023 Marti Maria Saguer
++//  Copyright (c) 1998-2024 Marti Maria Saguer
+ //
+ // Permission is hereby granted, free of charge, to any person obtaining
+ // a copy of this software and associated documentation files (the "Software"),
+@@ -295,7 +295,7 @@ void FloatXFORM(_cmsTRANSFORM* p,
+     cmsUInt8Number* output;
+     cmsFloat32Number fIn[cmsMAXCHANNELS], fOut[cmsMAXCHANNELS];
+     cmsFloat32Number OutOfGamut;
+-    cmsUInt32Number i, j, c, strideIn, strideOut;
++    size_t i, j, c, strideIn, strideOut;
+ 
+     _cmsHandleExtraChannels(p, in, out, PixelsPerLine, LineCount, Stride);
+ 
+@@ -322,9 +322,11 @@ void FloatXFORM(_cmsTRANSFORM* p,
+                 // Is current color out of gamut?
+                 if (OutOfGamut > 0.0) {
+ 
++                    _cmsAlarmCodesChunkType* ContextAlarmCodes = (_cmsAlarmCodesChunkType*)_cmsContextGetClientChunk(p->ContextID, AlarmCodesContext);
++
+                     // Certainly, out of gamut
+                     for (c = 0; c < cmsMAXCHANNELS; c++)
+-                        fOut[c] = -1.0;
++                        fOut[c] = ContextAlarmCodes->AlarmCodes[c] / 65535.0F;
+ 
+                 }
+                 else {
+@@ -361,7 +363,7 @@ void NullFloatXFORM(_cmsTRANSFORM* p,
+     cmsUInt8Number* accum;
+     cmsUInt8Number* output;
+     cmsFloat32Number fIn[cmsMAXCHANNELS];
+-    cmsUInt32Number i, j, strideIn, strideOut;
++    size_t i, j, strideIn, strideOut;
+ 
+     _cmsHandleExtraChannels(p, in, out, PixelsPerLine, LineCount, Stride);
+ 
+@@ -399,7 +401,7 @@ void NullXFORM(_cmsTRANSFORM* p,
+     cmsUInt8Number* accum;
+     cmsUInt8Number* output;
+     cmsUInt16Number wIn[cmsMAXCHANNELS];
+-    cmsUInt32Number i, j, strideIn, strideOut;
++    size_t i, j, strideIn, strideOut;
+ 
+     _cmsHandleExtraChannels(p, in, out, PixelsPerLine, LineCount, Stride);
+ 
+@@ -409,17 +411,17 @@ void NullXFORM(_cmsTRANSFORM* p,
+ 
+     for (i = 0; i < LineCount; i++) {
+ 
+-           accum = (cmsUInt8Number*)in + strideIn;
+-           output = (cmsUInt8Number*)out + strideOut;
++        accum = (cmsUInt8Number*)in + strideIn;
++        output = (cmsUInt8Number*)out + strideOut;
+ 
+-           for (j = 0; j < PixelsPerLine; j++) {
++        for (j = 0; j < PixelsPerLine; j++) {
+ 
+-                  accum = p->FromInput(p, wIn, accum, Stride->BytesPerPlaneIn);
+-                  output = p->ToOutput(p, wIn, output, Stride->BytesPerPlaneOut);
+-    }
++            accum = p->FromInput(p, wIn, accum, Stride->BytesPerPlaneIn);
++            output = p->ToOutput(p, wIn, output, Stride->BytesPerPlaneOut);
++        }
+ 
+-           strideIn += Stride->BytesPerLineIn;
+-           strideOut += Stride->BytesPerLineOut;
++        strideIn += Stride->BytesPerLineIn;
++        strideOut += Stride->BytesPerLineOut;
+     }
+ 
+ }
+@@ -437,7 +439,7 @@ void PrecalculatedXFORM(_cmsTRANSFORM* p,
+     CMSREGISTER cmsUInt8Number* accum;
+     CMSREGISTER cmsUInt8Number* output;
+     cmsUInt16Number wIn[cmsMAXCHANNELS], wOut[cmsMAXCHANNELS];
+-    cmsUInt32Number i, j, strideIn, strideOut;
++    size_t i, j, strideIn, strideOut;
+ 
+     _cmsHandleExtraChannels(p, in, out, PixelsPerLine, LineCount, Stride);
+ 
+@@ -500,7 +502,7 @@ void PrecalculatedXFORMGamutCheck(_cmsTRANSFORM* p,
+     cmsUInt8Number* accum;
+     cmsUInt8Number* output;
+     cmsUInt16Number wIn[cmsMAXCHANNELS], wOut[cmsMAXCHANNELS];
+-    cmsUInt32Number i, j, strideIn, strideOut;
++    size_t i, j, strideIn, strideOut;
+ 
+     _cmsHandleExtraChannels(p, in, out, PixelsPerLine, LineCount, Stride);
+ 
+@@ -511,18 +513,18 @@ void PrecalculatedXFORMGamutCheck(_cmsTRANSFORM* p,
+ 
+     for (i = 0; i < LineCount; i++) {
+ 
+-           accum = (cmsUInt8Number*)in + strideIn;
+-           output = (cmsUInt8Number*)out + strideOut;
++        accum = (cmsUInt8Number*)in + strideIn;
++        output = (cmsUInt8Number*)out + strideOut;
+ 
+-           for (j = 0; j < PixelsPerLine; j++) {
++        for (j = 0; j < PixelsPerLine; j++) {
+ 
+-                  accum = p->FromInput(p, wIn, accum, Stride->BytesPerPlaneIn);
+-                  TransformOnePixelWithGamutCheck(p, wIn, wOut);
+-                  output = p->ToOutput(p, wOut, output, Stride->BytesPerPlaneOut);
+-           }
++            accum = p->FromInput(p, wIn, accum, Stride->BytesPerPlaneIn);
++            TransformOnePixelWithGamutCheck(p, wIn, wOut);
++            output = p->ToOutput(p, wOut, output, Stride->BytesPerPlaneOut);
++        }
+ 
+-           strideIn += Stride->BytesPerLineIn;
+-           strideOut += Stride->BytesPerLineOut;
++        strideIn += Stride->BytesPerLineIn;
++        strideOut += Stride->BytesPerLineOut;
+     }
+ }
+ 
+@@ -540,7 +542,7 @@ void CachedXFORM(_cmsTRANSFORM* p,
+     cmsUInt8Number* output;
+     cmsUInt16Number wIn[cmsMAXCHANNELS], wOut[cmsMAXCHANNELS];
+     _cmsCACHE Cache;
+-    cmsUInt32Number i, j, strideIn, strideOut;
++    size_t i, j, strideIn, strideOut;
+ 
+     _cmsHandleExtraChannels(p, in, out, PixelsPerLine, LineCount, Stride);
+ 
+@@ -595,7 +597,7 @@ void CachedXFORMGamutCheck(_cmsTRANSFORM* p,
+     cmsUInt8Number* output;
+     cmsUInt16Number wIn[cmsMAXCHANNELS], wOut[cmsMAXCHANNELS];
+     _cmsCACHE Cache;
+-    cmsUInt32Number i, j, strideIn, strideOut;
++    size_t i, j, strideIn, strideOut;
+ 
+     _cmsHandleExtraChannels(p, in, out, PixelsPerLine, LineCount, Stride);
+ 
+@@ -712,7 +714,7 @@ void _cmsTransform2toTransformAdaptor(struct _cmstransform_struct *CMMcargo,
+                                       const cmsStride* Stride)
+ {
+ 
+-       cmsUInt32Number i, strideIn, strideOut;
++       size_t i, strideIn, strideOut;
+ 
+        _cmsHandleExtraChannels(CMMcargo, InputBuffer, OutputBuffer, PixelsPerLine, LineCount, Stride);
+ 
+@@ -1099,7 +1101,7 @@ cmsBool  IsProperColorSpace(cmsColorSpaceSignature Check, cmsUInt32Number dwForm
+     int Space1 = (int) T_COLORSPACE(dwFormat);
+     int Space2 = _cmsLCMScolorSpace(Check);
+ 
+-    if (Space1 == PT_ANY) return TRUE;
++    if (Space1 == PT_ANY) return (T_CHANNELS(dwFormat) == cmsChannelsOf(Check));
+     if (Space1 == Space2) return TRUE;
+ 
+     if (Space1 == PT_LabV2 && Space2 == PT_Lab) return TRUE;
+@@ -1160,7 +1162,15 @@ cmsHTRANSFORM CMSEXPORT cmsCreateExtendedTransform(cmsContext ContextID,
+     cmsColorSpaceSignature EntryColorSpace;
+     cmsColorSpaceSignature ExitColorSpace;
+     cmsPipeline* Lut;
+-    cmsUInt32Number LastIntent = Intents[nProfiles-1];
++    cmsUInt32Number LastIntent;
++
++    // Safeguard
++    if (nProfiles <= 0 || nProfiles > 255) {
++        cmsSignalError(ContextID, cmsERROR_RANGE, "Wrong number of profiles. 1..255 expected, %d found.", nProfiles);
++        return NULL;
++    }
++
++    LastIntent = Intents[nProfiles - 1];
+ 
+     // If it is a fake transform
+     if (dwFlags & cmsFLAGS_NULLTRANSFORM)
+diff --git a/src/java.desktop/share/native/liblcms/lcms2.h b/src/java.desktop/share/native/liblcms/lcms2.h
+index 2d9a8b124..5ba096613 100644
+--- a/src/java.desktop/share/native/liblcms/lcms2.h
++++ b/src/java.desktop/share/native/liblcms/lcms2.h
+@@ -30,7 +30,7 @@
+ //---------------------------------------------------------------------------------
+ //
+ //  Little Color Management System
+-//  Copyright (c) 1998-2023 Marti Maria Saguer
++//  Copyright (c) 1998-2025 Marti Maria Saguer
+ //
+ // Permission is hereby granted, free of charge, to any person obtaining
+ // a copy of this software and associated documentation files (the "Software"),
+@@ -52,7 +52,7 @@
+ //
+ //---------------------------------------------------------------------------------
+ //
+-// Version 2.16
++// Version 2.17
+ //
+ 
+ #ifndef _lcms2_H
+@@ -93,6 +93,9 @@
+ // Uncomment this to remove the "register" storage class
+ // #define CMS_NO_REGISTER_KEYWORD 1
+ 
++// Uncomment this to remove visibility attribute when building shared objects
++// #define CMS_NO_VISIBILITY 1
++
+ // ********** End of configuration toggles ******************************
+ 
+ // Needed for streams
+@@ -113,7 +116,7 @@ extern "C" {
+ #endif
+ 
+ // Version/release
+-#define LCMS_VERSION        2160
++#define LCMS_VERSION        2170
+ 
+ // I will give the chance of redefining basic types for compilers that are not fully C99 compliant
+ #ifndef CMS_BASIC_TYPES_ALREADY_DEFINED
+@@ -277,7 +280,7 @@ typedef int                  cmsBool;
+ #     define CMSAPI
+ #  endif
+ #else  // not Windows
+-#  ifdef HAVE_FUNC_ATTRIBUTE_VISIBILITY
++#  if defined(HAVE_FUNC_ATTRIBUTE_VISIBILITY) && !defined(CMS_NO_VISIBILITY)
+ #     define CMSEXPORT
+ #     define CMSAPI    __attribute__((visibility("default")))
+ #  else
+@@ -987,7 +990,6 @@ typedef void* cmsHTRANSFORM;
+ // IEEE 754-2008 "half"
+ #define TYPE_GRAY_HALF_FLT    (FLOAT_SH(1)|COLORSPACE_SH(PT_GRAY)|CHANNELS_SH(1)|BYTES_SH(2))
+ #define TYPE_RGB_HALF_FLT     (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(2))
+-#define TYPE_RGBA_HALF_FLT    (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(2))
+ #define TYPE_CMYK_HALF_FLT    (FLOAT_SH(1)|COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(2))
+ 
+ #define TYPE_RGBA_HALF_FLT    (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(2))
+diff --git a/src/java.desktop/share/native/liblcms/lcms2_internal.h b/src/java.desktop/share/native/liblcms/lcms2_internal.h
+index 75973edad..d14c0dd82 100644
+--- a/src/java.desktop/share/native/liblcms/lcms2_internal.h
++++ b/src/java.desktop/share/native/liblcms/lcms2_internal.h
+@@ -27,9 +27,10 @@
+ // However, the following notice accompanied the original version of this
+ // file:
+ //
++
+ //
+ //  Little Color Management System
+-//  Copyright (c) 1998-2023 Marti Maria Saguer
++//  Copyright (c) 1998-2024 Marti Maria Saguer
+ //
+ // Permission is hereby granted, free of charge, to any person obtaining
+ // a copy of this software and associated documentation files (the "Software"),
+@@ -467,7 +468,7 @@ cmsBool  _cmsRegisterTransformPlugin(cmsContext ContextID, cmsPluginBase* Plugin
+ // Mutex
+ cmsBool _cmsRegisterMutexPlugin(cmsContext ContextID, cmsPluginBase* Plugin);
+ 
+-// Paralellization
++// Parallelization
+ cmsBool _cmsRegisterParallelizationPlugin(cmsContext ContextID, cmsPluginBase* Plugin);
+ 
+ // ---------------------------------------------------------------------------------------------------------
+@@ -1000,7 +1001,7 @@ cmsBool           _cmsReadCHAD(cmsMAT3* Dest, cmsHPROFILE hProfile);
+ 
+ // Link several profiles to obtain a single LUT modelling the whole color transform. Intents, Black point
+ // compensation and Adaptation parameters may vary across profiles. BPC and Adaptation refers to the PCS
+-// after the profile. I.e, BPC[0] refers to connexion between profile(0) and profile(1)
++// after the profile. I.e, BPC[0] refers to connetion between profile(0) and profile(1)
+ cmsPipeline* _cmsLinkProfiles(cmsContext         ContextID,
+                               cmsUInt32Number    nProfiles,
+                               cmsUInt32Number    TheIntents[],
+diff --git a/src/java.desktop/share/native/liblcms/lcms2_plugin.h b/src/java.desktop/share/native/liblcms/lcms2_plugin.h
+index e7e7bd1f0..bdfc76f6b 100644
+--- a/src/java.desktop/share/native/liblcms/lcms2_plugin.h
++++ b/src/java.desktop/share/native/liblcms/lcms2_plugin.h
+@@ -30,7 +30,7 @@
+ //---------------------------------------------------------------------------------
+ //
+ //  Little Color Management System
+-//  Copyright (c) 1998-2023 Marti Maria Saguer
++//  Copyright (c) 1998-2024 Marti Maria Saguer
+ //
+ // Permission is hereby granted, free of charge, to any person obtaining
+ // a copy of this software and associated documentation files (the "Software"),
+diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/CHANGES b/src/java.desktop/share/native/libsplashscreen/libpng/CHANGES
+index 441b57ecf..834b5e192 100644
+--- a/src/java.desktop/share/native/libsplashscreen/libpng/CHANGES
++++ b/src/java.desktop/share/native/libsplashscreen/libpng/CHANGES
+@@ -6196,6 +6196,61 @@ Version 1.6.43 [February 23, 2024]
+     consistency verification and text linting.
+   Added version consistency verification to pngtest.c also.
+ 
++Version 1.6.44 [September 12, 2024]
++  Hardened calculations in chroma handling to prevent overflows, and
++    relaxed a constraint in cHRM validation to accomodate the standard
++    ACES AP1 set of color primaries.
++    (Contributed by John Bowler)
++  Removed the ASM implementation of ARM Neon optimizations and updated
++    the build accordingly. Only the remaining C implementation shall be
++    used from now on, thus ensuring the support of the PAC/BTI security
++    features on ARM64.
++    (Contributed by Ross Burton and John Bowler)
++  Fixed the pickup of the PNG_HARDWARE_OPTIMIZATIONS option in the
++    CMake build on FreeBSD/amd64. This is an important performance fix
++    on this platform.
++  Applied various fixes and improvements to the CMake build.
++    (Contributed by Eric Riff, Benjamin Buch and Erik Scholz)
++  Added fuzzing targets for the simplified read API.
++    (Contributed by Mikhail Khachayants)
++  Fixed a build error involving pngtest.c under a custom config.
++    This was a regression introduced in a code cleanup in libpng-1.6.43.
++    (Contributed by Ben Wagner)
++  Fixed and improved the config files for AppVeyor CI and Travis CI.
++
++Version 1.6.45 [January 7, 2025]
++  Added support for the cICP chunk.
++    (Contributed by Lucas Chollet and John Bowler)
++  Adjusted and improved various checks in colorspace calculations.
++    (Contributed by John Bowler)
++  Rearranged the write order of colorspace chunks for better conformance
++    with the PNG v3 draft specification.
++    (Contributed by John Bowler)
++  Raised the minimum required CMake version from 3.6 to 3.14.
++  Forked off a development branch for libpng version 1.8.
++
++Version 1.6.46 [January 23, 2025]
++  Added support for the mDCV and cLLI chunks.
++    (Contributed by John Bowler)
++  Fixed a build issue affecting C89 compilers.
++    This was a regression introduced in libpng-1.6.45.
++    (Contributed by John Bowler)
++  Added makefile.c89, specifically for testing C89 compilers.
++  Cleaned up contrib/pngminus: corrected an old typo, removed an old
++    workaround, and updated the CMake file.
++
++Version 1.6.47 [February 18, 2025]
++  Modified the behaviour of colorspace chunks in order to adhere
++    to the new precedence rules formulated in the latest draft of
++    the PNG Specification.
++    (Contributed by John Bowler)
++  Fixed a latent bug in `png_write_iCCP`.
++    This would have been a read-beyond-end-of-malloc vulnerability,
++    introduced early in the libpng-1.6.0 development, yet (fortunately!)
++    it was inaccessible before the above-mentioned modification of the
++    colorspace precedence rules, due to pre-existing colorspace checks.
++    (Reported by Bob Friesenhahn; fixed by John Bowler)
++
+ Send comments/corrections/commendations to png-mng-implement at lists.sf.net.
+ Subscription is required; visit
+ https://lists.sourceforge.net/lists/listinfo/png-mng-implement
+diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/LICENSE b/src/java.desktop/share/native/libsplashscreen/libpng/LICENSE
+index 25f298f0f..ea6df986c 100644
+--- a/src/java.desktop/share/native/libsplashscreen/libpng/LICENSE
++++ b/src/java.desktop/share/native/libsplashscreen/libpng/LICENSE
+@@ -4,8 +4,8 @@ COPYRIGHT NOTICE, DISCLAIMER, and LICENSE
+ PNG Reference Library License version 2
+ ---------------------------------------
+ 
+- * Copyright (c) 1995-2024 The PNG Reference Library Authors.
+- * Copyright (c) 2018-2024 Cosmin Truta.
++ * Copyright (c) 1995-2025 The PNG Reference Library Authors.
++ * Copyright (c) 2018-2025 Cosmin Truta.
+  * Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson.
+  * Copyright (c) 1996-1997 Andreas Dilger.
+  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
+diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/README b/src/java.desktop/share/native/libsplashscreen/libpng/README
+index a6ca3ae9f..57952fb21 100644
+--- a/src/java.desktop/share/native/libsplashscreen/libpng/README
++++ b/src/java.desktop/share/native/libsplashscreen/libpng/README
+@@ -1,4 +1,4 @@
+-README for libpng version 1.6.43
++README for libpng version 1.6.47
+ ================================
+ 
+ See the note about version numbers near the top of `png.h`.
+@@ -157,8 +157,6 @@ Files included in this distribution
+                           "PNG: The Definitive Guide" by Greg Roelofs,
+                           O'Reilly, 1999
+         libtests/     =>  Test programs
+-        oss-fuzz/     =>  Files used by the OSS-Fuzz project for fuzz-testing
+-                          libpng
+         pngexif/      =>  Program to inspect the EXIF information in PNG files
+         pngminim/     =>  Minimal decoder, encoder, and progressive decoder
+                           programs demonstrating the use of pngusr.dfa
+diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/png.c b/src/java.desktop/share/native/libsplashscreen/libpng/png.c
+index 232dff876..7b6de2f8e 100644
+--- a/src/java.desktop/share/native/libsplashscreen/libpng/png.c
++++ b/src/java.desktop/share/native/libsplashscreen/libpng/png.c
+@@ -29,7 +29,7 @@
+  * However, the following notice accompanied the original version of this
+  * file and, per its terms, should not be removed:
+  *
+- * Copyright (c) 2018-2024 Cosmin Truta
++ * Copyright (c) 2018-2025 Cosmin Truta
+  * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
+  * Copyright (c) 1996-1997 Andreas Dilger
+  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
+@@ -42,7 +42,34 @@
+ #include "pngpriv.h"
+ 
+ /* Generate a compiler error if there is an old png.h in the search path. */
+-typedef png_libpng_version_1_6_43 Your_png_h_is_not_version_1_6_43;
++typedef png_libpng_version_1_6_47 Your_png_h_is_not_version_1_6_47;
++
++/* Sanity check the chunks definitions - PNG_KNOWN_CHUNKS from pngpriv.h and the
++ * corresponding macro definitions.  This causes a compile time failure if
++ * something is wrong but generates no code.
++ *
++ * (1) The first check is that the PNG_CHUNK(cHNK, index) 'index' values must
++ * increment from 0 to the last value.
++ */
++#define PNG_CHUNK(cHNK, index) != (index) || ((index)+1)
++
++#if 0 PNG_KNOWN_CHUNKS < 0
++#  error PNG_KNOWN_CHUNKS chunk definitions are not in order
++#endif
++
++#undef PNG_CHUNK
++
++/* (2) The chunk name macros, png_cHNK, must all be valid and defined.  Since
++ * this is a preprocessor test undefined pp-tokens come out as zero and will
++ * fail this test.
++ */
++#define PNG_CHUNK(cHNK, index) !PNG_CHUNK_NAME_VALID(png_ ## cHNK) ||
++
++#if PNG_KNOWN_CHUNKS 0
++#  error png_cHNK not defined for some known cHNK
++#endif
++
++#undef PNG_CHUNK
+ 
+ /* Tells libpng that we have already handled the first "num_bytes" bytes
+  * of the PNG file signature.  If the PNG data is embedded into another
+@@ -270,21 +297,23 @@ png_create_png_struct,(png_const_charp user_png_ver, png_voidp error_ptr,
+     */
+    memset(&create_struct, 0, (sizeof create_struct));
+ 
+-   /* Added at libpng-1.2.6 */
+ #  ifdef PNG_USER_LIMITS_SUPPORTED
+       create_struct.user_width_max = PNG_USER_WIDTH_MAX;
+       create_struct.user_height_max = PNG_USER_HEIGHT_MAX;
+ 
+ #     ifdef PNG_USER_CHUNK_CACHE_MAX
+-      /* Added at libpng-1.2.43 and 1.4.0 */
+       create_struct.user_chunk_cache_max = PNG_USER_CHUNK_CACHE_MAX;
+ #     endif
+ 
+-#     ifdef PNG_USER_CHUNK_MALLOC_MAX
+-      /* Added at libpng-1.2.43 and 1.4.1, required only for read but exists
+-       * in png_struct regardless.
+-       */
++#     if PNG_USER_CHUNK_MALLOC_MAX > 0 /* default to compile-time limit */
+       create_struct.user_chunk_malloc_max = PNG_USER_CHUNK_MALLOC_MAX;
++
++      /* No compile-time limit, so initialize to the system limit: */
++#     elif defined PNG_MAX_MALLOC_64K /* legacy system limit */
++      create_struct.user_chunk_malloc_max = 65536U;
++
++#     else /* modern system limit SIZE_MAX (C99) */
++      create_struct.user_chunk_malloc_max = PNG_SIZE_MAX;
+ #     endif
+ #  endif
+ 
+@@ -626,13 +655,6 @@ png_free_data(png_const_structrp png_ptr, png_inforp info_ptr, png_uint_32 mask,
+    /* Free any eXIf entry */
+    if (((mask & PNG_FREE_EXIF) & info_ptr->free_me) != 0)
+    {
+-# ifdef PNG_READ_eXIf_SUPPORTED
+-      if (info_ptr->eXIf_buf)
+-      {
+-         png_free(png_ptr, info_ptr->eXIf_buf);
+-         info_ptr->eXIf_buf = NULL;
+-      }
+-# endif
+       if (info_ptr->exif)
+       {
+          png_free(png_ptr, info_ptr->exif);
+@@ -822,8 +844,8 @@ png_get_copyright(png_const_structrp png_ptr)
+    return PNG_STRING_COPYRIGHT
+ #else
+    return PNG_STRING_NEWLINE \
+-      "libpng version 1.6.43" PNG_STRING_NEWLINE \
+-      "Copyright (c) 2018-2024 Cosmin Truta" PNG_STRING_NEWLINE \
++      "libpng version 1.6.47" PNG_STRING_NEWLINE \
++      "Copyright (c) 2018-2025 Cosmin Truta" PNG_STRING_NEWLINE \
+       "Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson" \
+       PNG_STRING_NEWLINE \
+       "Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \
+@@ -1067,210 +1089,132 @@ png_zstream_error(png_structrp png_ptr, int ret)
+    }
+ }
+ 
+-/* png_convert_size: a PNGAPI but no longer in png.h, so deleted
+- * at libpng 1.5.5!
+- */
+-
+-/* Added at libpng version 1.2.34 and 1.4.0 (moved from pngset.c) */
+-#ifdef PNG_GAMMA_SUPPORTED /* always set if COLORSPACE */
+-static int
+-png_colorspace_check_gamma(png_const_structrp png_ptr,
+-    png_colorspacerp colorspace, png_fixed_point gAMA, int from)
+-   /* This is called to check a new gamma value against an existing one.  The
+-    * routine returns false if the new gamma value should not be written.
+-    *
+-    * 'from' says where the new gamma value comes from:
+-    *
+-    *    0: the new gamma value is the libpng estimate for an ICC profile
+-    *    1: the new gamma value comes from a gAMA chunk
+-    *    2: the new gamma value comes from an sRGB chunk
+-    */
++#ifdef PNG_COLORSPACE_SUPPORTED
++static png_int_32
++png_fp_add(png_int_32 addend0, png_int_32 addend1, int *error)
+ {
+-   png_fixed_point gtest;
+-
+-   if ((colorspace->flags & PNG_COLORSPACE_HAVE_GAMMA) != 0 &&
+-       (png_muldiv(>est, colorspace->gamma, PNG_FP_1, gAMA) == 0  ||
+-      png_gamma_significant(gtest) != 0))
++   /* Safely add two fixed point values setting an error flag and returning 0.5
++    * on overflow.
++    * IMPLEMENTATION NOTE: ANSI requires signed overflow not to occur, therefore
++    * relying on addition of two positive values producing a negative one is not
++    * safe.
++    */
++   if (addend0 > 0)
+    {
+-      /* Either this is an sRGB image, in which case the calculated gamma
+-       * approximation should match, or this is an image with a profile and the
+-       * value libpng calculates for the gamma of the profile does not match the
+-       * value recorded in the file.  The former, sRGB, case is an error, the
+-       * latter is just a warning.
+-       */
+-      if ((colorspace->flags & PNG_COLORSPACE_FROM_sRGB) != 0 || from == 2)
+-      {
+-         png_chunk_report(png_ptr, "gamma value does not match sRGB",
+-             PNG_CHUNK_ERROR);
+-         /* Do not overwrite an sRGB value */
+-         return from == 2;
+-      }
+-
+-      else /* sRGB tag not involved */
+-      {
+-         png_chunk_report(png_ptr, "gamma value does not match libpng estimate",
+-             PNG_CHUNK_WARNING);
+-         return from == 1;
+-      }
++      if (0x7fffffff - addend0 >= addend1)
++         return addend0+addend1;
+    }
+-
+-   return 1;
+-}
+-
+-void /* PRIVATE */
+-png_colorspace_set_gamma(png_const_structrp png_ptr,
+-    png_colorspacerp colorspace, png_fixed_point gAMA)
+-{
+-   /* Changed in libpng-1.5.4 to limit the values to ensure overflow can't
+-    * occur.  Since the fixed point representation is asymmetrical it is
+-    * possible for 1/gamma to overflow the limit of 21474 and this means the
+-    * gamma value must be at least 5/100000 and hence at most 20000.0.  For
+-    * safety the limits here are a little narrower.  The values are 0.00016 to
+-    * 6250.0, which are truly ridiculous gamma values (and will produce
+-    * displays that are all black or all white.)
+-    *
+-    * In 1.6.0 this test replaces the ones in pngrutil.c, in the gAMA chunk
+-    * handling code, which only required the value to be >0.
+-    */
+-   png_const_charp errmsg;
+-
+-   if (gAMA < 16 || gAMA > 625000000)
+-      errmsg = "gamma value out of range";
+-
+-#  ifdef PNG_READ_gAMA_SUPPORTED
+-   /* Allow the application to set the gamma value more than once */
+-   else if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 &&
+-      (colorspace->flags & PNG_COLORSPACE_FROM_gAMA) != 0)
+-      errmsg = "duplicate";
+-#  endif
+-
+-   /* Do nothing if the colorspace is already invalid */
+-   else if ((colorspace->flags & PNG_COLORSPACE_INVALID) != 0)
+-      return;
+-
+-   else
++   else if (addend0 < 0)
+    {
+-      if (png_colorspace_check_gamma(png_ptr, colorspace, gAMA,
+-          1/*from gAMA*/) != 0)
+-      {
+-         /* Store this gamma value. */
+-         colorspace->gamma = gAMA;
+-         colorspace->flags |=
+-            (PNG_COLORSPACE_HAVE_GAMMA | PNG_COLORSPACE_FROM_gAMA);
+-      }
+-
+-      /* At present if the check_gamma test fails the gamma of the colorspace is
+-       * not updated however the colorspace is not invalidated.  This
+-       * corresponds to the case where the existing gamma comes from an sRGB
+-       * chunk or profile.  An error message has already been output.
+-       */
+-      return;
++      if (-0x7fffffff - addend0 <= addend1)
++         return addend0+addend1;
+    }
++   else
++      return addend1;
+ 
+-   /* Error exit - errmsg has been set. */
+-   colorspace->flags |= PNG_COLORSPACE_INVALID;
+-   png_chunk_report(png_ptr, errmsg, PNG_CHUNK_WRITE_ERROR);
++   *error = 1;
++   return PNG_FP_1/2;
+ }
+ 
+-void /* PRIVATE */
+-png_colorspace_sync_info(png_const_structrp png_ptr, png_inforp info_ptr)
++static png_int_32
++png_fp_sub(png_int_32 addend0, png_int_32 addend1, int *error)
+ {
+-   if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) != 0)
++   /* As above but calculate addend0-addend1. */
++   if (addend1 > 0)
+    {
+-      /* Everything is invalid */
+-      info_ptr->valid &= ~(PNG_INFO_gAMA|PNG_INFO_cHRM|PNG_INFO_sRGB|
+-         PNG_INFO_iCCP);
+-
+-#     ifdef PNG_COLORSPACE_SUPPORTED
+-      /* Clean up the iCCP profile now if it won't be used. */
+-      png_free_data(png_ptr, info_ptr, PNG_FREE_ICCP, -1/*not used*/);
+-#     else
+-      PNG_UNUSED(png_ptr)
+-#     endif
++      if (-0x7fffffff + addend1 <= addend0)
++         return addend0-addend1;
+    }
+-
+-   else
++   else if (addend1 < 0)
+    {
+-#     ifdef PNG_COLORSPACE_SUPPORTED
+-      /* Leave the INFO_iCCP flag set if the pngset.c code has already set
+-       * it; this allows a PNG to contain a profile which matches sRGB and
+-       * yet still have that profile retrievable by the application.
+-       */
+-      if ((info_ptr->colorspace.flags & PNG_COLORSPACE_MATCHES_sRGB) != 0)
+-         info_ptr->valid |= PNG_INFO_sRGB;
+-
+-      else
+-         info_ptr->valid &= ~PNG_INFO_sRGB;
+-
+-      if ((info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
+-         info_ptr->valid |= PNG_INFO_cHRM;
+-
+-      else
+-         info_ptr->valid &= ~PNG_INFO_cHRM;
+-#     endif
+-
+-      if ((info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_GAMMA) != 0)
+-         info_ptr->valid |= PNG_INFO_gAMA;
+-
+-      else
+-         info_ptr->valid &= ~PNG_INFO_gAMA;
++      if (0x7fffffff + addend1 >= addend0)
++         return addend0-addend1;
+    }
++   else
++      return addend0;
++
++   *error = 1;
++   return PNG_FP_1/2;
+ }
+ 
+-#ifdef PNG_READ_SUPPORTED
+-void /* PRIVATE */
+-png_colorspace_sync(png_const_structrp png_ptr, png_inforp info_ptr)
++static int
++png_safe_add(png_int_32 *addend0_and_result, png_int_32 addend1,
++      png_int_32 addend2)
+ {
+-   if (info_ptr == NULL) /* reduce code size; check here not in the caller */
+-      return;
+-
+-   info_ptr->colorspace = png_ptr->colorspace;
+-   png_colorspace_sync_info(png_ptr, info_ptr);
++   /* Safely add three integers.  Returns 0 on success, 1 on overflow.  Does not
++    * set the result on overflow.
++    */
++   int error = 0;
++   int result = png_fp_add(*addend0_and_result,
++                           png_fp_add(addend1, addend2, &error),
++                           &error);
++   if (!error) *addend0_and_result = result;
++   return error;
+ }
+-#endif
+-#endif /* GAMMA */
+ 
+-#ifdef PNG_COLORSPACE_SUPPORTED
+ /* Added at libpng-1.5.5 to support read and write of true CIEXYZ values for
+  * cHRM, as opposed to using chromaticities.  These internal APIs return
+  * non-zero on a parameter error.  The X, Y and Z values are required to be
+  * positive and less than 1.0.
+  */
+-static int
++int /* PRIVATE */
+ png_xy_from_XYZ(png_xy *xy, const png_XYZ *XYZ)
+ {
+-   png_int_32 d, dwhite, whiteX, whiteY;
++   /* NOTE: returns 0 on success, 1 means error. */
++   png_int_32 d, dred, dgreen, dblue, dwhite, whiteX, whiteY;
+ 
+-   d = XYZ->red_X + XYZ->red_Y + XYZ->red_Z;
+-   if (png_muldiv(&xy->redx, XYZ->red_X, PNG_FP_1, d) == 0)
++   /* 'd' in each of the blocks below is just X+Y+Z for each component,
++    * x, y and z are X,Y,Z/(X+Y+Z).
++    */
++   d = XYZ->red_X;
++   if (png_safe_add(&d, XYZ->red_Y, XYZ->red_Z))
+       return 1;
+-   if (png_muldiv(&xy->redy, XYZ->red_Y, PNG_FP_1, d) == 0)
++   dred = d;
++   if (png_muldiv(&xy->redx, XYZ->red_X, PNG_FP_1, dred) == 0)
++      return 1;
++   if (png_muldiv(&xy->redy, XYZ->red_Y, PNG_FP_1, dred) == 0)
+       return 1;
+-   dwhite = d;
+-   whiteX = XYZ->red_X;
+-   whiteY = XYZ->red_Y;
+ 
+-   d = XYZ->green_X + XYZ->green_Y + XYZ->green_Z;
+-   if (png_muldiv(&xy->greenx, XYZ->green_X, PNG_FP_1, d) == 0)
++   d = XYZ->green_X;
++   if (png_safe_add(&d, XYZ->green_Y, XYZ->green_Z))
+       return 1;
+-   if (png_muldiv(&xy->greeny, XYZ->green_Y, PNG_FP_1, d) == 0)
++   dgreen = d;
++   if (png_muldiv(&xy->greenx, XYZ->green_X, PNG_FP_1, dgreen) == 0)
++      return 1;
++   if (png_muldiv(&xy->greeny, XYZ->green_Y, PNG_FP_1, dgreen) == 0)
+       return 1;
+-   dwhite += d;
+-   whiteX += XYZ->green_X;
+-   whiteY += XYZ->green_Y;
+ 
+-   d = XYZ->blue_X + XYZ->blue_Y + XYZ->blue_Z;
+-   if (png_muldiv(&xy->bluex, XYZ->blue_X, PNG_FP_1, d) == 0)
++   d = XYZ->blue_X;
++   if (png_safe_add(&d, XYZ->blue_Y, XYZ->blue_Z))
++      return 1;
++   dblue = d;
++   if (png_muldiv(&xy->bluex, XYZ->blue_X, PNG_FP_1, dblue) == 0)
+       return 1;
+-   if (png_muldiv(&xy->bluey, XYZ->blue_Y, PNG_FP_1, d) == 0)
++   if (png_muldiv(&xy->bluey, XYZ->blue_Y, PNG_FP_1, dblue) == 0)
+       return 1;
+-   dwhite += d;
+-   whiteX += XYZ->blue_X;
+-   whiteY += XYZ->blue_Y;
+ 
+-   /* The reference white is simply the sum of the end-point (X,Y,Z) vectors,
+-    * thus:
++   /* The reference white is simply the sum of the end-point (X,Y,Z) vectors so
++    * the fillowing calculates (X+Y+Z) of the reference white (media white,
++    * encoding white) itself:
+     */
++   d = dblue;
++   if (png_safe_add(&d, dred, dgreen))
++      return 1;
++   dwhite = d;
++
++   /* Find the white X,Y values from the sum of the red, green and blue X,Y
++    * values.
++    */
++   d = XYZ->red_X;
++   if (png_safe_add(&d, XYZ->green_X, XYZ->blue_X))
++      return 1;
++   whiteX = d;
++
++   d = XYZ->red_Y;
++   if (png_safe_add(&d, XYZ->green_Y, XYZ->blue_Y))
++      return 1;
++   whiteY = d;
++
+    if (png_muldiv(&xy->whitex, whiteX, PNG_FP_1, dwhite) == 0)
+       return 1;
+    if (png_muldiv(&xy->whitey, whiteY, PNG_FP_1, dwhite) == 0)
+@@ -1279,9 +1223,10 @@ png_xy_from_XYZ(png_xy *xy, const png_XYZ *XYZ)
+    return 0;
+ }
+ 
+-static int
++int /* PRIVATE */
+ png_XYZ_from_xy(png_XYZ *XYZ, const png_xy *xy)
+ {
++   /* NOTE: returns 0 on success, 1 means error. */
+    png_fixed_point red_inverse, green_inverse, blue_scale;
+    png_fixed_point left, right, denominator;
+ 
+@@ -1289,15 +1234,24 @@ png_XYZ_from_xy(png_XYZ *XYZ, const png_xy *xy)
+     * have end points with 0 tristimulus values (these are impossible end
+     * points, but they are used to cover the possible colors).  We check
+     * xy->whitey against 5, not 0, to avoid a possible integer overflow.
++    *
++    * The limits here will *not* accept ACES AP0, where bluey is -7700
++    * (-0.0770) because the PNG spec itself requires the xy values to be
++    * unsigned.  whitey is also required to be 5 or more to avoid overflow.
++    *
++    * Instead the upper limits have been relaxed to accomodate ACES AP1 where
++    * redz ends up as -600 (-0.006).  ProPhotoRGB was already "in range."
++    * The new limit accomodates the AP0 and AP1 ranges for z but not AP0 redy.
+     */
+-   if (xy->redx   < 0 || xy->redx > PNG_FP_1) return 1;
+-   if (xy->redy   < 0 || xy->redy > PNG_FP_1-xy->redx) return 1;
+-   if (xy->greenx < 0 || xy->greenx > PNG_FP_1) return 1;
+-   if (xy->greeny < 0 || xy->greeny > PNG_FP_1-xy->greenx) return 1;
+-   if (xy->bluex  < 0 || xy->bluex > PNG_FP_1) return 1;
+-   if (xy->bluey  < 0 || xy->bluey > PNG_FP_1-xy->bluex) return 1;
+-   if (xy->whitex < 0 || xy->whitex > PNG_FP_1) return 1;
+-   if (xy->whitey < 5 || xy->whitey > PNG_FP_1-xy->whitex) return 1;
++   const png_fixed_point fpLimit = PNG_FP_1+(PNG_FP_1/10);
++   if (xy->redx   < 0 || xy->redx > fpLimit) return 1;
++   if (xy->redy   < 0 || xy->redy > fpLimit-xy->redx) return 1;
++   if (xy->greenx < 0 || xy->greenx > fpLimit) return 1;
++   if (xy->greeny < 0 || xy->greeny > fpLimit-xy->greenx) return 1;
++   if (xy->bluex  < 0 || xy->bluex > fpLimit) return 1;
++   if (xy->bluey  < 0 || xy->bluey > fpLimit-xy->bluex) return 1;
++   if (xy->whitex < 0 || xy->whitex > fpLimit) return 1;
++   if (xy->whitey < 5 || xy->whitey > fpLimit-xy->whitex) return 1;
+ 
+    /* The reverse calculation is more difficult because the original tristimulus
+     * value had 9 independent values (red,green,blue)x(X,Y,Z) however only 8
+@@ -1442,18 +1396,23 @@ png_XYZ_from_xy(png_XYZ *XYZ, const png_xy *xy)
+     *  (green-x - blue-x)*(red-y - blue-y)-(green-y - blue-y)*(red-x - blue-x)
+     *
+     * Accuracy:
+-    * The input values have 5 decimal digits of accuracy.  The values are all in
+-    * the range 0 < value < 1, so simple products are in the same range but may
+-    * need up to 10 decimal digits to preserve the original precision and avoid
+-    * underflow.  Because we are using a 32-bit signed representation we cannot
+-    * match this; the best is a little over 9 decimal digits, less than 10.
++    * The input values have 5 decimal digits of accuracy.
++    *
++    * In the previous implementation the values were all in the range 0 < value
++    * < 1, so simple products are in the same range but may need up to 10
++    * decimal digits to preserve the original precision and avoid underflow.
++    * Because we are using a 32-bit signed representation we cannot match this;
++    * the best is a little over 9 decimal digits, less than 10.
++    *
++    * This range has now been extended to allow values up to 1.1, or 110,000 in
++    * fixed point.
+     *
+     * The approach used here is to preserve the maximum precision within the
+     * signed representation.  Because the red-scale calculation above uses the
+-    * difference between two products of values that must be in the range -1..+1
+-    * it is sufficient to divide the product by 7; ceil(100,000/32767*2).  The
+-    * factor is irrelevant in the calculation because it is applied to both
+-    * numerator and denominator.
++    * difference between two products of values that must be in the range
++    * -1.1..+1.1 it is sufficient to divide the product by 8;
++    * ceil(121,000/32767*2).  The factor is irrelevant in the calculation
++    * because it is applied to both numerator and denominator.
+     *
+     * Note that the values of the differences of the products of the
+     * chromaticities in the above equations tend to be small, for example for
+@@ -1475,49 +1434,64 @@ png_XYZ_from_xy(png_XYZ *XYZ, const png_xy *xy)
+     *  Adobe Wide Gamut RGB
+     *    0.258728243040113 0.724682314948566 0.016589442011321
+     */
+-   /* By the argument, above overflow should be impossible here. The return
+-    * value of 2 indicates an internal error to the caller.
+-    */
+-   if (png_muldiv(&left, xy->greenx-xy->bluex, xy->redy - xy->bluey, 7) == 0)
+-      return 2;
+-   if (png_muldiv(&right, xy->greeny-xy->bluey, xy->redx - xy->bluex, 7) == 0)
+-      return 2;
+-   denominator = left - right;
+-
+-   /* Now find the red numerator. */
+-   if (png_muldiv(&left, xy->greenx-xy->bluex, xy->whitey-xy->bluey, 7) == 0)
+-      return 2;
+-   if (png_muldiv(&right, xy->greeny-xy->bluey, xy->whitex-xy->bluex, 7) == 0)
+-      return 2;
+-
+-   /* Overflow is possible here and it indicates an extreme set of PNG cHRM
+-    * chunk values.  This calculation actually returns the reciprocal of the
+-    * scale value because this allows us to delay the multiplication of white-y
+-    * into the denominator, which tends to produce a small number.
+-    */
+-   if (png_muldiv(&red_inverse, xy->whitey, denominator, left-right) == 0 ||
+-       red_inverse <= xy->whitey /* r+g+b scales = white scale */)
+-      return 1;
++   {
++      int error = 0;
+ 
+-   /* Similarly for green_inverse: */
+-   if (png_muldiv(&left, xy->redy-xy->bluey, xy->whitex-xy->bluex, 7) == 0)
+-      return 2;
+-   if (png_muldiv(&right, xy->redx-xy->bluex, xy->whitey-xy->bluey, 7) == 0)
+-      return 2;
+-   if (png_muldiv(&green_inverse, xy->whitey, denominator, left-right) == 0 ||
+-       green_inverse <= xy->whitey)
+-      return 1;
++      /* By the argument above overflow should be impossible here, however the
++       * code now simply returns a failure code.  The xy subtracts in the
++       * arguments to png_muldiv are *not* checked for overflow because the
++       * checks at the start guarantee they are in the range 0..110000 and
++       * png_fixed_point is a 32-bit signed number.
++       */
++      if (png_muldiv(&left, xy->greenx-xy->bluex, xy->redy - xy->bluey, 8) == 0)
++         return 1;
++      if (png_muldiv(&right, xy->greeny-xy->bluey, xy->redx - xy->bluex, 8) ==
++            0)
++         return 1;
++      denominator = png_fp_sub(left, right, &error);
++      if (error) return 1;
+ 
+-   /* And the blue scale, the checks above guarantee this can't overflow but it
+-    * can still produce 0 for extreme cHRM values.
+-    */
+-   blue_scale = png_reciprocal(xy->whitey) - png_reciprocal(red_inverse) -
+-       png_reciprocal(green_inverse);
+-   if (blue_scale <= 0)
+-      return 1;
++      /* Now find the red numerator. */
++      if (png_muldiv(&left, xy->greenx-xy->bluex, xy->whitey-xy->bluey, 8) == 0)
++         return 1;
++      if (png_muldiv(&right, xy->greeny-xy->bluey, xy->whitex-xy->bluex, 8) ==
++            0)
++         return 1;
+ 
++      /* Overflow is possible here and it indicates an extreme set of PNG cHRM
++       * chunk values.  This calculation actually returns the reciprocal of the
++       * scale value because this allows us to delay the multiplication of
++       * white-y into the denominator, which tends to produce a small number.
++       */
++      if (png_muldiv(&red_inverse, xy->whitey, denominator,
++                     png_fp_sub(left, right, &error)) == 0 || error ||
++          red_inverse <= xy->whitey /* r+g+b scales = white scale */)
++         return 1;
+ 
+-   /* And fill in the png_XYZ: */
++      /* Similarly for green_inverse: */
++      if (png_muldiv(&left, xy->redy-xy->bluey, xy->whitex-xy->bluex, 8) == 0)
++         return 1;
++      if (png_muldiv(&right, xy->redx-xy->bluex, xy->whitey-xy->bluey, 8) == 0)
++         return 1;
++      if (png_muldiv(&green_inverse, xy->whitey, denominator,
++                     png_fp_sub(left, right, &error)) == 0 || error ||
++          green_inverse <= xy->whitey)
++         return 1;
++
++      /* And the blue scale, the checks above guarantee this can't overflow but
++       * it can still produce 0 for extreme cHRM values.
++       */
++      blue_scale = png_fp_sub(png_fp_sub(png_reciprocal(xy->whitey),
++                                         png_reciprocal(red_inverse), &error),
++                              png_reciprocal(green_inverse), &error);
++      if (error || blue_scale <= 0)
++         return 1;
++   }
++
++   /* And fill in the png_XYZ.  Again the subtracts are safe because of the
++    * checks on the xy values at the start (the subtracts just calculate the
++    * corresponding z values.)
++    */
+    if (png_muldiv(&XYZ->red_X, xy->redx, PNG_FP_1, red_inverse) == 0)
+       return 1;
+    if (png_muldiv(&XYZ->red_Y, xy->redy, PNG_FP_1, red_inverse) == 0)
+@@ -1544,250 +1518,9 @@ png_XYZ_from_xy(png_XYZ *XYZ, const png_xy *xy)
+ 
+    return 0; /*success*/
+ }
++#endif /* COLORSPACE */
+ 
+-static int
+-png_XYZ_normalize(png_XYZ *XYZ)
+-{
+-   png_int_32 Y;
+-
+-   if (XYZ->red_Y < 0 || XYZ->green_Y < 0 || XYZ->blue_Y < 0 ||
+-      XYZ->red_X < 0 || XYZ->green_X < 0 || XYZ->blue_X < 0 ||
+-      XYZ->red_Z < 0 || XYZ->green_Z < 0 || XYZ->blue_Z < 0)
+-      return 1;
+-
+-   /* Normalize by scaling so the sum of the end-point Y values is PNG_FP_1.
+-    * IMPLEMENTATION NOTE: ANSI requires signed overflow not to occur, therefore
+-    * relying on addition of two positive values producing a negative one is not
+-    * safe.
+-    */
+-   Y = XYZ->red_Y;
+-   if (0x7fffffff - Y < XYZ->green_X)
+-      return 1;
+-   Y += XYZ->green_Y;
+-   if (0x7fffffff - Y < XYZ->blue_X)
+-      return 1;
+-   Y += XYZ->blue_Y;
+-
+-   if (Y != PNG_FP_1)
+-   {
+-      if (png_muldiv(&XYZ->red_X, XYZ->red_X, PNG_FP_1, Y) == 0)
+-         return 1;
+-      if (png_muldiv(&XYZ->red_Y, XYZ->red_Y, PNG_FP_1, Y) == 0)
+-         return 1;
+-      if (png_muldiv(&XYZ->red_Z, XYZ->red_Z, PNG_FP_1, Y) == 0)
+-         return 1;
+-
+-      if (png_muldiv(&XYZ->green_X, XYZ->green_X, PNG_FP_1, Y) == 0)
+-         return 1;
+-      if (png_muldiv(&XYZ->green_Y, XYZ->green_Y, PNG_FP_1, Y) == 0)
+-         return 1;
+-      if (png_muldiv(&XYZ->green_Z, XYZ->green_Z, PNG_FP_1, Y) == 0)
+-         return 1;
+-
+-      if (png_muldiv(&XYZ->blue_X, XYZ->blue_X, PNG_FP_1, Y) == 0)
+-         return 1;
+-      if (png_muldiv(&XYZ->blue_Y, XYZ->blue_Y, PNG_FP_1, Y) == 0)
+-         return 1;
+-      if (png_muldiv(&XYZ->blue_Z, XYZ->blue_Z, PNG_FP_1, Y) == 0)
+-         return 1;
+-   }
+-
+-   return 0;
+-}
+-
+-static int
+-png_colorspace_endpoints_match(const png_xy *xy1, const png_xy *xy2, int delta)
+-{
+-   /* Allow an error of +/-0.01 (absolute value) on each chromaticity */
+-   if (PNG_OUT_OF_RANGE(xy1->whitex, xy2->whitex,delta) ||
+-       PNG_OUT_OF_RANGE(xy1->whitey, xy2->whitey,delta) ||
+-       PNG_OUT_OF_RANGE(xy1->redx,   xy2->redx,  delta) ||
+-       PNG_OUT_OF_RANGE(xy1->redy,   xy2->redy,  delta) ||
+-       PNG_OUT_OF_RANGE(xy1->greenx, xy2->greenx,delta) ||
+-       PNG_OUT_OF_RANGE(xy1->greeny, xy2->greeny,delta) ||
+-       PNG_OUT_OF_RANGE(xy1->bluex,  xy2->bluex, delta) ||
+-       PNG_OUT_OF_RANGE(xy1->bluey,  xy2->bluey, delta))
+-      return 0;
+-   return 1;
+-}
+-
+-/* Added in libpng-1.6.0, a different check for the validity of a set of cHRM
+- * chunk chromaticities.  Earlier checks used to simply look for the overflow
+- * condition (where the determinant of the matrix to solve for XYZ ends up zero
+- * because the chromaticity values are not all distinct.)  Despite this it is
+- * theoretically possible to produce chromaticities that are apparently valid
+- * but that rapidly degrade to invalid, potentially crashing, sets because of
+- * arithmetic inaccuracies when calculations are performed on them.  The new
+- * check is to round-trip xy -> XYZ -> xy and then check that the result is
+- * within a small percentage of the original.
+- */
+-static int
+-png_colorspace_check_xy(png_XYZ *XYZ, const png_xy *xy)
+-{
+-   int result;
+-   png_xy xy_test;
+-
+-   /* As a side-effect this routine also returns the XYZ endpoints. */
+-   result = png_XYZ_from_xy(XYZ, xy);
+-   if (result != 0)
+-      return result;
+-
+-   result = png_xy_from_XYZ(&xy_test, XYZ);
+-   if (result != 0)
+-      return result;
+-
+-   if (png_colorspace_endpoints_match(xy, &xy_test,
+-       5/*actually, the math is pretty accurate*/) != 0)
+-      return 0;
+-
+-   /* Too much slip */
+-   return 1;
+-}
+-
+-/* This is the check going the other way.  The XYZ is modified to normalize it
+- * (another side-effect) and the xy chromaticities are returned.
+- */
+-static int
+-png_colorspace_check_XYZ(png_xy *xy, png_XYZ *XYZ)
+-{
+-   int result;
+-   png_XYZ XYZtemp;
+-
+-   result = png_XYZ_normalize(XYZ);
+-   if (result != 0)
+-      return result;
+-
+-   result = png_xy_from_XYZ(xy, XYZ);
+-   if (result != 0)
+-      return result;
+-
+-   XYZtemp = *XYZ;
+-   return png_colorspace_check_xy(&XYZtemp, xy);
+-}
+-
+-/* Used to check for an endpoint match against sRGB */
+-static const png_xy sRGB_xy = /* From ITU-R BT.709-3 */
+-{
+-   /* color      x       y */
+-   /* red   */ 64000, 33000,
+-   /* green */ 30000, 60000,
+-   /* blue  */ 15000,  6000,
+-   /* white */ 31270, 32900
+-};
+-
+-static int
+-png_colorspace_set_xy_and_XYZ(png_const_structrp png_ptr,
+-    png_colorspacerp colorspace, const png_xy *xy, const png_XYZ *XYZ,
+-    int preferred)
+-{
+-   if ((colorspace->flags & PNG_COLORSPACE_INVALID) != 0)
+-      return 0;
+-
+-   /* The consistency check is performed on the chromaticities; this factors out
+-    * variations because of the normalization (or not) of the end point Y
+-    * values.
+-    */
+-   if (preferred < 2 &&
+-       (colorspace->flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
+-   {
+-      /* The end points must be reasonably close to any we already have.  The
+-       * following allows an error of up to +/-.001
+-       */
+-      if (png_colorspace_endpoints_match(xy, &colorspace->end_points_xy,
+-          100) == 0)
+-      {
+-         colorspace->flags |= PNG_COLORSPACE_INVALID;
+-         png_benign_error(png_ptr, "inconsistent chromaticities");
+-         return 0; /* failed */
+-      }
+-
+-      /* Only overwrite with preferred values */
+-      if (preferred == 0)
+-         return 1; /* ok, but no change */
+-   }
+-
+-   colorspace->end_points_xy = *xy;
+-   colorspace->end_points_XYZ = *XYZ;
+-   colorspace->flags |= PNG_COLORSPACE_HAVE_ENDPOINTS;
+-
+-   /* The end points are normally quoted to two decimal digits, so allow +/-0.01
+-    * on this test.
+-    */
+-   if (png_colorspace_endpoints_match(xy, &sRGB_xy, 1000) != 0)
+-      colorspace->flags |= PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB;
+-
+-   else
+-      colorspace->flags &= PNG_COLORSPACE_CANCEL(
+-         PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB);
+-
+-   return 2; /* ok and changed */
+-}
+-
+-int /* PRIVATE */
+-png_colorspace_set_chromaticities(png_const_structrp png_ptr,
+-    png_colorspacerp colorspace, const png_xy *xy, int preferred)
+-{
+-   /* We must check the end points to ensure they are reasonable - in the past
+-    * color management systems have crashed as a result of getting bogus
+-    * colorant values, while this isn't the fault of libpng it is the
+-    * responsibility of libpng because PNG carries the bomb and libpng is in a
+-    * position to protect against it.
+-    */
+-   png_XYZ XYZ;
+-
+-   switch (png_colorspace_check_xy(&XYZ, xy))
+-   {
+-      case 0: /* success */
+-         return png_colorspace_set_xy_and_XYZ(png_ptr, colorspace, xy, &XYZ,
+-             preferred);
+-
+-      case 1:
+-         /* We can't invert the chromaticities so we can't produce value XYZ
+-          * values.  Likely as not a color management system will fail too.
+-          */
+-         colorspace->flags |= PNG_COLORSPACE_INVALID;
+-         png_benign_error(png_ptr, "invalid chromaticities");
+-         break;
+-
+-      default:
+-         /* libpng is broken; this should be a warning but if it happens we
+-          * want error reports so for the moment it is an error.
+-          */
+-         colorspace->flags |= PNG_COLORSPACE_INVALID;
+-         png_error(png_ptr, "internal error checking chromaticities");
+-   }
+-
+-   return 0; /* failed */
+-}
+-
+-int /* PRIVATE */
+-png_colorspace_set_endpoints(png_const_structrp png_ptr,
+-    png_colorspacerp colorspace, const png_XYZ *XYZ_in, int preferred)
+-{
+-   png_XYZ XYZ = *XYZ_in;
+-   png_xy xy;
+-
+-   switch (png_colorspace_check_XYZ(&xy, &XYZ))
+-   {
+-      case 0:
+-         return png_colorspace_set_xy_and_XYZ(png_ptr, colorspace, &xy, &XYZ,
+-             preferred);
+-
+-      case 1:
+-         /* End points are invalid. */
+-         colorspace->flags |= PNG_COLORSPACE_INVALID;
+-         png_benign_error(png_ptr, "invalid end points");
+-         break;
+-
+-      default:
+-         colorspace->flags |= PNG_COLORSPACE_INVALID;
+-         png_error(png_ptr, "internal error checking chromaticities");
+-   }
+-
+-   return 0; /* failed */
+-}
+-
+-#if defined(PNG_sRGB_SUPPORTED) || defined(PNG_iCCP_SUPPORTED)
++#ifdef PNG_iCCP_SUPPORTED
+ /* Error message generation */
+ static char
+ png_icc_tag_char(png_uint_32 byte)
+@@ -1827,15 +1560,12 @@ is_ICC_signature(png_alloc_size_t it)
+ }
+ 
+ static int
+-png_icc_profile_error(png_const_structrp png_ptr, png_colorspacerp colorspace,
+-    png_const_charp name, png_alloc_size_t value, png_const_charp reason)
++png_icc_profile_error(png_const_structrp png_ptr, png_const_charp name,
++   png_alloc_size_t value, png_const_charp reason)
+ {
+    size_t pos;
+    char message[196]; /* see below for calculation */
+ 
+-   if (colorspace != NULL)
+-      colorspace->flags |= PNG_COLORSPACE_INVALID;
+-
+    pos = png_safecat(message, (sizeof message), 0, "profile '"); /* 9 chars */
+    pos = png_safecat(message, pos+79, pos, name); /* Truncate to 79 chars */
+    pos = png_safecat(message, (sizeof message), pos, "': "); /* +2 = 90 */
+@@ -1862,109 +1592,13 @@ png_icc_profile_error(png_const_structrp png_ptr, png_colorspacerp colorspace,
+    pos = png_safecat(message, (sizeof message), pos, reason);
+    PNG_UNUSED(pos)
+ 
+-   /* This is recoverable, but make it unconditionally an app_error on write to
+-    * avoid writing invalid ICC profiles into PNG files (i.e., we handle them
+-    * on read, with a warning, but on write unless the app turns off
+-    * application errors the PNG won't be written.)
+-    */
+-   png_chunk_report(png_ptr, message,
+-       (colorspace != NULL) ? PNG_CHUNK_ERROR : PNG_CHUNK_WRITE_ERROR);
++   png_chunk_benign_error(png_ptr, message);
+ 
+    return 0;
+ }
+-#endif /* sRGB || iCCP */
+-
+-#ifdef PNG_sRGB_SUPPORTED
+-int /* PRIVATE */
+-png_colorspace_set_sRGB(png_const_structrp png_ptr, png_colorspacerp colorspace,
+-    int intent)
+-{
+-   /* sRGB sets known gamma, end points and (from the chunk) intent. */
+-   /* IMPORTANT: these are not necessarily the values found in an ICC profile
+-    * because ICC profiles store values adapted to a D50 environment; it is
+-    * expected that the ICC profile mediaWhitePointTag will be D50; see the
+-    * checks and code elsewhere to understand this better.
+-    *
+-    * These XYZ values, which are accurate to 5dp, produce rgb to gray
+-    * coefficients of (6968,23435,2366), which are reduced (because they add up
+-    * to 32769 not 32768) to (6968,23434,2366).  These are the values that
+-    * libpng has traditionally used (and are the best values given the 15bit
+-    * algorithm used by the rgb to gray code.)
+-    */
+-   static const png_XYZ sRGB_XYZ = /* D65 XYZ (*not* the D50 adapted values!) */
+-   {
+-      /* color      X      Y      Z */
+-      /* red   */ 41239, 21264,  1933,
+-      /* green */ 35758, 71517, 11919,
+-      /* blue  */ 18048,  7219, 95053
+-   };
+-
+-   /* Do nothing if the colorspace is already invalidated. */
+-   if ((colorspace->flags & PNG_COLORSPACE_INVALID) != 0)
+-      return 0;
+-
+-   /* Check the intent, then check for existing settings.  It is valid for the
+-    * PNG file to have cHRM or gAMA chunks along with sRGB, but the values must
+-    * be consistent with the correct values.  If, however, this function is
+-    * called below because an iCCP chunk matches sRGB then it is quite
+-    * conceivable that an older app recorded incorrect gAMA and cHRM because of
+-    * an incorrect calculation based on the values in the profile - this does
+-    * *not* invalidate the profile (though it still produces an error, which can
+-    * be ignored.)
+-    */
+-   if (intent < 0 || intent >= PNG_sRGB_INTENT_LAST)
+-      return png_icc_profile_error(png_ptr, colorspace, "sRGB",
+-          (png_alloc_size_t)intent, "invalid sRGB rendering intent");
+-
+-   if ((colorspace->flags & PNG_COLORSPACE_HAVE_INTENT) != 0 &&
+-       colorspace->rendering_intent != intent)
+-      return png_icc_profile_error(png_ptr, colorspace, "sRGB",
+-         (png_alloc_size_t)intent, "inconsistent rendering intents");
+-
+-   if ((colorspace->flags & PNG_COLORSPACE_FROM_sRGB) != 0)
+-   {
+-      png_benign_error(png_ptr, "duplicate sRGB information ignored");
+-      return 0;
+-   }
+-
+-   /* If the standard sRGB cHRM chunk does not match the one from the PNG file
+-    * warn but overwrite the value with the correct one.
+-    */
+-   if ((colorspace->flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0 &&
+-       !png_colorspace_endpoints_match(&sRGB_xy, &colorspace->end_points_xy,
+-       100))
+-      png_chunk_report(png_ptr, "cHRM chunk does not match sRGB",
+-         PNG_CHUNK_ERROR);
+-
+-   /* This check is just done for the error reporting - the routine always
+-    * returns true when the 'from' argument corresponds to sRGB (2).
+-    */
+-   (void)png_colorspace_check_gamma(png_ptr, colorspace, PNG_GAMMA_sRGB_INVERSE,
+-       2/*from sRGB*/);
+-
+-   /* intent: bugs in GCC force 'int' to be used as the parameter type. */
+-   colorspace->rendering_intent = (png_uint_16)intent;
+-   colorspace->flags |= PNG_COLORSPACE_HAVE_INTENT;
+-
+-   /* endpoints */
+-   colorspace->end_points_xy = sRGB_xy;
+-   colorspace->end_points_XYZ = sRGB_XYZ;
+-   colorspace->flags |=
+-      (PNG_COLORSPACE_HAVE_ENDPOINTS|PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB);
+-
+-   /* gamma */
+-   colorspace->gamma = PNG_GAMMA_sRGB_INVERSE;
+-   colorspace->flags |= PNG_COLORSPACE_HAVE_GAMMA;
+-
+-   /* Finally record that we have an sRGB profile */
+-   colorspace->flags |=
+-      (PNG_COLORSPACE_MATCHES_sRGB|PNG_COLORSPACE_FROM_sRGB);
+-
+-   return 1; /* set */
+-}
+-#endif /* sRGB */
++#endif /* iCCP */
+ 
+-#ifdef PNG_iCCP_SUPPORTED
++#ifdef PNG_READ_iCCP_SUPPORTED
+ /* Encoded value of D50 as an ICC XYZNumber.  From the ICC 2010 spec the value
+  * is XYZ(0.9642,1.0,0.8249), which scales to:
+  *
+@@ -1974,21 +1608,19 @@ static const png_byte D50_nCIEXYZ[12] =
+    { 0x00, 0x00, 0xf6, 0xd6, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x2d };
+ 
+ static int /* bool */
+-icc_check_length(png_const_structrp png_ptr, png_colorspacerp colorspace,
+-    png_const_charp name, png_uint_32 profile_length)
++icc_check_length(png_const_structrp png_ptr, png_const_charp name,
++   png_uint_32 profile_length)
+ {
+    if (profile_length < 132)
+-      return png_icc_profile_error(png_ptr, colorspace, name, profile_length,
+-          "too short");
++      return png_icc_profile_error(png_ptr, name, profile_length, "too short");
+    return 1;
+ }
+ 
+-#ifdef PNG_READ_iCCP_SUPPORTED
+ int /* PRIVATE */
+-png_icc_check_length(png_const_structrp png_ptr, png_colorspacerp colorspace,
+-    png_const_charp name, png_uint_32 profile_length)
++png_icc_check_length(png_const_structrp png_ptr, png_const_charp name,
++   png_uint_32 profile_length)
+ {
+-   if (!icc_check_length(png_ptr, colorspace, name, profile_length))
++   if (!icc_check_length(png_ptr, name, profile_length))
+       return 0;
+ 
+    /* This needs to be here because the 'normal' check is in
+@@ -1997,30 +1629,17 @@ png_icc_check_length(png_const_structrp png_ptr, png_colorspacerp colorspace,
+     * the caller supplies the profile buffer so libpng doesn't allocate it.  See
+     * the call to icc_check_length below (the write case).
+     */
+-#  ifdef PNG_SET_USER_LIMITS_SUPPORTED
+-      else if (png_ptr->user_chunk_malloc_max > 0 &&
+-               png_ptr->user_chunk_malloc_max < profile_length)
+-         return png_icc_profile_error(png_ptr, colorspace, name, profile_length,
+-             "exceeds application limits");
+-#  elif PNG_USER_CHUNK_MALLOC_MAX > 0
+-      else if (PNG_USER_CHUNK_MALLOC_MAX < profile_length)
+-         return png_icc_profile_error(png_ptr, colorspace, name, profile_length,
+-             "exceeds libpng limits");
+-#  else /* !SET_USER_LIMITS */
+-      /* This will get compiled out on all 32-bit and better systems. */
+-      else if (PNG_SIZE_MAX < profile_length)
+-         return png_icc_profile_error(png_ptr, colorspace, name, profile_length,
+-             "exceeds system limits");
+-#  endif /* !SET_USER_LIMITS */
++   if (profile_length > png_chunk_max(png_ptr))
++      return png_icc_profile_error(png_ptr, name, profile_length,
++            "profile too long");
+ 
+    return 1;
+ }
+-#endif /* READ_iCCP */
+ 
+ int /* PRIVATE */
+-png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace,
+-    png_const_charp name, png_uint_32 profile_length,
+-    png_const_bytep profile/* first 132 bytes only */, int color_type)
++png_icc_check_header(png_const_structrp png_ptr, png_const_charp name,
++   png_uint_32 profile_length,
++   png_const_bytep profile/* first 132 bytes only */, int color_type)
+ {
+    png_uint_32 temp;
+ 
+@@ -2031,18 +1650,18 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace,
+     */
+    temp = png_get_uint_32(profile);
+    if (temp != profile_length)
+-      return png_icc_profile_error(png_ptr, colorspace, name, temp,
++      return png_icc_profile_error(png_ptr, name, temp,
+           "length does not match profile");
+ 
+    temp = (png_uint_32) (*(profile+8));
+    if (temp > 3 && (profile_length & 3))
+-      return png_icc_profile_error(png_ptr, colorspace, name, profile_length,
++      return png_icc_profile_error(png_ptr, name, profile_length,
+           "invalid length");
+ 
+    temp = png_get_uint_32(profile+128); /* tag count: 12 bytes/tag */
+    if (temp > 357913930 || /* (2^32-4-132)/12: maximum possible tag count */
+       profile_length < 132+12*temp) /* truncated tag table */
+-      return png_icc_profile_error(png_ptr, colorspace, name, temp,
++      return png_icc_profile_error(png_ptr, name, temp,
+           "tag count too large");
+ 
+    /* The 'intent' must be valid or we can't store it, ICC limits the intent to
+@@ -2050,14 +1669,14 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace,
+     */
+    temp = png_get_uint_32(profile+64);
+    if (temp >= 0xffff) /* The ICC limit */
+-      return png_icc_profile_error(png_ptr, colorspace, name, temp,
++      return png_icc_profile_error(png_ptr, name, temp,
+           "invalid rendering intent");
+ 
+    /* This is just a warning because the profile may be valid in future
+     * versions.
+     */
+    if (temp >= PNG_sRGB_INTENT_LAST)
+-      (void)png_icc_profile_error(png_ptr, NULL, name, temp,
++      (void)png_icc_profile_error(png_ptr, name, temp,
+           "intent outside defined range");
+ 
+    /* At this point the tag table can't be checked because it hasn't necessarily
+@@ -2074,7 +1693,7 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace,
+     */
+    temp = png_get_uint_32(profile+36); /* signature 'ascp' */
+    if (temp != 0x61637370)
+-      return png_icc_profile_error(png_ptr, colorspace, name, temp,
++      return png_icc_profile_error(png_ptr, name, temp,
+           "invalid signature");
+ 
+    /* Currently the PCS illuminant/adopted white point (the computational
+@@ -2085,7 +1704,7 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace,
+     * following is just a warning.
+     */
+    if (memcmp(profile+68, D50_nCIEXYZ, 12) != 0)
+-      (void)png_icc_profile_error(png_ptr, NULL, name, 0/*no tag value*/,
++      (void)png_icc_profile_error(png_ptr, name, 0/*no tag value*/,
+           "PCS illuminant is not D50");
+ 
+    /* The PNG spec requires this:
+@@ -2113,18 +1732,18 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace,
+    {
+       case 0x52474220: /* 'RGB ' */
+          if ((color_type & PNG_COLOR_MASK_COLOR) == 0)
+-            return png_icc_profile_error(png_ptr, colorspace, name, temp,
++            return png_icc_profile_error(png_ptr, name, temp,
+                 "RGB color space not permitted on grayscale PNG");
+          break;
+ 
+       case 0x47524159: /* 'GRAY' */
+          if ((color_type & PNG_COLOR_MASK_COLOR) != 0)
+-            return png_icc_profile_error(png_ptr, colorspace, name, temp,
++            return png_icc_profile_error(png_ptr, name, temp,
+                 "Gray color space not permitted on RGB PNG");
+          break;
+ 
+       default:
+-         return png_icc_profile_error(png_ptr, colorspace, name, temp,
++         return png_icc_profile_error(png_ptr, name, temp,
+              "invalid ICC profile color space");
+    }
+ 
+@@ -2149,7 +1768,7 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace,
+ 
+       case 0x61627374: /* 'abst' */
+          /* May not be embedded in an image */
+-         return png_icc_profile_error(png_ptr, colorspace, name, temp,
++         return png_icc_profile_error(png_ptr, name, temp,
+              "invalid embedded Abstract ICC profile");
+ 
+       case 0x6c696e6b: /* 'link' */
+@@ -2159,7 +1778,7 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace,
+           * therefore a DeviceLink profile should not be found embedded in a
+           * PNG.
+           */
+-         return png_icc_profile_error(png_ptr, colorspace, name, temp,
++         return png_icc_profile_error(png_ptr, name, temp,
+              "unexpected DeviceLink ICC profile class");
+ 
+       case 0x6e6d636c: /* 'nmcl' */
+@@ -2167,7 +1786,7 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace,
+           * contain an AToB0 tag that is open to misinterpretation.  Almost
+           * certainly it will fail the tests below.
+           */
+-         (void)png_icc_profile_error(png_ptr, NULL, name, temp,
++         (void)png_icc_profile_error(png_ptr, name, temp,
+              "unexpected NamedColor ICC profile class");
+          break;
+ 
+@@ -2177,7 +1796,7 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace,
+           * tag content to ensure they are backward compatible with one of the
+           * understood profiles.
+           */
+-         (void)png_icc_profile_error(png_ptr, NULL, name, temp,
++         (void)png_icc_profile_error(png_ptr, name, temp,
+              "unrecognized ICC profile class");
+          break;
+    }
+@@ -2193,7 +1812,7 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace,
+          break;
+ 
+       default:
+-         return png_icc_profile_error(png_ptr, colorspace, name, temp,
++         return png_icc_profile_error(png_ptr, name, temp,
+              "unexpected ICC PCS encoding");
+    }
+ 
+@@ -2201,9 +1820,9 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace,
+ }
+ 
+ int /* PRIVATE */
+-png_icc_check_tag_table(png_const_structrp png_ptr, png_colorspacerp colorspace,
+-    png_const_charp name, png_uint_32 profile_length,
+-    png_const_bytep profile /* header plus whole tag table */)
++png_icc_check_tag_table(png_const_structrp png_ptr, png_const_charp name,
++   png_uint_32 profile_length,
++   png_const_bytep profile /* header plus whole tag table */)
+ {
+    png_uint_32 tag_count = png_get_uint_32(profile+128);
+    png_uint_32 itag;
+@@ -2229,7 +1848,7 @@ png_icc_check_tag_table(png_const_structrp png_ptr, png_colorspacerp colorspace,
+        * profile.
+        */
+       if (tag_start > profile_length || tag_length > profile_length - tag_start)
+-         return png_icc_profile_error(png_ptr, colorspace, name, tag_id,
++         return png_icc_profile_error(png_ptr, name, tag_id,
+              "ICC profile tag outside profile");
+ 
+       if ((tag_start & 3) != 0)
+@@ -2238,307 +1857,132 @@ png_icc_check_tag_table(png_const_structrp png_ptr, png_colorspacerp colorspace,
+           * only a warning here because libpng does not care about the
+           * alignment.
+           */
+-         (void)png_icc_profile_error(png_ptr, NULL, name, tag_id,
++         (void)png_icc_profile_error(png_ptr, name, tag_id,
+              "ICC profile tag start not a multiple of 4");
+       }
+    }
+ 
+    return 1; /* success, maybe with warnings */
+ }
++#endif /* READ_iCCP */
+ 
+-#ifdef PNG_sRGB_SUPPORTED
+-#if PNG_sRGB_PROFILE_CHECKS >= 0
+-/* Information about the known ICC sRGB profiles */
+-static const struct
+-{
+-   png_uint_32 adler, crc, length;
+-   png_uint_32 md5[4];
+-   png_byte    have_md5;
+-   png_byte    is_broken;
+-   png_uint_16 intent;
+-
+-#  define PNG_MD5(a,b,c,d) { a, b, c, d }, (a!=0)||(b!=0)||(c!=0)||(d!=0)
+-#  define PNG_ICC_CHECKSUM(adler, crc, md5, intent, broke, date, length, fname)\
+-      { adler, crc, length, md5, broke, intent },
+-
+-} png_sRGB_checks[] =
+-{
+-   /* This data comes from contrib/tools/checksum-icc run on downloads of
+-    * all four ICC sRGB profiles from www.color.org.
+-    */
+-   /* adler32, crc32, MD5[4], intent, date, length, file-name */
+-   PNG_ICC_CHECKSUM(0x0a3fd9f6, 0x3b8772b9,
+-       PNG_MD5(0x29f83dde, 0xaff255ae, 0x7842fae4, 0xca83390d), 0, 0,
+-       "2009/03/27 21:36:31", 3048, "sRGB_IEC61966-2-1_black_scaled.icc")
+-
+-   /* ICC sRGB v2 perceptual no black-compensation: */
+-   PNG_ICC_CHECKSUM(0x4909e5e1, 0x427ebb21,
+-       PNG_MD5(0xc95bd637, 0xe95d8a3b, 0x0df38f99, 0xc1320389), 1, 0,
+-       "2009/03/27 21:37:45", 3052, "sRGB_IEC61966-2-1_no_black_scaling.icc")
+-
+-   PNG_ICC_CHECKSUM(0xfd2144a1, 0x306fd8ae,
+-       PNG_MD5(0xfc663378, 0x37e2886b, 0xfd72e983, 0x8228f1b8), 0, 0,
+-       "2009/08/10 17:28:01", 60988, "sRGB_v4_ICC_preference_displayclass.icc")
+-
+-   /* ICC sRGB v4 perceptual */
+-   PNG_ICC_CHECKSUM(0x209c35d2, 0xbbef7812,
+-       PNG_MD5(0x34562abf, 0x994ccd06, 0x6d2c5721, 0xd0d68c5d), 0, 0,
+-       "2007/07/25 00:05:37", 60960, "sRGB_v4_ICC_preference.icc")
+-
+-   /* The following profiles have no known MD5 checksum. If there is a match
+-    * on the (empty) MD5 the other fields are used to attempt a match and
+-    * a warning is produced.  The first two of these profiles have a 'cprt' tag
+-    * which suggests that they were also made by Hewlett Packard.
+-    */
+-   PNG_ICC_CHECKSUM(0xa054d762, 0x5d5129ce,
+-       PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 1, 0,
+-       "2004/07/21 18:57:42", 3024, "sRGB_IEC61966-2-1_noBPC.icc")
+-
+-   /* This is a 'mntr' (display) profile with a mediaWhitePointTag that does not
+-    * match the D50 PCS illuminant in the header (it is in fact the D65 values,
+-    * so the white point is recorded as the un-adapted value.)  The profiles
+-    * below only differ in one byte - the intent - and are basically the same as
+-    * the previous profile except for the mediaWhitePointTag error and a missing
+-    * chromaticAdaptationTag.
+-    */
+-   PNG_ICC_CHECKSUM(0xf784f3fb, 0x182ea552,
+-       PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 0, 1/*broken*/,
+-       "1998/02/09 06:49:00", 3144, "HP-Microsoft sRGB v2 perceptual")
+-
+-   PNG_ICC_CHECKSUM(0x0398f3fc, 0xf29e526d,
+-       PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 1, 1/*broken*/,
+-       "1998/02/09 06:49:00", 3144, "HP-Microsoft sRGB v2 media-relative")
+-};
+-
++#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
++#if (defined PNG_READ_mDCV_SUPPORTED) || (defined PNG_READ_cHRM_SUPPORTED)
+ static int
+-png_compare_ICC_profile_with_sRGB(png_const_structrp png_ptr,
+-    png_const_bytep profile, uLong adler)
++have_chromaticities(png_const_structrp png_ptr)
+ {
+-   /* The quick check is to verify just the MD5 signature and trust the
+-    * rest of the data.  Because the profile has already been verified for
+-    * correctness this is safe.  png_colorspace_set_sRGB will check the 'intent'
+-    * field too, so if the profile has been edited with an intent not defined
+-    * by sRGB (but maybe defined by a later ICC specification) the read of
+-    * the profile will fail at that point.
++   /* Handle new PNGv3 chunks and the precedence rules to determine whether
++    * png_struct::chromaticities must be processed.  Only required for RGB to
++    * gray.
++    *
++    * mDCV: this is the mastering colour space and it is independent of the
++    *       encoding so it needs to be used regardless of the encoded space.
++    *
++    * cICP: first in priority but not yet implemented - the chromaticities come
++    *       from the 'primaries'.
++    *
++    * iCCP: not supported by libpng (so ignored)
++    *
++    * sRGB: the defaults match sRGB
++    *
++    * cHRM: calculate the coefficients
+     */
++#  ifdef PNG_READ_mDCV_SUPPORTED
++      if (png_has_chunk(png_ptr, mDCV))
++         return 1;
++#     define check_chromaticities 1
++#  endif /*mDCV*/
+ 
+-   png_uint_32 length = 0;
+-   png_uint_32 intent = 0x10000; /* invalid */
+-#if PNG_sRGB_PROFILE_CHECKS > 1
+-   uLong crc = 0; /* the value for 0 length data */
+-#endif
+-   unsigned int i;
+-
+-#ifdef PNG_SET_OPTION_SUPPORTED
+-   /* First see if PNG_SKIP_sRGB_CHECK_PROFILE has been set to "on" */
+-   if (((png_ptr->options >> PNG_SKIP_sRGB_CHECK_PROFILE) & 3) ==
+-               PNG_OPTION_ON)
+-      return 0;
+-#endif
+-
+-   for (i=0; i < (sizeof png_sRGB_checks) / (sizeof png_sRGB_checks[0]); ++i)
+-   {
+-      if (png_get_uint_32(profile+84) == png_sRGB_checks[i].md5[0] &&
+-         png_get_uint_32(profile+88) == png_sRGB_checks[i].md5[1] &&
+-         png_get_uint_32(profile+92) == png_sRGB_checks[i].md5[2] &&
+-         png_get_uint_32(profile+96) == png_sRGB_checks[i].md5[3])
+-      {
+-         /* This may be one of the old HP profiles without an MD5, in that
+-          * case we can only use the length and Adler32 (note that these
+-          * are not used by default if there is an MD5!)
+-          */
+-#        if PNG_sRGB_PROFILE_CHECKS == 0
+-            if (png_sRGB_checks[i].have_md5 != 0)
+-               return 1+png_sRGB_checks[i].is_broken;
+-#        endif
+-
+-         /* Profile is unsigned or more checks have been configured in. */
+-         if (length == 0)
+-         {
+-            length = png_get_uint_32(profile);
+-            intent = png_get_uint_32(profile+64);
+-         }
+-
+-         /* Length *and* intent must match */
+-         if (length == (png_uint_32) png_sRGB_checks[i].length &&
+-            intent == (png_uint_32) png_sRGB_checks[i].intent)
+-         {
+-            /* Now calculate the adler32 if not done already. */
+-            if (adler == 0)
+-            {
+-               adler = adler32(0, NULL, 0);
+-               adler = adler32(adler, profile, length);
+-            }
+-
+-            if (adler == png_sRGB_checks[i].adler)
+-            {
+-               /* These basic checks suggest that the data has not been
+-                * modified, but if the check level is more than 1 perform
+-                * our own crc32 checksum on the data.
+-                */
+-#              if PNG_sRGB_PROFILE_CHECKS > 1
+-                  if (crc == 0)
+-                  {
+-                     crc = crc32(0, NULL, 0);
+-                     crc = crc32(crc, profile, length);
+-                  }
+-
+-                  /* So this check must pass for the 'return' below to happen.
+-                   */
+-                  if (crc == png_sRGB_checks[i].crc)
+-#              endif
+-               {
+-                  if (png_sRGB_checks[i].is_broken != 0)
+-                  {
+-                     /* These profiles are known to have bad data that may cause
+-                      * problems if they are used, therefore attempt to
+-                      * discourage their use, skip the 'have_md5' warning below,
+-                      * which is made irrelevant by this error.
+-                      */
+-                     png_chunk_report(png_ptr, "known incorrect sRGB profile",
+-                         PNG_CHUNK_ERROR);
+-                  }
+-
+-                  /* Warn that this being done; this isn't even an error since
+-                   * the profile is perfectly valid, but it would be nice if
+-                   * people used the up-to-date ones.
+-                   */
+-                  else if (png_sRGB_checks[i].have_md5 == 0)
+-                  {
+-                     png_chunk_report(png_ptr,
+-                         "out-of-date sRGB profile with no signature",
+-                         PNG_CHUNK_WARNING);
+-                  }
++#  ifdef PNG_READ_sRGB_SUPPORTED
++      if (png_has_chunk(png_ptr, sRGB))
++         return 0;
++#  endif /*sRGB*/
+ 
+-                  return 1+png_sRGB_checks[i].is_broken;
+-               }
+-            }
+-
+-# if PNG_sRGB_PROFILE_CHECKS > 0
+-         /* The signature matched, but the profile had been changed in some
+-          * way.  This probably indicates a data error or uninformed hacking.
+-          * Fall through to "no match".
+-          */
+-         png_chunk_report(png_ptr,
+-             "Not recognizing known sRGB profile that has been edited",
+-             PNG_CHUNK_WARNING);
+-         break;
+-# endif
+-         }
+-      }
+-   }
++#  ifdef PNG_READ_cHRM_SUPPORTED
++      if (png_has_chunk(png_ptr, cHRM))
++         return 1;
++#     define check_chromaticities 1
++#  endif /*cHRM*/
+ 
+-   return 0; /* no match */
++   return 0; /* sRGB defaults */
+ }
++#endif /* READ_mDCV || READ_cHRM */
+ 
+ void /* PRIVATE */
+-png_icc_set_sRGB(png_const_structrp png_ptr,
+-    png_colorspacerp colorspace, png_const_bytep profile, uLong adler)
++png_set_rgb_coefficients(png_structrp png_ptr)
+ {
+-   /* Is this profile one of the known ICC sRGB profiles?  If it is, just set
+-    * the sRGB information.
++   /* Set the rgb_to_gray coefficients from the colorspace if available.  Note
++    * that '_set' means that png_rgb_to_gray was called **and** it successfully
++    * set up the coefficients.
+     */
+-   if (png_compare_ICC_profile_with_sRGB(png_ptr, profile, adler) != 0)
+-      (void)png_colorspace_set_sRGB(png_ptr, colorspace,
+-         (int)/*already checked*/png_get_uint_32(profile+64));
+-}
+-#endif /* PNG_sRGB_PROFILE_CHECKS >= 0 */
+-#endif /* sRGB */
+-
+-int /* PRIVATE */
+-png_colorspace_set_ICC(png_const_structrp png_ptr, png_colorspacerp colorspace,
+-    png_const_charp name, png_uint_32 profile_length, png_const_bytep profile,
+-    int color_type)
+-{
+-   if ((colorspace->flags & PNG_COLORSPACE_INVALID) != 0)
+-      return 0;
+-
+-   if (icc_check_length(png_ptr, colorspace, name, profile_length) != 0 &&
+-       png_icc_check_header(png_ptr, colorspace, name, profile_length, profile,
+-           color_type) != 0 &&
+-       png_icc_check_tag_table(png_ptr, colorspace, name, profile_length,
+-           profile) != 0)
++   if (png_ptr->rgb_to_gray_coefficients_set == 0)
+    {
+-#     if defined(PNG_sRGB_SUPPORTED) && PNG_sRGB_PROFILE_CHECKS >= 0
+-         /* If no sRGB support, don't try storing sRGB information */
+-         png_icc_set_sRGB(png_ptr, colorspace, profile, 0);
+-#     endif
+-      return 1;
+-   }
++#  if check_chromaticities
++      png_XYZ xyz;
+ 
+-   /* Failure case */
+-   return 0;
+-}
+-#endif /* iCCP */
+-
+-#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
+-void /* PRIVATE */
+-png_colorspace_set_rgb_coefficients(png_structrp png_ptr)
+-{
+-   /* Set the rgb_to_gray coefficients from the colorspace. */
+-   if (png_ptr->rgb_to_gray_coefficients_set == 0 &&
+-      (png_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
+-   {
+-      /* png_set_background has not been called, get the coefficients from the Y
+-       * values of the colorspace colorants.
+-       */
+-      png_fixed_point r = png_ptr->colorspace.end_points_XYZ.red_Y;
+-      png_fixed_point g = png_ptr->colorspace.end_points_XYZ.green_Y;
+-      png_fixed_point b = png_ptr->colorspace.end_points_XYZ.blue_Y;
+-      png_fixed_point total = r+g+b;
+-
+-      if (total > 0 &&
+-         r >= 0 && png_muldiv(&r, r, 32768, total) && r >= 0 && r <= 32768 &&
+-         g >= 0 && png_muldiv(&g, g, 32768, total) && g >= 0 && g <= 32768 &&
+-         b >= 0 && png_muldiv(&b, b, 32768, total) && b >= 0 && b <= 32768 &&
+-         r+g+b <= 32769)
++      if (have_chromaticities(png_ptr) &&
++          png_XYZ_from_xy(&xyz, &png_ptr->chromaticities) == 0)
+       {
+-         /* We allow 0 coefficients here.  r+g+b may be 32769 if two or
+-          * all of the coefficients were rounded up.  Handle this by
+-          * reducing the *largest* coefficient by 1; this matches the
+-          * approach used for the default coefficients in pngrtran.c
++         /* png_set_rgb_to_gray has not set the coefficients, get them from the
++          * Y * values of the colorspace colorants.
+           */
+-         int add = 0;
++         png_fixed_point r = xyz.red_Y;
++         png_fixed_point g = xyz.green_Y;
++         png_fixed_point b = xyz.blue_Y;
++         png_fixed_point total = r+g+b;
++
++         if (total > 0 &&
++            r >= 0 && png_muldiv(&r, r, 32768, total) && r >= 0 && r <= 32768 &&
++            g >= 0 && png_muldiv(&g, g, 32768, total) && g >= 0 && g <= 32768 &&
++            b >= 0 && png_muldiv(&b, b, 32768, total) && b >= 0 && b <= 32768 &&
++            r+g+b <= 32769)
++         {
++            /* We allow 0 coefficients here.  r+g+b may be 32769 if two or
++             * all of the coefficients were rounded up.  Handle this by
++             * reducing the *largest* coefficient by 1; this matches the
++             * approach used for the default coefficients in pngrtran.c
++             */
++            int add = 0;
+ 
+-         if (r+g+b > 32768)
+-            add = -1;
+-         else if (r+g+b < 32768)
+-            add = 1;
++            if (r+g+b > 32768)
++               add = -1;
++            else if (r+g+b < 32768)
++               add = 1;
+ 
+-         if (add != 0)
+-         {
+-            if (g >= r && g >= b)
+-               g += add;
+-            else if (r >= g && r >= b)
+-               r += add;
+-            else
+-               b += add;
+-         }
++            if (add != 0)
++            {
++               if (g >= r && g >= b)
++                  g += add;
++               else if (r >= g && r >= b)
++                  r += add;
++               else
++                  b += add;
++            }
+ 
+-         /* Check for an internal error. */
+-         if (r+g+b != 32768)
+-            png_error(png_ptr,
+-                "internal error handling cHRM coefficients");
++            /* Check for an internal error. */
++            if (r+g+b != 32768)
++               png_error(png_ptr,
++                   "internal error handling cHRM coefficients");
+ 
+-         else
+-         {
+-            png_ptr->rgb_to_gray_red_coeff   = (png_uint_16)r;
+-            png_ptr->rgb_to_gray_green_coeff = (png_uint_16)g;
++            else
++            {
++               png_ptr->rgb_to_gray_red_coeff   = (png_uint_16)r;
++               png_ptr->rgb_to_gray_green_coeff = (png_uint_16)g;
++            }
+          }
+       }
+-
+-      /* This is a png_error at present even though it could be ignored -
+-       * it should never happen, but it is important that if it does, the
+-       * bug is fixed.
+-       */
+       else
+-         png_error(png_ptr, "internal error handling cHRM->XYZ");
++#  endif /* check_chromaticities */
++      {
++         /* Use the historical REC 709 (etc) values: */
++         png_ptr->rgb_to_gray_red_coeff   = 6968;
++         png_ptr->rgb_to_gray_green_coeff = 23434;
++         /* png_ptr->rgb_to_gray_blue_coeff  = 2366; */
++      }
+    }
+ }
+ #endif /* READ_RGB_TO_GRAY */
+ 
+-#endif /* COLORSPACE */
+-
+ void /* PRIVATE */
+ png_check_IHDR(png_const_structrp png_ptr,
+     png_uint_32 width, png_uint_32 height, int bit_depth,
+@@ -3320,7 +2764,27 @@ png_fixed(png_const_structrp png_ptr, double fp, png_const_charp text)
+ }
+ #endif
+ 
+-#if defined(PNG_GAMMA_SUPPORTED) || defined(PNG_COLORSPACE_SUPPORTED) ||\
++#if defined(PNG_FLOATING_POINT_SUPPORTED) && \
++   !defined(PNG_FIXED_POINT_MACRO_SUPPORTED) && \
++   (defined(PNG_cLLI_SUPPORTED) || defined(PNG_mDCV_SUPPORTED))
++png_uint_32
++png_fixed_ITU(png_const_structrp png_ptr, double fp, png_const_charp text)
++{
++   double r = floor(10000 * fp + .5);
++
++   if (r > 2147483647. || r < 0)
++      png_fixed_error(png_ptr, text);
++
++#  ifndef PNG_ERROR_TEXT_SUPPORTED
++   PNG_UNUSED(text)
++#  endif
++
++   return (png_uint_32)r;
++}
++#endif
++
++
++#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_COLORSPACE_SUPPORTED) ||\
+     defined(PNG_INCH_CONVERSIONS_SUPPORTED) || defined(PNG_READ_pHYs_SUPPORTED)
+ /* muldiv functions */
+ /* This API takes signed arguments and rounds the result to the nearest
+@@ -3328,7 +2792,7 @@ png_fixed(png_const_structrp png_ptr, double fp, png_const_charp text)
+  * the nearest .00001).  Overflow and divide by zero are signalled in
+  * the result, a boolean - true on success, false on overflow.
+  */
+-int
++int /* PRIVATE */
+ png_muldiv(png_fixed_point_p res, png_fixed_point a, png_int_32 times,
+     png_int_32 divisor)
+ {
+@@ -3442,27 +2906,7 @@ png_muldiv(png_fixed_point_p res, png_fixed_point a, png_int_32 times,
+ 
+    return 0;
+ }
+-#endif /* READ_GAMMA || INCH_CONVERSIONS */
+-
+-#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_INCH_CONVERSIONS_SUPPORTED)
+-/* The following is for when the caller doesn't much care about the
+- * result.
+- */
+-png_fixed_point
+-png_muldiv_warn(png_const_structrp png_ptr, png_fixed_point a, png_int_32 times,
+-    png_int_32 divisor)
+-{
+-   png_fixed_point result;
+-
+-   if (png_muldiv(&result, a, times, divisor) != 0)
+-      return result;
+-
+-   png_warning(png_ptr, "fixed point overflow ignored");
+-   return 0;
+-}
+-#endif
+ 
+-#ifdef PNG_GAMMA_SUPPORTED /* more fixed point functions for gamma */
+ /* Calculate a reciprocal, return 0 on div-by-zero or overflow. */
+ png_fixed_point
+ png_reciprocal(png_fixed_point a)
+@@ -3481,26 +2925,38 @@ png_reciprocal(png_fixed_point a)
+ 
+    return 0; /* error/overflow */
+ }
++#endif /* READ_GAMMA || COLORSPACE || INCH_CONVERSIONS || READ_pHYS */
+ 
++#ifdef PNG_READ_GAMMA_SUPPORTED
+ /* This is the shared test on whether a gamma value is 'significant' - whether
+  * it is worth doing gamma correction.
+  */
+ int /* PRIVATE */
+ png_gamma_significant(png_fixed_point gamma_val)
+ {
++   /* sRGB:       1/2.2 == 0.4545(45)
++    * AdobeRGB:   1/(2+51/256) ~= 0.45471 5dp
++    *
++    * So the correction from AdobeRGB to sRGB (output) is:
++    *
++    *    2.2/(2+51/256) == 1.00035524
++    *
++    * I.e. vanishly small (<4E-4) but still detectable in 16-bit linear (+/-
++    * 23).  Note that the Adobe choice seems to be something intended to give an
++    * exact number with 8 binary fractional digits - it is the closest to 2.2
++    * that is possible a base 2 .8p representation.
++    */
+    return gamma_val < PNG_FP_1 - PNG_GAMMA_THRESHOLD_FIXED ||
+        gamma_val > PNG_FP_1 + PNG_GAMMA_THRESHOLD_FIXED;
+ }
+-#endif
+ 
+-#ifdef PNG_READ_GAMMA_SUPPORTED
+-#ifdef PNG_16BIT_SUPPORTED
++#ifndef PNG_FLOATING_ARITHMETIC_SUPPORTED
+ /* A local convenience routine. */
+ static png_fixed_point
+ png_product2(png_fixed_point a, png_fixed_point b)
+ {
+-   /* The required result is 1/a * 1/b; the following preserves accuracy. */
+-#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
++   /* The required result is a * b; the following preserves accuracy. */
++#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED /* Should now be unused */
+    double r = a * 1E-5;
+    r *= b;
+    r = floor(r+.5);
+@@ -3516,9 +2972,8 @@ png_product2(png_fixed_point a, png_fixed_point b)
+ 
+    return 0; /* overflow */
+ }
+-#endif /* 16BIT */
++#endif /* FLOATING_ARITHMETIC */
+ 
+-/* The inverse of the above. */
+ png_fixed_point
+ png_reciprocal2(png_fixed_point a, png_fixed_point b)
+ {
+@@ -4171,10 +3626,27 @@ png_destroy_gamma_table(png_structrp png_ptr)
+  * tables, we don't make a full table if we are reducing to 8-bit in
+  * the future.  Note also how the gamma_16 tables are segmented so that
+  * we don't need to allocate > 64K chunks for a full 16-bit table.
++ *
++ * TODO: move this to pngrtran.c and make it static.  Better yet create
++ * pngcolor.c and put all the PNG_COLORSPACE stuff in there.
+  */
++#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
++   defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \
++   defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
++#  define GAMMA_TRANSFORMS 1 /* #ifdef CSE */
++#else
++#  define GAMMA_TRANSFORMS 0
++#endif
++
+ void /* PRIVATE */
+ png_build_gamma_table(png_structrp png_ptr, int bit_depth)
+ {
++   png_fixed_point file_gamma, screen_gamma;
++   png_fixed_point correction;
++#  if GAMMA_TRANSFORMS
++      png_fixed_point file_to_linear, linear_to_screen;
++#  endif
++
+    png_debug(1, "in png_build_gamma_table");
+ 
+    /* Remove any existing table; this copes with multiple calls to
+@@ -4189,27 +3661,44 @@ png_build_gamma_table(png_structrp png_ptr, int bit_depth)
+       png_destroy_gamma_table(png_ptr);
+    }
+ 
++   /* The following fields are set, finally, in png_init_read_transformations.
++    * If file_gamma is 0 (unset) nothing can be done otherwise if screen_gamma
++    * is 0 (unset) there is no gamma correction but to/from linear is possible.
++    */
++   file_gamma = png_ptr->file_gamma;
++   screen_gamma = png_ptr->screen_gamma;
++#  if GAMMA_TRANSFORMS
++      file_to_linear = png_reciprocal(file_gamma);
++#  endif
++
++   if (screen_gamma > 0)
++   {
++#     if GAMMA_TRANSFORMS
++         linear_to_screen = png_reciprocal(screen_gamma);
++#     endif
++      correction = png_reciprocal2(screen_gamma, file_gamma);
++   }
++   else /* screen gamma unknown */
++   {
++#     if GAMMA_TRANSFORMS
++         linear_to_screen = file_gamma;
++#     endif
++      correction = PNG_FP_1;
++   }
++
+    if (bit_depth <= 8)
+    {
+-      png_build_8bit_table(png_ptr, &png_ptr->gamma_table,
+-          png_ptr->screen_gamma > 0 ?
+-          png_reciprocal2(png_ptr->colorspace.gamma,
+-          png_ptr->screen_gamma) : PNG_FP_1);
++      png_build_8bit_table(png_ptr, &png_ptr->gamma_table, correction);
+ 
+-#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
+-   defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \
+-   defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
++#if GAMMA_TRANSFORMS
+       if ((png_ptr->transformations & (PNG_COMPOSE | PNG_RGB_TO_GRAY)) != 0)
+       {
+-         png_build_8bit_table(png_ptr, &png_ptr->gamma_to_1,
+-             png_reciprocal(png_ptr->colorspace.gamma));
++         png_build_8bit_table(png_ptr, &png_ptr->gamma_to_1, file_to_linear);
+ 
+          png_build_8bit_table(png_ptr, &png_ptr->gamma_from_1,
+-             png_ptr->screen_gamma > 0 ?
+-             png_reciprocal(png_ptr->screen_gamma) :
+-             png_ptr->colorspace.gamma/* Probably doing rgb_to_gray */);
++            linear_to_screen);
+       }
+-#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */
++#endif /* GAMMA_TRANSFORMS */
+    }
+ #ifdef PNG_16BIT_SUPPORTED
+    else
+@@ -4275,32 +3764,26 @@ png_build_gamma_table(png_structrp png_ptr, int bit_depth)
+        * reduced to 8 bits.
+        */
+       if ((png_ptr->transformations & (PNG_16_TO_8 | PNG_SCALE_16_TO_8)) != 0)
+-          png_build_16to8_table(png_ptr, &png_ptr->gamma_16_table, shift,
+-          png_ptr->screen_gamma > 0 ? png_product2(png_ptr->colorspace.gamma,
+-          png_ptr->screen_gamma) : PNG_FP_1);
+-
++         png_build_16to8_table(png_ptr, &png_ptr->gamma_16_table, shift,
++            png_reciprocal(correction));
+       else
+-          png_build_16bit_table(png_ptr, &png_ptr->gamma_16_table, shift,
+-          png_ptr->screen_gamma > 0 ? png_reciprocal2(png_ptr->colorspace.gamma,
+-          png_ptr->screen_gamma) : PNG_FP_1);
++         png_build_16bit_table(png_ptr, &png_ptr->gamma_16_table, shift,
++            correction);
+ 
+-#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
+-   defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \
+-   defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
++#  if GAMMA_TRANSFORMS
+       if ((png_ptr->transformations & (PNG_COMPOSE | PNG_RGB_TO_GRAY)) != 0)
+       {
+          png_build_16bit_table(png_ptr, &png_ptr->gamma_16_to_1, shift,
+-             png_reciprocal(png_ptr->colorspace.gamma));
++            file_to_linear);
+ 
+          /* Notice that the '16 from 1' table should be full precision, however
+           * the lookup on this table still uses gamma_shift, so it can't be.
+           * TODO: fix this.
+           */
+          png_build_16bit_table(png_ptr, &png_ptr->gamma_16_from_1, shift,
+-             png_ptr->screen_gamma > 0 ? png_reciprocal(png_ptr->screen_gamma) :
+-             png_ptr->colorspace.gamma/* Probably doing rgb_to_gray */);
++            linear_to_screen);
+       }
+-#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */
++#endif /* GAMMA_TRANSFORMS */
+    }
+ #endif /* 16BIT */
+ }
+diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/png.h b/src/java.desktop/share/native/libsplashscreen/libpng/png.h
+index 9f61a773c..ede12c34f 100644
+--- a/src/java.desktop/share/native/libsplashscreen/libpng/png.h
++++ b/src/java.desktop/share/native/libsplashscreen/libpng/png.h
+@@ -29,9 +29,9 @@
+  * However, the following notice accompanied the original version of this
+  * file and, per its terms, should not be removed:
+  *
+- * libpng version 1.6.43
++ * libpng version 1.6.47
+  *
+- * Copyright (c) 2018-2024 Cosmin Truta
++ * Copyright (c) 2018-2025 Cosmin Truta
+  * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
+  * Copyright (c) 1996-1997 Andreas Dilger
+  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
+@@ -43,7 +43,7 @@
+  *   libpng versions 0.89, June 1996, through 0.96, May 1997: Andreas Dilger
+  *   libpng versions 0.97, January 1998, through 1.6.35, July 2018:
+  *     Glenn Randers-Pehrson
+- *   libpng versions 1.6.36, December 2018, through 1.6.43, February 2024:
++ *   libpng versions 1.6.36, December 2018, through 1.6.47, February 2025:
+  *     Cosmin Truta
+  *   See also "Contributing Authors", below.
+  */
+@@ -55,8 +55,8 @@
+  * PNG Reference Library License version 2
+  * ---------------------------------------
+  *
+- *  * Copyright (c) 1995-2024 The PNG Reference Library Authors.
+- *  * Copyright (c) 2018-2024 Cosmin Truta.
++ *  * Copyright (c) 1995-2025 The PNG Reference Library Authors.
++ *  * Copyright (c) 2018-2025 Cosmin Truta.
+  *  * Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson.
+  *  * Copyright (c) 1996-1997 Andreas Dilger.
+  *  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
+@@ -267,7 +267,7 @@
+  *    ...
+  *    1.5.30                  15    10530  15.so.15.30[.0]
+  *    ...
+- *    1.6.43                  16    10643  16.so.16.43[.0]
++ *    1.6.47                  16    10647  16.so.16.47[.0]
+  *
+  *    Henceforth the source version will match the shared-library major and
+  *    minor numbers; the shared-library major version number will be used for
+@@ -303,7 +303,7 @@
+  */
+ 
+ /* Version information for png.h - this should match the version in png.c */
+-#define PNG_LIBPNG_VER_STRING "1.6.43"
++#define PNG_LIBPNG_VER_STRING "1.6.47"
+ #define PNG_HEADER_VERSION_STRING " libpng version " PNG_LIBPNG_VER_STRING "\n"
+ 
+ /* The versions of shared library builds should stay in sync, going forward */
+@@ -314,18 +314,18 @@
+ /* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */
+ #define PNG_LIBPNG_VER_MAJOR   1
+ #define PNG_LIBPNG_VER_MINOR   6
+-#define PNG_LIBPNG_VER_RELEASE 43
++#define PNG_LIBPNG_VER_RELEASE 47
+ 
+ /* This should be zero for a public release, or non-zero for a
+  * development version.
+  */
+-#define PNG_LIBPNG_VER_BUILD  0
++#define PNG_LIBPNG_VER_BUILD 0
+ 
+ /* Release Status */
+-#define PNG_LIBPNG_BUILD_ALPHA    1
+-#define PNG_LIBPNG_BUILD_BETA     2
+-#define PNG_LIBPNG_BUILD_RC       3
+-#define PNG_LIBPNG_BUILD_STABLE   4
++#define PNG_LIBPNG_BUILD_ALPHA               1
++#define PNG_LIBPNG_BUILD_BETA                2
++#define PNG_LIBPNG_BUILD_RC                  3
++#define PNG_LIBPNG_BUILD_STABLE              4
+ #define PNG_LIBPNG_BUILD_RELEASE_STATUS_MASK 7
+ 
+ /* Release-Specific Flags */
+@@ -345,7 +345,7 @@
+  * From version 1.0.1 it is:
+  * XXYYZZ, where XX=major, YY=minor, ZZ=release
+  */
+-#define PNG_LIBPNG_VER 10643 /* 1.6.43 */
++#define PNG_LIBPNG_VER 10647 /* 1.6.47 */
+ 
+ /* Library configuration: these options cannot be changed after
+  * the library has been built.
+@@ -455,7 +455,7 @@ extern "C" {
+ /* This triggers a compiler error in png.c, if png.c and png.h
+  * do not agree upon the version number.
+  */
+-typedef char* png_libpng_version_1_6_43;
++typedef char* png_libpng_version_1_6_47;
+ 
+ /* Basic control structions.  Read libpng-manual.txt or libpng.3 for more info.
+  *
+@@ -773,6 +773,21 @@ typedef png_unknown_chunk * * png_unknown_chunkpp;
+ #define PNG_INFO_sCAL 0x4000U  /* ESR, 1.0.6 */
+ #define PNG_INFO_IDAT 0x8000U  /* ESR, 1.0.6 */
+ #define PNG_INFO_eXIf 0x10000U /* GR-P, 1.6.31 */
++#define PNG_INFO_cICP 0x20000U /* PNGv3: 1.6.45 */
++#define PNG_INFO_cLLI 0x40000U /* PNGv3: 1.6.45 */
++#define PNG_INFO_mDCV 0x80000U /* PNGv3: 1.6.45 */
++/* APNG: these chunks are stored as unknown, these flags are never set
++ * however they are provided as a convenience for implementors of APNG and
++ * avoids any merge conflicts.
++ *
++ * Private chunks: these chunk names violate the chunk name recommendations
++ * because the chunk definitions have no signature and because the private
++ * chunks with these names have been reserved.  Private definitions should
++ * avoid them.
++ */
++#define PNG_INFO_acTL 0x100000U /* PNGv3: 1.6.45: unknown */
++#define PNG_INFO_fcTL 0x200000U /* PNGv3: 1.6.45: unknown */
++#define PNG_INFO_fdAT 0x400000U /* PNGv3: 1.6.45: unknown */
+ 
+ /* This is used for the transformation routines, as some of them
+  * change these values for the row.  It also should enable using
+@@ -852,7 +867,7 @@ typedef PNG_CALLBACK(int, *png_user_chunk_ptr, (png_structp,
+  * your compiler.  This may be very difficult - try using a different compiler
+  * to build the library!
+  */
+-PNG_FUNCTION(void, (PNGCAPI *png_longjmp_ptr), PNGARG((jmp_buf, int)), typedef);
++PNG_FUNCTION(void, (PNGCAPI *png_longjmp_ptr), (jmp_buf, int), typedef);
+ #endif
+ 
+ /* Transform masks for the high-level interface */
+@@ -2002,6 +2017,46 @@ PNG_FIXED_EXPORT(233, void, png_set_cHRM_XYZ_fixed, (png_const_structrp png_ptr,
+     png_fixed_point int_blue_Z))
+ #endif
+ 
++#ifdef PNG_cICP_SUPPORTED
++PNG_EXPORT(250, png_uint_32, png_get_cICP, (png_const_structrp png_ptr,
++    png_const_inforp info_ptr, png_bytep colour_primaries,
++    png_bytep transfer_function, png_bytep matrix_coefficients,
++    png_bytep video_full_range_flag));
++#endif
++
++#ifdef PNG_cICP_SUPPORTED
++PNG_EXPORT(251, void, png_set_cICP, (png_const_structrp png_ptr,
++    png_inforp info_ptr, png_byte colour_primaries,
++    png_byte transfer_function, png_byte matrix_coefficients,
++    png_byte video_full_range_flag));
++#endif
++
++#ifdef PNG_cLLI_SUPPORTED
++PNG_FP_EXPORT(252, png_uint_32, png_get_cLLI, (png_const_structrp png_ptr,
++         png_const_inforp info_ptr, double *maximum_content_light_level,
++         double *maximum_frame_average_light_level))
++PNG_FIXED_EXPORT(253, png_uint_32, png_get_cLLI_fixed,
++    (png_const_structrp png_ptr, png_const_inforp info_ptr,
++    /* The values below are in cd/m2 (nits) and are scaled by 10,000; not
++     * 100,000 as in the case of png_fixed_point.
++     */
++    png_uint_32p maximum_content_light_level_scaled_by_10000,
++    png_uint_32p maximum_frame_average_light_level_scaled_by_10000))
++#endif
++
++#ifdef PNG_cLLI_SUPPORTED
++PNG_FP_EXPORT(254, void, png_set_cLLI, (png_const_structrp png_ptr,
++         png_inforp info_ptr, double maximum_content_light_level,
++         double maximum_frame_average_light_level))
++PNG_FIXED_EXPORT(255, void, png_set_cLLI_fixed, (png_const_structrp png_ptr,
++    png_inforp info_ptr,
++    /* The values below are in cd/m2 (nits) and are scaled by 10,000; not
++     * 100,000 as in the case of png_fixed_point.
++     */
++    png_uint_32 maximum_content_light_level_scaled_by_10000,
++    png_uint_32 maximum_frame_average_light_level_scaled_by_10000))
++#endif
++
+ #ifdef PNG_eXIf_SUPPORTED
+ PNG_EXPORT(246, png_uint_32, png_get_eXIf, (png_const_structrp png_ptr,
+     png_inforp info_ptr, png_bytep *exif));
+@@ -2046,6 +2101,60 @@ PNG_EXPORT(144, void, png_set_IHDR, (png_const_structrp png_ptr,
+     int color_type, int interlace_method, int compression_method,
+     int filter_method));
+ 
++#ifdef PNG_mDCV_SUPPORTED
++PNG_FP_EXPORT(256, png_uint_32, png_get_mDCV, (png_const_structrp png_ptr,
++    png_const_inforp info_ptr,
++    /* The chromaticities of the mastering display.  As cHRM, but independent of
++     * the encoding endpoints in cHRM, or cICP, or iCCP.  These values will
++     * always be in the range 0 to 1.3107.
++     */
++    double *white_x, double *white_y, double *red_x, double *red_y,
++    double *green_x, double *green_y, double *blue_x, double *blue_y,
++    /* Mastering display luminance in cd/m2 (nits). */
++    double *mastering_display_maximum_luminance,
++    double *mastering_display_minimum_luminance))
++
++PNG_FIXED_EXPORT(257, png_uint_32, png_get_mDCV_fixed,
++    (png_const_structrp png_ptr, png_const_inforp info_ptr,
++    png_fixed_point *int_white_x, png_fixed_point *int_white_y,
++    png_fixed_point *int_red_x, png_fixed_point *int_red_y,
++    png_fixed_point *int_green_x, png_fixed_point *int_green_y,
++    png_fixed_point *int_blue_x, png_fixed_point *int_blue_y,
++    /* Mastering display luminance in cd/m2 (nits) multiplied (scaled) by
++     * 10,000.
++     */
++    png_uint_32p mastering_display_maximum_luminance_scaled_by_10000,
++    png_uint_32p mastering_display_minimum_luminance_scaled_by_10000))
++#endif
++
++#ifdef PNG_mDCV_SUPPORTED
++PNG_FP_EXPORT(258, void, png_set_mDCV, (png_const_structrp png_ptr,
++    png_inforp info_ptr,
++    /* The chromaticities of the mastering display.  As cHRM, but independent of
++     * the encoding endpoints in cHRM, or cICP, or iCCP.
++     */
++    double white_x, double white_y, double red_x, double red_y, double green_x,
++    double green_y, double blue_x, double blue_y,
++    /* Mastering display luminance in cd/m2 (nits). */
++    double mastering_display_maximum_luminance,
++    double mastering_display_minimum_luminance))
++
++PNG_FIXED_EXPORT(259, void, png_set_mDCV_fixed, (png_const_structrp png_ptr,
++    png_inforp info_ptr,
++    /* The admissible range of these values is not the full range of a PNG
++     * fixed point value.  Negative values cannot be encoded and the maximum
++     * value is about 1.3 */
++    png_fixed_point int_white_x, png_fixed_point int_white_y,
++    png_fixed_point int_red_x, png_fixed_point int_red_y,
++    png_fixed_point int_green_x, png_fixed_point int_green_y,
++    png_fixed_point int_blue_x, png_fixed_point int_blue_y,
++    /* These are PNG unsigned 4 byte values: 31-bit unsigned values.  The MSB
++     * must be zero.
++     */
++    png_uint_32 mastering_display_maximum_luminance_scaled_by_10000,
++    png_uint_32 mastering_display_minimum_luminance_scaled_by_10000))
++#endif
++
+ #ifdef PNG_oFFs_SUPPORTED
+ PNG_EXPORT(145, png_uint_32, png_get_oFFs, (png_const_structrp png_ptr,
+    png_const_inforp info_ptr, png_int_32 *offset_x, png_int_32 *offset_y,
+@@ -3266,7 +3375,7 @@ PNG_EXPORT(244, int, png_set_option, (png_structrp png_ptr, int option,
+  * one to use is one more than this.)
+  */
+ #ifdef PNG_EXPORT_LAST_ORDINAL
+-  PNG_EXPORT_LAST_ORDINAL(249);
++  PNG_EXPORT_LAST_ORDINAL(259);
+ #endif
+ 
+ #ifdef __cplusplus
+diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngconf.h b/src/java.desktop/share/native/libsplashscreen/libpng/pngconf.h
+index b3b441b11..70bca6fa1 100644
+--- a/src/java.desktop/share/native/libsplashscreen/libpng/pngconf.h
++++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngconf.h
+@@ -29,9 +29,9 @@
+  * However, the following notice accompanied the original version of this
+  * file and, per its terms, should not be removed:
+  *
+- * libpng version 1.6.43
++ * libpng version 1.6.47
+  *
+- * Copyright (c) 2018-2024 Cosmin Truta
++ * Copyright (c) 2018-2025 Cosmin Truta
+  * Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson
+  * Copyright (c) 1996-1997 Andreas Dilger
+  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
+@@ -116,7 +116,7 @@
+ 
+ /* The PNGARG macro was used in versions of libpng prior to 1.6.0 to protect
+  * against legacy (pre ISOC90) compilers that did not understand function
+- * prototypes.  It is not required for modern C compilers.
++ * prototypes.  [Deprecated.]
+  */
+ #ifndef PNGARG
+ #  define PNGARG(arglist) arglist
+@@ -326,7 +326,7 @@
+ 
+ #ifndef PNG_EXPORTA
+ #  define PNG_EXPORTA(ordinal, type, name, args, attributes) \
+-      PNG_FUNCTION(PNG_EXPORT_TYPE(type), (PNGAPI name), PNGARG(args), \
++      PNG_FUNCTION(PNG_EXPORT_TYPE(type), (PNGAPI name), args, \
+       PNG_LINKAGE_API attributes)
+ #endif
+ 
+@@ -344,7 +344,7 @@
+ #endif
+ 
+ #ifndef PNG_CALLBACK
+-#  define PNG_CALLBACK(type, name, args) type (PNGCBAPI name) PNGARG(args)
++#  define PNG_CALLBACK(type, name, args) type (PNGCBAPI name) args
+ #endif
+ 
+ /* Support for compiler specific function attributes.  These are used
+diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngerror.c b/src/java.desktop/share/native/libsplashscreen/libpng/pngerror.c
+index ea8dd1721..ea0103331 100644
+--- a/src/java.desktop/share/native/libsplashscreen/libpng/pngerror.c
++++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngerror.c
+@@ -48,13 +48,14 @@
+ 
+ #if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
+ 
+-static PNG_FUNCTION(void, png_default_error,PNGARG((png_const_structrp png_ptr,
+-    png_const_charp error_message)),PNG_NORETURN);
++static PNG_FUNCTION(void /* PRIVATE */,
++png_default_error,(png_const_structrp png_ptr, png_const_charp error_message),
++    PNG_NORETURN);
+ 
+ #ifdef PNG_WARNINGS_SUPPORTED
+ static void /* PRIVATE */
+-png_default_warning PNGARG((png_const_structrp png_ptr,
+-    png_const_charp warning_message));
++png_default_warning(png_const_structrp png_ptr,
++    png_const_charp warning_message);
+ #endif /* WARNINGS */
+ 
+ /* This function is called whenever there is a fatal error.  This function
+@@ -963,23 +964,37 @@ png_safe_warning(png_structp png_nonconst_ptr, png_const_charp warning_message)
+ int /* PRIVATE */
+ png_safe_execute(png_imagep image, int (*function)(png_voidp), png_voidp arg)
+ {
+-   png_voidp saved_error_buf = image->opaque->error_buf;
++   const png_voidp saved_error_buf = image->opaque->error_buf;
+    jmp_buf safe_jmpbuf;
+-   int result;
+ 
+    /* Safely execute function(arg), with png_error returning back here. */
+    if (setjmp(safe_jmpbuf) == 0)
+    {
++      int result;
++
+       image->opaque->error_buf = safe_jmpbuf;
+       result = function(arg);
+       image->opaque->error_buf = saved_error_buf;
+-      return result;
++
++      if (result)
++         return 1; /* success */
+    }
+ 
+-   /* On png_error, return via longjmp, pop the jmpbuf, and free the image. */
++   /* The function failed either because of a caught png_error and a regular
++    * return of false above or because of an uncaught png_error from the
++    * function itself.  Ensure that the error_buf is always set back to the
++    * value saved above:
++    */
+    image->opaque->error_buf = saved_error_buf;
+-   png_image_free(image);
+-   return 0;
++
++   /* On the final false return, when about to return control to the caller, the
++    * image is freed (png_image_free does this check but it is duplicated here
++    * for clarity:
++    */
++   if (saved_error_buf == NULL)
++      png_image_free(image);
++
++   return 0; /* failure */
+ }
+ #endif /* SIMPLIFIED READ || SIMPLIFIED_WRITE */
+ #endif /* READ || WRITE */
+diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngget.c b/src/java.desktop/share/native/libsplashscreen/libpng/pngget.c
+index 41e0a5abc..d67adbae2 100644
+--- a/src/java.desktop/share/native/libsplashscreen/libpng/pngget.c
++++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngget.c
+@@ -409,7 +409,13 @@ png_fixed_inches_from_microns(png_const_structrp png_ptr, png_int_32 microns)
+     * Notice that this can overflow - a warning is output and 0 is
+     * returned.
+     */
+-   return png_muldiv_warn(png_ptr, microns, 500, 127);
++   png_fixed_point result;
++
++   if (png_muldiv(&result, microns, 500, 127) != 0)
++      return result;
++
++   png_warning(png_ptr, "fixed point overflow ignored");
++   return 0;
+ }
+ 
+ png_fixed_point PNGAPI
+@@ -419,7 +425,7 @@ png_get_x_offset_inches_fixed(png_const_structrp png_ptr,
+    return png_fixed_inches_from_microns(png_ptr,
+        png_get_x_offset_microns(png_ptr, info_ptr));
+ }
+-#endif
++#endif /* FIXED_POINT */
+ 
+ #ifdef PNG_FIXED_POINT_SUPPORTED
+ png_fixed_point PNGAPI
+@@ -547,44 +553,31 @@ png_get_bKGD(png_const_structrp png_ptr, png_inforp info_ptr,
+ #  ifdef PNG_FLOATING_POINT_SUPPORTED
+ png_uint_32 PNGAPI
+ png_get_cHRM(png_const_structrp png_ptr, png_const_inforp info_ptr,
+-    double *white_x, double *white_y, double *red_x, double *red_y,
+-    double *green_x, double *green_y, double *blue_x, double *blue_y)
++    double *whitex, double *whitey, double *redx, double *redy,
++    double *greenx, double *greeny, double *bluex, double *bluey)
+ {
+    png_debug1(1, "in %s retrieval function", "cHRM");
+ 
+-   /* Quiet API change: this code used to only return the end points if a cHRM
+-    * chunk was present, but the end points can also come from iCCP or sRGB
+-    * chunks, so in 1.6.0 the png_get_ APIs return the end points regardless and
+-    * the png_set_ APIs merely check that set end points are mutually
+-    * consistent.
+-    */
++   /* PNGv3: this just returns the values store from the cHRM, if any. */
+    if (png_ptr != NULL && info_ptr != NULL &&
+-      (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
++       (info_ptr->valid & PNG_INFO_cHRM) != 0)
+    {
+-      if (white_x != NULL)
+-         *white_x = png_float(png_ptr,
+-             info_ptr->colorspace.end_points_xy.whitex, "cHRM white X");
+-      if (white_y != NULL)
+-         *white_y = png_float(png_ptr,
+-             info_ptr->colorspace.end_points_xy.whitey, "cHRM white Y");
+-      if (red_x != NULL)
+-         *red_x = png_float(png_ptr, info_ptr->colorspace.end_points_xy.redx,
+-             "cHRM red X");
+-      if (red_y != NULL)
+-         *red_y = png_float(png_ptr, info_ptr->colorspace.end_points_xy.redy,
+-             "cHRM red Y");
+-      if (green_x != NULL)
+-         *green_x = png_float(png_ptr,
+-             info_ptr->colorspace.end_points_xy.greenx, "cHRM green X");
+-      if (green_y != NULL)
+-         *green_y = png_float(png_ptr,
+-             info_ptr->colorspace.end_points_xy.greeny, "cHRM green Y");
+-      if (blue_x != NULL)
+-         *blue_x = png_float(png_ptr, info_ptr->colorspace.end_points_xy.bluex,
+-             "cHRM blue X");
+-      if (blue_y != NULL)
+-         *blue_y = png_float(png_ptr, info_ptr->colorspace.end_points_xy.bluey,
+-             "cHRM blue Y");
++      if (whitex != NULL)
++         *whitex = png_float(png_ptr, info_ptr->cHRM.whitex, "cHRM wx");
++      if (whitey != NULL)
++         *whitey = png_float(png_ptr, info_ptr->cHRM.whitey, "cHRM wy");
++      if (redx   != NULL)
++         *redx   = png_float(png_ptr, info_ptr->cHRM.redx,   "cHRM rx");
++      if (redy   != NULL)
++         *redy   = png_float(png_ptr, info_ptr->cHRM.redy,   "cHRM ry");
++      if (greenx != NULL)
++         *greenx = png_float(png_ptr, info_ptr->cHRM.greenx, "cHRM gx");
++      if (greeny != NULL)
++         *greeny = png_float(png_ptr, info_ptr->cHRM.greeny, "cHRM gy");
++      if (bluex  != NULL)
++         *bluex  = png_float(png_ptr, info_ptr->cHRM.bluex,  "cHRM bx");
++      if (bluey  != NULL)
++         *bluey  = png_float(png_ptr, info_ptr->cHRM.bluey,  "cHRM by");
+       return PNG_INFO_cHRM;
+    }
+ 
+@@ -597,38 +590,31 @@ png_get_cHRM_XYZ(png_const_structrp png_ptr, png_const_inforp info_ptr,
+     double *green_Y, double *green_Z, double *blue_X, double *blue_Y,
+     double *blue_Z)
+ {
++   png_XYZ XYZ;
+    png_debug1(1, "in %s retrieval function", "cHRM_XYZ(float)");
+ 
+    if (png_ptr != NULL && info_ptr != NULL &&
+-       (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
++       (info_ptr->valid & PNG_INFO_cHRM) != 0 &&
++       png_XYZ_from_xy(&XYZ, &info_ptr->cHRM) == 0)
+    {
+       if (red_X != NULL)
+-         *red_X = png_float(png_ptr, info_ptr->colorspace.end_points_XYZ.red_X,
+-             "cHRM red X");
++         *red_X = png_float(png_ptr, XYZ.red_X, "cHRM red X");
+       if (red_Y != NULL)
+-         *red_Y = png_float(png_ptr, info_ptr->colorspace.end_points_XYZ.red_Y,
+-             "cHRM red Y");
++         *red_Y = png_float(png_ptr, XYZ.red_Y, "cHRM red Y");
+       if (red_Z != NULL)
+-         *red_Z = png_float(png_ptr, info_ptr->colorspace.end_points_XYZ.red_Z,
+-             "cHRM red Z");
++         *red_Z = png_float(png_ptr, XYZ.red_Z, "cHRM red Z");
+       if (green_X != NULL)
+-         *green_X = png_float(png_ptr,
+-             info_ptr->colorspace.end_points_XYZ.green_X, "cHRM green X");
++         *green_X = png_float(png_ptr, XYZ.green_X, "cHRM green X");
+       if (green_Y != NULL)
+-         *green_Y = png_float(png_ptr,
+-             info_ptr->colorspace.end_points_XYZ.green_Y, "cHRM green Y");
++         *green_Y = png_float(png_ptr, XYZ.green_Y, "cHRM green Y");
+       if (green_Z != NULL)
+-         *green_Z = png_float(png_ptr,
+-             info_ptr->colorspace.end_points_XYZ.green_Z, "cHRM green Z");
++         *green_Z = png_float(png_ptr, XYZ.green_Z, "cHRM green Z");
+       if (blue_X != NULL)
+-         *blue_X = png_float(png_ptr,
+-             info_ptr->colorspace.end_points_XYZ.blue_X, "cHRM blue X");
++         *blue_X = png_float(png_ptr, XYZ.blue_X, "cHRM blue X");
+       if (blue_Y != NULL)
+-         *blue_Y = png_float(png_ptr,
+-             info_ptr->colorspace.end_points_XYZ.blue_Y, "cHRM blue Y");
++         *blue_Y = png_float(png_ptr, XYZ.blue_Y, "cHRM blue Y");
+       if (blue_Z != NULL)
+-         *blue_Z = png_float(png_ptr,
+-             info_ptr->colorspace.end_points_XYZ.blue_Z, "cHRM blue Z");
++         *blue_Z = png_float(png_ptr, XYZ.blue_Z, "cHRM blue Z");
+       return PNG_INFO_cHRM;
+    }
+ 
+@@ -645,29 +631,22 @@ png_get_cHRM_XYZ_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr,
+     png_fixed_point *int_blue_X, png_fixed_point *int_blue_Y,
+     png_fixed_point *int_blue_Z)
+ {
++   png_XYZ XYZ;
+    png_debug1(1, "in %s retrieval function", "cHRM_XYZ");
+ 
+    if (png_ptr != NULL && info_ptr != NULL &&
+-      (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
++       (info_ptr->valid & PNG_INFO_cHRM) != 0U &&
++       png_XYZ_from_xy(&XYZ, &info_ptr->cHRM) == 0)
+    {
+-      if (int_red_X != NULL)
+-         *int_red_X = info_ptr->colorspace.end_points_XYZ.red_X;
+-      if (int_red_Y != NULL)
+-         *int_red_Y = info_ptr->colorspace.end_points_XYZ.red_Y;
+-      if (int_red_Z != NULL)
+-         *int_red_Z = info_ptr->colorspace.end_points_XYZ.red_Z;
+-      if (int_green_X != NULL)
+-         *int_green_X = info_ptr->colorspace.end_points_XYZ.green_X;
+-      if (int_green_Y != NULL)
+-         *int_green_Y = info_ptr->colorspace.end_points_XYZ.green_Y;
+-      if (int_green_Z != NULL)
+-         *int_green_Z = info_ptr->colorspace.end_points_XYZ.green_Z;
+-      if (int_blue_X != NULL)
+-         *int_blue_X = info_ptr->colorspace.end_points_XYZ.blue_X;
+-      if (int_blue_Y != NULL)
+-         *int_blue_Y = info_ptr->colorspace.end_points_XYZ.blue_Y;
+-      if (int_blue_Z != NULL)
+-         *int_blue_Z = info_ptr->colorspace.end_points_XYZ.blue_Z;
++      if (int_red_X != NULL) *int_red_X = XYZ.red_X;
++      if (int_red_Y != NULL) *int_red_Y = XYZ.red_Y;
++      if (int_red_Z != NULL) *int_red_Z = XYZ.red_Z;
++      if (int_green_X != NULL) *int_green_X = XYZ.green_X;
++      if (int_green_Y != NULL) *int_green_Y = XYZ.green_Y;
++      if (int_green_Z != NULL) *int_green_Z = XYZ.green_Z;
++      if (int_blue_X != NULL) *int_blue_X = XYZ.blue_X;
++      if (int_blue_Y != NULL) *int_blue_Y = XYZ.blue_Y;
++      if (int_blue_Z != NULL) *int_blue_Z = XYZ.blue_Z;
+       return PNG_INFO_cHRM;
+    }
+ 
+@@ -676,31 +655,24 @@ png_get_cHRM_XYZ_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr,
+ 
+ png_uint_32 PNGAPI
+ png_get_cHRM_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr,
+-    png_fixed_point *white_x, png_fixed_point *white_y, png_fixed_point *red_x,
+-    png_fixed_point *red_y, png_fixed_point *green_x, png_fixed_point *green_y,
+-    png_fixed_point *blue_x, png_fixed_point *blue_y)
++    png_fixed_point *whitex, png_fixed_point *whitey, png_fixed_point *redx,
++    png_fixed_point *redy, png_fixed_point *greenx, png_fixed_point *greeny,
++    png_fixed_point *bluex, png_fixed_point *bluey)
+ {
+    png_debug1(1, "in %s retrieval function", "cHRM");
+ 
++   /* PNGv3: this just returns the values store from the cHRM, if any. */
+    if (png_ptr != NULL && info_ptr != NULL &&
+-      (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
++       (info_ptr->valid & PNG_INFO_cHRM) != 0)
+    {
+-      if (white_x != NULL)
+-         *white_x = info_ptr->colorspace.end_points_xy.whitex;
+-      if (white_y != NULL)
+-         *white_y = info_ptr->colorspace.end_points_xy.whitey;
+-      if (red_x != NULL)
+-         *red_x = info_ptr->colorspace.end_points_xy.redx;
+-      if (red_y != NULL)
+-         *red_y = info_ptr->colorspace.end_points_xy.redy;
+-      if (green_x != NULL)
+-         *green_x = info_ptr->colorspace.end_points_xy.greenx;
+-      if (green_y != NULL)
+-         *green_y = info_ptr->colorspace.end_points_xy.greeny;
+-      if (blue_x != NULL)
+-         *blue_x = info_ptr->colorspace.end_points_xy.bluex;
+-      if (blue_y != NULL)
+-         *blue_y = info_ptr->colorspace.end_points_xy.bluey;
++      if (whitex != NULL) *whitex = info_ptr->cHRM.whitex;
++      if (whitey != NULL) *whitey = info_ptr->cHRM.whitey;
++      if (redx   != NULL) *redx   = info_ptr->cHRM.redx;
++      if (redy   != NULL) *redy   = info_ptr->cHRM.redy;
++      if (greenx != NULL) *greenx = info_ptr->cHRM.greenx;
++      if (greeny != NULL) *greeny = info_ptr->cHRM.greeny;
++      if (bluex  != NULL) *bluex  = info_ptr->cHRM.bluex;
++      if (bluey  != NULL) *bluey  = info_ptr->cHRM.bluey;
+       return PNG_INFO_cHRM;
+    }
+ 
+@@ -717,11 +689,11 @@ png_get_gAMA_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr,
+ {
+    png_debug1(1, "in %s retrieval function", "gAMA");
+ 
++   /* PNGv3 compatibility: only report gAMA if it is really present. */
+    if (png_ptr != NULL && info_ptr != NULL &&
+-       (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_GAMMA) != 0 &&
+-       file_gamma != NULL)
++       (info_ptr->valid & PNG_INFO_gAMA) != 0)
+    {
+-      *file_gamma = info_ptr->colorspace.gamma;
++      if (file_gamma != NULL) *file_gamma = info_ptr->gamma;
+       return PNG_INFO_gAMA;
+    }
+ 
+@@ -736,12 +708,13 @@ png_get_gAMA(png_const_structrp png_ptr, png_const_inforp info_ptr,
+ {
+    png_debug1(1, "in %s retrieval function", "gAMA(float)");
+ 
++   /* PNGv3 compatibility: only report gAMA if it is really present. */
+    if (png_ptr != NULL && info_ptr != NULL &&
+-      (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_GAMMA) != 0 &&
+-      file_gamma != NULL)
++       (info_ptr->valid & PNG_INFO_gAMA) != 0)
+    {
+-      *file_gamma = png_float(png_ptr, info_ptr->colorspace.gamma,
+-          "png_get_gAMA");
++      if (file_gamma != NULL)
++         *file_gamma = png_float(png_ptr, info_ptr->gamma, "gAMA");
++
+       return PNG_INFO_gAMA;
+    }
+ 
+@@ -758,9 +731,10 @@ png_get_sRGB(png_const_structrp png_ptr, png_const_inforp info_ptr,
+    png_debug1(1, "in %s retrieval function", "sRGB");
+ 
+    if (png_ptr != NULL && info_ptr != NULL &&
+-      (info_ptr->valid & PNG_INFO_sRGB) != 0 && file_srgb_intent != NULL)
++      (info_ptr->valid & PNG_INFO_sRGB) != 0)
+    {
+-      *file_srgb_intent = info_ptr->colorspace.rendering_intent;
++      if (file_srgb_intent != NULL)
++         *file_srgb_intent = info_ptr->rendering_intent;
+       return PNG_INFO_sRGB;
+    }
+ 
+@@ -813,6 +787,136 @@ png_get_sPLT(png_const_structrp png_ptr, png_inforp info_ptr,
+ }
+ #endif
+ 
++#ifdef PNG_cICP_SUPPORTED
++png_uint_32 PNGAPI
++png_get_cICP(png_const_structrp png_ptr,
++             png_const_inforp info_ptr, png_bytep colour_primaries,
++             png_bytep transfer_function, png_bytep matrix_coefficients,
++             png_bytep video_full_range_flag)
++{
++    png_debug1(1, "in %s retrieval function", "cICP");
++
++    if (png_ptr != NULL && info_ptr != NULL &&
++        (info_ptr->valid & PNG_INFO_cICP) != 0 &&
++        colour_primaries != NULL && transfer_function != NULL &&
++        matrix_coefficients != NULL && video_full_range_flag != NULL)
++    {
++        *colour_primaries = info_ptr->cicp_colour_primaries;
++        *transfer_function = info_ptr->cicp_transfer_function;
++        *matrix_coefficients = info_ptr->cicp_matrix_coefficients;
++        *video_full_range_flag = info_ptr->cicp_video_full_range_flag;
++        return (PNG_INFO_cICP);
++    }
++
++    return 0;
++}
++#endif
++
++#ifdef PNG_cLLI_SUPPORTED
++#  ifdef PNG_FIXED_POINT_SUPPORTED
++png_uint_32 PNGAPI
++png_get_cLLI_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr,
++    png_uint_32p maxCLL,
++    png_uint_32p maxFALL)
++{
++   png_debug1(1, "in %s retrieval function", "cLLI");
++
++   if (png_ptr != NULL && info_ptr != NULL &&
++       (info_ptr->valid & PNG_INFO_cLLI) != 0)
++   {
++      if (maxCLL != NULL) *maxCLL = info_ptr->maxCLL;
++      if (maxFALL != NULL) *maxFALL = info_ptr->maxFALL;
++      return PNG_INFO_cLLI;
++   }
++
++   return 0;
++}
++#  endif
++
++#  ifdef PNG_FLOATING_POINT_SUPPORTED
++png_uint_32 PNGAPI
++png_get_cLLI(png_const_structrp png_ptr, png_const_inforp info_ptr,
++      double *maxCLL, double *maxFALL)
++{
++   png_debug1(1, "in %s retrieval function", "cLLI(float)");
++
++   if (png_ptr != NULL && info_ptr != NULL &&
++       (info_ptr->valid & PNG_INFO_cLLI) != 0)
++   {
++      if (maxCLL != NULL) *maxCLL = info_ptr->maxCLL * .0001;
++      if (maxFALL != NULL) *maxFALL = info_ptr->maxFALL * .0001;
++      return PNG_INFO_cLLI;
++   }
++
++   return 0;
++}
++#  endif
++#endif /* cLLI */
++
++#ifdef PNG_mDCV_SUPPORTED
++#  ifdef PNG_FIXED_POINT_SUPPORTED
++png_uint_32 PNGAPI
++png_get_mDCV_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr,
++    png_fixed_point *white_x, png_fixed_point *white_y,
++    png_fixed_point *red_x, png_fixed_point *red_y,
++    png_fixed_point *green_x, png_fixed_point *green_y,
++    png_fixed_point *blue_x, png_fixed_point *blue_y,
++    png_uint_32p mastering_maxDL, png_uint_32p mastering_minDL)
++{
++   png_debug1(1, "in %s retrieval function", "mDCV");
++
++   if (png_ptr != NULL && info_ptr != NULL &&
++       (info_ptr->valid & PNG_INFO_mDCV) != 0)
++   {
++      if (white_x != NULL) *white_x = info_ptr->mastering_white_x * 2;
++      if (white_y != NULL) *white_y = info_ptr->mastering_white_y * 2;
++      if (red_x != NULL) *red_x = info_ptr->mastering_red_x * 2;
++      if (red_y != NULL) *red_y = info_ptr->mastering_red_y * 2;
++      if (green_x != NULL) *green_x = info_ptr->mastering_green_x * 2;
++      if (green_y != NULL) *green_y = info_ptr->mastering_green_y * 2;
++      if (blue_x != NULL) *blue_x = info_ptr->mastering_blue_x * 2;
++      if (blue_y != NULL) *blue_y = info_ptr->mastering_blue_y * 2;
++      if (mastering_maxDL != NULL) *mastering_maxDL = info_ptr->mastering_maxDL;
++      if (mastering_minDL != NULL) *mastering_minDL = info_ptr->mastering_minDL;
++      return PNG_INFO_mDCV;
++   }
++
++   return 0;
++}
++#  endif
++
++#  ifdef PNG_FLOATING_POINT_SUPPORTED
++png_uint_32 PNGAPI
++png_get_mDCV(png_const_structrp png_ptr, png_const_inforp info_ptr,
++    double *white_x, double *white_y, double *red_x, double *red_y,
++    double *green_x, double *green_y, double *blue_x, double *blue_y,
++    double *mastering_maxDL, double *mastering_minDL)
++{
++   png_debug1(1, "in %s retrieval function", "mDCV(float)");
++
++   if (png_ptr != NULL && info_ptr != NULL &&
++       (info_ptr->valid & PNG_INFO_mDCV) != 0)
++   {
++      if (white_x != NULL) *white_x = info_ptr->mastering_white_x * .00002;
++      if (white_y != NULL) *white_y = info_ptr->mastering_white_y * .00002;
++      if (red_x != NULL) *red_x = info_ptr->mastering_red_x * .00002;
++      if (red_y != NULL) *red_y = info_ptr->mastering_red_y * .00002;
++      if (green_x != NULL) *green_x = info_ptr->mastering_green_x * .00002;
++      if (green_y != NULL) *green_y = info_ptr->mastering_green_y * .00002;
++      if (blue_x != NULL) *blue_x = info_ptr->mastering_blue_x * .00002;
++      if (blue_y != NULL) *blue_y = info_ptr->mastering_blue_y * .00002;
++      if (mastering_maxDL != NULL)
++         *mastering_maxDL = info_ptr->mastering_maxDL * .0001;
++      if (mastering_minDL != NULL)
++         *mastering_minDL = info_ptr->mastering_minDL * .0001;
++      return PNG_INFO_mDCV;
++   }
++
++   return 0;
++}
++#  endif /* FLOATING_POINT */
++#endif /* mDCV */
++
+ #ifdef PNG_eXIf_SUPPORTED
+ png_uint_32 PNGAPI
+ png_get_eXIf(png_const_structrp png_ptr, png_inforp info_ptr,
+diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pnginfo.h b/src/java.desktop/share/native/libsplashscreen/libpng/pnginfo.h
+index d241eaebf..bc6ed3d09 100644
+--- a/src/java.desktop/share/native/libsplashscreen/libpng/pnginfo.h
++++ b/src/java.desktop/share/native/libsplashscreen/libpng/pnginfo.h
+@@ -115,18 +115,12 @@ struct png_info_def
+     * and initialize the appropriate fields below.
+     */
+ 
+-#if defined(PNG_COLORSPACE_SUPPORTED) || defined(PNG_GAMMA_SUPPORTED)
+-   /* png_colorspace only contains 'flags' if neither GAMMA or COLORSPACE are
+-    * defined.  When COLORSPACE is switched on all the colorspace-defining
+-    * chunks should be enabled, when GAMMA is switched on all the gamma-defining
+-    * chunks should be enabled.  If this is not done it becomes possible to read
+-    * inconsistent PNG files and assign a probably incorrect interpretation to
+-    * the information.  (In other words, by carefully choosing which chunks to
+-    * recognize the system configuration can select an interpretation for PNG
+-    * files containing ambiguous data and this will result in inconsistent
+-    * behavior between different libpng builds!)
+-    */
+-   png_colorspace colorspace;
++#ifdef PNG_cICP_SUPPORTED
++   /* cICP chunk data */
++   png_byte cicp_colour_primaries;
++   png_byte cicp_transfer_function;
++   png_byte cicp_matrix_coefficients;
++   png_byte cicp_video_full_range_flag;
+ #endif
+ 
+ #ifdef PNG_iCCP_SUPPORTED
+@@ -136,6 +130,24 @@ struct png_info_def
+    png_uint_32 iccp_proflen;  /* ICC profile data length */
+ #endif
+ 
++#ifdef PNG_cLLI_SUPPORTED
++   png_uint_32 maxCLL;  /* cd/m2 (nits) * 10,000 */
++   png_uint_32 maxFALL;
++#endif
++
++#ifdef PNG_mDCV_SUPPORTED
++   png_uint_16 mastering_red_x;  /* CIE (xy) x * 50,000 */
++   png_uint_16 mastering_red_y;
++   png_uint_16 mastering_green_x;
++   png_uint_16 mastering_green_y;
++   png_uint_16 mastering_blue_x;
++   png_uint_16 mastering_blue_y;
++   png_uint_16 mastering_white_x;
++   png_uint_16 mastering_white_y;
++   png_uint_32 mastering_maxDL; /* cd/m2 (nits) * 10,000 */
++   png_uint_32 mastering_minDL;
++#endif
++
+ #ifdef PNG_TEXT_SUPPORTED
+    /* The tEXt, and zTXt chunks contain human-readable textual data in
+     * uncompressed, compressed, and optionally compressed forms, respectively.
+@@ -214,11 +226,8 @@ defined(PNG_READ_BACKGROUND_SUPPORTED)
+ #endif
+ 
+ #ifdef PNG_eXIf_SUPPORTED
+-   int num_exif;  /* Added at libpng-1.6.31 */
++   png_uint_32 num_exif;  /* Added at libpng-1.6.31 */
+    png_bytep exif;
+-# ifdef PNG_READ_eXIf_SUPPORTED
+-   png_bytep eXIf_buf;  /* Added at libpng-1.6.32 */
+-# endif
+ #endif
+ 
+ #ifdef PNG_hIST_SUPPORTED
+@@ -291,5 +300,16 @@ defined(PNG_READ_BACKGROUND_SUPPORTED)
+    png_bytepp row_pointers;        /* the image bits */
+ #endif
+ 
++#ifdef PNG_cHRM_SUPPORTED
++   png_xy cHRM;
++#endif
++
++#ifdef PNG_gAMA_SUPPORTED
++   png_fixed_point gamma;
++#endif
++
++#ifdef PNG_sRGB_SUPPORTED
++   int rendering_intent;
++#endif
+ };
+ #endif /* PNGINFO_H */
+diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pnglibconf.h b/src/java.desktop/share/native/libsplashscreen/libpng/pnglibconf.h
+index e78933bac..2150e046f 100644
+--- a/src/java.desktop/share/native/libsplashscreen/libpng/pnglibconf.h
++++ b/src/java.desktop/share/native/libsplashscreen/libpng/pnglibconf.h
+@@ -31,9 +31,9 @@
+  * However, the following notice accompanied the original version of this
+  * file and, per its terms, should not be removed:
+  */
+-/* libpng version 1.6.43 */
++/* libpng version 1.6.47 */
+ 
+-/* Copyright (c) 2018-2023 Cosmin Truta */
++/* Copyright (c) 2018-2025 Cosmin Truta */
+ /* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson */
+ 
+ /* This code is released under the libpng license. */
+diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngmem.c b/src/java.desktop/share/native/libsplashscreen/libpng/pngmem.c
+index d5ad0735f..ba9eb4df4 100644
+--- a/src/java.desktop/share/native/libsplashscreen/libpng/pngmem.c
++++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngmem.c
+@@ -101,30 +101,29 @@ png_malloc_base,(png_const_structrp png_ptr, png_alloc_size_t size),
+     * to implement a user memory handler.  This checks to be sure it isn't
+     * called with big numbers.
+     */
+-#ifndef PNG_USER_MEM_SUPPORTED
+-   PNG_UNUSED(png_ptr)
+-#endif
++#  ifdef PNG_MAX_MALLOC_64K
++      /* This is support for legacy systems which had segmented addressing
++       * limiting the maximum allocation size to 65536.  It takes precedence
++       * over PNG_SIZE_MAX which is set to 65535 on true 16-bit systems.
++       *
++       * TODO: libpng-1.8: finally remove both cases.
++       */
++      if (size > 65536U) return NULL;
++#  endif
+ 
+-   /* Some compilers complain that this is always true.  However, it
+-    * can be false when integer overflow happens.
++   /* This is checked too because the system malloc call below takes a (size_t).
+     */
+-   if (size > 0 && size <= PNG_SIZE_MAX
+-#     ifdef PNG_MAX_MALLOC_64K
+-         && size <= 65536U
+-#     endif
+-      )
+-   {
+-#ifdef PNG_USER_MEM_SUPPORTED
++   if (size > PNG_SIZE_MAX) return NULL;
++
++#  ifdef PNG_USER_MEM_SUPPORTED
+       if (png_ptr != NULL && png_ptr->malloc_fn != NULL)
+          return png_ptr->malloc_fn(png_constcast(png_structrp,png_ptr), size);
++#  else
++      PNG_UNUSED(png_ptr)
++#  endif
+ 
+-      else
+-#endif
+-         return malloc((size_t)size); /* checked for truncation above */
+-   }
+-
+-   else
+-      return NULL;
++   /* Use the system malloc */
++   return malloc((size_t)/*SAFE*/size); /* checked for truncation above */
+ }
+ 
+ #if defined(PNG_TEXT_SUPPORTED) || defined(PNG_sPLT_SUPPORTED) ||\
+diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngpread.c b/src/java.desktop/share/native/libsplashscreen/libpng/pngpread.c
+index 816631cae..86d0c7aaa 100644
+--- a/src/java.desktop/share/native/libsplashscreen/libpng/pngpread.c
++++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngpread.c
+@@ -60,6 +60,21 @@ if (png_ptr->push_length + 4 > png_ptr->buffer_size) \
+ if (png_ptr->buffer_size < N) \
+    { png_push_save_buffer(png_ptr); return; }
+ 
++#ifdef PNG_READ_INTERLACING_SUPPORTED
++/* Arrays to facilitate interlacing - use pass (0 - 6) as index. */
++
++/* Start of interlace block */
++static const png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
++/* Offset to next interlace block */
++static const png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
++/* Start of interlace block in the y direction */
++static const png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
++/* Offset to next interlace block in the y direction */
++static const png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
++
++/* TODO: Move these arrays to a common utility module to avoid duplication. */
++#endif
++
+ void PNGAPI
+ png_process_data(png_structrp png_ptr, png_inforp info_ptr,
+     png_bytep buffer, size_t buffer_size)
+@@ -207,17 +222,8 @@ png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr)
+     */
+    if ((png_ptr->mode & PNG_HAVE_CHUNK_HEADER) == 0)
+    {
+-      png_byte chunk_length[4];
+-      png_byte chunk_tag[4];
+-
+       PNG_PUSH_SAVE_BUFFER_IF_LT(8)
+-      png_push_fill_buffer(png_ptr, chunk_length, 4);
+-      png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length);
+-      png_reset_crc(png_ptr);
+-      png_crc_read(png_ptr, chunk_tag, 4);
+-      png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(chunk_tag);
+-      png_check_chunk_name(png_ptr, png_ptr->chunk_name);
+-      png_check_chunk_length(png_ptr, png_ptr->push_length);
++      png_ptr->push_length = png_read_chunk_header(png_ptr);
+       png_ptr->mode |= PNG_HAVE_CHUNK_HEADER;
+    }
+ 
+@@ -258,13 +264,13 @@ png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr)
+          png_error(png_ptr, "Invalid IHDR length");
+ 
+       PNG_PUSH_SAVE_BUFFER_IF_FULL
+-      png_handle_IHDR(png_ptr, info_ptr, png_ptr->push_length);
++      png_handle_chunk(png_ptr, info_ptr, png_ptr->push_length);
+    }
+ 
+    else if (chunk_name == png_IEND)
+    {
+       PNG_PUSH_SAVE_BUFFER_IF_FULL
+-      png_handle_IEND(png_ptr, info_ptr, png_ptr->push_length);
++      png_handle_chunk(png_ptr, info_ptr, png_ptr->push_length);
+ 
+       png_ptr->process_mode = PNG_READ_DONE_MODE;
+       png_push_have_end(png_ptr, info_ptr);
+@@ -281,12 +287,6 @@ png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr)
+    }
+ #endif
+ 
+-   else if (chunk_name == png_PLTE)
+-   {
+-      PNG_PUSH_SAVE_BUFFER_IF_FULL
+-      png_handle_PLTE(png_ptr, info_ptr, png_ptr->push_length);
+-   }
+-
+    else if (chunk_name == png_IDAT)
+    {
+       png_ptr->idat_size = png_ptr->push_length;
+@@ -299,155 +299,10 @@ png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr)
+       return;
+    }
+ 
+-#ifdef PNG_READ_gAMA_SUPPORTED
+-   else if (png_ptr->chunk_name == png_gAMA)
+-   {
+-      PNG_PUSH_SAVE_BUFFER_IF_FULL
+-      png_handle_gAMA(png_ptr, info_ptr, png_ptr->push_length);
+-   }
+-
+-#endif
+-#ifdef PNG_READ_sBIT_SUPPORTED
+-   else if (png_ptr->chunk_name == png_sBIT)
+-   {
+-      PNG_PUSH_SAVE_BUFFER_IF_FULL
+-      png_handle_sBIT(png_ptr, info_ptr, png_ptr->push_length);
+-   }
+-
+-#endif
+-#ifdef PNG_READ_cHRM_SUPPORTED
+-   else if (png_ptr->chunk_name == png_cHRM)
+-   {
+-      PNG_PUSH_SAVE_BUFFER_IF_FULL
+-      png_handle_cHRM(png_ptr, info_ptr, png_ptr->push_length);
+-   }
+-
+-#endif
+-#ifdef PNG_READ_eXIf_SUPPORTED
+-   else if (png_ptr->chunk_name == png_eXIf)
+-   {
+-      PNG_PUSH_SAVE_BUFFER_IF_FULL
+-      png_handle_eXIf(png_ptr, info_ptr, png_ptr->push_length);
+-   }
+-
+-#endif
+-#ifdef PNG_READ_sRGB_SUPPORTED
+-   else if (chunk_name == png_sRGB)
+-   {
+-      PNG_PUSH_SAVE_BUFFER_IF_FULL
+-      png_handle_sRGB(png_ptr, info_ptr, png_ptr->push_length);
+-   }
+-
+-#endif
+-#ifdef PNG_READ_iCCP_SUPPORTED
+-   else if (png_ptr->chunk_name == png_iCCP)
+-   {
+-      PNG_PUSH_SAVE_BUFFER_IF_FULL
+-      png_handle_iCCP(png_ptr, info_ptr, png_ptr->push_length);
+-   }
+-
+-#endif
+-#ifdef PNG_READ_sPLT_SUPPORTED
+-   else if (chunk_name == png_sPLT)
+-   {
+-      PNG_PUSH_SAVE_BUFFER_IF_FULL
+-      png_handle_sPLT(png_ptr, info_ptr, png_ptr->push_length);
+-   }
+-
+-#endif
+-#ifdef PNG_READ_tRNS_SUPPORTED
+-   else if (chunk_name == png_tRNS)
+-   {
+-      PNG_PUSH_SAVE_BUFFER_IF_FULL
+-      png_handle_tRNS(png_ptr, info_ptr, png_ptr->push_length);
+-   }
+-
+-#endif
+-#ifdef PNG_READ_bKGD_SUPPORTED
+-   else if (chunk_name == png_bKGD)
+-   {
+-      PNG_PUSH_SAVE_BUFFER_IF_FULL
+-      png_handle_bKGD(png_ptr, info_ptr, png_ptr->push_length);
+-   }
+-
+-#endif
+-#ifdef PNG_READ_hIST_SUPPORTED
+-   else if (chunk_name == png_hIST)
+-   {
+-      PNG_PUSH_SAVE_BUFFER_IF_FULL
+-      png_handle_hIST(png_ptr, info_ptr, png_ptr->push_length);
+-   }
+-
+-#endif
+-#ifdef PNG_READ_pHYs_SUPPORTED
+-   else if (chunk_name == png_pHYs)
+-   {
+-      PNG_PUSH_SAVE_BUFFER_IF_FULL
+-      png_handle_pHYs(png_ptr, info_ptr, png_ptr->push_length);
+-   }
+-
+-#endif
+-#ifdef PNG_READ_oFFs_SUPPORTED
+-   else if (chunk_name == png_oFFs)
+-   {
+-      PNG_PUSH_SAVE_BUFFER_IF_FULL
+-      png_handle_oFFs(png_ptr, info_ptr, png_ptr->push_length);
+-   }
+-#endif
+-
+-#ifdef PNG_READ_pCAL_SUPPORTED
+-   else if (chunk_name == png_pCAL)
+-   {
+-      PNG_PUSH_SAVE_BUFFER_IF_FULL
+-      png_handle_pCAL(png_ptr, info_ptr, png_ptr->push_length);
+-   }
+-
+-#endif
+-#ifdef PNG_READ_sCAL_SUPPORTED
+-   else if (chunk_name == png_sCAL)
+-   {
+-      PNG_PUSH_SAVE_BUFFER_IF_FULL
+-      png_handle_sCAL(png_ptr, info_ptr, png_ptr->push_length);
+-   }
+-
+-#endif
+-#ifdef PNG_READ_tIME_SUPPORTED
+-   else if (chunk_name == png_tIME)
+-   {
+-      PNG_PUSH_SAVE_BUFFER_IF_FULL
+-      png_handle_tIME(png_ptr, info_ptr, png_ptr->push_length);
+-   }
+-
+-#endif
+-#ifdef PNG_READ_tEXt_SUPPORTED
+-   else if (chunk_name == png_tEXt)
+-   {
+-      PNG_PUSH_SAVE_BUFFER_IF_FULL
+-      png_handle_tEXt(png_ptr, info_ptr, png_ptr->push_length);
+-   }
+-
+-#endif
+-#ifdef PNG_READ_zTXt_SUPPORTED
+-   else if (chunk_name == png_zTXt)
+-   {
+-      PNG_PUSH_SAVE_BUFFER_IF_FULL
+-      png_handle_zTXt(png_ptr, info_ptr, png_ptr->push_length);
+-   }
+-
+-#endif
+-#ifdef PNG_READ_iTXt_SUPPORTED
+-   else if (chunk_name == png_iTXt)
+-   {
+-      PNG_PUSH_SAVE_BUFFER_IF_FULL
+-      png_handle_iTXt(png_ptr, info_ptr, png_ptr->push_length);
+-   }
+-#endif
+-
+    else
+    {
+       PNG_PUSH_SAVE_BUFFER_IF_FULL
+-      png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length,
+-          PNG_HANDLE_CHUNK_AS_DEFAULT);
++      png_handle_chunk(png_ptr, info_ptr, png_ptr->push_length);
+    }
+ 
+    png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
+@@ -1004,27 +859,6 @@ png_push_process_row(png_structrp png_ptr)
+ void /* PRIVATE */
+ png_read_push_finish_row(png_structrp png_ptr)
+ {
+-#ifdef PNG_READ_INTERLACING_SUPPORTED
+-   /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
+-
+-   /* Start of interlace block */
+-   static const png_byte png_pass_start[] = {0, 4, 0, 2, 0, 1, 0};
+-
+-   /* Offset to next interlace block */
+-   static const png_byte png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1};
+-
+-   /* Start of interlace block in the y direction */
+-   static const png_byte png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1};
+-
+-   /* Offset to next interlace block in the y direction */
+-   static const png_byte png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2};
+-
+-   /* Height of interlace block.  This is not currently used - if you need
+-    * it, uncomment it here and in png.h
+-   static const png_byte png_pass_height[] = {8, 8, 4, 4, 2, 2, 1};
+-   */
+-#endif
+-
+    png_ptr->row_number++;
+    if (png_ptr->row_number < png_ptr->num_rows)
+       return;
+diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngpriv.h b/src/java.desktop/share/native/libsplashscreen/libpng/pngpriv.h
+index 18424542b..25bac4b9e 100644
+--- a/src/java.desktop/share/native/libsplashscreen/libpng/pngpriv.h
++++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngpriv.h
+@@ -168,47 +168,6 @@
+     * callbacks to do this.
+     */
+ #  define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_neon
+-
+-   /* By default the 'intrinsics' code in arm/filter_neon_intrinsics.c is used
+-    * if possible - if __ARM_NEON__ is set and the compiler version is not known
+-    * to be broken.  This is controlled by PNG_ARM_NEON_IMPLEMENTATION which can
+-    * be:
+-    *
+-    *    1  The intrinsics code (the default with __ARM_NEON__)
+-    *    2  The hand coded assembler (the default without __ARM_NEON__)
+-    *
+-    * It is possible to set PNG_ARM_NEON_IMPLEMENTATION in CPPFLAGS, however
+-    * this is *NOT* supported and may cease to work even after a minor revision
+-    * to libpng.  It *is* valid to do this for testing purposes, e.g. speed
+-    * testing or a new compiler, but the results should be communicated to the
+-    * libpng implementation list for incorporation in the next minor release.
+-    */
+-#  ifndef PNG_ARM_NEON_IMPLEMENTATION
+-#     if defined(__ARM_NEON__) || defined(__ARM_NEON)
+-#        if defined(__clang__)
+-            /* At present it is unknown by the libpng developers which versions
+-             * of clang support the intrinsics, however some or perhaps all
+-             * versions do not work with the assembler so this may be
+-             * irrelevant, so just use the default (do nothing here.)
+-             */
+-#        elif defined(__GNUC__)
+-            /* GCC 4.5.4 NEON support is known to be broken.  4.6.3 is known to
+-             * work, so if this *is* GCC, or G++, look for a version >4.5
+-             */
+-#           if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 6)
+-#              define PNG_ARM_NEON_IMPLEMENTATION 2
+-#           endif /* no GNUC support */
+-#        endif /* __GNUC__ */
+-#     else /* !defined __ARM_NEON__ */
+-         /* The 'intrinsics' code simply won't compile without this -mfpu=neon:
+-          */
+-#        if !defined(__aarch64__) && !defined(_M_ARM64)
+-            /* The assembler code currently does not work on ARM64 */
+-#          define PNG_ARM_NEON_IMPLEMENTATION 2
+-#        endif /* __aarch64__ */
+-#     endif /* __ARM_NEON__ */
+-#  endif /* !PNG_ARM_NEON_IMPLEMENTATION */
+-
+ #  ifndef PNG_ARM_NEON_IMPLEMENTATION
+       /* Use the intrinsics code by default. */
+ #     define PNG_ARM_NEON_IMPLEMENTATION 1
+@@ -741,7 +700,7 @@
+ #define PNG_FLAG_CRC_ANCILLARY_NOWARN     0x0200U
+ #define PNG_FLAG_CRC_CRITICAL_USE         0x0400U
+ #define PNG_FLAG_CRC_CRITICAL_IGNORE      0x0800U
+-#define PNG_FLAG_ASSUME_sRGB              0x1000U /* Added to libpng-1.5.4 */
++/*      PNG_FLAG_ASSUME_sRGB unused       0x1000U  * Added to libpng-1.5.4 */
+ #define PNG_FLAG_OPTIMIZE_ALPHA           0x2000U /* Added to libpng-1.5.4 */
+ #define PNG_FLAG_DETECT_UNINITIALIZED     0x4000U /* Added to libpng-1.5.4 */
+ /* #define PNG_FLAG_KEEP_UNKNOWN_CHUNKS      0x8000U */
+@@ -852,6 +811,8 @@
+ #ifdef PNG_FIXED_POINT_MACRO_SUPPORTED
+ #define png_fixed(png_ptr, fp, s) ((fp) <= 21474 && (fp) >= -21474 ?\
+     ((png_fixed_point)(100000 * (fp))) : (png_fixed_error(png_ptr, s),0))
++#define png_fixed_ITU(png_ptr, fp, s) ((fp) <= 214748 && (fp) >= 0 ?\
++    ((png_uint_32)(10000 * (fp))) : (png_fixed_error(png_ptr, s),0))
+ #endif
+ /* else the corresponding function is defined below, inside the scope of the
+  * cplusplus test.
+@@ -870,11 +831,31 @@
+  *
+  * PNG_32b correctly produces a value shifted by up to 24 bits, even on
+  * architectures where (int) is only 16 bits.
++ *
++ * 1.6.47: PNG_32b was made into a preprocessor evaluable macro by replacing the
++ * static_cast with a promoting binary operation using a guaranteed 32-bit
++ * (minimum) unsigned value.
+  */
+-#define PNG_32b(b,s) ((png_uint_32)(b) << (s))
++#define PNG_32b(b,s) (((0xFFFFFFFFU)&(b)) << (s))
+ #define PNG_U32(b1,b2,b3,b4) \
+    (PNG_32b(b1,24) | PNG_32b(b2,16) | PNG_32b(b3,8) | PNG_32b(b4,0))
+ 
++/* Chunk name validation.  When using these macros all the arguments should be
++ * constants, otherwise code bloat may well occur.  The macros are provided
++ * primarily for use in #if checks.
++ *
++ * PNG_32to8 produces a byte value with the right shift; used to extract the
++ * byte value from a chunk name.
++ */
++#define PNG_32to8(cn,s) (((cn) >> (s)) & 0xffU)
++#define PNG_CN_VALID_UPPER(b) ((b) >= 65 && (b) <= 90) /* upper-case ASCII */
++#define PNG_CN_VALID_ASCII(b) PNG_CN_VALID_UPPER((b) & ~32U)
++#define PNG_CHUNK_NAME_VALID(cn) (\
++   PNG_CN_VALID_ASCII(PNG_32to8(cn,24)) && /* critical, !ancillary */\
++   PNG_CN_VALID_ASCII(PNG_32to8(cn,16)) && /* public, !privately defined */\
++   PNG_CN_VALID_UPPER(PNG_32to8(cn, 8)) && /* VALID, !reserved */\
++   PNG_CN_VALID_ASCII(PNG_32to8(cn, 0))   /* data-dependent, !copy ok */)
++
+ /* Constants for known chunk types.
+  *
+  * MAINTAINERS: If you need to add a chunk, define the name here.
+@@ -902,9 +883,14 @@
+ #define png_IEND PNG_U32( 73,  69,  78,  68)
+ #define png_IHDR PNG_U32( 73,  72,  68,  82)
+ #define png_PLTE PNG_U32( 80,  76,  84,  69)
++#define png_acTL PNG_U32( 97,  99,  84,  76) /* PNGv3: APNG */
+ #define png_bKGD PNG_U32( 98,  75,  71,  68)
+ #define png_cHRM PNG_U32( 99,  72,  82,  77)
++#define png_cICP PNG_U32( 99,  73,  67,  80) /* PNGv3 */
++#define png_cLLI PNG_U32( 99,  76,  76,  73) /* PNGv3 */
+ #define png_eXIf PNG_U32(101,  88,  73, 102) /* registered July 2017 */
++#define png_fcTL PNG_U32(102,  99,  84,  76) /* PNGv3: APNG */
++#define png_fdAT PNG_U32(102, 100,  65,  84) /* PNGv3: APNG */
+ #define png_fRAc PNG_U32(102,  82,  65,  99) /* registered, not defined */
+ #define png_gAMA PNG_U32(103,  65,  77,  65)
+ #define png_gIFg PNG_U32(103,  73,  70, 103)
+@@ -913,6 +899,7 @@
+ #define png_hIST PNG_U32(104,  73,  83,  84)
+ #define png_iCCP PNG_U32(105,  67,  67,  80)
+ #define png_iTXt PNG_U32(105,  84,  88, 116)
++#define png_mDCV PNG_U32(109,  68,  67,  86) /* PNGv3 */
+ #define png_oFFs PNG_U32(111,  70,  70, 115)
+ #define png_pCAL PNG_U32(112,  67,  65,  76)
+ #define png_pHYs PNG_U32(112,  72,  89, 115)
+@@ -953,11 +940,74 @@
+ #define PNG_CHUNK_RESERVED(c)     (1 & ((c) >> 13))
+ #define PNG_CHUNK_SAFE_TO_COPY(c) (1 & ((c) >>  5))
+ 
++/* Known chunks.  All supported chunks must be listed here.  The macro PNG_CHUNK
++ * contains the four character ASCII name by which the chunk is identified.  The
++ * macro is implemented as required to build tables or switch statements which
++ * require entries for every known chunk.  The macro also contains an index
++ * value which should be in order (this is checked in png.c).
++ *
++ * Notice that "known" does not require "SUPPORTED"; tables should be built in
++ * such a way that chunks unsupported in a build require no more than the table
++ * entry (which should be small.)  In particular function pointers for
++ * unsupported chunks should be NULL.
++ *
++ * At present these index values are not exported (not part of the public API)
++ * so can be changed at will.  For convenience the names are in lexical sort
++ * order but with the critical chunks at the start in the order of occurence in
++ * a PNG.
++ *
++ * PNG_INFO_ values do not exist for every one of these chunk handles; for
++ * example PNG_INFO_{IDAT,IEND,tEXt,iTXt,zTXt} and possibly other chunks in the
++ * future.
++ */
++#define PNG_KNOWN_CHUNKS\
++   PNG_CHUNK(IHDR,  0)\
++   PNG_CHUNK(PLTE,  1)\
++   PNG_CHUNK(IDAT,  2)\
++   PNG_CHUNK(IEND,  3)\
++   PNG_CHUNK(acTL,  4)\
++   PNG_CHUNK(bKGD,  5)\
++   PNG_CHUNK(cHRM,  6)\
++   PNG_CHUNK(cICP,  7)\
++   PNG_CHUNK(cLLI,  8)\
++   PNG_CHUNK(eXIf,  9)\
++   PNG_CHUNK(fcTL, 10)\
++   PNG_CHUNK(fdAT, 11)\
++   PNG_CHUNK(gAMA, 12)\
++   PNG_CHUNK(hIST, 13)\
++   PNG_CHUNK(iCCP, 14)\
++   PNG_CHUNK(iTXt, 15)\
++   PNG_CHUNK(mDCV, 16)\
++   PNG_CHUNK(oFFs, 17)\
++   PNG_CHUNK(pCAL, 18)\
++   PNG_CHUNK(pHYs, 19)\
++   PNG_CHUNK(sBIT, 20)\
++   PNG_CHUNK(sCAL, 21)\
++   PNG_CHUNK(sPLT, 22)\
++   PNG_CHUNK(sRGB, 23)\
++   PNG_CHUNK(tEXt, 24)\
++   PNG_CHUNK(tIME, 25)\
++   PNG_CHUNK(tRNS, 26)\
++   PNG_CHUNK(zTXt, 27)
++
+ /* Gamma values (new at libpng-1.5.4): */
+ #define PNG_GAMMA_MAC_OLD 151724  /* Assume '1.8' is really 2.2/1.45! */
+ #define PNG_GAMMA_MAC_INVERSE 65909
+ #define PNG_GAMMA_sRGB_INVERSE 45455
+ 
++/* gamma sanity check.  libpng cannot implement gamma transforms outside a
++ * certain limit because of its use of 16-bit fixed point intermediate values.
++ * Gamma values that are too large or too small will zap the 16-bit values all
++ * to 0 or 65535 resulting in an obvious 'bad' image.
++ *
++ * In libpng 1.6.0 the limits were changed from 0.07..3 to 0.01..100 to
++ * accommodate the optimal 16-bit gamma of 36 and its reciprocal.
++ *
++ * These are png_fixed_point integral values:
++ */
++#define PNG_LIB_GAMMA_MIN 1000
++#define PNG_LIB_GAMMA_MAX 10000000
++
+ /* Almost everything below is C specific; the #defines above can be used in
+  * non-C code (so long as it is C-preprocessed) the rest of this stuff cannot.
+  */
+@@ -1021,7 +1071,6 @@ extern "C" {
+  *
+  * All of these functions must be declared with PNG_INTERNAL_FUNCTION.
+  */
+-
+ /* Zlib support */
+ #define PNG_UNEXPECTED_ZLIB_RETURN (-7)
+ PNG_INTERNAL_FUNCTION(void, png_zstream_error,(png_structrp png_ptr, int ret),
+@@ -1040,6 +1089,7 @@ PNG_INTERNAL_FUNCTION(void,png_free_buffer_list,(png_structrp png_ptr,
+    !defined(PNG_FIXED_POINT_MACRO_SUPPORTED) && \
+    (defined(PNG_gAMA_SUPPORTED) || defined(PNG_cHRM_SUPPORTED) || \
+    defined(PNG_sCAL_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) || \
++   defined(PNG_mDCV_SUPPORTED) || \
+    defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)) || \
+    (defined(PNG_sCAL_SUPPORTED) && \
+    defined(PNG_FLOATING_ARITHMETIC_SUPPORTED))
+@@ -1047,12 +1097,38 @@ PNG_INTERNAL_FUNCTION(png_fixed_point,png_fixed,(png_const_structrp png_ptr,
+    double fp, png_const_charp text),PNG_EMPTY);
+ #endif
+ 
++#if defined(PNG_FLOATING_POINT_SUPPORTED) && \
++   !defined(PNG_FIXED_POINT_MACRO_SUPPORTED) && \
++   (defined(PNG_cLLI_SUPPORTED) || defined(PNG_mDCV_SUPPORTED))
++PNG_INTERNAL_FUNCTION(png_uint_32,png_fixed_ITU,(png_const_structrp png_ptr,
++   double fp, png_const_charp text),PNG_EMPTY);
++#endif
++
+ /* Check the user version string for compatibility, returns false if the version
+  * numbers aren't compatible.
+  */
+ PNG_INTERNAL_FUNCTION(int,png_user_version_check,(png_structrp png_ptr,
+    png_const_charp user_png_ver),PNG_EMPTY);
+ 
++#ifdef PNG_READ_SUPPORTED /* should only be used on read */
++/* Security: read limits on the largest allocations while reading a PNG.  This
++ * avoids very large allocations caused by PNG files with damaged or altered
++ * chunk 'length' fields.
++ */
++#ifdef PNG_SET_USER_LIMITS_SUPPORTED /* run-time limit */
++#  define png_chunk_max(png_ptr) ((png_ptr)->user_chunk_malloc_max)
++
++#elif PNG_USER_CHUNK_MALLOC_MAX > 0 /* compile-time limit */
++#  define png_chunk_max(png_ptr) ((void)png_ptr, PNG_USER_CHUNK_MALLOC_MAX)
++
++#elif (defined PNG_MAX_MALLOC_64K)  /* legacy system limit */
++#  define png_chunk_max(png_ptr) ((void)png_ptr, 65536U)
++
++#else                               /* modern system limit SIZE_MAX (C99) */
++#  define png_chunk_max(png_ptr) ((void)png_ptr, PNG_SIZE_MAX)
++#endif
++#endif /* READ */
++
+ /* Internal base allocator - no messages, NULL on failure to allocate.  This
+  * does, however, call the application provided allocator and that could call
+  * png_error (although that would be a bug in the application implementation.)
+@@ -1152,9 +1228,6 @@ PNG_INTERNAL_FUNCTION(void,png_crc_read,(png_structrp png_ptr, png_bytep buf,
+ PNG_INTERNAL_FUNCTION(int,png_crc_finish,(png_structrp png_ptr,
+    png_uint_32 skip),PNG_EMPTY);
+ 
+-/* Read the CRC from the file and compare it to the libpng calculated CRC */
+-PNG_INTERNAL_FUNCTION(int,png_crc_error,(png_structrp png_ptr),PNG_EMPTY);
+-
+ /* Calculate the CRC over a section of data.  Note that we are only
+  * passing a maximum of 64K on systems that have this as a memory limit,
+  * since this is the maximum buffer size we can specify.
+@@ -1200,6 +1273,26 @@ PNG_INTERNAL_FUNCTION(void,png_write_cHRM_fixed,(png_structrp png_ptr,
+    /* The xy value must have been previously validated */
+ #endif
+ 
++#ifdef PNG_WRITE_cICP_SUPPORTED
++PNG_INTERNAL_FUNCTION(void,png_write_cICP,(png_structrp png_ptr,
++    png_byte colour_primaries, png_byte transfer_function,
++    png_byte matrix_coefficients, png_byte video_full_range_flag), PNG_EMPTY);
++#endif
++
++#ifdef PNG_WRITE_cLLI_SUPPORTED
++PNG_INTERNAL_FUNCTION(void,png_write_cLLI_fixed,(png_structrp png_ptr,
++   png_uint_32 maxCLL, png_uint_32 maxFALL), PNG_EMPTY);
++#endif
++
++#ifdef PNG_WRITE_mDCV_SUPPORTED
++PNG_INTERNAL_FUNCTION(void,png_write_mDCV_fixed,(png_structrp png_ptr,
++   png_uint_16 red_x, png_uint_16 red_y,
++   png_uint_16 green_x, png_uint_16 green_y,
++   png_uint_16 blue_x, png_uint_16 blue_y,
++   png_uint_16 white_x, png_uint_16 white_y,
++   png_uint_32 maxDL, png_uint_32 minDL), PNG_EMPTY);
++#endif
++
+ #ifdef PNG_WRITE_sRGB_SUPPORTED
+ PNG_INTERNAL_FUNCTION(void,png_write_sRGB,(png_structrp png_ptr,
+     int intent),PNG_EMPTY);
+@@ -1212,10 +1305,10 @@ PNG_INTERNAL_FUNCTION(void,png_write_eXIf,(png_structrp png_ptr,
+ 
+ #ifdef PNG_WRITE_iCCP_SUPPORTED
+ PNG_INTERNAL_FUNCTION(void,png_write_iCCP,(png_structrp png_ptr,
+-   png_const_charp name, png_const_bytep profile), PNG_EMPTY);
+-   /* The profile must have been previously validated for correctness, the
+-    * length comes from the first four bytes.  Only the base, deflate,
+-    * compression is supported.
++   png_const_charp name, png_const_bytep profile, png_uint_32 proflen),
++   PNG_EMPTY);
++   /* Writes a previously 'set' profile.  The profile argument is **not**
++    * compressed.
+     */
+ #endif
+ 
+@@ -1524,119 +1617,36 @@ PNG_INTERNAL_FUNCTION(void,png_do_bgr,(png_row_infop row_info,
+ /* The following decodes the appropriate chunks, and does error correction,
+  * then calls the appropriate callback for the chunk if it is valid.
+  */
+-
+-/* Decode the IHDR chunk */
+-PNG_INTERNAL_FUNCTION(void,png_handle_IHDR,(png_structrp png_ptr,
+-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
+-PNG_INTERNAL_FUNCTION(void,png_handle_PLTE,(png_structrp png_ptr,
+-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
+-PNG_INTERNAL_FUNCTION(void,png_handle_IEND,(png_structrp png_ptr,
+-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
+-
+-#ifdef PNG_READ_bKGD_SUPPORTED
+-PNG_INTERNAL_FUNCTION(void,png_handle_bKGD,(png_structrp png_ptr,
+-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
+-#endif
+-
+-#ifdef PNG_READ_cHRM_SUPPORTED
+-PNG_INTERNAL_FUNCTION(void,png_handle_cHRM,(png_structrp png_ptr,
+-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
+-#endif
+-
+-#ifdef PNG_READ_eXIf_SUPPORTED
+-PNG_INTERNAL_FUNCTION(void,png_handle_eXIf,(png_structrp png_ptr,
+-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
+-#endif
+-
+-#ifdef PNG_READ_gAMA_SUPPORTED
+-PNG_INTERNAL_FUNCTION(void,png_handle_gAMA,(png_structrp png_ptr,
+-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
+-#endif
+-
+-#ifdef PNG_READ_hIST_SUPPORTED
+-PNG_INTERNAL_FUNCTION(void,png_handle_hIST,(png_structrp png_ptr,
+-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
+-#endif
+-
+-#ifdef PNG_READ_iCCP_SUPPORTED
+-PNG_INTERNAL_FUNCTION(void,png_handle_iCCP,(png_structrp png_ptr,
+-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
+-#endif /* READ_iCCP */
+-
+-#ifdef PNG_READ_iTXt_SUPPORTED
+-PNG_INTERNAL_FUNCTION(void,png_handle_iTXt,(png_structrp png_ptr,
+-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
+-#endif
+-
+-#ifdef PNG_READ_oFFs_SUPPORTED
+-PNG_INTERNAL_FUNCTION(void,png_handle_oFFs,(png_structrp png_ptr,
+-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
+-#endif
+-
+-#ifdef PNG_READ_pCAL_SUPPORTED
+-PNG_INTERNAL_FUNCTION(void,png_handle_pCAL,(png_structrp png_ptr,
+-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
+-#endif
+-
+-#ifdef PNG_READ_pHYs_SUPPORTED
+-PNG_INTERNAL_FUNCTION(void,png_handle_pHYs,(png_structrp png_ptr,
+-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
+-#endif
+-
+-#ifdef PNG_READ_sBIT_SUPPORTED
+-PNG_INTERNAL_FUNCTION(void,png_handle_sBIT,(png_structrp png_ptr,
+-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
+-#endif
+-
+-#ifdef PNG_READ_sCAL_SUPPORTED
+-PNG_INTERNAL_FUNCTION(void,png_handle_sCAL,(png_structrp png_ptr,
+-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
+-#endif
+-
+-#ifdef PNG_READ_sPLT_SUPPORTED
+-PNG_INTERNAL_FUNCTION(void,png_handle_sPLT,(png_structrp png_ptr,
+-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
+-#endif /* READ_sPLT */
+-
+-#ifdef PNG_READ_sRGB_SUPPORTED
+-PNG_INTERNAL_FUNCTION(void,png_handle_sRGB,(png_structrp png_ptr,
+-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
+-#endif
+-
+-#ifdef PNG_READ_tEXt_SUPPORTED
+-PNG_INTERNAL_FUNCTION(void,png_handle_tEXt,(png_structrp png_ptr,
+-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
+-#endif
+-
+-#ifdef PNG_READ_tIME_SUPPORTED
+-PNG_INTERNAL_FUNCTION(void,png_handle_tIME,(png_structrp png_ptr,
+-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
+-#endif
+-
+-#ifdef PNG_READ_tRNS_SUPPORTED
+-PNG_INTERNAL_FUNCTION(void,png_handle_tRNS,(png_structrp png_ptr,
+-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
+-#endif
+-
+-#ifdef PNG_READ_zTXt_SUPPORTED
+-PNG_INTERNAL_FUNCTION(void,png_handle_zTXt,(png_structrp png_ptr,
+-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
+-#endif
+-
+-PNG_INTERNAL_FUNCTION(void,png_check_chunk_name,(png_const_structrp png_ptr,
+-    png_uint_32 chunk_name),PNG_EMPTY);
+-
+-PNG_INTERNAL_FUNCTION(void,png_check_chunk_length,(png_const_structrp png_ptr,
+-    png_uint_32 chunk_length),PNG_EMPTY);
+-
+-PNG_INTERNAL_FUNCTION(void,png_handle_unknown,(png_structrp png_ptr,
+-    png_inforp info_ptr, png_uint_32 length, int keep),PNG_EMPTY);
++typedef enum
++{
++   /* Result of a call to png_handle_chunk made to handle the current chunk
++    * png_struct::chunk_name on read.  Always informational, either the stream
++    * is read for the next chunk or the routine will call png_error.
++    *
++    * NOTE: order is important internally.  handled_saved and above are regarded
++    * as handling the chunk.
++    */
++   handled_error = 0,  /* bad crc or known and bad format or too long */
++   handled_discarded,  /* not saved in the unknown chunk list */
++   handled_saved,      /* saved in the unknown chunk list */
++   handled_ok          /* known, supported and handled without error */
++} png_handle_result_code;
++
++PNG_INTERNAL_FUNCTION(png_handle_result_code,png_handle_unknown,
++    (png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length, int keep),
++    PNG_EMPTY);
+    /* This is the function that gets called for unknown chunks.  The 'keep'
+     * argument is either non-zero for a known chunk that has been set to be
+     * handled as unknown or zero for an unknown chunk.  By default the function
+     * just skips the chunk or errors out if it is critical.
+     */
+ 
++PNG_INTERNAL_FUNCTION(png_handle_result_code,png_handle_chunk,
++    (png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
++   /* This handles the current chunk png_ptr->chunk_name with unread
++    * data[length] and returns one of the above result codes.
++    */
++
+ #if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) ||\
+     defined(PNG_HANDLE_AS_UNKNOWN_SUPPORTED)
+ PNG_INTERNAL_FUNCTION(int,png_chunk_unknown_handling,
+@@ -1676,8 +1686,6 @@ PNG_INTERNAL_FUNCTION(void,png_process_IDAT_data,(png_structrp png_ptr,
+     png_bytep buffer, size_t buffer_length),PNG_EMPTY);
+ PNG_INTERNAL_FUNCTION(void,png_push_process_row,(png_structrp png_ptr),
+     PNG_EMPTY);
+-PNG_INTERNAL_FUNCTION(void,png_push_handle_unknown,(png_structrp png_ptr,
+-   png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
+ PNG_INTERNAL_FUNCTION(void,png_push_have_info,(png_structrp png_ptr,
+    png_inforp info_ptr),PNG_EMPTY);
+ PNG_INTERNAL_FUNCTION(void,png_push_have_end,(png_structrp png_ptr,
+@@ -1690,109 +1698,28 @@ PNG_INTERNAL_FUNCTION(void,png_process_some_data,(png_structrp png_ptr,
+     png_inforp info_ptr),PNG_EMPTY);
+ PNG_INTERNAL_FUNCTION(void,png_read_push_finish_row,(png_structrp png_ptr),
+     PNG_EMPTY);
+-#  ifdef PNG_READ_tEXt_SUPPORTED
+-PNG_INTERNAL_FUNCTION(void,png_push_handle_tEXt,(png_structrp png_ptr,
+-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
+-PNG_INTERNAL_FUNCTION(void,png_push_read_tEXt,(png_structrp png_ptr,
+-    png_inforp info_ptr),PNG_EMPTY);
+-#  endif
+-#  ifdef PNG_READ_zTXt_SUPPORTED
+-PNG_INTERNAL_FUNCTION(void,png_push_handle_zTXt,(png_structrp png_ptr,
+-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
+-PNG_INTERNAL_FUNCTION(void,png_push_read_zTXt,(png_structrp png_ptr,
+-    png_inforp info_ptr),PNG_EMPTY);
+-#  endif
+-#  ifdef PNG_READ_iTXt_SUPPORTED
+-PNG_INTERNAL_FUNCTION(void,png_push_handle_iTXt,(png_structrp png_ptr,
+-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
+-PNG_INTERNAL_FUNCTION(void,png_push_read_iTXt,(png_structrp png_ptr,
+-    png_inforp info_ptr),PNG_EMPTY);
+-#  endif
+-
+ #endif /* PROGRESSIVE_READ */
+ 
+-/* Added at libpng version 1.6.0 */
+-#ifdef PNG_GAMMA_SUPPORTED
+-PNG_INTERNAL_FUNCTION(void,png_colorspace_set_gamma,(png_const_structrp png_ptr,
+-    png_colorspacerp colorspace, png_fixed_point gAMA), PNG_EMPTY);
+-   /* Set the colorspace gamma with a value provided by the application or by
+-    * the gAMA chunk on read.  The value will override anything set by an ICC
+-    * profile.
+-    */
+-
+-PNG_INTERNAL_FUNCTION(void,png_colorspace_sync_info,(png_const_structrp png_ptr,
+-    png_inforp info_ptr), PNG_EMPTY);
+-   /* Synchronize the info 'valid' flags with the colorspace */
+-
+-PNG_INTERNAL_FUNCTION(void,png_colorspace_sync,(png_const_structrp png_ptr,
+-    png_inforp info_ptr), PNG_EMPTY);
+-   /* Copy the png_struct colorspace to the info_struct and call the above to
+-    * synchronize the flags.  Checks for NULL info_ptr and does nothing.
+-    */
+-#endif
+-
+-/* Added at libpng version 1.4.0 */
+-#ifdef PNG_COLORSPACE_SUPPORTED
+-/* These internal functions are for maintaining the colorspace structure within
+- * a png_info or png_struct (or, indeed, both).
+- */
+-PNG_INTERNAL_FUNCTION(int,png_colorspace_set_chromaticities,
+-   (png_const_structrp png_ptr, png_colorspacerp colorspace, const png_xy *xy,
+-    int preferred), PNG_EMPTY);
+-
+-PNG_INTERNAL_FUNCTION(int,png_colorspace_set_endpoints,
+-   (png_const_structrp png_ptr, png_colorspacerp colorspace, const png_XYZ *XYZ,
+-    int preferred), PNG_EMPTY);
+-
+-#ifdef PNG_sRGB_SUPPORTED
+-PNG_INTERNAL_FUNCTION(int,png_colorspace_set_sRGB,(png_const_structrp png_ptr,
+-   png_colorspacerp colorspace, int intent), PNG_EMPTY);
+-   /* This does set the colorspace gAMA and cHRM values too, but doesn't set the
+-    * flags to write them, if it returns false there was a problem and an error
+-    * message has already been output (but the colorspace may still need to be
+-    * synced to record the invalid flag).
+-    */
+-#endif /* sRGB */
+-
+ #ifdef PNG_iCCP_SUPPORTED
+-PNG_INTERNAL_FUNCTION(int,png_colorspace_set_ICC,(png_const_structrp png_ptr,
+-   png_colorspacerp colorspace, png_const_charp name,
+-   png_uint_32 profile_length, png_const_bytep profile, int color_type),
+-   PNG_EMPTY);
+-   /* The 'name' is used for information only */
+-
+ /* Routines for checking parts of an ICC profile. */
+ #ifdef PNG_READ_iCCP_SUPPORTED
+ PNG_INTERNAL_FUNCTION(int,png_icc_check_length,(png_const_structrp png_ptr,
+-   png_colorspacerp colorspace, png_const_charp name,
+-   png_uint_32 profile_length), PNG_EMPTY);
++   png_const_charp name, png_uint_32 profile_length), PNG_EMPTY);
+ #endif /* READ_iCCP */
+ PNG_INTERNAL_FUNCTION(int,png_icc_check_header,(png_const_structrp png_ptr,
+-   png_colorspacerp colorspace, png_const_charp name,
+-   png_uint_32 profile_length,
++   png_const_charp name, png_uint_32 profile_length,
+    png_const_bytep profile /* first 132 bytes only */, int color_type),
+    PNG_EMPTY);
+ PNG_INTERNAL_FUNCTION(int,png_icc_check_tag_table,(png_const_structrp png_ptr,
+-   png_colorspacerp colorspace, png_const_charp name,
+-   png_uint_32 profile_length,
++   png_const_charp name, png_uint_32 profile_length,
+    png_const_bytep profile /* header plus whole tag table */), PNG_EMPTY);
+-#ifdef PNG_sRGB_SUPPORTED
+-PNG_INTERNAL_FUNCTION(void,png_icc_set_sRGB,(
+-   png_const_structrp png_ptr, png_colorspacerp colorspace,
+-   png_const_bytep profile, uLong adler), PNG_EMPTY);
+-   /* 'adler' is the Adler32 checksum of the uncompressed profile data. It may
+-    * be zero to indicate that it is not available.  It is used, if provided,
+-    * as a fast check on the profile when checking to see if it is sRGB.
+-    */
+-#endif
+ #endif /* iCCP */
+ 
+ #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
+-PNG_INTERNAL_FUNCTION(void,png_colorspace_set_rgb_coefficients,
+-   (png_structrp png_ptr), PNG_EMPTY);
+-   /* Set the rgb_to_gray coefficients from the colorspace Y values */
++PNG_INTERNAL_FUNCTION(void,png_set_rgb_coefficients, (png_structrp png_ptr),
++   PNG_EMPTY);
++   /* Set the rgb_to_gray coefficients from the cHRM Y values (if unset) */
+ #endif /* READ_RGB_TO_GRAY */
+-#endif /* COLORSPACE */
+ 
+ /* Added at libpng version 1.4.0 */
+ PNG_INTERNAL_FUNCTION(void,png_check_IHDR,(png_const_structrp png_ptr,
+@@ -2054,8 +1981,10 @@ PNG_INTERNAL_FUNCTION(int,png_check_fp_string,(png_const_charp string,
+    size_t size),PNG_EMPTY);
+ #endif /* pCAL || sCAL */
+ 
+-#if defined(PNG_GAMMA_SUPPORTED) ||\
+-    defined(PNG_INCH_CONVERSIONS_SUPPORTED) || defined(PNG_READ_pHYs_SUPPORTED)
++#if defined(PNG_READ_GAMMA_SUPPORTED) ||\
++    defined(PNG_COLORSPACE_SUPPORTED) ||\
++    defined(PNG_INCH_CONVERSIONS_SUPPORTED) ||\
++    defined(PNG_READ_pHYs_SUPPORTED)
+ /* Added at libpng version 1.5.0 */
+ /* This is a utility to provide a*times/div (rounded) and indicate
+  * if there is an overflow.  The result is a boolean - false (0)
+@@ -2064,22 +1993,14 @@ PNG_INTERNAL_FUNCTION(int,png_check_fp_string,(png_const_charp string,
+  */
+ PNG_INTERNAL_FUNCTION(int,png_muldiv,(png_fixed_point_p res, png_fixed_point a,
+    png_int_32 multiplied_by, png_int_32 divided_by),PNG_EMPTY);
+-#endif
+-
+-#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_INCH_CONVERSIONS_SUPPORTED)
+-/* Same deal, but issue a warning on overflow and return 0. */
+-PNG_INTERNAL_FUNCTION(png_fixed_point,png_muldiv_warn,
+-   (png_const_structrp png_ptr, png_fixed_point a, png_int_32 multiplied_by,
+-   png_int_32 divided_by),PNG_EMPTY);
+-#endif
+ 
+-#ifdef PNG_GAMMA_SUPPORTED
+ /* Calculate a reciprocal - used for gamma values.  This returns
+  * 0 if the argument is 0 in order to maintain an undefined value;
+  * there are no warnings.
+  */
+ PNG_INTERNAL_FUNCTION(png_fixed_point,png_reciprocal,(png_fixed_point a),
+    PNG_EMPTY);
++#endif
+ 
+ #ifdef PNG_READ_GAMMA_SUPPORTED
+ /* The same but gives a reciprocal of the product of two fixed point
+@@ -2088,14 +2009,22 @@ PNG_INTERNAL_FUNCTION(png_fixed_point,png_reciprocal,(png_fixed_point a),
+  */
+ PNG_INTERNAL_FUNCTION(png_fixed_point,png_reciprocal2,(png_fixed_point a,
+    png_fixed_point b),PNG_EMPTY);
+-#endif
+ 
+ /* Return true if the gamma value is significantly different from 1.0 */
+ PNG_INTERNAL_FUNCTION(int,png_gamma_significant,(png_fixed_point gamma_value),
+    PNG_EMPTY);
+-#endif
+ 
+-#ifdef PNG_READ_GAMMA_SUPPORTED
++/* PNGv3: 'resolve' the file gamma according to the new PNGv3 rules for colour
++ * space information.
++ *
++ * NOTE: this uses precisely those chunks that libpng supports.  For example it
++ * doesn't use iCCP and it can only use cICP for known and manageable
++ * transforms.  For this reason a gamma specified by png_set_gamma always takes
++ * precedence.
++ */
++PNG_INTERNAL_FUNCTION(png_fixed_point,png_resolve_file_gamma,
++   (png_const_structrp png_ptr),PNG_EMPTY);
++
+ /* Internal fixed point gamma correction.  These APIs are called as
+  * required to convert single values - they don't need to be fast,
+  * they are not used when processing image pixel values.
+@@ -2113,6 +2042,22 @@ PNG_INTERNAL_FUNCTION(void,png_destroy_gamma_table,(png_structrp png_ptr),
+    PNG_EMPTY);
+ PNG_INTERNAL_FUNCTION(void,png_build_gamma_table,(png_structrp png_ptr,
+    int bit_depth),PNG_EMPTY);
++#endif /* READ_GAMMA */
++
++#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
++/* Set the RGB coefficients if not already set by png_set_rgb_to_gray */
++PNG_INTERNAL_FUNCTION(void,png_set_rgb_coefficients,(png_structrp png_ptr),
++   PNG_EMPTY);
++#endif
++
++#if defined(PNG_cHRM_SUPPORTED) || defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
++PNG_INTERNAL_FUNCTION(int,png_XYZ_from_xy,(png_XYZ *XYZ, const png_xy *xy),
++   PNG_EMPTY);
++#endif /* cHRM || READ_RGB_TO_GRAY */
++
++#ifdef PNG_COLORSPACE_SUPPORTED
++PNG_INTERNAL_FUNCTION(int,png_xy_from_XYZ,(png_xy *xy, const png_XYZ *XYZ),
++   PNG_EMPTY);
+ #endif
+ 
+ /* SIMPLIFIED READ/WRITE SUPPORT */
+diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngread.c b/src/java.desktop/share/native/libsplashscreen/libpng/pngread.c
+index e9e944775..8a6381e1b 100644
+--- a/src/java.desktop/share/native/libsplashscreen/libpng/pngread.c
++++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngread.c
+@@ -29,7 +29,7 @@
+  * However, the following notice accompanied the original version of this
+  * file and, per its terms, should not be removed:
+  *
+- * Copyright (c) 2018-2024 Cosmin Truta
++ * Copyright (c) 2018-2025 Cosmin Truta
+  * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
+  * Copyright (c) 1996-1997 Andreas Dilger
+  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
+@@ -160,14 +160,11 @@ png_read_info(png_structrp png_ptr, png_inforp info_ptr)
+          png_ptr->mode |= PNG_AFTER_IDAT;
+       }
+ 
+-      /* This should be a binary subdivision search or a hash for
+-       * matching the chunk name rather than a linear search.
+-       */
+       if (chunk_name == png_IHDR)
+-         png_handle_IHDR(png_ptr, info_ptr, length);
++         png_handle_chunk(png_ptr, info_ptr, length);
+ 
+       else if (chunk_name == png_IEND)
+-         png_handle_IEND(png_ptr, info_ptr, length);
++         png_handle_chunk(png_ptr, info_ptr, length);
+ 
+ #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
+       else if ((keep = png_chunk_unknown_handling(png_ptr, chunk_name)) != 0)
+@@ -184,8 +181,6 @@ png_read_info(png_structrp png_ptr, png_inforp info_ptr)
+          }
+       }
+ #endif
+-      else if (chunk_name == png_PLTE)
+-         png_handle_PLTE(png_ptr, info_ptr, length);
+ 
+       else if (chunk_name == png_IDAT)
+       {
+@@ -193,99 +188,8 @@ png_read_info(png_structrp png_ptr, png_inforp info_ptr)
+          break;
+       }
+ 
+-#ifdef PNG_READ_bKGD_SUPPORTED
+-      else if (chunk_name == png_bKGD)
+-         png_handle_bKGD(png_ptr, info_ptr, length);
+-#endif
+-
+-#ifdef PNG_READ_cHRM_SUPPORTED
+-      else if (chunk_name == png_cHRM)
+-         png_handle_cHRM(png_ptr, info_ptr, length);
+-#endif
+-
+-#ifdef PNG_READ_eXIf_SUPPORTED
+-      else if (chunk_name == png_eXIf)
+-         png_handle_eXIf(png_ptr, info_ptr, length);
+-#endif
+-
+-#ifdef PNG_READ_gAMA_SUPPORTED
+-      else if (chunk_name == png_gAMA)
+-         png_handle_gAMA(png_ptr, info_ptr, length);
+-#endif
+-
+-#ifdef PNG_READ_hIST_SUPPORTED
+-      else if (chunk_name == png_hIST)
+-         png_handle_hIST(png_ptr, info_ptr, length);
+-#endif
+-
+-#ifdef PNG_READ_oFFs_SUPPORTED
+-      else if (chunk_name == png_oFFs)
+-         png_handle_oFFs(png_ptr, info_ptr, length);
+-#endif
+-
+-#ifdef PNG_READ_pCAL_SUPPORTED
+-      else if (chunk_name == png_pCAL)
+-         png_handle_pCAL(png_ptr, info_ptr, length);
+-#endif
+-
+-#ifdef PNG_READ_sCAL_SUPPORTED
+-      else if (chunk_name == png_sCAL)
+-         png_handle_sCAL(png_ptr, info_ptr, length);
+-#endif
+-
+-#ifdef PNG_READ_pHYs_SUPPORTED
+-      else if (chunk_name == png_pHYs)
+-         png_handle_pHYs(png_ptr, info_ptr, length);
+-#endif
+-
+-#ifdef PNG_READ_sBIT_SUPPORTED
+-      else if (chunk_name == png_sBIT)
+-         png_handle_sBIT(png_ptr, info_ptr, length);
+-#endif
+-
+-#ifdef PNG_READ_sRGB_SUPPORTED
+-      else if (chunk_name == png_sRGB)
+-         png_handle_sRGB(png_ptr, info_ptr, length);
+-#endif
+-
+-#ifdef PNG_READ_iCCP_SUPPORTED
+-      else if (chunk_name == png_iCCP)
+-         png_handle_iCCP(png_ptr, info_ptr, length);
+-#endif
+-
+-#ifdef PNG_READ_sPLT_SUPPORTED
+-      else if (chunk_name == png_sPLT)
+-         png_handle_sPLT(png_ptr, info_ptr, length);
+-#endif
+-
+-#ifdef PNG_READ_tEXt_SUPPORTED
+-      else if (chunk_name == png_tEXt)
+-         png_handle_tEXt(png_ptr, info_ptr, length);
+-#endif
+-
+-#ifdef PNG_READ_tIME_SUPPORTED
+-      else if (chunk_name == png_tIME)
+-         png_handle_tIME(png_ptr, info_ptr, length);
+-#endif
+-
+-#ifdef PNG_READ_tRNS_SUPPORTED
+-      else if (chunk_name == png_tRNS)
+-         png_handle_tRNS(png_ptr, info_ptr, length);
+-#endif
+-
+-#ifdef PNG_READ_zTXt_SUPPORTED
+-      else if (chunk_name == png_zTXt)
+-         png_handle_zTXt(png_ptr, info_ptr, length);
+-#endif
+-
+-#ifdef PNG_READ_iTXt_SUPPORTED
+-      else if (chunk_name == png_iTXt)
+-         png_handle_iTXt(png_ptr, info_ptr, length);
+-#endif
+-
+       else
+-         png_handle_unknown(png_ptr, info_ptr, length,
+-             PNG_HANDLE_CHUNK_AS_DEFAULT);
++         png_handle_chunk(png_ptr, info_ptr, length);
+    }
+ }
+ #endif /* SEQUENTIAL_READ */
+@@ -830,10 +734,10 @@ png_read_end(png_structrp png_ptr, png_inforp info_ptr)
+          png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT;
+ 
+       if (chunk_name == png_IEND)
+-         png_handle_IEND(png_ptr, info_ptr, length);
++         png_handle_chunk(png_ptr, info_ptr, length);
+ 
+       else if (chunk_name == png_IHDR)
+-         png_handle_IHDR(png_ptr, info_ptr, length);
++         png_handle_chunk(png_ptr, info_ptr, length);
+ 
+       else if (info_ptr == NULL)
+          png_crc_finish(png_ptr, length);
+@@ -867,102 +771,9 @@ png_read_end(png_structrp png_ptr, png_inforp info_ptr)
+ 
+          png_crc_finish(png_ptr, length);
+       }
+-      else if (chunk_name == png_PLTE)
+-         png_handle_PLTE(png_ptr, info_ptr, length);
+-
+-#ifdef PNG_READ_bKGD_SUPPORTED
+-      else if (chunk_name == png_bKGD)
+-         png_handle_bKGD(png_ptr, info_ptr, length);
+-#endif
+-
+-#ifdef PNG_READ_cHRM_SUPPORTED
+-      else if (chunk_name == png_cHRM)
+-         png_handle_cHRM(png_ptr, info_ptr, length);
+-#endif
+-
+-#ifdef PNG_READ_eXIf_SUPPORTED
+-      else if (chunk_name == png_eXIf)
+-         png_handle_eXIf(png_ptr, info_ptr, length);
+-#endif
+-
+-#ifdef PNG_READ_gAMA_SUPPORTED
+-      else if (chunk_name == png_gAMA)
+-         png_handle_gAMA(png_ptr, info_ptr, length);
+-#endif
+-
+-#ifdef PNG_READ_hIST_SUPPORTED
+-      else if (chunk_name == png_hIST)
+-         png_handle_hIST(png_ptr, info_ptr, length);
+-#endif
+-
+-#ifdef PNG_READ_oFFs_SUPPORTED
+-      else if (chunk_name == png_oFFs)
+-         png_handle_oFFs(png_ptr, info_ptr, length);
+-#endif
+-
+-#ifdef PNG_READ_pCAL_SUPPORTED
+-      else if (chunk_name == png_pCAL)
+-         png_handle_pCAL(png_ptr, info_ptr, length);
+-#endif
+-
+-#ifdef PNG_READ_sCAL_SUPPORTED
+-      else if (chunk_name == png_sCAL)
+-         png_handle_sCAL(png_ptr, info_ptr, length);
+-#endif
+-
+-#ifdef PNG_READ_pHYs_SUPPORTED
+-      else if (chunk_name == png_pHYs)
+-         png_handle_pHYs(png_ptr, info_ptr, length);
+-#endif
+-
+-#ifdef PNG_READ_sBIT_SUPPORTED
+-      else if (chunk_name == png_sBIT)
+-         png_handle_sBIT(png_ptr, info_ptr, length);
+-#endif
+-
+-#ifdef PNG_READ_sRGB_SUPPORTED
+-      else if (chunk_name == png_sRGB)
+-         png_handle_sRGB(png_ptr, info_ptr, length);
+-#endif
+-
+-#ifdef PNG_READ_iCCP_SUPPORTED
+-      else if (chunk_name == png_iCCP)
+-         png_handle_iCCP(png_ptr, info_ptr, length);
+-#endif
+-
+-#ifdef PNG_READ_sPLT_SUPPORTED
+-      else if (chunk_name == png_sPLT)
+-         png_handle_sPLT(png_ptr, info_ptr, length);
+-#endif
+-
+-#ifdef PNG_READ_tEXt_SUPPORTED
+-      else if (chunk_name == png_tEXt)
+-         png_handle_tEXt(png_ptr, info_ptr, length);
+-#endif
+-
+-#ifdef PNG_READ_tIME_SUPPORTED
+-      else if (chunk_name == png_tIME)
+-         png_handle_tIME(png_ptr, info_ptr, length);
+-#endif
+-
+-#ifdef PNG_READ_tRNS_SUPPORTED
+-      else if (chunk_name == png_tRNS)
+-         png_handle_tRNS(png_ptr, info_ptr, length);
+-#endif
+-
+-#ifdef PNG_READ_zTXt_SUPPORTED
+-      else if (chunk_name == png_zTXt)
+-         png_handle_zTXt(png_ptr, info_ptr, length);
+-#endif
+-
+-#ifdef PNG_READ_iTXt_SUPPORTED
+-      else if (chunk_name == png_iTXt)
+-         png_handle_iTXt(png_ptr, info_ptr, length);
+-#endif
+ 
+       else
+-         png_handle_unknown(png_ptr, info_ptr, length,
+-             PNG_HANDLE_CHUNK_AS_DEFAULT);
++         png_handle_chunk(png_ptr, info_ptr, length);
+    } while ((png_ptr->mode & PNG_HAVE_IEND) == 0);
+ }
+ #endif /* SEQUENTIAL_READ */
+@@ -1413,6 +1224,31 @@ png_image_format(png_structrp png_ptr)
+    return format;
+ }
+ 
++static int
++chromaticities_match_sRGB(const png_xy *xy)
++{
++#  define sRGB_TOLERANCE 1000
++   static const png_xy sRGB_xy = /* From ITU-R BT.709-3 */
++   {
++      /* color      x       y */
++      /* red   */ 64000, 33000,
++      /* green */ 30000, 60000,
++      /* blue  */ 15000,  6000,
++      /* white */ 31270, 32900
++   };
++
++   if (PNG_OUT_OF_RANGE(xy->whitex, sRGB_xy.whitex,sRGB_TOLERANCE) ||
++       PNG_OUT_OF_RANGE(xy->whitey, sRGB_xy.whitey,sRGB_TOLERANCE) ||
++       PNG_OUT_OF_RANGE(xy->redx,   sRGB_xy.redx,  sRGB_TOLERANCE) ||
++       PNG_OUT_OF_RANGE(xy->redy,   sRGB_xy.redy,  sRGB_TOLERANCE) ||
++       PNG_OUT_OF_RANGE(xy->greenx, sRGB_xy.greenx,sRGB_TOLERANCE) ||
++       PNG_OUT_OF_RANGE(xy->greeny, sRGB_xy.greeny,sRGB_TOLERANCE) ||
++       PNG_OUT_OF_RANGE(xy->bluex,  sRGB_xy.bluex, sRGB_TOLERANCE) ||
++       PNG_OUT_OF_RANGE(xy->bluey,  sRGB_xy.bluey, sRGB_TOLERANCE))
++      return 0;
++   return 1;
++}
++
+ /* Is the given gamma significantly different from sRGB?  The test is the same
+  * one used in pngrtran.c when deciding whether to do gamma correction.  The
+  * arithmetic optimizes the division by using the fact that the inverse of the
+@@ -1421,22 +1257,44 @@ png_image_format(png_structrp png_ptr)
+ static int
+ png_gamma_not_sRGB(png_fixed_point g)
+ {
+-   if (g < PNG_FP_1)
+-   {
+-      /* An uninitialized gamma is assumed to be sRGB for the simplified API. */
+-      if (g == 0)
+-         return 0;
+-
+-      return png_gamma_significant((g * 11 + 2)/5 /* i.e. *2.2, rounded */);
+-   }
++   /* 1.6.47: use the same sanity checks as used in pngrtran.c */
++   if (g < PNG_LIB_GAMMA_MIN || g > PNG_LIB_GAMMA_MAX)
++      return 0; /* Includes the uninitialized value 0 */
+ 
+-   return 1;
++   return png_gamma_significant((g * 11 + 2)/5 /* i.e. *2.2, rounded */);
+ }
+ 
+ /* Do the main body of a 'png_image_begin_read' function; read the PNG file
+  * header and fill in all the information.  This is executed in a safe context,
+  * unlike the init routine above.
+  */
++static int
++png_image_is_not_sRGB(png_const_structrp png_ptr)
++{
++   /* Does the colorspace **not** match sRGB?  The flag is only set if the
++    * answer can be determined reliably.
++    *
++    * png_struct::chromaticities always exists since the simplified API
++    * requires rgb-to-gray.  The mDCV, cICP and cHRM chunks may all set it to
++    * a non-sRGB value, so it needs to be checked but **only** if one of
++    * those chunks occured in the file.
++    */
++   /* Highest priority: check to be safe. */
++   if (png_has_chunk(png_ptr, cICP) || png_has_chunk(png_ptr, mDCV))
++      return !chromaticities_match_sRGB(&png_ptr->chromaticities);
++
++   /* If the image is marked as sRGB then it is... */
++   if (png_has_chunk(png_ptr, sRGB))
++      return 0;
++
++   /* Last stop: cHRM, must check: */
++   if (png_has_chunk(png_ptr, cHRM))
++      return !chromaticities_match_sRGB(&png_ptr->chromaticities);
++
++   /* Else default to sRGB */
++   return 0;
++}
++
+ static int
+ png_image_read_header(png_voidp argument)
+ {
+@@ -1458,17 +1316,13 @@ png_image_read_header(png_voidp argument)
+ 
+       image->format = format;
+ 
+-#ifdef PNG_COLORSPACE_SUPPORTED
+-      /* Does the colorspace match sRGB?  If there is no color endpoint
+-       * (colorant) information assume yes, otherwise require the
+-       * 'ENDPOINTS_MATCHP_sRGB' colorspace flag to have been set.  If the
+-       * colorspace has been determined to be invalid ignore it.
++      /* Greyscale images don't (typically) have colour space information and
++       * using it is pretty much impossible, so use sRGB for grayscale (it
++       * doesn't matter r==g==b so the transform is irrelevant.)
+        */
+-      if ((format & PNG_FORMAT_FLAG_COLOR) != 0 && ((png_ptr->colorspace.flags
+-         & (PNG_COLORSPACE_HAVE_ENDPOINTS|PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB|
+-            PNG_COLORSPACE_INVALID)) == PNG_COLORSPACE_HAVE_ENDPOINTS))
++      if ((format & PNG_FORMAT_FLAG_COLOR) != 0 &&
++          png_image_is_not_sRGB(png_ptr))
+          image->flags |= PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB;
+-#endif
+    }
+ 
+    /* We need the maximum number of entries regardless of the format the
+@@ -1656,21 +1510,18 @@ png_image_skip_unused_chunks(png_structrp png_ptr)
+     * potential vulnerability to security problems in the unused chunks.
+     *
+     * At present the iCCP chunk data isn't used, so iCCP chunk can be ignored
+-    * too.  This allows the simplified API to be compiled without iCCP support,
+-    * however if the support is there the chunk is still checked to detect
+-    * errors (which are unfortunately quite common.)
++    * too.  This allows the simplified API to be compiled without iCCP support.
+     */
+    {
+          static const png_byte chunks_to_process[] = {
+             98,  75,  71,  68, '\0',  /* bKGD */
+             99,  72,  82,  77, '\0',  /* cHRM */
++            99,  73,  67,  80, '\0',  /* cICP */
+            103,  65,  77,  65, '\0',  /* gAMA */
+-#        ifdef PNG_READ_iCCP_SUPPORTED
+-           105,  67,  67,  80, '\0',  /* iCCP */
+-#        endif
++           109,  68,  67,  86, '\0',  /* mDCV */
+            115,  66,  73,  84, '\0',  /* sBIT */
+            115,  82,  71,  66, '\0',  /* sRGB */
+-           };
++         };
+ 
+        /* Ignore unknown chunks and all other chunks except for the
+         * IHDR, PLTE, tRNS, IDAT, and IEND chunks.
+@@ -1699,7 +1550,15 @@ png_image_skip_unused_chunks(png_structrp png_ptr)
+ static void
+ set_file_encoding(png_image_read_control *display)
+ {
+-   png_fixed_point g = display->image->opaque->png_ptr->colorspace.gamma;
++   png_structrp png_ptr = display->image->opaque->png_ptr;
++   png_fixed_point g = png_resolve_file_gamma(png_ptr);
++
++   /* PNGv3: the result may be 0 however the 'default_gamma' should have been
++    * set before this is called so zero is an error:
++    */
++   if (g == 0)
++      png_error(png_ptr, "internal: default gamma not set");
++
+    if (png_gamma_significant(g) != 0)
+    {
+       if (png_gamma_not_sRGB(g) != 0)
+@@ -2187,24 +2046,18 @@ png_image_read_colormap(png_voidp argument)
+    /* Default the input file gamma if required - this is necessary because
+     * libpng assumes that if no gamma information is present the data is in the
+     * output format, but the simplified API deduces the gamma from the input
+-    * format.
++    * format.  The 'default' gamma value is also set by png_set_alpha_mode, but
++    * this is happening before any such call, so:
++    *
++    * TODO: should be an internal API and all this code should be copied into a
++    * single common gamma+colorspace file.
+     */
+-   if ((png_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_GAMMA) == 0)
+-   {
+-      /* Do this directly, not using the png_colorspace functions, to ensure
+-       * that it happens even if the colorspace is invalid (though probably if
+-       * it is the setting will be ignored)  Note that the same thing can be
+-       * achieved at the application interface with png_set_gAMA.
+-       */
+-      if (png_ptr->bit_depth == 16 &&
+-         (image->flags & PNG_IMAGE_FLAG_16BIT_sRGB) == 0)
+-         png_ptr->colorspace.gamma = PNG_GAMMA_LINEAR;
+-
+-      else
+-         png_ptr->colorspace.gamma = PNG_GAMMA_sRGB_INVERSE;
++   if (png_ptr->bit_depth == 16 &&
++      (image->flags & PNG_IMAGE_FLAG_16BIT_sRGB) == 0)
++      png_ptr->default_gamma = PNG_GAMMA_LINEAR;
+ 
+-      png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA;
+-   }
++   else
++      png_ptr->default_gamma = PNG_GAMMA_sRGB_INVERSE;
+ 
+    /* Decide what to do based on the PNG color type of the input data.  The
+     * utility function png_create_colormap_entry deals with most aspects of the
+@@ -2582,6 +2435,8 @@ png_image_read_colormap(png_voidp argument)
+ 
+             else
+             {
++               const png_fixed_point gamma = png_resolve_file_gamma(png_ptr);
++
+                /* Either the input or the output has no alpha channel, so there
+                 * will be no non-opaque pixels in the color-map; it will just be
+                 * grayscale.
+@@ -2596,10 +2451,13 @@ png_image_read_colormap(png_voidp argument)
+                 * this case and doing it in the palette; this will result in
+                 * duplicate palette entries, but that's better than the
+                 * alternative of double gamma correction.
++                *
++                * NOTE: PNGv3: check the resolved result of all the potentially
++                * different colour space chunks.
+                 */
+                if ((png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
+                   png_ptr->num_trans > 0) &&
+-                  png_gamma_not_sRGB(png_ptr->colorspace.gamma) != 0)
++                  png_gamma_not_sRGB(gamma) != 0)
+                {
+                   cmap_entries = (unsigned int)make_gray_file_colormap(display);
+                   data_encoding = P_FILE;
+@@ -2631,8 +2489,8 @@ png_image_read_colormap(png_voidp argument)
+                      if (output_encoding == P_sRGB)
+                         gray = png_sRGB_table[gray]; /* now P_LINEAR */
+ 
+-                     gray = PNG_DIV257(png_gamma_16bit_correct(gray,
+-                         png_ptr->colorspace.gamma)); /* now P_FILE */
++                     gray = PNG_DIV257(png_gamma_16bit_correct(gray, gamma));
++                        /* now P_FILE */
+ 
+                      /* And make sure the corresponding palette entry contains
+                       * exactly the required sRGB value.
+@@ -3763,6 +3621,12 @@ png_image_read_direct(png_voidp argument)
+       /* Set the gamma appropriately, linear for 16-bit input, sRGB otherwise.
+        */
+       {
++         /* This is safe but should no longer be necessary as
++          * png_ptr->default_gamma should have been set after the
++          * info-before-IDAT was read in png_image_read_header.
++          *
++          * TODO: 1.8: remove this and see what happens.
++          */
+          png_fixed_point input_gamma_default;
+ 
+          if ((base_format & PNG_FORMAT_FLAG_LINEAR) != 0 &&
+@@ -3818,8 +3682,9 @@ png_image_read_direct(png_voidp argument)
+           * yet; it's set below.  png_struct::gamma, however, is set to the
+           * final value.
+           */
+-         if (png_muldiv(>est, output_gamma, png_ptr->colorspace.gamma,
+-             PNG_FP_1) != 0 && png_gamma_significant(gtest) == 0)
++         if (png_muldiv(>est, output_gamma,
++                  png_resolve_file_gamma(png_ptr), PNG_FP_1) != 0 &&
++             png_gamma_significant(gtest) == 0)
+             do_local_background = 0;
+ 
+          else if (mode == PNG_ALPHA_STANDARD)
+diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngrtran.c b/src/java.desktop/share/native/libsplashscreen/libpng/pngrtran.c
+index a393de4b7..4f31f8f07 100644
+--- a/src/java.desktop/share/native/libsplashscreen/libpng/pngrtran.c
++++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngrtran.c
+@@ -247,9 +247,59 @@ png_set_strip_alpha(png_structrp png_ptr)
+ #endif
+ 
+ #if defined(PNG_READ_ALPHA_MODE_SUPPORTED) || defined(PNG_READ_GAMMA_SUPPORTED)
++/* PNGv3 conformance: this private API exists to resolve the now mandatory error
++ * resolution when multiple conflicting sources of gamma or colour space
++ * information are available.
++ *
++ * Terminology (assuming power law, "gamma", encodings):
++ *    "screen" gamma: a power law imposed by the output device when digital
++ *    samples are converted to visible light output.  The EOTF - volage to
++ *    luminance on output.
++ *
++ *    "file" gamma: a power law used to encode luminance levels from the input
++ *    data (the scene or the mastering display system) into digital voltages.
++ *    The OETF - luminance to voltage on input.
++ *
++ *    gamma "correction": a power law matching the **inverse** of the overall
++ *    transfer function from input luminance levels to output levels.  The
++ *    **inverse** of the OOTF; the correction "corrects" for the OOTF by aiming
++ *    to make the overall OOTF (including the correction) linear.
++ *
++ * It is important to understand this terminology because the defined terms are
++ * scattered throughout the libpng code and it is very easy to end up with the
++ * inverse of the power law required.
++ *
++ * Variable and struct::member names:
++ *    file_gamma        OETF  how the PNG data was encoded
++ *
++ *    screen_gamma      EOTF  how the screen will decode digital levels
++ *
++ *    -- not used --    OOTF  the net effect OETF x EOTF
++ *    gamma_correction        the inverse of OOTF to make the result linear
++ *
++ * All versions of libpng require a call to "png_set_gamma" to establish the
++ * "screen" gamma, the power law representing the EOTF.  png_set_gamma may also
++ * set or default the "file" gamma; the OETF.  gamma_correction is calculated
++ * internally.
++ *
++ * The earliest libpng versions required file_gamma to be supplied to set_gamma.
++ * Later versions started allowing png_set_gamma and, later, png_set_alpha_mode,
++ * to cause defaulting from the file data.
++ *
++ * PNGv3 mandated a particular form for this defaulting, one that is compatible
++ * with what libpng did except that if libpng detected inconsistencies it marked
++ * all the chunks as "invalid".  PNGv3 effectively invalidates this prior code.
++ *
++ * Behaviour implemented below:
++ *    translate_gamma_flags(gamma, is_screen)
++ *       The libpng-1.6 API for the gamma parameters to libpng APIs
++ *       (png_set_gamma and png_set_alpha_mode at present).  This allows the
++ *       'gamma' value to be passed as a png_fixed_point number or as one of a
++ *       set of integral values for specific "well known" examples of transfer
++ *       functions.  This is compatible with PNGv3.
++ */
+ static png_fixed_point
+-translate_gamma_flags(png_structrp png_ptr, png_fixed_point output_gamma,
+-    int is_screen)
++translate_gamma_flags(png_fixed_point output_gamma, int is_screen)
+ {
+    /* Check for flag values.  The main reason for having the old Mac value as a
+     * flag is that it is pretty near impossible to work out what the correct
+@@ -259,14 +309,6 @@ translate_gamma_flags(png_structrp png_ptr, png_fixed_point output_gamma,
+    if (output_gamma == PNG_DEFAULT_sRGB ||
+       output_gamma == PNG_FP_1 / PNG_DEFAULT_sRGB)
+    {
+-      /* If there is no sRGB support this just sets the gamma to the standard
+-       * sRGB value.  (This is a side effect of using this function!)
+-       */
+-#     ifdef PNG_READ_sRGB_SUPPORTED
+-         png_ptr->flags |= PNG_FLAG_ASSUME_sRGB;
+-#     else
+-         PNG_UNUSED(png_ptr)
+-#     endif
+       if (is_screen != 0)
+          output_gamma = PNG_GAMMA_sRGB;
+       else
+@@ -308,6 +350,33 @@ convert_gamma_value(png_structrp png_ptr, double output_gamma)
+    return (png_fixed_point)output_gamma;
+ }
+ #  endif
++
++static int
++unsupported_gamma(png_structrp png_ptr, png_fixed_point gamma, int warn)
++{
++   /* Validate a gamma value to ensure it is in a reasonable range.  The value
++    * is expected to be 1 or greater, but this range test allows for some
++    * viewing correction values.  The intent is to weed out the API users
++    * who might use the inverse of the gamma value accidentally!
++    *
++    * 1.6.47: apply the test in png_set_gamma as well but only warn and return
++    * false if it fires.
++    *
++    * TODO: 1.8: make this an app_error in png_set_gamma as well.
++    */
++   if (gamma < PNG_LIB_GAMMA_MIN || gamma > PNG_LIB_GAMMA_MAX)
++   {
++#     define msg "gamma out of supported range"
++      if (warn)
++         png_app_warning(png_ptr, msg);
++      else
++         png_app_error(png_ptr, msg);
++      return 1;
++#     undef msg
++   }
++
++   return 0;
++}
+ #endif /* READ_ALPHA_MODE || READ_GAMMA */
+ 
+ #ifdef PNG_READ_ALPHA_MODE_SUPPORTED
+@@ -315,31 +384,29 @@ void PNGFAPI
+ png_set_alpha_mode_fixed(png_structrp png_ptr, int mode,
+     png_fixed_point output_gamma)
+ {
+-   int compose = 0;
+    png_fixed_point file_gamma;
++   int compose = 0;
+ 
+    png_debug(1, "in png_set_alpha_mode_fixed");
+ 
+    if (png_rtran_ok(png_ptr, 0) == 0)
+       return;
+ 
+-   output_gamma = translate_gamma_flags(png_ptr, output_gamma, 1/*screen*/);
+-
+-   /* Validate the value to ensure it is in a reasonable range.  The value
+-    * is expected to be 1 or greater, but this range test allows for some
+-    * viewing correction values.  The intent is to weed out the API users
+-    * who might use the inverse of the gamma value accidentally!
+-    *
+-    * In libpng 1.6.0, we changed from 0.07..3 to 0.01..100, to accommodate
+-    * the optimal 16-bit gamma of 36 and its reciprocal.
+-    */
+-   if (output_gamma < 1000 || output_gamma > 10000000)
+-      png_error(png_ptr, "output gamma out of expected range");
++   output_gamma = translate_gamma_flags(output_gamma, 1/*screen*/);
++   if (unsupported_gamma(png_ptr, output_gamma, 0/*error*/))
++      return;
+ 
+    /* The default file gamma is the inverse of the output gamma; the output
+-    * gamma may be changed below so get the file value first:
++    * gamma may be changed below so get the file value first.  The default_gamma
++    * is set here and from the simplified API (which uses a different algorithm)
++    * so don't overwrite a set value:
+     */
+-   file_gamma = png_reciprocal(output_gamma);
++   file_gamma = png_ptr->default_gamma;
++   if (file_gamma == 0)
++   {
++      file_gamma = png_reciprocal(output_gamma);
++      png_ptr->default_gamma = file_gamma;
++   }
+ 
+    /* There are really 8 possibilities here, composed of any combination
+     * of:
+@@ -390,17 +457,7 @@ png_set_alpha_mode_fixed(png_structrp png_ptr, int mode,
+          png_error(png_ptr, "invalid alpha mode");
+    }
+ 
+-   /* Only set the default gamma if the file gamma has not been set (this has
+-    * the side effect that the gamma in a second call to png_set_alpha_mode will
+-    * be ignored.)
+-    */
+-   if (png_ptr->colorspace.gamma == 0)
+-   {
+-      png_ptr->colorspace.gamma = file_gamma;
+-      png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA;
+-   }
+-
+-   /* But always set the output gamma: */
++   /* Set the screen gamma values: */
+    png_ptr->screen_gamma = output_gamma;
+ 
+    /* Finally, if pre-multiplying, set the background fields to achieve the
+@@ -410,7 +467,7 @@ png_set_alpha_mode_fixed(png_structrp png_ptr, int mode,
+    {
+       /* And obtain alpha pre-multiplication by composing on black: */
+       memset(&png_ptr->background, 0, (sizeof png_ptr->background));
+-      png_ptr->background_gamma = png_ptr->colorspace.gamma; /* just in case */
++      png_ptr->background_gamma = file_gamma; /* just in case */
+       png_ptr->background_gamma_type = PNG_BACKGROUND_GAMMA_FILE;
+       png_ptr->transformations &= ~PNG_BACKGROUND_EXPAND;
+ 
+@@ -848,8 +905,8 @@ png_set_gamma_fixed(png_structrp png_ptr, png_fixed_point scrn_gamma,
+       return;
+ 
+    /* New in libpng-1.5.4 - reserve particular negative values as flags. */
+-   scrn_gamma = translate_gamma_flags(png_ptr, scrn_gamma, 1/*screen*/);
+-   file_gamma = translate_gamma_flags(png_ptr, file_gamma, 0/*file*/);
++   scrn_gamma = translate_gamma_flags(scrn_gamma, 1/*screen*/);
++   file_gamma = translate_gamma_flags(file_gamma, 0/*file*/);
+ 
+    /* Checking the gamma values for being >0 was added in 1.5.4 along with the
+     * premultiplied alpha support; this actually hides an undocumented feature
+@@ -863,17 +920,19 @@ png_set_gamma_fixed(png_structrp png_ptr, png_fixed_point scrn_gamma,
+     * libpng-1.6.0.
+     */
+    if (file_gamma <= 0)
+-      png_error(png_ptr, "invalid file gamma in png_set_gamma");
+-
++      png_app_error(png_ptr, "invalid file gamma in png_set_gamma");
+    if (scrn_gamma <= 0)
+-      png_error(png_ptr, "invalid screen gamma in png_set_gamma");
++      png_app_error(png_ptr, "invalid screen gamma in png_set_gamma");
+ 
+-   /* Set the gamma values unconditionally - this overrides the value in the PNG
+-    * file if a gAMA chunk was present.  png_set_alpha_mode provides a
+-    * different, easier, way to default the file gamma.
++   if (unsupported_gamma(png_ptr, file_gamma, 1/*warn*/) ||
++       unsupported_gamma(png_ptr, scrn_gamma, 1/*warn*/))
++      return;
++
++   /* 1.6.47: png_struct::file_gamma and png_struct::screen_gamma are now only
++    * written by this API.  This removes dependencies on the order of API calls
++    * and allows the complex gamma checks to be delayed until needed.
+     */
+-   png_ptr->colorspace.gamma = file_gamma;
+-   png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA;
++   png_ptr->file_gamma = file_gamma;
+    png_ptr->screen_gamma = scrn_gamma;
+ }
+ 
+@@ -1051,26 +1110,9 @@ png_set_rgb_to_gray_fixed(png_structrp png_ptr, int error_action,
+          png_ptr->rgb_to_gray_coefficients_set = 1;
+       }
+ 
+-      else
+-      {
+-         if (red >= 0 && green >= 0)
+-            png_app_warning(png_ptr,
+-                "ignoring out of range rgb_to_gray coefficients");
+-
+-         /* Use the defaults, from the cHRM chunk if set, else the historical
+-          * values which are close to the sRGB/HDTV/ITU-Rec 709 values.  See
+-          * png_do_rgb_to_gray for more discussion of the values.  In this case
+-          * the coefficients are not marked as 'set' and are not overwritten if
+-          * something has already provided a default.
+-          */
+-         if (png_ptr->rgb_to_gray_red_coeff == 0 &&
+-             png_ptr->rgb_to_gray_green_coeff == 0)
+-         {
+-            png_ptr->rgb_to_gray_red_coeff   = 6968;
+-            png_ptr->rgb_to_gray_green_coeff = 23434;
+-            /* png_ptr->rgb_to_gray_blue_coeff  = 2366; */
+-         }
+-      }
++      else if (red >= 0 && green >= 0)
++         png_app_warning(png_ptr,
++               "ignoring out of range rgb_to_gray coefficients");
+    }
+ }
+ 
+@@ -1311,6 +1353,80 @@ png_init_rgb_transformations(png_structrp png_ptr)
+ #endif /* READ_EXPAND && READ_BACKGROUND */
+ }
+ 
++#ifdef PNG_READ_GAMMA_SUPPORTED
++png_fixed_point /* PRIVATE */
++png_resolve_file_gamma(png_const_structrp png_ptr)
++{
++   png_fixed_point file_gamma;
++
++   /* The file gamma is determined by these precedence rules, in this order
++    * (i.e. use the first value found):
++    *
++    *    png_set_gamma; png_struct::file_gammma if not zero, then:
++    *    png_struct::chunk_gamma if not 0 (determined the PNGv3 rules), then:
++    *    png_set_gamma; 1/png_struct::screen_gamma if not zero
++    *
++    *    0 (i.e. do no gamma handling)
++    */
++   file_gamma = png_ptr->file_gamma;
++   if (file_gamma != 0)
++      return file_gamma;
++
++   file_gamma = png_ptr->chunk_gamma;
++   if (file_gamma != 0)
++      return file_gamma;
++
++   file_gamma = png_ptr->default_gamma;
++   if (file_gamma != 0)
++      return file_gamma;
++
++   /* If png_reciprocal oveflows it returns 0 which indicates to the caller that
++    * there is no usable file gamma.  (The checks added to png_set_gamma and
++    * png_set_alpha_mode should prevent a screen_gamma which would overflow.)
++    */
++   if (png_ptr->screen_gamma != 0)
++      file_gamma = png_reciprocal(png_ptr->screen_gamma);
++
++   return file_gamma;
++}
++
++static int
++png_init_gamma_values(png_structrp png_ptr)
++{
++   /* The following temporary indicates if overall gamma correction is
++    * required.
++    */
++   int gamma_correction = 0;
++   png_fixed_point file_gamma, screen_gamma;
++
++   /* Resolve the file_gamma.  See above: if png_ptr::screen_gamma is set
++    * file_gamma will always be set here:
++    */
++   file_gamma = png_resolve_file_gamma(png_ptr);
++   screen_gamma = png_ptr->screen_gamma;
++
++   if (file_gamma > 0) /* file has been set */
++   {
++      if (screen_gamma > 0) /* screen set too */
++         gamma_correction = png_gamma_threshold(file_gamma, screen_gamma);
++
++      else
++         /* Assume the output matches the input; a long time default behavior
++          * of libpng, although the standard has nothing to say about this.
++          */
++         screen_gamma = png_reciprocal(file_gamma);
++   }
++
++   else /* both unset, prevent corrections: */
++      file_gamma = screen_gamma = PNG_FP_1;
++
++   png_ptr->file_gamma = file_gamma;
++   png_ptr->screen_gamma = screen_gamma;
++   return gamma_correction;
++
++}
++#endif /* READ_GAMMA */
++
+ void /* PRIVATE */
+ png_init_read_transformations(png_structrp png_ptr)
+ {
+@@ -1330,59 +1446,22 @@ png_init_read_transformations(png_structrp png_ptr)
+     * the test needs to be performed later - here.  In addition prior to 1.5.4
+     * the tests were repeated for the PALETTE color type here - this is no
+     * longer necessary (and doesn't seem to have been necessary before.)
++    *
++    * PNGv3: the new mandatory precedence/priority rules for colour space chunks
++    * are handled here (by calling the above function).
++    *
++    * Turn the gamma transformation on or off as appropriate.  Notice that
++    * PNG_GAMMA just refers to the file->screen correction.  Alpha composition
++    * may independently cause gamma correction because it needs linear data
++    * (e.g. if the file has a gAMA chunk but the screen gamma hasn't been
++    * specified.)  In any case this flag may get turned off in the code
++    * immediately below if the transform can be handled outside the row loop.
+     */
+-   {
+-      /* The following temporary indicates if overall gamma correction is
+-       * required.
+-       */
+-      int gamma_correction = 0;
++   if (png_init_gamma_values(png_ptr) != 0)
++      png_ptr->transformations |= PNG_GAMMA;
+ 
+-      if (png_ptr->colorspace.gamma != 0) /* has been set */
+-      {
+-         if (png_ptr->screen_gamma != 0) /* screen set too */
+-            gamma_correction = png_gamma_threshold(png_ptr->colorspace.gamma,
+-                png_ptr->screen_gamma);
+-
+-         else
+-            /* Assume the output matches the input; a long time default behavior
+-             * of libpng, although the standard has nothing to say about this.
+-             */
+-            png_ptr->screen_gamma = png_reciprocal(png_ptr->colorspace.gamma);
+-      }
+-
+-      else if (png_ptr->screen_gamma != 0)
+-         /* The converse - assume the file matches the screen, note that this
+-          * perhaps undesirable default can (from 1.5.4) be changed by calling
+-          * png_set_alpha_mode (even if the alpha handling mode isn't required
+-          * or isn't changed from the default.)
+-          */
+-         png_ptr->colorspace.gamma = png_reciprocal(png_ptr->screen_gamma);
+-
+-      else /* neither are set */
+-         /* Just in case the following prevents any processing - file and screen
+-          * are both assumed to be linear and there is no way to introduce a
+-          * third gamma value other than png_set_background with 'UNIQUE', and,
+-          * prior to 1.5.4
+-          */
+-         png_ptr->screen_gamma = png_ptr->colorspace.gamma = PNG_FP_1;
+-
+-      /* We have a gamma value now. */
+-      png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA;
+-
+-      /* Now turn the gamma transformation on or off as appropriate.  Notice
+-       * that PNG_GAMMA just refers to the file->screen correction.  Alpha
+-       * composition may independently cause gamma correction because it needs
+-       * linear data (e.g. if the file has a gAMA chunk but the screen gamma
+-       * hasn't been specified.)  In any case this flag may get turned off in
+-       * the code immediately below if the transform can be handled outside the
+-       * row loop.
+-       */
+-      if (gamma_correction != 0)
+-         png_ptr->transformations |= PNG_GAMMA;
+-
+-      else
+-         png_ptr->transformations &= ~PNG_GAMMA;
+-   }
++   else
++      png_ptr->transformations &= ~PNG_GAMMA;
+ #endif
+ 
+    /* Certain transformations have the effect of preventing other
+@@ -1454,7 +1533,7 @@ png_init_read_transformations(png_structrp png_ptr)
+     * appropriately.
+     */
+    if ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0)
+-      png_colorspace_set_rgb_coefficients(png_ptr);
++      png_set_rgb_coefficients(png_ptr);
+ #endif
+ 
+ #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
+@@ -1597,10 +1676,10 @@ png_init_read_transformations(png_structrp png_ptr)
+     */
+    if ((png_ptr->transformations & PNG_GAMMA) != 0 ||
+        ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0 &&
+-        (png_gamma_significant(png_ptr->colorspace.gamma) != 0 ||
++        (png_gamma_significant(png_ptr->file_gamma) != 0 ||
+          png_gamma_significant(png_ptr->screen_gamma) != 0)) ||
+         ((png_ptr->transformations & PNG_COMPOSE) != 0 &&
+-         (png_gamma_significant(png_ptr->colorspace.gamma) != 0 ||
++         (png_gamma_significant(png_ptr->file_gamma) != 0 ||
+           png_gamma_significant(png_ptr->screen_gamma) != 0
+ #  ifdef PNG_READ_BACKGROUND_SUPPORTED
+          || (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_UNIQUE &&
+@@ -1656,8 +1735,8 @@ png_init_read_transformations(png_structrp png_ptr)
+                      break;
+ 
+                   case PNG_BACKGROUND_GAMMA_FILE:
+-                     g = png_reciprocal(png_ptr->colorspace.gamma);
+-                     gs = png_reciprocal2(png_ptr->colorspace.gamma,
++                     g = png_reciprocal(png_ptr->file_gamma);
++                     gs = png_reciprocal2(png_ptr->file_gamma,
+                          png_ptr->screen_gamma);
+                      break;
+ 
+@@ -1765,8 +1844,8 @@ png_init_read_transformations(png_structrp png_ptr)
+                   break;
+ 
+                case PNG_BACKGROUND_GAMMA_FILE:
+-                  g = png_reciprocal(png_ptr->colorspace.gamma);
+-                  gs = png_reciprocal2(png_ptr->colorspace.gamma,
++                  g = png_reciprocal(png_ptr->file_gamma);
++                  gs = png_reciprocal2(png_ptr->file_gamma,
+                       png_ptr->screen_gamma);
+                   break;
+ 
+@@ -2016,11 +2095,11 @@ png_read_transform_info(png_structrp png_ptr, png_inforp info_ptr)
+     * been called before this from png_read_update_info->png_read_start_row
+     * sometimes does the gamma transform and cancels the flag.
+     *
+-    * TODO: this looks wrong; the info_ptr should end up with a gamma equal to
+-    * the screen_gamma value.  The following probably results in weirdness if
+-    * the info_ptr is used by the app after the rows have been read.
++    * TODO: this is confusing.  It only changes the result of png_get_gAMA and,
++    * yes, it does return the value that the transformed data effectively has
++    * but does any app really understand this?
+     */
+-   info_ptr->colorspace.gamma = png_ptr->colorspace.gamma;
++   info_ptr->gamma = png_ptr->file_gamma;
+ #endif
+ 
+    if (info_ptr->bit_depth == 16)
+diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngrutil.c b/src/java.desktop/share/native/libsplashscreen/libpng/pngrutil.c
+index 5280140d1..6cf466d18 100644
+--- a/src/java.desktop/share/native/libsplashscreen/libpng/pngrutil.c
++++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngrutil.c
+@@ -46,6 +46,26 @@
+ 
+ #ifdef PNG_READ_SUPPORTED
+ 
++/* The minimum 'zlib' stream is assumed to be just the 2 byte header, 5 bytes
++ * minimum 'deflate' stream, and the 4 byte checksum.
++ */
++#define LZ77Min  (2U+5U+4U)
++
++#ifdef PNG_READ_INTERLACING_SUPPORTED
++/* Arrays to facilitate interlacing - use pass (0 - 6) as index. */
++
++/* Start of interlace block */
++static const png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
++/* Offset to next interlace block */
++static const png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
++/* Start of interlace block in the y direction */
++static const png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
++/* Offset to next interlace block in the y direction */
++static const png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
++
++/* TODO: Move these arrays to a common utility module to avoid duplication. */
++#endif
++
+ png_uint_32 PNGAPI
+ png_get_uint_31(png_const_structrp png_ptr, png_const_bytep buf)
+ {
+@@ -57,30 +77,6 @@ png_get_uint_31(png_const_structrp png_ptr, png_const_bytep buf)
+    return uval;
+ }
+ 
+-#if defined(PNG_READ_gAMA_SUPPORTED) || defined(PNG_READ_cHRM_SUPPORTED)
+-/* The following is a variation on the above for use with the fixed
+- * point values used for gAMA and cHRM.  Instead of png_error it
+- * issues a warning and returns (-1) - an invalid value because both
+- * gAMA and cHRM use *unsigned* integers for fixed point values.
+- */
+-#define PNG_FIXED_ERROR (-1)
+-
+-static png_fixed_point /* PRIVATE */
+-png_get_fixed_point(png_structrp png_ptr, png_const_bytep buf)
+-{
+-   png_uint_32 uval = png_get_uint_32(buf);
+-
+-   if (uval <= PNG_UINT_31_MAX)
+-      return (png_fixed_point)uval; /* known to be in range */
+-
+-   /* The caller can turn off the warning by passing NULL. */
+-   if (png_ptr != NULL)
+-      png_warning(png_ptr, "PNG fixed point integer out of range");
+-
+-   return PNG_FIXED_ERROR;
+-}
+-#endif
+-
+ #ifdef PNG_READ_INT_FUNCTIONS_SUPPORTED
+ /* NOTE: the read macros will obscure these definitions, so that if
+  * PNG_USE_READ_MACROS is set the library will not use them internally,
+@@ -177,6 +173,38 @@ png_read_sig(png_structrp png_ptr, png_inforp info_ptr)
+       png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE;
+ }
+ 
++/* This function is called to verify that a chunk name is valid.
++ * Do this using the bit-whacking approach from contrib/tools/pngfix.c
++ *
++ * Copied from libpng 1.7.
++ */
++static int
++check_chunk_name(png_uint_32 name)
++{
++   png_uint_32 t;
++
++   /* Remove bit 5 from all but the reserved byte; this means
++    * every 8-bit unit must be in the range 65-90 to be valid.
++    * So bit 5 must be zero, bit 6 must be set and bit 7 zero.
++    */
++   name &= ~PNG_U32(32,32,0,32);
++   t = (name & ~0x1f1f1f1fU) ^ 0x40404040U;
++
++   /* Subtract 65 for each 8-bit quantity, this must not
++    * overflow and each byte must then be in the range 0-25.
++    */
++   name -= PNG_U32(65,65,65,65);
++   t |= name;
++
++   /* Subtract 26, handling the overflow which should set the
++    * top three bits of each byte.
++    */
++   name -= PNG_U32(25,25,25,26);
++   t |= ~name;
++
++   return (t & 0xe0e0e0e0U) == 0U;
++}
++
+ /* Read the chunk header (length + type name).
+  * Put the type name into png_ptr->chunk_name, and return the length.
+  */
+@@ -184,33 +212,36 @@ png_uint_32 /* PRIVATE */
+ png_read_chunk_header(png_structrp png_ptr)
+ {
+    png_byte buf[8];
+-   png_uint_32 length;
++   png_uint_32 chunk_name, length;
+ 
+ #ifdef PNG_IO_STATE_SUPPORTED
+    png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_HDR;
+ #endif
+ 
+-   /* Read the length and the chunk name.
+-    * This must be performed in a single I/O call.
++   /* Read the length and the chunk name.  png_struct::chunk_name is immediately
++    * updated even if they are detectably wrong.  This aids error message
++    * handling by allowing png_chunk_error to be used.
+     */
+    png_read_data(png_ptr, buf, 8);
+    length = png_get_uint_31(png_ptr, buf);
++   png_ptr->chunk_name = chunk_name = PNG_CHUNK_FROM_STRING(buf+4);
+ 
+-   /* Put the chunk name into png_ptr->chunk_name. */
+-   png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(buf+4);
++   /* Reset the crc and run it over the chunk name. */
++   png_reset_crc(png_ptr);
++   png_calculate_crc(png_ptr, buf + 4, 4);
+ 
+    png_debug2(0, "Reading chunk typeid = 0x%lx, length = %lu",
+        (unsigned long)png_ptr->chunk_name, (unsigned long)length);
+ 
+-   /* Reset the crc and run it over the chunk name. */
+-   png_reset_crc(png_ptr);
+-   png_calculate_crc(png_ptr, buf + 4, 4);
++   /* Sanity check the length (first by <= 0x80) and the chunk name.  An error
++    * here indicates a broken stream and libpng has no recovery from this.
++    */
++   if (buf[0] >= 0x80U)
++      png_chunk_error(png_ptr, "bad header (invalid length)");
+ 
+    /* Check to see if chunk name is valid. */
+-   png_check_chunk_name(png_ptr, png_ptr->chunk_name);
+-
+-   /* Check for too-large chunk length */
+-   png_check_chunk_length(png_ptr, length);
++   if (!check_chunk_name(chunk_name))
++      png_chunk_error(png_ptr, "bad header (invalid type)");
+ 
+ #ifdef PNG_IO_STATE_SUPPORTED
+    png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_DATA;
+@@ -230,13 +261,85 @@ png_crc_read(png_structrp png_ptr, png_bytep buf, png_uint_32 length)
+    png_calculate_crc(png_ptr, buf, length);
+ }
+ 
++/* Compare the CRC stored in the PNG file with that calculated by libpng from
++ * the data it has read thus far.
++ */
++static int
++png_crc_error(png_structrp png_ptr, int handle_as_ancillary)
++{
++   png_byte crc_bytes[4];
++   png_uint_32 crc;
++   int need_crc = 1;
++
++   /* There are four flags two for ancillary and two for critical chunks.  The
++    * default setting of these flags is all zero.
++    *
++    * PNG_FLAG_CRC_ANCILLARY_USE
++    * PNG_FLAG_CRC_ANCILLARY_NOWARN
++    *  USE+NOWARN: no CRC calculation (implemented here), else;
++    *  NOWARN:     png_chunk_error on error (implemented in png_crc_finish)
++    *  else:       png_chunk_warning on error (implemented in png_crc_finish)
++    *              This is the default.
++    *
++    *    I.e. NOWARN without USE produces png_chunk_error.  The default setting
++    *    where neither are set does the same thing.
++    *
++    * PNG_FLAG_CRC_CRITICAL_USE
++    * PNG_FLAG_CRC_CRITICAL_IGNORE
++    *  IGNORE: no CRC calculation (implemented here), else;
++    *  USE:    png_chunk_warning on error (implemented in png_crc_finish)
++    *  else:   png_chunk_error on error (implemented in png_crc_finish)
++    *          This is the default.
++    *
++    * This arose because of original mis-implementation and has persisted for
++    * compatibility reasons.
++    *
++    * TODO: the flag names are internal so maybe this can be changed to
++    * something comprehensible.
++    */
++   if (handle_as_ancillary || PNG_CHUNK_ANCILLARY(png_ptr->chunk_name) != 0)
++   {
++      if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) ==
++          (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN))
++         need_crc = 0;
++   }
++
++   else /* critical */
++   {
++      if ((png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE) != 0)
++         need_crc = 0;
++   }
++
++#ifdef PNG_IO_STATE_SUPPORTED
++   png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_CRC;
++#endif
++
++   /* The chunk CRC must be serialized in a single I/O call. */
++   png_read_data(png_ptr, crc_bytes, 4);
++
++   if (need_crc != 0)
++   {
++      crc = png_get_uint_32(crc_bytes);
++      return crc != png_ptr->crc;
++   }
++
++   else
++      return 0;
++}
++
+ /* Optionally skip data and then check the CRC.  Depending on whether we
+  * are reading an ancillary or critical chunk, and how the program has set
+  * things up, we may calculate the CRC on the data and print a message.
+  * Returns '1' if there was a CRC error, '0' otherwise.
++ *
++ * There is one public version which is used in most places and another which
++ * takes the value for the 'critical' flag to check.  This allows PLTE and IEND
++ * handling code to ignore the CRC error and removes some confusing code
++ * duplication.
+  */
+-int /* PRIVATE */
+-png_crc_finish(png_structrp png_ptr, png_uint_32 skip)
++static int
++png_crc_finish_critical(png_structrp png_ptr, png_uint_32 skip,
++      int handle_as_ancillary)
+ {
+    /* The size of the local buffer for inflate is a good guess as to a
+     * reasonable size to use for buffering reads from the application.
+@@ -254,14 +357,24 @@ png_crc_finish(png_structrp png_ptr, png_uint_32 skip)
+       png_crc_read(png_ptr, tmpbuf, len);
+    }
+ 
+-   if (png_crc_error(png_ptr) != 0)
++   /* If 'handle_as_ancillary' has been requested and this is a critical chunk
++    * but PNG_FLAG_CRC_CRITICAL_IGNORE was set then png_read_crc did not, in
++    * fact, calculate the CRC so the ANCILLARY settings should not be used
++    * instead.
++    */
++   if (handle_as_ancillary &&
++       (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE) != 0)
++      handle_as_ancillary = 0;
++
++   /* TODO: this might be more comprehensible if png_crc_error was inlined here.
++    */
++   if (png_crc_error(png_ptr, handle_as_ancillary) != 0)
+    {
+-      if (PNG_CHUNK_ANCILLARY(png_ptr->chunk_name) != 0 ?
++      /* See above for the explanation of how the flags work. */
++      if (handle_as_ancillary || PNG_CHUNK_ANCILLARY(png_ptr->chunk_name) != 0 ?
+           (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN) == 0 :
+           (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE) != 0)
+-      {
+          png_chunk_warning(png_ptr, "CRC error");
+-      }
+ 
+       else
+          png_chunk_error(png_ptr, "CRC error");
+@@ -272,61 +385,29 @@ png_crc_finish(png_structrp png_ptr, png_uint_32 skip)
+    return 0;
+ }
+ 
+-/* Compare the CRC stored in the PNG file with that calculated by libpng from
+- * the data it has read thus far.
+- */
+ int /* PRIVATE */
+-png_crc_error(png_structrp png_ptr)
++png_crc_finish(png_structrp png_ptr, png_uint_32 skip)
+ {
+-   png_byte crc_bytes[4];
+-   png_uint_32 crc;
+-   int need_crc = 1;
+-
+-   if (PNG_CHUNK_ANCILLARY(png_ptr->chunk_name) != 0)
+-   {
+-      if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) ==
+-          (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN))
+-         need_crc = 0;
+-   }
+-
+-   else /* critical */
+-   {
+-      if ((png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE) != 0)
+-         need_crc = 0;
+-   }
+-
+-#ifdef PNG_IO_STATE_SUPPORTED
+-   png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_CRC;
+-#endif
+-
+-   /* The chunk CRC must be serialized in a single I/O call. */
+-   png_read_data(png_ptr, crc_bytes, 4);
+-
+-   if (need_crc != 0)
+-   {
+-      crc = png_get_uint_32(crc_bytes);
+-      return crc != png_ptr->crc;
+-   }
+-
+-   else
+-      return 0;
++   return png_crc_finish_critical(png_ptr, skip, 0/*critical handling*/);
+ }
+ 
+ #if defined(PNG_READ_iCCP_SUPPORTED) || defined(PNG_READ_iTXt_SUPPORTED) ||\
+     defined(PNG_READ_pCAL_SUPPORTED) || defined(PNG_READ_sCAL_SUPPORTED) ||\
+     defined(PNG_READ_sPLT_SUPPORTED) || defined(PNG_READ_tEXt_SUPPORTED) ||\
+-    defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_SEQUENTIAL_READ_SUPPORTED)
++    defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_READ_eXIf_SUPPORTED) ||\
++    defined(PNG_SEQUENTIAL_READ_SUPPORTED)
+ /* Manage the read buffer; this simply reallocates the buffer if it is not small
+  * enough (or if it is not allocated).  The routine returns a pointer to the
+  * buffer; if an error occurs and 'warn' is set the routine returns NULL, else
+- * it will call png_error (via png_malloc) on failure.  (warn == 2 means
+- * 'silent').
++ * it will call png_error on failure.
+  */
+ static png_bytep
+-png_read_buffer(png_structrp png_ptr, png_alloc_size_t new_size, int warn)
++png_read_buffer(png_structrp png_ptr, png_alloc_size_t new_size)
+ {
+    png_bytep buffer = png_ptr->read_buffer;
+ 
++   if (new_size > png_chunk_max(png_ptr)) return NULL;
++
+    if (buffer != NULL && new_size > png_ptr->read_buffer_size)
+    {
+       png_ptr->read_buffer = NULL;
+@@ -341,24 +422,17 @@ png_read_buffer(png_structrp png_ptr, png_alloc_size_t new_size, int warn)
+ 
+       if (buffer != NULL)
+       {
+-         memset(buffer, 0, new_size); /* just in case */
++#        ifndef PNG_NO_MEMZERO /* for detecting UIM bugs **only** */
++            memset(buffer, 0, new_size); /* just in case */
++#        endif
+          png_ptr->read_buffer = buffer;
+          png_ptr->read_buffer_size = new_size;
+       }
+-
+-      else if (warn < 2) /* else silent */
+-      {
+-         if (warn != 0)
+-             png_chunk_warning(png_ptr, "insufficient memory to read chunk");
+-
+-         else
+-             png_chunk_error(png_ptr, "insufficient memory to read chunk");
+-      }
+    }
+ 
+    return buffer;
+ }
+-#endif /* READ_iCCP|iTXt|pCAL|sCAL|sPLT|tEXt|zTXt|SEQUENTIAL_READ */
++#endif /* READ_iCCP|iTXt|pCAL|sCAL|sPLT|tEXt|zTXt|eXIf|SEQUENTIAL_READ */
+ 
+ /* png_inflate_claim: claim the zstream for some nefarious purpose that involves
+  * decompression.  Returns Z_OK on success, else a zlib error code.  It checks
+@@ -645,16 +719,7 @@ png_decompress_chunk(png_structrp png_ptr,
+     * maybe a '\0' terminator too.  We have to assume that 'prefix_size' is
+     * limited only by the maximum chunk size.
+     */
+-   png_alloc_size_t limit = PNG_SIZE_MAX;
+-
+-# ifdef PNG_SET_USER_LIMITS_SUPPORTED
+-   if (png_ptr->user_chunk_malloc_max > 0 &&
+-       png_ptr->user_chunk_malloc_max < limit)
+-      limit = png_ptr->user_chunk_malloc_max;
+-# elif PNG_USER_CHUNK_MALLOC_MAX > 0
+-   if (PNG_USER_CHUNK_MALLOC_MAX < limit)
+-      limit = PNG_USER_CHUNK_MALLOC_MAX;
+-# endif
++   png_alloc_size_t limit = png_chunk_max(png_ptr);
+ 
+    if (limit >= prefix_size + (terminate != 0))
+    {
+@@ -859,9 +924,9 @@ png_inflate_read(png_structrp png_ptr, png_bytep read_buffer, uInt read_size,
+ }
+ #endif /* READ_iCCP */
+ 
++/* CHUNK HANDLING */
+ /* Read and check the IDHR chunk */
+-
+-void /* PRIVATE */
++static png_handle_result_code
+ png_handle_IHDR(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+ {
+    png_byte buf[13];
+@@ -871,12 +936,7 @@ png_handle_IHDR(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+ 
+    png_debug(1, "in png_handle_IHDR");
+ 
+-   if ((png_ptr->mode & PNG_HAVE_IHDR) != 0)
+-      png_chunk_error(png_ptr, "out of place");
+-
+-   /* Check the length */
+-   if (length != 13)
+-      png_chunk_error(png_ptr, "invalid");
++   /* Length and position are checked by the caller. */
+ 
+    png_ptr->mode |= PNG_HAVE_IHDR;
+ 
+@@ -930,257 +990,196 @@ png_handle_IHDR(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+    png_debug1(3, "bit_depth = %d", png_ptr->bit_depth);
+    png_debug1(3, "channels = %d", png_ptr->channels);
+    png_debug1(3, "rowbytes = %lu", (unsigned long)png_ptr->rowbytes);
++
++   /* Rely on png_set_IHDR to completely validate the data and call png_error if
++    * it's wrong.
++    */
+    png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth,
+        color_type, interlace_type, compression_type, filter_type);
++
++   return handled_ok;
++   PNG_UNUSED(length)
+ }
+ 
+ /* Read and check the palette */
+-void /* PRIVATE */
++/* TODO: there are several obvious errors in this code when handling
++ * out-of-place chunks and there is much over-complexity caused by trying to
++ * patch up the problems.
++ */
++static png_handle_result_code
+ png_handle_PLTE(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+ {
+-   png_color palette[PNG_MAX_PALETTE_LENGTH];
+-   int max_palette_length, num, i;
+-#ifdef PNG_POINTER_INDEXING_SUPPORTED
+-   png_colorp pal_ptr;
+-#endif
++   png_const_charp errmsg = NULL;
+ 
+    png_debug(1, "in png_handle_PLTE");
+ 
+-   if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+-      png_chunk_error(png_ptr, "missing IHDR");
+-
+-   /* Moved to before the 'after IDAT' check below because otherwise duplicate
+-    * PLTE chunks are potentially ignored (the spec says there shall not be more
+-    * than one PLTE, the error is not treated as benign, so this check trumps
+-    * the requirement that PLTE appears before IDAT.)
++   /* 1.6.47: consistency.  This used to be especially treated as a critical
++    * error even in an image which is not colour mapped, there isn't a good
++    * justification for treating some errors here one way and others another so
++    * everything uses the same logic.
+     */
+-   else if ((png_ptr->mode & PNG_HAVE_PLTE) != 0)
+-      png_chunk_error(png_ptr, "duplicate");
++   if ((png_ptr->mode & PNG_HAVE_PLTE) != 0)
++      errmsg = "duplicate";
+ 
+    else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
+-   {
+-      /* This is benign because the non-benign error happened before, when an
+-       * IDAT was encountered in a color-mapped image with no PLTE.
+-       */
+-      png_crc_finish(png_ptr, length);
+-      png_chunk_benign_error(png_ptr, "out of place");
+-      return;
+-   }
++      errmsg = "out of place";
+ 
+-   png_ptr->mode |= PNG_HAVE_PLTE;
++   else if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) == 0)
++      errmsg = "ignored in grayscale PNG";
+ 
+-   if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) == 0)
+-   {
+-      png_crc_finish(png_ptr, length);
+-      png_chunk_benign_error(png_ptr, "ignored in grayscale PNG");
+-      return;
+-   }
++   else if (length > 3*PNG_MAX_PALETTE_LENGTH || (length % 3) != 0)
++      errmsg = "invalid";
+ 
+-#ifndef PNG_READ_OPT_PLTE_SUPPORTED
+-   if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
+-   {
+-      png_crc_finish(png_ptr, length);
+-      return;
+-   }
+-#endif
++   /* This drops PLTE in favour of tRNS or bKGD because both of those chunks
++    * can have an effect on the rendering of the image whereas PLTE only matters
++    * in the case of an 8-bit display with a decoder which controls the palette.
++    *
++    * The alternative here is to ignore the error and store the palette anyway;
++    * destroying the tRNS will definately cause problems.
++    *
++    * NOTE: the case of PNG_COLOR_TYPE_PALETTE need not be considered because
++    * the png_handle_ routines for the three 'after PLTE' chunks tRNS, bKGD and
++    * hIST all check for a preceding PLTE in these cases.
++    */
++   else if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE &&
++            (png_has_chunk(png_ptr, tRNS) || png_has_chunk(png_ptr, bKGD)))
++      errmsg = "out of place";
+ 
+-   if (length > 3*PNG_MAX_PALETTE_LENGTH || length % 3)
++   else
+    {
+-      png_crc_finish(png_ptr, length);
+-
+-      if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
+-         png_chunk_benign_error(png_ptr, "invalid");
+-
+-      else
+-         png_chunk_error(png_ptr, "invalid");
++      /* If the palette has 256 or fewer entries but is too large for the bit
++       * depth we don't issue an error to preserve the behavior of previous
++       * libpng versions. We silently truncate the unused extra palette entries
++       * here.
++       */
++      const unsigned max_palette_length =
++         (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) ?
++            1U << png_ptr->bit_depth : PNG_MAX_PALETTE_LENGTH;
+ 
+-      return;
+-   }
++      /* The cast is safe because 'length' is less than
++       * 3*PNG_MAX_PALETTE_LENGTH
++       */
++      const unsigned num = (length > 3U*max_palette_length) ?
++         max_palette_length : (unsigned)length / 3U;
+ 
+-   /* The cast is safe because 'length' is less than 3*PNG_MAX_PALETTE_LENGTH */
+-   num = (int)length / 3;
++      unsigned i, j;
++      png_byte buf[3*PNG_MAX_PALETTE_LENGTH];
++      png_color palette[PNG_MAX_PALETTE_LENGTH];
+ 
+-   /* If the palette has 256 or fewer entries but is too large for the bit
+-    * depth, we don't issue an error, to preserve the behavior of previous
+-    * libpng versions. We silently truncate the unused extra palette entries
+-    * here.
+-    */
+-   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+-      max_palette_length = (1 << png_ptr->bit_depth);
+-   else
+-      max_palette_length = PNG_MAX_PALETTE_LENGTH;
++      /* Read the chunk into the buffer then read to the end of the chunk. */
++      png_crc_read(png_ptr, buf, num*3U);
++      png_crc_finish_critical(png_ptr, length - 3U*num,
++            /* Handle as ancillary if PLTE is optional: */
++            png_ptr->color_type != PNG_COLOR_TYPE_PALETTE);
+ 
+-   if (num > max_palette_length)
+-      num = max_palette_length;
++      for (i = 0U, j = 0U; i < num; i++)
++      {
++         palette[i].red = buf[j++];
++         palette[i].green = buf[j++];
++         palette[i].blue = buf[j++];
++      }
+ 
+-#ifdef PNG_POINTER_INDEXING_SUPPORTED
+-   for (i = 0, pal_ptr = palette; i < num; i++, pal_ptr++)
+-   {
+-      png_byte buf[3];
++      /* A valid PLTE chunk has been read */
++      png_ptr->mode |= PNG_HAVE_PLTE;
+ 
+-      png_crc_read(png_ptr, buf, 3);
+-      pal_ptr->red = buf[0];
+-      pal_ptr->green = buf[1];
+-      pal_ptr->blue = buf[2];
++      /* TODO: png_set_PLTE has the side effect of setting png_ptr->palette to
++       * its own copy of the palette.  This has the side effect that when
++       * png_start_row is called (this happens after any call to
++       * png_read_update_info) the info_ptr palette gets changed.  This is
++       * extremely unexpected and confusing.
++       *
++       * REVIEW: there have been consistent bugs in the past about gamma and
++       * similar transforms to colour mapped images being useless because the
++       * modified palette cannot be accessed because of the above.
++       *
++       * CONSIDER: Fix this by not sharing the palette in this way.  But does
++       * this completely fix the problem?
++       */
++      png_set_PLTE(png_ptr, info_ptr, palette, num);
++      return handled_ok;
+    }
+-#else
+-   for (i = 0; i < num; i++)
+-   {
+-      png_byte buf[3];
+ 
+-      png_crc_read(png_ptr, buf, 3);
+-      /* Don't depend upon png_color being any order */
+-      palette[i].red = buf[0];
+-      palette[i].green = buf[1];
+-      palette[i].blue = buf[2];
+-   }
+-#endif
+-
+-   /* If we actually need the PLTE chunk (ie for a paletted image), we do
+-    * whatever the normal CRC configuration tells us.  However, if we
+-    * have an RGB image, the PLTE can be considered ancillary, so
+-    * we will act as though it is.
+-    */
+-#ifndef PNG_READ_OPT_PLTE_SUPPORTED
++   /* Here on error: errmsg is non NULL. */
+    if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+-#endif
+    {
+-      png_crc_finish(png_ptr, (png_uint_32) (length - (unsigned int)num * 3));
++      png_crc_finish(png_ptr, length);
++      png_chunk_error(png_ptr, errmsg);
+    }
+ 
+-#ifndef PNG_READ_OPT_PLTE_SUPPORTED
+-   else if (png_crc_error(png_ptr) != 0)  /* Only if we have a CRC error */
++   else /* not critical to this image */
+    {
+-      /* If we don't want to use the data from an ancillary chunk,
+-       * we have two options: an error abort, or a warning and we
+-       * ignore the data in this chunk (which should be OK, since
+-       * it's considered ancillary for a RGB or RGBA image).
+-       *
+-       * IMPLEMENTATION NOTE: this is only here because png_crc_finish uses the
+-       * chunk type to determine whether to check the ancillary or the critical
+-       * flags.
+-       */
+-      if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE) == 0)
+-      {
+-         if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN) != 0)
+-            return;
+-
+-         else
+-            png_chunk_error(png_ptr, "CRC error");
+-      }
+-
+-      /* Otherwise, we (optionally) emit a warning and use the chunk. */
+-      else if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN) == 0)
+-         png_chunk_warning(png_ptr, "CRC error");
++      png_crc_finish_critical(png_ptr, length, 1/*handle as ancillary*/);
++      png_chunk_benign_error(png_ptr, errmsg);
+    }
+-#endif
+ 
+-   /* TODO: png_set_PLTE has the side effect of setting png_ptr->palette to its
+-    * own copy of the palette.  This has the side effect that when png_start_row
+-    * is called (this happens after any call to png_read_update_info) the
+-    * info_ptr palette gets changed.  This is extremely unexpected and
+-    * confusing.
+-    *
+-    * Fix this by not sharing the palette in this way.
++   /* Because PNG_UNUSED(errmsg) does not work if all the uses are compiled out
++    * (this does happen).
+     */
+-   png_set_PLTE(png_ptr, info_ptr, palette, num);
+-
+-   /* The three chunks, bKGD, hIST and tRNS *must* appear after PLTE and before
+-    * IDAT.  Prior to 1.6.0 this was not checked; instead the code merely
+-    * checked the apparent validity of a tRNS chunk inserted before PLTE on a
+-    * palette PNG.  1.6.0 attempts to rigorously follow the standard and
+-    * therefore does a benign error if the erroneous condition is detected *and*
+-    * cancels the tRNS if the benign error returns.  The alternative is to
+-    * amend the standard since it would be rather hypocritical of the standards
+-    * maintainers to ignore it.
+-    */
+-#ifdef PNG_READ_tRNS_SUPPORTED
+-   if (png_ptr->num_trans > 0 ||
+-       (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS) != 0))
+-   {
+-      /* Cancel this because otherwise it would be used if the transforms
+-       * require it.  Don't cancel the 'valid' flag because this would prevent
+-       * detection of duplicate chunks.
+-       */
+-      png_ptr->num_trans = 0;
+-
+-      if (info_ptr != NULL)
+-         info_ptr->num_trans = 0;
+-
+-      png_chunk_benign_error(png_ptr, "tRNS must be after");
+-   }
+-#endif
+-
+-#ifdef PNG_READ_hIST_SUPPORTED
+-   if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST) != 0)
+-      png_chunk_benign_error(png_ptr, "hIST must be after");
+-#endif
+-
+-#ifdef PNG_READ_bKGD_SUPPORTED
+-   if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD) != 0)
+-      png_chunk_benign_error(png_ptr, "bKGD must be after");
+-#endif
++   return errmsg != NULL ? handled_error : handled_error;
+ }
+ 
+-void /* PRIVATE */
++/* On read the IDAT chunk is always handled specially, even if marked for
++ * unknown handling (this is allowed), so:
++ */
++#define png_handle_IDAT NULL
++
++static png_handle_result_code
+ png_handle_IEND(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+ {
+    png_debug(1, "in png_handle_IEND");
+ 
+-   if ((png_ptr->mode & PNG_HAVE_IHDR) == 0 ||
+-       (png_ptr->mode & PNG_HAVE_IDAT) == 0)
+-      png_chunk_error(png_ptr, "out of place");
+-
+    png_ptr->mode |= (PNG_AFTER_IDAT | PNG_HAVE_IEND);
+ 
+-   png_crc_finish(png_ptr, length);
+-
+    if (length != 0)
+       png_chunk_benign_error(png_ptr, "invalid");
+ 
++   png_crc_finish_critical(png_ptr, length, 1/*handle as ancillary*/);
++
++   return handled_ok;
+    PNG_UNUSED(info_ptr)
+ }
+ 
+ #ifdef PNG_READ_gAMA_SUPPORTED
+-void /* PRIVATE */
++static png_handle_result_code
+ png_handle_gAMA(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+ {
+-   png_fixed_point igamma;
++   png_uint_32 ugamma;
+    png_byte buf[4];
+ 
+    png_debug(1, "in png_handle_gAMA");
+ 
+-   if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+-      png_chunk_error(png_ptr, "missing IHDR");
++   png_crc_read(png_ptr, buf, 4);
+ 
+-   else if ((png_ptr->mode & (PNG_HAVE_IDAT|PNG_HAVE_PLTE)) != 0)
+-   {
+-      png_crc_finish(png_ptr, length);
+-      png_chunk_benign_error(png_ptr, "out of place");
+-      return;
+-   }
++   if (png_crc_finish(png_ptr, 0) != 0)
++      return handled_error;
++
++   ugamma = png_get_uint_32(buf);
+ 
+-   if (length != 4)
++   if (ugamma > PNG_UINT_31_MAX)
+    {
+-      png_crc_finish(png_ptr, length);
+       png_chunk_benign_error(png_ptr, "invalid");
+-      return;
++      return handled_error;
+    }
+ 
+-   png_crc_read(png_ptr, buf, 4);
+-
+-   if (png_crc_finish(png_ptr, 0) != 0)
+-      return;
++   png_set_gAMA_fixed(png_ptr, info_ptr, (png_fixed_point)/*SAFE*/ugamma);
+ 
+-   igamma = png_get_fixed_point(NULL, buf);
++#ifdef PNG_READ_GAMMA_SUPPORTED
++      /* PNGv3: chunk precedence for gamma is cICP, [iCCP], sRGB, gAMA.  gAMA is
++       * at the end of the chain so simply check for an unset value.
++       */
++      if (png_ptr->chunk_gamma == 0)
++         png_ptr->chunk_gamma = (png_fixed_point)/*SAFE*/ugamma;
++#endif /*READ_GAMMA*/
+ 
+-   png_colorspace_set_gamma(png_ptr, &png_ptr->colorspace, igamma);
+-   png_colorspace_sync(png_ptr, info_ptr);
++   return handled_ok;
++   PNG_UNUSED(length)
+ }
++#else
++#  define png_handle_gAMA NULL
+ #endif
+ 
+ #ifdef PNG_READ_sBIT_SUPPORTED
+-void /* PRIVATE */
++static png_handle_result_code /* PRIVATE */
+ png_handle_sBIT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+ {
+    unsigned int truelen, i;
+@@ -1189,23 +1188,6 @@ png_handle_sBIT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+ 
+    png_debug(1, "in png_handle_sBIT");
+ 
+-   if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+-      png_chunk_error(png_ptr, "missing IHDR");
+-
+-   else if ((png_ptr->mode & (PNG_HAVE_IDAT|PNG_HAVE_PLTE)) != 0)
+-   {
+-      png_crc_finish(png_ptr, length);
+-      png_chunk_benign_error(png_ptr, "out of place");
+-      return;
+-   }
+-
+-   if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT) != 0)
+-   {
+-      png_crc_finish(png_ptr, length);
+-      png_chunk_benign_error(png_ptr, "duplicate");
+-      return;
+-   }
+-
+    if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+    {
+       truelen = 3;
+@@ -1218,25 +1200,25 @@ png_handle_sBIT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+       sample_depth = png_ptr->bit_depth;
+    }
+ 
+-   if (length != truelen || length > 4)
++   if (length != truelen)
+    {
+-      png_chunk_benign_error(png_ptr, "invalid");
+       png_crc_finish(png_ptr, length);
+-      return;
++      png_chunk_benign_error(png_ptr, "bad length");
++      return handled_error;
+    }
+ 
+    buf[0] = buf[1] = buf[2] = buf[3] = sample_depth;
+    png_crc_read(png_ptr, buf, truelen);
+ 
+    if (png_crc_finish(png_ptr, 0) != 0)
+-      return;
++      return handled_error;
+ 
+    for (i=0; i sample_depth)
+       {
+          png_chunk_benign_error(png_ptr, "invalid");
+-         return;
++         return handled_error;
+       }
+    }
+ 
+@@ -1248,7 +1230,7 @@ png_handle_sBIT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+       png_ptr->sig_bit.alpha = buf[3];
+    }
+ 
+-   else
++   else /* grayscale */
+    {
+       png_ptr->sig_bit.gray = buf[0];
+       png_ptr->sig_bit.red = buf[0];
+@@ -1258,133 +1240,132 @@ png_handle_sBIT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+    }
+ 
+    png_set_sBIT(png_ptr, info_ptr, &(png_ptr->sig_bit));
++   return handled_ok;
+ }
++#else
++#  define png_handle_sBIT NULL
+ #endif
+ 
+ #ifdef PNG_READ_cHRM_SUPPORTED
+-void /* PRIVATE */
+-png_handle_cHRM(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
++static png_int_32
++png_get_int_32_checked(png_const_bytep buf, int *error)
+ {
+-   png_byte buf[32];
+-   png_xy xy;
++   png_uint_32 uval = png_get_uint_32(buf);
++   if ((uval & 0x80000000) == 0) /* non-negative */
++      return (png_int_32)uval;
+ 
+-   png_debug(1, "in png_handle_cHRM");
++   uval = (uval ^ 0xffffffff) + 1;  /* 2's complement: -x = ~x+1 */
++   if ((uval & 0x80000000) == 0) /* no overflow */
++      return -(png_int_32)uval;
+ 
+-   if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+-      png_chunk_error(png_ptr, "missing IHDR");
++   /* This version of png_get_int_32 has a way of returning the error to the
++    * caller, so:
++    */
++   *error = 1;
++   return 0; /* Safe */
++}
+ 
+-   else if ((png_ptr->mode & (PNG_HAVE_IDAT|PNG_HAVE_PLTE)) != 0)
+-   {
+-      png_crc_finish(png_ptr, length);
+-      png_chunk_benign_error(png_ptr, "out of place");
+-      return;
+-   }
++static png_handle_result_code /* PRIVATE */
++png_handle_cHRM(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
++{
++   int error = 0;
++   png_xy xy;
++   png_byte buf[32];
+ 
+-   if (length != 32)
+-   {
+-      png_crc_finish(png_ptr, length);
+-      png_chunk_benign_error(png_ptr, "invalid");
+-      return;
+-   }
++   png_debug(1, "in png_handle_cHRM");
+ 
+    png_crc_read(png_ptr, buf, 32);
+ 
+    if (png_crc_finish(png_ptr, 0) != 0)
+-      return;
++      return handled_error;
++
++   xy.whitex = png_get_int_32_checked(buf +  0, &error);
++   xy.whitey = png_get_int_32_checked(buf +  4, &error);
++   xy.redx   = png_get_int_32_checked(buf +  8, &error);
++   xy.redy   = png_get_int_32_checked(buf + 12, &error);
++   xy.greenx = png_get_int_32_checked(buf + 16, &error);
++   xy.greeny = png_get_int_32_checked(buf + 20, &error);
++   xy.bluex  = png_get_int_32_checked(buf + 24, &error);
++   xy.bluey  = png_get_int_32_checked(buf + 28, &error);
+ 
+-   xy.whitex = png_get_fixed_point(NULL, buf);
+-   xy.whitey = png_get_fixed_point(NULL, buf + 4);
+-   xy.redx   = png_get_fixed_point(NULL, buf + 8);
+-   xy.redy   = png_get_fixed_point(NULL, buf + 12);
+-   xy.greenx = png_get_fixed_point(NULL, buf + 16);
+-   xy.greeny = png_get_fixed_point(NULL, buf + 20);
+-   xy.bluex  = png_get_fixed_point(NULL, buf + 24);
+-   xy.bluey  = png_get_fixed_point(NULL, buf + 28);
+-
+-   if (xy.whitex == PNG_FIXED_ERROR ||
+-       xy.whitey == PNG_FIXED_ERROR ||
+-       xy.redx   == PNG_FIXED_ERROR ||
+-       xy.redy   == PNG_FIXED_ERROR ||
+-       xy.greenx == PNG_FIXED_ERROR ||
+-       xy.greeny == PNG_FIXED_ERROR ||
+-       xy.bluex  == PNG_FIXED_ERROR ||
+-       xy.bluey  == PNG_FIXED_ERROR)
++   if (error)
+    {
+-      png_chunk_benign_error(png_ptr, "invalid values");
+-      return;
++      png_chunk_benign_error(png_ptr, "invalid");
++      return handled_error;
+    }
+ 
+-   /* If a colorspace error has already been output skip this chunk */
+-   if ((png_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) != 0)
+-      return;
++   /* png_set_cHRM may complain about some of the values but this doesn't matter
++    * because it was a cHRM and it did have vaguely (if, perhaps, ridiculous)
++    * values.  Ridiculousity will be checked if the values are used later.
++    */
++   png_set_cHRM_fixed(png_ptr, info_ptr, xy.whitex, xy.whitey, xy.redx, xy.redy,
++         xy.greenx, xy.greeny, xy.bluex, xy.bluey);
+ 
+-   if ((png_ptr->colorspace.flags & PNG_COLORSPACE_FROM_cHRM) != 0)
+-   {
+-      png_ptr->colorspace.flags |= PNG_COLORSPACE_INVALID;
+-      png_colorspace_sync(png_ptr, info_ptr);
+-      png_chunk_benign_error(png_ptr, "duplicate");
+-      return;
+-   }
++   /* We only use 'chromaticities' for RGB to gray */
++#  ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
++      /* There is no need to check sRGB here, cICP is NYI and iCCP is not
++       * supported so just check mDCV.
++       */
++      if (!png_has_chunk(png_ptr, mDCV))
++      {
++         png_ptr->chromaticities = xy;
++      }
++#  endif /* READ_RGB_TO_GRAY */
+ 
+-   png_ptr->colorspace.flags |= PNG_COLORSPACE_FROM_cHRM;
+-   (void)png_colorspace_set_chromaticities(png_ptr, &png_ptr->colorspace, &xy,
+-       1/*prefer cHRM values*/);
+-   png_colorspace_sync(png_ptr, info_ptr);
++   return handled_ok;
++   PNG_UNUSED(length)
+ }
++#else
++#  define png_handle_cHRM NULL
+ #endif
+ 
+ #ifdef PNG_READ_sRGB_SUPPORTED
+-void /* PRIVATE */
++static png_handle_result_code /* PRIVATE */
+ png_handle_sRGB(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+ {
+    png_byte intent;
+ 
+    png_debug(1, "in png_handle_sRGB");
+ 
+-   if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+-      png_chunk_error(png_ptr, "missing IHDR");
+-
+-   else if ((png_ptr->mode & (PNG_HAVE_IDAT|PNG_HAVE_PLTE)) != 0)
+-   {
+-      png_crc_finish(png_ptr, length);
+-      png_chunk_benign_error(png_ptr, "out of place");
+-      return;
+-   }
+-
+-   if (length != 1)
+-   {
+-      png_crc_finish(png_ptr, length);
+-      png_chunk_benign_error(png_ptr, "invalid");
+-      return;
+-   }
+-
+    png_crc_read(png_ptr, &intent, 1);
+ 
+    if (png_crc_finish(png_ptr, 0) != 0)
+-      return;
++      return handled_error;
+ 
+-   /* If a colorspace error has already been output skip this chunk */
+-   if ((png_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) != 0)
+-      return;
+-
+-   /* Only one sRGB or iCCP chunk is allowed, use the HAVE_INTENT flag to detect
+-    * this.
++   /* This checks the range of the "rendering intent" because it is specified in
++    * the PNG spec itself; the "reserved" values will result in the chunk not
++    * being accepted, just as they do with the various "reserved" values in
++    * IHDR.
+     */
+-   if ((png_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_INTENT) != 0)
++   if (intent > 3/*PNGv3 spec*/)
+    {
+-      png_ptr->colorspace.flags |= PNG_COLORSPACE_INVALID;
+-      png_colorspace_sync(png_ptr, info_ptr);
+-      png_chunk_benign_error(png_ptr, "too many profiles");
+-      return;
++      png_chunk_benign_error(png_ptr, "invalid");
++      return handled_error;
+    }
+ 
+-   (void)png_colorspace_set_sRGB(png_ptr, &png_ptr->colorspace, intent);
+-   png_colorspace_sync(png_ptr, info_ptr);
++   png_set_sRGB(png_ptr, info_ptr, intent);
++   /* NOTE: png_struct::chromaticities is not set here because the RGB to gray
++    * coefficients are known without a need for the chromaticities.
++    */
++
++#ifdef PNG_READ_GAMMA_SUPPORTED
++      /* PNGv3: chunk precedence for gamma is cICP, [iCCP], sRGB, gAMA.  iCCP is
++       * not supported by libpng so the only requirement is to check for cICP
++       * setting the gamma (this is NYI, but this check is safe.)
++       */
++      if (!png_has_chunk(png_ptr, cICP) || png_ptr->chunk_gamma == 0)
++         png_ptr->chunk_gamma = PNG_GAMMA_sRGB_INVERSE;
++#endif /*READ_GAMMA*/
++
++   return handled_ok;
++   PNG_UNUSED(length)
+ }
++#else
++#  define png_handle_sRGB NULL
+ #endif /* READ_sRGB */
+ 
+ #ifdef PNG_READ_iCCP_SUPPORTED
+-void /* PRIVATE */
++static png_handle_result_code /* PRIVATE */
+ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+ /* Note: this does not properly handle profiles that are > 64K under DOS */
+ {
+@@ -1393,44 +1374,10 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+ 
+    png_debug(1, "in png_handle_iCCP");
+ 
+-   if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+-      png_chunk_error(png_ptr, "missing IHDR");
+-
+-   else if ((png_ptr->mode & (PNG_HAVE_IDAT|PNG_HAVE_PLTE)) != 0)
+-   {
+-      png_crc_finish(png_ptr, length);
+-      png_chunk_benign_error(png_ptr, "out of place");
+-      return;
+-   }
+-
+-   /* Consistent with all the above colorspace handling an obviously *invalid*
+-    * chunk is just ignored, so does not invalidate the color space.  An
+-    * alternative is to set the 'invalid' flags at the start of this routine
+-    * and only clear them in they were not set before and all the tests pass.
++   /* PNGv3: allow PNG files with both sRGB and iCCP because the PNG spec only
++    * ever said that there "should" be only one, not "shall" and the PNGv3
++    * colour chunk precedence rules give a handling for this case anyway.
+     */
+-
+-   /* The keyword must be at least one character and there is a
+-    * terminator (0) byte and the compression method byte, and the
+-    * 'zlib' datastream is at least 11 bytes.
+-    */
+-   if (length < 14)
+-   {
+-      png_crc_finish(png_ptr, length);
+-      png_chunk_benign_error(png_ptr, "too short");
+-      return;
+-   }
+-
+-   /* If a colorspace error has already been output skip this chunk */
+-   if ((png_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) != 0)
+-   {
+-      png_crc_finish(png_ptr, length);
+-      return;
+-   }
+-
+-   /* Only one sRGB or iCCP chunk is allowed, use the HAVE_INTENT flag to detect
+-    * this.
+-    */
+-   if ((png_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_INTENT) == 0)
+    {
+       uInt read_length, keyword_length;
+       char keyword[81];
+@@ -1440,19 +1387,16 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+        */
+       read_length = 81; /* maximum */
+       if (read_length > length)
+-         read_length = (uInt)length;
++         read_length = (uInt)/*SAFE*/length;
+ 
+       png_crc_read(png_ptr, (png_bytep)keyword, read_length);
+       length -= read_length;
+ 
+-      /* The minimum 'zlib' stream is assumed to be just the 2 byte header,
+-       * 5 bytes minimum 'deflate' stream, and the 4 byte checksum.
+-       */
+-      if (length < 11)
++      if (length < LZ77Min)
+       {
+          png_crc_finish(png_ptr, length);
+          png_chunk_benign_error(png_ptr, "too short");
+-         return;
++         return handled_error;
+       }
+ 
+       keyword_length = 0;
+@@ -1489,15 +1433,14 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+                    */
+                   png_uint_32 profile_length = png_get_uint_32(profile_header);
+ 
+-                  if (png_icc_check_length(png_ptr, &png_ptr->colorspace,
+-                      keyword, profile_length) != 0)
++                  if (png_icc_check_length(png_ptr, keyword, profile_length) !=
++                      0)
+                   {
+                      /* The length is apparently ok, so we can check the 132
+                       * byte header.
+                       */
+-                     if (png_icc_check_header(png_ptr, &png_ptr->colorspace,
+-                         keyword, profile_length, profile_header,
+-                         png_ptr->color_type) != 0)
++                     if (png_icc_check_header(png_ptr, keyword, profile_length,
++                              profile_header, png_ptr->color_type) != 0)
+                      {
+                         /* Now read the tag table; a variable size buffer is
+                          * needed at this point, allocate one for the whole
+@@ -1507,7 +1450,7 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+                         png_uint_32 tag_count =
+                            png_get_uint_32(profile_header + 128);
+                         png_bytep profile = png_read_buffer(png_ptr,
+-                            profile_length, 2/*silent*/);
++                              profile_length);
+ 
+                         if (profile != NULL)
+                         {
+@@ -1526,8 +1469,7 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+                            if (size == 0)
+                            {
+                               if (png_icc_check_tag_table(png_ptr,
+-                                  &png_ptr->colorspace, keyword, profile_length,
+-                                  profile) != 0)
++                                       keyword, profile_length, profile) != 0)
+                               {
+                                  /* The profile has been validated for basic
+                                   * security issues, so read the whole thing in.
+@@ -1559,13 +1501,6 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+                                     png_crc_finish(png_ptr, length);
+                                     finished = 1;
+ 
+-# if defined(PNG_sRGB_SUPPORTED) && PNG_sRGB_PROFILE_CHECKS >= 0
+-                                    /* Check for a match against sRGB */
+-                                    png_icc_set_sRGB(png_ptr,
+-                                        &png_ptr->colorspace, profile,
+-                                        png_ptr->zstream.adler);
+-# endif
+-
+                                     /* Steal the profile for info_ptr. */
+                                     if (info_ptr != NULL)
+                                     {
+@@ -1588,11 +1523,7 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+                                        }
+ 
+                                        else
+-                                       {
+-                                          png_ptr->colorspace.flags |=
+-                                             PNG_COLORSPACE_INVALID;
+                                           errmsg = "out of memory";
+-                                       }
+                                     }
+ 
+                                     /* else the profile remains in the read
+@@ -1600,13 +1531,10 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+                                      * chunks.
+                                      */
+ 
+-                                    if (info_ptr != NULL)
+-                                       png_colorspace_sync(png_ptr, info_ptr);
+-
+                                     if (errmsg == NULL)
+                                     {
+                                        png_ptr->zowner = 0;
+-                                       return;
++                                       return handled_ok;
+                                     }
+                                  }
+                                  if (errmsg == NULL)
+@@ -1647,22 +1575,21 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+          errmsg = "bad keyword";
+    }
+ 
+-   else
+-      errmsg = "too many profiles";
+-
+    /* Failure: the reason is in 'errmsg' */
+    if (finished == 0)
+       png_crc_finish(png_ptr, length);
+ 
+-   png_ptr->colorspace.flags |= PNG_COLORSPACE_INVALID;
+-   png_colorspace_sync(png_ptr, info_ptr);
+    if (errmsg != NULL) /* else already output */
+       png_chunk_benign_error(png_ptr, errmsg);
++
++   return handled_error;
+ }
++#else
++#  define png_handle_iCCP NULL
+ #endif /* READ_iCCP */
+ 
+ #ifdef PNG_READ_sPLT_SUPPORTED
+-void /* PRIVATE */
++static png_handle_result_code /* PRIVATE */
+ png_handle_sPLT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+ /* Note: this does not properly handle chunks that are > 64K under DOS */
+ {
+@@ -1683,43 +1610,24 @@ png_handle_sPLT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+       if (png_ptr->user_chunk_cache_max == 1)
+       {
+          png_crc_finish(png_ptr, length);
+-         return;
++         return handled_error;
+       }
+ 
+       if (--png_ptr->user_chunk_cache_max == 1)
+       {
+          png_warning(png_ptr, "No space in chunk cache for sPLT");
+          png_crc_finish(png_ptr, length);
+-         return;
++         return handled_error;
+       }
+    }
+ #endif
+ 
+-   if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+-      png_chunk_error(png_ptr, "missing IHDR");
+-
+-   else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
+-   {
+-      png_crc_finish(png_ptr, length);
+-      png_chunk_benign_error(png_ptr, "out of place");
+-      return;
+-   }
+-
+-#ifdef PNG_MAX_MALLOC_64K
+-   if (length > 65535U)
+-   {
+-      png_crc_finish(png_ptr, length);
+-      png_chunk_benign_error(png_ptr, "too large to fit in memory");
+-      return;
+-   }
+-#endif
+-
+-   buffer = png_read_buffer(png_ptr, length+1, 2/*silent*/);
++   buffer = png_read_buffer(png_ptr, length+1);
+    if (buffer == NULL)
+    {
+       png_crc_finish(png_ptr, length);
+       png_chunk_benign_error(png_ptr, "out of memory");
+-      return;
++      return handled_error;
+    }
+ 
+ 
+@@ -1730,7 +1638,7 @@ png_handle_sPLT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+    png_crc_read(png_ptr, buffer, length);
+ 
+    if (png_crc_finish(png_ptr, skip) != 0)
+-      return;
++      return handled_error;
+ 
+    buffer[length] = 0;
+ 
+@@ -1743,7 +1651,7 @@ png_handle_sPLT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+    if (length < 2U || entry_start > buffer + (length - 2U))
+    {
+       png_warning(png_ptr, "malformed sPLT chunk");
+-      return;
++      return handled_error;
+    }
+ 
+    new_palette.depth = *entry_start++;
+@@ -1757,7 +1665,7 @@ png_handle_sPLT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+    if ((data_length % (unsigned int)entry_size) != 0)
+    {
+       png_warning(png_ptr, "sPLT chunk has bad length");
+-      return;
++      return handled_error;
+    }
+ 
+    dl = (png_uint_32)(data_length / (unsigned int)entry_size);
+@@ -1766,7 +1674,7 @@ png_handle_sPLT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+    if (dl > max_dl)
+    {
+       png_warning(png_ptr, "sPLT chunk too long");
+-      return;
++      return handled_error;
+    }
+ 
+    new_palette.nentries = (png_int_32)(data_length / (unsigned int)entry_size);
+@@ -1777,10 +1685,9 @@ png_handle_sPLT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+    if (new_palette.entries == NULL)
+    {
+       png_warning(png_ptr, "sPLT chunk requires too much memory");
+-      return;
++      return handled_error;
+    }
+ 
+-#ifdef PNG_POINTER_INDEXING_SUPPORTED
+    for (i = 0; i < new_palette.nentries; i++)
+    {
+       pp = new_palette.entries + i;
+@@ -1803,31 +1710,6 @@ png_handle_sPLT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+ 
+       pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
+    }
+-#else
+-   pp = new_palette.entries;
+-
+-   for (i = 0; i < new_palette.nentries; i++)
+-   {
+-
+-      if (new_palette.depth == 8)
+-      {
+-         pp[i].red   = *entry_start++;
+-         pp[i].green = *entry_start++;
+-         pp[i].blue  = *entry_start++;
+-         pp[i].alpha = *entry_start++;
+-      }
+-
+-      else
+-      {
+-         pp[i].red   = png_get_uint_16(entry_start); entry_start += 2;
+-         pp[i].green = png_get_uint_16(entry_start); entry_start += 2;
+-         pp[i].blue  = png_get_uint_16(entry_start); entry_start += 2;
+-         pp[i].alpha = png_get_uint_16(entry_start); entry_start += 2;
+-      }
+-
+-      pp[i].frequency = png_get_uint_16(entry_start); entry_start += 2;
+-   }
+-#endif
+ 
+    /* Discard all chunk data except the name and stash that */
+    new_palette.name = (png_charp)buffer;
+@@ -1835,34 +1717,20 @@ png_handle_sPLT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+    png_set_sPLT(png_ptr, info_ptr, &new_palette, 1);
+ 
+    png_free(png_ptr, new_palette.entries);
++   return handled_ok;
+ }
++#else
++#  define png_handle_sPLT NULL
+ #endif /* READ_sPLT */
+ 
+ #ifdef PNG_READ_tRNS_SUPPORTED
+-void /* PRIVATE */
++static png_handle_result_code /* PRIVATE */
+ png_handle_tRNS(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+ {
+    png_byte readbuf[PNG_MAX_PALETTE_LENGTH];
+ 
+    png_debug(1, "in png_handle_tRNS");
+ 
+-   if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+-      png_chunk_error(png_ptr, "missing IHDR");
+-
+-   else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
+-   {
+-      png_crc_finish(png_ptr, length);
+-      png_chunk_benign_error(png_ptr, "out of place");
+-      return;
+-   }
+-
+-   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS) != 0)
+-   {
+-      png_crc_finish(png_ptr, length);
+-      png_chunk_benign_error(png_ptr, "duplicate");
+-      return;
+-   }
+-
+    if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
+    {
+       png_byte buf[2];
+@@ -1871,7 +1739,7 @@ png_handle_tRNS(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+       {
+          png_crc_finish(png_ptr, length);
+          png_chunk_benign_error(png_ptr, "invalid");
+-         return;
++         return handled_error;
+       }
+ 
+       png_crc_read(png_ptr, buf, 2);
+@@ -1887,7 +1755,7 @@ png_handle_tRNS(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+       {
+          png_crc_finish(png_ptr, length);
+          png_chunk_benign_error(png_ptr, "invalid");
+-         return;
++         return handled_error;
+       }
+ 
+       png_crc_read(png_ptr, buf, length);
+@@ -1901,10 +1769,9 @@ png_handle_tRNS(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+    {
+       if ((png_ptr->mode & PNG_HAVE_PLTE) == 0)
+       {
+-         /* TODO: is this actually an error in the ISO spec? */
+          png_crc_finish(png_ptr, length);
+          png_chunk_benign_error(png_ptr, "out of place");
+-         return;
++         return handled_error;
+       }
+ 
+       if (length > (unsigned int) png_ptr->num_palette ||
+@@ -1913,7 +1780,7 @@ png_handle_tRNS(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+       {
+          png_crc_finish(png_ptr, length);
+          png_chunk_benign_error(png_ptr, "invalid");
+-         return;
++         return handled_error;
+       }
+ 
+       png_crc_read(png_ptr, readbuf, length);
+@@ -1924,13 +1791,13 @@ png_handle_tRNS(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+    {
+       png_crc_finish(png_ptr, length);
+       png_chunk_benign_error(png_ptr, "invalid with alpha channel");
+-      return;
++      return handled_error;
+    }
+ 
+    if (png_crc_finish(png_ptr, 0) != 0)
+    {
+       png_ptr->num_trans = 0;
+-      return;
++      return handled_error;
+    }
+ 
+    /* TODO: this is a horrible side effect in the palette case because the
+@@ -1939,11 +1806,14 @@ png_handle_tRNS(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+     */
+    png_set_tRNS(png_ptr, info_ptr, readbuf, png_ptr->num_trans,
+        &(png_ptr->trans_color));
++   return handled_ok;
+ }
++#else
++#  define png_handle_tRNS NULL
+ #endif
+ 
+ #ifdef PNG_READ_bKGD_SUPPORTED
+-void /* PRIVATE */
++static png_handle_result_code /* PRIVATE */
+ png_handle_bKGD(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+ {
+    unsigned int truelen;
+@@ -1952,27 +1822,17 @@ png_handle_bKGD(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+ 
+    png_debug(1, "in png_handle_bKGD");
+ 
+-   if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+-      png_chunk_error(png_ptr, "missing IHDR");
+-
+-   else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0 ||
+-       (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
+-       (png_ptr->mode & PNG_HAVE_PLTE) == 0))
+-   {
+-      png_crc_finish(png_ptr, length);
+-      png_chunk_benign_error(png_ptr, "out of place");
+-      return;
+-   }
+-
+-   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD) != 0)
++   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+    {
+-      png_crc_finish(png_ptr, length);
+-      png_chunk_benign_error(png_ptr, "duplicate");
+-      return;
+-   }
++      if ((png_ptr->mode & PNG_HAVE_PLTE) == 0)
++      {
++         png_crc_finish(png_ptr, length);
++         png_chunk_benign_error(png_ptr, "out of place");
++         return handled_error;
++      }
+ 
+-   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+       truelen = 1;
++   }
+ 
+    else if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0)
+       truelen = 6;
+@@ -1984,13 +1844,13 @@ png_handle_bKGD(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+    {
+       png_crc_finish(png_ptr, length);
+       png_chunk_benign_error(png_ptr, "invalid");
+-      return;
++      return handled_error;
+    }
+ 
+    png_crc_read(png_ptr, buf, truelen);
+ 
+    if (png_crc_finish(png_ptr, 0) != 0)
+-      return;
++      return handled_error;
+ 
+    /* We convert the index value into RGB components so that we can allow
+     * arbitrary RGB values for background when we have transparency, and
+@@ -2006,7 +1866,7 @@ png_handle_bKGD(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+          if (buf[0] >= info_ptr->num_palette)
+          {
+             png_chunk_benign_error(png_ptr, "invalid index");
+-            return;
++            return handled_error;
+          }
+ 
+          background.red = (png_uint_16)png_ptr->palette[buf[0]].red;
+@@ -2027,7 +1887,7 @@ png_handle_bKGD(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+          if (buf[0] != 0 || buf[1] >= (unsigned int)(1 << png_ptr->bit_depth))
+          {
+             png_chunk_benign_error(png_ptr, "invalid gray level");
+-            return;
++            return handled_error;
+          }
+       }
+ 
+@@ -2045,7 +1905,7 @@ png_handle_bKGD(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+          if (buf[0] != 0 || buf[2] != 0 || buf[4] != 0)
+          {
+             png_chunk_benign_error(png_ptr, "invalid color");
+-            return;
++            return handled_error;
+          }
+       }
+ 
+@@ -2057,75 +1917,174 @@ png_handle_bKGD(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+    }
+ 
+    png_set_bKGD(png_ptr, info_ptr, &background);
++   return handled_ok;
+ }
++#else
++#  define png_handle_bKGD NULL
+ #endif
+ 
+-#ifdef PNG_READ_eXIf_SUPPORTED
+-void /* PRIVATE */
+-png_handle_eXIf(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
++#ifdef PNG_READ_cICP_SUPPORTED
++static png_handle_result_code /* PRIVATE */
++png_handle_cICP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+ {
+-   unsigned int i;
++   png_byte buf[4];
+ 
+-   png_debug(1, "in png_handle_eXIf");
++   png_debug(1, "in png_handle_cICP");
+ 
+-   if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+-      png_chunk_error(png_ptr, "missing IHDR");
++   png_crc_read(png_ptr, buf, 4);
+ 
+-   if (length < 2)
+-   {
+-      png_crc_finish(png_ptr, length);
+-      png_chunk_benign_error(png_ptr, "too short");
+-      return;
+-   }
++   if (png_crc_finish(png_ptr, 0) != 0)
++      return handled_error;
+ 
+-   else if (info_ptr == NULL || (info_ptr->valid & PNG_INFO_eXIf) != 0)
+-   {
+-      png_crc_finish(png_ptr, length);
+-      png_chunk_benign_error(png_ptr, "duplicate");
+-      return;
+-   }
++   png_set_cICP(png_ptr, info_ptr, buf[0], buf[1],  buf[2], buf[3]);
+ 
+-   info_ptr->free_me |= PNG_FREE_EXIF;
++   /* We only use 'chromaticities' for RGB to gray */
++#  ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
++      if (!png_has_chunk(png_ptr, mDCV))
++      {
++         /* TODO: png_ptr->chromaticities = chromaticities; */
++      }
++#  endif /* READ_RGB_TO_GRAY */
+ 
+-   info_ptr->eXIf_buf = png_voidcast(png_bytep,
+-             png_malloc_warn(png_ptr, length));
++#ifdef PNG_READ_GAMMA_SUPPORTED
++      /* PNGv3: chunk precedence for gamma is cICP, [iCCP], sRGB, gAMA.  cICP is
++       * at the head so simply set the gamma if it can be determined.  If not
++       * chunk_gamma remains unchanged; sRGB and gAMA handling check it for
++       * being zero.
++       */
++      /* TODO: set png_struct::chunk_gamma when possible */
++#endif /*READ_GAMMA*/
++
++   return handled_ok;
++   PNG_UNUSED(length)
++}
++#else
++#  define png_handle_cICP NULL
++#endif
++
++#ifdef PNG_READ_cLLI_SUPPORTED
++static png_handle_result_code /* PRIVATE */
++png_handle_cLLI(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
++{
++   png_byte buf[8];
+ 
+-   if (info_ptr->eXIf_buf == NULL)
++   png_debug(1, "in png_handle_cLLI");
++
++   png_crc_read(png_ptr, buf, 8);
++
++   if (png_crc_finish(png_ptr, 0) != 0)
++      return handled_error;
++
++   /* The error checking happens here, this puts it in just one place: */
++   png_set_cLLI_fixed(png_ptr, info_ptr, png_get_uint_32(buf),
++         png_get_uint_32(buf+4));
++   return handled_ok;
++   PNG_UNUSED(length)
++}
++#else
++#  define png_handle_cLLI NULL
++#endif
++
++#ifdef PNG_READ_mDCV_SUPPORTED
++static png_handle_result_code /* PRIVATE */
++png_handle_mDCV(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
++{
++   png_xy chromaticities;
++   png_byte buf[24];
++
++   png_debug(1, "in png_handle_mDCV");
++
++   png_crc_read(png_ptr, buf, 24);
++
++   if (png_crc_finish(png_ptr, 0) != 0)
++      return handled_error;
++
++   /* The error checking happens here, this puts it in just one place.  The
++    * odd /50000 scaling factor makes it more difficult but the (x.y) values are
++    * only two bytes so a <<1 is safe.
++    *
++    * WARNING: the PNG specification defines the cHRM chunk to **start** with
++    * the white point (x,y).  The W3C PNG v3 specification puts the white point
++    * **after* R,G,B.  The x,y values in mDCV are also scaled by 50,000 and
++    * stored in just two bytes, whereas those in cHRM are scaled by 100,000 and
++    * stored in four bytes.  This is very, very confusing.  These APIs remove
++    * the confusion by copying the existing, well established, API.
++    */
++   chromaticities.redx   = png_get_uint_16(buf+ 0U) << 1; /* red x */
++   chromaticities.redy   = png_get_uint_16(buf+ 2U) << 1; /* red y */
++   chromaticities.greenx = png_get_uint_16(buf+ 4U) << 1; /* green x */
++   chromaticities.greeny = png_get_uint_16(buf+ 6U) << 1; /* green y */
++   chromaticities.bluex  = png_get_uint_16(buf+ 8U) << 1; /* blue x */
++   chromaticities.bluey  = png_get_uint_16(buf+10U) << 1; /* blue y */
++   chromaticities.whitex = png_get_uint_16(buf+12U) << 1; /* white x */
++   chromaticities.whitey = png_get_uint_16(buf+14U) << 1; /* white y */
++
++   png_set_mDCV_fixed(png_ptr, info_ptr,
++         chromaticities.whitex, chromaticities.whitey,
++         chromaticities.redx, chromaticities.redy,
++         chromaticities.greenx, chromaticities.greeny,
++         chromaticities.bluex, chromaticities.bluey,
++         png_get_uint_32(buf+16U), /* peak luminance */
++         png_get_uint_32(buf+20U));/* minimum perceivable luminance */
++
++   /* We only use 'chromaticities' for RGB to gray */
++#  ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
++      png_ptr->chromaticities = chromaticities;
++#  endif /* READ_RGB_TO_GRAY */
++
++   return handled_ok;
++   PNG_UNUSED(length)
++}
++#else
++#  define png_handle_mDCV NULL
++#endif
++
++#ifdef PNG_READ_eXIf_SUPPORTED
++static png_handle_result_code /* PRIVATE */
++png_handle_eXIf(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
++{
++   png_bytep buffer = NULL;
++
++   png_debug(1, "in png_handle_eXIf");
++
++   buffer = png_read_buffer(png_ptr, length);
++
++   if (buffer == NULL)
+    {
+       png_crc_finish(png_ptr, length);
+       png_chunk_benign_error(png_ptr, "out of memory");
+-      return;
++      return handled_error;
+    }
+ 
+-   for (i = 0; i < length; i++)
++   png_crc_read(png_ptr, buffer, length);
++
++   if (png_crc_finish(png_ptr, 0) != 0)
++      return handled_error;
++
++   /* PNGv3: the code used to check the byte order mark at the start for MM or
++    * II, however PNGv3 states that the the first 4 bytes should be checked.
++    * The caller ensures that there are four bytes available.
++    */
+    {
+-      png_byte buf[1];
+-      png_crc_read(png_ptr, buf, 1);
+-      info_ptr->eXIf_buf[i] = buf[0];
+-      if (i == 1)
++      png_uint_32 header = png_get_uint_32(buffer);
++
++      /* These numbers are copied from the PNGv3 spec: */
++      if (header != 0x49492A00 && header != 0x4D4D002A)
+       {
+-         if ((buf[0] != 'M' && buf[0] != 'I') ||
+-             (info_ptr->eXIf_buf[0] != buf[0]))
+-         {
+-            png_crc_finish(png_ptr, length - 2);
+-            png_chunk_benign_error(png_ptr, "incorrect byte-order specifier");
+-            png_free(png_ptr, info_ptr->eXIf_buf);
+-            info_ptr->eXIf_buf = NULL;
+-            return;
+-         }
++         png_chunk_benign_error(png_ptr, "invalid");
++         return handled_error;
+       }
+    }
+ 
+-   if (png_crc_finish(png_ptr, 0) == 0)
+-      png_set_eXIf_1(png_ptr, info_ptr, length, info_ptr->eXIf_buf);
+-
+-   png_free(png_ptr, info_ptr->eXIf_buf);
+-   info_ptr->eXIf_buf = NULL;
++   png_set_eXIf_1(png_ptr, info_ptr, length, buffer);
++   return handled_ok;
+ }
++#else
++#  define png_handle_eXIf NULL
+ #endif
+ 
+ #ifdef PNG_READ_hIST_SUPPORTED
+-void /* PRIVATE */
++static png_handle_result_code /* PRIVATE */
+ png_handle_hIST(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+ {
+    unsigned int num, i;
+@@ -2133,25 +2092,13 @@ png_handle_hIST(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+ 
+    png_debug(1, "in png_handle_hIST");
+ 
+-   if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+-      png_chunk_error(png_ptr, "missing IHDR");
+-
+-   else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0 ||
+-       (png_ptr->mode & PNG_HAVE_PLTE) == 0)
+-   {
+-      png_crc_finish(png_ptr, length);
+-      png_chunk_benign_error(png_ptr, "out of place");
+-      return;
+-   }
+-
+-   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST) != 0)
+-   {
+-      png_crc_finish(png_ptr, length);
+-      png_chunk_benign_error(png_ptr, "duplicate");
+-      return;
+-   }
+-
+-   num = length / 2 ;
++   /* This cast is safe because the chunk definition limits the length to a
++    * maximum of 1024 bytes.
++    *
++    * TODO: maybe use png_uint_32 anyway, not unsigned int, to reduce the
++    * casts.
++    */
++   num = (unsigned int)length / 2 ;
+ 
+    if (length != num * 2 ||
+        num != (unsigned int)png_ptr->num_palette ||
+@@ -2159,7 +2106,7 @@ png_handle_hIST(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+    {
+       png_crc_finish(png_ptr, length);
+       png_chunk_benign_error(png_ptr, "invalid");
+-      return;
++      return handled_error;
+    }
+ 
+    for (i = 0; i < num; i++)
+@@ -2171,14 +2118,17 @@ png_handle_hIST(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+    }
+ 
+    if (png_crc_finish(png_ptr, 0) != 0)
+-      return;
++      return handled_error;
+ 
+    png_set_hIST(png_ptr, info_ptr, readbuf);
++   return handled_ok;
+ }
++#else
++#  define png_handle_hIST NULL
+ #endif
+ 
+ #ifdef PNG_READ_pHYs_SUPPORTED
+-void /* PRIVATE */
++static png_handle_result_code /* PRIVATE */
+ png_handle_pHYs(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+ {
+    png_byte buf[9];
+@@ -2187,44 +2137,24 @@ png_handle_pHYs(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+ 
+    png_debug(1, "in png_handle_pHYs");
+ 
+-   if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+-      png_chunk_error(png_ptr, "missing IHDR");
+-
+-   else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
+-   {
+-      png_crc_finish(png_ptr, length);
+-      png_chunk_benign_error(png_ptr, "out of place");
+-      return;
+-   }
+-
+-   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs) != 0)
+-   {
+-      png_crc_finish(png_ptr, length);
+-      png_chunk_benign_error(png_ptr, "duplicate");
+-      return;
+-   }
+-
+-   if (length != 9)
+-   {
+-      png_crc_finish(png_ptr, length);
+-      png_chunk_benign_error(png_ptr, "invalid");
+-      return;
+-   }
+-
+    png_crc_read(png_ptr, buf, 9);
+ 
+    if (png_crc_finish(png_ptr, 0) != 0)
+-      return;
++      return handled_error;
+ 
+    res_x = png_get_uint_32(buf);
+    res_y = png_get_uint_32(buf + 4);
+    unit_type = buf[8];
+    png_set_pHYs(png_ptr, info_ptr, res_x, res_y, unit_type);
++   return handled_ok;
++   PNG_UNUSED(length)
+ }
++#else
++#  define png_handle_pHYs NULL
+ #endif
+ 
+ #ifdef PNG_READ_oFFs_SUPPORTED
+-void /* PRIVATE */
++static png_handle_result_code /* PRIVATE */
+ png_handle_oFFs(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+ {
+    png_byte buf[9];
+@@ -2233,45 +2163,25 @@ png_handle_oFFs(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+ 
+    png_debug(1, "in png_handle_oFFs");
+ 
+-   if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+-      png_chunk_error(png_ptr, "missing IHDR");
+-
+-   else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
+-   {
+-      png_crc_finish(png_ptr, length);
+-      png_chunk_benign_error(png_ptr, "out of place");
+-      return;
+-   }
+-
+-   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs) != 0)
+-   {
+-      png_crc_finish(png_ptr, length);
+-      png_chunk_benign_error(png_ptr, "duplicate");
+-      return;
+-   }
+-
+-   if (length != 9)
+-   {
+-      png_crc_finish(png_ptr, length);
+-      png_chunk_benign_error(png_ptr, "invalid");
+-      return;
+-   }
+-
+    png_crc_read(png_ptr, buf, 9);
+ 
+    if (png_crc_finish(png_ptr, 0) != 0)
+-      return;
++      return handled_error;
+ 
+    offset_x = png_get_int_32(buf);
+    offset_y = png_get_int_32(buf + 4);
+    unit_type = buf[8];
+    png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, unit_type);
++   return handled_ok;
++   PNG_UNUSED(length)
+ }
++#else
++#  define png_handle_oFFs NULL
+ #endif
+ 
+ #ifdef PNG_READ_pCAL_SUPPORTED
+ /* Read the pCAL chunk (described in the PNG Extensions document) */
+-void /* PRIVATE */
++static png_handle_result_code /* PRIVATE */
+ png_handle_pCAL(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+ {
+    png_int_32 X0, X1;
+@@ -2281,40 +2191,22 @@ png_handle_pCAL(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+    int i;
+ 
+    png_debug(1, "in png_handle_pCAL");
+-
+-   if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+-      png_chunk_error(png_ptr, "missing IHDR");
+-
+-   else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
+-   {
+-      png_crc_finish(png_ptr, length);
+-      png_chunk_benign_error(png_ptr, "out of place");
+-      return;
+-   }
+-
+-   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL) != 0)
+-   {
+-      png_crc_finish(png_ptr, length);
+-      png_chunk_benign_error(png_ptr, "duplicate");
+-      return;
+-   }
+-
+    png_debug1(2, "Allocating and reading pCAL chunk data (%u bytes)",
+        length + 1);
+ 
+-   buffer = png_read_buffer(png_ptr, length+1, 2/*silent*/);
++   buffer = png_read_buffer(png_ptr, length+1);
+ 
+    if (buffer == NULL)
+    {
+       png_crc_finish(png_ptr, length);
+       png_chunk_benign_error(png_ptr, "out of memory");
+-      return;
++      return handled_error;
+    }
+ 
+    png_crc_read(png_ptr, buffer, length);
+ 
+    if (png_crc_finish(png_ptr, 0) != 0)
+-      return;
++      return handled_error;
+ 
+    buffer[length] = 0; /* Null terminate the last string */
+ 
+@@ -2330,7 +2222,7 @@ png_handle_pCAL(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+    if (endptr - buf <= 12)
+    {
+       png_chunk_benign_error(png_ptr, "invalid");
+-      return;
++      return handled_error;
+    }
+ 
+    png_debug(3, "Reading pCAL X0, X1, type, nparams, and units");
+@@ -2350,7 +2242,7 @@ png_handle_pCAL(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+        (type == PNG_EQUATION_HYPERBOLIC && nparams != 4))
+    {
+       png_chunk_benign_error(png_ptr, "invalid parameter count");
+-      return;
++      return handled_error;
+    }
+ 
+    else if (type >= PNG_EQUATION_LAST)
+@@ -2369,7 +2261,7 @@ png_handle_pCAL(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+    if (params == NULL)
+    {
+       png_chunk_benign_error(png_ptr, "out of memory");
+-      return;
++      return handled_error;
+    }
+ 
+    /* Get pointers to the start of each parameter string. */
+@@ -2387,20 +2279,29 @@ png_handle_pCAL(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+       {
+          png_free(png_ptr, params);
+          png_chunk_benign_error(png_ptr, "invalid data");
+-         return;
++         return handled_error;
+       }
+    }
+ 
+    png_set_pCAL(png_ptr, info_ptr, (png_charp)buffer, X0, X1, type, nparams,
+        (png_charp)units, params);
+ 
++   /* TODO: BUG: png_set_pCAL calls png_chunk_report which, in this case, calls
++    * png_benign_error and that can error out.
++    *
++    * png_read_buffer needs to be allocated with space for both nparams and the
++    * parameter strings.  Not hard to do.
++    */
+    png_free(png_ptr, params);
++   return handled_ok;
+ }
++#else
++#  define png_handle_pCAL NULL
+ #endif
+ 
+ #ifdef PNG_READ_sCAL_SUPPORTED
+ /* Read the sCAL chunk */
+-void /* PRIVATE */
++static png_handle_result_code /* PRIVATE */
+ png_handle_sCAL(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+ {
+    png_bytep buffer;
+@@ -2408,55 +2309,29 @@ png_handle_sCAL(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+    int state;
+ 
+    png_debug(1, "in png_handle_sCAL");
+-
+-   if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+-      png_chunk_error(png_ptr, "missing IHDR");
+-
+-   else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
+-   {
+-      png_crc_finish(png_ptr, length);
+-      png_chunk_benign_error(png_ptr, "out of place");
+-      return;
+-   }
+-
+-   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL) != 0)
+-   {
+-      png_crc_finish(png_ptr, length);
+-      png_chunk_benign_error(png_ptr, "duplicate");
+-      return;
+-   }
+-
+-   /* Need unit type, width, \0, height: minimum 4 bytes */
+-   else if (length < 4)
+-   {
+-      png_crc_finish(png_ptr, length);
+-      png_chunk_benign_error(png_ptr, "invalid");
+-      return;
+-   }
+-
+    png_debug1(2, "Allocating and reading sCAL chunk data (%u bytes)",
+        length + 1);
+ 
+-   buffer = png_read_buffer(png_ptr, length+1, 2/*silent*/);
++   buffer = png_read_buffer(png_ptr, length+1);
+ 
+    if (buffer == NULL)
+    {
+-      png_chunk_benign_error(png_ptr, "out of memory");
+       png_crc_finish(png_ptr, length);
+-      return;
++      png_chunk_benign_error(png_ptr, "out of memory");
++      return handled_error;
+    }
+ 
+    png_crc_read(png_ptr, buffer, length);
+    buffer[length] = 0; /* Null terminate the last string */
+ 
+    if (png_crc_finish(png_ptr, 0) != 0)
+-      return;
++      return handled_error;
+ 
+    /* Validate the unit. */
+    if (buffer[0] != 1 && buffer[0] != 2)
+    {
+       png_chunk_benign_error(png_ptr, "invalid unit");
+-      return;
++      return handled_error;
+    }
+ 
+    /* Validate the ASCII numbers, need two ASCII numbers separated by
+@@ -2485,15 +2360,22 @@ png_handle_sCAL(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+          png_chunk_benign_error(png_ptr, "non-positive height");
+ 
+       else
++      {
+          /* This is the (only) success case. */
+          png_set_sCAL_s(png_ptr, info_ptr, buffer[0],
+              (png_charp)buffer+1, (png_charp)buffer+heighti);
++         return handled_ok;
++      }
+    }
++
++   return handled_error;
+ }
++#else
++#  define png_handle_sCAL NULL
+ #endif
+ 
+ #ifdef PNG_READ_tIME_SUPPORTED
+-void /* PRIVATE */
++static png_handle_result_code /* PRIVATE */
+ png_handle_tIME(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+ {
+    png_byte buf[7];
+@@ -2501,30 +2383,17 @@ png_handle_tIME(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+ 
+    png_debug(1, "in png_handle_tIME");
+ 
+-   if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+-      png_chunk_error(png_ptr, "missing IHDR");
+-
+-   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME) != 0)
+-   {
+-      png_crc_finish(png_ptr, length);
+-      png_chunk_benign_error(png_ptr, "duplicate");
+-      return;
+-   }
+-
++   /* TODO: what is this doing here?  It should be happened in pngread.c and
++    * pngpread.c, although it could be moved to png_handle_chunk below and
++    * thereby avoid some code duplication.
++    */
+    if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
+       png_ptr->mode |= PNG_AFTER_IDAT;
+ 
+-   if (length != 7)
+-   {
+-      png_crc_finish(png_ptr, length);
+-      png_chunk_benign_error(png_ptr, "invalid");
+-      return;
+-   }
+-
+    png_crc_read(png_ptr, buf, 7);
+ 
+    if (png_crc_finish(png_ptr, 0) != 0)
+-      return;
++      return handled_error;
+ 
+    mod_time.second = buf[6];
+    mod_time.minute = buf[5];
+@@ -2534,12 +2403,16 @@ png_handle_tIME(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+    mod_time.year = png_get_uint_16(buf);
+ 
+    png_set_tIME(png_ptr, info_ptr, &mod_time);
++   return handled_ok;
++   PNG_UNUSED(length)
+ }
++#else
++#  define png_handle_tIME NULL
+ #endif
+ 
+ #ifdef PNG_READ_tEXt_SUPPORTED
+ /* Note: this does not properly handle chunks that are > 64K under DOS */
+-void /* PRIVATE */
++static png_handle_result_code /* PRIVATE */
+ png_handle_tEXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+ {
+    png_text  text_info;
+@@ -2556,45 +2429,35 @@ png_handle_tEXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+       if (png_ptr->user_chunk_cache_max == 1)
+       {
+          png_crc_finish(png_ptr, length);
+-         return;
++         return handled_error;
+       }
+ 
+       if (--png_ptr->user_chunk_cache_max == 1)
+       {
+          png_crc_finish(png_ptr, length);
+          png_chunk_benign_error(png_ptr, "no space in chunk cache");
+-         return;
++         return handled_error;
+       }
+    }
+ #endif
+ 
+-   if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+-      png_chunk_error(png_ptr, "missing IHDR");
+-
++   /* TODO: this doesn't work and shouldn't be necessary. */
+    if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
+       png_ptr->mode |= PNG_AFTER_IDAT;
+ 
+-#ifdef PNG_MAX_MALLOC_64K
+-   if (length > 65535U)
+-   {
+-      png_crc_finish(png_ptr, length);
+-      png_chunk_benign_error(png_ptr, "too large to fit in memory");
+-      return;
+-   }
+-#endif
+-
+-   buffer = png_read_buffer(png_ptr, length+1, 1/*warn*/);
++   buffer = png_read_buffer(png_ptr, length+1);
+ 
+    if (buffer == NULL)
+    {
++      png_crc_finish(png_ptr, length);
+       png_chunk_benign_error(png_ptr, "out of memory");
+-      return;
++      return handled_error;
+    }
+ 
+    png_crc_read(png_ptr, buffer, length);
+ 
+    if (png_crc_finish(png_ptr, skip) != 0)
+-      return;
++      return handled_error;
+ 
+    key = (png_charp)buffer;
+    key[length] = 0;
+@@ -2613,14 +2476,19 @@ png_handle_tEXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+    text_info.text = text;
+    text_info.text_length = strlen(text);
+ 
+-   if (png_set_text_2(png_ptr, info_ptr, &text_info, 1) != 0)
+-      png_warning(png_ptr, "Insufficient memory to process text chunk");
++   if (png_set_text_2(png_ptr, info_ptr, &text_info, 1) == 0)
++      return handled_ok;
++
++   png_chunk_benign_error(png_ptr, "out of memory");
++   return handled_error;
+ }
++#else
++#  define png_handle_tEXt NULL
+ #endif
+ 
+ #ifdef PNG_READ_zTXt_SUPPORTED
+ /* Note: this does not correctly handle chunks that are > 64K under DOS */
+-void /* PRIVATE */
++static png_handle_result_code /* PRIVATE */
+ png_handle_zTXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+ {
+    png_const_charp errmsg = NULL;
+@@ -2635,40 +2503,39 @@ png_handle_zTXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+       if (png_ptr->user_chunk_cache_max == 1)
+       {
+          png_crc_finish(png_ptr, length);
+-         return;
++         return handled_error;
+       }
+ 
+       if (--png_ptr->user_chunk_cache_max == 1)
+       {
+          png_crc_finish(png_ptr, length);
+          png_chunk_benign_error(png_ptr, "no space in chunk cache");
+-         return;
++         return handled_error;
+       }
+    }
+ #endif
+ 
+-   if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+-      png_chunk_error(png_ptr, "missing IHDR");
+-
++   /* TODO: should not be necessary. */
+    if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
+       png_ptr->mode |= PNG_AFTER_IDAT;
+ 
+    /* Note, "length" is sufficient here; we won't be adding
+-    * a null terminator later.
++    * a null terminator later.  The limit check in png_handle_chunk should be
++    * sufficient.
+     */
+-   buffer = png_read_buffer(png_ptr, length, 2/*silent*/);
++   buffer = png_read_buffer(png_ptr, length);
+ 
+    if (buffer == NULL)
+    {
+       png_crc_finish(png_ptr, length);
+       png_chunk_benign_error(png_ptr, "out of memory");
+-      return;
++      return handled_error;
+    }
+ 
+    png_crc_read(png_ptr, buffer, length);
+ 
+    if (png_crc_finish(png_ptr, 0) != 0)
+-      return;
++      return handled_error;
+ 
+    /* TODO: also check that the keyword contents match the spec! */
+    for (keyword_length = 0;
+@@ -2721,8 +2588,10 @@ png_handle_zTXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+             text.lang = NULL;
+             text.lang_key = NULL;
+ 
+-            if (png_set_text_2(png_ptr, info_ptr, &text, 1) != 0)
+-               errmsg = "insufficient memory";
++            if (png_set_text_2(png_ptr, info_ptr, &text, 1) == 0)
++               return handled_ok;
++
++            errmsg = "out of memory";
+          }
+       }
+ 
+@@ -2730,14 +2599,16 @@ png_handle_zTXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+          errmsg = png_ptr->zstream.msg;
+    }
+ 
+-   if (errmsg != NULL)
+-      png_chunk_benign_error(png_ptr, errmsg);
++   png_chunk_benign_error(png_ptr, errmsg);
++   return handled_error;
+ }
++#else
++#  define png_handle_zTXt NULL
+ #endif
+ 
+ #ifdef PNG_READ_iTXt_SUPPORTED
+ /* Note: this does not correctly handle chunks that are > 64K under DOS */
+-void /* PRIVATE */
++static png_handle_result_code /* PRIVATE */
+ png_handle_iTXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+ {
+    png_const_charp errmsg = NULL;
+@@ -2752,37 +2623,35 @@ png_handle_iTXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+       if (png_ptr->user_chunk_cache_max == 1)
+       {
+          png_crc_finish(png_ptr, length);
+-         return;
++         return handled_error;
+       }
+ 
+       if (--png_ptr->user_chunk_cache_max == 1)
+       {
+          png_crc_finish(png_ptr, length);
+          png_chunk_benign_error(png_ptr, "no space in chunk cache");
+-         return;
++         return handled_error;
+       }
+    }
+ #endif
+ 
+-   if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+-      png_chunk_error(png_ptr, "missing IHDR");
+-
++   /* TODO: should not be necessary. */
+    if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
+       png_ptr->mode |= PNG_AFTER_IDAT;
+ 
+-   buffer = png_read_buffer(png_ptr, length+1, 1/*warn*/);
++   buffer = png_read_buffer(png_ptr, length+1);
+ 
+    if (buffer == NULL)
+    {
+       png_crc_finish(png_ptr, length);
+       png_chunk_benign_error(png_ptr, "out of memory");
+-      return;
++      return handled_error;
+    }
+ 
+    png_crc_read(png_ptr, buffer, length);
+ 
+    if (png_crc_finish(png_ptr, 0) != 0)
+-      return;
++      return handled_error;
+ 
+    /* First the keyword. */
+    for (prefix_length=0;
+@@ -2872,8 +2741,10 @@ png_handle_iTXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+          text.text_length = 0;
+          text.itxt_length = uncompressed_length;
+ 
+-         if (png_set_text_2(png_ptr, info_ptr, &text, 1) != 0)
+-            errmsg = "insufficient memory";
++         if (png_set_text_2(png_ptr, info_ptr, &text, 1) == 0)
++            return handled_ok;
++
++         errmsg = "out of memory";
+       }
+    }
+ 
+@@ -2882,7 +2753,10 @@ png_handle_iTXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+ 
+    if (errmsg != NULL)
+       png_chunk_benign_error(png_ptr, errmsg);
++   return handled_error;
+ }
++#else
++#  define png_handle_iTXt NULL
+ #endif
+ 
+ #ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
+@@ -2890,7 +2764,7 @@ png_handle_iTXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+ static int
+ png_cache_unknown_chunk(png_structrp png_ptr, png_uint_32 length)
+ {
+-   png_alloc_size_t limit = PNG_SIZE_MAX;
++   const png_alloc_size_t limit = png_chunk_max(png_ptr);
+ 
+    if (png_ptr->unknown_chunk.data != NULL)
+    {
+@@ -2898,16 +2772,6 @@ png_cache_unknown_chunk(png_structrp png_ptr, png_uint_32 length)
+       png_ptr->unknown_chunk.data = NULL;
+    }
+ 
+-#  ifdef PNG_SET_USER_LIMITS_SUPPORTED
+-   if (png_ptr->user_chunk_malloc_max > 0 &&
+-       png_ptr->user_chunk_malloc_max < limit)
+-      limit = png_ptr->user_chunk_malloc_max;
+-
+-#  elif PNG_USER_CHUNK_MALLOC_MAX > 0
+-   if (PNG_USER_CHUNK_MALLOC_MAX < limit)
+-      limit = PNG_USER_CHUNK_MALLOC_MAX;
+-#  endif
+-
+    if (length <= limit)
+    {
+       PNG_CSTRING_FROM_CHUNK(png_ptr->unknown_chunk.name, png_ptr->chunk_name);
+@@ -2946,11 +2810,11 @@ png_cache_unknown_chunk(png_structrp png_ptr, png_uint_32 length)
+ #endif /* READ_UNKNOWN_CHUNKS */
+ 
+ /* Handle an unknown, or known but disabled, chunk */
+-void /* PRIVATE */
++png_handle_result_code /*PRIVATE*/
+ png_handle_unknown(png_structrp png_ptr, png_inforp info_ptr,
+     png_uint_32 length, int keep)
+ {
+-   int handled = 0; /* the chunk was handled */
++   png_handle_result_code handled = handled_discarded; /* the default */
+ 
+    png_debug(1, "in png_handle_unknown");
+ 
+@@ -2997,7 +2861,7 @@ png_handle_unknown(png_structrp png_ptr, png_inforp info_ptr,
+           *           error at this point unless it is to be saved.
+           * positive: The chunk was handled, libpng will ignore/discard it.
+           */
+-         if (ret < 0)
++         if (ret < 0) /* handled_error */
+             png_chunk_error(png_ptr, "error in user chunk");
+ 
+          else if (ret == 0)
+@@ -3031,7 +2895,7 @@ png_handle_unknown(png_structrp png_ptr, png_inforp info_ptr,
+ 
+          else /* chunk was handled */
+          {
+-            handled = 1;
++            handled = handled_ok;
+             /* Critical chunks can be safely discarded at this point. */
+             keep = PNG_HANDLE_CHUNK_NEVER;
+          }
+@@ -3116,7 +2980,7 @@ png_handle_unknown(png_structrp png_ptr, png_inforp info_ptr,
+              */
+             png_set_unknown_chunks(png_ptr, info_ptr,
+                 &png_ptr->unknown_chunk, 1);
+-            handled = 1;
++            handled = handled_saved;
+ #  ifdef PNG_USER_LIMITS_SUPPORTED
+             break;
+       }
+@@ -3142,79 +3006,267 @@ png_handle_unknown(png_structrp png_ptr, png_inforp info_ptr,
+ #endif /* !READ_UNKNOWN_CHUNKS */
+ 
+    /* Check for unhandled critical chunks */
+-   if (handled == 0 && PNG_CHUNK_CRITICAL(png_ptr->chunk_name))
++   if (handled < handled_saved && PNG_CHUNK_CRITICAL(png_ptr->chunk_name))
+       png_chunk_error(png_ptr, "unhandled critical chunk");
++
++   return handled;
+ }
+ 
+-/* This function is called to verify that a chunk name is valid.
+- * This function can't have the "critical chunk check" incorporated
+- * into it, since in the future we will need to be able to call user
+- * functions to handle unknown critical chunks after we check that
+- * the chunk name itself is valid.
++/* APNG handling: the minimal implementation of APNG handling in libpng 1.6
++ * requires that those significant applications which already handle APNG not
++ * get hosed.  To do this ensure the code here will have to ensure than APNG
++ * data by default (at least in 1.6) gets stored in the unknown chunk list.
++ * Maybe this can be relaxed in a few years but at present it's just the only
++ * safe way.
++ *
++ * ATM just cause unknown handling for all three chunks:
+  */
++#define png_handle_acTL NULL
++#define png_handle_fcTL NULL
++#define png_handle_fdAT NULL
+ 
+-/* Bit hacking: the test for an invalid byte in the 4 byte chunk name is:
++/*
++ * 1.6.47: This is the new table driven interface to all the chunk handling.
+  *
+- * ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97))
++ * The table describes the PNG standard rules for **reading** known chunks -
++ * every chunk which has an entry in PNG_KNOWN_CHUNKS.  The table contains an
++ * entry for each PNG_INDEX_cHNK describing the rules.
++ *
++ * In this initial version the only information in the entry is the
++ * png_handle_cHNK function for the chunk in question.  When chunk support is
++ * compiled out the entry will be NULL.
+  */
+-
+-void /* PRIVATE */
+-png_check_chunk_name(png_const_structrp png_ptr, png_uint_32 chunk_name)
++static const struct
+ {
+-   int i;
+-   png_uint_32 cn=chunk_name;
+-
+-   png_debug(1, "in png_check_chunk_name");
++   png_handle_result_code (*handler)(
++         png_structrp, png_inforp, png_uint_32 length);
++      /* A chunk-specific 'handler', NULL if the chunk is not supported in this
++       * build.
++       */
+ 
+-   for (i=1; i<=4; ++i)
++   /* Crushing these values helps on modern 32-bit architectures because the
++    * pointer and the following bit fields both end up requiring 32 bits.
++    * Typically this will halve the table size.  On 64-bit architectures the
++    * table entries will typically be 8 bytes.
++    */
++   png_uint_32 max_length :12; /* Length min, max in bytes */
++   png_uint_32 min_length :8;
++      /* Length errors on critical chunks have special handling to preserve the
++       * existing behaviour in libpng 1.6.  Anciallary chunks are checked below
++       * and produce a 'benign' error.
++       */
++   png_uint_32 pos_before :4; /* PNG_HAVE_ values chunk must precede */
++   png_uint_32 pos_after  :4; /* PNG_HAVE_ values chunk must follow */
++      /* NOTE: PLTE, tRNS and bKGD require special handling which depends on
++       * the colour type of the base image.
++       */
++   png_uint_32 multiple   :1; /* Multiple occurences permitted */
++      /* This is enabled for PLTE because PLTE may, in practice, be optional */
++}
++read_chunks[PNG_INDEX_unknown] =
++{
++   /* Definitions as above but done indirectly by #define so that
++    * PNG_KNOWN_CHUNKS can be used safely to build the table in order.
++    *
++    * Each CDcHNK definition lists the values for the parameters **after**
++    * the first, 'handler', function.  'handler' is NULL when the chunk has no
++    * compiled in support.
++    */
++#  define NoCheck 0x801U      /* Do not check the maximum length */
++#  define Limit   0x802U      /* Limit to png_chunk_max bytes */
++#  define LKMin   3U+LZ77Min  /* Minimum length of keyword+LZ77 */
++
++#define hIHDR PNG_HAVE_IHDR
++#define hPLTE PNG_HAVE_PLTE
++#define hIDAT PNG_HAVE_IDAT
++   /* For the two chunks, tRNS and bKGD which can occur in PNGs without a PLTE
++    * but must occur after the PLTE use this and put the check in the handler
++    * routine for colour mapped images were PLTE is required.  Also put a check
++    * in PLTE for other image types to drop the PLTE if tRNS or bKGD have been
++    * seen.
++    */
++#define hCOL  (PNG_HAVE_PLTE|PNG_HAVE_IDAT)
++   /* Used for the decoding chunks which must be before PLTE. */
++#define aIDAT PNG_AFTER_IDAT
++
++   /* Chunks from W3C PNG v3: */
++   /*       cHNK  max_len,   min, before, after, multiple */
++#  define CDIHDR      13U,   13U,  hIHDR,     0,        0
++#  define CDPLTE  NoCheck,    0U,      0, hIHDR,        1
++      /* PLTE errors are only critical for colour-map images, consequently the
++       * hander does all the checks.
++       */
++#  define CDIDAT  NoCheck,    0U,  aIDAT, hIHDR,        1
++#  define CDIEND  NoCheck,    0U,      0, aIDAT,        0
++      /* Historically data was allowed in IEND */
++#  define CDtRNS     256U,    0U,  hIDAT, hIHDR,        0
++#  define CDcHRM      32U,   32U,   hCOL, hIHDR,        0
++#  define CDgAMA       4U,    4U,   hCOL, hIHDR,        0
++#  define CDiCCP  NoCheck, LKMin,   hCOL, hIHDR,        0
++#  define CDsBIT       4U,    1U,   hCOL, hIHDR,        0
++#  define CDsRGB       1U,    1U,   hCOL, hIHDR,        0
++#  define CDcICP       4U,    4U,   hCOL, hIHDR,        0
++#  define CDmDCV      24U,   24U,   hCOL, hIHDR,        0
++#  define CDeXIf    Limit,    4U,      0, hIHDR,        0
++#  define CDcLLI       8U,    8U,   hCOL, hIHDR,        0
++#  define CDtEXt  NoCheck,    2U,      0, hIHDR,        1
++      /* Allocates 'length+1'; checked in the handler */
++#  define CDzTXt    Limit, LKMin,      0, hIHDR,        1
++#  define CDiTXt  NoCheck,    6U,      0, hIHDR,        1
++      /* Allocates 'length+1'; checked in the handler */
++#  define CDbKGD       6U,    1U,  hIDAT, hIHDR,        0
++#  define CDhIST    1024U,    0U,  hPLTE, hIHDR,        0
++#  define CDpHYs       9U,    9U,  hIDAT, hIHDR,        0
++#  define CDsPLT  NoCheck,    3U,  hIDAT, hIHDR,        1
++      /* Allocates 'length+1'; checked in the handler */
++#  define CDtIME       7U,    7U,      0, hIHDR,        0
++#  define CDacTL       8U,    8U,  hIDAT, hIHDR,        0
++#  define CDfcTL      25U,   26U,      0, hIHDR,        1
++#  define CDfdAT    Limit,    4U,  hIDAT, hIHDR,        1
++   /* Supported chunks from PNG extensions 1.5.0, NYI so limit */
++#  define CDoFFs       9U,    9U,  hIDAT, hIHDR,        0
++#  define CDpCAL  NoCheck,   14U,  hIDAT, hIHDR,        0
++      /* Allocates 'length+1'; checked in the handler */
++#  define CDsCAL    Limit,    4U,  hIDAT, hIHDR,        0
++      /* Allocates 'length+1'; checked in the handler */
++
++#  define PNG_CHUNK(cHNK, index) { png_handle_ ## cHNK, CD ## cHNK },
++   PNG_KNOWN_CHUNKS
++#  undef PNG_CHUNK
++};
++
++
++static png_index
++png_chunk_index_from_name(png_uint_32 chunk_name)
++{
++   /* For chunk png_cHNK return PNG_INDEX_cHNK.  Return PNG_INDEX_unknown if
++    * chunk_name is not known.  Notice that in a particular build "known" does
++    * not necessarily mean "supported", although the inverse applies.
++    */
++   switch (chunk_name)
+    {
+-      int c = cn & 0xff;
++#     define PNG_CHUNK(cHNK, index)\
++         case png_ ## cHNK: return PNG_INDEX_ ## cHNK; /* == index */
++
++      PNG_KNOWN_CHUNKS
+ 
+-      if (c < 65 || c > 122 || (c > 90 && c < 97))
+-         png_chunk_error(png_ptr, "invalid chunk type");
++#     undef PNG_CHUNK
+ 
+-      cn >>= 8;
++      default: return PNG_INDEX_unknown;
+    }
+ }
+ 
+-void /* PRIVATE */
+-png_check_chunk_length(png_const_structrp png_ptr, png_uint_32 length)
++png_handle_result_code /*PRIVATE*/
++png_handle_chunk(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+ {
+-   png_alloc_size_t limit = PNG_UINT_31_MAX;
+-
+-# ifdef PNG_SET_USER_LIMITS_SUPPORTED
+-   if (png_ptr->user_chunk_malloc_max > 0 &&
+-       png_ptr->user_chunk_malloc_max < limit)
+-      limit = png_ptr->user_chunk_malloc_max;
+-# elif PNG_USER_CHUNK_MALLOC_MAX > 0
+-   if (PNG_USER_CHUNK_MALLOC_MAX < limit)
+-      limit = PNG_USER_CHUNK_MALLOC_MAX;
+-# endif
+-   if (png_ptr->chunk_name == png_IDAT)
++   /* CSE: these things don't change, these autos are just to save typing and
++    * make the code more clear.
++    */
++   const png_uint_32 chunk_name = png_ptr->chunk_name;
++   const png_index chunk_index = png_chunk_index_from_name(chunk_name);
++
++   png_handle_result_code handled = handled_error;
++   png_const_charp errmsg = NULL;
++
++   /* Is this a known chunk?  If not there are no checks performed here;
++    * png_handle_unknown does the correct checks.  This means that the values
++    * for known but unsupported chunks in the above table are not used here
++    * however the chunks_seen fields in png_struct are still set.
++    */
++   if (chunk_index == PNG_INDEX_unknown ||
++       read_chunks[chunk_index].handler == NULL)
+    {
+-      png_alloc_size_t idat_limit = PNG_UINT_31_MAX;
+-      size_t row_factor =
+-         (size_t)png_ptr->width
+-         * (size_t)png_ptr->channels
+-         * (png_ptr->bit_depth > 8? 2: 1)
+-         + 1
+-         + (png_ptr->interlaced? 6: 0);
+-      if (png_ptr->height > PNG_UINT_32_MAX/row_factor)
+-         idat_limit = PNG_UINT_31_MAX;
+-      else
+-         idat_limit = png_ptr->height * row_factor;
+-      row_factor = row_factor > 32566? 32566 : row_factor;
+-      idat_limit += 6 + 5*(idat_limit/row_factor+1); /* zlib+deflate overhead */
+-      idat_limit=idat_limit < PNG_UINT_31_MAX? idat_limit : PNG_UINT_31_MAX;
+-      limit = limit < idat_limit? idat_limit : limit;
++      handled = png_handle_unknown(
++            png_ptr, info_ptr, length, PNG_HANDLE_CHUNK_AS_DEFAULT);
++   }
++
++   /* First check the position.   The first check is historical; the stream must
++    * start with IHDR and anything else causes libpng to give up immediately.
++    */
++   else if (chunk_index != PNG_INDEX_IHDR &&
++            (png_ptr->mode & PNG_HAVE_IHDR) == 0)
++      png_chunk_error(png_ptr, "missing IHDR"); /* NORETURN */
++
++   /* Before all the pos_before chunks, after all the pos_after chunks. */
++   else if (((png_ptr->mode & read_chunks[chunk_index].pos_before) != 0) ||
++            ((png_ptr->mode & read_chunks[chunk_index].pos_after) !=
++             read_chunks[chunk_index].pos_after))
++   {
++      errmsg = "out of place";
++   }
++
++   /* Now check for duplicates: duplicated critical chunks also produce a
++    * full error.
++    */
++   else if (read_chunks[chunk_index].multiple == 0 &&
++            png_file_has_chunk(png_ptr, chunk_index))
++   {
++      errmsg = "duplicate";
++   }
++
++   else if (length < read_chunks[chunk_index].min_length)
++      errmsg = "too short";
++   else
++   {
++      /* NOTE: apart from IHDR the critical chunks (PLTE, IDAT and IEND) are set
++       * up above not to do any length checks.
++       *
++       * The png_chunk_max check ensures that the variable length chunks are
++       * always checked at this point for being within the system allocation
++       * limits.
++       */
++      unsigned max_length = read_chunks[chunk_index].max_length;
++
++      switch (max_length)
++      {
++         case Limit:
++            /* png_read_chunk_header has already png_error'ed chunks with a
++             * length exceeding the 31-bit PNG limit, so just check the memory
++             * limit:
++             */
++            if (length <= png_chunk_max(png_ptr))
++               goto MeetsLimit;
++
++            errmsg = "length exceeds libpng limit";
++            break;
++
++         default:
++            if (length <= max_length)
++               goto MeetsLimit;
++
++            errmsg = "too long";
++            break;
++
++         case NoCheck:
++         MeetsLimit:
++            handled = read_chunks[chunk_index].handler(
++                  png_ptr, info_ptr, length);
++            break;
++      }
++   }
++
++   /* If there was an error or the chunk was simply skipped it is not counted as
++    * 'seen'.
++    */
++   if (errmsg != NULL)
++   {
++      if (PNG_CHUNK_CRITICAL(chunk_name)) /* stop immediately */
++         png_chunk_error(png_ptr, errmsg);
++      else /* ancillary chunk */
++      {
++         /* The chunk data is skipped: */
++         png_crc_finish(png_ptr, length);
++         png_chunk_benign_error(png_ptr, errmsg);
++      }
+    }
+ 
+-   if (length > limit)
++   else if (handled >= handled_saved)
+    {
+-      png_debug2(0," length = %lu, limit = %lu",
+-         (unsigned long)length,(unsigned long)limit);
+-      png_benign_error(png_ptr, "chunk data is too large");
++      if (chunk_index != PNG_INDEX_unknown)
++         png_file_add_chunk(png_ptr, chunk_index);
+    }
++
++   return handled;
+ }
+ 
+ /* Combines the row recently read in with the existing pixels in the row.  This
+@@ -3712,10 +3764,6 @@ void /* PRIVATE */
+ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass,
+     png_uint_32 transformations /* Because these may affect the byte layout */)
+ {
+-   /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
+-   /* Offset to next interlace block */
+-   static const unsigned int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
+-
+    png_debug(1, "in png_do_read_interlace");
+    if (row != NULL && row_info != NULL)
+    {
+@@ -4208,6 +4256,9 @@ png_read_IDAT_data(png_structrp png_ptr, png_bytep output,
+ 
+          avail_in = png_ptr->IDAT_read_size;
+ 
++         if (avail_in > png_chunk_max(png_ptr))
++            avail_in = (uInt)/*SAFE*/png_chunk_max(png_ptr);
++
+          if (avail_in > png_ptr->idat_size)
+             avail_in = (uInt)png_ptr->idat_size;
+ 
+@@ -4215,8 +4266,13 @@ png_read_IDAT_data(png_structrp png_ptr, png_bytep output,
+           * to minimize memory usage by causing lots of re-allocs, but
+           * realistically doing IDAT_read_size re-allocs is not likely to be a
+           * big problem.
++          *
++          * An error here corresponds to the system being out of memory.
+           */
+-         buffer = png_read_buffer(png_ptr, avail_in, 0/*error*/);
++         buffer = png_read_buffer(png_ptr, avail_in);
++
++         if (buffer == NULL)
++            png_chunk_error(png_ptr, "out of memory");
+ 
+          png_crc_read(png_ptr, buffer, avail_in);
+          png_ptr->idat_size -= avail_in;
+@@ -4353,20 +4409,6 @@ png_read_finish_IDAT(png_structrp png_ptr)
+ void /* PRIVATE */
+ png_read_finish_row(png_structrp png_ptr)
+ {
+-   /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
+-
+-   /* Start of interlace block */
+-   static const png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
+-
+-   /* Offset to next interlace block */
+-   static const png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
+-
+-   /* Start of interlace block in the y direction */
+-   static const png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
+-
+-   /* Offset to next interlace block in the y direction */
+-   static const png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
+-
+    png_debug(1, "in png_read_finish_row");
+    png_ptr->row_number++;
+    if (png_ptr->row_number < png_ptr->num_rows)
+@@ -4418,20 +4460,6 @@ png_read_finish_row(png_structrp png_ptr)
+ void /* PRIVATE */
+ png_read_start_row(png_structrp png_ptr)
+ {
+-   /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
+-
+-   /* Start of interlace block */
+-   static const png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
+-
+-   /* Offset to next interlace block */
+-   static const png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
+-
+-   /* Start of interlace block in the y direction */
+-   static const png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
+-
+-   /* Offset to next interlace block in the y direction */
+-   static const png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
+-
+    unsigned int max_pixel_depth;
+    size_t row_bytes;
+ 
+diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngset.c b/src/java.desktop/share/native/libsplashscreen/libpng/pngset.c
+index f53ab6fa1..1bfd292bd 100644
+--- a/src/java.desktop/share/native/libsplashscreen/libpng/pngset.c
++++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngset.c
+@@ -29,7 +29,7 @@
+  * However, the following notice accompanied the original version of this
+  * file and, per its terms, should not be removed:
+  *
+- * Copyright (c) 2018-2024 Cosmin Truta
++ * Copyright (c) 2018-2025 Cosmin Truta
+  * Copyright (c) 1998-2018 Glenn Randers-Pehrson
+  * Copyright (c) 1996-1997 Andreas Dilger
+  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
+@@ -70,27 +70,21 @@ png_set_cHRM_fixed(png_const_structrp png_ptr, png_inforp info_ptr,
+     png_fixed_point red_y, png_fixed_point green_x, png_fixed_point green_y,
+     png_fixed_point blue_x, png_fixed_point blue_y)
+ {
+-   png_xy xy;
+-
+    png_debug1(1, "in %s storage function", "cHRM fixed");
+ 
+    if (png_ptr == NULL || info_ptr == NULL)
+       return;
+ 
+-   xy.redx = red_x;
+-   xy.redy = red_y;
+-   xy.greenx = green_x;
+-   xy.greeny = green_y;
+-   xy.bluex = blue_x;
+-   xy.bluey = blue_y;
+-   xy.whitex = white_x;
+-   xy.whitey = white_y;
+-
+-   if (png_colorspace_set_chromaticities(png_ptr, &info_ptr->colorspace, &xy,
+-       2/* override with app values*/) != 0)
+-      info_ptr->colorspace.flags |= PNG_COLORSPACE_FROM_cHRM;
++   info_ptr->cHRM.redx = red_x;
++   info_ptr->cHRM.redy = red_y;
++   info_ptr->cHRM.greenx = green_x;
++   info_ptr->cHRM.greeny = green_y;
++   info_ptr->cHRM.bluex = blue_x;
++   info_ptr->cHRM.bluey = blue_y;
++   info_ptr->cHRM.whitex = white_x;
++   info_ptr->cHRM.whitey = white_y;
+ 
+-   png_colorspace_sync_info(png_ptr, info_ptr);
++   info_ptr->valid |= PNG_INFO_cHRM;
+ }
+ 
+ void PNGFAPI
+@@ -102,6 +96,7 @@ png_set_cHRM_XYZ_fixed(png_const_structrp png_ptr, png_inforp info_ptr,
+     png_fixed_point int_blue_Z)
+ {
+    png_XYZ XYZ;
++   png_xy xy;
+ 
+    png_debug1(1, "in %s storage function", "cHRM XYZ fixed");
+ 
+@@ -118,11 +113,14 @@ png_set_cHRM_XYZ_fixed(png_const_structrp png_ptr, png_inforp info_ptr,
+    XYZ.blue_Y = int_blue_Y;
+    XYZ.blue_Z = int_blue_Z;
+ 
+-   if (png_colorspace_set_endpoints(png_ptr, &info_ptr->colorspace,
+-       &XYZ, 2) != 0)
+-      info_ptr->colorspace.flags |= PNG_COLORSPACE_FROM_cHRM;
++   if (png_xy_from_XYZ(&xy, &XYZ) == 0)
++   {
++      info_ptr->cHRM = xy;
++      info_ptr->valid |= PNG_INFO_cHRM;
++   }
+ 
+-   png_colorspace_sync_info(png_ptr, info_ptr);
++   else
++      png_app_error(png_ptr, "invalid cHRM XYZ");
+ }
+ 
+ #  ifdef PNG_FLOATING_POINT_SUPPORTED
+@@ -162,6 +160,192 @@ png_set_cHRM_XYZ(png_const_structrp png_ptr, png_inforp info_ptr, double red_X,
+ 
+ #endif /* cHRM */
+ 
++#ifdef PNG_cICP_SUPPORTED
++void PNGAPI
++png_set_cICP(png_const_structrp png_ptr, png_inforp info_ptr,
++             png_byte colour_primaries, png_byte transfer_function,
++             png_byte matrix_coefficients, png_byte video_full_range_flag)
++{
++   png_debug1(1, "in %s storage function", "cICP");
++
++   if (png_ptr == NULL || info_ptr == NULL)
++      return;
++
++   info_ptr->cicp_colour_primaries = colour_primaries;
++   info_ptr->cicp_transfer_function = transfer_function;
++   info_ptr->cicp_matrix_coefficients = matrix_coefficients;
++   info_ptr->cicp_video_full_range_flag = video_full_range_flag;
++
++   if (info_ptr->cicp_matrix_coefficients != 0)
++   {
++      png_warning(png_ptr, "Invalid cICP matrix coefficients");
++      return;
++   }
++
++   info_ptr->valid |= PNG_INFO_cICP;
++}
++#endif /* cICP */
++
++#ifdef PNG_cLLI_SUPPORTED
++void PNGFAPI
++png_set_cLLI_fixed(png_const_structrp png_ptr, png_inforp info_ptr,
++    /* The values below are in cd/m2 (nits) and are scaled by 10,000; not
++     * 100,000 as in the case of png_fixed_point.
++     */
++    png_uint_32 maxCLL, png_uint_32 maxFALL)
++{
++   png_debug1(1, "in %s storage function", "cLLI");
++
++   if (png_ptr == NULL || info_ptr == NULL)
++      return;
++
++   /* Check the light level range: */
++   if (maxCLL > 0x7FFFFFFFU || maxFALL > 0x7FFFFFFFU)
++   {
++      /* The limit is 200kcd/m2; somewhat bright but not inconceivable because
++       * human vision is said to run up to 100Mcd/m2.  The sun is about 2Gcd/m2.
++       *
++       * The reference sRGB monitor is 80cd/m2 and the limit of PQ encoding is
++       * 2kcd/m2.
++       */
++      png_chunk_report(png_ptr, "cLLI light level exceeds PNG limit",
++            PNG_CHUNK_WRITE_ERROR);
++      return;
++   }
++
++   info_ptr->maxCLL = maxCLL;
++   info_ptr->maxFALL = maxFALL;
++   info_ptr->valid |= PNG_INFO_cLLI;
++}
++
++#  ifdef PNG_FLOATING_POINT_SUPPORTED
++void PNGAPI
++png_set_cLLI(png_const_structrp png_ptr, png_inforp info_ptr,
++   double maxCLL, double maxFALL)
++{
++   png_set_cLLI_fixed(png_ptr, info_ptr,
++       png_fixed_ITU(png_ptr, maxCLL, "png_set_cLLI(maxCLL)"),
++       png_fixed_ITU(png_ptr, maxFALL, "png_set_cLLI(maxFALL)"));
++}
++#  endif /* FLOATING_POINT */
++#endif /* cLLI */
++
++#ifdef PNG_mDCV_SUPPORTED
++static png_uint_16
++png_ITU_fixed_16(int *error, png_fixed_point v)
++{
++   /* Return a safe uint16_t value scaled according to the ITU H273 rules for
++    * 16-bit display chromaticities.  Functions like the corresponding
++    * png_fixed() internal function with regard to errors: it's an error on
++    * write, a chunk_benign_error on read: See the definition of
++    * png_chunk_report in pngpriv.h.
++    */
++   v /= 2; /* rounds to 0 in C: avoids insignificant arithmetic errors */
++   if (v > 65535 || v < 0)
++   {
++      *error = 1;
++      return 0;
++   }
++
++   return (png_uint_16)/*SAFE*/v;
++}
++
++void PNGAPI
++png_set_mDCV_fixed(png_const_structrp png_ptr, png_inforp info_ptr,
++    png_fixed_point white_x, png_fixed_point white_y,
++    png_fixed_point red_x, png_fixed_point red_y,
++    png_fixed_point green_x, png_fixed_point green_y,
++    png_fixed_point blue_x, png_fixed_point blue_y,
++    png_uint_32 maxDL,
++    png_uint_32 minDL)
++{
++   png_uint_16 rx, ry, gx, gy, bx, by, wx, wy;
++   int error;
++
++   png_debug1(1, "in %s storage function", "mDCV");
++
++   if (png_ptr == NULL || info_ptr == NULL)
++      return;
++
++   /* Check the input values to ensure they are in the expected range: */
++   error = 0;
++   rx = png_ITU_fixed_16(&error, red_x);
++   ry = png_ITU_fixed_16(&error, red_y);
++   gx = png_ITU_fixed_16(&error, green_x);
++   gy = png_ITU_fixed_16(&error, green_y);
++   bx = png_ITU_fixed_16(&error, blue_x);
++   by = png_ITU_fixed_16(&error, blue_y);
++   wx = png_ITU_fixed_16(&error, white_x);
++   wy = png_ITU_fixed_16(&error, white_y);
++
++   if (error)
++   {
++      png_chunk_report(png_ptr,
++         "mDCV chromaticities outside representable range",
++         PNG_CHUNK_WRITE_ERROR);
++      return;
++   }
++
++   /* Check the light level range: */
++   if (maxDL > 0x7FFFFFFFU || minDL > 0x7FFFFFFFU)
++   {
++      /* The limit is 200kcd/m2; somewhat bright but not inconceivable because
++       * human vision is said to run up to 100Mcd/m2.  The sun is about 2Gcd/m2.
++       *
++       * The reference sRGB monitor is 80cd/m2 and the limit of PQ encoding is
++       * 2kcd/m2.
++       */
++      png_chunk_report(png_ptr, "mDCV display light level exceeds PNG limit",
++            PNG_CHUNK_WRITE_ERROR);
++      return;
++   }
++
++   /* All values are safe, the settings are accepted.
++    *
++    * IMPLEMENTATION NOTE: in practice the values can be checked and assigned
++    * but the result is confusing if a writing app calls png_set_mDCV more than
++    * once, the second time with an invalid value.  This approach is more
++    * obviously correct at the cost of typing and a very slight machine
++    * overhead.
++    */
++   info_ptr->mastering_red_x = rx;
++   info_ptr->mastering_red_y = ry;
++   info_ptr->mastering_green_x = gx;
++   info_ptr->mastering_green_y = gy;
++   info_ptr->mastering_blue_x = bx;
++   info_ptr->mastering_blue_y = by;
++   info_ptr->mastering_white_x = wx;
++   info_ptr->mastering_white_y = wy;
++   info_ptr->mastering_maxDL = maxDL;
++   info_ptr->mastering_minDL = minDL;
++   info_ptr->valid |= PNG_INFO_mDCV;
++}
++
++#  ifdef PNG_FLOATING_POINT_SUPPORTED
++void PNGAPI
++png_set_mDCV(png_const_structrp png_ptr, png_inforp info_ptr,
++    double white_x, double white_y, double red_x, double red_y, double green_x,
++    double green_y, double blue_x, double blue_y,
++    double maxDL, double minDL)
++{
++   png_set_mDCV_fixed(png_ptr, info_ptr,
++      /* The ITU approach is to scale by 50,000, not 100,000 so just divide
++       * the input values by 2 and use png_fixed:
++       */
++      png_fixed(png_ptr, white_x / 2, "png_set_mDCV(white(x))"),
++      png_fixed(png_ptr, white_y / 2, "png_set_mDCV(white(y))"),
++      png_fixed(png_ptr, red_x / 2, "png_set_mDCV(red(x))"),
++      png_fixed(png_ptr, red_y / 2, "png_set_mDCV(red(y))"),
++      png_fixed(png_ptr, green_x / 2, "png_set_mDCV(green(x))"),
++      png_fixed(png_ptr, green_y / 2, "png_set_mDCV(green(y))"),
++      png_fixed(png_ptr, blue_x / 2, "png_set_mDCV(blue(x))"),
++      png_fixed(png_ptr, blue_y / 2, "png_set_mDCV(blue(y))"),
++      png_fixed_ITU(png_ptr, maxDL, "png_set_mDCV(maxDL)"),
++      png_fixed_ITU(png_ptr, minDL, "png_set_mDCV(minDL)"));
++}
++#  endif /* FLOATING_POINT */
++#endif /* mDCV */
++
+ #ifdef PNG_eXIf_SUPPORTED
+ void PNGAPI
+ png_set_eXIf(png_const_structrp png_ptr, png_inforp info_ptr,
+@@ -213,8 +397,8 @@ png_set_gAMA_fixed(png_const_structrp png_ptr, png_inforp info_ptr,
+    if (png_ptr == NULL || info_ptr == NULL)
+       return;
+ 
+-   png_colorspace_set_gamma(png_ptr, &info_ptr->colorspace, file_gamma);
+-   png_colorspace_sync_info(png_ptr, info_ptr);
++   info_ptr->gamma = file_gamma;
++   info_ptr->valid |= PNG_INFO_gAMA;
+ }
+ 
+ #  ifdef PNG_FLOATING_POINT_SUPPORTED
+@@ -673,8 +857,8 @@ png_set_sRGB(png_const_structrp png_ptr, png_inforp info_ptr, int srgb_intent)
+    if (png_ptr == NULL || info_ptr == NULL)
+       return;
+ 
+-   (void)png_colorspace_set_sRGB(png_ptr, &info_ptr->colorspace, srgb_intent);
+-   png_colorspace_sync_info(png_ptr, info_ptr);
++   info_ptr->rendering_intent = srgb_intent;
++   info_ptr->valid |= PNG_INFO_sRGB;
+ }
+ 
+ void PNGAPI
+@@ -686,15 +870,20 @@ png_set_sRGB_gAMA_and_cHRM(png_const_structrp png_ptr, png_inforp info_ptr,
+    if (png_ptr == NULL || info_ptr == NULL)
+       return;
+ 
+-   if (png_colorspace_set_sRGB(png_ptr, &info_ptr->colorspace,
+-       srgb_intent) != 0)
+-   {
+-      /* This causes the gAMA and cHRM to be written too */
+-      info_ptr->colorspace.flags |=
+-         PNG_COLORSPACE_FROM_gAMA|PNG_COLORSPACE_FROM_cHRM;
+-   }
++   png_set_sRGB(png_ptr, info_ptr, srgb_intent);
++
++#  ifdef PNG_gAMA_SUPPORTED
++      png_set_gAMA_fixed(png_ptr, info_ptr, PNG_GAMMA_sRGB_INVERSE);
++#  endif /* gAMA */
+ 
+-   png_colorspace_sync_info(png_ptr, info_ptr);
++#  ifdef PNG_cHRM_SUPPORTED
++      png_set_cHRM_fixed(png_ptr, info_ptr,
++         /* color      x       y */
++         /* white */ 31270, 32900,
++         /* red   */ 64000, 33000,
++         /* green */ 30000, 60000,
++         /* blue  */ 15000,  6000);
++#  endif /* cHRM */
+ }
+ #endif /* sRGB */
+ 
+@@ -717,27 +906,6 @@ png_set_iCCP(png_const_structrp png_ptr, png_inforp info_ptr,
+    if (compression_type != PNG_COMPRESSION_TYPE_BASE)
+       png_app_error(png_ptr, "Invalid iCCP compression method");
+ 
+-   /* Set the colorspace first because this validates the profile; do not
+-    * override previously set app cHRM or gAMA here (because likely as not the
+-    * application knows better than libpng what the correct values are.)  Pass
+-    * the info_ptr color_type field to png_colorspace_set_ICC because in the
+-    * write case it has not yet been stored in png_ptr.
+-    */
+-   {
+-      int result = png_colorspace_set_ICC(png_ptr, &info_ptr->colorspace, name,
+-          proflen, profile, info_ptr->color_type);
+-
+-      png_colorspace_sync_info(png_ptr, info_ptr);
+-
+-      /* Don't do any of the copying if the profile was bad, or inconsistent. */
+-      if (result == 0)
+-         return;
+-
+-      /* But do write the gAMA and cHRM chunks from the profile. */
+-      info_ptr->colorspace.flags |=
+-         PNG_COLORSPACE_FROM_gAMA|PNG_COLORSPACE_FROM_cHRM;
+-   }
+-
+    length = strlen(name)+1;
+    new_iccp_name = png_voidcast(png_charp, png_malloc_warn(png_ptr, length));
+ 
+@@ -1423,11 +1591,14 @@ png_set_keep_unknown_chunks(png_structrp png_ptr, int keep,
+       static const png_byte chunks_to_ignore[] = {
+          98,  75,  71,  68, '\0',  /* bKGD */
+          99,  72,  82,  77, '\0',  /* cHRM */
++         99,  73,  67,  80, '\0',  /* cICP */
++         99,  76,  76,  73, '\0',  /* cLLI */
+         101,  88,  73, 102, '\0',  /* eXIf */
+         103,  65,  77,  65, '\0',  /* gAMA */
+         104,  73,  83,  84, '\0',  /* hIST */
+         105,  67,  67,  80, '\0',  /* iCCP */
+         105,  84,  88, 116, '\0',  /* iTXt */
++        109,  68,  67,  86, '\0',  /* mDCV */
+         111,  70,  70, 115, '\0',  /* oFFs */
+         112,  67,  65,  76, '\0',  /* pCAL */
+         112,  72,  89, 115, '\0',  /* pHYs */
+@@ -1689,8 +1860,24 @@ png_set_chunk_malloc_max(png_structrp png_ptr,
+ {
+    png_debug(1, "in png_set_chunk_malloc_max");
+ 
++   /* pngstruct::user_chunk_malloc_max is initialized to a non-zero value in
++    * png.c.  This API supports '0' for unlimited, make sure the correct
++    * (unlimited) value is set here to avoid a need to check for 0 everywhere
++    * the parameter is used.
++    */
+    if (png_ptr != NULL)
+-      png_ptr->user_chunk_malloc_max = user_chunk_malloc_max;
++   {
++      if (user_chunk_malloc_max == 0U) /* unlimited */
++      {
++#        ifdef PNG_MAX_MALLOC_64K
++            png_ptr->user_chunk_malloc_max = 65536U;
++#        else
++            png_ptr->user_chunk_malloc_max = PNG_SIZE_MAX;
++#        endif
++      }
++      else
++         png_ptr->user_chunk_malloc_max = user_chunk_malloc_max;
++   }
+ }
+ #endif /* ?SET_USER_LIMITS */
+ 
+diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngstruct.h b/src/java.desktop/share/native/libsplashscreen/libpng/pngstruct.h
+index f153bdec6..d6c446564 100644
+--- a/src/java.desktop/share/native/libsplashscreen/libpng/pngstruct.h
++++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngstruct.h
+@@ -98,13 +98,7 @@ typedef struct png_compression_buffer
+ 
+ /* Colorspace support; structures used in png_struct, png_info and in internal
+  * functions to hold and communicate information about the color space.
+- *
+- * PNG_COLORSPACE_SUPPORTED is only required if the application will perform
+- * colorspace corrections, otherwise all the colorspace information can be
+- * skipped and the size of libpng can be reduced (significantly) by compiling
+- * out the colorspace support.
+  */
+-#ifdef PNG_COLORSPACE_SUPPORTED
+ /* The chromaticities of the red, green and blue colorants and the chromaticity
+  * of the corresponding white point (i.e. of rgb(1.0,1.0,1.0)).
+  */
+@@ -125,48 +119,36 @@ typedef struct png_XYZ
+    png_fixed_point green_X, green_Y, green_Z;
+    png_fixed_point blue_X, blue_Y, blue_Z;
+ } png_XYZ;
+-#endif /* COLORSPACE */
+ 
+-#if defined(PNG_COLORSPACE_SUPPORTED) || defined(PNG_GAMMA_SUPPORTED)
+-/* A colorspace is all the above plus, potentially, profile information;
+- * however at present libpng does not use the profile internally so it is only
+- * stored in the png_info struct (if iCCP is supported.)  The rendering intent
+- * is retained here and is checked.
+- *
+- * The file gamma encoding information is also stored here and gamma correction
+- * is done by libpng, whereas color correction must currently be done by the
+- * application.
++/* Chunk index values as an enum, PNG_INDEX_unknown is also a count of the
++ * number of chunks.
+  */
+-typedef struct png_colorspace
++#define PNG_CHUNK(cHNK, i) PNG_INDEX_ ## cHNK = (i),
++typedef enum
+ {
+-#ifdef PNG_GAMMA_SUPPORTED
+-   png_fixed_point gamma;        /* File gamma */
+-#endif
++   PNG_KNOWN_CHUNKS
++   PNG_INDEX_unknown
++} png_index;
++#undef PNG_CHUNK
+ 
+-#ifdef PNG_COLORSPACE_SUPPORTED
+-   png_xy      end_points_xy;    /* End points as chromaticities */
+-   png_XYZ     end_points_XYZ;   /* End points as CIE XYZ colorant values */
+-   png_uint_16 rendering_intent; /* Rendering intent of a profile */
+-#endif
+-
+-   /* Flags are always defined to simplify the code. */
+-   png_uint_16 flags;            /* As defined below */
+-} png_colorspace, * PNG_RESTRICT png_colorspacerp;
++/* Chunk flag values.  These are (png_uint_32 values) with exactly one bit set
++ * and can be combined into a flag set with bitwise 'or'.
++ *
++ * TODO: C23: convert these macros to C23 inlines (which are static).
++ */
++#define png_chunk_flag_from_index(i) (0x80000000U >> (31 - (i)))
++   /* The flag coresponding to the given png_index enum value.  This is defined
++    * for png_unknown as well (until it reaches the value 32) but this should
++    * not be relied on.
++    */
+ 
+-typedef const png_colorspace * PNG_RESTRICT png_const_colorspacerp;
++#define png_file_has_chunk(png_ptr, i)\
++   (((png_ptr)->chunks & png_chunk_flag_from_index(i)) != 0)
++   /* The chunk has been recorded in png_struct */
+ 
+-/* General flags for the 'flags' field */
+-#define PNG_COLORSPACE_HAVE_GAMMA           0x0001
+-#define PNG_COLORSPACE_HAVE_ENDPOINTS       0x0002
+-#define PNG_COLORSPACE_HAVE_INTENT          0x0004
+-#define PNG_COLORSPACE_FROM_gAMA            0x0008
+-#define PNG_COLORSPACE_FROM_cHRM            0x0010
+-#define PNG_COLORSPACE_FROM_sRGB            0x0020
+-#define PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB 0x0040
+-#define PNG_COLORSPACE_MATCHES_sRGB         0x0080 /* exact match on profile */
+-#define PNG_COLORSPACE_INVALID              0x8000
+-#define PNG_COLORSPACE_CANCEL(flags)        (0xffff ^ (flags))
+-#endif /* COLORSPACE || GAMMA */
++#define png_file_add_chunk(pnt_ptr, i)\
++   ((void)((png_ptr)->chunks |= png_chunk_flag_from_index(i)))
++   /* Record the chunk in the png_struct */
+ 
+ struct png_struct_def
+ {
+@@ -238,6 +220,11 @@ struct png_struct_def
+    int zlib_set_strategy;
+ #endif
+ 
++   png_uint_32 chunks; /* PNG_CF_ for every chunk read or (NYI) written */
++#  define png_has_chunk(png_ptr, cHNK)\
++      png_file_has_chunk(png_ptr, PNG_INDEX_ ## cHNK)
++      /* Convenience accessor - use this to check for a known chunk by name */
++
+    png_uint_32 width;         /* width of image in pixels */
+    png_uint_32 height;        /* height of image in pixels */
+    png_uint_32 num_rows;      /* number of rows in current pass */
+@@ -314,9 +301,16 @@ struct png_struct_def
+    png_uint_32 flush_rows;    /* number of rows written since last flush */
+ #endif
+ 
++#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
++   png_xy          chromaticities; /* From mDVC, cICP, [iCCP], sRGB or cHRM */
++#endif
++
+ #ifdef PNG_READ_GAMMA_SUPPORTED
+    int gamma_shift;      /* number of "insignificant" bits in 16-bit gamma */
+-   png_fixed_point screen_gamma; /* screen gamma value (display_exponent) */
++   png_fixed_point screen_gamma; /* screen gamma value (display exponent) */
++   png_fixed_point file_gamma;   /* file gamma value (encoding exponent) */
++   png_fixed_point chunk_gamma;  /* from cICP, iCCP, sRGB or gAMA */
++   png_fixed_point default_gamma;/* from png_set_alpha_mode */
+ 
+    png_bytep gamma_table;     /* gamma table for 8-bit depth files */
+    png_uint_16pp gamma_16_table; /* gamma table for 16-bit depth files */
+@@ -328,7 +322,7 @@ struct png_struct_def
+    png_uint_16pp gamma_16_from_1; /* converts from 1.0 to screen */
+    png_uint_16pp gamma_16_to_1; /* converts from file to 1.0 */
+ #endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */
+-#endif
++#endif /* READ_GAMMA */
+ 
+ #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_sBIT_SUPPORTED)
+    png_color_8 sig_bit;       /* significant bits in each available channel */
+@@ -378,8 +372,8 @@ struct png_struct_def
+ /* To do: remove this from libpng-1.7 */
+ #ifdef PNG_TIME_RFC1123_SUPPORTED
+    char time_buffer[29]; /* String to hold RFC 1123 time text */
+-#endif
+-#endif
++#endif /* TIME_RFC1123 */
++#endif /* LIBPNG_VER < 10700 */
+ 
+ /* New members added in libpng-1.0.6 */
+ 
+@@ -389,8 +383,8 @@ struct png_struct_def
+    png_voidp user_chunk_ptr;
+ #ifdef PNG_READ_USER_CHUNKS_SUPPORTED
+    png_user_chunk_ptr read_user_chunk_fn; /* user read chunk handler */
+-#endif
+-#endif
++#endif /* READ_USER_CHUNKS */
++#endif /* USER_CHUNKS */
+ 
+ #ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
+    int          unknown_default; /* As PNG_HANDLE_* */
+@@ -497,11 +491,5 @@ struct png_struct_def
+ /* New member added in libpng-1.5.7 */
+    void (*read_filter[PNG_FILTER_VALUE_LAST-1])(png_row_infop row_info,
+       png_bytep row, png_const_bytep prev_row);
+-
+-#ifdef PNG_READ_SUPPORTED
+-#if defined(PNG_COLORSPACE_SUPPORTED) || defined(PNG_GAMMA_SUPPORTED)
+-   png_colorspace   colorspace;
+-#endif
+-#endif
+ };
+ #endif /* PNGSTRUCT_H */
+diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/awt_InputMethod.c b/src/java.desktop/unix/native/libawt_xawt/awt/awt_InputMethod.c
+index f2ac63f3a..307b4c8be 100644
+--- a/src/java.desktop/unix/native/libawt_xawt/awt/awt_InputMethod.c
++++ b/src/java.desktop/unix/native/libawt_xawt/awt/awt_InputMethod.c
+@@ -1627,14 +1627,14 @@ JNIEXPORT jboolean JNICALL Java_sun_awt_X11InputMethodBase_setCompositionEnabled
+     if (NULL != pX11IMData->statusWindow) {
+         Window focus = 0;
+         int revert_to;
+-#if defined(_LP64) && !defined(_LITTLE_ENDIAN)
+-        // The Window value which is used for XGetICValues must be 32bit on BigEndian XOrg's xlib
+-        unsigned int w = 0;
+-#else
+         Window w = 0;
+-#endif
+         XGetInputFocus(awt_display, &focus, &revert_to);
+         XGetICValues(pX11IMData->current_ic, XNFocusWindow, &w, NULL);
++#if defined(_LP64) && !defined(_LITTLE_ENDIAN)
++        // On 64bit BigEndian,
++        // Window value may be stored on high 32bit by XGetICValues via XIM
++        if (w > 0xffffffffUL) w = w >> 32;
++#endif
+         if (RevertToPointerRoot == revert_to
+                 && pX11IMData->ic_active != pX11IMData->ic_passive) {
+             if (pX11IMData->current_ic == pX11IMData->ic_active) {
+@@ -1683,12 +1683,7 @@ JNIEXPORT jboolean JNICALL Java_sun_awt_X11InputMethodBase_isCompositionEnabledN
+ {
+     X11InputMethodData *pX11IMData = NULL;
+     char * ret = NULL;
+-#if defined(__linux__) && defined(_LP64) && !defined(_LITTLE_ENDIAN)
+-    // XIMPreeditState value which is used for XGetICValues must be 32bit on BigEndian XOrg's xlib
+-    unsigned int state = XIMPreeditUnKnown;
+-#else
+     XIMPreeditState state = XIMPreeditUnKnown;
+-#endif
+ 
+     XVaNestedList   pr_atrb;
+ 
+@@ -1704,6 +1699,11 @@ JNIEXPORT jboolean JNICALL Java_sun_awt_X11InputMethodBase_isCompositionEnabledN
+     ret = XGetICValues(pX11IMData->current_ic, XNPreeditAttributes, pr_atrb, NULL);
+     XFree((void *)pr_atrb);
+     AWT_UNLOCK();
++#if defined(__linux__) && defined(_LP64) && !defined(_LITTLE_ENDIAN)
++    // On 64bit BigEndian,
++    // XIMPreeditState value may be stored on high 32bit by XGetICValues via XIM
++    if (state > 0xffffffffUL) state = state >> 32;
++#endif
+ 
+     if ((ret != 0)
+             && ((strcmp(ret, XNPreeditAttributes) == 0)
+diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsCheckBoxMenuItemUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsCheckBoxMenuItemUI.java
+index 99966cb21..4984d4c9e 100644
+--- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsCheckBoxMenuItemUI.java
++++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsCheckBoxMenuItemUI.java
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+@@ -74,6 +74,26 @@ public class WindowsCheckBoxMenuItemUI extends BasicCheckBoxMenuItemUI {
+         }
+         super.paintBackground(g, menuItem, bgColor);
+     }
++
++    /**
++     * Paint MenuItem.
++     */
++    protected void paintMenuItem(Graphics g, JComponent c,
++                                 Icon checkIcon, Icon arrowIcon,
++                                 Color background, Color foreground,
++                                 int defaultTextIconGap) {
++        if (WindowsMenuItemUI.isVistaPainting()) {
++            WindowsMenuItemUI.paintMenuItem(accessor, g, c, checkIcon,
++                    arrowIcon, background, foreground,
++                    disabledForeground, acceleratorSelectionForeground,
++                    acceleratorForeground, defaultTextIconGap,
++                    menuItem, getPropertyPrefix());
++            return;
++        }
++        super.paintMenuItem(g, c, checkIcon, arrowIcon, background,
++                foreground, defaultTextIconGap);
++    }
++
+     /**
+      * Method which renders the text of the current menu item.
+      *
+diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsIconFactory.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsIconFactory.java
+index 3d8b523a2..8ed0fa082 100644
+--- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsIconFactory.java
++++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsIconFactory.java
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+@@ -846,6 +846,7 @@ public class WindowsIconFactory implements Serializable
+                 }
+                 assert menuItem == null || c == menuItem;
+                 Icon icon = getIcon();
++
+                 if (type == JCheckBoxMenuItem.class
+                       || type == JRadioButtonMenuItem.class) {
+                     AbstractButton b = (AbstractButton) c;
+@@ -869,19 +870,18 @@ public class WindowsIconFactory implements Serializable
+                         }
+                         XPStyle xp = XPStyle.getXP();
+                         if (xp != null) {
+-                            Skin skin;
+-                            skin =  xp.getSkin(c, backgroundPart);
+-                            skin.paintSkin(g, x, y,
+-                                getIconWidth(), getIconHeight(), backgroundState);
+-                            if (icon == null) {
+-                                skin = xp.getSkin(c, part);
++                            Skin skin = xp.getSkin(c, part);
++                            if (icon == null || icon.getIconHeight() <= 16) {
+                                 skin.paintSkin(g, x + OFFSET, y + OFFSET, state);
++                            } else {
++                                skin.paintSkin(g, x + OFFSET, y + icon.getIconHeight() / 2, state);
+                             }
+                         }
+                     }
+                 }
+                 if (icon != null) {
+-                    icon.paintIcon(c, g, x + OFFSET, y + OFFSET);
++                    icon.paintIcon(c, g, x + VistaMenuItemCheckIconFactory.getIconWidth(),
++                                   y + OFFSET);
+                 }
+             }
+             private static WindowsMenuItemUIAccessor getAccessor(
+diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuItemUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuItemUI.java
+index 578615829..a5ba0b9bb 100644
+--- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuItemUI.java
++++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuItemUI.java
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+@@ -31,9 +31,11 @@ import javax.swing.plaf.*;
+ import javax.swing.plaf.basic.*;
+ 
+ import sun.swing.SwingUtilities2;
++import sun.swing.MenuItemLayoutHelper;
+ 
+ import com.sun.java.swing.plaf.windows.TMSchema.*;
+ import com.sun.java.swing.plaf.windows.XPStyle.*;
++import com.sun.java.swing.SwingUtilities3;
+ 
+ /**
+  * Windows rendition of the component.
+@@ -47,8 +49,8 @@ import com.sun.java.swing.plaf.windows.XPStyle.*;
+  *
+  * @author Igor Kushnirskiy
+  */
+-
+ public class WindowsMenuItemUI extends BasicMenuItemUI {
++
+     final WindowsMenuItemUIAccessor accessor =
+         new  WindowsMenuItemUIAccessor() {
+ 
+@@ -68,6 +70,112 @@ public class WindowsMenuItemUI extends BasicMenuItemUI {
+         return new WindowsMenuItemUI();
+     }
+ 
++    protected void installDefaults() {
++        super.installDefaults();
++        String prefix = getPropertyPrefix();
++
++        if (acceleratorSelectionForeground == null ||
++                acceleratorSelectionForeground instanceof UIResource) {
++            acceleratorSelectionForeground =
++                    UIManager.getColor(prefix + ".acceleratorSelectionForeground");
++        }
++        if (acceleratorForeground == null ||
++                acceleratorForeground instanceof UIResource) {
++            acceleratorForeground =
++                    UIManager.getColor(prefix + ".acceleratorForeground");
++        }
++        if (disabledForeground == null ||
++                disabledForeground instanceof UIResource) {
++            disabledForeground =
++                    UIManager.getColor(prefix + ".disabledForeground");
++        }
++    }
++
++
++    protected void paintMenuItem(Graphics g, JComponent c,
++                                 Icon checkIcon, Icon arrowIcon,
++                                 Color background, Color foreground,
++                                 int defaultTextIconGap) {
++        if (WindowsMenuItemUI.isVistaPainting()) {
++            WindowsMenuItemUI.paintMenuItem(accessor, g, c, checkIcon,
++                                            arrowIcon, background, foreground,
++                                            disabledForeground, acceleratorSelectionForeground,
++                                            acceleratorForeground, defaultTextIconGap, menuItem,
++                                            getPropertyPrefix());
++            return;
++        }
++        super.paintMenuItem(g, c, checkIcon, arrowIcon, background,
++                foreground, defaultTextIconGap);
++    }
++
++    static void paintMenuItem(WindowsMenuItemUIAccessor accessor, Graphics g,
++                              JComponent c, Icon checkIcon, Icon arrowIcon,
++                              Color background, Color foreground,
++                              Color disabledForeground,
++                              Color acceleratorSelectionForeground,
++                              Color acceleratorForeground,
++                              int defaultTextIconGap, JMenuItem menuItem, String prefix) {
++        // Save original graphics font and color
++        Font holdf = g.getFont();
++        Color holdc = g.getColor();
++
++        JMenuItem mi = (JMenuItem) c;
++        g.setFont(mi.getFont());
++
++        Rectangle viewRect = new Rectangle(0, 0, mi.getWidth(), mi.getHeight());
++        SwingUtilities3.applyInsets(viewRect, mi.getInsets());
++
++        String acceleratorDelimiter =
++                UIManager.getString("MenuItem.acceleratorDelimiter");
++        if (acceleratorDelimiter == null) { acceleratorDelimiter = "+"; }
++        Font acceleratorFont = UIManager.getFont("MenuItem.acceleratorFont");
++        if (acceleratorFont == null) {
++            acceleratorFont = UIManager.getFont("MenuItem.font");
++        }
++
++        MenuItemLayoutHelper lh = new MenuItemLayoutHelper(mi, checkIcon,
++                arrowIcon, viewRect, defaultTextIconGap, acceleratorDelimiter,
++                mi.getComponentOrientation().isLeftToRight(), mi.getFont(),
++                acceleratorFont, MenuItemLayoutHelper.useCheckAndArrow(menuItem),
++                prefix);
++        MenuItemLayoutHelper.LayoutResult lr = lh.layoutMenuItem();
++
++        paintBackground(accessor, g, mi, background);
++        SwingUtilities3.paintCheckIcon(g, lh, lr, holdc, foreground);
++        SwingUtilities3.paintIcon(g, lh, lr, holdc);
++
++        if (lh.getCheckIcon() != null && lh.useCheckAndArrow()) {
++            Rectangle rect = lr.getTextRect();
++
++            rect.x += lh.getAfterCheckIconGap();
++
++            lr.setTextRect(rect);
++        }
++        if (!lh.getText().isEmpty()) {
++            if (lh.getHtmlView() != null) {
++                // Text is HTML
++                lh.getHtmlView().paint(g, lr.getTextRect());
++            } else {
++                // Text isn't HTML
++                paintText(accessor, g, lh.getMenuItem(),
++                          lr.getTextRect(), lh.getText());
++            }
++        }
++        if (lh.getCheckIcon() != null && lh.useCheckAndArrow()) {
++            Rectangle rect = lr.getAccRect();
++            rect.x += lh.getAfterCheckIconGap();
++            lr.setAccRect(rect);
++        }
++        SwingUtilities3.paintAccText(g, lh, lr, disabledForeground,
++                                     acceleratorSelectionForeground,
++                                     acceleratorForeground);
++        SwingUtilities3.paintArrowIcon(g, lh, lr, foreground);
++
++        // Restore original graphics font and color
++        g.setColor(holdc);
++        g.setFont(holdf);
++    }
++
+     /**
+      * Method which renders the text of the current menu item.
+      *
+diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuUI.java
+index 803952b80..aa99e0245 100644
+--- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuUI.java
++++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuUI.java
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+@@ -123,6 +123,26 @@ public class WindowsMenuUI extends BasicMenuUI {
+         hotTrackingOn = (obj instanceof Boolean) ? (Boolean)obj : true;
+     }
+ 
++    /**
++     * Paint MenuItem.
++     */
++    protected void paintMenuItem(Graphics g, JComponent c,
++                              Icon checkIcon, Icon arrowIcon,
++                              Color background, Color foreground,
++                              int defaultTextIconGap) {
++        if (WindowsMenuItemUI.isVistaPainting()) {
++            WindowsMenuItemUI.paintMenuItem(accessor, g, c, checkIcon, arrowIcon,
++                                            background, foreground,
++                                            disabledForeground, acceleratorSelectionForeground,
++                                            acceleratorForeground, defaultTextIconGap, menuItem,
++                                            getPropertyPrefix());
++            return;
++        }
++        super.paintMenuItem(g, c, checkIcon, arrowIcon, background,
++                                   foreground, defaultTextIconGap);
++    }
++
++
+     /**
+      * Draws the background of the menu.
+      * @since 1.4
+diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsRadioButtonMenuItemUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsRadioButtonMenuItemUI.java
+index cce34eb9a..bfcdd318e 100644
+--- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsRadioButtonMenuItemUI.java
++++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsRadioButtonMenuItemUI.java
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+@@ -74,6 +74,25 @@ public class WindowsRadioButtonMenuItemUI extends BasicRadioButtonMenuItemUI {
+         super.paintBackground(g, menuItem, bgColor);
+     }
+ 
++    /**
++     * Paint MenuItem.
++     */
++    protected void paintMenuItem(Graphics g, JComponent c,
++                                 Icon checkIcon, Icon arrowIcon,
++                                 Color background, Color foreground,
++                                 int defaultTextIconGap) {
++        if (WindowsMenuItemUI.isVistaPainting()) {
++            WindowsMenuItemUI.paintMenuItem(accessor, g, c, checkIcon,
++                    arrowIcon, background, foreground,
++                    disabledForeground, acceleratorSelectionForeground,
++                    acceleratorForeground, defaultTextIconGap,
++                    menuItem, getPropertyPrefix());
++            return;
++        }
++        super.paintMenuItem(g, c, checkIcon, arrowIcon, background,
++                foreground, defaultTextIconGap);
++    }
++
+     /**
+      * Method which renders the text of the current menu item.
+      *
+diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Button.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Button.cpp
+index 1a7a89fde..714becbca 100644
+--- a/src/java.desktop/windows/native/libawt/windows/awt_Button.cpp
++++ b/src/java.desktop/windows/native/libawt/windows/awt_Button.cpp
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 1996, 2025, Oracle and/or its affiliates. All rights reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+@@ -242,7 +242,7 @@ AwtButton::OwnerDrawItem(UINT /*ctrlId*/, DRAWITEMSTRUCT& drawInfo)
+         RECT focusRect;
+         VERIFY(::CopyRect(&focusRect, &rect));
+         VERIFY(::InflateRect(&focusRect,-inf,-inf));
+-        if(::DrawFocusRect(hDC, &focusRect) == 0)
++        if (!::IsRectEmpty(&focusRect) && (::DrawFocusRect(hDC, &focusRect) == 0))
+             VERIFY(::GetLastError() == 0);
+     }
+ 
+diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Checkbox.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Checkbox.cpp
+index d77ebb74a..f50ddbb5d 100644
+--- a/src/java.desktop/windows/native/libawt/windows/awt_Checkbox.cpp
++++ b/src/java.desktop/windows/native/libawt/windows/awt_Checkbox.cpp
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 1996, 2025, Oracle and/or its affiliates. All rights reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+@@ -290,13 +290,13 @@ AwtCheckbox::OwnerDrawItem(UINT /*ctrlId*/, DRAWITEMSTRUCT& drawInfo)
+     if ((drawInfo.itemState & ODS_FOCUS) &&
+         ((drawInfo.itemAction & ODA_FOCUS)||
+          (drawInfo.itemAction &ODA_DRAWENTIRE))) {
+-        if(::DrawFocusRect(hDC, &focusRect) == 0)
++        if (!::IsRectEmpty(&focusRect) && (::DrawFocusRect(hDC, &focusRect) == 0))
+             VERIFY(::GetLastError() == 0);
+     }
+     /*  erase focus rect */
+     else if (!(drawInfo.itemState & ODS_FOCUS) &&
+              (drawInfo.itemAction & ODA_FOCUS)) {
+-        if(::DrawFocusRect(hDC, &focusRect) == 0)
++        if (!::IsRectEmpty(&focusRect) && (::DrawFocusRect(hDC, &focusRect) == 0))
+             VERIFY(::GetLastError() == 0);
+     }
+ 
+diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp
+index cefccdec7..47b9b9adb 100644
+--- a/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp
++++ b/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 1996, 2022, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 1996, 2025, Oracle and/or its affiliates. All rights reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+@@ -4499,7 +4499,7 @@ void AwtComponent::DrawListItem(JNIEnv *env, DRAWITEMSTRUCT &drawInfo)
+     if ((drawInfo.itemState & ODS_FOCUS)  &&
+         (drawInfo.itemAction & (ODA_FOCUS | ODA_DRAWENTIRE))) {
+       if (!unfocusableChoice){
+-          if(::DrawFocusRect(hDC, &rect) == 0)
++          if (!::IsRectEmpty(&rect) && (::DrawFocusRect(hDC, &rect) == 0))
+               VERIFY(::GetLastError() == 0);
+       }
+     }
+diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/HttpRequestImpl.java b/src/java.net.http/share/classes/jdk/internal/net/http/HttpRequestImpl.java
+index 4f9d3cf56..d114d314b 100644
+--- a/src/java.net.http/share/classes/jdk/internal/net/http/HttpRequestImpl.java
++++ b/src/java.net.http/share/classes/jdk/internal/net/http/HttpRequestImpl.java
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+@@ -41,12 +41,15 @@ import java.util.Optional;
+ import java.net.http.HttpClient;
+ import java.net.http.HttpHeaders;
+ import java.net.http.HttpRequest;
++import java.util.function.BiPredicate;
++
+ import jdk.internal.net.http.common.HttpHeadersBuilder;
+ import jdk.internal.net.http.common.Utils;
+ import jdk.internal.net.http.websocket.OpeningHandshake;
+ import jdk.internal.net.http.websocket.WebSocketRequest;
+ 
+ import static jdk.internal.net.http.common.Utils.ALLOWED_HEADERS;
++import static jdk.internal.net.http.common.Utils.copyProxy;
+ 
+ public class HttpRequestImpl extends HttpRequest implements WebSocketRequest {
+ 
+@@ -125,15 +128,7 @@ public class HttpRequestImpl extends HttpRequest implements WebSocketRequest {
+             this.systemHeadersBuilder.setHeader("User-Agent", USER_AGENT);
+         }
+         this.uri = requestURI;
+-        if (isWebSocket) {
+-            // WebSocket determines and sets the proxy itself
+-            this.proxy = ((HttpRequestImpl) request).proxy;
+-        } else {
+-            if (ps != null)
+-                this.proxy = retrieveProxy(ps, uri);
+-            else
+-                this.proxy = null;
+-        }
++        this.proxy = retrieveProxy(request, ps, uri);
+         this.expectContinue = request.expectContinue();
+         this.secure = uri.getScheme().toLowerCase(Locale.US).equals("https");
+         this.requestPublisher = request.bodyPublisher().orElse(null);
+@@ -152,13 +147,18 @@ public class HttpRequestImpl extends HttpRequest implements WebSocketRequest {
+     /** Returns a new instance suitable for redirection. */
+     public static HttpRequestImpl newInstanceForRedirection(URI uri,
+                                                             String method,
+-                                                            HttpRequestImpl other) {
+-        return new HttpRequestImpl(uri, method, other);
++                                                            HttpRequestImpl other,
++                                                            boolean mayHaveBody) {
++        if (uri.getScheme().equalsIgnoreCase(other.uri.getScheme()) &&
++                uri.getRawAuthority().equals(other.uri.getRawAuthority())) {
++            return new HttpRequestImpl(uri, method, other, mayHaveBody, Optional.empty());
++        }
++        return new HttpRequestImpl(uri, method, other, mayHaveBody, Optional.of(Utils.ALLOWED_REDIRECT_HEADERS));
+     }
+ 
+     /** Returns a new instance suitable for authentication. */
+     public static HttpRequestImpl newInstanceForAuthentication(HttpRequestImpl other) {
+-        HttpRequestImpl request = new HttpRequestImpl(other.uri(), other.method(), other);
++        HttpRequestImpl request = new HttpRequestImpl(other.uri(), other.method(), other, true);
+         if (request.isWebSocket()) {
+             Utils.setWebSocketUpgradeHeaders(request);
+         }
+@@ -171,10 +171,21 @@ public class HttpRequestImpl extends HttpRequest implements WebSocketRequest {
+      */
+     private HttpRequestImpl(URI uri,
+                             String method,
+-                            HttpRequestImpl other) {
++                            HttpRequestImpl other,
++                            boolean mayHaveBody) {
++        this(uri, method, other, mayHaveBody, Optional.empty());
++    }
++
++    private HttpRequestImpl(URI uri,
++                            String method,
++                            HttpRequestImpl other,
++                            boolean mayHaveBody,
++                            Optional> redirectHeadersFilter) {
+         assert method == null || Utils.isValidName(method);
+-        this.method = method == null? "GET" : method;
+-        this.userHeaders = other.userHeaders;
++        this.method = method == null ? "GET" : method;
++        HttpHeaders userHeaders = redirectHeadersFilter.isPresent() ?
++                HttpHeaders.of(other.userHeaders.map(), redirectHeadersFilter.get()) : other.userHeaders;
++        this.userHeaders = userHeaders;
+         this.isWebSocket = other.isWebSocket;
+         this.systemHeadersBuilder = new HttpHeadersBuilder();
+         if (!userHeaders.firstValue("User-Agent").isPresent()) {
+@@ -184,13 +195,21 @@ public class HttpRequestImpl extends HttpRequest implements WebSocketRequest {
+         this.proxy = other.proxy;
+         this.expectContinue = other.expectContinue;
+         this.secure = uri.getScheme().toLowerCase(Locale.US).equals("https");
+-        this.requestPublisher = other.requestPublisher;  // may be null
++        this.requestPublisher = mayHaveBody ? publisher(other) : null; // may be null
+         this.acc = other.acc;
+         this.timeout = other.timeout;
+         this.version = other.version();
+         this.authority = null;
+     }
+ 
++    private BodyPublisher publisher(HttpRequestImpl other) {
++        BodyPublisher res = other.requestPublisher;
++        if (!Objects.equals(method, other.method)) {
++            res = null;
++        }
++        return res;
++    }
++
+     /* used for creating CONNECT requests  */
+     HttpRequestImpl(String method, InetSocketAddress authority, HttpHeaders headers) {
+         // TODO: isWebSocket flag is not specified, but the assumption is that
+@@ -281,16 +300,30 @@ public class HttpRequestImpl extends HttpRequest implements WebSocketRequest {
+     @Override
+     public boolean expectContinue() { return expectContinue; }
+ 
+-    /** Retrieves the proxy, from the given ProxySelector, if there is one. */
+-    private static Proxy retrieveProxy(ProxySelector ps, URI uri) {
+-        Proxy proxy = null;
+-        List pl = ps.select(uri);
+-        if (!pl.isEmpty()) {
+-            Proxy p = pl.get(0);
+-            if (p.type() == Proxy.Type.HTTP)
+-                proxy = p;
++    /** Retrieves a copy of the proxy either from the given {@link HttpRequest} or {@link ProxySelector}, if there is one. */
++    private static Proxy retrieveProxy(HttpRequest request, ProxySelector ps, URI uri) {
++
++        // WebSocket determines and sets the proxy itself
++        if (request instanceof HttpRequestImpl) {
++            HttpRequestImpl requestImpl = (HttpRequestImpl)request;
++            if (requestImpl.isWebSocket) {
++                return requestImpl.proxy;
++            }
++        }
++
++        // Try to find a matching one from the `ProxySelector`
++        if (ps != null) {
++            List pl = ps.select(uri);
++            if (!pl.isEmpty()) {
++                Proxy p = pl.get(0);
++                if (p.type() == Proxy.Type.HTTP) {
++                    return copyProxy(p);
++                }
++            }
+         }
+-        return proxy;
++
++        return null;
++
+     }
+ 
+     InetSocketAddress proxy() {
+@@ -306,7 +339,7 @@ public class HttpRequestImpl extends HttpRequest implements WebSocketRequest {
+     @Override
+     public void setProxy(Proxy proxy) {
+         assert isWebSocket;
+-        this.proxy = proxy;
++        this.proxy = copyProxy(proxy);
+     }
+ 
+     @Override
+diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/RedirectFilter.java b/src/java.net.http/share/classes/jdk/internal/net/http/RedirectFilter.java
+index 3161132f3..79e2a2fbf 100644
+--- a/src/java.net.http/share/classes/jdk/internal/net/http/RedirectFilter.java
++++ b/src/java.net.http/share/classes/jdk/internal/net/http/RedirectFilter.java
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2015, 2019, 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
+@@ -89,6 +89,31 @@ class RedirectFilter implements HeaderFilter {
+         }
+     }
+ 
++    private static boolean isRedirecting(int statusCode) {
++        // < 300: not a redirect codes
++        if (statusCode < 300) return false;
++        // 309-399 Unassigned => don't follow
++        // > 399: not a redirect code
++        if (statusCode > 308) return false;
++        switch (statusCode) {
++            // 300: MultipleChoice => don't follow
++            case 300:
++                return false;
++            // 304: Not Modified => don't follow
++            case 304:
++                return false;
++            // 305: Proxy Redirect => don't follow.
++            case 305:
++                return false;
++            // 306: Unused => don't follow
++            case 306:
++                return false;
++            // 301, 302, 303, 307, 308: OK to follow.
++            default:
++                return true;
++        }
++    }
++
+     /**
+      * Checks to see if a new request is needed and returns it.
+      * Null means response is ok to return to user.
+@@ -102,13 +127,13 @@ class RedirectFilter implements HeaderFilter {
+         if (rcode == HTTP_NOT_MODIFIED)
+             return null;
+ 
+-        if (rcode >= 300 && rcode <= 399) {
++        if (isRedirecting(rcode)) {
+             URI redir = getRedirectedURI(r.headers());
+             String newMethod = redirectedMethod(rcode, method);
+             Log.logTrace("response code: {0}, redirected URI: {1}", rcode, redir);
+             if (canRedirect(redir) && ++exchange.numberOfRedirects < max_redirects) {
+                 Log.logTrace("redirect to: {0} with method: {1}", redir, newMethod);
+-                return HttpRequestImpl.newInstanceForRedirection(redir, newMethod, request);
++                return HttpRequestImpl.newInstanceForRedirection(redir, newMethod, request, rcode != 303);
+             } else {
+                 Log.logTrace("not redirecting");
+                 return null;
+diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java b/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java
+index 984e6214b..15a9cf403 100644
+--- a/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java
++++ b/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+@@ -42,6 +42,7 @@ import java.io.UncheckedIOException;
+ import java.lang.System.Logger.Level;
+ import java.net.ConnectException;
+ import java.net.InetSocketAddress;
++import java.net.Proxy;
+ import java.net.URI;
+ import java.net.URLPermission;
+ import java.net.http.HttpClient;
+@@ -151,6 +152,18 @@ public final class Utils {
+     public static final BiPredicate
+             ALLOWED_HEADERS = (header, unused) -> !DISALLOWED_HEADERS_SET.contains(header);
+ 
++    private static final Set DISALLOWED_REDIRECT_HEADERS_SET = getDisallowedRedirectHeaders();
++
++    private static Set getDisallowedRedirectHeaders() {
++        Set headers = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
++        headers.addAll(Set.of("Authorization", "Cookie", "Origin", "Referer", "Host"));
++
++        return Collections.unmodifiableSet(headers);
++    }
++
++    public static final BiPredicate
++            ALLOWED_REDIRECT_HEADERS = (header, unused) -> !DISALLOWED_REDIRECT_HEADERS_SET.contains(header);
++
+     public static final BiPredicate VALIDATE_USER_HEADER =
+             (name, value) -> {
+                 assert name != null : "null header name";
+@@ -267,6 +280,17 @@ public final class Utils {
+                       : ! PROXY_AUTH_DISABLED_SCHEMES.isEmpty();
+     }
+ 
++    /**
++     * Creates a new {@link Proxy} instance for the given proxy iff it is
++     * neither null, {@link Proxy#NO_PROXY Proxy.NO_PROXY}, nor already a
++     * {@code Proxy} instance.
++     */
++    public static Proxy copyProxy(Proxy proxy) {
++        return proxy == null || proxy.getClass() == Proxy.class
++                ? proxy
++                : new Proxy(proxy.type(), proxy.address());
++    }
++
+     // WebSocket connection Upgrade headers
+     private static final String HEADER_CONNECTION = "Connection";
+     private static final String HEADER_UPGRADE    = "Upgrade";
+diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/websocket/OpeningHandshake.java b/src/java.net.http/share/classes/jdk/internal/net/http/websocket/OpeningHandshake.java
+index c0c3ab6e8..dad094688 100644
+--- a/src/java.net.http/share/classes/jdk/internal/net/http/websocket/OpeningHandshake.java
++++ b/src/java.net.http/share/classes/jdk/internal/net/http/websocket/OpeningHandshake.java
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+@@ -66,6 +66,7 @@ import java.util.stream.Collectors;
+ import java.util.stream.Stream;
+ 
+ import static java.lang.String.format;
++import static jdk.internal.net.http.common.Utils.copyProxy;
+ import static jdk.internal.net.http.common.Utils.isValidName;
+ import static jdk.internal.net.http.common.Utils.permissionForProxy;
+ import static jdk.internal.net.http.common.Utils.stringOf;
+@@ -373,7 +374,7 @@ public class OpeningHandshake {
+         if (proxy.type() != Proxy.Type.HTTP) {
+             return null;
+         }
+-        return proxy;
++        return copyProxy(proxy);
+     }
+ 
+     /**
+diff --git a/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathFactoryImpl.java b/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathFactoryImpl.java
+index d948a0a0c..f3125fcd3 100644
+--- a/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathFactoryImpl.java
++++ b/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathFactoryImpl.java
+@@ -184,6 +184,7 @@ public  class XPathFactoryImpl extends XPathFactory {
+                 if (value && _featureManager != null) {
+                     _featureManager.setFeature(JdkXmlFeatures.XmlFeature.ENABLE_EXTENSION_FUNCTION,
+                             JdkXmlFeatures.State.FSP, false);
++                    _xmlSecMgr.setSecureProcessing(value);
+                 }
+ 
+                 // all done processing feature
+diff --git a/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathImplUtil.java b/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathImplUtil.java
+index 14b47fd5d..8e46f9126 100644
+--- a/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathImplUtil.java
++++ b/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathImplUtil.java
+@@ -31,6 +31,7 @@ import com.sun.org.apache.xpath.internal.axes.LocPathIterator;
+ import com.sun.org.apache.xpath.internal.objects.XObject;
+ import com.sun.org.apache.xpath.internal.res.XPATHErrorResources;
+ import java.io.IOException;
++import javax.xml.XMLConstants;
+ import javax.xml.namespace.QName;
+ import javax.xml.parsers.DocumentBuilderFactory;
+ import javax.xml.parsers.ParserConfigurationException;
+@@ -54,7 +55,7 @@ import org.xml.sax.SAXException;
+  * This class contains several utility methods used by XPathImpl and
+  * XPathExpressionImpl
+  *
+- * @LastModified: Jan 2022
++ * @LastModified: June 2025
+  */
+ class XPathImplUtil {
+     XPathFunctionResolver functionResolver;
+@@ -130,6 +131,10 @@ class XPathImplUtil {
+             // so we really have to create a fresh DocumentBuilder every time we need one
+             // - KK
+             DocumentBuilderFactory dbf = JdkXmlUtils.getDOMFactory(overrideDefaultParser);
++            if (xmlSecMgr != null && xmlSecMgr.isSecureProcessingSet()) {
++                dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING,
++                        xmlSecMgr.isSecureProcessing());
++            }
+             return dbf.newDocumentBuilder().parse(source);
+         } catch (ParserConfigurationException | SAXException | IOException e) {
+             throw new XPathExpressionException (e);
+diff --git a/src/java.xml/share/classes/jdk/xml/internal/XMLSecurityManager.java b/src/java.xml/share/classes/jdk/xml/internal/XMLSecurityManager.java
+index 2dd165757..64de41f51 100644
+--- a/src/java.xml/share/classes/jdk/xml/internal/XMLSecurityManager.java
++++ b/src/java.xml/share/classes/jdk/xml/internal/XMLSecurityManager.java
+@@ -189,6 +189,12 @@ public final class XMLSecurityManager {
+      */
+     boolean secureProcessing;
+ 
++    /**
++     * Flag indicating the secure processing is set explicitly through factories'
++     * setFeature method and then the setSecureProcessing method
++     */
++    boolean secureProcessingSet;
++
+     /**
+      * States that determine if properties are set explicitly
+      */
+@@ -236,6 +242,7 @@ public final class XMLSecurityManager {
+      * Setting FEATURE_SECURE_PROCESSING explicitly
+      */
+     public void setSecureProcessing(boolean secure) {
++        secureProcessingSet = true;
+         secureProcessing = secure;
+         for (Limit limit : Limit.values()) {
+             if (secure) {
+@@ -254,6 +261,15 @@ public final class XMLSecurityManager {
+         return secureProcessing;
+     }
+ 
++    /**
++     * Returns the state indicating whether the Secure Processing is set explicitly,
++     * via factories' setFeature and then this class' setSecureProcessing method.
++     * @return the state indicating whether the Secure Processing is set explicitly
++     */
++    public boolean isSecureProcessingSet() {
++        return secureProcessingSet;
++    }
++
+     /**
+      * Set limit by property name and state
+      * @param propertyName property name
+diff --git a/src/jdk.accessibility/windows/classes/com/sun/java/accessibility/internal/AccessBridge.java b/src/jdk.accessibility/windows/classes/com/sun/java/accessibility/internal/AccessBridge.java
+index c75795f18..e0175ea44 100644
+--- a/src/jdk.accessibility/windows/classes/com/sun/java/accessibility/internal/AccessBridge.java
++++ b/src/jdk.accessibility/windows/classes/com/sun/java/accessibility/internal/AccessBridge.java
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+@@ -3838,6 +3838,8 @@ final public class AccessBridge {
+             return 0;
+         int code = keyStroke.getKeyCode();
+         switch (code) {
++            case KeyEvent.VK_TAB:
++            case KeyEvent.VK_SPACE:
+             case KeyEvent.VK_BACK_SPACE:
+             case KeyEvent.VK_DELETE:
+             case KeyEvent.VK_DOWN:
+@@ -3880,15 +3882,10 @@ final public class AccessBridge {
+             debugString("[INFO]:   Shortcut is control character: " + Integer.toHexString(keyCode));
+             return (char)keyCode;
+         }
+-        String keyText = KeyEvent.getKeyText(keyStroke.getKeyCode());
+-        debugString("[INFO]:   Shortcut is: " + keyText);
+-        if (keyText != null || keyText.length() > 0) {
+-            CharSequence seq = keyText.subSequence(0, 1);
+-            if (seq != null || seq.length() > 0) {
+-                return seq.charAt(0);
+-            }
+-        }
+-        return 0;
++
++        keyCode = keyStroke.getKeyCode();
++        debugString("[INFO]:   Shortcut is: " + Integer.toHexString(keyCode));
++        return (char)keyCode;
+     }
+ 
+     /*
+diff --git a/src/jdk.accessibility/windows/native/include/bridge/AccessBridgePackages.h b/src/jdk.accessibility/windows/native/include/bridge/AccessBridgePackages.h
+index 27c31be09..232cab4b2 100644
+--- a/src/jdk.accessibility/windows/native/include/bridge/AccessBridgePackages.h
++++ b/src/jdk.accessibility/windows/native/include/bridge/AccessBridgePackages.h
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+@@ -1108,6 +1108,8 @@ typedef long ABHWND64;
+ #define ACCESSIBLE_CONTROLCODE_KEYSTROKE        512  // Control code key pressed, character contains control code.
+ 
+ // The supported control code keys are:
++#define ACCESSIBLE_VK_TAB           9
++#define ACCESSIBLE_VK_SPACE         32
+ #define ACCESSIBLE_VK_BACK_SPACE    8
+ #define ACCESSIBLE_VK_DELETE        127
+ #define ACCESSIBLE_VK_DOWN          40
+diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/StringConcat.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/StringConcat.java
+index 4ade741a5..ecb63fcd2 100644
+--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/StringConcat.java
++++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/StringConcat.java
+@@ -140,25 +140,6 @@ public abstract class StringConcat {
+         return res.append(tree);
+     }
+ 
+-    /**
+-     * If the type is not accessible from current context, try to figure out the
+-     * sharpest accessible supertype.
+-     *
+-     * @param originalType type to sharpen
+-     * @return sharped type
+-     */
+-    Type sharpestAccessible(Type originalType) {
+-        if (originalType.hasTag(ARRAY)) {
+-            return types.makeArrayType(sharpestAccessible(types.elemtype(originalType)));
+-        }
+-
+-        Type type = originalType;
+-        while (!rs.isAccessible(gen.getAttrEnv(), type.asElement())) {
+-            type = types.supertype(type);
+-        }
+-        return type;
+-    }
+-
+     /**
+      * "Legacy" bytecode flavor: emit the StringBuilder.append chains for string
+      * concatenation.
+@@ -303,6 +284,14 @@ public abstract class StringConcat {
+ 
+             return splits.toList();
+         }
++
++        /**
++         * Returns true if the argument should be converted to a string eagerly, to preserve
++         * possible side-effects.
++         */
++        protected boolean shouldConvertToStringEagerly(Type argType) {
++            return !types.unboxedTypeOrType(argType).isPrimitive() && argType.tsym != syms.stringType.tsym;
++        }
+     }
+ 
+     /**
+@@ -331,14 +320,18 @@ public abstract class StringConcat {
+                 for (JCTree arg : t) {
+                     Object constVal = arg.type.constValue();
+                     if ("".equals(constVal)) continue;
+-                    if (arg.type == syms.botType) {
+-                        dynamicArgs.add(types.boxedClass(syms.voidType).type);
+-                    } else {
+-                        dynamicArgs.add(sharpestAccessible(arg.type));
++                    Type argType = arg.type;
++                    if (argType == syms.botType) {
++                        argType = types.boxedClass(syms.voidType).type;
+                     }
+                     if (!first || generateFirstArg) {
+                         gen.genExpr(arg, arg.type).load();
+                     }
++                    if (shouldConvertToStringEagerly(argType)) {
++                        gen.callMethod(pos, syms.stringType, names.valueOf, List.of(syms.objectType), true);
++                        argType = syms.stringType;
++                    }
++                    dynamicArgs.add(argType);
+                     first = false;
+                 }
+                 doCall(type, pos, dynamicArgs.toList());
+@@ -438,10 +431,15 @@ public abstract class StringConcat {
+                     } else {
+                         // Ordinary arguments come through the dynamic arguments.
+                         recipe.append(TAG_ARG);
+-                        dynamicArgs.add(sharpestAccessible(arg.type));
++                        Type argType = arg.type;
+                         if (!first || generateFirstArg) {
+                             gen.genExpr(arg, arg.type).load();
+                         }
++                        if (shouldConvertToStringEagerly(argType)) {
++                            gen.callMethod(pos, syms.stringType, names.valueOf, List.of(syms.objectType), true);
++                            argType = syms.stringType;
++                        }
++                        dynamicArgs.add(argType);
+                         first = false;
+                     }
+                 }
+diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/Config.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/Config.java
+index 83b633358..6fdd46f64 100644
+--- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/Config.java
++++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/Config.java
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2003, 2024, 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,6 +126,9 @@ final class Config {
+     // whether to print debug info during startup
+     private boolean showInfo = false;
+ 
++    // whether to allow legacy mechanisms
++    private boolean allowLegacy = false;
++
+     // template manager, initialized from parsed attributes
+     private TemplateManager templateManager;
+ 
+@@ -256,6 +259,10 @@ final class Config {
+         return (SunPKCS11.debug != null) || showInfo;
+     }
+ 
++    boolean getAllowLegacy() {
++        return allowLegacy;
++    }
++
+     TemplateManager getTemplateManager() {
+         if (templateManager == null) {
+             templateManager = new TemplateManager();
+@@ -449,6 +456,8 @@ final class Config {
+                 destroyTokenAfterLogout = parseBooleanEntry(word);
+             } else if (word.equals("showInfo")) {
+                 showInfo = parseBooleanEntry(word);
++            } else if (word.equals("allowLegacy")) {
++                allowLegacy = parseBooleanEntry(word);
+             } else if (word.equals("keyStoreCompatibilityMode")) {
+                 keyStoreCompatibilityMode = parseBooleanEntry(word);
+             } else if (word.equals("explicitCancel")) {
+diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11ECKeyFactory.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11ECKeyFactory.java
+index f19014cb0..0f3a8af3c 100644
+--- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11ECKeyFactory.java
++++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11ECKeyFactory.java
+@@ -294,7 +294,13 @@ final class P11ECKeyFactory extends P11KeyFactory {
+             try {
+                 token.p11.C_GetAttributeValue(session[0].id(), keyID, attributes);
+                 ECParameterSpec params = decodeParameters(attributes[1].getByteArray());
+-                ECPoint point = decodePoint(attributes[0].getByteArray(), params.getCurve());
++                ECPoint point;
++
++                if (!token.config.getUseEcX963Encoding()) {
++                    point = decodePoint(new DerValue(attributes[0].getByteArray()).getOctetString(), params.getCurve());
++                } else {
++                    point = decodePoint(attributes[0].getByteArray(), params.getCurve());
++                }
+                 return keySpec.cast(new ECPublicKeySpec(point, params));
+             } catch (IOException e) {
+                 throw new InvalidKeySpecException("Could not parse key", e);
+diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SunPKCS11.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SunPKCS11.java
+index ffbd67124..fdbd8cdac 100644
+--- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SunPKCS11.java
++++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SunPKCS11.java
+@@ -956,25 +956,6 @@ public final class SunPKCS11 extends AuthProvider {
+         }
+     }
+ 
+-    private static boolean isLegacy(CK_MECHANISM_INFO mechInfo)
+-            throws PKCS11Exception {
+-        // assume full support if no mech info available
+-        // For vendor-specific mechanisms, often no mech info is provided
+-        boolean partialSupport = false;
+-
+-        if (mechInfo != null) {
+-            if ((mechInfo.flags & CKF_DECRYPT) != 0) {
+-                // non-legacy cipher mechs should support encryption
+-                partialSupport |= ((mechInfo.flags & CKF_ENCRYPT) == 0);
+-            }
+-            if ((mechInfo.flags & CKF_VERIFY) != 0) {
+-                // non-legacy signature mechs should support signing
+-                partialSupport |= ((mechInfo.flags & CKF_SIGN) == 0);
+-            }
+-        }
+-        return partialSupport;
+-    }
+-
+     // test if a token is present and initialize this provider for it if so.
+     // does nothing if no token is found
+     // called from constructor and by poller
+@@ -1025,12 +1006,6 @@ public final class SunPKCS11 extends AuthProvider {
+                 }
+                 continue;
+             }
+-            if (isLegacy(mechInfo)) {
+-                if (showInfo) {
+-                    System.out.println("DISABLED due to legacy");
+-                }
+-                continue;
+-            }
+ 
+             // we do not know of mechs with the upper 32 bits set
+             if (longMech >>> 32 != 0) {
+@@ -1045,9 +1020,25 @@ public final class SunPKCS11 extends AuthProvider {
+             if (ds == null) {
+                 continue;
+             }
++            boolean allowLegacy = config.getAllowLegacy();
+             for (Descriptor d : ds) {
+                 Integer oldMech = supportedAlgs.get(d);
+                 if (oldMech == null) {
++
++                    // assume full support if no mech info available
++                    if (!allowLegacy && mechInfo != null) {
++                        if ((d.type == CIP &&
++                                (mechInfo.flags & CKF_ENCRYPT) == 0) ||
++                                (d.type == SIG &&
++                                (mechInfo.flags & CKF_SIGN) == 0)) {
++                            if (showInfo) {
++                                System.out.println("DISABLED " +  d.type +
++                                        " " + d.algorithm +
++                                        " due to partial support");
++                            }
++                            continue;
++                        }
++                    }
+                     supportedAlgs.put(d, integerMech);
+                     continue;
+                 }
+diff --git a/src/jdk.crypto.cryptoki/share/legal/pkcs11cryptotoken.md b/src/jdk.crypto.cryptoki/share/legal/pkcs11cryptotoken.md
+index 08d1e3c71..7877f54fe 100644
+--- a/src/jdk.crypto.cryptoki/share/legal/pkcs11cryptotoken.md
++++ b/src/jdk.crypto.cryptoki/share/legal/pkcs11cryptotoken.md
+@@ -1,16 +1,16 @@
+-## OASIS PKCS #11 Cryptographic Token Interface v3.0
++## OASIS PKCS #11 Cryptographic Token Interface v3.1
+ 
+ ### OASIS PKCS #11 Cryptographic Token Interface License
+ 
+ 
+-Copyright © OASIS Open 2020. All Rights Reserved.
++Copyright © OASIS Open 2023. All Rights Reserved.
+ 
+-    All capitalized terms in the following text have the meanings
++All capitalized terms in the following text have the meanings
+ assigned to them in the OASIS Intellectual Property Rights Policy (the
+ "OASIS IPR Policy"). The full Policy may be found at the OASIS website:
+-[http://www.oasis-open.org/policies-guidelines/ipr]
++[https://www.oasis-open.org/policies-guidelines/ipr/].
+ 
+-    This document and translations of it may be copied and furnished to
++This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it or
+ assist in its implementation may be prepared, copied, published, and
+ distributed, in whole or in part, without restriction of any kind,
+@@ -23,10 +23,10 @@ Committee (in which case the rules applicable to copyrights, as set
+ forth in the OASIS IPR Policy, must be followed) or as required to
+ translate it into languages other than English.
+ 
+-    The limited permissions granted above are perpetual and will not be
++The limited permissions granted above are perpetual and will not be
+ revoked by OASIS or its successors or assigns.
+ 
+-    This document and the information contained herein is provided on an
++This document and the information contained herein is provided on an
+ "AS IS" basis and OASIS DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
+ INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
+ INFORMATION HEREIN WILL NOT INFRINGE ANY OWNERSHIP RIGHTS OR ANY IMPLIED
+@@ -35,7 +35,11 @@ AND ITS MEMBERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL OR
+ CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THIS DOCUMENT OR ANY
+ PART THEREOF.
+ 
+-    [OASIS requests that any OASIS Party or any other party that
++As stated in the OASIS IPR Policy, the following three paragraphs in
++brackets apply to OASIS Standards Final Deliverable documents (Committee
++Specifications, OASIS Standards, or Approved Errata).
++
++[OASIS requests that any OASIS Party or any other party that
+ believes it has patent claims that would necessarily be infringed by
+ implementations of this OASIS Standards Final Deliverable, to notify
+ OASIS TC Administrator and provide an indication of its willingness to
+@@ -43,7 +47,7 @@ grant patent licenses to such patent claims in a manner consistent with
+ the IPR Mode of the OASIS Technical Committee that produced this
+ deliverable.]
+ 
+-    [OASIS invites any party to contact the OASIS TC Administrator if it
++[OASIS invites any party to contact the OASIS TC Administrator if it
+ is aware of a claim of ownership of any patent claims that would
+ necessarily be infringed by implementations of this OASIS Standards
+ Final Deliverable by a patent holder that is not willing to provide a
+@@ -52,7 +56,7 @@ of the OASIS Technical Committee that produced this OASIS Standards
+ Final Deliverable. OASIS may include such claims on its website, but
+ disclaims any obligation to do so.]
+ 
+-    [OASIS takes no position regarding the validity or scope of any
++[OASIS takes no position regarding the validity or scope of any
+ intellectual property or other rights that might be claimed to pertain
+ to the implementation or use of the technology described in this OASIS
+ Standards Final Deliverable or the extent to which any license under
+diff --git a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/pkcs11.h b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/pkcs11.h
+index 5b050def5..5933da0e3 100644
+--- a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/pkcs11.h
++++ b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/pkcs11.h
+@@ -1,8 +1,11 @@
+-/* Copyright (c) OASIS Open 2016-2019. All Rights Reserved.
+- * Distributed under the terms of the OASIS IPR Policy,
+- * [http://www.oasis-open.org/policies-guidelines/ipr], AS-IS, WITHOUT ANY
+- * IMPLIED OR EXPRESS WARRANTY; there is no warranty of MERCHANTABILITY, FITNESS FOR A
+- * PARTICULAR PURPOSE or NONINFRINGEMENT of the rights of others.
++/*
++ * PKCS #11 Specification Version 3.1
++ * OASIS Standard
++ * 23 July 2023
++ * Copyright (c) OASIS Open 2023. All Rights Reserved.
++ * Source: https://docs.oasis-open.org/pkcs11/pkcs11-spec/v3.1/os/include/pkcs11-v3.1/
++ * Latest stage of narrative specification: https://docs.oasis-open.org/pkcs11/pkcs11-spec/v3.1/pkcs11-spec-v3.1.html
++ * TC IPR Statement: https://www.oasis-open.org/committees/pkcs11/ipr.php
+  */
+ 
+ #ifndef _PKCS11_H_
+@@ -47,7 +50,7 @@ extern "C" {
+  *
+  * typedef CK_BYTE CK_PTR CK_BYTE_PTR;
+  *
+- * If you're using windows, it might be defined by:
++ * If you're using Windows, it might be defined by:
+  *
+  * #define CK_PTR *
+  *
+@@ -65,7 +68,7 @@ extern "C" {
+  *   CK_VOID_PTR pReserved
+  * );
+  *
+- * If you're using Windows to declare a function in a Win32 cryptoki .dll,
++ * If you're using Windows to declare a function in a Win32 Cryptoki .dll,
+  * it might be defined by:
+  *
+  * #define CK_DECLARE_FUNCTION(returnType, name) \
+@@ -241,4 +244,3 @@ struct CK_FUNCTION_LIST {
+ 
+ #endif /* _PKCS11_H_ */
+ 
+-
+diff --git a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/pkcs11f.h b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/pkcs11f.h
+index 0553c1dc7..80c43400d 100644
+--- a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/pkcs11f.h
++++ b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/pkcs11f.h
+@@ -1,12 +1,11 @@
+-/* Copyright (c) OASIS Open 2016, 2019. All Rights Reserved./
+- * /Distributed under the terms of the OASIS IPR Policy,
+- * [http://www.oasis-open.org/policies-guidelines/ipr], AS-IS, WITHOUT ANY
+- * IMPLIED OR EXPRESS WARRANTY; there is no warranty of MERCHANTABILITY, FITNESS FOR A
+- * PARTICULAR PURPOSE or NONINFRINGEMENT of the rights of others.
+- */
+-
+-/* Latest version of the specification:
+- * http://docs.oasis-open.org/pkcs11/pkcs11-base/v2.40/pkcs11-base-v2.40.html
++/*
++ * PKCS #11 Specification Version 3.1
++ * OASIS Standard
++ * 23 July 2023
++ * Copyright (c) OASIS Open 2023. All Rights Reserved.
++ * Source: https://docs.oasis-open.org/pkcs11/pkcs11-spec/v3.1/os/include/pkcs11-v3.1/
++ * Latest stage of narrative specification: https://docs.oasis-open.org/pkcs11/pkcs11-spec/v3.1/pkcs11-spec-v3.1.html
++ * TC IPR Statement: https://www.oasis-open.org/committees/pkcs11/ipr.php
+  */
+ 
+ /* This header file contains pretty much everything about all the
+diff --git a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/pkcs11t.h b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/pkcs11t.h
+index ab6ef326e..79d7cf7d7 100644
+--- a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/pkcs11t.h
++++ b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/pkcs11t.h
+@@ -1,12 +1,11 @@
+-/* Copyright (c) OASIS Open 2016, 2019. All Rights Reserved./
+- * /Distributed under the terms of the OASIS IPR Policy,
+- * [http://www.oasis-open.org/policies-guidelines/ipr], AS-IS, WITHOUT ANY
+- * IMPLIED OR EXPRESS WARRANTY; there is no warranty of MERCHANTABILITY, FITNESS FOR A
+- * PARTICULAR PURPOSE or NONINFRINGEMENT of the rights of others.
+- */
+-
+-/* Latest version of the specification:
+- * http://docs.oasis-open.org/pkcs11/pkcs11-base/v2.40/pkcs11-base-v2.40.html
++/*
++ * PKCS #11 Specification Version 3.1
++ * OASIS Standard
++ * 23 July 2023
++ * Copyright (c) OASIS Open 2023. All Rights Reserved.
++ * Source: https://docs.oasis-open.org/pkcs11/pkcs11-spec/v3.1/os/include/pkcs11-v3.1/
++ * Latest stage of narrative specification: https://docs.oasis-open.org/pkcs11/pkcs11-spec/v3.1/pkcs11-spec-v3.1.html
++ * TC IPR Statement: https://www.oasis-open.org/committees/pkcs11/ipr.php
+  */
+ 
+ /* See top of pkcs11.h for information about the macros that
+@@ -18,7 +17,7 @@
+ #define _PKCS11T_H_ 1
+ 
+ #define CRYPTOKI_VERSION_MAJOR          3
+-#define CRYPTOKI_VERSION_MINOR          0
++#define CRYPTOKI_VERSION_MINOR          1
+ #define CRYPTOKI_VERSION_AMENDMENT      0
+ 
+ #define CK_TRUE         1
+@@ -329,8 +328,11 @@ typedef CK_OBJECT_CLASS CK_PTR CK_OBJECT_CLASS_PTR;
+ #define CKP_EXTENDED_PROVIDER         0x00000002UL
+ #define CKP_AUTHENTICATION_TOKEN      0x00000003UL
+ #define CKP_PUBLIC_CERTIFICATES_TOKEN 0x00000004UL
++#define CKP_COMPLETE_PROVIDER         0x00000005UL
++#define CKP_HKDF_TLS_TOKEN            0x00000006UL
+ #define CKP_VENDOR_DEFINED            0x80000000UL
+ 
++
+ /* CK_HW_FEATURE_TYPE is a value that identifies the hardware feature type
+  * of an object with CK_OBJECT_CLASS equal to CKO_HW_FEATURE.
+  */
+@@ -409,9 +411,11 @@ typedef CK_ULONG          CK_KEY_TYPE;
+ #define CKK_EC_EDWARDS          0x00000040UL
+ #define CKK_EC_MONTGOMERY       0x00000041UL
+ #define CKK_HKDF                0x00000042UL
++
+ #define CKK_SHA512_224_HMAC     0x00000043UL
+ #define CKK_SHA512_256_HMAC     0x00000044UL
+ #define CKK_SHA512_T_HMAC       0x00000045UL
++#define CKK_HSS                 0x00000046UL
+ 
+ #define CKK_VENDOR_DEFINED      0x80000000UL
+ 
+@@ -481,9 +485,9 @@ typedef CK_ULONG          CK_ATTRIBUTE_TYPE;
+ #define CKA_CERTIFICATE_CATEGORY        0x00000087UL
+ #define CKA_JAVA_MIDP_SECURITY_DOMAIN   0x00000088UL
+ #define CKA_URL                         0x00000089UL
+-#define CKA_HASH_OF_SUBJECT_PUBLIC_KEY  0x0000008AUL
+-#define CKA_HASH_OF_ISSUER_PUBLIC_KEY   0x0000008BUL
+-#define CKA_NAME_HASH_ALGORITHM         0x0000008CUL
++#define CKA_HASH_OF_SUBJECT_PUBLIC_KEY  0x0000008aUL
++#define CKA_HASH_OF_ISSUER_PUBLIC_KEY   0x0000008bUL
++#define CKA_NAME_HASH_ALGORITHM         0x0000008cUL
+ #define CKA_CHECK_VALUE                 0x00000090UL
+ 
+ #define CKA_KEY_TYPE           0x00000100UL
+@@ -496,9 +500,9 @@ typedef CK_ULONG          CK_ATTRIBUTE_TYPE;
+ #define CKA_UNWRAP             0x00000107UL
+ #define CKA_SIGN               0x00000108UL
+ #define CKA_SIGN_RECOVER       0x00000109UL
+-#define CKA_VERIFY             0x0000010AUL
+-#define CKA_VERIFY_RECOVER     0x0000010BUL
+-#define CKA_DERIVE             0x0000010CUL
++#define CKA_VERIFY             0x0000010aUL
++#define CKA_VERIFY_RECOVER     0x0000010bUL
++#define CKA_DERIVE             0x0000010cUL
+ #define CKA_START_DATE         0x00000110UL
+ #define CKA_END_DATE           0x00000111UL
+ #define CKA_MODULUS            0x00000120UL
+@@ -555,12 +559,12 @@ typedef CK_ULONG          CK_ATTRIBUTE_TYPE;
+ #define CKA_OTP_TIME_REQUIREMENT      0x00000225UL
+ #define CKA_OTP_COUNTER_REQUIREMENT   0x00000226UL
+ #define CKA_OTP_PIN_REQUIREMENT       0x00000227UL
+-#define CKA_OTP_COUNTER               0x0000022EUL
+-#define CKA_OTP_TIME                  0x0000022FUL
+-#define CKA_OTP_USER_IDENTIFIER       0x0000022AUL
+-#define CKA_OTP_SERVICE_IDENTIFIER    0x0000022BUL
+-#define CKA_OTP_SERVICE_LOGO          0x0000022CUL
+-#define CKA_OTP_SERVICE_LOGO_TYPE     0x0000022DUL
++#define CKA_OTP_COUNTER               0x0000022eUL
++#define CKA_OTP_TIME                  0x0000022fUL
++#define CKA_OTP_USER_IDENTIFIER       0x0000022aUL
++#define CKA_OTP_SERVICE_IDENTIFIER    0x0000022bUL
++#define CKA_OTP_SERVICE_LOGO          0x0000022cUL
++#define CKA_OTP_SERVICE_LOGO_TYPE     0x0000022dUL
+ 
+ #define CKA_GOSTR3410_PARAMS            0x00000250UL
+ #define CKA_GOSTR3411_PARAMS            0x00000251UL
+@@ -586,6 +590,7 @@ typedef CK_ULONG          CK_ATTRIBUTE_TYPE;
+ #define CKA_SUPPORTED_CMS_ATTRIBUTES    0x00000503UL
+ #define CKA_ALLOWED_MECHANISMS          (CKF_ARRAY_ATTRIBUTE|0x00000600UL)
+ #define CKA_PROFILE_ID                  0x00000601UL
++
+ #define CKA_X2RATCHET_BAG               0x00000602UL
+ #define CKA_X2RATCHET_BAGSIZE           0x00000603UL
+ #define CKA_X2RATCHET_BOBS1STMSG        0x00000604UL
+@@ -603,6 +608,13 @@ typedef CK_ULONG          CK_ATTRIBUTE_TYPE;
+ #define CKA_X2RATCHET_NS                0x00000610UL
+ #define CKA_X2RATCHET_PNS               0x00000611UL
+ #define CKA_X2RATCHET_RK                0x00000612UL
++/* HSS */
++#define CKA_HSS_LEVELS                  0x00000617UL
++#define CKA_HSS_LMS_TYPE                0x00000618UL
++#define CKA_HSS_LMOTS_TYPE              0x00000619UL
++#define CKA_HSS_LMS_TYPES               0x0000061aUL
++#define CKA_HSS_LMOTS_TYPES             0x0000061bUL
++#define CKA_HSS_KEYS_REMAINING          0x0000061cUL
+ 
+ #define CKA_VENDOR_DEFINED              0x80000000UL
+ 
+@@ -644,11 +656,11 @@ typedef CK_ULONG          CK_MECHANISM_TYPE;
+ #define CKM_RIPEMD160_RSA_PKCS         0x00000008UL
+ #define CKM_RSA_PKCS_OAEP              0x00000009UL
+ 
+-#define CKM_RSA_X9_31_KEY_PAIR_GEN     0x0000000AUL
+-#define CKM_RSA_X9_31                  0x0000000BUL
+-#define CKM_SHA1_RSA_X9_31             0x0000000CUL
+-#define CKM_RSA_PKCS_PSS               0x0000000DUL
+-#define CKM_SHA1_RSA_PKCS_PSS          0x0000000EUL
++#define CKM_RSA_X9_31_KEY_PAIR_GEN     0x0000000aUL
++#define CKM_RSA_X9_31                  0x0000000bUL
++#define CKM_SHA1_RSA_X9_31             0x0000000cUL
++#define CKM_RSA_PKCS_PSS               0x0000000dUL
++#define CKM_SHA1_RSA_PKCS_PSS          0x0000000eUL
+ 
+ #define CKM_DSA_KEY_PAIR_GEN           0x00000010UL
+ #define CKM_DSA                        0x00000011UL
+@@ -659,8 +671,8 @@ typedef CK_ULONG          CK_MECHANISM_TYPE;
+ #define CKM_DSA_SHA512                 0x00000016UL
+ #define CKM_DSA_SHA3_224               0x00000018UL
+ #define CKM_DSA_SHA3_256               0x00000019UL
+-#define CKM_DSA_SHA3_384               0x0000001AUL
+-#define CKM_DSA_SHA3_512               0x0000001BUL
++#define CKM_DSA_SHA3_384               0x0000001aUL
++#define CKM_DSA_SHA3_512               0x0000001bUL
+ 
+ #define CKM_DH_PKCS_KEY_PAIR_GEN       0x00000020UL
+ #define CKM_DH_PKCS_DERIVE             0x00000021UL
+@@ -682,12 +694,12 @@ typedef CK_ULONG          CK_MECHANISM_TYPE;
+ 
+ #define CKM_SHA512_224                 0x00000048UL
+ #define CKM_SHA512_224_HMAC            0x00000049UL
+-#define CKM_SHA512_224_HMAC_GENERAL    0x0000004AUL
+-#define CKM_SHA512_224_KEY_DERIVATION  0x0000004BUL
+-#define CKM_SHA512_256                 0x0000004CUL
+-#define CKM_SHA512_256_HMAC            0x0000004DUL
+-#define CKM_SHA512_256_HMAC_GENERAL    0x0000004EUL
+-#define CKM_SHA512_256_KEY_DERIVATION  0x0000004FUL
++#define CKM_SHA512_224_HMAC_GENERAL    0x0000004aUL
++#define CKM_SHA512_224_KEY_DERIVATION  0x0000004bUL
++#define CKM_SHA512_256                 0x0000004cUL
++#define CKM_SHA512_256_HMAC            0x0000004dUL
++#define CKM_SHA512_256_HMAC_GENERAL    0x0000004eUL
++#define CKM_SHA512_256_KEY_DERIVATION  0x0000004fUL
+ 
+ #define CKM_SHA512_T                   0x00000050UL
+ #define CKM_SHA512_T_HMAC              0x00000051UL
+@@ -781,25 +793,25 @@ typedef CK_ULONG          CK_MECHANISM_TYPE;
+ #define CKM_SECURID                    0x00000282UL
+ #define CKM_HOTP_KEY_GEN               0x00000290UL
+ #define CKM_HOTP                       0x00000291UL
+-#define CKM_ACTI                       0x000002A0UL
+-#define CKM_ACTI_KEY_GEN               0x000002A1UL
+-
+-#define CKM_SHA3_256                   0x000002B0UL
+-#define CKM_SHA3_256_HMAC              0x000002B1UL
+-#define CKM_SHA3_256_HMAC_GENERAL      0x000002B2UL
+-#define CKM_SHA3_256_KEY_GEN           0x000002B3UL
+-#define CKM_SHA3_224                   0x000002B5UL
+-#define CKM_SHA3_224_HMAC              0x000002B6UL
+-#define CKM_SHA3_224_HMAC_GENERAL      0x000002B7UL
+-#define CKM_SHA3_224_KEY_GEN           0x000002B8UL
+-#define CKM_SHA3_384                   0x000002C0UL
+-#define CKM_SHA3_384_HMAC              0x000002C1UL
+-#define CKM_SHA3_384_HMAC_GENERAL      0x000002C2UL
+-#define CKM_SHA3_384_KEY_GEN           0x000002C3UL
+-#define CKM_SHA3_512                   0x000002D0UL
+-#define CKM_SHA3_512_HMAC              0x000002D1UL
+-#define CKM_SHA3_512_HMAC_GENERAL      0x000002D2UL
+-#define CKM_SHA3_512_KEY_GEN           0x000002D3UL
++#define CKM_ACTI                       0x000002a0UL
++#define CKM_ACTI_KEY_GEN               0x000002a1UL
++
++#define CKM_SHA3_256                   0x000002b0UL
++#define CKM_SHA3_256_HMAC              0x000002b1UL
++#define CKM_SHA3_256_HMAC_GENERAL      0x000002b2UL
++#define CKM_SHA3_256_KEY_GEN           0x000002b3UL
++#define CKM_SHA3_224                   0x000002b5UL
++#define CKM_SHA3_224_HMAC              0x000002b6UL
++#define CKM_SHA3_224_HMAC_GENERAL      0x000002b7UL
++#define CKM_SHA3_224_KEY_GEN           0x000002b8UL
++#define CKM_SHA3_384                   0x000002c0UL
++#define CKM_SHA3_384_HMAC              0x000002c1UL
++#define CKM_SHA3_384_HMAC_GENERAL      0x000002c2UL
++#define CKM_SHA3_384_KEY_GEN           0x000002c3UL
++#define CKM_SHA3_512                   0x000002d0UL
++#define CKM_SHA3_512_HMAC              0x000002d1UL
++#define CKM_SHA3_512_HMAC_GENERAL      0x000002d2UL
++#define CKM_SHA3_512_KEY_GEN           0x000002d3UL
+ 
+ 
+ #define CKM_CAST_KEY_GEN               0x00000300UL
+@@ -870,9 +882,9 @@ typedef CK_ULONG          CK_MECHANISM_TYPE;
+ #define CKM_SHA3_256_KEY_DERIVATION    0x00000397UL
+ #define CKM_SHA3_224_KEY_DERIVATION    0x00000398UL
+ #define CKM_SHA3_384_KEY_DERIVATION    0x00000399UL
+-#define CKM_SHA3_512_KEY_DERIVATION    0x0000039AUL
+-#define CKM_SHAKE_128_KEY_DERIVATION   0x0000039BUL
+-#define CKM_SHAKE_256_KEY_DERIVATION   0x0000039CUL
++#define CKM_SHA3_512_KEY_DERIVATION    0x0000039aUL
++#define CKM_SHAKE_128_KEY_DERIVATION   0x0000039bUL
++#define CKM_SHAKE_256_KEY_DERIVATION   0x0000039cUL
+ #define CKM_SHA3_256_KEY_DERIVE  CKM_SHA3_256_KEY_DERIVATION
+ #define CKM_SHA3_224_KEY_DERIVE  CKM_SHA3_224_KEY_DERIVATION
+ #define CKM_SHA3_384_KEY_DERIVE  CKM_SHA3_384_KEY_DERIVATION
+@@ -880,40 +892,42 @@ typedef CK_ULONG          CK_MECHANISM_TYPE;
+ #define CKM_SHAKE_128_KEY_DERIVE CKM_SHAKE_128_KEY_DERIVATION
+ #define CKM_SHAKE_256_KEY_DERIVE CKM_SHAKE_256_KEY_DERIVATION
+ 
+-#define CKM_PBE_MD2_DES_CBC            0x000003A0UL
+-#define CKM_PBE_MD5_DES_CBC            0x000003A1UL
+-#define CKM_PBE_MD5_CAST_CBC           0x000003A2UL
+-#define CKM_PBE_MD5_CAST3_CBC          0x000003A3UL
+-#define CKM_PBE_MD5_CAST5_CBC          0x000003A4UL /* Deprecated */
+-#define CKM_PBE_MD5_CAST128_CBC        0x000003A4UL
+-#define CKM_PBE_SHA1_CAST5_CBC         0x000003A5UL /* Deprecated */
+-#define CKM_PBE_SHA1_CAST128_CBC       0x000003A5UL
+-#define CKM_PBE_SHA1_RC4_128           0x000003A6UL
+-#define CKM_PBE_SHA1_RC4_40            0x000003A7UL
+-#define CKM_PBE_SHA1_DES3_EDE_CBC      0x000003A8UL
+-#define CKM_PBE_SHA1_DES2_EDE_CBC      0x000003A9UL
+-#define CKM_PBE_SHA1_RC2_128_CBC       0x000003AAUL
+-#define CKM_PBE_SHA1_RC2_40_CBC        0x000003ABUL
+-
+-#define CKM_PKCS5_PBKD2                0x000003B0UL
+-
+-#define CKM_PBA_SHA1_WITH_SHA1_HMAC    0x000003C0UL
+-
+-#define CKM_WTLS_PRE_MASTER_KEY_GEN         0x000003D0UL
+-#define CKM_WTLS_MASTER_KEY_DERIVE          0x000003D1UL
+-#define CKM_WTLS_MASTER_KEY_DERIVE_DH_ECC   0x000003D2UL
+-#define CKM_WTLS_PRF                        0x000003D3UL
+-#define CKM_WTLS_SERVER_KEY_AND_MAC_DERIVE  0x000003D4UL
+-#define CKM_WTLS_CLIENT_KEY_AND_MAC_DERIVE  0x000003D5UL
+-
+-#define CKM_TLS12_MAC                       0x000003D8UL
+-#define CKM_TLS12_KDF                       0x000003D9UL
+-#define CKM_TLS12_MASTER_KEY_DERIVE         0x000003E0UL
+-#define CKM_TLS12_KEY_AND_MAC_DERIVE        0x000003E1UL
+-#define CKM_TLS12_MASTER_KEY_DERIVE_DH      0x000003E2UL
+-#define CKM_TLS12_KEY_SAFE_DERIVE           0x000003E3UL
+-#define CKM_TLS_MAC                         0x000003E4UL
+-#define CKM_TLS_KDF                         0x000003E5UL
++#define CKM_PBE_MD2_DES_CBC            0x000003a0UL
++#define CKM_PBE_MD5_DES_CBC            0x000003a1UL
++#define CKM_PBE_MD5_CAST_CBC           0x000003a2UL
++#define CKM_PBE_MD5_CAST3_CBC          0x000003a3UL
++#define CKM_PBE_MD5_CAST5_CBC          0x000003a4UL /* Deprecated */
++#define CKM_PBE_MD5_CAST128_CBC        0x000003a4UL
++#define CKM_PBE_SHA1_CAST5_CBC         0x000003a5UL /* Deprecated */
++#define CKM_PBE_SHA1_CAST128_CBC       0x000003a5UL
++#define CKM_PBE_SHA1_RC4_128           0x000003a6UL
++#define CKM_PBE_SHA1_RC4_40            0x000003a7UL
++#define CKM_PBE_SHA1_DES3_EDE_CBC      0x000003a8UL
++#define CKM_PBE_SHA1_DES2_EDE_CBC      0x000003a9UL
++#define CKM_PBE_SHA1_RC2_128_CBC       0x000003aaUL
++#define CKM_PBE_SHA1_RC2_40_CBC        0x000003abUL
++
++#define CKM_PKCS5_PBKD2                0x000003b0UL
++
++#define CKM_PBA_SHA1_WITH_SHA1_HMAC    0x000003c0UL
++
++#define CKM_WTLS_PRE_MASTER_KEY_GEN         0x000003d0UL
++#define CKM_WTLS_MASTER_KEY_DERIVE          0x000003d1UL
++#define CKM_WTLS_MASTER_KEY_DERIVE_DH_ECC   0x000003d2UL
++#define CKM_WTLS_PRF                        0x000003d3UL
++#define CKM_WTLS_SERVER_KEY_AND_MAC_DERIVE  0x000003d4UL
++#define CKM_WTLS_CLIENT_KEY_AND_MAC_DERIVE  0x000003d5UL
++
++#define CKM_TLS10_MAC_SERVER                0x000003d6UL
++#define CKM_TLS10_MAC_CLIENT                0x000003d7UL
++#define CKM_TLS12_MAC                       0x000003d8UL
++#define CKM_TLS12_KDF                       0x000003d9UL
++#define CKM_TLS12_MASTER_KEY_DERIVE         0x000003e0UL
++#define CKM_TLS12_KEY_AND_MAC_DERIVE        0x000003e1UL
++#define CKM_TLS12_MASTER_KEY_DERIVE_DH      0x000003e2UL
++#define CKM_TLS12_KEY_SAFE_DERIVE           0x000003e3UL
++#define CKM_TLS_MAC                         0x000003e4UL
++#define CKM_TLS_KDF                         0x000003e5UL
+ 
+ #define CKM_KEY_WRAP_LYNKS             0x00000400UL
+ #define CKM_KEY_WRAP_SET_OAEP          0x00000401UL
+@@ -983,7 +997,7 @@ typedef CK_ULONG          CK_MECHANISM_TYPE;
+ #define CKM_ECDSA_SHA256               0x00001044UL
+ #define CKM_ECDSA_SHA384               0x00001045UL
+ #define CKM_ECDSA_SHA512               0x00001046UL
+-#define CKM_EC_KEY_PAIR_GEN_W_EXTRA_BITS 0x0000140BUL
++#define CKM_EC_KEY_PAIR_GEN_W_EXTRA_BITS 0x0000140bUL
+ 
+ #define CKM_ECDH1_DERIVE               0x00001050UL
+ #define CKM_ECDH1_COFACTOR_DERIVE      0x00001051UL
+@@ -1012,12 +1026,12 @@ typedef CK_ULONG          CK_MECHANISM_TYPE;
+ #define CKM_AES_GCM                    0x00001087UL
+ #define CKM_AES_CCM                    0x00001088UL
+ #define CKM_AES_CTS                    0x00001089UL
+-#define CKM_AES_CMAC                   0x0000108AUL
+-#define CKM_AES_CMAC_GENERAL           0x0000108BUL
++#define CKM_AES_CMAC                   0x0000108aUL
++#define CKM_AES_CMAC_GENERAL           0x0000108bUL
+ 
+-#define CKM_AES_XCBC_MAC               0x0000108CUL
+-#define CKM_AES_XCBC_MAC_96            0x0000108DUL
+-#define CKM_AES_GMAC                   0x0000108EUL
++#define CKM_AES_XCBC_MAC               0x0000108cUL
++#define CKM_AES_XCBC_MAC_96            0x0000108dUL
++#define CKM_AES_GMAC                   0x0000108eUL
+ 
+ #define CKM_BLOWFISH_KEY_GEN           0x00001090UL
+ #define CKM_BLOWFISH_CBC               0x00001091UL
+@@ -1066,6 +1080,7 @@ typedef CK_ULONG          CK_MECHANISM_TYPE;
+ #define CKM_AES_KEY_WRAP               0x00002109UL     /* WAS: 0x00001090 */
+ #define CKM_AES_KEY_WRAP_PAD           0x0000210AUL     /* WAS: 0x00001091 */
+ #define CKM_AES_KEY_WRAP_KWP           0x0000210BUL
++#define CKM_AES_KEY_WRAP_PKCS7         0x0000210CUL
+ 
+ #define CKM_RSA_PKCS_TPM_1_1           0x00004001UL
+ #define CKM_RSA_PKCS_OAEP_TPM_1_1      0x00004002UL
+@@ -1125,6 +1140,14 @@ typedef CK_ULONG          CK_MECHANISM_TYPE;
+ #define CKM_SP800_108_FEEDBACK_KDF     0x000003adUL
+ #define CKM_SP800_108_DOUBLE_PIPELINE_KDF 0x000003aeUL
+ 
++#define CKM_IKE2_PRF_PLUS_DERIVE       0x0000402eUL
++#define CKM_IKE_PRF_DERIVE             0x0000402fUL
++#define CKM_IKE1_PRF_DERIVE            0x00004030UL
++#define CKM_IKE1_EXTENDED_DERIVE       0x00004031UL
++#define CKM_HSS_KEY_PAIR_GEN           0x00004032UL
++#define CKM_HSS                        0x00004033UL
++
++
+ #define CKM_VENDOR_DEFINED             0x80000000UL
+ 
+ typedef CK_MECHANISM_TYPE CK_PTR CK_MECHANISM_TYPE_PTR;
+@@ -1320,6 +1343,7 @@ typedef CK_ULONG          CK_RV;
+ #define CKR_FUNCTION_REJECTED                 0x00000200UL
+ #define CKR_TOKEN_RESOURCE_EXCEEDED           0x00000201UL
+ #define CKR_OPERATION_CANCEL_FAILED           0x00000202UL
++#define CKR_KEY_EXHAUSTED                     0x00000203UL
+ 
+ #define CKR_VENDOR_DEFINED                    0x80000000UL
+ 
+@@ -1436,6 +1460,7 @@ typedef CK_RSA_PKCS_MGF_TYPE CK_PTR CK_RSA_PKCS_MGF_TYPE_PTR;
+ #define CKG_MGF1_SHA3_384     0x00000008UL
+ #define CKG_MGF1_SHA3_512     0x00000009UL
+ 
++
+ /* CK_RSA_PKCS_OAEP_SOURCE_TYPE  is used to indicate the source
+  * of the encoding parameter when formatting a message block
+  * for the PKCS #1 OAEP encryption scheme.
+@@ -1701,8 +1726,7 @@ typedef struct CK_DES_CBC_ENCRYPT_DATA_PARAMS {
+     CK_ULONG    length;
+ } CK_DES_CBC_ENCRYPT_DATA_PARAMS;
+ 
+-typedef CK_DES_CBC_ENCRYPT_DATA_PARAMS CK_PTR \
+-        CK_DES_CBC_ENCRYPT_DATA_PARAMS_PTR;
++typedef CK_DES_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_DES_CBC_ENCRYPT_DATA_PARAMS_PTR;
+ 
+ typedef struct CK_AES_CBC_ENCRYPT_DATA_PARAMS {
+     CK_BYTE     iv[16];
+@@ -1710,8 +1734,7 @@ typedef struct CK_AES_CBC_ENCRYPT_DATA_PARAMS {
+     CK_ULONG    length;
+ } CK_AES_CBC_ENCRYPT_DATA_PARAMS;
+ 
+-typedef CK_AES_CBC_ENCRYPT_DATA_PARAMS CK_PTR \
+-        CK_AES_CBC_ENCRYPT_DATA_PARAMS_PTR;
++typedef CK_AES_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_AES_CBC_ENCRYPT_DATA_PARAMS_PTR;
+ 
+ /* CK_SKIPJACK_PRIVATE_WRAP_PARAMS provides the parameters to the
+  * CKM_SKIPJACK_PRIVATE_WRAP mechanism
+@@ -2051,6 +2074,7 @@ typedef CK_ULONG CK_GENERATOR_FUNCTION;
+ #define CKG_GENERATE         0x00000001UL
+ #define CKG_GENERATE_COUNTER 0x00000002UL
+ #define CKG_GENERATE_RANDOM  0x00000003UL
++#define CKG_GENERATE_COUNTER_XOR 0x00000004UL
+ 
+ typedef struct CK_GCM_MESSAGE_PARAMS {
+     CK_BYTE_PTR           pIv;
+@@ -2061,7 +2085,7 @@ typedef struct CK_GCM_MESSAGE_PARAMS {
+     CK_ULONG              ulTagBits;
+ } CK_GCM_MESSAGE_PARAMS;
+ 
+-typedef CK_GCM_MESSAGE_PARAMS CK_GCM_MESSAGE_PARAMS_PTR;
++typedef CK_GCM_MESSAGE_PARAMS CK_PTR CK_GCM_MESSAGE_PARAMS_PTR;
+ 
+ typedef struct CK_CCM_PARAMS {
+     CK_ULONG    ulDataLen;
+@@ -2084,7 +2108,7 @@ typedef struct CK_CCM_MESSAGE_PARAMS {
+     CK_ULONG              ulMACLen;
+ } CK_CCM_MESSAGE_PARAMS;
+ 
+-typedef CK_CCM_MESSAGE_PARAMS CK_CCM_MESSAGE_PARAMS_PTR;
++typedef CK_CCM_MESSAGE_PARAMS CK_PTR CK_CCM_MESSAGE_PARAMS_PTR;
+ 
+ /* Deprecated. Use CK_GCM_PARAMS */
+ typedef struct CK_AES_GCM_PARAMS {
+@@ -2339,7 +2363,6 @@ typedef struct CK_SALSA20_PARAMS {
+     CK_BYTE_PTR pNonce;
+     CK_ULONG    ulNonceBits;
+ } CK_SALSA20_PARAMS;
+-
+ typedef CK_SALSA20_PARAMS CK_PTR CK_SALSA20_PARAMS_PTR;
+ 
+ typedef struct CK_SALSA20_CHACHA20_POLY1305_PARAMS {
+@@ -2423,6 +2446,7 @@ typedef struct CK_XEDDSA_PARAMS {
+ } CK_XEDDSA_PARAMS;
+ typedef CK_XEDDSA_PARAMS CK_PTR CK_XEDDSA_PARAMS_PTR;
+ 
++/* HKDF params */
+ typedef struct CK_HKDF_PARAMS {
+     CK_BBOOL          bExtract;
+     CK_BBOOL          bExpand;
+@@ -2440,5 +2464,60 @@ typedef CK_HKDF_PARAMS CK_PTR CK_HKDF_PARAMS_PTR;
+ #define CKF_HKDF_SALT_DATA   0x00000002UL
+ #define CKF_HKDF_SALT_KEY    0x00000004UL
+ 
++/* HSS */
++typedef CK_ULONG                   CK_HSS_LEVELS;
++typedef CK_ULONG                   CK_LMS_TYPE;
++typedef CK_ULONG                   CK_LMOTS_TYPE;
++
++typedef struct specifiedParams {
++    CK_HSS_LEVELS levels;
++    CK_LMS_TYPE   lm_type[8];
++    CK_LMOTS_TYPE lm_ots_type[8];
++} specifiedParams;
++
++/* IKE Params */
++typedef struct CK_IKE2_PRF_PLUS_DERIVE_PARAMS {
++    CK_MECHANISM_TYPE prfMechanism;
++    CK_BBOOL          bHasSeedKey;
++    CK_OBJECT_HANDLE  hSeedKey;
++    CK_BYTE_PTR       pSeedData;
++    CK_ULONG          ulSeedDataLen;
++} CK_IKE2_PRF_PLUS_DERIVE_PARAMS;
++typedef CK_IKE2_PRF_PLUS_DERIVE_PARAMS CK_PTR CK_IKE2_PRF_PLUS_DERIVE_PARAMS_PTR;
++
++typedef struct CK_IKE_PRF_DERIVE_PARAMS {
++    CK_MECHANISM_TYPE prfMechanism;
++    CK_BBOOL          bDataAsKey;
++    CK_BBOOL          bRekey;
++    CK_BYTE_PTR       pNi;
++    CK_ULONG          ulNiLen;
++    CK_BYTE_PTR       pNr;
++    CK_ULONG          ulNrLen;
++    CK_OBJECT_HANDLE  hNewKey;
++} CK_IKE_PRF_DERIVE_PARAMS;
++typedef CK_IKE_PRF_DERIVE_PARAMS CK_PTR CK_IKE_PRF_DERIVE_PARAMS_PTR;
++
++typedef struct CK_IKE1_PRF_DERIVE_PARAMS {
++    CK_MECHANISM_TYPE prfMechanism;
++    CK_BBOOL          bHasPrevKey;
++    CK_OBJECT_HANDLE  hKeygxy;
++    CK_OBJECT_HANDLE  hPrevKey;
++    CK_BYTE_PTR       pCKYi;
++    CK_ULONG          ulCKYiLen;
++    CK_BYTE_PTR       pCKYr;
++    CK_ULONG          ulCKYrLen;
++    CK_BYTE           keyNumber;
++} CK_IKE1_PRF_DERIVE_PARAMS;
++typedef CK_IKE1_PRF_DERIVE_PARAMS CK_PTR CK_IKE1_PRF_DERIVE_PARAMS_PTR;
++
++typedef struct CK_IKE1_EXTENDED_DERIVE_PARAMS {
++    CK_MECHANISM_TYPE prfMechanism;
++    CK_BBOOL          bHasKeygxy;
++    CK_OBJECT_HANDLE  hKeygxy;
++    CK_BYTE_PTR       pExtraData;
++    CK_ULONG          ulExtraDataLen;
++} CK_IKE1_EXTENDED_DERIVE_PARAMS;
++typedef CK_IKE1_EXTENDED_DERIVE_PARAMS CK_PTR CK_IKE1_EXTENDED_DERIVE_PARAMS_PTR;
++
+ #endif /* _PKCS11T_H_ */
+ 
+diff --git a/src/jdk.hotspot.agent/linux/native/libsaproc/LinuxDebuggerLocal.c b/src/jdk.hotspot.agent/linux/native/libsaproc/LinuxDebuggerLocal.c
+index 0d834302c..6afafea09 100644
+--- a/src/jdk.hotspot.agent/linux/native/libsaproc/LinuxDebuggerLocal.c
++++ b/src/jdk.hotspot.agent/linux/native/libsaproc/LinuxDebuggerLocal.c
+@@ -22,6 +22,13 @@
+  *
+  */
+ 
++/*
++ * This file has been modified by Loongson Technology in 2022. These
++ * modifications are Copyright (c) 2021, 2022, Loongson Technology, and are made
++ * available on the same license terms set forth above.
++ *
++ */
++
+ #include 
+ #include "libproc.h"
+ #include "proc_service.h"
+@@ -54,10 +61,18 @@
+ #include "sun_jvm_hotspot_debugger_ppc64_PPC64ThreadContext.h"
+ #endif
+ 
++#if defined(mips64) || defined(mips64el)
++#include "sun_jvm_hotspot_debugger_mips64_MIPS64ThreadContext.h"
++#endif
++
+ #ifdef aarch64
+ #include "sun_jvm_hotspot_debugger_aarch64_AARCH64ThreadContext.h"
+ #endif
+ 
++#ifdef loongarch64
++#include "sun_jvm_hotspot_debugger_loongarch64_LOONGARCH64ThreadContext.h"
++#endif
++
+ static jfieldID p_ps_prochandle_ID = 0;
+ static jfieldID threadList_ID = 0;
+ static jfieldID loadObjectList_ID = 0;
+@@ -397,7 +412,7 @@ JNIEXPORT jbyteArray JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLo
+   return (err == PS_OK)? array : 0;
+ }
+ 
+-#if defined(i386) || defined(amd64) || defined(sparc) || defined(sparcv9) | defined(ppc64) || defined(ppc64le) || defined(aarch64)
++#if defined(i386) || defined(amd64) || defined(sparc) || defined(sparcv9) | defined(ppc64) || defined(ppc64le) || defined(aarch64) || defined(loongarch64)
+ JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_getThreadIntegerRegisterSet0
+   (JNIEnv *env, jobject this_obj, jint lwp_id) {
+ 
+@@ -425,8 +440,14 @@ JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLo
+ #if defined(sparc) || defined(sparcv9)
+ #define NPRGREG sun_jvm_hotspot_debugger_sparc_SPARCThreadContext_NPRGREG
+ #endif
++#ifdef loongarch64
++#define NPRGREG sun_jvm_hotspot_debugger_loongarch64_LOONGARCH64ThreadContext_NPRGREG
++#endif
+ #if defined(ppc64) || defined(ppc64le)
+ #define NPRGREG sun_jvm_hotspot_debugger_ppc64_PPC64ThreadContext_NPRGREG
++#endif
++#if defined(mips64) || defined(mips64el)
++#define NPRGREG sun_jvm_hotspot_debugger_mips64_MIPS64ThreadContext_NPRGREG
+ #endif
+ 
+ 
+@@ -534,6 +555,18 @@ JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLo
+   }
+ #endif /* aarch64 */
+ 
++#if defined(loongarch64)
++
++#define REG_INDEX(reg) sun_jvm_hotspot_debugger_loongarch64_LOONGARCH64ThreadContext_##reg
++
++  {
++    int i;
++    for (i = 0; i < 31; i++)
++      regs[i] = gregs.regs[i];
++    regs[REG_INDEX(PC)] = gregs.csr_era;
++  }
++#endif /* loongarch64 */
++
+ #if defined(ppc64) || defined(ppc64le)
+ #define REG_INDEX(reg) sun_jvm_hotspot_debugger_ppc64_PPC64ThreadContext_##reg
+ 
+@@ -574,6 +607,45 @@ JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLo
+ 
+ #endif
+ 
++#if defined(mips64) || defined(mips64el)
++
++#define REG_INDEX(reg) sun_jvm_hotspot_debugger_mips64_MIPS64ThreadContext_##reg
++
++  regs[REG_INDEX(ZERO)]  = gregs.regs[0];
++  regs[REG_INDEX(AT)]  = gregs.regs[1];
++  regs[REG_INDEX(V0)]  = gregs.regs[2];
++  regs[REG_INDEX(V1)]  = gregs.regs[3];
++  regs[REG_INDEX(A0)]  = gregs.regs[4];
++  regs[REG_INDEX(A1)]  = gregs.regs[5];
++  regs[REG_INDEX(A2)]  = gregs.regs[6];
++  regs[REG_INDEX(A3)]  = gregs.regs[7];
++  regs[REG_INDEX(T0)]  = gregs.regs[8];
++  regs[REG_INDEX(T1)]  = gregs.regs[9];
++  regs[REG_INDEX(T2)]  = gregs.regs[10];
++  regs[REG_INDEX(T3)]  = gregs.regs[11];
++  regs[REG_INDEX(T4)]  = gregs.regs[12];
++  regs[REG_INDEX(T5)]  = gregs.regs[13];
++  regs[REG_INDEX(T6)]  = gregs.regs[14];
++  regs[REG_INDEX(T7)]  = gregs.regs[15];
++  regs[REG_INDEX(S0)]  = gregs.regs[16];
++  regs[REG_INDEX(S1)]  = gregs.regs[17];
++  regs[REG_INDEX(S2)]  = gregs.regs[18];
++  regs[REG_INDEX(S3)]  = gregs.regs[19];
++  regs[REG_INDEX(S4)]  = gregs.regs[20];
++  regs[REG_INDEX(S5)]  = gregs.regs[21];
++  regs[REG_INDEX(S6)]  = gregs.regs[22];
++  regs[REG_INDEX(S7)]  = gregs.regs[23];
++  regs[REG_INDEX(T8)]  = gregs.regs[24];
++  regs[REG_INDEX(T9)]  = gregs.regs[25];
++  regs[REG_INDEX(K0)]  = gregs.regs[26];
++  regs[REG_INDEX(K1)]  = gregs.regs[27];
++  regs[REG_INDEX(GP)]  = gregs.regs[28];
++  regs[REG_INDEX(SP)]  = gregs.regs[29];
++  regs[REG_INDEX(FP)]  = gregs.regs[30];
++  regs[REG_INDEX(S8)]  = gregs.regs[30];
++  regs[REG_INDEX(RA)]  = gregs.regs[31];
++#endif /* mips */
++
+   (*env)->ReleaseLongArrayElements(env, array, regs, JNI_COMMIT);
+   return array;
+ }
+diff --git a/src/jdk.hotspot.agent/linux/native/libsaproc/libproc.h b/src/jdk.hotspot.agent/linux/native/libsaproc/libproc.h
+index 8318e8e02..07064e76e 100644
+--- a/src/jdk.hotspot.agent/linux/native/libsaproc/libproc.h
++++ b/src/jdk.hotspot.agent/linux/native/libsaproc/libproc.h
+@@ -22,6 +22,13 @@
+  *
+  */
+ 
++/*
++ * This file has been modified by Loongson Technology in 2022. These
++ * modifications are Copyright (c) 2022, Loongson Technology, and are made
++ * available on the same license terms set forth above.
++ *
++ */
++
+ #ifndef _LIBPROC_H_
+ #define _LIBPROC_H_
+ 
+@@ -37,13 +44,17 @@
+ #include 
+ #define user_regs_struct  pt_regs
+ #endif
+-#if defined(aarch64) || defined(arm64)
++#if defined(aarch64) || defined(arm64) || defined(loongarch64)
+ #include 
+ #define user_regs_struct user_pt_regs
+ #elif defined(arm)
+ #include 
+ #define user_regs_struct  pt_regs
+ #endif
++#if defined(mips) || defined(mipsel) || defined(mips64) || defined(mips64el)
++#include 
++#define user_regs_struct  pt_regs
++#endif
+ 
+ // This C bool type must be int for compatibility with Linux calls and
+ // it would be a mistake to equivalence it to C++ bool on many platforms
+diff --git a/src/jdk.hotspot.agent/linux/native/libsaproc/ps_proc.c b/src/jdk.hotspot.agent/linux/native/libsaproc/ps_proc.c
+index c22b5d1cb..36d634396 100644
+--- a/src/jdk.hotspot.agent/linux/native/libsaproc/ps_proc.c
++++ b/src/jdk.hotspot.agent/linux/native/libsaproc/ps_proc.c
+@@ -22,6 +22,12 @@
+  *
+  */
+ 
++/*
++ * This file has been modified by Loongson Technology in 2022, These
++ * modifications are Copyright (c) 2022, Loongson Technology, and are made
++ * available on the same license terms set forth above.
++ */
++
+ #include 
+ #include 
+ #include 
+@@ -151,7 +157,7 @@ static bool process_get_lwp_regs(struct ps_prochandle* ph, pid_t pid, struct use
+    return false;
+  }
+  return true;
+-#elif defined(PTRACE_GETREGS_REQ)
++#elif defined(PTRACE_GETREGS_REQ) && !defined(loongarch64)
+  if (ptrace_getregs(PTRACE_GETREGS_REQ, pid, user, NULL) < 0) {
+    print_debug("ptrace(PTRACE_GETREGS, ...) failed for lwp %d\n", pid);
+    return false;
+diff --git a/src/jdk.hotspot.agent/macosx/native/libsaproc/ps_core.c b/src/jdk.hotspot.agent/macosx/native/libsaproc/ps_core.c
+index 9228522e6..dc66033e4 100644
+--- a/src/jdk.hotspot.agent/macosx/native/libsaproc/ps_core.c
++++ b/src/jdk.hotspot.agent/macosx/native/libsaproc/ps_core.c
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved.
+  * Copyright (c) 2021, Azul Systems, Inc. All rights reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+@@ -622,11 +622,16 @@ static bool read_core_segments(struct ps_prochandle* ph) {
+         print_debug("failed to read LC_SEGMENT_64 i = %d!\n", i);
+         goto err;
+       }
+-      if (add_map_info(ph, fd, segcmd.fileoff, segcmd.vmaddr, segcmd.vmsize) == NULL) {
+-        print_debug("Failed to add map_info at i = %d\n", i);
+-        goto err;
++      // The base of the library is offset by a random amount which ends up as a load command with a
++      // filesize of 0.  This must be ignored otherwise the base address of the library is wrong.
++      if (segcmd.filesize != 0) {
++        if (add_map_info(ph, fd, segcmd.fileoff, segcmd.vmaddr, segcmd.vmsize) == NULL) {
++          print_debug("Failed to add map_info at i = %d\n", i);
++          goto err;
++        }
+       }
+-      print_debug("LC_SEGMENT_64 added: nsects=%d fileoff=0x%llx vmaddr=0x%llx vmsize=0x%llx filesize=0x%llx %s\n",
++      print_debug("LC_SEGMENT_64 %s: nsects=%d fileoff=0x%llx vmaddr=0x%llx vmsize=0x%llx filesize=0x%llx %s\n",
++                  segcmd.filesize == 0 ? "with filesize == 0 ignored" : "added",
+                   segcmd.nsects, segcmd.fileoff, segcmd.vmaddr, segcmd.vmsize,
+                   segcmd.filesize, &segcmd.segname[0]);
+     } else if (lcmd.cmd == LC_THREAD || lcmd.cmd == LC_UNIXTHREAD) {
+diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/HotSpotAgent.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/HotSpotAgent.java
+index 0f5f0119c..1b2f11a06 100644
+--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/HotSpotAgent.java
++++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/HotSpotAgent.java
+@@ -23,6 +23,12 @@
+  *
+  */
+ 
++/*
++ * This file has been modified by Loongson Technology in 2021. These
++ * modifications are Copyright (c) 2018, 2021, Loongson Technology, and are made
++ * available on the same license terms set forth above.
++ *
++ */
+ package sun.jvm.hotspot;
+ 
+ import java.rmi.RemoteException;
+@@ -39,6 +45,8 @@ import sun.jvm.hotspot.debugger.MachineDescriptionAArch64;
+ import sun.jvm.hotspot.debugger.MachineDescriptionIntelX86;
+ import sun.jvm.hotspot.debugger.MachineDescriptionSPARC32Bit;
+ import sun.jvm.hotspot.debugger.MachineDescriptionSPARC64Bit;
++import sun.jvm.hotspot.debugger.MachineDescriptionMIPS64;
++import sun.jvm.hotspot.debugger.MachineDescriptionLOONGARCH64;
+ import sun.jvm.hotspot.debugger.NoSuchSymbolException;
+ import sun.jvm.hotspot.debugger.bsd.BsdDebuggerLocal;
+ import sun.jvm.hotspot.debugger.linux.LinuxDebuggerLocal;
+@@ -598,6 +606,10 @@ public class HotSpotAgent {
+             } else {
+                     machDesc = new MachineDescriptionSPARC32Bit();
+             }
++        } else if (cpu.equals("mips64")) {
++            machDesc = new MachineDescriptionMIPS64();
++        } else if (cpu.equals("loongarch64")) {
++            machDesc = new MachineDescriptionLOONGARCH64();
+         } else {
+           try {
+             machDesc = (MachineDescription)
+diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/MachineDescriptionLOONGARCH64.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/MachineDescriptionLOONGARCH64.java
+new file mode 100644
+index 000000000..99cea8c7f
+--- /dev/null
++++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/MachineDescriptionLOONGARCH64.java
+@@ -0,0 +1,41 @@
++/*
++ * Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2018, 2021, Loongson Technology. 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 sun.jvm.hotspot.debugger;
++
++public class MachineDescriptionLOONGARCH64 extends MachineDescriptionTwosComplement implements MachineDescription {
++  public long getAddressSize() {
++    return 8;
++  }
++
++
++  public boolean isBigEndian() {
++    return false;
++  }
++
++  public boolean isLP64() {
++    return true;
++  }
++}
+diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/MachineDescriptionMIPS64.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/MachineDescriptionMIPS64.java
+new file mode 100644
+index 000000000..1b49efd20
+--- /dev/null
++++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/MachineDescriptionMIPS64.java
+@@ -0,0 +1,41 @@
++/*
++ * Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2018, Loongson Technology. 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 sun.jvm.hotspot.debugger;
++
++public class MachineDescriptionMIPS64 extends MachineDescriptionTwosComplement implements MachineDescription {
++  public long getAddressSize() {
++    return 8;
++  }
++
++
++  public boolean isBigEndian() {
++    return "big".equals(System.getProperty("sun.cpu.endian"));
++  }
++
++  public boolean isLP64() {
++    return true;
++  }
++}
+diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxCDebugger.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxCDebugger.java
+index 5e5a6bb71..7d7f6424e 100644
+--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxCDebugger.java
++++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxCDebugger.java
+@@ -23,6 +23,12 @@
+  *
+  */
+ 
++/*
++ * This file has been modified by Loongson Technology in 2022, These
++ * modifications are Copyright (c) 2019, 2022, Loongson Technology, and are made
++ * available on the same license terms set forth above.
++ */
++
+ package sun.jvm.hotspot.debugger.linux;
+ 
+ import java.io.*;
+@@ -34,12 +40,16 @@ import sun.jvm.hotspot.debugger.x86.*;
+ import sun.jvm.hotspot.debugger.amd64.*;
+ import sun.jvm.hotspot.debugger.aarch64.*;
+ import sun.jvm.hotspot.debugger.sparc.*;
++import sun.jvm.hotspot.debugger.mips64.*;
++import sun.jvm.hotspot.debugger.loongarch64.*;
+ import sun.jvm.hotspot.debugger.ppc64.*;
+ import sun.jvm.hotspot.debugger.linux.x86.*;
+ import sun.jvm.hotspot.debugger.linux.amd64.*;
+ import sun.jvm.hotspot.debugger.linux.sparc.*;
+ import sun.jvm.hotspot.debugger.linux.ppc64.*;
+ import sun.jvm.hotspot.debugger.linux.aarch64.*;
++import sun.jvm.hotspot.debugger.linux.mips64.*;
++import sun.jvm.hotspot.debugger.linux.loongarch64.*;
+ import sun.jvm.hotspot.utilities.*;
+ 
+ class LinuxCDebugger implements CDebugger {
+@@ -102,7 +112,21 @@ class LinuxCDebugger implements CDebugger {
+        Address pc  = context.getRegisterAsAddress(SPARCThreadContext.R_O7);
+        if (pc == null) return null;
+        return new LinuxSPARCCFrame(dbg, sp, pc, LinuxDebuggerLocal.getAddressSize());
+-    }  else if (cpu.equals("ppc64")) {
++    } else if (cpu.equals("mips64")) {
++       MIPS64ThreadContext context = (MIPS64ThreadContext) thread.getContext();
++       Address sp = context.getRegisterAsAddress(MIPS64ThreadContext.SP);
++       if (sp == null) return null;
++       Address pc  = context.getRegisterAsAddress(MIPS64ThreadContext.PC);
++       if (pc == null) return null;
++       return new LinuxMIPS64CFrame(dbg, sp, pc);
++    } else if (cpu.equals("loongarch64")) {
++       LOONGARCH64ThreadContext context = (LOONGARCH64ThreadContext) thread.getContext();
++       Address fp = context.getRegisterAsAddress(LOONGARCH64ThreadContext.FP);
++       if (fp == null) return null;
++       Address pc  = context.getRegisterAsAddress(LOONGARCH64ThreadContext.PC);
++       if (pc == null) return null;
++       return new LinuxLOONGARCH64CFrame(dbg, fp, pc);
++    } else if (cpu.equals("ppc64")) {
+         PPC64ThreadContext context = (PPC64ThreadContext) thread.getContext();
+         Address sp = context.getRegisterAsAddress(PPC64ThreadContext.SP);
+         if (sp == null) return null;
+diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxThreadContextFactory.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxThreadContextFactory.java
+index 4b786eecc..4ead33827 100644
+--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxThreadContextFactory.java
++++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxThreadContextFactory.java
+@@ -22,6 +22,12 @@
+  *
+  */
+ 
++/*
++ * This file has been modified by Loongson Technology in 2021, These
++ * modifications are Copyright (c) 2019, 2021, Loongson Technology, and are made
++ * available on the same license terms set forth above.
++ */
++
+ package sun.jvm.hotspot.debugger.linux;
+ 
+ import java.lang.reflect.*;
+@@ -30,6 +36,8 @@ import sun.jvm.hotspot.debugger.linux.amd64.*;
+ import sun.jvm.hotspot.debugger.linux.x86.*;
+ import sun.jvm.hotspot.debugger.linux.ppc64.*;
+ import sun.jvm.hotspot.debugger.linux.sparc.*;
++import sun.jvm.hotspot.debugger.linux.mips64.*;
++import sun.jvm.hotspot.debugger.linux.loongarch64.*;
+ 
+ class LinuxThreadContextFactory {
+    static ThreadContext createThreadContext(LinuxDebugger dbg) {
+@@ -40,7 +48,11 @@ class LinuxThreadContextFactory {
+          return new LinuxAMD64ThreadContext(dbg);
+       } else if (cpu.equals("sparc")) {
+          return new LinuxSPARCThreadContext(dbg);
+-      }  else if (cpu.equals("ppc64")) {
++      } else if (cpu.equals("mips64")) {
++         return new LinuxMIPS64ThreadContext(dbg);
++      } else if (cpu.equals("loongarch64")) {
++         return new LinuxLOONGARCH64ThreadContext(dbg);
++      } else if (cpu.equals("ppc64")) {
+           return new LinuxPPC64ThreadContext(dbg);
+       } else  {
+         try {
+diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/loongarch64/LinuxLOONGARCH64CFrame.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/loongarch64/LinuxLOONGARCH64CFrame.java
+new file mode 100644
+index 000000000..0e6caee5a
+--- /dev/null
++++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/loongarch64/LinuxLOONGARCH64CFrame.java
+@@ -0,0 +1,92 @@
++/*
++ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2015, 2022, Loongson Technology. 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 sun.jvm.hotspot.debugger.linux.loongarch64;
++
++import sun.jvm.hotspot.debugger.*;
++import sun.jvm.hotspot.debugger.linux.*;
++import sun.jvm.hotspot.debugger.cdbg.*;
++import sun.jvm.hotspot.debugger.cdbg.basic.*;
++import sun.jvm.hotspot.debugger.loongarch64.*;
++
++final public class LinuxLOONGARCH64CFrame extends BasicCFrame {
++   // package/class internals only
++   public LinuxLOONGARCH64CFrame(LinuxDebugger dbg, Address fp, Address pc) {
++      super(dbg.getCDebugger());
++      this.fp = fp;
++      this.pc = pc;
++      this.dbg = dbg;
++   }
++
++   // override base class impl to avoid ELF parsing
++   public ClosestSymbol closestSymbolToPC() {
++      // try native lookup in debugger.
++      return dbg.lookup(dbg.getAddressValue(pc()));
++   }
++
++   public Address pc() {
++      return pc;
++   }
++
++   public Address localVariableBase() {
++      return fp;
++   }
++
++   public CFrame sender(ThreadProxy thread) {
++      LOONGARCH64ThreadContext context = (LOONGARCH64ThreadContext) thread.getContext();
++      Address sp = context.getRegisterAsAddress(LOONGARCH64ThreadContext.SP);
++      Address nextFP;
++      Address nextPC;
++
++      if ((fp == null) || fp.lessThan(sp)) {
++        return null;
++      }
++
++      try {
++        nextFP = fp.getAddressAt(-2 * ADDRESS_SIZE);
++      } catch (Exception e) {
++        return null;
++      }
++      if (nextFP == null) {
++        return null;
++      }
++
++      try {
++        nextPC  = fp.getAddressAt(-1 * ADDRESS_SIZE);
++      } catch (Exception e) {
++        return null;
++      }
++      if (nextPC == null) {
++        return null;
++      }
++
++      return new LinuxLOONGARCH64CFrame(dbg, nextFP, nextPC);
++   }
++
++   private static final int ADDRESS_SIZE = 8;
++   private Address pc;
++   private Address fp;
++   private LinuxDebugger dbg;
++}
+diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/loongarch64/LinuxLOONGARCH64ThreadContext.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/loongarch64/LinuxLOONGARCH64ThreadContext.java
+new file mode 100644
+index 000000000..604642598
+--- /dev/null
++++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/loongarch64/LinuxLOONGARCH64ThreadContext.java
+@@ -0,0 +1,47 @@
++/*
++ * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2015, 2021, Loongson Technology. 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 sun.jvm.hotspot.debugger.linux.loongarch64;
++
++import sun.jvm.hotspot.debugger.*;
++import sun.jvm.hotspot.debugger.loongarch64.*;
++import sun.jvm.hotspot.debugger.linux.*;
++
++public class LinuxLOONGARCH64ThreadContext extends LOONGARCH64ThreadContext {
++  private LinuxDebugger debugger;
++
++  public LinuxLOONGARCH64ThreadContext(LinuxDebugger debugger) {
++    super();
++    this.debugger = debugger;
++  }
++
++  public void setRegisterAsAddress(int index, Address value) {
++    setRegister(index, debugger.getAddressValue(value));
++  }
++
++  public Address getRegisterAsAddress(int index) {
++    return debugger.newAddress(getRegister(index));
++  }
++}
+diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/mips64/LinuxMIPS64CFrame.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/mips64/LinuxMIPS64CFrame.java
+new file mode 100644
+index 000000000..2e3eb564d
+--- /dev/null
++++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/mips64/LinuxMIPS64CFrame.java
+@@ -0,0 +1,80 @@
++/*
++ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2015, 2018, Loongson Technology. 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 sun.jvm.hotspot.debugger.linux.mips64;
++
++import sun.jvm.hotspot.debugger.*;
++import sun.jvm.hotspot.debugger.linux.*;
++import sun.jvm.hotspot.debugger.cdbg.*;
++import sun.jvm.hotspot.debugger.cdbg.basic.*;
++import sun.jvm.hotspot.debugger.mips64.*;
++
++final public class LinuxMIPS64CFrame extends BasicCFrame {
++   // package/class internals only
++   public LinuxMIPS64CFrame(LinuxDebugger dbg, Address ebp, Address pc) {
++      super(dbg.getCDebugger());
++      this.ebp = ebp;
++      this.pc = pc;
++      this.dbg = dbg;
++   }
++
++   // override base class impl to avoid ELF parsing
++   public ClosestSymbol closestSymbolToPC() {
++      // try native lookup in debugger.
++      return dbg.lookup(dbg.getAddressValue(pc()));
++   }
++
++   public Address pc() {
++      return pc;
++   }
++
++   public Address localVariableBase() {
++      return ebp;
++   }
++
++   public CFrame sender(ThreadProxy thread) {
++      MIPS64ThreadContext context = (MIPS64ThreadContext) thread.getContext();
++      Address esp = context.getRegisterAsAddress(MIPS64ThreadContext.SP);
++
++      if ( (ebp == null) || ebp.lessThan(esp) ) {
++        return null;
++      }
++
++      Address nextEBP = ebp.getAddressAt( 0 * ADDRESS_SIZE);
++      if (nextEBP == null) {
++        return null;
++      }
++      Address nextPC  = ebp.getAddressAt( 1 * ADDRESS_SIZE);
++      if (nextPC == null) {
++        return null;
++      }
++      return new LinuxMIPS64CFrame(dbg, nextEBP, nextPC);
++   }
++
++   private static final int ADDRESS_SIZE = 4;
++   private Address pc;
++   private Address ebp;
++   private LinuxDebugger dbg;
++}
+diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/mips64/LinuxMIPS64ThreadContext.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/mips64/LinuxMIPS64ThreadContext.java
+new file mode 100644
+index 000000000..98e0f3f0b
+--- /dev/null
++++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/mips64/LinuxMIPS64ThreadContext.java
+@@ -0,0 +1,47 @@
++/*
++ * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2015, 2018, Loongson Technology. 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 sun.jvm.hotspot.debugger.linux.mips64;
++
++import sun.jvm.hotspot.debugger.*;
++import sun.jvm.hotspot.debugger.mips64.*;
++import sun.jvm.hotspot.debugger.linux.*;
++
++public class LinuxMIPS64ThreadContext extends MIPS64ThreadContext {
++  private LinuxDebugger debugger;
++
++  public LinuxMIPS64ThreadContext(LinuxDebugger debugger) {
++    super();
++    this.debugger = debugger;
++  }
++
++  public void setRegisterAsAddress(int index, Address value) {
++    setRegister(index, debugger.getAddressValue(value));
++  }
++
++  public Address getRegisterAsAddress(int index) {
++    return debugger.newAddress(getRegister(index));
++  }
++}
+diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/loongarch64/LOONGARCH64ThreadContext.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/loongarch64/LOONGARCH64ThreadContext.java
+new file mode 100644
+index 000000000..1de3cb1a4
+--- /dev/null
++++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/loongarch64/LOONGARCH64ThreadContext.java
+@@ -0,0 +1,128 @@
++/*
++ * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2015, 2021, Loongson Technology. 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 sun.jvm.hotspot.debugger.loongarch64;
++
++import java.lang.annotation.Native;
++
++import sun.jvm.hotspot.debugger.*;
++import sun.jvm.hotspot.debugger.cdbg.*;
++
++/** Specifies the thread context on loongarch64 platforms; only a sub-portion
++    of the context is guaranteed to be present on all operating
++    systems. */
++
++public abstract class LOONGARCH64ThreadContext implements ThreadContext {
++
++  // NOTE: the indices for the various registers must be maintained as
++  // listed across various operating systems. However, only a small
++  // subset of the registers' values are guaranteed to be present (and
++  // must be present for the SA's stack walking to work): EAX, EBX,
++  // ECX, EDX, ESI, EDI, EBP, ESP, and EIP.
++
++  // One instance of the Native annotation is enough to trigger header generation
++  // for this file.
++  @Native
++  public static final int ZERO = 0;
++  public static final int RA = 1;
++  public static final int TP = 2;
++  public static final int SP = 3;
++  public static final int A0 = 4;
++  public static final int A1 = 5;
++  public static final int A2 = 6;
++  public static final int A3 = 7;
++  public static final int A4 = 8;
++  public static final int A5 = 9;
++  public static final int A6 = 10;
++  public static final int A7 = 11;
++  public static final int T0 = 12;
++  public static final int T1 = 13;
++  public static final int T2 = 14;
++  public static final int T3 = 15;
++  public static final int T4 = 16;
++  public static final int T5 = 17;
++  public static final int T6 = 18;
++  public static final int T7 = 19;
++  public static final int T8 = 20;
++  public static final int RX = 21;
++  public static final int FP = 22;
++  public static final int S0 = 23;
++  public static final int S1 = 24;
++  public static final int S2 = 25;
++  public static final int S3 = 26;
++  public static final int S4 = 27;
++  public static final int S5 = 28;
++  public static final int S6 = 29;
++  public static final int S7 = 30;
++  public static final int S8 = 31;
++  public static final int PC = 32;
++  public static final int NPRGREG = 33;
++
++  private static final String[] regNames = {
++    "ZERO",    "RA",    "TP",    "SP",
++    "A0",      "A1",    "A2",    "A3",
++    "A4",      "A5",    "A6",    "A7",
++    "T0",      "T1",    "T2",    "T3",
++    "T4",      "T5",    "T6",    "T7",
++    "T8",      "RX",    "FP",    "S0",
++    "S1",      "S2",    "S3",    "S4",
++    "S5",      "S6",    "S7",    "S8",
++    "PC"
++  };
++
++  private long[] data;
++
++  public LOONGARCH64ThreadContext() {
++    data = new long[NPRGREG];
++  }
++
++  public int getNumRegisters() {
++    return NPRGREG;
++  }
++
++  public String getRegisterName(int index) {
++    return regNames[index];
++  }
++
++  public void setRegister(int index, long value) {
++    data[index] = value;
++  }
++
++  public long getRegister(int index) {
++    return data[index];
++  }
++
++  public CFrame getTopFrame(Debugger dbg) {
++    return null;
++  }
++
++  /** This can't be implemented in this class since we would have to
++      tie the implementation to, for example, the debugging system */
++  public abstract void setRegisterAsAddress(int index, Address value);
++
++  /** This can't be implemented in this class since we would have to
++      tie the implementation to, for example, the debugging system */
++  public abstract Address getRegisterAsAddress(int index);
++}
+diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/mips64/MIPS64ThreadContext.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/mips64/MIPS64ThreadContext.java
+new file mode 100644
+index 000000000..d3479a65e
+--- /dev/null
++++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/mips64/MIPS64ThreadContext.java
+@@ -0,0 +1,128 @@
++/*
++ * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2015, 2018, Loongson Technology. 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 sun.jvm.hotspot.debugger.mips64;
++
++import java.lang.annotation.Native;
++
++import sun.jvm.hotspot.debugger.*;
++import sun.jvm.hotspot.debugger.cdbg.*;
++
++/** Specifies the thread context on mips64 platforms; only a sub-portion
++    of the context is guaranteed to be present on all operating
++    systems. */
++
++public abstract class MIPS64ThreadContext implements ThreadContext {
++
++  // NOTE: the indices for the various registers must be maintained as
++  // listed across various operating systems. However, only a small
++  // subset of the registers' values are guaranteed to be present (and
++  // must be present for the SA's stack walking to work): EAX, EBX,
++  // ECX, EDX, ESI, EDI, EBP, ESP, and EIP.
++
++  // One instance of the Native annotation is enough to trigger header generation
++  // for this file.
++  @Native
++  public static final int ZERO = 0;
++  public static final int AT = 1;
++  public static final int V0 = 2;
++  public static final int V1 = 3;
++  public static final int A0 = 4;
++  public static final int A1 = 5;
++  public static final int A2 = 6;
++  public static final int A3 = 7;
++  public static final int T0 = 8;
++  public static final int T1 = 9;
++  public static final int T2 = 10;
++  public static final int T3 = 11;
++  public static final int T4 = 12;
++  public static final int T5 = 13;
++  public static final int T6 = 14;
++  public static final int T7 = 15;
++  public static final int S0 = 16;
++  public static final int S1 = 17;
++  public static final int S2 = 18;
++  public static final int S3 = 19;
++  public static final int S4 = 20;
++  public static final int S5 = 21;
++  public static final int S6 = 22;
++  public static final int S7 = 23;
++  public static final int T8 = 24;
++  public static final int T9 = 25;
++  public static final int K0 = 26;
++  public static final int K1 = 27;
++  public static final int GP = 28;
++  public static final int SP = 29;
++  public static final int FP = 30;
++  public static final int RA = 31;
++  public static final int PC = 32;
++  public static final int NPRGREG = 33;
++
++  private static final String[] regNames = {
++    "ZERO",    "AT",    "V0",    "V1",
++    "A0",      "A1",    "A2",    "A3",
++    "T0",      "T1",    "T2",    "T3",
++    "T4",      "T5",    "T6",    "T7",
++    "S0",      "S1",    "S2",    "S3",
++    "S4",      "S5",    "S6",    "S7",
++    "T8",      "T9",    "K0",    "K1",
++    "GP",      "SP",    "FP",    "RA",
++    "PC"
++  };
++
++  private long[] data;
++
++  public MIPS64ThreadContext() {
++    data = new long[NPRGREG];
++  }
++
++  public int getNumRegisters() {
++    return NPRGREG;
++  }
++
++  public String getRegisterName(int index) {
++    return regNames[index];
++  }
++
++  public void setRegister(int index, long value) {
++    data[index] = value;
++  }
++
++  public long getRegister(int index) {
++    return data[index];
++  }
++
++  public CFrame getTopFrame(Debugger dbg) {
++    return null;
++  }
++
++  /** This can't be implemented in this class since we would have to
++      tie the implementation to, for example, the debugging system */
++  public abstract void setRegisterAsAddress(int index, Address value);
++
++  /** This can't be implemented in this class since we would have to
++      tie the implementation to, for example, the debugging system */
++  public abstract Address getRegisterAsAddress(int index);
++}
+diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/posix/elf/ELFHeader.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/posix/elf/ELFHeader.java
+index 7113a3a49..de47531db 100644
+--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/posix/elf/ELFHeader.java
++++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/posix/elf/ELFHeader.java
+@@ -22,6 +22,12 @@
+  *
+  */
+ 
++/*
++ * This file has been modified by Loongson Technology in 2021, These
++ * modifications are Copyright (c) 2019, 2021, Loongson Technology, and are made
++ * available on the same license terms set forth above.
++ */
++
+ package sun.jvm.hotspot.debugger.posix.elf;
+ 
+ import java.io.FileInputStream;
+@@ -63,6 +69,8 @@ public interface ELFHeader {
+     public static final int ARCH_i860 = 7;
+     /** MIPS architecture type. */
+     public static final int ARCH_MIPS = 8;
++    /** LOONGARCH architecture type. */
++    public static final int ARCH_LOONGARCH = 9;
+ 
+     /** Returns a file type which is defined by the file type constants. */
+     public short getFileType();
+diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/ProcDebuggerLocal.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/ProcDebuggerLocal.java
+index 74e957d94..46ece3611 100644
+--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/ProcDebuggerLocal.java
++++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/ProcDebuggerLocal.java
+@@ -32,11 +32,13 @@ import sun.jvm.hotspot.debugger.*;
+ import sun.jvm.hotspot.debugger.cdbg.*;
+ import sun.jvm.hotspot.debugger.proc.amd64.*;
+ import sun.jvm.hotspot.debugger.proc.aarch64.*;
++import sun.jvm.hotspot.debugger.proc.mips64.*;
+ import sun.jvm.hotspot.debugger.proc.sparc.*;
+ import sun.jvm.hotspot.debugger.proc.ppc64.*;
+ import sun.jvm.hotspot.debugger.proc.x86.*;
+ import sun.jvm.hotspot.debugger.ppc64.*;
+ import sun.jvm.hotspot.debugger.amd64.*;
++import sun.jvm.hotspot.debugger.mips64.*;
+ import sun.jvm.hotspot.debugger.aarch64.*;
+ import sun.jvm.hotspot.debugger.sparc.*;
+ import sun.jvm.hotspot.debugger.x86.*;
+@@ -90,6 +92,10 @@ public class ProcDebuggerLocal extends DebuggerBase implements ProcDebugger {
+             threadFactory = new ProcAMD64ThreadFactory(this);
+             pcRegIndex = AMD64ThreadContext.RIP;
+             fpRegIndex = AMD64ThreadContext.RBP;
++        } else if (cpu.equals("mips64") || cpu.equals("mips64el")) {
++            threadFactory = new ProcMIPS64ThreadFactory(this);
++            pcRegIndex = MIPS64ThreadContext.PC;
++            fpRegIndex = MIPS64ThreadContext.FP;
+         } else if (cpu.equals("aarch64")) {
+             threadFactory = new ProcAARCH64ThreadFactory(this);
+             pcRegIndex = AARCH64ThreadContext.PC;
+diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/loongarch64/ProcLOONGARCH64Thread.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/loongarch64/ProcLOONGARCH64Thread.java
+new file mode 100644
+index 000000000..1f60fa6cf
+--- /dev/null
++++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/loongarch64/ProcLOONGARCH64Thread.java
+@@ -0,0 +1,92 @@
++/*
++ * Copyright (c) 2002, 2003, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2015, 2021, Loongson Technology. 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 sun.jvm.hotspot.debugger.proc.loongarch64;
++
++import sun.jvm.hotspot.debugger.*;
++import sun.jvm.hotspot.debugger.loongarch64.*;
++import sun.jvm.hotspot.debugger.proc.*;
++import sun.jvm.hotspot.utilities.*;
++
++public class ProcLOONGARCH64Thread implements ThreadProxy {
++  private ProcDebugger debugger;
++  private int         id;
++
++  public ProcLOONGARCH64Thread(ProcDebugger debugger, Address addr) {
++    this.debugger = debugger;
++
++    // FIXME: the size here should be configurable. However, making it
++    // so would produce a dependency on the "types" package from the
++    // debugger package, which is not desired.
++    this.id       = (int) addr.getCIntegerAt(0, 4, true);
++  }
++
++  public ProcLOONGARCH64Thread(ProcDebugger debugger, long id) {
++    this.debugger = debugger;
++    this.id = (int) id;
++  }
++
++  public ThreadContext getContext() throws IllegalThreadStateException {
++    ProcLOONGARCH64ThreadContext context = new ProcLOONGARCH64ThreadContext(debugger);
++    long[] regs = debugger.getThreadIntegerRegisterSet(id);
++    /*
++       _NGREG in reg.h is defined to be 19. Because we have included
++       debug registers LOONGARCH64ThreadContext.NPRGREG is 25.
++    */
++
++    if (Assert.ASSERTS_ENABLED) {
++      Assert.that(regs.length <= LOONGARCH64ThreadContext.NPRGREG, "size of register set is greater than " + LOONGARCH64ThreadContext.NPRGREG);
++    }
++    for (int i = 0; i < regs.length; i++) {
++      context.setRegister(i, regs[i]);
++    }
++    return context;
++  }
++
++  public boolean canSetContext() throws DebuggerException {
++    return false;
++  }
++
++  public void setContext(ThreadContext context)
++    throws IllegalThreadStateException, DebuggerException {
++    throw new DebuggerException("Unimplemented");
++  }
++
++  public String toString() {
++    return "t@" + id;
++  }
++
++  public boolean equals(Object obj) {
++    if ((obj == null) || !(obj instanceof ProcLOONGARCH64Thread)) {
++      return false;
++    }
++
++    return (((ProcLOONGARCH64Thread) obj).id == id);
++  }
++
++  public int hashCode() {
++    return id;
++  }
++}
+diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/loongarch64/ProcLOONGARCH64ThreadContext.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/loongarch64/ProcLOONGARCH64ThreadContext.java
+new file mode 100644
+index 000000000..ef5597ac4
+--- /dev/null
++++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/loongarch64/ProcLOONGARCH64ThreadContext.java
+@@ -0,0 +1,47 @@
++/*
++ * Copyright (c) 2002, 2003, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2015, 2021, Loongson Technology. 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 sun.jvm.hotspot.debugger.proc.loongarch64;
++
++import sun.jvm.hotspot.debugger.*;
++import sun.jvm.hotspot.debugger.loongarch64.*;
++import sun.jvm.hotspot.debugger.proc.*;
++
++public class ProcLOONGARCH64ThreadContext extends LOONGARCH64ThreadContext {
++  private ProcDebugger debugger;
++
++  public ProcLOONGARCH64ThreadContext(ProcDebugger debugger) {
++    super();
++    this.debugger = debugger;
++  }
++
++  public void setRegisterAsAddress(int index, Address value) {
++    setRegister(index, debugger.getAddressValue(value));
++  }
++
++  public Address getRegisterAsAddress(int index) {
++    return debugger.newAddress(getRegister(index));
++  }
++}
+diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/loongarch64/ProcLOONGARCH64ThreadFactory.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/loongarch64/ProcLOONGARCH64ThreadFactory.java
+new file mode 100644
+index 000000000..abad1bb38
+--- /dev/null
++++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/loongarch64/ProcLOONGARCH64ThreadFactory.java
+@@ -0,0 +1,45 @@
++/*
++ * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2015, 2021, Loongson Technology. 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 sun.jvm.hotspot.debugger.proc.loongarch64;
++
++import sun.jvm.hotspot.debugger.*;
++import sun.jvm.hotspot.debugger.proc.*;
++
++public class ProcLOONGARCH64ThreadFactory implements ProcThreadFactory {
++  private ProcDebugger debugger;
++
++  public ProcLOONGARCH64ThreadFactory(ProcDebugger debugger) {
++    this.debugger = debugger;
++  }
++
++  public ThreadProxy createThreadWrapper(Address threadIdentifierAddr) {
++    return new ProcLOONGARCH64Thread(debugger, threadIdentifierAddr);
++  }
++
++  public ThreadProxy createThreadWrapper(long id) {
++    return new ProcLOONGARCH64Thread(debugger, id);
++  }
++}
+diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/mips64/ProcMIPS64Thread.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/mips64/ProcMIPS64Thread.java
+new file mode 100644
+index 000000000..5c1e0be89
+--- /dev/null
++++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/mips64/ProcMIPS64Thread.java
+@@ -0,0 +1,92 @@
++/*
++ * Copyright (c) 2002, 2003, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2015, 2018, Loongson Technology. 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 sun.jvm.hotspot.debugger.proc.mips64;
++
++import sun.jvm.hotspot.debugger.*;
++import sun.jvm.hotspot.debugger.mips64.*;
++import sun.jvm.hotspot.debugger.proc.*;
++import sun.jvm.hotspot.utilities.*;
++
++public class ProcMIPS64Thread implements ThreadProxy {
++  private ProcDebugger debugger;
++  private int         id;
++
++  public ProcMIPS64Thread(ProcDebugger debugger, Address addr) {
++    this.debugger = debugger;
++
++    // FIXME: the size here should be configurable. However, making it
++    // so would produce a dependency on the "types" package from the
++    // debugger package, which is not desired.
++    this.id       = (int) addr.getCIntegerAt(0, 4, true);
++  }
++
++  public ProcMIPS64Thread(ProcDebugger debugger, long id) {
++    this.debugger = debugger;
++    this.id = (int) id;
++  }
++
++  public ThreadContext getContext() throws IllegalThreadStateException {
++    ProcMIPS64ThreadContext context = new ProcMIPS64ThreadContext(debugger);
++    long[] regs = debugger.getThreadIntegerRegisterSet(id);
++    /*
++       _NGREG in reg.h is defined to be 19. Because we have included
++       debug registers MIPS64ThreadContext.NPRGREG is 25.
++    */
++
++    if (Assert.ASSERTS_ENABLED) {
++      Assert.that(regs.length <= MIPS64ThreadContext.NPRGREG, "size of register set is greater than " + MIPS64ThreadContext.NPRGREG);
++    }
++    for (int i = 0; i < regs.length; i++) {
++      context.setRegister(i, regs[i]);
++    }
++    return context;
++  }
++
++  public boolean canSetContext() throws DebuggerException {
++    return false;
++  }
++
++  public void setContext(ThreadContext context)
++    throws IllegalThreadStateException, DebuggerException {
++    throw new DebuggerException("Unimplemented");
++  }
++
++  public String toString() {
++    return "t@" + id;
++  }
++
++  public boolean equals(Object obj) {
++    if ((obj == null) || !(obj instanceof ProcMIPS64Thread)) {
++      return false;
++    }
++
++    return (((ProcMIPS64Thread) obj).id == id);
++  }
++
++  public int hashCode() {
++    return id;
++  }
++}
+diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/mips64/ProcMIPS64ThreadContext.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/mips64/ProcMIPS64ThreadContext.java
+new file mode 100644
+index 000000000..d44223d76
+--- /dev/null
++++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/mips64/ProcMIPS64ThreadContext.java
+@@ -0,0 +1,47 @@
++/*
++ * Copyright (c) 2002, 2003, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2015, 2018, Loongson Technology. 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 sun.jvm.hotspot.debugger.proc.mips64;
++
++import sun.jvm.hotspot.debugger.*;
++import sun.jvm.hotspot.debugger.mips64.*;
++import sun.jvm.hotspot.debugger.proc.*;
++
++public class ProcMIPS64ThreadContext extends MIPS64ThreadContext {
++  private ProcDebugger debugger;
++
++  public ProcMIPS64ThreadContext(ProcDebugger debugger) {
++    super();
++    this.debugger = debugger;
++  }
++
++  public void setRegisterAsAddress(int index, Address value) {
++    setRegister(index, debugger.getAddressValue(value));
++  }
++
++  public Address getRegisterAsAddress(int index) {
++    return debugger.newAddress(getRegister(index));
++  }
++}
+diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/mips64/ProcMIPS64ThreadFactory.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/mips64/ProcMIPS64ThreadFactory.java
+new file mode 100644
+index 000000000..bad478fc5
+--- /dev/null
++++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/mips64/ProcMIPS64ThreadFactory.java
+@@ -0,0 +1,45 @@
++/*
++ * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2015, 2018, Loongson Technology. 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 sun.jvm.hotspot.debugger.proc.mips64;
++
++import sun.jvm.hotspot.debugger.*;
++import sun.jvm.hotspot.debugger.proc.*;
++
++public class ProcMIPS64ThreadFactory implements ProcThreadFactory {
++  private ProcDebugger debugger;
++
++  public ProcMIPS64ThreadFactory(ProcDebugger debugger) {
++    this.debugger = debugger;
++  }
++
++  public ThreadProxy createThreadWrapper(Address threadIdentifierAddr) {
++    return new ProcMIPS64Thread(debugger, threadIdentifierAddr);
++  }
++
++  public ThreadProxy createThreadWrapper(long id) {
++    return new ProcMIPS64Thread(debugger, id);
++  }
++}
+diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/RemoteDebuggerClient.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/RemoteDebuggerClient.java
+index b6253f6d6..5eecb08a1 100644
+--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/RemoteDebuggerClient.java
++++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/RemoteDebuggerClient.java
+@@ -22,6 +22,12 @@
+  *
+  */
+ 
++/*
++ * This file has been modified by Loongson Technology in 2021, These
++ * modifications are Copyright (c) 2019, 2021, Loongson Technology, and are made
++ * available on the same license terms set forth above.
++ */
++
+ package sun.jvm.hotspot.debugger.remote;
+ 
+ import java.rmi.*;
+@@ -34,6 +40,8 @@ import sun.jvm.hotspot.debugger.remote.sparc.*;
+ import sun.jvm.hotspot.debugger.remote.x86.*;
+ import sun.jvm.hotspot.debugger.remote.amd64.*;
+ import sun.jvm.hotspot.debugger.remote.ppc64.*;
++import sun.jvm.hotspot.debugger.remote.mips64.*;
++import sun.jvm.hotspot.debugger.remote.loongarch64.*;
+ 
+ /** An implementation of Debugger which wraps a
+     RemoteDebugger, providing remote debugging via RMI.
+@@ -76,6 +84,16 @@ public class RemoteDebuggerClient extends DebuggerBase implements JVMDebugger {
+         cachePageSize = 4096;
+         cacheNumPages = parseCacheNumPagesProperty(cacheSize / cachePageSize);
+         unalignedAccessesOkay = true;
++      } else if (cpu.equals("mips64") || cpu.equals("mips64el")) {
++        threadFactory = new RemoteMIPS64ThreadFactory(this);
++        cachePageSize = 4096;
++        cacheNumPages = parseCacheNumPagesProperty(cacheSize / cachePageSize);
++        unalignedAccessesOkay = true;
++      } else if (cpu.equals("loongarch64")) {
++        threadFactory = new RemoteLOONGARCH64ThreadFactory(this);
++        cachePageSize = 4096;
++        cacheNumPages = parseCacheNumPagesProperty(cacheSize / cachePageSize);
++        unalignedAccessesOkay = true;
+       } else {
+         try {
+           Class tf = Class.forName("sun.jvm.hotspot.debugger.remote." +
+diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/loongarch64/RemoteLOONGARCH64Thread.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/loongarch64/RemoteLOONGARCH64Thread.java
+new file mode 100644
+index 000000000..242dd279e
+--- /dev/null
++++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/loongarch64/RemoteLOONGARCH64Thread.java
+@@ -0,0 +1,54 @@
++/*
++ * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2018, 2021, Loongson Technology. 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 sun.jvm.hotspot.debugger.remote.loongarch64;
++
++import sun.jvm.hotspot.debugger.*;
++import sun.jvm.hotspot.debugger.loongarch64.*;
++import sun.jvm.hotspot.debugger.remote.*;
++import sun.jvm.hotspot.utilities.*;
++
++public class RemoteLOONGARCH64Thread extends RemoteThread  {
++  public RemoteLOONGARCH64Thread(RemoteDebuggerClient debugger, Address addr) {
++     super(debugger, addr);
++  }
++
++  public RemoteLOONGARCH64Thread(RemoteDebuggerClient debugger, long id) {
++     super(debugger, id);
++  }
++
++  public ThreadContext getContext() throws IllegalThreadStateException {
++    RemoteLOONGARCH64ThreadContext context = new RemoteLOONGARCH64ThreadContext(debugger);
++    long[] regs = (addr != null)? debugger.getThreadIntegerRegisterSet(addr) :
++                                  debugger.getThreadIntegerRegisterSet(id);
++    if (Assert.ASSERTS_ENABLED) {
++      Assert.that(regs.length == LOONGARCH64ThreadContext.NPRGREG, "size of register set must match");
++    }
++    for (int i = 0; i < regs.length; i++) {
++      context.setRegister(i, regs[i]);
++    }
++    return context;
++  }
++}
+diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/loongarch64/RemoteLOONGARCH64ThreadContext.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/loongarch64/RemoteLOONGARCH64ThreadContext.java
+new file mode 100644
+index 000000000..634d5ad04
+--- /dev/null
++++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/loongarch64/RemoteLOONGARCH64ThreadContext.java
+@@ -0,0 +1,51 @@
++/*
++ * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2018, 2021, Loongson Technology. 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 sun.jvm.hotspot.debugger.remote.loongarch64;
++
++import sun.jvm.hotspot.debugger.*;
++import sun.jvm.hotspot.debugger.loongarch64.*;
++import sun.jvm.hotspot.debugger.remote.*;
++
++public class RemoteLOONGARCH64ThreadContext extends LOONGARCH64ThreadContext {
++  private RemoteDebuggerClient debugger;
++
++  public RemoteLOONGARCH64ThreadContext(RemoteDebuggerClient debugger) {
++    super();
++    this.debugger = debugger;
++  }
++
++  /** This can't be implemented in this class since we would have to
++      tie the implementation to, for example, the debugging system */
++  public void setRegisterAsAddress(int index, Address value) {
++    setRegister(index, debugger.getAddressValue(value));
++  }
++
++  /** This can't be implemented in this class since we would have to
++      tie the implementation to, for example, the debugging system */
++  public Address getRegisterAsAddress(int index) {
++    return debugger.newAddress(getRegister(index));
++  }
++}
+diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/loongarch64/RemoteLOONGARCH64ThreadFactory.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/loongarch64/RemoteLOONGARCH64ThreadFactory.java
+new file mode 100644
+index 000000000..4fb9cc7c0
+--- /dev/null
++++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/loongarch64/RemoteLOONGARCH64ThreadFactory.java
+@@ -0,0 +1,45 @@
++/*
++ * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2018, 2021, Loongson Technology. 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 sun.jvm.hotspot.debugger.remote.loongarch64;
++
++import sun.jvm.hotspot.debugger.*;
++import sun.jvm.hotspot.debugger.remote.*;
++
++public class RemoteLOONGARCH64ThreadFactory implements RemoteThreadFactory {
++  private RemoteDebuggerClient debugger;
++
++  public RemoteLOONGARCH64ThreadFactory(RemoteDebuggerClient debugger) {
++    this.debugger = debugger;
++  }
++
++  public ThreadProxy createThreadWrapper(Address threadIdentifierAddr) {
++    return new RemoteLOONGARCH64Thread(debugger, threadIdentifierAddr);
++  }
++
++  public ThreadProxy createThreadWrapper(long id) {
++    return new RemoteLOONGARCH64Thread(debugger, id);
++  }
++}
+diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/mips64/RemoteMIPS64Thread.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/mips64/RemoteMIPS64Thread.java
+new file mode 100644
+index 000000000..c2f7d841f
+--- /dev/null
++++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/mips64/RemoteMIPS64Thread.java
+@@ -0,0 +1,54 @@
++/*
++ * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2018, Loongson Technology. 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 sun.jvm.hotspot.debugger.remote.mips64;
++
++import sun.jvm.hotspot.debugger.*;
++import sun.jvm.hotspot.debugger.mips64.*;
++import sun.jvm.hotspot.debugger.remote.*;
++import sun.jvm.hotspot.utilities.*;
++
++public class RemoteMIPS64Thread extends RemoteThread  {
++  public RemoteMIPS64Thread(RemoteDebuggerClient debugger, Address addr) {
++     super(debugger, addr);
++  }
++
++  public RemoteMIPS64Thread(RemoteDebuggerClient debugger, long id) {
++     super(debugger, id);
++  }
++
++  public ThreadContext getContext() throws IllegalThreadStateException {
++    RemoteMIPS64ThreadContext context = new RemoteMIPS64ThreadContext(debugger);
++    long[] regs = (addr != null)? debugger.getThreadIntegerRegisterSet(addr) :
++                                  debugger.getThreadIntegerRegisterSet(id);
++    if (Assert.ASSERTS_ENABLED) {
++      Assert.that(regs.length == MIPS64ThreadContext.NPRGREG, "size of register set must match");
++    }
++    for (int i = 0; i < regs.length; i++) {
++      context.setRegister(i, regs[i]);
++    }
++    return context;
++  }
++}
+diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/mips64/RemoteMIPS64ThreadContext.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/mips64/RemoteMIPS64ThreadContext.java
+new file mode 100644
+index 000000000..23646905d
+--- /dev/null
++++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/mips64/RemoteMIPS64ThreadContext.java
+@@ -0,0 +1,51 @@
++/*
++ * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2018, Loongson Technology. 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 sun.jvm.hotspot.debugger.remote.mips64;
++
++import sun.jvm.hotspot.debugger.*;
++import sun.jvm.hotspot.debugger.mips64.*;
++import sun.jvm.hotspot.debugger.remote.*;
++
++public class RemoteMIPS64ThreadContext extends MIPS64ThreadContext {
++  private RemoteDebuggerClient debugger;
++
++  public RemoteMIPS64ThreadContext(RemoteDebuggerClient debugger) {
++    super();
++    this.debugger = debugger;
++  }
++
++  /** This can't be implemented in this class since we would have to
++      tie the implementation to, for example, the debugging system */
++  public void setRegisterAsAddress(int index, Address value) {
++    setRegister(index, debugger.getAddressValue(value));
++  }
++
++  /** This can't be implemented in this class since we would have to
++      tie the implementation to, for example, the debugging system */
++  public Address getRegisterAsAddress(int index) {
++    return debugger.newAddress(getRegister(index));
++  }
++}
+diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/mips64/RemoteMIPS64ThreadFactory.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/mips64/RemoteMIPS64ThreadFactory.java
+new file mode 100644
+index 000000000..b39b01449
+--- /dev/null
++++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/mips64/RemoteMIPS64ThreadFactory.java
+@@ -0,0 +1,45 @@
++/*
++ * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2018, Loongson Technology. 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 sun.jvm.hotspot.debugger.remote.mips64;
++
++import sun.jvm.hotspot.debugger.*;
++import sun.jvm.hotspot.debugger.remote.*;
++
++public class RemoteMIPS64ThreadFactory implements RemoteThreadFactory {
++  private RemoteDebuggerClient debugger;
++
++  public RemoteMIPS64ThreadFactory(RemoteDebuggerClient debugger) {
++    this.debugger = debugger;
++  }
++
++  public ThreadProxy createThreadWrapper(Address threadIdentifierAddr) {
++    return new RemoteMIPS64Thread(debugger, threadIdentifierAddr);
++  }
++
++  public ThreadProxy createThreadWrapper(long id) {
++    return new RemoteMIPS64Thread(debugger, id);
++  }
++}
+diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Threads.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Threads.java
+index 190062785..04681fa0e 100644
+--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Threads.java
++++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Threads.java
+@@ -22,6 +22,12 @@
+  *
+  */
+ 
++/*
++ * This file has been modified by Loongson Technology in 2021, These
++ * modifications are Copyright (c) 2019, 2021, Loongson Technology, and are made
++ * available on the same license terms set forth above.
++ */
++
+ package sun.jvm.hotspot.runtime;
+ 
+ import java.util.*;
+@@ -39,6 +45,8 @@ import sun.jvm.hotspot.runtime.linux_x86.LinuxX86JavaThreadPDAccess;
+ import sun.jvm.hotspot.runtime.linux_amd64.LinuxAMD64JavaThreadPDAccess;
+ import sun.jvm.hotspot.runtime.linux_aarch64.LinuxAARCH64JavaThreadPDAccess;
+ import sun.jvm.hotspot.runtime.linux_ppc64.LinuxPPC64JavaThreadPDAccess;
++import sun.jvm.hotspot.runtime.linux_mips64.LinuxMIPS64JavaThreadPDAccess;
++import sun.jvm.hotspot.runtime.linux_loongarch64.LinuxLOONGARCH64JavaThreadPDAccess;
+ import sun.jvm.hotspot.runtime.linux_sparc.LinuxSPARCJavaThreadPDAccess;
+ import sun.jvm.hotspot.runtime.bsd_x86.BsdX86JavaThreadPDAccess;
+ import sun.jvm.hotspot.runtime.bsd_amd64.BsdAMD64JavaThreadPDAccess;
+@@ -99,6 +107,10 @@ public class Threads {
+                 access = new LinuxPPC64JavaThreadPDAccess();
+             } else if (cpu.equals("aarch64")) {
+                 access = new LinuxAARCH64JavaThreadPDAccess();
++            } else if (cpu.equals("mips64")) {
++                access = new LinuxMIPS64JavaThreadPDAccess();
++            } else if (cpu.equals("loongarch64")) {
++                access = new LinuxLOONGARCH64JavaThreadPDAccess();
+             } else {
+               try {
+                 access = (JavaThreadPDAccess)
+diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/linux_loongarch64/LinuxLOONGARCH64JavaThreadPDAccess.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/linux_loongarch64/LinuxLOONGARCH64JavaThreadPDAccess.java
+new file mode 100644
+index 000000000..ee1003e35
+--- /dev/null
++++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/linux_loongarch64/LinuxLOONGARCH64JavaThreadPDAccess.java
+@@ -0,0 +1,133 @@
++/*
++ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2018, 2021, Loongson Technology. 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 sun.jvm.hotspot.runtime.linux_loongarch64;
++
++import java.io.*;
++import java.util.*;
++
++import sun.jvm.hotspot.debugger.*;
++import sun.jvm.hotspot.debugger.loongarch64.*;
++import sun.jvm.hotspot.runtime.*;
++import sun.jvm.hotspot.runtime.loongarch64.*;
++import sun.jvm.hotspot.types.*;
++import sun.jvm.hotspot.utilities.*;
++
++public class LinuxLOONGARCH64JavaThreadPDAccess implements JavaThreadPDAccess {
++  private static AddressField  lastJavaFPField;
++  private static AddressField  osThreadField;
++
++  // Field from OSThread
++  private static CIntegerField osThreadThreadIDField;
++
++  // This is currently unneeded but is being kept in case we change
++  // the currentFrameGuess algorithm
++  private static final long GUESS_SCAN_RANGE = 128 * 1024;
++
++  static {
++    VM.registerVMInitializedObserver(new Observer() {
++        public void update(Observable o, Object data) {
++          initialize(VM.getVM().getTypeDataBase());
++        }
++      });
++  }
++
++  private static synchronized void initialize(TypeDataBase db) {
++    Type type = db.lookupType("JavaThread");
++    osThreadField = type.getAddressField("_osthread");
++
++    Type anchorType = db.lookupType("JavaFrameAnchor");
++    lastJavaFPField = anchorType.getAddressField("_last_Java_fp");
++
++    Type osThreadType = db.lookupType("OSThread");
++    osThreadThreadIDField = osThreadType.getCIntegerField("_thread_id");
++  }
++
++  public Address getLastJavaFP(Address addr) {
++    return lastJavaFPField.getValue(addr.addOffsetTo(sun.jvm.hotspot.runtime.JavaThread.getAnchorField().getOffset()));
++  }
++
++  public Address getLastJavaPC(Address addr) {
++    return null;
++  }
++
++  public Address getBaseOfStackPointer(Address addr) {
++    return null;
++  }
++
++  public Frame getLastFramePD(JavaThread thread, Address addr) {
++    Address fp = thread.getLastJavaFP();
++    if (fp == null) {
++      return null; // no information
++    }
++    return new LOONGARCH64Frame(thread.getLastJavaSP(), fp);
++  }
++
++  public RegisterMap newRegisterMap(JavaThread thread, boolean updateMap) {
++    return new LOONGARCH64RegisterMap(thread, updateMap);
++  }
++
++  public Frame getCurrentFrameGuess(JavaThread thread, Address addr) {
++    ThreadProxy t = getThreadProxy(addr);
++    LOONGARCH64ThreadContext context = (LOONGARCH64ThreadContext) t.getContext();
++    LOONGARCH64CurrentFrameGuess guesser = new LOONGARCH64CurrentFrameGuess(context, thread);
++    if (!guesser.run(GUESS_SCAN_RANGE)) {
++      return null;
++    }
++    if (guesser.getPC() == null) {
++      return new LOONGARCH64Frame(guesser.getSP(), guesser.getFP());
++    } else {
++      return new LOONGARCH64Frame(guesser.getSP(), guesser.getFP(), guesser.getPC());
++    }
++  }
++
++  public void printThreadIDOn(Address addr, PrintStream tty) {
++    tty.print(getThreadProxy(addr));
++  }
++
++  public void printInfoOn(Address threadAddr, PrintStream tty) {
++    tty.print("Thread id: ");
++    printThreadIDOn(threadAddr, tty);
++    // tty.println("\nPostJavaState: " + getPostJavaState(threadAddr));
++  }
++
++  public Address getLastSP(Address addr) {
++    ThreadProxy t = getThreadProxy(addr);
++    LOONGARCH64ThreadContext context = (LOONGARCH64ThreadContext) t.getContext();
++    return context.getRegisterAsAddress(LOONGARCH64ThreadContext.SP);
++  }
++
++  public ThreadProxy getThreadProxy(Address addr) {
++    // Addr is the address of the JavaThread.
++    // Fetch the OSThread (for now and for simplicity, not making a
++    // separate "OSThread" class in this package)
++    Address osThreadAddr = osThreadField.getValue(addr);
++    // Get the address of the _thread_id from the OSThread
++    Address threadIdAddr = osThreadAddr.addOffsetTo(osThreadThreadIDField.getOffset());
++
++    JVMDebugger debugger = VM.getVM().getDebugger();
++    return debugger.getThreadForIdentifierAddress(threadIdAddr);
++  }
++}
+diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/linux_mips64/LinuxMIPS64JavaThreadPDAccess.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/linux_mips64/LinuxMIPS64JavaThreadPDAccess.java
+new file mode 100644
+index 000000000..181f431b6
+--- /dev/null
++++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/linux_mips64/LinuxMIPS64JavaThreadPDAccess.java
+@@ -0,0 +1,133 @@
++/*
++ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2018, Loongson Technology. 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 sun.jvm.hotspot.runtime.linux_mips64;
++
++import java.io.*;
++import java.util.*;
++
++import sun.jvm.hotspot.debugger.*;
++import sun.jvm.hotspot.debugger.mips64.*;
++import sun.jvm.hotspot.runtime.*;
++import sun.jvm.hotspot.runtime.mips64.*;
++import sun.jvm.hotspot.types.*;
++import sun.jvm.hotspot.utilities.*;
++
++public class LinuxMIPS64JavaThreadPDAccess implements JavaThreadPDAccess {
++  private static AddressField  osThreadField;
++
++  // Field from OSThread
++  private static CIntegerField osThreadThreadIDField;
++
++  // This is currently unneeded but is being kept in case we change
++  // the currentFrameGuess algorithm
++  private static final long GUESS_SCAN_RANGE = 128 * 1024;
++
++  static {
++    VM.registerVMInitializedObserver(new Observer() {
++        public void update(Observable o, Object data) {
++          initialize(VM.getVM().getTypeDataBase());
++        }
++      });
++  }
++
++  private static synchronized void initialize(TypeDataBase db) {
++    Type type = db.lookupType("JavaThread");
++    osThreadField = type.getAddressField("_osthread");
++
++    Type osThreadType = db.lookupType("OSThread");
++    osThreadThreadIDField = osThreadType.getCIntegerField("_thread_id");
++  }
++
++  public Address getLastJavaFP(Address addr) {
++    return null;
++  }
++
++  public Address getLastJavaPC(Address addr) {
++    return null;
++  }
++
++  public Address getBaseOfStackPointer(Address addr) {
++    return null;
++  }
++
++  public Frame getLastFramePD(JavaThread thread, Address addr) {
++    Address fp = thread.getLastJavaFP();
++    if (fp == null) {
++      return null; // no information
++    }
++    return new MIPS64Frame(thread.getLastJavaSP(), fp);
++  }
++
++  public RegisterMap newRegisterMap(JavaThread thread, boolean updateMap) {
++    return new MIPS64RegisterMap(thread, updateMap);
++  }
++
++  public Frame getCurrentFrameGuess(JavaThread thread, Address addr) {
++    ThreadProxy t = getThreadProxy(addr);
++    MIPS64ThreadContext context = (MIPS64ThreadContext) t.getContext();
++    MIPS64CurrentFrameGuess guesser = new MIPS64CurrentFrameGuess(context, thread);
++    if (!guesser.run(GUESS_SCAN_RANGE)) {
++      return null;
++    }
++    if (guesser.getPC() == null) {
++      return new MIPS64Frame(guesser.getSP(), guesser.getFP());
++    } else {
++      return new MIPS64Frame(guesser.getSP(), guesser.getFP(), guesser.getPC());
++    }
++  }
++
++  public void printThreadIDOn(Address addr, PrintStream tty) {
++    tty.print(getThreadProxy(addr));
++  }
++
++  public void printInfoOn(Address threadAddr, PrintStream tty) {
++    tty.print("Thread id: ");
++    printThreadIDOn(threadAddr, tty);
++    // tty.println("\nPostJavaState: " + getPostJavaState(threadAddr));
++  }
++
++  public Address getLastSP(Address addr) {
++    ThreadProxy t = getThreadProxy(addr);
++    MIPS64ThreadContext context = (MIPS64ThreadContext) t.getContext();
++    return context.getRegisterAsAddress(MIPS64ThreadContext.SP);
++  }
++
++  public Address getLastFP(Address addr) {
++    return getLastSP(addr).getAddressAt(0);
++  }
++
++  public ThreadProxy getThreadProxy(Address addr) {
++    // Addr is the address of the JavaThread.
++    // Fetch the OSThread (for now and for simplicity, not making a
++    // separate "OSThread" class in this package)
++    Address osThreadAddr = osThreadField.getValue(addr);
++    // Get the address of the _thread_id from the OSThread
++    Address threadIdAddr = osThreadAddr.addOffsetTo(osThreadThreadIDField.getOffset());
++
++    JVMDebugger debugger = VM.getVM().getDebugger();
++    return debugger.getThreadForIdentifierAddress(threadIdAddr);
++  }
++}
+diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/loongarch64/LOONGARCH64CurrentFrameGuess.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/loongarch64/LOONGARCH64CurrentFrameGuess.java
+new file mode 100644
+index 000000000..824270e13
+--- /dev/null
++++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/loongarch64/LOONGARCH64CurrentFrameGuess.java
+@@ -0,0 +1,250 @@
++/*
++ * Copyright (c) 2001, 2006, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2018, 2022, Loongson Technology. 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 sun.jvm.hotspot.runtime.loongarch64;
++
++import sun.jvm.hotspot.debugger.*;
++import sun.jvm.hotspot.debugger.loongarch64.*;
++import sun.jvm.hotspot.code.*;
++import sun.jvm.hotspot.interpreter.*;
++import sun.jvm.hotspot.runtime.*;
++
++/** 

Should be able to be used on all loongarch64 platforms we support ++ (Win32, Solaris/loongarch64, and soon Linux) to implement JavaThread's ++ "currentFrameGuess()" functionality. Input is an LOONGARCH64ThreadContext; ++ output is SP, FP, and PC for an LOONGARCH64Frame. Instantiation of the ++ LOONGARCH64Frame is left to the caller, since we may need to subclass ++ LOONGARCH64Frame to support signal handler frames on Unix platforms.

++ ++

Algorithm is to walk up the stack within a given range (say, ++ 512K at most) looking for a plausible PC and SP for a Java frame, ++ also considering those coming in from the context. If we find a PC ++ that belongs to the VM (i.e., in generated code like the ++ interpreter or CodeCache) then we try to find an associated EBP. ++ We repeat this until we either find a complete frame or run out of ++ stack to look at.

*/ ++ ++public class LOONGARCH64CurrentFrameGuess { ++ private LOONGARCH64ThreadContext context; ++ private JavaThread thread; ++ private Address spFound; ++ private Address fpFound; ++ private Address pcFound; ++ ++ private static final boolean DEBUG = System.getProperty("sun.jvm.hotspot.runtime.loongarch64.LOONGARCH64Frame.DEBUG") ++ != null; ++ ++ public LOONGARCH64CurrentFrameGuess(LOONGARCH64ThreadContext context, ++ JavaThread thread) { ++ this.context = context; ++ this.thread = thread; ++ } ++ ++ /** Returns false if not able to find a frame within a reasonable range. */ ++ public boolean run(long regionInBytesToSearch) { ++ Address sp = context.getRegisterAsAddress(LOONGARCH64ThreadContext.SP); ++ Address pc = context.getRegisterAsAddress(LOONGARCH64ThreadContext.PC); ++ Address fp = context.getRegisterAsAddress(LOONGARCH64ThreadContext.FP); ++ if (sp == null) { ++ // Bail out if no last java frame eithe ++ if (thread.getLastJavaSP() != null) { ++ setValues(thread.getLastJavaSP(), thread.getLastJavaFP(), null); ++ return true; ++ } ++ // Bail out ++ return false; ++ } ++ Address end = sp.addOffsetTo(regionInBytesToSearch); ++ VM vm = VM.getVM(); ++ ++ setValues(null, null, null); // Assume we're not going to find anything ++ ++ if (vm.isJavaPCDbg(pc)) { ++ if (vm.isClientCompiler()) { ++ // If the topmost frame is a Java frame, we are (pretty much) ++ // guaranteed to have a viable EBP. We should be more robust ++ // than this (we have the potential for losing entire threads' ++ // stack traces) but need to see how much work we really have ++ // to do here. Searching the stack for an (SP, FP) pair is ++ // hard since it's easy to misinterpret inter-frame stack ++ // pointers as base-of-frame pointers; we also don't know the ++ // sizes of C1 frames (not registered in the nmethod) so can't ++ // derive them from ESP. ++ ++ setValues(sp, fp, pc); ++ return true; ++ } else { ++ if (vm.getInterpreter().contains(pc)) { ++ if (DEBUG) { ++ System.out.println("CurrentFrameGuess: choosing interpreter frame: sp = " + ++ sp + ", fp = " + fp + ", pc = " + pc); ++ } ++ setValues(sp, fp, pc); ++ return true; ++ } ++ ++ // For the server compiler, EBP is not guaranteed to be valid ++ // for compiled code. In addition, an earlier attempt at a ++ // non-searching algorithm (see below) failed because the ++ // stack pointer from the thread context was pointing ++ // (considerably) beyond the ostensible end of the stack, into ++ // garbage; walking from the topmost frame back caused a crash. ++ // ++ // This algorithm takes the current PC as a given and tries to ++ // find the correct corresponding SP by walking up the stack ++ // and repeatedly performing stackwalks (very inefficient). ++ // ++ // FIXME: there is something wrong with stackwalking across ++ // adapter frames...this is likely to be the root cause of the ++ // failure with the simpler algorithm below. ++ ++ for (long offset = 0; ++ offset < regionInBytesToSearch; ++ offset += vm.getAddressSize()) { ++ try { ++ Address curSP = sp.addOffsetTo(offset); ++ Frame frame = new LOONGARCH64Frame(curSP, null, pc); ++ RegisterMap map = thread.newRegisterMap(false); ++ while (frame != null) { ++ if (frame.isEntryFrame() && frame.entryFrameIsFirst()) { ++ // We were able to traverse all the way to the ++ // bottommost Java frame. ++ // This sp looks good. Keep it. ++ if (DEBUG) { ++ System.out.println("CurrentFrameGuess: Choosing sp = " + curSP + ", pc = " + pc); ++ } ++ setValues(curSP, null, pc); ++ return true; ++ } ++ frame = frame.sender(map); ++ } ++ } catch (Exception e) { ++ if (DEBUG) { ++ System.out.println("CurrentFrameGuess: Exception " + e + " at offset " + offset); ++ } ++ // Bad SP. Try another. ++ } ++ } ++ ++ // Were not able to find a plausible SP to go with this PC. ++ // Bail out. ++ return false; ++ ++ /* ++ // Original algorithm which does not work because SP was ++ // pointing beyond where it should have: ++ ++ // For the server compiler, EBP is not guaranteed to be valid ++ // for compiled code. We see whether the PC is in the ++ // interpreter and take care of that, otherwise we run code ++ // (unfortunately) duplicated from LOONGARCH64Frame.senderForCompiledFrame. ++ ++ CodeCache cc = vm.getCodeCache(); ++ if (cc.contains(pc)) { ++ CodeBlob cb = cc.findBlob(pc); ++ ++ // See if we can derive a frame pointer from SP and PC ++ // NOTE: This is the code duplicated from LOONGARCH64Frame ++ Address saved_fp = null; ++ int llink_offset = cb.getLinkOffset(); ++ if (llink_offset >= 0) { ++ // Restore base-pointer, since next frame might be an interpreter frame. ++ Address fp_addr = sp.addOffsetTo(VM.getVM().getAddressSize() * llink_offset); ++ saved_fp = fp_addr.getAddressAt(0); ++ } ++ ++ setValues(sp, saved_fp, pc); ++ return true; ++ } ++ */ ++ } ++ } else { ++ // If the current program counter was not known to us as a Java ++ // PC, we currently assume that we are in the run-time system ++ // and attempt to look to thread-local storage for saved ESP and ++ // EBP. Note that if these are null (because we were, in fact, ++ // in Java code, i.e., vtable stubs or similar, and the SA ++ // didn't have enough insight into the target VM to understand ++ // that) then we are going to lose the entire stack trace for ++ // the thread, which is sub-optimal. FIXME. ++ ++ if (DEBUG) { ++ System.out.println("CurrentFrameGuess: choosing last Java frame: sp = " + ++ thread.getLastJavaSP() + ", fp = " + thread.getLastJavaFP()); ++ } ++ if (thread.getLastJavaSP() == null) { ++ return false; // No known Java frames on stack ++ } ++ ++ // The runtime has a nasty habit of not saving fp in the frame ++ // anchor, leaving us to grovel about in the stack to find a ++ // plausible address. Fortunately, this only happens in ++ // compiled code; there we always have a valid PC, and we always ++ // push LR and FP onto the stack as a pair, with FP at the lower ++ // address. ++ pc = thread.getLastJavaPC(); ++ fp = thread.getLastJavaFP(); ++ sp = thread.getLastJavaSP(); ++ ++ if (fp == null) { ++ CodeCache cc = vm.getCodeCache(); ++ if (cc.contains(pc)) { ++ CodeBlob cb = cc.findBlob(pc); ++ if (DEBUG) { ++ System.out.println("FP is null. Found blob frame size " + cb.getFrameSize()); ++ } ++ // See if we can derive a frame pointer from SP and PC ++ long link_offset = cb.getFrameSize() - 2 * VM.getVM().getAddressSize(); ++ if (link_offset >= 0) { ++ fp = sp.addOffsetTo(link_offset); ++ } ++ } ++ } ++ ++ // We found a PC in the frame anchor. Check that it's plausible, and ++ // if it is, use it. ++ if (vm.isJavaPCDbg(pc)) { ++ setValues(sp, fp, pc); ++ } else { ++ setValues(sp, fp, null); ++ } ++ ++ return true; ++ } ++ } ++ ++ public Address getSP() { return spFound; } ++ public Address getFP() { return fpFound; } ++ /** May be null if getting values from thread-local storage; take ++ care to call the correct LOONGARCH64Frame constructor to recover this if ++ necessary */ ++ public Address getPC() { return pcFound; } ++ ++ private void setValues(Address sp, Address fp, Address pc) { ++ spFound = sp; ++ fpFound = fp; ++ pcFound = pc; ++ } ++} +diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/loongarch64/LOONGARCH64Frame.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/loongarch64/LOONGARCH64Frame.java +new file mode 100644 +index 000000000..058afc94d +--- /dev/null ++++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/loongarch64/LOONGARCH64Frame.java +@@ -0,0 +1,526 @@ ++/* ++ * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2018, 2021, Loongson Technology. 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 sun.jvm.hotspot.runtime.loongarch64; ++ ++import java.util.*; ++import sun.jvm.hotspot.code.*; ++import sun.jvm.hotspot.compiler.*; ++import sun.jvm.hotspot.debugger.*; ++import sun.jvm.hotspot.oops.*; ++import sun.jvm.hotspot.runtime.*; ++import sun.jvm.hotspot.types.*; ++import sun.jvm.hotspot.utilities.*; ++ ++/** Specialization of and implementation of abstract methods of the ++ Frame class for the loongarch64 family of CPUs. */ ++ ++public class LOONGARCH64Frame extends Frame { ++ private static final boolean DEBUG; ++ static { ++ DEBUG = System.getProperty("sun.jvm.hotspot.runtime.loongarch64.LOONGARCH64Frame.DEBUG") != null; ++ } ++ ++ // Java frames ++ private static final int JAVA_FRAME_LINK_OFFSET = 0; ++ private static final int JAVA_FRAME_RETURN_ADDR_OFFSET = 1; ++ private static final int JAVA_FRAME_SENDER_SP_OFFSET = 2; ++ ++ // Native frames ++ private static final int NATIVE_FRAME_LINK_OFFSET = -2; ++ private static final int NATIVE_FRAME_RETURN_ADDR_OFFSET = -1; ++ private static final int NATIVE_FRAME_SENDER_SP_OFFSET = 0; ++ ++ // Interpreter frames ++ private static final int INTERPRETER_FRAME_SENDER_SP_OFFSET = -1; ++ private static final int INTERPRETER_FRAME_LAST_SP_OFFSET = INTERPRETER_FRAME_SENDER_SP_OFFSET - 1; ++ private static final int INTERPRETER_FRAME_LOCALS_OFFSET = INTERPRETER_FRAME_LAST_SP_OFFSET - 1; ++ private static final int INTERPRETER_FRAME_METHOD_OFFSET = INTERPRETER_FRAME_LOCALS_OFFSET - 1; ++ private static final int INTERPRETER_FRAME_MIRROR_OFFSET = INTERPRETER_FRAME_METHOD_OFFSET - 1; ++ private static final int INTERPRETER_FRAME_MDX_OFFSET = INTERPRETER_FRAME_MIRROR_OFFSET - 1; ++ private static final int INTERPRETER_FRAME_CACHE_OFFSET = INTERPRETER_FRAME_MDX_OFFSET - 1; ++ private static final int INTERPRETER_FRAME_BCX_OFFSET = INTERPRETER_FRAME_CACHE_OFFSET - 1; ++ private static final int INTERPRETER_FRAME_INITIAL_SP_OFFSET = INTERPRETER_FRAME_BCX_OFFSET - 1; ++ private static final int INTERPRETER_FRAME_MONITOR_BLOCK_TOP_OFFSET = INTERPRETER_FRAME_INITIAL_SP_OFFSET; ++ private static final int INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET = INTERPRETER_FRAME_INITIAL_SP_OFFSET; ++ ++ // Entry frames ++ private static final int ENTRY_FRAME_CALL_WRAPPER_OFFSET = -9; ++ ++ private static VMReg fp = new VMReg(22 << 1); ++ ++ // an additional field beyond sp and pc: ++ Address raw_fp; // frame pointer ++ private Address raw_unextendedSP; ++ ++ private LOONGARCH64Frame() { ++ } ++ ++ private void adjustForDeopt() { ++ if ( pc != null) { ++ // Look for a deopt pc and if it is deopted convert to original pc ++ CodeBlob cb = VM.getVM().getCodeCache().findBlob(pc); ++ if (cb != null && cb.isJavaMethod()) { ++ NMethod nm = (NMethod) cb; ++ if (pc.equals(nm.deoptHandlerBegin())) { ++ if (Assert.ASSERTS_ENABLED) { ++ Assert.that(this.getUnextendedSP() != null, "null SP in Java frame"); ++ } ++ // adjust pc if frame is deoptimized. ++ pc = this.getUnextendedSP().getAddressAt(nm.origPCOffset()); ++ deoptimized = true; ++ } ++ } ++ } ++ } ++ ++ public LOONGARCH64Frame(Address raw_sp, Address raw_fp, Address pc) { ++ this.raw_sp = raw_sp; ++ this.raw_unextendedSP = raw_sp; ++ this.raw_fp = raw_fp; ++ this.pc = pc; ++ adjustUnextendedSP(); ++ ++ // Frame must be fully constructed before this call ++ adjustForDeopt(); ++ ++ if (DEBUG) { ++ System.out.println("LOONGARCH64Frame(sp, fp, pc): " + this); ++ dumpStack(); ++ } ++ } ++ ++ public LOONGARCH64Frame(Address raw_sp, Address raw_fp) { ++ this.raw_sp = raw_sp; ++ this.raw_unextendedSP = raw_sp; ++ this.raw_fp = raw_fp; ++ this.pc = raw_fp.getAddressAt(1 * VM.getVM().getAddressSize()); ++ adjustUnextendedSP(); ++ ++ // Frame must be fully constructed before this call ++ adjustForDeopt(); ++ ++ if (DEBUG) { ++ System.out.println("LOONGARCH64Frame(sp, fp): " + this); ++ dumpStack(); ++ } ++ } ++ ++ public LOONGARCH64Frame(Address raw_sp, Address raw_unextendedSp, Address raw_fp, Address pc) { ++ this.raw_sp = raw_sp; ++ this.raw_unextendedSP = raw_unextendedSp; ++ this.raw_fp = raw_fp; ++ this.pc = pc; ++ adjustUnextendedSP(); ++ ++ // Frame must be fully constructed before this call ++ adjustForDeopt(); ++ ++ if (DEBUG) { ++ System.out.println("LOONGARCH64Frame(sp, unextendedSP, fp, pc): " + this); ++ dumpStack(); ++ } ++ ++ } ++ ++ public Object clone() { ++ LOONGARCH64Frame frame = new LOONGARCH64Frame(); ++ frame.raw_sp = raw_sp; ++ frame.raw_unextendedSP = raw_unextendedSP; ++ frame.raw_fp = raw_fp; ++ frame.pc = pc; ++ frame.deoptimized = deoptimized; ++ return frame; ++ } ++ ++ public boolean equals(Object arg) { ++ if (arg == null) { ++ return false; ++ } ++ ++ if (!(arg instanceof LOONGARCH64Frame)) { ++ return false; ++ } ++ ++ LOONGARCH64Frame other = (LOONGARCH64Frame) arg; ++ ++ return (AddressOps.equal(getSP(), other.getSP()) && ++ AddressOps.equal(getUnextendedSP(), other.getUnextendedSP()) && ++ AddressOps.equal(getFP(), other.getFP()) && ++ AddressOps.equal(getPC(), other.getPC())); ++ } ++ ++ public int hashCode() { ++ if (raw_sp == null) { ++ return 0; ++ } ++ ++ return raw_sp.hashCode(); ++ } ++ ++ public String toString() { ++ return "sp: " + (getSP() == null? "null" : getSP().toString()) + ++ ", unextendedSP: " + (getUnextendedSP() == null? "null" : getUnextendedSP().toString()) + ++ ", fp: " + (getFP() == null? "null" : getFP().toString()) + ++ ", pc: " + (pc == null? "null" : pc.toString()); ++ } ++ ++ // accessors for the instance variables ++ public Address getFP() { return raw_fp; } ++ public Address getSP() { return raw_sp; } ++ public Address getID() { return raw_sp; } ++ ++ // FIXME: not implemented yet (should be done for Solaris/LOONGARCH) ++ public boolean isSignalHandlerFrameDbg() { return false; } ++ public int getSignalNumberDbg() { return 0; } ++ public String getSignalNameDbg() { return null; } ++ ++ public boolean isInterpretedFrameValid() { ++ if (Assert.ASSERTS_ENABLED) { ++ Assert.that(isInterpretedFrame(), "Not an interpreted frame"); ++ } ++ ++ // These are reasonable sanity checks ++ if (getFP() == null || getFP().andWithMask(0x3) != null) { ++ return false; ++ } ++ ++ if (getSP() == null || getSP().andWithMask(0x3) != null) { ++ return false; ++ } ++ ++ if (getFP().addOffsetTo(INTERPRETER_FRAME_INITIAL_SP_OFFSET * VM.getVM().getAddressSize()).lessThan(getSP())) { ++ return false; ++ } ++ ++ // These are hacks to keep us out of trouble. ++ // The problem with these is that they mask other problems ++ if (getFP().lessThanOrEqual(getSP())) { ++ // this attempts to deal with unsigned comparison above ++ return false; ++ } ++ ++ if (getFP().minus(getSP()) > 4096 * VM.getVM().getAddressSize()) { ++ // stack frames shouldn't be large. ++ return false; ++ } ++ ++ return true; ++ } ++ ++ // FIXME: not applicable in current system ++ // void patch_pc(Thread* thread, address pc); ++ ++ public Frame sender(RegisterMap regMap, CodeBlob cb) { ++ LOONGARCH64RegisterMap map = (LOONGARCH64RegisterMap) regMap; ++ ++ if (Assert.ASSERTS_ENABLED) { ++ Assert.that(map != null, "map must be set"); ++ } ++ ++ // Default is we done have to follow them. The sender_for_xxx will ++ // update it accordingly ++ map.setIncludeArgumentOops(false); ++ ++ if (isEntryFrame()) return senderForEntryFrame(map); ++ if (isInterpretedFrame()) return senderForInterpreterFrame(map); ++ ++ if(cb == null) { ++ cb = VM.getVM().getCodeCache().findBlob(getPC()); ++ } else { ++ if (Assert.ASSERTS_ENABLED) { ++ Assert.that(cb.equals(VM.getVM().getCodeCache().findBlob(getPC())), "Must be the same"); ++ } ++ } ++ ++ if (cb != null) { ++ return senderForCompiledFrame(map, cb); ++ } ++ ++ // Must be native-compiled frame, i.e. the marshaling code for native ++ // methods that exists in the core system. ++ return new LOONGARCH64Frame(getSenderSP(), getLink(), getSenderPC()); ++ } ++ ++ private Frame senderForEntryFrame(LOONGARCH64RegisterMap map) { ++ if (DEBUG) { ++ System.out.println("senderForEntryFrame"); ++ } ++ if (Assert.ASSERTS_ENABLED) { ++ Assert.that(map != null, "map must be set"); ++ } ++ // Java frame called from C; skip all C frames and return top C ++ // frame of that chunk as the sender ++ LOONGARCH64JavaCallWrapper jcw = (LOONGARCH64JavaCallWrapper) getEntryFrameCallWrapper(); ++ if (Assert.ASSERTS_ENABLED) { ++ Assert.that(!entryFrameIsFirst(), "next Java fp must be non zero"); ++ Assert.that(jcw.getLastJavaSP().greaterThan(getSP()), "must be above this frame on stack"); ++ } ++ LOONGARCH64Frame fr; ++ if (jcw.getLastJavaPC() != null) { ++ fr = new LOONGARCH64Frame(jcw.getLastJavaSP(), jcw.getLastJavaFP(), jcw.getLastJavaPC()); ++ } else { ++ fr = new LOONGARCH64Frame(jcw.getLastJavaSP(), jcw.getLastJavaFP()); ++ } ++ map.clear(); ++ if (Assert.ASSERTS_ENABLED) { ++ Assert.that(map.getIncludeArgumentOops(), "should be set by clear"); ++ } ++ return fr; ++ } ++ ++ //------------------------------------------------------------------------------ ++ // frame::adjust_unextended_sp ++ private void adjustUnextendedSP() { ++ // On loongarch, sites calling method handle intrinsics and lambda forms are treated ++ // as any other call site. Therefore, no special action is needed when we are ++ // returning to any of these call sites. ++ ++ CodeBlob cb = cb(); ++ NMethod senderNm = (cb == null) ? null : cb.asNMethodOrNull(); ++ if (senderNm != null) { ++ // If the sender PC is a deoptimization point, get the original PC. ++ if (senderNm.isDeoptEntry(getPC()) || ++ senderNm.isDeoptMhEntry(getPC())) { ++ // DEBUG_ONLY(verifyDeoptriginalPc(senderNm, raw_unextendedSp)); ++ } ++ } ++ } ++ ++ private Frame senderForInterpreterFrame(LOONGARCH64RegisterMap map) { ++ if (DEBUG) { ++ System.out.println("senderForInterpreterFrame"); ++ } ++ Address unextendedSP = addressOfStackSlot(INTERPRETER_FRAME_SENDER_SP_OFFSET).getAddressAt(0); ++ Address sp = getSenderSP(); ++ // We do not need to update the callee-save register mapping because above ++ // us is either another interpreter frame or a converter-frame, but never ++ // directly a compiled frame. ++ // 11/24/04 SFG. With the removal of adapter frames this is no longer true. ++ // However c2 no longer uses callee save register for java calls so there ++ // are no callee register to find. ++ ++ if (map.getUpdateMap()) ++ updateMapWithSavedLink(map, addressOfStackSlot(JAVA_FRAME_LINK_OFFSET)); ++ ++ return new LOONGARCH64Frame(sp, unextendedSP, getLink(), getSenderPC()); ++ } ++ ++ private void updateMapWithSavedLink(RegisterMap map, Address savedFPAddr) { ++ map.setLocation(fp, savedFPAddr); ++ } ++ ++ private Frame senderForCompiledFrame(LOONGARCH64RegisterMap map, CodeBlob cb) { ++ if (DEBUG) { ++ System.out.println("senderForCompiledFrame"); ++ } ++ ++ // ++ // NOTE: some of this code is (unfortunately) duplicated in LOONGARCH64CurrentFrameGuess ++ // ++ ++ if (Assert.ASSERTS_ENABLED) { ++ Assert.that(map != null, "map must be set"); ++ } ++ ++ // frame owned by optimizing compiler ++ if (Assert.ASSERTS_ENABLED) { ++ Assert.that(cb.getFrameSize() >= 0, "must have non-zero frame size"); ++ } ++ Address senderSP = getUnextendedSP().addOffsetTo(cb.getFrameSize()); ++ ++ // On Intel the return_address is always the word on the stack ++ Address senderPC = senderSP.getAddressAt(-1 * VM.getVM().getAddressSize()); ++ ++ // This is the saved value of EBP which may or may not really be an FP. ++ // It is only an FP if the sender is an interpreter frame (or C1?). ++ Address savedFPAddr = senderSP.addOffsetTo(- JAVA_FRAME_SENDER_SP_OFFSET * VM.getVM().getAddressSize()); ++ ++ if (map.getUpdateMap()) { ++ // Tell GC to use argument oopmaps for some runtime stubs that need it. ++ // For C1, the runtime stub might not have oop maps, so set this flag ++ // outside of update_register_map. ++ map.setIncludeArgumentOops(cb.callerMustGCArguments()); ++ ++ if (cb.getOopMaps() != null) { ++ ImmutableOopMapSet.updateRegisterMap(this, cb, map, true); ++ } ++ ++ // Since the prolog does the save and restore of EBP there is no oopmap ++ // for it so we must fill in its location as if there was an oopmap entry ++ // since if our caller was compiled code there could be live jvm state in it. ++ updateMapWithSavedLink(map, savedFPAddr); ++ } ++ ++ return new LOONGARCH64Frame(senderSP, savedFPAddr.getAddressAt(0), senderPC); ++ } ++ ++ protected boolean hasSenderPD() { ++ // FIXME ++ // Check for null ebp? Need to do some tests. ++ return true; ++ } ++ ++ public long frameSize() { ++ return (getSenderSP().minus(getSP()) / VM.getVM().getAddressSize()); ++ } ++ ++ public Address getLink() { ++ if (isJavaFrame()) ++ return addressOfStackSlot(JAVA_FRAME_LINK_OFFSET).getAddressAt(0); ++ return addressOfStackSlot(NATIVE_FRAME_LINK_OFFSET).getAddressAt(0); ++ } ++ ++ public Address getUnextendedSP() { return raw_unextendedSP; } ++ ++ // Return address: ++ public Address getSenderPCAddr() { ++ if (isJavaFrame()) ++ return addressOfStackSlot(JAVA_FRAME_RETURN_ADDR_OFFSET); ++ return addressOfStackSlot(NATIVE_FRAME_RETURN_ADDR_OFFSET); ++ } ++ ++ public Address getSenderPC() { return getSenderPCAddr().getAddressAt(0); } ++ ++ public Address getSenderSP() { ++ if (isJavaFrame()) ++ return addressOfStackSlot(JAVA_FRAME_SENDER_SP_OFFSET); ++ return addressOfStackSlot(NATIVE_FRAME_SENDER_SP_OFFSET); ++ } ++ ++ public Address addressOfInterpreterFrameLocals() { ++ return addressOfStackSlot(INTERPRETER_FRAME_LOCALS_OFFSET); ++ } ++ ++ private Address addressOfInterpreterFrameBCX() { ++ return addressOfStackSlot(INTERPRETER_FRAME_BCX_OFFSET); ++ } ++ ++ public int getInterpreterFrameBCI() { ++ // FIXME: this is not atomic with respect to GC and is unsuitable ++ // for use in a non-debugging, or reflective, system. Need to ++ // figure out how to express this. ++ Address bcp = addressOfInterpreterFrameBCX().getAddressAt(0); ++ Address methodHandle = addressOfInterpreterFrameMethod().getAddressAt(0); ++ Method method = (Method)Metadata.instantiateWrapperFor(methodHandle); ++ return bcpToBci(bcp, method); ++ } ++ ++ public Address addressOfInterpreterFrameMDX() { ++ return addressOfStackSlot(INTERPRETER_FRAME_MDX_OFFSET); ++ } ++ ++ // FIXME ++ //inline int frame::interpreter_frame_monitor_size() { ++ // return BasicObjectLock::size(); ++ //} ++ ++ // expression stack ++ // (the max_stack arguments are used by the GC; see class FrameClosure) ++ ++ public Address addressOfInterpreterFrameExpressionStack() { ++ Address monitorEnd = interpreterFrameMonitorEnd().address(); ++ return monitorEnd.addOffsetTo(-1 * VM.getVM().getAddressSize()); ++ } ++ ++ public int getInterpreterFrameExpressionStackDirection() { return -1; } ++ ++ // top of expression stack ++ public Address addressOfInterpreterFrameTOS() { ++ return getSP(); ++ } ++ ++ /** Expression stack from top down */ ++ public Address addressOfInterpreterFrameTOSAt(int slot) { ++ return addressOfInterpreterFrameTOS().addOffsetTo(slot * VM.getVM().getAddressSize()); ++ } ++ ++ public Address getInterpreterFrameSenderSP() { ++ if (Assert.ASSERTS_ENABLED) { ++ Assert.that(isInterpretedFrame(), "interpreted frame expected"); ++ } ++ return addressOfStackSlot(INTERPRETER_FRAME_SENDER_SP_OFFSET).getAddressAt(0); ++ } ++ ++ // Monitors ++ public BasicObjectLock interpreterFrameMonitorBegin() { ++ return new BasicObjectLock(addressOfStackSlot(INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET)); ++ } ++ ++ public BasicObjectLock interpreterFrameMonitorEnd() { ++ Address result = addressOfStackSlot(INTERPRETER_FRAME_MONITOR_BLOCK_TOP_OFFSET).getAddressAt(0); ++ if (Assert.ASSERTS_ENABLED) { ++ // make sure the pointer points inside the frame ++ Assert.that(AddressOps.gt(getFP(), result), "result must < than frame pointer"); ++ Assert.that(AddressOps.lte(getSP(), result), "result must >= than stack pointer"); ++ } ++ return new BasicObjectLock(result); ++ } ++ ++ public int interpreterFrameMonitorSize() { ++ return BasicObjectLock.size(); ++ } ++ ++ // Method ++ public Address addressOfInterpreterFrameMethod() { ++ return addressOfStackSlot(INTERPRETER_FRAME_METHOD_OFFSET); ++ } ++ ++ // Constant pool cache ++ public Address addressOfInterpreterFrameCPCache() { ++ return addressOfStackSlot(INTERPRETER_FRAME_CACHE_OFFSET); ++ } ++ ++ // Entry frames ++ public JavaCallWrapper getEntryFrameCallWrapper() { ++ return new LOONGARCH64JavaCallWrapper(addressOfStackSlot(ENTRY_FRAME_CALL_WRAPPER_OFFSET).getAddressAt(0)); ++ } ++ ++ protected Address addressOfSavedOopResult() { ++ // offset is 2 for compiler2 and 3 for compiler1 ++ return getSP().addOffsetTo((VM.getVM().isClientCompiler() ? 2 : 3) * ++ VM.getVM().getAddressSize()); ++ } ++ ++ protected Address addressOfSavedReceiver() { ++ return getSP().addOffsetTo(-4 * VM.getVM().getAddressSize()); ++ } ++ ++ private void dumpStack() { ++ if (getFP() != null) { ++ for (Address addr = getSP().addOffsetTo(-5 * VM.getVM().getAddressSize()); ++ AddressOps.lte(addr, getFP().addOffsetTo(5 * VM.getVM().getAddressSize())); ++ addr = addr.addOffsetTo(VM.getVM().getAddressSize())) { ++ System.out.println(addr + ": " + addr.getAddressAt(0)); ++ } ++ } else { ++ for (Address addr = getSP().addOffsetTo(-5 * VM.getVM().getAddressSize()); ++ AddressOps.lte(addr, getSP().addOffsetTo(20 * VM.getVM().getAddressSize())); ++ addr = addr.addOffsetTo(VM.getVM().getAddressSize())) { ++ System.out.println(addr + ": " + addr.getAddressAt(0)); ++ } ++ } ++ } ++} +diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/loongarch64/LOONGARCH64JavaCallWrapper.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/loongarch64/LOONGARCH64JavaCallWrapper.java +new file mode 100644 +index 000000000..0625e10a4 +--- /dev/null ++++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/loongarch64/LOONGARCH64JavaCallWrapper.java +@@ -0,0 +1,57 @@ ++/* ++ * Copyright (c) 2001, 2002, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2018, 2021, Loongson Technology. 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 sun.jvm.hotspot.runtime.loongarch64; ++ ++import java.util.*; ++import sun.jvm.hotspot.debugger.*; ++import sun.jvm.hotspot.types.*; ++import sun.jvm.hotspot.runtime.*; ++ ++public class LOONGARCH64JavaCallWrapper extends JavaCallWrapper { ++ private static AddressField lastJavaFPField; ++ ++ static { ++ VM.registerVMInitializedObserver(new Observer() { ++ public void update(Observable o, Object data) { ++ initialize(VM.getVM().getTypeDataBase()); ++ } ++ }); ++ } ++ ++ private static synchronized void initialize(TypeDataBase db) { ++ Type type = db.lookupType("JavaFrameAnchor"); ++ ++ lastJavaFPField = type.getAddressField("_last_Java_fp"); ++ } ++ ++ public LOONGARCH64JavaCallWrapper(Address addr) { ++ super(addr); ++ } ++ ++ public Address getLastJavaFP() { ++ return lastJavaFPField.getValue(addr.addOffsetTo(anchorField.getOffset())); ++ } ++} +diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/loongarch64/LOONGARCH64RegisterMap.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/loongarch64/LOONGARCH64RegisterMap.java +new file mode 100644 +index 000000000..2cf904d38 +--- /dev/null ++++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/loongarch64/LOONGARCH64RegisterMap.java +@@ -0,0 +1,52 @@ ++/* ++ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2018, 2021, Loongson Technology. 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 sun.jvm.hotspot.runtime.loongarch64; ++ ++import sun.jvm.hotspot.debugger.*; ++import sun.jvm.hotspot.runtime.*; ++ ++public class LOONGARCH64RegisterMap extends RegisterMap { ++ ++ /** This is the only public constructor */ ++ public LOONGARCH64RegisterMap(JavaThread thread, boolean updateMap) { ++ super(thread, updateMap); ++ } ++ ++ protected LOONGARCH64RegisterMap(RegisterMap map) { ++ super(map); ++ } ++ ++ public Object clone() { ++ LOONGARCH64RegisterMap retval = new LOONGARCH64RegisterMap(this); ++ return retval; ++ } ++ ++ // no PD state to clear or copy: ++ protected void clearPD() {} ++ protected void initializePD() {} ++ protected void initializeFromPD(RegisterMap map) {} ++ protected Address getLocationPD(VMReg reg) { return null; } ++} +diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/mips64/MIPS64CurrentFrameGuess.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/mips64/MIPS64CurrentFrameGuess.java +new file mode 100644 +index 000000000..c11458abe +--- /dev/null ++++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/mips64/MIPS64CurrentFrameGuess.java +@@ -0,0 +1,217 @@ ++/* ++ * Copyright (c) 2001, 2006, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2018, Loongson Technology. 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 sun.jvm.hotspot.runtime.mips64; ++ ++import sun.jvm.hotspot.debugger.*; ++import sun.jvm.hotspot.debugger.mips64.*; ++import sun.jvm.hotspot.code.*; ++import sun.jvm.hotspot.interpreter.*; ++import sun.jvm.hotspot.runtime.*; ++ ++/**

Should be able to be used on all mips64 platforms we support ++ (Win32, Solaris/mips64, and soon Linux) to implement JavaThread's ++ "currentFrameGuess()" functionality. Input is an MIPS64ThreadContext; ++ output is SP, FP, and PC for an MIPS64Frame. Instantiation of the ++ MIPS64Frame is left to the caller, since we may need to subclass ++ MIPS64Frame to support signal handler frames on Unix platforms.

++ ++

Algorithm is to walk up the stack within a given range (say, ++ 512K at most) looking for a plausible PC and SP for a Java frame, ++ also considering those coming in from the context. If we find a PC ++ that belongs to the VM (i.e., in generated code like the ++ interpreter or CodeCache) then we try to find an associated EBP. ++ We repeat this until we either find a complete frame or run out of ++ stack to look at.

*/ ++ ++public class MIPS64CurrentFrameGuess { ++ private MIPS64ThreadContext context; ++ private JavaThread thread; ++ private Address spFound; ++ private Address fpFound; ++ private Address pcFound; ++ ++ private static final boolean DEBUG = System.getProperty("sun.jvm.hotspot.runtime.mips64.MIPS64Frame.DEBUG") ++ != null; ++ ++ public MIPS64CurrentFrameGuess(MIPS64ThreadContext context, ++ JavaThread thread) { ++ this.context = context; ++ this.thread = thread; ++ } ++ ++ /** Returns false if not able to find a frame within a reasonable range. */ ++ public boolean run(long regionInBytesToSearch) { ++ Address sp = context.getRegisterAsAddress(MIPS64ThreadContext.SP); ++ Address pc = context.getRegisterAsAddress(MIPS64ThreadContext.PC); ++ Address fp = context.getRegisterAsAddress(MIPS64ThreadContext.FP); ++ if (sp == null) { ++ // Bail out if no last java frame eithe ++ if (thread.getLastJavaSP() != null) { ++ setValues(thread.getLastJavaSP(), thread.getLastJavaFP(), null); ++ return true; ++ } ++ // Bail out ++ return false; ++ } ++ Address end = sp.addOffsetTo(regionInBytesToSearch); ++ VM vm = VM.getVM(); ++ ++ setValues(null, null, null); // Assume we're not going to find anything ++ ++ if (vm.isJavaPCDbg(pc)) { ++ if (vm.isClientCompiler()) { ++ // If the topmost frame is a Java frame, we are (pretty much) ++ // guaranteed to have a viable EBP. We should be more robust ++ // than this (we have the potential for losing entire threads' ++ // stack traces) but need to see how much work we really have ++ // to do here. Searching the stack for an (SP, FP) pair is ++ // hard since it's easy to misinterpret inter-frame stack ++ // pointers as base-of-frame pointers; we also don't know the ++ // sizes of C1 frames (not registered in the nmethod) so can't ++ // derive them from ESP. ++ ++ setValues(sp, fp, pc); ++ return true; ++ } else { ++ if (vm.getInterpreter().contains(pc)) { ++ if (DEBUG) { ++ System.out.println("CurrentFrameGuess: choosing interpreter frame: sp = " + ++ sp + ", fp = " + fp + ", pc = " + pc); ++ } ++ setValues(sp, fp, pc); ++ return true; ++ } ++ ++ // For the server compiler, EBP is not guaranteed to be valid ++ // for compiled code. In addition, an earlier attempt at a ++ // non-searching algorithm (see below) failed because the ++ // stack pointer from the thread context was pointing ++ // (considerably) beyond the ostensible end of the stack, into ++ // garbage; walking from the topmost frame back caused a crash. ++ // ++ // This algorithm takes the current PC as a given and tries to ++ // find the correct corresponding SP by walking up the stack ++ // and repeatedly performing stackwalks (very inefficient). ++ // ++ // FIXME: there is something wrong with stackwalking across ++ // adapter frames...this is likely to be the root cause of the ++ // failure with the simpler algorithm below. ++ ++ for (long offset = 0; ++ offset < regionInBytesToSearch; ++ offset += vm.getAddressSize()) { ++ try { ++ Address curSP = sp.addOffsetTo(offset); ++ Frame frame = new MIPS64Frame(curSP, null, pc); ++ RegisterMap map = thread.newRegisterMap(false); ++ while (frame != null) { ++ if (frame.isEntryFrame() && frame.entryFrameIsFirst()) { ++ // We were able to traverse all the way to the ++ // bottommost Java frame. ++ // This sp looks good. Keep it. ++ if (DEBUG) { ++ System.out.println("CurrentFrameGuess: Choosing sp = " + curSP + ", pc = " + pc); ++ } ++ setValues(curSP, null, pc); ++ return true; ++ } ++ frame = frame.sender(map); ++ } ++ } catch (Exception e) { ++ if (DEBUG) { ++ System.out.println("CurrentFrameGuess: Exception " + e + " at offset " + offset); ++ } ++ // Bad SP. Try another. ++ } ++ } ++ ++ // Were not able to find a plausible SP to go with this PC. ++ // Bail out. ++ return false; ++ ++ /* ++ // Original algorithm which does not work because SP was ++ // pointing beyond where it should have: ++ ++ // For the server compiler, EBP is not guaranteed to be valid ++ // for compiled code. We see whether the PC is in the ++ // interpreter and take care of that, otherwise we run code ++ // (unfortunately) duplicated from MIPS64Frame.senderForCompiledFrame. ++ ++ CodeCache cc = vm.getCodeCache(); ++ if (cc.contains(pc)) { ++ CodeBlob cb = cc.findBlob(pc); ++ ++ // See if we can derive a frame pointer from SP and PC ++ // NOTE: This is the code duplicated from MIPS64Frame ++ Address saved_fp = null; ++ int llink_offset = cb.getLinkOffset(); ++ if (llink_offset >= 0) { ++ // Restore base-pointer, since next frame might be an interpreter frame. ++ Address fp_addr = sp.addOffsetTo(VM.getVM().getAddressSize() * llink_offset); ++ saved_fp = fp_addr.getAddressAt(0); ++ } ++ ++ setValues(sp, saved_fp, pc); ++ return true; ++ } ++ */ ++ } ++ } else { ++ // If the current program counter was not known to us as a Java ++ // PC, we currently assume that we are in the run-time system ++ // and attempt to look to thread-local storage for saved ESP and ++ // EBP. Note that if these are null (because we were, in fact, ++ // in Java code, i.e., vtable stubs or similar, and the SA ++ // didn't have enough insight into the target VM to understand ++ // that) then we are going to lose the entire stack trace for ++ // the thread, which is sub-optimal. FIXME. ++ ++ if (DEBUG) { ++ System.out.println("CurrentFrameGuess: choosing last Java frame: sp = " + ++ thread.getLastJavaSP() + ", fp = " + thread.getLastJavaFP()); ++ } ++ if (thread.getLastJavaSP() == null) { ++ return false; // No known Java frames on stack ++ } ++ setValues(thread.getLastJavaSP(), thread.getLastJavaFP(), null); ++ return true; ++ } ++ } ++ ++ public Address getSP() { return spFound; } ++ public Address getFP() { return fpFound; } ++ /** May be null if getting values from thread-local storage; take ++ care to call the correct MIPS64Frame constructor to recover this if ++ necessary */ ++ public Address getPC() { return pcFound; } ++ ++ private void setValues(Address sp, Address fp, Address pc) { ++ spFound = sp; ++ fpFound = fp; ++ pcFound = pc; ++ } ++} +diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/mips64/MIPS64Frame.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/mips64/MIPS64Frame.java +new file mode 100644 +index 000000000..65d88016e +--- /dev/null ++++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/mips64/MIPS64Frame.java +@@ -0,0 +1,537 @@ ++/* ++ * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2018, Loongson Technology. 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 sun.jvm.hotspot.runtime.mips64; ++ ++import java.util.*; ++import sun.jvm.hotspot.code.*; ++import sun.jvm.hotspot.compiler.*; ++import sun.jvm.hotspot.debugger.*; ++import sun.jvm.hotspot.oops.*; ++import sun.jvm.hotspot.runtime.*; ++import sun.jvm.hotspot.types.*; ++import sun.jvm.hotspot.utilities.*; ++ ++/** Specialization of and implementation of abstract methods of the ++ Frame class for the mips64 family of CPUs. */ ++ ++public class MIPS64Frame extends Frame { ++ private static final boolean DEBUG; ++ static { ++ DEBUG = System.getProperty("sun.jvm.hotspot.runtime.mips64.MIPS64Frame.DEBUG") != null; ++ } ++ ++ // All frames ++ private static final int LINK_OFFSET = 0; ++ private static final int RETURN_ADDR_OFFSET = 1; ++ private static final int SENDER_SP_OFFSET = 2; ++ ++ // Interpreter frames ++ private static final int INTERPRETER_FRAME_SENDER_SP_OFFSET = -1; ++ private static final int INTERPRETER_FRAME_LAST_SP_OFFSET = INTERPRETER_FRAME_SENDER_SP_OFFSET - 1; ++ private static final int INTERPRETER_FRAME_METHOD_OFFSET = INTERPRETER_FRAME_LAST_SP_OFFSET - 1; ++ private static int INTERPRETER_FRAME_MIRROR_OFFSET; ++ private static int INTERPRETER_FRAME_MDX_OFFSET; // Non-core builds only ++ private static int INTERPRETER_FRAME_CACHE_OFFSET; ++ private static int INTERPRETER_FRAME_LOCALS_OFFSET; ++ private static int INTERPRETER_FRAME_BCX_OFFSET; ++ private static int INTERPRETER_FRAME_INITIAL_SP_OFFSET; ++ private static int INTERPRETER_FRAME_MONITOR_BLOCK_TOP_OFFSET; ++ private static int INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET; ++ ++ // Entry frames ++ private static int ENTRY_FRAME_CALL_WRAPPER_OFFSET; ++ ++ private static VMReg rbp; ++ ++ static { ++ VM.registerVMInitializedObserver(new Observer() { ++ public void update(Observable o, Object data) { ++ initialize(VM.getVM().getTypeDataBase()); ++ } ++ }); ++ } ++ ++ private static synchronized void initialize(TypeDataBase db) { ++ INTERPRETER_FRAME_MIRROR_OFFSET = INTERPRETER_FRAME_METHOD_OFFSET - 1; ++ INTERPRETER_FRAME_MDX_OFFSET = INTERPRETER_FRAME_MIRROR_OFFSET - 1; ++ INTERPRETER_FRAME_CACHE_OFFSET = INTERPRETER_FRAME_MDX_OFFSET - 1; ++ INTERPRETER_FRAME_LOCALS_OFFSET = INTERPRETER_FRAME_CACHE_OFFSET - 1; ++ INTERPRETER_FRAME_BCX_OFFSET = INTERPRETER_FRAME_LOCALS_OFFSET - 1; ++ INTERPRETER_FRAME_INITIAL_SP_OFFSET = INTERPRETER_FRAME_BCX_OFFSET - 1; ++ INTERPRETER_FRAME_MONITOR_BLOCK_TOP_OFFSET = INTERPRETER_FRAME_INITIAL_SP_OFFSET; ++ INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET = INTERPRETER_FRAME_INITIAL_SP_OFFSET; ++ ++ ENTRY_FRAME_CALL_WRAPPER_OFFSET = db.lookupIntConstant("frame::entry_frame_call_wrapper_offset"); ++ if (VM.getVM().getAddressSize() == 4) { ++ rbp = new VMReg(5); ++ } else { ++ rbp = new VMReg(5 << 1); ++ } ++ } ++ ++ ++ // an additional field beyond sp and pc: ++ Address raw_fp; // frame pointer ++ private Address raw_unextendedSP; ++ ++ private MIPS64Frame() { ++ } ++ ++ private void adjustForDeopt() { ++ if ( pc != null) { ++ // Look for a deopt pc and if it is deopted convert to original pc ++ CodeBlob cb = VM.getVM().getCodeCache().findBlob(pc); ++ if (cb != null && cb.isJavaMethod()) { ++ NMethod nm = (NMethod) cb; ++ if (pc.equals(nm.deoptHandlerBegin())) { ++ if (Assert.ASSERTS_ENABLED) { ++ Assert.that(this.getUnextendedSP() != null, "null SP in Java frame"); ++ } ++ // adjust pc if frame is deoptimized. ++ pc = this.getUnextendedSP().getAddressAt(nm.origPCOffset()); ++ deoptimized = true; ++ } ++ } ++ } ++ } ++ ++ public MIPS64Frame(Address raw_sp, Address raw_fp, Address pc) { ++ this.raw_sp = raw_sp; ++ this.raw_unextendedSP = raw_sp; ++ this.raw_fp = raw_fp; ++ this.pc = pc; ++ adjustUnextendedSP(); ++ ++ // Frame must be fully constructed before this call ++ adjustForDeopt(); ++ ++ if (DEBUG) { ++ System.out.println("MIPS64Frame(sp, fp, pc): " + this); ++ dumpStack(); ++ } ++ } ++ ++ public MIPS64Frame(Address raw_sp, Address raw_fp) { ++ this.raw_sp = raw_sp; ++ this.raw_unextendedSP = raw_sp; ++ this.raw_fp = raw_fp; ++ this.pc = raw_sp.getAddressAt(-1 * VM.getVM().getAddressSize()); ++ adjustUnextendedSP(); ++ ++ // Frame must be fully constructed before this call ++ adjustForDeopt(); ++ ++ if (DEBUG) { ++ System.out.println("MIPS64Frame(sp, fp): " + this); ++ dumpStack(); ++ } ++ } ++ ++ public MIPS64Frame(Address raw_sp, Address raw_unextendedSp, Address raw_fp, Address pc) { ++ this.raw_sp = raw_sp; ++ this.raw_unextendedSP = raw_unextendedSp; ++ this.raw_fp = raw_fp; ++ this.pc = pc; ++ adjustUnextendedSP(); ++ ++ // Frame must be fully constructed before this call ++ adjustForDeopt(); ++ ++ if (DEBUG) { ++ System.out.println("MIPS64Frame(sp, unextendedSP, fp, pc): " + this); ++ dumpStack(); ++ } ++ ++ } ++ ++ public Object clone() { ++ MIPS64Frame frame = new MIPS64Frame(); ++ frame.raw_sp = raw_sp; ++ frame.raw_unextendedSP = raw_unextendedSP; ++ frame.raw_fp = raw_fp; ++ frame.pc = pc; ++ frame.deoptimized = deoptimized; ++ return frame; ++ } ++ ++ public boolean equals(Object arg) { ++ if (arg == null) { ++ return false; ++ } ++ ++ if (!(arg instanceof MIPS64Frame)) { ++ return false; ++ } ++ ++ MIPS64Frame other = (MIPS64Frame) arg; ++ ++ return (AddressOps.equal(getSP(), other.getSP()) && ++ AddressOps.equal(getUnextendedSP(), other.getUnextendedSP()) && ++ AddressOps.equal(getFP(), other.getFP()) && ++ AddressOps.equal(getPC(), other.getPC())); ++ } ++ ++ public int hashCode() { ++ if (raw_sp == null) { ++ return 0; ++ } ++ ++ return raw_sp.hashCode(); ++ } ++ ++ public String toString() { ++ return "sp: " + (getSP() == null? "null" : getSP().toString()) + ++ ", unextendedSP: " + (getUnextendedSP() == null? "null" : getUnextendedSP().toString()) + ++ ", fp: " + (getFP() == null? "null" : getFP().toString()) + ++ ", pc: " + (pc == null? "null" : pc.toString()); ++ } ++ ++ // accessors for the instance variables ++ public Address getFP() { return raw_fp; } ++ public Address getSP() { return raw_sp; } ++ public Address getID() { return raw_sp; } ++ ++ // FIXME: not implemented yet (should be done for Solaris/MIPS) ++ public boolean isSignalHandlerFrameDbg() { return false; } ++ public int getSignalNumberDbg() { return 0; } ++ public String getSignalNameDbg() { return null; } ++ ++ public boolean isInterpretedFrameValid() { ++ if (Assert.ASSERTS_ENABLED) { ++ Assert.that(isInterpretedFrame(), "Not an interpreted frame"); ++ } ++ ++ // These are reasonable sanity checks ++ if (getFP() == null || getFP().andWithMask(0x3) != null) { ++ return false; ++ } ++ ++ if (getSP() == null || getSP().andWithMask(0x3) != null) { ++ return false; ++ } ++ ++ if (getFP().addOffsetTo(INTERPRETER_FRAME_INITIAL_SP_OFFSET * VM.getVM().getAddressSize()).lessThan(getSP())) { ++ return false; ++ } ++ ++ // These are hacks to keep us out of trouble. ++ // The problem with these is that they mask other problems ++ if (getFP().lessThanOrEqual(getSP())) { ++ // this attempts to deal with unsigned comparison above ++ return false; ++ } ++ ++ if (getFP().minus(getSP()) > 4096 * VM.getVM().getAddressSize()) { ++ // stack frames shouldn't be large. ++ return false; ++ } ++ ++ return true; ++ } ++ ++ // FIXME: not applicable in current system ++ // void patch_pc(Thread* thread, address pc); ++ ++ public Frame sender(RegisterMap regMap, CodeBlob cb) { ++ MIPS64RegisterMap map = (MIPS64RegisterMap) regMap; ++ ++ if (Assert.ASSERTS_ENABLED) { ++ Assert.that(map != null, "map must be set"); ++ } ++ ++ // Default is we done have to follow them. The sender_for_xxx will ++ // update it accordingly ++ map.setIncludeArgumentOops(false); ++ ++ if (isEntryFrame()) return senderForEntryFrame(map); ++ if (isInterpretedFrame()) return senderForInterpreterFrame(map); ++ ++ if(cb == null) { ++ cb = VM.getVM().getCodeCache().findBlob(getPC()); ++ } else { ++ if (Assert.ASSERTS_ENABLED) { ++ Assert.that(cb.equals(VM.getVM().getCodeCache().findBlob(getPC())), "Must be the same"); ++ } ++ } ++ ++ if (cb != null) { ++ return senderForCompiledFrame(map, cb); ++ } ++ ++ // Must be native-compiled frame, i.e. the marshaling code for native ++ // methods that exists in the core system. ++ return new MIPS64Frame(getSenderSP(), getLink(), getSenderPC()); ++ } ++ ++ private Frame senderForEntryFrame(MIPS64RegisterMap map) { ++ if (DEBUG) { ++ System.out.println("senderForEntryFrame"); ++ } ++ if (Assert.ASSERTS_ENABLED) { ++ Assert.that(map != null, "map must be set"); ++ } ++ // Java frame called from C; skip all C frames and return top C ++ // frame of that chunk as the sender ++ MIPS64JavaCallWrapper jcw = (MIPS64JavaCallWrapper) getEntryFrameCallWrapper(); ++ if (Assert.ASSERTS_ENABLED) { ++ Assert.that(!entryFrameIsFirst(), "next Java fp must be non zero"); ++ Assert.that(jcw.getLastJavaSP().greaterThan(getSP()), "must be above this frame on stack"); ++ } ++ MIPS64Frame fr; ++ if (jcw.getLastJavaPC() != null) { ++ fr = new MIPS64Frame(jcw.getLastJavaSP(), jcw.getLastJavaFP(), jcw.getLastJavaPC()); ++ } else { ++ fr = new MIPS64Frame(jcw.getLastJavaSP(), jcw.getLastJavaFP()); ++ } ++ map.clear(); ++ if (Assert.ASSERTS_ENABLED) { ++ Assert.that(map.getIncludeArgumentOops(), "should be set by clear"); ++ } ++ return fr; ++ } ++ ++ //------------------------------------------------------------------------------ ++ // frame::adjust_unextended_sp ++ private void adjustUnextendedSP() { ++ // On mips, sites calling method handle intrinsics and lambda forms are treated ++ // as any other call site. Therefore, no special action is needed when we are ++ // returning to any of these call sites. ++ ++ CodeBlob cb = cb(); ++ NMethod senderNm = (cb == null) ? null : cb.asNMethodOrNull(); ++ if (senderNm != null) { ++ // If the sender PC is a deoptimization point, get the original PC. ++ if (senderNm.isDeoptEntry(getPC()) || ++ senderNm.isDeoptMhEntry(getPC())) { ++ // DEBUG_ONLY(verifyDeoptriginalPc(senderNm, raw_unextendedSp)); ++ } ++ } ++ } ++ ++ private Frame senderForInterpreterFrame(MIPS64RegisterMap map) { ++ if (DEBUG) { ++ System.out.println("senderForInterpreterFrame"); ++ } ++ Address unextendedSP = addressOfStackSlot(INTERPRETER_FRAME_SENDER_SP_OFFSET).getAddressAt(0); ++ Address sp = addressOfStackSlot(SENDER_SP_OFFSET); ++ // We do not need to update the callee-save register mapping because above ++ // us is either another interpreter frame or a converter-frame, but never ++ // directly a compiled frame. ++ // 11/24/04 SFG. With the removal of adapter frames this is no longer true. ++ // However c2 no longer uses callee save register for java calls so there ++ // are no callee register to find. ++ ++ if (map.getUpdateMap()) ++ updateMapWithSavedLink(map, addressOfStackSlot(LINK_OFFSET)); ++ ++ return new MIPS64Frame(sp, unextendedSP, getLink(), getSenderPC()); ++ } ++ ++ private void updateMapWithSavedLink(RegisterMap map, Address savedFPAddr) { ++ map.setLocation(rbp, savedFPAddr); ++ } ++ ++ private Frame senderForCompiledFrame(MIPS64RegisterMap map, CodeBlob cb) { ++ if (DEBUG) { ++ System.out.println("senderForCompiledFrame"); ++ } ++ ++ // ++ // NOTE: some of this code is (unfortunately) duplicated in MIPS64CurrentFrameGuess ++ // ++ ++ if (Assert.ASSERTS_ENABLED) { ++ Assert.that(map != null, "map must be set"); ++ } ++ ++ // frame owned by optimizing compiler ++ if (Assert.ASSERTS_ENABLED) { ++ Assert.that(cb.getFrameSize() >= 0, "must have non-zero frame size"); ++ } ++ Address senderSP = getUnextendedSP().addOffsetTo(cb.getFrameSize()); ++ ++ // On Intel the return_address is always the word on the stack ++ Address senderPC = senderSP.getAddressAt(-1 * VM.getVM().getAddressSize()); ++ ++ // This is the saved value of EBP which may or may not really be an FP. ++ // It is only an FP if the sender is an interpreter frame (or C1?). ++ Address savedFPAddr = senderSP.addOffsetTo(- SENDER_SP_OFFSET * VM.getVM().getAddressSize()); ++ ++ if (map.getUpdateMap()) { ++ // Tell GC to use argument oopmaps for some runtime stubs that need it. ++ // For C1, the runtime stub might not have oop maps, so set this flag ++ // outside of update_register_map. ++ map.setIncludeArgumentOops(cb.callerMustGCArguments()); ++ ++ if (cb.getOopMaps() != null) { ++ ImmutableOopMapSet.updateRegisterMap(this, cb, map, true); ++ } ++ ++ // Since the prolog does the save and restore of EBP there is no oopmap ++ // for it so we must fill in its location as if there was an oopmap entry ++ // since if our caller was compiled code there could be live jvm state in it. ++ updateMapWithSavedLink(map, savedFPAddr); ++ } ++ ++ return new MIPS64Frame(senderSP, savedFPAddr.getAddressAt(0), senderPC); ++ } ++ ++ protected boolean hasSenderPD() { ++ // FIXME ++ // Check for null ebp? Need to do some tests. ++ return true; ++ } ++ ++ public long frameSize() { ++ return (getSenderSP().minus(getSP()) / VM.getVM().getAddressSize()); ++ } ++ ++ public Address getLink() { ++ return addressOfStackSlot(LINK_OFFSET).getAddressAt(0); ++ } ++ ++ public Address getUnextendedSP() { return raw_unextendedSP; } ++ ++ // Return address: ++ public Address getSenderPCAddr() { return addressOfStackSlot(RETURN_ADDR_OFFSET); } ++ public Address getSenderPC() { return getSenderPCAddr().getAddressAt(0); } ++ ++ public Address getSenderSP() { return addressOfStackSlot(SENDER_SP_OFFSET); } ++ ++ public Address addressOfInterpreterFrameLocals() { ++ return addressOfStackSlot(INTERPRETER_FRAME_LOCALS_OFFSET); ++ } ++ ++ private Address addressOfInterpreterFrameBCX() { ++ return addressOfStackSlot(INTERPRETER_FRAME_BCX_OFFSET); ++ } ++ ++ public int getInterpreterFrameBCI() { ++ // FIXME: this is not atomic with respect to GC and is unsuitable ++ // for use in a non-debugging, or reflective, system. Need to ++ // figure out how to express this. ++ Address bcp = addressOfInterpreterFrameBCX().getAddressAt(0); ++ Address methodHandle = addressOfInterpreterFrameMethod().getAddressAt(0); ++ Method method = (Method)Metadata.instantiateWrapperFor(methodHandle); ++ return bcpToBci(bcp, method); ++ } ++ ++ public Address addressOfInterpreterFrameMDX() { ++ return addressOfStackSlot(INTERPRETER_FRAME_MDX_OFFSET); + } + -+ public void setRegisterAsAddress(int index, Address value) { -+ setRegister(index, debugger.getAddressValue(value)); ++ // FIXME ++ //inline int frame::interpreter_frame_monitor_size() { ++ // return BasicObjectLock::size(); ++ //} ++ ++ // expression stack ++ // (the max_stack arguments are used by the GC; see class FrameClosure) ++ ++ public Address addressOfInterpreterFrameExpressionStack() { ++ Address monitorEnd = interpreterFrameMonitorEnd().address(); ++ return monitorEnd.addOffsetTo(-1 * VM.getVM().getAddressSize()); + } + -+ public Address getRegisterAsAddress(int index) { -+ return debugger.newAddress(getRegister(index)); ++ public int getInterpreterFrameExpressionStackDirection() { return -1; } ++ ++ // top of expression stack ++ public Address addressOfInterpreterFrameTOS() { ++ return getSP(); ++ } ++ ++ /** Expression stack from top down */ ++ public Address addressOfInterpreterFrameTOSAt(int slot) { ++ return addressOfInterpreterFrameTOS().addOffsetTo(slot * VM.getVM().getAddressSize()); ++ } ++ ++ public Address getInterpreterFrameSenderSP() { ++ if (Assert.ASSERTS_ENABLED) { ++ Assert.that(isInterpretedFrame(), "interpreted frame expected"); ++ } ++ return addressOfStackSlot(INTERPRETER_FRAME_SENDER_SP_OFFSET).getAddressAt(0); ++ } ++ ++ // Monitors ++ public BasicObjectLock interpreterFrameMonitorBegin() { ++ return new BasicObjectLock(addressOfStackSlot(INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET)); ++ } ++ ++ public BasicObjectLock interpreterFrameMonitorEnd() { ++ Address result = addressOfStackSlot(INTERPRETER_FRAME_MONITOR_BLOCK_TOP_OFFSET).getAddressAt(0); ++ if (Assert.ASSERTS_ENABLED) { ++ // make sure the pointer points inside the frame ++ Assert.that(AddressOps.gt(getFP(), result), "result must < than frame pointer"); ++ Assert.that(AddressOps.lte(getSP(), result), "result must >= than stack pointer"); ++ } ++ return new BasicObjectLock(result); ++ } ++ ++ public int interpreterFrameMonitorSize() { ++ return BasicObjectLock.size(); ++ } ++ ++ // Method ++ public Address addressOfInterpreterFrameMethod() { ++ return addressOfStackSlot(INTERPRETER_FRAME_METHOD_OFFSET); ++ } ++ ++ // Constant pool cache ++ public Address addressOfInterpreterFrameCPCache() { ++ return addressOfStackSlot(INTERPRETER_FRAME_CACHE_OFFSET); ++ } ++ ++ // Entry frames ++ public JavaCallWrapper getEntryFrameCallWrapper() { ++ return new MIPS64JavaCallWrapper(addressOfStackSlot(ENTRY_FRAME_CALL_WRAPPER_OFFSET).getAddressAt(0)); ++ } ++ ++ protected Address addressOfSavedOopResult() { ++ // offset is 2 for compiler2 and 3 for compiler1 ++ return getSP().addOffsetTo((VM.getVM().isClientCompiler() ? 2 : 3) * ++ VM.getVM().getAddressSize()); ++ } ++ ++ protected Address addressOfSavedReceiver() { ++ return getSP().addOffsetTo(-4 * VM.getVM().getAddressSize()); ++ } ++ ++ private void dumpStack() { ++ if (getFP() != null) { ++ for (Address addr = getSP().addOffsetTo(-5 * VM.getVM().getAddressSize()); ++ AddressOps.lte(addr, getFP().addOffsetTo(5 * VM.getVM().getAddressSize())); ++ addr = addr.addOffsetTo(VM.getVM().getAddressSize())) { ++ System.out.println(addr + ": " + addr.getAddressAt(0)); ++ } ++ } else { ++ for (Address addr = getSP().addOffsetTo(-5 * VM.getVM().getAddressSize()); ++ AddressOps.lte(addr, getSP().addOffsetTo(20 * VM.getVM().getAddressSize())); ++ addr = addr.addOffsetTo(VM.getVM().getAddressSize())) { ++ System.out.println(addr + ": " + addr.getAddressAt(0)); ++ } ++ } + } +} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/loongarch64/ProcLOONGARCH64ThreadFactory.java jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/loongarch64/ProcLOONGARCH64ThreadFactory.java ---- openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/loongarch64/ProcLOONGARCH64ThreadFactory.java 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/loongarch64/ProcLOONGARCH64ThreadFactory.java 2023-09-12 13:54:26.377575791 +0800 -@@ -0,0 +1,45 @@ +diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/mips64/MIPS64JavaCallWrapper.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/mips64/MIPS64JavaCallWrapper.java +new file mode 100644 +index 000000000..dfe3066af +--- /dev/null ++++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/mips64/MIPS64JavaCallWrapper.java +@@ -0,0 +1,57 @@ +/* -+ * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2021, Loongson Technology. All rights reserved. ++ * Copyright (c) 2001, 2002, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2018, Loongson Technology. 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 @@ -116105,1283 +183294,14476 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.hotspot.agent/shar + * + */ + -+package sun.jvm.hotspot.debugger.proc.loongarch64; ++package sun.jvm.hotspot.runtime.mips64; + ++import java.util.*; +import sun.jvm.hotspot.debugger.*; -+import sun.jvm.hotspot.debugger.proc.*; ++import sun.jvm.hotspot.types.*; ++import sun.jvm.hotspot.runtime.*; + -+public class ProcLOONGARCH64ThreadFactory implements ProcThreadFactory { -+ private ProcDebugger debugger; ++public class MIPS64JavaCallWrapper extends JavaCallWrapper { ++ private static AddressField lastJavaFPField; + -+ public ProcLOONGARCH64ThreadFactory(ProcDebugger debugger) { -+ this.debugger = debugger; ++ static { ++ VM.registerVMInitializedObserver(new Observer() { ++ public void update(Observable o, Object data) { ++ initialize(VM.getVM().getTypeDataBase()); ++ } ++ }); + } + -+ public ThreadProxy createThreadWrapper(Address threadIdentifierAddr) { -+ return new ProcLOONGARCH64Thread(debugger, threadIdentifierAddr); ++ private static synchronized void initialize(TypeDataBase db) { ++ Type type = db.lookupType("JavaFrameAnchor"); ++ ++ lastJavaFPField = type.getAddressField("_last_Java_fp"); + } + -+ public ThreadProxy createThreadWrapper(long id) { -+ return new ProcLOONGARCH64Thread(debugger, id); ++ public MIPS64JavaCallWrapper(Address addr) { ++ super(addr); ++ } ++ ++ public Address getLastJavaFP() { ++ return lastJavaFPField.getValue(addr.addOffsetTo(anchorField.getOffset())); ++ } ++} +diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/mips64/MIPS64RegisterMap.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/mips64/MIPS64RegisterMap.java +new file mode 100644 +index 000000000..f2da760af +--- /dev/null ++++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/mips64/MIPS64RegisterMap.java +@@ -0,0 +1,52 @@ ++/* ++ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2018, Loongson Technology. 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 sun.jvm.hotspot.runtime.mips64; ++ ++import sun.jvm.hotspot.debugger.*; ++import sun.jvm.hotspot.runtime.*; ++ ++public class MIPS64RegisterMap extends RegisterMap { ++ ++ /** This is the only public constructor */ ++ public MIPS64RegisterMap(JavaThread thread, boolean updateMap) { ++ super(thread, updateMap); ++ } ++ ++ protected MIPS64RegisterMap(RegisterMap map) { ++ super(map); ++ } ++ ++ public Object clone() { ++ MIPS64RegisterMap retval = new MIPS64RegisterMap(this); ++ return retval; + } ++ ++ // no PD state to clear or copy: ++ protected void clearPD() {} ++ protected void initializePD() {} ++ protected void initializeFromPD(RegisterMap map) {} ++ protected Address getLocationPD(VMReg reg) { return null; } ++} +diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/PlatformInfo.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/PlatformInfo.java +index 7d7a6107c..06d79318d 100644 +--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/PlatformInfo.java ++++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/PlatformInfo.java +@@ -22,6 +22,13 @@ + * + */ + ++/* ++ * This file has been modified by Loongson Technology in 2021. These ++ * modifications are Copyright (c) 2018, 2021, Loongson Technology, and are made ++ * available on the same license terms set forth above. ++ * ++ */ ++ + package sun.jvm.hotspot.utilities; + + /** Provides canonicalized OS and CPU information for the rest of the +@@ -54,7 +61,7 @@ public class PlatformInfo { + + public static boolean knownCPU(String cpu) { + final String[] KNOWN = +- new String[] {"i386", "x86", "x86_64", "amd64", "sparc", "sparcv9", "ppc64", "ppc64le", "aarch64"}; ++ new String[] {"i386", "x86", "x86_64", "amd64", "sparc", "sparcv9", "ppc64", "ppc64le", "aarch64", "mips64", "mips64el", "loongarch64"}; + + for(String s : KNOWN) { + if(s.equals(cpu)) +@@ -101,6 +108,12 @@ public class PlatformInfo { + if (cpu.equals("ppc64le")) + return "ppc64"; + ++ if (cpu.equals("mips64el")) ++ return "mips64"; ++ ++ if (cpu.equals("loongarch64")) ++ return "loongarch64"; ++ + return cpu; + + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/keymap/BindingReader.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/keymap/BindingReader.java +index 46a45ae39..74d3a46ec 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/keymap/BindingReader.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/keymap/BindingReader.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2018, the original author or authors. ++ * Copyright (c) 2002-2018, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -66,7 +66,7 @@ public class BindingReader { + T o = null; + int[] remaining = new int[1]; + boolean hasRead = false; +- for (;;) { ++ for (; ; ) { + if (local != null) { + o = local.getBound(opBuffer, remaining); + } +@@ -78,8 +78,7 @@ public class BindingReader { + if (remaining[0] >= 0) { + runMacro(opBuffer.substring(opBuffer.length() - remaining[0])); + opBuffer.setLength(opBuffer.length() - remaining[0]); +- } +- else { ++ } else { + long ambiguousTimeout = keys.getAmbiguousTimeout(); + if (ambiguousTimeout > 0 && peekCharacter(ambiguousTimeout) != NonBlockingReader.READ_EXPIRED) { + o = null; +@@ -234,5 +233,4 @@ public class BindingReader { + public String getLastBinding() { + return lastBinding; + } +- + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/keymap/KeyMap.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/keymap/KeyMap.java +index 43c3a1b4f..a8a90ea5e 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/keymap/KeyMap.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/keymap/KeyMap.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2016, the original author or authors. ++ * Copyright (c) 2002-2016, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -8,8 +8,6 @@ + */ + package jdk.internal.org.jline.keymap; + +-import java.io.IOException; +-import java.io.StringWriter; + import java.util.ArrayList; + import java.util.Collection; + import java.util.Comparator; +@@ -218,7 +216,6 @@ public class KeyMap { + return seqs; + } + +- + public static String esc() { + return "\033"; + } +@@ -264,7 +261,6 @@ public class KeyMap { + // Methods + // + +- + public T getUnicode() { + return unicode; + } +@@ -306,9 +302,7 @@ public class KeyMap { + } + for (int c = 0; c < keyMap.mapping.length; c++) { + if (keyMap.mapping[c] instanceof KeyMap) { +- doGetBoundKeys((KeyMap) keyMap.mapping[c], +- prefix + (char) (c), +- bound); ++ doGetBoundKeys((KeyMap) keyMap.mapping[c], prefix + (char) (c), bound); + } else if (keyMap.mapping[c] != null) { + bound.put(prefix + (char) (c), (T) keyMap.mapping[c]); + } +@@ -456,5 +450,4 @@ public class KeyMap { + } + } + } +- + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Binding.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Binding.java +index 0070b55c2..15e7a49a6 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Binding.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Binding.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2016, the original author or authors. ++ * Copyright (c) 2002-2016, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -14,9 +14,8 @@ package jdk.internal.org.jline.reader; + * @see Macro + * @see Reference + * @see Widget +- * @see jdk.internal.org.jline.keymap.KeyMap ++ * @see org.jline.keymap.KeyMap + * + * @author Guillaume Nodet + */ +-public interface Binding { +-} ++public interface Binding {} +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Buffer.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Buffer.java +index 9fdd6e0bd..8d65891d9 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Buffer.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Buffer.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2017, the original author or authors. ++ * Copyright (c) 2002-2017, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -84,4 +84,8 @@ public interface Buffer { + + void copyFrom(Buffer buffer); + ++ /** ++ * Clear any internal buffer. ++ */ ++ void zeroOut(); + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Candidate.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Candidate.java +index 0e9553849..e28e72ffb 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Candidate.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Candidate.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2019, the original author or authors. ++ * Copyright (c) 2002-2019, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -47,7 +47,15 @@ public class Candidate implements Comparable { + * @param complete the complete flag + * @param sort the sort flag + */ +- public Candidate(String value, String displ, String group, String descr, String suffix, String key, boolean complete, int sort) { ++ public Candidate( ++ String value, ++ String displ, ++ String group, ++ String descr, ++ String suffix, ++ String key, ++ boolean complete, ++ int sort) { + this.value = Objects.requireNonNull(value); + this.displ = Objects.requireNonNull(displ); + this.group = group; +@@ -69,7 +77,8 @@ public class Candidate implements Comparable { + * @param key the key + * @param complete the complete flag + */ +- public Candidate(String value, String displ, String group, String descr, String suffix, String key, boolean complete) { ++ public Candidate( ++ String value, String displ, String group, String descr, String suffix, String key, boolean complete) { + this(value, displ, group, descr, suffix, key, complete, 0); + } + +@@ -159,11 +168,10 @@ public class Candidate implements Comparable { + return sort; + } + +- + @Override + public int compareTo(Candidate o) { + // If both candidates have same sort, use default behavior +- if( sort == o.sort() ) { ++ if (sort == o.sort()) { + return value.compareTo(o.value); + } else { + return Integer.compare(sort, o.sort()); +@@ -180,7 +188,7 @@ public class Candidate implements Comparable { + + @Override + public int hashCode() { +- return Objects.hash(value); ++ return Objects.hashCode(value); + } + + @Override +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Completer.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Completer.java +index b87db7afb..7a5937460 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Completer.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Completer.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2018, the original author or authors. ++ * Copyright (c) 2002-2018, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -18,8 +18,7 @@ import java.util.List; + * @author Guillaume Nodet + * @since 2.3 + */ +-public interface Completer +-{ ++public interface Completer { + /** + * Populates candidates with a list of possible completions for the command line. + * +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/CompletingParsedLine.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/CompletingParsedLine.java +index 52a36b838..93558001a 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/CompletingParsedLine.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/CompletingParsedLine.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2018, the original author or authors. ++ * Copyright (c) 2002-2018, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -10,7 +10,7 @@ package jdk.internal.org.jline.reader; + + /** + * An extension of {@link ParsedLine} that, being aware of the quoting and escaping rules +- * of the {@link jdk.internal.org.jline.reader.Parser} that produced it, knows if and how a completion candidate ++ * of the {@link org.jline.reader.Parser} that produced it, knows if and how a completion candidate + * should be escaped/quoted. + * + * @author Eric Bottard +@@ -22,5 +22,4 @@ public interface CompletingParsedLine extends ParsedLine { + int rawWordCursor(); + + int rawWordLength(); +- + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/CompletionMatcher.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/CompletionMatcher.java +index 58117c8f2..4a2334642 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/CompletionMatcher.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/CompletionMatcher.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2020, the original author or authors. ++ * Copyright (c) 2002-2020, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -23,8 +23,13 @@ public interface CompletionMatcher { + * @param errors number of errors accepted in matching + * @param originalGroupName value of JLineReader variable original-group-name + */ +- void compile(Map options, boolean prefix, CompletingParsedLine line +- , boolean caseInsensitive, int errors, String originalGroupName); ++ void compile( ++ Map options, ++ boolean prefix, ++ CompletingParsedLine line, ++ boolean caseInsensitive, ++ int errors, ++ String originalGroupName); + + /** + * +@@ -44,5 +49,4 @@ public interface CompletionMatcher { + * @return a common prefix of matched candidates + */ + String getCommonPrefix(); +- + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/EOFError.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/EOFError.java +index 382db8bc4..8a4f51617 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/EOFError.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/EOFError.java +@@ -1,20 +1,10 @@ + /* +- * Licensed to the Apache Software Foundation (ASF) under one +- * or more contributor license agreements. See the NOTICE file +- * distributed with this work for additional information +- * regarding copyright ownership. The ASF licenses this file +- * to you under the Apache License, Version 2.0 (the +- * "License"); you may not use this file except in compliance +- * with the License. You may obtain a copy of the License at ++ * Copyright (c) 2023, the original author(s). + * +- * http://www.apache.org/licenses/LICENSE-2.0 ++ * This software is distributable under the BSD license. See the terms of the ++ * BSD license in the documentation provided with this software. + * +- * Unless required by applicable law or agreed to in writing, +- * software distributed under the License is distributed on an +- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +- * KIND, either express or implied. See the License for the +- * specific language governing permissions and limitations +- * under the License. ++ * https://opensource.org/licenses/BSD-3-Clause + */ + package jdk.internal.org.jline.reader; + +@@ -45,7 +35,7 @@ public class EOFError extends SyntaxError { + return missing; + } + +- public int getOpenBrackets(){ ++ public int getOpenBrackets() { + return openBrackets; + } + +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Editor.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Editor.java +index e99706ed5..b2fadd3bd 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Editor.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Editor.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2019, the original author or authors. ++ * Copyright (c) 2002-2019, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -13,6 +13,8 @@ import java.util.List; + + public interface Editor { + public void open(List files) throws IOException; ++ + public void run() throws IOException; ++ + public void setRestricted(boolean restricted); + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/EndOfFileException.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/EndOfFileException.java +index 9f70420d9..1e50a7ea1 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/EndOfFileException.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/EndOfFileException.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2020, the original author or authors. ++ * Copyright (c) 2002-2020, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -17,8 +17,7 @@ public class EndOfFileException extends RuntimeException { + private static final long serialVersionUID = 528485360925144689L; + private String partialLine; + +- public EndOfFileException() { +- } ++ public EndOfFileException() {} + + public EndOfFileException(String message) { + super(message); +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Expander.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Expander.java +index 0562e92ed..614c89b3e 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Expander.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Expander.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2016, the original author or authors. ++ * Copyright (c) 2002-2016, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -13,5 +13,4 @@ public interface Expander { + String expandHistory(History history, String line); + + String expandVar(String word); +- + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Highlighter.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Highlighter.java +index 136fb2032..dad62551e 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Highlighter.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Highlighter.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2021, the original author or authors. ++ * Copyright (c) 2002-2021, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/History.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/History.java +index 7a669eddd..0cb46a1ee 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/History.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/History.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2018, the original author or authors. ++ * Copyright (c) 2002-2018, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -21,8 +21,7 @@ import java.util.ListIterator; + * @author Jason Dillon + * @since 2.3 + */ +-public interface History extends Iterable +-{ ++public interface History extends Iterable { + + /** + * Initialize the history for the given reader. +@@ -75,7 +74,6 @@ public interface History extends Iterable + */ + void purge() throws IOException; + +- + int size(); + + default boolean isEmpty() { +@@ -110,8 +108,7 @@ public interface History extends Iterable + // Entries + // + +- interface Entry +- { ++ interface Entry { + int index(); + + Instant time(); +@@ -132,14 +129,17 @@ public interface History extends Iterable + default Iterator reverseIterator(int index) { + return new Iterator() { + private final ListIterator it = iterator(index + 1); ++ + @Override + public boolean hasNext() { + return it.hasPrevious(); + } ++ + @Override + public Entry next() { + return it.previous(); + } ++ + @Override + public void remove() { + it.remove(); +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/LineReader.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/LineReader.java +index 03729853c..bc513f5f6 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/LineReader.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/LineReader.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2021, the original author or authors. ++ * Copyright (c) 2002-2023, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -21,7 +21,7 @@ import jdk.internal.org.jline.utils.AttributedString; + + /** Read lines from the console, with input editing. + * +- *

Thread safety

++ *

Thread safety

+ * The LineReader implementations are not thread safe, + * thus you should not attempt to use a single reader in several threads. + * Any attempt to call one of the readLine call while one is +@@ -31,7 +31,7 @@ import jdk.internal.org.jline.utils.AttributedString; + * {@link #printAbove(String)} or {@link #printAbove(AttributedString)} at + * any time to allow text to be printed above the current prompt. + * +- *

Prompt strings

++ *

Prompt strings

+ * It is traditional for an interactive console-based program + * to print a short prompt string to signal that the user is expected + * to type a command. JLine supports 3 kinds of prompt string: +@@ -81,7 +81,6 @@ import jdk.internal.org.jline.utils.AttributedString; + * + * + */ +- + public interface LineReader { + + /** +@@ -284,6 +283,7 @@ public interface LineReader { + String MAIN = "main"; + String EMACS = "emacs"; + String SAFE = ".safe"; ++ String DUMB = "dumb"; + String MENU = "menu"; + + // +@@ -301,6 +301,7 @@ public interface LineReader { + * they are displayed in a list below the field to be completed + */ + String MENU_LIST_MAX = "menu-list-max"; ++ + String DISABLE_HISTORY = "disable-history"; + String DISABLE_COMPLETION = "disable-completion"; + String EDITING_MODE = "editing-mode"; +@@ -317,18 +318,23 @@ public interface LineReader { + String ORIGINAL_GROUP_NAME = "ORIGINAL_GROUP_NAME"; + /** Completion style for displaying groups name */ + String COMPLETION_STYLE_GROUP = "COMPLETION_STYLE_GROUP"; ++ + String COMPLETION_STYLE_LIST_GROUP = "COMPLETION_STYLE_LIST_GROUP"; + /** Completion style for displaying the current selected item */ + String COMPLETION_STYLE_SELECTION = "COMPLETION_STYLE_SELECTION"; ++ + String COMPLETION_STYLE_LIST_SELECTION = "COMPLETION_STYLE_LIST_SELECTION"; + /** Completion style for displaying the candidate description */ + String COMPLETION_STYLE_DESCRIPTION = "COMPLETION_STYLE_DESCRIPTION"; ++ + String COMPLETION_STYLE_LIST_DESCRIPTION = "COMPLETION_STYLE_LIST_DESCRIPTION"; + /** Completion style for displaying the matching part of candidates */ + String COMPLETION_STYLE_STARTING = "COMPLETION_STYLE_STARTING"; ++ + String COMPLETION_STYLE_LIST_STARTING = "COMPLETION_STYLE_LIST_STARTING"; + /** Completion style for displaying the list */ + String COMPLETION_STYLE_BACKGROUND = "COMPLETION_STYLE_BACKGROUND"; ++ + String COMPLETION_STYLE_LIST_BACKGROUND = "COMPLETION_STYLE_LIST_BACKGROUND"; + /** + * Set the template for prompts for secondary (continuation) lines. +@@ -390,6 +396,26 @@ public interface LineReader { + */ + String SUGGESTIONS_MIN_BUFFER_SIZE = "suggestions-min-buffer-size"; + ++ /** ++ * Max number of times a command can be repeated. ++ */ ++ String MAX_REPEAT_COUNT = "max-repeat-count"; ++ ++ /** ++ * Number of spaces to display a tabulation, the default is 4. ++ */ ++ String TAB_WIDTH = "tab-width"; ++ ++ /** ++ * Name of inputrc to read at line reader creation time. ++ */ ++ String INPUT_RC_FILE_NAME = "input-rc-file-name"; ++ ++ /** ++ * Prefix to automatically delegate variables to system properties ++ */ ++ String SYSTEM_PROPERTY_PREFIX = "system-property-prefix"; ++ + Map> defaultKeyMaps(); + + enum Option { +@@ -469,8 +495,7 @@ public interface LineReader { + EMPTY_WORD_OPTIONS(true), + + /** Disable the undo feature */ +- DISABLE_UNDO +- ; ++ DISABLE_UNDO; + + private final boolean def; + +@@ -611,7 +636,8 @@ public interface LineReader { + * @throws EndOfFileException if an EOF has been found (using Ctrl-D for example) + * @throws java.io.IOError in case of other i/o errors + */ +- String readLine(String prompt, String rightPrompt, Character mask, String buffer) throws UserInterruptException, EndOfFileException; ++ String readLine(String prompt, String rightPrompt, Character mask, String buffer) ++ throws UserInterruptException, EndOfFileException; + + /** + * Read a line from the in {@link InputStream}, and return the line +@@ -631,7 +657,8 @@ public interface LineReader { + * @throws EndOfFileException if an EOF has been found (using Ctrl-D for example) + * @throws java.io.IOError in case of other i/o errors + */ +- String readLine(String prompt, String rightPrompt, MaskingCallback maskingCallback, String buffer) throws UserInterruptException, EndOfFileException; ++ String readLine(String prompt, String rightPrompt, MaskingCallback maskingCallback, String buffer) ++ throws UserInterruptException, EndOfFileException; + + /** + * Prints a line above the prompt and redraw everything. +@@ -702,7 +729,7 @@ public interface LineReader { + void runMacro(String macro); + + /** +- * Read a mouse event when the {@link jdk.internal.org.jline.utils.InfoCmp.Capability#key_mouse} sequence ++ * Read a mouse event when the {@link org.jline.utils.InfoCmp.Capability#key_mouse} sequence + * has just been read on the input stream. + * Compared to {@link Terminal#readMouseEvent()}, this method takes into account keys + * that have been pushed back using {@link #runMacro(String)}. +@@ -750,4 +777,9 @@ public interface LineReader { + void setAutosuggestion(SuggestionType type); + + SuggestionType getAutosuggestion(); ++ ++ /** ++ * Clear any internal buffers. ++ */ ++ void zeroOut(); + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/LineReaderBuilder.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/LineReaderBuilder.java +index 14d5a0e8b..942bba360 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/LineReaderBuilder.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/LineReaderBuilder.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2020, the original author or authors. ++ * Copyright (c) 2002-2020, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -38,8 +38,7 @@ public final class LineReaderBuilder { + Expander expander; + CompletionMatcher completionMatcher; + +- private LineReaderBuilder() { +- } ++ private LineReaderBuilder() {} + + public LineReaderBuilder terminal(Terminal terminal) { + this.terminal = terminal; +@@ -88,8 +87,9 @@ public final class LineReaderBuilder { + try { + if (!Boolean.getBoolean(LineReader.PROP_SUPPORT_PARSEDLINE) + && !(parser.parse("", 0) instanceof CompletingParsedLine)) { +- Log.warn("The Parser of class " + parser.getClass().getName() + " does not support the CompletingParsedLine interface. " + +- "Completion with escaped or quoted words won't work correctly."); ++ Log.warn("The Parser of class " + parser.getClass().getName() ++ + " does not support the CompletingParsedLine interface. " ++ + "Completion with escaped or quoted words won't work correctly."); + } + } catch (Throwable t) { + // Ignore +@@ -153,5 +153,4 @@ public final class LineReaderBuilder { + } + return reader; + } +- + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Macro.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Macro.java +index e66efcc5f..b00769aff 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Macro.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Macro.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2016, the original author or authors. ++ * Copyright (c) 2002-2016, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -35,7 +35,6 @@ public class Macro implements Binding { + + @Override + public String toString() { +- return "Macro[" + +- sequence + ']'; ++ return "Macro[" + sequence + ']'; + } + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/MaskingCallback.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/MaskingCallback.java +index 03501aaf0..3b624e306 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/MaskingCallback.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/MaskingCallback.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2018, the original author or authors. ++ * Copyright (c) 2002-2018, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -31,5 +31,4 @@ public interface MaskingCallback { + * @return the modified line + */ + String history(String line); +- + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/ParsedLine.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/ParsedLine.java +index 683c4b48d..3d87e6b80 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/ParsedLine.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/ParsedLine.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2018, the original author or authors. ++ * Copyright (c) 2002-2018, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -64,5 +64,4 @@ public interface ParsedLine { + * @return the cursor position within the line + */ + int cursor(); +- + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Parser.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Parser.java +index 1f7df67d5..5db53818f 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Parser.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Parser.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2021, the original author or authors. ++ * Copyright (c) 2002-2021, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -35,7 +35,7 @@ public interface Parser { + + default String getCommand(final String line) { + String out; +- Pattern patternCommand = Pattern.compile("^\\s*" + REGEX_VARIABLE + "=(" + REGEX_COMMAND + ")(\\s+|$)"); ++ Pattern patternCommand = Pattern.compile("^\\s*" + REGEX_VARIABLE + "=(" + REGEX_COMMAND + ")(\\s+|$)"); + Matcher matcher = patternCommand.matcher(line); + if (matcher.find()) { + out = matcher.group(1); +@@ -50,7 +50,7 @@ public interface Parser { + + default String getVariable(final String line) { + String out = null; +- Pattern patternCommand = Pattern.compile("^\\s*(" + REGEX_VARIABLE + ")\\s*=[^=~].*"); ++ Pattern patternCommand = Pattern.compile("^\\s*(" + REGEX_VARIABLE + ")\\s*=[^=~].*"); + Matcher matcher = patternCommand.matcher(line); + if (matcher.find()) { + out = matcher.group(1); +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/PrintAboveWriter.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/PrintAboveWriter.java +index 63c9decd1..e23988310 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/PrintAboveWriter.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/PrintAboveWriter.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2021, the original author or authors. ++ * Copyright (c) 2002-2021, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Reference.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Reference.java +index f799a3da2..2fb1aaa67 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Reference.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Reference.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2016, the original author or authors. ++ * Copyright (c) 2002-2016, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -38,7 +38,6 @@ public class Reference implements Binding { + + @Override + public String toString() { +- return "Reference[" + +- name + ']'; ++ return "Reference[" + name + ']'; + } + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/SyntaxError.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/SyntaxError.java +index e46143e4c..eaf3e1d75 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/SyntaxError.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/SyntaxError.java +@@ -1,20 +1,10 @@ + /* +- * Licensed to the Apache Software Foundation (ASF) under one +- * or more contributor license agreements. See the NOTICE file +- * distributed with this work for additional information +- * regarding copyright ownership. The ASF licenses this file +- * to you under the Apache License, Version 2.0 (the +- * "License"); you may not use this file except in compliance +- * with the License. You may obtain a copy of the License at ++ * Copyright (c) 2023, the original author(s). + * +- * http://www.apache.org/licenses/LICENSE-2.0 ++ * This software is distributable under the BSD license. See the terms of the ++ * BSD license in the documentation provided with this software. + * +- * Unless required by applicable law or agreed to in writing, +- * software distributed under the License is distributed on an +- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +- * KIND, either express or implied. See the License for the +- * specific language governing permissions and limitations +- * under the License. ++ * https://opensource.org/licenses/BSD-3-Clause + */ + package jdk.internal.org.jline.reader; + +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/UserInterruptException.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/UserInterruptException.java +index b5510cab5..68bec8041 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/UserInterruptException.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/UserInterruptException.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2016, the original author or authors. ++ * Copyright (c) 2002-2016, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -14,23 +14,19 @@ package jdk.internal.org.jline.reader; + * interrupt character (ctrl-C). The partially entered line is + * available via the {@link #getPartialLine()} method. + */ +-public class UserInterruptException +- extends RuntimeException +-{ ++public class UserInterruptException extends RuntimeException { + private static final long serialVersionUID = 6172232572140736750L; + + private final String partialLine; + +- public UserInterruptException(String partialLine) +- { ++ public UserInterruptException(String partialLine) { + this.partialLine = partialLine; + } + + /** + * @return the partially entered line when ctrl-C was pressed + */ +- public String getPartialLine() +- { ++ public String getPartialLine() { + return partialLine; + } + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Widget.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Widget.java +index d5add7fb1..ae831c5ea 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Widget.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Widget.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2016, the original author or authors. ++ * Copyright (c) 2002-2016, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -15,5 +15,4 @@ package jdk.internal.org.jline.reader; + public interface Widget extends Binding { + + boolean apply(); +- + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/BufferImpl.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/BufferImpl.java +index a3b2a21ac..a68ef229f 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/BufferImpl.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/BufferImpl.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2017, the original author or authors. ++ * Copyright (c) 2002-2017, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -8,6 +8,7 @@ + */ + package jdk.internal.org.jline.reader.impl; + ++import java.util.Arrays; + import java.util.Objects; + + import jdk.internal.org.jline.reader.Buffer; +@@ -19,8 +20,7 @@ import jdk.internal.org.jline.reader.Buffer; + * @author Jason Dillon + * @since 2.0 + */ +-public class BufferImpl implements Buffer +-{ ++public class BufferImpl implements Buffer { + private int cursor = 0; + private int cursorCol = -1; + private int[] buffer; +@@ -45,7 +45,7 @@ public class BufferImpl implements Buffer + this.g1 = buffer.g1; + } + +- public BufferImpl copy () { ++ public BufferImpl copy() { + return new BufferImpl(this); + } + +@@ -106,7 +106,7 @@ public class BufferImpl implements Buffer + * @param c the character to insert + */ + public void write(int c) { +- write(new int[] { c }); ++ write(new int[] {c}); + } + + /** +@@ -120,7 +120,7 @@ public class BufferImpl implements Buffer + if (overTyping) { + delete(1); + } +- write(new int[] { c }); ++ write(new int[] {c}); + } + + /** +@@ -223,8 +223,7 @@ public class BufferImpl implements Buffer + + if ((cursor + where) < 0) { + where = -cursor; +- } +- else if ((cursor + where) > length()) { ++ } else if ((cursor + where) > length()) { + where = length() - cursor; + } + +@@ -369,4 +368,9 @@ public class BufferImpl implements Buffer + g1 += l; + } + } ++ ++ @Override ++ public void zeroOut() { ++ Arrays.fill(buffer, 0); ++ } + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/CompletionMatcherImpl.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/CompletionMatcherImpl.java +index f829f13d5..761ee1815 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/CompletionMatcherImpl.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/CompletionMatcherImpl.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2021, the original author or authors. ++ * Copyright (c) 2002-2021, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -8,26 +8,25 @@ + */ + package jdk.internal.org.jline.reader.impl; + +-import jdk.internal.org.jline.reader.Candidate; +-import jdk.internal.org.jline.reader.CompletingParsedLine; +-import jdk.internal.org.jline.reader.CompletionMatcher; +-import jdk.internal.org.jline.reader.LineReader; +-import jdk.internal.org.jline.utils.AttributedString; +- + import java.util.*; + import java.util.function.Function; + import java.util.function.Predicate; + import java.util.regex.Pattern; + import java.util.stream.Collectors; + ++import jdk.internal.org.jline.reader.Candidate; ++import jdk.internal.org.jline.reader.CompletingParsedLine; ++import jdk.internal.org.jline.reader.CompletionMatcher; ++import jdk.internal.org.jline.reader.LineReader; ++import jdk.internal.org.jline.utils.AttributedString; ++ + public class CompletionMatcherImpl implements CompletionMatcher { + protected Predicate exact; + protected List>, Map>>> matchers; + private Map> matching; + private boolean caseInsensitive; + +- public CompletionMatcherImpl() { +- } ++ public CompletionMatcherImpl() {} + + protected void reset(boolean caseInsensitive) { + this.caseInsensitive = caseInsensitive; +@@ -37,8 +36,13 @@ public class CompletionMatcherImpl implements CompletionMatcher { + } + + @Override +- public void compile(Map options, boolean prefix, CompletingParsedLine line +- , boolean caseInsensitive, int errors, String originalGroupName) { ++ public void compile( ++ Map options, ++ boolean prefix, ++ CompletingParsedLine line, ++ boolean caseInsensitive, ++ int errors, ++ String originalGroupName) { + reset(caseInsensitive); + defaultMatchers(options, prefix, line, caseInsensitive, errors, originalGroupName); + } +@@ -47,15 +51,18 @@ public class CompletionMatcherImpl implements CompletionMatcher { + public List matches(List candidates) { + matching = Collections.emptyMap(); + Map> sortedCandidates = sort(candidates); +- for (Function>, +- Map>> matcher : matchers) { ++ for (Function>, Map>> matcher : matchers) { + matching = matcher.apply(sortedCandidates); + if (!matching.isEmpty()) { + break; + } + } +- return !matching.isEmpty() ? matching.entrySet().stream().flatMap(e -> e.getValue().stream()).distinct().collect(Collectors.toList()) +- : new ArrayList<>(); ++ return !matching.isEmpty() ++ ? matching.entrySet().stream() ++ .flatMap(e -> e.getValue().stream()) ++ .distinct() ++ .collect(Collectors.toList()) ++ : new ArrayList<>(); + } + + @Override +@@ -63,10 +70,12 @@ public class CompletionMatcherImpl implements CompletionMatcher { + if (matching == null) { + throw new IllegalStateException(); + } +- return matching.values().stream().flatMap(Collection::stream) ++ return matching.values().stream() ++ .flatMap(Collection::stream) + .filter(Candidate::complete) + .filter(c -> exact.test(c.value())) +- .findFirst().orElse(null); ++ .findFirst() ++ .orElse(null); + } + + @Override +@@ -84,8 +93,13 @@ public class CompletionMatcherImpl implements CompletionMatcher { + /** + * Default JLine matchers + */ +- protected void defaultMatchers(Map options, boolean prefix, CompletingParsedLine line +- , boolean caseInsensitive, int errors, String originalGroupName) { ++ protected void defaultMatchers( ++ Map options, ++ boolean prefix, ++ CompletingParsedLine line, ++ boolean caseInsensitive, ++ int errors, ++ String originalGroupName) { + // Find matchers + // TODO: glob completion + String wd = line.word(); +@@ -94,8 +108,7 @@ public class CompletionMatcherImpl implements CompletionMatcher { + if (prefix) { + matchers = new ArrayList<>(Arrays.asList( + simpleMatcher(s -> (caseInsensitive ? s.toLowerCase() : s).startsWith(wp)), +- simpleMatcher(s -> (caseInsensitive ? s.toLowerCase() : s).contains(wp)) +- )); ++ simpleMatcher(s -> (caseInsensitive ? s.toLowerCase() : s).contains(wp)))); + if (LineReader.Option.COMPLETE_MATCHER_TYPO.isSet(options)) { + matchers.add(typoMatcher(wp, errors, caseInsensitive, originalGroupName)); + } +@@ -109,14 +122,14 @@ public class CompletionMatcherImpl implements CompletionMatcher { + Pattern p1 = Pattern.compile(Pattern.quote(wp) + ".*" + Pattern.quote(ws) + ".*"); + Pattern p2 = Pattern.compile(".*" + Pattern.quote(wp) + ".*" + Pattern.quote(ws) + ".*"); + matchers = new ArrayList<>(Arrays.asList( +- simpleMatcher(s -> p1.matcher(caseInsensitive ? s.toLowerCase() : s).matches()), +- simpleMatcher(s -> p2.matcher(caseInsensitive ? s.toLowerCase() : s).matches()) +- )); ++ simpleMatcher(s -> p1.matcher(caseInsensitive ? s.toLowerCase() : s) ++ .matches()), ++ simpleMatcher(s -> p2.matcher(caseInsensitive ? s.toLowerCase() : s) ++ .matches()))); + } else { + matchers = new ArrayList<>(Arrays.asList( + simpleMatcher(s -> (caseInsensitive ? s.toLowerCase() : s).startsWith(wdi)), +- simpleMatcher(s -> (caseInsensitive ? s.toLowerCase() : s).contains(wdi)) +- )); ++ simpleMatcher(s -> (caseInsensitive ? s.toLowerCase() : s).contains(wdi)))); + } + if (LineReader.Option.COMPLETE_MATCHER_CAMELCASE.isSet(options)) { + matchers.add(simpleMatcher(s -> camelMatch(wd, 0, s, 0))); +@@ -128,18 +141,20 @@ public class CompletionMatcherImpl implements CompletionMatcher { + } + } + +- protected Function>, +- Map>> simpleMatcher(Predicate predicate) { ++ protected Function>, Map>> simpleMatcher( ++ Predicate predicate) { + return m -> m.entrySet().stream() + .filter(e -> predicate.test(e.getKey())) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + } + +- protected Function>, +- Map>> typoMatcher(String word, int errors, boolean caseInsensitive, String originalGroupName) { ++ protected Function>, Map>> typoMatcher( ++ String word, int errors, boolean caseInsensitive, String originalGroupName) { + return m -> { + Map> map = m.entrySet().stream() +- .filter(e -> ReaderUtils.distance(word, caseInsensitive ? e.getKey().toLowerCase() : e.getKey()) < errors) ++ .filter(e -> ReaderUtils.distance( ++ word, caseInsensitive ? e.getKey().toLowerCase() : e.getKey()) ++ < errors) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + if (map.size() > 1) { + map.computeIfAbsent(word, w -> new ArrayList<>()) +@@ -178,7 +193,8 @@ public class CompletionMatcherImpl implements CompletionMatcher { + Map> sortedCandidates = new HashMap<>(); + for (Candidate candidate : candidates) { + sortedCandidates +- .computeIfAbsent(AttributedString.fromAnsi(candidate.value()).toString(), s -> new ArrayList<>()) ++ .computeIfAbsent( ++ AttributedString.fromAnsi(candidate.value()).toString(), s -> new ArrayList<>()) + .add(candidate); + } + return sortedCandidates; +@@ -206,5 +222,4 @@ public class CompletionMatcherImpl implements CompletionMatcher { + } + return new String(s1, 0, len); + } +- +-} +\ No newline at end of file +} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/loongarch64/ProcLOONGARCH64Thread.java jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/loongarch64/ProcLOONGARCH64Thread.java ---- openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/loongarch64/ProcLOONGARCH64Thread.java 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/loongarch64/ProcLOONGARCH64Thread.java 2023-09-12 13:54:26.377575791 +0800 -@@ -0,0 +1,92 @@ +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/DefaultExpander.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/DefaultExpander.java +index b534b96ff..e5e7735a3 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/DefaultExpander.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/DefaultExpander.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2016, the original author or authors. ++ * Copyright (c) 2002-2016, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -32,27 +32,25 @@ public class DefaultExpander implements Expander { + if (unicode > 0) { + escaped = (--unicode >= 0); + sb.append(c); +- } +- else if (escaped) { ++ } else if (escaped) { + if (c == 'u') { + unicode = 4; + } else { + escaped = false; + } + sb.append(c); +- } +- else if (c == '\'') { ++ } else if (c == '\'') { + inQuote = !inQuote; + sb.append(c); +- } +- else if (inQuote) { ++ } else if (inQuote) { + sb.append(c); +- } +- else { ++ } else { + switch (c) { + case '\\': +- // any '\!' should be considered an expansion escape, so skip expansion and strip the escape character +- // a leading '\^' should be considered an expansion escape, so skip expansion and strip the escape character ++ // any '\!' should be considered an expansion escape, so skip expansion and strip the escape ++ // character ++ // a leading '\^' should be considered an expansion escape, so skip expansion and strip the ++ // escape character + // otherwise, add the escape + escaped = true; + sb.append(c); +@@ -91,7 +89,8 @@ public class DefaultExpander implements Expander { + if (history.size() == 0) { + throw new IllegalArgumentException("!$: event not found"); + } +- String previous = history.get(history.index() - 1).trim(); ++ String previous = ++ history.get(history.index() - 1).trim(); + int lastSpace = previous.lastIndexOf(' '); + if (lastSpace != -1) { + rep = previous.substring(lastSpace + 1); +@@ -128,14 +127,18 @@ public class DefaultExpander implements Expander { + try { + idx = Integer.parseInt(line.substring(i1, i)); + } catch (NumberFormatException e) { +- throw new IllegalArgumentException((neg ? "!-" : "!") + line.substring(i1, i) + ": event not found"); ++ throw new IllegalArgumentException( ++ (neg ? "!-" : "!") + line.substring(i1, i) + ": event not found"); + } + if (neg && idx > 0 && idx <= history.size()) { + rep = history.get(history.index() - idx); +- } else if (!neg && idx > history.index() - history.size() && idx <= history.index()) { ++ } else if (!neg ++ && idx > history.index() - history.size() ++ && idx <= history.index()) { + rep = history.get(idx - 1); + } else { +- throw new IllegalArgumentException((neg ? "!-" : "!") + line.substring(i1, i) + ": event not found"); ++ throw new IllegalArgumentException( ++ (neg ? "!-" : "!") + line.substring(i1, i) + ": event not found"); + } + break; + default: +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/DefaultHighlighter.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/DefaultHighlighter.java +index ac286ad73..55d39efde 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/DefaultHighlighter.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/DefaultHighlighter.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2021, the original author or authors. ++ * Copyright (c) 2002-2021, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -10,9 +10,9 @@ package jdk.internal.org.jline.reader.impl; + + import java.util.regex.Pattern; + ++import jdk.internal.org.jline.reader.Highlighter; + import jdk.internal.org.jline.reader.LineReader; + import jdk.internal.org.jline.reader.LineReader.RegionType; +-import jdk.internal.org.jline.reader.Highlighter; + import jdk.internal.org.jline.utils.AttributedString; + import jdk.internal.org.jline.utils.AttributedStringBuilder; + import jdk.internal.org.jline.utils.AttributedStyle; +@@ -57,7 +57,8 @@ public class DefaultHighlighter implements Highlighter { + while (negativeStart > 0 && reader.getBuffer().atChar(negativeStart - 1) != '\n') { + negativeStart--; + } +- while (negativeEnd < reader.getBuffer().length() - 1 && reader.getBuffer().atChar(negativeEnd + 1) != '\n') { ++ while (negativeEnd < reader.getBuffer().length() - 1 ++ && reader.getBuffer().atChar(negativeEnd + 1) != '\n') { + negativeEnd++; + } + } +@@ -104,5 +105,4 @@ public class DefaultHighlighter implements Highlighter { + } + return sb.toAttributedString(); + } +- + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/DefaultParser.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/DefaultParser.java +index d9b3a9948..26cdf6abc 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/DefaultParser.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/DefaultParser.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2020, the original author or authors. ++ * Copyright (c) 2002-2020, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -21,18 +21,18 @@ import jdk.internal.org.jline.reader.Parser; + public class DefaultParser implements Parser { + + public enum Bracket { +- ROUND, // () +- CURLY, // {} +- SQUARE, // [] +- ANGLE // <> ++ ROUND, // () ++ CURLY, // {} ++ SQUARE, // [] ++ ANGLE // <> + } + + public static class BlockCommentDelims { + private final String start; + private final String end; ++ + public BlockCommentDelims(String start, String end) { +- if (start == null || end == null +- || start.isEmpty() || end.isEmpty() || start.equals(end)) { ++ if (start == null || end == null || start.isEmpty() || end.isEmpty() || start.equals(end)) { + throw new IllegalArgumentException("Bad block comment delimiter!"); + } + this.start = start; +@@ -185,22 +185,22 @@ public class DefaultParser implements Parser { + int i = 0; + for (Bracket b : bs) { + switch (b) { +- case ROUND: +- openingBrackets[i] = '('; +- closingBrackets[i] = ')'; +- break; +- case CURLY: +- openingBrackets[i] = '{'; +- closingBrackets[i] = '}'; +- break; +- case SQUARE: +- openingBrackets[i] = '['; +- closingBrackets[i] = ']'; +- break; +- case ANGLE: +- openingBrackets[i] = '<'; +- closingBrackets[i] = '>'; +- break; ++ case ROUND: ++ openingBrackets[i] = '('; ++ closingBrackets[i] = ')'; ++ break; ++ case CURLY: ++ openingBrackets[i] = '{'; ++ closingBrackets[i] = '}'; ++ break; ++ case SQUARE: ++ openingBrackets[i] = '['; ++ closingBrackets[i] = ']'; ++ break; ++ case ANGLE: ++ openingBrackets[i] = '<'; ++ closingBrackets[i] = '>'; ++ break; + } + i++; + } +@@ -229,7 +229,6 @@ public class DefaultParser implements Parser { + return name != null && regexVariable != null && name.matches(regexVariable); + } + +- + @Override + public String getCommand(final String line) { + String out = ""; +@@ -296,7 +295,7 @@ public class DefaultParser implements Parser { + if (quoteStart < 0 && isQuoteChar(line, i) && !lineCommented && !blockCommented) { + // Start a quote block + quoteStart = i; +- if (current.length()==0) { ++ if (current.length() == 0) { + quotedWord = true; + if (context == ParseContext.SPLIT_LINE) { + current.append(line.charAt(i)); +@@ -324,13 +323,15 @@ public class DefaultParser implements Parser { + } + } else { + // Delimiter +- rawWordLength = handleDelimiterAndGetRawWordLength(current, words, rawWordStart, rawWordCursor, rawWordLength, i); ++ rawWordLength = handleDelimiterAndGetRawWordLength( ++ current, words, rawWordStart, rawWordCursor, rawWordLength, i); + rawWordStart = i + 1; + } + } else { + if (quoteStart < 0 && !blockCommented && (lineCommented || isLineCommentStarted(line, i))) { + lineCommented = true; +- } else if (quoteStart < 0 && !lineCommented ++ } else if (quoteStart < 0 ++ && !lineCommented + && (blockCommented || isCommentDelim(line, i, blockCommentStart))) { + if (blockCommented) { + if (blockCommentEnd != null && isCommentDelim(line, i, blockCommentEnd)) { +@@ -339,12 +340,12 @@ public class DefaultParser implements Parser { + } + } else { + blockCommented = true; +- rawWordLength = handleDelimiterAndGetRawWordLength(current, words, rawWordStart, rawWordCursor, rawWordLength, i); ++ rawWordLength = handleDelimiterAndGetRawWordLength( ++ current, words, rawWordStart, rawWordCursor, rawWordLength, i); + i += blockCommentStart == null ? 0 : blockCommentStart.length() - 1; + rawWordStart = i + 1; + } +- } else if (quoteStart < 0 && !lineCommented +- && isCommentDelim(line, i, blockCommentEnd)) { ++ } else if (quoteStart < 0 && !lineCommented && isCommentDelim(line, i, blockCommentEnd)) { + current.append(line.charAt(i)); + blockCommentInRightOrder = false; + } else if (!isEscapeChar(line, i)) { +@@ -377,16 +378,14 @@ public class DefaultParser implements Parser { + throw new EOFError(-1, -1, "Escaped new line", "newline"); + } + if (eofOnUnclosedQuote && quoteStart >= 0) { +- throw new EOFError(-1, -1, "Missing closing quote", line.charAt(quoteStart) == '\'' +- ? "quote" : "dquote"); ++ throw new EOFError( ++ -1, -1, "Missing closing quote", line.charAt(quoteStart) == '\'' ? "quote" : "dquote"); + } + if (blockCommented) { +- throw new EOFError(-1, -1, "Missing closing block comment delimiter", +- "add: " + blockCommentEnd); ++ throw new EOFError(-1, -1, "Missing closing block comment delimiter", "add: " + blockCommentEnd); + } + if (!blockCommentInRightOrder) { +- throw new EOFError(-1, -1, "Missing opening block comment delimiter", +- "missing: " + blockCommentStart); ++ throw new EOFError(-1, -1, "Missing opening block comment delimiter", "missing: " + blockCommentStart); + } + if (bracketChecker.isClosingBracketMissing() || bracketChecker.isOpeningBracketMissing()) { + String message = null; +@@ -398,8 +397,13 @@ public class DefaultParser implements Parser { + message = "Missing opening bracket"; + missing = "missing: " + bracketChecker.getMissingOpeningBracket(); + } +- throw new EOFError(-1, -1, message, missing, +- bracketChecker.getOpenBrackets(), bracketChecker.getNextClosingBracket()); ++ throw new EOFError( ++ -1, ++ -1, ++ message, ++ missing, ++ bracketChecker.getOpenBrackets(), ++ bracketChecker.getNextClosingBracket()); + } + } + +@@ -420,7 +424,13 @@ public class DefaultParser implements Parser { + return !isQuoted(buffer, pos) && !isEscaped(buffer, pos) && isDelimiterChar(buffer, pos); + } + +- private int handleDelimiterAndGetRawWordLength(StringBuilder current, List words, int rawWordStart, int rawWordCursor, int rawWordLength, int pos) { ++ private int handleDelimiterAndGetRawWordLength( ++ StringBuilder current, ++ List words, ++ int rawWordStart, ++ int rawWordCursor, ++ int rawWordLength, ++ int pos) { + if (current.length() > 0) { + words.add(current.toString()); + current.setLength(0); // reset the arg +@@ -470,7 +480,7 @@ public class DefaultParser implements Parser { + + public boolean isLineCommentStarted(final CharSequence buffer, final int pos) { + if (lineCommentDelims != null) { +- for (String comment: lineCommentDelims) { ++ for (String comment : lineCommentDelims) { + if (isCommentDelim(buffer, pos, comment)) { + return true; + } +@@ -584,8 +594,8 @@ public class DefaultParser implements Parser { + } else { + bid = bracketId(closingBrackets, buffer, pos); + if (bid >= 0) { +- if (!nested.isEmpty() && bid == nested.get(nested.size()-1)) { +- nested.remove(nested.size()-1); ++ if (!nested.isEmpty() && bid == nested.get(nested.size() - 1)) { ++ nested.remove(nested.size() - 1); + } else { + missingOpeningBracket = bid; + } +@@ -634,7 +644,7 @@ public class DefaultParser implements Parser { + } + + private int bracketId(final char[] brackets, final CharSequence buffer, final int pos) { +- for (int i=0; i < brackets.length; i++) { ++ for (int i = 0; i < brackets.length; i++) { + if (buffer.charAt(pos) == brackets[i]) { + return i; + } +@@ -648,8 +658,7 @@ public class DefaultParser implements Parser { + * + * @author Marc Prud'hommeaux + */ +- public class ArgumentList implements ParsedLine, CompletingParsedLine +- { ++ public class ArgumentList implements ParsedLine, CompletingParsedLine { + private final String line; + + private final List words; +@@ -667,11 +676,21 @@ public class DefaultParser implements Parser { + private final int rawWordLength; + + @Deprecated +- public ArgumentList(final String line, final List words, +- final int wordIndex, final int wordCursor, +- final int cursor) { +- this(line, words, wordIndex, wordCursor, cursor, +- null, wordCursor, words.get(wordIndex).length()); ++ public ArgumentList( ++ final String line, ++ final List words, ++ final int wordIndex, ++ final int wordCursor, ++ final int cursor) { ++ this( ++ line, ++ words, ++ wordIndex, ++ wordCursor, ++ cursor, ++ null, ++ wordCursor, ++ words.get(wordIndex).length()); + } + + /** +@@ -685,10 +704,15 @@ public class DefaultParser implements Parser { + * @param rawWordCursor the cursor position inside the raw word (i.e. including quotes and escape characters) + * @param rawWordLength the raw word length, including quotes and escape characters + */ +- public ArgumentList(final String line, final List words, +- final int wordIndex, final int wordCursor, +- final int cursor, final String openingQuote, +- final int rawWordCursor, final int rawWordLength) { ++ public ArgumentList( ++ final String line, ++ final List words, ++ final int wordIndex, ++ final int wordCursor, ++ final int cursor, ++ final String openingQuote, ++ final int rawWordCursor, ++ final int rawWordLength) { + this.line = line; + this.words = Collections.unmodifiableList(Objects.requireNonNull(words)); + this.wordIndex = wordIndex; +@@ -732,8 +756,8 @@ public class DefaultParser implements Parser { + Predicate needToBeEscaped; + String quote = openingQuote; + boolean middleQuotes = false; +- if (openingQuote==null) { +- for (int i=0; i < sb.length(); i++) { ++ if (openingQuote == null) { ++ for (int i = 0; i < sb.length(); i++) { + if (isQuoteChar(sb, i)) { + middleQuotes = true; + break; +@@ -746,7 +770,8 @@ public class DefaultParser implements Parser { + // Delimiters (spaces) don't need to be escaped, nor do other quotes, but everything else does. + // Also, close the quote at the end + if (openingQuote != null) { +- needToBeEscaped = i -> isRawEscapeChar(sb.charAt(i)) || String.valueOf(sb.charAt(i)).equals(openingQuote); ++ needToBeEscaped = i -> isRawEscapeChar(sb.charAt(i)) ++ || String.valueOf(sb.charAt(i)).equals(openingQuote); + } + // Completion is protected by middle quotes: + // Delimiters (spaces) don't need to be escaped, nor do quotes, but everything else does. +@@ -756,8 +781,8 @@ public class DefaultParser implements Parser { + // No quote protection, need to escape everything: delimiter chars (spaces), quote chars + // and escapes themselves + else { +- needToBeEscaped = i -> isDelimiterChar(sb, i) || isRawEscapeChar(sb.charAt(i)) +- || isRawQuoteChar(sb.charAt(i)); ++ needToBeEscaped = i -> ++ isDelimiterChar(sb, i) || isRawEscapeChar(sb.charAt(i)) || isRawQuoteChar(sb.charAt(i)); + } + for (int i = 0; i < sb.length(); i++) { + if (needToBeEscaped.test(i)) { +@@ -792,5 +817,4 @@ public class DefaultParser implements Parser { + return rawWordLength; + } + } +- + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/InputRC.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/InputRC.java +new file mode 100644 +index 000000000..0c3aee057 +--- /dev/null ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/InputRC.java +@@ -0,0 +1,394 @@ +/* -+ * Copyright (c) 2002, 2003, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2021, Loongson Technology. 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. ++ * Copyright (c) 2002-2023, the original author(s). + * -+ * 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 software is distributable under the BSD license. See the terms of the ++ * BSD license in the documentation provided with this software. + * ++ * https://opensource.org/licenses/BSD-3-Clause + */ ++package jdk.internal.org.jline.reader.impl; ++ ++import java.io.BufferedReader; ++import java.io.IOException; ++import java.io.InputStream; ++import java.io.InputStreamReader; ++import java.io.Reader; ++import java.net.URL; ++import java.util.ArrayList; ++import java.util.List; ++import java.util.Locale; + -+package sun.jvm.hotspot.debugger.proc.loongarch64; ++import jdk.internal.org.jline.reader.LineReader; ++import jdk.internal.org.jline.reader.Macro; ++import jdk.internal.org.jline.reader.Reference; ++import jdk.internal.org.jline.terminal.Terminal; ++import jdk.internal.org.jline.utils.Log; + -+import sun.jvm.hotspot.debugger.*; -+import sun.jvm.hotspot.debugger.loongarch64.*; -+import sun.jvm.hotspot.debugger.proc.*; -+import sun.jvm.hotspot.utilities.*; ++public final class InputRC { + -+public class ProcLOONGARCH64Thread implements ThreadProxy { -+ private ProcDebugger debugger; -+ private int id; ++ public static void configure(LineReader reader, URL url) throws IOException { ++ try (InputStream is = url.openStream()) { ++ configure(reader, is); ++ } ++ } + -+ public ProcLOONGARCH64Thread(ProcDebugger debugger, Address addr) { -+ this.debugger = debugger; ++ public static void configure(LineReader reader, InputStream is) throws IOException { ++ try (InputStreamReader r = new InputStreamReader(is)) { ++ configure(reader, r); ++ } ++ } + -+ // FIXME: the size here should be configurable. However, making it -+ // so would produce a dependency on the "types" package from the -+ // debugger package, which is not desired. -+ this.id = (int) addr.getCIntegerAt(0, 4, true); -+ } ++ public static void configure(LineReader reader, Reader r) throws IOException { ++ BufferedReader br; ++ if (r instanceof BufferedReader) { ++ br = (BufferedReader) r; ++ } else { ++ br = new BufferedReader(r); ++ } + -+ public ProcLOONGARCH64Thread(ProcDebugger debugger, long id) { -+ this.debugger = debugger; -+ this.id = (int) id; -+ } ++ Terminal terminal = reader.getTerminal(); + -+ public ThreadContext getContext() throws IllegalThreadStateException { -+ ProcLOONGARCH64ThreadContext context = new ProcLOONGARCH64ThreadContext(debugger); -+ long[] regs = debugger.getThreadIntegerRegisterSet(id); -+ /* -+ _NGREG in reg.h is defined to be 19. Because we have included -+ debug registers LOONGARCH64ThreadContext.NPRGREG is 25. -+ */ ++ if (Terminal.TYPE_DUMB.equals(terminal.getType()) || Terminal.TYPE_DUMB_COLOR.equals(terminal.getType())) { ++ reader.getVariables().putIfAbsent(LineReader.EDITING_MODE, "dumb"); ++ } else { ++ reader.getVariables().putIfAbsent(LineReader.EDITING_MODE, "emacs"); ++ } + -+ if (Assert.ASSERTS_ENABLED) { -+ Assert.that(regs.length <= LOONGARCH64ThreadContext.NPRGREG, "size of register set is greater than " + LOONGARCH64ThreadContext.NPRGREG); -+ } -+ for (int i = 0; i < regs.length; i++) { -+ context.setRegister(i, regs[i]); ++ reader.setKeyMap(LineReader.MAIN); ++ new InputRC(reader).parse(br); ++ if ("vi".equals(reader.getVariable(LineReader.EDITING_MODE))) { ++ reader.getKeyMaps().put(LineReader.MAIN, reader.getKeyMaps().get(LineReader.VIINS)); ++ } else if ("emacs".equals(reader.getVariable(LineReader.EDITING_MODE))) { ++ reader.getKeyMaps().put(LineReader.MAIN, reader.getKeyMaps().get(LineReader.EMACS)); ++ } else if ("dumb".equals(reader.getVariable(LineReader.EDITING_MODE))) { ++ reader.getKeyMaps().put(LineReader.MAIN, reader.getKeyMaps().get(LineReader.DUMB)); ++ } + } -+ return context; -+ } -+ -+ public boolean canSetContext() throws DebuggerException { -+ return false; -+ } -+ -+ public void setContext(ThreadContext context) -+ throws IllegalThreadStateException, DebuggerException { -+ throw new DebuggerException("Unimplemented"); -+ } + -+ public String toString() { -+ return "t@" + id; -+ } ++ private final LineReader reader; + -+ public boolean equals(Object obj) { -+ if ((obj == null) || !(obj instanceof ProcLOONGARCH64Thread)) { -+ return false; ++ private InputRC(LineReader reader) { ++ this.reader = reader; + } + -+ return (((ProcLOONGARCH64Thread) obj).id == id); -+ } ++ private void parse(BufferedReader br) throws IOException, IllegalArgumentException { ++ String line; ++ boolean parsing = true; ++ List ifsStack = new ArrayList<>(); ++ while ((line = br.readLine()) != null) { ++ try { ++ line = line.trim(); ++ if (line.length() == 0) { ++ continue; ++ } ++ if (line.charAt(0) == '#') { ++ continue; ++ } ++ int i = 0; ++ if (line.charAt(i) == '$') { ++ String cmd; ++ String args; ++ ++i; ++ while (i < line.length() && (line.charAt(i) == ' ' || line.charAt(i) == '\t')) { ++ i++; ++ } ++ int s = i; ++ while (i < line.length() && (line.charAt(i) != ' ' && line.charAt(i) != '\t')) { ++ i++; ++ } ++ cmd = line.substring(s, i); ++ while (i < line.length() && (line.charAt(i) == ' ' || line.charAt(i) == '\t')) { ++ i++; ++ } ++ s = i; ++ while (i < line.length() && (line.charAt(i) != ' ' && line.charAt(i) != '\t')) { ++ i++; ++ } ++ args = line.substring(s, i); ++ if ("if".equalsIgnoreCase(cmd)) { ++ ifsStack.add(parsing); ++ if (!parsing) { ++ continue; ++ } ++ if (args.startsWith("term=")) { ++ // TODO ++ } else if (args.startsWith("mode=")) { ++ String mode = (String) reader.getVariable(LineReader.EDITING_MODE); ++ parsing = args.substring("mode=".length()).equalsIgnoreCase(mode); ++ } else { ++ parsing = args.equalsIgnoreCase(reader.getAppName()); ++ } ++ } else if ("else".equalsIgnoreCase(cmd)) { ++ if (ifsStack.isEmpty()) { ++ throw new IllegalArgumentException("$else found without matching $if"); ++ } ++ boolean invert = true; ++ for (boolean b : ifsStack) { ++ if (!b) { ++ invert = false; ++ break; ++ } ++ } ++ if (invert) { ++ parsing = !parsing; ++ } ++ } else if ("endif".equalsIgnoreCase(cmd)) { ++ if (ifsStack.isEmpty()) { ++ throw new IllegalArgumentException("endif found without matching $if"); ++ } ++ parsing = ifsStack.remove(ifsStack.size() - 1); ++ } else if ("include".equalsIgnoreCase(cmd)) { ++ // TODO ++ } ++ continue; ++ } ++ if (!parsing) { ++ continue; ++ } ++ if (line.charAt(i++) == '"') { ++ boolean esc = false; ++ for (; ; i++) { ++ if (i >= line.length()) { ++ throw new IllegalArgumentException("Missing closing quote on line '" + line + "'"); ++ } ++ if (esc) { ++ esc = false; ++ } else if (line.charAt(i) == '\\') { ++ esc = true; ++ } else if (line.charAt(i) == '"') { ++ break; ++ } ++ } ++ } ++ while (i < line.length() && line.charAt(i) != ':' && line.charAt(i) != ' ' && line.charAt(i) != '\t') { ++ i++; ++ } ++ String keySeq = line.substring(0, i); ++ boolean equivalency = i + 1 < line.length() && line.charAt(i) == ':' && line.charAt(i + 1) == '='; ++ i++; ++ if (equivalency) { ++ i++; ++ } ++ if (keySeq.equalsIgnoreCase("set")) { ++ String key; ++ String val; ++ while (i < line.length() && (line.charAt(i) == ' ' || line.charAt(i) == '\t')) { ++ i++; ++ } ++ int s = i; ++ while (i < line.length() && (line.charAt(i) != ' ' && line.charAt(i) != '\t')) { ++ i++; ++ } ++ key = line.substring(s, i); ++ while (i < line.length() && (line.charAt(i) == ' ' || line.charAt(i) == '\t')) { ++ i++; ++ } ++ s = i; ++ while (i < line.length() && (line.charAt(i) != ' ' && line.charAt(i) != '\t')) { ++ i++; ++ } ++ val = line.substring(s, i); ++ setVar(reader, key, val); ++ } else { ++ while (i < line.length() && (line.charAt(i) == ' ' || line.charAt(i) == '\t')) { ++ i++; ++ } ++ int start = i; ++ if (i < line.length() && (line.charAt(i) == '\'' || line.charAt(i) == '\"')) { ++ char delim = line.charAt(i++); ++ boolean esc = false; ++ for (; ; i++) { ++ if (i >= line.length()) { ++ break; ++ } ++ if (esc) { ++ esc = false; ++ } else if (line.charAt(i) == '\\') { ++ esc = true; ++ } else if (line.charAt(i) == delim) { ++ break; ++ } ++ } ++ } ++ for (; i < line.length() && line.charAt(i) != ' ' && line.charAt(i) != '\t'; i++) ++ ; ++ String val = line.substring(Math.min(start, line.length()), Math.min(i, line.length())); ++ if (keySeq.charAt(0) == '"') { ++ keySeq = translateQuoted(keySeq); ++ } else { ++ // Bind key name ++ String keyName = ++ keySeq.lastIndexOf('-') > 0 ? keySeq.substring(keySeq.lastIndexOf('-') + 1) : keySeq; ++ char key = getKeyFromName(keyName); ++ keyName = keySeq.toLowerCase(); ++ keySeq = ""; ++ if (keyName.contains("meta-") || keyName.contains("m-")) { ++ keySeq += "\u001b"; ++ } ++ if (keyName.contains("control-") || keyName.contains("c-") || keyName.contains("ctrl-")) { ++ key = (char) (Character.toUpperCase(key) & 0x1f); ++ } ++ keySeq += key; ++ } ++ if (val.length() > 0 && (val.charAt(0) == '\'' || val.charAt(0) == '\"')) { ++ reader.getKeys().bind(new Macro(translateQuoted(val)), keySeq); ++ } else { ++ reader.getKeys().bind(new Reference(val), keySeq); ++ } ++ } ++ } catch (IllegalArgumentException e) { ++ Log.warn("Unable to parse user configuration: ", e); ++ } ++ } ++ } + -+ public int hashCode() { -+ return id; -+ } -+} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/mips64/ProcMIPS64ThreadContext.java jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/mips64/ProcMIPS64ThreadContext.java ---- openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/mips64/ProcMIPS64ThreadContext.java 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/mips64/ProcMIPS64ThreadContext.java 2023-09-12 13:54:26.377575791 +0800 -@@ -0,0 +1,47 @@ -+/* -+ * Copyright (c) 2002, 2003, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2018, Loongson Technology. 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. -+ * -+ */ ++ private static String translateQuoted(String keySeq) { ++ int i; ++ String str = keySeq.substring(1, keySeq.length() - 1); ++ StringBuilder sb = new StringBuilder(); ++ for (i = 0; i < str.length(); i++) { ++ char c = str.charAt(i); ++ if (c == '\\') { ++ boolean ctrl = str.regionMatches(i, "\\C-", 0, 3) || str.regionMatches(i, "\\M-\\C-", 0, 6); ++ boolean meta = str.regionMatches(i, "\\M-", 0, 3) || str.regionMatches(i, "\\C-\\M-", 0, 6); ++ i += (meta ? 3 : 0) + (ctrl ? 3 : 0) + (!meta && !ctrl ? 1 : 0); ++ if (i >= str.length()) { ++ break; ++ } ++ c = str.charAt(i); ++ if (meta) { ++ sb.append("\u001b"); ++ } ++ if (ctrl) { ++ c = c == '?' ? 0x7f : (char) (Character.toUpperCase(c) & 0x1f); ++ } ++ if (!meta && !ctrl) { ++ switch (c) { ++ case 'a': ++ c = 0x07; ++ break; ++ case 'b': ++ c = '\b'; ++ break; ++ case 'd': ++ c = 0x7f; ++ break; ++ case 'e': ++ c = 0x1b; ++ break; ++ case 'f': ++ c = '\f'; ++ break; ++ case 'n': ++ c = '\n'; ++ break; ++ case 'r': ++ c = '\r'; ++ break; ++ case 't': ++ c = '\t'; ++ break; ++ case 'v': ++ c = 0x0b; ++ break; ++ case '\\': ++ c = '\\'; ++ break; ++ case '0': ++ case '1': ++ case '2': ++ case '3': ++ case '4': ++ case '5': ++ case '6': ++ case '7': ++ c = 0; ++ for (int j = 0; j < 3; j++, i++) { ++ if (i >= str.length()) { ++ break; ++ } ++ int k = Character.digit(str.charAt(i), 8); ++ if (k < 0) { ++ break; ++ } ++ c = (char) (c * 8 + k); ++ } ++ c &= 0xFF; ++ break; ++ case 'x': ++ i++; ++ c = 0; ++ for (int j = 0; j < 2; j++, i++) { ++ if (i >= str.length()) { ++ break; ++ } ++ int k = Character.digit(str.charAt(i), 16); ++ if (k < 0) { ++ break; ++ } ++ c = (char) (c * 16 + k); ++ } ++ c &= 0xFF; ++ break; ++ case 'u': ++ i++; ++ c = 0; ++ for (int j = 0; j < 4; j++, i++) { ++ if (i >= str.length()) { ++ break; ++ } ++ int k = Character.digit(str.charAt(i), 16); ++ if (k < 0) { ++ break; ++ } ++ c = (char) (c * 16 + k); ++ } ++ break; ++ } ++ } ++ sb.append(c); ++ } else { ++ sb.append(c); ++ } ++ } ++ return sb.toString(); ++ } ++ ++ private static char getKeyFromName(String name) { ++ if ("DEL".equalsIgnoreCase(name) || "Rubout".equalsIgnoreCase(name)) { ++ return 0x7f; ++ } else if ("ESC".equalsIgnoreCase(name) || "Escape".equalsIgnoreCase(name)) { ++ return '\033'; ++ } else if ("LFD".equalsIgnoreCase(name) || "NewLine".equalsIgnoreCase(name)) { ++ return '\n'; ++ } else if ("RET".equalsIgnoreCase(name) || "Return".equalsIgnoreCase(name)) { ++ return '\r'; ++ } else if ("SPC".equalsIgnoreCase(name) || "Space".equalsIgnoreCase(name)) { ++ return ' '; ++ } else if ("Tab".equalsIgnoreCase(name)) { ++ return '\t'; ++ } else { ++ return name.charAt(0); ++ } ++ } + -+package sun.jvm.hotspot.debugger.proc.mips64; ++ static void setVar(LineReader reader, String key, String val) { ++ if (LineReader.KEYMAP.equalsIgnoreCase(key)) { ++ reader.setKeyMap(val); ++ return; ++ } + -+import sun.jvm.hotspot.debugger.*; -+import sun.jvm.hotspot.debugger.mips64.*; -+import sun.jvm.hotspot.debugger.proc.*; ++ for (LineReader.Option option : LineReader.Option.values()) { ++ if (option.name().toLowerCase(Locale.ENGLISH).replace('_', '-').equals(val)) { ++ if ("on".equalsIgnoreCase(val)) { ++ reader.setOpt(option); ++ } else if ("off".equalsIgnoreCase(val)) { ++ reader.unsetOpt(option); ++ } ++ return; ++ } ++ } + -+public class ProcMIPS64ThreadContext extends MIPS64ThreadContext { -+ private ProcDebugger debugger; ++ reader.setVariable(key, val); ++ } ++} +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/KillRing.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/KillRing.java +index f89ed35d0..2510fd9e3 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/KillRing.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/KillRing.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2018, the original author or authors. ++ * Copyright (c) 2002-2018, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/LineReaderImpl.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/LineReaderImpl.java +index ee8a434e1..94ed9ae45 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/LineReaderImpl.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/LineReaderImpl.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2022, the original author or authors. ++ * Copyright (c) 2002-2023, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -18,6 +18,9 @@ import java.io.IOException; + import java.io.InputStream; + import java.io.InterruptedIOException; + import java.lang.reflect.Constructor; ++import java.nio.file.Files; ++import java.nio.file.Path; ++import java.nio.file.Paths; + import java.time.Instant; + import java.util.*; + import java.util.concurrent.atomic.AtomicBoolean; +@@ -56,6 +59,7 @@ import static jdk.internal.org.jline.keymap.KeyMap.del; + import static jdk.internal.org.jline.keymap.KeyMap.esc; + import static jdk.internal.org.jline.keymap.KeyMap.range; + import static jdk.internal.org.jline.keymap.KeyMap.translate; ++import static jdk.internal.org.jline.terminal.TerminalBuilder.PROP_DISABLE_ALTERNATE_CHARSET; + + /** + * A reader for terminal applications. It supports custom tab-completion, +@@ -66,23 +70,27 @@ import static jdk.internal.org.jline.keymap.KeyMap.translate; + * @author Guillaume Nodet + */ + @SuppressWarnings("StatementWithEmptyBody") +-public class LineReaderImpl implements LineReader, Flushable +-{ ++public class LineReaderImpl implements LineReader, Flushable { + public static final char NULL_MASK = 0; + ++ /** ++ * @deprecated use {@link #DEFAULT_TAB_WIDTH} and {@link #getTabWidth()} ++ */ ++ @Deprecated + public static final int TAB_WIDTH = 4; + ++ public static final int DEFAULT_TAB_WIDTH = 4; + + public static final String DEFAULT_WORDCHARS = "*?_-.[]~=/&;!#$%^(){}<>"; + public static final String DEFAULT_REMOVE_SUFFIX_CHARS = " \t\n;&|"; + public static final String DEFAULT_COMMENT_BEGIN = "#"; + public static final String DEFAULT_SEARCH_TERMINATORS = "\033\012"; + public static final String DEFAULT_BELL_STYLE = ""; +- public static final int DEFAULT_LIST_MAX = 100; +- public static final int DEFAULT_MENU_LIST_MAX = Integer.MAX_VALUE; +- public static final int DEFAULT_ERRORS = 2; +- public static final long DEFAULT_BLINK_MATCHING_PAREN = 500L; +- public static final long DEFAULT_AMBIGUOUS_BINDING = 1000L; ++ public static final int DEFAULT_LIST_MAX = 100; ++ public static final int DEFAULT_MENU_LIST_MAX = Integer.MAX_VALUE; ++ public static final int DEFAULT_ERRORS = 2; ++ public static final long DEFAULT_BLINK_MATCHING_PAREN = 500L; ++ public static final long DEFAULT_AMBIGUOUS_BINDING = 1000L; + public static final String DEFAULT_SECONDARY_PROMPT_PATTERN = "%M> "; + public static final String DEFAULT_OTHERS_GROUP_NAME = "others"; + public static final String DEFAULT_ORIGINAL_GROUP_NAME = "original"; +@@ -96,9 +104,10 @@ public class LineReaderImpl implements LineReader, Flushable + public static final String DEFAULT_COMPLETION_STYLE_LIST_GROUP = "fg:black,bold"; + public static final String DEFAULT_COMPLETION_STYLE_LIST_SELECTION = DEFAULT_COMPLETION_STYLE_SELECTION; + public static final String DEFAULT_COMPLETION_STYLE_LIST_BACKGROUND = "bg:bright-magenta"; +- public static final int DEFAULT_INDENTATION = 0; +- public static final int DEFAULT_FEATURES_MAX_BUFFER_SIZE = 1000; +- public static final int DEFAULT_SUGGESTIONS_MIN_BUFFER_SIZE = 1; ++ public static final int DEFAULT_INDENTATION = 0; ++ public static final int DEFAULT_FEATURES_MAX_BUFFER_SIZE = 1000; ++ public static final int DEFAULT_SUGGESTIONS_MIN_BUFFER_SIZE = 1; ++ public static final String DEFAULT_SYSTEM_PROPERTY_PREFIX = "org.jline.reader.props."; + + private static final int MIN_ROWS = 3; + +@@ -109,6 +118,7 @@ public class LineReaderImpl implements LineReader, Flushable + + public static final String FOCUS_IN_SEQ = "\033[I"; + public static final String FOCUS_OUT_SEQ = "\033[O"; ++ public static final int DEFAULT_MAX_REPEAT_COUNT = 9999; + + /** + * Possible states in which the current readline operation may be in. +@@ -197,27 +207,28 @@ public class LineReaderImpl implements LineReader, Flushable + protected int searchIndex = -1; + protected boolean doAutosuggestion; + +- + // Reading buffers + protected final BindingReader bindingReader; + +- + /** + * VI character find + */ + protected int findChar; + -+ public ProcMIPS64ThreadContext(ProcDebugger debugger) { -+ super(); -+ this.debugger = debugger; -+ } + protected int findDir; + protected int findTailAdd; + /** + * VI history string search + */ + private int searchDir; + -+ public void setRegisterAsAddress(int index, Address value) { -+ setRegister(index, debugger.getAddressValue(value)); -+ } + private String searchString; + + /** + * Region state + */ + protected int regionMark; + -+ public Address getRegisterAsAddress(int index) { -+ return debugger.newAddress(getRegister(index)); -+ } -+} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/mips64/ProcMIPS64ThreadFactory.java jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/mips64/ProcMIPS64ThreadFactory.java ---- openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/mips64/ProcMIPS64ThreadFactory.java 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/mips64/ProcMIPS64ThreadFactory.java 2023-09-12 13:54:26.377575791 +0800 -@@ -0,0 +1,45 @@ -+/* -+ * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2018, Loongson Technology. 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. -+ * -+ */ + protected RegionType regionActive; + + private boolean forceChar; +@@ -232,7 +243,7 @@ public class LineReaderImpl implements LineReader, Flushable + + protected KillRing killRing = new KillRing(); + +- protected UndoTree undo = new UndoTree<>(this::setBuffer); ++ protected UndoTree undo; + protected boolean isUndo; + + /** +@@ -242,7 +253,7 @@ public class LineReaderImpl implements LineReader, Flushable + /* + * Current internal state of the line reader + */ +- protected State state = State.DONE; ++ protected State state = State.DONE; + protected final AtomicBoolean startedReading = new AtomicBoolean(); + protected boolean reading; + +@@ -278,7 +289,10 @@ public class LineReaderImpl implements LineReader, Flushable + */ + protected List commandsBuffer = new ArrayList<>(); + +- int candidateStartPosition = 0; ++ protected int candidateStartPosition = 0; + -+package sun.jvm.hotspot.debugger.proc.mips64; ++ protected String alternateIn; ++ protected String alternateOut; + + public LineReaderImpl(Terminal terminal) throws IOException { + this(terminal, terminal.getName(), null); +@@ -288,6 +302,7 @@ public class LineReaderImpl implements LineReader, Flushable + this(terminal, appName, null); + } + ++ @SuppressWarnings("this-escape") + public LineReaderImpl(Terminal terminal, String appName, Map variables) { + Objects.requireNonNull(terminal, "terminal can not be null"); + this.terminal = terminal; +@@ -300,11 +315,40 @@ public class LineReaderImpl implements LineReader, Flushable + } else { + this.variables = new HashMap<>(); + } ++ String prefix = getString(SYSTEM_PROPERTY_PREFIX, DEFAULT_SYSTEM_PROPERTY_PREFIX); ++ if (prefix != null) { ++ Properties sysProps = System.getProperties(); ++ for (String s : sysProps.stringPropertyNames()) { ++ if (s.startsWith(prefix)) { ++ String key = s.substring(prefix.length()); ++ InputRC.setVar(this, key, sysProps.getProperty(s)); ++ } ++ } ++ } + -+import sun.jvm.hotspot.debugger.*; -+import sun.jvm.hotspot.debugger.proc.*; + this.keyMaps = defaultKeyMaps(); ++ if (!Boolean.getBoolean(PROP_DISABLE_ALTERNATE_CHARSET)) { ++ this.alternateIn = Curses.tputs(terminal.getStringCapability(Capability.enter_alt_charset_mode)); ++ this.alternateOut = Curses.tputs(terminal.getStringCapability(Capability.exit_alt_charset_mode)); ++ } + ++ undo = new UndoTree<>(this::setBuffer); + builtinWidgets = builtinWidgets(); + widgets = new HashMap<>(builtinWidgets); + bindingReader = new BindingReader(terminal.reader()); ++ ++ String inputRc = getString(INPUT_RC_FILE_NAME, null); ++ if (inputRc != null) { ++ Path inputRcPath = Paths.get(inputRc); ++ if (Files.exists(inputRcPath)) { ++ try (InputStream is = Files.newInputStream(inputRcPath)) { ++ InputRC.configure(this, is); ++ } catch (Exception e) { ++ Log.debug("Error reading inputRc config file: ", inputRc, e); ++ } ++ } ++ } + -+public class ProcMIPS64ThreadFactory implements ProcThreadFactory { -+ private ProcDebugger debugger; + doDisplay(); + } + +@@ -489,7 +533,8 @@ public class LineReaderImpl implements LineReader, Flushable + * @param buffer A string that will be set for editing. + * @return A line that is read from the terminal, can never be null. + */ +- public String readLine(String prompt, Character mask, String buffer) throws UserInterruptException, EndOfFileException { ++ public String readLine(String prompt, Character mask, String buffer) ++ throws UserInterruptException, EndOfFileException { + return readLine(prompt, null, mask, buffer); + } + +@@ -503,7 +548,8 @@ public class LineReaderImpl implements LineReader, Flushable + * @param buffer A string that will be set for editing. + * @return A line that is read from the terminal, can never be null. + */ +- public String readLine(String prompt, String rightPrompt, Character mask, String buffer) throws UserInterruptException, EndOfFileException { ++ public String readLine(String prompt, String rightPrompt, Character mask, String buffer) ++ throws UserInterruptException, EndOfFileException { + return readLine(prompt, rightPrompt, mask != null ? new SimpleMaskingCallback(mask) : null, buffer); + } + +@@ -517,7 +563,8 @@ public class LineReaderImpl implements LineReader, Flushable + * @param buffer A string that will be set for editing. + * @return A line that is read from the terminal, can never be null. + */ +- public String readLine(String prompt, String rightPrompt, MaskingCallback maskingCallback, String buffer) throws UserInterruptException, EndOfFileException { ++ public String readLine(String prompt, String rightPrompt, MaskingCallback maskingCallback, String buffer) ++ throws UserInterruptException, EndOfFileException { + // prompt may be null + // maskingCallback may be null + // buffer may be null +@@ -618,23 +665,14 @@ public class LineReaderImpl implements LineReader, Flushable + // Move into application mode + if (!dumb) { + terminal.puts(Capability.keypad_xmit); +- if (isSet(Option.AUTO_FRESH_LINE)) +- callWidget(FRESH_LINE); +- if (isSet(Option.MOUSE)) +- terminal.trackMouse(Terminal.MouseTracking.Normal); +- if (isSet(Option.BRACKETED_PASTE)) +- terminal.writer().write(BRACKETED_PASTE_ON); +- } else { +- // For dumb terminals, we need to make sure that CR are ignored +- Attributes attr = new Attributes(originalAttributes); +- attr.setInputFlag(Attributes.InputFlag.IGNCR, true); +- terminal.setAttributes(attr); ++ if (isSet(Option.AUTO_FRESH_LINE)) callWidget(FRESH_LINE); ++ if (isSet(Option.MOUSE)) terminal.trackMouse(Terminal.MouseTracking.Normal); ++ if (isSet(Option.BRACKETED_PASTE)) terminal.writer().write(BRACKETED_PASTE_ON); + } + + callWidget(CALLBACK_INIT); + +- if (!isSet(Option.DISABLE_UNDO)) +- undo.newState(buf.copy()); ++ if (!isSet(Option.DISABLE_UNDO)) undo.newState(buf.copy()); + + // Draw initial prompt + redrawLine(); +@@ -654,7 +692,8 @@ public class LineReaderImpl implements LineReader, Flushable + throw new EndOfFileException().partialLine(buf.length() > 0 ? buf.toString() : null); + } + Log.trace("Binding: ", o); +- if (buf.length() == 0 && getLastBinding().charAt(0) == originalAttributes.getControlChar(ControlChar.VEOF)) { ++ if (buf.length() == 0 ++ && getLastBinding().charAt(0) == originalAttributes.getControlChar(ControlChar.VEOF)) { + throw new EndOfFileException(); + } + +@@ -675,12 +714,17 @@ public class LineReaderImpl implements LineReader, Flushable + try { + lock.lock(); + // Get executable widget +- Buffer copy = buf.length() <= getInt(FEATURES_MAX_BUFFER_SIZE, DEFAULT_FEATURES_MAX_BUFFER_SIZE) ? buf.copy() : null; ++ Buffer copy = buf.length() <= getInt(FEATURES_MAX_BUFFER_SIZE, DEFAULT_FEATURES_MAX_BUFFER_SIZE) ++ ? buf.copy() ++ : null; + Widget w = getWidget(o); + if (!w.apply()) { + beep(); + } +- if (!isSet(Option.DISABLE_UNDO) && !isUndo && copy != null && buf.length() <= getInt(FEATURES_MAX_BUFFER_SIZE, DEFAULT_FEATURES_MAX_BUFFER_SIZE) ++ if (!isSet(Option.DISABLE_UNDO) ++ && !isUndo ++ && copy != null ++ && buf.length() <= getInt(FEATURES_MAX_BUFFER_SIZE, DEFAULT_FEATURES_MAX_BUFFER_SIZE) + && !copy.toString().equals(buf.toString())) { + undo.newState(buf.copy()); + } +@@ -718,13 +762,18 @@ public class LineReaderImpl implements LineReader, Flushable + } else { + throw e; + } +- } +- finally { ++ } finally { ++ AtomicBoolean interrupted = new AtomicBoolean(Thread.interrupted()); + try { + lock.lock(); + + this.reading = false; + ++ Terminal.SignalHandler tmpHandler = terminal.handle(Signal.INT, s -> interrupted.set(true)); ++ if (previousIntrHandler == null) { ++ previousIntrHandler = tmpHandler; ++ } + -+ public ProcMIPS64ThreadFactory(ProcDebugger debugger) { -+ this.debugger = debugger; -+ } + cleanup(); + if (originalAttributes != null) { + terminal.setAttributes(originalAttributes); +@@ -741,13 +790,15 @@ public class LineReaderImpl implements LineReader, Flushable + } finally { + lock.unlock(); + startedReading.set(false); ++ if (interrupted.get()) { ++ Thread.currentThread().interrupt(); ++ } + } + } + } + + private boolean isTerminalDumb() { +- return Terminal.TYPE_DUMB.equals(terminal.getType()) +- || Terminal.TYPE_DUMB_COLOR.equals(terminal.getType()); ++ return Terminal.TYPE_DUMB.equals(terminal.getType()) || Terminal.TYPE_DUMB_COLOR.equals(terminal.getType()); + } + + private void doDisplay() { +@@ -757,8 +808,7 @@ public class LineReaderImpl implements LineReader, Flushable + + display = new Display(terminal, false); + display.resize(size.getRows(), size.getColumns()); +- if (isSet(Option.DELAY_LINE_WRAP)) +- display.setDelayLineWrap(true); ++ if (isSet(Option.DELAY_LINE_WRAP)) display.setDelayLineWrap(true); + } + + @Override +@@ -965,8 +1015,10 @@ public class LineReaderImpl implements LineReader, Flushable + if (!YANK_POP.equals(ref) && !YANK.equals(ref)) { + killRing.resetLastYank(); + } +- if (!KILL_LINE.equals(ref) && !KILL_WHOLE_LINE.equals(ref) +- && !BACKWARD_KILL_WORD.equals(ref) && !KILL_WORD.equals(ref)) { ++ if (!KILL_LINE.equals(ref) ++ && !KILL_WHOLE_LINE.equals(ref) ++ && !BACKWARD_KILL_WORD.equals(ref) ++ && !KILL_WORD.equals(ref)) { + killRing.resetLastKill(); + } + } +@@ -1083,7 +1135,7 @@ public class LineReaderImpl implements LineReader, Flushable + if (isSet(Option.BRACKETED_PASTE)) { + terminal.writer().write(BRACKETED_PASTE_OFF); + } +- Constructor ctor = Class.forName("jdk.internal.org.jline.builtins.Nano").getConstructor(Terminal.class, File.class); ++ Constructor ctor = Class.forName("org.jline.builtins.Nano").getConstructor(Terminal.class, File.class); + Editor editor = (Editor) ctor.newInstance(terminal, new File(file.getParent())); + editor.setRestricted(true); + editor.open(Collections.singletonList(file.getName())); +@@ -1097,6 +1149,10 @@ public class LineReaderImpl implements LineReader, Flushable + } + } + ++ protected int getTabWidth() { ++ return getInt(LineReader.TAB_WIDTH, DEFAULT_TAB_WIDTH); ++ } + -+ public ThreadProxy createThreadWrapper(Address threadIdentifierAddr) { -+ return new ProcMIPS64Thread(debugger, threadIdentifierAddr); -+ } + // + // Widget implementation + // +@@ -1137,26 +1193,27 @@ public class LineReaderImpl implements LineReader, Flushable + } + + // we only add it to the history if the buffer is not empty +- if (historyLine != null && historyLine.length() > 0 ) { ++ if (historyLine != null && historyLine.length() > 0) { + history.add(Instant.now(), historyLine); + } + return str; + } + +- protected void handleSignal(Signal signal) { ++ protected synchronized void handleSignal(Signal signal) { + doAutosuggestion = false; + if (signal == Signal.WINCH) { ++ size.copy(terminal.getBufferSize()); ++ display.resize(size.getRows(), size.getColumns()); + Status status = Status.getStatus(terminal, false); + if (status != null) { +- status.hardReset(); ++ status.resize(size); ++ status.reset(); + } +- size.copy(terminal.getBufferSize()); +- display.resize(size.getRows(), size.getColumns()); +- // restores prompt but also prevents scrolling in consoleZ, see #492 +- // redrawLine(); ++ terminal.puts(Capability.carriage_return); ++ terminal.puts(Capability.clr_eos); ++ redrawLine(); + redisplay(); +- } +- else if (signal == Signal.CONT) { ++ } else if (signal == Signal.CONT) { + terminal.enterRawMode(); + size.copy(terminal.getBufferSize()); + display.resize(size.getRows(), size.getColumns()); +@@ -1200,13 +1257,11 @@ public class LineReaderImpl implements LineReader, Flushable + // + + public void setPrompt(final String prompt) { +- this.prompt = (prompt == null ? AttributedString.EMPTY +- : expandPromptPattern(prompt, 0, "", 0)); ++ this.prompt = (prompt == null ? AttributedString.EMPTY : expandPromptPattern(prompt, 0, "", 0)); + } + + public void setRightPrompt(final String rightPrompt) { +- this.rightPrompt = (rightPrompt == null ? AttributedString.EMPTY +- : expandPromptPattern(rightPrompt, 0, "", 0)); ++ this.rightPrompt = (rightPrompt == null ? AttributedString.EMPTY : expandPromptPattern(rightPrompt, 0, "", 0)); + } + + protected void setBuffer(Buffer buffer) { +@@ -1233,7 +1288,7 @@ public class LineReaderImpl implements LineReader, Flushable + * @param op The incoming operation to remap + * @return The remaped operation + */ +- protected String viDeleteChangeYankToRemap (String op) { ++ protected String viDeleteChangeYankToRemap(String op) { + switch (op) { + case SEND_BREAK: + case BACKWARD_CHAR: +@@ -1292,7 +1347,6 @@ public class LineReaderImpl implements LineReader, Flushable + return VICMD.equals(keyMap); + } + +- + // + // Movement + // +@@ -1332,7 +1386,6 @@ public class LineReaderImpl implements LineReader, Flushable + return true; + } + +- + // + // Word movement + // +@@ -1365,9 +1418,7 @@ public class LineReaderImpl implements LineReader, Flushable + buf.move(1); + } + } else { +- while (buf.cursor() < buf.length() +- && !isViAlphaNum(buf.currChar()) +- && !isWhitespace(buf.currChar())) { ++ while (buf.cursor() < buf.length() && !isViAlphaNum(buf.currChar()) && !isWhitespace(buf.currChar())) { + buf.move(1); + } + } +@@ -1375,9 +1426,7 @@ public class LineReaderImpl implements LineReader, Flushable + return true; + } + int nl = buf.currChar() == '\n' ? 1 : 0; +- while (buf.cursor() < buf.length() +- && nl < 2 +- && isWhitespace(buf.currChar())) { ++ while (buf.cursor() < buf.length() && nl < 2 && isWhitespace(buf.currChar())) { + buf.move(1); + nl += buf.currChar() == '\n' ? 1 : 0; + } +@@ -1397,9 +1446,7 @@ public class LineReaderImpl implements LineReader, Flushable + return true; + } + int nl = buf.currChar() == '\n' ? 1 : 0; +- while (buf.cursor() < buf.length() +- && nl < 2 +- && isWhitespace(buf.currChar())) { ++ while (buf.cursor() < buf.length() && nl < 2 && isWhitespace(buf.currChar())) { + buf.move(1); + nl += buf.currChar() == '\n' ? 1 : 0; + } +@@ -1451,7 +1498,9 @@ public class LineReaderImpl implements LineReader, Flushable + } + } else { + buf.move(1); +- while (buf.cursor() < buf.length() && !isViAlphaNum(buf.nextChar()) && !isWhitespace(buf.nextChar())) { ++ while (buf.cursor() < buf.length() ++ && !isViAlphaNum(buf.nextChar()) ++ && !isWhitespace(buf.nextChar())) { + buf.move(1); + } + } +@@ -1720,9 +1769,7 @@ public class LineReaderImpl implements LineReader, Flushable + buf.move(1); + } + while (buf.cursor() < buf.length() && isWord(buf.currChar())) { +- buf.currChar(first +- ? Character.toUpperCase(buf.currChar()) +- : Character.toLowerCase(buf.currChar())); ++ buf.currChar(first ? Character.toUpperCase(buf.currChar()) : Character.toLowerCase(buf.currChar())); + buf.move(1); + first = false; + } +@@ -1810,7 +1857,8 @@ public class LineReaderImpl implements LineReader, Flushable + sta1--; + } + end1 = sta1; +- while (end1 < lend && !isDelimiter(buf.atChar(++end1))); ++ while (end1 < lend && !isDelimiter(buf.atChar(++end1))) ++ ; + if (neg) { + end2 = sta1 - 1; + while (end2 > lstart && isDelimiter(buf.atChar(end2 - 1))) { +@@ -1819,9 +1867,11 @@ public class LineReaderImpl implements LineReader, Flushable + if (end2 < lstart) { + // No word before, use the word after + sta2 = end1; +- while (isDelimiter(buf.atChar(++sta2))); ++ while (isDelimiter(buf.atChar(++sta2))) ++ ; + end2 = sta2; +- while (end2 < lend && !isDelimiter(buf.atChar(++end2))); ++ while (end2 < lend && !isDelimiter(buf.atChar(++end2))) ++ ; + } else { + sta2 = end2; + while (sta2 > lstart && !isDelimiter(buf.atChar(sta2 - 1))) { +@@ -1830,7 +1880,8 @@ public class LineReaderImpl implements LineReader, Flushable + } + } else { + sta2 = end1; +- while (sta2 < lend && isDelimiter(buf.atChar(++sta2))); ++ while (sta2 < lend && isDelimiter(buf.atChar(++sta2))) ++ ; + if (sta2 == lend) { + // No word after, use the word before + end2 = sta1; +@@ -1843,19 +1894,24 @@ public class LineReaderImpl implements LineReader, Flushable + } + } else { + end2 = sta2; +- while (end2 < lend && !isDelimiter(buf.atChar(++end2))) ; ++ while (end2 < lend && !isDelimiter(buf.atChar(++end2))) ++ ; + } + } + if (sta1 < sta2) { +- String res = buf.substring(0, sta1) + buf.substring(sta2, end2) +- + buf.substring(end1, sta2) + buf.substring(sta1, end1) ++ String res = buf.substring(0, sta1) ++ + buf.substring(sta2, end2) ++ + buf.substring(end1, sta2) ++ + buf.substring(sta1, end1) + + buf.substring(end2); + buf.clear(); + buf.write(res); + buf.cursor(neg ? end1 : end2); + } else { +- String res = buf.substring(0, sta2) + buf.substring(sta1, end1) +- + buf.substring(end2, sta1) + buf.substring(sta2, end2) ++ String res = buf.substring(0, sta2) ++ + buf.substring(sta1, end1) ++ + buf.substring(end2, sta1) ++ + buf.substring(sta2, end2) + + buf.substring(end1); + buf.clear(); + buf.write(res); +@@ -1988,11 +2044,11 @@ public class LineReaderImpl implements LineReader, Flushable + while (count-- > 0) { + do { + buf.move(findDir); +- } while (buf.cursor() > 0 && buf.cursor() < buf.length() ++ } while (buf.cursor() > 0 ++ && buf.cursor() < buf.length() + && buf.currChar() != findChar + && buf.currChar() != '\n'); +- if (buf.cursor() <= 0 || buf.cursor() >= buf.length() +- || buf.currChar() == '\n') { ++ if (buf.cursor() <= 0 || buf.cursor() >= buf.length() || buf.currChar() == '\n') { + buf.cursor(cursor); + return false; + } +@@ -2211,18 +2267,17 @@ public class LineReaderImpl implements LineReader, Flushable + * character or if there was no matching bracket. + */ + protected boolean doViMatchBracket() { +- int pos = buf.cursor(); ++ int pos = buf.cursor(); + + if (pos == buf.length()) { + return false; + } + +- int type = getBracketType(buf.atChar(pos)); +- int move = (type < 0) ? -1 : 1; +- int count = 1; ++ int type = getBracketType(buf.atChar(pos)); ++ int move = (type < 0) ? -1 : 1; ++ int count = 1; + +- if (type == 0) +- return false; ++ if (type == 0) return false; + + while (count > 0) { + pos += move; +@@ -2235,8 +2290,7 @@ public class LineReaderImpl implements LineReader, Flushable + int curType = getBracketType(buf.atChar(pos)); + if (curType == type) { + ++count; +- } +- else if (curType == -type) { ++ } else if (curType == -type) { + --count; + } + } +@@ -2245,8 +2299,7 @@ public class LineReaderImpl implements LineReader, Flushable + * Slight adjustment for delete-to, yank-to, change-to to ensure + * that the matching paren is consumed + */ +- if (move > 0 && isInViMoveOperation()) +- ++pos; ++ if (move > 0 && isInViMoveOperation()) ++pos; + + buf.cursor(pos); + return true; +@@ -2259,14 +2312,20 @@ public class LineReaderImpl implements LineReader, Flushable + * @return 1 is square, 2 curly, 3 parent, or zero for none. The value + * will be negated if it is the closing form of the bracket. + */ +- protected int getBracketType (int ch) { ++ protected int getBracketType(int ch) { + switch (ch) { +- case '[': return 1; +- case ']': return -1; +- case '{': return 2; +- case '}': return -2; +- case '(': return 3; +- case ')': return -3; ++ case '[': ++ return 1; ++ case ']': ++ return -1; ++ case '{': ++ return 2; ++ case '}': ++ return -2; ++ case '(': ++ return 3; ++ case ')': ++ return -3; + default: + return 0; + } +@@ -2331,7 +2390,7 @@ public class LineReaderImpl implements LineReader, Flushable + buf.clear(); + println(); + redrawLine(); +-// state = State.INTERRUPT; ++ // state = State.INTERRUPT; + return false; + } + return true; +@@ -2378,6 +2437,10 @@ public class LineReaderImpl implements LineReader, Flushable + protected boolean digitArgument() { + String s = getLastBinding(); + repeatCount = (repeatCount * 10) + s.charAt(s.length() - 1) - '0'; ++ int maxRepeatCount = getInt(MAX_REPEAT_COUNT, DEFAULT_MAX_REPEAT_COUNT); ++ if (repeatCount > maxRepeatCount) { ++ throw new IllegalArgumentException("digit argument should be less than " + maxRepeatCount); ++ } + isArgDigit = true; + return true; + } +@@ -2438,10 +2501,12 @@ public class LineReaderImpl implements LineReader, Flushable + protected boolean viYankWholeLine() { + int s, e; + int p = buf.cursor(); +- while (buf.move(-1) == -1 && buf.prevChar() != '\n') ; ++ while (buf.move(-1) == -1 && buf.prevChar() != '\n') ++ ; + s = buf.cursor(); + for (int i = 0; i < repeatCount; i++) { +- while (buf.move(1) == 1 && buf.prevChar() != '\n') ; ++ while (buf.move(1) == 1 && buf.prevChar() != '\n') ++ ; + } + e = buf.cursor(); + yankBuffer = buf.substring(s, e); +@@ -2554,15 +2619,19 @@ public class LineReaderImpl implements LineReader, Flushable + return doSearchHistory(true); + } + +- static class Pair { +- final U u; final V v; ++ static class Pair { ++ final U u; ++ final V v; ++ + public Pair(U u, V v) { + this.u = u; + this.v = v; + } + -+ public ThreadProxy createThreadWrapper(long id) { -+ return new ProcMIPS64Thread(debugger, id); -+ } -+} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/mips64/ProcMIPS64Thread.java jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/mips64/ProcMIPS64Thread.java ---- openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/mips64/ProcMIPS64Thread.java 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/mips64/ProcMIPS64Thread.java 2023-09-12 13:54:26.377575791 +0800 -@@ -0,0 +1,92 @@ -+/* -+ * Copyright (c) 2002, 2003, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2018, Loongson Technology. 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. -+ * -+ */ + public U getU() { + return u; + } + -+package sun.jvm.hotspot.debugger.proc.mips64; + public V getV() { + return v; + } +@@ -2575,7 +2644,8 @@ public class LineReaderImpl implements LineReader, Flushable + + KeyMap terminators = new KeyMap<>(); + getString(SEARCH_TERMINATORS, DEFAULT_SEARCH_TERMINATORS) +- .codePoints().forEach(c -> bind(terminators, ACCEPT_LINE, new String(Character.toChars(c)))); ++ .codePoints() ++ .forEach(c -> bind(terminators, ACCEPT_LINE, new String(Character.toChars(c)))); + + Buffer originalBuffer = buf.copy(); + searchIndex = -1; +@@ -2583,8 +2653,8 @@ public class LineReaderImpl implements LineReader, Flushable + searchBackward = backward; + searchFailing = false; + post = () -> new AttributedString((searchFailing ? "failing" + " " : "") +- + (searchBackward ? "bck-i-search" : "fwd-i-search") +- + ": " + searchTerm + "_"); ++ + (searchBackward ? "bck-i-search" : "fwd-i-search") ++ + ": " + searchTerm + "_"); + + redisplay(); + try { +@@ -2630,8 +2700,9 @@ public class LineReaderImpl implements LineReader, Flushable + searchFailing = false; + } else { + boolean caseInsensitive = isSet(Option.CASE_INSENSITIVE_SEARCH); +- Pattern pat = Pattern.compile(pattern, caseInsensitive ? Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE +- : Pattern.UNICODE_CASE); ++ Pattern pat = Pattern.compile( ++ pattern, ++ caseInsensitive ? Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE : Pattern.UNICODE_CASE); + Pair pair = null; + if (searchBackward) { + boolean nextOnly = next; +@@ -2641,7 +2712,11 @@ public class LineReaderImpl implements LineReader, Flushable + .orElse(null); + if (pair == null) { + pair = StreamSupport.stream( +- Spliterators.spliteratorUnknownSize(history.reverseIterator(searchIndex < 0 ? history.last() : searchIndex - 1), Spliterator.ORDERED), false) ++ Spliterators.spliteratorUnknownSize( ++ history.reverseIterator( ++ searchIndex < 0 ? history.last() : searchIndex - 1), ++ Spliterator.ORDERED), ++ false) + .flatMap(e -> matches(pat, e.line(), e.index()).stream()) + .findFirst() + .orElse(null); +@@ -2654,7 +2729,11 @@ public class LineReaderImpl implements LineReader, Flushable + .orElse(null); + if (pair == null) { + pair = StreamSupport.stream( +- Spliterators.spliteratorUnknownSize(history.iterator((searchIndex < 0 ? history.last() : searchIndex) + 1), Spliterator.ORDERED), false) ++ Spliterators.spliteratorUnknownSize( ++ history.iterator( ++ (searchIndex < 0 ? history.last() : searchIndex) + 1), ++ Spliterator.ORDERED), ++ false) + .flatMap(e -> matches(pat, e.line(), e.index()).stream()) + .findFirst() + .orElse(null); +@@ -2714,7 +2793,10 @@ public class LineReaderImpl implements LineReader, Flushable + sb.append("\\E"); + inQuote = false; + } +- sb.append("[").append(Character.toLowerCase(c)).append(Character.toUpperCase(c)).append("]"); ++ sb.append("[") ++ .append(Character.toLowerCase(c)) ++ .append(Character.toUpperCase(c)) ++ .append("]"); + } else { + if (!inQuote) { + sb.append("\\Q"); +@@ -2742,8 +2824,7 @@ public class LineReaderImpl implements LineReader, Flushable + } + + protected boolean historySearchForward() { +- if (historyBuffer == null || buf.length() == 0 +- || !buf.toString().equals(history.current())) { ++ if (historyBuffer == null || buf.length() == 0 || !buf.toString().equals(history.current())) { + historyBuffer = buf.copy(); + searchBuffer = getFirstWord(); + } +@@ -2791,8 +2872,7 @@ public class LineReaderImpl implements LineReader, Flushable + } + + protected boolean historySearchBackward() { +- if (historyBuffer == null || buf.length() == 0 +- || !buf.toString().equals(history.current())) { ++ if (historyBuffer == null || buf.length() == 0 || !buf.toString().equals(history.current())) { + historyBuffer = buf.copy(); + searchBuffer = getFirstWord(); + } +@@ -2984,7 +3064,7 @@ public class LineReaderImpl implements LineReader, Flushable + } + + void indention(int nb, StringBuilder sb) { +- int indent = getInt(INDENTATION, DEFAULT_INDENTATION)*nb; ++ int indent = getInt(INDENTATION, DEFAULT_INDENTATION) * nb; + for (int i = 0; i < indent; i++) { + sb.append(' '); + } +@@ -3017,7 +3097,6 @@ public class LineReaderImpl implements LineReader, Flushable + return true; + } + +- + // + // History Control + // +@@ -3108,13 +3187,11 @@ public class LineReaderImpl implements LineReader, Flushable + } + + protected boolean viUpLineOrHistory() { +- return upLine() +- || upHistory() && viFirstNonBlank(); ++ return upLine() || upHistory() && viFirstNonBlank(); + } + + protected boolean viDownLineOrHistory() { +- return downLine() +- || downHistory() && viFirstNonBlank(); ++ return downLine() || downHistory() && viFirstNonBlank(); + } + + protected boolean upLine() { +@@ -3175,8 +3252,7 @@ public class LineReaderImpl implements LineReader, Flushable + } + + protected boolean viChangeEol() { +- return viChange(buf.cursor(), buf.length()) +- && setKeyMap(VIINS); ++ return viChange(buf.cursor(), buf.length()) && setKeyMap(VIINS); + } + + protected boolean viKillEol() { +@@ -3199,7 +3275,8 @@ public class LineReaderImpl implements LineReader, Flushable + + protected boolean viJoin() { + if (buf.down()) { +- while (buf.move(-1) == -1 && buf.prevChar() != '\n') ; ++ while (buf.move(-1) == -1 && buf.prevChar() != '\n') ++ ; + buf.backspace(); + buf.write(' '); + buf.move(-1); +@@ -3253,14 +3330,16 @@ public class LineReaderImpl implements LineReader, Flushable + + protected boolean beginningOfLine() { + while (count-- > 0) { +- while (buf.move(-1) == -1 && buf.prevChar() != '\n') ; ++ while (buf.move(-1) == -1 && buf.prevChar() != '\n') ++ ; + } + return true; + } + + protected boolean endOfLine() { + while (count-- > 0) { +- while (buf.move(1) == 1 && buf.currChar() != '\n') ; ++ while (buf.move(1) == 1 && buf.currChar() != '\n') ++ ; + } + return true; + } +@@ -3384,7 +3463,7 @@ public class LineReaderImpl implements LineReader, Flushable + // what is really happening is that if we are in "move-mode" then the + // cursor can't be moved off the end of the line, but in "edit-mode" it + // is ok, but I have no easy way of knowing which mode we are in. +- if (! isChange && startPos > 0 && startPos == buf.length()) { ++ if (!isChange && startPos > 0 && startPos == buf.length()) { + buf.move(-1); + } + return true; +@@ -3424,14 +3503,16 @@ public class LineReaderImpl implements LineReader, Flushable + } + + protected boolean viOpenLineAbove() { +- while (buf.move(-1) == -1 && buf.prevChar() != '\n') ; ++ while (buf.move(-1) == -1 && buf.prevChar() != '\n') ++ ; + buf.write('\n'); + buf.move(-1); + return setKeyMap(VIINS); + } + + protected boolean viOpenLineBelow() { +- while (buf.move(1) == 1 && buf.currChar() != '\n') ; ++ while (buf.move(1) == 1 && buf.currChar() != '\n') ++ ; + buf.write('\n'); + return setKeyMap(VIINS); + } +@@ -3443,11 +3524,12 @@ public class LineReaderImpl implements LineReader, Flushable + */ + protected boolean viPutAfter() { + if (yankBuffer.indexOf('\n') >= 0) { +- while (buf.move(1) == 1 && buf.currChar() != '\n'); ++ while (buf.move(1) == 1 && buf.currChar() != '\n') ++ ; + buf.move(1); + putString(yankBuffer); +- buf.move(- yankBuffer.length()); +- } else if (yankBuffer.length () != 0) { ++ buf.move(-yankBuffer.length()); ++ } else if (yankBuffer.length() != 0) { + if (buf.cursor() < buf.length()) { + buf.move(1); + } +@@ -3461,10 +3543,11 @@ public class LineReaderImpl implements LineReader, Flushable + + protected boolean viPutBefore() { + if (yankBuffer.indexOf('\n') >= 0) { +- while (buf.move(-1) == -1 && buf.prevChar() != '\n'); ++ while (buf.move(-1) == -1 && buf.prevChar() != '\n') ++ ; + putString(yankBuffer); +- buf.move(- yankBuffer.length()); +- } else if (yankBuffer.length () != 0) { ++ buf.move(-yankBuffer.length()); ++ } else if (yankBuffer.length() != 0) { + if (buf.cursor() > 0) { + buf.move(-1); + } +@@ -3681,7 +3764,7 @@ public class LineReaderImpl implements LineReader, Flushable + addBuiltinWidget(widgets, MENU_EXPAND_OR_COMPLETE, this::menuExpandOrComplete); + addBuiltinWidget(widgets, NEG_ARGUMENT, this::negArgument); + addBuiltinWidget(widgets, OVERWRITE_MODE, this::overwriteMode); +-// addBuiltinWidget(widgets, QUIT, this::quit); ++ // addBuiltinWidget(widgets, QUIT, this::quit); + addBuiltinWidget(widgets, QUOTED_INSERT, this::quotedInsert); + addBuiltinWidget(widgets, REDISPLAY, this::redisplay); + addBuiltinWidget(widgets, REDRAW_LINE, this::redrawLine); +@@ -3774,6 +3857,7 @@ public class LineReaderImpl implements LineReader, Flushable + public String toString() { + return name; + } + -+import sun.jvm.hotspot.debugger.*; -+import sun.jvm.hotspot.debugger.mips64.*; -+import sun.jvm.hotspot.debugger.proc.*; -+import sun.jvm.hotspot.utilities.*; + @Override + public boolean apply() { + return widget.apply(); +@@ -3797,14 +3881,11 @@ public class LineReaderImpl implements LineReader, Flushable + + Status status = Status.getStatus(terminal, false); + if (status != null) { +- if (terminal.getType().startsWith(AbstractWindowsTerminal.TYPE_WINDOWS)) { +- status.resize(); +- } + status.redraw(); + } + + if (size.getRows() > 0 && size.getRows() < MIN_ROWS) { +- AttributedStringBuilder sb = new AttributedStringBuilder().tabs(TAB_WIDTH); ++ AttributedStringBuilder sb = new AttributedStringBuilder().tabs(getTabWidth()); + + sb.append(prompt); + concat(getHighlightedBuffer(buf.toString()).columnSplitLength(Integer.MAX_VALUE), sb); +@@ -3877,14 +3958,15 @@ public class LineReaderImpl implements LineReader, Flushable + int cursorNewLinesId = -1; + int cursorColPos = -1; + if (size.getColumns() > 0) { +- AttributedStringBuilder sb = new AttributedStringBuilder().tabs(TAB_WIDTH); ++ AttributedStringBuilder sb = new AttributedStringBuilder().tabs(getTabWidth()); + sb.append(prompt); + String buffer = buf.upToCursor(); + if (maskingCallback != null) { + buffer = maskingCallback.display(buffer); + } + sb.append(insertSecondaryPrompts(new AttributedString(buffer), secondaryPrompts, false)); +- List promptLines = sb.columnSplitLength(size.getColumns(), false, display.delayLineWrap()); ++ List promptLines = ++ sb.columnSplitLength(size.getColumns(), false, display.delayLineWrap()); + if (!promptLines.isEmpty()) { + cursorNewLinesId = promptLines.size() - 1; + cursorColPos = promptLines.get(promptLines.size() - 1).columnLength(); +@@ -3904,7 +3986,7 @@ public class LineReaderImpl implements LineReader, Flushable + int lineId = newLines.size() - displaySize + 1; + int endId = displaySize; + int startId = 1; +- if (lineId > cursorNewLinesId) { ++ if (lineId > cursorNewLinesId) { + lineId = cursorNewLinesId; + endId = displaySize - 1; + startId = 0; +@@ -3949,10 +4031,9 @@ public class LineReaderImpl implements LineReader, Flushable + } + History history = getHistory(); + StringBuilder sb = new StringBuilder(); +- for (char c: buffer.replace("\\", "\\\\").toCharArray()) { +- if (c == '(' || c == ')' || c == '[' || c == ']' || c == '{' || c == '}' || c == '^' || c == '*' +- || c == '$' || c == '.' || c == '?' || c == '+' || c == '|' || c == '<' || c == '>' || c == '!' +- || c == '-') { ++ for (char c : buffer.replace("\\", "\\\\").toCharArray()) { ++ if (c == '(' || c == ')' || c == '[' || c == ']' || c == '{' || c == '}' || c == '^' || c == '*' || c == '$' ++ || c == '.' || c == '?' || c == '+' || c == '|' || c == '<' || c == '>' || c == '!' || c == '-') { + sb.append('\\'); + } + sb.append(c); +@@ -3984,7 +4065,7 @@ public class LineReaderImpl implements LineReader, Flushable + AttributedString attBuf = getHighlightedBuffer(buf.toString()); + + AttributedString tNewBuf = insertSecondaryPrompts(attBuf, secondaryPrompts); +- AttributedStringBuilder full = new AttributedStringBuilder().tabs(TAB_WIDTH); ++ AttributedStringBuilder full = new AttributedStringBuilder().tabs(getTabWidth()); + full.append(prompt); + full.append(tNewBuf); + if (doAutosuggestion && !isTerminalDumb()) { +@@ -4040,15 +4121,15 @@ public class LineReaderImpl implements LineReader, Flushable + if (maskingCallback != null) { + buffer = maskingCallback.display(buffer); + } +- if (highlighter != null && !isSet(Option.DISABLE_HIGHLIGHTER) ++ if (highlighter != null ++ && !isSet(Option.DISABLE_HIGHLIGHTER) + && buffer.length() < getInt(FEATURES_MAX_BUFFER_SIZE, DEFAULT_FEATURES_MAX_BUFFER_SIZE)) { + return highlighter.highlight(this, buffer); + } + return new AttributedString(buffer); + } + +- private AttributedString expandPromptPattern(String pattern, int padToWidth, +- String message, int line) { ++ private AttributedString expandPromptPattern(String pattern, int padToWidth, String message, int line) { + ArrayList parts = new ArrayList<>(); + boolean isHidden = false; + int padPartIndex = -1; +@@ -4065,7 +4146,8 @@ public class LineReaderImpl implements LineReader, Flushable + if (ch == '%' && i < plen) { + int count = 0; + boolean countSeen = false; +- decode: while (true) { ++ decode: ++ while (true) { + ch = pattern.charAt(i++); + switch (ch) { + case '{': +@@ -4073,7 +4155,7 @@ public class LineReaderImpl implements LineReader, Flushable + String str = sb.toString(); + AttributedString astr; + if (!isHidden) { +- astr = AttributedString.fromAnsi(str); ++ astr = fromAnsi(str); + cols += astr.columnLength(); + } else { + astr = new AttributedString(str, AttributedStyle.HIDDEN); +@@ -4096,12 +4178,10 @@ public class LineReaderImpl implements LineReader, Flushable + sb.append(getInt(LINE_OFFSET, 0) + line); + break decode; + case 'M': +- if (message != null) +- sb.append(message); ++ if (message != null) sb.append(message); + break decode; + case 'P': +- if (countSeen && count >= 0) +- padToWidth = count; ++ if (countSeen && count >= 0) padToWidth = count; + if (i < plen) { + padChar = pattern.charAt(i++); + // FIXME check surrogate +@@ -4140,25 +4220,28 @@ public class LineReaderImpl implements LineReader, Flushable + break decode; + } + } +- } else +- sb.append(ch); ++ } else sb.append(ch); + } + if (padToWidth > cols && padToWidth > 0) { + int padCharCols = WCWidth.wcwidth(padChar); + int padCount = (padToWidth - cols) / padCharCols; + sb = padPartString; +- while (--padCount >= 0) +- sb.insert(padPos, (char) padChar); // FIXME if wide +- parts.set(padPartIndex, AttributedString.fromAnsi(sb.toString())); ++ while (--padCount >= 0) sb.insert(padPos, (char) padChar); // FIXME if wide ++ parts.set(padPartIndex, fromAnsi(sb.toString())); + } + return AttributedString.join(null, parts); + } + ++ private AttributedString fromAnsi(String str) { ++ return AttributedString.fromAnsi(str, Collections.singletonList(0), alternateIn, alternateOut); ++ } + -+public class ProcMIPS64Thread implements ThreadProxy { -+ private ProcDebugger debugger; -+ private int id; + private AttributedString insertSecondaryPrompts(AttributedString str, List prompts) { + return insertSecondaryPrompts(str, prompts, true); + } + +- private AttributedString insertSecondaryPrompts(AttributedString strAtt, List prompts, boolean computePrompts) { ++ private AttributedString insertSecondaryPrompts( ++ AttributedString strAtt, List prompts, boolean computePrompts) { + Objects.requireNonNull(prompts); + List lines = strAtt.columnSplitLength(Integer.MAX_VALUE); + AttributedStringBuilder sb = new AttributedStringBuilder(); +@@ -4171,7 +4254,9 @@ public class LineReaderImpl implements LineReader, Flushable + if (computePrompts && secondaryPromptPattern.contains("%P")) { + width = prompt.columnLength(); + if (width > size.getColumns() || prompt.contains('\n')) { +- width = new TerminalLine(prompt.toString(), 0, size.getColumns()).getEndLine().length(); ++ width = new TerminalLine(prompt.toString(), 0, size.getColumns()) ++ .getEndLine() ++ .length(); + } + for (int line = 0; line < lines.size() - 1; line++) { + AttributedString prompt; +@@ -4227,11 +4312,9 @@ public class LineReaderImpl implements LineReader, Flushable + + private AttributedString addRightPrompt(AttributedString prompt, AttributedString line) { + int width = prompt.columnLength(); +- boolean endsWithNl = line.length() > 0 +- && line.charAt(line.length() - 1) == '\n'; ++ boolean endsWithNl = line.length() > 0 && line.charAt(line.length() - 1) == '\n'; + // columnLength counts -1 for the final newline; adjust for that +- int nb = size.getColumns() - width +- - (line.columnLength() + (endsWithNl ? 1 : 0)); ++ int nb = size.getColumns() - width - (line.columnLength() + (endsWithNl ? 1 : 0)); + if (nb >= 3) { + AttributedStringBuilder sb = new AttributedStringBuilder(size.getColumns()); + sb.append(line, 0, endsWithNl ? line.length() - 1 : line.length()); +@@ -4253,8 +4336,8 @@ public class LineReaderImpl implements LineReader, Flushable + + protected boolean insertTab() { + return isSet(Option.INSERT_TAB) +- && getLastBinding().equals("\t") +- && buf.toString().matches("(^|[\\s\\S]*\n)[\r\n\t ]*"); ++ && getLastBinding().equals("\t") ++ && buf.toString().matches("(^|[\\s\\S]*\n)[\r\n\t ]*"); + } + + protected boolean expandHistory() { +@@ -4465,7 +4548,8 @@ public class LineReaderImpl implements LineReader, Flushable + if (op != null) { + String chars = getString(REMOVE_SUFFIX_CHARS, DEFAULT_REMOVE_SUFFIX_CHARS); + String ref = op instanceof Reference ? ((Reference) op).name() : null; +- if (SELF_INSERT.equals(ref) && chars.indexOf(getLastBinding().charAt(0)) >= 0 ++ if (SELF_INSERT.equals(ref) ++ && chars.indexOf(getLastBinding().charAt(0)) >= 0 + || ACCEPT_LINE.equals(ref)) { + buf.backspace(completion.suffix().length()); + if (getLastBinding().charAt(0) != ' ') { +@@ -4533,27 +4617,35 @@ public class LineReaderImpl implements LineReader, Flushable + public String word() { + return line.word(); + } + -+ public ProcMIPS64Thread(ProcDebugger debugger, Address addr) { -+ this.debugger = debugger; + public int wordCursor() { + return line.wordCursor(); + } + -+ // FIXME: the size here should be configurable. However, making it -+ // so would produce a dependency on the "types" package from the -+ // debugger package, which is not desired. -+ this.id = (int) addr.getCIntegerAt(0, 4, true); -+ } + public int wordIndex() { + return line.wordIndex(); + } + -+ public ProcMIPS64Thread(ProcDebugger debugger, long id) { -+ this.debugger = debugger; -+ this.id = (int) id; -+ } + public List words() { + return line.words(); + } + -+ public ThreadContext getContext() throws IllegalThreadStateException { -+ ProcMIPS64ThreadContext context = new ProcMIPS64ThreadContext(debugger); -+ long[] regs = debugger.getThreadIntegerRegisterSet(id); -+ /* -+ _NGREG in reg.h is defined to be 19. Because we have included -+ debug registers MIPS64ThreadContext.NPRGREG is 25. -+ */ + public String line() { + return line.line(); + } + -+ if (Assert.ASSERTS_ENABLED) { -+ Assert.that(regs.length <= MIPS64ThreadContext.NPRGREG, "size of register set is greater than " + MIPS64ThreadContext.NPRGREG); -+ } -+ for (int i = 0; i < regs.length; i++) { -+ context.setRegister(i, regs[i]); -+ } -+ return context; -+ } + public int cursor() { + return line.cursor(); + } + -+ public boolean canSetContext() throws DebuggerException { -+ return false; -+ } + public CharSequence escape(CharSequence candidate, boolean complete) { + return candidate; + } + -+ public void setContext(ThreadContext context) -+ throws IllegalThreadStateException, DebuggerException { -+ throw new DebuggerException("Unimplemented"); -+ } + public int rawWordCursor() { + return wordCursor(); + } + -+ public String toString() { -+ return "t@" + id; -+ } + public int rawWordLength() { + return word().length(); + } +@@ -4564,8 +4656,7 @@ public class LineReaderImpl implements LineReader, Flushable + protected Comparator getCandidateComparator(boolean caseInsensitive, String word) { + String wdi = caseInsensitive ? word.toLowerCase() : word; + ToIntFunction wordDistance = w -> ReaderUtils.distance(wdi, caseInsensitive ? w.toLowerCase() : w); +- return Comparator +- .comparing(Candidate::value, Comparator.comparingInt(wordDistance)) ++ return Comparator.comparing(Candidate::value, Comparator.comparingInt(wordDistance)) + .thenComparing(Comparator.naturalOrder()); + } + +@@ -4577,9 +4668,10 @@ public class LineReaderImpl implements LineReader, Flushable + return getString(ORIGINAL_GROUP_NAME, DEFAULT_ORIGINAL_GROUP_NAME); + } + +- + protected Comparator getGroupComparator() { +- return Comparator.comparingInt(s -> getOthersGroupName().equals(s) ? 1 : getOriginalGroupName().equals(s) ? -1 : 0) ++ return Comparator.comparingInt(s -> getOthersGroupName().equals(s) ++ ? 1 ++ : getOriginalGroupName().equals(s) ? -1 : 0) + .thenComparing(String::toLowerCase, Comparator.naturalOrder()); + } + +@@ -4600,11 +4692,9 @@ public class LineReaderImpl implements LineReader, Flushable + // the same description + candidates.sort(Comparator.comparing(Candidate::value)); + Candidate first = candidates.get(0); +- String disp = candidates.stream() +- .map(Candidate::displ) +- .collect(Collectors.joining(" ")); +- possible.add(new Candidate(first.value(), disp, first.group(), +- first.descr(), first.suffix(), null, first.complete())); ++ String disp = candidates.stream().map(Candidate::displ).collect(Collectors.joining(" ")); ++ possible.add(new Candidate( ++ first.value(), disp, first.group(), first.descr(), first.suffix(), null, first.complete())); + } + } + } +@@ -4636,8 +4726,10 @@ public class LineReaderImpl implements LineReader, Flushable + } + + private int promptLines() { +- AttributedString text = insertSecondaryPrompts(AttributedStringBuilder.append(prompt, buf.toString()), new ArrayList<>()); +- return text.columnSplitLength(size.getColumns(), false, display.delayLineWrap()).size(); ++ AttributedString text = ++ insertSecondaryPrompts(AttributedStringBuilder.append(prompt, buf.toString()), new ArrayList<>()); ++ return text.columnSplitLength(size.getColumns(), false, display.delayLineWrap()) ++ .size(); + } + + private class MenuSupport implements Supplier { +@@ -4651,7 +4743,8 @@ public class LineReaderImpl implements LineReader, Flushable + int columns; + String completed; + +- public MenuSupport(List original, String completed, BiFunction escaper) { ++ public MenuSupport( ++ List original, String completed, BiFunction escaper) { + this.possible = new ArrayList<>(); + this.escaper = escaper; + this.selection = -1; +@@ -4714,7 +4807,7 @@ public class LineReaderImpl implements LineReader, Flushable + if (selection - row + axis > options) { + // selection is the last row/column + // so there are fewer options than other rows +- axis = options%axis; ++ axis = options % axis; + } + selection = selection - row + ((axis + row + step) % axis); + update(); +@@ -4772,7 +4865,9 @@ public class LineReaderImpl implements LineReader, Flushable + AttributedString post = pr.post; + if (post.length() > 0 && post.charAt(post.length() - 1) != '\n') { + post = new AttributedStringBuilder(post.length() + 1) +- .append(post).append("\n").toAttributedString(); ++ .append(post) ++ .append("\n") ++ .toAttributedString(); + } + List lines = post.columnSplitLength(size.getColumns(), true, display.delayLineWrap()); + List sub = new ArrayList<>(lines.subList(topLine, topLine + displayed)); +@@ -4785,7 +4880,8 @@ public class LineReaderImpl implements LineReader, Flushable + .append(" of ") + .append(Integer.toString(lines.size())) + .append("\n") +- .style(AttributedStyle.DEFAULT).toAttributedString()); ++ .style(AttributedStyle.DEFAULT) ++ .toAttributedString()); + computed = AttributedString.join(AttributedString.EMPTY, sub); + } else { + computed = pr.post; +@@ -4798,10 +4894,10 @@ public class LineReaderImpl implements LineReader, Flushable + public AttributedString get() { + return computed; + } +- + } + +- protected boolean doMenu(List original, String completed, BiFunction escaper) { ++ protected boolean doMenu( ++ List original, String completed, BiFunction escaper) { + // Reorder candidates according to display order + final List possible = new ArrayList<>(); + boolean caseInsensitive = isSet(Option.CASE_INSENSITIVE); +@@ -4854,7 +4950,7 @@ public class LineReaderImpl implements LineReader, Flushable + if (completion.suffix() != null) { + String chars = getString(REMOVE_SUFFIX_CHARS, DEFAULT_REMOVE_SUFFIX_CHARS); + if (SELF_INSERT.equals(ref) +- && chars.indexOf(getLastBinding().charAt(0)) >= 0 ++ && chars.indexOf(getLastBinding().charAt(0)) >= 0 + || BACKWARD_DELETE_CHAR.equals(ref)) { + buf.backspace(completion.suffix().length()); + } +@@ -4866,8 +4962,8 @@ public class LineReaderImpl implements LineReader, Flushable + } + if (!ACCEPT_LINE.equals(ref) + && !(SELF_INSERT.equals(ref) +- && completion.suffix() != null +- && completion.suffix().startsWith(getLastBinding()))) { ++ && completion.suffix() != null ++ && completion.suffix().startsWith(getLastBinding()))) { + pushBackBinding(true); + } + post = null; +@@ -4888,29 +4984,40 @@ public class LineReaderImpl implements LineReader, Flushable + return doList(new ArrayList<>(), "", false, null, false); + } + +- protected boolean doList(List possible +- , String completed, boolean runLoop, BiFunction escaper) { ++ protected boolean doList( ++ List possible, ++ String completed, ++ boolean runLoop, ++ BiFunction escaper) { + return doList(possible, completed, runLoop, escaper, false); + } + +- protected boolean doList(List possible +- , String completed +- , boolean runLoop, BiFunction escaper, boolean forSuggestion) { ++ protected boolean doList( ++ List possible, ++ String completed, ++ boolean runLoop, ++ BiFunction escaper, ++ boolean forSuggestion) { + // If we list only and if there's a big + // number of items, we should ask the user + // for confirmation, display the list + // and redraw the line at the bottom + mergeCandidates(possible); +- AttributedString text = insertSecondaryPrompts(AttributedStringBuilder.append(prompt, buf.toString()), new ArrayList<>()); +- int promptLines = text.columnSplitLength(size.getColumns(), false, display.delayLineWrap()).size(); ++ AttributedString text = ++ insertSecondaryPrompts(AttributedStringBuilder.append(prompt, buf.toString()), new ArrayList<>()); ++ int promptLines = text.columnSplitLength(size.getColumns(), false, display.delayLineWrap()) ++ .size(); + PostResult postResult = computePost(possible, null, null, completed); + int lines = postResult.lines; + int listMax = getInt(LIST_MAX, DEFAULT_LIST_MAX); +- if (listMax > 0 && possible.size() >= listMax +- || lines >= size.getRows() - promptLines) { ++ int possibleSize = possible.size(); ++ if (possibleSize == 0 || size.getRows() == 0) { ++ return false; ++ } ++ if (listMax > 0 && possibleSize >= listMax || lines >= size.getRows() - promptLines) { + if (!forSuggestion) { + // prompt +- post = () -> new AttributedString(getAppName() + ": do you wish to see all " + possible.size() ++ post = () -> new AttributedString(getAppName() + ": do you wish to see all " + possibleSize + + " possibilities (" + lines + " lines)?"); + redisplay(true); + int c = readCharacter(); +@@ -4930,8 +5037,7 @@ public class LineReaderImpl implements LineReader, Flushable + String current = completed + sb.toString(); + List cands; + if (sb.length() > 0) { +- completionMatcher.compile(options, false, new CompletingWord(current), caseInsensitive, 0 +- , null); ++ completionMatcher.compile(options, false, new CompletingWord(current), caseInsensitive, 0, null); + cands = completionMatcher.matches(possible).stream() + .sorted(getCandidateComparator(caseInsensitive, current)) + .collect(Collectors.toList()); +@@ -4944,8 +5050,10 @@ public class LineReaderImpl implements LineReader, Flushable + candidateStartPosition = candidateStartPosition(cands); + } + post = () -> { +- AttributedString t = insertSecondaryPrompts(AttributedStringBuilder.append(prompt, buf.toString()), new ArrayList<>()); +- int pl = t.columnSplitLength(size.getColumns(), false, display.delayLineWrap()).size(); ++ AttributedString t = insertSecondaryPrompts( ++ AttributedStringBuilder.append(prompt, buf.toString()), new ArrayList<>()); ++ int pl = t.columnSplitLength(size.getColumns(), false, display.delayLineWrap()) ++ .size(); + PostResult pr = computePost(cands, null, null, current); + if (pr.lines >= size.getRows() - pl) { + post = null; +@@ -4954,7 +5062,8 @@ public class LineReaderImpl implements LineReader, Flushable + redisplay(false); + buf.cursor(oldCursor); + println(); +- List ls = pr.post.columnSplitLength(size.getColumns(), false, display.delayLineWrap()); ++ List ls = ++ pr.post.columnSplitLength(size.getColumns(), false, display.delayLineWrap()); + Display d = new Display(terminal, false); + d.resize(size.getRows(), size.getColumns()); + d.update(ls, -1); +@@ -5074,25 +5183,41 @@ public class LineReaderImpl implements LineReader, Flushable + } + } + +- protected PostResult computePost(List possible, Candidate selection, List ordered, String completed) { +- return computePost(possible, selection, ordered, completed, display::wcwidth, size.getColumns(), isSet(Option.AUTO_GROUP), isSet(Option.GROUP), isSet(Option.LIST_ROWS_FIRST)); +- } +- +- protected PostResult computePost(List possible, Candidate selection, List ordered, String completed, Function wcwidth, int width, boolean autoGroup, boolean groupName, boolean rowsFirst) { ++ protected PostResult computePost( ++ List possible, Candidate selection, List ordered, String completed) { ++ return computePost( ++ possible, ++ selection, ++ ordered, ++ completed, ++ display::wcwidth, ++ size.getColumns(), ++ isSet(Option.AUTO_GROUP), ++ isSet(Option.GROUP), ++ isSet(Option.LIST_ROWS_FIRST)); ++ } ++ ++ protected PostResult computePost( ++ List possible, ++ Candidate selection, ++ List ordered, ++ String completed, ++ Function wcwidth, ++ int width, ++ boolean autoGroup, ++ boolean groupName, ++ boolean rowsFirst) { + List strings = new ArrayList<>(); +- boolean customOrder = possible.stream().anyMatch(c -> c.sort() != 0); + if (groupName) { + Comparator groupComparator = getGroupComparator(); +- Map> sorted; +- sorted = groupComparator != null +- ? new TreeMap<>(groupComparator) +- : new LinkedHashMap<>(); ++ Map> sorted; ++ sorted = groupComparator != null ? new TreeMap<>(groupComparator) : new LinkedHashMap<>(); + for (Candidate cand : possible) { + String group = cand.group(); +- sorted.computeIfAbsent(group != null ? group : "", s -> new LinkedHashMap<>()) +- .put((customOrder ? cand.sort() : cand.value()), cand); ++ sorted.computeIfAbsent(group != null ? group : "", s -> new ArrayList<>()) ++ .add(cand); + } +- for (Map.Entry> entry : sorted.entrySet()) { ++ for (Map.Entry> entry : sorted.entrySet()) { + String group = entry.getKey(); + if (group.isEmpty() && sorted.size() > 1) { + group = getOthersGroupName(); +@@ -5100,27 +5225,30 @@ public class LineReaderImpl implements LineReader, Flushable + if (!group.isEmpty() && autoGroup) { + strings.add(group); + } +- strings.add(new ArrayList<>(entry.getValue().values())); ++ List candidates = entry.getValue(); ++ Collections.sort(candidates); ++ strings.add(candidates); + if (ordered != null) { +- ordered.addAll(entry.getValue().values()); ++ ordered.addAll(candidates); + } + } + } else { + Set groups = new LinkedHashSet<>(); +- TreeMap sorted = new TreeMap<>(); ++ List sorted = new ArrayList<>(); + for (Candidate cand : possible) { + String group = cand.group(); + if (group != null) { + groups.add(group); + } +- sorted.put((customOrder ? cand.sort() : cand.value()), cand); ++ sorted.add(cand); + } + if (autoGroup) { + strings.addAll(groups); + } +- strings.add(new ArrayList<>(sorted.values())); ++ Collections.sort(sorted); ++ strings.add(sorted); + if (ordered != null) { +- ordered.addAll(sorted.values()); ++ ordered.addAll(sorted); + } + } + return toColumns(strings, selection, completed, wcwidth, width, rowsFirst); +@@ -5163,12 +5291,15 @@ public class LineReaderImpl implements LineReader, Flushable + } + + private int candidateStartPosition(List cands) { +- List values = cands.stream().map(c -> AttributedString.stripAnsi(c.displ())) +- .filter(c -> !c.matches("\\w+") && c.length() > 1).collect(Collectors.toList()); ++ List values = cands.stream() ++ .map(c -> AttributedString.stripAnsi(c.displ())) ++ .filter(c -> !c.matches("\\w+") && c.length() > 1) ++ .collect(Collectors.toList()); + Set notDelimiters = new HashSet<>(); +- values.forEach(v -> v.substring(0, v.length() - 1).chars() ++ values.forEach(v -> v.substring(0, v.length() - 1) ++ .chars() + .filter(c -> !Character.isDigit(c) && !Character.isAlphabetic(c)) +- .forEach(c -> notDelimiters.add(Character.toString((char)c)))); ++ .forEach(c -> notDelimiters.add(Character.toString((char) c)))); + int width = size.getColumns(); + int promptLength = prompt != null ? prompt.length() : 0; + if (promptLength > 0) { +@@ -5179,8 +5310,7 @@ public class LineReaderImpl implements LineReader, Flushable + int out = tl.getStartPos(); + String buffer = tl.getEndLine(); + for (int i = buffer.length(); i > 0; i--) { +- if (buffer.substring(0, i).matches(".*\\W") +- && !notDelimiters.contains(buffer.substring(i - 1, i))) { ++ if (buffer.substring(0, i).matches(".*\\W") && !notDelimiters.contains(buffer.substring(i - 1, i))) { + out += i; + break; + } +@@ -5189,7 +5319,13 @@ public class LineReaderImpl implements LineReader, Flushable + } + + @SuppressWarnings("unchecked") +- protected PostResult toColumns(List items, Candidate selection, String completed, Function wcwidth, int width, boolean rowsFirst) { ++ protected PostResult toColumns( ++ List items, ++ Candidate selection, ++ String completed, ++ Function wcwidth, ++ int width, ++ boolean rowsFirst) { + int[] out = new int[2]; + // TODO: support Option.LIST_PACKED + // Compute column width +@@ -5199,8 +5335,7 @@ public class LineReaderImpl implements LineReader, Flushable + if (item instanceof String) { + int len = wcwidth.apply((String) item); + maxWidth = Math.max(maxWidth, len); +- } +- else if (item instanceof List) { ++ } else if (item instanceof List) { + for (Candidate cand : (List) item) { + listSize++; + int len = wcwidth.apply(cand.displ()); +@@ -5218,7 +5353,10 @@ public class LineReaderImpl implements LineReader, Flushable + AttributedStringBuilder sb = new AttributedStringBuilder(); + if (listSize > 0) { + if (isSet(Option.AUTO_MENU_LIST) +- && listSize < Math.min(getInt(MENU_LIST_MAX, DEFAULT_MENU_LIST_MAX), visibleDisplayRows() - promptLines())) { ++ && listSize ++ < Math.min( ++ getInt(MENU_LIST_MAX, DEFAULT_MENU_LIST_MAX), ++ visibleDisplayRows() - promptLines())) { + maxWidth = Math.max(maxWidth, MENU_LIST_WIDTH); + sb.tabs(Math.max(Math.min(candidateStartPosition, width - maxWidth - 1), 1)); + width = maxWidth + 2; +@@ -5251,8 +5389,16 @@ public class LineReaderImpl implements LineReader, Flushable + } + + @SuppressWarnings("unchecked") +- protected void toColumns(Object items, int width, int maxWidth, AttributedStringBuilder sb, Candidate selection, String completed +- , boolean rowsFirst, boolean doMenuList, int[] out) { ++ protected void toColumns( ++ Object items, ++ int width, ++ int maxWidth, ++ AttributedStringBuilder sb, ++ Candidate selection, ++ String completed, ++ boolean rowsFirst, ++ boolean doMenuList, ++ int[] out) { + if (maxWidth <= 0 || width <= 0) { + return; + } +@@ -5305,18 +5451,20 @@ public class LineReaderImpl implements LineReader, Flushable + if (idx < candidates.size()) { + Candidate cand = candidates.get(idx); + boolean hasRightItem = j < columns - 1 && index.applyAsInt(i, j + 1) < candidates.size(); +- AttributedString left = AttributedString.fromAnsi(cand.displ()); +- AttributedString right = AttributedString.fromAnsi(cand.descr()); ++ AttributedString left = fromAnsi(cand.displ()); ++ AttributedString right = fromAnsi(cand.descr()); + int lw = left.columnLength(); + int rw = 0; + if (right != null) { +- int rem = maxWidth - (lw + MARGIN_BETWEEN_DISPLAY_AND_DESC +- + DESC_PREFIX.length() + DESC_SUFFIX.length()); ++ int rem = maxWidth ++ - (lw ++ + MARGIN_BETWEEN_DISPLAY_AND_DESC ++ + DESC_PREFIX.length() ++ + DESC_SUFFIX.length()); + rw = right.columnLength(); + if (rw > rem) { + right = AttributedStringBuilder.append( +- right.columnSubSequence(0, rem - WCWidth.wcwidth('\u2026')), +- "\u2026"); ++ right.columnSubSequence(0, rem - WCWidth.wcwidth('\u2026')), "\u2026"); + rw = right.columnLength(); + } + right = AttributedStringBuilder.append(DESC_PREFIX, right, DESC_SUFFIX); +@@ -5325,8 +5473,9 @@ public class LineReaderImpl implements LineReader, Flushable + if (cand == selection) { + out[1] = i; + asb.style(getCompletionStyleSelection(doMenuList)); +- if (left.toString().regionMatches( +- isSet(Option.CASE_INSENSITIVE), 0, completed, 0, completed.length())) { ++ if (left.toString() ++ .regionMatches( ++ isSet(Option.CASE_INSENSITIVE), 0, completed, 0, completed.length())) { + asb.append(left.toString(), 0, completed.length()); + asb.append(left.toString(), completed.length(), left.length()); + } else { +@@ -5340,8 +5489,9 @@ public class LineReaderImpl implements LineReader, Flushable + } + asb.style(AttributedStyle.DEFAULT); + } else { +- if (left.toString().regionMatches( +- isSet(Option.CASE_INSENSITIVE), 0, completed, 0, completed.length())) { ++ if (left.toString() ++ .regionMatches( ++ isSet(Option.CASE_INSENSITIVE), 0, completed, 0, completed.length())) { + asb.style(getCompletionStyleStarting(doMenuList)); + asb.append(left, 0, completed.length()); + asb.style(AttributedStyle.DEFAULT); +@@ -5447,7 +5597,7 @@ public class LineReaderImpl implements LineReader, Flushable + } + + protected AttributedStyle buildStyle(String str) { +- return AttributedString.fromAnsi("\u001b[" + str + "m ").styleAt(0); ++ return fromAnsi("\u001b[" + str + "m ").styleAt(0); + } + + /** +@@ -5477,14 +5627,14 @@ public class LineReaderImpl implements LineReader, Flushable + } + if (next && !history.next()) { + return false; +- } +- else if (!next && !history.previous()) { ++ } else if (!next && !history.previous()) { + return false; + } + +- setBuffer(modifiedHistory.containsKey(history.index()) +- ? modifiedHistory.get(history.index()) +- : history.current()); ++ setBuffer( ++ modifiedHistory.containsKey(history.index()) ++ ? modifiedHistory.get(history.index()) ++ : history.current()); + + return true; + } +@@ -5515,7 +5665,6 @@ public class LineReaderImpl implements LineReader, Flushable + redrawLine(); + } + +- + // + // Actions + // +@@ -5725,8 +5874,7 @@ public class LineReaderImpl implements LineReader, Flushable + + public boolean mouse() { + MouseEvent event = readMouseEvent(); +- if (event.getType() == MouseEvent.Type.Released +- && event.getButton() == MouseEvent.Button.Button1) { ++ if (event.getType() == MouseEvent.Type.Released && event.getButton() == MouseEvent.Button.Button1) { + StringBuilder tsb = new StringBuilder(); + Cursor cursor = terminal.getCursorPosition(c -> tsb.append((char) c)); + bindingReader.runMacro(tsb.toString()); +@@ -5734,15 +5882,20 @@ public class LineReaderImpl implements LineReader, Flushable + List secondaryPrompts = new ArrayList<>(); + getDisplayedBufferWithPrompts(secondaryPrompts); + +- AttributedStringBuilder sb = new AttributedStringBuilder().tabs(TAB_WIDTH); ++ AttributedStringBuilder sb = new AttributedStringBuilder().tabs(getTabWidth()); + sb.append(prompt); + sb.append(insertSecondaryPrompts(new AttributedString(buf.upToCursor()), secondaryPrompts, false)); +- List promptLines = sb.columnSplitLength(size.getColumns(), false, display.delayLineWrap()); ++ List promptLines = ++ sb.columnSplitLength(size.getColumns(), false, display.delayLineWrap()); + + int currentLine = promptLines.size() - 1; + int wantedLine = Math.max(0, Math.min(currentLine + event.getY() - cursor.getY(), secondaryPrompts.size())); +- int pl0 = currentLine == 0 ? prompt.columnLength() : secondaryPrompts.get(currentLine - 1).columnLength(); +- int pl1 = wantedLine == 0 ? prompt.columnLength() : secondaryPrompts.get(wantedLine - 1).columnLength(); ++ int pl0 = currentLine == 0 ++ ? prompt.columnLength() ++ : secondaryPrompts.get(currentLine - 1).columnLength(); ++ int pl1 = wantedLine == 0 ++ ? prompt.columnLength() ++ : secondaryPrompts.get(wantedLine - 1).columnLength(); + int adjust = pl1 - pl0; + buf.moveXY(event.getX() - cursor.getX() - adjust, event.getY() - cursor.getY()); + } +@@ -5814,13 +5967,11 @@ public class LineReaderImpl implements LineReader, Flushable + bell_preference = BellType.VISIBLE; + break; + case "on": +- bell_preference = getBoolean(PREFER_VISIBLE_BELL, false) +- ? BellType.VISIBLE : BellType.AUDIBLE; ++ bell_preference = getBoolean(PREFER_VISIBLE_BELL, false) ? BellType.VISIBLE : BellType.AUDIBLE; + break; + } + if (bell_preference == BellType.VISIBLE) { +- if (terminal.puts(Capability.flash_screen) +- || terminal.puts(Capability.bell)) { ++ if (terminal.puts(Capability.flash_screen) || terminal.puts(Capability.bell)) { + flush(); + } + } else if (bell_preference == BellType.AUDIBLE) { +@@ -5869,8 +6020,7 @@ public class LineReaderImpl implements LineReader, Flushable + + protected boolean isWord(int c) { + String wordchars = getString(WORDCHARS, DEFAULT_WORDCHARS); +- return Character.isLetterOrDigit(c) +- || (c < 128 && wordchars.indexOf((char) c) >= 0); ++ return Character.isLetterOrDigit(c) || (c < 128 && wordchars.indexOf((char) c) >= 0); + } + + String getString(String name, String def) { +@@ -5899,6 +6049,8 @@ public class LineReaderImpl implements LineReader, Flushable + keyMaps.put(VIOPP, viOpp()); + keyMaps.put(VISUAL, visual()); + keyMaps.put(SAFE, safe()); ++ keyMaps.put(DUMB, dumb()); ++ + if (getBoolean(BIND_TTY_SPECIAL_CHARS, true)) { + Attributes attr = terminal.getAttributes(); + bindConsoleChars(keyMaps.get(EMACS), attr); +@@ -5909,240 +6061,241 @@ public class LineReaderImpl implements LineReader, Flushable + keyMap.setUnicode(new Reference(SELF_INSERT)); + keyMap.setAmbiguousTimeout(getLong(AMBIGUOUS_BINDING, DEFAULT_AMBIGUOUS_BINDING)); + } +- // By default, link main to emacs +- keyMaps.put(MAIN, keyMaps.get(EMACS)); ++ // By default, link main to emacs unless the temrinal is dumb ++ keyMaps.put(MAIN, keyMaps.get(isTerminalDumb() ? DUMB : EMACS)); + -+ public boolean equals(Object obj) { -+ if ((obj == null) || !(obj instanceof ProcMIPS64Thread)) { -+ return false; -+ } + return keyMaps; + } + + public KeyMap emacs() { + KeyMap emacs = new KeyMap<>(); + bindKeys(emacs); +- bind(emacs, SET_MARK_COMMAND, ctrl('@')); +- bind(emacs, BEGINNING_OF_LINE, ctrl('A')); +- bind(emacs, BACKWARD_CHAR, ctrl('B')); +- bind(emacs, DELETE_CHAR_OR_LIST, ctrl('D')); +- bind(emacs, END_OF_LINE, ctrl('E')); +- bind(emacs, FORWARD_CHAR, ctrl('F')); +- bind(emacs, SEND_BREAK, ctrl('G')); +- bind(emacs, BACKWARD_DELETE_CHAR, ctrl('H')); +- bind(emacs, EXPAND_OR_COMPLETE, ctrl('I')); +- bind(emacs, ACCEPT_LINE, ctrl('J')); +- bind(emacs, KILL_LINE, ctrl('K')); +- bind(emacs, CLEAR_SCREEN, ctrl('L')); +- bind(emacs, ACCEPT_LINE, ctrl('M')); +- bind(emacs, DOWN_LINE_OR_HISTORY, ctrl('N')); +- bind(emacs, ACCEPT_LINE_AND_DOWN_HISTORY, ctrl('O')); +- bind(emacs, UP_LINE_OR_HISTORY, ctrl('P')); +- bind(emacs, HISTORY_INCREMENTAL_SEARCH_BACKWARD, ctrl('R')); +- bind(emacs, HISTORY_INCREMENTAL_SEARCH_FORWARD, ctrl('S')); +- bind(emacs, TRANSPOSE_CHARS, ctrl('T')); +- bind(emacs, KILL_WHOLE_LINE, ctrl('U')); +- bind(emacs, QUOTED_INSERT, ctrl('V')); +- bind(emacs, BACKWARD_KILL_WORD, ctrl('W')); +- bind(emacs, YANK, ctrl('Y')); +- bind(emacs, CHARACTER_SEARCH, ctrl(']')); +- bind(emacs, UNDO, ctrl('_')); +- bind(emacs, SELF_INSERT, range(" -~")); +- bind(emacs, INSERT_CLOSE_PAREN, ")"); +- bind(emacs, INSERT_CLOSE_SQUARE, "]"); +- bind(emacs, INSERT_CLOSE_CURLY, "}"); +- bind(emacs, BACKWARD_DELETE_CHAR, del()); +- bind(emacs, VI_MATCH_BRACKET, translate("^X^B")); +- bind(emacs, SEND_BREAK, translate("^X^G")); +- bind(emacs, EDIT_AND_EXECUTE_COMMAND, translate("^X^E")); +- bind(emacs, VI_FIND_NEXT_CHAR, translate("^X^F")); +- bind(emacs, VI_JOIN, translate("^X^J")); +- bind(emacs, KILL_BUFFER, translate("^X^K")); +- bind(emacs, INFER_NEXT_HISTORY, translate("^X^N")); +- bind(emacs, OVERWRITE_MODE, translate("^X^O")); +- bind(emacs, REDO, translate("^X^R")); +- bind(emacs, UNDO, translate("^X^U")); +- bind(emacs, VI_CMD_MODE, translate("^X^V")); +- bind(emacs, EXCHANGE_POINT_AND_MARK, translate("^X^X")); +- bind(emacs, DO_LOWERCASE_VERSION, translate("^XA-^XZ")); +- bind(emacs, WHAT_CURSOR_POSITION, translate("^X=")); +- bind(emacs, KILL_LINE, translate("^X^?")); +- bind(emacs, SEND_BREAK, alt(ctrl('G'))); +- bind(emacs, BACKWARD_KILL_WORD, alt(ctrl('H'))); +- bind(emacs, SELF_INSERT_UNMETA, alt(ctrl('M'))); +- bind(emacs, COMPLETE_WORD, alt(esc())); +- bind(emacs, CHARACTER_SEARCH_BACKWARD, alt(ctrl(']'))); +- bind(emacs, COPY_PREV_WORD, alt(ctrl('_'))); +- bind(emacs, SET_MARK_COMMAND, alt(' ')); +- bind(emacs, NEG_ARGUMENT, alt('-')); +- bind(emacs, DIGIT_ARGUMENT, range("\\E0-\\E9")); +- bind(emacs, BEGINNING_OF_HISTORY, alt('<')); +- bind(emacs, LIST_CHOICES, alt('=')); +- bind(emacs, END_OF_HISTORY, alt('>')); +- bind(emacs, LIST_CHOICES, alt('?')); +- bind(emacs, DO_LOWERCASE_VERSION, range("^[A-^[Z")); +- bind(emacs, ACCEPT_AND_HOLD, alt('a')); +- bind(emacs, BACKWARD_WORD, alt('b')); +- bind(emacs, CAPITALIZE_WORD, alt('c')); +- bind(emacs, KILL_WORD, alt('d')); +- bind(emacs, KILL_WORD, translate("^[[3;5~")); // ctrl-delete +- bind(emacs, FORWARD_WORD, alt('f')); +- bind(emacs, DOWN_CASE_WORD, alt('l')); +- bind(emacs, HISTORY_SEARCH_FORWARD, alt('n')); +- bind(emacs, HISTORY_SEARCH_BACKWARD, alt('p')); +- bind(emacs, TRANSPOSE_WORDS, alt('t')); +- bind(emacs, UP_CASE_WORD, alt('u')); +- bind(emacs, YANK_POP, alt('y')); +- bind(emacs, BACKWARD_KILL_WORD, alt(del())); ++ bind(emacs, SET_MARK_COMMAND, ctrl('@')); ++ bind(emacs, BEGINNING_OF_LINE, ctrl('A')); ++ bind(emacs, BACKWARD_CHAR, ctrl('B')); ++ bind(emacs, DELETE_CHAR_OR_LIST, ctrl('D')); ++ bind(emacs, END_OF_LINE, ctrl('E')); ++ bind(emacs, FORWARD_CHAR, ctrl('F')); ++ bind(emacs, SEND_BREAK, ctrl('G')); ++ bind(emacs, BACKWARD_DELETE_CHAR, ctrl('H')); ++ bind(emacs, EXPAND_OR_COMPLETE, ctrl('I')); ++ bind(emacs, ACCEPT_LINE, ctrl('J')); ++ bind(emacs, KILL_LINE, ctrl('K')); ++ bind(emacs, CLEAR_SCREEN, ctrl('L')); ++ bind(emacs, ACCEPT_LINE, ctrl('M')); ++ bind(emacs, DOWN_LINE_OR_HISTORY, ctrl('N')); ++ bind(emacs, ACCEPT_LINE_AND_DOWN_HISTORY, ctrl('O')); ++ bind(emacs, UP_LINE_OR_HISTORY, ctrl('P')); ++ bind(emacs, HISTORY_INCREMENTAL_SEARCH_BACKWARD, ctrl('R')); ++ bind(emacs, HISTORY_INCREMENTAL_SEARCH_FORWARD, ctrl('S')); ++ bind(emacs, TRANSPOSE_CHARS, ctrl('T')); ++ bind(emacs, KILL_WHOLE_LINE, ctrl('U')); ++ bind(emacs, QUOTED_INSERT, ctrl('V')); ++ bind(emacs, BACKWARD_KILL_WORD, ctrl('W')); ++ bind(emacs, YANK, ctrl('Y')); ++ bind(emacs, CHARACTER_SEARCH, ctrl(']')); ++ bind(emacs, UNDO, ctrl('_')); ++ bind(emacs, SELF_INSERT, range(" -~")); ++ bind(emacs, INSERT_CLOSE_PAREN, ")"); ++ bind(emacs, INSERT_CLOSE_SQUARE, "]"); ++ bind(emacs, INSERT_CLOSE_CURLY, "}"); ++ bind(emacs, BACKWARD_DELETE_CHAR, del()); ++ bind(emacs, VI_MATCH_BRACKET, translate("^X^B")); ++ bind(emacs, SEND_BREAK, translate("^X^G")); ++ bind(emacs, EDIT_AND_EXECUTE_COMMAND, translate("^X^E")); ++ bind(emacs, VI_FIND_NEXT_CHAR, translate("^X^F")); ++ bind(emacs, VI_JOIN, translate("^X^J")); ++ bind(emacs, KILL_BUFFER, translate("^X^K")); ++ bind(emacs, INFER_NEXT_HISTORY, translate("^X^N")); ++ bind(emacs, OVERWRITE_MODE, translate("^X^O")); ++ bind(emacs, REDO, translate("^X^R")); ++ bind(emacs, UNDO, translate("^X^U")); ++ bind(emacs, VI_CMD_MODE, translate("^X^V")); ++ bind(emacs, EXCHANGE_POINT_AND_MARK, translate("^X^X")); ++ bind(emacs, DO_LOWERCASE_VERSION, translate("^XA-^XZ")); ++ bind(emacs, WHAT_CURSOR_POSITION, translate("^X=")); ++ bind(emacs, KILL_LINE, translate("^X^?")); ++ bind(emacs, SEND_BREAK, alt(ctrl('G'))); ++ bind(emacs, BACKWARD_KILL_WORD, alt(ctrl('H'))); ++ bind(emacs, SELF_INSERT_UNMETA, alt(ctrl('M'))); ++ bind(emacs, COMPLETE_WORD, alt(esc())); ++ bind(emacs, CHARACTER_SEARCH_BACKWARD, alt(ctrl(']'))); ++ bind(emacs, COPY_PREV_WORD, alt(ctrl('_'))); ++ bind(emacs, SET_MARK_COMMAND, alt(' ')); ++ bind(emacs, NEG_ARGUMENT, alt('-')); ++ bind(emacs, DIGIT_ARGUMENT, range("\\E0-\\E9")); ++ bind(emacs, BEGINNING_OF_HISTORY, alt('<')); ++ bind(emacs, LIST_CHOICES, alt('=')); ++ bind(emacs, END_OF_HISTORY, alt('>')); ++ bind(emacs, LIST_CHOICES, alt('?')); ++ bind(emacs, DO_LOWERCASE_VERSION, range("^[A-^[Z")); ++ bind(emacs, ACCEPT_AND_HOLD, alt('a')); ++ bind(emacs, BACKWARD_WORD, alt('b')); ++ bind(emacs, CAPITALIZE_WORD, alt('c')); ++ bind(emacs, KILL_WORD, alt('d')); ++ bind(emacs, KILL_WORD, translate("^[[3;5~")); // ctrl-delete ++ bind(emacs, FORWARD_WORD, alt('f')); ++ bind(emacs, DOWN_CASE_WORD, alt('l')); ++ bind(emacs, HISTORY_SEARCH_FORWARD, alt('n')); ++ bind(emacs, HISTORY_SEARCH_BACKWARD, alt('p')); ++ bind(emacs, TRANSPOSE_WORDS, alt('t')); ++ bind(emacs, UP_CASE_WORD, alt('u')); ++ bind(emacs, YANK_POP, alt('y')); ++ bind(emacs, BACKWARD_KILL_WORD, alt(del())); + bindArrowKeys(emacs); +- bind(emacs, FORWARD_WORD, translate("^[[1;5C")); // ctrl-left +- bind(emacs, BACKWARD_WORD, translate("^[[1;5D")); // ctrl-right +- bind(emacs, FORWARD_WORD, alt(key(Capability.key_right))); +- bind(emacs, BACKWARD_WORD, alt(key(Capability.key_left))); +- bind(emacs, FORWARD_WORD, alt(translate("^[[C"))); +- bind(emacs, BACKWARD_WORD, alt(translate("^[[D"))); ++ bind(emacs, FORWARD_WORD, translate("^[[1;5C")); // ctrl-left ++ bind(emacs, BACKWARD_WORD, translate("^[[1;5D")); // ctrl-right ++ bind(emacs, FORWARD_WORD, alt(key(Capability.key_right))); ++ bind(emacs, BACKWARD_WORD, alt(key(Capability.key_left))); ++ bind(emacs, FORWARD_WORD, alt(translate("^[[C"))); ++ bind(emacs, BACKWARD_WORD, alt(translate("^[[D"))); + return emacs; + } + + public KeyMap viInsertion() { + KeyMap viins = new KeyMap<>(); + bindKeys(viins); +- bind(viins, SELF_INSERT, range("^@-^_")); +- bind(viins, LIST_CHOICES, ctrl('D')); +- bind(viins, SEND_BREAK, ctrl('G')); +- bind(viins, BACKWARD_DELETE_CHAR, ctrl('H')); +- bind(viins, EXPAND_OR_COMPLETE, ctrl('I')); +- bind(viins, ACCEPT_LINE, ctrl('J')); +- bind(viins, CLEAR_SCREEN, ctrl('L')); +- bind(viins, ACCEPT_LINE, ctrl('M')); +- bind(viins, MENU_COMPLETE, ctrl('N')); +- bind(viins, REVERSE_MENU_COMPLETE, ctrl('P')); +- bind(viins, HISTORY_INCREMENTAL_SEARCH_BACKWARD, ctrl('R')); +- bind(viins, HISTORY_INCREMENTAL_SEARCH_FORWARD, ctrl('S')); +- bind(viins, TRANSPOSE_CHARS, ctrl('T')); +- bind(viins, KILL_WHOLE_LINE, ctrl('U')); +- bind(viins, QUOTED_INSERT, ctrl('V')); +- bind(viins, BACKWARD_KILL_WORD, ctrl('W')); +- bind(viins, YANK, ctrl('Y')); +- bind(viins, VI_CMD_MODE, ctrl('[')); +- bind(viins, UNDO, ctrl('_')); +- bind(viins, HISTORY_INCREMENTAL_SEARCH_BACKWARD, ctrl('X') + "r"); +- bind(viins, HISTORY_INCREMENTAL_SEARCH_FORWARD, ctrl('X') + "s"); +- bind(viins, SELF_INSERT, range(" -~")); +- bind(viins, INSERT_CLOSE_PAREN, ")"); +- bind(viins, INSERT_CLOSE_SQUARE, "]"); +- bind(viins, INSERT_CLOSE_CURLY, "}"); +- bind(viins, BACKWARD_DELETE_CHAR, del()); ++ bind(viins, SELF_INSERT, range("^@-^_")); ++ bind(viins, LIST_CHOICES, ctrl('D')); ++ bind(viins, SEND_BREAK, ctrl('G')); ++ bind(viins, BACKWARD_DELETE_CHAR, ctrl('H')); ++ bind(viins, EXPAND_OR_COMPLETE, ctrl('I')); ++ bind(viins, ACCEPT_LINE, ctrl('J')); ++ bind(viins, CLEAR_SCREEN, ctrl('L')); ++ bind(viins, ACCEPT_LINE, ctrl('M')); ++ bind(viins, MENU_COMPLETE, ctrl('N')); ++ bind(viins, REVERSE_MENU_COMPLETE, ctrl('P')); ++ bind(viins, HISTORY_INCREMENTAL_SEARCH_BACKWARD, ctrl('R')); ++ bind(viins, HISTORY_INCREMENTAL_SEARCH_FORWARD, ctrl('S')); ++ bind(viins, TRANSPOSE_CHARS, ctrl('T')); ++ bind(viins, KILL_WHOLE_LINE, ctrl('U')); ++ bind(viins, QUOTED_INSERT, ctrl('V')); ++ bind(viins, BACKWARD_KILL_WORD, ctrl('W')); ++ bind(viins, YANK, ctrl('Y')); ++ bind(viins, VI_CMD_MODE, ctrl('[')); ++ bind(viins, UNDO, ctrl('_')); ++ bind(viins, HISTORY_INCREMENTAL_SEARCH_BACKWARD, ctrl('X') + "r"); ++ bind(viins, HISTORY_INCREMENTAL_SEARCH_FORWARD, ctrl('X') + "s"); ++ bind(viins, SELF_INSERT, range(" -~")); ++ bind(viins, INSERT_CLOSE_PAREN, ")"); ++ bind(viins, INSERT_CLOSE_SQUARE, "]"); ++ bind(viins, INSERT_CLOSE_CURLY, "}"); ++ bind(viins, BACKWARD_DELETE_CHAR, del()); + bindArrowKeys(viins); + return viins; + } + + public KeyMap viCmd() { + KeyMap vicmd = new KeyMap<>(); +- bind(vicmd, LIST_CHOICES, ctrl('D')); +- bind(vicmd, EMACS_EDITING_MODE, ctrl('E')); +- bind(vicmd, SEND_BREAK, ctrl('G')); +- bind(vicmd, VI_BACKWARD_CHAR, ctrl('H')); +- bind(vicmd, ACCEPT_LINE, ctrl('J')); +- bind(vicmd, KILL_LINE, ctrl('K')); +- bind(vicmd, CLEAR_SCREEN, ctrl('L')); +- bind(vicmd, ACCEPT_LINE, ctrl('M')); +- bind(vicmd, VI_DOWN_LINE_OR_HISTORY, ctrl('N')); +- bind(vicmd, VI_UP_LINE_OR_HISTORY, ctrl('P')); +- bind(vicmd, QUOTED_INSERT, ctrl('Q')); +- bind(vicmd, HISTORY_INCREMENTAL_SEARCH_BACKWARD, ctrl('R')); +- bind(vicmd, HISTORY_INCREMENTAL_SEARCH_FORWARD, ctrl('S')); +- bind(vicmd, TRANSPOSE_CHARS, ctrl('T')); +- bind(vicmd, KILL_WHOLE_LINE, ctrl('U')); +- bind(vicmd, QUOTED_INSERT, ctrl('V')); +- bind(vicmd, BACKWARD_KILL_WORD, ctrl('W')); +- bind(vicmd, YANK, ctrl('Y')); +- bind(vicmd, HISTORY_INCREMENTAL_SEARCH_BACKWARD, ctrl('X') + "r"); +- bind(vicmd, HISTORY_INCREMENTAL_SEARCH_FORWARD, ctrl('X') + "s"); +- bind(vicmd, SEND_BREAK, alt(ctrl('G'))); +- bind(vicmd, BACKWARD_KILL_WORD, alt(ctrl('H'))); +- bind(vicmd, SELF_INSERT_UNMETA, alt(ctrl('M'))); +- bind(vicmd, COMPLETE_WORD, alt(esc())); +- bind(vicmd, CHARACTER_SEARCH_BACKWARD, alt(ctrl(']'))); +- bind(vicmd, SET_MARK_COMMAND, alt(' ')); +-// bind(vicmd, INSERT_COMMENT, alt('#')); +-// bind(vicmd, INSERT_COMPLETIONS, alt('*')); +- bind(vicmd, DIGIT_ARGUMENT, alt('-')); +- bind(vicmd, BEGINNING_OF_HISTORY, alt('<')); +- bind(vicmd, LIST_CHOICES, alt('=')); +- bind(vicmd, END_OF_HISTORY, alt('>')); +- bind(vicmd, LIST_CHOICES, alt('?')); +- bind(vicmd, DO_LOWERCASE_VERSION, range("^[A-^[Z")); +- bind(vicmd, BACKWARD_WORD, alt('b')); +- bind(vicmd, CAPITALIZE_WORD, alt('c')); +- bind(vicmd, KILL_WORD, alt('d')); +- bind(vicmd, FORWARD_WORD, alt('f')); +- bind(vicmd, DOWN_CASE_WORD, alt('l')); +- bind(vicmd, HISTORY_SEARCH_FORWARD, alt('n')); +- bind(vicmd, HISTORY_SEARCH_BACKWARD, alt('p')); +- bind(vicmd, TRANSPOSE_WORDS, alt('t')); +- bind(vicmd, UP_CASE_WORD, alt('u')); +- bind(vicmd, YANK_POP, alt('y')); +- bind(vicmd, BACKWARD_KILL_WORD, alt(del())); +- +- bind(vicmd, FORWARD_CHAR, " "); +- bind(vicmd, VI_INSERT_COMMENT, "#"); +- bind(vicmd, END_OF_LINE, "$"); +- bind(vicmd, VI_MATCH_BRACKET, "%"); +- bind(vicmd, VI_DOWN_LINE_OR_HISTORY, "+"); +- bind(vicmd, VI_REV_REPEAT_FIND, ","); +- bind(vicmd, VI_UP_LINE_OR_HISTORY, "-"); +- bind(vicmd, VI_REPEAT_CHANGE, "."); +- bind(vicmd, VI_HISTORY_SEARCH_BACKWARD, "/"); +- bind(vicmd, VI_DIGIT_OR_BEGINNING_OF_LINE, "0"); +- bind(vicmd, DIGIT_ARGUMENT, range("1-9")); +- bind(vicmd, VI_REPEAT_FIND, ";"); +- bind(vicmd, LIST_CHOICES, "="); +- bind(vicmd, VI_HISTORY_SEARCH_FORWARD, "?"); +- bind(vicmd, VI_ADD_EOL, "A"); +- bind(vicmd, VI_BACKWARD_BLANK_WORD, "B"); +- bind(vicmd, VI_CHANGE_EOL, "C"); +- bind(vicmd, VI_KILL_EOL, "D"); +- bind(vicmd, VI_FORWARD_BLANK_WORD_END, "E"); +- bind(vicmd, VI_FIND_PREV_CHAR, "F"); +- bind(vicmd, VI_FETCH_HISTORY, "G"); +- bind(vicmd, VI_INSERT_BOL, "I"); +- bind(vicmd, VI_JOIN, "J"); +- bind(vicmd, VI_REV_REPEAT_SEARCH, "N"); +- bind(vicmd, VI_OPEN_LINE_ABOVE, "O"); +- bind(vicmd, VI_PUT_BEFORE, "P"); +- bind(vicmd, VI_REPLACE, "R"); +- bind(vicmd, VI_KILL_LINE, "S"); +- bind(vicmd, VI_FIND_PREV_CHAR_SKIP, "T"); +- bind(vicmd, REDO, "U"); +- bind(vicmd, VISUAL_LINE_MODE, "V"); +- bind(vicmd, VI_FORWARD_BLANK_WORD, "W"); +- bind(vicmd, VI_BACKWARD_DELETE_CHAR, "X"); +- bind(vicmd, VI_YANK_WHOLE_LINE, "Y"); +- bind(vicmd, VI_FIRST_NON_BLANK, "^"); +- bind(vicmd, VI_ADD_NEXT, "a"); +- bind(vicmd, VI_BACKWARD_WORD, "b"); +- bind(vicmd, VI_CHANGE, "c"); +- bind(vicmd, VI_DELETE, "d"); +- bind(vicmd, VI_FORWARD_WORD_END, "e"); +- bind(vicmd, VI_FIND_NEXT_CHAR, "f"); +- bind(vicmd, WHAT_CURSOR_POSITION, "ga"); +- bind(vicmd, VI_BACKWARD_BLANK_WORD_END, "gE"); +- bind(vicmd, VI_BACKWARD_WORD_END, "ge"); +- bind(vicmd, VI_BACKWARD_CHAR, "h"); +- bind(vicmd, VI_INSERT, "i"); +- bind(vicmd, DOWN_LINE_OR_HISTORY, "j"); +- bind(vicmd, UP_LINE_OR_HISTORY, "k"); +- bind(vicmd, VI_FORWARD_CHAR, "l"); +- bind(vicmd, VI_REPEAT_SEARCH, "n"); +- bind(vicmd, VI_OPEN_LINE_BELOW, "o"); +- bind(vicmd, VI_PUT_AFTER, "p"); +- bind(vicmd, VI_REPLACE_CHARS, "r"); +- bind(vicmd, VI_SUBSTITUTE, "s"); +- bind(vicmd, VI_FIND_NEXT_CHAR_SKIP, "t"); +- bind(vicmd, UNDO, "u"); +- bind(vicmd, VISUAL_MODE, "v"); +- bind(vicmd, VI_FORWARD_WORD, "w"); +- bind(vicmd, VI_DELETE_CHAR, "x"); +- bind(vicmd, VI_YANK, "y"); +- bind(vicmd, VI_GOTO_COLUMN, "|"); +- bind(vicmd, VI_SWAP_CASE, "~"); +- bind(vicmd, VI_BACKWARD_CHAR, del()); ++ bind(vicmd, LIST_CHOICES, ctrl('D')); ++ bind(vicmd, EMACS_EDITING_MODE, ctrl('E')); ++ bind(vicmd, SEND_BREAK, ctrl('G')); ++ bind(vicmd, VI_BACKWARD_CHAR, ctrl('H')); ++ bind(vicmd, ACCEPT_LINE, ctrl('J')); ++ bind(vicmd, KILL_LINE, ctrl('K')); ++ bind(vicmd, CLEAR_SCREEN, ctrl('L')); ++ bind(vicmd, ACCEPT_LINE, ctrl('M')); ++ bind(vicmd, VI_DOWN_LINE_OR_HISTORY, ctrl('N')); ++ bind(vicmd, VI_UP_LINE_OR_HISTORY, ctrl('P')); ++ bind(vicmd, QUOTED_INSERT, ctrl('Q')); ++ bind(vicmd, HISTORY_INCREMENTAL_SEARCH_BACKWARD, ctrl('R')); ++ bind(vicmd, HISTORY_INCREMENTAL_SEARCH_FORWARD, ctrl('S')); ++ bind(vicmd, TRANSPOSE_CHARS, ctrl('T')); ++ bind(vicmd, KILL_WHOLE_LINE, ctrl('U')); ++ bind(vicmd, QUOTED_INSERT, ctrl('V')); ++ bind(vicmd, BACKWARD_KILL_WORD, ctrl('W')); ++ bind(vicmd, YANK, ctrl('Y')); ++ bind(vicmd, HISTORY_INCREMENTAL_SEARCH_BACKWARD, ctrl('X') + "r"); ++ bind(vicmd, HISTORY_INCREMENTAL_SEARCH_FORWARD, ctrl('X') + "s"); ++ bind(vicmd, SEND_BREAK, alt(ctrl('G'))); ++ bind(vicmd, BACKWARD_KILL_WORD, alt(ctrl('H'))); ++ bind(vicmd, SELF_INSERT_UNMETA, alt(ctrl('M'))); ++ bind(vicmd, COMPLETE_WORD, alt(esc())); ++ bind(vicmd, CHARACTER_SEARCH_BACKWARD, alt(ctrl(']'))); ++ bind(vicmd, SET_MARK_COMMAND, alt(' ')); ++ // bind(vicmd, INSERT_COMMENT, alt('#')); ++ // bind(vicmd, INSERT_COMPLETIONS, alt('*')); ++ bind(vicmd, DIGIT_ARGUMENT, alt('-')); ++ bind(vicmd, BEGINNING_OF_HISTORY, alt('<')); ++ bind(vicmd, LIST_CHOICES, alt('=')); ++ bind(vicmd, END_OF_HISTORY, alt('>')); ++ bind(vicmd, LIST_CHOICES, alt('?')); ++ bind(vicmd, DO_LOWERCASE_VERSION, range("^[A-^[Z")); ++ bind(vicmd, BACKWARD_WORD, alt('b')); ++ bind(vicmd, CAPITALIZE_WORD, alt('c')); ++ bind(vicmd, KILL_WORD, alt('d')); ++ bind(vicmd, FORWARD_WORD, alt('f')); ++ bind(vicmd, DOWN_CASE_WORD, alt('l')); ++ bind(vicmd, HISTORY_SEARCH_FORWARD, alt('n')); ++ bind(vicmd, HISTORY_SEARCH_BACKWARD, alt('p')); ++ bind(vicmd, TRANSPOSE_WORDS, alt('t')); ++ bind(vicmd, UP_CASE_WORD, alt('u')); ++ bind(vicmd, YANK_POP, alt('y')); ++ bind(vicmd, BACKWARD_KILL_WORD, alt(del())); ++ ++ bind(vicmd, FORWARD_CHAR, " "); ++ bind(vicmd, VI_INSERT_COMMENT, "#"); ++ bind(vicmd, END_OF_LINE, "$"); ++ bind(vicmd, VI_MATCH_BRACKET, "%"); ++ bind(vicmd, VI_DOWN_LINE_OR_HISTORY, "+"); ++ bind(vicmd, VI_REV_REPEAT_FIND, ","); ++ bind(vicmd, VI_UP_LINE_OR_HISTORY, "-"); ++ bind(vicmd, VI_REPEAT_CHANGE, "."); ++ bind(vicmd, VI_HISTORY_SEARCH_BACKWARD, "/"); ++ bind(vicmd, VI_DIGIT_OR_BEGINNING_OF_LINE, "0"); ++ bind(vicmd, DIGIT_ARGUMENT, range("1-9")); ++ bind(vicmd, VI_REPEAT_FIND, ";"); ++ bind(vicmd, LIST_CHOICES, "="); ++ bind(vicmd, VI_HISTORY_SEARCH_FORWARD, "?"); ++ bind(vicmd, VI_ADD_EOL, "A"); ++ bind(vicmd, VI_BACKWARD_BLANK_WORD, "B"); ++ bind(vicmd, VI_CHANGE_EOL, "C"); ++ bind(vicmd, VI_KILL_EOL, "D"); ++ bind(vicmd, VI_FORWARD_BLANK_WORD_END, "E"); ++ bind(vicmd, VI_FIND_PREV_CHAR, "F"); ++ bind(vicmd, VI_FETCH_HISTORY, "G"); ++ bind(vicmd, VI_INSERT_BOL, "I"); ++ bind(vicmd, VI_JOIN, "J"); ++ bind(vicmd, VI_REV_REPEAT_SEARCH, "N"); ++ bind(vicmd, VI_OPEN_LINE_ABOVE, "O"); ++ bind(vicmd, VI_PUT_BEFORE, "P"); ++ bind(vicmd, VI_REPLACE, "R"); ++ bind(vicmd, VI_KILL_LINE, "S"); ++ bind(vicmd, VI_FIND_PREV_CHAR_SKIP, "T"); ++ bind(vicmd, REDO, "U"); ++ bind(vicmd, VISUAL_LINE_MODE, "V"); ++ bind(vicmd, VI_FORWARD_BLANK_WORD, "W"); ++ bind(vicmd, VI_BACKWARD_DELETE_CHAR, "X"); ++ bind(vicmd, VI_YANK_WHOLE_LINE, "Y"); ++ bind(vicmd, VI_FIRST_NON_BLANK, "^"); ++ bind(vicmd, VI_ADD_NEXT, "a"); ++ bind(vicmd, VI_BACKWARD_WORD, "b"); ++ bind(vicmd, VI_CHANGE, "c"); ++ bind(vicmd, VI_DELETE, "d"); ++ bind(vicmd, VI_FORWARD_WORD_END, "e"); ++ bind(vicmd, VI_FIND_NEXT_CHAR, "f"); ++ bind(vicmd, WHAT_CURSOR_POSITION, "ga"); ++ bind(vicmd, VI_BACKWARD_BLANK_WORD_END, "gE"); ++ bind(vicmd, VI_BACKWARD_WORD_END, "ge"); ++ bind(vicmd, VI_BACKWARD_CHAR, "h"); ++ bind(vicmd, VI_INSERT, "i"); ++ bind(vicmd, DOWN_LINE_OR_HISTORY, "j"); ++ bind(vicmd, UP_LINE_OR_HISTORY, "k"); ++ bind(vicmd, VI_FORWARD_CHAR, "l"); ++ bind(vicmd, VI_REPEAT_SEARCH, "n"); ++ bind(vicmd, VI_OPEN_LINE_BELOW, "o"); ++ bind(vicmd, VI_PUT_AFTER, "p"); ++ bind(vicmd, VI_REPLACE_CHARS, "r"); ++ bind(vicmd, VI_SUBSTITUTE, "s"); ++ bind(vicmd, VI_FIND_NEXT_CHAR_SKIP, "t"); ++ bind(vicmd, UNDO, "u"); ++ bind(vicmd, VISUAL_MODE, "v"); ++ bind(vicmd, VI_FORWARD_WORD, "w"); ++ bind(vicmd, VI_DELETE_CHAR, "x"); ++ bind(vicmd, VI_YANK, "y"); ++ bind(vicmd, VI_GOTO_COLUMN, "|"); ++ bind(vicmd, VI_SWAP_CASE, "~"); ++ bind(vicmd, VI_BACKWARD_CHAR, del()); + + bindArrowKeys(vicmd); + return vicmd; +@@ -6150,38 +6303,46 @@ public class LineReaderImpl implements LineReader, Flushable + + public KeyMap menu() { + KeyMap menu = new KeyMap<>(); +- bind(menu, MENU_COMPLETE, "\t"); +- bind(menu, REVERSE_MENU_COMPLETE, key(Capability.back_tab)); +- bind(menu, ACCEPT_LINE, "\r", "\n"); ++ bind(menu, MENU_COMPLETE, "\t"); ++ bind(menu, REVERSE_MENU_COMPLETE, key(Capability.back_tab)); ++ bind(menu, ACCEPT_LINE, "\r", "\n"); + bindArrowKeys(menu); + return menu; + } + + public KeyMap safe() { + KeyMap safe = new KeyMap<>(); +- bind(safe, SELF_INSERT, range("^@-^?")); +- bind(safe, ACCEPT_LINE, "\r", "\n"); +- bind(safe, SEND_BREAK, ctrl('G')); ++ bind(safe, SELF_INSERT, range("^@-^?")); ++ bind(safe, ACCEPT_LINE, "\r", "\n"); ++ bind(safe, SEND_BREAK, ctrl('G')); + return safe; + } + ++ public KeyMap dumb() { ++ KeyMap dumb = new KeyMap<>(); ++ bind(dumb, SELF_INSERT, range("^@-^?")); ++ bind(dumb, ACCEPT_LINE, "\r", "\n"); ++ bind(dumb, BEEP, ctrl('G')); ++ return dumb; ++ } ++ + public KeyMap visual() { + KeyMap visual = new KeyMap<>(); +- bind(visual, UP_LINE, key(Capability.key_up), "k"); +- bind(visual, DOWN_LINE, key(Capability.key_down), "j"); +- bind(visual, this::deactivateRegion, esc()); +- bind(visual, EXCHANGE_POINT_AND_MARK, "o"); +- bind(visual, PUT_REPLACE_SELECTION, "p"); +- bind(visual, VI_DELETE, "x"); +- bind(visual, VI_OPER_SWAP_CASE, "~"); ++ bind(visual, UP_LINE, key(Capability.key_up), "k"); ++ bind(visual, DOWN_LINE, key(Capability.key_down), "j"); ++ bind(visual, this::deactivateRegion, esc()); ++ bind(visual, EXCHANGE_POINT_AND_MARK, "o"); ++ bind(visual, PUT_REPLACE_SELECTION, "p"); ++ bind(visual, VI_DELETE, "x"); ++ bind(visual, VI_OPER_SWAP_CASE, "~"); + return visual; + } + + public KeyMap viOpp() { + KeyMap viOpp = new KeyMap<>(); +- bind(viOpp, UP_LINE, key(Capability.key_up), "k"); +- bind(viOpp, DOWN_LINE, key(Capability.key_down), "j"); +- bind(viOpp, VI_CMD_MODE, esc()); ++ bind(viOpp, UP_LINE, key(Capability.key_up), "k"); ++ bind(viOpp, DOWN_LINE, key(Capability.key_down), "j"); ++ bind(viOpp, VI_CMD_MODE, esc()); + return viOpp; + } + +@@ -6210,19 +6371,19 @@ public class LineReaderImpl implements LineReader, Flushable + } + + private void bindArrowKeys(KeyMap map) { +- bind(map, UP_LINE_OR_SEARCH, key(Capability.key_up)); +- bind(map, DOWN_LINE_OR_SEARCH, key(Capability.key_down)); +- bind(map, BACKWARD_CHAR, key(Capability.key_left)); +- bind(map, FORWARD_CHAR, key(Capability.key_right)); +- bind(map, BEGINNING_OF_LINE, key(Capability.key_home)); +- bind(map, END_OF_LINE, key(Capability.key_end)); +- bind(map, DELETE_CHAR, key(Capability.key_dc)); +- bind(map, KILL_WHOLE_LINE, key(Capability.key_dl)); +- bind(map, OVERWRITE_MODE, key(Capability.key_ic)); +- bind(map, MOUSE, key(Capability.key_mouse)); +- bind(map, BEGIN_PASTE, BRACKETED_PASTE_BEGIN); +- bind(map, FOCUS_IN, FOCUS_IN_SEQ); +- bind(map, FOCUS_OUT, FOCUS_OUT_SEQ); ++ bind(map, UP_LINE_OR_SEARCH, key(Capability.key_up)); ++ bind(map, DOWN_LINE_OR_SEARCH, key(Capability.key_down)); ++ bind(map, BACKWARD_CHAR, key(Capability.key_left)); ++ bind(map, FORWARD_CHAR, key(Capability.key_right)); ++ bind(map, BEGINNING_OF_LINE, key(Capability.key_home)); ++ bind(map, END_OF_LINE, key(Capability.key_end)); ++ bind(map, DELETE_CHAR, key(Capability.key_dc)); ++ bind(map, KILL_WHOLE_LINE, key(Capability.key_dl)); ++ bind(map, OVERWRITE_MODE, key(Capability.key_ic)); ++ bind(map, MOUSE, key(Capability.key_mouse)); ++ bind(map, BEGIN_PASTE, BRACKETED_PASTE_BEGIN); ++ bind(map, FOCUS_IN, FOCUS_IN_SEQ); ++ bind(map, FOCUS_OUT, FOCUS_OUT_SEQ); + } + + /** +@@ -6231,14 +6392,10 @@ public class LineReaderImpl implements LineReader, Flushable + */ + private void bindConsoleChars(KeyMap keyMap, Attributes attr) { + if (attr != null) { +- rebind(keyMap, BACKWARD_DELETE_CHAR, +- del(), (char) attr.getControlChar(ControlChar.VERASE)); +- rebind(keyMap, BACKWARD_KILL_WORD, +- ctrl('W'), (char) attr.getControlChar(ControlChar.VWERASE)); +- rebind(keyMap, KILL_WHOLE_LINE, +- ctrl('U'), (char) attr.getControlChar(ControlChar.VKILL)); +- rebind(keyMap, QUOTED_INSERT, +- ctrl('V'), (char) attr.getControlChar(ControlChar.VLNEXT)); ++ rebind(keyMap, BACKWARD_DELETE_CHAR, del(), (char) attr.getControlChar(ControlChar.VERASE)); ++ rebind(keyMap, BACKWARD_KILL_WORD, ctrl('W'), (char) attr.getControlChar(ControlChar.VWERASE)); ++ rebind(keyMap, KILL_WHOLE_LINE, ctrl('U'), (char) attr.getControlChar(ControlChar.VKILL)); ++ rebind(keyMap, QUOTED_INSERT, ctrl('V'), (char) attr.getControlChar(ControlChar.VLNEXT)); + } + } + +@@ -6250,4 +6407,8 @@ public class LineReaderImpl implements LineReader, Flushable + } + } + ++ @Override ++ public void zeroOut() { ++ buf.zeroOut(); ++ } + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/ReaderUtils.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/ReaderUtils.java +index 0ae9475bd..cdc60dccc 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/ReaderUtils.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/ReaderUtils.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2020, the original author or authors. ++ * Copyright (c) 2002-2020, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -13,7 +13,7 @@ import jdk.internal.org.jline.utils.Levenshtein; + + public class ReaderUtils { + +- private ReaderUtils() { } ++ private ReaderUtils() {} + + public static boolean isSet(LineReader reader, LineReader.Option option) { + return reader != null && reader.isSet(option); +@@ -30,8 +30,7 @@ public class ReaderUtils { + return (Boolean) v; + } else if (v != null) { + String s = v.toString(); +- return s.isEmpty() || s.equalsIgnoreCase("on") +- || s.equalsIgnoreCase("1") || s.equalsIgnoreCase("true"); ++ return s.isEmpty() || s.equalsIgnoreCase("on") || s.equalsIgnoreCase("1") || s.equalsIgnoreCase("true"); + } + return def; + } +@@ -77,5 +76,4 @@ public class ReaderUtils { + return Levenshtein.distance(word, cand); + } + } +- + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/SimpleMaskingCallback.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/SimpleMaskingCallback.java +index fd6c2663c..423497f3d 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/SimpleMaskingCallback.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/SimpleMaskingCallback.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2017, the original author or authors. ++ * Copyright (c) 2002-2017, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -8,10 +8,10 @@ + */ + package jdk.internal.org.jline.reader.impl; + +-import jdk.internal.org.jline.reader.MaskingCallback; +- + import java.util.Objects; + ++import jdk.internal.org.jline.reader.MaskingCallback; + -+ return (((ProcMIPS64Thread) obj).id == id); -+ } + /** + * Simple {@link MaskingCallback} that will replace all the characters in the line with the given mask. + * If the given mask is equal to {@link LineReaderImpl#NULL_MASK} then the line will be replaced with an empty String. +@@ -29,7 +29,7 @@ public final class SimpleMaskingCallback implements MaskingCallback { + return ""; + } else { + StringBuilder sb = new StringBuilder(line.length()); +- for (int i = line.length(); i-- > 0;) { ++ for (int i = line.length(); i-- > 0; ) { + sb.append((char) mask); + } + return sb.toString(); +@@ -40,5 +40,4 @@ public final class SimpleMaskingCallback implements MaskingCallback { + public String history(String line) { + return null; + } +- + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/UndoTree.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/UndoTree.java +index 0a467f9d7..3b193f9eb 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/UndoTree.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/UndoTree.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2016, the original author or authors. ++ * Copyright (c) 2002-2016, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -20,6 +20,7 @@ public class UndoTree { + private final Node parent; + private Node current; + ++ @SuppressWarnings("this-escape") + public UndoTree(Consumer s) { + state = s; + parent = new Node(null); +@@ -71,5 +72,4 @@ public class UndoTree { + state = s; + } + } +- + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/AggregateCompleter.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/AggregateCompleter.java +index e8e41088c..145823c53 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/AggregateCompleter.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/AggregateCompleter.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2016, the original author or authors. ++ * Copyright (c) 2002-2016, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -24,9 +24,7 @@ import jdk.internal.org.jline.reader.ParsedLine; + * @author Jason Dillon + * @since 2.3 + */ +-public class AggregateCompleter +- implements Completer +-{ ++public class AggregateCompleter implements Completer { + private final Collection completers; + + /** +@@ -78,9 +76,6 @@ public class AggregateCompleter + */ + @Override + public String toString() { +- return getClass().getSimpleName() + "{" + +- "completers=" + completers + +- '}'; ++ return getClass().getSimpleName() + "{" + "completers=" + completers + '}'; + } +- + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/ArgumentCompleter.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/ArgumentCompleter.java +index f84c8a900..f0efa2922 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/ArgumentCompleter.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/ArgumentCompleter.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2019, the original author or authors. ++ * Copyright (c) 2002-2019, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -29,8 +29,7 @@ import jdk.internal.org.jline.reader.ParsedLine; + * @author Jason Dillon + * @since 2.3 + */ +-public class ArgumentCompleter implements Completer +-{ ++public class ArgumentCompleter implements Completer { + private final List completers = new ArrayList<>(); + + private boolean strict = true; +@@ -108,12 +107,12 @@ public class ArgumentCompleter implements Completer + // if we are beyond the end of the completers, just use the last one + if (line.wordIndex() >= completers.size()) { + completer = completers.get(completers.size() - 1); +- } +- else { ++ } else { + completer = completers.get(line.wordIndex()); + } + +- // ensure that all the previous completers are successful before allowing this completer to pass (only if strict). ++ // ensure that all the previous completers are successful before allowing this completer to pass (only if ++ // strict). + for (int i = strictCommand ? 0 : 1; isStrict() && (i < line.wordIndex()); i++) { + int idx = i >= completers.size() ? (completers.size() - 1) : i; + if (idx == 0 && !strictCommand) { +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/EnumCompleter.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/EnumCompleter.java +index 6a18d3cfd..a701f2e35 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/EnumCompleter.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/EnumCompleter.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2016, the original author or authors. ++ * Copyright (c) 2002-2016, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -19,8 +19,7 @@ import jdk.internal.org.jline.reader.Completer; + * @author Jason Dillon + * @since 2.3 + */ +-public class EnumCompleter extends StringsCompleter +-{ ++public class EnumCompleter extends StringsCompleter { + public EnumCompleter(Class> source) { + Objects.requireNonNull(source); + for (Enum n : source.getEnumConstants()) { +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/FileNameCompleter.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/FileNameCompleter.java +index 3d173f72e..32bf6e349 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/FileNameCompleter.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/FileNameCompleter.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2018, the original author or authors. ++ * Copyright (c) 2002-2018, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -9,6 +9,7 @@ + package jdk.internal.org.jline.reader.impl.completer; + + import java.io.IOException; ++import java.nio.file.DirectoryStream; + import java.nio.file.Files; + import java.nio.file.Path; + import java.nio.file.Paths; +@@ -41,11 +42,10 @@ import jdk.internal.org.jline.utils.AttributedStyle; + * @author Marc Prud'hommeaux + * @author Jason Dillon + * @since 2.3 +- * @deprecated use jdk.internal.org.jline.builtins.Completers$FileNameCompleter instead ++ * @deprecated use org.jline.builtins.Completers$FileNameCompleter instead + */ + @Deprecated +-public class FileNameCompleter implements Completer +-{ ++public class FileNameCompleter implements Completer { + + public void complete(LineReader reader, ParsedLine commandLine, final List candidates) { + assert commandLine != null; +@@ -72,20 +72,21 @@ public class FileNameCompleter implements Completer + curBuf = ""; + current = getUserDir(); + } +- try { +- Files.newDirectoryStream(current, this::accept).forEach(p -> { ++ try (DirectoryStream directoryStream = Files.newDirectoryStream(current, this::accept)) { ++ directoryStream.forEach(p -> { + String value = curBuf + p.getFileName().toString(); + if (Files.isDirectory(p)) { + candidates.add(new Candidate( + value + (reader.isSet(Option.AUTO_PARAM_SLASH) ? sep : ""), + getDisplay(reader.getTerminal(), p), +- null, null, ++ null, ++ null, + reader.isSet(Option.AUTO_REMOVE_SLASH) ? sep : null, + null, + false)); + } else { +- candidates.add(new Candidate(value, getDisplay(reader.getTerminal(), p), +- null, null, null, null, true)); ++ candidates.add( ++ new Candidate(value, getDisplay(reader.getTerminal(), p), null, null, null, null, true)); + } + }); + } catch (IOException e) { +@@ -125,5 +126,4 @@ public class FileNameCompleter implements Completer + } + return name; + } +- + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/NullCompleter.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/NullCompleter.java +index f3efefdc9..21ce836a3 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/NullCompleter.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/NullCompleter.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2016, the original author or authors. ++ * Copyright (c) 2002-2016, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -22,11 +22,8 @@ import jdk.internal.org.jline.reader.ParsedLine; + * @author Jason Dillon + * @since 2.3 + */ +-public final class NullCompleter +- implements Completer +-{ ++public final class NullCompleter implements Completer { + public static final NullCompleter INSTANCE = new NullCompleter(); + +- public void complete(LineReader reader, final ParsedLine line, final List candidates) { +- } ++ public void complete(LineReader reader, final ParsedLine line, final List candidates) {} + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/StringsCompleter.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/StringsCompleter.java +index 8baac657b..c791ef68e 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/StringsCompleter.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/StringsCompleter.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2019, the original author or authors. ++ * Copyright (c) 2002-2019, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -27,8 +27,7 @@ import jdk.internal.org.jline.utils.AttributedString; + * @author Jason Dillon + * @since 2.3 + */ +-public class StringsCompleter implements Completer +-{ ++public class StringsCompleter implements Completer { + protected Collection candidates; + protected Supplier> stringsSupplier; + +@@ -54,7 +53,7 @@ public class StringsCompleter implements Completer + } + } + +- public StringsCompleter(Candidate ... candidates) { ++ public StringsCompleter(Candidate... candidates) { + this(Arrays.asList(candidates)); + } + +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/SystemCompleter.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/SystemCompleter.java +index a17a356bf..2fe6f8df4 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/SystemCompleter.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/SystemCompleter.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2020, the original author or authors. ++ * Copyright (c) 2002-2020, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -22,8 +22,8 @@ import jdk.internal.org.jline.utils.AttributedString; + * @author Matti Rinta-Nikkola + */ + public class SystemCompleter implements Completer { +- private Map> completers = new HashMap<>(); +- private Map aliasCommand = new HashMap<>(); ++ private Map> completers = new HashMap<>(); ++ private Map aliasCommand = new HashMap<>(); + private StringsCompleter commands; + private boolean compiled = false; + +@@ -44,9 +44,9 @@ public class SystemCompleter implements Completer { + commands.complete(reader, commandLine, candidates); + } else if (reader.getParser().validVariableName(buffer.substring(0, eq))) { + String curBuf = buffer.substring(0, eq + 1); +- for (String c: completers.keySet()) { +- candidates.add(new Candidate(AttributedString.stripAnsi(curBuf+c) +- , c, null, null, null, null, true)); ++ for (String c : completers.keySet()) { ++ candidates.add( ++ new Candidate(AttributedString.stripAnsi(curBuf + c), c, null, null, null, null, true)); + } + } + } else { +@@ -81,7 +81,7 @@ public class SystemCompleter implements Completer { + } + + public void add(List commands, Completer completer) { +- for (String c: commands) { ++ for (String c : commands) { + add(c, completer); + } + } +@@ -104,22 +104,22 @@ public class SystemCompleter implements Completer { + if (other.isCompiled()) { + throw new IllegalStateException(); + } +- for (Map.Entry> entry: other.getCompleters().entrySet()) { +- for (Completer c: entry.getValue()) { ++ for (Map.Entry> entry : other.getCompleters().entrySet()) { ++ for (Completer c : entry.getValue()) { + add(entry.getKey(), c); + } + } + addAliases(other.getAliases()); + } + +- public void addAliases(Map aliasCommand) { ++ public void addAliases(Map aliasCommand) { + if (compiled) { + throw new IllegalStateException(); + } + this.aliasCommand.putAll(aliasCommand); + } + +- private Map getAliases() { ++ private Map getAliases() { + return aliasCommand; + } + +@@ -128,7 +128,7 @@ public class SystemCompleter implements Completer { + return; + } + Map> compiledCompleters = new HashMap<>(); +- for (Map.Entry> entry: completers.entrySet()) { ++ for (Map.Entry> entry : completers.entrySet()) { + if (entry.getValue().size() == 1) { + compiledCompleters.put(entry.getKey(), entry.getValue()); + } else { +@@ -143,8 +143,7 @@ public class SystemCompleter implements Completer { + compiled = true; + } + +- public Map> getCompleters() { ++ public Map> getCompleters() { + return completers; + } +- + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/history/DefaultHistory.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/history/DefaultHistory.java +index cdd1bc520..c696b33ba 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/history/DefaultHistory.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/history/DefaultHistory.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2021, the original author or authors. ++ * Copyright (c) 2002-2021, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -41,9 +41,9 @@ public class DefaultHistory implements History { + private int offset = 0; + private int index = 0; + +- public DefaultHistory() { +- } ++ public DefaultHistory() {} + ++ @SuppressWarnings("this-escape") + public DefaultHistory(LineReader reader) { + attach(reader); + } +@@ -67,8 +67,7 @@ public class DefaultHistory implements History { + this.reader = reader; + try { + load(); +- } +- catch (IllegalArgumentException | IOException e) { ++ } catch (IllegalArgumentException | IOException e) { + Log.warn("Failed to load history", e); + } + } +@@ -117,13 +116,13 @@ public class DefaultHistory implements History { + } + } + +- private String doHistoryFileDataKey (Path path){ ++ private String doHistoryFileDataKey(Path path) { + return path != null ? path.toAbsolutePath().toString() : null; + } + + private HistoryFileData getHistoryFileData(Path path) { + String key = doHistoryFileDataKey(path); +- if (!historyFiles.containsKey(key)){ ++ if (!historyFiles.containsKey(key)) { + historyFiles.put(key, new HistoryFileData()); + } + return historyFiles.get(key); +@@ -133,7 +132,7 @@ public class DefaultHistory implements History { + historyFiles.put(doHistoryFileDataKey(path), historyFileData); + } + +- private boolean isLineReaderHistory (Path path) throws IOException { ++ private boolean isLineReaderHistory(Path path) throws IOException { + Path lrp = getPath(); + if (lrp == null) { + return path == null; +@@ -141,23 +140,23 @@ public class DefaultHistory implements History { + return Files.isSameFile(lrp, path); + } + +- private void setLastLoaded(Path path, int lastloaded){ ++ private void setLastLoaded(Path path, int lastloaded) { + getHistoryFileData(path).setLastLoaded(lastloaded); + } + +- private void setEntriesInFile(Path path, int entriesInFile){ ++ private void setEntriesInFile(Path path, int entriesInFile) { + getHistoryFileData(path).setEntriesInFile(entriesInFile); + } + +- private void incEntriesInFile(Path path, int amount){ ++ private void incEntriesInFile(Path path, int amount) { + getHistoryFileData(path).incEntriesInFile(amount); + } + +- private int getLastLoaded(Path path){ ++ private int getLastLoaded(Path path) { + return getHistoryFileData(path).getLastLoaded(); + } + +- private int getEntriesInFile(Path path){ ++ private int getEntriesInFile(Path path) { + return getHistoryFileData(path).getEntriesInFile(); + } + +@@ -168,9 +167,8 @@ public class DefaultHistory implements History { + protected void addHistoryLine(Path path, String line, boolean checkDuplicates) { + if (reader.isSet(LineReader.Option.HISTORY_TIMESTAMPED)) { + int idx = line.indexOf(':'); +- final String badHistoryFileSyntax = "Bad history file syntax! " + +- "The history file `" + path + "` may be an older history: " + +- "please remove it or use a different history file."; ++ final String badHistoryFileSyntax = "Bad history file syntax! " + "The history file `" + path ++ + "` may be an older history: " + "please remove it or use a different history file."; + if (idx < 0) { + throw new IllegalArgumentException(badHistoryFileSyntax); + } +@@ -183,8 +181,7 @@ public class DefaultHistory implements History { + + String unescaped = unescape(line.substring(idx + 1)); + internalAdd(time, unescaped, checkDuplicates); +- } +- else { ++ } else { + internalAdd(Instant.now(), unescape(line), checkDuplicates); + } + } +@@ -210,8 +207,7 @@ public class DefaultHistory implements History { + + @Override + public void append(Path file, boolean incremental) throws IOException { +- internalWrite(file != null ? file : getPath(), +- incremental ? getLastLoaded(file) : 0); ++ internalWrite(file != null ? file : getPath(), incremental ? getLastLoaded(file) : 0); + } + + @Override +@@ -227,8 +223,11 @@ public class DefaultHistory implements History { + Files.createDirectories(parent); + } + // Append new items to the history file +- try (BufferedWriter writer = Files.newBufferedWriter(path.toAbsolutePath(), +- StandardOpenOption.WRITE, StandardOpenOption.APPEND, StandardOpenOption.CREATE)) { ++ try (BufferedWriter writer = Files.newBufferedWriter( ++ path.toAbsolutePath(), ++ StandardOpenOption.WRITE, ++ StandardOpenOption.APPEND, ++ StandardOpenOption.CREATE)) { + for (Entry entry : items.subList(from, items.size())) { + if (isPersistable(entry)) { + writer.append(format(entry)); +@@ -248,18 +247,23 @@ public class DefaultHistory implements History { + Log.trace("Trimming history path: ", path); + // Load all history entries + LinkedList allItems = new LinkedList<>(); +- try (BufferedReader reader = Files.newBufferedReader(path)) { +- reader.lines().forEach(l -> { +- int idx = l.indexOf(':'); +- Instant time = Instant.ofEpochMilli(Long.parseLong(l.substring(0, idx))); +- String line = unescape(l.substring(idx + 1)); +- allItems.add(createEntry(allItems.size(), time, line)); ++ try (BufferedReader historyFileReader = Files.newBufferedReader(path)) { ++ historyFileReader.lines().forEach(l -> { ++ if (reader.isSet(LineReader.Option.HISTORY_TIMESTAMPED)) { ++ int idx = l.indexOf(':'); ++ Instant time = Instant.ofEpochMilli(Long.parseLong(l.substring(0, idx))); ++ String line = unescape(l.substring(idx + 1)); ++ allItems.add(createEntry(allItems.size(), time, line)); ++ } else { ++ allItems.add(createEntry(allItems.size(), Instant.now(), unescape(l))); ++ } + }); + } + // Remove duplicates + List trimmedItems = doTrimHistory(allItems, max); + // Write history +- Path temp = Files.createTempFile(path.toAbsolutePath().getParent(), path.getFileName().toString(), ".tmp"); ++ Path temp = Files.createTempFile( ++ path.toAbsolutePath().getParent(), path.getFileName().toString(), ".tmp"); + try (BufferedWriter writer = Files.newBufferedWriter(temp, StandardOpenOption.WRITE)) { + for (Entry entry : trimmedItems) { + writer.append(format(entry)); +@@ -351,7 +355,7 @@ public class DefaultHistory implements History { + public String get(final int index) { + int idx = index - offset; + if (idx >= items.size() || idx < 0) { +- throw new IllegalArgumentException("IndexOutOfBounds: Index:" + idx +", Size:" + items.size()); ++ throw new IllegalArgumentException("IndexOutOfBounds: Index:" + idx + ", Size:" + items.size()); + } + return items.get(idx).line(); + } +@@ -382,8 +386,7 @@ public class DefaultHistory implements History { + if (isSet(reader, LineReader.Option.HISTORY_INCREMENTAL)) { + try { + save(); +- } +- catch (IOException e) { ++ } catch (IOException e) { + Log.warn("Failed to save history", e); + } + } +@@ -417,7 +420,7 @@ public class DefaultHistory implements History { + protected void internalAdd(Instant time, String line, boolean checkDuplicates) { + Entry entry = new EntryImpl(offset + items.size(), time, line); + if (checkDuplicates) { +- for (Entry e: items) { ++ for (Entry e : items) { + if (e.line().trim().equals(line.trim())) { + return; + } +@@ -430,7 +433,7 @@ public class DefaultHistory implements History { + private void maybeResize() { + while (size() > getInt(reader, LineReader.HISTORY_SIZE, DEFAULT_HISTORY_SIZE)) { + items.removeFirst(); +- for (HistoryFileData hfd: historyFiles.values()) { ++ for (HistoryFileData hfd : historyFiles.values()) { + hfd.decLastLoaded(); + } + offset++; +@@ -633,8 +636,7 @@ public class DefaultHistory implements History { + private int lastLoaded = 0; + private int entriesInFile = 0; + +- public HistoryFileData() { +- } ++ public HistoryFileData() {} + + public HistoryFileData(int lastLoaded, int entriesInFile) { + this.lastLoaded = lastLoaded; +@@ -667,8 +669,5 @@ public class DefaultHistory implements History { + public void incEntriesInFile(int amount) { + entriesInFile = entriesInFile + amount; + } +- + } +- + } +- +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/Attributes.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/Attributes.java +index b1bab287e..04959488c 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/Attributes.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/Attributes.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2016, the original author or authors. ++ * Copyright (c) 2002-2016, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -43,63 +43,65 @@ public class Attributes { + * Input flags - software input processing + */ + public enum InputFlag { +- IGNBRK, /* ignore BREAK condition */ +- BRKINT, /* map BREAK to SIGINTR */ +- IGNPAR, /* ignore (discard) parity errors */ +- PARMRK, /* mark parity and framing errors */ +- INPCK, /* enable checking of parity errors */ +- ISTRIP, /* strip 8th bit off chars */ +- INLCR, /* map NL into CR */ +- IGNCR, /* ignore CR */ +- ICRNL, /* map CR to NL (ala CRMOD) */ +- IXON, /* enable output flow control */ +- IXOFF, /* enable input flow control */ +- IXANY, /* any char will restart after stop */ +- IMAXBEL, /* ring bell on input queue full */ +- IUTF8 /* maintain state for UTF-8 VERASE */ ++ IGNBRK, /* ignore BREAK condition */ ++ BRKINT, /* map BREAK to SIGINTR */ ++ IGNPAR, /* ignore (discard) parity errors */ ++ PARMRK, /* mark parity and framing errors */ ++ INPCK, /* enable checking of parity errors */ ++ ISTRIP, /* strip 8th bit off chars */ ++ INLCR, /* map NL into CR */ ++ IGNCR, /* ignore CR */ ++ ICRNL, /* map CR to NL (ala CRMOD) */ ++ IXON, /* enable output flow control */ ++ IXOFF, /* enable input flow control */ ++ IXANY, /* any char will restart after stop */ ++ IMAXBEL, /* ring bell on input queue full */ ++ IUTF8, /* maintain state for UTF-8 VERASE */ ++ ++ INORMEOL /* normalize end-of-line */ + } + + /* + * Output flags - software output processing + */ + public enum OutputFlag { +- OPOST, /* enable following output processing */ +- ONLCR, /* map NL to CR-NL (ala CRMOD) */ +- OXTABS, /* expand tabs to spaces */ +- ONOEOT, /* discard EOT's (^D) on output) */ +- OCRNL, /* map CR to NL on output */ +- ONOCR, /* no CR output at column 0 */ +- ONLRET, /* NL performs CR function */ +- OFILL, /* use fill characters for delay */ +- NLDLY, /* \n delay */ +- TABDLY, /* horizontal tab delay */ +- CRDLY, /* \r delay */ +- FFDLY, /* form feed delay */ +- BSDLY, /* \b delay */ +- VTDLY, /* vertical tab delay */ +- OFDEL /* fill is DEL, else NUL */ ++ OPOST, /* enable following output processing */ ++ ONLCR, /* map NL to CR-NL (ala CRMOD) */ ++ OXTABS, /* expand tabs to spaces */ ++ ONOEOT, /* discard EOT's (^D) on output) */ ++ OCRNL, /* map CR to NL on output */ ++ ONOCR, /* no CR output at column 0 */ ++ ONLRET, /* NL performs CR function */ ++ OFILL, /* use fill characters for delay */ ++ NLDLY, /* \n delay */ ++ TABDLY, /* horizontal tab delay */ ++ CRDLY, /* \r delay */ ++ FFDLY, /* form feed delay */ ++ BSDLY, /* \b delay */ ++ VTDLY, /* vertical tab delay */ ++ OFDEL /* fill is DEL, else NUL */ + } + + /* + * Control flags - hardware control of terminal + */ + public enum ControlFlag { +- CIGNORE, /* ignore control flags */ +- CS5, /* 5 bits (pseudo) */ +- CS6, /* 6 bits */ +- CS7, /* 7 bits */ +- CS8, /* 8 bits */ +- CSTOPB, /* send 2 stop bits */ +- CREAD, /* enable receiver */ +- PARENB, /* parity enable */ +- PARODD, /* odd parity, else even */ +- HUPCL, /* hang up on last close */ +- CLOCAL, /* ignore modem status lines */ +- CCTS_OFLOW, /* CTS flow control of output */ +- CRTS_IFLOW, /* RTS flow control of input */ +- CDTR_IFLOW, /* DTR flow control of input */ +- CDSR_OFLOW, /* DSR flow control of output */ +- CCAR_OFLOW /* DCD flow control of output */ ++ CIGNORE, /* ignore control flags */ ++ CS5, /* 5 bits (pseudo) */ ++ CS6, /* 6 bits */ ++ CS7, /* 7 bits */ ++ CS8, /* 8 bits */ ++ CSTOPB, /* send 2 stop bits */ ++ CREAD, /* enable receiver */ ++ PARENB, /* parity enable */ ++ PARODD, /* odd parity, else even */ ++ HUPCL, /* hang up on last close */ ++ CLOCAL, /* ignore modem status lines */ ++ CCTS_OFLOW, /* CTS flow control of output */ ++ CRTS_IFLOW, /* RTS flow control of input */ ++ CDTR_IFLOW, /* DTR flow control of input */ ++ CDSR_OFLOW, /* DSR flow control of output */ ++ CCAR_OFLOW /* DCD flow control of output */ + } + + /* +@@ -110,23 +112,23 @@ public class Attributes { + * input flag. + */ + public enum LocalFlag { +- ECHOKE, /* visual erase for line kill */ +- ECHOE, /* visually erase chars */ +- ECHOK, /* echo NL after line kill */ +- ECHO, /* enable echoing */ +- ECHONL, /* echo NL even if ECHO is off */ +- ECHOPRT, /* visual erase mode for hardcopy */ +- ECHOCTL, /* echo control chars as ^(Char) */ +- ISIG, /* enable signals INTR, QUIT, [D]SUSP */ +- ICANON, /* canonicalize input lines */ +- ALTWERASE, /* use alternate WERASE algorithm */ +- IEXTEN, /* enable DISCARD and LNEXT */ +- EXTPROC, /* external processing */ +- TOSTOP, /* stop background jobs from output */ +- FLUSHO, /* output being flushed (state) */ +- NOKERNINFO, /* no kernel output from VSTATUS */ +- PENDIN, /* XXX retype pending input (state) */ +- NOFLSH /* don't flush after interrupt */ ++ ECHOKE, /* visual erase for line kill */ ++ ECHOE, /* visually erase chars */ ++ ECHOK, /* echo NL after line kill */ ++ ECHO, /* enable echoing */ ++ ECHONL, /* echo NL even if ECHO is off */ ++ ECHOPRT, /* visual erase mode for hardcopy */ ++ ECHOCTL, /* echo control chars as ^(Char) */ ++ ISIG, /* enable signals INTR, QUIT, [D]SUSP */ ++ ICANON, /* canonicalize input lines */ ++ ALTWERASE, /* use alternate WERASE algorithm */ ++ IEXTEN, /* enable DISCARD and LNEXT */ ++ EXTPROC, /* external processing */ ++ TOSTOP, /* stop background jobs from output */ ++ FLUSHO, /* output being flushed (state) */ ++ NOKERNINFO, /* no kernel output from VSTATUS */ ++ PENDIN, /* XXX retype pending input (state) */ ++ NOFLSH /* don't flush after interrupt */ + } + + final EnumSet iflag = EnumSet.noneOf(InputFlag.class); +@@ -135,9 +137,9 @@ public class Attributes { + final EnumSet lflag = EnumSet.noneOf(LocalFlag.class); + final EnumMap cchars = new EnumMap<>(ControlChar.class); + +- public Attributes() { +- } ++ public Attributes() {} + ++ @SuppressWarnings("this-escape") + public Attributes(Attributes attr) { + copy(attr); + } +@@ -310,13 +312,12 @@ public class Attributes { + + @Override + public String toString() { +- return "Attributes[" + +- "lflags: " + append(lflag) + ", " + +- "iflags: " + append(iflag) + ", " + +- "oflags: " + append(oflag) + ", " + +- "cflags: " + append(cflag) + ", " + +- "cchars: " + append(EnumSet.allOf(ControlChar.class), this::display) + +- "]"; ++ return "Attributes[" + "lflags: " ++ + append(lflag) + ", " + "iflags: " ++ + append(iflag) + ", " + "oflags: " ++ + append(oflag) + ", " + "cflags: " ++ + append(cflag) + ", " + "cchars: " ++ + append(EnumSet.allOf(ControlChar.class), this::display) + "]"; + } + + private String display(ControlChar c) { +@@ -345,5 +346,4 @@ public class Attributes { + private > String append(EnumSet set, Function toString) { + return set.stream().map(toString).collect(Collectors.joining(" ")); + } +- + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/Cursor.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/Cursor.java +index c561349cb..9bc3d9028 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/Cursor.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/Cursor.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2016, the original author or authors. ++ * Copyright (c) 2002-2016, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/MouseEvent.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/MouseEvent.java +index df59e3f41..059b43c51 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/MouseEvent.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/MouseEvent.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2016, the original author or authors. ++ * Copyright (c) 2002-2016, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -71,12 +71,11 @@ public class MouseEvent { + + @Override + public String toString() { +- return "MouseEvent[" + +- "type=" + type + +- ", button=" + button + +- ", modifiers=" + modifiers + +- ", x=" + x + +- ", y=" + y + +- ']'; ++ return "MouseEvent[" + "type=" ++ + type + ", button=" ++ + button + ", modifiers=" ++ + modifiers + ", x=" ++ + x + ", y=" ++ + y + ']'; + } + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/Size.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/Size.java +index 29870ad62..fde3bf359 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/Size.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/Size.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2018, the original author or authors. ++ * Copyright (c) 2002-2018, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -13,9 +13,9 @@ public class Size { + private int rows; + private int cols; + +- public Size() { +- } ++ public Size() {} + ++ @SuppressWarnings("this-escape") + public Size(int columns, int rows) { + this(); + setColumns(columns); +@@ -50,7 +50,7 @@ public class Size { + * @return the cursor position + */ + public int cursorPos(int row, int col) { +- return row * (cols+1) + col; ++ return row * (cols + 1) + col; + } + + public void copy(Size size) { +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/Terminal.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/Terminal.java +index 38ffb029f..054915e13 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/Terminal.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/Terminal.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2018, the original author or authors. ++ * Copyright (c) 2002-2018, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -34,6 +34,7 @@ public interface Terminal extends Closeable, Flushable { + * Type used for dumb terminals. + */ + String TYPE_DUMB = "dumb"; + -+ public int hashCode() { -+ return id; -+ } -+} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/ProcDebuggerLocal.java jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/ProcDebuggerLocal.java ---- openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/ProcDebuggerLocal.java 2022-10-12 23:00:03.000000000 +0800 -+++ jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/ProcDebuggerLocal.java 2023-09-12 13:54:26.377575791 +0800 -@@ -32,11 +32,13 @@ - import sun.jvm.hotspot.debugger.cdbg.*; - import sun.jvm.hotspot.debugger.proc.amd64.*; - import sun.jvm.hotspot.debugger.proc.aarch64.*; -+import sun.jvm.hotspot.debugger.proc.mips64.*; - import sun.jvm.hotspot.debugger.proc.sparc.*; - import sun.jvm.hotspot.debugger.proc.ppc64.*; - import sun.jvm.hotspot.debugger.proc.x86.*; - import sun.jvm.hotspot.debugger.ppc64.*; - import sun.jvm.hotspot.debugger.amd64.*; -+import sun.jvm.hotspot.debugger.mips64.*; - import sun.jvm.hotspot.debugger.aarch64.*; - import sun.jvm.hotspot.debugger.sparc.*; - import sun.jvm.hotspot.debugger.x86.*; -@@ -90,6 +92,10 @@ - threadFactory = new ProcAMD64ThreadFactory(this); - pcRegIndex = AMD64ThreadContext.RIP; - fpRegIndex = AMD64ThreadContext.RBP; -+ } else if (cpu.equals("mips64") || cpu.equals("mips64el")) { -+ threadFactory = new ProcMIPS64ThreadFactory(this); -+ pcRegIndex = MIPS64ThreadContext.PC; -+ fpRegIndex = MIPS64ThreadContext.FP; - } else if (cpu.equals("aarch64")) { - threadFactory = new ProcAARCH64ThreadFactory(this); - pcRegIndex = AARCH64ThreadContext.PC; -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/loongarch64/RemoteLOONGARCH64ThreadContext.java jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/loongarch64/RemoteLOONGARCH64ThreadContext.java ---- openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/loongarch64/RemoteLOONGARCH64ThreadContext.java 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/loongarch64/RemoteLOONGARCH64ThreadContext.java 2023-09-12 13:54:26.377575791 +0800 -@@ -0,0 +1,51 @@ -+/* -+ * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2018, 2021, Loongson Technology. 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. -+ * -+ */ + String TYPE_DUMB_COLOR = "dumb-color"; + + String getName(); +@@ -42,6 +43,9 @@ public interface Terminal extends Closeable, Flushable { + // Signal support + // + ++ /** ++ * Types of signals. ++ */ + enum Signal { + INT, + QUIT, +@@ -51,16 +55,55 @@ public interface Terminal extends Closeable, Flushable { + WINCH + } + ++ /** ++ * The SignalHandler defines the interface used to trap signals and perform specific behaviors. ++ * @see Terminal.Signal ++ * @see Terminal#handle(Signal, SignalHandler) ++ */ + interface SignalHandler { + ++ /** ++ * The {@code SIG_DFL} value can be used to specify that the JVM default behavior ++ * should be used to handle this signal. ++ */ + SignalHandler SIG_DFL = NativeSignalHandler.SIG_DFL; + -+package sun.jvm.hotspot.debugger.remote.loongarch64; ++ /** ++ * The {@code SIG_IGN} value can be used to ignore this signal and not perform ++ * any special processing. ++ */ + SignalHandler SIG_IGN = NativeSignalHandler.SIG_IGN; + ++ /** ++ * Handle the signal. ++ * @param signal the signal ++ */ + void handle(Signal signal); + } + ++ /** ++ * Registers a handler for the given {@link Signal}. ++ *

++ * Note that the JVM does not easily allow catching the {@link Signal#QUIT} signal, which causes a thread dump ++ * to be displayed. This signal is mainly used when connecting through an SSH socket to a virtual terminal. ++ * ++ * @param signal the signal to register a handler for ++ * @param handler the handler ++ * @return the previous signal handler ++ */ + SignalHandler handle(Signal signal, SignalHandler handler); + ++ /** ++ * Raise the specific signal. ++ * This is not method usually called by non system terminals. ++ * When accessing a terminal through a SSH or Telnet connection, signals may be ++ * conveyed by the protocol and thus need to be raised when reaching the terminal code. ++ * The terminals do that automatically when the terminal input stream has a character ++ * mapped to {@link Attributes.ControlChar#VINTR}, {@link Attributes.ControlChar#VQUIT}, ++ * or {@link Attributes.ControlChar#VSUSP}. ++ * ++ * @param signal the signal to raise ++ */ + void raise(Signal signal); + + // +@@ -180,8 +223,21 @@ public interface Terminal extends Closeable, Flushable { + + boolean echo(boolean echo); + ++ /** ++ * Returns the terminal attributes. ++ * The returned object can be safely modified ++ * further used in a call to {@link #setAttributes(Attributes)}. ++ * ++ * @return the terminal attributes. ++ */ + Attributes getAttributes(); + ++ /** ++ * Set the terminal attributes. ++ * The terminal will perform a copy of the given attributes. ++ * ++ * @param attr the new attributes ++ */ + void setAttributes(Attributes attr); + + /** +@@ -334,5 +390,4 @@ public interface Terminal extends Closeable, Flushable { + * Color support + */ + ColorPalette getPalette(); +- + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/TerminalBuilder.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/TerminalBuilder.java +index 8c047e373..3b02ec2d8 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/TerminalBuilder.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/TerminalBuilder.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2021, the original author or authors. ++ * Copyright (c) 2002-2021, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -8,9 +8,6 @@ + */ + package jdk.internal.org.jline.terminal; + +-import java.io.FileDescriptor; +-import java.io.FileInputStream; +-import java.io.FileOutputStream; + import java.io.IOException; + import java.io.InputStream; + import java.io.OutputStream; +@@ -19,11 +16,16 @@ import java.nio.charset.Charset; + import java.nio.charset.StandardCharsets; + import java.nio.charset.UnsupportedCharsetException; + import java.util.ArrayList; ++import java.util.Arrays; ++import java.util.Collections; ++import java.util.Comparator; ++import java.util.HashSet; + import java.util.List; + import java.util.Locale; + import java.util.Map; + import java.util.Optional; + import java.util.ServiceLoader; ++import java.util.Set; + import java.util.concurrent.atomic.AtomicReference; + import java.util.function.Function; + import java.util.stream.Collectors; +@@ -31,8 +33,10 @@ import java.util.stream.Stream; + + import jdk.internal.org.jline.terminal.impl.AbstractPosixTerminal; + import jdk.internal.org.jline.terminal.impl.AbstractTerminal; +-import jdk.internal.org.jline.terminal.impl.AbstractWindowsTerminal; + import jdk.internal.org.jline.terminal.impl.DumbTerminal; ++import jdk.internal.org.jline.terminal.impl.DumbTerminalProvider; ++import jdk.internal.org.jline.terminal.spi.SystemStream; ++import jdk.internal.org.jline.terminal.spi.TerminalExt; + import jdk.internal.org.jline.terminal.spi.TerminalProvider; + import jdk.internal.org.jline.utils.Log; + import jdk.internal.org.jline.utils.OSUtils; +@@ -49,16 +53,30 @@ public final class TerminalBuilder { + public static final String PROP_ENCODING = "org.jline.terminal.encoding"; + public static final String PROP_CODEPAGE = "org.jline.terminal.codepage"; + public static final String PROP_TYPE = "org.jline.terminal.type"; +- public static final String PROP_JNA = "org.jline.terminal.jna"; +- public static final String PROP_JANSI = "org.jline.terminal.jansi"; +- public static final String PROP_EXEC = "org.jline.terminal.exec"; +- public static final String PROP_DUMB = "org.jline.terminal.dumb"; ++ public static final String PROP_PROVIDER = "org.jline.terminal.provider"; ++ public static final String PROP_PROVIDERS = "org.jline.terminal.providers"; ++ public static final String PROP_PROVIDER_FFM = "ffm"; ++ public static final String PROP_PROVIDER_JNI = "jni"; ++ public static final String PROP_PROVIDER_JANSI = "jansi"; ++ public static final String PROP_PROVIDER_JNA = "jna"; ++ public static final String PROP_PROVIDER_EXEC = "exec"; ++ public static final String PROP_PROVIDER_DUMB = "dumb"; ++ public static final String PROP_PROVIDERS_DEFAULT = String.join( ++ ",", PROP_PROVIDER_FFM, PROP_PROVIDER_JNI, PROP_PROVIDER_JANSI, PROP_PROVIDER_JNA, PROP_PROVIDER_EXEC); ++ public static final String PROP_FFM = "org.jline.terminal." + PROP_PROVIDER_FFM; ++ public static final String PROP_JNI = "org.jline.terminal." + PROP_PROVIDER_JNI; ++ public static final String PROP_JANSI = "org.jline.terminal." + PROP_PROVIDER_JANSI; ++ public static final String PROP_JNA = "org.jline.terminal." + PROP_PROVIDER_JNA; ++ public static final String PROP_EXEC = "org.jline.terminal." + PROP_PROVIDER_EXEC; ++ public static final String PROP_DUMB = "org.jline.terminal." + PROP_PROVIDER_DUMB; + public static final String PROP_DUMB_COLOR = "org.jline.terminal.dumb.color"; + public static final String PROP_OUTPUT = "org.jline.terminal.output"; + public static final String PROP_OUTPUT_OUT = "out"; + public static final String PROP_OUTPUT_ERR = "err"; + public static final String PROP_OUTPUT_OUT_ERR = "out-err"; + public static final String PROP_OUTPUT_ERR_OUT = "err-out"; ++ public static final String PROP_OUTPUT_FORCED_OUT = "forced-out"; ++ public static final String PROP_OUTPUT_FORCED_ERR = "forced-err"; + + // + // Other system properties controlling various jline parts +@@ -68,6 +86,32 @@ public final class TerminalBuilder { + public static final String PROP_COLOR_DISTANCE = "org.jline.utils.colorDistance"; + public static final String PROP_DISABLE_ALTERNATE_CHARSET = "org.jline.utils.disableAlternateCharset"; + ++ // ++ // System properties controlling how FileDescriptor are create. ++ // The value can be a comma separated list of defined mechanisms. ++ // ++ public static final String PROP_FILE_DESCRIPTOR_CREATION_MODE = "org.jline.terminal.pty.fileDescriptorCreationMode"; ++ public static final String PROP_FILE_DESCRIPTOR_CREATION_MODE_NATIVE = "native"; ++ public static final String PROP_FILE_DESCRIPTOR_CREATION_MODE_REFLECTION = "reflection"; ++ public static final String PROP_FILE_DESCRIPTOR_CREATION_MODE_DEFAULT = ++ String.join(",", PROP_FILE_DESCRIPTOR_CREATION_MODE_REFLECTION, PROP_FILE_DESCRIPTOR_CREATION_MODE_NATIVE); + -+import sun.jvm.hotspot.debugger.*; -+import sun.jvm.hotspot.debugger.loongarch64.*; -+import sun.jvm.hotspot.debugger.remote.*; ++ // ++ // System properties controlling how RedirectPipe are created. ++ // The value can be a comma separated list of defined mechanisms. ++ // ++ public static final String PROP_REDIRECT_PIPE_CREATION_MODE = "org.jline.terminal.exec.redirectPipeCreationMode"; ++ public static final String PROP_REDIRECT_PIPE_CREATION_MODE_NATIVE = "native"; ++ public static final String PROP_REDIRECT_PIPE_CREATION_MODE_REFLECTION = "reflection"; ++ public static final String PROP_REDIRECT_PIPE_CREATION_MODE_DEFAULT = ++ String.join(",", PROP_REDIRECT_PIPE_CREATION_MODE_REFLECTION, PROP_REDIRECT_PIPE_CREATION_MODE_NATIVE); + -+public class RemoteLOONGARCH64ThreadContext extends LOONGARCH64ThreadContext { -+ private RemoteDebuggerClient debugger; ++ public static final Set DEPRECATED_PROVIDERS = ++ Collections.unmodifiableSet(new HashSet<>(Arrays.asList(PROP_PROVIDER_JNA, PROP_PROVIDER_JANSI))); + -+ public RemoteLOONGARCH64ThreadContext(RemoteDebuggerClient debugger) { -+ super(); -+ this.debugger = debugger; -+ } ++ public static final String PROP_DISABLE_DEPRECATED_PROVIDER_WARNING = ++ "org.jline.terminal.disableDeprecatedProviderWarning"; + -+ /** This can't be implemented in this class since we would have to -+ tie the implementation to, for example, the debugging system */ -+ public void setRegisterAsAddress(int index, Address value) { -+ setRegister(index, debugger.getAddressValue(value)); -+ } + // + // Terminal output control + // +@@ -75,7 +119,9 @@ public final class TerminalBuilder { + SysOut, + SysErr, + SysOutOrSysErr, +- SysErrOrSysOut ++ SysErrOrSysOut, ++ ForcedSysOut, ++ ForcedSysErr + } + + /** +@@ -115,20 +161,23 @@ public final class TerminalBuilder { + private int codepage; + private Boolean system; + private SystemOutput systemOutput; ++ private String provider; ++ private String providers; + private Boolean jna; + private Boolean jansi; ++ private Boolean jni; + private Boolean exec; ++ private Boolean ffm; + private Boolean dumb; + private Boolean color; + private Attributes attributes; + private Size size; +- private boolean nativeSignals = false; ++ private boolean nativeSignals = true; + private Function inputStreamWrapper = in -> in; + private Terminal.SignalHandler signalHandler = Terminal.SignalHandler.SIG_DFL; + private boolean paused = false; + +- private TerminalBuilder() { +- } ++ private TerminalBuilder() {} + + public TerminalBuilder name(String name) { + this.name = name; +@@ -160,6 +209,16 @@ public final class TerminalBuilder { + return this; + } + ++ public TerminalBuilder provider(String provider) { ++ this.provider = provider; ++ return this; ++ } + -+ /** This can't be implemented in this class since we would have to -+ tie the implementation to, for example, the debugging system */ -+ public Address getRegisterAsAddress(int index) { -+ return debugger.newAddress(getRegister(index)); -+ } -+} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/loongarch64/RemoteLOONGARCH64ThreadFactory.java jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/loongarch64/RemoteLOONGARCH64ThreadFactory.java ---- openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/loongarch64/RemoteLOONGARCH64ThreadFactory.java 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/loongarch64/RemoteLOONGARCH64ThreadFactory.java 2023-09-12 13:54:26.377575791 +0800 -@@ -0,0 +1,45 @@ -+/* -+ * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2018, 2021, Loongson Technology. 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. -+ * -+ */ ++ public TerminalBuilder providers(String providers) { ++ this.providers = providers; ++ return this; ++ } + -+package sun.jvm.hotspot.debugger.remote.loongarch64; + public TerminalBuilder jna(boolean jna) { + this.jna = jna; + return this; +@@ -170,11 +229,21 @@ public final class TerminalBuilder { + return this; + } + ++ public TerminalBuilder jni(boolean jni) { ++ this.jni = jni; ++ return this; ++ } + -+import sun.jvm.hotspot.debugger.*; -+import sun.jvm.hotspot.debugger.remote.*; + public TerminalBuilder exec(boolean exec) { + this.exec = exec; + return this; + } + ++ public TerminalBuilder ffm(boolean ffm) { ++ this.ffm = ffm; ++ return this; ++ } + -+public class RemoteLOONGARCH64ThreadFactory implements RemoteThreadFactory { -+ private RemoteDebuggerClient debugger; + public TerminalBuilder dumb(boolean dumb) { + this.dumb = dumb; + return this; +@@ -280,6 +349,12 @@ public final class TerminalBuilder { + return this; + } + ++ /** ++ * Determines the default value for signal handlers. ++ * All signals will be mapped to the given handler. ++ * @param signalHandler the default signal handler ++ * @return The builder ++ */ + public TerminalBuilder signalHandler(Terminal.SignalHandler signalHandler) { + this.signalHandler = signalHandler; + return this; +@@ -305,6 +380,11 @@ public final class TerminalBuilder { + return this; + } + ++ /** ++ * Builds the terminal. ++ * @return the newly created terminal, never {@code null} ++ * @throws IOException if an error occurs ++ */ + public Terminal build() throws IOException { + Terminal override = TERMINAL_OVERRIDE.get(); + Terminal terminal = override != null ? override : doBuild(); +@@ -313,7 +393,8 @@ public final class TerminalBuilder { + } + Log.debug(() -> "Using terminal " + terminal.getClass().getSimpleName()); + if (terminal instanceof AbstractPosixTerminal) { +- Log.debug(() -> "Using pty " + ((AbstractPosixTerminal) terminal).getPty().getClass().getSimpleName()); ++ Log.debug(() -> "Using pty " ++ + ((AbstractPosixTerminal) terminal).getPty().getClass().getSimpleName()); + } + return terminal; + } +@@ -323,144 +404,76 @@ public final class TerminalBuilder { + if (name == null) { + name = "JLine terminal"; + } +- Charset encoding = this.encoding; +- if (encoding == null) { +- String charsetName = System.getProperty(PROP_ENCODING); +- if (charsetName != null && Charset.isSupported(charsetName)) { +- encoding = Charset.forName(charsetName); +- } +- } +- if (encoding == null) { +- int codepage = this.codepage; +- if (codepage <= 0) { +- String str = System.getProperty(PROP_CODEPAGE); +- if (str != null) { +- codepage = Integer.parseInt(str); +- } +- } +- if (codepage >= 0) { +- encoding = getCodepageCharset(codepage); +- } else { +- encoding = StandardCharsets.UTF_8; +- } +- } +- String type = this.type; +- if (type == null) { +- type = System.getProperty(PROP_TYPE); +- } +- if (type == null) { +- type = System.getenv("TERM"); +- } +- Boolean jna = this.jna; +- if (jna == null) { +- jna = getBoolean(PROP_JNA, true); +- } +- Boolean jansi = this.jansi; +- if (jansi == null) { +- jansi = getBoolean(PROP_JANSI, true); +- } +- Boolean exec = this.exec; +- if (exec == null) { +- exec = getBoolean(PROP_EXEC, true); ++ Charset encoding = computeEncoding(); ++ String type = computeType(); ++ ++ String provider = this.provider; ++ if (provider == null) { ++ provider = System.getProperty(PROP_PROVIDER, null); + } + -+ public RemoteLOONGARCH64ThreadFactory(RemoteDebuggerClient debugger) { -+ this.debugger = debugger; -+ } ++ boolean forceDumb = ++ (DumbTerminal.TYPE_DUMB.equals(type) || type != null && type.startsWith(DumbTerminal.TYPE_DUMB_COLOR)) ++ || (provider != null && provider.equals(PROP_PROVIDER_DUMB)); + Boolean dumb = this.dumb; + if (dumb == null) { + dumb = getBoolean(PROP_DUMB, null); + } + IllegalStateException exception = new IllegalStateException("Unable to create a terminal"); +- List providers = new ArrayList<>(); +- if (jna) { +- try { +- TerminalProvider provider = TerminalProvider.load("jna"); +- providers.add(provider); +- } catch (Throwable t) { +- Log.debug("Unable to load JNA support: ", t); +- exception.addSuppressed(t); +- } +- } +- if (jansi) { +- try { +- TerminalProvider provider = TerminalProvider.load("jansi"); +- providers.add(provider); +- } catch (Throwable t) { +- Log.debug("Unable to load JANSI support: ", t); +- exception.addSuppressed(t); +- } +- } +- if (exec) +- { +- try { +- TerminalProvider provider = TerminalProvider.load("exec"); +- providers.add(provider); +- } catch (Throwable t) { +- Log.debug("Unable to load EXEC support: ", t); +- exception.addSuppressed(t); +- } +- } +- ++ List providers = getProviders(provider, exception); + Terminal terminal = null; + if ((system != null && system) || (system == null && in == null && out == null)) { +- if (system != null && ((in != null && !in.equals(System.in)) || +- (out != null && !out.equals(System.out) && !out.equals(System.err)))) { ++ if (system != null ++ && ((in != null && !in.equals(System.in)) ++ || (out != null && !out.equals(System.out) && !out.equals(System.err)))) { + throw new IllegalArgumentException("Cannot create a system terminal using non System streams"); + } + if (attributes != null || size != null) { + Log.warn("Attributes and size fields are ignored when creating a system terminal"); + } +- if (out != null) { +- if (out.equals(System.out)) { +- systemOutput = SystemOutput.SysOut; +- } else if (out.equals(System.err)) { +- systemOutput = SystemOutput.SysErr; +- } +- } +- if (systemOutput == null) { +- String str = System.getProperty(PROP_OUTPUT); +- if (str != null) { +- switch (str.trim().toLowerCase(Locale.ROOT)) { +- case PROP_OUTPUT_OUT: systemOutput = SystemOutput.SysOut; break; +- case PROP_OUTPUT_ERR: systemOutput = SystemOutput.SysErr; break; +- case PROP_OUTPUT_OUT_ERR: systemOutput = SystemOutput.SysOutOrSysErr; break; +- case PROP_OUTPUT_ERR_OUT: systemOutput = SystemOutput.SysErrOrSysOut; break; +- default: +- Log.debug("Unsupported value for " + PROP_OUTPUT + ": " + str + ". Supported values are: " +- + String.join(", ", PROP_OUTPUT_OUT, PROP_OUTPUT_ERR, PROP_OUTPUT_OUT_ERR,PROP_OUTPUT_ERR_OUT) +- + "."); +- } +- } +- } +- if (systemOutput == null) { +- systemOutput = SystemOutput.SysOutOrSysErr; +- } +- Map system = Stream.of(TerminalProvider.Stream.values()) +- .collect(Collectors.toMap(stream -> stream, stream -> providers.stream().anyMatch(p -> p.isSystemStream(stream)))); +- TerminalProvider.Stream console = select(system, systemOutput); ++ SystemOutput systemOutput = computeSystemOutput(); ++ Map system = Stream.of(SystemStream.values()) ++ .collect(Collectors.toMap( ++ stream -> stream, stream -> providers.stream().anyMatch(p -> p.isSystemStream(stream)))); ++ SystemStream systemStream = select(system, systemOutput); + +- if (system.get(TerminalProvider.Stream.Input) && console != null) { ++ if (!forceDumb && system.get(SystemStream.Input) && systemStream != null) { + if (attributes != null || size != null) { + Log.warn("Attributes and size fields are ignored when creating a system terminal"); + } + boolean ansiPassThrough = OSUtils.IS_CONEMU; + // Cygwin defaults to XTERM, but actually supports 256 colors, + // so if the value comes from the environment, change it to xterm-256color +- if ((OSUtils.IS_CYGWIN || OSUtils.IS_MSYSTEM) && "xterm".equals(type) +- && this.type == null && System.getProperty(PROP_TYPE) == null) { ++ if ((OSUtils.IS_CYGWIN || OSUtils.IS_MSYSTEM) ++ && "xterm".equals(type) ++ && this.type == null ++ && System.getProperty(PROP_TYPE) == null) { + type = "xterm-256color"; + } +- for ( TerminalProvider provider : providers) { ++ for (TerminalProvider prov : providers) { + if (terminal == null) { + try { +- terminal = provider.sysTerminal(name, type, ansiPassThrough, encoding, +- nativeSignals, signalHandler, paused, console, inputStreamWrapper); ++ terminal = prov.sysTerminal( ++ name, ++ type, ++ ansiPassThrough, ++ encoding, ++ nativeSignals, ++ signalHandler, ++ paused, ++ systemStream, ++ inputStreamWrapper); + } catch (Throwable t) { +- Log.debug("Error creating " + provider.name() + " based terminal: ", t.getMessage(), t); ++ Log.debug("Error creating " + prov.name() + " based terminal: ", t.getMessage(), t); + exception.addSuppressed(t); + } + } + } +- if (terminal == null && OSUtils.IS_WINDOWS && !jna && !jansi && (dumb == null || !dumb)) { +- throw new IllegalStateException("Unable to create a system terminal. On windows, either " +- + "JNA or JANSI library is required. Make sure to add one of those in the classpath."); ++ if (terminal == null && OSUtils.IS_WINDOWS && providers.isEmpty() && (dumb == null || !dumb)) { ++ throw new IllegalStateException( ++ "Unable to create a system terminal. On Windows, either JLine's native libraries, JNA " ++ + "or Jansi library is required. Make sure to add one of those in the classpath.", ++ exception); + } + } + if (terminal instanceof AbstractTerminal) { +@@ -468,54 +481,42 @@ public final class TerminalBuilder { + if (SYSTEM_TERMINAL.compareAndSet(null, t)) { + t.setOnClose(() -> SYSTEM_TERMINAL.compareAndSet(t, null)); + } else { +- exception.addSuppressed(new IllegalStateException("A system terminal is already running. " + +- "Make sure to use the created system Terminal on the LineReaderBuilder if you're using one " + +- "or that previously created system Terminals have been correctly closed.")); ++ exception.addSuppressed(new IllegalStateException("A system terminal is already running. " ++ + "Make sure to use the created system Terminal on the LineReaderBuilder if you're using one " ++ + "or that previously created system Terminals have been correctly closed.")); + terminal.close(); + terminal = null; + } + } +- if (terminal == null && (dumb == null || dumb)) { +- // forced colored dumb terminal +- Boolean color = this.color; +- if (color == null) { +- color = getBoolean(PROP_DUMB_COLOR, false); +- // detect emacs using the env variable +- if (!color) { +- String emacs = System.getenv("INSIDE_EMACS"); +- color = emacs != null && emacs.contains("comint"); +- } +- // detect Intellij Idea +- if (!color) { +- String command = getParentProcessCommand(); +- color = command != null && command.contains("idea"); +- } +- if (!color) { +- color = system.get(TerminalProvider.Stream.Output) && System.getenv("TERM") != null; +- } +- if (!color && dumb == null) { +- if (Log.isDebugEnabled()) { +- Log.warn("input is tty: {}", system.get(TerminalProvider.Stream.Input)); +- Log.warn("output is tty: {}", system.get(TerminalProvider.Stream.Output)); +- Log.warn("error is tty: {}", system.get(TerminalProvider.Stream.Error)); +- Log.warn("Creating a dumb terminal", exception); +- } else { +- Log.warn("Unable to create a system terminal, creating a dumb terminal (enable debug logging for more information)"); +- } ++ if (terminal == null && (forceDumb || dumb == null || dumb)) { ++ if (!forceDumb && dumb == null) { ++ if (Log.isDebugEnabled()) { ++ Log.warn("input is tty: " + system.get(SystemStream.Input)); ++ Log.warn("output is tty: " + system.get(SystemStream.Output)); ++ Log.warn("error is tty: " + system.get(SystemStream.Error)); ++ Log.warn("Creating a dumb terminal", exception); ++ } else { ++ Log.warn( ++ "Unable to create a system terminal, creating a dumb terminal (enable debug logging for more information)"); + } + } +- terminal = new DumbTerminal(name, color ? Terminal.TYPE_DUMB_COLOR : Terminal.TYPE_DUMB, +- new FileInputStream(FileDescriptor.in), +- new FileOutputStream(console == TerminalProvider.Stream.Output ? FileDescriptor.out : FileDescriptor.err), +- encoding, signalHandler); ++ type = getDumbTerminalType(dumb, systemStream); ++ terminal = new DumbTerminalProvider() ++ .sysTerminal(name, type, false, encoding, nativeSignals, signalHandler, paused, systemStream, inputStreamWrapper); ++ if (OSUtils.IS_WINDOWS) { ++ Attributes attr = terminal.getAttributes(); ++ attr.setInputFlag(Attributes.InputFlag.IGNCR, true); ++ terminal.setAttributes(attr); ++ } + } + } else { +- for ( TerminalProvider provider : providers) { ++ for (TerminalProvider prov : providers) { + if (terminal == null) { + try { +- terminal = provider.newTerminal(name, type, inputStreamWrapper.apply(in), out, encoding, signalHandler, paused, attributes, size); ++ terminal = prov.newTerminal( ++ name, type, in, out, encoding, signalHandler, paused, attributes, size); + } catch (Throwable t) { +- Log.debug("Error creating " + provider.name() + " based terminal: ", t.getMessage(), t); ++ Log.debug("Error creating " + prov.name() + " based terminal: ", t.getMessage(), t); + exception.addSuppressed(t); + } + } +@@ -524,25 +525,220 @@ public final class TerminalBuilder { + if (terminal == null) { + throw exception; + } ++ if (terminal instanceof TerminalExt) { ++ TerminalExt te = (TerminalExt) terminal; ++ if (DEPRECATED_PROVIDERS.contains(te.getProvider().name()) ++ && !getBoolean(PROP_DISABLE_DEPRECATED_PROVIDER_WARNING, false)) { ++ Log.warn("The terminal provider " + te.getProvider().name() ++ + " has been deprecated, check your configuration. This warning can be disabled by setting the system property " ++ + PROP_DISABLE_DEPRECATED_PROVIDER_WARNING + " to true."); ++ } ++ } + return terminal; + } + +- private TerminalProvider.Stream select(Map system, SystemOutput systemOutput) { ++ private String getDumbTerminalType(Boolean dumb, SystemStream systemStream) { ++ // forced colored dumb terminal ++ Boolean color = this.color; ++ if (color == null) { ++ color = getBoolean(PROP_DUMB_COLOR, null); ++ } ++ if (dumb == null) { ++ // detect emacs using the env variable ++ if (color == null) { ++ String emacs = System.getenv("INSIDE_EMACS"); ++ if (emacs != null && emacs.contains("comint")) { ++ color = true; ++ } ++ } ++ // detect Intellij Idea ++ if (color == null) { ++ // using the env variable on windows ++ String ideHome = System.getenv("IDE_HOME"); ++ if (ideHome != null) { ++ color = true; ++ } else { ++ // using the parent process command on unix/mac ++ String command = getParentProcessCommand(); ++ if (command != null && command.endsWith("/idea")) { ++ color = true; ++ } ++ } ++ } ++ if (color == null) { ++ color = systemStream != null && System.getenv("TERM") != null; ++ } ++ } else { ++ if (color == null) { ++ color = false; ++ } ++ } ++ return color ? Terminal.TYPE_DUMB_COLOR : Terminal.TYPE_DUMB; ++ } + -+ public ThreadProxy createThreadWrapper(Address threadIdentifierAddr) { -+ return new RemoteLOONGARCH64Thread(debugger, threadIdentifierAddr); -+ } ++ public SystemOutput computeSystemOutput() { ++ SystemOutput systemOutput = null; ++ if (out != null) { ++ if (out.equals(System.out)) { ++ systemOutput = SystemOutput.SysOut; ++ } else if (out.equals(System.err)) { ++ systemOutput = SystemOutput.SysErr; ++ } ++ } ++ if (systemOutput == null) { ++ systemOutput = this.systemOutput; ++ } ++ if (systemOutput == null) { ++ String str = System.getProperty(PROP_OUTPUT); ++ if (str != null) { ++ switch (str.trim().toLowerCase(Locale.ROOT)) { ++ case PROP_OUTPUT_OUT: ++ systemOutput = SystemOutput.SysOut; ++ break; ++ case PROP_OUTPUT_ERR: ++ systemOutput = SystemOutput.SysErr; ++ break; ++ case PROP_OUTPUT_OUT_ERR: ++ systemOutput = SystemOutput.SysOutOrSysErr; ++ break; ++ case PROP_OUTPUT_ERR_OUT: ++ systemOutput = SystemOutput.SysErrOrSysOut; ++ break; ++ case PROP_OUTPUT_FORCED_OUT: ++ systemOutput = SystemOutput.ForcedSysOut; ++ break; ++ case PROP_OUTPUT_FORCED_ERR: ++ systemOutput = SystemOutput.ForcedSysErr; ++ break; ++ default: ++ Log.debug("Unsupported value for " + PROP_OUTPUT + ": " + str + ". Supported values are: " ++ + String.join( ++ ", ", ++ PROP_OUTPUT_OUT, ++ PROP_OUTPUT_ERR, ++ PROP_OUTPUT_OUT_ERR, ++ PROP_OUTPUT_ERR_OUT) ++ + "."); ++ } ++ } ++ } ++ if (systemOutput == null) { ++ systemOutput = SystemOutput.SysOutOrSysErr; ++ } ++ return systemOutput; ++ } + -+ public ThreadProxy createThreadWrapper(long id) { -+ return new RemoteLOONGARCH64Thread(debugger, id); -+ } -+} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/loongarch64/RemoteLOONGARCH64Thread.java jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/loongarch64/RemoteLOONGARCH64Thread.java ---- openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/loongarch64/RemoteLOONGARCH64Thread.java 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/loongarch64/RemoteLOONGARCH64Thread.java 2023-09-12 13:54:26.377575791 +0800 -@@ -0,0 +1,54 @@ -+/* -+ * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2018, 2021, Loongson Technology. 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. -+ * -+ */ ++ public String computeType() { ++ String type = this.type; ++ if (type == null) { ++ type = System.getProperty(PROP_TYPE); ++ } ++ if (type == null) { ++ type = System.getenv("TERM"); ++ } ++ return type; ++ } + -+package sun.jvm.hotspot.debugger.remote.loongarch64; ++ public Charset computeEncoding() { ++ Charset encoding = this.encoding; ++ if (encoding == null) { ++ String charsetName = System.getProperty(PROP_ENCODING); ++ if (charsetName != null && Charset.isSupported(charsetName)) { ++ encoding = Charset.forName(charsetName); ++ } ++ } ++ if (encoding == null) { ++ int codepage = this.codepage; ++ if (codepage <= 0) { ++ String str = System.getProperty(PROP_CODEPAGE); ++ if (str != null) { ++ codepage = Integer.parseInt(str); ++ } ++ } ++ if (codepage >= 0) { ++ encoding = getCodepageCharset(codepage); ++ } else { ++ encoding = StandardCharsets.UTF_8; ++ } ++ } ++ return encoding; ++ } + -+import sun.jvm.hotspot.debugger.*; -+import sun.jvm.hotspot.debugger.loongarch64.*; -+import sun.jvm.hotspot.debugger.remote.*; -+import sun.jvm.hotspot.utilities.*; ++ /** ++ * Get the list of available terminal providers. ++ * This list is sorted according to the {@link #PROP_PROVIDERS} system property. ++ * @param provider if not {@code null}, only this provider will be checked ++ * @param exception if a provider throws an exception, it will be added to this exception as a suppressed exception ++ * @return a list of terminal providers ++ */ ++ public List getProviders(String provider, IllegalStateException exception) { ++ List providers = new ArrayList<>(); ++ // Check ffm provider ++ checkProvider(provider, exception, providers, ffm, PROP_FFM, PROP_PROVIDER_FFM); ++ // Check jni provider ++ checkProvider(provider, exception, providers, jni, PROP_JNI, PROP_PROVIDER_JNI); ++ // Check jansi provider ++ checkProvider(provider, exception, providers, jansi, PROP_JANSI, PROP_PROVIDER_JANSI); ++ // Check jna provider ++ checkProvider(provider, exception, providers, jna, PROP_JNA, PROP_PROVIDER_JNA); ++ // Check exec provider ++ checkProvider(provider, exception, providers, exec, PROP_EXEC, PROP_PROVIDER_EXEC); ++ // Order providers ++ List order = Arrays.asList( ++ (this.providers != null ? this.providers : System.getProperty(PROP_PROVIDERS, PROP_PROVIDERS_DEFAULT)) ++ .split(",")); ++ providers.sort(Comparator.comparing(l -> { ++ int idx = order.indexOf(l.name()); ++ return idx >= 0 ? idx : Integer.MAX_VALUE; ++ })); ++ String names = providers.stream().map(TerminalProvider::name).collect(Collectors.joining(", ")); ++ Log.debug("Available providers: " + names); ++ return providers; ++ } ++ ++ private void checkProvider( ++ String provider, ++ IllegalStateException exception, ++ List providers, ++ Boolean load, ++ String property, ++ String name) { ++ Boolean doLoad = provider != null ? (Boolean) name.equals(provider) : load; ++ if (doLoad == null) { ++ doLoad = getBoolean(property, true); ++ } ++ if (doLoad) { ++ try { ++ TerminalProvider prov = TerminalProvider.load(name); ++ prov.isSystemStream(SystemStream.Output); ++ providers.add(prov); ++ } catch (Throwable t) { ++ Log.debug("Unable to load " + name + " provider: ", t); ++ exception.addSuppressed(t); ++ } ++ } ++ } + -+public class RemoteLOONGARCH64Thread extends RemoteThread { -+ public RemoteLOONGARCH64Thread(RemoteDebuggerClient debugger, Address addr) { -+ super(debugger, addr); -+ } ++ private SystemStream select(Map system, SystemOutput systemOutput) { + switch (systemOutput) { + case SysOut: +- return select(system, TerminalProvider.Stream.Output); ++ return select(system, SystemStream.Output); + case SysErr: +- return select(system, TerminalProvider.Stream.Error); ++ return select(system, SystemStream.Error); + case SysOutOrSysErr: +- return select(system, TerminalProvider.Stream.Output, TerminalProvider.Stream.Error); ++ return select(system, SystemStream.Output, SystemStream.Error); + case SysErrOrSysOut: +- return select(system, TerminalProvider.Stream.Error, TerminalProvider.Stream.Output); ++ return select(system, SystemStream.Error, SystemStream.Output); ++ case ForcedSysOut: ++ return SystemStream.Output; ++ case ForcedSysErr: ++ return SystemStream.Error; + } + return null; + } + +- private static TerminalProvider.Stream select(Map system, TerminalProvider.Stream... streams) { +- for (TerminalProvider.Stream s : streams) { ++ private static SystemStream select(Map system, SystemStream... streams) { ++ for (SystemStream s : streams) { + if (system.get(s)) { + return s; + } +@@ -557,7 +753,9 @@ public final class TerminalBuilder { + Object parent = ((Optional) phClass.getMethod("parent").invoke(current)).orElse(null); + Method infoMethod = phClass.getMethod("info"); + Object info = infoMethod.invoke(parent); +- Object command = ((Optional) infoMethod.getReturnType().getMethod("command").invoke(info)).orElse(null); ++ Object command = ((Optional) ++ infoMethod.getReturnType().getMethod("command").invoke(info)) ++ .orElse(null); + return (String) command; + } catch (Throwable t) { + return null; +@@ -582,7 +780,7 @@ public final class TerminalBuilder { + private static final int UTF8_CODE_PAGE = 65001; + + private static Charset getCodepageCharset(int codepage) { +- //http://docs.oracle.com/javase/6/docs/technotes/guides/intl/encoding.doc.html ++ // http://docs.oracle.com/javase/6/docs/technotes/guides/intl/encoding.doc.html + if (codepage == UTF8_CODE_PAGE) { + return StandardCharsets.UTF_8; + } +@@ -629,5 +827,4 @@ public final class TerminalBuilder { + public static void setTerminalOverride(final Terminal terminal) { + TERMINAL_OVERRIDE.set(terminal); + } +- + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractPosixTerminal.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractPosixTerminal.java +index b5f55b80f..5d000d070 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractPosixTerminal.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractPosixTerminal.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2016, the original author or authors. ++ * Copyright (c) 2002-2016, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -18,6 +18,8 @@ import jdk.internal.org.jline.terminal.Attributes; + import jdk.internal.org.jline.terminal.Cursor; + import jdk.internal.org.jline.terminal.Size; + import jdk.internal.org.jline.terminal.spi.Pty; ++import jdk.internal.org.jline.terminal.spi.SystemStream; ++import jdk.internal.org.jline.terminal.spi.TerminalProvider; + + public abstract class AbstractPosixTerminal extends AbstractTerminal { + +@@ -28,7 +30,8 @@ public abstract class AbstractPosixTerminal extends AbstractTerminal { + this(name, type, pty, null, SignalHandler.SIG_DFL); + } + +- public AbstractPosixTerminal(String name, String type, Pty pty, Charset encoding, SignalHandler signalHandler) throws IOException { ++ public AbstractPosixTerminal(String name, String type, Pty pty, Charset encoding, SignalHandler signalHandler) ++ throws IOException { + super(name, type, encoding, signalHandler); + Objects.requireNonNull(pty); + this.pty = pty; +@@ -82,4 +85,13 @@ public abstract class AbstractPosixTerminal extends AbstractTerminal { + return CursorSupport.getCursorPosition(this, discarded); + } + ++ @Override ++ public TerminalProvider getProvider() { ++ return getPty().getProvider(); ++ } + -+ public RemoteLOONGARCH64Thread(RemoteDebuggerClient debugger, long id) { -+ super(debugger, id); -+ } ++ @Override ++ public SystemStream getSystemStream() { ++ return getPty().getSystemStream(); ++ } + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractPty.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractPty.java +index 0feab84fc..3fbe63f3c 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractPty.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractPty.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2019, the original author or authors. ++ * Copyright (c) 2002-2019, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -8,20 +8,39 @@ + */ + package jdk.internal.org.jline.terminal.impl; + +-import jdk.internal.org.jline.terminal.Attributes; +-import jdk.internal.org.jline.terminal.spi.Pty; +-import jdk.internal.org.jline.utils.NonBlockingInputStream; +- ++import java.io.FileDescriptor; ++import java.io.FilterInputStream; + import java.io.IOError; + import java.io.IOException; + import java.io.InputStream; + import java.io.InterruptedIOException; ++import java.lang.reflect.Field; ++ ++//import jdk.internal.org.jline.nativ.JLineLibrary; ++//import jdk.internal.org.jline.nativ.JLineNativeLoader; ++import jdk.internal.org.jline.terminal.Attributes; ++import jdk.internal.org.jline.terminal.spi.Pty; ++import jdk.internal.org.jline.terminal.spi.SystemStream; ++import jdk.internal.org.jline.terminal.spi.TerminalProvider; ++import jdk.internal.org.jline.utils.NonBlockingInputStream; + ++import static jdk.internal.org.jline.terminal.TerminalBuilder.PROP_FILE_DESCRIPTOR_CREATION_MODE; ++import static jdk.internal.org.jline.terminal.TerminalBuilder.PROP_FILE_DESCRIPTOR_CREATION_MODE_DEFAULT; ++import static jdk.internal.org.jline.terminal.TerminalBuilder.PROP_FILE_DESCRIPTOR_CREATION_MODE_NATIVE; ++import static jdk.internal.org.jline.terminal.TerminalBuilder.PROP_FILE_DESCRIPTOR_CREATION_MODE_REFLECTION; + import static jdk.internal.org.jline.terminal.TerminalBuilder.PROP_NON_BLOCKING_READS; + + public abstract class AbstractPty implements Pty { + ++ protected final TerminalProvider provider; ++ protected final SystemStream systemStream; + private Attributes current; ++ private boolean skipNextLf; + -+ public ThreadContext getContext() throws IllegalThreadStateException { -+ RemoteLOONGARCH64ThreadContext context = new RemoteLOONGARCH64ThreadContext(debugger); -+ long[] regs = (addr != null)? debugger.getThreadIntegerRegisterSet(addr) : -+ debugger.getThreadIntegerRegisterSet(id); -+ if (Assert.ASSERTS_ENABLED) { -+ Assert.that(regs.length == LOONGARCH64ThreadContext.NPRGREG, "size of register set must match"); ++ public AbstractPty(TerminalProvider provider, SystemStream systemStream) { ++ this.provider = provider; ++ this.systemStream = systemStream; + } -+ for (int i = 0; i < regs.length; i++) { -+ context.setRegister(i, regs[i]); + + @Override + public void setAttr(Attributes attr) throws IOException { +@@ -32,10 +51,32 @@ public abstract class AbstractPty implements Pty { + @Override + public InputStream getSlaveInput() throws IOException { + InputStream si = doGetSlaveInput(); ++ InputStream nsi = new FilterInputStream(si) { ++ @Override ++ public int read() throws IOException { ++ for (; ; ) { ++ int c = super.read(); ++ if (current.getInputFlag(Attributes.InputFlag.INORMEOL)) { ++ if (c == '\r') { ++ skipNextLf = true; ++ c = '\n'; ++ } else if (c == '\n') { ++ if (skipNextLf) { ++ skipNextLf = false; ++ continue; ++ } ++ } else { ++ skipNextLf = false; ++ } ++ } ++ return c; ++ } ++ } ++ }; + if (Boolean.parseBoolean(System.getProperty(PROP_NON_BLOCKING_READS, "true"))) { +- return new PtyInputStream(si); ++ return new PtyInputStream(nsi); + } else { +- return si; ++ return nsi; + } + } + +@@ -49,6 +90,16 @@ public abstract class AbstractPty implements Pty { + } + } + ++ @Override ++ public TerminalProvider getProvider() { ++ return provider; + } -+ return context; -+ } -+} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/mips64/RemoteMIPS64ThreadContext.java jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/mips64/RemoteMIPS64ThreadContext.java ---- openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/mips64/RemoteMIPS64ThreadContext.java 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/mips64/RemoteMIPS64ThreadContext.java 2023-09-12 13:54:26.377575791 +0800 -@@ -0,0 +1,51 @@ -+/* -+ * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2018, Loongson Technology. 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 sun.jvm.hotspot.debugger.remote.mips64; ++ @Override ++ public SystemStream getSystemStream() { ++ return systemStream; ++ } + -+import sun.jvm.hotspot.debugger.*; -+import sun.jvm.hotspot.debugger.mips64.*; -+import sun.jvm.hotspot.debugger.remote.*; + class PtyInputStream extends NonBlockingInputStream { + final InputStream in; + int c = 0; +@@ -102,4 +153,103 @@ public abstract class AbstractPty implements Pty { + } + } + ++ private static FileDescriptorCreator fileDescriptorCreator; ++ ++ protected static FileDescriptor newDescriptor(int fd) { ++ if (fileDescriptorCreator == null) { ++ String str = ++ System.getProperty(PROP_FILE_DESCRIPTOR_CREATION_MODE, PROP_FILE_DESCRIPTOR_CREATION_MODE_DEFAULT); ++ String[] modes = str.split(","); ++ IllegalStateException ise = new IllegalStateException("Unable to create FileDescriptor"); ++ for (String mode : modes) { ++ try { ++ switch (mode) { ++ case PROP_FILE_DESCRIPTOR_CREATION_MODE_NATIVE: ++ fileDescriptorCreator = null;//new NativeFileDescriptorCreator(); ++ break; ++ case PROP_FILE_DESCRIPTOR_CREATION_MODE_REFLECTION: ++ fileDescriptorCreator = new ReflectionFileDescriptorCreator(); ++ break; ++ } ++ } catch (Throwable t) { ++ // ignore ++ ise.addSuppressed(t); ++ } ++ if (fileDescriptorCreator != null) { ++ break; ++ } ++ } ++ if (fileDescriptorCreator == null) { ++ throw ise; ++ } ++ } ++ return fileDescriptorCreator.newDescriptor(fd); ++ } + -+public class RemoteMIPS64ThreadContext extends MIPS64ThreadContext { -+ private RemoteDebuggerClient debugger; ++ interface FileDescriptorCreator { ++ FileDescriptor newDescriptor(int fd); ++ } + -+ public RemoteMIPS64ThreadContext(RemoteDebuggerClient debugger) { -+ super(); -+ this.debugger = debugger; -+ } ++ /* ++ * Class that could be used on OpenJDK 17. However, it requires the following JVM option ++ * --add-exports java.base/jdk.internal.access=ALL-UNNAMED ++ * so the benefit does not seem important enough to warrant the problems caused ++ * by access the jdk.internal.access package at compile time, which itself requires ++ * custom compiler options and a different maven module, or at least a different compile ++ * phase with a JDK 17 compiler. ++ * So, just keep the ReflectionFileDescriptorCreator for now. ++ * ++ static class Jdk17FileDescriptorCreator implements FileDescriptorCreator { ++ private final jdk.internal.access.JavaIOFileDescriptorAccess fdAccess; ++ Jdk17FileDescriptorCreator() { ++ fdAccess = jdk.internal.access.SharedSecrets.getJavaIOFileDescriptorAccess(); ++ } + -+ /** This can't be implemented in this class since we would have to -+ tie the implementation to, for example, the debugging system */ -+ public void setRegisterAsAddress(int index, Address value) { -+ setRegister(index, debugger.getAddressValue(value)); -+ } ++ @Override ++ public FileDescriptor newDescriptor(int fd) { ++ FileDescriptor descriptor = new FileDescriptor(); ++ fdAccess.set(descriptor, fd); ++ return descriptor; ++ } ++ } ++ */ + -+ /** This can't be implemented in this class since we would have to -+ tie the implementation to, for example, the debugging system */ -+ public Address getRegisterAsAddress(int index) { -+ return debugger.newAddress(getRegister(index)); -+ } -+} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/mips64/RemoteMIPS64ThreadFactory.java jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/mips64/RemoteMIPS64ThreadFactory.java ---- openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/mips64/RemoteMIPS64ThreadFactory.java 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/mips64/RemoteMIPS64ThreadFactory.java 2023-09-12 13:54:26.377575791 +0800 -@@ -0,0 +1,45 @@ -+/* -+ * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2018, Loongson Technology. 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. -+ * -+ */ ++ /** ++ * Reflection based file descriptor creator. ++ * This requires the following option ++ * --add-opens java.base/java.io=ALL-UNNAMED ++ */ ++ static class ReflectionFileDescriptorCreator implements FileDescriptorCreator { ++ private final Field fileDescriptorField; + -+package sun.jvm.hotspot.debugger.remote.mips64; ++ ReflectionFileDescriptorCreator() throws Exception { ++ Field field = FileDescriptor.class.getDeclaredField("fd"); ++ field.setAccessible(true); ++ fileDescriptorField = field; ++ } + -+import sun.jvm.hotspot.debugger.*; -+import sun.jvm.hotspot.debugger.remote.*; ++ @Override ++ public FileDescriptor newDescriptor(int fd) { ++ FileDescriptor descriptor = new FileDescriptor(); ++ try { ++ fileDescriptorField.set(descriptor, fd); ++ } catch (IllegalAccessException e) { ++ // This should not happen as the field has been set accessible ++ throw new IllegalStateException(e); ++ } ++ return descriptor; ++ } ++ } + -+public class RemoteMIPS64ThreadFactory implements RemoteThreadFactory { -+ private RemoteDebuggerClient debugger; ++// static class NativeFileDescriptorCreator implements FileDescriptorCreator { ++// NativeFileDescriptorCreator() { ++// // Force load the library ++// JLineNativeLoader.initialize(); ++// } ++// ++// @Override ++// public FileDescriptor newDescriptor(int fd) { ++// return JLineLibrary.newFileDescriptor(fd); ++// } ++// } + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractTerminal.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractTerminal.java +index e92233c7b..4fb49b29b 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractTerminal.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractTerminal.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2021, the original author or authors. ++ * Copyright (c) 2002-2021, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -27,7 +27,7 @@ import jdk.internal.org.jline.terminal.Attributes.InputFlag; + import jdk.internal.org.jline.terminal.Attributes.LocalFlag; + import jdk.internal.org.jline.terminal.Cursor; + import jdk.internal.org.jline.terminal.MouseEvent; +-import jdk.internal.org.jline.terminal.Terminal; ++import jdk.internal.org.jline.terminal.spi.TerminalExt; + import jdk.internal.org.jline.utils.ColorPalette; + import jdk.internal.org.jline.utils.Curses; + import jdk.internal.org.jline.utils.InfoCmp; +@@ -35,7 +35,7 @@ import jdk.internal.org.jline.utils.InfoCmp.Capability; + import jdk.internal.org.jline.utils.Log; + import jdk.internal.org.jline.utils.Status; + +-public abstract class AbstractTerminal implements Terminal { ++public abstract class AbstractTerminal implements TerminalExt { + + protected final String name; + protected final String type; +@@ -44,7 +44,7 @@ public abstract class AbstractTerminal implements Terminal { + protected final Set bools = new HashSet<>(); + protected final Map ints = new HashMap<>(); + protected final Map strings = new HashMap<>(); +- protected final ColorPalette palette = new ColorPalette(this); ++ protected final ColorPalette palette; + protected Status status; + protected Runnable onClose; + +@@ -52,10 +52,13 @@ public abstract class AbstractTerminal implements Terminal { + this(name, type, null, SignalHandler.SIG_DFL); + } + +- public AbstractTerminal(String name, String type, Charset encoding, SignalHandler signalHandler) throws IOException { ++ @SuppressWarnings("this-escape") ++ public AbstractTerminal(String name, String type, Charset encoding, SignalHandler signalHandler) ++ throws IOException { + this.name = name; + this.type = type != null ? type : "ansi"; + this.encoding = encoding != null ? encoding : Charset.defaultCharset(); ++ this.palette = new ColorPalette(this); + for (Signal signal : Signal.values()) { + handlers.put(signal, signalHandler); + } +@@ -85,12 +88,13 @@ public abstract class AbstractTerminal implements Terminal { + public void raise(Signal signal) { + Objects.requireNonNull(signal); + SignalHandler handler = handlers.get(signal); +- if (handler != SignalHandler.SIG_DFL && handler != SignalHandler.SIG_IGN) { ++ if (handler == SignalHandler.SIG_DFL) { ++ if (status != null && signal == Signal.WINCH) { ++ status.resize(); ++ } ++ } else if (handler != SignalHandler.SIG_IGN) { + handler.handle(signal); + } +- if (status != null && signal == Signal.WINCH) { +- status.resize(); +- } + } + + public final void close() throws IOException { +@@ -105,8 +109,7 @@ public abstract class AbstractTerminal implements Terminal { + + protected void doClose() throws IOException { + if (status != null) { +- status.update(null); +- flush(); ++ status.close(); + } + } + +@@ -126,7 +129,7 @@ public abstract class AbstractTerminal implements Terminal { + if (cc != null) { + int vcc = getAttributes().getControlChar(cc); + if (vcc > 0 && vcc < 32) { +- writer().write(new char[]{'^', (char) (vcc + '@')}, 0, 2); ++ writer().write(new char[] {'^', (char) (vcc + '@')}, 0, 2); + } + } + } +@@ -217,8 +220,7 @@ public abstract class AbstractTerminal implements Terminal { + } + + private MouseEvent lastMouseEvent = new MouseEvent( +- MouseEvent.Type.Moved, MouseEvent.Button.NoButton, +- EnumSet.noneOf(MouseEvent.Modifier.class), 0, 0); ++ MouseEvent.Type.Moved, MouseEvent.Button.NoButton, EnumSet.noneOf(MouseEvent.Modifier.class), 0, 0); + + @Override + public boolean hasMouseSupport() { +@@ -268,16 +270,13 @@ public abstract class AbstractTerminal implements Terminal { + } + + @Override +- public void pause() { +- } ++ public void pause() {} + + @Override +- public void pause(boolean wait) throws InterruptedException { +- } ++ public void pause(boolean wait) throws InterruptedException {} + + @Override +- public void resume() { +- } ++ public void resume() {} + + @Override + public boolean paused() { +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractWindowsConsoleWriter.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractWindowsConsoleWriter.java +index 0c36902a1..301b89eb7 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractWindowsConsoleWriter.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractWindowsConsoleWriter.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2017, the original author or authors. ++ * Copyright (c) 2002-2017, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -29,11 +29,8 @@ public abstract class AbstractWindowsConsoleWriter extends Writer { + } + + @Override +- public void flush() { +- } ++ public void flush() {} + + @Override +- public void close() { +- } +- ++ public void close() {} + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractWindowsTerminal.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractWindowsTerminal.java +index 57cfb5d50..03c42fb19 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractWindowsTerminal.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractWindowsTerminal.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2019, the original author or authors. ++ * Copyright (c) 2002-2023, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -8,8 +8,20 @@ + */ + package jdk.internal.org.jline.terminal.impl; + ++import java.io.IOException; ++import java.io.InputStream; ++import java.io.OutputStream; ++import java.io.PrintWriter; ++import java.io.Writer; ++import java.nio.charset.Charset; ++import java.util.HashMap; ++import java.util.Map; ++import java.util.function.Function; ++ + import jdk.internal.org.jline.terminal.Attributes; + import jdk.internal.org.jline.terminal.Size; ++import jdk.internal.org.jline.terminal.spi.SystemStream; ++import jdk.internal.org.jline.terminal.spi.TerminalProvider; + import jdk.internal.org.jline.utils.Curses; + import jdk.internal.org.jline.utils.InfoCmp; + import jdk.internal.org.jline.utils.Log; +@@ -21,17 +33,6 @@ import jdk.internal.org.jline.utils.ShutdownHooks; + import jdk.internal.org.jline.utils.Signals; + import jdk.internal.org.jline.utils.WriterOutputStream; + +-import java.io.IOException; +-import java.io.InputStream; +-import java.io.OutputStream; +-import java.io.PrintWriter; +-import java.io.Writer; +-import java.nio.charset.Charset; +-import java.nio.charset.StandardCharsets; +-import java.util.HashMap; +-import java.util.Map; +-import java.util.function.Function; +- + /** + * The AbstractWindowsTerminal is used as the base class for windows terminal. + * Due to windows limitations, mostly the missing support for ansi sequences, +@@ -44,7 +45,7 @@ import java.util.function.Function; + * the writer() becomes the primary output, while the output() is bridged + * to the writer() using a WriterOutputStream wrapper. + */ +-public abstract class AbstractWindowsTerminal extends AbstractTerminal { ++public abstract class AbstractWindowsTerminal extends AbstractTerminal { + + public static final String TYPE_WINDOWS = "windows"; + public static final String TYPE_WINDOWS_256_COLOR = "windows-256color"; +@@ -56,12 +57,13 @@ public abstract class AbstractWindowsTerminal extends AbstractTerminal { + private static final int UTF8_CODE_PAGE = 65001; + + protected static final int ENABLE_PROCESSED_INPUT = 0x0001; +- protected static final int ENABLE_LINE_INPUT = 0x0002; +- protected static final int ENABLE_ECHO_INPUT = 0x0004; +- protected static final int ENABLE_WINDOW_INPUT = 0x0008; +- protected static final int ENABLE_MOUSE_INPUT = 0x0010; +- protected static final int ENABLE_INSERT_MODE = 0x0020; ++ protected static final int ENABLE_LINE_INPUT = 0x0002; ++ protected static final int ENABLE_ECHO_INPUT = 0x0004; ++ protected static final int ENABLE_WINDOW_INPUT = 0x0008; ++ protected static final int ENABLE_MOUSE_INPUT = 0x0010; ++ protected static final int ENABLE_INSERT_MODE = 0x0020; + protected static final int ENABLE_QUICK_EDIT_MODE = 0x0040; ++ protected static final int ENABLE_EXTENDED_FLAGS = 0x0080; + + protected final Writer slaveInputPipe; + protected final InputStream input; +@@ -71,7 +73,12 @@ public abstract class AbstractWindowsTerminal extends AbstractTerminal { + protected final Map nativeHandlers = new HashMap<>(); + protected final ShutdownHooks.Task closer; + protected final Attributes attributes = new Attributes(); +- protected final int originalConsoleMode; ++ protected final Console inConsole; ++ protected final Console outConsole; ++ protected final int originalInConsoleMode; ++ protected final int originalOutConsoleMode; ++ private final TerminalProvider provider; ++ private final SystemStream systemStream; + + protected final Object lock = new Object(); + protected boolean paused = true; +@@ -80,21 +87,42 @@ public abstract class AbstractWindowsTerminal extends AbstractTerminal { + protected MouseTracking tracking = MouseTracking.Off; + protected boolean focusTracking = false; + private volatile boolean closing; +- +- public AbstractWindowsTerminal(Writer writer, String name, String type, Charset encoding, boolean nativeSignals, SignalHandler signalHandler, Function inputStreamWrapper) throws IOException { ++ protected boolean skipNextLf; ++ ++ @SuppressWarnings("this-escape") ++ public AbstractWindowsTerminal( ++ TerminalProvider provider, ++ SystemStream systemStream, ++ Writer writer, ++ String name, ++ String type, ++ Charset encoding, ++ boolean nativeSignals, ++ SignalHandler signalHandler, ++ Console inConsole, ++ int inConsoleMode, ++ Console outConsole, ++ int outConsoleMode, ++ Function inputStreamWrapper) ++ throws IOException { + super(name, type, encoding, signalHandler); ++ this.provider = provider; ++ this.systemStream = systemStream; + NonBlockingPumpReader reader = NonBlocking.nonBlockingPumpReader(); + this.slaveInputPipe = reader.getWriter(); + this.input = inputStreamWrapper.apply(NonBlocking.nonBlockingStream(reader, encoding())); + this.reader = NonBlocking.nonBlocking(name, input, encoding()); + this.writer = new PrintWriter(writer); + this.output = new WriterOutputStream(writer, encoding()); ++ this.inConsole = inConsole; ++ this.outConsole = outConsole; + parseInfoCmp(); + // Attributes +- originalConsoleMode = getConsoleMode(); ++ this.originalInConsoleMode = inConsoleMode; ++ this.originalOutConsoleMode = outConsoleMode; + attributes.setLocalFlag(Attributes.LocalFlag.ISIG, true); + attributes.setControlChar(Attributes.ControlChar.VINTR, ctrl('C')); +- attributes.setControlChar(Attributes.ControlChar.VEOF, ctrl('D')); ++ attributes.setControlChar(Attributes.ControlChar.VEOF, ctrl('D')); + attributes.setControlChar(Attributes.ControlChar.VSUSP, ctrl('Z')); + // Handle signals + if (nativeSignals) { +@@ -148,7 +176,7 @@ public abstract class AbstractWindowsTerminal extends AbstractTerminal { + } + + public Attributes getAttributes() { +- int mode = getConsoleMode(); ++ int mode = getConsoleMode(inConsole); + if ((mode & ENABLE_ECHO_INPUT) != 0) { + attributes.setLocalFlag(Attributes.LocalFlag.ECHO, true); + } +@@ -173,8 +201,11 @@ public abstract class AbstractWindowsTerminal extends AbstractTerminal { + } + if (tracking != MouseTracking.Off) { + mode |= ENABLE_MOUSE_INPUT; ++ // mouse events not send with quick edit mode ++ // to disable ENABLE_QUICK_EDIT_MODE just set extended flag ++ mode |= ENABLE_EXTENDED_FLAGS; + } +- setConsoleMode(mode); ++ setConsoleMode(inConsole, mode); + } + + protected int ctrl(char key) { +@@ -197,23 +228,26 @@ public abstract class AbstractWindowsTerminal extends AbstractTerminal { + } + reader.close(); + writer.close(); +- setConsoleMode(originalConsoleMode); ++ setConsoleMode(inConsole, originalInConsoleMode); ++ setConsoleMode(outConsole, originalOutConsoleMode); + } + + static final int SHIFT_FLAG = 0x01; +- static final int ALT_FLAG = 0x02; +- static final int CTRL_FLAG = 0x04; +- +- static final int RIGHT_ALT_PRESSED = 0x0001; +- static final int LEFT_ALT_PRESSED = 0x0002; +- static final int RIGHT_CTRL_PRESSED = 0x0004; +- static final int LEFT_CTRL_PRESSED = 0x0008; +- static final int SHIFT_PRESSED = 0x0010; +- static final int NUMLOCK_ON = 0x0020; +- static final int SCROLLLOCK_ON = 0x0040; +- static final int CAPSLOCK_ON = 0x0080; +- +- protected void processKeyEvent(final boolean isKeyDown, final short virtualKeyCode, char ch, final int controlKeyState) throws IOException { ++ static final int ALT_FLAG = 0x02; ++ static final int CTRL_FLAG = 0x04; ++ ++ static final int RIGHT_ALT_PRESSED = 0x0001; ++ static final int LEFT_ALT_PRESSED = 0x0002; ++ static final int RIGHT_CTRL_PRESSED = 0x0004; ++ static final int LEFT_CTRL_PRESSED = 0x0008; ++ static final int SHIFT_PRESSED = 0x0010; ++ static final int NUMLOCK_ON = 0x0020; ++ static final int SCROLLLOCK_ON = 0x0040; ++ static final int CAPSLOCK_ON = 0x0080; ++ ++ protected void processKeyEvent( ++ final boolean isKeyDown, final short virtualKeyCode, char ch, final int controlKeyState) ++ throws IOException { + final boolean isCtrl = (controlKeyState & (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED)) > 0; + final boolean isAlt = (controlKeyState & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED)) > 0; + final boolean isShift = (controlKeyState & SHIFT_PRESSED) > 0; +@@ -222,11 +256,13 @@ public abstract class AbstractWindowsTerminal extends AbstractTerminal { + // Pressing "Alt Gr" is translated to Alt-Ctrl, hence it has to be checked that Ctrl is _not_ pressed, + // otherwise inserting of "Alt Gr" codes on non-US keyboards would yield errors + if (ch != 0 +- && (controlKeyState & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED | RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED | SHIFT_PRESSED)) +- == (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED)) { ++ && (controlKeyState ++ & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED | RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED)) ++ == (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED)) { + processInputChar(ch); + } else { +- final String keySeq = getEscapeSequence(virtualKeyCode, (isCtrl ? CTRL_FLAG : 0) + (isAlt ? ALT_FLAG : 0) + (isShift ? SHIFT_FLAG : 0)); ++ final String keySeq = getEscapeSequence( ++ virtualKeyCode, (isCtrl ? CTRL_FLAG : 0) + (isAlt ? ALT_FLAG : 0) + (isShift ? SHIFT_FLAG : 0)); + if (keySeq != null) { + for (char c : keySeq.toCharArray()) { + processInputChar(c); +@@ -240,7 +276,7 @@ public abstract class AbstractWindowsTerminal extends AbstractTerminal { + * 4). Ctrl + Space(0x20) : uchar=0x20 + * 5). Ctrl + : uchar=0 + * 6). Ctrl + Alt + : uchar=0 +- */ ++ */ + if (ch > 0) { + if (isAlt) { + processInputChar('\033'); +@@ -254,10 +290,10 @@ public abstract class AbstractWindowsTerminal extends AbstractTerminal { + } else { + processInputChar(ch); + } +- } else if (isCtrl) { //Handles the ctrl key events(uchar=0) ++ } else if (isCtrl) { // Handles the ctrl key events(uchar=0) + if (virtualKeyCode >= 'A' && virtualKeyCode <= 'Z') { + ch = (char) (virtualKeyCode - 0x40); +- } else if (virtualKeyCode == 191) { //? ++ } else if (virtualKeyCode == 191) { // ? + ch = 127; + } + if (ch > 0) { +@@ -275,7 +311,7 @@ public abstract class AbstractWindowsTerminal extends AbstractTerminal { + else { + // support ALT+NumPad input method + if (virtualKeyCode == 0x12 /*VK_MENU ALT key*/ && ch > 0) { +- processInputChar(ch); // no such combination in Windows ++ processInputChar(ch); // no such combination in Windows + } + } + } +@@ -468,7 +504,19 @@ public abstract class AbstractWindowsTerminal extends AbstractTerminal { + raise(Signal.INFO); + } + } +- if (c == '\r') { ++ if (attributes.getInputFlag(Attributes.InputFlag.INORMEOL)) { ++ if (c == '\r') { ++ skipNextLf = true; ++ c = '\n'; ++ } else if (c == '\n') { ++ if (skipNextLf) { ++ skipNextLf = false; ++ return; ++ } ++ } else { ++ skipNextLf = false; ++ } ++ } else if (c == '\r') { + if (attributes.getInputFlag(Attributes.InputFlag.IGNCR)) { + return; + } +@@ -478,10 +526,10 @@ public abstract class AbstractWindowsTerminal extends AbstractTerminal { + } else if (c == '\n' && attributes.getInputFlag(Attributes.InputFlag.INLCR)) { + c = '\r'; + } +-// if (attributes.getLocalFlag(Attributes.LocalFlag.ECHO)) { +-// processOutputByte(c); +-// masterOutput.flush(); +-// } ++ // if (attributes.getLocalFlag(Attributes.LocalFlag.ECHO)) { ++ // processOutputByte(c); ++ // masterOutput.flush(); ++ // } + slaveInputPipe.write(c); + } + +@@ -492,9 +540,9 @@ public abstract class AbstractWindowsTerminal extends AbstractTerminal { + return true; + } + +- protected abstract int getConsoleMode(); ++ protected abstract int getConsoleMode(Console console); + +- protected abstract void setConsoleMode(int mode); ++ protected abstract void setConsoleMode(Console console, int mode); + + /** + * Read a single input event from the input buffer and process it. +@@ -504,5 +552,13 @@ public abstract class AbstractWindowsTerminal extends AbstractTerminal { + */ + protected abstract boolean processConsoleInput() throws IOException; + +-} ++ @Override ++ public TerminalProvider getProvider() { ++ return provider; ++ } + ++ @Override ++ public SystemStream getSystemStream() { ++ return systemStream; ++ } ++} +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/CursorSupport.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/CursorSupport.java +index ef22cd0a7..14253d8c1 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/CursorSupport.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/CursorSupport.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2016, the original author or authors. ++ * Copyright (c) 2002-2016, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -8,17 +8,17 @@ + */ + package jdk.internal.org.jline.terminal.impl; + +-import jdk.internal.org.jline.terminal.Cursor; +-import jdk.internal.org.jline.terminal.Terminal; +-import jdk.internal.org.jline.utils.Curses; +-import jdk.internal.org.jline.utils.InfoCmp; +- + import java.io.IOError; + import java.io.IOException; + import java.util.function.IntConsumer; + import java.util.regex.Matcher; + import java.util.regex.Pattern; + ++import jdk.internal.org.jline.terminal.Cursor; ++import jdk.internal.org.jline.terminal.Terminal; ++import jdk.internal.org.jline.utils.Curses; ++import jdk.internal.org.jline.utils.InfoCmp; + -+ public RemoteMIPS64ThreadFactory(RemoteDebuggerClient debugger) { -+ this.debugger = debugger; -+ } + public class CursorSupport { + + public static Cursor getCursorPosition(Terminal terminal, IntConsumer discarded) { +@@ -105,5 +105,4 @@ public class CursorSupport { + throw new IOError(e); + } + } +- + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/Diag.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/Diag.java +index dfa784c29..dc54ea215 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/Diag.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/Diag.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2022, the original author or authors. ++ * Copyright (c) 2022, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -17,6 +17,7 @@ import java.util.concurrent.TimeUnit; + + import jdk.internal.org.jline.terminal.Attributes; + import jdk.internal.org.jline.terminal.Terminal; ++import jdk.internal.org.jline.terminal.spi.SystemStream; + import jdk.internal.org.jline.terminal.spi.TerminalProvider; + import jdk.internal.org.jline.utils.OSUtils; + +@@ -26,7 +27,7 @@ public class Diag { + diag(System.out); + } + +- static void diag(PrintStream out) { ++ public static void diag(PrintStream out) { + out.println("System properties"); + out.println("================="); + out.println("os.name = " + System.getProperty("os.name")); +@@ -50,6 +51,17 @@ public class Diag { + out.println("IS_OSX = " + OSUtils.IS_OSX); + out.println(); + ++ // FFM ++ out.println("FFM Support"); ++ out.println("================="); ++ try { ++ TerminalProvider provider = TerminalProvider.load("ffm"); ++ testProvider(out, provider); ++ } catch (Throwable t) { ++ out.println("FFM support not available: " + t); ++ } ++ out.println(); + -+ public ThreadProxy createThreadWrapper(Address threadIdentifierAddr) { -+ return new RemoteMIPS64Thread(debugger, threadIdentifierAddr); -+ } + out.println("JnaSupport"); + out.println("================="); + try { +@@ -60,13 +72,23 @@ public class Diag { + } + out.println(); + +- out.println("JansiSupport"); ++ out.println("Jansi2Support"); + out.println("================="); + try { + TerminalProvider provider = TerminalProvider.load("jansi"); + testProvider(out, provider); + } catch (Throwable t) { +- out.println("Jansi support not available: " + t); ++ out.println("Jansi 2 support not available: " + t); ++ } ++ out.println(); ++ ++ out.println("JniSupport"); ++ out.println("================="); ++ try { ++ TerminalProvider provider = TerminalProvider.load("jni"); ++ testProvider(out, provider); ++ } catch (Throwable t) { ++ out.println("JNI support not available: " + t); + } + out.println(); + +@@ -83,32 +105,45 @@ public class Diag { + + private static void testProvider(PrintStream out, TerminalProvider provider) { + try { +- out.println("StdIn stream = " + provider.isSystemStream(TerminalProvider.Stream.Input)); +- out.println("StdOut stream = " + provider.isSystemStream(TerminalProvider.Stream.Output)); +- out.println("StdErr stream = " + provider.isSystemStream(TerminalProvider.Stream.Error)); ++ out.println("StdIn stream = " + provider.isSystemStream(SystemStream.Input)); ++ out.println("StdOut stream = " + provider.isSystemStream(SystemStream.Output)); ++ out.println("StdErr stream = " + provider.isSystemStream(SystemStream.Error)); + } catch (Throwable t2) { + out.println("Unable to check stream: " + t2); + } + try { +- out.println("StdIn stream name = " + provider.systemStreamName(TerminalProvider.Stream.Input)); +- out.println("StdOut stream name = " + provider.systemStreamName(TerminalProvider.Stream.Output)); +- out.println("StdErr stream name = " + provider.systemStreamName(TerminalProvider.Stream.Error)); ++ out.println("StdIn stream name = " + provider.systemStreamName(SystemStream.Input)); ++ out.println("StdOut stream name = " + provider.systemStreamName(SystemStream.Output)); ++ out.println("StdErr stream name = " + provider.systemStreamName(SystemStream.Error)); + } catch (Throwable t2) { + out.println("Unable to check stream names: " + t2); + } +- try (Terminal terminal = provider.sysTerminal("diag", "xterm", false, StandardCharsets.UTF_8, +- false, Terminal.SignalHandler.SIG_DFL, false, TerminalProvider.Stream.Output, input -> input) ) { ++ try (Terminal terminal = provider.sysTerminal( ++ "diag", ++ "xterm", ++ false, ++ StandardCharsets.UTF_8, ++ false, ++ Terminal.SignalHandler.SIG_DFL, ++ false, ++ SystemStream.Output, ++ input -> input)) { + if (terminal != null) { + Attributes attr = terminal.enterRawMode(); + try { + out.println("Terminal size: " + terminal.getSize()); +- ForkJoinTask t = new ForkJoinPool(1).submit(() -> terminal.reader().read(1) ); ++ ForkJoinTask t = ++ new ForkJoinPool(1).submit(() -> terminal.reader().read(1)); + int r = t.get(1000, TimeUnit.MILLISECONDS); + StringBuilder sb = new StringBuilder(); + sb.append("The terminal seems to work: "); + sb.append("terminal ").append(terminal.getClass().getName()); + if (terminal instanceof AbstractPosixTerminal) { +- sb.append(" with pty ").append(((AbstractPosixTerminal) terminal).getPty().getClass().getName()); ++ sb.append(" with pty ") ++ .append(((AbstractPosixTerminal) terminal) ++ .getPty() ++ .getClass() ++ .getName()); + } + out.println(sb); + } catch (Throwable t3) { +@@ -129,5 +164,4 @@ public class Diag { + static S load(Class clazz) { + return ServiceLoader.load(clazz, clazz.getClassLoader()).iterator().next(); + } +- + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/DumbTerminal.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/DumbTerminal.java +index 0b8cb57cb..2922132c1 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/DumbTerminal.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/DumbTerminal.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2018, the original author or authors. ++ * Copyright (c) 2002-2018, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -14,38 +14,58 @@ import java.io.OutputStream; + import java.io.OutputStreamWriter; + import java.io.PrintWriter; + import java.nio.charset.Charset; ++import java.util.function.Function; + + import jdk.internal.org.jline.terminal.Attributes; + import jdk.internal.org.jline.terminal.Attributes.ControlChar; + import jdk.internal.org.jline.terminal.Size; ++import jdk.internal.org.jline.terminal.spi.SystemStream; ++import jdk.internal.org.jline.terminal.spi.TerminalProvider; + import jdk.internal.org.jline.utils.NonBlocking; + import jdk.internal.org.jline.utils.NonBlockingInputStream; + import jdk.internal.org.jline.utils.NonBlockingReader; + + public class DumbTerminal extends AbstractTerminal { + ++ private final TerminalProvider provider; ++ private final SystemStream systemStream; + private final NonBlockingInputStream input; + private final OutputStream output; + private final NonBlockingReader reader; + private final PrintWriter writer; + private final Attributes attributes; + private final Size size; ++ private boolean skipNextLf; + +- public DumbTerminal(InputStream in, OutputStream out) throws IOException { +- this(TYPE_DUMB, TYPE_DUMB, in, out, null); ++ public DumbTerminal(InputStream in, OutputStream out, Function inputStreamWrapper) throws IOException { ++ this(TYPE_DUMB, TYPE_DUMB, in, out, null, inputStreamWrapper); + } + +- public DumbTerminal(String name, String type, InputStream in, OutputStream out, Charset encoding) throws IOException { +- this(name, type, in, out, encoding, SignalHandler.SIG_DFL); ++ public DumbTerminal(String name, String type, InputStream in, OutputStream out, Charset encoding, Function inputStreamWrapper) ++ throws IOException { ++ this(null, null, name, type, in, out, encoding, SignalHandler.SIG_DFL, inputStreamWrapper); + } + +- public DumbTerminal(String name, String type, InputStream in, OutputStream out, Charset encoding, SignalHandler signalHandler) throws IOException { ++ @SuppressWarnings("this-escape") ++ public DumbTerminal( ++ TerminalProvider provider, ++ SystemStream systemStream, ++ String name, ++ String type, ++ InputStream in, ++ OutputStream out, ++ Charset encoding, ++ SignalHandler signalHandler, ++ Function inputStreamWrapper) ++ throws IOException { + super(name, type, encoding, signalHandler); +- NonBlockingInputStream nbis = NonBlocking.nonBlocking(getName(), in); ++ this.provider = provider; ++ this.systemStream = systemStream; ++ NonBlockingInputStream nbis = NonBlocking.nonBlocking(getName(), inputStreamWrapper.apply(in)); + this.input = new NonBlockingInputStream() { + @Override + public int read(long timeout, boolean isPeek) throws IOException { +- for (;;) { ++ for (; ; ) { + int c = nbis.read(timeout, isPeek); + if (attributes.getLocalFlag(Attributes.LocalFlag.ISIG)) { + if (c == attributes.getControlChar(ControlChar.VINTR)) { +@@ -62,7 +82,19 @@ public class DumbTerminal extends AbstractTerminal { + continue; + } + } +- if (c == '\r') { ++ if (attributes.getInputFlag(Attributes.InputFlag.INORMEOL)) { ++ if (c == '\r') { ++ skipNextLf = true; ++ c = '\n'; ++ } else if (c == '\n') { ++ if (skipNextLf) { ++ skipNextLf = false; ++ continue; ++ } ++ } else { ++ skipNextLf = false; ++ } ++ } else if (c == '\r') { + if (attributes.getInputFlag(Attributes.InputFlag.IGNCR)) { + continue; + } +@@ -80,10 +112,10 @@ public class DumbTerminal extends AbstractTerminal { + this.reader = NonBlocking.nonBlocking(getName(), input, encoding()); + this.writer = new PrintWriter(new OutputStreamWriter(output, encoding())); + this.attributes = new Attributes(); +- this.attributes.setControlChar(ControlChar.VERASE, (char) 127); ++ this.attributes.setControlChar(ControlChar.VERASE, (char) 127); + this.attributes.setControlChar(ControlChar.VWERASE, (char) 23); +- this.attributes.setControlChar(ControlChar.VKILL, (char) 21); +- this.attributes.setControlChar(ControlChar.VLNEXT, (char) 22); ++ this.attributes.setControlChar(ControlChar.VKILL, (char) 21); ++ this.attributes.setControlChar(ControlChar.VLNEXT, (char) 22); + this.size = new Size(); + parseInfoCmp(); + } +@@ -107,9 +139,7 @@ public class DumbTerminal extends AbstractTerminal { + } + + public Attributes getAttributes() { +- Attributes attr = new Attributes(); +- attr.copy(attributes); +- return attr; ++ return new Attributes(attributes); + } + + public void setAttributes(Attributes attr) { +@@ -126,4 +156,13 @@ public class DumbTerminal extends AbstractTerminal { + size.copy(sz); + } + ++ @Override ++ public TerminalProvider getProvider() { ++ return provider; ++ } + -+ public ThreadProxy createThreadWrapper(long id) { -+ return new RemoteMIPS64Thread(debugger, id); -+ } -+} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/mips64/RemoteMIPS64Thread.java jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/mips64/RemoteMIPS64Thread.java ---- openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/mips64/RemoteMIPS64Thread.java 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/mips64/RemoteMIPS64Thread.java 2023-09-12 13:54:26.377575791 +0800 -@@ -0,0 +1,54 @@ ++ @Override ++ public SystemStream getSystemStream() { ++ return systemStream; ++ } + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/DumbTerminalProvider.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/DumbTerminalProvider.java +new file mode 100644 +index 000000000..b99185d3d +--- /dev/null ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/DumbTerminalProvider.java +@@ -0,0 +1,92 @@ +/* -+ * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2018, Loongson Technology. 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. ++ * Copyright (c) 2023, the original author(s). + * -+ * 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 software is distributable under the BSD license. See the terms of the ++ * BSD license in the documentation provided with this software. + * ++ * https://opensource.org/licenses/BSD-3-Clause + */ ++package jdk.internal.org.jline.terminal.impl; ++ ++import java.io.FileDescriptor; ++import java.io.FileInputStream; ++import java.io.FileOutputStream; ++import java.io.IOException; ++import java.io.InputStream; ++import java.io.OutputStream; ++import java.nio.charset.Charset; ++import java.util.function.Function; ++ ++import jdk.internal.org.jline.terminal.Attributes; ++import jdk.internal.org.jline.terminal.Size; ++import jdk.internal.org.jline.terminal.Terminal; ++import jdk.internal.org.jline.terminal.TerminalBuilder; ++import jdk.internal.org.jline.terminal.spi.SystemStream; ++import jdk.internal.org.jline.terminal.spi.TerminalProvider; ++ ++public class DumbTerminalProvider implements TerminalProvider { + -+package sun.jvm.hotspot.debugger.remote.mips64; ++ @Override ++ public String name() { ++ return TerminalBuilder.PROP_PROVIDER_DUMB; ++ } + -+import sun.jvm.hotspot.debugger.*; -+import sun.jvm.hotspot.debugger.mips64.*; -+import sun.jvm.hotspot.debugger.remote.*; -+import sun.jvm.hotspot.utilities.*; ++ @Override ++ public Terminal sysTerminal( ++ String name, ++ String type, ++ boolean ansiPassThrough, ++ Charset encoding, ++ boolean nativeSignals, ++ Terminal.SignalHandler signalHandler, ++ boolean paused, ++ SystemStream systemStream, ++ Function inputStreamWrapper) ++ throws IOException { ++ return new DumbTerminal( ++ this, ++ systemStream, ++ name, ++ type, ++ new FileInputStream(FileDescriptor.in), ++ new FileOutputStream(systemStream == SystemStream.Error ? FileDescriptor.err : FileDescriptor.out), ++ encoding, ++ signalHandler, ++ inputStreamWrapper); ++ } + -+public class RemoteMIPS64Thread extends RemoteThread { -+ public RemoteMIPS64Thread(RemoteDebuggerClient debugger, Address addr) { -+ super(debugger, addr); -+ } ++ @Override ++ public Terminal newTerminal( ++ String name, ++ String type, ++ InputStream masterInput, ++ OutputStream masterOutput, ++ Charset encoding, ++ Terminal.SignalHandler signalHandler, ++ boolean paused, ++ Attributes attributes, ++ Size size) ++ throws IOException { ++ throw new UnsupportedOperationException(); ++ } + -+ public RemoteMIPS64Thread(RemoteDebuggerClient debugger, long id) { -+ super(debugger, id); -+ } ++ @Override ++ public boolean isSystemStream(SystemStream stream) { ++ return false; ++ } + -+ public ThreadContext getContext() throws IllegalThreadStateException { -+ RemoteMIPS64ThreadContext context = new RemoteMIPS64ThreadContext(debugger); -+ long[] regs = (addr != null)? debugger.getThreadIntegerRegisterSet(addr) : -+ debugger.getThreadIntegerRegisterSet(id); -+ if (Assert.ASSERTS_ENABLED) { -+ Assert.that(regs.length == MIPS64ThreadContext.NPRGREG, "size of register set must match"); ++ @Override ++ public String systemStreamName(SystemStream stream) { ++ return null; + } -+ for (int i = 0; i < regs.length; i++) { -+ context.setRegister(i, regs[i]); ++ ++ //@Override ++ //public int systemStreamWidth(SystemStream stream) { ++ // return 0; ++ //} ++ ++ @Override ++ public String toString() { ++ return "TerminalProvider[" + name() + "]"; + } -+ return context; -+ } +} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/RemoteDebuggerClient.java jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/RemoteDebuggerClient.java ---- openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/RemoteDebuggerClient.java 2022-10-12 23:00:03.000000000 +0800 -+++ jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/RemoteDebuggerClient.java 2023-09-12 13:54:26.377575791 +0800 -@@ -22,6 +22,12 @@ +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/ExternalTerminal.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/ExternalTerminal.java +index 2814b52c7..5033fd612 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/ExternalTerminal.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/ExternalTerminal.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2018, the original author or authors. ++ * Copyright (c) 2002-2018, the original author(s). * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -8,10 +8,6 @@ */ + package jdk.internal.org.jline.terminal.impl; -+/* -+ * This file has been modified by Loongson Technology in 2021, These -+ * modifications are Copyright (c) 2019, 2021, Loongson Technology, and are made -+ * available on the same license terms set forth above. -+ */ +-import jdk.internal.org.jline.terminal.Attributes; +-import jdk.internal.org.jline.terminal.Cursor; +-import jdk.internal.org.jline.terminal.Size; +- + import java.io.IOException; + import java.io.InputStream; + import java.io.OutputStream; +@@ -19,6 +15,11 @@ import java.nio.charset.Charset; + import java.util.concurrent.atomic.AtomicBoolean; + import java.util.function.IntConsumer; + ++import jdk.internal.org.jline.terminal.Attributes; ++import jdk.internal.org.jline.terminal.Cursor; ++import jdk.internal.org.jline.terminal.Size; ++import jdk.internal.org.jline.terminal.spi.TerminalProvider; + - package sun.jvm.hotspot.debugger.remote; + /** + * Console implementation with embedded line disciplined. + * +@@ -32,45 +33,59 @@ import java.util.function.IntConsumer; + */ + public class ExternalTerminal extends LineDisciplineTerminal { - import java.rmi.*; -@@ -34,6 +40,8 @@ - import sun.jvm.hotspot.debugger.remote.x86.*; - import sun.jvm.hotspot.debugger.remote.amd64.*; - import sun.jvm.hotspot.debugger.remote.ppc64.*; -+import sun.jvm.hotspot.debugger.remote.mips64.*; -+import sun.jvm.hotspot.debugger.remote.loongarch64.*; ++ private final TerminalProvider provider; + protected final AtomicBoolean closed = new AtomicBoolean(); + protected final InputStream masterInput; + protected final Object lock = new Object(); + protected boolean paused = true; + protected Thread pumpThread; - /** An implementation of Debugger which wraps a - RemoteDebugger, providing remote debugging via RMI. -@@ -76,6 +84,16 @@ - cachePageSize = 4096; - cacheNumPages = parseCacheNumPagesProperty(cacheSize / cachePageSize); - unalignedAccessesOkay = true; -+ } else if (cpu.equals("mips64") || cpu.equals("mips64el")) { -+ threadFactory = new RemoteMIPS64ThreadFactory(this); -+ cachePageSize = 4096; -+ cacheNumPages = parseCacheNumPagesProperty(cacheSize / cachePageSize); -+ unalignedAccessesOkay = true; -+ } else if (cpu.equals("loongarch64")) { -+ threadFactory = new RemoteLOONGARCH64ThreadFactory(this); -+ cachePageSize = 4096; -+ cacheNumPages = parseCacheNumPagesProperty(cacheSize / cachePageSize); -+ unalignedAccessesOkay = true; - } else { - try { - Class tf = Class.forName("sun.jvm.hotspot.debugger.remote." + -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/HotSpotAgent.java jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/HotSpotAgent.java ---- openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/HotSpotAgent.java 2022-10-12 23:00:03.000000000 +0800 -+++ jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/HotSpotAgent.java 2023-09-12 13:54:26.345575751 +0800 -@@ -23,6 +23,12 @@ +- public ExternalTerminal(String name, String type, +- InputStream masterInput, +- OutputStream masterOutput, +- Charset encoding) throws IOException { +- this(name, type, masterInput, masterOutput, encoding, SignalHandler.SIG_DFL); ++ public ExternalTerminal( ++ String name, String type, InputStream masterInput, OutputStream masterOutput, Charset encoding) ++ throws IOException { ++ this(null, name, type, masterInput, masterOutput, encoding, SignalHandler.SIG_DFL); + } + +- public ExternalTerminal(String name, String type, +- InputStream masterInput, +- OutputStream masterOutput, +- Charset encoding, +- SignalHandler signalHandler) throws IOException { +- this(name, type, masterInput, masterOutput, encoding, signalHandler, false); ++ public ExternalTerminal( ++ TerminalProvider provider, ++ String name, ++ String type, ++ InputStream masterInput, ++ OutputStream masterOutput, ++ Charset encoding, ++ SignalHandler signalHandler) ++ throws IOException { ++ this(provider, name, type, masterInput, masterOutput, encoding, signalHandler, false); + } + +- public ExternalTerminal(String name, String type, +- InputStream masterInput, +- OutputStream masterOutput, +- Charset encoding, +- SignalHandler signalHandler, +- boolean paused) throws IOException { +- this(name, type, masterInput, masterOutput, encoding, signalHandler, paused, null, null); ++ public ExternalTerminal( ++ TerminalProvider provider, ++ String name, ++ String type, ++ InputStream masterInput, ++ OutputStream masterOutput, ++ Charset encoding, ++ SignalHandler signalHandler, ++ boolean paused) ++ throws IOException { ++ this(provider, name, type, masterInput, masterOutput, encoding, signalHandler, paused, null, null); + } + +- public ExternalTerminal(String name, String type, +- InputStream masterInput, +- OutputStream masterOutput, +- Charset encoding, +- SignalHandler signalHandler, +- boolean paused, +- Attributes attributes, +- Size size) throws IOException { ++ @SuppressWarnings("this-escape") ++ public ExternalTerminal( ++ TerminalProvider provider, ++ String name, ++ String type, ++ InputStream masterInput, ++ OutputStream masterOutput, ++ Charset encoding, ++ SignalHandler signalHandler, ++ boolean paused, ++ Attributes attributes, ++ Size size) ++ throws IOException { + super(name, type, masterOutput, encoding, signalHandler); ++ this.provider = provider; + this.masterInput = masterInput; + if (attributes != null) { + setAttributes(attributes); +@@ -171,4 +186,8 @@ public class ExternalTerminal extends LineDisciplineTerminal { + return CursorSupport.getCursorPosition(this, discarded); + } + ++ @Override ++ public TerminalProvider getProvider() { ++ return provider; ++ } + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/LineDisciplineTerminal.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/LineDisciplineTerminal.java +index 0f290379b..4e7a396bb 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/LineDisciplineTerminal.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/LineDisciplineTerminal.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2018, the original author or authors. ++ * Copyright (c) 2002-2018, the original author(s). * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -14,6 +14,7 @@ import java.io.OutputStream; + import java.io.OutputStreamWriter; + import java.io.PrintWriter; + import java.nio.charset.Charset; ++import java.util.EnumSet; + import java.util.Objects; + + import jdk.internal.org.jline.terminal.Attributes; +@@ -23,6 +24,8 @@ import jdk.internal.org.jline.terminal.Attributes.LocalFlag; + import jdk.internal.org.jline.terminal.Attributes.OutputFlag; + import jdk.internal.org.jline.terminal.Size; + import jdk.internal.org.jline.terminal.Terminal; ++import jdk.internal.org.jline.terminal.spi.SystemStream; ++import jdk.internal.org.jline.terminal.spi.TerminalProvider; + import jdk.internal.org.jline.utils.NonBlocking; + import jdk.internal.org.jline.utils.NonBlockingPumpInputStream; + import jdk.internal.org.jline.utils.NonBlockingReader; +@@ -45,21 +48,6 @@ import jdk.internal.org.jline.utils.NonBlockingReader; */ + public class LineDisciplineTerminal extends AbstractTerminal { -+/* -+ * This file has been modified by Loongson Technology in 2021. These -+ * modifications are Copyright (c) 2018, 2021, Loongson Technology, and are made -+ * available on the same license terms set forth above. -+ * -+ */ - package sun.jvm.hotspot; +- private static final String DEFAULT_TERMINAL_ATTRIBUTES = +- "speed 9600 baud; 24 rows; 80 columns;\n" + +- "lflags: icanon isig iexten echo echoe -echok echoke -echonl echoctl\n" + +- "\t-echoprt -altwerase -noflsh -tostop -flusho pendin -nokerninfo\n" + +- "\t-extproc\n" + +- "iflags: -istrip icrnl -inlcr -igncr ixon -ixoff ixany imaxbel iutf8\n" + +- "\t-ignbrk brkint -inpck -ignpar -parmrk\n" + +- "oflags: opost onlcr -oxtabs -onocr -onlret\n" + +- "cflags: cread cs8 -parenb -parodd hupcl -clocal -cstopb -crtscts -dsrflow\n" + +- "\t-dtrflow -mdmbuf\n" + +- "cchars: discard = ^O; dsusp = ^Y; eof = ^D; eol = ;\n" + +- "\teol2 = ; erase = ^?; intr = ^C; kill = ^U; lnext = ^V;\n" + +- "\tmin = 1; quit = ^\\; reprint = ^R; start = ^Q; status = ^T;\n" + +- "\tstop = ^S; susp = ^Z; time = 0; werase = ^W;\n"; +- + private static final int PIPE_SIZE = 1024; - import java.rmi.RemoteException; -@@ -39,6 +45,8 @@ - import sun.jvm.hotspot.debugger.MachineDescriptionIntelX86; - import sun.jvm.hotspot.debugger.MachineDescriptionSPARC32Bit; - import sun.jvm.hotspot.debugger.MachineDescriptionSPARC64Bit; -+import sun.jvm.hotspot.debugger.MachineDescriptionMIPS64; -+import sun.jvm.hotspot.debugger.MachineDescriptionLOONGARCH64; - import sun.jvm.hotspot.debugger.NoSuchSymbolException; - import sun.jvm.hotspot.debugger.bsd.BsdDebuggerLocal; - import sun.jvm.hotspot.debugger.linux.LinuxDebuggerLocal; -@@ -598,6 +606,10 @@ - } else { - machDesc = new MachineDescriptionSPARC32Bit(); - } -+ } else if (cpu.equals("mips64")) { -+ machDesc = new MachineDescriptionMIPS64(); -+ } else if (cpu.equals("loongarch64")) { -+ machDesc = new MachineDescriptionLOONGARCH64(); - } else { - try { - machDesc = (MachineDescription) -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/linux_loongarch64/LinuxLOONGARCH64JavaThreadPDAccess.java jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/linux_loongarch64/LinuxLOONGARCH64JavaThreadPDAccess.java ---- openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/linux_loongarch64/LinuxLOONGARCH64JavaThreadPDAccess.java 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/linux_loongarch64/LinuxLOONGARCH64JavaThreadPDAccess.java 2023-09-12 13:54:26.429575856 +0800 -@@ -0,0 +1,133 @@ -+/* -+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2018, 2021, Loongson Technology. 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. -+ * -+ */ + /* +@@ -84,20 +72,20 @@ public class LineDisciplineTerminal extends AbstractTerminal { + * Console data + */ + protected final Attributes attributes; + -+package sun.jvm.hotspot.runtime.linux_loongarch64; + protected final Size size; + +- public LineDisciplineTerminal(String name, +- String type, +- OutputStream masterOutput, +- Charset encoding) throws IOException { ++ protected boolean skipNextLf; ++ ++ public LineDisciplineTerminal(String name, String type, OutputStream masterOutput, Charset encoding) ++ throws IOException { + this(name, type, masterOutput, encoding, SignalHandler.SIG_DFL); + } + +- public LineDisciplineTerminal(String name, +- String type, +- OutputStream masterOutput, +- Charset encoding, +- SignalHandler signalHandler) throws IOException { ++ @SuppressWarnings("this-escape") ++ public LineDisciplineTerminal( ++ String name, String type, OutputStream masterOutput, Charset encoding, SignalHandler signalHandler) ++ throws IOException { + super(name, type, encoding, signalHandler); + NonBlockingPumpInputStream input = NonBlocking.nonBlockingPumpInputStream(PIPE_SIZE); + this.slaveInputPipe = input.getOutputStream(); +@@ -106,11 +94,66 @@ public class LineDisciplineTerminal extends AbstractTerminal { + this.slaveOutput = new FilteringOutputStream(); + this.slaveWriter = new PrintWriter(new OutputStreamWriter(slaveOutput, encoding())); + this.masterOutput = masterOutput; +- this.attributes = ExecPty.doGetAttr(DEFAULT_TERMINAL_ATTRIBUTES); ++ this.attributes = getDefaultTerminalAttributes(); + this.size = new Size(160, 50); + parseInfoCmp(); + } + ++ private static Attributes getDefaultTerminalAttributes() { ++ // speed 9600 baud; 24 rows; 80 columns; ++ // lflags: icanon isig iexten echo echoe -echok echoke -echonl echoctl ++ // -echoprt -altwerase -noflsh -tostop -flusho pendin -nokerninfo ++ // -extproc ++ // iflags: -istrip icrnl -inlcr -igncr ixon -ixoff ixany imaxbel iutf8 ++ // -ignbrk brkint -inpck -ignpar -parmrk ++ // oflags: opost onlcr -oxtabs -onocr -onlret ++ // cflags: cread cs8 -parenb -parodd hupcl -clocal -cstopb -crtscts -dsrflow ++ // -dtrflow -mdmbuf ++ // cchars: discard = ^O; dsusp = ^Y; eof = ^D; eol = ; ++ // eol2 = ; erase = ^?; intr = ^C; kill = ^U; lnext = ^V; ++ // min = 1; quit = ^\\; reprint = ^R; start = ^Q; status = ^T; ++ // stop = ^S; susp = ^Z; time = 0; werase = ^W; ++ Attributes attr = new Attributes(); ++ attr.setLocalFlags(EnumSet.of( ++ LocalFlag.ICANON, ++ LocalFlag.ISIG, ++ LocalFlag.IEXTEN, ++ LocalFlag.ECHO, ++ LocalFlag.ECHOE, ++ LocalFlag.ECHOKE, ++ LocalFlag.ECHOCTL, ++ LocalFlag.PENDIN)); ++ attr.setInputFlags(EnumSet.of( ++ InputFlag.ICRNL, ++ InputFlag.IXON, ++ InputFlag.IXANY, ++ InputFlag.IMAXBEL, ++ InputFlag.IUTF8, ++ InputFlag.BRKINT)); ++ attr.setOutputFlags(EnumSet.of(OutputFlag.OPOST, OutputFlag.ONLCR)); ++ attr.setControlChar(ControlChar.VDISCARD, ctrl('O')); ++ attr.setControlChar(ControlChar.VDSUSP, ctrl('Y')); ++ attr.setControlChar(ControlChar.VEOF, ctrl('D')); ++ attr.setControlChar(ControlChar.VERASE, ctrl('?')); ++ attr.setControlChar(ControlChar.VINTR, ctrl('C')); ++ attr.setControlChar(ControlChar.VKILL, ctrl('U')); ++ attr.setControlChar(ControlChar.VLNEXT, ctrl('V')); ++ attr.setControlChar(ControlChar.VMIN, 1); ++ attr.setControlChar(ControlChar.VQUIT, ctrl('\\')); ++ attr.setControlChar(ControlChar.VREPRINT, ctrl('R')); ++ attr.setControlChar(ControlChar.VSTART, ctrl('Q')); ++ attr.setControlChar(ControlChar.VSTATUS, ctrl('T')); ++ attr.setControlChar(ControlChar.VSTOP, ctrl('S')); ++ attr.setControlChar(ControlChar.VSUSP, ctrl('Z')); ++ attr.setControlChar(ControlChar.VTIME, 0); ++ attr.setControlChar(ControlChar.VWERASE, ctrl('W')); ++ return attr; ++ } ++ ++ private static int ctrl(char c) { ++ return c == '?' ? 177 : c - 64; ++ } ++ + public NonBlockingReader reader() { + return slaveReader; + } +@@ -130,9 +173,7 @@ public class LineDisciplineTerminal extends AbstractTerminal { + } + + public Attributes getAttributes() { +- Attributes attr = new Attributes(); +- attr.copy(attributes); +- return attr; ++ return new Attributes(attributes); + } + + public void setAttributes(Attributes attr) { +@@ -149,9 +190,9 @@ public class LineDisciplineTerminal extends AbstractTerminal { + size.copy(sz); + } + +- @Override ++ @Override + public void raise(Signal signal) { +- Objects.requireNonNull(signal); ++ Objects.requireNonNull(signal); + // Do not call clear() atm as this can cause + // deadlock between reading / writing threads + // TODO: any way to fix that ? +@@ -214,7 +255,19 @@ public class LineDisciplineTerminal extends AbstractTerminal { + raise(Signal.INFO); + } + } +- if (c == '\r') { ++ if (attributes.getInputFlag(InputFlag.INORMEOL)) { ++ if (c == '\r') { ++ skipNextLf = true; ++ c = '\n'; ++ } else if (c == '\n') { ++ if (skipNextLf) { ++ skipNextLf = false; ++ return false; ++ } ++ } else { ++ skipNextLf = false; ++ } ++ } else if (c == '\r') { + if (attributes.getInputFlag(InputFlag.IGNCR)) { + return false; + } +@@ -273,6 +326,16 @@ public class LineDisciplineTerminal extends AbstractTerminal { + } + } + ++ @Override ++ public TerminalProvider getProvider() { ++ return null; ++ } + -+import java.io.*; -+import java.util.*; ++ @Override ++ public SystemStream getSystemStream() { ++ return null; ++ } + -+import sun.jvm.hotspot.debugger.*; -+import sun.jvm.hotspot.debugger.loongarch64.*; -+import sun.jvm.hotspot.runtime.*; -+import sun.jvm.hotspot.runtime.loongarch64.*; -+import sun.jvm.hotspot.types.*; -+import sun.jvm.hotspot.utilities.*; + private class FilteringOutputStream extends OutputStream { + @Override + public void write(int b) throws IOException { +@@ -284,13 +347,12 @@ public class LineDisciplineTerminal extends AbstractTerminal { + public void write(byte[] b, int off, int len) throws IOException { + if (b == null) { + throw new NullPointerException(); +- } else if ((off < 0) || (off > b.length) || (len < 0) || +- ((off + len) > b.length) || ((off + len) < 0)) { ++ } else if ((off < 0) || (off > b.length) || (len < 0) || ((off + len) > b.length) || ((off + len) < 0)) { + throw new IndexOutOfBoundsException(); + } else if (len == 0) { + return; + } +- for (int i = 0 ; i < len ; i++) { ++ for (int i = 0; i < len; i++) { + processOutputByte(b[off + i]); + } + flush(); +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/MouseSupport.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/MouseSupport.java +index 89ae6e5b7..eef25c90d 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/MouseSupport.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/MouseSupport.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2016, the original author or authors. ++ * Copyright (c) 2002-2016, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -8,11 +8,6 @@ + */ + package jdk.internal.org.jline.terminal.impl; + +-import jdk.internal.org.jline.terminal.MouseEvent; +-import jdk.internal.org.jline.terminal.Terminal; +-import jdk.internal.org.jline.utils.InfoCmp; +-import jdk.internal.org.jline.utils.InputStreamReader; +- + import java.io.EOFException; + import java.io.IOError; + import java.io.IOException; +@@ -20,6 +15,11 @@ import java.nio.charset.StandardCharsets; + import java.util.EnumSet; + import java.util.function.IntSupplier; + ++import jdk.internal.org.jline.terminal.MouseEvent; ++import jdk.internal.org.jline.terminal.Terminal; ++import jdk.internal.org.jline.utils.InfoCmp; ++import jdk.internal.org.jline.utils.InputStreamReader; + -+public class LinuxLOONGARCH64JavaThreadPDAccess implements JavaThreadPDAccess { -+ private static AddressField lastJavaFPField; -+ private static AddressField osThreadField; + public class MouseSupport { + + public static boolean hasMouseSupport(Terminal terminal) { +@@ -78,7 +78,8 @@ public class MouseSupport { + case 0: + button = MouseEvent.Button.Button1; + if (last.getButton() == button +- && (last.getType() == MouseEvent.Type.Pressed || last.getType() == MouseEvent.Type.Dragged)) { ++ && (last.getType() == MouseEvent.Type.Pressed ++ || last.getType() == MouseEvent.Type.Dragged)) { + type = MouseEvent.Type.Dragged; + } else { + type = MouseEvent.Type.Pressed; +@@ -87,7 +88,8 @@ public class MouseSupport { + case 1: + button = MouseEvent.Button.Button2; + if (last.getButton() == button +- && (last.getType() == MouseEvent.Type.Pressed || last.getType() == MouseEvent.Type.Dragged)) { ++ && (last.getType() == MouseEvent.Type.Pressed ++ || last.getType() == MouseEvent.Type.Dragged)) { + type = MouseEvent.Type.Dragged; + } else { + type = MouseEvent.Type.Pressed; +@@ -96,7 +98,8 @@ public class MouseSupport { + case 2: + button = MouseEvent.Button.Button3; + if (last.getButton() == button +- && (last.getType() == MouseEvent.Type.Pressed || last.getType() == MouseEvent.Type.Dragged)) { ++ && (last.getType() == MouseEvent.Type.Pressed ++ || last.getType() == MouseEvent.Type.Dragged)) { + type = MouseEvent.Type.Dragged; + } else { + type = MouseEvent.Type.Pressed; +@@ -134,5 +137,4 @@ public class MouseSupport { + throw new IOError(e); + } + } +- + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/NativeSignalHandler.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/NativeSignalHandler.java +index 00c584c6c..bba177794 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/NativeSignalHandler.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/NativeSignalHandler.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2016, the original author or authors. ++ * Copyright (c) 2002-2016, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -17,8 +17,7 @@ public final class NativeSignalHandler implements SignalHandler { + + public static final NativeSignalHandler SIG_IGN = new NativeSignalHandler(); + +- private NativeSignalHandler() { +- } ++ private NativeSignalHandler() {} + + public void handle(Signal signal) { + throw new UnsupportedOperationException(); +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/PosixPtyTerminal.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/PosixPtyTerminal.java +index f85e3fe0b..d34103e4d 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/PosixPtyTerminal.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/PosixPtyTerminal.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2018, the original author or authors. ++ * Copyright (c) 2002-2018, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -38,15 +38,34 @@ public class PosixPtyTerminal extends AbstractPosixTerminal { + private Thread outputPumpThread; + private boolean paused = true; + +- public PosixPtyTerminal(String name, String type, Pty pty, InputStream in, OutputStream out, Charset encoding) throws IOException { ++ public PosixPtyTerminal(String name, String type, Pty pty, InputStream in, OutputStream out, Charset encoding) ++ throws IOException { + this(name, type, pty, in, out, encoding, SignalHandler.SIG_DFL); + } + +- public PosixPtyTerminal(String name, String type, Pty pty, InputStream in, OutputStream out, Charset encoding, SignalHandler signalHandler) throws IOException { ++ public PosixPtyTerminal( ++ String name, ++ String type, ++ Pty pty, ++ InputStream in, ++ OutputStream out, ++ Charset encoding, ++ SignalHandler signalHandler) ++ throws IOException { + this(name, type, pty, in, out, encoding, signalHandler, false); + } + +- public PosixPtyTerminal(String name, String type, Pty pty, InputStream in, OutputStream out, Charset encoding, SignalHandler signalHandler, boolean paused) throws IOException { ++ @SuppressWarnings("this-escape") ++ public PosixPtyTerminal( ++ String name, ++ String type, ++ Pty pty, ++ InputStream in, ++ OutputStream out, ++ Charset encoding, ++ SignalHandler signalHandler, ++ boolean paused) ++ throws IOException { + super(name, type, pty, encoding, signalHandler); + this.in = Objects.requireNonNull(in); + this.out = Objects.requireNonNull(out); +@@ -113,7 +132,7 @@ public class PosixPtyTerminal extends AbstractPosixTerminal { + if (p1 != null) { + p1.join(); + } +- if (p2 !=null) { ++ if (p2 != null) { + p2.join(); + } + } +@@ -167,7 +186,7 @@ public class PosixPtyTerminal extends AbstractPosixTerminal { + + private void pumpIn() { + try { +- for (;;) { ++ for (; ; ) { + synchronized (lock) { + if (paused) { + inputPumpThread = null; +@@ -193,7 +212,7 @@ public class PosixPtyTerminal extends AbstractPosixTerminal { + + private void pumpOut() { + try { +- for (;;) { ++ for (; ; ) { + synchronized (lock) { + if (paused) { + outputPumpThread = null; +@@ -221,5 +240,4 @@ public class PosixPtyTerminal extends AbstractPosixTerminal { + // Ignore + } + } +- + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/PosixSysTerminal.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/PosixSysTerminal.java +index a55f3d4a7..135ed0bb0 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/PosixSysTerminal.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/PosixSysTerminal.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2018, the original author or authors. ++ * Copyright (c) 2002-2018, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -18,8 +18,9 @@ import java.util.HashMap; + import java.util.Map; + import java.util.function.Function; + +-import jdk.internal.org.jline.utils.NonBlocking; + import jdk.internal.org.jline.terminal.spi.Pty; ++import jdk.internal.org.jline.utils.FastBufferedOutputStream; ++import jdk.internal.org.jline.utils.NonBlocking; + import jdk.internal.org.jline.utils.NonBlockingInputStream; + import jdk.internal.org.jline.utils.NonBlockingReader; + import jdk.internal.org.jline.utils.ShutdownHooks; +@@ -35,12 +36,14 @@ public class PosixSysTerminal extends AbstractPosixTerminal { + protected final Map nativeHandlers = new HashMap<>(); + protected final Task closer; + +- public PosixSysTerminal(String name, String type, Pty pty, Charset encoding, +- boolean nativeSignals, SignalHandler signalHandler, +- Function inputStreamWrapper) throws IOException { ++ @SuppressWarnings("this-escape") ++ public PosixSysTerminal( ++ String name, String type, Pty pty, Charset encoding, boolean nativeSignals, SignalHandler signalHandler, ++ Function inputStreamWrapper) ++ throws IOException { + super(name, type, pty, encoding, signalHandler); + this.input = NonBlocking.nonBlocking(getName(), inputStreamWrapper.apply(pty.getSlaveInput())); +- this.output = pty.getSlaveOutput(); ++ this.output = new FastBufferedOutputStream(pty.getSlaveOutput()); + this.reader = NonBlocking.nonBlocking(getName(), input, encoding()); + this.writer = new PrintWriter(new OutputStreamWriter(output, encoding())); + parseInfoCmp(); +@@ -98,5 +101,4 @@ public class PosixSysTerminal extends AbstractPosixTerminal { + // Do not call reader.close() + reader.shutdown(); + } +- + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/ExecPty.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/exec/ExecPty.java +similarity index 71% +rename from src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/ExecPty.java +rename to src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/exec/ExecPty.java +index 5377b4acd..c0a35cbd6 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/ExecPty.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/exec/ExecPty.java +@@ -1,18 +1,18 @@ + /* +- * Copyright (c) 2002-2016, the original author or authors. ++ * Copyright (c) 2002-2016, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * https://opensource.org/licenses/BSD-3-Clause + */ +-package jdk.internal.org.jline.terminal.impl; ++package jdk.internal.org.jline.terminal.impl.exec; + ++import java.io.FileDescriptor; + import java.io.FileInputStream; + import java.io.FileOutputStream; + import java.io.IOException; + import java.io.InputStream; +-import java.io.FileDescriptor; + import java.io.OutputStream; + import java.util.ArrayList; + import java.util.List; +@@ -26,8 +26,10 @@ import jdk.internal.org.jline.terminal.Attributes.InputFlag; + import jdk.internal.org.jline.terminal.Attributes.LocalFlag; + import jdk.internal.org.jline.terminal.Attributes.OutputFlag; + import jdk.internal.org.jline.terminal.Size; +-import jdk.internal.org.jline.terminal.spi.TerminalProvider; ++import jdk.internal.org.jline.terminal.impl.AbstractPty; + import jdk.internal.org.jline.terminal.spi.Pty; ++import jdk.internal.org.jline.terminal.spi.SystemStream; ++import jdk.internal.org.jline.terminal.spi.TerminalProvider; + import jdk.internal.org.jline.utils.OSUtils; + + import static jdk.internal.org.jline.utils.ExecHelper.exec; +@@ -35,28 +37,26 @@ import static jdk.internal.org.jline.utils.ExecHelper.exec; + public class ExecPty extends AbstractPty implements Pty { + + private final String name; +- private final TerminalProvider.Stream console; + +- public static Pty current(TerminalProvider.Stream console) throws IOException { ++ public static Pty current(TerminalProvider provider, SystemStream systemStream) throws IOException { + try { + String result = exec(true, OSUtils.TTY_COMMAND); +- if (console != TerminalProvider.Stream.Output && console != TerminalProvider.Stream.Error) { +- throw new IllegalArgumentException("console should be Output or Error: " + console); ++ if (systemStream != SystemStream.Output && systemStream != SystemStream.Error) { ++ throw new IllegalArgumentException("systemStream should be Output or Error: " + systemStream); + } +- return new ExecPty(result.trim(), console); ++ return new ExecPty(provider, systemStream, result.trim()); + } catch (IOException e) { + throw new IOException("Not a tty", e); + } + } + +- protected ExecPty(String name, TerminalProvider.Stream console) { ++ protected ExecPty(TerminalProvider provider, SystemStream systemStream, String name) { ++ super(provider, systemStream); + this.name = name; +- this.console = console; + } + + @Override +- public void close() throws IOException { +- } ++ public void close() throws IOException {} + + public String getName() { + return name; +@@ -74,18 +74,16 @@ public class ExecPty extends AbstractPty implements Pty { + + @Override + protected InputStream doGetSlaveInput() throws IOException { +- return console != null +- ? new FileInputStream(FileDescriptor.in) +- : new FileInputStream(getName()); ++ return systemStream != null ? new FileInputStream(FileDescriptor.in) : new FileInputStream(getName()); + } + + @Override + public OutputStream getSlaveOutput() throws IOException { +- return console == TerminalProvider.Stream.Output ++ return systemStream == SystemStream.Output + ? new FileOutputStream(FileDescriptor.out) +- : console == TerminalProvider.Stream.Error +- ? new FileOutputStream(FileDescriptor.err) +- : new FileOutputStream(getName()); ++ : systemStream == SystemStream.Error ++ ? new FileOutputStream(FileDescriptor.err) ++ : new FileOutputStream(getName()); + } + + @Override +@@ -99,18 +97,30 @@ public class ExecPty extends AbstractPty implements Pty { + List commands = getFlagsToSet(attr, getAttr()); + if (!commands.isEmpty()) { + commands.add(0, OSUtils.STTY_COMMAND); +- if (console == null) { ++ if (systemStream == null) { + commands.add(1, OSUtils.STTY_F_OPTION); + commands.add(2, getName()); + } +- exec(console != null, commands.toArray(new String[0])); ++ try { ++ exec(systemStream != null, commands.toArray(new String[0])); ++ } catch (IOException e) { ++ // Handle partial failures with GNU stty, see #97 ++ if (e.toString().contains("unable to perform all requested operations")) { ++ commands = getFlagsToSet(attr, getAttr()); ++ if (!commands.isEmpty()) { ++ throw new IOException("Could not set the following flags: " + String.join(", ", commands), e); ++ } ++ } else { ++ throw e; ++ } ++ } + } + } + + protected List getFlagsToSet(Attributes attr, Attributes current) { + List commands = new ArrayList<>(); + for (InputFlag flag : InputFlag.values()) { +- if (attr.getInputFlag(flag) != current.getInputFlag(flag)) { ++ if (attr.getInputFlag(flag) != current.getInputFlag(flag) && flag != InputFlag.INORMEOL) { + commands.add((attr.getInputFlag(flag) ? flag.name() : "-" + flag.name()).toLowerCase()); + } + } +@@ -137,11 +147,9 @@ public class ExecPty extends AbstractPty implements Pty { + commands.add(cchar.name().toLowerCase().substring(1)); + if (cchar == ControlChar.VMIN || cchar == ControlChar.VTIME) { + commands.add(Integer.toString(v)); +- } +- else if (v == 0) { ++ } else if (v == 0) { + commands.add(undef); +- } +- else { ++ } else { + if (v >= 128) { + v -= 128; + str += "M-"; +@@ -165,12 +173,12 @@ public class ExecPty extends AbstractPty implements Pty { + } + + protected String doGetConfig() throws IOException { +- return console != null +- ? exec(true, OSUtils.STTY_COMMAND, "-a") ++ return systemStream != null ++ ? exec(true, OSUtils.STTY_COMMAND, "-a") + : exec(false, OSUtils.STTY_COMMAND, OSUtils.STTY_F_OPTION, getName(), "-a"); + } + +- static Attributes doGetAttr(String cfg) throws IOException { ++ public static Attributes doGetAttr(String cfg) throws IOException { + Attributes attributes = new Attributes(); + for (InputFlag flag : InputFlag.values()) { + Boolean value = doGetFlag(cfg, flag); +@@ -201,16 +209,19 @@ public class ExecPty extends AbstractPty implements Pty { + if ("reprint".endsWith(name)) { + name = "(?:reprint|rprnt)"; + } +- Matcher matcher = Pattern.compile("[\\s;]" + name + "\\s*=\\s*(.+?)[\\s;]").matcher(cfg); ++ Matcher matcher = ++ Pattern.compile("[\\s;]" + name + "\\s*=\\s*(.+?)[\\s;]").matcher(cfg); + if (matcher.find()) { +- attributes.setControlChar(cchar, parseControlChar(matcher.group(1).toUpperCase())); ++ attributes.setControlChar( ++ cchar, parseControlChar(matcher.group(1).toUpperCase())); + } + } + return attributes; + } + + private static Boolean doGetFlag(String cfg, Enum flag) { +- Matcher matcher = Pattern.compile("(?:^|[\\s;])(\\-?" + flag.name().toLowerCase() + ")(?:[\\s;]|$)").matcher(cfg); ++ Matcher matcher = Pattern.compile("(?:^|[\\s;])(\\-?" + flag.name().toLowerCase() + ")(?:[\\s;]|$)") ++ .matcher(cfg); + return matcher.find() ? !matcher.group(1).startsWith("-") : null; + } + +@@ -259,9 +270,7 @@ public class ExecPty extends AbstractPty implements Pty { + + static int doGetInt(String name, String cfg) throws IOException { + String[] patterns = new String[] { +- "\\b([0-9]+)\\s+" + name + "\\b", +- "\\b" + name + "\\s+([0-9]+)\\b", +- "\\b" + name + "\\s*=\\s*([0-9]+)\\b" ++ "\\b([0-9]+)\\s+" + name + "\\b", "\\b" + name + "\\s+([0-9]+)\\b", "\\b" + name + "\\s*=\\s*([0-9]+)\\b" + }; + for (String pattern : patterns) { + Matcher matcher = Pattern.compile(pattern).matcher(cfg); +@@ -274,23 +283,29 @@ public class ExecPty extends AbstractPty implements Pty { + + @Override + public void setSize(Size size) throws IOException { +- if (console != null) { +- exec(true, +- OSUtils.STTY_COMMAND, +- "columns", Integer.toString(size.getColumns()), +- "rows", Integer.toString(size.getRows())); ++ if (systemStream != null) { ++ exec( ++ true, ++ OSUtils.STTY_COMMAND, ++ "columns", ++ Integer.toString(size.getColumns()), ++ "rows", ++ Integer.toString(size.getRows())); + } else { +- exec(false, +- OSUtils.STTY_COMMAND, +- OSUtils.STTY_F_OPTION, getName(), +- "columns", Integer.toString(size.getColumns()), +- "rows", Integer.toString(size.getRows())); ++ exec( ++ false, ++ OSUtils.STTY_COMMAND, ++ OSUtils.STTY_F_OPTION, ++ getName(), ++ "columns", ++ Integer.toString(size.getColumns()), ++ "rows", ++ Integer.toString(size.getRows())); + } + } + + @Override + public String toString() { +- return "ExecPty[" + getName() + (console != null ? ", system]" : "]"); ++ return "ExecPty[" + getName() + (systemStream != null ? ", system]" : "]"); + } +- + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/exec/ExecTerminalProvider.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/exec/ExecTerminalProvider.java +index 8bdeede2e..36ff4a635 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/exec/ExecTerminalProvider.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/exec/ExecTerminalProvider.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2022, the original author or authors. ++ * Copyright (c) 2022, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -17,117 +17,249 @@ import java.lang.reflect.Field; + import java.nio.charset.Charset; + import java.util.function.Function; + ++//import jdk.internal.org.jline.nativ.JLineLibrary; ++//import jdk.internal.org.jline.nativ.JLineNativeLoader; + import jdk.internal.org.jline.terminal.Attributes; + import jdk.internal.org.jline.terminal.Size; + import jdk.internal.org.jline.terminal.Terminal; +-import jdk.internal.org.jline.terminal.impl.ExecPty; ++import jdk.internal.org.jline.terminal.TerminalBuilder; + import jdk.internal.org.jline.terminal.impl.ExternalTerminal; + import jdk.internal.org.jline.terminal.impl.PosixSysTerminal; + import jdk.internal.org.jline.terminal.spi.Pty; ++import jdk.internal.org.jline.terminal.spi.SystemStream; + import jdk.internal.org.jline.terminal.spi.TerminalProvider; + import jdk.internal.org.jline.utils.ExecHelper; ++import jdk.internal.org.jline.utils.Log; + import jdk.internal.org.jline.utils.OSUtils; + +-public class ExecTerminalProvider implements TerminalProvider +-{ ++import static jdk.internal.org.jline.terminal.TerminalBuilder.PROP_REDIRECT_PIPE_CREATION_MODE; ++import static jdk.internal.org.jline.terminal.TerminalBuilder.PROP_REDIRECT_PIPE_CREATION_MODE_DEFAULT; ++import static jdk.internal.org.jline.terminal.TerminalBuilder.PROP_REDIRECT_PIPE_CREATION_MODE_NATIVE; ++import static jdk.internal.org.jline.terminal.TerminalBuilder.PROP_REDIRECT_PIPE_CREATION_MODE_REFLECTION; + -+ // Field from OSThread -+ private static CIntegerField osThreadThreadIDField; ++public class ExecTerminalProvider implements TerminalProvider { + -+ // This is currently unneeded but is being kept in case we change -+ // the currentFrameGuess algorithm -+ private static final long GUESS_SCAN_RANGE = 128 * 1024; ++ private static boolean warned; + + public String name() { +- return "exec"; ++ return TerminalBuilder.PROP_PROVIDER_EXEC; + } + +- public Pty current(Stream consoleStream) throws IOException { +- return ExecPty.current(consoleStream); ++ public Pty current(SystemStream systemStream) throws IOException { ++ return ExecPty.current(this, systemStream); + } + + @Override +- public Terminal sysTerminal(String name, String type, boolean ansiPassThrough, Charset encoding, +- boolean nativeSignals, Terminal.SignalHandler signalHandler, boolean paused, +- Stream consoleStream, Function inputStreamWrapper) throws IOException { ++ public Terminal sysTerminal( ++ String name, ++ String type, ++ boolean ansiPassThrough, ++ Charset encoding, ++ boolean nativeSignals, ++ Terminal.SignalHandler signalHandler, ++ boolean paused, ++ SystemStream systemStream, ++ Function inputStreamWrapper) ++ throws IOException { + if (OSUtils.IS_WINDOWS) { +- return winSysTerminal(name, type, ansiPassThrough, encoding, nativeSignals, signalHandler, paused, consoleStream, inputStreamWrapper ); ++ return winSysTerminal( ++ name, type, ansiPassThrough, encoding, nativeSignals, signalHandler, paused, systemStream, inputStreamWrapper); + } else { +- return posixSysTerminal(name, type, ansiPassThrough, encoding, nativeSignals, signalHandler, paused, consoleStream, inputStreamWrapper ); ++ return posixSysTerminal( ++ name, type, ansiPassThrough, encoding, nativeSignals, signalHandler, paused, systemStream, inputStreamWrapper); + } + } + +- public Terminal winSysTerminal(String name, String type, boolean ansiPassThrough, Charset encoding, +- boolean nativeSignals, Terminal.SignalHandler signalHandler, boolean paused, +- Stream consoleStream, Function inputStreamWrapper ) throws IOException { ++ public Terminal winSysTerminal( ++ String name, ++ String type, ++ boolean ansiPassThrough, ++ Charset encoding, ++ boolean nativeSignals, ++ Terminal.SignalHandler signalHandler, ++ boolean paused, ++ SystemStream systemStream, ++ Function inputStreamWrapper) ++ throws IOException { + if (OSUtils.IS_CYGWIN || OSUtils.IS_MSYSTEM) { +- Pty pty = current(consoleStream); ++ Pty pty = current(systemStream); + return new PosixSysTerminal(name, type, pty, encoding, nativeSignals, signalHandler, inputStreamWrapper); + } else { + return null; + } + } + +- public Terminal posixSysTerminal(String name, String type, boolean ansiPassThrough, Charset encoding, +- boolean nativeSignals, Terminal.SignalHandler signalHandler, boolean paused, +- Stream consoleStream, Function inputStreamWrapper) throws IOException { +- Pty pty = current(consoleStream); ++ public Terminal posixSysTerminal( ++ String name, ++ String type, ++ boolean ansiPassThrough, ++ Charset encoding, ++ boolean nativeSignals, ++ Terminal.SignalHandler signalHandler, ++ boolean paused, ++ SystemStream systemStream, ++ Function inputStreamWrapper) ++ throws IOException { ++ Pty pty = current(systemStream); + return new PosixSysTerminal(name, type, pty, encoding, nativeSignals, signalHandler, inputStreamWrapper); + } + + @Override +- public Terminal newTerminal(String name, String type, InputStream in, OutputStream out, +- Charset encoding, Terminal.SignalHandler signalHandler, boolean paused, +- Attributes attributes, Size size) throws IOException +- { +- return new ExternalTerminal(name, type, in, out, encoding, signalHandler, paused, attributes, size); ++ public Terminal newTerminal( ++ String name, ++ String type, ++ InputStream in, ++ OutputStream out, ++ Charset encoding, ++ Terminal.SignalHandler signalHandler, ++ boolean paused, ++ Attributes attributes, ++ Size size) ++ throws IOException { ++ return new ExternalTerminal(this, name, type, in, out, encoding, signalHandler, paused, attributes, size); + } + + @Override +- public boolean isSystemStream(Stream stream) { ++ public boolean isSystemStream(SystemStream stream) { + try { +- return isWindowsSystemStream(stream) || isPosixSystemStream(stream); ++ return isPosixSystemStream(stream) || isWindowsSystemStream(stream); + } catch (Throwable t) { + return false; + } + } + +- public boolean isWindowsSystemStream(Stream stream) { +- return systemStreamName( stream ) != null; ++ public boolean isWindowsSystemStream(SystemStream stream) { ++ return systemStreamName(stream) != null; + } + +- public boolean isPosixSystemStream(Stream stream) { ++ public boolean isPosixSystemStream(SystemStream stream) { + try { + Process p = new ProcessBuilder(OSUtils.TEST_COMMAND, "-t", Integer.toString(stream.ordinal())) +- .inheritIO().start(); ++ .inheritIO() ++ .start(); + return p.waitFor() == 0; + } catch (Throwable t) { ++ Log.debug("ExecTerminalProvider failed 'test -t' for " + stream, t); + // ignore + } + return false; + } + + @Override +- public String systemStreamName(Stream stream) { ++ public String systemStreamName(SystemStream stream) { + try { +- ProcessBuilder.Redirect input = stream == Stream.Input +- ? ProcessBuilder.Redirect.INHERIT +- : getRedirect(stream == Stream.Output ? FileDescriptor.out : FileDescriptor.err); +- Process p = new ProcessBuilder(OSUtils.TTY_COMMAND).redirectInput(input).start(); ++ ProcessBuilder.Redirect input = stream == SystemStream.Input ++ ? ProcessBuilder.Redirect.INHERIT ++ : newDescriptor(stream == SystemStream.Output ? FileDescriptor.out : FileDescriptor.err); ++ Process p = ++ new ProcessBuilder(OSUtils.TTY_COMMAND).redirectInput(input).start(); + String result = ExecHelper.waitAndCapture(p); + if (p.exitValue() == 0) { + return result.trim(); + } + } catch (Throwable t) { ++ if ("java.lang.reflect.InaccessibleObjectException" ++ .equals(t.getClass().getName()) ++ && !warned) { ++ Log.warn( ++ "The ExecTerminalProvider requires the JVM options: '--add-opens java.base/java.lang=ALL-UNNAMED'"); ++ warned = true; ++ } + // ignore + } + return null; + } + +- private ProcessBuilder.Redirect getRedirect(FileDescriptor fd) throws ReflectiveOperationException { +- // This is not really allowed, but this is the only way to redirect the output or error stream +- // to the input. This is definitely not something you'd usually want to do, but in the case of +- // the `tty` utility, it provides a way to get +- Class rpi = Class.forName("java.lang.ProcessBuilder$RedirectPipeImpl"); +- Constructor cns = rpi.getDeclaredConstructor(); +- cns.setAccessible(true); +- ProcessBuilder.Redirect input = (ProcessBuilder.Redirect) cns.newInstance(); +- Field f = rpi.getDeclaredField("fd"); +- f.setAccessible(true); +- f.set(input, fd); +- return input; ++// @Override ++// public int systemStreamWidth(SystemStream stream) { ++// try (ExecPty pty = new ExecPty(this, stream, null)) { ++// return pty.getSize().getColumns(); ++// } catch (Throwable t) { ++// return -1; ++// } ++// } + -+ static { -+ VM.registerVMInitializedObserver(new Observer() { -+ public void update(Observable o, Object data) { -+ initialize(VM.getVM().getTypeDataBase()); ++ private static RedirectPipeCreator redirectPipeCreator; ++ ++ protected static ProcessBuilder.Redirect newDescriptor(FileDescriptor fd) { ++ if (redirectPipeCreator == null) { ++ String str = System.getProperty(PROP_REDIRECT_PIPE_CREATION_MODE, PROP_REDIRECT_PIPE_CREATION_MODE_DEFAULT); ++ String[] modes = str.split(","); ++ IllegalStateException ise = new IllegalStateException("Unable to create RedirectPipe"); ++ for (String mode : modes) { ++ try { ++ switch (mode) { ++ case PROP_REDIRECT_PIPE_CREATION_MODE_NATIVE: ++ redirectPipeCreator = null;//new NativeRedirectPipeCreator(); ++ break; ++ case PROP_REDIRECT_PIPE_CREATION_MODE_REFLECTION: ++ redirectPipeCreator = new ReflectionRedirectPipeCreator(); ++ break; ++ } ++ } catch (Throwable t) { ++ // ignore ++ ise.addSuppressed(t); ++ } ++ if (redirectPipeCreator != null) { ++ break; ++ } ++ } ++ if (redirectPipeCreator == null) { ++ throw ise; ++ } + } -+ }); -+ } -+ -+ private static synchronized void initialize(TypeDataBase db) { -+ Type type = db.lookupType("JavaThread"); -+ osThreadField = type.getAddressField("_osthread"); -+ -+ Type anchorType = db.lookupType("JavaFrameAnchor"); -+ lastJavaFPField = anchorType.getAddressField("_last_Java_fp"); -+ -+ Type osThreadType = db.lookupType("OSThread"); -+ osThreadThreadIDField = osThreadType.getCIntegerField("_thread_id"); -+ } -+ -+ public Address getLastJavaFP(Address addr) { -+ return lastJavaFPField.getValue(addr.addOffsetTo(sun.jvm.hotspot.runtime.JavaThread.getAnchorField().getOffset())); -+ } -+ -+ public Address getLastJavaPC(Address addr) { -+ return null; -+ } -+ -+ public Address getBaseOfStackPointer(Address addr) { -+ return null; -+ } -+ -+ public Frame getLastFramePD(JavaThread thread, Address addr) { -+ Address fp = thread.getLastJavaFP(); -+ if (fp == null) { -+ return null; // no information ++ return redirectPipeCreator.newRedirectPipe(fd); + } -+ return new LOONGARCH64Frame(thread.getLastJavaSP(), fp); -+ } -+ -+ public RegisterMap newRegisterMap(JavaThread thread, boolean updateMap) { -+ return new LOONGARCH64RegisterMap(thread, updateMap); -+ } + -+ public Frame getCurrentFrameGuess(JavaThread thread, Address addr) { -+ ThreadProxy t = getThreadProxy(addr); -+ LOONGARCH64ThreadContext context = (LOONGARCH64ThreadContext) t.getContext(); -+ LOONGARCH64CurrentFrameGuess guesser = new LOONGARCH64CurrentFrameGuess(context, thread); -+ if (!guesser.run(GUESS_SCAN_RANGE)) { -+ return null; -+ } -+ if (guesser.getPC() == null) { -+ return new LOONGARCH64Frame(guesser.getSP(), guesser.getFP()); -+ } else { -+ return new LOONGARCH64Frame(guesser.getSP(), guesser.getFP(), guesser.getPC()); ++ interface RedirectPipeCreator { ++ ProcessBuilder.Redirect newRedirectPipe(FileDescriptor fd); + } -+ } + -+ public void printThreadIDOn(Address addr, PrintStream tty) { -+ tty.print(getThreadProxy(addr)); -+ } ++ /** ++ * Reflection based file descriptor creator. ++ * This requires the following option ++ * --add-opens java.base/java.lang=ALL-UNNAMED ++ */ ++ static class ReflectionRedirectPipeCreator implements RedirectPipeCreator { ++ private final Constructor constructor; ++ private final Field fdField; ++ ++ @SuppressWarnings("unchecked") ++ ReflectionRedirectPipeCreator() throws Exception { ++ Class rpi = Class.forName("java.lang.ProcessBuilder$RedirectPipeImpl"); ++ constructor = (Constructor) rpi.getDeclaredConstructor(); ++ constructor.setAccessible(true); ++ fdField = rpi.getDeclaredField("fd"); ++ fdField.setAccessible(true); ++ } + -+ public void printInfoOn(Address threadAddr, PrintStream tty) { -+ tty.print("Thread id: "); -+ printThreadIDOn(threadAddr, tty); -+ // tty.println("\nPostJavaState: " + getPostJavaState(threadAddr)); -+ } ++ @Override ++ public ProcessBuilder.Redirect newRedirectPipe(FileDescriptor fd) { ++ try { ++ ProcessBuilder.Redirect input = constructor.newInstance(); ++ fdField.set(input, fd); ++ return input; ++ } catch (ReflectiveOperationException e) { ++ // This should not happen as the field has been set accessible ++ throw new IllegalStateException(e); ++ } ++ } ++ } + -+ public Address getLastSP(Address addr) { -+ ThreadProxy t = getThreadProxy(addr); -+ LOONGARCH64ThreadContext context = (LOONGARCH64ThreadContext) t.getContext(); -+ return context.getRegisterAsAddress(LOONGARCH64ThreadContext.SP); -+ } ++// static class NativeRedirectPipeCreator implements RedirectPipeCreator { ++// public NativeRedirectPipeCreator() { ++// // Force load the library ++// JLineNativeLoader.initialize(); ++// } ++// ++// @Override ++// public ProcessBuilder.Redirect newRedirectPipe(FileDescriptor fd) { ++// return JLineLibrary.newRedirectPipe(fd); ++// } ++// } + -+ public ThreadProxy getThreadProxy(Address addr) { -+ // Addr is the address of the JavaThread. -+ // Fetch the OSThread (for now and for simplicity, not making a -+ // separate "OSThread" class in this package) -+ Address osThreadAddr = osThreadField.getValue(addr); -+ // Get the address of the _thread_id from the OSThread -+ Address threadIdAddr = osThreadAddr.addOffsetTo(osThreadThreadIDField.getOffset()); ++ @Override ++ public String toString() { ++ return "TerminalProvider[" + name() + "]"; + } + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/spi/Pty.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/spi/Pty.java +index b1e220567..d72e0e669 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/spi/Pty.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/spi/Pty.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2016, the original author or authors. ++ * Copyright (c) 2002-2016, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -34,4 +34,7 @@ public interface Pty extends Closeable { + + void setSize(Size size) throws IOException; + ++ SystemStream getSystemStream(); + -+ JVMDebugger debugger = VM.getVM().getDebugger(); -+ return debugger.getThreadForIdentifierAddress(threadIdAddr); -+ } -+} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/linux_mips64/LinuxMIPS64JavaThreadPDAccess.java jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/linux_mips64/LinuxMIPS64JavaThreadPDAccess.java ---- openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/linux_mips64/LinuxMIPS64JavaThreadPDAccess.java 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/linux_mips64/LinuxMIPS64JavaThreadPDAccess.java 2023-09-12 13:54:26.429575856 +0800 -@@ -0,0 +1,133 @@ ++ TerminalProvider getProvider(); + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/spi/SystemStream.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/spi/SystemStream.java +new file mode 100644 +index 000000000..5f9502482 +--- /dev/null ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/spi/SystemStream.java +@@ -0,0 +1,15 @@ +/* -+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2018, Loongson Technology. 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. ++ * Copyright (c) 2023, the original author(s). + * -+ * 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). ++ * This software is distributable under the BSD license. See the terms of the ++ * BSD license in the documentation provided with this software. + * -+ * 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. ++ * https://opensource.org/licenses/BSD-3-Clause ++ */ ++package jdk.internal.org.jline.terminal.spi; ++ ++public enum SystemStream { ++ Input, ++ Output, ++ Error ++} +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/spi/TerminalExt.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/spi/TerminalExt.java +new file mode 100644 +index 000000000..00cfb2e9d +--- /dev/null ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/spi/TerminalExt.java +@@ -0,0 +1,31 @@ ++/* ++ * Copyright (c) 2023, the original author(s). + * -+ * 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 software is distributable under the BSD license. See the terms of the ++ * BSD license in the documentation provided with this software. + * ++ * https://opensource.org/licenses/BSD-3-Clause + */ ++package jdk.internal.org.jline.terminal.spi; + -+package sun.jvm.hotspot.runtime.linux_mips64; ++import jdk.internal.org.jline.terminal.Terminal; + -+import java.io.*; -+import java.util.*; ++/** ++ * The {@code TerminalExt} interface is implemented by {@code Terminal}s ++ * and provides access to the Terminal's internals. ++ */ ++public interface TerminalExt extends Terminal { + -+import sun.jvm.hotspot.debugger.*; -+import sun.jvm.hotspot.debugger.mips64.*; -+import sun.jvm.hotspot.runtime.*; -+import sun.jvm.hotspot.runtime.mips64.*; -+import sun.jvm.hotspot.types.*; -+import sun.jvm.hotspot.utilities.*; ++ /** ++ * Returns the {@code TerminalProvider} that created this terminal ++ * or {@code null} if the terminal was created with no provider. ++ */ ++ TerminalProvider getProvider(); + -+public class LinuxMIPS64JavaThreadPDAccess implements JavaThreadPDAccess { -+ private static AddressField osThreadField; ++ /** ++ * The underlying system stream, may be {@link SystemStream#Output}, ++ * {@link SystemStream#Error}, or {@code null} if this terminal is not bound ++ * to a system stream. ++ */ ++ SystemStream getSystemStream(); ++} +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/spi/TerminalProvider.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/spi/TerminalProvider.java +index 69f353c57..272df6fed 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/spi/TerminalProvider.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/spi/TerminalProvider.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2022, the original author or authors. ++ * Copyright (c) 2022, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -11,10 +11,8 @@ package jdk.internal.org.jline.terminal.spi; + import java.io.IOException; + import java.io.InputStream; + import java.io.OutputStream; +-import java.net.URL; + import java.nio.charset.Charset; + import java.util.Properties; +-import java.util.ServiceLoader; + import java.util.function.Function; + + import jdk.internal.org.jline.terminal.Attributes; +@@ -22,30 +20,39 @@ import jdk.internal.org.jline.terminal.Size; + import jdk.internal.org.jline.terminal.Terminal; + import jdk.internal.org.jline.terminal.impl.exec.ExecTerminalProvider; + +-public interface TerminalProvider +-{ +- +- enum Stream { +- Input, +- Output, +- Error +- } ++public interface TerminalProvider { + + String name(); + +- Terminal sysTerminal(String name, String type, boolean ansiPassThrough, +- Charset encoding, boolean nativeSignals, +- Terminal.SignalHandler signalHandler, boolean paused, +- Stream consoleStream, Function inputStreamWrapper) throws IOException; ++ Terminal sysTerminal( ++ String name, ++ String type, ++ boolean ansiPassThrough, ++ Charset encoding, ++ boolean nativeSignals, ++ Terminal.SignalHandler signalHandler, ++ boolean paused, ++ SystemStream systemStream, ++ Function inputStreamWrapper) ++ throws IOException; + +- Terminal newTerminal(String name, String type, +- InputStream masterInput, OutputStream masterOutput, +- Charset encoding, Terminal.SignalHandler signalHandler, +- boolean paused, Attributes attributes, Size size) throws IOException; ++ Terminal newTerminal( ++ String name, ++ String type, ++ InputStream masterInput, ++ OutputStream masterOutput, ++ Charset encoding, ++ Terminal.SignalHandler signalHandler, ++ boolean paused, ++ Attributes attributes, ++ Size size) ++ throws IOException; + +- boolean isSystemStream(Stream stream); ++ boolean isSystemStream(SystemStream stream); + +- String systemStreamName(Stream stream); ++ String systemStreamName(SystemStream stream); + -+ // Field from OSThread -+ private static CIntegerField osThreadThreadIDField; ++ //int systemStreamWidth(SystemStream stream); + + static TerminalProvider load(String name) throws IOException { + switch (name) { +@@ -62,7 +69,7 @@ public interface TerminalProvider + if (cl == null) { + cl = ClassLoader.getSystemClassLoader(); + } +- InputStream is = cl.getResourceAsStream( "META-INF/services/org/jline/terminal/provider/" + name); ++ InputStream is = cl.getResourceAsStream("META-INF/services/org/jline/terminal/provider/" + name); + if (is != null) { + Properties props = new Properties(); + try { +@@ -71,14 +78,13 @@ public interface TerminalProvider + if (className == null) { + throw new IOException("No class defined in terminal provider file " + name); + } +- Class clazz = cl.loadClass( className ); ++ Class clazz = cl.loadClass(className); + return (TerminalProvider) clazz.getConstructor().newInstance(); +- } catch ( Exception e ) { +- throw new IOException("Unable to load terminal provider " + name, e); ++ } catch (Exception e) { ++ throw new IOException("Unable to load terminal provider " + name + ": " + e.getMessage(), e); + } + } else { + throw new IOException("Unable to find terminal provider " + name); + } + } +- + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/AnsiWriter.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/AnsiWriter.java +index 958d0ec74..302406dde 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/AnsiWriter.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/AnsiWriter.java +@@ -1,17 +1,10 @@ + /* +- * Copyright (C) 2009-2018 the original author(s). ++ * Copyright (c) 2009-2018, the original author(s). + * +- * Licensed under the Apache License, Version 2.0 (the "License"); +- * you may not use this file except in compliance with the License. +- * You may obtain a copy of the License at ++ * This software is distributable under the BSD license. See the terms of the ++ * BSD license in the documentation provided with this software. + * +- * http://www.apache.org/licenses/LICENSE-2.0 +- * +- * Unless required by applicable law or agreed to in writing, software +- * distributed under the License is distributed on an "AS IS" BASIS, +- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +- * See the License for the specific language governing permissions and +- * limitations under the License. ++ * https://opensource.org/licenses/BSD-3-Clause + */ + package jdk.internal.org.jline.utils; + +@@ -252,12 +245,10 @@ public class AnsiWriter extends FilterWriter { + * @throws IOException if no more non-null values left + */ + private int getNextOptionInt(Iterator optionsIterator) throws IOException { +- for (;;) { +- if (!optionsIterator.hasNext()) +- throw new IllegalArgumentException(); ++ for (; ; ) { ++ if (!optionsIterator.hasNext()) throw new IllegalArgumentException(); + Object arg = optionsIterator.next(); +- if (arg != null) +- return (Integer) arg; ++ if (arg != null) return (Integer) arg; + } + } + +@@ -346,27 +337,21 @@ public class AnsiWriter extends FilterWriter { + int g = getNextOptionInt(optionsIterator); + int b = getNextOptionInt(optionsIterator); + if (r >= 0 && r <= 255 && g >= 0 && g <= 255 && b >= 0 && b <= 255) { +- if (value == 38) +- processSetForegroundColorExt(r, g, b); +- else +- processSetBackgroundColorExt(r, g, b); ++ if (value == 38) processSetForegroundColorExt(r, g, b); ++ else processSetBackgroundColorExt(r, g, b); + } else { + throw new IllegalArgumentException(); + } +- } +- else if (arg2or5 == 5) { ++ } else if (arg2or5 == 5) { + // 256 color style like `esc[38;5;m` + int paletteIndex = getNextOptionInt(optionsIterator); + if (paletteIndex >= 0 && paletteIndex <= 255) { +- if (value == 38) +- processSetForegroundColorExt(paletteIndex); +- else +- processSetBackgroundColorExt(paletteIndex); ++ if (value == 38) processSetForegroundColorExt(paletteIndex); ++ else processSetBackgroundColorExt(paletteIndex); + } else { + throw new IllegalArgumentException(); + } +- } +- else { ++ } else { + throw new IllegalArgumentException(); + } + } else { +@@ -449,47 +434,41 @@ public class AnsiWriter extends FilterWriter { + * Process CSI u ANSI code, corresponding to RCP \u2013 Restore Cursor Position + * @throws IOException if an error occurs + */ +- protected void processRestoreCursorPosition() throws IOException { +- } ++ protected void processRestoreCursorPosition() throws IOException {} + + /** + * Process CSI s ANSI code, corresponding to SCP \u2013 Save Cursor Position + * @throws IOException if an error occurs + */ +- protected void processSaveCursorPosition() throws IOException { +- } ++ protected void processSaveCursorPosition() throws IOException {} + + /** + * Process CSI s ANSI code, corresponding to IL \u2013 Insert Line + * @param optionInt the option + * @throws IOException if an error occurs + */ +- protected void processInsertLine(int optionInt) throws IOException { +- } ++ protected void processInsertLine(int optionInt) throws IOException {} + + /** + * Process CSI s ANSI code, corresponding to DL \u2013 Delete Line + * @param optionInt the option + * @throws IOException if an error occurs + */ +- protected void processDeleteLine(int optionInt) throws IOException { +- } ++ protected void processDeleteLine(int optionInt) throws IOException {} + + /** + * Process CSI n T ANSI code, corresponding to SD \u2013 Scroll Down + * @param optionInt the option + * @throws IOException if an error occurs + */ +- protected void processScrollDown(int optionInt) throws IOException { +- } ++ protected void processScrollDown(int optionInt) throws IOException {} + + /** + * Process CSI n U ANSI code, corresponding to SU \u2013 Scroll Up + * @param optionInt the option + * @throws IOException if an error occurs + */ +- protected void processScrollUp(int optionInt) throws IOException { +- } ++ protected void processScrollUp(int optionInt) throws IOException {} + + protected static final int ERASE_SCREEN_TO_END = 0; + protected static final int ERASE_SCREEN_TO_BEGINING = 1; +@@ -500,8 +479,7 @@ public class AnsiWriter extends FilterWriter { + * @param eraseOption the erase option + * @throws IOException if an error occurs + */ +- protected void processEraseScreen(int eraseOption) throws IOException { +- } ++ protected void processEraseScreen(int eraseOption) throws IOException {} + + protected static final int ERASE_LINE_TO_END = 0; + protected static final int ERASE_LINE_TO_BEGINING = 1; +@@ -512,25 +490,27 @@ public class AnsiWriter extends FilterWriter { + * @param eraseOption the erase option + * @throws IOException if an error occurs + */ +- protected void processEraseLine(int eraseOption) throws IOException { +- } ++ protected void processEraseLine(int eraseOption) throws IOException {} ++ ++ protected static final int ATTRIBUTE_INTENSITY_BOLD = 1; // Intensity: Bold ++ protected static final int ATTRIBUTE_INTENSITY_FAINT = 2; // Intensity; Faint not widely supported ++ protected static final int ATTRIBUTE_ITALIC = 3; // Italic; on not widely supported. Sometimes treated as inverse. ++ protected static final int ATTRIBUTE_UNDERLINE = 4; // Underline; Single ++ protected static final int ATTRIBUTE_BLINK_SLOW = 5; // Blink; Slow less than 150 per minute ++ protected static final int ATTRIBUTE_BLINK_FAST = 6; // Blink; Rapid MS-DOS ANSI.SYS; 150 per minute or more ++ protected static final int ATTRIBUTE_NEGATIVE_ON = ++ 7; // Image; Negative inverse or reverse; swap foreground and background ++ protected static final int ATTRIBUTE_CONCEAL_ON = 8; // Conceal on ++ protected static final int ATTRIBUTE_UNDERLINE_DOUBLE = 21; // Underline; Double not widely supported ++ protected static final int ATTRIBUTE_INTENSITY_NORMAL = 22; // Intensity; Normal not bold and not faint ++ protected static final int ATTRIBUTE_UNDERLINE_OFF = 24; // Underline; None ++ protected static final int ATTRIBUTE_BLINK_OFF = 25; // Blink; off + +- protected static final int ATTRIBUTE_INTENSITY_BOLD = 1; // Intensity: Bold +- protected static final int ATTRIBUTE_INTENSITY_FAINT = 2; // Intensity; Faint not widely supported +- protected static final int ATTRIBUTE_ITALIC = 3; // Italic; on not widely supported. Sometimes treated as inverse. +- protected static final int ATTRIBUTE_UNDERLINE = 4; // Underline; Single +- protected static final int ATTRIBUTE_BLINK_SLOW = 5; // Blink; Slow less than 150 per minute +- protected static final int ATTRIBUTE_BLINK_FAST = 6; // Blink; Rapid MS-DOS ANSI.SYS; 150 per minute or more +- protected static final int ATTRIBUTE_NEGATIVE_ON = 7; // Image; Negative inverse or reverse; swap foreground and background +- protected static final int ATTRIBUTE_CONCEAL_ON = 8; // Conceal on +- protected static final int ATTRIBUTE_UNDERLINE_DOUBLE = 21; // Underline; Double not widely supported +- protected static final int ATTRIBUTE_INTENSITY_NORMAL = 22; // Intensity; Normal not bold and not faint +- protected static final int ATTRIBUTE_UNDERLINE_OFF = 24; // Underline; None +- protected static final int ATTRIBUTE_BLINK_OFF = 25; // Blink; off + @Deprecated + protected static final int ATTRIBUTE_NEGATIVE_Off = 27; // Image; Positive ++ + protected static final int ATTRIBUTE_NEGATIVE_OFF = 27; // Image; Positive +- protected static final int ATTRIBUTE_CONCEAL_OFF = 28; // Reveal conceal off ++ protected static final int ATTRIBUTE_CONCEAL_OFF = 28; // Reveal conceal off + + /** + * process SGR other than 0 (reset), 30-39 (foreground), +@@ -546,8 +526,7 @@ public class AnsiWriter extends FilterWriter { + * @see #processDefaultTextColor() + * @see #processDefaultBackgroundColor() + */ +- protected void processSetAttribute(int attribute) throws IOException { +- } ++ protected void processSetAttribute(int attribute) throws IOException {} + + protected static final int BLACK = 0; + protected static final int RED = 1; +@@ -584,8 +563,7 @@ public class AnsiWriter extends FilterWriter { + * @param paletteIndex the text color in the palette + * @throws IOException if an error occurs + */ +- protected void processSetForegroundColorExt(int paletteIndex) throws IOException { +- } ++ protected void processSetForegroundColorExt(int paletteIndex) throws IOException {} + + /** + * process SGR 38 corresponding to extended set text color (foreground) +@@ -625,8 +603,7 @@ public class AnsiWriter extends FilterWriter { + * @param paletteIndex the background color in the palette + * @throws IOException if an error occurs + */ +- protected void processSetBackgroundColorExt(int paletteIndex) throws IOException { +- } ++ protected void processSetBackgroundColorExt(int paletteIndex) throws IOException {} + + /** + * process SGR 48 corresponding to extended set background color +@@ -644,22 +621,19 @@ public class AnsiWriter extends FilterWriter { + * process SGR 39 corresponding to Default text color (foreground) + * @throws IOException if an error occurs + */ +- protected void processDefaultTextColor() throws IOException { +- } ++ protected void processDefaultTextColor() throws IOException {} + + /** + * process SGR 49 corresponding to Default background color + * @throws IOException if an error occurs + */ +- protected void processDefaultBackgroundColor() throws IOException { +- } ++ protected void processDefaultBackgroundColor() throws IOException {} + + /** + * process SGR 0 corresponding to Reset / Normal + * @throws IOException if an error occurs + */ +- protected void processAttributeRest() throws IOException { +- } ++ protected void processAttributeRest() throws IOException {} + + /** + * process CSI n ; m H corresponding to CUP \u2013 Cursor Position or +@@ -668,24 +642,21 @@ public class AnsiWriter extends FilterWriter { + * @param col the column + * @throws IOException if an error occurs + */ +- protected void processCursorTo(int row, int col) throws IOException { +- } ++ protected void processCursorTo(int row, int col) throws IOException {} + + /** + * process CSI n G corresponding to CHA \u2013 Cursor Horizontal Absolute + * @param x the column + * @throws IOException if an error occurs + */ +- protected void processCursorToColumn(int x) throws IOException { +- } ++ protected void processCursorToColumn(int x) throws IOException {} + + /** + * process CSI n F corresponding to CPL \u2013 Cursor Previous Line + * @param count line count + * @throws IOException if an error occurs + */ +- protected void processCursorUpLine(int count) throws IOException { +- } ++ protected void processCursorUpLine(int count) throws IOException {} + + /** + * process CSI n E corresponding to CNL \u2013 Cursor Next Line +@@ -704,8 +675,7 @@ public class AnsiWriter extends FilterWriter { + * @param count the count + * @throws IOException if an error occurs + */ +- protected void processCursorLeft(int count) throws IOException { +- } ++ protected void processCursorLeft(int count) throws IOException {} + + /** + * process CSI n C corresponding to CUF \u2013 Cursor Forward +@@ -724,19 +694,16 @@ public class AnsiWriter extends FilterWriter { + * @param count the count + * @throws IOException if an error occurs + */ +- protected void processCursorDown(int count) throws IOException { +- } ++ protected void processCursorDown(int count) throws IOException {} + + /** + * process CSI n A corresponding to CUU \u2013 Cursor Up + * @param count the count + * @throws IOException if an error occurs + */ +- protected void processCursorUp(int count) throws IOException { +- } ++ protected void processCursorUp(int count) throws IOException {} + +- protected void processUnknownExtension(ArrayList options, int command) { +- } ++ protected void processUnknownExtension(ArrayList options, int command) {} + + /** + * process OSC 0;text BEL corresponding to Change Window and Icon label +@@ -751,23 +718,20 @@ public class AnsiWriter extends FilterWriter { + * process OSC 1;text BEL corresponding to Change Icon label + * @param name the icon name + */ +- protected void processChangeIconName(String name) { +- } ++ protected void processChangeIconName(String name) {} + + /** + * process OSC 2;text BEL corresponding to Change Window title + * @param title the title + */ +- protected void processChangeWindowTitle(String title) { +- } ++ protected void processChangeWindowTitle(String title) {} + + /** + * Process unknown OSC command. + * @param command the command + * @param param the param + */ +- protected void processUnknownOperatingSystemCommand(int command, String param) { +- } ++ protected void processUnknownOperatingSystemCommand(int command, String param) {} + + /** + * Process character set sequence. +@@ -781,17 +745,13 @@ public class AnsiWriter extends FilterWriter { + return true; + } + +- protected void processCharsetSelect(int set, char seq) { +- } ++ protected void processCharsetSelect(int set, char seq) {} + + private int optionInt(ArrayList options, int index) { +- if (options.size() <= index) +- throw new IllegalArgumentException(); ++ if (options.size() <= index) throw new IllegalArgumentException(); + Object value = options.get(index); +- if (value == null) +- throw new IllegalArgumentException(); +- if (!value.getClass().equals(Integer.class)) +- throw new IllegalArgumentException(); ++ if (value == null) throw new IllegalArgumentException(); ++ if (!value.getClass().equals(Integer.class)) throw new IllegalArgumentException(); + return (Integer) value; + } + +@@ -828,5 +788,4 @@ public class AnsiWriter extends FilterWriter { + flush(); + super.close(); + } +- + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/AttributedCharSequence.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/AttributedCharSequence.java +index ccb0aaf68..6386f5bba 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/AttributedCharSequence.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/AttributedCharSequence.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2021, the original author or authors. ++ * Copyright (c) 2002-2021, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -15,6 +15,7 @@ import jdk.internal.org.jline.terminal.Terminal; + import jdk.internal.org.jline.terminal.impl.AbstractWindowsTerminal; + import jdk.internal.org.jline.utils.InfoCmp.Capability; + ++import static jdk.internal.org.jline.terminal.TerminalBuilder.PROP_DISABLE_ALTERNATE_CHARSET; + import static jdk.internal.org.jline.utils.AttributedStyle.BG_COLOR; + import static jdk.internal.org.jline.utils.AttributedStyle.BG_COLOR_EXP; + import static jdk.internal.org.jline.utils.AttributedStyle.FG_COLOR; +@@ -30,12 +31,11 @@ import static jdk.internal.org.jline.utils.AttributedStyle.F_FAINT; + import static jdk.internal.org.jline.utils.AttributedStyle.F_FOREGROUND; + import static jdk.internal.org.jline.utils.AttributedStyle.F_FOREGROUND_IND; + import static jdk.internal.org.jline.utils.AttributedStyle.F_FOREGROUND_RGB; ++import static jdk.internal.org.jline.utils.AttributedStyle.F_HIDDEN; + import static jdk.internal.org.jline.utils.AttributedStyle.F_INVERSE; + import static jdk.internal.org.jline.utils.AttributedStyle.F_ITALIC; + import static jdk.internal.org.jline.utils.AttributedStyle.F_UNDERLINE; +-import static jdk.internal.org.jline.utils.AttributedStyle.F_HIDDEN; + import static jdk.internal.org.jline.utils.AttributedStyle.MASK; +-import static jdk.internal.org.jline.terminal.TerminalBuilder.PROP_DISABLE_ALTERNATE_CHARSET; + + public abstract class AttributedCharSequence implements CharSequence { + +@@ -120,6 +120,7 @@ public abstract class AttributedCharSequence implements CharSequence { + char c = charAt(i); + if (altIn != null && altOut != null) { + char pc = c; ++ // @spotless:off + switch (c) { + case '\u2518': c = 'j'; break; + case '\u2510': c = 'k'; break; +@@ -133,15 +134,16 @@ public abstract class AttributedCharSequence implements CharSequence { + case '\u252C': c = 'w'; break; + case '\u2502': c = 'x'; break; + } ++ // @spotless:on + boolean oldalt = alt; + alt = c != pc; + if (oldalt ^ alt) { + sb.append(alt ? altIn : altOut); + } + } +- long s = styleCodeAt(i) & ~F_HIDDEN; // The hidden flag does not change the ansi styles ++ long s = styleCodeAt(i) & ~F_HIDDEN; // The hidden flag does not change the ansi styles + if (style != s) { +- long d = (style ^ s) & MASK; ++ long d = (style ^ s) & MASK; + long fg = (s & F_FOREGROUND) != 0 ? s & (FG_COLOR | F_FOREGROUND) : 0; + long bg = (s & F_BACKGROUND) != 0 ? s & (BG_COLOR | F_BACKGROUND) : 0; + if (s == 0) { +@@ -172,16 +174,16 @@ public abstract class AttributedCharSequence implements CharSequence { + if (fg > 0) { + int rounded = -1; + if ((fg & F_FOREGROUND_RGB) != 0) { +- int r = (int)(fg >> (FG_COLOR_EXP + 16)) & 0xFF; +- int g = (int)(fg >> (FG_COLOR_EXP + 8)) & 0xFF; +- int b = (int)(fg >> FG_COLOR_EXP) & 0xFF; ++ int r = (int) (fg >> (FG_COLOR_EXP + 16)) & 0xFF; ++ int g = (int) (fg >> (FG_COLOR_EXP + 8)) & 0xFF; ++ int b = (int) (fg >> FG_COLOR_EXP) & 0xFF; + if (colors >= HIGH_COLORS) { + first = attr(sb, "38;2;" + r + ";" + g + ";" + b, first); + } else { + rounded = palette.round(r, g, b); + } + } else if ((fg & F_FOREGROUND_IND) != 0) { +- rounded = palette.round((int)(fg >> FG_COLOR_EXP) & 0xFF); ++ rounded = palette.round((int) (fg >> FG_COLOR_EXP) & 0xFF); + } + if (rounded >= 0) { + if (colors >= HIGH_COLORS && force == ForceMode.ForceTrueColors) { +@@ -211,16 +213,16 @@ public abstract class AttributedCharSequence implements CharSequence { + if (bg > 0) { + int rounded = -1; + if ((bg & F_BACKGROUND_RGB) != 0) { +- int r = (int)(bg >> (BG_COLOR_EXP + 16)) & 0xFF; +- int g = (int)(bg >> (BG_COLOR_EXP + 8)) & 0xFF; +- int b = (int)(bg >> BG_COLOR_EXP) & 0xFF; ++ int r = (int) (bg >> (BG_COLOR_EXP + 16)) & 0xFF; ++ int g = (int) (bg >> (BG_COLOR_EXP + 8)) & 0xFF; ++ int b = (int) (bg >> BG_COLOR_EXP) & 0xFF; + if (colors >= HIGH_COLORS) { + first = attr(sb, "48;2;" + r + ";" + g + ";" + b, first); + } else { + rounded = palette.round(r, g, b); + } + } else if ((bg & F_BACKGROUND_IND) != 0) { +- rounded = palette.round((int)(bg >> BG_COLOR_EXP) & 0xFF); ++ rounded = palette.round((int) (bg >> BG_COLOR_EXP) & 0xFF); + } + if (rounded >= 0) { + if (colors >= HIGH_COLORS && force == ForceMode.ForceTrueColors) { +@@ -243,8 +245,7 @@ public abstract class AttributedCharSequence implements CharSequence { + background = bg; + } + if ((d & (F_BOLD | F_FAINT)) != 0) { +- if ( (d & F_BOLD) != 0 && (s & F_BOLD) == 0 +- || (d & F_FAINT) != 0 && (s & F_FAINT) == 0) { ++ if ((d & F_BOLD) != 0 && (s & F_BOLD) == 0 || (d & F_FAINT) != 0 && (s & F_FAINT) == 0) { + first = attr(sb, "22", first); + } + if ((d & F_BOLD) != 0 && (s & F_BOLD) != 0) { +@@ -360,8 +361,7 @@ public abstract class AttributedCharSequence implements CharSequence { + int len = length(); + for (int cur = 0; cur < len; ) { + int cp = codePointAt(cur); +- if (!isHidden(cur)) +- cols += WCWidth.wcwidth(cp); ++ if (!isHidden(cur)) cols += WCWidth.wcwidth(cp); + cur += Character.charCount(cp); + } + return cols; +@@ -382,8 +382,7 @@ public abstract class AttributedCharSequence implements CharSequence { + int end = begin; + while (end < this.length()) { + int cp = codePointAt(end); +- if (cp == '\n') +- break; ++ if (cp == '\n') break; + int w = isHidden(end) ? 0 : WCWidth.wcwidth(cp); + if (col + w > stop) { + break; +@@ -407,7 +406,7 @@ public abstract class AttributedCharSequence implements CharSequence { + int cp = codePointAt(cur); + int w = isHidden(cur) ? 0 : WCWidth.wcwidth(cp); + if (cp == '\n') { +- strings.add(subSequence(beg, includeNewlines ? cur+1 : cur)); ++ strings.add(subSequence(beg, includeNewlines ? cur + 1 : cur)); + beg = cur + 1; + col = 0; + } else if ((col += w) > columns) { +@@ -429,5 +428,4 @@ public abstract class AttributedCharSequence implements CharSequence { + public AttributedString toAttributedString() { + return substring(0, length()); + } +- + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/AttributedString.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/AttributedString.java +index 47492b72e..3c70a6d0e 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/AttributedString.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/AttributedString.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2016, the original author or authors. ++ * Copyright (c) 2002-2016, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -15,6 +15,8 @@ import java.util.Objects; + import java.util.regex.Matcher; + import java.util.regex.Pattern; + ++import jdk.internal.org.jline.terminal.Terminal; + -+ // This is currently unneeded but is being kept in case we change -+ // the currentFrameGuess algorithm -+ private static final long GUESS_SCAN_RANGE = 128 * 1024; + /** + * Attributed string. + * Instances of this class are immutables. +@@ -103,11 +105,28 @@ public class AttributedString extends AttributedCharSequence { + } + + public static AttributedString fromAnsi(String ansi, List tabs) { ++ return fromAnsi(ansi, tabs, null, null); ++ } + -+ static { -+ VM.registerVMInitializedObserver(new Observer() { -+ public void update(Observable o, Object data) { -+ initialize(VM.getVM().getTypeDataBase()); ++ public static AttributedString fromAnsi(String ansi, Terminal terminal) { ++ String alternateIn, alternateOut; ++ if (!DISABLE_ALTERNATE_CHARSET) { ++ alternateIn = Curses.tputs(terminal.getStringCapability(InfoCmp.Capability.enter_alt_charset_mode)); ++ alternateOut = Curses.tputs(terminal.getStringCapability(InfoCmp.Capability.exit_alt_charset_mode)); ++ } else { ++ alternateIn = null; ++ alternateOut = null; + } -+ }); -+ } -+ -+ private static synchronized void initialize(TypeDataBase db) { -+ Type type = db.lookupType("JavaThread"); -+ osThreadField = type.getAddressField("_osthread"); -+ -+ Type osThreadType = db.lookupType("OSThread"); -+ osThreadThreadIDField = osThreadType.getCIntegerField("_thread_id"); -+ } ++ return fromAnsi(ansi, Arrays.asList(0), alternateIn, alternateOut); ++ } + -+ public Address getLastJavaFP(Address addr) { -+ return null; -+ } ++ public static AttributedString fromAnsi(String ansi, List tabs, String altIn, String altOut) { + if (ansi == null) { + return null; + } + return new AttributedStringBuilder(ansi.length()) + .tabs(tabs) ++ .altCharset(altIn, altOut) + .ansiAppend(ansi) + .toAttributedString(); + } +@@ -116,9 +135,7 @@ public class AttributedString extends AttributedCharSequence { + if (ansi == null) { + return null; + } +- return new AttributedStringBuilder(ansi.length()) +- .ansiAppend(ansi) +- .toString(); ++ return new AttributedStringBuilder(ansi.length()).ansiAppend(ansi).toString(); + } + + @Override +@@ -162,7 +179,7 @@ public class AttributedString extends AttributedCharSequence { + } + result = matcher.find(); + } while (result); +- return new AttributedString(buffer, newstyle, start , end); ++ return new AttributedString(buffer, newstyle, start, end); + } + return this; + } +@@ -179,15 +196,16 @@ public class AttributedString extends AttributedCharSequence { + + private boolean arrEq(char[] a1, char[] a2, int s1, int s2, int l) { + for (int i = 0; i < l; i++) { +- if (a1[s1+i] != a2[s2+i]) { ++ if (a1[s1 + i] != a2[s2 + i]) { + return false; + } + } + return true; + } + -+ public Address getLastJavaPC(Address addr) { -+ return null; -+ } + private boolean arrEq(long[] a1, long[] a2, int s1, int s2, int l) { + for (int i = 0; i < l; i++) { +- if (a1[s1+i] != a2[s2+i]) { ++ if (a1[s1 + i] != a2[s2 + i]) { + return false; + } + } +@@ -221,5 +239,4 @@ public class AttributedString extends AttributedCharSequence { + } + return sb.toAttributedString(); + } +- + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/AttributedStringBuilder.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/AttributedStringBuilder.java +index 779675348..554381d36 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/AttributedStringBuilder.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/AttributedStringBuilder.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2018, the original author or authors. ++ * Copyright (c) 2002-2018, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -27,6 +27,9 @@ public class AttributedStringBuilder extends AttributedCharSequence implements A + private long[] style; + private int length; + private TabStops tabs = new TabStops(0); ++ private char[] altIn; ++ private char[] altOut; ++ private boolean inAltCharset; + private int lastLineLength = 0; + private AttributedStyle current = AttributedStyle.DEFAULT; + +@@ -81,10 +84,7 @@ public class AttributedStringBuilder extends AttributedCharSequence implements A + @Override + public AttributedString subSequence(int start, int end) { + return new AttributedString( +- Arrays.copyOfRange(buffer, start, end), +- Arrays.copyOfRange(style, start, end), +- 0, +- end - start); ++ Arrays.copyOfRange(buffer, start, end), Arrays.copyOfRange(style, start, end), 0, end - start); + } + + @Override +@@ -108,6 +108,14 @@ public class AttributedStringBuilder extends AttributedCharSequence implements A + return append(Character.toString(c)); + } + ++ public AttributedStringBuilder append(char c, int repeat) { ++ AttributedString s = new AttributedString(Character.toString(c), current); ++ while (repeat-- > 0) { ++ append(s); ++ } ++ return this; ++ } + -+ public Address getBaseOfStackPointer(Address addr) { -+ return null; -+ } + public AttributedStringBuilder append(CharSequence csq, AttributedStyle style) { + return append(new AttributedString(csq, style)); + } +@@ -117,12 +125,12 @@ public class AttributedStringBuilder extends AttributedCharSequence implements A + return this; + } + +- public AttributedStringBuilder style(Function style) { ++ public AttributedStringBuilder style(Function style) { + current = style.apply(current); + return this; + } + +- public AttributedStringBuilder styled(Function style, CharSequence cs) { ++ public AttributedStringBuilder styled(Function style, CharSequence cs) { + return styled(style, sb -> sb.append(cs)); + } + +@@ -130,7 +138,8 @@ public class AttributedStringBuilder extends AttributedCharSequence implements A + return styled(s -> style, sb -> sb.append(cs)); + } + +- public AttributedStringBuilder styled(Function style, Consumer consumer) { ++ public AttributedStringBuilder styled( ++ Function style, Consumer consumer) { + AttributedStyle prev = current; + current = style.apply(prev); + consumer.accept(this); +@@ -338,23 +347,90 @@ public class AttributedStringBuilder extends AttributedCharSequence implements A + // This is not a SGR code, so ignore + ansiState = 0; + } +- } else if (c == '\t' && tabs.defined()) { +- insertTab(current); + } else { +- ensureCapacity(length + 1); +- buffer[length] = c; +- style[length] = this.current.getStyle(); +- if (c == '\n') { +- lastLineLength = 0; ++ if (ansiState >= 1) { ++ ensureCapacity(length + 1); ++ buffer[length++] = 27; ++ if (ansiState >= 2) { ++ ensureCapacity(length + 1); ++ buffer[length++] = '['; ++ } ++ ansiState = 0; ++ } ++ if (c == '\t' && tabs.defined()) { ++ insertTab(current); + } else { +- lastLineLength++; ++ ensureCapacity(length + 1); ++ if (inAltCharset) { ++ switch (c) { ++ case 'j': ++ c = '\u2518'; ++ break; ++ case 'k': ++ c = '\u2510'; ++ break; ++ case 'l': ++ c = '\u250C'; ++ break; ++ case 'm': ++ c = '\u2514'; ++ break; ++ case 'n': ++ c = '\u253C'; ++ break; ++ case 'q': ++ c = '\u2500'; ++ break; ++ case 't': ++ c = '\u251C'; ++ break; ++ case 'u': ++ c = '\u2524'; ++ break; ++ case 'v': ++ c = '\u2534'; ++ break; ++ case 'w': ++ c = '\u252C'; ++ break; ++ case 'x': ++ c = '\u2502'; ++ break; ++ } ++ } ++ buffer[length] = c; ++ style[length] = this.current.getStyle(); ++ if (c == '\n') { ++ lastLineLength = 0; ++ } else { ++ lastLineLength++; ++ } ++ length++; ++ if (altIn != null && altOut != null) { ++ char[] alt = inAltCharset ? altOut : altIn; ++ if (equals(buffer, length - alt.length, alt, 0, alt.length)) { ++ inAltCharset = !inAltCharset; ++ length -= alt.length; ++ } ++ } + } +- length++; + } + } + return this; + } + ++ private static boolean equals(char[] a, int aFromIndex, char[] b, int bFromIndex, int length) { ++ if (aFromIndex < 0 || bFromIndex < 0 || aFromIndex + length > a.length || bFromIndex + length > b.length) { ++ return false; ++ } ++ for (int i = 0; i < length; i++) { ++ if (a[aFromIndex + i] != b[bFromIndex + i]) { ++ return false; ++ } ++ } ++ return true; ++ } + -+ public Frame getLastFramePD(JavaThread thread, Address addr) { -+ Address fp = thread.getLastJavaFP(); -+ if (fp == null) { -+ return null; // no information + protected void insertTab(AttributedStyle s) { + int nb = tabs.spaces(lastLineLength); + ensureCapacity(length + nb); +@@ -393,6 +469,15 @@ public class AttributedStringBuilder extends AttributedCharSequence implements A + return this; + } + ++ public AttributedStringBuilder altCharset(String altIn, String altOut) { ++ if (length > 0) { ++ throw new IllegalStateException("Cannot change alternative charset after appending text"); ++ } ++ this.altIn = altIn != null ? altIn.toCharArray() : null; ++ this.altOut = altOut != null ? altOut.toCharArray() : null; ++ return this; + } -+ return new MIPS64Frame(thread.getLastJavaSP(), fp); -+ } + -+ public RegisterMap newRegisterMap(JavaThread thread, boolean updateMap) { -+ return new MIPS64RegisterMap(thread, updateMap); -+ } + public AttributedStringBuilder styleMatches(Pattern pattern, AttributedStyle s) { + Matcher matcher = pattern.matcher(this); + while (matcher.find()) { +@@ -416,7 +501,7 @@ public class AttributedStringBuilder extends AttributedCharSequence implements A + return this; + } + +- private class TabStops { ++ private static class TabStops { + private List tabs = new ArrayList<>(); + private int lastStop = 0; + private int lastSize = 0; +@@ -428,7 +513,7 @@ public class AttributedStringBuilder extends AttributedCharSequence implements A + public TabStops(List tabs) { + this.tabs = tabs; + int p = 0; +- for (int s: tabs) { ++ for (int s : tabs) { + if (s <= p) { + continue; + } +@@ -447,7 +532,7 @@ public class AttributedStringBuilder extends AttributedCharSequence implements A + if (lastLineLength >= lastStop) { + out = lastSize - (lastLineLength - lastStop) % lastSize; + } else { +- for (int s: tabs) { ++ for (int s : tabs) { + if (s > lastLineLength) { + out = s - lastLineLength; + break; +@@ -456,7 +541,5 @@ public class AttributedStringBuilder extends AttributedCharSequence implements A + } + return out; + } +- + } +- + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/AttributedStyle.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/AttributedStyle.java +index 902e2e1f3..7845e99e0 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/AttributedStyle.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/AttributedStyle.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2021, the original author or authors. ++ * Copyright (c) 2002-2021, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -15,39 +15,39 @@ package jdk.internal.org.jline.utils; + */ + public class AttributedStyle { + +- public static final int BLACK = 0; +- public static final int RED = 1; +- public static final int GREEN = 2; +- public static final int YELLOW = 3; +- public static final int BLUE = 4; +- public static final int MAGENTA = 5; +- public static final int CYAN = 6; +- public static final int WHITE = 7; +- +- public static final int BRIGHT = 8; +- +- static final long F_BOLD = 0x00000001; +- static final long F_FAINT = 0x00000002; +- static final long F_ITALIC = 0x00000004; +- static final long F_UNDERLINE = 0x00000008; +- static final long F_BLINK = 0x00000010; +- static final long F_INVERSE = 0x00000020; +- static final long F_CONCEAL = 0x00000040; +- static final long F_CROSSED_OUT = 0x00000080; +- static final long F_FOREGROUND_IND = 0x00000100; +- static final long F_FOREGROUND_RGB = 0x00000200; +- static final long F_FOREGROUND = F_FOREGROUND_IND | F_FOREGROUND_RGB; +- static final long F_BACKGROUND_IND = 0x00000400; +- static final long F_BACKGROUND_RGB = 0x00000800; +- static final long F_BACKGROUND = F_BACKGROUND_IND | F_BACKGROUND_RGB; +- static final long F_HIDDEN = 0x00001000; +- +- static final long MASK = 0x00001FFF; +- +- static final int FG_COLOR_EXP = 15; +- static final int BG_COLOR_EXP = 39; +- static final long FG_COLOR = 0xFFFFFFL << FG_COLOR_EXP; +- static final long BG_COLOR = 0xFFFFFFL << BG_COLOR_EXP; ++ public static final int BLACK = 0; ++ public static final int RED = 1; ++ public static final int GREEN = 2; ++ public static final int YELLOW = 3; ++ public static final int BLUE = 4; ++ public static final int MAGENTA = 5; ++ public static final int CYAN = 6; ++ public static final int WHITE = 7; ++ ++ public static final int BRIGHT = 8; ++ ++ static final long F_BOLD = 0x00000001; ++ static final long F_FAINT = 0x00000002; ++ static final long F_ITALIC = 0x00000004; ++ static final long F_UNDERLINE = 0x00000008; ++ static final long F_BLINK = 0x00000010; ++ static final long F_INVERSE = 0x00000020; ++ static final long F_CONCEAL = 0x00000040; ++ static final long F_CROSSED_OUT = 0x00000080; ++ static final long F_FOREGROUND_IND = 0x00000100; ++ static final long F_FOREGROUND_RGB = 0x00000200; ++ static final long F_FOREGROUND = F_FOREGROUND_IND | F_FOREGROUND_RGB; ++ static final long F_BACKGROUND_IND = 0x00000400; ++ static final long F_BACKGROUND_RGB = 0x00000800; ++ static final long F_BACKGROUND = F_BACKGROUND_IND | F_BACKGROUND_RGB; ++ static final long F_HIDDEN = 0x00001000; ++ ++ static final long MASK = 0x00001FFF; ++ ++ static final int FG_COLOR_EXP = 15; ++ static final int BG_COLOR_EXP = 39; ++ static final long FG_COLOR = 0xFFFFFFL << FG_COLOR_EXP; ++ static final long BG_COLOR = 0xFFFFFFL << BG_COLOR_EXP; + + public static final AttributedStyle DEFAULT = new AttributedStyle(); + public static final AttributedStyle BOLD = DEFAULT.bold(); +@@ -70,8 +70,9 @@ public class AttributedStyle { + + public AttributedStyle(long style, long mask) { + this.style = style; +- this.mask = mask & MASK | ((style & F_FOREGROUND) != 0 ? FG_COLOR : 0) +- | ((style & F_BACKGROUND) != 0 ? BG_COLOR : 0); ++ this.mask = mask & MASK ++ | ((style & F_FOREGROUND) != 0 ? FG_COLOR : 0) ++ | ((style & F_BACKGROUND) != 0 ? BG_COLOR : 0); + } + + public AttributedStyle bold() { +@@ -176,7 +177,9 @@ public class AttributedStyle { + } + + public AttributedStyle foreground(int color) { +- return new AttributedStyle(style & ~FG_COLOR | F_FOREGROUND_IND | (((long) color << FG_COLOR_EXP) & FG_COLOR), mask | F_FOREGROUND_IND); ++ return new AttributedStyle( ++ style & ~FG_COLOR | F_FOREGROUND_IND | (((long) color << FG_COLOR_EXP) & FG_COLOR), ++ mask | F_FOREGROUND_IND); + } + + public AttributedStyle foreground(int r, int g, int b) { +@@ -184,7 +187,9 @@ public class AttributedStyle { + } + + public AttributedStyle foregroundRgb(int color) { +- return new AttributedStyle(style & ~FG_COLOR | F_FOREGROUND_RGB | ((((long) color & 0xFFFFFF) << FG_COLOR_EXP) & FG_COLOR), mask | F_FOREGROUND_RGB); ++ return new AttributedStyle( ++ style & ~FG_COLOR | F_FOREGROUND_RGB | ((((long) color & 0xFFFFFF) << FG_COLOR_EXP) & FG_COLOR), ++ mask | F_FOREGROUND_RGB); + } + + public AttributedStyle foregroundOff() { +@@ -196,7 +201,9 @@ public class AttributedStyle { + } + + public AttributedStyle background(int color) { +- return new AttributedStyle(style & ~BG_COLOR | F_BACKGROUND_IND | (((long) color << BG_COLOR_EXP) & BG_COLOR), mask | F_BACKGROUND_IND); ++ return new AttributedStyle( ++ style & ~BG_COLOR | F_BACKGROUND_IND | (((long) color << BG_COLOR_EXP) & BG_COLOR), ++ mask | F_BACKGROUND_IND); + } + + public AttributedStyle background(int r, int g, int b) { +@@ -204,7 +211,9 @@ public class AttributedStyle { + } + + public AttributedStyle backgroundRgb(int color) { +- return new AttributedStyle(style & ~BG_COLOR | F_BACKGROUND_RGB | ((((long) color & 0xFFFFFF) << BG_COLOR_EXP) & BG_COLOR), mask | F_BACKGROUND_RGB); ++ return new AttributedStyle( ++ style & ~BG_COLOR | F_BACKGROUND_RGB | ((((long) color & 0xFFFFFF) << BG_COLOR_EXP) & BG_COLOR), ++ mask | F_BACKGROUND_RGB); + } + + public AttributedStyle backgroundOff() { +@@ -249,7 +258,6 @@ public class AttributedStyle { + AttributedStyle that = (AttributedStyle) o; + if (style != that.style) return false; + return mask == that.mask; +- + } + + @Override +@@ -266,10 +274,6 @@ public class AttributedStyle { + + @Override + public String toString() { +- return "AttributedStyle{" + +- "style=" + style + +- ", mask=" + mask + +- ", ansi=" + toAnsi() + +- '}'; ++ return "AttributedStyle{" + "style=" + style + ", mask=" + mask + ", ansi=" + toAnsi() + '}'; + } + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/ClosedException.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/ClosedException.java +index f2adb0878..a6f5bfb5b 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/ClosedException.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/ClosedException.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2016, the original author or authors. ++ * Copyright (c) 2002-2016, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -14,8 +14,7 @@ public class ClosedException extends IOException { + + private static final long serialVersionUID = 3085420657077696L; + +- public ClosedException() { +- } ++ public ClosedException() {} + + public ClosedException(String message) { + super(message); +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/ColorPalette.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/ColorPalette.java +index 6f55273a7..b4175fe13 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/ColorPalette.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/ColorPalette.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2020, the original author or authors. ++ * Copyright (c) 2002-2020, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -21,7 +21,8 @@ import jdk.internal.org.jline.terminal.Terminal; + */ + public class ColorPalette { + +- public static final String XTERM_INITC = "\\E]4;%p1%d;rgb\\:%p2%{255}%*%{1000}%/%2.2X/%p3%{255}%*%{1000}%/%2.2X/%p4%{255}%*%{1000}%/%2.2X\\E\\\\"; ++ public static final String XTERM_INITC = ++ "\\E]4;%p1%d;rgb\\:%p2%{255}%*%{1000}%/%2.2X/%p3%{255}%*%{1000}%/%2.2X/%p4%{255}%*%{1000}%/%2.2X\\E\\\\"; + + public static final ColorPalette DEFAULT = new ColorPalette(); + +@@ -41,6 +42,7 @@ public class ColorPalette { + this(terminal, null); + } + ++ @SuppressWarnings("this-escape") + public ColorPalette(Terminal terminal, String distance) throws IOException { + this.terminal = terminal; + this.distanceName = distance; +@@ -245,10 +247,13 @@ public class ColorPalette { + if (rgb.size() != 3) { + return null; + } +- double r = Integer.parseInt(rgb.get(0), 16) / ((1 << (4 * rgb.get(0).length())) - 1.0); +- double g = Integer.parseInt(rgb.get(1), 16) / ((1 << (4 * rgb.get(1).length())) - 1.0); +- double b = Integer.parseInt(rgb.get(2), 16) / ((1 << (4 * rgb.get(2).length())) - 1.0); +- palette[idx] = (int)((Math.round(r * 255) << 16) + (Math.round(g * 255) << 8) + Math.round(b * 255)); ++ double r = Integer.parseInt(rgb.get(0), 16) ++ / ((1 << (4 * rgb.get(0).length())) - 1.0); ++ double g = Integer.parseInt(rgb.get(1), 16) ++ / ((1 << (4 * rgb.get(1).length())) - 1.0); ++ double b = Integer.parseInt(rgb.get(2), 16) ++ / ((1 << (4 * rgb.get(2).length())) - 1.0); ++ palette[idx] = (int) ((Math.round(r * 255) << 16) + (Math.round(g * 255) << 8) + Math.round(b * 255)); + black &= palette[idx] == 0; + } + if (black) { +@@ -256,7 +261,13 @@ public class ColorPalette { + } + } + int max = 256; +- while (max > 0 && palette[--max] == 0); ++ while (max > 0 && palette[--max] == 0) ++ ; + return Arrays.copyOfRange(palette, 0, max + 1); + } + -+ public Frame getCurrentFrameGuess(JavaThread thread, Address addr) { -+ ThreadProxy t = getThreadProxy(addr); -+ MIPS64ThreadContext context = (MIPS64ThreadContext) t.getContext(); -+ MIPS64CurrentFrameGuess guesser = new MIPS64CurrentFrameGuess(context, thread); -+ if (!guesser.run(GUESS_SCAN_RANGE)) { -+ return null; -+ } -+ if (guesser.getPC() == null) { -+ return new MIPS64Frame(guesser.getSP(), guesser.getFP()); -+ } else { -+ return new MIPS64Frame(guesser.getSP(), guesser.getFP(), guesser.getPC()); ++ @Override ++ public String toString() { ++ return "ColorPalette[" + "length=" + getLength() + ", " + "distance='" + getDist() + "\']"; + } -+ } + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Colors.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Colors.java +index dc452e103..d5e7644d3 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Colors.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Colors.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2018, the original author or authors. ++ * Copyright (c) 2002-2018, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -21,6 +21,8 @@ import static jdk.internal.org.jline.terminal.TerminalBuilder.PROP_COLOR_DISTANC + + public class Colors { + ++ // @spotless:off + -+ public void printThreadIDOn(Address addr, PrintStream tty) { -+ tty.print(getThreadProxy(addr)); -+ } + /** + * Default 256 colors palette + */ +@@ -111,24 +113,26 @@ public class Colors { + 0x2e2e2e, 0x5c5c5c, 0x737373, 0x8b8b8b, 0xa2a2a2, 0xb9b9b9, 0xd0d0d0, 0xe7e7e7, + }; + ++ // @spotless:on ++ + /** D50 illuminant for CAM color spaces */ +- public static final double[] D50 = new double[] { 96.422f, 100.0f, 82.521f }; ++ public static final double[] D50 = new double[] {96.422f, 100.0f, 82.521f}; + /** D65 illuminant for CAM color spaces */ +- public static final double[] D65 = new double[] { 95.047, 100.0, 108.883 }; ++ public static final double[] D65 = new double[] {95.047, 100.0, 108.883}; + + /** Average surrounding for CAM color spaces */ +- public static final double[] averageSurrounding = new double[] { 1.0, 0.690, 1.0 }; ++ public static final double[] averageSurrounding = new double[] {1.0, 0.690, 1.0}; + /** Dim surrounding for CAM color spaces */ +- public static final double[] dimSurrounding = new double[] { 0.9, 0.590, 0.9 }; ++ public static final double[] dimSurrounding = new double[] {0.9, 0.590, 0.9}; + /** Dark surrounding for CAM color spaces */ +- public static final double[] darkSurrounding = new double[] { 0.8, 0.525, 0.8 }; ++ public static final double[] darkSurrounding = new double[] {0.8, 0.525, 0.8}; + + /** sRGB encoding environment */ +- public static final double[] sRGB_encoding_environment = vc(D50, 64.0, 64.0/5, dimSurrounding); ++ public static final double[] sRGB_encoding_environment = vc(D50, 64.0, 64.0 / 5, dimSurrounding); + /** sRGB typical environment */ +- public static final double[] sRGB_typical_environment = vc(D50, 200.0, 200.0/5, averageSurrounding); ++ public static final double[] sRGB_typical_environment = vc(D50, 200.0, 200.0 / 5, averageSurrounding); + /** Adobe RGB environment */ +- public static final double[] AdobeRGB_environment = vc(D65, 160.0, 160.0/5, averageSurrounding); ++ public static final double[] AdobeRGB_environment = vc(D65, 160.0, 160.0 / 5, averageSurrounding); + + private static int[] COLORS_256 = DEFAULT_COLORS_256; + +@@ -149,8 +153,9 @@ public class Colors { + if (COLOR_NAMES == null) { + Map colors = new LinkedHashMap<>(); + try (InputStream is = InfoCmp.class.getResourceAsStream("colors.txt"); +- BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) { +- br.lines().map(String::trim) ++ BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) { ++ br.lines() ++ .map(String::trim) + .filter(s -> !s.startsWith("#")) + .filter(s -> !s.isEmpty()) + .forEachOrdered(s -> { +@@ -206,7 +211,7 @@ public class Colors { + if (dist == null) { + dist = System.getProperty(PROP_COLOR_DISTANCE, "cie76"); + } +- return doGetDistance(dist); ++ return new NamedDistance(dist, doGetDistance(dist)); + } + + private static Distance doGetDistance(String dist) { +@@ -216,7 +221,7 @@ public class Colors { + double[] c1 = rgb(p1); + double[] c2 = rgb(p2); + double rmean = (c1[0] + c2[0]) / 2.0; +- double[] w = { 2.0 + rmean, 4.0, 3.0 - rmean }; ++ double[] w = {2.0 + rmean, 4.0, 3.0 - rmean}; + return scalar(c1, c2, w); + }; + } +@@ -228,7 +233,7 @@ public class Colors { + } + if (dist.matches("lab\\(([0-9]+(\\.[0-9]+)?),([0-9]+(\\.[0-9]+)?)\\)")) { + double[] w = getWeights(dist); +- return (p1, p2) -> scalar(rgb2cielab(p1), rgb2cielab(p2), new double[] { w[0], w[1], w[1] }); ++ return (p1, p2) -> scalar(rgb2cielab(p1), rgb2cielab(p2), new double[] {w[0], w[1], w[1]}); + } + if (dist.equals("cie94")) { + return (p1, p2) -> cie94(rgb2cielab(p1), rgb2cielab(p2)); +@@ -251,7 +256,7 @@ public class Colors { + double[] c1 = camlab(p1, sRGB_typical_environment); + double[] c2 = camlab(p2, sRGB_typical_environment); + double[] w = getWeights(dist); +- return scalar(c1, c2, new double[] { w[0], w[1], w[1] }); ++ return scalar(c1, c2, new double[] {w[0], w[1], w[1]}); + }; + } + if (dist.matches("camlch")) { +@@ -273,20 +278,37 @@ public class Colors { + } + + private static double[] getWeights(String dist) { +- String[] weights = dist.substring(dist.indexOf('(') + 1, dist.length() - 1).split(","); ++ String[] weights = ++ dist.substring(dist.indexOf('(') + 1, dist.length() - 1).split(","); + return Stream.of(weights).mapToDouble(Double::parseDouble).toArray(); + } + + private static double scalar(double[] c1, double[] c2, double[] w) { +- return sqr((c1[0] - c2[0]) * w[0]) +- + sqr((c1[1] - c2[1]) * w[1]) +- + sqr((c1[2] - c2[2]) * w[2]); ++ return sqr((c1[0] - c2[0]) * w[0]) + sqr((c1[1] - c2[1]) * w[1]) + sqr((c1[2] - c2[2]) * w[2]); + } + + private static double scalar(double[] c1, double[] c2) { +- return sqr(c1[0] - c2[0]) +- + sqr(c1[1] - c2[1]) +- + sqr(c1[2] - c2[2]); ++ return sqr(c1[0] - c2[0]) + sqr(c1[1] - c2[1]) + sqr(c1[2] - c2[2]); ++ } + -+ public void printInfoOn(Address threadAddr, PrintStream tty) { -+ tty.print("Thread id: "); -+ printThreadIDOn(threadAddr, tty); -+ // tty.println("\nPostJavaState: " + getPostJavaState(threadAddr)); -+ } ++ private static class NamedDistance implements Distance { ++ private final String name; ++ private final Distance delegate; + -+ public Address getLastSP(Address addr) { -+ ThreadProxy t = getThreadProxy(addr); -+ MIPS64ThreadContext context = (MIPS64ThreadContext) t.getContext(); -+ return context.getRegisterAsAddress(MIPS64ThreadContext.SP); -+ } ++ public NamedDistance(String name, Distance delegate) { ++ this.name = name; ++ this.delegate = delegate; ++ } + -+ public Address getLastFP(Address addr) { -+ return getLastSP(addr).getAddressAt(0); -+ } ++ @Override ++ public double compute(int c1, int c2) { ++ return delegate.compute(c1, c2); ++ } + -+ public ThreadProxy getThreadProxy(Address addr) { -+ // Addr is the address of the JavaThread. -+ // Fetch the OSThread (for now and for simplicity, not making a -+ // separate "OSThread" class in this package) -+ Address osThreadAddr = osThreadField.getValue(addr); -+ // Get the address of the _thread_id from the OSThread -+ Address threadIdAddr = osThreadAddr.addOffsetTo(osThreadThreadIDField.getOffset()); ++ @Override ++ public String toString() { ++ return name; ++ } + } + + private static final int L = 0; +@@ -325,7 +347,7 @@ public class Colors { + double c_star_average_ab = (c_star_1_ab + c_star_2_ab) / 2.0; + double c_star_average_ab_pot_3 = c_star_average_ab * c_star_average_ab * c_star_average_ab; + double c_star_average_ab_pot_7 = c_star_average_ab_pot_3 * c_star_average_ab_pot_3 * c_star_average_ab; +- double G = 0.5 * (1.0 - Math.sqrt(c_star_average_ab_pot_7 / (c_star_average_ab_pot_7 + 6103515625.0))); //25^7 ++ double G = 0.5 * (1.0 - Math.sqrt(c_star_average_ab_pot_7 / (c_star_average_ab_pot_7 + 6103515625.0))); // 25^7 + double a1_prime = (1.0 + G) * lab1[A]; + double a2_prime = (1.0 + G) * lab2[A]; + double C_prime_1 = Math.sqrt(a1_prime * a1_prime + lab1[B] * lab1[B]); +@@ -365,16 +387,18 @@ public class Colors { + + 0.24 * Math.cos(Math.toRadians(h_prime_average * 2.0)) + + 0.32 * Math.cos(Math.toRadians(h_prime_average * 3.0 + 6.0)) + - 0.20 * Math.cos(Math.toRadians(h_prime_average * 4.0 - 63.0)); +- double S_L = 1.0 + ((0.015 * L_prime_average_minus_50_square) / Math.sqrt(20.0 + L_prime_average_minus_50_square)); ++ double S_L = ++ 1.0 + ((0.015 * L_prime_average_minus_50_square) / Math.sqrt(20.0 + L_prime_average_minus_50_square)); + double S_C = 1.0 + 0.045 * C_prime_average; + double S_H = 1.0 + 0.015 * T * C_prime_average; + double h_prime_average_minus_275_div_25 = (h_prime_average - 275.0) / (25.0); +- double h_prime_average_minus_275_div_25_square = h_prime_average_minus_275_div_25 * h_prime_average_minus_275_div_25; ++ double h_prime_average_minus_275_div_25_square = ++ h_prime_average_minus_275_div_25 * h_prime_average_minus_275_div_25; + double delta_theta = 30.0 * Math.exp(-h_prime_average_minus_275_div_25_square); + double C_prime_average_pot_3 = C_prime_average * C_prime_average * C_prime_average; + double C_prime_average_pot_7 = C_prime_average_pot_3 * C_prime_average_pot_3 * C_prime_average; +- double R_C = 2.0 * Math.sqrt(C_prime_average_pot_7 / (C_prime_average_pot_7 + 6103515625.0)); //25^7 +- double R_T = - Math.sin(Math.toRadians(2.0 * delta_theta)) * R_C; ++ double R_C = 2.0 * Math.sqrt(C_prime_average_pot_7 / (C_prime_average_pot_7 + 6103515625.0)); // 25^7 ++ double R_T = -Math.sin(Math.toRadians(2.0 * delta_theta)) * R_C; + double dLKlsl = delta_L_prime / (kl * S_L); + double dCkcsc = delta_C_prime / (kc * S_C); + double dHkhsh = delta_H_prime / (kh * S_H); +@@ -392,11 +416,11 @@ public class Colors { + double sM = ((1.0 / 0.0228) * Math.log(1.0 + 0.0228 * lch[1])); + double a = sM * Math.cos(Math.toRadians(lch[2])); + double b = sM * Math.sin(Math.toRadians(lch[2])); +- return new double[] {sJ, a, b }; ++ return new double[] {sJ, a, b}; + } + + static double camlch(double[] c1, double[] c2) { +- return camlch(c1, c2, new double[] { 1.0, 1.0, 1.0 }); ++ return camlch(c1, c2, new double[] {1.0, 1.0, 1.0}); + } + + static double camlch(double[] c1, double[] c2, double[] w) { +@@ -414,18 +438,16 @@ public class Colors { + private static double hueDifference(double hue1, double hue2, double c) { + double difference = (hue2 - hue1) % c; + double ch = c / 2; +- if (difference > ch) +- difference -= c; +- if (difference < -ch) +- difference += c; ++ if (difference > ch) difference -= c; ++ if (difference < -ch) difference += c; + return difference; + } + + private static double[] rgb(int color) { + int r = (color >> 16) & 0xFF; +- int g = (color >> 8) & 0xFF; +- int b = (color >> 0) & 0xFF; +- return new double[] { r / 255.0, g / 255.0, b / 255.0 }; ++ int g = (color >> 8) & 0xFF; ++ int b = (color >> 0) & 0xFF; ++ return new double[] {r / 255.0, g / 255.0, b / 255.0}; + } + + static double[] rgb2xyz(int color) { +@@ -454,13 +476,13 @@ public class Colors { + + static double[] lch2lab(double[] lch) { + double toRad = Math.PI / 180; +- return new double[] { lch[0], lch[1] * Math.cos(lch[2] * toRad), lch[1] * Math.sin(lch[2] * toRad) }; ++ return new double[] {lch[0], lch[1] * Math.cos(lch[2] * toRad), lch[1] * Math.sin(lch[2] * toRad)}; + } + + private static double[] xyz2camlch(double[] xyz, double[] vc) { + double[] XYZ = new double[] {xyz[0] * 100.0, xyz[1] * 100.0, xyz[2] * 100.0}; + double[] cam = forwardTransform(XYZ, vc); +- return new double[] { cam[J], cam[M], cam[h] }; ++ return new double[] {cam[J], cam[M], cam[h]}; + } + + /** Lightness */ +@@ -478,12 +500,12 @@ public class Colors { + /** Hue */ + public static final int h = 6; + +- + /** CIECAM02 appearance correlates */ + private static double[] forwardTransform(double[] XYZ, double[] vc) { + // calculate sharpened cone response + double[] RGB = forwardPreAdaptationConeResponse(XYZ); +- // calculate corresponding (sharpened) cone response considering various luminance level and surround conditions in D ++ // calculate corresponding (sharpened) cone response considering various luminance level and surround conditions ++ // in D + double[] RGB_c = forwardPostAdaptationConeResponse(RGB, vc); + // calculate HPE equal area cone fundamentals + double[] RGBPrime = CAT02toHPE(RGB_c); +@@ -501,37 +523,40 @@ public class Colors { + // calculate eccentricity + double e = ((12500.0 / 13.0) * vc[VC_N_C] * vc[VC_N_CB]) * (Math.cos(Math.toRadians(h) + 2.0) + 3.8); + // get t +- double t = e * Math.sqrt(Math.pow(a, 2.0) + Math.pow(b, 2.0)) / (RGBPrime_a[0] + RGBPrime_a[1] + 1.05 * RGBPrime_a[2]); ++ double t = e ++ * Math.sqrt(Math.pow(a, 2.0) + Math.pow(b, 2.0)) ++ / (RGBPrime_a[0] + RGBPrime_a[1] + 1.05 * RGBPrime_a[2]); + // calculate brightness + double Q = (4.0 / vc[VC_C]) * Math.sqrt(J / 100.0) * (vc[VC_A_W] + 4.0) * Math.pow(vc[VC_F_L], 0.25); + // calculate the correlates of chroma, colorfulness, and saturation +- double C = Math.signum(t) * Math.pow(Math.abs(t), 0.9) * Math.sqrt(J / 100.0) * Math.pow(1.64- Math.pow(0.29, vc[VC_N]), 0.73); ++ double C = Math.signum(t) ++ * Math.pow(Math.abs(t), 0.9) ++ * Math.sqrt(J / 100.0) ++ * Math.pow(1.64 - Math.pow(0.29, vc[VC_N]), 0.73); + double M = C * Math.pow(vc[VC_F_L], 0.25); + double s = 100.0 * Math.sqrt(M / Q); + // calculate hue composition + double H = calculateH(h); +- return new double[] { J, Q, C, M, s, H, h }; ++ return new double[] {J, Q, C, M, s, H, h}; + } + + private static double calculateH(double h) { +- if (h < 20.14) +- h = h + 360; ++ if (h < 20.14) h = h + 360; + double i; +- if (h >= 20.14 && h < 90.0) { // index i = 1 ++ if (h >= 20.14 && h < 90.0) { // index i = 1 + i = (h - 20.14) / 0.8; + return 100.0 * i / (i + (90 - h) / 0.7); + } else if (h < 164.25) { // index i = 2 + i = (h - 90) / 0.7; + return 100.0 + 100.0 * i / (i + (164.25 - h) / 1); +- } else if (h < 237.53) { // index i = 3 ++ } else if (h < 237.53) { // index i = 3 + i = (h - 164.25) / 1.0; + return 200.0 + 100.0 * i / (i + (237.53 - h) / 1.2); +- } else if (h <= 380.14) { // index i = 4 ++ } else if (h <= 380.14) { // index i = 4 + i = (h - 237.53) / 1.2; + double H = 300.0 + 100.0 * i / (i + (380.14 - h) / 0.8); + // don't use 400 if we can use 0 +- if (H <= 400.0 && H >= 399.999) +- H = 0; ++ if (H <= 400.0 && H >= 399.999) H = 0; + return H; + } else { + throw new IllegalArgumentException("h outside assumed range 0..360: " + h); +@@ -540,8 +565,8 @@ public class Colors { + + private static double[] forwardResponseCompression(double[] RGB, double[] vc) { + double[] result = new double[3]; +- for(int channel = 0; channel < RGB.length; channel++) { +- if(RGB[channel] >= 0) { ++ for (int channel = 0; channel < RGB.length; channel++) { ++ if (RGB[channel] >= 0) { + double n = Math.pow(vc[VC_F_L] * RGB[channel] / 100.0, 0.42); + result[channel] = 400.0 * n / (n + 27.13) + 0.1; + } else { +@@ -553,22 +578,22 @@ public class Colors { + } + + private static double[] forwardPostAdaptationConeResponse(double[] RGB, double[] vc) { +- return new double[] { vc[VC_D_RGB_R] * RGB[0], vc[VC_D_RGB_G] * RGB[1], vc[VC_D_RGB_B] * RGB[2] }; ++ return new double[] {vc[VC_D_RGB_R] * RGB[0], vc[VC_D_RGB_G] * RGB[1], vc[VC_D_RGB_B] * RGB[2]}; + } + + public static double[] CAT02toHPE(double[] RGB) { + double[] RGBPrime = new double[3]; +- RGBPrime[0] = 0.7409792 * RGB[0] + 0.2180250 * RGB[1] + 0.0410058 * RGB[2]; +- RGBPrime[1] = 0.2853532 * RGB[0] + 0.6242014 * RGB[1] + 0.0904454 * RGB[2]; ++ RGBPrime[0] = 0.7409792 * RGB[0] + 0.2180250 * RGB[1] + 0.0410058 * RGB[2]; ++ RGBPrime[1] = 0.2853532 * RGB[0] + 0.6242014 * RGB[1] + 0.0904454 * RGB[2]; + RGBPrime[2] = -0.0096280 * RGB[0] - 0.0056980 * RGB[1] + 1.0153260 * RGB[2]; + return RGBPrime; + } + + private static double[] forwardPreAdaptationConeResponse(double[] XYZ) { + double[] RGB = new double[3]; +- RGB[0] = 0.7328 * XYZ[0] + 0.4296 * XYZ[1] - 0.1624 * XYZ[2]; ++ RGB[0] = 0.7328 * XYZ[0] + 0.4296 * XYZ[1] - 0.1624 * XYZ[2]; + RGB[1] = -0.7036 * XYZ[0] + 1.6975 * XYZ[1] + 0.0061 * XYZ[2]; +- RGB[2] = 0.0030 * XYZ[0] + 0.0136 * XYZ[1] + 0.9834 * XYZ[2]; ++ RGB[2] = 0.0030 * XYZ[0] + 0.0136 * XYZ[1] + 0.9834 * XYZ[2]; + return RGB; + } + +@@ -581,8 +606,8 @@ public class Colors { + static final int VC_Z_W = 2; + static final int VC_L_A = 3; + static final int VC_Y_B = 4; +- static final int VC_F = 5; +- static final int VC_C = 6; ++ static final int VC_F = 5; ++ static final int VC_C = 6; + static final int VC_N_C = 7; + + static final int VC_Z = 8; +@@ -607,33 +632,33 @@ public class Colors { + vc[VC_N_C] = surrounding[SUR_N_C]; + + double[] RGB_w = forwardPreAdaptationConeResponse(xyz_w); +- double D = Math.max(0.0, Math.min(1.0, vc[VC_F] * (1.0 - (1.0 / 3.6) * Math.pow(Math.E, (-L_A - 42.0) / 92.0)))); ++ double D = ++ Math.max(0.0, Math.min(1.0, vc[VC_F] * (1.0 - (1.0 / 3.6) * Math.pow(Math.E, (-L_A - 42.0) / 92.0)))); + double Yw = xyz_w[1]; + double[] RGB_c = new double[] { +- (D * Yw / RGB_w[0]) + (1.0 - D), +- (D * Yw / RGB_w[1]) + (1.0 - D), +- (D * Yw / RGB_w[2]) + (1.0 - D), ++ (D * Yw / RGB_w[0]) + (1.0 - D), (D * Yw / RGB_w[1]) + (1.0 - D), (D * Yw / RGB_w[2]) + (1.0 - D), + }; + + // calculate increase in brightness and colorfulness caused by brighter viewing environments + double L_Ax5 = 5.0 * L_A; + double k = 1.0 / (L_Ax5 + 1.0); + double kpow4 = Math.pow(k, 4.0); +- vc[VC_F_L] = 0.2 * kpow4 * (L_Ax5) + 0.1 * Math.pow(1.0 - kpow4, 2.0) * Math.pow(L_Ax5, 1.0/3.0); ++ vc[VC_F_L] = 0.2 * kpow4 * (L_Ax5) + 0.1 * Math.pow(1.0 - kpow4, 2.0) * Math.pow(L_Ax5, 1.0 / 3.0); + + // calculate response compression on J and C caused by background lightness. + vc[VC_N] = Y_b / Yw; + vc[VC_Z] = 1.48 + Math.sqrt(vc[VC_N]); + + vc[VC_N_BB] = 0.725 * Math.pow(1.0 / vc[VC_N], 0.2); +- vc[VC_N_CB] = vc[VC_N_BB]; // chromatic contrast factors (calculate increase in J, Q, and C caused by dark backgrounds) ++ vc[VC_N_CB] = vc[ ++ VC_N_BB]; // chromatic contrast factors (calculate increase in J, Q, and C caused by dark backgrounds) + + // calculate achromatic response to white + double[] RGB_wc = new double[] {RGB_c[0] * RGB_w[0], RGB_c[1] * RGB_w[1], RGB_c[2] * RGB_w[2]}; + double[] RGBPrime_w = CAT02toHPE(RGB_wc); + double[] RGBPrime_aw = new double[3]; +- for(int channel = 0; channel < RGBPrime_w.length; channel++) { +- if(RGBPrime_w[channel] >= 0) { ++ for (int channel = 0; channel < RGBPrime_w.length; channel++) { ++ if (RGBPrime_w[channel] >= 0) { + double n = Math.pow(vc[VC_F_L] * RGBPrime_w[channel] / 100.0, 0.42); + RGBPrime_aw[channel] = 400.0 * n / (n + 27.13) + 0.1; + } else { +@@ -660,7 +685,7 @@ public class Colors { + double x = vr * 0.4124564 + vg * 0.3575761 + vb * 0.1804375; + double y = vr * 0.2126729 + vg * 0.7151522 + vb * 0.0721750; + double z = vr * 0.0193339 + vg * 0.1191920 + vb * 0.9503041; +- return new double[] { x, y, z }; ++ return new double[] {x, y, z}; + } + + private static double pivotRgb(double n) { +@@ -674,11 +699,12 @@ public class Colors { + double l = 116.0 * fy - 16.0; + double a = 500.0 * (fx - fy); + double b = 200.0 * (fy - fz); +- return new double[] { l, a, b }; ++ return new double[] {l, a, b}; + } + + private static final double epsilon = 216.0 / 24389.0; + private static final double kappa = 24389.0 / 27.0; + -+ JVMDebugger debugger = VM.getVM().getDebugger(); -+ return debugger.getThreadForIdentifierAddress(threadIdAddr); -+ } -+} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/loongarch64/LOONGARCH64CurrentFrameGuess.java jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/loongarch64/LOONGARCH64CurrentFrameGuess.java ---- openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/loongarch64/LOONGARCH64CurrentFrameGuess.java 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/loongarch64/LOONGARCH64CurrentFrameGuess.java 2023-09-12 13:54:26.429575856 +0800 -@@ -0,0 +1,250 @@ + private static double pivotXyz(double n) { + return n > epsilon ? Math.cbrt(n) : (kappa * n + 16) / 116; + } +@@ -686,5 +712,4 @@ public class Colors { + private static double sqr(double n) { + return n * n; + } +- + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Curses.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Curses.java +index bdfd4c37b..b9ada2707 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Curses.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Curses.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2018, the original author or authors. ++ * Copyright (c) 2002-2018, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -29,8 +29,7 @@ public final class Curses { + private static final int IFTE_THEN = 2; + private static final int IFTE_ELSE = 3; + +- private Curses() { +- } ++ private Curses() {} + + /** + * Print the given terminal capabilities +@@ -95,9 +94,9 @@ public final class Curses { + case 'n': + out.append('\n'); + break; +-// case 'l': +-// rawPrint('\l'); +-// break; ++ // case 'l': ++ // rawPrint('\l'); ++ // break; + case 'r': + if (exec) { + out.append('\r'); +@@ -138,7 +137,7 @@ public final class Curses { + case '^': + ch = str.charAt(index++); + if (exec) { +- out.append((char)(ch - '@')); ++ out.append((char) (ch - '@')); + } + break; + case '%': +@@ -195,7 +194,8 @@ public final class Curses { + break; + case '{': + int start = index; +- while (str.charAt(index++) != '}') ; ++ while (str.charAt(index++) != '}') ++ ; + if (exec) { + int v = Integer.parseInt(str.substring(start, index - 1)); + stack.push(v); +@@ -364,10 +364,18 @@ public final class Curses { + int cnv; + while ("-+# ".indexOf(ch) >= 0) { + switch (ch) { +- case '-': left = true; break; +- case '+': plus = true; break; +- case '#': alternate = true; break; +- case ' ': space = true; break; ++ case '-': ++ left = true; ++ break; ++ case '+': ++ plus = true; ++ break; ++ case '#': ++ alternate = true; ++ break; ++ case ' ': ++ space = true; ++ break; + } + ch = str.charAt(index++); + } +@@ -473,5 +481,4 @@ public final class Curses { + return Integer.parseInt(pop.toString()); + } + } +- + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/DiffHelper.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/DiffHelper.java +index 3852f5727..93b065395 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/DiffHelper.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/DiffHelper.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2016, the original author or authors. ++ * Copyright (c) 2002-2016, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -25,7 +25,9 @@ public class DiffHelper { + * which means: delete "Hello", add "Goodbye" and keep " world." + */ + public enum Operation { +- DELETE, INSERT, EQUAL ++ DELETE, ++ INSERT, ++ EQUAL + } + + /** +@@ -86,16 +88,13 @@ public class DiffHelper { + && text1.charAt(commonStart) == text2.charAt(commonStart) + && text1.styleAt(commonStart).equals(text2.styleAt(commonStart))) { + if (text1.isHidden(commonStart)) { +- if (startHiddenRange < 0) +- startHiddenRange = commonStart; +- } else +- startHiddenRange = -1; ++ if (startHiddenRange < 0) startHiddenRange = commonStart; ++ } else startHiddenRange = -1; + commonStart++; + } + if (startHiddenRange >= 0 +- && ((l1 > commonStart && text1.isHidden(commonStart)) +- || (l2 > commonStart && text2.isHidden(commonStart)))) +- commonStart = startHiddenRange; ++ && ((l1 > commonStart && text1.isHidden(commonStart)) ++ || (l2 > commonStart && text2.isHidden(commonStart)))) commonStart = startHiddenRange; + + startHiddenRange = -1; + int commonEnd = 0; +@@ -103,32 +102,24 @@ public class DiffHelper { + && text1.charAt(l1 - commonEnd - 1) == text2.charAt(l2 - commonEnd - 1) + && text1.styleAt(l1 - commonEnd - 1).equals(text2.styleAt(l2 - commonEnd - 1))) { + if (text1.isHidden(l1 - commonEnd - 1)) { +- if (startHiddenRange < 0) +- startHiddenRange = commonEnd; +- } else +- startHiddenRange = -1; ++ if (startHiddenRange < 0) startHiddenRange = commonEnd; ++ } else startHiddenRange = -1; + commonEnd++; + } +- if (startHiddenRange >= 0) +- commonEnd = startHiddenRange; ++ if (startHiddenRange >= 0) commonEnd = startHiddenRange; + LinkedList diffs = new LinkedList<>(); + if (commonStart > 0) { +- diffs.add(new Diff(DiffHelper.Operation.EQUAL, +- text1.subSequence(0, commonStart))); ++ diffs.add(new Diff(DiffHelper.Operation.EQUAL, text1.subSequence(0, commonStart))); + } + if (l2 > commonStart + commonEnd) { +- diffs.add(new Diff(DiffHelper.Operation.INSERT, +- text2.subSequence(commonStart, l2 - commonEnd))); ++ diffs.add(new Diff(DiffHelper.Operation.INSERT, text2.subSequence(commonStart, l2 - commonEnd))); + } + if (l1 > commonStart + commonEnd) { +- diffs.add(new Diff(DiffHelper.Operation.DELETE, +- text1.subSequence(commonStart, l1 - commonEnd))); ++ diffs.add(new Diff(DiffHelper.Operation.DELETE, text1.subSequence(commonStart, l1 - commonEnd))); + } + if (commonEnd > 0) { +- diffs.add(new Diff(DiffHelper.Operation.EQUAL, +- text1.subSequence(l1 - commonEnd, l1))); ++ diffs.add(new Diff(DiffHelper.Operation.EQUAL, text1.subSequence(l1 - commonEnd, l1))); + } + return diffs; + } +- + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Display.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Display.java +index aaeab9b71..557024a12 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Display.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Display.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2020, the original author or authors. ++ * Copyright (c) 2002-2020, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -37,8 +37,8 @@ public class Display { + protected final boolean fullScreen; + protected List oldLines = Collections.emptyList(); + protected int cursorPos; +- private int columns; +- private int columns1; // columns+1 ++ protected int columns; ++ protected int columns1; // columns+1 + protected int rows; + protected boolean reset; + protected boolean delayLineWrap; +@@ -49,15 +49,15 @@ public class Display { + protected final boolean delayedWrapAtEol; + protected final boolean cursorDownIsNewLine; + ++ @SuppressWarnings("this-escape") + public Display(Terminal terminal, boolean fullscreen) { + this.terminal = terminal; + this.fullScreen = fullscreen; + + this.canScroll = can(Capability.insert_line, Capability.parm_insert_line) +- && can(Capability.delete_line, Capability.parm_delete_line); ++ && can(Capability.delete_line, Capability.parm_delete_line); + this.wrapAtEol = terminal.getBooleanCapability(Capability.auto_right_margin); +- this.delayedWrapAtEol = this.wrapAtEol +- && terminal.getBooleanCapability(Capability.eat_newline_glitch); ++ this.delayedWrapAtEol = this.wrapAtEol && terminal.getBooleanCapability(Capability.eat_newline_glitch); + this.cursorDownIsNewLine = "\n".equals(Curses.tputs(terminal.getStringCapability(Capability.cursor_down))); + } + +@@ -69,18 +69,22 @@ public class Display { + public boolean delayLineWrap() { + return delayLineWrap; + } +- public void setDelayLineWrap(boolean v) { delayLineWrap = v; } ++ ++ public void setDelayLineWrap(boolean v) { ++ delayLineWrap = v; ++ } + + public void resize(int rows, int columns) { + if (rows == 0 || columns == 0) { +- columns = Integer.MAX_VALUE - 1; ++ columns = 1; + rows = 1; + } + if (this.rows != rows || this.columns != columns) { + this.rows = rows; + this.columns = columns; + this.columns1 = columns + 1; +- oldLines = AttributedString.join(AttributedString.EMPTY, oldLines).columnSplitLength(columns, true, delayLineWrap()); ++ oldLines = AttributedString.join(AttributedString.EMPTY, oldLines) ++ .columnSplitLength(columns, true, delayLineWrap()); + } + } + +@@ -128,7 +132,8 @@ public class Display { + // If dumb display, get rid of ansi sequences now + Integer cols = terminal.getNumericCapability(Capability.max_colors); + if (cols == null || cols < 8) { +- newLines = newLines.stream().map(s -> new AttributedString(s.toString())) ++ newLines = newLines.stream() ++ .map(s -> new AttributedString(s.toString())) + .collect(Collectors.toList()); + } + +@@ -138,12 +143,13 @@ public class Display { + int nbFooters = 0; + // Find common headers and footers + int l = newLines.size(); +- while (nbHeaders < l +- && Objects.equals(newLines.get(nbHeaders), oldLines.get(nbHeaders))) { ++ while (nbHeaders < l && Objects.equals(newLines.get(nbHeaders), oldLines.get(nbHeaders))) { + nbHeaders++; + } + while (nbFooters < l - nbHeaders - 1 +- && Objects.equals(newLines.get(newLines.size() - nbFooters - 1), oldLines.get(oldLines.size() - nbFooters - 1))) { ++ && Objects.equals( ++ newLines.get(newLines.size() - nbFooters - 1), ++ oldLines.get(oldLines.size() - nbFooters - 1))) { + nbFooters++; + } + List o1 = newLines.subList(nbHeaders, newLines.size() - nbFooters); +@@ -190,18 +196,14 @@ public class Display { + int numLines = Math.min(rows, Math.max(oldLines.size(), newLines.size())); + boolean wrapNeeded = false; + while (lineIndex < numLines) { +- AttributedString oldLine = +- lineIndex < oldLines.size() ? oldLines.get(lineIndex) +- : AttributedString.NEWLINE; +- AttributedString newLine = +- lineIndex < newLines.size() ? newLines.get(lineIndex) +- : AttributedString.NEWLINE; ++ AttributedString oldLine = lineIndex < oldLines.size() ? oldLines.get(lineIndex) : AttributedString.NEWLINE; ++ AttributedString newLine = lineIndex < newLines.size() ? newLines.get(lineIndex) : AttributedString.NEWLINE; + currentPos = lineIndex * columns1; + int curCol = currentPos; + int oldLength = oldLine.length(); + int newLength = newLine.length(); +- boolean oldNL = oldLength > 0 && oldLine.charAt(oldLength-1)=='\n'; +- boolean newNL = newLength > 0 && newLine.charAt(newLength-1)=='\n'; ++ boolean oldNL = oldLength > 0 && oldLine.charAt(oldLength - 1) == '\n'; ++ boolean newNL = newLength > 0 && newLine.charAt(newLength - 1) == '\n'; + if (oldNL) { + oldLength--; + oldLine = oldLine.substring(0, oldLength); +@@ -210,9 +212,7 @@ public class Display { + newLength--; + newLine = newLine.substring(0, newLength); + } +- if (wrapNeeded +- && lineIndex == (cursorPos + 1) / columns1 +- && lineIndex < newLines.size()) { ++ if (wrapNeeded && lineIndex == (cursorPos + 1) / columns1 && lineIndex < newLines.size()) { + // move from right margin to next line's left margin + cursorPos++; + if (newLength == 0 || newLine.isHidden(0)) { +@@ -250,8 +250,7 @@ public class Display { + } + break; + case INSERT: +- if (i <= diffs.size() - 2 +- && diffs.get(i + 1).operation == DiffHelper.Operation.EQUAL) { ++ if (i <= diffs.size() - 2 && diffs.get(i + 1).operation == DiffHelper.Operation.EQUAL) { + cursorPos = moveVisualCursorTo(currentPos); + if (insertChars(width)) { + rawPrint(diff.text); +@@ -282,8 +281,7 @@ public class Display { + if (currentPos - curCol >= columns) { + continue; + } +- if (i <= diffs.size() - 2 +- && diffs.get(i + 1).operation == DiffHelper.Operation.EQUAL) { ++ if (i <= diffs.size() - 2 && diffs.get(i + 1).operation == DiffHelper.Operation.EQUAL) { + if (currentPos + diffs.get(i + 1).text.columnLength() < columns) { + moveVisualCursorTo(currentPos); + if (deleteChars(width)) { +@@ -305,25 +303,23 @@ public class Display { + } + } + lineIndex++; +- boolean newWrap = ! newNL && lineIndex < newLines.size(); +- if (targetCursorPos + 1 == lineIndex * columns1 +- && (newWrap || ! delayLineWrap)) +- targetCursorPos++; ++ boolean newWrap = !newNL && lineIndex < newLines.size(); ++ if (targetCursorPos + 1 == lineIndex * columns1 && (newWrap || !delayLineWrap)) targetCursorPos++; + boolean atRight = (cursorPos - curCol) % columns1 == columns; + wrapNeeded = false; + if (this.delayedWrapAtEol) { +- boolean oldWrap = ! oldNL && lineIndex < oldLines.size(); +- if (newWrap != oldWrap && ! (oldWrap && cleared)) { +- moveVisualCursorTo(lineIndex*columns1-1, newLines); +- if (newWrap) +- wrapNeeded = true; +- else +- terminal.puts(Capability.clr_eol); ++ boolean oldWrap = !oldNL && lineIndex < oldLines.size(); ++ if (newWrap != oldWrap && !(oldWrap && cleared)) { ++ moveVisualCursorTo(lineIndex * columns1 - 1, newLines); ++ if (newWrap) wrapNeeded = true; ++ else terminal.puts(Capability.clr_eol); + } + } else if (atRight) { + if (this.wrapAtEol) { +- terminal.writer().write(" \b"); +- cursorPos++; ++ if (!fullScreen || (fullScreen && lineIndex < numLines)) { ++ terminal.writer().write(" \b"); ++ cursorPos++; ++ } + } else { + terminal.puts(Capability.carriage_return); // CR / not newline. + cursorPos = curCol; +@@ -358,8 +354,7 @@ public class Display { + } + + protected boolean can(Capability single, Capability multi) { +- return terminal.getStringCapability(single) != null +- || terminal.getStringCapability(multi) != null; ++ return terminal.getStringCapability(single) != null || terminal.getStringCapability(multi) != null; + } + + protected boolean perform(Capability single, Capability multi, int nb) { +@@ -405,7 +400,7 @@ public class Display { + } + } + } +- return max != 0 ? new int[] { start1, start2, max } : null; ++ return max != 0 ? new int[] {start1, start2, max} : null; + } + + /* +@@ -413,8 +408,7 @@ public class Display { + * We're at the right margin if {@code (cursorPos % columns1) == columns}. + * This method knows how to move both *from* and *to* the right margin. + */ +- protected void moveVisualCursorTo(int targetPos, +- List newLines) { ++ protected void moveVisualCursorTo(int targetPos, List newLines) { + if (cursorPos != targetPos) { + boolean atRight = (targetPos % columns1) == columns; + moveVisualCursorTo(targetPos - (atRight ? 1 : 0)); +@@ -422,12 +416,11 @@ public class Display { + // There is no portable way to move to the right margin + // except by writing a character in the right-most column. + int row = targetPos / columns1; +- AttributedString lastChar = row >= newLines.size() ? AttributedString.EMPTY +- : newLines.get(row).columnSubSequence(columns-1, columns); +- if (lastChar.length() == 0) +- rawPrint((int) ' '); +- else +- rawPrint(lastChar); ++ AttributedString lastChar = row >= newLines.size() ++ ? AttributedString.EMPTY ++ : newLines.get(row).columnSubSequence(columns - 1, columns); ++ if (lastChar.length() == 0) rawPrint((int) ' '); ++ else rawPrint(lastChar); + cursorPos++; + } + } +@@ -499,5 +492,4 @@ public class Display { + public int wcwidth(String str) { + return str != null ? AttributedString.fromAnsi(str).columnLength() : 0; + } +- + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/ExecHelper.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/ExecHelper.java +index 9fce26fcf..5d3c23566 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/ExecHelper.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/ExecHelper.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2016, the original author or authors. ++ * Copyright (c) 2002-2016, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -22,8 +22,7 @@ import java.util.Objects; + */ + public final class ExecHelper { + +- private ExecHelper() { +- } ++ private ExecHelper() {} + + public static String exec(boolean redirectInput, final String... cmd) throws IOException { + Objects.requireNonNull(cmd); +@@ -31,7 +30,7 @@ public final class ExecHelper { + Log.trace("Running: ", cmd); + ProcessBuilder pb = new ProcessBuilder(cmd); + if (OSUtils.IS_AIX) { +- Map env = pb.environment(); ++ Map env = pb.environment(); + env.put("PATH", "/opt/freeware/bin:" + env.get("PATH")); + env.put("LANG", "C"); + env.put("LC_ALL", "C"); +@@ -90,4 +89,3 @@ public final class ExecHelper { + } + } + } +- +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/FastBufferedOutputStream.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/FastBufferedOutputStream.java +new file mode 100644 +index 000000000..62c29c17f +--- /dev/null ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/FastBufferedOutputStream.java +@@ -0,0 +1,61 @@ +/* -+ * Copyright (c) 2001, 2006, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2018, 2022, Loongson Technology. 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). ++ * Copyright (c) 2009-2023, the original author(s). + * -+ * 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 software is distributable under the BSD license. See the terms of the ++ * BSD license in the documentation provided with this software. + * ++ * https://opensource.org/licenses/BSD-3-Clause + */ ++package jdk.internal.org.jline.utils; + -+package sun.jvm.hotspot.runtime.loongarch64; -+ -+import sun.jvm.hotspot.debugger.*; -+import sun.jvm.hotspot.debugger.loongarch64.*; -+import sun.jvm.hotspot.code.*; -+import sun.jvm.hotspot.interpreter.*; -+import sun.jvm.hotspot.runtime.*; ++import java.io.FilterOutputStream; ++import java.io.IOException; ++import java.io.OutputStream; + -+/**

Should be able to be used on all loongarch64 platforms we support -+ (Win32, Solaris/loongarch64, and soon Linux) to implement JavaThread's -+ "currentFrameGuess()" functionality. Input is an LOONGARCH64ThreadContext; -+ output is SP, FP, and PC for an LOONGARCH64Frame. Instantiation of the -+ LOONGARCH64Frame is left to the caller, since we may need to subclass -+ LOONGARCH64Frame to support signal handler frames on Unix platforms.

++/** ++ * A simple buffering output stream with no synchronization. ++ */ ++public class FastBufferedOutputStream extends FilterOutputStream { + -+

Algorithm is to walk up the stack within a given range (say, -+ 512K at most) looking for a plausible PC and SP for a Java frame, -+ also considering those coming in from the context. If we find a PC -+ that belongs to the VM (i.e., in generated code like the -+ interpreter or CodeCache) then we try to find an associated EBP. -+ We repeat this until we either find a complete frame or run out of -+ stack to look at.

*/ ++ protected final byte[] buf = new byte[8192]; ++ protected int count; + -+public class LOONGARCH64CurrentFrameGuess { -+ private LOONGARCH64ThreadContext context; -+ private JavaThread thread; -+ private Address spFound; -+ private Address fpFound; -+ private Address pcFound; ++ public FastBufferedOutputStream(OutputStream out) { ++ super(out); ++ } + -+ private static final boolean DEBUG = System.getProperty("sun.jvm.hotspot.runtime.loongarch64.LOONGARCH64Frame.DEBUG") -+ != null; ++ @Override ++ public void write(int b) throws IOException { ++ if (count >= buf.length) { ++ flushBuffer(); ++ } ++ buf[count++] = (byte) b; ++ } + -+ public LOONGARCH64CurrentFrameGuess(LOONGARCH64ThreadContext context, -+ JavaThread thread) { -+ this.context = context; -+ this.thread = thread; -+ } ++ @Override ++ public void write(byte b[], int off, int len) throws IOException { ++ if (len >= buf.length) { ++ flushBuffer(); ++ out.write(b, off, len); ++ return; ++ } ++ if (len > buf.length - count) { ++ flushBuffer(); ++ } ++ System.arraycopy(b, off, buf, count, len); ++ count += len; ++ } + -+ /** Returns false if not able to find a frame within a reasonable range. */ -+ public boolean run(long regionInBytesToSearch) { -+ Address sp = context.getRegisterAsAddress(LOONGARCH64ThreadContext.SP); -+ Address pc = context.getRegisterAsAddress(LOONGARCH64ThreadContext.PC); -+ Address fp = context.getRegisterAsAddress(LOONGARCH64ThreadContext.FP); -+ if (sp == null) { -+ // Bail out if no last java frame eithe -+ if (thread.getLastJavaSP() != null) { -+ setValues(thread.getLastJavaSP(), thread.getLastJavaFP(), null); -+ return true; -+ } -+ // Bail out -+ return false; ++ private void flushBuffer() throws IOException { ++ if (count > 0) { ++ out.write(buf, 0, count); ++ count = 0; ++ } + } -+ Address end = sp.addOffsetTo(regionInBytesToSearch); -+ VM vm = VM.getVM(); + -+ setValues(null, null, null); // Assume we're not going to find anything ++ @Override ++ public void flush() throws IOException { ++ flushBuffer(); ++ out.flush(); ++ } ++} +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/InfoCmp.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/InfoCmp.java +index 23a760714..32cf3f563 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/InfoCmp.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/InfoCmp.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2019, the original author or authors. ++ * Copyright (c) 2002-2019, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -28,476 +28,474 @@ public final class InfoCmp { + + private static final Map CAPS = new HashMap<>(); + +- private InfoCmp() { +- } ++ private InfoCmp() {} + + @SuppressWarnings("unused") + public enum Capability { +- +- auto_left_margin, // auto_left_margin, bw, bw +- auto_right_margin, // auto_right_margin, am, am +- back_color_erase, // back_color_erase, bce, ut +- can_change, // can_change, ccc, cc +- ceol_standout_glitch, // ceol_standout_glitch, xhp, xs +- col_addr_glitch, // col_addr_glitch, xhpa, YA +- cpi_changes_res, // cpi_changes_res, cpix, YF +- cr_cancels_micro_mode, // cr_cancels_micro_mode, crxm, YB +- dest_tabs_magic_smso, // dest_tabs_magic_smso, xt, xt +- eat_newline_glitch, // eat_newline_glitch, xenl, xn +- erase_overstrike, // erase_overstrike, eo, eo +- generic_type, // generic_type, gn, gn +- hard_copy, // hard_copy, hc, hc +- hard_cursor, // hard_cursor, chts, HC +- has_meta_key, // has_meta_key, km, km +- has_print_wheel, // has_print_wheel, daisy, YC +- has_status_line, // has_status_line, hs, hs +- hue_lightness_saturation, // hue_lightness_saturation, hls, hl +- insert_null_glitch, // insert_null_glitch, in, in +- lpi_changes_res, // lpi_changes_res, lpix, YG +- memory_above, // memory_above, da, da +- memory_below, // memory_below, db, db +- move_insert_mode, // move_insert_mode, mir, mi +- move_standout_mode, // move_standout_mode, msgr, ms +- needs_xon_xoff, // needs_xon_xoff, nxon, nx +- no_esc_ctlc, // no_esc_ctlc, xsb, xb +- no_pad_char, // no_pad_char, npc, NP +- non_dest_scroll_region, // non_dest_scroll_region, ndscr, ND +- non_rev_rmcup, // non_rev_rmcup, nrrmc, NR +- over_strike, // over_strike, os, os +- prtr_silent, // prtr_silent, mc5i, 5i +- row_addr_glitch, // row_addr_glitch, xvpa, YD +- semi_auto_right_margin, // semi_auto_right_margin, sam, YE +- status_line_esc_ok, // status_line_esc_ok, eslok, es +- tilde_glitch, // tilde_glitch, hz, hz +- transparent_underline, // transparent_underline, ul, ul +- xon_xoff, // xon_xoff, xon, xo +- columns, // columns, cols, co +- init_tabs, // init_tabs, it, it +- label_height, // label_height, lh, lh +- label_width, // label_width, lw, lw +- lines, // lines, lines, li +- lines_of_memory, // lines_of_memory, lm, lm +- magic_cookie_glitch, // magic_cookie_glitch, xmc, sg +- max_attributes, // max_attributes, ma, ma +- max_colors, // max_colors, colors, Co +- max_pairs, // max_pairs, pairs, pa +- maximum_windows, // maximum_windows, wnum, MW +- no_color_video, // no_color_video, ncv, NC +- num_labels, // num_labels, nlab, Nl +- padding_baud_rate, // padding_baud_rate, pb, pb +- virtual_terminal, // virtual_terminal, vt, vt +- width_status_line, // width_status_line, wsl, ws +- bit_image_entwining, // bit_image_entwining, bitwin, Yo +- bit_image_type, // bit_image_type, bitype, Yp +- buffer_capacity, // buffer_capacity, bufsz, Ya +- buttons, // buttons, btns, BT +- dot_horz_spacing, // dot_horz_spacing, spinh, Yc +- dot_vert_spacing, // dot_vert_spacing, spinv, Yb +- max_micro_address, // max_micro_address, maddr, Yd +- max_micro_jump, // max_micro_jump, mjump, Ye +- micro_col_size, // micro_col_size, mcs, Yf +- micro_line_size, // micro_line_size, mls, Yg +- number_of_pins, // number_of_pins, npins, Yh +- output_res_char, // output_res_char, orc, Yi +- output_res_horz_inch, // output_res_horz_inch, orhi, Yk +- output_res_line, // output_res_line, orl, Yj +- output_res_vert_inch, // output_res_vert_inch, orvi, Yl +- print_rate, // print_rate, cps, Ym +- wide_char_size, // wide_char_size, widcs, Yn +- acs_chars, // acs_chars, acsc, ac +- back_tab, // back_tab, cbt, bt +- bell, // bell, bel, bl +- carriage_return, // carriage_return, cr, cr +- change_char_pitch, // change_char_pitch, cpi, ZA +- change_line_pitch, // change_line_pitch, lpi, ZB +- change_res_horz, // change_res_horz, chr, ZC +- change_res_vert, // change_res_vert, cvr, ZD +- change_scroll_region, // change_scroll_region, csr, cs +- char_padding, // char_padding, rmp, rP +- clear_all_tabs, // clear_all_tabs, tbc, ct +- clear_margins, // clear_margins, mgc, MC +- clear_screen, // clear_screen, clear, cl +- clr_bol, // clr_bol, el1, cb +- clr_eol, // clr_eol, el, ce +- clr_eos, // clr_eos, ed, cd +- column_address, // column_address, hpa, ch +- command_character, // command_character, cmdch, CC +- create_window, // create_window, cwin, CW +- cursor_address, // cursor_address, cup, cm +- cursor_down, // cursor_down, cud1, do +- cursor_home, // cursor_home, home, ho +- cursor_invisible, // cursor_invisible, civis, vi +- cursor_left, // cursor_left, cub1, le +- cursor_mem_address, // cursor_mem_address, mrcup, CM +- cursor_normal, // cursor_normal, cnorm, ve +- cursor_right, // cursor_right, cuf1, nd +- cursor_to_ll, // cursor_to_ll, ll, ll +- cursor_up, // cursor_up, cuu1, up +- cursor_visible, // cursor_visible, cvvis, vs +- define_char, // define_char, defc, ZE +- delete_character, // delete_character, dch1, dc +- delete_line, // delete_line, dl1, dl +- dial_phone, // dial_phone, dial, DI +- dis_status_line, // dis_status_line, dsl, ds +- display_clock, // display_clock, dclk, DK +- down_half_line, // down_half_line, hd, hd +- ena_acs, // ena_acs, enacs, eA +- enter_alt_charset_mode, // enter_alt_charset_mode, smacs, as +- enter_am_mode, // enter_am_mode, smam, SA +- enter_blink_mode, // enter_blink_mode, blink, mb +- enter_bold_mode, // enter_bold_mode, bold, md +- enter_ca_mode, // enter_ca_mode, smcup, ti +- enter_delete_mode, // enter_delete_mode, smdc, dm +- enter_dim_mode, // enter_dim_mode, dim, mh +- enter_doublewide_mode, // enter_doublewide_mode, swidm, ZF +- enter_draft_quality, // enter_draft_quality, sdrfq, ZG +- enter_insert_mode, // enter_insert_mode, smir, im +- enter_italics_mode, // enter_italics_mode, sitm, ZH +- enter_leftward_mode, // enter_leftward_mode, slm, ZI +- enter_micro_mode, // enter_micro_mode, smicm, ZJ +- enter_near_letter_quality, // enter_near_letter_quality, snlq, ZK +- enter_normal_quality, // enter_normal_quality, snrmq, ZL +- enter_protected_mode, // enter_protected_mode, prot, mp +- enter_reverse_mode, // enter_reverse_mode, rev, mr +- enter_secure_mode, // enter_secure_mode, invis, mk +- enter_shadow_mode, // enter_shadow_mode, sshm, ZM +- enter_standout_mode, // enter_standout_mode, smso, so +- enter_subscript_mode, // enter_subscript_mode, ssubm, ZN +- enter_superscript_mode, // enter_superscript_mode, ssupm, ZO +- enter_underline_mode, // enter_underline_mode, smul, us +- enter_upward_mode, // enter_upward_mode, sum, ZP +- enter_xon_mode, // enter_xon_mode, smxon, SX +- erase_chars, // erase_chars, ech, ec +- exit_alt_charset_mode, // exit_alt_charset_mode, rmacs, ae +- exit_am_mode, // exit_am_mode, rmam, RA +- exit_attribute_mode, // exit_attribute_mode, sgr0, me +- exit_ca_mode, // exit_ca_mode, rmcup, te +- exit_delete_mode, // exit_delete_mode, rmdc, ed +- exit_doublewide_mode, // exit_doublewide_mode, rwidm, ZQ +- exit_insert_mode, // exit_insert_mode, rmir, ei +- exit_italics_mode, // exit_italics_mode, ritm, ZR +- exit_leftward_mode, // exit_leftward_mode, rlm, ZS +- exit_micro_mode, // exit_micro_mode, rmicm, ZT +- exit_shadow_mode, // exit_shadow_mode, rshm, ZU +- exit_standout_mode, // exit_standout_mode, rmso, se +- exit_subscript_mode, // exit_subscript_mode, rsubm, ZV +- exit_superscript_mode, // exit_superscript_mode, rsupm, ZW +- exit_underline_mode, // exit_underline_mode, rmul, ue +- exit_upward_mode, // exit_upward_mode, rum, ZX +- exit_xon_mode, // exit_xon_mode, rmxon, RX +- fixed_pause, // fixed_pause, pause, PA +- flash_hook, // flash_hook, hook, fh +- flash_screen, // flash_screen, flash, vb +- form_feed, // form_feed, ff, ff +- from_status_line, // from_status_line, fsl, fs +- goto_window, // goto_window, wingo, WG +- hangup, // hangup, hup, HU +- init_1string, // init_1string, is1, i1 +- init_2string, // init_2string, is2, is +- init_3string, // init_3string, is3, i3 +- init_file, // init_file, if, if +- init_prog, // init_prog, iprog, iP +- initialize_color, // initialize_color, initc, Ic +- initialize_pair, // initialize_pair, initp, Ip +- insert_character, // insert_character, ich1, ic +- insert_line, // insert_line, il1, al +- insert_padding, // insert_padding, ip, ip +- key_a1, // key_a1, ka1, K1 +- key_a3, // key_a3, ka3, K3 +- key_b2, // key_b2, kb2, K2 +- key_backspace, // key_backspace, kbs, kb +- key_beg, // key_beg, kbeg, @1 +- key_btab, // key_btab, kcbt, kB +- key_c1, // key_c1, kc1, K4 +- key_c3, // key_c3, kc3, K5 +- key_cancel, // key_cancel, kcan, @2 +- key_catab, // key_catab, ktbc, ka +- key_clear, // key_clear, kclr, kC +- key_close, // key_close, kclo, @3 +- key_command, // key_command, kcmd, @4 +- key_copy, // key_copy, kcpy, @5 +- key_create, // key_create, kcrt, @6 +- key_ctab, // key_ctab, kctab, kt +- key_dc, // key_dc, kdch1, kD +- key_dl, // key_dl, kdl1, kL +- key_down, // key_down, kcud1, kd +- key_eic, // key_eic, krmir, kM +- key_end, // key_end, kend, @7 +- key_enter, // key_enter, kent, @8 +- key_eol, // key_eol, kel, kE +- key_eos, // key_eos, ked, kS +- key_exit, // key_exit, kext, @9 +- key_f0, // key_f0, kf0, k0 +- key_f1, // key_f1, kf1, k1 +- key_f10, // key_f10, kf10, k; +- key_f11, // key_f11, kf11, F1 +- key_f12, // key_f12, kf12, F2 +- key_f13, // key_f13, kf13, F3 +- key_f14, // key_f14, kf14, F4 +- key_f15, // key_f15, kf15, F5 +- key_f16, // key_f16, kf16, F6 +- key_f17, // key_f17, kf17, F7 +- key_f18, // key_f18, kf18, F8 +- key_f19, // key_f19, kf19, F9 +- key_f2, // key_f2, kf2, k2 +- key_f20, // key_f20, kf20, FA +- key_f21, // key_f21, kf21, FB +- key_f22, // key_f22, kf22, FC +- key_f23, // key_f23, kf23, FD +- key_f24, // key_f24, kf24, FE +- key_f25, // key_f25, kf25, FF +- key_f26, // key_f26, kf26, FG +- key_f27, // key_f27, kf27, FH +- key_f28, // key_f28, kf28, FI +- key_f29, // key_f29, kf29, FJ +- key_f3, // key_f3, kf3, k3 +- key_f30, // key_f30, kf30, FK +- key_f31, // key_f31, kf31, FL +- key_f32, // key_f32, kf32, FM +- key_f33, // key_f33, kf33, FN +- key_f34, // key_f34, kf34, FO +- key_f35, // key_f35, kf35, FP +- key_f36, // key_f36, kf36, FQ +- key_f37, // key_f37, kf37, FR +- key_f38, // key_f38, kf38, FS +- key_f39, // key_f39, kf39, FT +- key_f4, // key_f4, kf4, k4 +- key_f40, // key_f40, kf40, FU +- key_f41, // key_f41, kf41, FV +- key_f42, // key_f42, kf42, FW +- key_f43, // key_f43, kf43, FX +- key_f44, // key_f44, kf44, FY +- key_f45, // key_f45, kf45, FZ +- key_f46, // key_f46, kf46, Fa +- key_f47, // key_f47, kf47, Fb +- key_f48, // key_f48, kf48, Fc +- key_f49, // key_f49, kf49, Fd +- key_f5, // key_f5, kf5, k5 +- key_f50, // key_f50, kf50, Fe +- key_f51, // key_f51, kf51, Ff +- key_f52, // key_f52, kf52, Fg +- key_f53, // key_f53, kf53, Fh +- key_f54, // key_f54, kf54, Fi +- key_f55, // key_f55, kf55, Fj +- key_f56, // key_f56, kf56, Fk +- key_f57, // key_f57, kf57, Fl +- key_f58, // key_f58, kf58, Fm +- key_f59, // key_f59, kf59, Fn +- key_f6, // key_f6, kf6, k6 +- key_f60, // key_f60, kf60, Fo +- key_f61, // key_f61, kf61, Fp +- key_f62, // key_f62, kf62, Fq +- key_f63, // key_f63, kf63, Fr +- key_f7, // key_f7, kf7, k7 +- key_f8, // key_f8, kf8, k8 +- key_f9, // key_f9, kf9, k9 +- key_find, // key_find, kfnd, @0 +- key_help, // key_help, khlp, %1 +- key_home, // key_home, khome, kh +- key_ic, // key_ic, kich1, kI +- key_il, // key_il, kil1, kA +- key_left, // key_left, kcub1, kl +- key_ll, // key_ll, kll, kH +- key_mark, // key_mark, kmrk, %2 +- key_message, // key_message, kmsg, %3 +- key_move, // key_move, kmov, %4 +- key_next, // key_next, knxt, %5 +- key_npage, // key_npage, knp, kN +- key_open, // key_open, kopn, %6 +- key_options, // key_options, kopt, %7 +- key_ppage, // key_ppage, kpp, kP +- key_previous, // key_previous, kprv, %8 +- key_print, // key_print, kprt, %9 +- key_redo, // key_redo, krdo, %0 +- key_reference, // key_reference, kref, &1 +- key_refresh, // key_refresh, krfr, &2 +- key_replace, // key_replace, krpl, &3 +- key_restart, // key_restart, krst, &4 +- key_resume, // key_resume, kres, &5 +- key_right, // key_right, kcuf1, kr +- key_save, // key_save, ksav, &6 +- key_sbeg, // key_sbeg, kBEG, &9 +- key_scancel, // key_scancel, kCAN, &0 +- key_scommand, // key_scommand, kCMD, *1 +- key_scopy, // key_scopy, kCPY, *2 +- key_screate, // key_screate, kCRT, *3 +- key_sdc, // key_sdc, kDC, *4 +- key_sdl, // key_sdl, kDL, *5 +- key_select, // key_select, kslt, *6 +- key_send, // key_send, kEND, *7 +- key_seol, // key_seol, kEOL, *8 +- key_sexit, // key_sexit, kEXT, *9 +- key_sf, // key_sf, kind, kF +- key_sfind, // key_sfind, kFND, *0 +- key_shelp, // key_shelp, kHLP, #1 +- key_shome, // key_shome, kHOM, #2 +- key_sic, // key_sic, kIC, #3 +- key_sleft, // key_sleft, kLFT, #4 +- key_smessage, // key_smessage, kMSG, %a +- key_smove, // key_smove, kMOV, %b +- key_snext, // key_snext, kNXT, %c +- key_soptions, // key_soptions, kOPT, %d +- key_sprevious, // key_sprevious, kPRV, %e +- key_sprint, // key_sprint, kPRT, %f +- key_sr, // key_sr, kri, kR +- key_sredo, // key_sredo, kRDO, %g +- key_sreplace, // key_sreplace, kRPL, %h +- key_sright, // key_sright, kRIT, %i +- key_srsume, // key_srsume, kRES, %j +- key_ssave, // key_ssave, kSAV, !1 +- key_ssuspend, // key_ssuspend, kSPD, !2 +- key_stab, // key_stab, khts, kT +- key_sundo, // key_sundo, kUND, !3 +- key_suspend, // key_suspend, kspd, &7 +- key_undo, // key_undo, kund, &8 +- key_up, // key_up, kcuu1, ku +- keypad_local, // keypad_local, rmkx, ke +- keypad_xmit, // keypad_xmit, smkx, ks +- lab_f0, // lab_f0, lf0, l0 +- lab_f1, // lab_f1, lf1, l1 +- lab_f10, // lab_f10, lf10, la +- lab_f2, // lab_f2, lf2, l2 +- lab_f3, // lab_f3, lf3, l3 +- lab_f4, // lab_f4, lf4, l4 +- lab_f5, // lab_f5, lf5, l5 +- lab_f6, // lab_f6, lf6, l6 +- lab_f7, // lab_f7, lf7, l7 +- lab_f8, // lab_f8, lf8, l8 +- lab_f9, // lab_f9, lf9, l9 +- label_format, // label_format, fln, Lf +- label_off, // label_off, rmln, LF +- label_on, // label_on, smln, LO +- meta_off, // meta_off, rmm, mo +- meta_on, // meta_on, smm, mm +- micro_column_address, // micro_column_address, mhpa, ZY +- micro_down, // micro_down, mcud1, ZZ +- micro_left, // micro_left, mcub1, Za +- micro_right, // micro_right, mcuf1, Zb +- micro_row_address, // micro_row_address, mvpa, Zc +- micro_up, // micro_up, mcuu1, Zd +- newline, // newline, nel, nw +- order_of_pins, // order_of_pins, porder, Ze +- orig_colors, // orig_colors, oc, oc +- orig_pair, // orig_pair, op, op +- pad_char, // pad_char, pad, pc +- parm_dch, // parm_dch, dch, DC +- parm_delete_line, // parm_delete_line, dl, DL +- parm_down_cursor, // parm_down_cursor, cud, DO +- parm_down_micro, // parm_down_micro, mcud, Zf +- parm_ich, // parm_ich, ich, IC +- parm_index, // parm_index, indn, SF +- parm_insert_line, // parm_insert_line, il, AL +- parm_left_cursor, // parm_left_cursor, cub, LE +- parm_left_micro, // parm_left_micro, mcub, Zg +- parm_right_cursor, // parm_right_cursor, cuf, RI +- parm_right_micro, // parm_right_micro, mcuf, Zh +- parm_rindex, // parm_rindex, rin, SR +- parm_up_cursor, // parm_up_cursor, cuu, UP +- parm_up_micro, // parm_up_micro, mcuu, Zi +- pkey_key, // pkey_key, pfkey, pk +- pkey_local, // pkey_local, pfloc, pl +- pkey_xmit, // pkey_xmit, pfx, px +- plab_norm, // plab_norm, pln, pn +- print_screen, // print_screen, mc0, ps +- prtr_non, // prtr_non, mc5p, pO +- prtr_off, // prtr_off, mc4, pf +- prtr_on, // prtr_on, mc5, po +- pulse, // pulse, pulse, PU +- quick_dial, // quick_dial, qdial, QD +- remove_clock, // remove_clock, rmclk, RC +- repeat_char, // repeat_char, rep, rp +- req_for_input, // req_for_input, rfi, RF +- reset_1string, // reset_1string, rs1, r1 +- reset_2string, // reset_2string, rs2, r2 +- reset_3string, // reset_3string, rs3, r3 +- reset_file, // reset_file, rf, rf +- restore_cursor, // restore_cursor, rc, rc +- row_address, // row_address, vpa, cv +- save_cursor, // save_cursor, sc, sc +- scroll_forward, // scroll_forward, ind, sf +- scroll_reverse, // scroll_reverse, ri, sr +- select_char_set, // select_char_set, scs, Zj +- set_attributes, // set_attributes, sgr, sa +- set_background, // set_background, setb, Sb +- set_bottom_margin, // set_bottom_margin, smgb, Zk +- set_bottom_margin_parm, // set_bottom_margin_parm, smgbp, Zl +- set_clock, // set_clock, sclk, SC +- set_color_pair, // set_color_pair, scp, sp +- set_foreground, // set_foreground, setf, Sf +- set_left_margin, // set_left_margin, smgl, ML +- set_left_margin_parm, // set_left_margin_parm, smglp, Zm +- set_right_margin, // set_right_margin, smgr, MR +- set_right_margin_parm, // set_right_margin_parm, smgrp, Zn +- set_tab, // set_tab, hts, st +- set_top_margin, // set_top_margin, smgt, Zo +- set_top_margin_parm, // set_top_margin_parm, smgtp, Zp +- set_window, // set_window, wind, wi +- start_bit_image, // start_bit_image, sbim, Zq +- start_char_set_def, // start_char_set_def, scsd, Zr +- stop_bit_image, // stop_bit_image, rbim, Zs +- stop_char_set_def, // stop_char_set_def, rcsd, Zt +- subscript_characters, // subscript_characters, subcs, Zu +- superscript_characters, // superscript_characters, supcs, Zv +- tab, // tab, ht, ta +- these_cause_cr, // these_cause_cr, docr, Zw +- to_status_line, // to_status_line, tsl, ts +- tone, // tone, tone, TO +- underline_char, // underline_char, uc, uc +- up_half_line, // up_half_line, hu, hu +- user0, // user0, u0, u0 +- user1, // user1, u1, u1 +- user2, // user2, u2, u2 +- user3, // user3, u3, u3 +- user4, // user4, u4, u4 +- user5, // user5, u5, u5 +- user6, // user6, u6, u6 +- user7, // user7, u7, u7 +- user8, // user8, u8, u8 +- user9, // user9, u9, u9 +- wait_tone, // wait_tone, wait, WA +- xoff_character, // xoff_character, xoffc, XF +- xon_character, // xon_character, xonc, XN +- zero_motion, // zero_motion, zerom, Zx +- alt_scancode_esc, // alt_scancode_esc, scesa, S8 +- bit_image_carriage_return, // bit_image_carriage_return, bicr, Yv +- bit_image_newline, // bit_image_newline, binel, Zz +- bit_image_repeat, // bit_image_repeat, birep, Xy +- char_set_names, // char_set_names, csnm, Zy +- code_set_init, // code_set_init, csin, ci +- color_names, // color_names, colornm, Yw +- define_bit_image_region, // define_bit_image_region, defbi, Yx +- device_type, // device_type, devt, dv +- display_pc_char, // display_pc_char, dispc, S1 +- end_bit_image_region, // end_bit_image_region, endbi, Yy +- enter_pc_charset_mode, // enter_pc_charset_mode, smpch, S2 +- enter_scancode_mode, // enter_scancode_mode, smsc, S4 +- exit_pc_charset_mode, // exit_pc_charset_mode, rmpch, S3 +- exit_scancode_mode, // exit_scancode_mode, rmsc, S5 +- get_mouse, // get_mouse, getm, Gm +- key_mouse, // key_mouse, kmous, Km +- mouse_info, // mouse_info, minfo, Mi +- pc_term_options, // pc_term_options, pctrm, S6 +- pkey_plab, // pkey_plab, pfxl, xl +- req_mouse_pos, // req_mouse_pos, reqmp, RQ +- scancode_escape, // scancode_escape, scesc, S7 +- set0_des_seq, // set0_des_seq, s0ds, s0 +- set1_des_seq, // set1_des_seq, s1ds, s1 +- set2_des_seq, // set2_des_seq, s2ds, s2 +- set3_des_seq, // set3_des_seq, s3ds, s3 +- set_a_background, // set_a_background, setab, AB +- set_a_foreground, // set_a_foreground, setaf, AF +- set_color_band, // set_color_band, setcolor, Yz +- set_lr_margin, // set_lr_margin, smglr, ML +- set_page_length, // set_page_length, slines, YZ +- set_tb_margin, // set_tb_margin, smgtb, MT +- enter_horizontal_hl_mode, // enter_horizontal_hl_mode, ehhlm, Xh +- enter_left_hl_mode, // enter_left_hl_mode, elhlm, Xl +- enter_low_hl_mode, // enter_low_hl_mode, elohlm, Xo +- enter_right_hl_mode, // enter_right_hl_mode, erhlm, Xr +- enter_top_hl_mode, // enter_top_hl_mode, ethlm, Xt +- enter_vertical_hl_mode, // enter_vertical_hl_mode, evhlm, Xv +- set_a_attributes, // set_a_attributes, sgr1, sA +- set_pglen_inch, // set_pglen_inch, slength, sL) ++ auto_left_margin, // auto_left_margin, bw, bw ++ auto_right_margin, // auto_right_margin, am, am ++ back_color_erase, // back_color_erase, bce, ut ++ can_change, // can_change, ccc, cc ++ ceol_standout_glitch, // ceol_standout_glitch, xhp, xs ++ col_addr_glitch, // col_addr_glitch, xhpa, YA ++ cpi_changes_res, // cpi_changes_res, cpix, YF ++ cr_cancels_micro_mode, // cr_cancels_micro_mode, crxm, YB ++ dest_tabs_magic_smso, // dest_tabs_magic_smso, xt, xt ++ eat_newline_glitch, // eat_newline_glitch, xenl, xn ++ erase_overstrike, // erase_overstrike, eo, eo ++ generic_type, // generic_type, gn, gn ++ hard_copy, // hard_copy, hc, hc ++ hard_cursor, // hard_cursor, chts, HC ++ has_meta_key, // has_meta_key, km, km ++ has_print_wheel, // has_print_wheel, daisy, YC ++ has_status_line, // has_status_line, hs, hs ++ hue_lightness_saturation, // hue_lightness_saturation, hls, hl ++ insert_null_glitch, // insert_null_glitch, in, in ++ lpi_changes_res, // lpi_changes_res, lpix, YG ++ memory_above, // memory_above, da, da ++ memory_below, // memory_below, db, db ++ move_insert_mode, // move_insert_mode, mir, mi ++ move_standout_mode, // move_standout_mode, msgr, ms ++ needs_xon_xoff, // needs_xon_xoff, nxon, nx ++ no_esc_ctlc, // no_esc_ctlc, xsb, xb ++ no_pad_char, // no_pad_char, npc, NP ++ non_dest_scroll_region, // non_dest_scroll_region, ndscr, ND ++ non_rev_rmcup, // non_rev_rmcup, nrrmc, NR ++ over_strike, // over_strike, os, os ++ prtr_silent, // prtr_silent, mc5i, 5i ++ row_addr_glitch, // row_addr_glitch, xvpa, YD ++ semi_auto_right_margin, // semi_auto_right_margin, sam, YE ++ status_line_esc_ok, // status_line_esc_ok, eslok, es ++ tilde_glitch, // tilde_glitch, hz, hz ++ transparent_underline, // transparent_underline, ul, ul ++ xon_xoff, // xon_xoff, xon, xo ++ columns, // columns, cols, co ++ init_tabs, // init_tabs, it, it ++ label_height, // label_height, lh, lh ++ label_width, // label_width, lw, lw ++ lines, // lines, lines, li ++ lines_of_memory, // lines_of_memory, lm, lm ++ magic_cookie_glitch, // magic_cookie_glitch, xmc, sg ++ max_attributes, // max_attributes, ma, ma ++ max_colors, // max_colors, colors, Co ++ max_pairs, // max_pairs, pairs, pa ++ maximum_windows, // maximum_windows, wnum, MW ++ no_color_video, // no_color_video, ncv, NC ++ num_labels, // num_labels, nlab, Nl ++ padding_baud_rate, // padding_baud_rate, pb, pb ++ virtual_terminal, // virtual_terminal, vt, vt ++ width_status_line, // width_status_line, wsl, ws ++ bit_image_entwining, // bit_image_entwining, bitwin, Yo ++ bit_image_type, // bit_image_type, bitype, Yp ++ buffer_capacity, // buffer_capacity, bufsz, Ya ++ buttons, // buttons, btns, BT ++ dot_horz_spacing, // dot_horz_spacing, spinh, Yc ++ dot_vert_spacing, // dot_vert_spacing, spinv, Yb ++ max_micro_address, // max_micro_address, maddr, Yd ++ max_micro_jump, // max_micro_jump, mjump, Ye ++ micro_col_size, // micro_col_size, mcs, Yf ++ micro_line_size, // micro_line_size, mls, Yg ++ number_of_pins, // number_of_pins, npins, Yh ++ output_res_char, // output_res_char, orc, Yi ++ output_res_horz_inch, // output_res_horz_inch, orhi, Yk ++ output_res_line, // output_res_line, orl, Yj ++ output_res_vert_inch, // output_res_vert_inch, orvi, Yl ++ print_rate, // print_rate, cps, Ym ++ wide_char_size, // wide_char_size, widcs, Yn ++ acs_chars, // acs_chars, acsc, ac ++ back_tab, // back_tab, cbt, bt ++ bell, // bell, bel, bl ++ carriage_return, // carriage_return, cr, cr ++ change_char_pitch, // change_char_pitch, cpi, ZA ++ change_line_pitch, // change_line_pitch, lpi, ZB ++ change_res_horz, // change_res_horz, chr, ZC ++ change_res_vert, // change_res_vert, cvr, ZD ++ change_scroll_region, // change_scroll_region, csr, cs ++ char_padding, // char_padding, rmp, rP ++ clear_all_tabs, // clear_all_tabs, tbc, ct ++ clear_margins, // clear_margins, mgc, MC ++ clear_screen, // clear_screen, clear, cl ++ clr_bol, // clr_bol, el1, cb ++ clr_eol, // clr_eol, el, ce ++ clr_eos, // clr_eos, ed, cd ++ column_address, // column_address, hpa, ch ++ command_character, // command_character, cmdch, CC ++ create_window, // create_window, cwin, CW ++ cursor_address, // cursor_address, cup, cm ++ cursor_down, // cursor_down, cud1, do ++ cursor_home, // cursor_home, home, ho ++ cursor_invisible, // cursor_invisible, civis, vi ++ cursor_left, // cursor_left, cub1, le ++ cursor_mem_address, // cursor_mem_address, mrcup, CM ++ cursor_normal, // cursor_normal, cnorm, ve ++ cursor_right, // cursor_right, cuf1, nd ++ cursor_to_ll, // cursor_to_ll, ll, ll ++ cursor_up, // cursor_up, cuu1, up ++ cursor_visible, // cursor_visible, cvvis, vs ++ define_char, // define_char, defc, ZE ++ delete_character, // delete_character, dch1, dc ++ delete_line, // delete_line, dl1, dl ++ dial_phone, // dial_phone, dial, DI ++ dis_status_line, // dis_status_line, dsl, ds ++ display_clock, // display_clock, dclk, DK ++ down_half_line, // down_half_line, hd, hd ++ ena_acs, // ena_acs, enacs, eA ++ enter_alt_charset_mode, // enter_alt_charset_mode, smacs, as ++ enter_am_mode, // enter_am_mode, smam, SA ++ enter_blink_mode, // enter_blink_mode, blink, mb ++ enter_bold_mode, // enter_bold_mode, bold, md ++ enter_ca_mode, // enter_ca_mode, smcup, ti ++ enter_delete_mode, // enter_delete_mode, smdc, dm ++ enter_dim_mode, // enter_dim_mode, dim, mh ++ enter_doublewide_mode, // enter_doublewide_mode, swidm, ZF ++ enter_draft_quality, // enter_draft_quality, sdrfq, ZG ++ enter_insert_mode, // enter_insert_mode, smir, im ++ enter_italics_mode, // enter_italics_mode, sitm, ZH ++ enter_leftward_mode, // enter_leftward_mode, slm, ZI ++ enter_micro_mode, // enter_micro_mode, smicm, ZJ ++ enter_near_letter_quality, // enter_near_letter_quality, snlq, ZK ++ enter_normal_quality, // enter_normal_quality, snrmq, ZL ++ enter_protected_mode, // enter_protected_mode, prot, mp ++ enter_reverse_mode, // enter_reverse_mode, rev, mr ++ enter_secure_mode, // enter_secure_mode, invis, mk ++ enter_shadow_mode, // enter_shadow_mode, sshm, ZM ++ enter_standout_mode, // enter_standout_mode, smso, so ++ enter_subscript_mode, // enter_subscript_mode, ssubm, ZN ++ enter_superscript_mode, // enter_superscript_mode, ssupm, ZO ++ enter_underline_mode, // enter_underline_mode, smul, us ++ enter_upward_mode, // enter_upward_mode, sum, ZP ++ enter_xon_mode, // enter_xon_mode, smxon, SX ++ erase_chars, // erase_chars, ech, ec ++ exit_alt_charset_mode, // exit_alt_charset_mode, rmacs, ae ++ exit_am_mode, // exit_am_mode, rmam, RA ++ exit_attribute_mode, // exit_attribute_mode, sgr0, me ++ exit_ca_mode, // exit_ca_mode, rmcup, te ++ exit_delete_mode, // exit_delete_mode, rmdc, ed ++ exit_doublewide_mode, // exit_doublewide_mode, rwidm, ZQ ++ exit_insert_mode, // exit_insert_mode, rmir, ei ++ exit_italics_mode, // exit_italics_mode, ritm, ZR ++ exit_leftward_mode, // exit_leftward_mode, rlm, ZS ++ exit_micro_mode, // exit_micro_mode, rmicm, ZT ++ exit_shadow_mode, // exit_shadow_mode, rshm, ZU ++ exit_standout_mode, // exit_standout_mode, rmso, se ++ exit_subscript_mode, // exit_subscript_mode, rsubm, ZV ++ exit_superscript_mode, // exit_superscript_mode, rsupm, ZW ++ exit_underline_mode, // exit_underline_mode, rmul, ue ++ exit_upward_mode, // exit_upward_mode, rum, ZX ++ exit_xon_mode, // exit_xon_mode, rmxon, RX ++ fixed_pause, // fixed_pause, pause, PA ++ flash_hook, // flash_hook, hook, fh ++ flash_screen, // flash_screen, flash, vb ++ form_feed, // form_feed, ff, ff ++ from_status_line, // from_status_line, fsl, fs ++ goto_window, // goto_window, wingo, WG ++ hangup, // hangup, hup, HU ++ init_1string, // init_1string, is1, i1 ++ init_2string, // init_2string, is2, is ++ init_3string, // init_3string, is3, i3 ++ init_file, // init_file, if, if ++ init_prog, // init_prog, iprog, iP ++ initialize_color, // initialize_color, initc, Ic ++ initialize_pair, // initialize_pair, initp, Ip ++ insert_character, // insert_character, ich1, ic ++ insert_line, // insert_line, il1, al ++ insert_padding, // insert_padding, ip, ip ++ key_a1, // key_a1, ka1, K1 ++ key_a3, // key_a3, ka3, K3 ++ key_b2, // key_b2, kb2, K2 ++ key_backspace, // key_backspace, kbs, kb ++ key_beg, // key_beg, kbeg, @1 ++ key_btab, // key_btab, kcbt, kB ++ key_c1, // key_c1, kc1, K4 ++ key_c3, // key_c3, kc3, K5 ++ key_cancel, // key_cancel, kcan, @2 ++ key_catab, // key_catab, ktbc, ka ++ key_clear, // key_clear, kclr, kC ++ key_close, // key_close, kclo, @3 ++ key_command, // key_command, kcmd, @4 ++ key_copy, // key_copy, kcpy, @5 ++ key_create, // key_create, kcrt, @6 ++ key_ctab, // key_ctab, kctab, kt ++ key_dc, // key_dc, kdch1, kD ++ key_dl, // key_dl, kdl1, kL ++ key_down, // key_down, kcud1, kd ++ key_eic, // key_eic, krmir, kM ++ key_end, // key_end, kend, @7 ++ key_enter, // key_enter, kent, @8 ++ key_eol, // key_eol, kel, kE ++ key_eos, // key_eos, ked, kS ++ key_exit, // key_exit, kext, @9 ++ key_f0, // key_f0, kf0, k0 ++ key_f1, // key_f1, kf1, k1 ++ key_f10, // key_f10, kf10, k; ++ key_f11, // key_f11, kf11, F1 ++ key_f12, // key_f12, kf12, F2 ++ key_f13, // key_f13, kf13, F3 ++ key_f14, // key_f14, kf14, F4 ++ key_f15, // key_f15, kf15, F5 ++ key_f16, // key_f16, kf16, F6 ++ key_f17, // key_f17, kf17, F7 ++ key_f18, // key_f18, kf18, F8 ++ key_f19, // key_f19, kf19, F9 ++ key_f2, // key_f2, kf2, k2 ++ key_f20, // key_f20, kf20, FA ++ key_f21, // key_f21, kf21, FB ++ key_f22, // key_f22, kf22, FC ++ key_f23, // key_f23, kf23, FD ++ key_f24, // key_f24, kf24, FE ++ key_f25, // key_f25, kf25, FF ++ key_f26, // key_f26, kf26, FG ++ key_f27, // key_f27, kf27, FH ++ key_f28, // key_f28, kf28, FI ++ key_f29, // key_f29, kf29, FJ ++ key_f3, // key_f3, kf3, k3 ++ key_f30, // key_f30, kf30, FK ++ key_f31, // key_f31, kf31, FL ++ key_f32, // key_f32, kf32, FM ++ key_f33, // key_f33, kf33, FN ++ key_f34, // key_f34, kf34, FO ++ key_f35, // key_f35, kf35, FP ++ key_f36, // key_f36, kf36, FQ ++ key_f37, // key_f37, kf37, FR ++ key_f38, // key_f38, kf38, FS ++ key_f39, // key_f39, kf39, FT ++ key_f4, // key_f4, kf4, k4 ++ key_f40, // key_f40, kf40, FU ++ key_f41, // key_f41, kf41, FV ++ key_f42, // key_f42, kf42, FW ++ key_f43, // key_f43, kf43, FX ++ key_f44, // key_f44, kf44, FY ++ key_f45, // key_f45, kf45, FZ ++ key_f46, // key_f46, kf46, Fa ++ key_f47, // key_f47, kf47, Fb ++ key_f48, // key_f48, kf48, Fc ++ key_f49, // key_f49, kf49, Fd ++ key_f5, // key_f5, kf5, k5 ++ key_f50, // key_f50, kf50, Fe ++ key_f51, // key_f51, kf51, Ff ++ key_f52, // key_f52, kf52, Fg ++ key_f53, // key_f53, kf53, Fh ++ key_f54, // key_f54, kf54, Fi ++ key_f55, // key_f55, kf55, Fj ++ key_f56, // key_f56, kf56, Fk ++ key_f57, // key_f57, kf57, Fl ++ key_f58, // key_f58, kf58, Fm ++ key_f59, // key_f59, kf59, Fn ++ key_f6, // key_f6, kf6, k6 ++ key_f60, // key_f60, kf60, Fo ++ key_f61, // key_f61, kf61, Fp ++ key_f62, // key_f62, kf62, Fq ++ key_f63, // key_f63, kf63, Fr ++ key_f7, // key_f7, kf7, k7 ++ key_f8, // key_f8, kf8, k8 ++ key_f9, // key_f9, kf9, k9 ++ key_find, // key_find, kfnd, @0 ++ key_help, // key_help, khlp, %1 ++ key_home, // key_home, khome, kh ++ key_ic, // key_ic, kich1, kI ++ key_il, // key_il, kil1, kA ++ key_left, // key_left, kcub1, kl ++ key_ll, // key_ll, kll, kH ++ key_mark, // key_mark, kmrk, %2 ++ key_message, // key_message, kmsg, %3 ++ key_move, // key_move, kmov, %4 ++ key_next, // key_next, knxt, %5 ++ key_npage, // key_npage, knp, kN ++ key_open, // key_open, kopn, %6 ++ key_options, // key_options, kopt, %7 ++ key_ppage, // key_ppage, kpp, kP ++ key_previous, // key_previous, kprv, %8 ++ key_print, // key_print, kprt, %9 ++ key_redo, // key_redo, krdo, %0 ++ key_reference, // key_reference, kref, &1 ++ key_refresh, // key_refresh, krfr, &2 ++ key_replace, // key_replace, krpl, &3 ++ key_restart, // key_restart, krst, &4 ++ key_resume, // key_resume, kres, &5 ++ key_right, // key_right, kcuf1, kr ++ key_save, // key_save, ksav, &6 ++ key_sbeg, // key_sbeg, kBEG, &9 ++ key_scancel, // key_scancel, kCAN, &0 ++ key_scommand, // key_scommand, kCMD, *1 ++ key_scopy, // key_scopy, kCPY, *2 ++ key_screate, // key_screate, kCRT, *3 ++ key_sdc, // key_sdc, kDC, *4 ++ key_sdl, // key_sdl, kDL, *5 ++ key_select, // key_select, kslt, *6 ++ key_send, // key_send, kEND, *7 ++ key_seol, // key_seol, kEOL, *8 ++ key_sexit, // key_sexit, kEXT, *9 ++ key_sf, // key_sf, kind, kF ++ key_sfind, // key_sfind, kFND, *0 ++ key_shelp, // key_shelp, kHLP, #1 ++ key_shome, // key_shome, kHOM, #2 ++ key_sic, // key_sic, kIC, #3 ++ key_sleft, // key_sleft, kLFT, #4 ++ key_smessage, // key_smessage, kMSG, %a ++ key_smove, // key_smove, kMOV, %b ++ key_snext, // key_snext, kNXT, %c ++ key_soptions, // key_soptions, kOPT, %d ++ key_sprevious, // key_sprevious, kPRV, %e ++ key_sprint, // key_sprint, kPRT, %f ++ key_sr, // key_sr, kri, kR ++ key_sredo, // key_sredo, kRDO, %g ++ key_sreplace, // key_sreplace, kRPL, %h ++ key_sright, // key_sright, kRIT, %i ++ key_srsume, // key_srsume, kRES, %j ++ key_ssave, // key_ssave, kSAV, !1 ++ key_ssuspend, // key_ssuspend, kSPD, !2 ++ key_stab, // key_stab, khts, kT ++ key_sundo, // key_sundo, kUND, !3 ++ key_suspend, // key_suspend, kspd, &7 ++ key_undo, // key_undo, kund, &8 ++ key_up, // key_up, kcuu1, ku ++ keypad_local, // keypad_local, rmkx, ke ++ keypad_xmit, // keypad_xmit, smkx, ks ++ lab_f0, // lab_f0, lf0, l0 ++ lab_f1, // lab_f1, lf1, l1 ++ lab_f10, // lab_f10, lf10, la ++ lab_f2, // lab_f2, lf2, l2 ++ lab_f3, // lab_f3, lf3, l3 ++ lab_f4, // lab_f4, lf4, l4 ++ lab_f5, // lab_f5, lf5, l5 ++ lab_f6, // lab_f6, lf6, l6 ++ lab_f7, // lab_f7, lf7, l7 ++ lab_f8, // lab_f8, lf8, l8 ++ lab_f9, // lab_f9, lf9, l9 ++ label_format, // label_format, fln, Lf ++ label_off, // label_off, rmln, LF ++ label_on, // label_on, smln, LO ++ meta_off, // meta_off, rmm, mo ++ meta_on, // meta_on, smm, mm ++ micro_column_address, // micro_column_address, mhpa, ZY ++ micro_down, // micro_down, mcud1, ZZ ++ micro_left, // micro_left, mcub1, Za ++ micro_right, // micro_right, mcuf1, Zb ++ micro_row_address, // micro_row_address, mvpa, Zc ++ micro_up, // micro_up, mcuu1, Zd ++ newline, // newline, nel, nw ++ order_of_pins, // order_of_pins, porder, Ze ++ orig_colors, // orig_colors, oc, oc ++ orig_pair, // orig_pair, op, op ++ pad_char, // pad_char, pad, pc ++ parm_dch, // parm_dch, dch, DC ++ parm_delete_line, // parm_delete_line, dl, DL ++ parm_down_cursor, // parm_down_cursor, cud, DO ++ parm_down_micro, // parm_down_micro, mcud, Zf ++ parm_ich, // parm_ich, ich, IC ++ parm_index, // parm_index, indn, SF ++ parm_insert_line, // parm_insert_line, il, AL ++ parm_left_cursor, // parm_left_cursor, cub, LE ++ parm_left_micro, // parm_left_micro, mcub, Zg ++ parm_right_cursor, // parm_right_cursor, cuf, RI ++ parm_right_micro, // parm_right_micro, mcuf, Zh ++ parm_rindex, // parm_rindex, rin, SR ++ parm_up_cursor, // parm_up_cursor, cuu, UP ++ parm_up_micro, // parm_up_micro, mcuu, Zi ++ pkey_key, // pkey_key, pfkey, pk ++ pkey_local, // pkey_local, pfloc, pl ++ pkey_xmit, // pkey_xmit, pfx, px ++ plab_norm, // plab_norm, pln, pn ++ print_screen, // print_screen, mc0, ps ++ prtr_non, // prtr_non, mc5p, pO ++ prtr_off, // prtr_off, mc4, pf ++ prtr_on, // prtr_on, mc5, po ++ pulse, // pulse, pulse, PU ++ quick_dial, // quick_dial, qdial, QD ++ remove_clock, // remove_clock, rmclk, RC ++ repeat_char, // repeat_char, rep, rp ++ req_for_input, // req_for_input, rfi, RF ++ reset_1string, // reset_1string, rs1, r1 ++ reset_2string, // reset_2string, rs2, r2 ++ reset_3string, // reset_3string, rs3, r3 ++ reset_file, // reset_file, rf, rf ++ restore_cursor, // restore_cursor, rc, rc ++ row_address, // row_address, vpa, cv ++ save_cursor, // save_cursor, sc, sc ++ scroll_forward, // scroll_forward, ind, sf ++ scroll_reverse, // scroll_reverse, ri, sr ++ select_char_set, // select_char_set, scs, Zj ++ set_attributes, // set_attributes, sgr, sa ++ set_background, // set_background, setb, Sb ++ set_bottom_margin, // set_bottom_margin, smgb, Zk ++ set_bottom_margin_parm, // set_bottom_margin_parm, smgbp, Zl ++ set_clock, // set_clock, sclk, SC ++ set_color_pair, // set_color_pair, scp, sp ++ set_foreground, // set_foreground, setf, Sf ++ set_left_margin, // set_left_margin, smgl, ML ++ set_left_margin_parm, // set_left_margin_parm, smglp, Zm ++ set_right_margin, // set_right_margin, smgr, MR ++ set_right_margin_parm, // set_right_margin_parm, smgrp, Zn ++ set_tab, // set_tab, hts, st ++ set_top_margin, // set_top_margin, smgt, Zo ++ set_top_margin_parm, // set_top_margin_parm, smgtp, Zp ++ set_window, // set_window, wind, wi ++ start_bit_image, // start_bit_image, sbim, Zq ++ start_char_set_def, // start_char_set_def, scsd, Zr ++ stop_bit_image, // stop_bit_image, rbim, Zs ++ stop_char_set_def, // stop_char_set_def, rcsd, Zt ++ subscript_characters, // subscript_characters, subcs, Zu ++ superscript_characters, // superscript_characters, supcs, Zv ++ tab, // tab, ht, ta ++ these_cause_cr, // these_cause_cr, docr, Zw ++ to_status_line, // to_status_line, tsl, ts ++ tone, // tone, tone, TO ++ underline_char, // underline_char, uc, uc ++ up_half_line, // up_half_line, hu, hu ++ user0, // user0, u0, u0 ++ user1, // user1, u1, u1 ++ user2, // user2, u2, u2 ++ user3, // user3, u3, u3 ++ user4, // user4, u4, u4 ++ user5, // user5, u5, u5 ++ user6, // user6, u6, u6 ++ user7, // user7, u7, u7 ++ user8, // user8, u8, u8 ++ user9, // user9, u9, u9 ++ wait_tone, // wait_tone, wait, WA ++ xoff_character, // xoff_character, xoffc, XF ++ xon_character, // xon_character, xonc, XN ++ zero_motion, // zero_motion, zerom, Zx ++ alt_scancode_esc, // alt_scancode_esc, scesa, S8 ++ bit_image_carriage_return, // bit_image_carriage_return, bicr, Yv ++ bit_image_newline, // bit_image_newline, binel, Zz ++ bit_image_repeat, // bit_image_repeat, birep, Xy ++ char_set_names, // char_set_names, csnm, Zy ++ code_set_init, // code_set_init, csin, ci ++ color_names, // color_names, colornm, Yw ++ define_bit_image_region, // define_bit_image_region, defbi, Yx ++ device_type, // device_type, devt, dv ++ display_pc_char, // display_pc_char, dispc, S1 ++ end_bit_image_region, // end_bit_image_region, endbi, Yy ++ enter_pc_charset_mode, // enter_pc_charset_mode, smpch, S2 ++ enter_scancode_mode, // enter_scancode_mode, smsc, S4 ++ exit_pc_charset_mode, // exit_pc_charset_mode, rmpch, S3 ++ exit_scancode_mode, // exit_scancode_mode, rmsc, S5 ++ get_mouse, // get_mouse, getm, Gm ++ key_mouse, // key_mouse, kmous, Km ++ mouse_info, // mouse_info, minfo, Mi ++ pc_term_options, // pc_term_options, pctrm, S6 ++ pkey_plab, // pkey_plab, pfxl, xl ++ req_mouse_pos, // req_mouse_pos, reqmp, RQ ++ scancode_escape, // scancode_escape, scesc, S7 ++ set0_des_seq, // set0_des_seq, s0ds, s0 ++ set1_des_seq, // set1_des_seq, s1ds, s1 ++ set2_des_seq, // set2_des_seq, s2ds, s2 ++ set3_des_seq, // set3_des_seq, s3ds, s3 ++ set_a_background, // set_a_background, setab, AB ++ set_a_foreground, // set_a_foreground, setaf, AF ++ set_color_band, // set_color_band, setcolor, Yz ++ set_lr_margin, // set_lr_margin, smglr, ML ++ set_page_length, // set_page_length, slines, YZ ++ set_tb_margin, // set_tb_margin, smgtb, MT ++ enter_horizontal_hl_mode, // enter_horizontal_hl_mode, ehhlm, Xh ++ enter_left_hl_mode, // enter_left_hl_mode, elhlm, Xl ++ enter_low_hl_mode, // enter_low_hl_mode, elohlm, Xo ++ enter_right_hl_mode, // enter_right_hl_mode, erhlm, Xr ++ enter_top_hl_mode, // enter_top_hl_mode, ethlm, Xt ++ enter_vertical_hl_mode, // enter_vertical_hl_mode, evhlm, Xv ++ set_a_attributes, // set_a_attributes, sgr1, sA ++ set_pglen_inch, // set_pglen_inch, slength, sL) + ; + + public String[] getNames() { +@@ -515,8 +513,9 @@ public final class InfoCmp { + public static Map getCapabilitiesByName() { + Map capabilities = new LinkedHashMap<>(); + try (InputStream is = InfoCmp.class.getResourceAsStream("capabilities.txt"); +- BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) { +- br.lines().map(String::trim) ++ BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) { ++ br.lines() ++ .map(String::trim) + .filter(s -> !s.startsWith("#")) + .filter(s -> !s.isEmpty()) + .forEach(s -> { +@@ -539,9 +538,7 @@ public final class InfoCmp { + CAPS.putIfAbsent(terminal, caps); + } + +- public static String getInfoCmp( +- String terminal +- ) throws IOException, InterruptedException { ++ public static String getInfoCmp(String terminal) throws IOException, InterruptedException { + String caps = getLoadedInfoCmp(terminal); + if (caps == null) { + Process p = new ProcessBuilder(OSUtils.INFOCMP_COMMAND, terminal).start(); +@@ -563,8 +560,7 @@ public final class InfoCmp { + String capabilities, + Set bools, + Map ints, +- Map strings +- ) { ++ Map strings) { + Map capsByName = getCapabilitiesByName(); + String[] lines = capabilities.split("\n"); + for (int i = 1; i < lines.length; i++) { +@@ -609,7 +605,7 @@ public final class InfoCmp { + + static String loadDefaultInfoCmp(String name) { + try (InputStream is = InfoCmp.class.getResourceAsStream(name + ".caps"); +- BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) { ++ BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) { + return br.lines().collect(Collectors.joining("\n", "", "\n")); + } catch (IOException e) { + throw new IOError(e); +@@ -617,11 +613,23 @@ public final class InfoCmp { + } + + static { +- for (String s : Arrays.asList("dumb", "dumb-color", "ansi", "xterm", "xterm-256color", +- "windows", "windows-256color", "windows-conemu", "windows-vtp", +- "screen", "screen-256color", "rxvt-unicode", "rxvt-unicode-256color", "rxvt-basic", "rxvt")) { ++ for (String s : Arrays.asList( ++ "dumb", ++ "dumb-color", ++ "ansi", ++ "xterm", ++ "xterm-256color", ++ "windows", ++ "windows-256color", ++ "windows-conemu", ++ "windows-vtp", ++ "screen", ++ "screen-256color", ++ "rxvt-unicode", ++ "rxvt-unicode-256color", ++ "rxvt-basic", ++ "rxvt")) { + setDefaultInfoCmp(s, () -> loadDefaultInfoCmp(s)); + } + } +- + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/InputStreamReader.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/InputStreamReader.java +index fda314fb9..449d6aa69 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/InputStreamReader.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/InputStreamReader.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2016, the original author or authors. ++ * Copyright (c) 2002-2016, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -22,7 +22,6 @@ import java.nio.charset.CodingErrorAction; + import java.nio.charset.MalformedInputException; + import java.nio.charset.UnmappableCharacterException; + +- + /** + * + * NOTE for JLine: the default InputStreamReader that comes from the JRE +@@ -66,9 +65,10 @@ public class InputStreamReader extends Reader { + public InputStreamReader(InputStream in) { + super(in); + this.in = in; +- decoder = Charset.defaultCharset().newDecoder().onMalformedInput( +- CodingErrorAction.REPLACE).onUnmappableCharacter( +- CodingErrorAction.REPLACE); ++ decoder = Charset.defaultCharset() ++ .newDecoder() ++ .onMalformedInput(CodingErrorAction.REPLACE) ++ .onUnmappableCharacter(CodingErrorAction.REPLACE); + bytes.limit(0); + } + +@@ -87,20 +87,19 @@ public class InputStreamReader extends Reader { + * @throws UnsupportedEncodingException + * if the encoding specified by {@code enc} cannot be found. + */ +- public InputStreamReader(InputStream in, final String enc) +- throws UnsupportedEncodingException { ++ public InputStreamReader(InputStream in, final String enc) throws UnsupportedEncodingException { + super(in); + if (enc == null) { + throw new NullPointerException(); + } + this.in = in; + try { +- decoder = Charset.forName(enc).newDecoder().onMalformedInput( +- CodingErrorAction.REPLACE).onUnmappableCharacter( +- CodingErrorAction.REPLACE); ++ decoder = Charset.forName(enc) ++ .newDecoder() ++ .onMalformedInput(CodingErrorAction.REPLACE) ++ .onUnmappableCharacter(CodingErrorAction.REPLACE); + } catch (IllegalArgumentException e) { +- throw (UnsupportedEncodingException) +- new UnsupportedEncodingException(enc).initCause(e); ++ throw (UnsupportedEncodingException) new UnsupportedEncodingException(enc).initCause(e); + } + bytes.limit(0); + } +@@ -134,9 +133,9 @@ public class InputStreamReader extends Reader { + public InputStreamReader(InputStream in, Charset charset) { + super(in); + this.in = in; +- decoder = charset.newDecoder().onMalformedInput( +- CodingErrorAction.REPLACE).onUnmappableCharacter( +- CodingErrorAction.REPLACE); ++ decoder = charset.newDecoder() ++ .onMalformedInput(CodingErrorAction.REPLACE) ++ .onUnmappableCharacter(CodingErrorAction.REPLACE); + bytes.limit(0); + } + +@@ -257,8 +256,7 @@ public class InputStreamReader extends Reader { + // fill the buffer if needed + if (needInput) { + try { +- if ((in.available() == 0) +- && (out.position() > offset)) { ++ if ((in.available() == 0) && (out.position() > offset)) { + // we could return the result without blocking read + break; + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Levenshtein.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Levenshtein.java +index cc95593ed..015515f7d 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Levenshtein.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Levenshtein.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2016, the original author or authors. ++ * Copyright (c) 2002-2016, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -49,9 +49,8 @@ public class Levenshtein { + return distance(lhs, rhs, 1, 1, 1, 1); + } + +- public static int distance(CharSequence source, CharSequence target, +- int deleteCost, int insertCost, +- int replaceCost, int swapCost) { ++ public static int distance( ++ CharSequence source, CharSequence target, int deleteCost, int insertCost, int replaceCost, int swapCost) { + /* + * Required to facilitate the premise to the algorithm that two swaps of the + * same character are never required for optimality. +@@ -115,5 +114,4 @@ public class Levenshtein { + } + return table[source.length() - 1][target.length() - 1]; + } +- + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Log.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Log.java +index 91f18755e..254173d5b 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Log.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Log.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2020, the original author or authors. ++ * Copyright (c) 2002-2020, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -73,8 +73,7 @@ public final class Log { + } + } + out.print("]"); +- } +- else { ++ } else { + out.print(message); + } + } +@@ -84,11 +83,10 @@ public final class Log { + // ByteArrayOutputStream baos = new ByteArrayOutputStream(); + // PrintStream ps = new PrintStream(baos); + // for (int i = 0; i < messages.length; i++) { +-// // Special handling for the last message if its a throwable, render its stack on the next line ++// // Special handling for the last message if it's a throwable, render its stack on the next line + // if (i + 1 == messages.length && messages[i] instanceof Throwable) { + // cause = (Throwable) messages[i]; +-// } +-// else { ++// } else { + // render(ps, messages[i]); + // } + // } +@@ -122,5 +120,4 @@ public final class Log { + // static boolean isEnabled(Level level) { + // return logger.isLoggable(level); + // } +- + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlocking.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlocking.java +index f8cb53489..4130634ca 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlocking.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlocking.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2018, the original author or authors. ++ * Copyright (c) 2002-2018, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -84,8 +84,7 @@ public class NonBlocking { + + @Override + public int available() { +- return (int) (reader.available() * this.encoder.averageBytesPerChar()) +- + bytes.remaining(); ++ return (int) (reader.available() * this.encoder.averageBytesPerChar()) + bytes.remaining(); + } + + @Override +@@ -124,7 +123,6 @@ public class NonBlocking { + return READ_EXPIRED; + } + } +- + } + + private static class NonBlockingInputStreamReader extends NonBlockingReader { +@@ -135,10 +133,12 @@ public class NonBlocking { + private final CharBuffer chars; + + public NonBlockingInputStreamReader(NonBlockingInputStream inputStream, Charset encoding) { +- this(inputStream, +- (encoding != null ? encoding : Charset.defaultCharset()).newDecoder() +- .onMalformedInput(CodingErrorAction.REPLACE) +- .onUnmappableCharacter(CodingErrorAction.REPLACE)); ++ this( ++ inputStream, ++ (encoding != null ? encoding : Charset.defaultCharset()) ++ .newDecoder() ++ .onMalformedInput(CodingErrorAction.REPLACE) ++ .onUnmappableCharacter(CodingErrorAction.REPLACE)); + } + + public NonBlockingInputStreamReader(NonBlockingInputStream input, CharsetDecoder decoder) { +@@ -201,8 +201,8 @@ public class NonBlocking { + bytes.position(0); + bytes.limit(0); + } +- int nb = input.readBuffered(bytes.array(), bytes.limit(), +- bytes.capacity() - bytes.limit(), t.timeout()); ++ int nb = input.readBuffered( ++ bytes.array(), bytes.limit(), bytes.capacity() - bytes.limit(), t.timeout()); + if (nb < 0) { + return nb; + } +@@ -227,5 +227,4 @@ public class NonBlocking { + input.close(); + } + } +- + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingInputStream.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingInputStream.java +index a4283eb70..10ab68cfd 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingInputStream.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingInputStream.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2018, the original author or authors. ++ * Copyright (c) 2002-2018, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -74,7 +74,7 @@ public abstract class NonBlockingInputStream extends InputStream { + if (c == EOF) { + return EOF; + } +- b[off] = (byte)c; ++ b[off] = (byte) c; + return 1; + } + +@@ -115,9 +115,7 @@ public abstract class NonBlockingInputStream extends InputStream { + * thread is currently blocked waiting for I/O it may not actually + * shut down until the I/O is received. + */ +- public void shutdown() { +- } ++ public void shutdown() {} + + public abstract int read(long timeout, boolean isPeek) throws IOException; +- + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingInputStreamImpl.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingInputStreamImpl.java +index 680047fbe..24cf13a0e 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingInputStreamImpl.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingInputStreamImpl.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2018, the original author or authors. ++ * Copyright (c) 2002-2018, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -26,17 +26,15 @@ import java.io.InterruptedIOException; + * the thread that handles blocking I/O. + * + */ +-public class NonBlockingInputStreamImpl +- extends NonBlockingInputStream +-{ +- private InputStream in; // The actual input stream +- private int b = READ_EXPIRED; // Recently read byte +- +- private String name; +- private boolean threadIsReading = false; +- private IOException exception = null; +- private long threadDelay = 60 * 1000; +- private Thread thread; ++public class NonBlockingInputStreamImpl extends NonBlockingInputStream { ++ private InputStream in; // The actual input stream ++ private int b = READ_EXPIRED; // Recently read byte ++ ++ private String name; ++ private boolean threadIsReading = false; ++ private IOException exception = null; ++ private long threadDelay = 60 * 1000; ++ private Thread thread; + + /** + * Creates a NonBlockingReader out of a normal blocking +@@ -97,8 +95,7 @@ public class NonBlockingInputStreamImpl + if (exception != null) { + assert b == READ_EXPIRED; + IOException toBeThrown = exception; +- if (!isPeek) +- exception = null; ++ if (!isPeek) exception = null; + throw toBeThrown; + } + +@@ -109,11 +106,9 @@ public class NonBlockingInputStreamImpl + */ + if (b >= -1) { + assert exception == null; +- } +- else if (!isPeek && timeout <= 0L && !threadIsReading) { ++ } else if (!isPeek && timeout <= 0L && !threadIsReading) { + b = in.read(); +- } +- else { ++ } else { + /* + * If the thread isn't reading already, then ask it to do so. + */ +@@ -128,14 +123,13 @@ public class NonBlockingInputStreamImpl + * now we play the waiting game. + */ + Timeout t = new Timeout(timeout); +- while (!t.elapsed()) { ++ while (!t.elapsed()) { + try { + if (Thread.interrupted()) { + throw new InterruptedException(); + } + wait(t.timeout()); +- } +- catch (InterruptedException e) { ++ } catch (InterruptedException e) { + exception = (IOException) new InterruptedIOException().initCause(e); + } + +@@ -143,8 +137,7 @@ public class NonBlockingInputStreamImpl + assert b == READ_EXPIRED; + + IOException toBeThrown = exception; +- if (!isPeek) +- exception = null; ++ if (!isPeek) exception = null; + throw toBeThrown; + } + +@@ -168,7 +161,7 @@ public class NonBlockingInputStreamImpl + return ret; + } + +- private void run () { ++ private void run() { + Log.debug("NonBlockingInputStream start"); + boolean needToRead; + +@@ -236,5 +229,4 @@ public class NonBlockingInputStreamImpl + } + } + } +- + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingPumpInputStream.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingPumpInputStream.java +index 5a3613443..aad6e3d0f 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingPumpInputStream.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingPumpInputStream.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2017, the original author or authors. ++ * Copyright (c) 2002-2017, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -57,11 +57,7 @@ public class NonBlockingPumpInputStream extends NonBlockingInputStream { + throw new InterruptedIOException(); + } + } +- return buffer.hasRemaining() +- ? 0 +- : closed +- ? EOF +- : READ_EXPIRED; ++ return buffer.hasRemaining() ? 0 : closed ? EOF : READ_EXPIRED; + } + + private static boolean rewind(ByteBuffer buffer, ByteBuffer other) { +@@ -167,7 +163,7 @@ public class NonBlockingPumpInputStream extends NonBlockingInputStream { + + @Override + public void write(int b) throws IOException { +- NonBlockingPumpInputStream.this.write(new byte[] { (byte) b }, 0, 1); ++ NonBlockingPumpInputStream.this.write(new byte[] {(byte) b}, 0, 1); + } + + @Override +@@ -184,7 +180,5 @@ public class NonBlockingPumpInputStream extends NonBlockingInputStream { + public void close() throws IOException { + NonBlockingPumpInputStream.this.close(); + } +- + } +- + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingPumpReader.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingPumpReader.java +index f36423f03..63db6e5f5 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingPumpReader.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingPumpReader.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2017, the original author or authors. ++ * Copyright (c) 2002-2017, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -121,7 +121,7 @@ public class NonBlockingPumpReader extends NonBlockingReader { + try { + if (timeout > 0) { + if (!notEmpty.await(timeout, TimeUnit.MILLISECONDS)) { +- throw new IOException( "Timeout reading" ); ++ throw new IOException("Timeout reading"); + } + } else { + notEmpty.await(); +@@ -207,14 +207,11 @@ public class NonBlockingPumpReader extends NonBlockingReader { + } + + @Override +- public void flush() throws IOException { +- } ++ public void flush() throws IOException {} + + @Override + public void close() throws IOException { + NonBlockingPumpReader.this.close(); + } +- + } +- + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingReader.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingReader.java +index e2f664f29..460f548b5 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingReader.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingReader.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2018, the original author or authors. ++ * Copyright (c) 2002-2018, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -23,8 +23,7 @@ public abstract class NonBlockingReader extends Reader { + * thread is currently blocked waiting for I/O it will not actually + * shut down until the I/O is received. + */ +- public void shutdown() { +- } ++ public void shutdown() {} + + @Override + public int read() throws IOException { +@@ -109,5 +108,4 @@ public abstract class NonBlockingReader extends Reader { + * @throws IOException if anything wrong happens + */ + protected abstract int read(long timeout, boolean isPeek) throws IOException; +- + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingReaderImpl.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingReaderImpl.java +index d384cc9a0..5aaabd1d3 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingReaderImpl.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingReaderImpl.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2018, the original author or authors. ++ * Copyright (c) 2002-2018, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -28,19 +28,17 @@ import java.io.Reader; + * @since 2.7 + * @author Scott C. Gray <scottgray1@gmail.com> + */ +-public class NonBlockingReaderImpl +- extends NonBlockingReader +-{ ++public class NonBlockingReaderImpl extends NonBlockingReader { + public static final int READ_EXPIRED = -2; + +- private Reader in; // The actual input stream +- private int ch = READ_EXPIRED; // Recently read character ++ private Reader in; // The actual input stream ++ private int ch = READ_EXPIRED; // Recently read character + +- private String name; +- private boolean threadIsReading = false; +- private IOException exception = null; +- private long threadDelay = 60 * 1000; +- private Thread thread; ++ private String name; ++ private boolean threadIsReading = false; ++ private IOException exception = null; ++ private long threadDelay = 60 * 1000; ++ private Thread thread; + + /** + * Creates a NonBlockingReader out of a normal blocking +@@ -135,8 +133,7 @@ public class NonBlockingReaderImpl + if (exception != null) { + assert ch == READ_EXPIRED; + IOException toBeThrown = exception; +- if (!isPeek) +- exception = null; ++ if (!isPeek) exception = null; + throw toBeThrown; + } + +@@ -147,11 +144,9 @@ public class NonBlockingReaderImpl + */ + if (ch >= -1) { + assert exception == null; +- } +- else if (!isPeek && timeout <= 0L && !threadIsReading) { ++ } else if (!isPeek && timeout <= 0L && !threadIsReading) { + ch = in.read(); +- } +- else { ++ } else { + /* + * If the thread isn't reading already, then ask it to do so. + */ +@@ -166,14 +161,13 @@ public class NonBlockingReaderImpl + * now we play the waiting game. + */ + Timeout t = new Timeout(timeout); +- while (!t.elapsed()) { ++ while (!t.elapsed()) { + try { + if (Thread.interrupted()) { + throw new InterruptedException(); + } + wait(t.timeout()); +- } +- catch (InterruptedException e) { ++ } catch (InterruptedException e) { + exception = (IOException) new InterruptedIOException().initCause(e); + } + +@@ -181,8 +175,7 @@ public class NonBlockingReaderImpl + assert ch == READ_EXPIRED; + + IOException toBeThrown = exception; +- if (!isPeek) +- exception = null; ++ if (!isPeek) exception = null; + throw toBeThrown; + } + +@@ -206,7 +199,7 @@ public class NonBlockingReaderImpl + return ret; + } + +- private void run () { ++ private void run() { + Log.debug("NonBlockingReader start"); + boolean needToRead; + +@@ -245,12 +238,12 @@ public class NonBlockingReaderImpl + IOException failure = null; + try { + charRead = in.read(); +-// if (charRead < 0) { +-// continue; +-// } ++ // if (charRead < 0) { ++ // continue; ++ // } + } catch (IOException e) { + failure = e; +-// charRead = -1; ++ // charRead = -1; + } + + /* +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/OSUtils.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/OSUtils.java +index 974877318..344d081c1 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/OSUtils.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/OSUtils.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2016, the original author or authors. ++ * Copyright (c) 2002-2016, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -9,16 +9,23 @@ + package jdk.internal.org.jline.utils; + + import java.io.File; +-import java.nio.file.Files; +-import java.nio.file.Paths; + + public class OSUtils { + +- public static final boolean IS_WINDOWS = System.getProperty("os.name").toLowerCase().contains("win"); ++ public static final boolean IS_LINUX = ++ System.getProperty("os.name").toLowerCase().contains("linux"); + +- public static final boolean IS_CYGWIN = IS_WINDOWS +- && System.getenv("PWD") != null +- && System.getenv("PWD").startsWith("/"); ++ public static final boolean IS_WINDOWS = ++ System.getProperty("os.name").toLowerCase().contains("win"); + -+ if (vm.isJavaPCDbg(pc)) { -+ if (vm.isClientCompiler()) { -+ // If the topmost frame is a Java frame, we are (pretty much) -+ // guaranteed to have a viable EBP. We should be more robust -+ // than this (we have the potential for losing entire threads' -+ // stack traces) but need to see how much work we really have -+ // to do here. Searching the stack for an (SP, FP) pair is -+ // hard since it's easy to misinterpret inter-frame stack -+ // pointers as base-of-frame pointers; we also don't know the -+ // sizes of C1 frames (not registered in the nmethod) so can't -+ // derive them from ESP. ++ public static final boolean IS_OSX = ++ System.getProperty("os.name").toLowerCase().contains("mac"); + -+ setValues(sp, fp, pc); -+ return true; -+ } else { -+ if (vm.getInterpreter().contains(pc)) { -+ if (DEBUG) { -+ System.out.println("CurrentFrameGuess: choosing interpreter frame: sp = " + -+ sp + ", fp = " + fp + ", pc = " + pc); -+ } -+ setValues(sp, fp, pc); -+ return true; -+ } ++ public static final boolean IS_AIX = ++ System.getProperty("os.name").toLowerCase().contains("aix"); + -+ // For the server compiler, EBP is not guaranteed to be valid -+ // for compiled code. In addition, an earlier attempt at a -+ // non-searching algorithm (see below) failed because the -+ // stack pointer from the thread context was pointing -+ // (considerably) beyond the ostensible end of the stack, into -+ // garbage; walking from the topmost frame back caused a crash. -+ // -+ // This algorithm takes the current PC as a given and tries to -+ // find the correct corresponding SP by walking up the stack -+ // and repeatedly performing stackwalks (very inefficient). -+ // -+ // FIXME: there is something wrong with stackwalking across -+ // adapter frames...this is likely to be the root cause of the -+ // failure with the simpler algorithm below. ++ public static final boolean IS_CYGWIN = ++ IS_WINDOWS && System.getenv("PWD") != null && System.getenv("PWD").startsWith("/"); + + @Deprecated + public static final boolean IS_MINGW = IS_WINDOWS +@@ -28,7 +35,7 @@ public class OSUtils { + public static final boolean IS_MSYSTEM = IS_WINDOWS + && System.getenv("MSYSTEM") != null + && (System.getenv("MSYSTEM").startsWith("MINGW") +- || System.getenv("MSYSTEM").equals("MSYS")); ++ || System.getenv("MSYSTEM").equals("MSYS")); + + public static final boolean IS_WSL = System.getenv("WSL_DISTRO_NAME") != null; + +@@ -36,11 +43,7 @@ public class OSUtils { + + public static final boolean IS_WSL2 = IS_WSL && !IS_WSL1; + +- public static final boolean IS_CONEMU = IS_WINDOWS +- && System.getenv("ConEmuPID") != null; +- +- public static final boolean IS_OSX = System.getProperty("os.name").toLowerCase().contains("mac"); +- public static final boolean IS_AIX = System.getProperty("os.name").equals("AIX"); ++ public static final boolean IS_CONEMU = IS_WINDOWS && System.getenv("ConEmuPID") != null; + + public static String TTY_COMMAND; + public static String STTY_COMMAND; +@@ -48,64 +51,57 @@ public class OSUtils { + public static String INFOCMP_COMMAND; + public static String TEST_COMMAND; + ++ private static boolean isExecutable(File f) { ++ return f.canExecute() && !f.isDirectory(); ++ } + -+ for (long offset = 0; -+ offset < regionInBytesToSearch; -+ offset += vm.getAddressSize()) { -+ try { -+ Address curSP = sp.addOffsetTo(offset); -+ Frame frame = new LOONGARCH64Frame(curSP, null, pc); -+ RegisterMap map = thread.newRegisterMap(false); -+ while (frame != null) { -+ if (frame.isEntryFrame() && frame.entryFrameIsFirst()) { -+ // We were able to traverse all the way to the -+ // bottommost Java frame. -+ // This sp looks good. Keep it. -+ if (DEBUG) { -+ System.out.println("CurrentFrameGuess: Choosing sp = " + curSP + ", pc = " + pc); + static { +- String tty; +- String stty; +- String sttyfopt; +- String infocmp; +- String test; +- if (OSUtils.IS_CYGWIN || OSUtils.IS_MSYSTEM) { +- tty = null; +- stty = null; +- sttyfopt = null; +- infocmp = null; +- test = null; +- String path = System.getenv("PATH"); +- if (path != null) { +- String[] paths = path.split(";"); +- for (String p : paths) { +- if (tty == null && new File(p, "tty.exe").exists()) { +- tty = new File(p, "tty.exe").getAbsolutePath(); +- } +- if (stty == null && new File(p, "stty.exe").exists()) { +- stty = new File(p, "stty.exe").getAbsolutePath(); +- } +- if (infocmp == null && new File(p, "infocmp.exe").exists()) { +- infocmp = new File(p, "infocmp.exe").getAbsolutePath(); +- } +- if (test == null && new File(p, "test.exe").exists()) { +- test = new File(p, "test.exe").getAbsolutePath(); +- } ++ boolean cygwinOrMsys = OSUtils.IS_CYGWIN || OSUtils.IS_MSYSTEM; ++ String suffix = cygwinOrMsys ? ".exe" : ""; ++ String tty = null; ++ String stty = null; ++ String sttyfopt = null; ++ String infocmp = null; ++ String test = null; ++ String path = System.getenv("PATH"); ++ if (path != null) { ++ String[] paths = path.split(File.pathSeparator); ++ for (String p : paths) { ++ File ttyFile = new File(p, "tty" + suffix); ++ if (tty == null && isExecutable(ttyFile)) { ++ tty = ttyFile.getAbsolutePath(); + } -+ setValues(curSP, null, pc); -+ return true; -+ } -+ frame = frame.sender(map); -+ } -+ } catch (Exception e) { -+ if (DEBUG) { -+ System.out.println("CurrentFrameGuess: Exception " + e + " at offset " + offset); -+ } -+ // Bad SP. Try another. -+ } ++ File sttyFile = new File(p, "stty" + suffix); ++ if (stty == null && isExecutable(sttyFile)) { ++ stty = sttyFile.getAbsolutePath(); ++ } ++ File infocmpFile = new File(p, "infocmp" + suffix); ++ if (infocmp == null && isExecutable(infocmpFile)) { ++ infocmp = infocmpFile.getAbsolutePath(); ++ } ++ File testFile = new File(p, "test" + suffix); ++ if (test == null && isExecutable(testFile)) { ++ test = testFile.getAbsolutePath(); + } + } +- if (tty == null) { +- tty = "tty.exe"; +- } +- if (stty == null) { +- stty = "stty.exe"; +- } +- if (infocmp == null) { +- infocmp = "infocmp.exe"; +- } +- if (test == null) { +- test = "test.exe"; +- } +- } else { +- tty = "tty"; +- stty = IS_OSX ? "/bin/stty" : "stty"; +- sttyfopt = IS_OSX ? "-f" : "-F"; +- infocmp = "infocmp"; +- test = isTestCommandValid("/usr/bin/test") ? "/usr/bin/test" +- : "/bin/test"; + } ++ if (tty == null) { ++ tty = "tty" + suffix; ++ } ++ if (stty == null) { ++ stty = "stty" + suffix; + } ++ if (infocmp == null) { ++ infocmp = "infocmp" + suffix; ++ } ++ if (test == null) { ++ test = "test" + suffix; ++ } ++ sttyfopt = IS_OSX ? "-f" : "-F"; + TTY_COMMAND = tty; + STTY_COMMAND = stty; + STTY_F_OPTION = sttyfopt; + INFOCMP_COMMAND = infocmp; + TEST_COMMAND = test; + } +- +- private static boolean isTestCommandValid(String command) { +- return Files.isExecutable(Paths.get(command)); +- } + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/PumpReader.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/PumpReader.java +index a6894e767..ce68fa5f8 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/PumpReader.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/PumpReader.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2017, the original author or authors. ++ * Copyright (c) 2002-2017, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -378,7 +378,6 @@ public class PumpReader extends Reader { + public void close() throws IOException { + reader.close(); + } +- + } + + private static class InputStream extends java.io.InputStream { +@@ -464,7 +463,5 @@ public class PumpReader extends Reader { + public void close() throws IOException { + reader.close(); + } +- + } +- + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/ShutdownHooks.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/ShutdownHooks.java +index 8089de321..d5456df03 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/ShutdownHooks.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/ShutdownHooks.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2016, the original author or authors. ++ * Copyright (c) 2002-2016, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -18,8 +18,7 @@ import java.util.Objects; + * @author Jason Dillon + * @since 2.7 + */ +-public final class ShutdownHooks +-{ ++public final class ShutdownHooks { + private static final List tasks = new ArrayList<>(); + + private static Thread hook; +@@ -29,8 +28,7 @@ public final class ShutdownHooks + + // Install the hook thread if needed + if (hook == null) { +- hook = addHook(new Thread("JLine Shutdown Hook") +- { ++ hook = addHook(new Thread("JLine Shutdown Hook") { + @Override + public void run() { + runTasks(); +@@ -53,8 +51,7 @@ public final class ShutdownHooks + Log.debug("Running task: ", task); + try { + task.run(); +- } +- catch (Throwable e) { ++ } catch (Throwable e) { + Log.warn("Task failed", e); + } + } +@@ -91,8 +88,7 @@ public final class ShutdownHooks + + try { + Runtime.getRuntime().removeShutdownHook(thread); +- } +- catch (IllegalStateException e) { ++ } catch (IllegalStateException e) { + // The VM is shutting down, not a big deal; ignore + } + } +@@ -100,8 +96,7 @@ public final class ShutdownHooks + /** + * Essentially a {@link Runnable} which allows running to throw an exception. + */ +- public interface Task +- { ++ public interface Task { + void run() throws Exception; + } + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Signals.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Signals.java +index b94f1fa31..9b25a8047 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Signals.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Signals.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2020, the original author or authors. ++ * Copyright (c) 2002-2020, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -21,8 +21,7 @@ import java.util.Objects; + */ + public final class Signals { + +- private Signals() { +- } ++ private Signals() {} + + /** + * +@@ -41,8 +40,8 @@ public final class Signals { + try { + Class signalHandlerClass = Class.forName("sun.misc.SignalHandler"); + // Implement signal handler +- Object signalHandler = Proxy.newProxyInstance(loader, +- new Class[]{signalHandlerClass}, (proxy, method, args) -> { ++ Object signalHandler = ++ Proxy.newProxyInstance(loader, new Class[] {signalHandlerClass}, (proxy, method, args) -> { + // only method we are proxying is handle() + if (method.getDeclaringClass() == Object.class) { + if ("toString".equals(method.getName())) { +@@ -101,8 +100,7 @@ public final class Signals { + return null; + } + Class signalHandlerClass = Class.forName("sun.misc.SignalHandler"); +- return signalClass.getMethod("handle", signalClass, signalHandlerClass) +- .invoke(null, signal, handler); ++ return signalClass.getMethod("handle", signalClass, signalHandlerClass).invoke(null, signal, handler); + } + + @SuppressWarnings("") +@@ -120,5 +118,4 @@ public final class Signals { + } + return handler != null ? handler.toString() : "null"; + } +- + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Status.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Status.java +index e8d9e49e8..7348b1ea1 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Status.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Status.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2019, the original author or authors. ++ * Copyright (c) 2002-2019, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -8,187 +8,266 @@ + */ + package jdk.internal.org.jline.utils; + +-import java.util.Objects; +-import java.util.Collections; + import java.util.ArrayList; ++import java.util.Collections; + import java.util.List; ++import java.util.Objects; ++import java.util.Optional; ++ ++import jdk.internal.org.jline.terminal.Size; + import jdk.internal.org.jline.terminal.Terminal; + import jdk.internal.org.jline.terminal.impl.AbstractTerminal; + import jdk.internal.org.jline.utils.InfoCmp.Capability; +-import jdk.internal.org.jline.terminal.Size; + + public class Status { + +- protected final AbstractTerminal terminal; ++ protected final Terminal terminal; + protected final boolean supported; +- protected List oldLines = Collections.emptyList(); +- protected List linesToRestore = Collections.emptyList(); +- protected int rows; +- protected int columns; +- protected boolean force; + protected boolean suspended = false; + protected AttributedString borderString; + protected int border = 0; ++ protected Display display; ++ protected List lines = Collections.emptyList(); ++ protected int scrollRegion; + + public static Status getStatus(Terminal terminal) { + return getStatus(terminal, true); + } + +- public static Status getStatus(Terminal terminal, boolean create) { +- return terminal instanceof AbstractTerminal +- ? ((AbstractTerminal) terminal).getStatus(create) +- : null; ++ public static Optional getExistingStatus(Terminal terminal) { ++ return Optional.ofNullable(getStatus(terminal, false)); + } + ++ public static Status getStatus(Terminal terminal, boolean create) { ++ return terminal instanceof AbstractTerminal ? ((AbstractTerminal) terminal).getStatus(create) : null; ++ } + +- public Status(AbstractTerminal terminal) { ++ @SuppressWarnings("this-escape") ++ public Status(Terminal terminal) { + this.terminal = Objects.requireNonNull(terminal, "terminal can not be null"); + this.supported = terminal.getStringCapability(Capability.change_scroll_region) != null +- && terminal.getStringCapability(Capability.save_cursor) != null +- && terminal.getStringCapability(Capability.restore_cursor) != null +- && terminal.getStringCapability(Capability.cursor_address) != null; ++ && terminal.getStringCapability(Capability.save_cursor) != null ++ && terminal.getStringCapability(Capability.restore_cursor) != null ++ && terminal.getStringCapability(Capability.cursor_address) != null; + if (supported) { +- char borderChar = '\u2700'; +- AttributedStringBuilder bb = new AttributedStringBuilder(); +- for (int i = 0; i < 200; i++) { +- bb.append(borderChar); +- } +- borderString = bb.toAttributedString(); ++ display = new MovingCursorDisplay(terminal); + resize(); ++ display.reset(); ++ scrollRegion = display.rows - 1; + } + } + ++ public void close() { ++ terminal.puts(Capability.save_cursor); ++ terminal.puts(Capability.change_scroll_region, 0, display.rows - 1); ++ terminal.puts(Capability.restore_cursor); ++ terminal.flush(); ++ } + -+ // Were not able to find a plausible SP to go with this PC. -+ // Bail out. -+ return false; + public void setBorder(boolean border) { + this.border = border ? 1 : 0; + } + + public void resize() { +- Size size = terminal.getSize(); +- this.rows = size.getRows(); +- this.columns = size.getColumns(); +- this.force = true; ++ resize(terminal.getSize()); + } + +- public void reset() { +- this.force = true; ++ public void resize(Size size) { ++ display.resize(size.getRows(), size.getColumns()); + } + +- public void hardReset() { +- if (suspended) { +- return; ++ public void reset() { ++ if (supported) { ++ display.reset(); ++ scrollRegion = display.rows; ++ terminal.puts(Capability.change_scroll_region, 0, scrollRegion); + } +- List lines = new ArrayList<>(oldLines); +- int b = border; +- update(null); +- border = b; +- update(lines); + } + + public void redraw() { + if (suspended) { + return; + } +- update(oldLines); ++ update(lines); + } + +- public void clear() { +- privateClear(oldLines.size()); ++ public void hide() { ++ update(Collections.emptyList()); + } + +- private void clearAll() { +- int b = border; +- border = 0; +- privateClear(oldLines.size() + b); ++ public void update(List lines) { ++ update(lines, true); + } + +- private void privateClear(int statusSize) { +- List as = new ArrayList<>(); +- for (int i = 0; i < statusSize; i++) { +- as.add(new AttributedString("")); +- } +- if (!as.isEmpty()) { +- update(as); +- } +- } ++ private final AttributedString ellipsis = ++ new AttributedStringBuilder().append("\u2026", AttributedStyle.INVERSE).toAttributedString(); + +- public void update(List lines) { ++ /** ++ * Returns true if the cursor may be misplaced and should ++ * be updated. ++ */ ++ public void update(List lines, boolean flush) { + if (!supported) { + return; + } +- if (lines == null) { +- lines = Collections.emptyList(); +- } ++ this.lines = new ArrayList<>(lines); + if (suspended) { +- linesToRestore = new ArrayList<>(lines); + return; + } +- if (lines.isEmpty()) { +- clearAll(); ++ ++ lines = new ArrayList<>(lines); ++ // add border ++ int rows = display.rows; ++ int columns = display.columns; ++ if (border == 1 && !lines.isEmpty() && rows > 1) { ++ lines.add(0, getBorderString(columns)); + } +- if (oldLines.equals(lines) && !force) { +- return; ++ // trim or complete lines to the full width ++ for (int i = 0; i < lines.size(); i++) { ++ AttributedString str = lines.get(i); ++ if (str.columnLength() > columns) { ++ str = new AttributedStringBuilder(columns) ++ .append(lines.get(i).columnSubSequence(0, columns - ellipsis.columnLength())) ++ .append(ellipsis) ++ .toAttributedString(); ++ } else if (str.columnLength() < columns) { ++ str = new AttributedStringBuilder(columns) ++ .append(str) ++ .append(' ', columns - str.columnLength()) ++ .toAttributedString(); ++ } ++ lines.set(i, str); + } +- int statusSize = lines.size() + (lines.size() == 0 ? 0 : border); +- int nb = statusSize - oldLines.size() - (oldLines.size() == 0 ? 0 : border); +- if (nb > 0) { +- for (int i = 0; i < nb; i++) { ++ ++ List oldLines = this.display.oldLines; ++ ++ int newScrollRegion = display.rows - 1 - lines.size(); ++ // Update the scroll region if needed. ++ // Note that settings the scroll region usually moves the cursor, so we need to get ready for that. ++ if (newScrollRegion < scrollRegion) { ++ // We need to scroll up to grow the status bar ++ terminal.puts(Capability.save_cursor); ++ for (int i = newScrollRegion; i < scrollRegion; i++) { + terminal.puts(Capability.cursor_down); + } +- for (int i = 0; i < nb; i++) { ++ terminal.puts(Capability.change_scroll_region, 0, newScrollRegion); ++ terminal.puts(Capability.restore_cursor); ++ for (int i = newScrollRegion; i < scrollRegion; i++) { + terminal.puts(Capability.cursor_up); + } ++ scrollRegion = newScrollRegion; ++ } else if (newScrollRegion > scrollRegion) { ++ terminal.puts(Capability.save_cursor); ++ terminal.puts(Capability.change_scroll_region, 0, newScrollRegion); ++ terminal.puts(Capability.restore_cursor); ++ scrollRegion = newScrollRegion; + } +- terminal.puts(Capability.save_cursor); +- terminal.puts(Capability.cursor_address, rows - statusSize, 0); +- if (!terminal.puts(Capability.clr_eos)) { +- for (int i = rows - statusSize; i < rows; i++) { +- terminal.puts(Capability.cursor_address, i, 0); ++ ++ // if the display has more lines, we need to add empty ones to make sure they will be erased ++ List toDraw = new ArrayList<>(lines); ++ int nbToDraw = toDraw.size(); ++ int nbOldLines = oldLines.size(); ++ if (nbOldLines > nbToDraw) { ++ terminal.puts(Capability.save_cursor); ++ terminal.puts(Capability.cursor_address, display.rows - nbOldLines, 0); ++ for (int i = 0; i < nbOldLines - nbToDraw; i++) { + terminal.puts(Capability.clr_eol); ++ if (i < nbOldLines - nbToDraw - 1) { ++ terminal.puts(Capability.cursor_down); ++ } ++ oldLines.remove(0); + } ++ terminal.puts(Capability.restore_cursor); + } +- if (border == 1 && lines.size() > 0) { +- terminal.puts(Capability.cursor_address, rows - statusSize, 0); +- borderString.columnSubSequence(0, columns).print(terminal); +- } +- for (int i = 0; i < lines.size(); i++) { +- terminal.puts(Capability.cursor_address, rows - lines.size() + i, 0); +- if (lines.get(i).length() > columns) { +- AttributedStringBuilder asb = new AttributedStringBuilder(); +- asb.append(lines.get(i).substring(0, columns - 3)).append("...", new AttributedStyle(AttributedStyle.INVERSE)); +- asb.toAttributedString().columnSubSequence(0, columns).print(terminal); +- } else { +- lines.get(i).columnSubSequence(0, columns).print(terminal); ++ // update display ++ display.update(lines, -1, flush); ++ } ++ ++ private AttributedString getBorderString(int columns) { ++ if (borderString == null || borderString.length() != columns) { ++ char borderChar = '\u2700'; ++ AttributedStringBuilder bb = new AttributedStringBuilder(); ++ for (int i = 0; i < columns; i++) { ++ bb.append(borderChar); + } ++ borderString = bb.toAttributedString(); + } +- terminal.puts(Capability.change_scroll_region, 0, rows - 1 - statusSize); +- terminal.puts(Capability.restore_cursor); +- terminal.flush(); +- oldLines = new ArrayList<>(lines); +- force = false; ++ return borderString; + } + ++ /** ++ * The {@code suspend} method is used when a full-screen. ++ * If the status was not already suspended, the lines ++ * used by the status are cleared during this call. ++ */ + public void suspend() { +- if (suspended) { +- return; ++ if (!suspended) { ++ suspended = true; + } +- linesToRestore = new ArrayList<>(oldLines); +- int b = border; +- update(null); +- border = b; +- suspended = true; + } + ++ /** ++ * The {@code restore()} call is the opposite of {@code suspend()} and ++ * will make the status bar be updated again. ++ * If the status was suspended, the lines ++ * used by the status will be drawn during this call. ++ */ + public void restore() { +- if (!suspended) { +- return; ++ if (suspended) { ++ suspended = false; ++ update(this.lines); + } +- suspended = false; +- update(linesToRestore); +- linesToRestore = Collections.emptyList(); + } + + public int size() { +- return oldLines.size() + border; ++ return size(this.lines); ++ } + -+ /* -+ // Original algorithm which does not work because SP was -+ // pointing beyond where it should have: ++ private int size(List lines) { ++ int l = lines.size(); ++ return l > 0 ? l + border : 0; ++ } + -+ // For the server compiler, EBP is not guaranteed to be valid -+ // for compiled code. We see whether the PC is in the -+ // interpreter and take care of that, otherwise we run code -+ // (unfortunately) duplicated from LOONGARCH64Frame.senderForCompiledFrame. ++ @Override ++ public String toString() { ++ return "Status[" + "supported=" + supported + ']'; + } + ++ static class MovingCursorDisplay extends Display { ++ protected int firstLine; + -+ CodeCache cc = vm.getCodeCache(); -+ if (cc.contains(pc)) { -+ CodeBlob cb = cc.findBlob(pc); ++ public MovingCursorDisplay(Terminal terminal) { ++ super(terminal, false); ++ } + -+ // See if we can derive a frame pointer from SP and PC -+ // NOTE: This is the code duplicated from LOONGARCH64Frame -+ Address saved_fp = null; -+ int llink_offset = cb.getLinkOffset(); -+ if (llink_offset >= 0) { -+ // Restore base-pointer, since next frame might be an interpreter frame. -+ Address fp_addr = sp.addOffsetTo(VM.getVM().getAddressSize() * llink_offset); -+ saved_fp = fp_addr.getAddressAt(0); -+ } ++ @Override ++ public void update(List newLines, int targetCursorPos, boolean flush) { ++ cursorPos = -1; ++ firstLine = rows - newLines.size(); ++ super.update(newLines, targetCursorPos, flush); ++ if (cursorPos != -1) { ++ terminal.puts(Capability.restore_cursor); ++ } ++ } + -+ setValues(sp, saved_fp, pc); -+ return true; ++ @Override ++ protected void moveVisualCursorTo(int targetPos, List newLines) { ++ initCursor(); ++ super.moveVisualCursorTo(targetPos, newLines); + } -+ */ -+ } -+ } else { -+ // If the current program counter was not known to us as a Java -+ // PC, we currently assume that we are in the run-time system -+ // and attempt to look to thread-local storage for saved ESP and -+ // EBP. Note that if these are null (because we were, in fact, -+ // in Java code, i.e., vtable stubs or similar, and the SA -+ // didn't have enough insight into the target VM to understand -+ // that) then we are going to lose the entire stack trace for -+ // the thread, which is sub-optimal. FIXME. + -+ if (DEBUG) { -+ System.out.println("CurrentFrameGuess: choosing last Java frame: sp = " + -+ thread.getLastJavaSP() + ", fp = " + thread.getLastJavaFP()); -+ } -+ if (thread.getLastJavaSP() == null) { -+ return false; // No known Java frames on stack -+ } ++ @Override ++ protected int moveVisualCursorTo(int i1) { ++ initCursor(); ++ return super.moveVisualCursorTo(i1); ++ } + -+ // The runtime has a nasty habit of not saving fp in the frame -+ // anchor, leaving us to grovel about in the stack to find a -+ // plausible address. Fortunately, this only happens in -+ // compiled code; there we always have a valid PC, and we always -+ // push LR and FP onto the stack as a pair, with FP at the lower -+ // address. -+ pc = thread.getLastJavaPC(); -+ fp = thread.getLastJavaFP(); -+ sp = thread.getLastJavaSP(); ++ void initCursor() { ++ if (cursorPos == -1) { ++ terminal.puts(Capability.save_cursor); ++ terminal.puts(Capability.cursor_address, firstLine, 0); ++ cursorPos = 0; ++ } ++ } ++ } + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/StyleResolver.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/StyleResolver.java +index be1659957..29d87cbc3 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/StyleResolver.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/StyleResolver.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2018, the original author or authors. ++ * Copyright (c) 2002-2018, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -55,12 +55,12 @@ public class StyleResolver { + return null; + } + } else { +- // load indexed color +- Integer color = color(name); +- if (color != null && color != -1) { +- color = Colors.DEFAULT_COLORS_256[color]; +- } +- return color; ++ // load indexed color ++ Integer color = color(name); ++ if (color != null && color != -1) { ++ color = Colors.DEFAULT_COLORS_256[color]; ++ } ++ return color; + } + } + +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Timeout.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Timeout.java +index edea89cf2..1e3091e19 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Timeout.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Timeout.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2018, the original author or authors. ++ * Copyright (c) 2002-2018, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -44,5 +44,4 @@ public class Timeout { + public long timeout() { + return timeout > 0 ? Math.max(1, end - cur) : timeout; + } +- + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/WCWidth.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/WCWidth.java +index db3a8d3d9..7b0caf91c 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/WCWidth.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/WCWidth.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2016, the original author or authors. ++ * Copyright (c) 2002-2016, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -10,8 +10,7 @@ package jdk.internal.org.jline.utils; + + public final class WCWidth { + +- private WCWidth() { +- } ++ private WCWidth() {} + + /* The following two functions define the column width of an ISO 10646 + * character as follows: +@@ -44,88 +43,86 @@ public final class WCWidth { + * This implementation assumes that wchar_t characters are encoded + * in ISO 10646. + */ +- public static int wcwidth(int ucs) +- { ++ public static int wcwidth(int ucs) { + + /* test for 8-bit control characters */ +- if (ucs == 0) +- return 0; +- if (ucs < 32 || (ucs >= 0x7f && ucs < 0xa0)) +- return -1; ++ if (ucs == 0) return 0; ++ if (ucs < 32 || (ucs >= 0x7f && ucs < 0xa0)) return -1; + + /* binary search in table of non-spacing characters */ +- if (bisearch(ucs, combining, combining.length - 1)) +- return 0; ++ if (bisearch(ucs, combining, combining.length - 1)) return 0; + + /* if we arrive here, ucs is not a combining or C0/C1 control character */ +- return 1 + +- ((ucs >= 0x1100 && +- (ucs <= 0x115f || /* Hangul Jamo init. consonants */ +- ucs == 0x2329 || ucs == 0x232a || +- (ucs >= 0x2e80 && ucs <= 0xa4cf && +- ucs != 0x303f) || /* CJK ... Yi */ +- (ucs >= 0xac00 && ucs <= 0xd7a3) || /* Hangul Syllables */ +- (ucs >= 0xf900 && ucs <= 0xfaff) || /* CJK Compatibility Ideographs */ +- (ucs >= 0xfe10 && ucs <= 0xfe19) || /* Vertical forms */ +- (ucs >= 0xfe30 && ucs <= 0xfe6f) || /* CJK Compatibility Forms */ +- (ucs >= 0xff00 && ucs <= 0xff60) || /* Fullwidth Forms */ +- (ucs >= 0xffe0 && ucs <= 0xffe6) || +- (ucs >= 0x1f000 && ucs <= 0x1feee) || +- (ucs >= 0x20000 && ucs <= 0x2fffd) || +- (ucs >= 0x30000 && ucs <= 0x3fffd))) ? 1 : 0); ++ return 1 ++ + ((ucs >= 0x1100 ++ && (ucs <= 0x115f ++ || /* Hangul Jamo init. consonants */ ucs == 0x2329 ++ || ucs == 0x232a ++ || (ucs >= 0x2e80 && ucs <= 0xa4cf && ucs != 0x303f) ++ || /* CJK ... Yi */ (ucs >= 0xac00 && ucs <= 0xd7a3) ++ || /* Hangul Syllables */ (ucs >= 0xf900 && ucs <= 0xfaff) ++ || /* CJK Compatibility Ideographs */ (ucs >= 0xfe10 && ucs <= 0xfe19) ++ || /* Vertical forms */ (ucs >= 0xfe30 && ucs <= 0xfe6f) ++ || /* CJK Compatibility Forms */ (ucs >= 0xff00 && ucs <= 0xff60) ++ || /* Fullwidth Forms */ (ucs >= 0xffe0 && ucs <= 0xffe6) ++ || (ucs >= 0x1f000 && ucs <= 0x1feee) ++ || (ucs >= 0x20000 && ucs <= 0x2fffd) ++ || (ucs >= 0x30000 && ucs <= 0x3fffd))) ++ ? 1 ++ : 0); + } + + /* sorted list of non-overlapping intervals of non-spacing characters */ + /* generated by "uniset +cat=Me +cat=Mn +cat=Cf -00AD +1160-11FF +200B c" */ + static Interval[] combining = { +- new Interval( 0x0300, 0x036F ), new Interval( 0x0483, 0x0486 ), new Interval( 0x0488, 0x0489 ), +- new Interval( 0x0591, 0x05BD ), new Interval( 0x05BF, 0x05BF ), new Interval( 0x05C1, 0x05C2 ), +- new Interval( 0x05C4, 0x05C5 ), new Interval( 0x05C7, 0x05C7 ), new Interval( 0x0600, 0x0603 ), +- new Interval( 0x0610, 0x0615 ), new Interval( 0x064B, 0x065E ), new Interval( 0x0670, 0x0670 ), +- new Interval( 0x06D6, 0x06E4 ), new Interval( 0x06E7, 0x06E8 ), new Interval( 0x06EA, 0x06ED ), +- new Interval( 0x070F, 0x070F ), new Interval( 0x0711, 0x0711 ), new Interval( 0x0730, 0x074A ), +- new Interval( 0x07A6, 0x07B0 ), new Interval( 0x07EB, 0x07F3 ), new Interval( 0x0901, 0x0902 ), +- new Interval( 0x093C, 0x093C ), new Interval( 0x0941, 0x0948 ), new Interval( 0x094D, 0x094D ), +- new Interval( 0x0951, 0x0954 ), new Interval( 0x0962, 0x0963 ), new Interval( 0x0981, 0x0981 ), +- new Interval( 0x09BC, 0x09BC ), new Interval( 0x09C1, 0x09C4 ), new Interval( 0x09CD, 0x09CD ), +- new Interval( 0x09E2, 0x09E3 ), new Interval( 0x0A01, 0x0A02 ), new Interval( 0x0A3C, 0x0A3C ), +- new Interval( 0x0A41, 0x0A42 ), new Interval( 0x0A47, 0x0A48 ), new Interval( 0x0A4B, 0x0A4D ), +- new Interval( 0x0A70, 0x0A71 ), new Interval( 0x0A81, 0x0A82 ), new Interval( 0x0ABC, 0x0ABC ), +- new Interval( 0x0AC1, 0x0AC5 ), new Interval( 0x0AC7, 0x0AC8 ), new Interval( 0x0ACD, 0x0ACD ), +- new Interval( 0x0AE2, 0x0AE3 ), new Interval( 0x0B01, 0x0B01 ), new Interval( 0x0B3C, 0x0B3C ), +- new Interval( 0x0B3F, 0x0B3F ), new Interval( 0x0B41, 0x0B43 ), new Interval( 0x0B4D, 0x0B4D ), +- new Interval( 0x0B56, 0x0B56 ), new Interval( 0x0B82, 0x0B82 ), new Interval( 0x0BC0, 0x0BC0 ), +- new Interval( 0x0BCD, 0x0BCD ), new Interval( 0x0C3E, 0x0C40 ), new Interval( 0x0C46, 0x0C48 ), +- new Interval( 0x0C4A, 0x0C4D ), new Interval( 0x0C55, 0x0C56 ), new Interval( 0x0CBC, 0x0CBC ), +- new Interval( 0x0CBF, 0x0CBF ), new Interval( 0x0CC6, 0x0CC6 ), new Interval( 0x0CCC, 0x0CCD ), +- new Interval( 0x0CE2, 0x0CE3 ), new Interval( 0x0D41, 0x0D43 ), new Interval( 0x0D4D, 0x0D4D ), +- new Interval( 0x0DCA, 0x0DCA ), new Interval( 0x0DD2, 0x0DD4 ), new Interval( 0x0DD6, 0x0DD6 ), +- new Interval( 0x0E31, 0x0E31 ), new Interval( 0x0E34, 0x0E3A ), new Interval( 0x0E47, 0x0E4E ), +- new Interval( 0x0EB1, 0x0EB1 ), new Interval( 0x0EB4, 0x0EB9 ), new Interval( 0x0EBB, 0x0EBC ), +- new Interval( 0x0EC8, 0x0ECD ), new Interval( 0x0F18, 0x0F19 ), new Interval( 0x0F35, 0x0F35 ), +- new Interval( 0x0F37, 0x0F37 ), new Interval( 0x0F39, 0x0F39 ), new Interval( 0x0F71, 0x0F7E ), +- new Interval( 0x0F80, 0x0F84 ), new Interval( 0x0F86, 0x0F87 ), new Interval( 0x0F90, 0x0F97 ), +- new Interval( 0x0F99, 0x0FBC ), new Interval( 0x0FC6, 0x0FC6 ), new Interval( 0x102D, 0x1030 ), +- new Interval( 0x1032, 0x1032 ), new Interval( 0x1036, 0x1037 ), new Interval( 0x1039, 0x1039 ), +- new Interval( 0x1058, 0x1059 ), new Interval( 0x1160, 0x11FF ), new Interval( 0x135F, 0x135F ), +- new Interval( 0x1712, 0x1714 ), new Interval( 0x1732, 0x1734 ), new Interval( 0x1752, 0x1753 ), +- new Interval( 0x1772, 0x1773 ), new Interval( 0x17B4, 0x17B5 ), new Interval( 0x17B7, 0x17BD ), +- new Interval( 0x17C6, 0x17C6 ), new Interval( 0x17C9, 0x17D3 ), new Interval( 0x17DD, 0x17DD ), +- new Interval( 0x180B, 0x180D ), new Interval( 0x18A9, 0x18A9 ), new Interval( 0x1920, 0x1922 ), +- new Interval( 0x1927, 0x1928 ), new Interval( 0x1932, 0x1932 ), new Interval( 0x1939, 0x193B ), +- new Interval( 0x1A17, 0x1A18 ), new Interval( 0x1B00, 0x1B03 ), new Interval( 0x1B34, 0x1B34 ), +- new Interval( 0x1B36, 0x1B3A ), new Interval( 0x1B3C, 0x1B3C ), new Interval( 0x1B42, 0x1B42 ), +- new Interval( 0x1B6B, 0x1B73 ), new Interval( 0x1DC0, 0x1DCA ), new Interval( 0x1DFE, 0x1DFF ), +- new Interval( 0x200B, 0x200F ), new Interval( 0x202A, 0x202E ), new Interval( 0x2060, 0x2063 ), +- new Interval( 0x206A, 0x206F ), new Interval( 0x20D0, 0x20EF ), new Interval( 0x302A, 0x302F ), +- new Interval( 0x3099, 0x309A ), new Interval( 0xA806, 0xA806 ), new Interval( 0xA80B, 0xA80B ), +- new Interval( 0xA825, 0xA826 ), new Interval( 0xFB1E, 0xFB1E ), new Interval( 0xFE00, 0xFE0F ), +- new Interval( 0xFE20, 0xFE23 ), new Interval( 0xFEFF, 0xFEFF ), new Interval( 0xFFF9, 0xFFFB ), +- new Interval( 0x10A01, 0x10A03 ), new Interval( 0x10A05, 0x10A06 ), new Interval( 0x10A0C, 0x10A0F ), +- new Interval( 0x10A38, 0x10A3A ), new Interval( 0x10A3F, 0x10A3F ), new Interval( 0x1D167, 0x1D169 ), +- new Interval( 0x1D173, 0x1D182 ), new Interval( 0x1D185, 0x1D18B ), new Interval( 0x1D1AA, 0x1D1AD ), +- new Interval( 0x1D242, 0x1D244 ), new Interval( 0x1F3FB, 0x1F3FF ), new Interval( 0xE0001, 0xE0001 ), +- new Interval( 0xE0020, 0xE007F ), new Interval( 0xE0100, 0xE01EF ) ++ new Interval(0x0300, 0x036F), new Interval(0x0483, 0x0486), new Interval(0x0488, 0x0489), ++ new Interval(0x0591, 0x05BD), new Interval(0x05BF, 0x05BF), new Interval(0x05C1, 0x05C2), ++ new Interval(0x05C4, 0x05C5), new Interval(0x05C7, 0x05C7), new Interval(0x0600, 0x0603), ++ new Interval(0x0610, 0x0615), new Interval(0x064B, 0x065E), new Interval(0x0670, 0x0670), ++ new Interval(0x06D6, 0x06E4), new Interval(0x06E7, 0x06E8), new Interval(0x06EA, 0x06ED), ++ new Interval(0x070F, 0x070F), new Interval(0x0711, 0x0711), new Interval(0x0730, 0x074A), ++ new Interval(0x07A6, 0x07B0), new Interval(0x07EB, 0x07F3), new Interval(0x0901, 0x0902), ++ new Interval(0x093C, 0x093C), new Interval(0x0941, 0x0948), new Interval(0x094D, 0x094D), ++ new Interval(0x0951, 0x0954), new Interval(0x0962, 0x0963), new Interval(0x0981, 0x0981), ++ new Interval(0x09BC, 0x09BC), new Interval(0x09C1, 0x09C4), new Interval(0x09CD, 0x09CD), ++ new Interval(0x09E2, 0x09E3), new Interval(0x0A01, 0x0A02), new Interval(0x0A3C, 0x0A3C), ++ new Interval(0x0A41, 0x0A42), new Interval(0x0A47, 0x0A48), new Interval(0x0A4B, 0x0A4D), ++ new Interval(0x0A70, 0x0A71), new Interval(0x0A81, 0x0A82), new Interval(0x0ABC, 0x0ABC), ++ new Interval(0x0AC1, 0x0AC5), new Interval(0x0AC7, 0x0AC8), new Interval(0x0ACD, 0x0ACD), ++ new Interval(0x0AE2, 0x0AE3), new Interval(0x0B01, 0x0B01), new Interval(0x0B3C, 0x0B3C), ++ new Interval(0x0B3F, 0x0B3F), new Interval(0x0B41, 0x0B43), new Interval(0x0B4D, 0x0B4D), ++ new Interval(0x0B56, 0x0B56), new Interval(0x0B82, 0x0B82), new Interval(0x0BC0, 0x0BC0), ++ new Interval(0x0BCD, 0x0BCD), new Interval(0x0C3E, 0x0C40), new Interval(0x0C46, 0x0C48), ++ new Interval(0x0C4A, 0x0C4D), new Interval(0x0C55, 0x0C56), new Interval(0x0CBC, 0x0CBC), ++ new Interval(0x0CBF, 0x0CBF), new Interval(0x0CC6, 0x0CC6), new Interval(0x0CCC, 0x0CCD), ++ new Interval(0x0CE2, 0x0CE3), new Interval(0x0D41, 0x0D43), new Interval(0x0D4D, 0x0D4D), ++ new Interval(0x0DCA, 0x0DCA), new Interval(0x0DD2, 0x0DD4), new Interval(0x0DD6, 0x0DD6), ++ new Interval(0x0E31, 0x0E31), new Interval(0x0E34, 0x0E3A), new Interval(0x0E47, 0x0E4E), ++ new Interval(0x0EB1, 0x0EB1), new Interval(0x0EB4, 0x0EB9), new Interval(0x0EBB, 0x0EBC), ++ new Interval(0x0EC8, 0x0ECD), new Interval(0x0F18, 0x0F19), new Interval(0x0F35, 0x0F35), ++ new Interval(0x0F37, 0x0F37), new Interval(0x0F39, 0x0F39), new Interval(0x0F71, 0x0F7E), ++ new Interval(0x0F80, 0x0F84), new Interval(0x0F86, 0x0F87), new Interval(0x0F90, 0x0F97), ++ new Interval(0x0F99, 0x0FBC), new Interval(0x0FC6, 0x0FC6), new Interval(0x102D, 0x1030), ++ new Interval(0x1032, 0x1032), new Interval(0x1036, 0x1037), new Interval(0x1039, 0x1039), ++ new Interval(0x1058, 0x1059), new Interval(0x1160, 0x11FF), new Interval(0x135F, 0x135F), ++ new Interval(0x1712, 0x1714), new Interval(0x1732, 0x1734), new Interval(0x1752, 0x1753), ++ new Interval(0x1772, 0x1773), new Interval(0x17B4, 0x17B5), new Interval(0x17B7, 0x17BD), ++ new Interval(0x17C6, 0x17C6), new Interval(0x17C9, 0x17D3), new Interval(0x17DD, 0x17DD), ++ new Interval(0x180B, 0x180D), new Interval(0x18A9, 0x18A9), new Interval(0x1920, 0x1922), ++ new Interval(0x1927, 0x1928), new Interval(0x1932, 0x1932), new Interval(0x1939, 0x193B), ++ new Interval(0x1A17, 0x1A18), new Interval(0x1B00, 0x1B03), new Interval(0x1B34, 0x1B34), ++ new Interval(0x1B36, 0x1B3A), new Interval(0x1B3C, 0x1B3C), new Interval(0x1B42, 0x1B42), ++ new Interval(0x1B6B, 0x1B73), new Interval(0x1DC0, 0x1DCA), new Interval(0x1DFE, 0x1DFF), ++ new Interval(0x200B, 0x200F), new Interval(0x202A, 0x202E), new Interval(0x2060, 0x2063), ++ new Interval(0x206A, 0x206F), new Interval(0x20D0, 0x20EF), new Interval(0x302A, 0x302F), ++ new Interval(0x3099, 0x309A), new Interval(0xA806, 0xA806), new Interval(0xA80B, 0xA80B), ++ new Interval(0xA825, 0xA826), new Interval(0xFB1E, 0xFB1E), new Interval(0xFE00, 0xFE0F), ++ new Interval(0xFE20, 0xFE23), new Interval(0xFEFF, 0xFEFF), new Interval(0xFFF9, 0xFFFB), ++ new Interval(0x10A01, 0x10A03), new Interval(0x10A05, 0x10A06), new Interval(0x10A0C, 0x10A0F), ++ new Interval(0x10A38, 0x10A3A), new Interval(0x10A3F, 0x10A3F), new Interval(0x1D167, 0x1D169), ++ new Interval(0x1D173, 0x1D182), new Interval(0x1D185, 0x1D18B), new Interval(0x1D1AA, 0x1D1AD), ++ new Interval(0x1D242, 0x1D244), new Interval(0x1F3FB, 0x1F3FF), new Interval(0xE0001, 0xE0001), ++ new Interval(0xE0020, 0xE007F), new Interval(0xE0100, 0xE01EF) + }; + + private static class Interval { +@@ -143,20 +140,14 @@ public final class WCWidth { + int min = 0; + int mid; + +- if (ucs < table[0].first || ucs > table[max].last) +- return false; ++ if (ucs < table[0].first || ucs > table[max].last) return false; + while (max >= min) { + mid = (min + max) / 2; +- if (ucs > table[mid].last) +- min = mid + 1; +- else if (ucs < table[mid].first) +- max = mid - 1; +- else +- return true; ++ if (ucs > table[mid].last) min = mid + 1; ++ else if (ucs < table[mid].first) max = mid - 1; ++ else return true; + } + + return false; + } +- +- + } +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/WriterOutputStream.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/WriterOutputStream.java +index 3ad63a8f3..b1285f963 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/WriterOutputStream.java ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/WriterOutputStream.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2002-2017, the original author or authors. ++ * Copyright (c) 2002-2017, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. +@@ -35,9 +35,11 @@ public class WriterOutputStream extends OutputStream { + private final CharBuffer decoderOut = CharBuffer.allocate(128); + + public WriterOutputStream(Writer out, Charset charset) { +- this(out, charset.newDecoder() +- .onMalformedInput(CodingErrorAction.REPLACE) +- .onUnmappableCharacter(CodingErrorAction.REPLACE)); ++ this( ++ out, ++ charset.newDecoder() ++ .onMalformedInput(CodingErrorAction.REPLACE) ++ .onUnmappableCharacter(CodingErrorAction.REPLACE)); + } + + public WriterOutputStream(Writer out, CharsetDecoder decoder) { +@@ -47,7 +49,7 @@ public class WriterOutputStream extends OutputStream { + + @Override + public void write(int b) throws IOException { +- write(new byte[] { (byte)b }, 0, 1); ++ write(new byte[] {(byte) b}, 0, 1); + } + + @Override +diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/windows-conemu.caps b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/windows-conemu.caps +index 719bcf862..f5caa4402 100644 +--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/windows-conemu.caps ++++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/windows-conemu.caps +@@ -5,6 +5,9 @@ windows-conemu|conemu windows terminal, + cr=^M, cub=\E[%p1%dD, cub1=\E[D, cud=\E[%p1%dB, cud1=\E[B, + cuf=\E[%p1%dC, cuf1=\E[C, cup=\E[%i%p1%d;%p2%dH, + cuu=\E[%p1%dA, cuu1=\E[A, ++ civis=\E[?25l, cvvis=\E[?25h, ++ smcup=\E[?1049h, rmcup=\E[?1049l, ++ rc=\E8, sc=\E7, + il=\E[%p1%dL, il1=\E[L, + dl=\E[%p1%dM, dl1=\E[M, + ech=\E[%p1%dX, +diff --git a/src/jdk.internal.le/share/legal/jline.md b/src/jdk.internal.le/share/legal/jline.md +index 6840c69cf..5b813c0af 100644 +--- a/src/jdk.internal.le/share/legal/jline.md ++++ b/src/jdk.internal.le/share/legal/jline.md +@@ -1,9 +1,9 @@ +-## JLine v3.22.0 ++## JLine v3.26.1 + + ### JLine License +
+ 
+-Copyright (c) 2002-2018, the original author or authors.
++Copyright (c) 2002-2023, the original author or authors.
+ All rights reserved.
+ 
+ https://opensource.org/licenses/BSD-3-Clause
+diff --git a/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/JnaTerminalProvider.java b/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/JnaTerminalProvider.java
+index b820ce218..4137643c7 100644
+--- a/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/JnaTerminalProvider.java
++++ b/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/JnaTerminalProvider.java
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2002-2020, the original author or authors.
++ * Copyright (c) 2002-2020, the original author(s).
+  *
+  * This software is distributable under the BSD license. See the terms of the
+  * BSD license in the documentation provided with this software.
+@@ -8,99 +8,146 @@
+  */
+ package jdk.internal.org.jline.terminal.impl.jna;
+ 
++import java.io.IOException;
++import java.io.InputStream;
++import java.io.OutputStream;
++import java.nio.charset.Charset;
++import java.util.function.Function;
++
+ import jdk.internal.org.jline.terminal.Attributes;
+ import jdk.internal.org.jline.terminal.Size;
+ import jdk.internal.org.jline.terminal.Terminal;
+-import jdk.internal.org.jline.terminal.impl.PosixPtyTerminal;
+-import jdk.internal.org.jline.terminal.impl.PosixSysTerminal;
++import jdk.internal.org.jline.terminal.TerminalBuilder;
++//import jdk.internal.org.jline.terminal.impl.PosixPtyTerminal;
++//import jdk.internal.org.jline.terminal.impl.PosixSysTerminal;
+ import jdk.internal.org.jline.terminal.impl.jna.win.JnaWinSysTerminal;
+-import jdk.internal.org.jline.terminal.spi.TerminalProvider;
+ import jdk.internal.org.jline.terminal.spi.Pty;
++import jdk.internal.org.jline.terminal.spi.SystemStream;
++import jdk.internal.org.jline.terminal.spi.TerminalProvider;
+ import jdk.internal.org.jline.utils.OSUtils;
+ 
+-import java.io.IOException;
+-import java.io.InputStream;
+-import java.io.OutputStream;
+-import java.nio.charset.Charset;
+-import java.util.function.Function;
++public class JnaTerminalProvider implements TerminalProvider {
 +
-+      if (fp == null) {
-+        CodeCache cc = vm.getCodeCache();
-+        if (cc.contains(pc)) {
-+          CodeBlob cb = cc.findBlob(pc);
-+          if (DEBUG) {
-+            System.out.println("FP is null.  Found blob frame size " + cb.getFrameSize());
-+          }
-+          // See if we can derive a frame pointer from SP and PC
-+          long link_offset = cb.getFrameSize() - 2 * VM.getVM().getAddressSize();
-+          if (link_offset >= 0) {
-+            fp = sp.addOffsetTo(link_offset);
-+          }
++    public JnaTerminalProvider() {
++        checkSystemStream(SystemStream.Output);
++    }
+ 
+-public class JnaTerminalProvider implements TerminalProvider
+-{
+     @Override
+     public String name() {
+-        return "jna";
++        return TerminalBuilder.PROP_PROVIDER_JNA;
+     }
+ 
+-//    public Pty current(TerminalProvider.Stream console) throws IOException {
+-//        return JnaNativePty.current(console);
++//    public Pty current(SystemStream systemStream) throws IOException {
++//        return JnaNativePty.current(this, systemStream);
+ //    }
+ //
+ //    public Pty open(Attributes attributes, Size size) throws IOException {
+-//        return JnaNativePty.open(attributes, size);
++//        return JnaNativePty.open(this, attributes, size);
+ //    }
+ 
+     @Override
+-    public Terminal sysTerminal(String name, String type, boolean ansiPassThrough, Charset encoding,
+-                                boolean nativeSignals, Terminal.SignalHandler signalHandler, boolean paused,
+-                                Stream consoleStream, Function inputStreamWrapper) throws IOException {
++    public Terminal sysTerminal(
++            String name,
++            String type,
++            boolean ansiPassThrough,
++            Charset encoding,
++            boolean nativeSignals,
++            Terminal.SignalHandler signalHandler,
++            boolean paused,
++            SystemStream systemStream,
++            Function inputStreamWrapper)
++            throws IOException {
+         if (OSUtils.IS_WINDOWS) {
+-            return winSysTerminal(name, type, ansiPassThrough, encoding, nativeSignals, signalHandler, paused, consoleStream, inputStreamWrapper );
++            return winSysTerminal(name, type, ansiPassThrough, encoding, nativeSignals, signalHandler, paused, systemStream, inputStreamWrapper );
+         } else {
+             return null;
+         }
+     }
+ 
+-    public Terminal winSysTerminal(String name, String type, boolean ansiPassThrough, Charset encoding,
+-                                   boolean nativeSignals, Terminal.SignalHandler signalHandler, boolean paused,
+-                                   Stream console, Function inputStreamWrapper) throws IOException {
+-        return JnaWinSysTerminal.createTerminal(name, type, ansiPassThrough, encoding, nativeSignals, signalHandler, paused, console, inputStreamWrapper);
++    public Terminal winSysTerminal(
++            String name,
++            String type,
++            boolean ansiPassThrough,
++            Charset encoding,
++            boolean nativeSignals,
++            Terminal.SignalHandler signalHandler,
++            boolean paused,
++            SystemStream systemStream,
++            Function inputStreamWrapper)
++            throws IOException {
++        return JnaWinSysTerminal.createTerminal(
++                this, systemStream, name, type, ansiPassThrough, encoding, nativeSignals, signalHandler, paused, inputStreamWrapper);
+     }
+ 
+-//    public Terminal posixSysTerminal(String name, String type, boolean ansiPassThrough, Charset encoding,
+-//                                     boolean nativeSignals, Terminal.SignalHandler signalHandler, boolean paused,
+-//                                     Stream consoleStream) throws IOException {
+-//        Pty pty = current(consoleStream);
++//    public Terminal posixSysTerminal(
++//            String name,
++//            String type,
++//            boolean ansiPassThrough,
++//            Charset encoding,
++//            boolean nativeSignals,
++//            Terminal.SignalHandler signalHandler,
++//            boolean paused,
++//            SystemStream systemStream)
++//            throws IOException {
++//        Pty pty = current(systemStream);
+ //        return new PosixSysTerminal(name, type, pty, encoding, nativeSignals, signalHandler);
+ //    }
+ 
+     @Override
+-    public Terminal newTerminal(String name, String type, InputStream in, OutputStream out,
+-                                Charset encoding, Terminal.SignalHandler signalHandler, boolean paused,
+-                                Attributes attributes, Size size) throws IOException
+-    {
++    public Terminal newTerminal(
++            String name,
++            String type,
++            InputStream in,
++            OutputStream out,
++            Charset encoding,
++            Terminal.SignalHandler signalHandler,
++            boolean paused,
++            Attributes attributes,
++            Size size)
++            throws IOException {
+ //        Pty pty = open(attributes, size);
+ //        return new PosixPtyTerminal(name, type, pty, in, out, encoding, signalHandler, paused);
+         return null;
+     }
+ 
+     @Override
+-    public boolean isSystemStream(Stream stream) {
++    public boolean isSystemStream(SystemStream stream) {
+         try {
+-            if (OSUtils.IS_WINDOWS) {
+-                return isWindowsSystemStream(stream);
+-            } else {
+-//                return isPosixSystemStream(stream);
+-                return false;
+-            }
++            return checkSystemStream(stream);
+         } catch (Throwable t) {
+             return false;
+         }
+     }
+ 
+-    public boolean isWindowsSystemStream(Stream stream) {
+-        return JnaWinSysTerminal.isWindowsSystemStream(stream);
++    private boolean checkSystemStream(SystemStream stream) {
++        if (OSUtils.IS_WINDOWS) {
++            return JnaWinSysTerminal.isWindowsSystemStream(stream);
++        } else {
++//            return JnaNativePty.isPosixSystemStream(stream);
++            return false;
 +        }
-+      }
+     }
+ 
+-//    public boolean isPosixSystemStream(Stream stream) {
+-//        return JnaNativePty.isPosixSystemStream(stream);
+-//    }
+-
+     @Override
+-    public String systemStreamName(Stream stream) {
++    public String systemStreamName(SystemStream stream) {
+ //        if (OSUtils.IS_WINDOWS) {
+             return null;
+ //        } else {
+ //            return JnaNativePty.posixSystemStreamName(stream);
+ //        }
+     }
 +
-+      // We found a PC in the frame anchor. Check that it's plausible, and
-+      // if it is, use it.
-+      if (vm.isJavaPCDbg(pc)) {
-+        setValues(sp, fp, pc);
-+      } else {
-+        setValues(sp, fp, null);
-+      }
++//    @Override
++//    public int systemStreamWidth(SystemStream stream) {
++//        try (Pty pty = current(stream)) {
++//            return pty.getSize().getColumns();
++//        } catch (Throwable t) {
++//            return -1;
++//        }
++//    }
 +
-+      return true;
++    @Override
++    public String toString() {
++        return "TerminalProvider[" + name() + "]";
 +    }
-+  }
+ }
+diff --git a/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/JnaWinConsoleWriter.java b/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/JnaWinConsoleWriter.java
+index a4469003c..8dad17d7c 100644
+--- a/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/JnaWinConsoleWriter.java
++++ b/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/JnaWinConsoleWriter.java
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2002-2017, the original author or authors.
++ * Copyright (c) 2002-2017, the original author(s).
+  *
+  * This software is distributable under the BSD license. See the terms of the
+  * BSD license in the documentation provided with this software.
+@@ -8,12 +8,13 @@
+  */
+ package jdk.internal.org.jline.terminal.impl.jna.win;
+ 
++import java.io.IOException;
 +
-+  public Address getSP() { return spFound; }
-+  public Address getFP() { return fpFound; }
-+  /** May be null if getting values from thread-local storage; take
-+      care to call the correct LOONGARCH64Frame constructor to recover this if
-+      necessary */
-+  public Address getPC() { return pcFound; }
++import jdk.internal.org.jline.terminal.impl.AbstractWindowsConsoleWriter;
 +
-+  private void setValues(Address sp, Address fp, Address pc) {
-+    spFound = sp;
-+    fpFound = fp;
-+    pcFound = pc;
-+  }
-+}
-diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/loongarch64/LOONGARCH64Frame.java jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/loongarch64/LOONGARCH64Frame.java
---- openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/loongarch64/LOONGARCH64Frame.java	1970-01-01 08:00:00.000000000 +0800
-+++ jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/loongarch64/LOONGARCH64Frame.java	2023-09-12 13:54:26.429575856 +0800
-@@ -0,0 +1,526 @@
+ //import com.sun.jna.LastErrorException;
+ //import com.sun.jna.Pointer;
+ //import com.sun.jna.ptr.IntByReference;
+-import jdk.internal.org.jline.terminal.impl.AbstractWindowsConsoleWriter;
+-
+-import java.io.IOException;
+ 
+ class JnaWinConsoleWriter extends AbstractWindowsConsoleWriter {
+ 
+@@ -32,5 +33,4 @@ class JnaWinConsoleWriter extends AbstractWindowsConsoleWriter {
+             throw new IOException("Failed to write to console", e);
+         }
+     }
+-
+ }
+diff --git a/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/JnaWinSysTerminal.java b/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/JnaWinSysTerminal.java
+index 5ffc5d714..8afa32712 100644
+--- a/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/JnaWinSysTerminal.java
++++ b/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/JnaWinSysTerminal.java
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2002-2020, the original author or authors.
++ * Copyright (c) 2002-2020, the original author(s).
+  *
+  * This software is distributable under the BSD license. See the terms of the
+  * BSD license in the documentation provided with this software.
+@@ -16,25 +16,43 @@ import java.nio.charset.Charset;
+ import java.util.function.Function;
+ import java.util.function.IntConsumer;
+ 
+-//import com.sun.jna.LastErrorException;
+-//import com.sun.jna.Pointer;
+-//import com.sun.jna.ptr.IntByReference;
+ import jdk.internal.org.jline.terminal.Cursor;
+ import jdk.internal.org.jline.terminal.Size;
+ import jdk.internal.org.jline.terminal.impl.AbstractWindowsTerminal;
++import jdk.internal.org.jline.terminal.spi.SystemStream;
+ import jdk.internal.org.jline.terminal.spi.TerminalProvider;
++import jdk.internal.org.jline.utils.InfoCmp.Capability;
+ import jdk.internal.org.jline.utils.InfoCmp;
+ import jdk.internal.org.jline.utils.OSUtils;
+ 
+-public class JnaWinSysTerminal extends AbstractWindowsTerminal {
++//import com.sun.jna.LastErrorException;
++//import com.sun.jna.Pointer;
++//import com.sun.jna.ptr.IntByReference;
++
++public class JnaWinSysTerminal extends AbstractWindowsTerminal {
+ 
+     private static final Pointer consoleIn = Kernel32.INSTANCE.GetStdHandle(Kernel32.STD_INPUT_HANDLE);
+     private static final Pointer consoleOut = Kernel32.INSTANCE.GetStdHandle(Kernel32.STD_OUTPUT_HANDLE);
+     private static final Pointer consoleErr = Kernel32.INSTANCE.GetStdHandle(Kernel32.STD_ERROR_HANDLE);
+ 
+-    public static JnaWinSysTerminal createTerminal(String name, String type, boolean ansiPassThrough, Charset encoding, boolean nativeSignals, SignalHandler signalHandler, boolean paused, TerminalProvider.Stream consoleStream, Function inputStreamWrapper) throws IOException {
++    public static JnaWinSysTerminal createTerminal(
++            TerminalProvider provider,
++            SystemStream systemStream,
++            String name,
++            String type,
++            boolean ansiPassThrough,
++            Charset encoding,
++            boolean nativeSignals,
++            SignalHandler signalHandler,
++            boolean paused,
++            Function inputStreamWrapper)
++            throws IOException {
++        // Get input console mode
++        IntByReference inMode = new IntByReference();
++        Kernel32.INSTANCE.GetConsoleMode(JnaWinSysTerminal.consoleIn, inMode);
++        // Get output console and mode
+         Pointer console;
+-        switch (consoleStream) {
++        switch (systemStream) {
+             case Output:
+                 console = JnaWinSysTerminal.consoleOut;
+                 break;
+@@ -42,38 +60,42 @@ public class JnaWinSysTerminal extends AbstractWindowsTerminal {
+                 console = JnaWinSysTerminal.consoleErr;
+                 break;
+             default:
+-                throw new IllegalArgumentException("Unsupport stream for console: " + consoleStream);
++                throw new IllegalArgumentException("Unsupported stream for console: " + systemStream);
+         }
++        IntByReference outMode = new IntByReference();
++        Kernel32.INSTANCE.GetConsoleMode(console, outMode);
++        // Create writer
+         Writer writer;
+         if (ansiPassThrough) {
+-            if (type == null) {
+-                type = OSUtils.IS_CONEMU ? TYPE_WINDOWS_CONEMU : TYPE_WINDOWS;
+-            }
++            type = type != null ? type : OSUtils.IS_CONEMU ? TYPE_WINDOWS_CONEMU : TYPE_WINDOWS;
+             writer = new JnaWinConsoleWriter(console);
+         } else {
+-            IntByReference mode = new IntByReference();
+-            Kernel32.INSTANCE.GetConsoleMode(console, mode);
+-            try {
+-                Kernel32.INSTANCE.SetConsoleMode(console, mode.getValue() | AbstractWindowsTerminal.ENABLE_VIRTUAL_TERMINAL_PROCESSING);
+-                if (type == null) {
+-                    type = TYPE_WINDOWS_VTP;
+-                }
++            if (enableVtp(console, outMode.getValue())) {
++                type = type != null ? type : TYPE_WINDOWS_VTP;
+                 writer = new JnaWinConsoleWriter(console);
+-            } catch (LastErrorException e) {
+-                if (OSUtils.IS_CONEMU) {
+-                    if (type == null) {
+-                        type = TYPE_WINDOWS_CONEMU;
+-                    }
+-                    writer = new JnaWinConsoleWriter(console);
+-                } else {
+-                    if (type == null) {
+-                        type = TYPE_WINDOWS;
+-                    }
+-                    writer = new WindowsAnsiWriter(new BufferedWriter(new JnaWinConsoleWriter(console)), console);
+-                }
++            } else if (OSUtils.IS_CONEMU) {
++                type = type != null ? type : TYPE_WINDOWS_CONEMU;
++                writer = new JnaWinConsoleWriter(console);
++            } else {
++                type = type != null ? type : TYPE_WINDOWS;
++                writer = new WindowsAnsiWriter(new BufferedWriter(new JnaWinConsoleWriter(console)), console);
+             }
+         }
+-        JnaWinSysTerminal terminal = new JnaWinSysTerminal(writer, name, type, encoding, nativeSignals, signalHandler, inputStreamWrapper);
++        // Create terminal
++        JnaWinSysTerminal terminal = new JnaWinSysTerminal(
++                provider,
++                systemStream,
++                writer,
++                name,
++                type,
++                encoding,
++                nativeSignals,
++                signalHandler,
++                JnaWinSysTerminal.consoleIn,
++                inMode.getValue(),
++                console,
++                outMode.getValue(),
++                inputStreamWrapper);
+         // Start input pump thread
+         if (!paused) {
+             terminal.resume();
+@@ -81,15 +103,32 @@ public class JnaWinSysTerminal extends AbstractWindowsTerminal {
+         return terminal;
+     }
+ 
+-    public static boolean isWindowsSystemStream(TerminalProvider.Stream stream) {
++    private static boolean enableVtp(Pointer console, int outMode) {
++        try {
++            Kernel32.INSTANCE.SetConsoleMode(
++                    console, outMode | AbstractWindowsTerminal.ENABLE_VIRTUAL_TERMINAL_PROCESSING);
++            return true;
++        } catch (LastErrorException e) {
++            return false;
++        }
++    }
++
++    public static boolean isWindowsSystemStream(SystemStream stream) {
+         try {
+             IntByReference mode = new IntByReference();
+             Pointer console;
+             switch (stream) {
+-                case Input: console = consoleIn; break;
+-                case Output: console = consoleOut; break;
+-                case Error: console = consoleErr; break;
+-                default: return false;
++                case Input:
++                    console = consoleIn;
++                    break;
++                case Output:
++                    console = consoleOut;
++                    break;
++                case Error:
++                    console = consoleErr;
++                    break;
++                default:
++                    return false;
+             }
+             Kernel32.INSTANCE.GetConsoleMode(console, mode);
+             return true;
+@@ -98,27 +137,53 @@ public class JnaWinSysTerminal extends AbstractWindowsTerminal {
+         }
+     }
+ 
+-    JnaWinSysTerminal(Writer writer, String name, String type, Charset encoding, boolean nativeSignals, SignalHandler signalHandler,
+-            Function inputStreamWrapper) throws IOException {
+-        super(writer, name, type, encoding, nativeSignals, signalHandler, inputStreamWrapper);
+-        strings.put(InfoCmp.Capability.key_mouse, "\\E[M");
++    JnaWinSysTerminal(
++            TerminalProvider provider,
++            SystemStream systemStream,
++            Writer writer,
++            String name,
++            String type,
++            Charset encoding,
++            boolean nativeSignals,
++            SignalHandler signalHandler,
++            Pointer inConsole,
++            int inConsoleMode,
++            Pointer outConsole,
++            int outConsoleMode,
++            Function inputStreamWrapper)
++            throws IOException {
++        super(
++                provider,
++                systemStream,
++                writer,
++                name,
++                type,
++                encoding,
++                nativeSignals,
++                signalHandler,
++                inConsole,
++                inConsoleMode,
++                outConsole,
++                outConsoleMode,
++                inputStreamWrapper);
++        this.strings.put(Capability.key_mouse, "\\E[M");
+     }
+ 
+     @Override
+-    protected int getConsoleMode() {
++    protected int getConsoleMode(Pointer console) {
+         IntByReference mode = new IntByReference();
+-        Kernel32.INSTANCE.GetConsoleMode(consoleIn, mode);
++        Kernel32.INSTANCE.GetConsoleMode(console, mode);
+         return mode.getValue();
+     }
+ 
+     @Override
+-    protected void setConsoleMode(int mode) {
+-        Kernel32.INSTANCE.SetConsoleMode(consoleIn, mode);
++    protected void setConsoleMode(Pointer console, int mode) {
++        Kernel32.INSTANCE.SetConsoleMode(console, mode);
+     }
+ 
+     public Size getSize() {
+         Kernel32.CONSOLE_SCREEN_BUFFER_INFO info = new Kernel32.CONSOLE_SCREEN_BUFFER_INFO();
+-        Kernel32.INSTANCE.GetConsoleScreenBufferInfo(consoleOut, info);
++        Kernel32.INSTANCE.GetConsoleScreenBufferInfo(outConsole, info);
+         return new Size(info.windowWidth(), info.windowHeight());
+     }
+ 
+@@ -154,10 +219,11 @@ public class JnaWinSysTerminal extends AbstractWindowsTerminal {
+     }
+ 
+     private void processKeyEvent(Kernel32.KEY_EVENT_RECORD keyEvent) throws IOException {
+-        processKeyEvent(keyEvent.bKeyDown, keyEvent.wVirtualKeyCode, keyEvent.uChar.UnicodeChar, keyEvent.dwControlKeyState);
++        processKeyEvent(
++                keyEvent.bKeyDown, keyEvent.wVirtualKeyCode, keyEvent.uChar.UnicodeChar, keyEvent.dwControlKeyState);
+     }
+ 
+-    private char[] focus = new char[] { '\033', '[', ' ' };
++    private char[] focus = new char[] {'\033', '[', ' '};
+ 
+     private void processFocusEvent(boolean hasFocus) throws IOException {
+         if (focusTracking) {
+@@ -166,7 +232,7 @@ public class JnaWinSysTerminal extends AbstractWindowsTerminal {
+         }
+     }
+ 
+-    private char[] mouse = new char[] { '\033', '[', 'M', ' ', ' ', ' ' };
++    private char[] mouse = new char[] {'\033', '[', 'M', ' ', ' ', ' '};
+ 
+     private void processMouseEvent(Kernel32.MOUSE_EVENT_RECORD mouseEvent) throws IOException {
+         int dwEventFlags = mouseEvent.dwEventFlags;
+@@ -177,7 +243,7 @@ public class JnaWinSysTerminal extends AbstractWindowsTerminal {
+             return;
+         }
+         int cb = 0;
+-        dwEventFlags &= ~ Kernel32.DOUBLE_CLICK; // Treat double-clicks as normal
++        dwEventFlags &= ~Kernel32.DOUBLE_CLICK; // Treat double-clicks as normal
+         if (dwEventFlags == Kernel32.MOUSE_WHEELED) {
+             cb |= 64;
+             if ((dwButtonState >> 16) < 0) {
+@@ -223,5 +289,4 @@ public class JnaWinSysTerminal extends AbstractWindowsTerminal {
+         Kernel32.INSTANCE.GetConsoleScreenBufferInfo(consoleOut, info);
+         return new Cursor(info.dwCursorPosition.X, info.dwCursorPosition.Y);
+     }
+-
+ }
+diff --git a/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/Kernel32.java b/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/Kernel32.java
+index 6f350501a..d3e20364a 100644
+--- a/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/Kernel32.java
++++ b/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/Kernel32.java
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2002-2018, the original author or authors.
++ * Copyright (c) 2002-2018, the original author(s).
+  *
+  * This software is distributable under the BSD license. See the terms of the
+  * BSD license in the documentation provided with this software.
+@@ -30,46 +30,46 @@ interface Kernel32 {//extends StdCallLibrary {
+ 
+ //    Pointer INVALID_HANDLE_VALUE = Pointer.createConstant(-1L);
+ 
+-    int STD_INPUT_HANDLE =  -10;
++    int STD_INPUT_HANDLE = -10;
+     int STD_OUTPUT_HANDLE = -11;
+-    int STD_ERROR_HANDLE =  -12;
+-
+-    int ENABLE_PROCESSED_INPUT =    0x0001;
+-    int ENABLE_LINE_INPUT =         0x0002;
+-    int ENABLE_ECHO_INPUT =         0x0004;
+-    int ENABLE_WINDOW_INPUT =       0x0008;
+-    int ENABLE_MOUSE_INPUT =        0x0010;
+-    int ENABLE_INSERT_MODE =        0x0020;
+-    int ENABLE_QUICK_EDIT_MODE =    0x0040;
+-    int ENABLE_EXTENDED_FLAGS =     0x0080;
+-
+-    int RIGHT_ALT_PRESSED =     0x0001;
+-    int LEFT_ALT_PRESSED =      0x0002;
+-    int RIGHT_CTRL_PRESSED =    0x0004;
+-    int LEFT_CTRL_PRESSED =     0x0008;
+-    int SHIFT_PRESSED =         0x0010;
+-
+-    int FOREGROUND_BLUE =       0x0001;
+-    int FOREGROUND_GREEN =      0x0002;
+-    int FOREGROUND_RED =        0x0004;
+-    int FOREGROUND_INTENSITY =  0x0008;
+-    int BACKGROUND_BLUE =       0x0010;
+-    int BACKGROUND_GREEN =      0x0020;
+-    int BACKGROUND_RED =        0x0040;
+-    int BACKGROUND_INTENSITY =  0x0080;
++    int STD_ERROR_HANDLE = -12;
++
++    int ENABLE_PROCESSED_INPUT = 0x0001;
++    int ENABLE_LINE_INPUT = 0x0002;
++    int ENABLE_ECHO_INPUT = 0x0004;
++    int ENABLE_WINDOW_INPUT = 0x0008;
++    int ENABLE_MOUSE_INPUT = 0x0010;
++    int ENABLE_INSERT_MODE = 0x0020;
++    int ENABLE_QUICK_EDIT_MODE = 0x0040;
++    int ENABLE_EXTENDED_FLAGS = 0x0080;
++
++    int RIGHT_ALT_PRESSED = 0x0001;
++    int LEFT_ALT_PRESSED = 0x0002;
++    int RIGHT_CTRL_PRESSED = 0x0004;
++    int LEFT_CTRL_PRESSED = 0x0008;
++    int SHIFT_PRESSED = 0x0010;
++
++    int FOREGROUND_BLUE = 0x0001;
++    int FOREGROUND_GREEN = 0x0002;
++    int FOREGROUND_RED = 0x0004;
++    int FOREGROUND_INTENSITY = 0x0008;
++    int BACKGROUND_BLUE = 0x0010;
++    int BACKGROUND_GREEN = 0x0020;
++    int BACKGROUND_RED = 0x0040;
++    int BACKGROUND_INTENSITY = 0x0080;
+ 
+     // Button state
+     int FROM_LEFT_1ST_BUTTON_PRESSED = 0x0001;
+-    int RIGHTMOST_BUTTON_PRESSED     = 0x0002;
++    int RIGHTMOST_BUTTON_PRESSED = 0x0002;
+     int FROM_LEFT_2ND_BUTTON_PRESSED = 0x0004;
+     int FROM_LEFT_3RD_BUTTON_PRESSED = 0x0008;
+     int FROM_LEFT_4TH_BUTTON_PRESSED = 0x0010;
+ 
+     // Event flags
+-    int MOUSE_MOVED                  = 0x0001;
+-    int DOUBLE_CLICK                 = 0x0002;
+-    int MOUSE_WHEELED                = 0x0004;
+-    int MOUSE_HWHEELED               = 0x0008;
++    int MOUSE_MOVED = 0x0001;
++    int DOUBLE_CLICK = 0x0002;
++    int MOUSE_WHEELED = 0x0004;
++    int MOUSE_HWHEELED = 0x0008;
+ 
+     // DWORD WINAPI WaitForSingleObject(
+     //  _In_ HANDLE hHandle,
+@@ -94,18 +94,18 @@ interface Kernel32 {//extends StdCallLibrary {
+ //    // UINT WINAPI GetConsoleCP(void)
+ //    int GetConsoleCP();
+ //
+-    // UINT WINAPI GetConsoleOutputCP(void)
+-    int GetConsoleOutputCP();
+-
+     // BOOL WINAPI FillConsoleOutputCharacter(
+     // _In_ HANDLE hConsoleOutput,
+     // _In_ TCHAR cCharacter,
+     // _In_ DWORD nLength,
+     // _In_ COORD dwWriteCoord,
+     // _Out_ LPDWORD lpNumberOfCharsWritten);
+-    void FillConsoleOutputCharacter(Pointer in_hConsoleOutput,
+-                                    char in_cCharacter, int in_nLength, COORD in_dwWriteCoord,
+-                                    IntByReference out_lpNumberOfCharsWritten)
++    void FillConsoleOutputCharacter(
++            Pointer in_hConsoleOutput,
++            char in_cCharacter,
++            int in_nLength,
++            COORD in_dwWriteCoord,
++            IntByReference out_lpNumberOfCharsWritten)
+             throws LastErrorException;
+ 
+     // BOOL WINAPI FillConsoleOutputAttribute(
+@@ -114,56 +114,53 @@ interface Kernel32 {//extends StdCallLibrary {
+     // _In_ DWORD nLength,
+     // _In_ COORD dwWriteCoord,
+     // _Out_ LPDWORD lpNumberOfAttrsWritten);
+-    void FillConsoleOutputAttribute(Pointer in_hConsoleOutput,
+-                                    short in_wAttribute, int in_nLength, COORD in_dwWriteCoord,
+-                                    IntByReference out_lpNumberOfAttrsWritten)
++    void FillConsoleOutputAttribute(
++            Pointer in_hConsoleOutput,
++            short in_wAttribute,
++            int in_nLength,
++            COORD in_dwWriteCoord,
++            IntByReference out_lpNumberOfAttrsWritten)
+             throws LastErrorException;
+-//
+-////    // BOOL WINAPI GetConsoleCursorInfo(
+-////    // _In_ HANDLE hConsoleOutput,
+-////    // _Out_ PCONSOLE_CURSOR_INFO lpConsoleCursorInfo);
+-////    void GetConsoleCursorInfo(Pointer in_hConsoleOutput,
+-////                              CONSOLE_CURSOR_INFO.ByReference out_lpConsoleCursorInfo)
+-////            throws LastErrorException;
+-//
++
++//    // BOOL WINAPI GetConsoleCursorInfo(
++//    // _In_ HANDLE hConsoleOutput,
++//    // _Out_ PCONSOLE_CURSOR_INFO lpConsoleCursorInfo);
++//    void GetConsoleCursorInfo(Pointer in_hConsoleOutput, CONSOLE_CURSOR_INFO.ByReference out_lpConsoleCursorInfo)
++//            throws LastErrorException;
++
+     // BOOL WINAPI GetConsoleMode(
+     //   _In_   HANDLE hConsoleHandle,
+     //   _Out_  LPDWORD lpMode);
+-    void GetConsoleMode(
+-            Pointer in_hConsoleOutput,
+-            IntByReference out_lpMode)
+-            throws LastErrorException;
++    void GetConsoleMode(Pointer in_hConsoleOutput, IntByReference out_lpMode) throws LastErrorException;
+ 
+     // BOOL WINAPI GetConsoleScreenBufferInfo(
+     // _In_   HANDLE hConsoleOutput,
+     // _Out_  PCONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo);
+-    void GetConsoleScreenBufferInfo(
+-            Pointer in_hConsoleOutput,
+-            CONSOLE_SCREEN_BUFFER_INFO out_lpConsoleScreenBufferInfo)
++    void GetConsoleScreenBufferInfo(Pointer in_hConsoleOutput, CONSOLE_SCREEN_BUFFER_INFO out_lpConsoleScreenBufferInfo)
+             throws LastErrorException;
+ //
+ //    // BOOL WINAPI GetNumberOfConsoleInputEvents(
+ //    // _In_ HANDLE hConsoleInput,
+ //    // _Out_ LPDWORD lpcNumberOfEvents);
+-//    void GetNumberOfConsoleInputEvents(Pointer in_hConsoleOutput,
+-//                                       IntByReference out_lpcNumberOfEvents) throws LastErrorException;
++//    void GetNumberOfConsoleInputEvents(Pointer in_hConsoleOutput, IntByReference out_lpcNumberOfEvents)
++//            throws LastErrorException;
+ //
+     // BOOL WINAPI ReadConsoleInput(
+     // _In_ HANDLE hConsoleInput,
+     // _Out_ PINPUT_RECORD lpBuffer,
+     // _In_ DWORD nLength,
+     // _Out_ LPDWORD lpNumberOfEventsRead);
+-    void ReadConsoleInput(Pointer in_hConsoleOutput,
+-                          INPUT_RECORD[] out_lpBuffer, int in_nLength,
+-                          IntByReference out_lpNumberOfEventsRead) throws LastErrorException;
++    void ReadConsoleInput(
++            Pointer in_hConsoleOutput,
++            INPUT_RECORD[] out_lpBuffer,
++            int in_nLength,
++            IntByReference out_lpNumberOfEventsRead)
++            throws LastErrorException;
+ 
+ //    // BOOL WINAPI SetConsoleCtrlHandler(
+ //    // _In_opt_  PHANDLER_ROUTINE HandlerRoutine,
+ //    // _In_      BOOL Add);
+-//    void SetConsoleCtrlHandler(
+-//            Pointer in_opt_HandlerRoutine,
+-//            boolean in_Add)
+-//            throws LastErrorException;
++//    void SetConsoleCtrlHandler(Pointer in_opt_HandlerRoutine, boolean in_Add) throws LastErrorException;
+ //
+ //    // BOOL WINAPI ReadConsoleOutput(
+ //    // _In_     HANDLE hConsoleOutput,
+@@ -171,12 +168,21 @@ interface Kernel32 {//extends StdCallLibrary {
+ //    // _In_     COORD dwBufferSize,
+ //    // _In_     COORD dwBufferCoord,
+ //    // _Inout_  PSMALL_RECT lpReadRegion);
+-////    void ReadConsoleOutput(Pointer in_hConsoleOutput, CHAR_INFO[] out_lpBuffer,
+-////                           COORD in_dwBufferSize, COORD in_dwBufferCoord,
+-////                           SMALL_RECT inout_lpReadRegion) throws LastErrorException;
+-////    void ReadConsoleOutputA(Pointer in_hConsoleOutput, CHAR_INFO[] out_lpBuffer,
+-////                            COORD in_dwBufferSize, COORD in_dwBufferCoord,
+-////                            SMALL_RECT inout_lpReadRegion) throws LastErrorException;
++//    void ReadConsoleOutput(
++//            Pointer in_hConsoleOutput,
++//            CHAR_INFO[] out_lpBuffer,
++//            COORD in_dwBufferSize,
++//            COORD in_dwBufferCoord,
++//            SMALL_RECT inout_lpReadRegion)
++//            throws LastErrorException;
++//
++//    void ReadConsoleOutputA(
++//            Pointer in_hConsoleOutput,
++//            CHAR_INFO[] out_lpBuffer,
++//            COORD in_dwBufferSize,
++//            COORD in_dwBufferCoord,
++//            SMALL_RECT inout_lpReadRegion)
++//            throws LastErrorException;
+ //
+ //    // BOOL WINAPI ReadConsoleOutputCharacter(
+ //    // _In_   HANDLE hConsoleOutput,
+@@ -184,20 +190,26 @@ interface Kernel32 {//extends StdCallLibrary {
+ //    // _In_   DWORD nLength,
+ //    // _In_   COORD dwReadCoord,
+ //    // _Out_  LPDWORD lpNumberOfCharsRead);
+-//    void ReadConsoleOutputCharacter(Pointer in_hConsoleOutput,
+-//                                    char[] ouy_lpCharacter, int in_nLength, COORD in_dwReadCoord,
+-//                                    IntByReference out_lpNumberOfCharsRead)
++//    void ReadConsoleOutputCharacter(
++//            Pointer in_hConsoleOutput,
++//            char[] ouy_lpCharacter,
++//            int in_nLength,
++//            COORD in_dwReadCoord,
++//            IntByReference out_lpNumberOfCharsRead)
+ //            throws LastErrorException;
+-//    void ReadConsoleOutputCharacterA(Pointer in_hConsoleOutput,
+-//                                     byte[] ouy_lpCharacter, int in_nLength, COORD in_dwReadCoord,
+-//                                     IntByReference out_lpNumberOfCharsRead)
++//
++//    void ReadConsoleOutputCharacterA(
++//            Pointer in_hConsoleOutput,
++//            byte[] ouy_lpCharacter,
++//            int in_nLength,
++//            COORD in_dwReadCoord,
++//            IntByReference out_lpNumberOfCharsRead)
+ //            throws LastErrorException;
+ //
+ //    // BOOL WINAPI SetConsoleCursorInfo(
+ //    // _In_ HANDLE hConsoleOutput,
+ //    // _In_ const CONSOLE_CURSOR_INFO *lpConsoleCursorInfo);
+-//    void SetConsoleCursorInfo(Pointer in_hConsoleOutput,
+-//                              CONSOLE_CURSOR_INFO in_lpConsoleCursorInfo)
++//    void SetConsoleCursorInfo(Pointer in_hConsoleOutput, CONSOLE_CURSOR_INFO in_lpConsoleCursorInfo)
+ //            throws LastErrorException;
+ //
+ //    // BOOL WINAPI SetConsoleCP(
+@@ -207,47 +219,39 @@ interface Kernel32 {//extends StdCallLibrary {
+ //    // BOOL WINAPI SetConsoleOutputCP(
+ //    // _In_ UINT wCodePageID);
+ //    void SetConsoleOutputCP(int in_wCodePageID) throws LastErrorException;
+-//
++
+     // BOOL WINAPI SetConsoleCursorPosition(
+     // _In_ HANDLE hConsoleOutput,
+     // _In_ COORD dwCursorPosition);
+-    void SetConsoleCursorPosition(Pointer in_hConsoleOutput,
+-                                  COORD in_dwCursorPosition) throws LastErrorException;
++    void SetConsoleCursorPosition(Pointer in_hConsoleOutput, COORD in_dwCursorPosition) throws LastErrorException;
+ 
+     // BOOL WINAPI SetConsoleMode(
+     //   _In_  HANDLE hConsoleHandle,
+     //   _In_  DWORD dwMode);
+-    void SetConsoleMode(
+-            Pointer in_hConsoleOutput,
+-            int in_dwMode) throws LastErrorException;
++    void SetConsoleMode(Pointer in_hConsoleOutput, int in_dwMode) throws LastErrorException;
+ 
+ //    // BOOL WINAPI SetConsoleScreenBufferSize(
+ //    // __in HANDLE hConsoleOutput,
+ //    // __in COORD dwSize
+ //    // );
+-//    void SetConsoleScreenBufferSize(Pointer in_hConsoleOutput,
+-//                                    COORD in_dwSize) throws LastErrorException;
+-//
++//    void SetConsoleScreenBufferSize(Pointer in_hConsoleOutput, COORD in_dwSize) throws LastErrorException;
++
+     // BOOL WINAPI SetConsoleTextAttribute(
+     // _In_ HANDLE hConsoleOutput,
+     // _In_ WORD   wAttributes
+     // );
+-    void SetConsoleTextAttribute(Pointer in_hConsoleOutput,
+-                                 short in_wAttributes)
+-            throws LastErrorException;
++    void SetConsoleTextAttribute(Pointer in_hConsoleOutput, short in_wAttributes) throws LastErrorException;
+ 
+     // BOOL WINAPI SetConsoleTitle(
+     // _In_ LPCTSTR lpConsoleTitle
+     // );
+-    void SetConsoleTitle(String in_lpConsoleTitle)
+-            throws LastErrorException;
++    void SetConsoleTitle(String in_lpConsoleTitle) throws LastErrorException;
+ 
+ //    // BOOL WINAPI SetConsoleWindowInfo(
+ //    // _In_ HANDLE hConsoleOutput,
+ //    // _In_ BOOL bAbsolute,
+ //    // _In_ const SMALL_RECT *lpConsoleWindow);
+-//    void SetConsoleWindowInfo(Pointer in_hConsoleOutput,
+-//                              boolean in_bAbsolute, SMALL_RECT in_lpConsoleWindow)
++//    void SetConsoleWindowInfo(Pointer in_hConsoleOutput, boolean in_bAbsolute, SMALL_RECT in_lpConsoleWindow)
+ //            throws LastErrorException;
+ 
+     // BOOL WINAPI WriteConsole(
+@@ -257,8 +261,13 @@ interface Kernel32 {//extends StdCallLibrary {
+     //  _Out_            LPDWORD lpNumberOfCharsWritten,
+     //  _Reserved_       LPVOID  lpReserved
+     // );
+-    void WriteConsoleW(Pointer in_hConsoleOutput, char[] in_lpBuffer, int in_nNumberOfCharsToWrite,
+-                          IntByReference out_lpNumberOfCharsWritten, Pointer reserved_lpReserved) throws LastErrorException;
++    void WriteConsoleW(
++            Pointer in_hConsoleOutput,
++            char[] in_lpBuffer,
++            int in_nNumberOfCharsToWrite,
++            IntByReference out_lpNumberOfCharsWritten,
++            Pointer reserved_lpReserved)
++            throws LastErrorException;
+ 
+ //    // BOOL WINAPI WriteConsoleOutput(
+ //    // _In_ HANDLE hConsoleOutput,
+@@ -266,12 +275,21 @@ interface Kernel32 {//extends StdCallLibrary {
+ //    // _In_ COORD dwBufferSize,
+ //    // _In_ COORD dwBufferCoord,
+ //    // _Inout_ PSMALL_RECT lpWriteRegion);
+-////    void WriteConsoleOutput(Pointer in_hConsoleOutput, CHAR_INFO[] in_lpBuffer,
+-////                            COORD in_dwBufferSize, COORD in_dwBufferCoord,
+-////                            SMALL_RECT inout_lpWriteRegion) throws LastErrorException;
+-////    void WriteConsoleOutputA(Pointer in_hConsoleOutput, CHAR_INFO[] in_lpBuffer,
+-////                             COORD in_dwBufferSize, COORD in_dwBufferCoord,
+-////                             SMALL_RECT inout_lpWriteRegion) throws LastErrorException;
++//    void WriteConsoleOutput(
++//            Pointer in_hConsoleOutput,
++//            CHAR_INFO[] in_lpBuffer,
++//            COORD in_dwBufferSize,
++//            COORD in_dwBufferCoord,
++//            SMALL_RECT inout_lpWriteRegion)
++//            throws LastErrorException;
++//
++//    void WriteConsoleOutputA(
++//            Pointer in_hConsoleOutput,
++//            CHAR_INFO[] in_lpBuffer,
++//            COORD in_dwBufferSize,
++//            COORD in_dwBufferCoord,
++//            SMALL_RECT inout_lpWriteRegion)
++//            throws LastErrorException;
+ //
+ //    // BOOL WINAPI WriteConsoleOutputCharacter(
+ //    // _In_ HANDLE hConsoleOutput,
+@@ -279,26 +297,34 @@ interface Kernel32 {//extends StdCallLibrary {
+ //    // _In_ DWORD nLength,
+ //    // _In_ COORD dwWriteCoord,
+ //    // _Out_ LPDWORD lpNumberOfCharsWritten);
+-//    void WriteConsoleOutputCharacter(Pointer in_hConsoleOutput,
+-//                                     char[] in_lpCharacter, int in_nLength, COORD in_dwWriteCoord,
+-//                                     IntByReference out_lpNumberOfCharsWritten)
+-//            throws LastErrorException;
+-//    void WriteConsoleOutputCharacterA(Pointer in_hConsoleOutput,
+-//                                      byte[] in_lpCharacter, int in_nLength, COORD in_dwWriteCoord,
+-//                                      IntByReference out_lpNumberOfCharsWritten)
++//    void WriteConsoleOutputCharacter(
++//            Pointer in_hConsoleOutput,
++//            char[] in_lpCharacter,
++//            int in_nLength,
++//            COORD in_dwWriteCoord,
++//            IntByReference out_lpNumberOfCharsWritten)
+ //            throws LastErrorException;
+ //
++//    void WriteConsoleOutputCharacterA(
++//            Pointer in_hConsoleOutput,
++//            byte[] in_lpCharacter,
++//            int in_nLength,
++//            COORD in_dwWriteCoord,
++//            IntByReference out_lpNumberOfCharsWritten)
++//            throws LastErrorException;
++
+     // BOOL WINAPI ScrollConsoleScreenBuffer(
+     //     _In_           HANDLE     hConsoleOutput,
+     //     _In_     const SMALL_RECT *lpScrollRectangle,
+     //     _In_opt_ const SMALL_RECT *lpClipRectangle,
+     //     _In_           COORD      dwDestinationOrigin,
+     //     _In_     const CHAR_INFO  *lpFill);
+-    void ScrollConsoleScreenBuffer(Pointer in_hConsoleOutput,
+-                                   SMALL_RECT in_lpScrollRectangle,
+-                                   SMALL_RECT in_lpClipRectangle,
+-                                   COORD in_dwDestinationOrigin,
+-                                   CHAR_INFO in_lpFill)
++    void ScrollConsoleScreenBuffer(
++            Pointer in_hConsoleOutput,
++            SMALL_RECT in_lpScrollRectangle,
++            SMALL_RECT in_lpClipRectangle,
++            COORD in_dwDestinationOrigin,
++            CHAR_INFO in_lpFill)
+             throws LastErrorException;
+ 
+     // typedef struct _CHAR_INFO {
+@@ -309,8 +335,7 @@ interface Kernel32 {//extends StdCallLibrary {
+     //   WORD  Attributes;
+     // } CHAR_INFO, *PCHAR_INFO;
+     class CHAR_INFO {//extends Structure {
+-        public CHAR_INFO() {
+-        }
++        public CHAR_INFO() {}
+ 
+         public CHAR_INFO(char c, short attr) {
+             uChar = new UnionChar(c);
+@@ -329,7 +354,7 @@ interface Kernel32 {//extends StdCallLibrary {
+ //            return (CHAR_INFO[]) new CHAR_INFO().toArray(size);
+ //        }
+ //
+-//        private static String[] fieldOrder = { "uChar", "Attributes" };
++//        private static String[] fieldOrder = {"uChar", "Attributes"};
+ //
+ //        @Override
+ //        protected java.util.List getFieldOrder() {
+@@ -345,11 +370,9 @@ interface Kernel32 {//extends StdCallLibrary {
+         public int dwSize;
+         public boolean bVisible;
+ 
+-//        public static class ByReference extends CONSOLE_CURSOR_INFO implements
+-//                Structure.ByReference {
+-//        }
++//        public static class ByReference extends CONSOLE_CURSOR_INFO implements Structure.ByReference {}
+ //
+-//        private static String[] fieldOrder = { "dwSize", "bVisible" };
++//        private static String[] fieldOrder = {"dwSize", "bVisible"};
+ //
+ //        @Override
+ //        protected java.util.List getFieldOrder() {
+@@ -365,13 +388,15 @@ interface Kernel32 {//extends StdCallLibrary {
+     //   COORD      dwMaximumWindowSize;
+     // } CONSOLE_SCREEN_BUFFER_INFO;
+     class CONSOLE_SCREEN_BUFFER_INFO {//extends Structure {
+-        public COORD      dwSize;
+-        public COORD      dwCursorPosition;
+-        public short      wAttributes;
++        public COORD dwSize;
++        public COORD dwCursorPosition;
++        public short wAttributes;
+         public SMALL_RECT srWindow;
+-        public COORD      dwMaximumWindowSize;
++        public COORD dwMaximumWindowSize;
+ 
+-//        private static String[] fieldOrder = { "dwSize", "dwCursorPosition", "wAttributes", "srWindow", "dwMaximumWindowSize" };
++//        private static String[] fieldOrder = {
++//            "dwSize", "dwCursorPosition", "wAttributes", "srWindow", "dwMaximumWindowSize"
++//        };
+ //
+ //        @Override
+ //        protected java.util.List getFieldOrder() {
+@@ -392,8 +417,7 @@ interface Kernel32 {//extends StdCallLibrary {
+     //    SHORT Y;
+     //  } COORD, *PCOORD;
+     class COORD {//extends Structure implements Structure.ByValue {
+-        public COORD() {
+-        }
++        public COORD() {}
+ 
+         public COORD(short X, short Y) {
+             this.X = X;
+@@ -403,7 +427,7 @@ interface Kernel32 {//extends StdCallLibrary {
+         public short X;
+         public short Y;
+ 
+-//        private static String[] fieldOrder = { "X", "Y" };
++//        private static String[] fieldOrder = {"X", "Y"};
+ //
+ //        @Override
+ //        protected java.util.List getFieldOrder() {
+@@ -489,7 +513,9 @@ interface Kernel32 {//extends StdCallLibrary {
+         public UnionChar uChar;
+         public int dwControlKeyState;
+ 
+-//        private static String[] fieldOrder = {"bKeyDown", "wRepeatCount", "wVirtualKeyCode", "wVirtualScanCode", "uChar", "dwControlKeyState"};
++//        private static String[] fieldOrder = {
++//            "bKeyDown", "wRepeatCount", "wVirtualKeyCode", "wVirtualScanCode", "uChar", "dwControlKeyState"
++//        };
+ //
+ //        @Override
+ //        protected java.util.List getFieldOrder() {
+@@ -509,7 +535,7 @@ interface Kernel32 {//extends StdCallLibrary {
+         public int dwControlKeyState;
+         public int dwEventFlags;
+ 
+-//        private static String[] fieldOrder = { "dwMousePosition", "dwButtonState", "dwControlKeyState", "dwEventFlags"};
++//        private static String[] fieldOrder = {"dwMousePosition", "dwButtonState", "dwControlKeyState", "dwEventFlags"};
+ //
+ //        @Override
+ //        protected java.util.List getFieldOrder() {
+@@ -548,7 +574,7 @@ interface Kernel32 {//extends StdCallLibrary {
+ 
+     // typedef struct _FOCUS_EVENT_RECORD {
+     //  BOOL bSetFocus;
+-    //} FOCUS_EVENT_RECORD;
++    // } FOCUS_EVENT_RECORD;
+     class FOCUS_EVENT_RECORD {//extends Structure {
+         public boolean bSetFocus;
+ 
+@@ -567,8 +593,7 @@ interface Kernel32 {//extends StdCallLibrary {
+     //    SHORT Bottom;
+     //  } SMALL_RECT;
+     class SMALL_RECT {//extends Structure {
+-        public SMALL_RECT() {
+-        }
++        public SMALL_RECT() {}
+ 
+         public SMALL_RECT(SMALL_RECT org) {
+             this(org.Top, org.Left, org.Bottom, org.Right);
+@@ -586,7 +611,7 @@ interface Kernel32 {//extends StdCallLibrary {
+         public short Right;
+         public short Bottom;
+ 
+-//        private static String[] fieldOrder = { "Left", "Top", "Right", "Bottom" };
++//        private static String[] fieldOrder = {"Left", "Top", "Right", "Bottom"};
+ //
+ //        @Override
+ //        protected java.util.List getFieldOrder() {
+@@ -594,18 +619,16 @@ interface Kernel32 {//extends StdCallLibrary {
+ //        }
+ 
+         public short width() {
+-            return (short)(this.Right - this.Left);
++            return (short) (this.Right - this.Left);
+         }
+ 
+         public short height() {
+-            return (short)(this.Bottom - this.Top);
++            return (short) (this.Bottom - this.Top);
+         }
+-
+     }
+ 
+     class UnionChar {//extends Union {
+-        public UnionChar() {
+-        }
++        public UnionChar() {}
+ 
+         public UnionChar(char c) {
+ //            setType(char.class);
+diff --git a/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/Kernel32Impl.java b/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/Kernel32Impl.java
+index 2008bfacd..90c19bd91 100644
+--- a/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/Kernel32Impl.java
++++ b/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/Kernel32Impl.java
+@@ -43,9 +43,6 @@ public class Kernel32Impl implements Kernel32 {
+     @Override
+     public native Pointer GetStdHandle(int nStdHandle);
+ 
+-    @Override
+-    public native int GetConsoleOutputCP();
+-
+     @Override
+     public native void FillConsoleOutputCharacter(Pointer in_hConsoleOutput, char in_cCharacter, int in_nLength, COORD in_dwWriteCoord, IntByReference out_lpNumberOfCharsWritten) throws LastErrorException;
+ 
+diff --git a/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/WindowsAnsiWriter.java b/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/WindowsAnsiWriter.java
+index 7e1b82db8..6d3f217cb 100644
+--- a/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/WindowsAnsiWriter.java
++++ b/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/WindowsAnsiWriter.java
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2002-2016, the original author or authors.
++ * Copyright (c) 2002-2016, the original author(s).
+  *
+  * This software is distributable under the BSD license. See the terms of the
+  * BSD license in the documentation provided with this software.
+@@ -11,11 +11,12 @@ package jdk.internal.org.jline.terminal.impl.jna.win;
+ import java.io.IOException;
+ import java.io.Writer;
+ 
+-//import com.sun.jna.Pointer;
+-//import com.sun.jna.ptr.IntByReference;
+ import jdk.internal.org.jline.utils.AnsiWriter;
+ import jdk.internal.org.jline.utils.Colors;
+ 
++//import com.sun.jna.Pointer;
++//import com.sun.jna.ptr.IntByReference;
++
+ import static jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.BACKGROUND_BLUE;
+ import static jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.BACKGROUND_GREEN;
+ import static jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.BACKGROUND_INTENSITY;
+@@ -25,7 +26,6 @@ import static jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.FOREGROUND_G
+ import static jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.FOREGROUND_INTENSITY;
+ import static jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.FOREGROUND_RED;
+ 
+-
+ /**
+  * A Windows ANSI escape processor, uses JNA to access native platform
+  * API's to change the console attributes.
+@@ -36,41 +36,41 @@ import static jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.FOREGROUND_R
+  */
+ public final class WindowsAnsiWriter extends AnsiWriter {
+ 
+-    private static final short FOREGROUND_BLACK   = 0;
+-    private static final short FOREGROUND_YELLOW  = (short) (FOREGROUND_RED|FOREGROUND_GREEN);
+-    private static final short FOREGROUND_MAGENTA = (short) (FOREGROUND_BLUE|FOREGROUND_RED);
+-    private static final short FOREGROUND_CYAN    = (short) (FOREGROUND_BLUE|FOREGROUND_GREEN);
+-    private static final short FOREGROUND_WHITE   = (short) (FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE);
++    private static final short FOREGROUND_BLACK = 0;
++    private static final short FOREGROUND_YELLOW = (short) (FOREGROUND_RED | FOREGROUND_GREEN);
++    private static final short FOREGROUND_MAGENTA = (short) (FOREGROUND_BLUE | FOREGROUND_RED);
++    private static final short FOREGROUND_CYAN = (short) (FOREGROUND_BLUE | FOREGROUND_GREEN);
++    private static final short FOREGROUND_WHITE = (short) (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
+ 
+-    private static final short BACKGROUND_BLACK   = 0;
+-    private static final short BACKGROUND_YELLOW  = (short) (BACKGROUND_RED|BACKGROUND_GREEN);
+-    private static final short BACKGROUND_MAGENTA = (short) (BACKGROUND_BLUE|BACKGROUND_RED);
+-    private static final short BACKGROUND_CYAN    = (short) (BACKGROUND_BLUE|BACKGROUND_GREEN);
+-    private static final short BACKGROUND_WHITE   = (short) (BACKGROUND_RED|BACKGROUND_GREEN|BACKGROUND_BLUE);
++    private static final short BACKGROUND_BLACK = 0;
++    private static final short BACKGROUND_YELLOW = (short) (BACKGROUND_RED | BACKGROUND_GREEN);
++    private static final short BACKGROUND_MAGENTA = (short) (BACKGROUND_BLUE | BACKGROUND_RED);
++    private static final short BACKGROUND_CYAN = (short) (BACKGROUND_BLUE | BACKGROUND_GREEN);
++    private static final short BACKGROUND_WHITE = (short) (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE);
+ 
+     private static final short ANSI_FOREGROUND_COLOR_MAP[] = {
+-            FOREGROUND_BLACK,
+-            FOREGROUND_RED,
+-            FOREGROUND_GREEN,
+-            FOREGROUND_YELLOW,
+-            FOREGROUND_BLUE,
+-            FOREGROUND_MAGENTA,
+-            FOREGROUND_CYAN,
+-            FOREGROUND_WHITE,
++        FOREGROUND_BLACK,
++        FOREGROUND_RED,
++        FOREGROUND_GREEN,
++        FOREGROUND_YELLOW,
++        FOREGROUND_BLUE,
++        FOREGROUND_MAGENTA,
++        FOREGROUND_CYAN,
++        FOREGROUND_WHITE,
+     };
+ 
+     private static final short ANSI_BACKGROUND_COLOR_MAP[] = {
+-            BACKGROUND_BLACK,
+-            BACKGROUND_RED,
+-            BACKGROUND_GREEN,
+-            BACKGROUND_YELLOW,
+-            BACKGROUND_BLUE,
+-            BACKGROUND_MAGENTA,
+-            BACKGROUND_CYAN,
+-            BACKGROUND_WHITE,
++        BACKGROUND_BLACK,
++        BACKGROUND_RED,
++        BACKGROUND_GREEN,
++        BACKGROUND_YELLOW,
++        BACKGROUND_BLUE,
++        BACKGROUND_MAGENTA,
++        BACKGROUND_CYAN,
++        BACKGROUND_WHITE,
+     };
+ 
+-    private final static int MAX_ESCAPE_SEQUENCE_LENGTH = 100;
++    private static final int MAX_ESCAPE_SEQUENCE_LENGTH = 100;
+ 
+     private final Pointer console;
+ 
+@@ -134,7 +134,7 @@ public final class WindowsAnsiWriter extends AnsiWriter {
+     protected void processEraseScreen(int eraseOption) throws IOException {
+         getConsoleInfo();
+         IntByReference written = new IntByReference();
+-        switch(eraseOption) {
++        switch (eraseOption) {
+             case ERASE_SCREEN:
+                 Kernel32.COORD topLeft = new Kernel32.COORD();
+                 topLeft.X = 0;
+@@ -147,36 +147,44 @@ public final class WindowsAnsiWriter extends AnsiWriter {
+                 Kernel32.COORD topLeft2 = new Kernel32.COORD();
+                 topLeft2.X = 0;
+                 topLeft2.Y = info.srWindow.Top;
+-                int lengthToCursor = (info.dwCursorPosition.Y - info.srWindow.Top) * info.dwSize.X + info.dwCursorPosition.X;
++                int lengthToCursor =
++                        (info.dwCursorPosition.Y - info.srWindow.Top) * info.dwSize.X + info.dwCursorPosition.X;
+                 Kernel32.INSTANCE.FillConsoleOutputCharacter(console, ' ', lengthToCursor, topLeft2, written);
+-                Kernel32.INSTANCE.FillConsoleOutputAttribute(console, info.wAttributes, lengthToCursor, topLeft2, written);
++                Kernel32.INSTANCE.FillConsoleOutputAttribute(
++                        console, info.wAttributes, lengthToCursor, topLeft2, written);
+                 break;
+             case ERASE_SCREEN_TO_END:
+-                int lengthToEnd = (info.srWindow.Bottom - info.dwCursorPosition.Y) * info.dwSize.X +
+-                        (info.dwSize.X - info.dwCursorPosition.X);
++                int lengthToEnd = (info.srWindow.Bottom - info.dwCursorPosition.Y) * info.dwSize.X
++                        + (info.dwSize.X - info.dwCursorPosition.X);
+                 Kernel32.INSTANCE.FillConsoleOutputCharacter(console, ' ', lengthToEnd, info.dwCursorPosition, written);
+-                Kernel32.INSTANCE.FillConsoleOutputAttribute(console, info.wAttributes, lengthToEnd, info.dwCursorPosition, written);
++                Kernel32.INSTANCE.FillConsoleOutputAttribute(
++                        console, info.wAttributes, lengthToEnd, info.dwCursorPosition, written);
+         }
+     }
+ 
+     protected void processEraseLine(int eraseOption) throws IOException {
+         getConsoleInfo();
+         IntByReference written = new IntByReference();
+-        switch(eraseOption) {
++        switch (eraseOption) {
+             case ERASE_LINE:
+                 Kernel32.COORD leftColCurrRow = new Kernel32.COORD((short) 0, info.dwCursorPosition.Y);
+                 Kernel32.INSTANCE.FillConsoleOutputCharacter(console, ' ', info.dwSize.X, leftColCurrRow, written);
+-                Kernel32.INSTANCE.FillConsoleOutputAttribute(console, info.wAttributes, info.dwSize.X, leftColCurrRow, written);
++                Kernel32.INSTANCE.FillConsoleOutputAttribute(
++                        console, info.wAttributes, info.dwSize.X, leftColCurrRow, written);
+                 break;
+             case ERASE_LINE_TO_BEGINING:
+                 Kernel32.COORD leftColCurrRow2 = new Kernel32.COORD((short) 0, info.dwCursorPosition.Y);
+-                Kernel32.INSTANCE.FillConsoleOutputCharacter(console, ' ', info.dwCursorPosition.X, leftColCurrRow2, written);
+-                Kernel32.INSTANCE.FillConsoleOutputAttribute(console, info.wAttributes, info.dwCursorPosition.X, leftColCurrRow2, written);
++                Kernel32.INSTANCE.FillConsoleOutputCharacter(
++                        console, ' ', info.dwCursorPosition.X, leftColCurrRow2, written);
++                Kernel32.INSTANCE.FillConsoleOutputAttribute(
++                        console, info.wAttributes, info.dwCursorPosition.X, leftColCurrRow2, written);
+                 break;
+             case ERASE_LINE_TO_END:
+                 int lengthToLastCol = info.dwSize.X - info.dwCursorPosition.X;
+-                Kernel32.INSTANCE.FillConsoleOutputCharacter(console, ' ', lengthToLastCol, info.dwCursorPosition, written);
+-                Kernel32.INSTANCE.FillConsoleOutputAttribute(console, info.wAttributes, lengthToLastCol, info.dwCursorPosition, written);
++                Kernel32.INSTANCE.FillConsoleOutputCharacter(
++                        console, ' ', lengthToLastCol, info.dwCursorPosition, written);
++                Kernel32.INSTANCE.FillConsoleOutputAttribute(
++                        console, info.wAttributes, lengthToLastCol, info.dwCursorPosition, written);
+         }
+     }
+ 
+@@ -218,7 +226,7 @@ public final class WindowsAnsiWriter extends AnsiWriter {
+             scroll.Top = 0;
+             Kernel32.COORD org = new Kernel32.COORD();
+             org.X = 0;
+-            org.Y = (short)(- nb);
++            org.Y = (short) (-nb);
+             Kernel32.CHAR_INFO info = new Kernel32.CHAR_INFO(' ', originalColors);
+             Kernel32.INSTANCE.ScrollConsoleScreenBuffer(console, scroll, scroll, org, info);
+         }
+@@ -247,29 +255,31 @@ public final class WindowsAnsiWriter extends AnsiWriter {
+     protected void processSetForegroundColorExt(int paletteIndex) throws IOException {
+         int color = Colors.roundColor(paletteIndex, 16);
+         info.wAttributes = (short) ((info.wAttributes & ~0x0007) | ANSI_FOREGROUND_COLOR_MAP[color & 0x07]);
+-        info.wAttributes = (short) ((info.wAttributes & ~FOREGROUND_INTENSITY) | (color >= 8 ? FOREGROUND_INTENSITY : 0));
++        info.wAttributes =
++                (short) ((info.wAttributes & ~FOREGROUND_INTENSITY) | (color >= 8 ? FOREGROUND_INTENSITY : 0));
+         applyAttribute();
+     }
+ 
+     protected void processSetBackgroundColorExt(int paletteIndex) throws IOException {
+         int color = Colors.roundColor(paletteIndex, 16);
+-        info.wAttributes = (short)((info.wAttributes & ~0x0070 ) | ANSI_BACKGROUND_COLOR_MAP[color & 0x07]);
+-        info.wAttributes = (short) ((info.wAttributes & ~BACKGROUND_INTENSITY) | (color >= 8 ? BACKGROUND_INTENSITY : 0));
++        info.wAttributes = (short) ((info.wAttributes & ~0x0070) | ANSI_BACKGROUND_COLOR_MAP[color & 0x07]);
++        info.wAttributes =
++                (short) ((info.wAttributes & ~BACKGROUND_INTENSITY) | (color >= 8 ? BACKGROUND_INTENSITY : 0));
+         applyAttribute();
+     }
+ 
+     protected void processDefaultTextColor() throws IOException {
+-        info.wAttributes = (short)((info.wAttributes & ~0x000F ) | (originalColors & 0x000F));
++        info.wAttributes = (short) ((info.wAttributes & ~0x000F) | (originalColors & 0x000F));
+         applyAttribute();
+     }
+ 
+     protected void processDefaultBackgroundColor() throws IOException {
+-        info.wAttributes = (short)((info.wAttributes & ~0x00F0 ) | (originalColors & 0x00F0));
++        info.wAttributes = (short) ((info.wAttributes & ~0x00F0) | (originalColors & 0x00F0));
+         applyAttribute();
+     }
+ 
+     protected void processAttributeRest() throws IOException {
+-        info.wAttributes = (short)((info.wAttributes & ~0x00FF ) | originalColors);
++        info.wAttributes = (short) ((info.wAttributes & ~0x00FF) | originalColors);
+         this.negative = false;
+         this.bold = false;
+         this.underline = false;
+@@ -277,7 +287,7 @@ public final class WindowsAnsiWriter extends AnsiWriter {
+     }
+ 
+     protected void processSetAttribute(int attribute) throws IOException {
+-        switch(attribute) {
++        switch (attribute) {
+             case ATTRIBUTE_INTENSITY_BOLD:
+                 bold = true;
+                 applyAttribute();
+@@ -330,7 +340,7 @@ public final class WindowsAnsiWriter extends AnsiWriter {
+         scroll.Top = info.dwCursorPosition.Y;
+         Kernel32.COORD org = new Kernel32.COORD();
+         org.X = 0;
+-        org.Y = (short)(info.dwCursorPosition.Y + optionInt);
++        org.Y = (short) (info.dwCursorPosition.Y + optionInt);
+         Kernel32.CHAR_INFO info = new Kernel32.CHAR_INFO(' ', originalColors);
+         Kernel32.INSTANCE.ScrollConsoleScreenBuffer(console, scroll, scroll, org, info);
+     }
+@@ -342,7 +352,7 @@ public final class WindowsAnsiWriter extends AnsiWriter {
+         scroll.Top = info.dwCursorPosition.Y;
+         Kernel32.COORD org = new Kernel32.COORD();
+         org.X = 0;
+-        org.Y = (short)(info.dwCursorPosition.Y - optionInt);
++        org.Y = (short) (info.dwCursorPosition.Y - optionInt);
+         Kernel32.CHAR_INFO info = new Kernel32.CHAR_INFO(' ', originalColors);
+         Kernel32.INSTANCE.ScrollConsoleScreenBuffer(console, scroll, scroll, org, info);
+     }
+diff --git a/src/jdk.internal.le/windows/native/lible/Kernel32.cpp b/src/jdk.internal.le/windows/native/lible/Kernel32.cpp
+index 89fcc0acb..e0a71f085 100644
+--- a/src/jdk.internal.le/windows/native/lible/Kernel32.cpp
++++ b/src/jdk.internal.le/windows/native/lible/Kernel32.cpp
+@@ -327,16 +327,6 @@ JNIEXPORT jobject JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_win_Kern
+                           nStdHandle);
+ }
+ 
+-/*
+- * Class:     jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl
+- * Method:    GetConsoleOutputCP
+- * Signature: ()I
+- */
+-JNIEXPORT jint JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl_GetConsoleOutputCP
+-  (JNIEnv *, jobject) {
+-    return GetConsoleOutputCP();
+-}
+-
+ /*
+  * Class:     jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl
+  * Method:    FillConsoleOutputCharacter
+diff --git a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot.loongarch64/src/jdk/vm/ci/hotspot/loongarch64/LoongArch64HotSpotJVMCIBackendFactory.java b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot.loongarch64/src/jdk/vm/ci/hotspot/loongarch64/LoongArch64HotSpotJVMCIBackendFactory.java
+new file mode 100644
+index 000000000..0d3953ddf
+--- /dev/null
++++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot.loongarch64/src/jdk/vm/ci/hotspot/loongarch64/LoongArch64HotSpotJVMCIBackendFactory.java
+@@ -0,0 +1,220 @@
 +/*
-+ * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
-+ * Copyright (c) 2018, 2021, Loongson Technology. All rights reserved.
++ * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2022, Loongson Technology. 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
@@ -117401,517 +197783,516 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.hotspot.agent/shar
 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 + * or visit www.oracle.com if you need additional information or have any
 + * questions.
-+ *
 + */
++package jdk.vm.ci.hotspot.loongarch64;
 +
-+package sun.jvm.hotspot.runtime.loongarch64;
-+
-+import java.util.*;
-+import sun.jvm.hotspot.code.*;
-+import sun.jvm.hotspot.compiler.*;
-+import sun.jvm.hotspot.debugger.*;
-+import sun.jvm.hotspot.oops.*;
-+import sun.jvm.hotspot.runtime.*;
-+import sun.jvm.hotspot.types.*;
-+import sun.jvm.hotspot.utilities.*;
-+
-+/** Specialization of and implementation of abstract methods of the
-+    Frame class for the loongarch64 family of CPUs. */
-+
-+public class LOONGARCH64Frame extends Frame {
-+  private static final boolean DEBUG;
-+  static {
-+    DEBUG = System.getProperty("sun.jvm.hotspot.runtime.loongarch64.LOONGARCH64Frame.DEBUG") != null;
-+  }
-+
-+  // Java frames
-+  private static final int JAVA_FRAME_LINK_OFFSET             =  0;
-+  private static final int JAVA_FRAME_RETURN_ADDR_OFFSET      =  1;
-+  private static final int JAVA_FRAME_SENDER_SP_OFFSET        =  2;
-+
-+  // Native frames
-+  private static final int NATIVE_FRAME_LINK_OFFSET           =  -2;
-+  private static final int NATIVE_FRAME_RETURN_ADDR_OFFSET    =  -1;
-+  private static final int NATIVE_FRAME_SENDER_SP_OFFSET      =  0;
-+
-+  // Interpreter frames
-+  private static final int INTERPRETER_FRAME_SENDER_SP_OFFSET = -1;
-+  private static final int INTERPRETER_FRAME_LAST_SP_OFFSET   = INTERPRETER_FRAME_SENDER_SP_OFFSET - 1;
-+  private static final int INTERPRETER_FRAME_LOCALS_OFFSET    = INTERPRETER_FRAME_LAST_SP_OFFSET - 1;
-+  private static final int INTERPRETER_FRAME_METHOD_OFFSET    = INTERPRETER_FRAME_LOCALS_OFFSET - 1;
-+  private static final int INTERPRETER_FRAME_MIRROR_OFFSET    = INTERPRETER_FRAME_METHOD_OFFSET - 1;
-+  private static final int INTERPRETER_FRAME_MDX_OFFSET       = INTERPRETER_FRAME_MIRROR_OFFSET - 1;
-+  private static final int INTERPRETER_FRAME_CACHE_OFFSET     = INTERPRETER_FRAME_MDX_OFFSET - 1;
-+  private static final int INTERPRETER_FRAME_BCX_OFFSET       = INTERPRETER_FRAME_CACHE_OFFSET - 1;
-+  private static final int INTERPRETER_FRAME_INITIAL_SP_OFFSET = INTERPRETER_FRAME_BCX_OFFSET - 1;
-+  private static final int INTERPRETER_FRAME_MONITOR_BLOCK_TOP_OFFSET = INTERPRETER_FRAME_INITIAL_SP_OFFSET;
-+  private static final int INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET = INTERPRETER_FRAME_INITIAL_SP_OFFSET;
-+
-+  // Entry frames
-+  private static final int ENTRY_FRAME_CALL_WRAPPER_OFFSET = -9;
-+
-+  private static VMReg fp = new VMReg(22 << 1);
-+
-+  // an additional field beyond sp and pc:
-+  Address raw_fp; // frame pointer
-+  private Address raw_unextendedSP;
-+
-+  private LOONGARCH64Frame() {
-+  }
-+
-+  private void adjustForDeopt() {
-+    if ( pc != null) {
-+      // Look for a deopt pc and if it is deopted convert to original pc
-+      CodeBlob cb = VM.getVM().getCodeCache().findBlob(pc);
-+      if (cb != null && cb.isJavaMethod()) {
-+        NMethod nm = (NMethod) cb;
-+        if (pc.equals(nm.deoptHandlerBegin())) {
-+          if (Assert.ASSERTS_ENABLED) {
-+            Assert.that(this.getUnextendedSP() != null, "null SP in Java frame");
-+          }
-+          // adjust pc if frame is deoptimized.
-+          pc = this.getUnextendedSP().getAddressAt(nm.origPCOffset());
-+          deoptimized = true;
-+        }
-+      }
-+    }
-+  }
-+
-+  public LOONGARCH64Frame(Address raw_sp, Address raw_fp, Address pc) {
-+    this.raw_sp = raw_sp;
-+    this.raw_unextendedSP = raw_sp;
-+    this.raw_fp = raw_fp;
-+    this.pc = pc;
-+    adjustUnextendedSP();
-+
-+    // Frame must be fully constructed before this call
-+    adjustForDeopt();
-+
-+    if (DEBUG) {
-+      System.out.println("LOONGARCH64Frame(sp, fp, pc): " + this);
-+      dumpStack();
-+    }
-+  }
-+
-+  public LOONGARCH64Frame(Address raw_sp, Address raw_fp) {
-+    this.raw_sp = raw_sp;
-+    this.raw_unextendedSP = raw_sp;
-+    this.raw_fp = raw_fp;
-+    this.pc = raw_fp.getAddressAt(1 * VM.getVM().getAddressSize());
-+    adjustUnextendedSP();
-+
-+    // Frame must be fully constructed before this call
-+    adjustForDeopt();
-+
-+    if (DEBUG) {
-+      System.out.println("LOONGARCH64Frame(sp, fp): " + this);
-+      dumpStack();
-+    }
-+  }
-+
-+  public LOONGARCH64Frame(Address raw_sp, Address raw_unextendedSp, Address raw_fp, Address pc) {
-+    this.raw_sp = raw_sp;
-+    this.raw_unextendedSP = raw_unextendedSp;
-+    this.raw_fp = raw_fp;
-+    this.pc = pc;
-+    adjustUnextendedSP();
-+
-+    // Frame must be fully constructed before this call
-+    adjustForDeopt();
-+
-+    if (DEBUG) {
-+      System.out.println("LOONGARCH64Frame(sp, unextendedSP, fp, pc): " + this);
-+      dumpStack();
-+    }
++import static java.util.Collections.emptyMap;
++import static jdk.vm.ci.common.InitTimer.timer;
 +
-+  }
++import java.util.EnumSet;
++import java.util.Map;
 +
-+  public Object clone() {
-+    LOONGARCH64Frame frame = new LOONGARCH64Frame();
-+    frame.raw_sp = raw_sp;
-+    frame.raw_unextendedSP = raw_unextendedSP;
-+    frame.raw_fp = raw_fp;
-+    frame.pc = pc;
-+    frame.deoptimized = deoptimized;
-+    return frame;
-+  }
++import jdk.vm.ci.loongarch64.LoongArch64;
++import jdk.vm.ci.loongarch64.LoongArch64.CPUFeature;
++import jdk.vm.ci.code.Architecture;
++import jdk.vm.ci.code.RegisterConfig;
++import jdk.vm.ci.code.TargetDescription;
++import jdk.vm.ci.code.stack.StackIntrospection;
++import jdk.vm.ci.common.InitTimer;
++import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider;
++import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider;
++import jdk.vm.ci.hotspot.HotSpotJVMCIBackendFactory;
++import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
++import jdk.vm.ci.hotspot.HotSpotMetaAccessProvider;
++import jdk.vm.ci.hotspot.HotSpotStackIntrospection;
++import jdk.vm.ci.meta.ConstantReflectionProvider;
++import jdk.vm.ci.runtime.JVMCIBackend;
 +
-+  public boolean equals(Object arg) {
-+    if (arg == null) {
-+      return false;
-+    }
++public class LoongArch64HotSpotJVMCIBackendFactory implements HotSpotJVMCIBackendFactory {
 +
-+    if (!(arg instanceof LOONGARCH64Frame)) {
-+      return false;
-+    }
++    protected EnumSet computeFeatures(@SuppressWarnings("unused") LoongArch64HotSpotVMConfig config) {
++        // Configure the feature set using the HotSpot flag settings.
++        EnumSet features = EnumSet.noneOf(LoongArch64.CPUFeature.class);
 +
-+    LOONGARCH64Frame other = (LOONGARCH64Frame) arg;
++        if ((config.vmVersionFeatures & config.loongarch64LA32) != 0) {
++            features.add(LoongArch64.CPUFeature.LA32);
++        }
 +
-+    return (AddressOps.equal(getSP(), other.getSP()) &&
-+            AddressOps.equal(getUnextendedSP(), other.getUnextendedSP()) &&
-+            AddressOps.equal(getFP(), other.getFP()) &&
-+            AddressOps.equal(getPC(), other.getPC()));
-+  }
++        if ((config.vmVersionFeatures & config.loongarch64LA64) != 0) {
++            features.add(LoongArch64.CPUFeature.LA64);
++        }
 +
-+  public int hashCode() {
-+    if (raw_sp == null) {
-+      return 0;
-+    }
++        if ((config.vmVersionFeatures & config.loongarch64LLEXC) != 0) {
++            features.add(LoongArch64.CPUFeature.LLEXC);
++        }
 +
-+    return raw_sp.hashCode();
-+  }
++        if ((config.vmVersionFeatures & config.loongarch64SCDLY) != 0) {
++            features.add(LoongArch64.CPUFeature.SCDLY);
++        }
 +
-+  public String toString() {
-+    return "sp: " + (getSP() == null? "null" : getSP().toString()) +
-+         ", unextendedSP: " + (getUnextendedSP() == null? "null" : getUnextendedSP().toString()) +
-+         ", fp: " + (getFP() == null? "null" : getFP().toString()) +
-+         ", pc: " + (pc == null? "null" : pc.toString());
-+  }
++        if ((config.vmVersionFeatures & config.loongarch64LLDBAR) != 0) {
++            features.add(LoongArch64.CPUFeature.LLDBAR);
++        }
 +
-+  // accessors for the instance variables
-+  public Address getFP() { return raw_fp; }
-+  public Address getSP() { return raw_sp; }
-+  public Address getID() { return raw_sp; }
++        if ((config.vmVersionFeatures & config.loongarch64LBT_X86) != 0) {
++            features.add(LoongArch64.CPUFeature.LBT_X86);
++        }
 +
-+  // FIXME: not implemented yet (should be done for Solaris/LOONGARCH)
-+  public boolean isSignalHandlerFrameDbg() { return false; }
-+  public int     getSignalNumberDbg()      { return 0;     }
-+  public String  getSignalNameDbg()        { return null;  }
++        if ((config.vmVersionFeatures & config.loongarch64LBT_ARM) != 0) {
++            features.add(LoongArch64.CPUFeature.LBT_ARM);
++        }
 +
-+  public boolean isInterpretedFrameValid() {
-+    if (Assert.ASSERTS_ENABLED) {
-+      Assert.that(isInterpretedFrame(), "Not an interpreted frame");
-+    }
++        if ((config.vmVersionFeatures & config.loongarch64LBT_MIPS) != 0) {
++            features.add(LoongArch64.CPUFeature.LBT_MIPS);
++        }
 +
-+    // These are reasonable sanity checks
-+    if (getFP() == null || getFP().andWithMask(0x3) != null) {
-+      return false;
-+    }
++        if ((config.vmVersionFeatures & config.loongarch64CCDMA) != 0) {
++            features.add(LoongArch64.CPUFeature.CCDMA);
++        }
 +
-+    if (getSP() == null || getSP().andWithMask(0x3) != null) {
-+      return false;
-+    }
++        if ((config.vmVersionFeatures & config.loongarch64COMPLEX) != 0) {
++            features.add(LoongArch64.CPUFeature.COMPLEX);
++        }
 +
-+    if (getFP().addOffsetTo(INTERPRETER_FRAME_INITIAL_SP_OFFSET * VM.getVM().getAddressSize()).lessThan(getSP())) {
-+      return false;
-+    }
++        if ((config.vmVersionFeatures & config.loongarch64FP) != 0) {
++            features.add(LoongArch64.CPUFeature.FP);
++        }
 +
-+    // These are hacks to keep us out of trouble.
-+    // The problem with these is that they mask other problems
-+    if (getFP().lessThanOrEqual(getSP())) {
-+      // this attempts to deal with unsigned comparison above
-+      return false;
-+    }
++        if ((config.vmVersionFeatures & config.loongarch64CRYPTO) != 0) {
++            features.add(LoongArch64.CPUFeature.CRYPTO);
++        }
 +
-+    if (getFP().minus(getSP()) > 4096 * VM.getVM().getAddressSize()) {
-+      // stack frames shouldn't be large.
-+      return false;
-+    }
++        if ((config.vmVersionFeatures & config.loongarch64LSX) != 0) {
++            features.add(LoongArch64.CPUFeature.LSX);
++        }
 +
-+    return true;
-+  }
++        if ((config.vmVersionFeatures & config.loongarch64LASX) != 0) {
++            features.add(LoongArch64.CPUFeature.LASX);
++        }
 +
-+  // FIXME: not applicable in current system
-+  //  void    patch_pc(Thread* thread, address pc);
++        if ((config.vmVersionFeatures & config.loongarch64LAM) != 0) {
++            features.add(LoongArch64.CPUFeature.LAM);
++        }
 +
-+  public Frame sender(RegisterMap regMap, CodeBlob cb) {
-+    LOONGARCH64RegisterMap map = (LOONGARCH64RegisterMap) regMap;
++        if ((config.vmVersionFeatures & config.loongarch64LLSYNC) != 0) {
++            features.add(LoongArch64.CPUFeature.LLSYNC);
++        }
 +
-+    if (Assert.ASSERTS_ENABLED) {
-+      Assert.that(map != null, "map must be set");
-+    }
++        if ((config.vmVersionFeatures & config.loongarch64TGTSYNC) != 0) {
++            features.add(LoongArch64.CPUFeature.TGTSYNC);
++        }
 +
-+    // Default is we done have to follow them. The sender_for_xxx will
-+    // update it accordingly
-+    map.setIncludeArgumentOops(false);
++        if ((config.vmVersionFeatures & config.loongarch64ULSYNC) != 0) {
++            features.add(LoongArch64.CPUFeature.ULSYNC);
++        }
 +
-+    if (isEntryFrame())       return senderForEntryFrame(map);
-+    if (isInterpretedFrame()) return senderForInterpreterFrame(map);
++        if ((config.vmVersionFeatures & config.loongarch64UAL) != 0) {
++            features.add(LoongArch64.CPUFeature.UAL);
++        }
 +
-+    if(cb == null) {
-+      cb = VM.getVM().getCodeCache().findBlob(getPC());
-+    } else {
-+      if (Assert.ASSERTS_ENABLED) {
-+        Assert.that(cb.equals(VM.getVM().getCodeCache().findBlob(getPC())), "Must be the same");
-+      }
++        return features;
 +    }
 +
-+    if (cb != null) {
-+      return senderForCompiledFrame(map, cb);
-+    }
++    protected EnumSet computeFlags(@SuppressWarnings("unused") LoongArch64HotSpotVMConfig config) {
++        EnumSet flags = EnumSet.noneOf(LoongArch64.Flag.class);
 +
-+    // Must be native-compiled frame, i.e. the marshaling code for native
-+    // methods that exists in the core system.
-+    return new LOONGARCH64Frame(getSenderSP(), getLink(), getSenderPC());
-+  }
++        if (config.useLSX) {
++            flags.add(LoongArch64.Flag.useLSX);
++        }
 +
-+  private Frame senderForEntryFrame(LOONGARCH64RegisterMap map) {
-+    if (DEBUG) {
-+      System.out.println("senderForEntryFrame");
++        if (config.useLASX) {
++            flags.add(LoongArch64.Flag.useLASX);
++        }
++
++        return flags;
 +    }
-+    if (Assert.ASSERTS_ENABLED) {
-+      Assert.that(map != null, "map must be set");
++
++    protected TargetDescription createTarget(LoongArch64HotSpotVMConfig config) {
++        final int stackFrameAlignment = 16;
++        final int implicitNullCheckLimit = 4096;
++        final boolean inlineObjects = true;
++        Architecture arch = new LoongArch64(computeFeatures(config), computeFlags(config));
++        return new TargetDescription(arch, true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects);
 +    }
-+    // Java frame called from C; skip all C frames and return top C
-+    // frame of that chunk as the sender
-+    LOONGARCH64JavaCallWrapper jcw = (LOONGARCH64JavaCallWrapper) getEntryFrameCallWrapper();
-+    if (Assert.ASSERTS_ENABLED) {
-+      Assert.that(!entryFrameIsFirst(), "next Java fp must be non zero");
-+      Assert.that(jcw.getLastJavaSP().greaterThan(getSP()), "must be above this frame on stack");
++
++    protected HotSpotConstantReflectionProvider createConstantReflection(HotSpotJVMCIRuntime runtime) {
++        return new HotSpotConstantReflectionProvider(runtime);
 +    }
-+    LOONGARCH64Frame fr;
-+    if (jcw.getLastJavaPC() != null) {
-+      fr = new LOONGARCH64Frame(jcw.getLastJavaSP(), jcw.getLastJavaFP(), jcw.getLastJavaPC());
-+    } else {
-+      fr = new LOONGARCH64Frame(jcw.getLastJavaSP(), jcw.getLastJavaFP());
++
++    protected RegisterConfig createRegisterConfig(LoongArch64HotSpotVMConfig config, TargetDescription target) {
++        return new LoongArch64HotSpotRegisterConfig(target, config.useCompressedOops);
 +    }
-+    map.clear();
-+    if (Assert.ASSERTS_ENABLED) {
-+      Assert.that(map.getIncludeArgumentOops(), "should be set by clear");
++
++    protected HotSpotCodeCacheProvider createCodeCache(HotSpotJVMCIRuntime runtime, TargetDescription target, RegisterConfig regConfig) {
++        return new HotSpotCodeCacheProvider(runtime, runtime.getConfig(), target, regConfig);
 +    }
-+    return fr;
-+  }
 +
-+  //------------------------------------------------------------------------------
-+  // frame::adjust_unextended_sp
-+  private void adjustUnextendedSP() {
-+    // On loongarch, sites calling method handle intrinsics and lambda forms are treated
-+    // as any other call site. Therefore, no special action is needed when we are
-+    // returning to any of these call sites.
++    protected HotSpotMetaAccessProvider createMetaAccess(HotSpotJVMCIRuntime runtime) {
++        return new HotSpotMetaAccessProvider(runtime);
++    }
 +
-+    CodeBlob cb = cb();
-+    NMethod senderNm = (cb == null) ? null : cb.asNMethodOrNull();
-+    if (senderNm != null) {
-+      // If the sender PC is a deoptimization point, get the original PC.
-+      if (senderNm.isDeoptEntry(getPC()) ||
-+          senderNm.isDeoptMhEntry(getPC())) {
-+        // DEBUG_ONLY(verifyDeoptriginalPc(senderNm, raw_unextendedSp));
-+      }
++    @Override
++    public String getArchitecture() {
++        return "loongarch64";
 +    }
-+  }
 +
-+  private Frame senderForInterpreterFrame(LOONGARCH64RegisterMap map) {
-+    if (DEBUG) {
-+      System.out.println("senderForInterpreterFrame");
++    @Override
++    public String toString() {
++        return "JVMCIBackend:" + getArchitecture();
 +    }
-+    Address unextendedSP = addressOfStackSlot(INTERPRETER_FRAME_SENDER_SP_OFFSET).getAddressAt(0);
-+    Address sp = getSenderSP();
-+    // We do not need to update the callee-save register mapping because above
-+    // us is either another interpreter frame or a converter-frame, but never
-+    // directly a compiled frame.
-+    // 11/24/04 SFG. With the removal of adapter frames this is no longer true.
-+    // However c2 no longer uses callee save register for java calls so there
-+    // are no callee register to find.
 +
-+    if (map.getUpdateMap())
-+      updateMapWithSavedLink(map, addressOfStackSlot(JAVA_FRAME_LINK_OFFSET));
++    @Override
++    @SuppressWarnings("try")
++    public JVMCIBackend createJVMCIBackend(HotSpotJVMCIRuntime runtime, JVMCIBackend host) {
 +
-+    return new LOONGARCH64Frame(sp, unextendedSP, getLink(), getSenderPC());
-+  }
++        assert host == null;
++        LoongArch64HotSpotVMConfig config = new LoongArch64HotSpotVMConfig(runtime.getConfigStore());
++        TargetDescription target = createTarget(config);
 +
-+  private void updateMapWithSavedLink(RegisterMap map, Address savedFPAddr) {
-+    map.setLocation(fp, savedFPAddr);
-+  }
++        RegisterConfig regConfig;
++        HotSpotCodeCacheProvider codeCache;
++        ConstantReflectionProvider constantReflection;
++        HotSpotMetaAccessProvider metaAccess;
++        StackIntrospection stackIntrospection;
++        try (InitTimer t = timer("create providers")) {
++            try (InitTimer rt = timer("create MetaAccess provider")) {
++                metaAccess = createMetaAccess(runtime);
++            }
++            try (InitTimer rt = timer("create RegisterConfig")) {
++                regConfig = createRegisterConfig(config, target);
++            }
++            try (InitTimer rt = timer("create CodeCache provider")) {
++                codeCache = createCodeCache(runtime, target, regConfig);
++            }
++            try (InitTimer rt = timer("create ConstantReflection provider")) {
++                constantReflection = createConstantReflection(runtime);
++            }
++            try (InitTimer rt = timer("create StackIntrospection provider")) {
++                stackIntrospection = new HotSpotStackIntrospection(runtime);
++            }
++        }
++        try (InitTimer rt = timer("instantiate backend")) {
++            return createBackend(metaAccess, codeCache, constantReflection, stackIntrospection);
++        }
++    }
 +
-+  private Frame senderForCompiledFrame(LOONGARCH64RegisterMap map, CodeBlob cb) {
-+    if (DEBUG) {
-+      System.out.println("senderForCompiledFrame");
++    protected JVMCIBackend createBackend(HotSpotMetaAccessProvider metaAccess, HotSpotCodeCacheProvider codeCache, ConstantReflectionProvider constantReflection,
++                    StackIntrospection stackIntrospection) {
++        return new JVMCIBackend(metaAccess, codeCache, constantReflection, stackIntrospection);
 +    }
++}
+diff --git a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot.loongarch64/src/jdk/vm/ci/hotspot/loongarch64/LoongArch64HotSpotRegisterConfig.java b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot.loongarch64/src/jdk/vm/ci/hotspot/loongarch64/LoongArch64HotSpotRegisterConfig.java
+new file mode 100644
+index 000000000..2ee6a4b84
+--- /dev/null
++++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot.loongarch64/src/jdk/vm/ci/hotspot/loongarch64/LoongArch64HotSpotRegisterConfig.java
+@@ -0,0 +1,297 @@
++/*
++ * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2022, Loongson Technology. All rights reserved.
++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
++ *
++ * This code is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 only, as
++ * published by the Free Software Foundation.
++ *
++ * This code is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * version 2 for more details (a copy is included in the LICENSE file that
++ * accompanied this code).
++ *
++ * You should have received a copy of the GNU General Public License version
++ * 2 along with this work; if not, write to the Free Software Foundation,
++ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
++ *
++ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
++ * or visit www.oracle.com if you need additional information or have any
++ * questions.
++ */
++package jdk.vm.ci.hotspot.loongarch64;
 +
-+    //
-+    // NOTE: some of this code is (unfortunately) duplicated in LOONGARCH64CurrentFrameGuess
-+    //
++import static jdk.vm.ci.loongarch64.LoongArch64.ra;
++import static jdk.vm.ci.loongarch64.LoongArch64.a0;
++import static jdk.vm.ci.loongarch64.LoongArch64.a1;
++import static jdk.vm.ci.loongarch64.LoongArch64.a2;
++import static jdk.vm.ci.loongarch64.LoongArch64.a3;
++import static jdk.vm.ci.loongarch64.LoongArch64.a4;
++import static jdk.vm.ci.loongarch64.LoongArch64.a5;
++import static jdk.vm.ci.loongarch64.LoongArch64.a6;
++import static jdk.vm.ci.loongarch64.LoongArch64.a7;
++import static jdk.vm.ci.loongarch64.LoongArch64.SCR1;
++import static jdk.vm.ci.loongarch64.LoongArch64.SCR2;
++import static jdk.vm.ci.loongarch64.LoongArch64.t0;
++import static jdk.vm.ci.loongarch64.LoongArch64.v0;
++import static jdk.vm.ci.loongarch64.LoongArch64.s5;
++import static jdk.vm.ci.loongarch64.LoongArch64.s6;
++import static jdk.vm.ci.loongarch64.LoongArch64.sp;
++import static jdk.vm.ci.loongarch64.LoongArch64.fp;
++import static jdk.vm.ci.loongarch64.LoongArch64.tp;
++import static jdk.vm.ci.loongarch64.LoongArch64.rx;
++import static jdk.vm.ci.loongarch64.LoongArch64.f0;
++import static jdk.vm.ci.loongarch64.LoongArch64.f1;
++import static jdk.vm.ci.loongarch64.LoongArch64.f2;
++import static jdk.vm.ci.loongarch64.LoongArch64.f3;
++import static jdk.vm.ci.loongarch64.LoongArch64.f4;
++import static jdk.vm.ci.loongarch64.LoongArch64.f5;
++import static jdk.vm.ci.loongarch64.LoongArch64.f6;
++import static jdk.vm.ci.loongarch64.LoongArch64.f7;
++import static jdk.vm.ci.loongarch64.LoongArch64.fv0;
++import static jdk.vm.ci.loongarch64.LoongArch64.zero;
 +
-+    if (Assert.ASSERTS_ENABLED) {
-+      Assert.that(map != null, "map must be set");
-+    }
++import java.util.ArrayList;
++import java.util.HashSet;
++import java.util.List;
++import java.util.Set;
 +
-+    // frame owned by optimizing compiler
-+    if (Assert.ASSERTS_ENABLED) {
-+        Assert.that(cb.getFrameSize() >= 0, "must have non-zero frame size");
-+    }
-+    Address senderSP = getUnextendedSP().addOffsetTo(cb.getFrameSize());
++import jdk.vm.ci.loongarch64.LoongArch64;
++import jdk.vm.ci.code.Architecture;
++import jdk.vm.ci.code.CallingConvention;
++import jdk.vm.ci.code.CallingConvention.Type;
++import jdk.vm.ci.code.Register;
++import jdk.vm.ci.code.RegisterArray;
++import jdk.vm.ci.code.RegisterAttributes;
++import jdk.vm.ci.code.RegisterConfig;
++import jdk.vm.ci.code.StackSlot;
++import jdk.vm.ci.code.TargetDescription;
++import jdk.vm.ci.code.ValueKindFactory;
++import jdk.vm.ci.common.JVMCIError;
++import jdk.vm.ci.hotspot.HotSpotCallingConventionType;
++import jdk.vm.ci.meta.AllocatableValue;
++import jdk.vm.ci.meta.JavaKind;
++import jdk.vm.ci.meta.JavaType;
++import jdk.vm.ci.meta.PlatformKind;
++import jdk.vm.ci.meta.Value;
++import jdk.vm.ci.meta.ValueKind;
 +
-+    // On Intel the return_address is always the word on the stack
-+    Address senderPC = senderSP.getAddressAt(-1 * VM.getVM().getAddressSize());
++public class LoongArch64HotSpotRegisterConfig implements RegisterConfig {
 +
-+    // This is the saved value of EBP which may or may not really be an FP.
-+    // It is only an FP if the sender is an interpreter frame (or C1?).
-+    Address savedFPAddr = senderSP.addOffsetTo(- JAVA_FRAME_SENDER_SP_OFFSET * VM.getVM().getAddressSize());
++    private final TargetDescription target;
 +
-+    if (map.getUpdateMap()) {
-+      // Tell GC to use argument oopmaps for some runtime stubs that need it.
-+      // For C1, the runtime stub might not have oop maps, so set this flag
-+      // outside of update_register_map.
-+      map.setIncludeArgumentOops(cb.callerMustGCArguments());
++    private final RegisterArray allocatable;
 +
-+      if (cb.getOopMaps() != null) {
-+        ImmutableOopMapSet.updateRegisterMap(this, cb, map, true);
-+      }
++    /**
++     * The caller saved registers always include all parameter registers.
++     */
++    private final RegisterArray callerSaved;
 +
-+      // Since the prolog does the save and restore of EBP there is no oopmap
-+      // for it so we must fill in its location as if there was an oopmap entry
-+      // since if our caller was compiled code there could be live jvm state in it.
-+      updateMapWithSavedLink(map, savedFPAddr);
-+    }
++    private final boolean allAllocatableAreCallerSaved;
 +
-+    return new LOONGARCH64Frame(senderSP, savedFPAddr.getAddressAt(0), senderPC);
-+  }
++    private final RegisterAttributes[] attributesMap;
 +
-+  protected boolean hasSenderPD() {
-+    // FIXME
-+    // Check for null ebp? Need to do some tests.
-+    return true;
-+  }
++    @Override
++    public RegisterArray getAllocatableRegisters() {
++        return allocatable;
++    }
 +
-+  public long frameSize() {
-+    return (getSenderSP().minus(getSP()) / VM.getVM().getAddressSize());
-+  }
++    @Override
++    public RegisterArray filterAllocatableRegisters(PlatformKind kind, RegisterArray registers) {
++        ArrayList list = new ArrayList<>();
++        for (Register reg : registers) {
++            if (target.arch.canStoreValue(reg.getRegisterCategory(), kind)) {
++                list.add(reg);
++            }
++        }
 +
-+  public Address getLink() {
-+    if (isJavaFrame())
-+      return addressOfStackSlot(JAVA_FRAME_LINK_OFFSET).getAddressAt(0);
-+    return addressOfStackSlot(NATIVE_FRAME_LINK_OFFSET).getAddressAt(0);
-+  }
++        return new RegisterArray(list);
++    }
 +
-+  public Address getUnextendedSP() { return raw_unextendedSP; }
++    @Override
++    public RegisterAttributes[] getAttributesMap() {
++        return attributesMap.clone();
++    }
 +
-+  // Return address:
-+  public Address getSenderPCAddr() {
-+    if (isJavaFrame())
-+      return addressOfStackSlot(JAVA_FRAME_RETURN_ADDR_OFFSET);
-+    return addressOfStackSlot(NATIVE_FRAME_RETURN_ADDR_OFFSET);
-+  }
++    private final RegisterArray javaGeneralParameterRegisters = new RegisterArray(t0, a0, a1, a2, a3, a4, a5, a6, a7);
++    private final RegisterArray nativeGeneralParameterRegisters = new RegisterArray(a0, a1, a2, a3, a4, a5, a6, a7);
++    private final RegisterArray floatParameterRegisters = new RegisterArray(f0, f1, f2, f3, f4, f5, f6, f7);
 +
-+  public Address getSenderPC()     { return getSenderPCAddr().getAddressAt(0);      }
++    public static final Register heapBaseRegister = s5;
++    public static final Register TREG = s6;
 +
-+  public Address getSenderSP()     {
-+    if (isJavaFrame())
-+      return addressOfStackSlot(JAVA_FRAME_SENDER_SP_OFFSET);
-+    return addressOfStackSlot(NATIVE_FRAME_SENDER_SP_OFFSET);
-+  }
++    private static final RegisterArray reservedRegisters = new RegisterArray(fp, ra, zero, sp, tp, rx, SCR1, SCR2, TREG);
 +
-+  public Address addressOfInterpreterFrameLocals() {
-+    return addressOfStackSlot(INTERPRETER_FRAME_LOCALS_OFFSET);
-+  }
++    private static RegisterArray initAllocatable(Architecture arch, boolean reserveForHeapBase) {
++        RegisterArray allRegisters = arch.getAvailableValueRegisters();
++        Register[] registers = new Register[allRegisters.size() - reservedRegisters.size() - (reserveForHeapBase ? 1 : 0)];
++        List reservedRegistersList = reservedRegisters.asList();
 +
-+  private Address addressOfInterpreterFrameBCX() {
-+    return addressOfStackSlot(INTERPRETER_FRAME_BCX_OFFSET);
-+  }
++        int idx = 0;
++        for (Register reg : allRegisters) {
++            if (reservedRegistersList.contains(reg)) {
++                // skip reserved registers
++                continue;
++            }
++            if (reserveForHeapBase && reg.equals(heapBaseRegister)) {
++                // skip heap base register
++                continue;
++            }
 +
-+  public int getInterpreterFrameBCI() {
-+    // FIXME: this is not atomic with respect to GC and is unsuitable
-+    // for use in a non-debugging, or reflective, system. Need to
-+    // figure out how to express this.
-+    Address bcp = addressOfInterpreterFrameBCX().getAddressAt(0);
-+    Address methodHandle = addressOfInterpreterFrameMethod().getAddressAt(0);
-+    Method method = (Method)Metadata.instantiateWrapperFor(methodHandle);
-+    return bcpToBci(bcp, method);
-+  }
++            registers[idx++] = reg;
++        }
 +
-+  public Address addressOfInterpreterFrameMDX() {
-+    return addressOfStackSlot(INTERPRETER_FRAME_MDX_OFFSET);
-+  }
++        assert idx == registers.length;
++        return new RegisterArray(registers);
++    }
 +
-+  // FIXME
-+  //inline int frame::interpreter_frame_monitor_size() {
-+  //  return BasicObjectLock::size();
-+  //}
++    public LoongArch64HotSpotRegisterConfig(TargetDescription target, boolean useCompressedOops) {
++        this(target, initAllocatable(target.arch, useCompressedOops));
++        assert callerSaved.size() >= allocatable.size();
++    }
 +
-+  // expression stack
-+  // (the max_stack arguments are used by the GC; see class FrameClosure)
++    public LoongArch64HotSpotRegisterConfig(TargetDescription target, RegisterArray allocatable) {
++        this.target = target;
 +
-+  public Address addressOfInterpreterFrameExpressionStack() {
-+    Address monitorEnd = interpreterFrameMonitorEnd().address();
-+    return monitorEnd.addOffsetTo(-1 * VM.getVM().getAddressSize());
-+  }
++        this.allocatable = allocatable;
++        Set callerSaveSet = new HashSet<>();
++        allocatable.addTo(callerSaveSet);
++        floatParameterRegisters.addTo(callerSaveSet);
++        javaGeneralParameterRegisters.addTo(callerSaveSet);
++        nativeGeneralParameterRegisters.addTo(callerSaveSet);
++        callerSaved = new RegisterArray(callerSaveSet);
 +
-+  public int getInterpreterFrameExpressionStackDirection() { return -1; }
++        allAllocatableAreCallerSaved = true;
++        attributesMap = RegisterAttributes.createMap(this, LoongArch64.allRegisters);
++    }
 +
-+  // top of expression stack
-+  public Address addressOfInterpreterFrameTOS() {
-+    return getSP();
-+  }
++    @Override
++    public RegisterArray getCallerSaveRegisters() {
++        return callerSaved;
++    }
 +
-+  /** Expression stack from top down */
-+  public Address addressOfInterpreterFrameTOSAt(int slot) {
-+    return addressOfInterpreterFrameTOS().addOffsetTo(slot * VM.getVM().getAddressSize());
-+  }
++    @Override
++    public RegisterArray getCalleeSaveRegisters() {
++        return null;
++    }
 +
-+  public Address getInterpreterFrameSenderSP() {
-+    if (Assert.ASSERTS_ENABLED) {
-+      Assert.that(isInterpretedFrame(), "interpreted frame expected");
++    @Override
++    public boolean areAllAllocatableRegistersCallerSaved() {
++        return allAllocatableAreCallerSaved;
 +    }
-+    return addressOfStackSlot(INTERPRETER_FRAME_SENDER_SP_OFFSET).getAddressAt(0);
-+  }
 +
-+  // Monitors
-+  public BasicObjectLock interpreterFrameMonitorBegin() {
-+    return new BasicObjectLock(addressOfStackSlot(INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET));
-+  }
++    @Override
++    public CallingConvention getCallingConvention(Type type, JavaType returnType, JavaType[] parameterTypes, ValueKindFactory valueKindFactory) {
++        HotSpotCallingConventionType hotspotType = (HotSpotCallingConventionType) type;
++        if (type == HotSpotCallingConventionType.NativeCall) {
++            return callingConvention(nativeGeneralParameterRegisters, returnType, parameterTypes, hotspotType, valueKindFactory);
++        }
++        // On x64, parameter locations are the same whether viewed
++        // from the caller or callee perspective
++        return callingConvention(javaGeneralParameterRegisters, returnType, parameterTypes, hotspotType, valueKindFactory);
++    }
 +
-+  public BasicObjectLock interpreterFrameMonitorEnd() {
-+    Address result = addressOfStackSlot(INTERPRETER_FRAME_MONITOR_BLOCK_TOP_OFFSET).getAddressAt(0);
-+    if (Assert.ASSERTS_ENABLED) {
-+      // make sure the pointer points inside the frame
-+      Assert.that(AddressOps.gt(getFP(), result), "result must <  than frame pointer");
-+      Assert.that(AddressOps.lte(getSP(), result), "result must >= than stack pointer");
++    @Override
++    public RegisterArray getCallingConventionRegisters(Type type, JavaKind kind) {
++        HotSpotCallingConventionType hotspotType = (HotSpotCallingConventionType) type;
++        switch (kind) {
++            case Boolean:
++            case Byte:
++            case Short:
++            case Char:
++            case Int:
++            case Long:
++            case Object:
++                return hotspotType == HotSpotCallingConventionType.NativeCall ? nativeGeneralParameterRegisters : javaGeneralParameterRegisters;
++            case Float:
++            case Double:
++                return floatParameterRegisters;
++            default:
++                throw JVMCIError.shouldNotReachHere();
++        }
 +    }
-+    return new BasicObjectLock(result);
-+  }
 +
-+  public int interpreterFrameMonitorSize() {
-+    return BasicObjectLock.size();
-+  }
++    private CallingConvention callingConvention(RegisterArray generalParameterRegisters, JavaType returnType, JavaType[] parameterTypes, HotSpotCallingConventionType type,
++                    ValueKindFactory valueKindFactory) {
++        AllocatableValue[] locations = new AllocatableValue[parameterTypes.length];
 +
-+  // Method
-+  public Address addressOfInterpreterFrameMethod() {
-+    return addressOfStackSlot(INTERPRETER_FRAME_METHOD_OFFSET);
-+  }
++        int currentGeneral = 0;
++        int currentFloat = 0;
++        int currentStackOffset = 0;
 +
-+  // Constant pool cache
-+  public Address addressOfInterpreterFrameCPCache() {
-+    return addressOfStackSlot(INTERPRETER_FRAME_CACHE_OFFSET);
-+  }
++        for (int i = 0; i < parameterTypes.length; i++) {
++            final JavaKind kind = parameterTypes[i].getJavaKind().getStackKind();
 +
-+  // Entry frames
-+  public JavaCallWrapper getEntryFrameCallWrapper() {
-+    return new LOONGARCH64JavaCallWrapper(addressOfStackSlot(ENTRY_FRAME_CALL_WRAPPER_OFFSET).getAddressAt(0));
-+  }
++            switch (kind) {
++                case Byte:
++                case Boolean:
++                case Short:
++                case Char:
++                case Int:
++                case Long:
++                case Object:
++                    if (currentGeneral < generalParameterRegisters.size()) {
++                        Register register = generalParameterRegisters.get(currentGeneral++);
++                        locations[i] = register.asValue(valueKindFactory.getValueKind(kind));
++                    }
++                    break;
++                case Float:
++                case Double:
++                    if (currentFloat < floatParameterRegisters.size()) {
++                        Register register = floatParameterRegisters.get(currentFloat++);
++                        locations[i] = register.asValue(valueKindFactory.getValueKind(kind));
++                    } else if (currentGeneral < generalParameterRegisters.size()) {
++                        Register register = generalParameterRegisters.get(currentGeneral++);
++                        locations[i] = register.asValue(valueKindFactory.getValueKind(kind));
++                    }
++                    break;
++                default:
++                    throw JVMCIError.shouldNotReachHere();
++            }
 +
-+  protected Address addressOfSavedOopResult() {
-+    // offset is 2 for compiler2 and 3 for compiler1
-+    return getSP().addOffsetTo((VM.getVM().isClientCompiler() ? 2 : 3) *
-+                               VM.getVM().getAddressSize());
-+  }
++            if (locations[i] == null) {
++                ValueKind valueKind = valueKindFactory.getValueKind(kind);
++                locations[i] = StackSlot.get(valueKind, currentStackOffset, !type.out);
++                currentStackOffset += Math.max(valueKind.getPlatformKind().getSizeInBytes(), target.wordSize);
++            }
++        }
 +
-+  protected Address addressOfSavedReceiver() {
-+    return getSP().addOffsetTo(-4 * VM.getVM().getAddressSize());
-+  }
++        JavaKind returnKind = returnType == null ? JavaKind.Void : returnType.getJavaKind();
++        AllocatableValue returnLocation = returnKind == JavaKind.Void ? Value.ILLEGAL : getReturnRegister(returnKind).asValue(valueKindFactory.getValueKind(returnKind.getStackKind()));
++        return new CallingConvention(currentStackOffset, returnLocation, locations);
++    }
 +
-+  private void dumpStack() {
-+    if (getFP() != null) {
-+      for (Address addr = getSP().addOffsetTo(-5 * VM.getVM().getAddressSize());
-+           AddressOps.lte(addr, getFP().addOffsetTo(5 * VM.getVM().getAddressSize()));
-+           addr = addr.addOffsetTo(VM.getVM().getAddressSize())) {
-+        System.out.println(addr + ": " + addr.getAddressAt(0));
-+      }
-+    } else {
-+      for (Address addr = getSP().addOffsetTo(-5 * VM.getVM().getAddressSize());
-+           AddressOps.lte(addr, getSP().addOffsetTo(20 * VM.getVM().getAddressSize()));
-+           addr = addr.addOffsetTo(VM.getVM().getAddressSize())) {
-+        System.out.println(addr + ": " + addr.getAddressAt(0));
-+      }
++    @Override
++    public Register getReturnRegister(JavaKind kind) {
++        switch (kind) {
++            case Boolean:
++            case Byte:
++            case Char:
++            case Short:
++            case Int:
++            case Long:
++            case Object:
++                return v0;
++            case Float:
++            case Double:
++                return fv0;
++            case Void:
++            case Illegal:
++                return null;
++            default:
++                throw new UnsupportedOperationException("no return register for type " + kind);
++        }
++    }
++
++    @Override
++    public Register getFrameRegister() {
++        return sp;
++    }
++
++    @Override
++    public String toString() {
++        return String.format("Allocatable: " + getAllocatableRegisters() + "%n" + "CallerSave:  " + getCallerSaveRegisters() + "%n");
 +    }
-+  }
 +}
-diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/loongarch64/LOONGARCH64JavaCallWrapper.java jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/loongarch64/LOONGARCH64JavaCallWrapper.java
---- openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/loongarch64/LOONGARCH64JavaCallWrapper.java	1970-01-01 08:00:00.000000000 +0800
-+++ jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/loongarch64/LOONGARCH64JavaCallWrapper.java	2023-09-12 13:54:26.429575856 +0800
-@@ -0,0 +1,57 @@
+diff --git a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot.loongarch64/src/jdk/vm/ci/hotspot/loongarch64/LoongArch64HotSpotVMConfig.java b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot.loongarch64/src/jdk/vm/ci/hotspot/loongarch64/LoongArch64HotSpotVMConfig.java
+new file mode 100644
+index 000000000..c8605976a
+--- /dev/null
++++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot.loongarch64/src/jdk/vm/ci/hotspot/loongarch64/LoongArch64HotSpotVMConfig.java
+@@ -0,0 +1,77 @@
 +/*
-+ * Copyright (c) 2001, 2002, Oracle and/or its affiliates. All rights reserved.
-+ * Copyright (c) 2018, 2021, Loongson Technology. All rights reserved.
++ * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2022, Loongson Technology. 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
@@ -117931,48 +198312,70 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.hotspot.agent/shar
 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 + * or visit www.oracle.com if you need additional information or have any
 + * questions.
-+ *
 + */
++package jdk.vm.ci.hotspot.loongarch64;
 +
-+package sun.jvm.hotspot.runtime.loongarch64;
++import jdk.vm.ci.hotspot.HotSpotVMConfigAccess;
++import jdk.vm.ci.hotspot.HotSpotVMConfigStore;
++import jdk.vm.ci.services.Services;
 +
-+import java.util.*;
-+import sun.jvm.hotspot.debugger.*;
-+import sun.jvm.hotspot.types.*;
-+import sun.jvm.hotspot.runtime.*;
++/**
++ * Used to access native configuration details.
++ *
++ * All non-static, public fields in this class are so that they can be compiled as constants.
++ */
++class LoongArch64HotSpotVMConfig extends HotSpotVMConfigAccess {
 +
-+public class LOONGARCH64JavaCallWrapper extends JavaCallWrapper {
-+  private static AddressField lastJavaFPField;
++    LoongArch64HotSpotVMConfig(HotSpotVMConfigStore config) {
++        super(config);
++    }
 +
-+  static {
-+    VM.registerVMInitializedObserver(new Observer() {
-+        public void update(Observable o, Object data) {
-+          initialize(VM.getVM().getTypeDataBase());
-+        }
-+      });
-+  }
++    final boolean useCompressedOops = getFlag("UseCompressedOops", Boolean.class);
 +
-+  private static synchronized void initialize(TypeDataBase db) {
-+    Type type = db.lookupType("JavaFrameAnchor");
++    // CPU Capabilities
 +
-+    lastJavaFPField  = type.getAddressField("_last_Java_fp");
-+  }
++    /*
++     * These flags are set based on the corresponding command line flags.
++     */
++    final boolean useLSX = getFlag("UseLSX", Boolean.class);
++    final boolean useLASX = getFlag("UseLASX", Boolean.class);
 +
-+  public LOONGARCH64JavaCallWrapper(Address addr) {
-+    super(addr);
-+  }
++    final long vmVersionFeatures = getFieldValue("Abstract_VM_Version::_features", Long.class, "uint64_t");
 +
-+  public Address getLastJavaFP() {
-+    return lastJavaFPField.getValue(addr.addOffsetTo(anchorField.getOffset()));
-+  }
++    /*
++     * These flags are set if the corresponding support is in the hardware.
++     */
++    // Checkstyle: stop
++    final long loongarch64LA32 = getConstant("VM_Version::CPU_LA32", Long.class);
++    final long loongarch64LA64 = getConstant("VM_Version::CPU_LA64", Long.class);
++    final long loongarch64LLEXC = getConstant("VM_Version::CPU_LLEXC", Long.class);
++    final long loongarch64SCDLY = getConstant("VM_Version::CPU_SCDLY", Long.class);
++    final long loongarch64LLDBAR = getConstant("VM_Version::CPU_LLDBAR", Long.class);
++    final long loongarch64LBT_X86 = getConstant("VM_Version::CPU_LBT_X86", Long.class);
++    final long loongarch64LBT_ARM = getConstant("VM_Version::CPU_LBT_ARM", Long.class);
++    final long loongarch64LBT_MIPS = getConstant("VM_Version::CPU_LBT_MIPS", Long.class);
++    final long loongarch64CCDMA = getConstant("VM_Version::CPU_CCDMA", Long.class);
++    final long loongarch64COMPLEX = getConstant("VM_Version::CPU_COMPLEX", Long.class);
++    final long loongarch64FP = getConstant("VM_Version::CPU_FP", Long.class);
++    final long loongarch64CRYPTO = getConstant("VM_Version::CPU_CRYPTO", Long.class);
++    final long loongarch64LSX = getConstant("VM_Version::CPU_LSX", Long.class);
++    final long loongarch64LASX = getConstant("VM_Version::CPU_LASX", Long.class);
++    final long loongarch64LAM = getConstant("VM_Version::CPU_LAM", Long.class);
++    final long loongarch64LLSYNC = getConstant("VM_Version::CPU_LLSYNC", Long.class);
++    final long loongarch64TGTSYNC = getConstant("VM_Version::CPU_TGTSYNC", Long.class);
++    final long loongarch64ULSYNC = getConstant("VM_Version::CPU_ULSYNC", Long.class);
++    final long loongarch64UAL = getConstant("VM_Version::CPU_UAL", Long.class);
++    // Checkstyle: resume
 +}
-diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/loongarch64/LOONGARCH64RegisterMap.java jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/loongarch64/LOONGARCH64RegisterMap.java
---- openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/loongarch64/LOONGARCH64RegisterMap.java	1970-01-01 08:00:00.000000000 +0800
-+++ jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/loongarch64/LOONGARCH64RegisterMap.java	2023-09-12 13:54:26.429575856 +0800
-@@ -0,0 +1,52 @@
+diff --git a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot.loongarch64/src/jdk/vm/ci/hotspot/loongarch64/package-info.java b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot.loongarch64/src/jdk/vm/ci/hotspot/loongarch64/package-info.java
+new file mode 100644
+index 000000000..1048ea9d6
+--- /dev/null
++++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot.loongarch64/src/jdk/vm/ci/hotspot/loongarch64/package-info.java
+@@ -0,0 +1,28 @@
 +/*
-+ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
-+ * Copyright (c) 2018, 2021, Loongson Technology. All rights reserved.
++ * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2022, Loongson Technology. 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
@@ -117992,43 +198395,274 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.hotspot.agent/shar
 + * 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.
++ */
++
++/**
++ * The LoongArch64 HotSpot specific portions of the JVMCI API.
++ */
++package jdk.vm.ci.hotspot.loongarch64;
+diff --git a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.loongarch64/src/jdk/vm/ci/loongarch64/LoongArch64.java b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.loongarch64/src/jdk/vm/ci/loongarch64/LoongArch64.java
+new file mode 100644
+index 000000000..1bb12e7a5
+--- /dev/null
++++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.loongarch64/src/jdk/vm/ci/loongarch64/LoongArch64.java
+@@ -0,0 +1,247 @@
++/*
++ * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2022, Loongson Technology. All rights reserved.
++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
++ *
++ * This code is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 only, as
++ * published by the Free Software Foundation.
++ *
++ * This code is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * version 2 for more details (a copy is included in the LICENSE file that
++ * accompanied this code).
++ *
++ * You should have received a copy of the GNU General Public License version
++ * 2 along with this work; if not, write to the Free Software Foundation,
++ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 + *
++ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
++ * or visit www.oracle.com if you need additional information or have any
++ * questions.
 + */
++package jdk.vm.ci.loongarch64;
 +
-+package sun.jvm.hotspot.runtime.loongarch64;
++import java.nio.ByteOrder;
++import java.util.EnumSet;
 +
-+import sun.jvm.hotspot.debugger.*;
-+import sun.jvm.hotspot.runtime.*;
++import jdk.vm.ci.code.Architecture;
++import jdk.vm.ci.code.Register;
++import jdk.vm.ci.code.Register.RegisterCategory;
++import jdk.vm.ci.code.RegisterArray;
++import jdk.vm.ci.meta.JavaKind;
++import jdk.vm.ci.meta.PlatformKind;
 +
-+public class LOONGARCH64RegisterMap extends RegisterMap {
++/**
++ * Represents the LoongArch64 architecture.
++ */
++public class LoongArch64 extends Architecture {
 +
-+  /** This is the only public constructor */
-+  public LOONGARCH64RegisterMap(JavaThread thread, boolean updateMap) {
-+    super(thread, updateMap);
-+  }
++    public static final RegisterCategory CPU = new RegisterCategory("CPU");
 +
-+  protected LOONGARCH64RegisterMap(RegisterMap map) {
-+    super(map);
-+  }
++    // General purpose CPU registers
++    public static final Register zero = new Register(0, 0, "r0", CPU);
++    public static final Register ra = new Register(1, 1, "r1", CPU);
++    public static final Register tp = new Register(2, 2, "r2", CPU);
++    public static final Register sp = new Register(3, 3, "r3", CPU);
++    public static final Register a0 = new Register(4, 4, "r4", CPU);
++    public static final Register a1 = new Register(5, 5, "r5", CPU);
++    public static final Register a2 = new Register(6, 6, "r6", CPU);
++    public static final Register a3 = new Register(7, 7, "r7", CPU);
++    public static final Register a4 = new Register(8, 8, "r8", CPU);
++    public static final Register a5 = new Register(9, 9, "r9", CPU);
++    public static final Register a6 = new Register(10, 10, "r10", CPU);
++    public static final Register a7 = new Register(11, 11, "r11", CPU);
++    public static final Register t0 = new Register(12, 12, "r12", CPU);
++    public static final Register t1 = new Register(13, 13, "r13", CPU);
++    public static final Register t2 = new Register(14, 14, "r14", CPU);
++    public static final Register t3 = new Register(15, 15, "r15", CPU);
++    public static final Register t4 = new Register(16, 16, "r16", CPU);
++    public static final Register t5 = new Register(17, 17, "r17", CPU);
++    public static final Register t6 = new Register(18, 18, "r18", CPU);
++    public static final Register t7 = new Register(19, 19, "r19", CPU);
++    public static final Register t8 = new Register(20, 20, "r20", CPU);
++    public static final Register rx = new Register(21, 21, "r21", CPU);
++    public static final Register fp = new Register(22, 22, "r22", CPU);
++    public static final Register s0 = new Register(23, 23, "r23", CPU);
++    public static final Register s1 = new Register(24, 24, "r24", CPU);
++    public static final Register s2 = new Register(25, 25, "r25", CPU);
++    public static final Register s3 = new Register(26, 26, "r26", CPU);
++    public static final Register s4 = new Register(27, 27, "r27", CPU);
++    public static final Register s5 = new Register(28, 28, "r28", CPU);
++    public static final Register s6 = new Register(29, 29, "r29", CPU);
++    public static final Register s7 = new Register(30, 30, "r30", CPU);
++    public static final Register s8 = new Register(31, 31, "r31", CPU);
 +
-+  public Object clone() {
-+    LOONGARCH64RegisterMap retval = new LOONGARCH64RegisterMap(this);
-+    return retval;
-+  }
++    public static final Register SCR1 = t7;
++    public static final Register SCR2 = t4;
++    public static final Register v0 = a0;
 +
-+  // no PD state to clear or copy:
-+  protected void clearPD() {}
-+  protected void initializePD() {}
-+  protected void initializeFromPD(RegisterMap map) {}
-+  protected Address getLocationPD(VMReg reg) { return null; }
++    // @formatter:off
++    public static final RegisterArray cpuRegisters = new RegisterArray(
++        zero, ra,  tp,  sp,  a0,  a1,  a2,  a3,
++        a4,   a5,  a6,  a7,  t0,  t1,  t2,  t3,
++        t4,   t5,  t6,  t7,  t8,  rx,  fp,  s0,
++        s1,   s2,  s3,  s4,  s5,  s6,  s7,  s8
++    );
++    // @formatter:on
++
++    public static final RegisterCategory SIMD = new RegisterCategory("SIMD");
++
++    // Simd registers
++    public static final Register f0 = new Register(32, 0, "f0", SIMD);
++    public static final Register f1 = new Register(33, 1, "f1", SIMD);
++    public static final Register f2 = new Register(34, 2, "f2", SIMD);
++    public static final Register f3 = new Register(35, 3, "f3", SIMD);
++    public static final Register f4 = new Register(36, 4, "f4", SIMD);
++    public static final Register f5 = new Register(37, 5, "f5", SIMD);
++    public static final Register f6 = new Register(38, 6, "f6", SIMD);
++    public static final Register f7 = new Register(39, 7, "f7", SIMD);
++    public static final Register f8 = new Register(40, 8, "f8", SIMD);
++    public static final Register f9 = new Register(41, 9, "f9", SIMD);
++    public static final Register f10 = new Register(42, 10, "f10", SIMD);
++    public static final Register f11 = new Register(43, 11, "f11", SIMD);
++    public static final Register f12 = new Register(44, 12, "f12", SIMD);
++    public static final Register f13 = new Register(45, 13, "f13", SIMD);
++    public static final Register f14 = new Register(46, 14, "f14", SIMD);
++    public static final Register f15 = new Register(47, 15, "f15", SIMD);
++    public static final Register f16 = new Register(48, 16, "f16", SIMD);
++    public static final Register f17 = new Register(49, 17, "f17", SIMD);
++    public static final Register f18 = new Register(50, 18, "f18", SIMD);
++    public static final Register f19 = new Register(51, 19, "f19", SIMD);
++    public static final Register f20 = new Register(52, 20, "f20", SIMD);
++    public static final Register f21 = new Register(53, 21, "f21", SIMD);
++    public static final Register f22 = new Register(54, 22, "f22", SIMD);
++    public static final Register f23 = new Register(55, 23, "f23", SIMD);
++    public static final Register f24 = new Register(56, 24, "f24", SIMD);
++    public static final Register f25 = new Register(57, 25, "f25", SIMD);
++    public static final Register f26 = new Register(58, 26, "f26", SIMD);
++    public static final Register f27 = new Register(59, 27, "f27", SIMD);
++    public static final Register f28 = new Register(60, 28, "f28", SIMD);
++    public static final Register f29 = new Register(61, 29, "f29", SIMD);
++    public static final Register f30 = new Register(62, 30, "f30", SIMD);
++    public static final Register f31 = new Register(63, 31, "f31", SIMD);
++
++    public static final Register fv0 = f0;
++
++    // @formatter:off
++    public static final RegisterArray simdRegisters = new RegisterArray(
++        f0,  f1,  f2,  f3,  f4,  f5,  f6,  f7,
++        f8,  f9,  f10, f11, f12, f13, f14, f15,
++        f16, f17, f18, f19, f20, f21, f22, f23,
++        f24, f25, f26, f27, f28, f29, f30, f31
++    );
++    // @formatter:on
++
++    // @formatter:off
++    public static final RegisterArray allRegisters = new RegisterArray(
++        zero, ra,  tp,  sp,  a0,  a1,  a2,  a3,
++        a4,   a5,  a6,  a7,  t0,  t1,  t2,  t3,
++        t4,   t5,  t6,  t7,  t8,  rx,  fp,  s0,
++        s1,   s2,  s3,  s4,  s5,  s6,  s7,  s8,
++
++        f0,   f1,  f2,  f3,  f4,  f5,  f6,  f7,
++        f8,   f9,  f10, f11, f12, f13, f14, f15,
++        f16,  f17, f18, f19, f20, f21, f22, f23,
++        f24,  f25, f26, f27, f28, f29, f30, f31
++    );
++    // @formatter:on
++
++    /**
++     * Basic set of CPU features mirroring what is returned from the cpuid instruction. See:
++     * {@code VM_Version::cpuFeatureFlags}.
++     */
++    public enum CPUFeature {
++        LA32,
++        LA64,
++        LLEXC,
++        SCDLY,
++        LLDBAR,
++        LBT_X86,
++        LBT_ARM,
++        LBT_MIPS,
++        CCDMA,
++        COMPLEX,
++        FP,
++        CRYPTO,
++        LSX,
++        LASX,
++        LAM,
++        LLSYNC,
++        TGTSYNC,
++        ULSYNC,
++        UAL
++    }
++
++    private final EnumSet features;
++
++    /**
++     * Set of flags to control code emission.
++     */
++    public enum Flag {
++        useLSX,
++        useLASX
++    }
++
++    private final EnumSet flags;
++
++    public LoongArch64(EnumSet features, EnumSet flags) {
++        super("loongarch64", LoongArch64Kind.QWORD, ByteOrder.LITTLE_ENDIAN, true, allRegisters, 0, 0, 0);
++        this.features = features;
++        this.flags = flags;
++    }
++
++    public EnumSet getFeatures() {
++        return features;
++    }
++
++    public EnumSet getFlags() {
++        return flags;
++    }
++
++    @Override
++    public PlatformKind getPlatformKind(JavaKind javaKind) {
++        switch (javaKind) {
++            case Boolean:
++            case Byte:
++                return LoongArch64Kind.BYTE;
++            case Short:
++            case Char:
++                return LoongArch64Kind.WORD;
++            case Int:
++                return LoongArch64Kind.DWORD;
++            case Long:
++            case Object:
++                return LoongArch64Kind.QWORD;
++            case Float:
++                return LoongArch64Kind.SINGLE;
++            case Double:
++                return LoongArch64Kind.DOUBLE;
++            default:
++                return null;
++        }
++    }
++
++    @Override
++    public boolean canStoreValue(RegisterCategory category, PlatformKind platformKind) {
++        LoongArch64Kind kind = (LoongArch64Kind) platformKind;
++        if (kind.isInteger()) {
++            return category.equals(CPU);
++        } else if (kind.isSIMD()) {
++            return category.equals(SIMD);
++        }
++        return false;
++    }
++
++    @Override
++    public LoongArch64Kind getLargestStorableKind(RegisterCategory category) {
++        if (category.equals(CPU)) {
++            return LoongArch64Kind.QWORD;
++        } else if (category.equals(SIMD)) {
++            return LoongArch64Kind.V256_QWORD;
++        } else {
++            return null;
++        }
++    }
 +}
-diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/mips64/MIPS64CurrentFrameGuess.java jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/mips64/MIPS64CurrentFrameGuess.java
---- openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/mips64/MIPS64CurrentFrameGuess.java	1970-01-01 08:00:00.000000000 +0800
-+++ jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/mips64/MIPS64CurrentFrameGuess.java	2023-09-12 13:54:26.433575861 +0800
-@@ -0,0 +1,217 @@
+diff --git a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.loongarch64/src/jdk/vm/ci/loongarch64/LoongArch64Kind.java b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.loongarch64/src/jdk/vm/ci/loongarch64/LoongArch64Kind.java
+new file mode 100644
+index 000000000..84b7f2027
+--- /dev/null
++++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.loongarch64/src/jdk/vm/ci/loongarch64/LoongArch64Kind.java
+@@ -0,0 +1,163 @@
 +/*
-+ * Copyright (c) 2001, 2006, Oracle and/or its affiliates. All rights reserved.
-+ * Copyright (c) 2018, Loongson Technology. All rights reserved.
++ * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2022, Loongson Technology. 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
@@ -118048,208 +198682,1429 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.hotspot.agent/shar
 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 + * or visit www.oracle.com if you need additional information or have any
 + * questions.
-+ *
 + */
++package jdk.vm.ci.loongarch64;
 +
-+package sun.jvm.hotspot.runtime.mips64;
++import jdk.vm.ci.meta.PlatformKind;
 +
-+import sun.jvm.hotspot.debugger.*;
-+import sun.jvm.hotspot.debugger.mips64.*;
-+import sun.jvm.hotspot.code.*;
-+import sun.jvm.hotspot.interpreter.*;
-+import sun.jvm.hotspot.runtime.*;
++public enum LoongArch64Kind implements PlatformKind {
 +
-+/** 

Should be able to be used on all mips64 platforms we support -+ (Win32, Solaris/mips64, and soon Linux) to implement JavaThread's -+ "currentFrameGuess()" functionality. Input is an MIPS64ThreadContext; -+ output is SP, FP, and PC for an MIPS64Frame. Instantiation of the -+ MIPS64Frame is left to the caller, since we may need to subclass -+ MIPS64Frame to support signal handler frames on Unix platforms.

++ // scalar ++ BYTE(1), ++ WORD(2), ++ DWORD(4), ++ QWORD(8), ++ UBYTE(1), ++ UWORD(2), ++ UDWORD(4), ++ SINGLE(4), ++ DOUBLE(8), + -+

Algorithm is to walk up the stack within a given range (say, -+ 512K at most) looking for a plausible PC and SP for a Java frame, -+ also considering those coming in from the context. If we find a PC -+ that belongs to the VM (i.e., in generated code like the -+ interpreter or CodeCache) then we try to find an associated EBP. -+ We repeat this until we either find a complete frame or run out of -+ stack to look at.

*/ ++ // SIMD ++ V128_BYTE(16, BYTE), ++ V128_WORD(16, WORD), ++ V128_DWORD(16, DWORD), ++ V128_QWORD(16, QWORD), ++ V128_SINGLE(16, SINGLE), ++ V128_DOUBLE(16, DOUBLE), ++ V256_BYTE(32, BYTE), ++ V256_WORD(32, WORD), ++ V256_DWORD(32, DWORD), ++ V256_QWORD(32, QWORD), ++ V256_SINGLE(32, SINGLE), ++ V256_DOUBLE(32, DOUBLE); + -+public class MIPS64CurrentFrameGuess { -+ private MIPS64ThreadContext context; -+ private JavaThread thread; -+ private Address spFound; -+ private Address fpFound; -+ private Address pcFound; ++ private final int size; ++ private final int vectorLength; + -+ private static final boolean DEBUG = System.getProperty("sun.jvm.hotspot.runtime.mips64.MIPS64Frame.DEBUG") -+ != null; ++ private final LoongArch64Kind scalar; ++ private final EnumKey key = new EnumKey<>(this); + -+ public MIPS64CurrentFrameGuess(MIPS64ThreadContext context, -+ JavaThread thread) { -+ this.context = context; -+ this.thread = thread; -+ } ++ LoongArch64Kind(int size) { ++ this.size = size; ++ this.scalar = this; ++ this.vectorLength = 1; ++ } + -+ /** Returns false if not able to find a frame within a reasonable range. */ -+ public boolean run(long regionInBytesToSearch) { -+ Address sp = context.getRegisterAsAddress(MIPS64ThreadContext.SP); -+ Address pc = context.getRegisterAsAddress(MIPS64ThreadContext.PC); -+ Address fp = context.getRegisterAsAddress(MIPS64ThreadContext.FP); -+ if (sp == null) { -+ // Bail out if no last java frame eithe -+ if (thread.getLastJavaSP() != null) { -+ setValues(thread.getLastJavaSP(), thread.getLastJavaFP(), null); -+ return true; -+ } -+ // Bail out -+ return false; ++ LoongArch64Kind(int size, LoongArch64Kind scalar) { ++ this.size = size; ++ this.scalar = scalar; ++ ++ assert size % scalar.size == 0; ++ this.vectorLength = size / scalar.size; + } -+ Address end = sp.addOffsetTo(regionInBytesToSearch); -+ VM vm = VM.getVM(); + -+ setValues(null, null, null); // Assume we're not going to find anything ++ public LoongArch64Kind getScalar() { ++ return scalar; ++ } + -+ if (vm.isJavaPCDbg(pc)) { -+ if (vm.isClientCompiler()) { -+ // If the topmost frame is a Java frame, we are (pretty much) -+ // guaranteed to have a viable EBP. We should be more robust -+ // than this (we have the potential for losing entire threads' -+ // stack traces) but need to see how much work we really have -+ // to do here. Searching the stack for an (SP, FP) pair is -+ // hard since it's easy to misinterpret inter-frame stack -+ // pointers as base-of-frame pointers; we also don't know the -+ // sizes of C1 frames (not registered in the nmethod) so can't -+ // derive them from ESP. ++ @Override ++ public int getSizeInBytes() { ++ return size; ++ } + -+ setValues(sp, fp, pc); -+ return true; -+ } else { -+ if (vm.getInterpreter().contains(pc)) { -+ if (DEBUG) { -+ System.out.println("CurrentFrameGuess: choosing interpreter frame: sp = " + -+ sp + ", fp = " + fp + ", pc = " + pc); -+ } -+ setValues(sp, fp, pc); -+ return true; -+ } ++ @Override ++ public int getVectorLength() { ++ return vectorLength; ++ } + -+ // For the server compiler, EBP is not guaranteed to be valid -+ // for compiled code. In addition, an earlier attempt at a -+ // non-searching algorithm (see below) failed because the -+ // stack pointer from the thread context was pointing -+ // (considerably) beyond the ostensible end of the stack, into -+ // garbage; walking from the topmost frame back caused a crash. -+ // -+ // This algorithm takes the current PC as a given and tries to -+ // find the correct corresponding SP by walking up the stack -+ // and repeatedly performing stackwalks (very inefficient). -+ // -+ // FIXME: there is something wrong with stackwalking across -+ // adapter frames...this is likely to be the root cause of the -+ // failure with the simpler algorithm below. ++ @Override ++ public Key getKey() { ++ return key; ++ } + -+ for (long offset = 0; -+ offset < regionInBytesToSearch; -+ offset += vm.getAddressSize()) { -+ try { -+ Address curSP = sp.addOffsetTo(offset); -+ Frame frame = new MIPS64Frame(curSP, null, pc); -+ RegisterMap map = thread.newRegisterMap(false); -+ while (frame != null) { -+ if (frame.isEntryFrame() && frame.entryFrameIsFirst()) { -+ // We were able to traverse all the way to the -+ // bottommost Java frame. -+ // This sp looks good. Keep it. -+ if (DEBUG) { -+ System.out.println("CurrentFrameGuess: Choosing sp = " + curSP + ", pc = " + pc); -+ } -+ setValues(curSP, null, pc); ++ public boolean isInteger() { ++ switch (this) { ++ case BYTE: ++ case WORD: ++ case DWORD: ++ case QWORD: ++ case UBYTE: ++ case UWORD: ++ case UDWORD: + return true; -+ } -+ frame = frame.sender(map); -+ } -+ } catch (Exception e) { -+ if (DEBUG) { -+ System.out.println("CurrentFrameGuess: Exception " + e + " at offset " + offset); -+ } -+ // Bad SP. Try another. -+ } ++ default: ++ return false; + } ++ } + -+ // Were not able to find a plausible SP to go with this PC. -+ // Bail out. -+ return false; -+ -+ /* -+ // Original algorithm which does not work because SP was -+ // pointing beyond where it should have: -+ -+ // For the server compiler, EBP is not guaranteed to be valid -+ // for compiled code. We see whether the PC is in the -+ // interpreter and take care of that, otherwise we run code -+ // (unfortunately) duplicated from MIPS64Frame.senderForCompiledFrame. ++ public boolean isSIMD() { ++ switch (this) { ++ case SINGLE: ++ case DOUBLE: ++ case V128_BYTE: ++ case V128_WORD: ++ case V128_DWORD: ++ case V128_QWORD: ++ case V128_SINGLE: ++ case V128_DOUBLE: ++ case V256_BYTE: ++ case V256_WORD: ++ case V256_DWORD: ++ case V256_QWORD: ++ case V256_SINGLE: ++ case V256_DOUBLE: ++ return true; ++ default: ++ return false; ++ } ++ } + -+ CodeCache cc = vm.getCodeCache(); -+ if (cc.contains(pc)) { -+ CodeBlob cb = cc.findBlob(pc); ++ @Override ++ public char getTypeChar() { ++ switch (this) { ++ case BYTE: ++ return 'b'; ++ case WORD: ++ return 'w'; ++ case DWORD: ++ return 'd'; ++ case QWORD: ++ return 'q'; ++ case SINGLE: ++ return 'S'; ++ case DOUBLE: ++ return 'D'; ++ case V128_BYTE: ++ case V128_WORD: ++ case V128_DWORD: ++ case V128_QWORD: ++ case V128_SINGLE: ++ case V128_DOUBLE: ++ case V256_BYTE: ++ case V256_WORD: ++ case V256_DWORD: ++ case V256_QWORD: ++ case V256_SINGLE: ++ case V256_DOUBLE: ++ return 'v'; ++ default: ++ return '-'; ++ } ++ } ++} +diff --git a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.loongarch64/src/jdk/vm/ci/loongarch64/package-info.java b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.loongarch64/src/jdk/vm/ci/loongarch64/package-info.java +new file mode 100644 +index 000000000..9d020833e +--- /dev/null ++++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.loongarch64/src/jdk/vm/ci/loongarch64/package-info.java +@@ -0,0 +1,28 @@ ++/* ++ * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2022, Loongson Technology. 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. ++ */ + -+ // See if we can derive a frame pointer from SP and PC -+ // NOTE: This is the code duplicated from MIPS64Frame -+ Address saved_fp = null; -+ int llink_offset = cb.getLinkOffset(); -+ if (llink_offset >= 0) { -+ // Restore base-pointer, since next frame might be an interpreter frame. -+ Address fp_addr = sp.addOffsetTo(VM.getVM().getAddressSize() * llink_offset); -+ saved_fp = fp_addr.getAddressAt(0); -+ } ++/** ++ * The LoongArch64 platform independent portions of the JVMCI API. ++ */ ++package jdk.vm.ci.loongarch64; +diff --git a/src/jdk.internal.vm.ci/share/classes/module-info.java b/src/jdk.internal.vm.ci/share/classes/module-info.java +index fed310d38..661f106d3 100644 +--- a/src/jdk.internal.vm.ci/share/classes/module-info.java ++++ b/src/jdk.internal.vm.ci/share/classes/module-info.java +@@ -23,6 +23,12 @@ + * questions. + */ + ++/* ++ * This file has been modified by Loongson Technology in 2022, These ++ * modifications are Copyright (c) 2022, Loongson Technology, and are made ++ * available on the same license terms set forth above. ++ */ + -+ setValues(sp, saved_fp, pc); -+ return true; + module jdk.internal.vm.ci { + exports jdk.vm.ci.services to jdk.internal.vm.compiler; + exports jdk.vm.ci.runtime to +@@ -37,6 +43,7 @@ module jdk.internal.vm.ci { + + provides jdk.vm.ci.hotspot.HotSpotJVMCIBackendFactory with + jdk.vm.ci.hotspot.aarch64.AArch64HotSpotJVMCIBackendFactory, ++ jdk.vm.ci.hotspot.loongarch64.LoongArch64HotSpotJVMCIBackendFactory, + jdk.vm.ci.hotspot.amd64.AMD64HotSpotJVMCIBackendFactory, + jdk.vm.ci.hotspot.sparc.SPARCHotSpotJVMCIBackendFactory; + } +diff --git a/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Main.java b/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Main.java +index 087ff688a..f32e299c2 100644 +--- a/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Main.java ++++ b/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Main.java +@@ -175,6 +175,7 @@ public class Main { + private boolean hasExpiringCert = false; + private boolean hasExpiringTsaCert = false; + private boolean noTimestamp = true; ++ private boolean hasNonexistentEntries = false; + + // Expiration date. The value could be null if signed by a trusted cert. + private Date expireDate = null; +@@ -695,6 +696,7 @@ public class Main { + Map sigMap = new HashMap<>(); + Map sigNameMap = new HashMap<>(); + Map unparsableSignatures = new HashMap<>(); ++ Map> entriesInSF = new HashMap<>(); + + try { + jf = new JarFile(jarName, true); +@@ -731,6 +733,7 @@ public class Main { + break; + } + } ++ entriesInSF.put(alias, sf.getEntries().keySet()); + if (!found) { + unparsableSignatures.putIfAbsent(alias, + String.format( +@@ -829,6 +832,9 @@ public class Main { + sb.append('\n'); + } + } ++ for (var signed : entriesInSF.values()) { ++ signed.remove(name); ++ } + } else if (showcerts && !verbose.equals("all")) { + // Print no info for unsigned entries when -verbose:all, + // to be consistent with old behavior. +@@ -1020,6 +1026,13 @@ public class Main { + if (verbose != null) { + System.out.println(history); + } ++ var signed = entriesInSF.get(s); ++ if (!signed.isEmpty()) { ++ if (verbose != null) { ++ System.out.println(rb.getString("history.nonexistent.entries") + signed); ++ } ++ hasNonexistentEntries = true; ++ } + } else { + unparsableSignatures.putIfAbsent(s, String.format( + rb.getString("history.nobk"), s)); +@@ -1243,6 +1256,7 @@ public class Main { + (hasExpiringTsaCert && expireDate != null) || + (noTimestamp && expireDate != null) || + (hasExpiredTsaCert && signerNotExpired) || ++ hasNonexistentEntries || + extraAttrsDetected) { + + if (hasExpiredTsaCert && signerNotExpired) { +@@ -1280,6 +1294,9 @@ public class Main { + : "no.timestamp.verifying"), expireDate)); + } + } ++ if (hasNonexistentEntries) { ++ warnings.add(rb.getString("nonexistent.entries.found")); ++ } + if (extraAttrsDetected) { + warnings.add(rb.getString("extra.attributes.detected")); + } +diff --git a/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources.java b/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources.java +index 800a946d6..6c3d5260b 100644 +--- a/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources.java ++++ b/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources.java +@@ -164,6 +164,7 @@ public class Resources extends java.util.ListResourceBundle { + + {"history.with.ts", "- Signed by \"%1$s\"\n Digest algorithm: %2$s\n Signature algorithm: %3$s, %4$s\n Timestamped by \"%6$s\" on %5$tc\n Timestamp digest algorithm: %7$s\n Timestamp signature algorithm: %8$s, %9$s"}, + {"history.without.ts", "- Signed by \"%1$s\"\n Digest algorithm: %2$s\n Signature algorithm: %3$s, %4$s"}, ++ {"history.nonexistent.entries", " Warning: nonexistent signed entries: "}, + {"history.unparsable", "- Unparsable signature-related file %s"}, + {"history.nosf", "- Missing signature-related file META-INF/%s.SF"}, + {"history.nobk", "- Missing block file for signature-related file META-INF/%s.SF"}, +@@ -174,6 +175,7 @@ public class Resources extends java.util.ListResourceBundle { + {"key.bit.weak", "%d-bit key (weak)"}, + {"key.bit.disabled", "%d-bit key (disabled)"}, + {"unknown.size", "unknown size"}, ++ {"nonexistent.entries.found", "This jar contains signed entries for files that do not exist. See the -verbose output for more details."}, + {"extra.attributes.detected", "POSIX file permission and/or symlink attributes detected. These attributes are ignored when signing and are not protected by the signature."}, + + {"jarsigner.", "jarsigner: "}, +diff --git a/src/jdk.jartool/share/classes/sun/tools/jar/GNUStyleOptions.java b/src/jdk.jartool/share/classes/sun/tools/jar/GNUStyleOptions.java +index 3bb3b8b40..dcf7b1049 100644 +--- a/src/jdk.jartool/share/classes/sun/tools/jar/GNUStyleOptions.java ++++ b/src/jdk.jartool/share/classes/sun/tools/jar/GNUStyleOptions.java +@@ -188,6 +188,13 @@ class GNUStyleOptions { + } + }, + ++ // Extract options ++ new Option(false, OptionType.EXTRACT, "--keep-old-files", "-k") { ++ void process(Main jartool, String opt, String arg) { ++ jartool.kflag = true; ++ } ++ }, ++ + // Hidden options + new Option(false, OptionType.OTHER, "-P") { + void process(Main jartool, String opt, String arg) { +@@ -230,6 +237,7 @@ class GNUStyleOptions { + CREATE("create"), + CREATE_UPDATE("create.update"), + CREATE_UPDATE_INDEX("create.update.index"), ++ EXTRACT("extract"), + OTHER("other"); + + /** Resource lookup section prefix. */ +diff --git a/src/jdk.jartool/share/classes/sun/tools/jar/Main.java b/src/jdk.jartool/share/classes/sun/tools/jar/Main.java +index 00607d412..857521018 100644 +--- a/src/jdk.jartool/share/classes/sun/tools/jar/Main.java ++++ b/src/jdk.jartool/share/classes/sun/tools/jar/Main.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 1996, 2024, 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 +@@ -149,8 +149,9 @@ public class Main { + * nflag: Perform jar normalization at the end + * pflag: preserve/don't strip leading slash and .. component from file name + * dflag: print module descriptor ++ * kflag: keep existing file + */ +- boolean cflag, uflag, xflag, tflag, vflag, flag0, Mflag, iflag, nflag, pflag, dflag; ++ boolean cflag, uflag, xflag, tflag, vflag, flag0, Mflag, iflag, nflag, pflag, dflag, kflag; + + boolean suppressDeprecateMsg = false; + +@@ -242,7 +243,7 @@ public class Main { + * Starts main program with the specified arguments. + */ + @SuppressWarnings({"removal"}) +- public synchronized boolean run(String args[]) { ++ public synchronized boolean run(String[] args) { + ok = true; + if (!parseArgs(args)) { + return false; +@@ -385,11 +386,9 @@ public class Main { + if (fname != null) { + list(fname, files); + } else { +- InputStream in = new FileInputStream(FileDescriptor.in); +- try { +- list(new BufferedInputStream(in), files); +- } finally { +- in.close(); ++ try (InputStream in = new FileInputStream(FileDescriptor.in); ++ BufferedInputStream bis = new BufferedInputStream(in)) { ++ list(bis, files); + } + } + } else if (xflag) { +@@ -405,18 +404,12 @@ public class Main { + // latter can handle it. + + String[] files = filesMapToFiles(filesMap); +- if (fname != null && files != null) { ++ if (fname != null) { + extract(fname, files); + } else { +- InputStream in = (fname == null) +- ? new FileInputStream(FileDescriptor.in) +- : new FileInputStream(fname); +- try { +- if (!extract(new BufferedInputStream(in), files) && fname != null) { +- extract(fname, files); +- } +- } finally { +- in.close(); ++ try (InputStream in = new FileInputStream(FileDescriptor.in); ++ BufferedInputStream bis = new BufferedInputStream(in)) { ++ extract(bis, files); + } + } + } else if (iflag) { +@@ -497,7 +490,7 @@ public class Main { + /** + * Parses command line arguments. + */ +- boolean parseArgs(String args[]) { ++ boolean parseArgs(String[] args) { + /* Preprocess and expand @file arguments */ + try { + args = CommandLine.parse(args); +@@ -584,6 +577,9 @@ public class Main { + case '0': + flag0 = true; + break; ++ case 'k': ++ kflag = true; ++ break; + case 'i': + if (cflag || uflag || xflag || tflag) { + usageError(getMsg("error.multiple.main.operations")); +@@ -617,6 +613,9 @@ public class Main { + usageError(getMsg("error.bad.option")); + return false; + } ++ if (kflag && !xflag) { ++ warn(formatMsg("warn.option.is.ignored", "--keep-old-files/-k/k")); ++ } + + /* parse file arguments */ + int n = args.length - count; +@@ -919,118 +918,116 @@ public class Main { + Map moduleInfos, + JarIndex jarIndex) throws IOException + { +- ZipInputStream zis = new ZipInputStream(in); +- ZipOutputStream zos = new JarOutputStream(out); +- ZipEntry e = null; +- boolean foundManifest = false; + boolean updateOk = true; ++ try (ZipInputStream zis = new ZipInputStream(in); ++ ZipOutputStream zos = new JarOutputStream(out)) { + +- // All actual entries added/updated/existing, in the jar file (excl manifest +- // and module-info.class ). +- Set jentries = new HashSet<>(); +- +- if (jarIndex != null) { +- addIndex(jarIndex, zos); +- } ++ if (jarIndex != null) { ++ addIndex(jarIndex, zos); ++ } ++ ZipEntry e = null; ++ boolean foundManifest = false; ++ // All actual entries added/updated/existing, in the jar file (excl manifest ++ // and module-info.class ). ++ Set jentries = new HashSet<>(); + +- // put the old entries first, replace if necessary +- while ((e = zis.getNextEntry()) != null) { +- String name = e.getName(); ++ // put the old entries first, replace if necessary ++ while ((e = zis.getNextEntry()) != null) { ++ String name = e.getName(); + +- boolean isManifestEntry = equalsIgnoreCase(name, MANIFEST_NAME); +- boolean isModuleInfoEntry = isModuleInfoEntry(name); ++ boolean isManifestEntry = equalsIgnoreCase(name, MANIFEST_NAME); ++ boolean isModuleInfoEntry = isModuleInfoEntry(name); + +- if ((jarIndex != null && equalsIgnoreCase(name, INDEX_NAME)) +- || (Mflag && isManifestEntry)) { +- continue; +- } else if (isManifestEntry && ((newManifest != null) || ++ if ((jarIndex != null && equalsIgnoreCase(name, INDEX_NAME)) ++ || (Mflag && isManifestEntry)) { ++ continue; ++ } else if (isManifestEntry && ((newManifest != null) || + (ename != null) || isMultiRelease)) { +- foundManifest = true; +- if (newManifest != null) { +- // Don't read from the newManifest InputStream, as we +- // might need it below, and we can't re-read the same data +- // twice. +- try (FileInputStream fis = new FileInputStream(mname)) { +- if (isAmbiguousMainClass(new Manifest(fis))) { +- return false; ++ foundManifest = true; ++ if (newManifest != null) { ++ // Don't read from the newManifest InputStream, as we ++ // might need it below, and we can't re-read the same data ++ // twice. ++ try (FileInputStream fis = new FileInputStream(mname)) { ++ if (isAmbiguousMainClass(new Manifest(fis))) { ++ return false; ++ } + } + } +- } +- // Update the manifest. +- Manifest old = new Manifest(zis); +- if (newManifest != null) { +- old.read(newManifest); +- } +- if (!updateManifest(old, zos)) { +- return false; +- } +- } else if (moduleInfos != null && isModuleInfoEntry) { +- moduleInfos.putIfAbsent(name, zis.readAllBytes()); +- } else { +- boolean isDir = e.isDirectory(); +- if (!entryMap.containsKey(name)) { // copy the old stuff +- // do our own compression +- ZipEntry e2 = new ZipEntry(name); +- e2.setMethod(e.getMethod()); +- e2.setTime(e.getTime()); +- e2.setComment(e.getComment()); +- e2.setExtra(e.getExtra()); +- if (e.getMethod() == ZipEntry.STORED) { +- e2.setSize(e.getSize()); +- e2.setCrc(e.getCrc()); ++ // Update the manifest. ++ Manifest old = new Manifest(zis); ++ if (newManifest != null) { ++ old.read(newManifest); ++ } ++ if (!updateManifest(old, zos)) { ++ return false; ++ } ++ } else if (moduleInfos != null && isModuleInfoEntry) { ++ moduleInfos.putIfAbsent(name, zis.readAllBytes()); ++ } else { ++ boolean isDir = e.isDirectory(); ++ if (!entryMap.containsKey(name)) { // copy the old stuff ++ // do our own compression ++ ZipEntry e2 = new ZipEntry(name); ++ e2.setMethod(e.getMethod()); ++ e2.setTime(e.getTime()); ++ e2.setComment(e.getComment()); ++ e2.setExtra(e.getExtra()); ++ if (e.getMethod() == ZipEntry.STORED) { ++ e2.setSize(e.getSize()); ++ e2.setCrc(e.getCrc()); ++ } ++ zos.putNextEntry(e2); ++ copy(zis, zos); ++ } else { // replace with the new files ++ Entry ent = entryMap.get(name); ++ addFile(zos, ent); ++ entryMap.remove(name); ++ entries.remove(ent); ++ isDir = ent.isDir; ++ } ++ if (!isDir) { ++ jentries.add(name); + } +- zos.putNextEntry(e2); +- copy(zis, zos); +- } else { // replace with the new files +- Entry ent = entryMap.get(name); +- addFile(zos, ent); +- entryMap.remove(name); +- entries.remove(ent); +- isDir = ent.isDir; +- } +- if (!isDir) { +- jentries.add(name); + } + } +- } + +- // add the remaining new files +- for (Entry entry : entries) { +- addFile(zos, entry); +- if (!entry.isDir) { +- jentries.add(entry.name); ++ // add the remaining new files ++ for (Entry entry : entries) { ++ addFile(zos, entry); ++ if (!entry.isDir) { ++ jentries.add(entry.name); ++ } + } +- } +- if (!foundManifest) { +- if (newManifest != null) { +- Manifest m = new Manifest(newManifest); +- updateOk = !isAmbiguousMainClass(m); +- if (updateOk) { +- if (!updateManifest(m, zos)) { ++ if (!foundManifest) { ++ if (newManifest != null) { ++ Manifest m = new Manifest(newManifest); ++ updateOk = !isAmbiguousMainClass(m); ++ if (updateOk) { ++ if (!updateManifest(m, zos)) { ++ updateOk = false; ++ } ++ } ++ } else if (ename != null) { ++ if (!updateManifest(new Manifest(), zos)) { + updateOk = false; + } + } +- } else if (ename != null) { +- if (!updateManifest(new Manifest(), zos)) { ++ } ++ if (updateOk) { ++ if (moduleInfos != null && !moduleInfos.isEmpty()) { ++ Set pkgs = new HashSet<>(); ++ jentries.forEach(je -> addPackageIfNamed(pkgs, je)); ++ addExtendedModuleAttributes(moduleInfos, pkgs); ++ updateOk = checkModuleInfo(moduleInfos.get(MODULE_INFO), jentries); ++ updateModuleInfo(moduleInfos, zos); ++ // TODO: check manifest main classes, etc ++ } else if (moduleVersion != null || modulesToHash != null) { ++ error(getMsg("error.module.options.without.info")); + updateOk = false; + } + } + } +- if (updateOk) { +- if (moduleInfos != null && !moduleInfos.isEmpty()) { +- Set pkgs = new HashSet<>(); +- jentries.forEach( je -> addPackageIfNamed(pkgs, je)); +- addExtendedModuleAttributes(moduleInfos, pkgs); +- updateOk = checkModuleInfo(moduleInfos.get(MODULE_INFO), jentries); +- updateModuleInfo(moduleInfos, zos); +- // TODO: check manifest main classes, etc +- } else if (moduleVersion != null || modulesToHash != null) { +- error(getMsg("error.module.options.without.info")); +- updateOk = false; +- } +- } +- zis.close(); +- zos.close(); + return updateOk; + } + +@@ -1352,19 +1349,12 @@ public class Main { + + /** + * Extracts specified entries from JAR file. +- * +- * @return whether entries were found and successfully extracted +- * (indicating this was a zip file without "leading garbage") + */ +- boolean extract(InputStream in, String files[]) throws IOException { ++ void extract(InputStream in, String[] files) throws IOException { + ZipInputStream zis = new ZipInputStream(in); + ZipEntry e; +- // Set of all directory entries specified in archive. Disallows +- // null entries. Disallows all entries if using pre-6.0 behavior. +- boolean entriesFound = false; + Set dirs = newDirSet(); + while ((e = zis.getNextEntry()) != null) { +- entriesFound = true; + if (files == null) { + dirs.add(extractFile(zis, e)); + } else { +@@ -1383,32 +1373,31 @@ public class Main { + // instead of during, because creating a file in a directory changes + // that directory's timestamp. + updateLastModifiedTime(dirs); +- +- return entriesFound; + } + + /** + * Extracts specified entries from JAR file, via ZipFile. + */ +- void extract(String fname, String files[]) throws IOException { +- ZipFile zf = new ZipFile(fname); +- Set dirs = newDirSet(); +- Enumeration zes = zf.entries(); +- while (zes.hasMoreElements()) { +- ZipEntry e = zes.nextElement(); +- if (files == null) { +- dirs.add(extractFile(zf.getInputStream(e), e)); +- } else { +- String name = e.getName(); +- for (String file : files) { +- if (name.startsWith(file)) { +- dirs.add(extractFile(zf.getInputStream(e), e)); +- break; ++ void extract(String fname, String[] files) throws IOException { ++ final Set dirs; ++ try (ZipFile zf = new ZipFile(fname)) { ++ dirs = newDirSet(); ++ Enumeration zes = zf.entries(); ++ while (zes.hasMoreElements()) { ++ ZipEntry e = zes.nextElement(); ++ if (files == null) { ++ dirs.add(extractFile(zf.getInputStream(e), e)); ++ } else { ++ String name = e.getName(); ++ for (String file : files) { ++ if (name.startsWith(file)) { ++ dirs.add(extractFile(zf.getInputStream(e), e)); ++ break; ++ } + } + } + } + } +- zf.close(); + updateLastModifiedTime(dirs); + } + +@@ -1448,6 +1437,12 @@ public class Main { + output(formatMsg("out.create", name)); + } + } else { ++ if (f.exists() && kflag) { ++ if (vflag) { ++ output(formatMsg("out.kept", name)); ++ } ++ return rc; ++ } + if (f.getParent() != null) { + File d = new File(f.getParent()); + if (!d.exists() && !d.mkdirs() || !d.isDirectory()) { +@@ -1483,7 +1478,7 @@ public class Main { + /** + * Lists contents of JAR file. + */ +- void list(InputStream in, String files[]) throws IOException { ++ void list(InputStream in, String[] files) throws IOException { + ZipInputStream zis = new ZipInputStream(in); + ZipEntry e; + while ((e = zis.getNextEntry()) != null) { +@@ -1501,13 +1496,13 @@ public class Main { + /** + * Lists contents of JAR file, via ZipFile. + */ +- void list(String fname, String files[]) throws IOException { +- ZipFile zf = new ZipFile(fname); +- Enumeration zes = zf.entries(); +- while (zes.hasMoreElements()) { +- printEntry(zes.nextElement(), files); ++ void list(String fname, String[] files) throws IOException { ++ try (ZipFile zf = new ZipFile(fname)) { ++ Enumeration zes = zf.entries(); ++ while (zes.hasMoreElements()) { ++ printEntry(zes.nextElement(), files); ++ } + } +- zf.close(); + } + + /** +@@ -1550,10 +1545,8 @@ public class Main { + // class path attribute will give us jar file name with + // '/' as separators, so we need to change them to the + // appropriate one before we open the jar file. +- JarFile rf = new JarFile(jar.replace('/', File.separatorChar)); +- +- if (rf != null) { +- Manifest man = rf.getManifest(); ++ try (JarFile jarFile = new JarFile(jar.replace('/', File.separatorChar))) { ++ Manifest man = jarFile.getManifest(); + if (man != null) { + Attributes attr = man.getMainAttributes(); + if (attr != null) { +@@ -1574,7 +1567,6 @@ public class Main { + } + } + } +- rf.close(); + return files; + } + +@@ -1681,7 +1673,7 @@ public class Main { + /** + * Main routine to start program. + */ +- public static void main(String args[]) { ++ public static void main(String[] args) { + Main jartool = new Main(System.out, System.err, "jar"); + System.exit(jartool.run(args) ? 0 : 1); + } +diff --git a/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties b/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties +index 4f75242c0..912915cb9 100644 +--- a/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties ++++ b/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties +@@ -133,6 +133,8 @@ warn.release.unexpected.versioned.entry=\ + unexpected versioned entry {0} + warn.flag.is.deprecated=\ + Warning: The {0} option is deprecated, and is planned for removal in a future JDK release\n ++warn.option.is.ignored=\ ++ Warning: The {0} option is not valid with current usage, will be ignored. + out.added.manifest=\ + added manifest + out.added.module-info=\ +@@ -155,6 +157,8 @@ out.create=\ + \ \ created: {0} + out.extracted=\ + extracted: {0} ++out.kept=\ ++ \ \ skipped: {0} exists + out.inflated=\ + \ inflated: {0} + out.size=\ +@@ -234,7 +238,10 @@ main.help.opt.main.list=\ + main.help.opt.main.update=\ + \ -u, --update Update an existing jar archive + main.help.opt.main.extract=\ +-\ -x, --extract Extract named (or all) files from the archive ++\ -x, --extract Extract named (or all) files from the archive.\n\ ++\ If a file with the same name appears more than once in\n\ ++\ the archive, each copy will be extracted, with later copies\n\ ++\ overwriting (replacing) earlier copies unless -k is specified. + main.help.opt.main.describe-module=\ + \ -d, --describe-module Print the module descriptor, or automatic module name + main.help.opt.any=\ +@@ -287,6 +294,15 @@ main.help.opt.create.update.index=\ + \ Operation modifiers valid only in create, update, and generate-index mode:\n + main.help.opt.create.update.index.no-compress=\ + \ -0, --no-compress Store only; use no ZIP compression ++main.help.opt.extract=\ ++\ Operation modifiers valid only in extract mode:\n ++main.help.opt.extract.keep-old-files=\ ++\ -k, --keep-old-files Do not overwrite existing files.\n\ ++\ If a Jar file entry with the same name exists in the target\n\ ++\ directory, the existing file will not be overwritten.\n\ ++\ As a result, if a file appears more than once in an\n\ ++\ archive, later copies will not overwrite earlier copies.\n\ ++\ Also note that some file system can be case insensitive. + main.help.opt.other=\ + \ Other options:\n + main.help.opt.other.help=\ +diff --git a/src/jdk.pack/share/native/common-unpack/constants.h b/src/jdk.pack/share/native/common-unpack/constants.h +index 8d8376dd2..6fc34f75a 100644 +--- a/src/jdk.pack/share/native/common-unpack/constants.h ++++ b/src/jdk.pack/share/native/common-unpack/constants.h +@@ -203,7 +203,7 @@ enum { + AO_HAVE_FIELD_FLAGS_HI = 1<<10, + AO_HAVE_METHOD_FLAGS_HI = 1<<11, + AO_HAVE_CODE_FLAGS_HI = 1<<12, +- AO_UNUSED_MBZ = (-1)<<13, // options bits reserved for future use. ++ AO_UNUSED_MBZ = (int)((~0U)<<13), // options bits reserved for future use. + + #define ARCHIVE_BIT_DO(F) \ + F(AO_HAVE_SPECIAL_FORMATS) \ +diff --git a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/options/Options.java b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/options/Options.java +index 32f7fde60..2453ec166 100644 +--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/options/Options.java ++++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/options/Options.java +@@ -416,16 +416,34 @@ public final class Options { + * @param args arguments from command line + */ + public void process(final String[] args) { ++ final LinkedList prepArgList = new LinkedList<>(); ++ addSystemProperties(NASHORN_ARGS_PREPEND_PROPERTY, prepArgList); ++ final LinkedList postArgList = new LinkedList<>(); ++ addSystemProperties(NASHORN_ARGS_PROPERTY, postArgList); + final LinkedList argList = new LinkedList<>(); +- addSystemProperties(NASHORN_ARGS_PREPEND_PROPERTY, argList); +- processArgList(argList); +- assert argList.isEmpty(); +- Collections.addAll(argList, args); +- processArgList(argList); +- assert argList.isEmpty(); +- addSystemProperties(NASHORN_ARGS_PROPERTY, argList); ++ for (final String arg : args) { ++ if (arg.startsWith(definePropPrefix)) { ++ final String value = arg.substring(definePropPrefix.length()); ++ final int eq = value.indexOf('='); ++ if (eq != -1) { ++ String name = value.substring(0, eq); ++ if (name.equals(NASHORN_ARGS_PREPEND_PROPERTY)) { ++ addNashornProperties(value.substring(eq + 1), prepArgList, false); ++ continue; ++ } else if (name.equals(NASHORN_ARGS_PROPERTY)) { ++ addNashornProperties(value.substring(eq + 1), postArgList, true); ++ continue; ++ } ++ } ++ } ++ argList.add(arg); ++ } ++ processArgList(prepArgList); ++ assert prepArgList.isEmpty(); + processArgList(argList); + assert argList.isEmpty(); ++ processArgList(postArgList); ++ assert postArgList.isEmpty(); + } + + private void processArgList(final LinkedList argList) { +@@ -529,6 +547,23 @@ public final class Options { + } + } + ++ private static void addNashornProperties(final String args, final LinkedList argList, boolean prepend) { ++ if (args != null) { ++ final StringTokenizer st = new StringTokenizer(args); ++ final LinkedList prepArgList = new LinkedList<>(); ++ while (st.hasMoreTokens()) { ++ if (prepend) { ++ prepArgList.add(st.nextToken()); ++ } else { ++ argList.add(st.nextToken()); ++ } ++ } ++ if (prepend) { ++ argList.addAll(0,prepArgList); ++ } + } -+ */ -+ } -+ } else { -+ // If the current program counter was not known to us as a Java -+ // PC, we currently assume that we are in the run-time system -+ // and attempt to look to thread-local storage for saved ESP and -+ // EBP. Note that if these are null (because we were, in fact, -+ // in Java code, i.e., vtable stubs or similar, and the SA -+ // didn't have enough insight into the target VM to understand -+ // that) then we are going to lose the entire stack trace for -+ // the thread, which is sub-optimal. FIXME. -+ -+ if (DEBUG) { -+ System.out.println("CurrentFrameGuess: choosing last Java frame: sp = " + -+ thread.getLastJavaSP() + ", fp = " + thread.getLastJavaFP()); -+ } -+ if (thread.getLastJavaSP() == null) { -+ return false; // No known Java frames on stack -+ } -+ setValues(thread.getLastJavaSP(), thread.getLastJavaFP(), null); -+ return true; + } ++ + /** + * Retrieves an option template identified by key. + * @param shortKey the short (that is without the e.g. "nashorn.option." part) key +diff --git a/src/utils/hsdis/Makefile b/src/utils/hsdis/Makefile +index 2514a895d..08fbe3b95 100644 +--- a/src/utils/hsdis/Makefile ++++ b/src/utils/hsdis/Makefile +@@ -94,6 +94,9 @@ CC = gcc + endif + CFLAGS += -O + DLDFLAGS += -shared ++ifeq ($(ARCH), mips64) ++DLDFLAGS += -Wl,-z,noexecstack ++endif + LDFLAGS += -ldl + OUTFLAGS += -o $@ + else +diff --git a/test/failure_handler/src/share/conf/windows.properties b/test/failure_handler/src/share/conf/windows.properties +index fddd80ad0..ab005c357 100644 +--- a/test/failure_handler/src/share/conf/windows.properties ++++ b/test/failure_handler/src/share/conf/windows.properties +@@ -1,5 +1,5 @@ + # +-# Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. ++# Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + # + # This code is free software; you can redistribute it and/or modify it +@@ -22,10 +22,10 @@ + # + + config.execSuffix=.exe +-config.getChildren.app=bash ++config.getChildren.app=powershell + config.getChildren.pattern=%p +-config.getChildren.args=-c\0wmic process where ParentProcessId=%p get ProcessId | tail -n+2 + config.getChildren.args.delimiter=\0 ++config.getChildren.args=-NoLogo\0-Command\0"Get-CimInstance Win32_Process -Filter \\\"ParentProcessId = %p\\\" | Select-Object ProcessId" | tail -n+4 + ################################################################################ + # process info to gather + ################################################################################ +@@ -39,8 +39,9 @@ native.pattern=%p + native.javaOnly=false + native.args=%p + +-native.info.app=wmic +-native.info.args=process where processId=%p list full ++native.info.app=powershell ++native.info.delimiter=\0 ++native.info.args=-NoLogo\0-Command\0"Get-WmiObject Win32_Process -Filter \\\"ProcessId = %p\\\" | Format-List -Property *" + + native.pmap.app=pmap + native.pmap.normal.args=%p +@@ -89,8 +90,9 @@ system.events.delimiter=\0 + system.events.system.args=-NoLogo\0-Command\0Get-EventLog System -After (Get-Date).AddDays(-1) | Format-List + system.events.application.args=-NoLogo\0-Command\0Get-EventLog Application -After (Get-Date).AddDays(-1) | Format-List + +-system.os.app=wmic +-system.os.args=os get /format:list ++system.os.app=powershell ++system.os.delimiter=\0 ++system.os.args=-NoLogo\0-Command\0Get-WmiObject Win32_OperatingSystem | Format-List -Property * + + process.top.app=top + process.top.args=-b -n 1 +diff --git a/test/hotspot/gtest/gc/shared/test_collectorPolicy.cpp b/test/hotspot/gtest/gc/shared/test_collectorPolicy.cpp +index ce50b73a6..7f2cb854c 100644 +--- a/test/hotspot/gtest/gc/shared/test_collectorPolicy.cpp ++++ b/test/hotspot/gtest/gc/shared/test_collectorPolicy.cpp +@@ -78,7 +78,7 @@ class TestGenCollectorPolicy { + FLAG_SET_ERGO(size_t, InitialHeapSize, 100 * M); + FLAG_SET_ERGO(size_t, OldSize, 4 * M); + FLAG_SET_ERGO(size_t, NewSize, 1 * M); +- FLAG_SET_ERGO(size_t, MaxNewSize, 80 * M); ++ FLAG_SET_ERGO(size_t, MaxNewSize, 50 * M); + Arguments::set_min_heap_size(40 * M); + + ASSERT_NO_FATAL_FAILURE(setter1->execute()); +@@ -227,10 +227,16 @@ TEST_VM(CollectorPolicy, young_min_ergo) { + TestGenCollectorPolicy::TestWrapper::test(&setter, &checker); + } + ++// Tests require at least 128M of MaxHeap ++// otherwise ergonomic is different and generation sizes might be changed. ++ + // If NewSize has been ergonomically set, the collector policy + // should use it for min but calculate the initial young size + // using NewRatio. + TEST_VM(CollectorPolicy, young_scaled_initial_ergo) { ++ if (MaxHeapSize < 128 * M) { ++ return; ++ } + TestGenCollectorPolicy::SetNewSizeErgo setter(20 * M); + TestGenCollectorPolicy::CheckScaledYoungInitial checker; + +@@ -243,6 +249,9 @@ TEST_VM(CollectorPolicy, young_scaled_initial_ergo) { + // the rest of the VM lifetime. This is an irreversible change and + // could impact other tests so we use TEST_OTHER_VM + TEST_OTHER_VM(CollectorPolicy, young_cmd) { ++ if (MaxHeapSize < 128 * M) { ++ return; + } + // If NewSize is set on the command line, it should be used + // for both min and initial young size if less than min heap. + TestGenCollectorPolicy::SetNewSizeCmd setter(20 * M); +@@ -255,8 +264,8 @@ TEST_OTHER_VM(CollectorPolicy, young_cmd) { + + // If NewSize is set on command line, but is larger than the min + // heap size, it should only be used for initial young size. +- TestGenCollectorPolicy::SetNewSizeCmd setter_large(80 * M); +- TestGenCollectorPolicy::CheckYoungInitial checker_large(80 * M); ++ TestGenCollectorPolicy::SetNewSizeCmd setter_large(50 * M); ++ TestGenCollectorPolicy::CheckYoungInitial checker_large(50 * M); + TestGenCollectorPolicy::TestWrapper::test(&setter_large, &checker_large); + } + +diff --git a/test/hotspot/gtest/gc/shared/test_memset_with_concurrent_readers.cpp b/test/hotspot/gtest/gc/shared/test_memset_with_concurrent_readers.cpp +index 24f25b87a..7a3845e33 100644 +--- a/test/hotspot/gtest/gc/shared/test_memset_with_concurrent_readers.cpp ++++ b/test/hotspot/gtest/gc/shared/test_memset_with_concurrent_readers.cpp +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2016, 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,10 +24,13 @@ + #include "precompiled.hpp" + #include "gc/shared/memset_with_concurrent_readers.hpp" + #include "utilities/globalDefinitions.hpp" +-#include "unittest.hpp" + ++#include "utilities/vmassert_uninstall.hpp" + #include + #include ++#include "utilities/vmassert_reinstall.hpp" ++ ++#include "unittest.hpp" + + static unsigned line_byte(const char* line, size_t i) { + return unsigned(line[i]) & 0xFF; +diff --git a/test/hotspot/gtest/jfr/test_networkUtilization.cpp b/test/hotspot/gtest/jfr/test_networkUtilization.cpp +index 19d6a6e2c..42cd18356 100644 +--- a/test/hotspot/gtest/jfr/test_networkUtilization.cpp ++++ b/test/hotspot/gtest/jfr/test_networkUtilization.cpp +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2018, 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 +@@ -42,11 +42,13 @@ + #include "utilities/globalDefinitions.hpp" + #include "utilities/growableArray.hpp" + +-#include "unittest.hpp" +- ++#include "utilities/vmassert_uninstall.hpp" + #include + #include + #include ++#include "utilities/vmassert_reinstall.hpp" ++ ++#include "unittest.hpp" + + namespace { + +diff --git a/test/hotspot/gtest/unittest.hpp b/test/hotspot/gtest/unittest.hpp +index 0494a0e24..91edf6adb 100644 +--- a/test/hotspot/gtest/unittest.hpp ++++ b/test/hotspot/gtest/unittest.hpp +@@ -28,19 +28,10 @@ + #include + + #define GTEST_DONT_DEFINE_TEST 1 +-#include "gtest/gtest.h" + +-// gtest/gtest.h includes assert.h which will define the assert macro, but hotspot has its +-// own standards incompatible assert macro that takes two parameters. +-// The workaround is to undef assert and then re-define it. The re-definition +-// must unfortunately be copied since debug.hpp might already have been +-// included and a second include wouldn't work due to the header guards in debug.hpp. +-#ifdef assert +- #undef assert +- #ifdef vmassert +- #define assert(p, ...) vmassert(p, __VA_ARGS__) +- #endif +-#endif ++#include "utilities/vmassert_uninstall.hpp" ++#include "gtest/gtest.h" ++#include "utilities/vmassert_reinstall.hpp" + + #define CONCAT(a, b) a ## b + +diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt +index 3e692d0fa..f219093b8 100644 +--- a/test/hotspot/jtreg/ProblemList.txt ++++ b/test/hotspot/jtreg/ProblemList.txt +@@ -164,22 +164,22 @@ runtime/jni/terminatedThread/TestTerminatedThread.java 8219652 aix-ppc64 + + serviceability/dcmd/gc/RunFinalizationTest.java 8227120 generic-all + serviceability/sa/ClhsdbAttach.java 8193639 solaris-all +-serviceability/sa/ClhsdbCDSCore.java 8294316,8193639,8267433 solaris-all,macosx-x64 ++serviceability/sa/ClhsdbCDSCore.java 8193639,8267433 solaris-all,macosx-x64 + serviceability/sa/ClhsdbCDSJstackPrintAll.java 8193639 solaris-all + serviceability/sa/CDSJMapClstats.java 8193639 solaris-all + serviceability/sa/ClhsdbField.java 8193639 solaris-all +-serviceability/sa/ClhsdbFindPC.java 8294316,8193639,8267433 solaris-all,macosx-x64 ++serviceability/sa/ClhsdbFindPC.java 8193639,8267433 solaris-all,macosx-x64 + serviceability/sa/ClhsdbFlags.java 8193639 solaris-all + serviceability/sa/ClhsdbInspect.java 8193639 solaris-all + serviceability/sa/ClhsdbJdis.java 8193639 solaris-all + serviceability/sa/ClhsdbJhisto.java 8193639 solaris-all + serviceability/sa/ClhsdbJstack.java 8193639 solaris-all + serviceability/sa/ClhsdbLongConstant.java 8193639 solaris-all +-serviceability/sa/ClhsdbPmap.java 8294316,8193639,8267433 solaris-all,macosx-x64 ++serviceability/sa/ClhsdbPmap.java 8193639,8267433 solaris-all,macosx-x64 + serviceability/sa/ClhsdbPrintAll.java 8193639 solaris-all + serviceability/sa/ClhsdbPrintAs.java 8193639 solaris-all + serviceability/sa/ClhsdbPrintStatics.java 8193639 solaris-all +-serviceability/sa/ClhsdbPstack.java 8294316,8193639,8267433 solaris-all,macosx-x64 ++serviceability/sa/ClhsdbPstack.java 8193639,8267433 solaris-all,macosx-x64 + serviceability/sa/ClhsdbRegionDetailsScanOopsForG1.java 8193639 solaris-all + serviceability/sa/ClhsdbScanOops.java 8193639 solaris-all + serviceability/sa/ClhsdbSource.java 8193639 solaris-all +@@ -203,8 +203,8 @@ serviceability/sa/TestInstanceKlassSize.java 8193639 solaris-all + serviceability/sa/TestInstanceKlassSizeForInterface.java 8193639 solaris-all + serviceability/sa/TestIntConstant.java 8193639 solaris-all + serviceability/sa/TestJhsdbJstackLock.java 8193639 solaris-all +-serviceability/sa/TestJmapCore.java 8294316,8193639,8267433 solaris-all,macosx-x64 +-serviceability/sa/TestJmapCoreMetaspace.java 8294316,8193639,8267433 solaris-all,macosx-x64 ++serviceability/sa/TestJmapCore.java 8193639,8267433 solaris-all,macosx-x64 ++serviceability/sa/TestJmapCoreMetaspace.java 8193639,8267433 solaris-all,macosx-x64 + serviceability/sa/TestPrintMdo.java 8193639 solaris-all + serviceability/sa/TestRevPtrsForInvokeDynamic.java 8191270 generic-all + serviceability/sa/TestType.java 8193639 solaris-all +diff --git a/test/hotspot/jtreg/compiler/cpuflags/TestAESIntrinsicsOnSupportedConfig.java b/test/hotspot/jtreg/compiler/cpuflags/TestAESIntrinsicsOnSupportedConfig.java +index ac17e567b..9b004a203 100644 +--- a/test/hotspot/jtreg/compiler/cpuflags/TestAESIntrinsicsOnSupportedConfig.java ++++ b/test/hotspot/jtreg/compiler/cpuflags/TestAESIntrinsicsOnSupportedConfig.java +@@ -21,12 +21,18 @@ + * questions. + */ + ++/* ++ * This file has been modified by Loongson Technology in 2021, These ++ * modifications are Copyright (c) 2021, Loongson Technology, and are made ++ * available on the same license terms set forth above. ++ */ + -+ public Address getSP() { return spFound; } -+ public Address getFP() { return fpFound; } -+ /** May be null if getting values from thread-local storage; take -+ care to call the correct MIPS64Frame constructor to recover this if -+ necessary */ -+ public Address getPC() { return pcFound; } + /* + * @test + * @library /test/lib / + * @modules java.base/jdk.internal.misc + * java.management +- * @requires vm.cpu.features ~= ".*aes.*" & !vm.graal.enabled ++ * @requires (vm.cpu.features ~= ".*aes.*" | os.arch == "loongarch64") & !vm.graal.enabled + * @build sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission +diff --git a/test/hotspot/jtreg/compiler/cpuflags/TestAESIntrinsicsOnUnsupportedConfig.java b/test/hotspot/jtreg/compiler/cpuflags/TestAESIntrinsicsOnUnsupportedConfig.java +index 60b2d0332..981a23997 100644 +--- a/test/hotspot/jtreg/compiler/cpuflags/TestAESIntrinsicsOnUnsupportedConfig.java ++++ b/test/hotspot/jtreg/compiler/cpuflags/TestAESIntrinsicsOnUnsupportedConfig.java +@@ -21,6 +21,12 @@ + * questions. + */ + ++/* ++ * This file has been modified by Loongson Technology in 2021, These ++ * modifications are Copyright (c) 2021, Loongson Technology, and are made ++ * available on the same license terms set forth above. ++ */ + -+ private void setValues(Address sp, Address fp, Address pc) { -+ spFound = sp; -+ fpFound = fp; -+ pcFound = pc; -+ } -+} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/mips64/MIPS64Frame.java jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/mips64/MIPS64Frame.java ---- openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/mips64/MIPS64Frame.java 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/mips64/MIPS64Frame.java 2023-09-12 13:54:26.433575861 +0800 -@@ -0,0 +1,537 @@ + /* + * @test + * @library /test/lib / +@@ -28,7 +34,7 @@ + * java.management + * + * @build sun.hotspot.WhiteBox +- * @requires !(vm.cpu.features ~= ".*aes.*") ++ * @requires !(vm.cpu.features ~= ".*aes.*" | os.arch == "loongarch64") + * @requires vm.compiler1.enabled | !vm.graal.enabled + * @run driver ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission +diff --git a/test/hotspot/jtreg/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForOtherCPU.java b/test/hotspot/jtreg/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForOtherCPU.java +index faa9fdbae..a635f03d2 100644 +--- a/test/hotspot/jtreg/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForOtherCPU.java ++++ b/test/hotspot/jtreg/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForOtherCPU.java +@@ -21,6 +21,12 @@ + * questions. + */ + +/* -+ * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2018, Loongson Technology. All rights reserved. ++ * This file has been modified by Loongson Technology in 2021, These ++ * modifications are Copyright (c) 2021, Loongson Technology, and are made ++ * available on the same license terms set forth above. ++ */ ++ + package compiler.intrinsics.sha.cli.testcases; + + import compiler.intrinsics.sha.cli.SHAOptionsBase; +@@ -32,19 +38,20 @@ import jdk.test.lib.cli.predicate.OrPredicate; + + /** + * Generic test case for SHA-related options targeted to any CPU except +- * AArch64, PPC, S390x, SPARC and X86. ++ * AArch64, PPC, S390x, SPARC, LoongArch64 and X86. + */ + public class GenericTestCaseForOtherCPU extends + SHAOptionsBase.TestCase { + public GenericTestCaseForOtherCPU(String optionName) { +- // Execute the test case on any CPU except AArch64, PPC, S390x, SPARC and X86. ++ // Execute the test case on any CPU except AArch64, PPC, S390x, SPARC, LoongArch64 and X86. + super(optionName, new NotPredicate( + new OrPredicate(Platform::isAArch64, + new OrPredicate(Platform::isS390x, + new OrPredicate(Platform::isSparc, + new OrPredicate(Platform::isPPC, ++ new OrPredicate(Platform::isLoongArch64, + new OrPredicate(Platform::isX64, +- Platform::isX86))))))); ++ Platform::isX86)))))))); + } + + @Override +diff --git a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/CodeInstallationTest.java b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/CodeInstallationTest.java +index 62d0e9915..c3fa3fb93 100644 +--- a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/CodeInstallationTest.java ++++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/CodeInstallationTest.java +@@ -29,6 +29,7 @@ import jdk.vm.ci.code.InstalledCode; + import jdk.vm.ci.code.TargetDescription; + import jdk.vm.ci.code.test.amd64.AMD64TestAssembler; + import jdk.vm.ci.code.test.sparc.SPARCTestAssembler; ++import jdk.vm.ci.code.test.loongarch64.LoongArch64TestAssembler; + import jdk.vm.ci.hotspot.HotSpotCompiledCode; + import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; + import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; +@@ -37,6 +38,7 @@ import jdk.vm.ci.meta.MetaAccessProvider; + import jdk.vm.ci.runtime.JVMCI; + import jdk.vm.ci.runtime.JVMCIBackend; + import jdk.vm.ci.sparc.SPARC; ++import jdk.vm.ci.loongarch64.LoongArch64; + import org.junit.Assert; + + import java.lang.reflect.Method; +@@ -72,6 +74,8 @@ public class CodeInstallationTest { + return new AMD64TestAssembler(codeCache, config); + } else if (arch instanceof SPARC) { + return new SPARCTestAssembler(codeCache, config); ++ } else if (arch instanceof LoongArch64) { ++ return new LoongArch64TestAssembler(codeCache, config); + } else { + Assert.fail("unsupported architecture"); + return null; +diff --git a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/DataPatchTest.java b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/DataPatchTest.java +index 8afc7d7b9..520d7707a 100644 +--- a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/DataPatchTest.java ++++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/DataPatchTest.java +@@ -23,7 +23,7 @@ + + /** + * @test +- * @requires vm.jvmci & (vm.simpleArch == "x64" | vm.simpleArch == "sparcv9") ++ * @requires vm.jvmci & (vm.simpleArch == "x64" | vm.simpleArch == "sparcv9" | vm.simpleArch == "loongarch64") + * @library / + * @modules jdk.internal.vm.ci/jdk.vm.ci.hotspot + * jdk.internal.vm.ci/jdk.vm.ci.meta +@@ -32,7 +32,8 @@ + * jdk.internal.vm.ci/jdk.vm.ci.runtime + * jdk.internal.vm.ci/jdk.vm.ci.amd64 + * jdk.internal.vm.ci/jdk.vm.ci.sparc +- * @compile CodeInstallationTest.java DebugInfoTest.java TestAssembler.java TestHotSpotVMConfig.java amd64/AMD64TestAssembler.java sparc/SPARCTestAssembler.java ++ * jdk.internal.vm.ci/jdk.vm.ci.loongarch64 ++ * @compile CodeInstallationTest.java DebugInfoTest.java TestAssembler.java TestHotSpotVMConfig.java amd64/AMD64TestAssembler.java sparc/SPARCTestAssembler.java loongarch64/LoongArch64TestAssembler.java + * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -Djvmci.Compiler=null jdk.vm.ci.code.test.DataPatchTest + */ + +diff --git a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/InterpreterFrameSizeTest.java b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/InterpreterFrameSizeTest.java +index 75d0748da..a6826e2ff 100644 +--- a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/InterpreterFrameSizeTest.java ++++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/InterpreterFrameSizeTest.java +@@ -23,7 +23,7 @@ + + /** + * @test +- * @requires vm.jvmci & (vm.simpleArch == "x64" | vm.simpleArch == "sparcv9") ++ * @requires vm.jvmci & (vm.simpleArch == "x64" | vm.simpleArch == "sparcv9" | vm.simpleArch == "loongarch64") + * @modules jdk.internal.vm.ci/jdk.vm.ci.hotspot + * jdk.internal.vm.ci/jdk.vm.ci.code + * jdk.internal.vm.ci/jdk.vm.ci.code.site +@@ -32,7 +32,8 @@ + * jdk.internal.vm.ci/jdk.vm.ci.common + * jdk.internal.vm.ci/jdk.vm.ci.amd64 + * jdk.internal.vm.ci/jdk.vm.ci.sparc +- * @compile CodeInstallationTest.java TestAssembler.java TestHotSpotVMConfig.java amd64/AMD64TestAssembler.java sparc/SPARCTestAssembler.java ++ * jdk.internal.vm.ci/jdk.vm.ci.loongarch64 ++ * @compile CodeInstallationTest.java TestAssembler.java TestHotSpotVMConfig.java amd64/AMD64TestAssembler.java sparc/SPARCTestAssembler.java loongarch64/LoongArch64TestAssembler.java + * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -Djvmci.Compiler=null jdk.vm.ci.code.test.InterpreterFrameSizeTest + */ + +diff --git a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/MaxOopMapStackOffsetTest.java b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/MaxOopMapStackOffsetTest.java +index a67fa2c1d..59cce6454 100644 +--- a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/MaxOopMapStackOffsetTest.java ++++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/MaxOopMapStackOffsetTest.java +@@ -23,7 +23,7 @@ + + /** + * @test +- * @requires vm.jvmci & (vm.simpleArch == "x64" | vm.simpleArch == "sparcv9") ++ * @requires vm.jvmci & (vm.simpleArch == "x64" | vm.simpleArch == "sparcv9" | vm.simpleArch == "loongarch64") + * @library / + * @modules jdk.internal.vm.ci/jdk.vm.ci.hotspot + * jdk.internal.vm.ci/jdk.vm.ci.meta +@@ -33,7 +33,8 @@ + * jdk.internal.vm.ci/jdk.vm.ci.runtime + * jdk.internal.vm.ci/jdk.vm.ci.amd64 + * jdk.internal.vm.ci/jdk.vm.ci.sparc +- * @compile CodeInstallationTest.java DebugInfoTest.java TestAssembler.java TestHotSpotVMConfig.java amd64/AMD64TestAssembler.java sparc/SPARCTestAssembler.java ++ * jdk.internal.vm.ci/jdk.vm.ci.loongarch64 ++ * @compile CodeInstallationTest.java DebugInfoTest.java TestAssembler.java TestHotSpotVMConfig.java amd64/AMD64TestAssembler.java sparc/SPARCTestAssembler.java loongarch64/LoongArch64TestAssembler.java + * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -Djvmci.Compiler=null jdk.vm.ci.code.test.MaxOopMapStackOffsetTest + */ + +diff --git a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/NativeCallTest.java b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/NativeCallTest.java +index d9e1f24c3..259218b30 100644 +--- a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/NativeCallTest.java ++++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/NativeCallTest.java +@@ -23,7 +23,7 @@ + + /** + * @test +- * @requires vm.jvmci & (vm.simpleArch == "x64" | vm.simpleArch == "sparcv9") ++ * @requires vm.jvmci & (vm.simpleArch == "x64" | vm.simpleArch == "sparcv9" | vm.simpleArch == "loongarch64") + * @library /test/lib / + * @modules jdk.internal.vm.ci/jdk.vm.ci.hotspot + * jdk.internal.vm.ci/jdk.vm.ci.code +@@ -33,7 +33,8 @@ + * jdk.internal.vm.ci/jdk.vm.ci.common + * jdk.internal.vm.ci/jdk.vm.ci.amd64 + * jdk.internal.vm.ci/jdk.vm.ci.sparc +- * @compile CodeInstallationTest.java TestHotSpotVMConfig.java NativeCallTest.java TestAssembler.java sparc/SPARCTestAssembler.java amd64/AMD64TestAssembler.java ++ * jdk.internal.vm.ci/jdk.vm.ci.loongarch64 ++ * @compile CodeInstallationTest.java TestHotSpotVMConfig.java NativeCallTest.java TestAssembler.java sparc/SPARCTestAssembler.java amd64/AMD64TestAssembler.java loongarch64/LoongArch64TestAssembler.java + * @run junit/othervm/native -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -Xbootclasspath/a:. jdk.vm.ci.code.test.NativeCallTest + */ + package jdk.vm.ci.code.test; +diff --git a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/SimpleCodeInstallationTest.java b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/SimpleCodeInstallationTest.java +index 9b9211405..00d0f53cd 100644 +--- a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/SimpleCodeInstallationTest.java ++++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/SimpleCodeInstallationTest.java +@@ -23,7 +23,7 @@ + + /** + * @test +- * @requires vm.jvmci & (vm.simpleArch == "x64" | vm.simpleArch == "sparcv9") ++ * @requires vm.jvmci & (vm.simpleArch == "x64" | vm.simpleArch == "sparcv9" | vm.simpleArch == "loongarch64") + * @library / + * @modules jdk.internal.vm.ci/jdk.vm.ci.hotspot + * jdk.internal.vm.ci/jdk.vm.ci.meta +@@ -32,7 +32,8 @@ + * jdk.internal.vm.ci/jdk.vm.ci.runtime + * jdk.internal.vm.ci/jdk.vm.ci.amd64 + * jdk.internal.vm.ci/jdk.vm.ci.sparc +- * @compile CodeInstallationTest.java DebugInfoTest.java TestAssembler.java TestHotSpotVMConfig.java amd64/AMD64TestAssembler.java sparc/SPARCTestAssembler.java ++ * jdk.internal.vm.ci/jdk.vm.ci.loongarch64 ++ * @compile CodeInstallationTest.java DebugInfoTest.java TestAssembler.java TestHotSpotVMConfig.java amd64/AMD64TestAssembler.java sparc/SPARCTestAssembler.java loongarch64/LoongArch64TestAssembler.java + * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -Djvmci.Compiler=null jdk.vm.ci.code.test.SimpleCodeInstallationTest + */ + +diff --git a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/SimpleDebugInfoTest.java b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/SimpleDebugInfoTest.java +index 5b2204868..ecfcb1cf0 100644 +--- a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/SimpleDebugInfoTest.java ++++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/SimpleDebugInfoTest.java +@@ -23,7 +23,7 @@ + + /** + * @test +- * @requires vm.jvmci & (vm.simpleArch == "x64" | vm.simpleArch == "sparcv9") ++ * @requires vm.jvmci & (vm.simpleArch == "x64" | vm.simpleArch == "sparcv9" | vm.simpleArch == "loongarch64") + * @library / + * @modules jdk.internal.vm.ci/jdk.vm.ci.hotspot + * jdk.internal.vm.ci/jdk.vm.ci.meta +@@ -32,7 +32,8 @@ + * jdk.internal.vm.ci/jdk.vm.ci.runtime + * jdk.internal.vm.ci/jdk.vm.ci.amd64 + * jdk.internal.vm.ci/jdk.vm.ci.sparc +- * @compile CodeInstallationTest.java DebugInfoTest.java TestAssembler.java TestHotSpotVMConfig.java amd64/AMD64TestAssembler.java sparc/SPARCTestAssembler.java ++ * jdk.internal.vm.ci/jdk.vm.ci.loongarch64 ++ * @compile CodeInstallationTest.java DebugInfoTest.java TestAssembler.java TestHotSpotVMConfig.java amd64/AMD64TestAssembler.java sparc/SPARCTestAssembler.java loongarch64/LoongArch64TestAssembler.java + * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -Djvmci.Compiler=null jdk.vm.ci.code.test.SimpleDebugInfoTest + */ + +diff --git a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/VirtualObjectDebugInfoTest.java b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/VirtualObjectDebugInfoTest.java +index a10e90acd..5b1a58c74 100644 +--- a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/VirtualObjectDebugInfoTest.java ++++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/VirtualObjectDebugInfoTest.java +@@ -23,7 +23,7 @@ + + /** + * @test +- * @requires vm.jvmci & (vm.simpleArch == "x64" | vm.simpleArch == "sparcv9") ++ * @requires vm.jvmci & (vm.simpleArch == "x64" | vm.simpleArch == "sparcv9" | vm.simpleArch == "loongarch64") + * @library / + * @modules jdk.internal.vm.ci/jdk.vm.ci.hotspot + * jdk.internal.vm.ci/jdk.vm.ci.meta +@@ -32,7 +32,8 @@ + * jdk.internal.vm.ci/jdk.vm.ci.runtime + * jdk.internal.vm.ci/jdk.vm.ci.amd64 + * jdk.internal.vm.ci/jdk.vm.ci.sparc +- * @compile CodeInstallationTest.java DebugInfoTest.java TestAssembler.java TestHotSpotVMConfig.java amd64/AMD64TestAssembler.java sparc/SPARCTestAssembler.java ++ * jdk.internal.vm.ci/jdk.vm.ci.loongarch64 ++ * @compile CodeInstallationTest.java DebugInfoTest.java TestAssembler.java TestHotSpotVMConfig.java amd64/AMD64TestAssembler.java sparc/SPARCTestAssembler.java loongarch64/LoongArch64TestAssembler.java + * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -Djvmci.Compiler=null jdk.vm.ci.code.test.VirtualObjectDebugInfoTest + */ + +diff --git a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/loongarch64/LoongArch64TestAssembler.java b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/loongarch64/LoongArch64TestAssembler.java +new file mode 100644 +index 000000000..4c7686845 +--- /dev/null ++++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/loongarch64/LoongArch64TestAssembler.java +@@ -0,0 +1,568 @@ ++/* ++ * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2022, Loongson Technology. 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 @@ -118269,589 +200124,727 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.hotspot.agent/shar + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. -+ * + */ + -+package sun.jvm.hotspot.runtime.mips64; -+ -+import java.util.*; -+import sun.jvm.hotspot.code.*; -+import sun.jvm.hotspot.compiler.*; -+import sun.jvm.hotspot.debugger.*; -+import sun.jvm.hotspot.oops.*; -+import sun.jvm.hotspot.runtime.*; -+import sun.jvm.hotspot.types.*; -+import sun.jvm.hotspot.utilities.*; -+ -+/** Specialization of and implementation of abstract methods of the -+ Frame class for the mips64 family of CPUs. */ -+ -+public class MIPS64Frame extends Frame { -+ private static final boolean DEBUG; -+ static { -+ DEBUG = System.getProperty("sun.jvm.hotspot.runtime.mips64.MIPS64Frame.DEBUG") != null; -+ } -+ -+ // All frames -+ private static final int LINK_OFFSET = 0; -+ private static final int RETURN_ADDR_OFFSET = 1; -+ private static final int SENDER_SP_OFFSET = 2; -+ -+ // Interpreter frames -+ private static final int INTERPRETER_FRAME_SENDER_SP_OFFSET = -1; -+ private static final int INTERPRETER_FRAME_LAST_SP_OFFSET = INTERPRETER_FRAME_SENDER_SP_OFFSET - 1; -+ private static final int INTERPRETER_FRAME_METHOD_OFFSET = INTERPRETER_FRAME_LAST_SP_OFFSET - 1; -+ private static int INTERPRETER_FRAME_MIRROR_OFFSET; -+ private static int INTERPRETER_FRAME_MDX_OFFSET; // Non-core builds only -+ private static int INTERPRETER_FRAME_CACHE_OFFSET; -+ private static int INTERPRETER_FRAME_LOCALS_OFFSET; -+ private static int INTERPRETER_FRAME_BCX_OFFSET; -+ private static int INTERPRETER_FRAME_INITIAL_SP_OFFSET; -+ private static int INTERPRETER_FRAME_MONITOR_BLOCK_TOP_OFFSET; -+ private static int INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET; -+ -+ // Entry frames -+ private static int ENTRY_FRAME_CALL_WRAPPER_OFFSET; -+ -+ private static VMReg rbp; ++package jdk.vm.ci.code.test.loongarch64; + -+ static { -+ VM.registerVMInitializedObserver(new Observer() { -+ public void update(Observable o, Object data) { -+ initialize(VM.getVM().getTypeDataBase()); -+ } -+ }); -+ } ++import jdk.vm.ci.loongarch64.LoongArch64; ++import jdk.vm.ci.loongarch64.LoongArch64Kind; ++import jdk.vm.ci.code.CallingConvention; ++import jdk.vm.ci.code.CodeCacheProvider; ++import jdk.vm.ci.code.DebugInfo; ++import jdk.vm.ci.code.Register; ++import jdk.vm.ci.code.RegisterArray; ++import jdk.vm.ci.code.RegisterValue; ++import jdk.vm.ci.code.StackSlot; ++import jdk.vm.ci.code.site.ConstantReference; ++import jdk.vm.ci.code.site.DataSectionReference; ++import jdk.vm.ci.code.test.TestAssembler; ++import jdk.vm.ci.code.test.TestHotSpotVMConfig; ++import jdk.vm.ci.hotspot.HotSpotCallingConventionType; ++import jdk.vm.ci.hotspot.HotSpotConstant; ++import jdk.vm.ci.hotspot.HotSpotForeignCallTarget; ++import jdk.vm.ci.meta.AllocatableValue; ++import jdk.vm.ci.meta.JavaKind; ++import jdk.vm.ci.meta.VMConstant; + -+ private static synchronized void initialize(TypeDataBase db) { -+ INTERPRETER_FRAME_MIRROR_OFFSET = INTERPRETER_FRAME_METHOD_OFFSET - 1; -+ INTERPRETER_FRAME_MDX_OFFSET = INTERPRETER_FRAME_MIRROR_OFFSET - 1; -+ INTERPRETER_FRAME_CACHE_OFFSET = INTERPRETER_FRAME_MDX_OFFSET - 1; -+ INTERPRETER_FRAME_LOCALS_OFFSET = INTERPRETER_FRAME_CACHE_OFFSET - 1; -+ INTERPRETER_FRAME_BCX_OFFSET = INTERPRETER_FRAME_LOCALS_OFFSET - 1; -+ INTERPRETER_FRAME_INITIAL_SP_OFFSET = INTERPRETER_FRAME_BCX_OFFSET - 1; -+ INTERPRETER_FRAME_MONITOR_BLOCK_TOP_OFFSET = INTERPRETER_FRAME_INITIAL_SP_OFFSET; -+ INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET = INTERPRETER_FRAME_INITIAL_SP_OFFSET; ++public class LoongArch64TestAssembler extends TestAssembler { + -+ ENTRY_FRAME_CALL_WRAPPER_OFFSET = db.lookupIntConstant("frame::entry_frame_call_wrapper_offset"); -+ if (VM.getVM().getAddressSize() == 4) { -+ rbp = new VMReg(5); -+ } else { -+ rbp = new VMReg(5 << 1); ++ private static final Register scratchRegister = LoongArch64.SCR1; ++ private static final Register doubleScratch = LoongArch64.f23; ++ private static final RegisterArray nativeGeneralParameterRegisters = new RegisterArray(LoongArch64.a0, ++ LoongArch64.a1, LoongArch64.a2, ++ LoongArch64.a3, LoongArch64.a4, ++ LoongArch64.a5, LoongArch64.a6, ++ LoongArch64.a7); ++ private static final RegisterArray floatParameterRegisters = new RegisterArray(LoongArch64.f0, ++ LoongArch64.f1, LoongArch64.f2, ++ LoongArch64.f3, LoongArch64.f4, ++ LoongArch64.f5, LoongArch64.f6, ++ LoongArch64.f7); ++ private static int currentGeneral = 0; ++ private static int currentFloat = 0; ++ public LoongArch64TestAssembler(CodeCacheProvider codeCache, TestHotSpotVMConfig config) { ++ super(codeCache, config, ++ 16 /* initialFrameSize */, 16 /* stackAlignment */, ++ LoongArch64Kind.UDWORD /* narrowOopKind */, ++ /* registers */ ++ LoongArch64.a0, LoongArch64.a1, LoongArch64.a2, LoongArch64.a3, ++ LoongArch64.a4, LoongArch64.a5, LoongArch64.a6, LoongArch64.a7); + } -+ } -+ -+ -+ // an additional field beyond sp and pc: -+ Address raw_fp; // frame pointer -+ private Address raw_unextendedSP; -+ -+ private MIPS64Frame() { -+ } + -+ private void adjustForDeopt() { -+ if ( pc != null) { -+ // Look for a deopt pc and if it is deopted convert to original pc -+ CodeBlob cb = VM.getVM().getCodeCache().findBlob(pc); -+ if (cb != null && cb.isJavaMethod()) { -+ NMethod nm = (NMethod) cb; -+ if (pc.equals(nm.deoptHandlerBegin())) { -+ if (Assert.ASSERTS_ENABLED) { -+ Assert.that(this.getUnextendedSP() != null, "null SP in Java frame"); -+ } -+ // adjust pc if frame is deoptimized. -+ pc = this.getUnextendedSP().getAddressAt(nm.origPCOffset()); -+ deoptimized = true; -+ } -+ } ++ private static int low(int x, int l) { ++ assert l < 32; ++ return (x >> 0) & ((1 << l)-1); + } -+ } -+ -+ public MIPS64Frame(Address raw_sp, Address raw_fp, Address pc) { -+ this.raw_sp = raw_sp; -+ this.raw_unextendedSP = raw_sp; -+ this.raw_fp = raw_fp; -+ this.pc = pc; -+ adjustUnextendedSP(); + -+ // Frame must be fully constructed before this call -+ adjustForDeopt(); -+ -+ if (DEBUG) { -+ System.out.println("MIPS64Frame(sp, fp, pc): " + this); -+ dumpStack(); ++ private static int low16(int x) { ++ return low(x, 16); + } -+ } -+ -+ public MIPS64Frame(Address raw_sp, Address raw_fp) { -+ this.raw_sp = raw_sp; -+ this.raw_unextendedSP = raw_sp; -+ this.raw_fp = raw_fp; -+ this.pc = raw_sp.getAddressAt(-1 * VM.getVM().getAddressSize()); -+ adjustUnextendedSP(); + -+ // Frame must be fully constructed before this call -+ adjustForDeopt(); -+ -+ if (DEBUG) { -+ System.out.println("MIPS64Frame(sp, fp): " + this); -+ dumpStack(); ++ private void emitNop() { ++ code.emitInt(0x3400000); + } -+ } -+ -+ public MIPS64Frame(Address raw_sp, Address raw_unextendedSp, Address raw_fp, Address pc) { -+ this.raw_sp = raw_sp; -+ this.raw_unextendedSP = raw_unextendedSp; -+ this.raw_fp = raw_fp; -+ this.pc = pc; -+ adjustUnextendedSP(); + -+ // Frame must be fully constructed before this call -+ adjustForDeopt(); -+ -+ if (DEBUG) { -+ System.out.println("MIPS64Frame(sp, unextendedSP, fp, pc): " + this); -+ dumpStack(); ++ private void emitPcaddu12i(Register rj, int si20) { ++ // pcaddu12i ++ code.emitInt((0b0001110 << 25) ++ | (low(si20, 20) << 5) ++ | rj.encoding); + } + -+ } -+ -+ public Object clone() { -+ MIPS64Frame frame = new MIPS64Frame(); -+ frame.raw_sp = raw_sp; -+ frame.raw_unextendedSP = raw_unextendedSP; -+ frame.raw_fp = raw_fp; -+ frame.pc = pc; -+ frame.deoptimized = deoptimized; -+ return frame; -+ } -+ -+ public boolean equals(Object arg) { -+ if (arg == null) { -+ return false; ++ private void emitAdd(Register rd, Register rj, Register rk) { ++ // add_d ++ code.emitInt((0b00000000000100001 << 15) ++ | (rk.encoding << 10) ++ | (rj.encoding << 5) ++ | rd.encoding); + } + -+ if (!(arg instanceof MIPS64Frame)) { -+ return false; ++ private void emitAdd(Register rd, Register rj, int si12) { ++ // addi_d ++ code.emitInt((0b0000001011 << 22) ++ | (low(si12, 12) << 10) ++ | (rj.encoding << 5) ++ | rd.encoding); + } + -+ MIPS64Frame other = (MIPS64Frame) arg; -+ -+ return (AddressOps.equal(getSP(), other.getSP()) && -+ AddressOps.equal(getUnextendedSP(), other.getUnextendedSP()) && -+ AddressOps.equal(getFP(), other.getFP()) && -+ AddressOps.equal(getPC(), other.getPC())); -+ } -+ -+ public int hashCode() { -+ if (raw_sp == null) { -+ return 0; ++ private void emitSub(Register rd, Register rj, Register rk) { ++ // sub_d ++ code.emitInt((0b00000000000100011 << 15) ++ | (rk.encoding << 10) ++ | (rj.encoding << 5) ++ | rd.encoding); + } + -+ return raw_sp.hashCode(); -+ } -+ -+ public String toString() { -+ return "sp: " + (getSP() == null? "null" : getSP().toString()) + -+ ", unextendedSP: " + (getUnextendedSP() == null? "null" : getUnextendedSP().toString()) + -+ ", fp: " + (getFP() == null? "null" : getFP().toString()) + -+ ", pc: " + (pc == null? "null" : pc.toString()); -+ } -+ -+ // accessors for the instance variables -+ public Address getFP() { return raw_fp; } -+ public Address getSP() { return raw_sp; } -+ public Address getID() { return raw_sp; } -+ -+ // FIXME: not implemented yet (should be done for Solaris/MIPS) -+ public boolean isSignalHandlerFrameDbg() { return false; } -+ public int getSignalNumberDbg() { return 0; } -+ public String getSignalNameDbg() { return null; } -+ -+ public boolean isInterpretedFrameValid() { -+ if (Assert.ASSERTS_ENABLED) { -+ Assert.that(isInterpretedFrame(), "Not an interpreted frame"); ++ private void emitShiftLeft(Register rd, Register rj, int shift) { ++ // slli_d ++ code.emitInt((0b00000000010000 << 18) ++ | (low(( (0b01 << 6) | shift ), 8) << 10) ++ | (rj.encoding << 5) ++ | rd.encoding); + } + -+ // These are reasonable sanity checks -+ if (getFP() == null || getFP().andWithMask(0x3) != null) { -+ return false; ++ private void emitLu12i_w(Register rj, int imm20) { ++ // lu12i_w ++ code.emitInt((0b0001010 << 25) ++ | (low(imm20, 20)<<5) ++ | rj.encoding); + } + -+ if (getSP() == null || getSP().andWithMask(0x3) != null) { -+ return false; ++ private void emitOri(Register rd, Register rj, int ui12) { ++ // ori ++ code.emitInt((0b0000001110 << 22) ++ | (low(ui12, 12) << 10) ++ | (rj.encoding << 5) ++ | rd.encoding); + } + -+ if (getFP().addOffsetTo(INTERPRETER_FRAME_INITIAL_SP_OFFSET * VM.getVM().getAddressSize()).lessThan(getSP())) { -+ return false; ++ private void emitLu32i_d(Register rj, int imm20) { ++ // lu32i_d ++ code.emitInt((0b0001011 << 25) ++ | (low(imm20, 20)<<5) ++ | rj.encoding); + } + -+ // These are hacks to keep us out of trouble. -+ // The problem with these is that they mask other problems -+ if (getFP().lessThanOrEqual(getSP())) { -+ // this attempts to deal with unsigned comparison above -+ return false; ++ private void emitLu52i_d(Register rd, Register rj, int imm12) { ++ // lu52i_d ++ code.emitInt((0b0000001100 << 22) ++ | (low(imm12, 12) << 10) ++ | (rj.encoding << 5) ++ | rd.encoding); + } + -+ if (getFP().minus(getSP()) > 4096 * VM.getVM().getAddressSize()) { -+ // stack frames shouldn't be large. -+ return false; ++ private void emitLoadImmediate(Register rd, int imm32) { ++ emitLu12i_w(rd, (imm32 >> 12) & 0xfffff); ++ emitOri(rd, rd, imm32 & 0xfff); + } + -+ return true; -+ } -+ -+ // FIXME: not applicable in current system -+ // void patch_pc(Thread* thread, address pc); -+ -+ public Frame sender(RegisterMap regMap, CodeBlob cb) { -+ MIPS64RegisterMap map = (MIPS64RegisterMap) regMap; -+ -+ if (Assert.ASSERTS_ENABLED) { -+ Assert.that(map != null, "map must be set"); ++ private void emitLi52(Register rj, long imm) { ++ emitLu12i_w(rj, (int) ((imm >> 12) & 0xfffff)); ++ emitOri(rj, rj, (int) (imm & 0xfff)); ++ emitLu32i_d(rj, (int) ((imm >> 32) & 0xfffff)); + } + -+ // Default is we done have to follow them. The sender_for_xxx will -+ // update it accordingly -+ map.setIncludeArgumentOops(false); ++ private void emitLi64(Register rj, long imm) { ++ emitLu12i_w(rj, (int) ((imm >> 12) & 0xfffff)); ++ emitOri(rj, rj, (int) (imm & 0xfff)); ++ emitLu32i_d(rj, (int) ((imm >> 32) & 0xfffff)); ++ emitLu52i_d(rj, rj, (int) ((imm >> 52) & 0xfff)); ++ } + -+ if (isEntryFrame()) return senderForEntryFrame(map); -+ if (isInterpretedFrame()) return senderForInterpreterFrame(map); ++ private void emitOr(Register rd, Register rj, Register rk) { ++ // orr ++ code.emitInt((0b00000000000101010 << 15) ++ | (rk.encoding << 10) ++ | (rj.encoding << 5) ++ | rd.encoding); ++ } + -+ if(cb == null) { -+ cb = VM.getVM().getCodeCache().findBlob(getPC()); -+ } else { -+ if (Assert.ASSERTS_ENABLED) { -+ Assert.that(cb.equals(VM.getVM().getCodeCache().findBlob(getPC())), "Must be the same"); -+ } ++ private void emitMove(Register rd, Register rs) { ++ // move ++ emitOr(rd, rs, LoongArch64.zero); + } + -+ if (cb != null) { -+ return senderForCompiledFrame(map, cb); ++ private void emitMovfr2gr(Register rd, LoongArch64Kind kind, Register rj) { ++ // movfr2gr_s/movfr2gr_d ++ int opc = 0; ++ switch (kind) { ++ case SINGLE: opc = 0b0000000100010100101101; break; ++ case DOUBLE: opc = 0b0000000100010100101110; break; ++ default: throw new IllegalArgumentException(); ++ } ++ code.emitInt((opc << 10) ++ | (rj.encoding << 5) ++ | rd.encoding); + } + -+ // Must be native-compiled frame, i.e. the marshaling code for native -+ // methods that exists in the core system. -+ return new MIPS64Frame(getSenderSP(), getLink(), getSenderPC()); -+ } ++ private void emitLoadRegister(Register rd, LoongArch64Kind kind, Register rj, int offset) { ++ // load ++ assert offset >= 0; ++ int opc = 0; ++ switch (kind) { ++ case BYTE: opc = 0b0010100000; break; ++ case WORD: opc = 0b0010100001; break; ++ case DWORD: opc = 0b0010100010; break; ++ case QWORD: opc = 0b0010100011; break; ++ case UDWORD: opc = 0b0010101010; break; ++ case SINGLE: opc = 0b0010101100; break; ++ case DOUBLE: opc = 0b0010101110; break; ++ default: throw new IllegalArgumentException(); ++ } ++ code.emitInt((opc << 22) ++ | (low(offset, 12) << 10) ++ | (rj.encoding << 5) ++ | rd.encoding); ++ } + -+ private Frame senderForEntryFrame(MIPS64RegisterMap map) { -+ if (DEBUG) { -+ System.out.println("senderForEntryFrame"); ++ private void emitStoreRegister(Register rd, LoongArch64Kind kind, Register rj, int offset) { ++ // store ++ assert offset >= 0; ++ int opc = 0; ++ switch (kind) { ++ case BYTE: opc = 0b0010100100; break; ++ case WORD: opc = 0b0010100101; break; ++ case DWORD: opc = 0b0010100110; break; ++ case QWORD: opc = 0b0010100111; break; ++ case SINGLE: opc = 0b0010101101; break; ++ case DOUBLE: opc = 0b0010101111; break; ++ default: throw new IllegalArgumentException(); ++ } ++ code.emitInt((opc << 22) ++ | (low(offset, 12) << 10) ++ | (rj.encoding << 5) ++ | rd.encoding); + } -+ if (Assert.ASSERTS_ENABLED) { -+ Assert.that(map != null, "map must be set"); ++ ++ private void emitJirl(Register rd, Register rj, int offs) { ++ // jirl ++ code.emitInt((0b010011 << 26) ++ | (low16(offs >> 2) << 10) ++ | (rj.encoding << 5) ++ | rd.encoding); + } -+ // Java frame called from C; skip all C frames and return top C -+ // frame of that chunk as the sender -+ MIPS64JavaCallWrapper jcw = (MIPS64JavaCallWrapper) getEntryFrameCallWrapper(); -+ if (Assert.ASSERTS_ENABLED) { -+ Assert.that(!entryFrameIsFirst(), "next Java fp must be non zero"); -+ Assert.that(jcw.getLastJavaSP().greaterThan(getSP()), "must be above this frame on stack"); ++ ++ @Override ++ public void emitGrowStack(int size) { ++ assert size % 16 == 0; ++ if (size > -4096 && size < 0) { ++ emitAdd(LoongArch64.sp, LoongArch64.sp, -size); ++ } else if (size == 0) { ++ // No-op ++ } else if (size < 4096) { ++ emitAdd(LoongArch64.sp, LoongArch64.sp, -size); ++ } else if (size < 65535) { ++ emitLoadImmediate(scratchRegister, size); ++ emitSub(LoongArch64.sp, LoongArch64.sp, scratchRegister); ++ } else { ++ throw new IllegalArgumentException(); ++ } + } -+ MIPS64Frame fr; -+ if (jcw.getLastJavaPC() != null) { -+ fr = new MIPS64Frame(jcw.getLastJavaSP(), jcw.getLastJavaFP(), jcw.getLastJavaPC()); -+ } else { -+ fr = new MIPS64Frame(jcw.getLastJavaSP(), jcw.getLastJavaFP()); ++ ++ @Override ++ public void emitPrologue() { ++ // Must be patchable by NativeJump::patch_verified_entry ++ emitNop(); ++ emitGrowStack(32); ++ emitStoreRegister(LoongArch64.ra, LoongArch64Kind.QWORD, LoongArch64.sp, 24); ++ emitStoreRegister(LoongArch64.fp, LoongArch64Kind.QWORD, LoongArch64.sp, 16); ++ emitGrowStack(-16); ++ emitMove(LoongArch64.fp, LoongArch64.sp); ++ setDeoptRescueSlot(newStackSlot(LoongArch64Kind.QWORD)); + } -+ map.clear(); -+ if (Assert.ASSERTS_ENABLED) { -+ Assert.that(map.getIncludeArgumentOops(), "should be set by clear"); ++ ++ @Override ++ public void emitEpilogue() { ++ recordMark(config.MARKID_DEOPT_HANDLER_ENTRY); ++ recordCall(new HotSpotForeignCallTarget(config.handleDeoptStub), 4*4, true, null); ++ emitCall(0xdeaddeaddeadL); + } -+ return fr; -+ } + -+ //------------------------------------------------------------------------------ -+ // frame::adjust_unextended_sp -+ private void adjustUnextendedSP() { -+ // On mips, sites calling method handle intrinsics and lambda forms are treated -+ // as any other call site. Therefore, no special action is needed when we are -+ // returning to any of these call sites. ++ @Override ++ public void emitCallPrologue(CallingConvention cc, Object... prim) { ++ emitGrowStack(cc.getStackSize()); ++ frameSize += cc.getStackSize(); ++ AllocatableValue[] args = cc.getArguments(); ++ for (int i = 0; i < args.length; i++) { ++ emitLoad(args[i], prim[i]); ++ } ++ currentGeneral = 0; ++ currentFloat = 0; ++ } + -+ CodeBlob cb = cb(); -+ NMethod senderNm = (cb == null) ? null : cb.asNMethodOrNull(); -+ if (senderNm != null) { -+ // If the sender PC is a deoptimization point, get the original PC. -+ if (senderNm.isDeoptEntry(getPC()) || -+ senderNm.isDeoptMhEntry(getPC())) { -+ // DEBUG_ONLY(verifyDeoptriginalPc(senderNm, raw_unextendedSp)); -+ } ++ @Override ++ public void emitCallEpilogue(CallingConvention cc) { ++ emitGrowStack(-cc.getStackSize()); ++ frameSize -= cc.getStackSize(); + } -+ } + -+ private Frame senderForInterpreterFrame(MIPS64RegisterMap map) { -+ if (DEBUG) { -+ System.out.println("senderForInterpreterFrame"); ++ @Override ++ public void emitCall(long addr) { ++ // long call (absolute) ++ // lu12i_w(T4, split_low20(value >> 12)); ++ // lu32i_d(T4, split_low20(value >> 32)); ++ // jirl(RA, T4, split_low12(value)); ++ emitLu12i_w(LoongArch64.t4, (int) ((addr >> 12) & 0xfffff)); ++ emitLu32i_d(LoongArch64.t4, (int) ((addr >> 32) & 0xfffff)); ++ emitJirl(LoongArch64.ra, LoongArch64.t4, (int) (addr & 0xfff)); + } -+ Address unextendedSP = addressOfStackSlot(INTERPRETER_FRAME_SENDER_SP_OFFSET).getAddressAt(0); -+ Address sp = addressOfStackSlot(SENDER_SP_OFFSET); -+ // We do not need to update the callee-save register mapping because above -+ // us is either another interpreter frame or a converter-frame, but never -+ // directly a compiled frame. -+ // 11/24/04 SFG. With the removal of adapter frames this is no longer true. -+ // However c2 no longer uses callee save register for java calls so there -+ // are no callee register to find. + -+ if (map.getUpdateMap()) -+ updateMapWithSavedLink(map, addressOfStackSlot(LINK_OFFSET)); ++ @Override ++ public void emitLoad(AllocatableValue av, Object prim) { ++ if (av instanceof RegisterValue) { ++ Register reg = ((RegisterValue) av).getRegister(); ++ if (prim instanceof Float) { ++ if (currentFloat < floatParameterRegisters.size()) { ++ currentFloat++; ++ emitLoadFloat(reg, (Float) prim); ++ } else if (currentGeneral < nativeGeneralParameterRegisters.size()) { ++ currentGeneral++; ++ emitLoadFloat(doubleScratch, (Float) prim); ++ emitMovfr2gr(reg, LoongArch64Kind.SINGLE, doubleScratch); ++ } ++ } else if (prim instanceof Double) { ++ if (currentFloat < floatParameterRegisters.size()) { ++ currentFloat++; ++ emitLoadDouble(reg, (Double) prim); ++ } else if (currentGeneral < nativeGeneralParameterRegisters.size()) { ++ currentGeneral++; ++ emitLoadDouble(doubleScratch, (Double) prim); ++ emitMovfr2gr(reg, LoongArch64Kind.DOUBLE, doubleScratch); ++ } ++ } else if (prim instanceof Integer) { ++ emitLoadInt(reg, (Integer) prim); ++ } else if (prim instanceof Long) { ++ emitLoadLong(reg, (Long) prim); ++ } ++ } else if (av instanceof StackSlot) { ++ StackSlot slot = (StackSlot) av; ++ if (prim instanceof Float) { ++ emitFloatToStack(slot, emitLoadFloat(doubleScratch, (Float) prim)); ++ } else if (prim instanceof Double) { ++ emitDoubleToStack(slot, emitLoadDouble(doubleScratch, (Double) prim)); ++ } else if (prim instanceof Integer) { ++ emitIntToStack(slot, emitLoadInt(scratchRegister, (Integer) prim)); ++ } else if (prim instanceof Long) { ++ emitLongToStack(slot, emitLoadLong(scratchRegister, (Long) prim)); ++ } else { ++ assert false : "Unimplemented"; ++ } ++ } else { ++ throw new IllegalArgumentException("Unknown value " + av); ++ } ++ } + -+ return new MIPS64Frame(sp, unextendedSP, getLink(), getSenderPC()); -+ } ++ @Override ++ public Register emitLoadPointer(HotSpotConstant c) { ++ recordDataPatchInCode(new ConstantReference((VMConstant) c)); + -+ private void updateMapWithSavedLink(RegisterMap map, Address savedFPAddr) { -+ map.setLocation(rbp, savedFPAddr); -+ } ++ Register ret = newRegister(); ++ // need to match patchable_li52 instruction sequence ++ // lu12i_ori_lu32i ++ emitLi52(ret, 0xdeaddead); ++ return ret; ++ } + -+ private Frame senderForCompiledFrame(MIPS64RegisterMap map, CodeBlob cb) { -+ if (DEBUG) { -+ System.out.println("senderForCompiledFrame"); ++ @Override ++ public Register emitLoadPointer(Register b, int offset) { ++ Register ret = newRegister(); ++ emitLoadRegister(ret, LoongArch64Kind.QWORD, b, offset); ++ return ret; + } + -+ // -+ // NOTE: some of this code is (unfortunately) duplicated in MIPS64CurrentFrameGuess -+ // ++ @Override ++ public Register emitLoadNarrowPointer(DataSectionReference ref) { ++ recordDataPatchInCode(ref); + -+ if (Assert.ASSERTS_ENABLED) { -+ Assert.that(map != null, "map must be set"); ++ Register ret = newRegister(); ++ emitPcaddu12i(ret, 0xdead >> 12); ++ emitAdd(ret, ret, 0xdead & 0xfff); ++ emitLoadRegister(ret, LoongArch64Kind.UDWORD, ret, 0); ++ return ret; + } + -+ // frame owned by optimizing compiler -+ if (Assert.ASSERTS_ENABLED) { -+ Assert.that(cb.getFrameSize() >= 0, "must have non-zero frame size"); -+ } -+ Address senderSP = getUnextendedSP().addOffsetTo(cb.getFrameSize()); ++ @Override ++ public Register emitLoadPointer(DataSectionReference ref) { ++ recordDataPatchInCode(ref); + -+ // On Intel the return_address is always the word on the stack -+ Address senderPC = senderSP.getAddressAt(-1 * VM.getVM().getAddressSize()); ++ Register ret = newRegister(); ++ emitPcaddu12i(ret, 0xdead >> 12); ++ emitAdd(ret, ret, 0xdead & 0xfff); ++ emitLoadRegister(ret, LoongArch64Kind.QWORD, ret, 0); ++ return ret; ++ } + -+ // This is the saved value of EBP which may or may not really be an FP. -+ // It is only an FP if the sender is an interpreter frame (or C1?). -+ Address savedFPAddr = senderSP.addOffsetTo(- SENDER_SP_OFFSET * VM.getVM().getAddressSize()); ++ private Register emitLoadDouble(Register reg, double c) { ++ DataSectionReference ref = new DataSectionReference(); ++ ref.setOffset(data.position()); ++ data.emitDouble(c); + -+ if (map.getUpdateMap()) { -+ // Tell GC to use argument oopmaps for some runtime stubs that need it. -+ // For C1, the runtime stub might not have oop maps, so set this flag -+ // outside of update_register_map. -+ map.setIncludeArgumentOops(cb.callerMustGCArguments()); ++ recordDataPatchInCode(ref); ++ emitPcaddu12i(scratchRegister, 0xdead >> 12); ++ emitAdd(scratchRegister, scratchRegister, 0xdead & 0xfff); ++ emitLoadRegister(reg, LoongArch64Kind.DOUBLE, scratchRegister, 0); ++ return reg; ++ } + -+ if (cb.getOopMaps() != null) { -+ ImmutableOopMapSet.updateRegisterMap(this, cb, map, true); -+ } ++ private Register emitLoadFloat(Register reg, float c) { ++ DataSectionReference ref = new DataSectionReference(); ++ ref.setOffset(data.position()); ++ data.emitFloat(c); + -+ // Since the prolog does the save and restore of EBP there is no oopmap -+ // for it so we must fill in its location as if there was an oopmap entry -+ // since if our caller was compiled code there could be live jvm state in it. -+ updateMapWithSavedLink(map, savedFPAddr); ++ recordDataPatchInCode(ref); ++ emitPcaddu12i(scratchRegister, 0xdead >> 12); ++ emitAdd(scratchRegister, scratchRegister, 0xdead & 0xfff); ++ emitLoadRegister(reg, LoongArch64Kind.SINGLE, scratchRegister, 0); ++ return reg; + } + -+ return new MIPS64Frame(senderSP, savedFPAddr.getAddressAt(0), senderPC); -+ } -+ -+ protected boolean hasSenderPD() { -+ // FIXME -+ // Check for null ebp? Need to do some tests. -+ return true; -+ } ++ @Override ++ public Register emitLoadFloat(float c) { ++ Register ret = LoongArch64.fv0; ++ return emitLoadFloat(ret, c); ++ } + -+ public long frameSize() { -+ return (getSenderSP().minus(getSP()) / VM.getVM().getAddressSize()); -+ } ++ private Register emitLoadLong(Register reg, long c) { ++ emitLi64(reg, c); ++ return reg; ++ } + -+ public Address getLink() { -+ return addressOfStackSlot(LINK_OFFSET).getAddressAt(0); -+ } ++ @Override ++ public Register emitLoadLong(long c) { ++ Register ret = newRegister(); ++ return emitLoadLong(ret, c); ++ } + -+ public Address getUnextendedSP() { return raw_unextendedSP; } ++ private Register emitLoadInt(Register reg, int c) { ++ emitLoadImmediate(reg, c); ++ return reg; ++ } + -+ // Return address: -+ public Address getSenderPCAddr() { return addressOfStackSlot(RETURN_ADDR_OFFSET); } -+ public Address getSenderPC() { return getSenderPCAddr().getAddressAt(0); } ++ @Override ++ public Register emitLoadInt(int c) { ++ Register ret = newRegister(); ++ return emitLoadInt(ret, c); ++ } + -+ public Address getSenderSP() { return addressOfStackSlot(SENDER_SP_OFFSET); } ++ @Override ++ public Register emitIntArg0() { ++ return codeCache.getRegisterConfig() ++ .getCallingConventionRegisters(HotSpotCallingConventionType.JavaCall, JavaKind.Int) ++ .get(0); ++ } + -+ public Address addressOfInterpreterFrameLocals() { -+ return addressOfStackSlot(INTERPRETER_FRAME_LOCALS_OFFSET); -+ } ++ @Override ++ public Register emitIntArg1() { ++ return codeCache.getRegisterConfig() ++ .getCallingConventionRegisters(HotSpotCallingConventionType.JavaCall, JavaKind.Int) ++ .get(1); ++ } + -+ private Address addressOfInterpreterFrameBCX() { -+ return addressOfStackSlot(INTERPRETER_FRAME_BCX_OFFSET); -+ } ++ @Override ++ public Register emitIntAdd(Register a, Register b) { ++ emitAdd(a, a, b); ++ return a; ++ } + -+ public int getInterpreterFrameBCI() { -+ // FIXME: this is not atomic with respect to GC and is unsuitable -+ // for use in a non-debugging, or reflective, system. Need to -+ // figure out how to express this. -+ Address bcp = addressOfInterpreterFrameBCX().getAddressAt(0); -+ Address methodHandle = addressOfInterpreterFrameMethod().getAddressAt(0); -+ Method method = (Method)Metadata.instantiateWrapperFor(methodHandle); -+ return bcpToBci(bcp, method); -+ } ++ @Override ++ public void emitTrap(DebugInfo info) { ++ // Dereference null pointer ++ emitMove(scratchRegister, LoongArch64.zero); ++ recordImplicitException(info); ++ emitLoadRegister(LoongArch64.zero, LoongArch64Kind.QWORD, scratchRegister, 0); ++ } + -+ public Address addressOfInterpreterFrameMDX() { -+ return addressOfStackSlot(INTERPRETER_FRAME_MDX_OFFSET); -+ } ++ @Override ++ public void emitIntRet(Register a) { ++ emitMove(LoongArch64.v0, a); ++ emitMove(LoongArch64.sp, LoongArch64.fp); ++ emitLoadRegister(LoongArch64.ra, LoongArch64Kind.QWORD, LoongArch64.sp, 8); ++ emitLoadRegister(LoongArch64.fp, LoongArch64Kind.QWORD, LoongArch64.sp, 0); ++ emitGrowStack(-16); ++ emitJirl(LoongArch64.zero, LoongArch64.ra, 0); ++ } + -+ // FIXME -+ //inline int frame::interpreter_frame_monitor_size() { -+ // return BasicObjectLock::size(); -+ //} ++ @Override ++ public void emitFloatRet(Register a) { ++ assert a == LoongArch64.fv0 : "Unimplemented move " + a; ++ emitMove(LoongArch64.sp, LoongArch64.fp); ++ emitLoadRegister(LoongArch64.ra, LoongArch64Kind.QWORD, LoongArch64.sp, 8); ++ emitLoadRegister(LoongArch64.fp, LoongArch64Kind.QWORD, LoongArch64.sp, 0); ++ emitGrowStack(-16); ++ emitJirl(LoongArch64.zero, LoongArch64.ra, 0); ++ } + -+ // expression stack -+ // (the max_stack arguments are used by the GC; see class FrameClosure) ++ @Override ++ public void emitPointerRet(Register a) { ++ emitIntRet(a); ++ } + -+ public Address addressOfInterpreterFrameExpressionStack() { -+ Address monitorEnd = interpreterFrameMonitorEnd().address(); -+ return monitorEnd.addOffsetTo(-1 * VM.getVM().getAddressSize()); -+ } ++ @Override ++ public StackSlot emitPointerToStack(Register a) { ++ return emitLongToStack(a); ++ } + -+ public int getInterpreterFrameExpressionStackDirection() { return -1; } ++ @Override ++ public StackSlot emitNarrowPointerToStack(Register a) { ++ return emitIntToStack(a); ++ } + -+ // top of expression stack -+ public Address addressOfInterpreterFrameTOS() { -+ return getSP(); -+ } ++ @Override ++ public Register emitUncompressPointer(Register compressed, long base, int shift) { ++ if (shift > 0) { ++ emitShiftLeft(compressed, compressed, shift); ++ } + -+ /** Expression stack from top down */ -+ public Address addressOfInterpreterFrameTOSAt(int slot) { -+ return addressOfInterpreterFrameTOS().addOffsetTo(slot * VM.getVM().getAddressSize()); -+ } ++ if (base != 0) { ++ emitLoadLong(scratchRegister, base); ++ emitAdd(compressed, compressed, scratchRegister); ++ } + -+ public Address getInterpreterFrameSenderSP() { -+ if (Assert.ASSERTS_ENABLED) { -+ Assert.that(isInterpretedFrame(), "interpreted frame expected"); ++ return compressed; + } -+ return addressOfStackSlot(INTERPRETER_FRAME_SENDER_SP_OFFSET).getAddressAt(0); -+ } -+ -+ // Monitors -+ public BasicObjectLock interpreterFrameMonitorBegin() { -+ return new BasicObjectLock(addressOfStackSlot(INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET)); -+ } + -+ public BasicObjectLock interpreterFrameMonitorEnd() { -+ Address result = addressOfStackSlot(INTERPRETER_FRAME_MONITOR_BLOCK_TOP_OFFSET).getAddressAt(0); -+ if (Assert.ASSERTS_ENABLED) { -+ // make sure the pointer points inside the frame -+ Assert.that(AddressOps.gt(getFP(), result), "result must < than frame pointer"); -+ Assert.that(AddressOps.lte(getSP(), result), "result must >= than stack pointer"); ++ private StackSlot emitDoubleToStack(StackSlot slot, Register a) { ++ emitStoreRegister(a, LoongArch64Kind.DOUBLE, LoongArch64.sp, slot.getOffset(frameSize)); ++ return slot; + } -+ return new BasicObjectLock(result); -+ } + -+ public int interpreterFrameMonitorSize() { -+ return BasicObjectLock.size(); -+ } ++ @Override ++ public StackSlot emitDoubleToStack(Register a) { ++ StackSlot ret = newStackSlot(LoongArch64Kind.DOUBLE); ++ return emitDoubleToStack(ret, a); ++ } + -+ // Method -+ public Address addressOfInterpreterFrameMethod() { -+ return addressOfStackSlot(INTERPRETER_FRAME_METHOD_OFFSET); -+ } ++ private StackSlot emitFloatToStack(StackSlot slot, Register a) { ++ emitStoreRegister(a, LoongArch64Kind.SINGLE, LoongArch64.sp, slot.getOffset(frameSize)); ++ return slot; ++ } + -+ // Constant pool cache -+ public Address addressOfInterpreterFrameCPCache() { -+ return addressOfStackSlot(INTERPRETER_FRAME_CACHE_OFFSET); -+ } ++ @Override ++ public StackSlot emitFloatToStack(Register a) { ++ StackSlot ret = newStackSlot(LoongArch64Kind.SINGLE); ++ return emitFloatToStack(ret, a); ++ } + -+ // Entry frames -+ public JavaCallWrapper getEntryFrameCallWrapper() { -+ return new MIPS64JavaCallWrapper(addressOfStackSlot(ENTRY_FRAME_CALL_WRAPPER_OFFSET).getAddressAt(0)); -+ } ++ private StackSlot emitIntToStack(StackSlot slot, Register a) { ++ emitStoreRegister(a, LoongArch64Kind.DWORD, LoongArch64.sp, slot.getOffset(frameSize)); ++ return slot; ++ } + -+ protected Address addressOfSavedOopResult() { -+ // offset is 2 for compiler2 and 3 for compiler1 -+ return getSP().addOffsetTo((VM.getVM().isClientCompiler() ? 2 : 3) * -+ VM.getVM().getAddressSize()); -+ } ++ @Override ++ public StackSlot emitIntToStack(Register a) { ++ StackSlot ret = newStackSlot(LoongArch64Kind.DWORD); ++ return emitIntToStack(ret, a); ++ } + -+ protected Address addressOfSavedReceiver() { -+ return getSP().addOffsetTo(-4 * VM.getVM().getAddressSize()); -+ } ++ private StackSlot emitLongToStack(StackSlot slot, Register a) { ++ emitStoreRegister(a, LoongArch64Kind.QWORD, LoongArch64.sp, slot.getOffset(frameSize)); ++ return slot; ++ } + -+ private void dumpStack() { -+ if (getFP() != null) { -+ for (Address addr = getSP().addOffsetTo(-5 * VM.getVM().getAddressSize()); -+ AddressOps.lte(addr, getFP().addOffsetTo(5 * VM.getVM().getAddressSize())); -+ addr = addr.addOffsetTo(VM.getVM().getAddressSize())) { -+ System.out.println(addr + ": " + addr.getAddressAt(0)); -+ } -+ } else { -+ for (Address addr = getSP().addOffsetTo(-5 * VM.getVM().getAddressSize()); -+ AddressOps.lte(addr, getSP().addOffsetTo(20 * VM.getVM().getAddressSize())); -+ addr = addr.addOffsetTo(VM.getVM().getAddressSize())) { -+ System.out.println(addr + ": " + addr.getAddressAt(0)); -+ } ++ @Override ++ public StackSlot emitLongToStack(Register a) { ++ StackSlot ret = newStackSlot(LoongArch64Kind.QWORD); ++ return emitLongToStack(ret, a); + } -+ } ++ +} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/mips64/MIPS64JavaCallWrapper.java jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/mips64/MIPS64JavaCallWrapper.java ---- openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/mips64/MIPS64JavaCallWrapper.java 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/mips64/MIPS64JavaCallWrapper.java 2023-09-12 13:54:26.433575861 +0800 -@@ -0,0 +1,57 @@ +diff --git a/test/hotspot/jtreg/compiler/runtime/criticalnatives/argumentcorruption/CheckLongArgs.java b/test/hotspot/jtreg/compiler/runtime/criticalnatives/argumentcorruption/CheckLongArgs.java +index acb86812d..664ea11d0 100644 +--- a/test/hotspot/jtreg/compiler/runtime/criticalnatives/argumentcorruption/CheckLongArgs.java ++++ b/test/hotspot/jtreg/compiler/runtime/criticalnatives/argumentcorruption/CheckLongArgs.java +@@ -21,10 +21,17 @@ + * questions. + */ + +/* -+ * Copyright (c) 2001, 2002, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2018, Loongson Technology. 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. -+ * ++ * This file has been modified by Loongson Technology in 2021, These ++ * modifications are Copyright (c) 2021, Loongson Technology, and are made ++ * available on the same license terms set forth above. + */ + -+package sun.jvm.hotspot.runtime.mips64; -+ -+import java.util.*; -+import sun.jvm.hotspot.debugger.*; -+import sun.jvm.hotspot.types.*; -+import sun.jvm.hotspot.runtime.*; + + /* @test + * @bug 8167409 + * @requires (os.arch != "aarch64") & (os.arch != "arm") ++ * @requires (os.arch != "mips64el") & (os.arch != "loongarch64") + * @run main/othervm/native -Xcomp -XX:+CriticalJNINatives compiler.runtime.criticalnatives.argumentcorruption.CheckLongArgs + */ + package compiler.runtime.criticalnatives.argumentcorruption; +diff --git a/test/hotspot/jtreg/compiler/runtime/criticalnatives/lookup/LookUp.java b/test/hotspot/jtreg/compiler/runtime/criticalnatives/lookup/LookUp.java +index eab36f931..ee5ab2f6d 100644 +--- a/test/hotspot/jtreg/compiler/runtime/criticalnatives/lookup/LookUp.java ++++ b/test/hotspot/jtreg/compiler/runtime/criticalnatives/lookup/LookUp.java +@@ -21,10 +21,17 @@ + * questions. + */ + ++/* ++ * This file has been modified by Loongson Technology in 2021, These ++ * modifications are Copyright (c) 2021, Loongson Technology, and are made ++ * available on the same license terms set forth above. ++ */ + -+public class MIPS64JavaCallWrapper extends JavaCallWrapper { -+ private static AddressField lastJavaFPField; + + /* @test + * @bug 8167408 + * @requires (os.arch != "aarch64") & (os.arch != "arm") ++ * @requires (os.arch != "mips64el") & (os.arch != "loongarch64") + * @run main/othervm/native -Xcomp -XX:+CriticalJNINatives compiler.runtime.criticalnatives.lookup.LookUp + */ + package compiler.runtime.criticalnatives.lookup; +diff --git a/test/hotspot/jtreg/compiler/testlibrary/sha/predicate/IntrinsicPredicates.java b/test/hotspot/jtreg/compiler/testlibrary/sha/predicate/IntrinsicPredicates.java +index 7774dabcb..c1cb6e00f 100644 +--- a/test/hotspot/jtreg/compiler/testlibrary/sha/predicate/IntrinsicPredicates.java ++++ b/test/hotspot/jtreg/compiler/testlibrary/sha/predicate/IntrinsicPredicates.java +@@ -21,6 +21,12 @@ + * questions. + */ + ++/* ++ * This file has been modified by Loongson Technology in 2021, These ++ * modifications are Copyright (c) 2021, Loongson Technology, and are made ++ * available on the same license terms set forth above. ++ */ + -+ static { -+ VM.registerVMInitializedObserver(new Observer() { -+ public void update(Observable o, Object data) { -+ initialize(VM.getVM().getTypeDataBase()); -+ } -+ }); -+ } + package compiler.testlibrary.sha.predicate; + + import jdk.test.lib.Platform; +@@ -63,10 +69,12 @@ public class IntrinsicPredicates { + = new OrPredicate(new CPUSpecificPredicate("aarch64.*", new String[] { "sha1" }, null), + new OrPredicate(new CPUSpecificPredicate("s390.*", new String[] { "sha1" }, null), + new OrPredicate(new CPUSpecificPredicate("sparc.*", new String[] { "sha1" }, null), ++ // Basic instructions are used to implement SHA1 Intrinsics on LA, so "sha1" feature is not needed. ++ new OrPredicate(new CPUSpecificPredicate("loongarch64.*", null, null), + // x86 variants + new OrPredicate(new CPUSpecificPredicate("amd64.*", new String[] { "sha" }, null), + new OrPredicate(new CPUSpecificPredicate("i386.*", new String[] { "sha" }, null), +- new CPUSpecificPredicate("x86.*", new String[] { "sha" }, null)))))); ++ new CPUSpecificPredicate("x86.*", new String[] { "sha" }, null))))))); + + public static final BooleanSupplier SHA256_INSTRUCTION_AVAILABLE + = new OrPredicate(new CPUSpecificPredicate("aarch64.*", new String[] { "sha256" }, null), +@@ -74,12 +82,14 @@ public class IntrinsicPredicates { + new OrPredicate(new CPUSpecificPredicate("sparc.*", new String[] { "sha256" }, null), + new OrPredicate(new CPUSpecificPredicate("ppc64.*", new String[] { "sha" }, null), + new OrPredicate(new CPUSpecificPredicate("ppc64le.*", new String[] { "sha" }, null), ++ // Basic instructions are used to implement SHA256 Intrinsics on LA, so "sha256" feature is not needed. ++ new OrPredicate(new CPUSpecificPredicate("loongarch64.*", null, null), + // x86 variants + new OrPredicate(new CPUSpecificPredicate("amd64.*", new String[] { "sha" }, null), + new OrPredicate(new CPUSpecificPredicate("i386.*", new String[] { "sha" }, null), + new OrPredicate(new CPUSpecificPredicate("x86.*", new String[] { "sha" }, null), + new OrPredicate(new CPUSpecificPredicate("amd64.*", new String[] { "avx2", "bmi2" }, null), +- new CPUSpecificPredicate("x86_64", new String[] { "avx2", "bmi2" }, null)))))))))); ++ new CPUSpecificPredicate("x86_64", new String[] { "avx2", "bmi2" }, null))))))))))); + + public static final BooleanSupplier SHA512_INSTRUCTION_AVAILABLE + = new OrPredicate(new CPUSpecificPredicate("aarch64.*", new String[] { "sha512" }, null), +diff --git a/test/hotspot/jtreg/gc/stress/TestStressG1Humongous.java b/test/hotspot/jtreg/gc/stress/TestStressG1Humongous.java +index 5aea51a24..da63e0255 100644 +--- a/test/hotspot/jtreg/gc/stress/TestStressG1Humongous.java ++++ b/test/hotspot/jtreg/gc/stress/TestStressG1Humongous.java +@@ -24,14 +24,41 @@ + package gc.stress; + + /* +- * @test TestStressG1Humongous ++ * @test + * @key gc stress + * @summary Stress G1 by humongous allocations in situation near OOM + * @requires vm.gc.G1 + * @requires !vm.flightRecorder + * @library /test/lib + * @modules java.base/jdk.internal.misc +- * @run driver/timeout=1300 gc.stress.TestStressG1Humongous ++ * @run driver/timeout=180 gc.stress.TestStressG1Humongous 4 3 1.1 120 ++ */ + -+ private static synchronized void initialize(TypeDataBase db) { -+ Type type = db.lookupType("JavaFrameAnchor"); ++/* ++ * @test ++ * @requires vm.gc.G1 ++ * @requires !vm.flightRecorder ++ * @library /test/lib ++ * @modules java.base/jdk.internal.misc ++ * @run driver/timeout=180 gc.stress.TestStressG1Humongous 16 5 2.1 120 ++ */ + -+ lastJavaFPField = type.getAddressField("_last_Java_fp"); -+ } ++/* ++ * @test ++ * @requires vm.gc.G1 ++ * @requires !vm.flightRecorder ++ * @library /test/lib ++ * @modules java.base/jdk.internal.misc ++ * @run driver/timeout=180 gc.stress.TestStressG1Humongous 32 4 0.6 120 ++ */ + -+ public MIPS64JavaCallWrapper(Address addr) { -+ super(addr); -+ } ++/* ++ * @test ++ * @requires vm.gc.G1 ++ * @requires !vm.flightRecorder ++ * @library /test/lib ++ * @modules java.base/jdk.internal.misc ++ * @run driver/timeout=900 gc.stress.TestStressG1Humongous 1 7 0.6 600 + */ + + import java.util.ArrayList; +@@ -48,17 +75,19 @@ import jdk.test.lib.process.OutputAnalyzer; + public class TestStressG1Humongous{ + + public static void main(String[] args) throws Exception { ++ if (args.length != 4) { ++ throw new IllegalArgumentException("Test expects 4 arguments"); ++ } + -+ public Address getLastJavaFP() { -+ return lastJavaFPField.getValue(addr.addOffsetTo(anchorField.getOffset())); -+ } -+} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/mips64/MIPS64RegisterMap.java jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/mips64/MIPS64RegisterMap.java ---- openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/mips64/MIPS64RegisterMap.java 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/mips64/MIPS64RegisterMap.java 2023-09-12 13:54:26.433575861 +0800 -@@ -0,0 +1,52 @@ + // Limit heap size on 32-bit platforms + int heapSize = Platform.is32bit() ? 512 : 1024; +- // Heap size, region size, threads, humongous size, timeout +- run(heapSize, 4, 3, 1.1, 120); +- run(heapSize, 16, 5, 2.1, 120); +- run(heapSize, 32, 4, 0.6, 120); +- run(heapSize, 1, 7, 0.6, 600); +- } + +- private static void run(int heapSize, int regionSize, int threads, double humongousSize, int timeout) +- throws Exception { ++ // Region size, threads, humongous size, and timeout passed as @run arguments ++ int regionSize = Integer.parseInt(args[0]); ++ int threads = Integer.parseInt(args[1]); ++ double humongousSize = Double.parseDouble(args[2]); ++ int timeout = Integer.parseInt(args[3]); ++ + ArrayList options = new ArrayList<>(); + Collections.addAll(options, Utils.getTestJavaOpts()); + Collections.addAll(options, +diff --git a/test/hotspot/jtreg/runtime/CheckUnhandledOops/TestVerifyOops.java b/test/hotspot/jtreg/runtime/CheckUnhandledOops/TestVerifyOops.java +new file mode 100644 +index 000000000..3326124d4 +--- /dev/null ++++ b/test/hotspot/jtreg/runtime/CheckUnhandledOops/TestVerifyOops.java +@@ -0,0 +1,36 @@ +/* -+ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2018, Loongson Technology. All rights reserved. ++ * Copyright (c) 2019, 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 @@ -118871,118 +200864,199 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.hotspot.agent/shar + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. -+ * + */ + -+package sun.jvm.hotspot.runtime.mips64; -+ -+import sun.jvm.hotspot.debugger.*; -+import sun.jvm.hotspot.runtime.*; -+ -+public class MIPS64RegisterMap extends RegisterMap { -+ -+ /** This is the only public constructor */ -+ public MIPS64RegisterMap(JavaThread thread, boolean updateMap) { -+ super(thread, updateMap); -+ } -+ -+ protected MIPS64RegisterMap(RegisterMap map) { -+ super(map); -+ } ++/* ++ * @test ++ * @bug 8231058 ++ * @requires vm.debug & (os.arch != "sparc") & (os.arch != "sparcv9") ++ * @run main/othervm -XX:+VerifyOops TestVerifyOops ++ */ + -+ public Object clone() { -+ MIPS64RegisterMap retval = new MIPS64RegisterMap(this); -+ return retval; -+ } ++public class TestVerifyOops { + -+ // no PD state to clear or copy: -+ protected void clearPD() {} -+ protected void initializePD() {} -+ protected void initializeFromPD(RegisterMap map) {} -+ protected Address getLocationPD(VMReg reg) { return null; } ++ public static void main(String[] args) { ++ System.out.println("Test passed"); ++ } +} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Threads.java jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Threads.java ---- openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Threads.java 2022-10-12 23:00:03.000000000 +0800 -+++ jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Threads.java 2023-09-12 13:54:26.417575841 +0800 -@@ -22,6 +22,12 @@ - * +diff --git a/test/hotspot/jtreg/runtime/ReservedStack/ReservedStackTest.java b/test/hotspot/jtreg/runtime/ReservedStack/ReservedStackTest.java +index 127bb6abc..c9277604a 100644 +--- a/test/hotspot/jtreg/runtime/ReservedStack/ReservedStackTest.java ++++ b/test/hotspot/jtreg/runtime/ReservedStack/ReservedStackTest.java +@@ -21,6 +21,12 @@ + * questions. */ +/* + * This file has been modified by Loongson Technology in 2021, These -+ * modifications are Copyright (c) 2019, 2021, Loongson Technology, and are made ++ * modifications are Copyright (c) 2021, Loongson Technology, and are made + * available on the same license terms set forth above. + */ + - package sun.jvm.hotspot.runtime; - - import java.util.*; -@@ -39,6 +45,8 @@ - import sun.jvm.hotspot.runtime.linux_amd64.LinuxAMD64JavaThreadPDAccess; - import sun.jvm.hotspot.runtime.linux_aarch64.LinuxAARCH64JavaThreadPDAccess; - import sun.jvm.hotspot.runtime.linux_ppc64.LinuxPPC64JavaThreadPDAccess; -+import sun.jvm.hotspot.runtime.linux_mips64.LinuxMIPS64JavaThreadPDAccess; -+import sun.jvm.hotspot.runtime.linux_loongarch64.LinuxLOONGARCH64JavaThreadPDAccess; - import sun.jvm.hotspot.runtime.linux_sparc.LinuxSPARCJavaThreadPDAccess; - import sun.jvm.hotspot.runtime.bsd_x86.BsdX86JavaThreadPDAccess; - import sun.jvm.hotspot.runtime.bsd_amd64.BsdAMD64JavaThreadPDAccess; -@@ -99,6 +107,10 @@ - access = new LinuxPPC64JavaThreadPDAccess(); - } else if (cpu.equals("aarch64")) { - access = new LinuxAARCH64JavaThreadPDAccess(); -+ } else if (cpu.equals("mips64")) { -+ access = new LinuxMIPS64JavaThreadPDAccess(); -+ } else if (cpu.equals("loongarch64")) { -+ access = new LinuxLOONGARCH64JavaThreadPDAccess(); - } else { - try { - access = (JavaThreadPDAccess) -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/PlatformInfo.java jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/PlatformInfo.java ---- openjdk/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/PlatformInfo.java 2022-10-12 23:00:03.000000000 +0800 -+++ jdk11u-ls/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/PlatformInfo.java 2023-09-12 13:54:26.445575876 +0800 -@@ -22,6 +22,13 @@ + /* + * @test ReservedStackTest * - */ +@@ -239,7 +245,7 @@ public class ReservedStackTest { + return Platform.isAix() || + (Platform.isLinux() && + (Platform.isPPC() || Platform.isS390x() || Platform.isX64() || +- Platform.isX86())) || ++ Platform.isX86() || Platform.isMIPS() || Platform.isLoongArch64())) || + Platform.isOSX() || + Platform.isSolaris(); + } +diff --git a/test/hotspot/jtreg/runtime/logging/ClassLoadUnloadTest.java b/test/hotspot/jtreg/runtime/logging/ClassLoadUnloadTest.java +index 783dedaef..f7cd01f87 100644 +--- a/test/hotspot/jtreg/runtime/logging/ClassLoadUnloadTest.java ++++ b/test/hotspot/jtreg/runtime/logging/ClassLoadUnloadTest.java +@@ -42,8 +42,6 @@ import java.util.Collections; + import java.util.List; -+/* -+ * This file has been modified by Loongson Technology in 2021. These -+ * modifications are Copyright (c) 2018, 2021, Loongson Technology, and are made -+ * available on the same license terms set forth above. -+ * -+ */ -+ - package sun.jvm.hotspot.utilities; + public class ClassLoadUnloadTest { +- private static OutputAnalyzer out; +- private static ProcessBuilder pb; + private static class ClassUnloadTestMain { + public static void main(String... args) throws Exception { + String className = "test.Empty"; +@@ -54,79 +52,78 @@ public class ClassLoadUnloadTest { + } + } - /** Provides canonicalized OS and CPU information for the rest of the -@@ -54,7 +61,7 @@ +- static void checkFor(String... outputStrings) throws Exception { +- out = new OutputAnalyzer(pb.start()); ++ static void checkFor(OutputAnalyzer output, String... outputStrings) throws Exception { + for (String s: outputStrings) { +- out.shouldContain(s); ++ output.shouldContain(s); + } +- out.shouldHaveExitValue(0); + } - public static boolean knownCPU(String cpu) { - final String[] KNOWN = -- new String[] {"i386", "x86", "x86_64", "amd64", "sparc", "sparcv9", "ppc64", "ppc64le", "aarch64"}; -+ new String[] {"i386", "x86", "x86_64", "amd64", "sparc", "sparcv9", "ppc64", "ppc64le", "aarch64", "mips64", "mips64el", "loongarch64"}; +- static void checkAbsent(String... outputStrings) throws Exception { +- out = new OutputAnalyzer(pb.start()); ++ static void checkAbsent(OutputAnalyzer output, String... outputStrings) throws Exception { + for (String s: outputStrings) { +- out.shouldNotContain(s); ++ output.shouldNotContain(s); + } +- out.shouldHaveExitValue(0); + } - for(String s : KNOWN) { - if(s.equals(cpu)) -@@ -101,6 +108,12 @@ - if (cpu.equals("ppc64le")) - return "ppc64"; + // Use the same command-line heap size setting as ../ClassUnload/UnloadTest.java +- static ProcessBuilder exec(String... args) throws Exception { ++ static OutputAnalyzer exec(String... args) throws Exception { + List argsList = new ArrayList<>(); + Collections.addAll(argsList, args); +- Collections.addAll(argsList, "-Xmn8m"); +- Collections.addAll(argsList, "-Dtest.class.path=" + System.getProperty("test.class.path", ".")); +- Collections.addAll(argsList, "-XX:+ClassUnloading"); +- Collections.addAll(argsList, ClassUnloadTestMain.class.getName()); +- return ProcessTools.createJavaProcessBuilder(argsList); ++ Collections.addAll(argsList, "-Xmn8m", "-Dtest.class.path=" + System.getProperty("test.class.path", "."), ++ "-XX:+ClassUnloading", ClassUnloadTestMain.class.getName()); ++ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(argsList); ++ OutputAnalyzer output = new OutputAnalyzer(pb.start()); ++ output.shouldHaveExitValue(0); ++ return output; + } -+ if (cpu.equals("mips64el")) -+ return "mips64"; -+ -+ if (cpu.equals("loongarch64")) -+ return "loongarch64"; + public static void main(String... args) throws Exception { + ++ OutputAnalyzer output; + - return cpu; + // -Xlog:class+unload=info +- pb = exec("-Xlog:class+unload=info"); +- checkFor("[class,unload]", "unloading class"); ++ output = exec("-Xlog:class+unload=info"); ++ checkFor(output, "[class,unload]", "unloading class"); - } -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot.loongarch64/src/jdk/vm/ci/hotspot/loongarch64/LoongArch64HotSpotJVMCIBackendFactory.java jdk11u-ls/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot.loongarch64/src/jdk/vm/ci/hotspot/loongarch64/LoongArch64HotSpotJVMCIBackendFactory.java ---- openjdk/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot.loongarch64/src/jdk/vm/ci/hotspot/loongarch64/LoongArch64HotSpotJVMCIBackendFactory.java 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot.loongarch64/src/jdk/vm/ci/hotspot/loongarch64/LoongArch64HotSpotJVMCIBackendFactory.java 2023-09-12 13:54:26.497575942 +0800 -@@ -0,0 +1,220 @@ + // -Xlog:class+unload=off +- pb = exec("-Xlog:class+unload=off"); +- checkAbsent("[class,unload]"); ++ output = exec("-Xlog:class+unload=off"); ++ checkAbsent(output,"[class,unload]"); + + // -XX:+TraceClassUnloading +- pb = exec("-XX:+TraceClassUnloading"); +- checkFor("[class,unload]", "unloading class"); ++ output = exec("-XX:+TraceClassUnloading"); ++ checkFor(output, "[class,unload]", "unloading class"); + + // -XX:-TraceClassUnloading +- pb = exec("-XX:-TraceClassUnloading"); +- checkAbsent("[class,unload]"); ++ output = exec("-XX:-TraceClassUnloading"); ++ checkAbsent(output, "[class,unload]"); + + // -Xlog:class+load=info +- pb = exec("-Xlog:class+load=info"); +- checkFor("[class,load]", "java.lang.Object", "source:"); ++ output = exec("-Xlog:class+load=info"); ++ checkFor(output,"[class,load]", "java.lang.Object", "source:"); + + // -Xlog:class+load=debug +- pb = exec("-Xlog:class+load=debug"); +- checkFor("[class,load]", "java.lang.Object", "source:", "klass:", "super:", "loader:", "bytes:"); ++ output = exec("-Xlog:class+load=debug"); ++ checkFor(output,"[class,load]", "java.lang.Object", "source:", "klass:", "super:", "loader:", "bytes:"); + + // -Xlog:class+load=off +- pb = exec("-Xlog:class+load=off"); +- checkAbsent("[class,load]"); ++ output = exec("-Xlog:class+load=off"); ++ checkAbsent(output,"[class,load]"); + + // -XX:+TraceClassLoading +- pb = exec("-XX:+TraceClassLoading"); +- checkFor("[class,load]", "java.lang.Object", "source:"); ++ output = exec("-XX:+TraceClassLoading"); ++ checkFor(output, "[class,load]", "java.lang.Object", "source:"); + + // -XX:-TraceClassLoading +- pb = exec("-XX:-TraceClassLoading"); +- checkAbsent("[class,load]"); ++ output = exec("-XX:-TraceClassLoading"); ++ checkAbsent(output, "[class,load]"); + + // -verbose:class +- pb = exec("-verbose:class"); +- checkFor("[class,load]", "java.lang.Object", "source:"); +- checkFor("[class,unload]", "unloading class"); ++ output = exec("-verbose:class"); ++ checkFor(output,"[class,load]", "java.lang.Object", "source:"); ++ checkFor(output,"[class,unload]", "unloading class"); + + // -Xlog:class+loader+data=trace +- pb = exec("-Xlog:class+loader+data=trace"); +- checkFor("[class,loader,data]", "create loader data"); ++ output = exec("-Xlog:class+loader+data=trace"); ++ checkFor(output, "[class,loader,data]", "create loader data"); + + } + } +diff --git a/test/hotspot/jtreg/runtime/modules/AccessCheck/MethodAccessReadTwice.java b/test/hotspot/jtreg/runtime/modules/AccessCheck/MethodAccessReadTwice.java +index 29bbe7f39..d6b85ced2 100644 +--- a/test/hotspot/jtreg/runtime/modules/AccessCheck/MethodAccessReadTwice.java ++++ b/test/hotspot/jtreg/runtime/modules/AccessCheck/MethodAccessReadTwice.java +@@ -29,8 +29,8 @@ + * after the module read edge is added. + * @compile ModuleLibrary.java + * p2/c2.java +- * p5/c5.java +- * p7/c7.java ++ * p5/c5.jasm ++ * p7/c7.jasm + * @run main/othervm MethodAccessReadTwice + */ + +diff --git a/test/hotspot/jtreg/runtime/modules/AccessCheck/p5/c5.jasm b/test/hotspot/jtreg/runtime/modules/AccessCheck/p5/c5.jasm +new file mode 100644 +index 000000000..69a8143de +--- /dev/null ++++ b/test/hotspot/jtreg/runtime/modules/AccessCheck/p5/c5.jasm +@@ -0,0 +1,76 @@ +/* -+ * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2022, Loongson Technology. All rights reserved. ++ * Copyright (c) 2021, Google LLC. 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 @@ -119003,210 +201077,327 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.internal.vm.ci/sha + * or visit www.oracle.com if you need additional information or have any + * questions. + */ -+package jdk.vm.ci.hotspot.loongarch64; -+ -+import static java.util.Collections.emptyMap; -+import static jdk.vm.ci.common.InitTimer.timer; -+ -+import java.util.EnumSet; -+import java.util.Map; -+ -+import jdk.vm.ci.loongarch64.LoongArch64; -+import jdk.vm.ci.loongarch64.LoongArch64.CPUFeature; -+import jdk.vm.ci.code.Architecture; -+import jdk.vm.ci.code.RegisterConfig; -+import jdk.vm.ci.code.TargetDescription; -+import jdk.vm.ci.code.stack.StackIntrospection; -+import jdk.vm.ci.common.InitTimer; -+import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider; -+import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider; -+import jdk.vm.ci.hotspot.HotSpotJVMCIBackendFactory; -+import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; -+import jdk.vm.ci.hotspot.HotSpotMetaAccessProvider; -+import jdk.vm.ci.hotspot.HotSpotStackIntrospection; -+import jdk.vm.ci.meta.ConstantReflectionProvider; -+import jdk.vm.ci.runtime.JVMCIBackend; -+ -+public class LoongArch64HotSpotJVMCIBackendFactory implements HotSpotJVMCIBackendFactory { -+ -+ protected EnumSet computeFeatures(@SuppressWarnings("unused") LoongArch64HotSpotVMConfig config) { -+ // Configure the feature set using the HotSpot flag settings. -+ EnumSet features = EnumSet.noneOf(LoongArch64.CPUFeature.class); -+ -+ if ((config.vmVersionFeatures & config.loongarch64LA32) != 0) { -+ features.add(LoongArch64.CPUFeature.LA32); -+ } -+ -+ if ((config.vmVersionFeatures & config.loongarch64LA64) != 0) { -+ features.add(LoongArch64.CPUFeature.LA64); -+ } -+ -+ if ((config.vmVersionFeatures & config.loongarch64LLEXC) != 0) { -+ features.add(LoongArch64.CPUFeature.LLEXC); -+ } -+ -+ if ((config.vmVersionFeatures & config.loongarch64SCDLY) != 0) { -+ features.add(LoongArch64.CPUFeature.SCDLY); -+ } -+ -+ if ((config.vmVersionFeatures & config.loongarch64LLDBAR) != 0) { -+ features.add(LoongArch64.CPUFeature.LLDBAR); -+ } -+ -+ if ((config.vmVersionFeatures & config.loongarch64LBT_X86) != 0) { -+ features.add(LoongArch64.CPUFeature.LBT_X86); -+ } -+ -+ if ((config.vmVersionFeatures & config.loongarch64LBT_ARM) != 0) { -+ features.add(LoongArch64.CPUFeature.LBT_ARM); -+ } -+ -+ if ((config.vmVersionFeatures & config.loongarch64LBT_MIPS) != 0) { -+ features.add(LoongArch64.CPUFeature.LBT_MIPS); -+ } -+ -+ if ((config.vmVersionFeatures & config.loongarch64CCDMA) != 0) { -+ features.add(LoongArch64.CPUFeature.CCDMA); -+ } -+ -+ if ((config.vmVersionFeatures & config.loongarch64COMPLEX) != 0) { -+ features.add(LoongArch64.CPUFeature.COMPLEX); -+ } -+ -+ if ((config.vmVersionFeatures & config.loongarch64FP) != 0) { -+ features.add(LoongArch64.CPUFeature.FP); -+ } -+ -+ if ((config.vmVersionFeatures & config.loongarch64CRYPTO) != 0) { -+ features.add(LoongArch64.CPUFeature.CRYPTO); -+ } -+ -+ if ((config.vmVersionFeatures & config.loongarch64LSX) != 0) { -+ features.add(LoongArch64.CPUFeature.LSX); -+ } -+ -+ if ((config.vmVersionFeatures & config.loongarch64LASX) != 0) { -+ features.add(LoongArch64.CPUFeature.LASX); -+ } -+ -+ if ((config.vmVersionFeatures & config.loongarch64LAM) != 0) { -+ features.add(LoongArch64.CPUFeature.LAM); -+ } -+ -+ if ((config.vmVersionFeatures & config.loongarch64LLSYNC) != 0) { -+ features.add(LoongArch64.CPUFeature.LLSYNC); -+ } -+ -+ if ((config.vmVersionFeatures & config.loongarch64TGTSYNC) != 0) { -+ features.add(LoongArch64.CPUFeature.TGTSYNC); -+ } -+ -+ if ((config.vmVersionFeatures & config.loongarch64ULSYNC) != 0) { -+ features.add(LoongArch64.CPUFeature.ULSYNC); -+ } -+ -+ if ((config.vmVersionFeatures & config.loongarch64UAL) != 0) { -+ features.add(LoongArch64.CPUFeature.UAL); -+ } -+ -+ return features; -+ } + -+ protected EnumSet computeFlags(@SuppressWarnings("unused") LoongArch64HotSpotVMConfig config) { -+ EnumSet flags = EnumSet.noneOf(LoongArch64.Flag.class); -+ -+ if (config.useLSX) { -+ flags.add(LoongArch64.Flag.useLSX); -+ } -+ -+ if (config.useLASX) { -+ flags.add(LoongArch64.Flag.useLASX); -+ } -+ -+ return flags; -+ } ++/* ++ * Test input for the fix for JDK-8174954, which checks for an expected ++ * IllegalAccessError when the parameter type of an invokedynamic is ++ * inaccessible. ++ * ++ * The test assumes that given the string concatenation expression "" + param, ++ * javac generates an invokedynamic that uses the specific type of param. The ++ * fix for JDK-8273914 make javac eagerly convert param to a String before ++ * passing it to the invokedynamic call, which avoids the accessibility issue ++ * the test is trying to exercise. ++ * ++ * This jasm file contains the bytecode javac generated before the fix for ++ * JDK-8273914, to continue to exercise the invokedynamic behaviour that ++ * JDK-8174954 is testing. ++ */ + -+ protected TargetDescription createTarget(LoongArch64HotSpotVMConfig config) { -+ final int stackFrameAlignment = 16; -+ final int implicitNullCheckLimit = 4096; -+ final boolean inlineObjects = true; -+ Architecture arch = new LoongArch64(computeFeatures(config), computeFlags(config)); -+ return new TargetDescription(arch, true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects); -+ } ++package p5; + -+ protected HotSpotConstantReflectionProvider createConstantReflection(HotSpotJVMCIRuntime runtime) { -+ return new HotSpotConstantReflectionProvider(runtime); -+ } ++super public class c5 ++ version 55:0 ++{ ++ public Method "":"()V" ++ stack 1 locals 1 ++ { ++ aload_0; ++ invokespecial Method java/lang/Object."":"()V"; ++ return; ++ } ++ public Method method5:"(Lp2/c2;)V" ++ stack 2 locals 2 ++ { ++ getstatic Field java/lang/System.out:"Ljava/io/PrintStream;"; ++ aload_1; ++ invokedynamic InvokeDynamic REF_invokeStatic:Method java/lang/invoke/StringConcatFactory.makeConcatWithConstants:"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;":makeConcatWithConstants:"(Lp2/c2;)Ljava/lang/String;" { ++ String "In c5\'s method5 with param = " ++ }; ++ invokevirtual Method java/io/PrintStream.println:"(Ljava/lang/String;)V"; ++ return; ++ } ++ public Method methodAddReadEdge:"(Ljava/lang/Module;)V" ++ stack 2 locals 2 ++ { ++ ldc class c5; ++ invokevirtual Method java/lang/Class.getModule:"()Ljava/lang/Module;"; ++ aload_1; ++ invokevirtual Method java/lang/Module.addReads:"(Ljava/lang/Module;)Ljava/lang/Module;"; ++ pop; ++ return; ++ } ++ ++ public static final InnerClass Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles; ++ ++} // end Class c5 +diff --git a/test/hotspot/jtreg/runtime/modules/AccessCheck/p7/c7.jasm b/test/hotspot/jtreg/runtime/modules/AccessCheck/p7/c7.jasm +new file mode 100644 +index 000000000..fd8783f4c +--- /dev/null ++++ b/test/hotspot/jtreg/runtime/modules/AccessCheck/p7/c7.jasm +@@ -0,0 +1,113 @@ ++/* ++ * Copyright (c) 2021, Google LLC. 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. ++ */ + -+ protected RegisterConfig createRegisterConfig(LoongArch64HotSpotVMConfig config, TargetDescription target) { -+ return new LoongArch64HotSpotRegisterConfig(target, config.useCompressedOops); -+ } ++/* ++ * Test input for the fix for JDK-8174954, which checks for an expected ++ * IllegalAccessError when the parameter type of an invokedynamic is ++ * inaccessible. ++ * ++ * The test assumes that given the string concatenation expression "" + param, ++ * javac generates an invokedynamic that uses the specific type of param. The ++ * fix for JDK-8273914 make javac eagerly convert param to a String before ++ * passing it to the invokedynamic call, which avoids the accessibility issue ++ * the test is trying to exercise. ++ * ++ * This jasm file contains the bytecode javac generated before the fix for ++ * JDK-8273914, to continue to exercise the invokedynamic behaviour that ++ * JDK-8174954 is testing. ++ */ + -+ protected HotSpotCodeCacheProvider createCodeCache(HotSpotJVMCIRuntime runtime, TargetDescription target, RegisterConfig regConfig) { -+ return new HotSpotCodeCacheProvider(runtime, runtime.getConfig(), target, regConfig); -+ } ++package p7; + -+ protected HotSpotMetaAccessProvider createMetaAccess(HotSpotJVMCIRuntime runtime) { -+ return new HotSpotMetaAccessProvider(runtime); -+ } ++super public class c7 ++ version 55:0 ++{ ++ public Method "":"()V" ++ stack 1 locals 1 ++ { ++ aload_0; ++ invokespecial Method java/lang/Object."":"()V"; ++ return; ++ } ++ public Method method7:"(Lp2/c2;Ljava/lang/Module;)V" ++ stack 3 locals 4 ++ { ++ try t0; ++ getstatic Field java/lang/System.out:"Ljava/io/PrintStream;"; ++ aload_1; ++ invokedynamic InvokeDynamic REF_invokeStatic:Method java/lang/invoke/StringConcatFactory.makeConcatWithConstants:"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;":makeConcatWithConstants:"(Lp2/c2;)Ljava/lang/String;" { ++ String "In c7\'s method7 with param = " ++ }; ++ invokevirtual Method java/io/PrintStream.println:"(Ljava/lang/String;)V"; ++ new class java/lang/RuntimeException; ++ dup; ++ ldc String "c7 failed to throw expected IllegalAccessError"; ++ invokespecial Method java/lang/RuntimeException."":"(Ljava/lang/String;)V"; ++ athrow; ++ endtry t0; ++ catch t0 java/lang/IllegalAccessError; ++ stack_frame_type stack1; ++ stack_map class java/lang/IllegalAccessError; ++ astore_3; ++ aload_0; ++ aload_2; ++ invokevirtual Method methodAddReadEdge:"(Ljava/lang/Module;)V"; ++ try t1; ++ getstatic Field java/lang/System.out:"Ljava/io/PrintStream;"; ++ aload_1; ++ invokedynamic InvokeDynamic REF_invokeStatic:Method java/lang/invoke/StringConcatFactory.makeConcatWithConstants:"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;":makeConcatWithConstants:"(Lp2/c2;)Ljava/lang/String;" { ++ String "In c7\'s method7 with param = " ++ }; ++ invokevirtual Method java/io/PrintStream.println:"(Ljava/lang/String;)V"; ++ endtry t1; ++ goto L61; ++ catch t1 java/lang/IllegalAccessError; ++ stack_frame_type stack1; ++ stack_map class java/lang/IllegalAccessError; ++ astore_3; ++ new class java/lang/RuntimeException; ++ dup; ++ aload_3; ++ invokevirtual Method java/lang/IllegalAccessError.getMessage:"()Ljava/lang/String;"; ++ invokedynamic InvokeDynamic REF_invokeStatic:Method java/lang/invoke/StringConcatFactory.makeConcatWithConstants:"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;":makeConcatWithConstants:"(Ljava/lang/String;)Ljava/lang/String;" { ++ String "Unexpected IllegalAccessError: " ++ }; ++ invokespecial Method java/lang/RuntimeException."":"(Ljava/lang/String;)V"; ++ athrow; ++ L61: stack_frame_type same; ++ return; ++ } ++ public Method methodAddReadEdge:"(Ljava/lang/Module;)V" ++ stack 2 locals 2 ++ { ++ ldc class c7; ++ invokevirtual Method java/lang/Class.getModule:"()Ljava/lang/Module;"; ++ aload_1; ++ invokevirtual Method java/lang/Module.addReads:"(Ljava/lang/Module;)Ljava/lang/Module;"; ++ pop; ++ return; ++ } ++ ++ public static final InnerClass Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles; ++ ++} // end Class c7 +diff --git a/test/hotspot/jtreg/serviceability/dcmd/gc/HeapDumpCompressedTest.java b/test/hotspot/jtreg/serviceability/dcmd/gc/HeapDumpCompressedTest.java +index bfcd5bf35..9032d610c 100644 +--- a/test/hotspot/jtreg/serviceability/dcmd/gc/HeapDumpCompressedTest.java ++++ b/test/hotspot/jtreg/serviceability/dcmd/gc/HeapDumpCompressedTest.java +@@ -36,14 +36,37 @@ import jdk.test.lib.process.OutputAnalyzer; + + /* + * @test +- * @summary Test of diagnostic command GC.heap_dump with gzipped output (Serial, Parallel and G1) ++ * @requires vm.gc.Serial ++ * @summary Test of diagnostic command GC.heap_dump with gzipped output (Serial GC) + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.compiler + * java.management + * jdk.internal.jvmstat/sun.jvmstat.monitor + * @run main/othervm -XX:+UseSerialGC HeapDumpCompressedTest ++ */ + -+ @Override -+ public String getArchitecture() { -+ return "loongarch64"; -+ } ++/* ++ * @test ++ * @requires vm.gc.Parallel ++ * @summary Test of diagnostic command GC.heap_dump with gzipped output (Parallel GC) ++ * @library /test/lib ++ * @modules java.base/jdk.internal.misc ++ * java.compiler ++ * java.management ++ * jdk.internal.jvmstat/sun.jvmstat.monitor + * @run main/othervm -XX:+UseParallelGC HeapDumpCompressedTest ++ */ + -+ @Override -+ public String toString() { -+ return "JVMCIBackend:" + getArchitecture(); -+ } ++/* ++ * @test ++ * @requires vm.gc.G1 ++ * @summary Test of diagnostic command GC.heap_dump with gzipped output (G1 GC) ++ * @library /test/lib ++ * @modules java.base/jdk.internal.misc ++ * java.compiler ++ * java.management ++ * jdk.internal.jvmstat/sun.jvmstat.monitor + * @run main/othervm -XX:+UseG1GC HeapDumpCompressedTest + */ + +diff --git a/test/hotspot/jtreg/serviceability/dcmd/gc/RunGCTest.java b/test/hotspot/jtreg/serviceability/dcmd/gc/RunGCTest.java +index 6156f4690..33182fc78 100644 +--- a/test/hotspot/jtreg/serviceability/dcmd/gc/RunGCTest.java ++++ b/test/hotspot/jtreg/serviceability/dcmd/gc/RunGCTest.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -36,13 +36,12 @@ import jdk.test.lib.dcmd.JMXExecutor; + /* + * @test + * @summary Test of diagnostic command GC.run +- * @requires vm.gc != "Z" + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.compiler + * java.management + * jdk.internal.jvmstat/sun.jvmstat.monitor +- * @run testng/othervm -Xlog:gc=debug:RunGC.gclog -XX:-ExplicitGCInvokesConcurrent RunGCTest ++ * @run testng/othervm -Xlog:gc:RunGC.gclog -XX:-ExplicitGCInvokesConcurrent RunGCTest + */ + public class RunGCTest { + public void run(CommandExecutor executor) { +@@ -58,7 +57,7 @@ public class RunGCTest { + } + + OutputAnalyzer output = new OutputAnalyzer(gcLog, ""); +- output.shouldContain("Pause Full (Diagnostic Command)"); ++ output.shouldContain("(Diagnostic Command)"); + } + + @Test +diff --git a/test/hotspot/jtreg/serviceability/jvmti/DynamicCodeGenerated/DynamicCodeGeneratedTest.java b/test/hotspot/jtreg/serviceability/jvmti/DynamicCodeGenerated/DynamicCodeGeneratedTest.java +new file mode 100644 +index 000000000..76d89df40 +--- /dev/null ++++ b/test/hotspot/jtreg/serviceability/jvmti/DynamicCodeGenerated/DynamicCodeGeneratedTest.java +@@ -0,0 +1,56 @@ ++/* ++ * 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. ++ */ + -+ @Override -+ @SuppressWarnings("try") -+ public JVMCIBackend createJVMCIBackend(HotSpotJVMCIRuntime runtime, JVMCIBackend host) { ++/* ++ * @test ++ * @bug 8212155 ++ * @summary Test concurrent enabling and posting of DynamicCodeGenerated events. ++ * @library /test/lib ++ * @run main/othervm/native -agentlib:DynamicCodeGenerated DynamicCodeGeneratedTest ++ */ + -+ assert host == null; -+ LoongArch64HotSpotVMConfig config = new LoongArch64HotSpotVMConfig(runtime.getConfigStore()); -+ TargetDescription target = createTarget(config); ++import java.lang.ref.Reference; + -+ RegisterConfig regConfig; -+ HotSpotCodeCacheProvider codeCache; -+ ConstantReflectionProvider constantReflection; -+ HotSpotMetaAccessProvider metaAccess; -+ StackIntrospection stackIntrospection; -+ try (InitTimer t = timer("create providers")) { -+ try (InitTimer rt = timer("create MetaAccess provider")) { -+ metaAccess = createMetaAccess(runtime); -+ } -+ try (InitTimer rt = timer("create RegisterConfig")) { -+ regConfig = createRegisterConfig(config, target); -+ } -+ try (InitTimer rt = timer("create CodeCache provider")) { -+ codeCache = createCodeCache(runtime, target, regConfig); -+ } -+ try (InitTimer rt = timer("create ConstantReflection provider")) { -+ constantReflection = createConstantReflection(runtime); -+ } -+ try (InitTimer rt = timer("create StackIntrospection provider")) { -+ stackIntrospection = new HotSpotStackIntrospection(runtime); -+ } -+ } -+ try (InitTimer rt = timer("instantiate backend")) { -+ return createBackend(metaAccess, codeCache, constantReflection, stackIntrospection); -+ } ++public class DynamicCodeGeneratedTest { ++ static { ++ System.loadLibrary("DynamicCodeGenerated"); + } ++ public static native void changeEventNotificationMode(); + -+ protected JVMCIBackend createBackend(HotSpotMetaAccessProvider metaAccess, HotSpotCodeCacheProvider codeCache, ConstantReflectionProvider constantReflection, -+ StackIntrospection stackIntrospection) { -+ return new JVMCIBackend(metaAccess, codeCache, constantReflection, stackIntrospection); ++ public static void main(String[] args) { ++ // Try to enable DynamicCodeGenerated event while it is posted ++ // using JvmtiDynamicCodeEventCollector from VtableStubs::find_stub ++ Thread t = new Thread(() -> { ++ changeEventNotificationMode(); ++ }); ++ t.setDaemon(true); ++ t.start(); ++ ++ for (int i = 0; i < 2000; i++) { ++ new Thread(() -> { ++ String result = "string" + System.currentTimeMillis(); ++ Reference.reachabilityFence(result); ++ }).start(); ++ } + } +} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot.loongarch64/src/jdk/vm/ci/hotspot/loongarch64/LoongArch64HotSpotRegisterConfig.java jdk11u-ls/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot.loongarch64/src/jdk/vm/ci/hotspot/loongarch64/LoongArch64HotSpotRegisterConfig.java ---- openjdk/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot.loongarch64/src/jdk/vm/ci/hotspot/loongarch64/LoongArch64HotSpotRegisterConfig.java 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot.loongarch64/src/jdk/vm/ci/hotspot/loongarch64/LoongArch64HotSpotRegisterConfig.java 2023-09-12 13:54:26.497575942 +0800 -@@ -0,0 +1,297 @@ +diff --git a/test/hotspot/jtreg/serviceability/jvmti/DynamicCodeGenerated/libDynamicCodeGenerated.cpp b/test/hotspot/jtreg/serviceability/jvmti/DynamicCodeGenerated/libDynamicCodeGenerated.cpp +new file mode 100644 +index 000000000..5e809cbf9 +--- /dev/null ++++ b/test/hotspot/jtreg/serviceability/jvmti/DynamicCodeGenerated/libDynamicCodeGenerated.cpp +@@ -0,0 +1,58 @@ +/* -+ * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2022, Loongson Technology. 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 @@ -119227,287 +201418,4075 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.internal.vm.ci/sha + * or visit www.oracle.com if you need additional information or have any + * questions. + */ -+package jdk.vm.ci.hotspot.loongarch64; -+ -+import static jdk.vm.ci.loongarch64.LoongArch64.ra; -+import static jdk.vm.ci.loongarch64.LoongArch64.a0; -+import static jdk.vm.ci.loongarch64.LoongArch64.a1; -+import static jdk.vm.ci.loongarch64.LoongArch64.a2; -+import static jdk.vm.ci.loongarch64.LoongArch64.a3; -+import static jdk.vm.ci.loongarch64.LoongArch64.a4; -+import static jdk.vm.ci.loongarch64.LoongArch64.a5; -+import static jdk.vm.ci.loongarch64.LoongArch64.a6; -+import static jdk.vm.ci.loongarch64.LoongArch64.a7; -+import static jdk.vm.ci.loongarch64.LoongArch64.SCR1; -+import static jdk.vm.ci.loongarch64.LoongArch64.SCR2; -+import static jdk.vm.ci.loongarch64.LoongArch64.t0; -+import static jdk.vm.ci.loongarch64.LoongArch64.v0; -+import static jdk.vm.ci.loongarch64.LoongArch64.s5; -+import static jdk.vm.ci.loongarch64.LoongArch64.s6; -+import static jdk.vm.ci.loongarch64.LoongArch64.sp; -+import static jdk.vm.ci.loongarch64.LoongArch64.fp; -+import static jdk.vm.ci.loongarch64.LoongArch64.tp; -+import static jdk.vm.ci.loongarch64.LoongArch64.rx; -+import static jdk.vm.ci.loongarch64.LoongArch64.f0; -+import static jdk.vm.ci.loongarch64.LoongArch64.f1; -+import static jdk.vm.ci.loongarch64.LoongArch64.f2; -+import static jdk.vm.ci.loongarch64.LoongArch64.f3; -+import static jdk.vm.ci.loongarch64.LoongArch64.f4; -+import static jdk.vm.ci.loongarch64.LoongArch64.f5; -+import static jdk.vm.ci.loongarch64.LoongArch64.f6; -+import static jdk.vm.ci.loongarch64.LoongArch64.f7; -+import static jdk.vm.ci.loongarch64.LoongArch64.fv0; -+import static jdk.vm.ci.loongarch64.LoongArch64.zero; -+ -+import java.util.ArrayList; -+import java.util.HashSet; -+import java.util.List; -+import java.util.Set; -+ -+import jdk.vm.ci.loongarch64.LoongArch64; -+import jdk.vm.ci.code.Architecture; -+import jdk.vm.ci.code.CallingConvention; -+import jdk.vm.ci.code.CallingConvention.Type; -+import jdk.vm.ci.code.Register; -+import jdk.vm.ci.code.RegisterArray; -+import jdk.vm.ci.code.RegisterAttributes; -+import jdk.vm.ci.code.RegisterConfig; -+import jdk.vm.ci.code.StackSlot; -+import jdk.vm.ci.code.TargetDescription; -+import jdk.vm.ci.code.ValueKindFactory; -+import jdk.vm.ci.common.JVMCIError; -+import jdk.vm.ci.hotspot.HotSpotCallingConventionType; -+import jdk.vm.ci.meta.AllocatableValue; -+import jdk.vm.ci.meta.JavaKind; -+import jdk.vm.ci.meta.JavaType; -+import jdk.vm.ci.meta.PlatformKind; -+import jdk.vm.ci.meta.Value; -+import jdk.vm.ci.meta.ValueKind; -+ -+public class LoongArch64HotSpotRegisterConfig implements RegisterConfig { + -+ private final TargetDescription target; ++#include ++#include + -+ private final RegisterArray allocatable; ++static jvmtiEnv* jvmti = NULL; + -+ /** -+ * The caller saved registers always include all parameter registers. -+ */ -+ private final RegisterArray callerSaved; ++#ifdef __cplusplus ++extern "C" { ++#endif + -+ private final boolean allAllocatableAreCallerSaved; ++JNIEXPORT ++void JNICALL Java_DynamicCodeGeneratedTest_changeEventNotificationMode(JNIEnv* jni, jclass cls) { ++ while (true) { ++ jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_DYNAMIC_CODE_GENERATED, NULL); ++ jvmti->SetEventNotificationMode(JVMTI_DISABLE, JVMTI_EVENT_DYNAMIC_CODE_GENERATED, NULL); ++ } ++} + -+ private final RegisterAttributes[] attributesMap; ++#ifdef __cplusplus ++} ++#endif + -+ @Override -+ public RegisterArray getAllocatableRegisters() { -+ return allocatable; -+ } ++void JNICALL DynamicCodeGenerated(jvmtiEnv* jvmti, const char* name, const void* address, jint length) { + -+ @Override -+ public RegisterArray filterAllocatableRegisters(PlatformKind kind, RegisterArray registers) { -+ ArrayList list = new ArrayList<>(); -+ for (Register reg : registers) { -+ if (target.arch.canStoreValue(reg.getRegisterCategory(), kind)) { -+ list.add(reg); -+ } -+ } ++} + -+ return new RegisterArray(list); -+ } ++JNIEXPORT jint JNICALL ++Agent_OnLoad(JavaVM* vm, char* options, void* reserved) { ++ vm->GetEnv((void**)&jvmti, JVMTI_VERSION_1_0); ++ jvmtiEventCallbacks callbacks; ++ memset(&callbacks, 0, sizeof(callbacks)); ++ callbacks.DynamicCodeGenerated = DynamicCodeGenerated; ++ jvmti->SetEventCallbacks(&callbacks, sizeof(callbacks)); + -+ @Override -+ public RegisterAttributes[] getAttributesMap() { -+ return attributesMap.clone(); -+ } ++ return 0; ++} +diff --git a/test/hotspot/jtreg/testlibrary_tests/TestMutuallyExclusivePlatformPredicates.java b/test/hotspot/jtreg/testlibrary_tests/TestMutuallyExclusivePlatformPredicates.java +index 126a43a90..55bd135f6 100644 +--- a/test/hotspot/jtreg/testlibrary_tests/TestMutuallyExclusivePlatformPredicates.java ++++ b/test/hotspot/jtreg/testlibrary_tests/TestMutuallyExclusivePlatformPredicates.java +@@ -45,7 +45,7 @@ import java.util.Set; + */ + public class TestMutuallyExclusivePlatformPredicates { + private static enum MethodGroup { +- ARCH("isAArch64", "isARM", "isPPC", "isS390x", "isSparc", "isX64", "isX86"), ++ ARCH("isAArch64", "isARM", "isPPC", "isS390x", "isSparc", "isX64", "isX86", "isMIPS", "isLoongArch64"), + BITNESS("is32bit", "is64bit"), + OS("isAix", "isLinux", "isOSX", "isSolaris", "isWindows"), + VM_TYPE("isClient", "isServer", "isGraal", "isMinimal", "isZero", "isEmbedded"), +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_anonclassloader_keep_class/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_anonclassloader_keep_class/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_anonclassloader_keep_class/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_anonclassloader_keep_obj/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_anonclassloader_keep_obj/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_anonclassloader_keep_obj/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level1_inMemoryCompilation_keep_cl/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level1_inMemoryCompilation_keep_cl/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level1_inMemoryCompilation_keep_cl/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level1_inMemoryCompilation_keep_class/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level1_inMemoryCompilation_keep_class/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level1_inMemoryCompilation_keep_class/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level1_inMemoryCompilation_keep_obj/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level1_inMemoryCompilation_keep_obj/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level1_inMemoryCompilation_keep_obj/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level1_keep_cl/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level1_keep_cl/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level1_keep_cl/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level1_keep_class/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level1_keep_class/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level1_keep_class/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level1_keep_obj/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level1_keep_obj/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level1_keep_obj/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level2_inMemoryCompilation_keep_cl/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level2_inMemoryCompilation_keep_cl/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level2_inMemoryCompilation_keep_cl/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level2_inMemoryCompilation_keep_class/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level2_inMemoryCompilation_keep_class/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level2_inMemoryCompilation_keep_class/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level2_inMemoryCompilation_keep_obj/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level2_inMemoryCompilation_keep_obj/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level2_inMemoryCompilation_keep_obj/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level2_keep_cl/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level2_keep_cl/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level2_keep_cl/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level2_keep_class/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level2_keep_class/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level2_keep_class/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level2_keep_obj/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level2_keep_obj/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level2_keep_obj/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level3_inMemoryCompilation_keep_cl/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level3_inMemoryCompilation_keep_cl/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level3_inMemoryCompilation_keep_cl/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level3_inMemoryCompilation_keep_class/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level3_inMemoryCompilation_keep_class/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level3_inMemoryCompilation_keep_class/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level3_inMemoryCompilation_keep_obj/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level3_inMemoryCompilation_keep_obj/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level3_inMemoryCompilation_keep_obj/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level3_keep_cl/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level3_keep_cl/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level3_keep_cl/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level3_keep_class/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level3_keep_class/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level3_keep_class/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level3_keep_obj/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level3_keep_obj/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level3_keep_obj/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level4_inMemoryCompilation_keep_cl/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level4_inMemoryCompilation_keep_cl/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level4_inMemoryCompilation_keep_cl/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level4_inMemoryCompilation_keep_class/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level4_inMemoryCompilation_keep_class/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level4_inMemoryCompilation_keep_class/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level4_inMemoryCompilation_keep_obj/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level4_inMemoryCompilation_keep_obj/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level4_inMemoryCompilation_keep_obj/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level4_keep_cl/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level4_keep_cl/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level4_keep_cl/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level4_keep_class/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level4_keep_class/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level4_keep_class/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level4_keep_obj/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level4_keep_obj/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_compilation_level4_keep_obj/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_humongous_class_inMemoryCompilation_keep_cl/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_humongous_class_inMemoryCompilation_keep_cl/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_humongous_class_inMemoryCompilation_keep_cl/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_humongous_class_inMemoryCompilation_keep_class/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_humongous_class_inMemoryCompilation_keep_class/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_humongous_class_inMemoryCompilation_keep_class/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_humongous_class_inMemoryCompilation_keep_obj/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_humongous_class_inMemoryCompilation_keep_obj/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_humongous_class_inMemoryCompilation_keep_obj/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_humongous_class_keep_cl/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_humongous_class_keep_cl/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_humongous_class_keep_cl/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_humongous_class_keep_class/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_humongous_class_keep_class/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_humongous_class_keep_class/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_humongous_class_keep_obj/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_humongous_class_keep_obj/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_humongous_class_keep_obj/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_jni_classloading_inMemoryCompilation_keep_cl/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_jni_classloading_inMemoryCompilation_keep_cl/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_jni_classloading_inMemoryCompilation_keep_cl/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_jni_classloading_inMemoryCompilation_keep_class/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_jni_classloading_inMemoryCompilation_keep_class/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_jni_classloading_inMemoryCompilation_keep_class/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_jni_classloading_inMemoryCompilation_keep_obj/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_jni_classloading_inMemoryCompilation_keep_obj/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_jni_classloading_inMemoryCompilation_keep_obj/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_jni_classloading_keep_cl/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_jni_classloading_keep_cl/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_jni_classloading_keep_cl/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_jni_classloading_keep_class/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_jni_classloading_keep_class/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_jni_classloading_keep_class/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_jni_classloading_keep_obj/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_jni_classloading_keep_obj/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_jni_classloading_keep_obj/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_jni_global_ref_inMemoryCompilation_keep_cl/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_jni_global_ref_inMemoryCompilation_keep_cl/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_jni_global_ref_inMemoryCompilation_keep_cl/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_jni_global_ref_inMemoryCompilation_keep_class/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_jni_global_ref_inMemoryCompilation_keep_class/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_jni_global_ref_inMemoryCompilation_keep_class/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_jni_global_ref_inMemoryCompilation_keep_obj/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_jni_global_ref_inMemoryCompilation_keep_obj/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_jni_global_ref_inMemoryCompilation_keep_obj/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_jni_global_ref_keep_cl/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_jni_global_ref_keep_cl/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_jni_global_ref_keep_cl/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_jni_global_ref_keep_class/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_jni_global_ref_keep_class/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_jni_global_ref_keep_class/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_jni_global_ref_keep_obj/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_jni_global_ref_keep_obj/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_jni_global_ref_keep_obj/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_jni_local_ref_inMemoryCompilation_keep_cl/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_jni_local_ref_inMemoryCompilation_keep_cl/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_jni_local_ref_inMemoryCompilation_keep_cl/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_jni_local_ref_inMemoryCompilation_keep_class/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_jni_local_ref_inMemoryCompilation_keep_class/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_jni_local_ref_inMemoryCompilation_keep_class/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_jni_local_ref_inMemoryCompilation_keep_obj/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_jni_local_ref_inMemoryCompilation_keep_obj/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_jni_local_ref_inMemoryCompilation_keep_obj/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_jni_local_ref_keep_cl/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_jni_local_ref_keep_cl/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_jni_local_ref_keep_cl/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_jni_local_ref_keep_class/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_jni_local_ref_keep_class/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_jni_local_ref_keep_class/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_jni_local_ref_keep_obj/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_jni_local_ref_keep_obj/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_jni_local_ref_keep_obj/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_inMemoryCompilation_keep_cl/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_inMemoryCompilation_keep_cl/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_inMemoryCompilation_keep_cl/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_inMemoryCompilation_keep_class/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_inMemoryCompilation_keep_class/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_inMemoryCompilation_keep_class/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_inMemoryCompilation_keep_obj/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_inMemoryCompilation_keep_obj/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_inMemoryCompilation_keep_obj/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_keep_cl/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_keep_cl/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_keep_cl/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_keep_class/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_keep_class/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_keep_class/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_keep_obj/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_keep_obj/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_keep_obj/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_stackLocal_inMemoryCompilation_keep_cl/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_stackLocal_inMemoryCompilation_keep_cl/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_stackLocal_inMemoryCompilation_keep_cl/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_stackLocal_inMemoryCompilation_keep_class/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_stackLocal_inMemoryCompilation_keep_class/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_stackLocal_inMemoryCompilation_keep_class/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_stackLocal_inMemoryCompilation_keep_obj/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_stackLocal_inMemoryCompilation_keep_obj/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_stackLocal_inMemoryCompilation_keep_obj/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_stackLocal_keep_cl/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_stackLocal_keep_cl/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_stackLocal_keep_cl/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_stackLocal_keep_class/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_stackLocal_keep_class/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_stackLocal_keep_class/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_stackLocal_keep_obj/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_stackLocal_keep_obj/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_stackLocal_keep_obj/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_staticField_inMemoryCompilation_keep_cl/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_staticField_inMemoryCompilation_keep_cl/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_staticField_inMemoryCompilation_keep_cl/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_staticField_inMemoryCompilation_keep_class/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_staticField_inMemoryCompilation_keep_class/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_staticField_inMemoryCompilation_keep_class/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_staticField_inMemoryCompilation_keep_obj/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_staticField_inMemoryCompilation_keep_obj/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_staticField_inMemoryCompilation_keep_obj/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_staticField_keep_cl/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_staticField_keep_cl/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_staticField_keep_cl/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_staticField_keep_class/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_staticField_keep_class/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_staticField_keep_class/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_staticField_keep_obj/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_staticField_keep_obj/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_staticField_keep_obj/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_strongRef_inMemoryCompilation_keep_cl/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_strongRef_inMemoryCompilation_keep_cl/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_strongRef_inMemoryCompilation_keep_cl/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_strongRef_inMemoryCompilation_keep_class/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_strongRef_inMemoryCompilation_keep_class/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_strongRef_inMemoryCompilation_keep_class/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_strongRef_inMemoryCompilation_keep_obj/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_strongRef_inMemoryCompilation_keep_obj/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_strongRef_inMemoryCompilation_keep_obj/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_strongRef_keep_cl/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_strongRef_keep_cl/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_strongRef_keep_cl/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_strongRef_keep_class/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_strongRef_keep_class/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_strongRef_keep_class/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_strongRef_keep_obj/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_strongRef_keep_obj/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_strongRef_keep_obj/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_threadItself_inMemoryCompilation_keep_cl/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_threadItself_inMemoryCompilation_keep_cl/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_threadItself_inMemoryCompilation_keep_cl/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_threadItself_inMemoryCompilation_keep_class/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_threadItself_inMemoryCompilation_keep_class/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_threadItself_inMemoryCompilation_keep_class/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_threadItself_inMemoryCompilation_keep_obj/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_threadItself_inMemoryCompilation_keep_obj/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_threadItself_inMemoryCompilation_keep_obj/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_threadItself_keep_cl/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_threadItself_keep_cl/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_threadItself_keep_cl/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_threadItself_keep_class/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_threadItself_keep_class/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_threadItself_keep_class/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_threadItself_keep_obj/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_threadItself_keep_obj/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_threadItself_keep_obj/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_phantom_ref_inMemoryCompilation_keep_cl/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_phantom_ref_inMemoryCompilation_keep_cl/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_phantom_ref_inMemoryCompilation_keep_cl/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_phantom_ref_inMemoryCompilation_keep_class/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_phantom_ref_inMemoryCompilation_keep_class/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_phantom_ref_inMemoryCompilation_keep_class/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_phantom_ref_inMemoryCompilation_keep_obj/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_phantom_ref_inMemoryCompilation_keep_obj/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_phantom_ref_inMemoryCompilation_keep_obj/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_phantom_ref_keep_cl/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_phantom_ref_keep_cl/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_phantom_ref_keep_cl/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_phantom_ref_keep_class/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_phantom_ref_keep_class/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_phantom_ref_keep_class/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_phantom_ref_keep_obj/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_phantom_ref_keep_obj/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_phantom_ref_keep_obj/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_prot_domains_inMemoryCompilation_keep_cl/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_prot_domains_inMemoryCompilation_keep_cl/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_prot_domains_inMemoryCompilation_keep_cl/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_prot_domains_inMemoryCompilation_keep_class/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_prot_domains_inMemoryCompilation_keep_class/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_prot_domains_inMemoryCompilation_keep_class/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_prot_domains_inMemoryCompilation_keep_obj/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_prot_domains_inMemoryCompilation_keep_obj/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_prot_domains_inMemoryCompilation_keep_obj/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_prot_domains_keep_cl/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_prot_domains_keep_cl/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_prot_domains_keep_cl/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_prot_domains_keep_class/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_prot_domains_keep_class/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_prot_domains_keep_class/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_prot_domains_keep_obj/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_prot_domains_keep_obj/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_prot_domains_keep_obj/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_redefinition_inMemoryCompilation_keep_cl/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_redefinition_inMemoryCompilation_keep_cl/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_redefinition_inMemoryCompilation_keep_cl/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_redefinition_inMemoryCompilation_keep_class/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_redefinition_inMemoryCompilation_keep_class/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_redefinition_inMemoryCompilation_keep_class/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_redefinition_inMemoryCompilation_keep_obj/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_redefinition_inMemoryCompilation_keep_obj/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_redefinition_inMemoryCompilation_keep_obj/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_redefinition_keep_cl/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_redefinition_keep_cl/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_redefinition_keep_cl/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_redefinition_keep_class/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_redefinition_keep_class/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_redefinition_keep_class/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_redefinition_keep_obj/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_redefinition_keep_obj/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_redefinition_keep_obj/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_reflection_classloading_inMemoryCompilation_keep_cl/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_reflection_classloading_inMemoryCompilation_keep_cl/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_reflection_classloading_inMemoryCompilation_keep_cl/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_reflection_classloading_inMemoryCompilation_keep_class/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_reflection_classloading_inMemoryCompilation_keep_class/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_reflection_classloading_inMemoryCompilation_keep_class/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_reflection_classloading_inMemoryCompilation_keep_obj/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_reflection_classloading_inMemoryCompilation_keep_obj/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_reflection_classloading_inMemoryCompilation_keep_obj/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_reflection_classloading_keep_cl/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_reflection_classloading_keep_cl/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_reflection_classloading_keep_cl/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_reflection_classloading_keep_class/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_reflection_classloading_keep_class/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_reflection_classloading_keep_class/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_reflection_classloading_keep_obj/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_reflection_classloading_keep_obj/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_reflection_classloading_keep_obj/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_weak_ref_inMemoryCompilation_keep_cl/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_weak_ref_inMemoryCompilation_keep_cl/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_weak_ref_inMemoryCompilation_keep_cl/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_weak_ref_inMemoryCompilation_keep_class/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_weak_ref_inMemoryCompilation_keep_class/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_weak_ref_inMemoryCompilation_keep_class/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_weak_ref_inMemoryCompilation_keep_obj/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_weak_ref_inMemoryCompilation_keep_obj/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_weak_ref_inMemoryCompilation_keep_obj/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_weak_ref_keep_cl/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_weak_ref_keep_cl/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_weak_ref_keep_cl/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_weak_ref_keep_class/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_weak_ref_keep_class/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_weak_ref_keep_class/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_weak_ref_keep_obj/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_weak_ref_keep_obj/TEST.properties +deleted file mode 100644 +index 04b22a107..000000000 +--- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_weak_ref_keep_obj/TEST.properties ++++ /dev/null +@@ -1,23 +0,0 @@ +-# +-# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +-# +-# This code is free software; you can redistribute it and/or modify it +-# under the terms of the GNU General Public License version 2 only, as +-# published by the Free Software Foundation. +-# +-# This code is distributed in the hope that it will be useful, but WITHOUT +-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-# version 2 for more details (a copy is included in the LICENSE file that +-# accompanied this code). +-# +-# You should have received a copy of the GNU General Public License version +-# 2 along with this work; if not, write to the Free Software Foundation, +-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +-# +-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +-# or visit www.oracle.com if you need additional information or have any +-# questions. +-# +-exclusiveAccess.dirs=. +diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/gc/Memory.java b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/Memory.java +index f5c70671e..244bcf423 100644 +--- a/test/hotspot/jtreg/vmTestbase/nsk/share/gc/Memory.java ++++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/Memory.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2005, 2024, 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 +@@ -150,12 +150,9 @@ public final class Memory { + * @return length of array + */ + public static int getArrayLength(long memory, long objectSize) { +- int referenceSize = getReferenceSize(); + int arrayExtraSize = getArrayExtraSize(); +- return (int) Math.min( +- (memory - arrayExtraSize) / (objectSize + referenceSize), +- Integer.MAX_VALUE +- ); ++ return (int) Math.min((memory - arrayExtraSize) / objectSize, ++ Integer.MAX_VALUE); + } + + /** +@@ -166,7 +163,7 @@ public final class Memory { + * @return size of array + */ + public static long getArraySize(int length, long objectSize) { +- return getObjectExtraSize() + length * (objectSize + getReferenceSize()); ++ return getArrayExtraSize() + length * objectSize; + } + + /** +diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt +index ec71b1b23..3051f69cc 100644 +--- a/test/jdk/ProblemList.txt ++++ b/test/jdk/ProblemList.txt +@@ -445,7 +445,7 @@ java/awt/image/VolatileImage/CustomCompositeTest.java 8199002 windows-all,linux- + java/awt/image/VolatileImage/GradientPaints.java 8199003 linux-all + java/awt/JAWT/JAWT.sh 8197798 windows-all + java/awt/Debug/DumpOnKey/DumpOnKey.java 8202667 windows-all +-java/awt/Focus/WindowUpdateFocusabilityTest/WindowUpdateFocusabilityTest.java 8202926 linux-all ++java/awt/Focus/WindowUpdateFocusabilityTest/WindowUpdateFocusabilityTest.java 8339929 linux-all + java/awt/datatransfer/ConstructFlavoredObjectTest/ConstructFlavoredObjectTest.java 8202860 linux-all + java/awt/FileDialog/FilenameFilterTest/FilenameFilterTest.java 8202882 linux-all + java/awt/Frame/FramesGC/FramesGC.java 8079069 macosx-all +@@ -485,6 +485,8 @@ java/awt/event/MouseEvent/FrameMouseEventAbsoluteCoordsTest/FrameMouseEventAbsol + # Several tests which fail sometimes on macos11 + java/awt/Dialog/MakeWindowAlwaysOnTop/MakeWindowAlwaysOnTop.java 8266243 macosx-aarch64 + ++java/awt/Graphics2D/CopyAreaOOB.java 8343106 macosx-aarch64 + -+ private final RegisterArray javaGeneralParameterRegisters = new RegisterArray(t0, a0, a1, a2, a3, a4, a5, a6, a7); -+ private final RegisterArray nativeGeneralParameterRegisters = new RegisterArray(a0, a1, a2, a3, a4, a5, a6, a7); -+ private final RegisterArray floatParameterRegisters = new RegisterArray(f0, f1, f2, f3, f4, f5, f6, f7); + # This test fails on macOS 14 + java/awt/Choice/SelectNewItemTest/SelectNewItemTest.java 8324782 macosx-all + +@@ -604,7 +606,6 @@ com/sun/nio/sctp/SctpChannel/SocketOptionTests.java 8141694 linux-al + + # jdk_security + +-sun/security/pkcs11/ec/TestKeyFactory.java 8026976 generic-all + sun/security/pkcs11/KeyStore/ClientAuth.sh 8254806 solaris-all + sun/security/pkcs11/sslecc/ClientJSSEServerJSSE.java 8161536 generic-all + +@@ -710,7 +711,6 @@ javax/swing/JComboBox/8182031/ComboPopupTest.java 8196465 linux-all,macosx-all + javax/swing/JFileChooser/6738668/bug6738668.java 8194946 generic-all + javax/swing/JFileChooser/8062561/bug8062561.java 8196466 linux-all,macosx-all + javax/swing/JInternalFrame/Test6325652.java 8196467 macosx-all +-javax/swing/JInternalFrame/8146321/JInternalFrameIconTest.java 8225045 linux-all + javax/swing/JLabel/6596966/bug6596966.java 8040914 macosx-all + javax/swing/JPopupMenu/4870644/bug4870644.java 8194130 macosx-all + javax/swing/JSpinner/8223788/JSpinnerButtonFocusTest.java 8238085 macosx-all +diff --git a/test/jdk/build/AbsPathsInImage.java b/test/jdk/build/AbsPathsInImage.java +index 64a223984..a47ee781f 100644 +--- a/test/jdk/build/AbsPathsInImage.java ++++ b/test/jdk/build/AbsPathsInImage.java +@@ -208,7 +208,7 @@ public class AbsPathsInImage { + for (byte[] searchPattern : searchPatterns) { + boolean found = true; + for (int j = 0; j < searchPattern.length; j++) { +- if ((i + j > data.length || data[i + j] != searchPattern[j])) { ++ if ((i + j >= data.length || data[i + j] != searchPattern[j])) { + found = false; + break; + } +diff --git a/test/jdk/com/sun/nio/sctp/SctpChannel/CloseDescriptors.java b/test/jdk/com/sun/nio/sctp/SctpChannel/CloseDescriptors.java +index 073b8f4a1..425338d10 100644 +--- a/test/jdk/com/sun/nio/sctp/SctpChannel/CloseDescriptors.java ++++ b/test/jdk/com/sun/nio/sctp/SctpChannel/CloseDescriptors.java +@@ -120,7 +120,7 @@ public class CloseDescriptors { + private static boolean check() throws Exception { + long myPid = ProcessHandle.current().pid(); + ProcessBuilder pb = new ProcessBuilder( +- "lsof", "-U", "-a", "-p", Long.toString(myPid)); ++ "lsof", "-U", "-a", "-w", "-p", Long.toString(myPid)); + pb.redirectErrorStream(true); + Process p = pb.start(); + p.waitFor(); +diff --git a/test/jdk/java/awt/FullScreen/SetFullScreenTest.java b/test/jdk/java/awt/FullScreen/SetFullScreenTest.java +new file mode 100644 +index 000000000..316bc2f64 +--- /dev/null ++++ b/test/jdk/java/awt/FullScreen/SetFullScreenTest.java +@@ -0,0 +1,89 @@ ++/* ++ * Copyright (c) 2024, 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. ++ */ + -+ public static final Register heapBaseRegister = s5; -+ public static final Register TREG = s6; ++import java.awt.Color; ++import java.awt.Frame; ++import java.awt.GraphicsDevice; ++import java.awt.GraphicsEnvironment; ++import java.awt.Robot; ++import jtreg.SkippedException; + -+ private static final RegisterArray reservedRegisters = new RegisterArray(fp, ra, zero, sp, tp, rx, SCR1, SCR2, TREG); ++import static java.awt.EventQueue.invokeAndWait; + -+ private static RegisterArray initAllocatable(Architecture arch, boolean reserveForHeapBase) { -+ RegisterArray allRegisters = arch.getAvailableValueRegisters(); -+ Register[] registers = new Register[allRegisters.size() - reservedRegisters.size() - (reserveForHeapBase ? 1 : 0)]; -+ List reservedRegistersList = reservedRegisters.asList(); ++/* ++ * @test ++ * @key headful ++ * @bug 8312518 ++ * @library /test/lib ++ * @summary Setting fullscreen window using setFullScreenWindow() shows up ++ * as black screen on newer macOS versions (13 & 14). ++ */ + -+ int idx = 0; -+ for (Register reg : allRegisters) { -+ if (reservedRegistersList.contains(reg)) { -+ // skip reserved registers -+ continue; ++public class SetFullScreenTest { ++ private static Frame frame; ++ private static GraphicsDevice gd; ++ private static Robot robot; ++ private static volatile int width; ++ private static volatile int height; ++ ++ public static void main(String[] args) throws Exception { ++ try { ++ robot = new Robot(); ++ invokeAndWait(() -> { ++ gd = GraphicsEnvironment.getLocalGraphicsEnvironment(). ++ getDefaultScreenDevice(); ++ if (!gd.isFullScreenSupported()) { ++ throw new SkippedException("Full Screen mode not supported"); ++ } ++ }); ++ ++ invokeAndWait(() -> { ++ frame = new Frame("Test FullScreen mode"); ++ frame.setBackground(Color.RED); ++ frame.setSize(100, 100); ++ frame.setLocation(10, 10); ++ frame.setVisible(true); ++ }); ++ robot.delay(1000); ++ ++ invokeAndWait(() -> gd.setFullScreenWindow(frame)); ++ robot.waitForIdle(); ++ robot.delay(300); ++ ++ invokeAndWait(() -> { ++ width = gd.getFullScreenWindow().getWidth(); ++ height = gd.getFullScreenWindow().getHeight(); ++ }); ++ ++ if (!robot.getPixelColor(width / 2, height / 2).equals(Color.RED)) { ++ System.err.println("Actual color: " + robot.getPixelColor(width / 2, height / 2) ++ + " Expected color: " + Color.RED); ++ throw new RuntimeException("Test Failed! Window not in full screen mode"); + } -+ if (reserveForHeapBase && reg.equals(heapBaseRegister)) { -+ // skip heap base register -+ continue; ++ } finally { ++ if (frame != null) { ++ frame.dispose(); + } -+ -+ registers[idx++] = reg; + } -+ -+ assert idx == registers.length; -+ return new RegisterArray(registers); -+ } -+ -+ public LoongArch64HotSpotRegisterConfig(TargetDescription target, boolean useCompressedOops) { -+ this(target, initAllocatable(target.arch, useCompressedOops)); -+ assert callerSaved.size() >= allocatable.size(); -+ } -+ -+ public LoongArch64HotSpotRegisterConfig(TargetDescription target, RegisterArray allocatable) { -+ this.target = target; -+ -+ this.allocatable = allocatable; -+ Set callerSaveSet = new HashSet<>(); -+ allocatable.addTo(callerSaveSet); -+ floatParameterRegisters.addTo(callerSaveSet); -+ javaGeneralParameterRegisters.addTo(callerSaveSet); -+ nativeGeneralParameterRegisters.addTo(callerSaveSet); -+ callerSaved = new RegisterArray(callerSaveSet); -+ -+ allAllocatableAreCallerSaved = true; -+ attributesMap = RegisterAttributes.createMap(this, LoongArch64.allRegisters); + } -+ -+ @Override -+ public RegisterArray getCallerSaveRegisters() { -+ return callerSaved; ++} +diff --git a/test/jdk/java/awt/List/MouseDraggedOutCauseScrollingTest/MouseDraggedOutCauseScrollingTest.html b/test/jdk/java/awt/List/MouseDraggedOutCauseScrollingTest/MouseDraggedOutCauseScrollingTest.html +deleted file mode 100644 +index 7049e8270..000000000 +--- a/test/jdk/java/awt/List/MouseDraggedOutCauseScrollingTest/MouseDraggedOutCauseScrollingTest.html ++++ /dev/null +@@ -1,43 +0,0 @@ +- +- +- +- +- +- ManualYesNoTest +- +- +- +-

ManualYesNoTest
Bug ID:

+- +-

See the dialog box (usually in upper left corner) for instructions

+- +- +- +- +diff --git a/test/jdk/java/awt/List/MouseDraggedOutCauseScrollingTest/MouseDraggedOutCauseScrollingTest.java b/test/jdk/java/awt/List/MouseDraggedOutCauseScrollingTest/MouseDraggedOutCauseScrollingTest.java +index 8b509a123..446b7a3a9 100644 +--- a/test/jdk/java/awt/List/MouseDraggedOutCauseScrollingTest/MouseDraggedOutCauseScrollingTest.java ++++ b/test/jdk/java/awt/List/MouseDraggedOutCauseScrollingTest/MouseDraggedOutCauseScrollingTest.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2013, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -22,29 +22,29 @@ + */ + + /* +- test ++ @test + @bug 6243382 8006070 + @summary Dragging of mouse outside of a List and Choice area don't work properly on XAWT +- @author Dmitry.Cherepanov@SUN.COM area=awt.list +- @run applet/manual=yesno MouseDraggedOutCauseScrollingTest.html ++ @requires (os.family == "linux") ++ @library /java/awt/regtesthelpers ++ @run main/manual MouseDraggedOutCauseScrollingTest + */ + +-import java.applet.Applet; +-import java.awt.*; ++import java.awt.Choice; ++import java.awt.Frame; ++import java.awt.GridLayout; ++import java.awt.List; ++import java.awt.Toolkit; + +-public class MouseDraggedOutCauseScrollingTest extends Applet +-{ +- Choice choice; +- List singleList; +- List multipleList; ++public class MouseDraggedOutCauseScrollingTest { + +- public void init() +- { +- this.setLayout (new GridLayout (1, 3)); ++ static Frame createUI() { ++ Frame frame = new Frame("MouseDraggedOutCausesScrollingTest"); ++ frame.setLayout(new GridLayout(1, 3)); + +- choice = new Choice(); +- singleList = new List(3, false); +- multipleList = new List(3, true); ++ Choice choice = new Choice(); ++ List singleList = new List(3, false); ++ List multipleList = new List(3, true); + + choice.add("Choice"); + for (int i = 1; i < 100; i++){ +@@ -59,188 +59,66 @@ public class MouseDraggedOutCauseScrollingTest extends Applet + for (int i = 1; i < 100; i++) + multipleList.add(""+i); + +- this.add(choice); +- this.add(singleList); +- this.add(multipleList); ++ frame.add(choice); ++ frame.add(singleList); ++ frame.add(multipleList); ++ frame.setSize(400, 100); ++ return frame; + } + ++ public static void main(String[] args) throws Exception { + String toolkitName = Toolkit.getDefaultToolkit().getClass().getName(); ++ + if (!toolkitName.equals("sun.awt.X11.XToolkit")) { +- String[] instructions = +- { +- "This test is not applicable to the current platform. Press PASS" +- }; +- Sysout.createDialogWithInstructions( instructions ); +- } else { +- String[] instructions = +- { +- "0) Please note, that this is only Motif/XAWT test. At first, make the applet active", +- "1.1) Click on the choice", +- "1.2) Press the left button of the mouse and keep on any item of the choice, for example 5", +- "1.3) Drag mouse out of the area of the unfurled list, at the same time hold the X coordinate of the mouse position about the same", +- "1.4) To make sure, that when the Y coordinate of the mouse position higher of the upper bound of the list then scrolling UP of the list and selected item changes on the upper. If not, the test failed", +- "1.5) To make sure, that when the Y coordinate of the mouse position under of the lower bound of the list then scrolling DOWN of the list and selected item changes on the lower. If not, the test failed", +- "-----------------------------------", +- "2.1) Click on the single list", +- "2.2) Press the left button of the mouse and keep on any item of the list, for example 5", +- "2.3) Drag mouse out of the area of the unfurled list, at the same time hold the X coordinate of the mouse position about the same", +- "2.4) To make sure, that when the Y coordinate of the mouse position higher of the upper bound of the list then scrolling UP of the list and selected item changes on the upper. If not, the test failed", +- "2.5) To make sure, that when the Y coordinate of the mouse position under of the lower bound of the list then scrolling DOWN of the list and selected item changes on the lower. If not, the test failed", +- "-----------------------------------", +- "3.1) Click on the multiple list", +- "3.2) Press the left button of the mouse and keep on any item of the list, for example 5", +- "3.3) Drag mouse out of the area of the unfurled list, at the same time hold the X coordinate of the mouse position about the same", +- "3.4) To make sure, that when the Y coordinate of the mouse position higher of the upper bound of the list then scrolling of the list NO OCCURED and selected item NO CHANGES on the upper. If not, the test failed", +- "3.5) To make sure, that when the Y coordinate of the mouse position under of the lower bound of the list then scrolling of the list NO OCCURED and selected item NO CHANGES on the lower. If not, the test failed", +- "4) Test passed." +- }; +- Sysout.createDialogWithInstructions( instructions ); ++ System.out.println(INAPPLICABLE); ++ return; + } + +- }//End init() +- +- public void start () +- { +- setSize (400,100); +- setVisible(true); +- validate(); +- +- }// start() +- +-}// class ManualYesNoTest +- +-/**************************************************** +- Standard Test Machinery +- DO NOT modify anything below -- it's a standard +- chunk of code whose purpose is to make user +- interaction uniform, and thereby make it simpler +- to read and understand someone else's test. +- ****************************************************/ +- +-/** +- This is part of the standard test machinery. +- It creates a dialog (with the instructions), and is the interface +- for sending text messages to the user. +- To print the instructions, send an array of strings to Sysout.createDialog +- WithInstructions method. Put one line of instructions per array entry. +- To display a message for the tester to see, simply call Sysout.println +- with the string to be displayed. +- This mimics System.out.println but works within the test harness as well +- as standalone. +- */ +- +-class Sysout +-{ +- private static TestDialog dialog; +- +- public static void createDialogWithInstructions( String[] instructions ) +- { +- dialog = new TestDialog( new Frame(), "Instructions" ); +- dialog.printInstructions( instructions ); +- dialog.setVisible(true); +- println( "Any messages for the tester will display here." ); +- } +- +- public static void createDialog( ) +- { +- dialog = new TestDialog( new Frame(), "Instructions" ); +- String[] defInstr = { "Instructions will appear here. ", "" } ; +- dialog.printInstructions( defInstr ); +- dialog.setVisible(true); +- println( "Any messages for the tester will display here." ); +- } +- +- +- public static void printInstructions( String[] instructions ) +- { +- dialog.printInstructions( instructions ); +- } +- +- +- public static void println( String messageIn ) +- { +- dialog.displayMessage( messageIn ); +- } +- +-}// Sysout class +- +-/** +- This is part of the standard test machinery. It provides a place for the +- test instructions to be displayed, and a place for interactive messages +- to the user to be displayed. +- To have the test instructions displayed, see Sysout. +- To have a message to the user be displayed, see Sysout. +- Do not call anything in this dialog directly. +- */ +-class TestDialog extends Dialog +-{ +- +- TextArea instructionsText; +- TextArea messageText; +- int maxStringLength = 80; +- +- //DO NOT call this directly, go through Sysout +- public TestDialog( Frame frame, String name ) +- { +- super( frame, name ); +- int scrollBoth = TextArea.SCROLLBARS_BOTH; +- instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth ); +- add( "North", instructionsText ); +- +- messageText = new TextArea( "", 5, maxStringLength, scrollBoth ); +- add("Center", messageText); +- +- pack(); +- +- setVisible(true); +- }// TestDialog() +- +- //DO NOT call this directly, go through Sysout +- public void printInstructions( String[] instructions ) +- { +- //Clear out any current instructions +- instructionsText.setText( "" ); +- +- //Go down array of instruction strings +- +- String printStr, remainingStr; +- for( int i=0; i < instructions.length; i++ ) +- { +- //chop up each into pieces maxSringLength long +- remainingStr = instructions[ i ]; +- while( remainingStr.length() > 0 ) +- { +- //if longer than max then chop off first max chars to print +- if( remainingStr.length() >= maxStringLength ) +- { +- //Try to chop on a word boundary +- int posOfSpace = remainingStr. +- lastIndexOf( ' ', maxStringLength - 1 ); +- +- if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1; +- +- printStr = remainingStr.substring( 0, posOfSpace + 1 ); +- remainingStr = remainingStr.substring( posOfSpace + 1 ); +- } +- //else just print +- else +- { +- printStr = remainingStr; +- remainingStr = ""; +- } +- +- instructionsText.append( printStr + "\n" ); +- +- }// while +- +- }// for +- +- }//printInstructions() +- +- //DO NOT call this directly, go through Sysout +- public void displayMessage( String messageIn ) +- { +- messageText.append( messageIn + "\n" ); +- System.out.println(messageIn); ++ PassFailJFrame ++ .builder() ++ .instructions(INSTRUCTIONS) ++ .rows(40) ++ .columns(70) ++ .testUI(MouseDraggedOutCauseScrollingTest::createUI) ++ .build() ++ .awaitAndCheck(); + } + +-}// TestDialog class ++ static final String INAPPLICABLE = "The test is not applicable to the current platform. Test PASSES."; ++ static final String INSTRUCTIONS = "0) Please note, that this is an XAWT/Linux only test. First, make the test window is active.\n" + ++ "-----------------------------------\n" + ++ "1.1) Click on the Choice.\n" + ++ "1.2) Press and hold down the left button of the mouse to select (eg) item 5 in the choice.\n" + ++ "1.3) Drag the mouse vertically out of the area of the open list,\n" + ++ " keeping the X coordinate of the mouse position about the same.\n" + ++ "1.4) Check that when the Y coordinate of the mouse position is higher than the upper bound of the list\n" + ++ " then the list continues to scrolls UP and the selected item changes at the top until you reach the topmost item.\n" + ++ " If not, the test failed. Press FAIL.\n" + ++ "1.5) Check that when the Y coordinate of the mouse position is lower than the lower bound of the list\n" + ++ " then the list continues to scroll DOWN and the selected item changes at the bottom until you reach the bottommost item.\n" + ++ " If not, the test failed. Press FAIL.\n" + ++ "-----------------------------------\n" + ++ "2.1) Click on the Single List.\n" + ++ "2.2) Press and hold down the left button of the mouse to select (eg) item 5 in the list.\n" + ++ "2.3) Drag the mouse vertically out of the area of the open list,\n" + ++ " keeping the X coordinate of the mouse position about the same.\n" + ++ "2.4) Check that when the Y coordinate of the mouse position is higher than the upper bound of the list\n" + ++ " then the list continues to scrolls UP and the selected item changes at the top until you reach the topmost item.\n" + ++ " If not, the test failed. Press FAIL.\n" + ++ "2.5) Check that when the Y coordinate of the mouse position is lower than the lower bound of the list\n" + ++ " then the list continues to scroll DOWN and the selected item changes at the bottom until you reach the bottommost item.\n" + ++ " If not, the test failed. Press FAIL.\n" + ++ "-----------------------------------\n" + ++ "3.1) Click on the Multiple List.\n" + ++ "3.2) Press and hold down the left button of the mouse to select (eg) item 5 in the list.\n" + ++ "3.3) Drag the mouse vertically out of the area of the open list,\n" + ++ " keeping the X coordinate of the mouse position about the same.\n" + ++ "3.4) Check that when the Y coordinate of the mouse is higher than the upper bound of the list\n" + ++ " that scrolling of the list DOES NOT OCCUR and the selected item IS UNCHANGED at the top.\n" + ++ " If not, the test failed. Press FAIL.\n" + ++ "3.5) Check that when the Y coordinate of the mouse is below the lower bound of the list\n" + ++ " that scrolling of the list DOES NOT OCCUR and the selected item IS UNCHANGED at the bottom.\n" + ++ " If not, the test failed. Press FAIL.\n" + ++ "-----------------------------------\n" + ++ "4) The test has now passed. Press PASS."; ++} +diff --git a/test/jdk/java/awt/Modal/PrintDialogsTest/PrintDialogsTest.html b/test/jdk/java/awt/Modal/PrintDialogsTest/PrintDialogsTest.html +index a562b886a..e69de29bb 100644 +--- a/test/jdk/java/awt/Modal/PrintDialogsTest/PrintDialogsTest.html ++++ b/test/jdk/java/awt/Modal/PrintDialogsTest/PrintDialogsTest.html +@@ -1,44 +0,0 @@ +- +- +- +- +- PrintDialogsTest +- +- +- +- +-Please select dialog modality type and parent; also select +-the print auxiliary dialog to be displayed (Page Setup or Print dialog). +-Then click "Start test" button. +- +-When the windows will appear check if modal blocking for Dialog works as expected. +-Then push "Open" button on the Dialog to show the auxiliary dialog and check +-if it blocks the rest of the application. Then close it and check correctness +-of modal blocking behavior for the Dialog again. To close all the test +-windows please push "Finish" button. +- +-To finish the overall test push "Pass" or "Fail" button depending on result. +- +- +- +diff --git a/test/jdk/java/awt/Modal/PrintDialogsTest/PrintDialogsTest.java b/test/jdk/java/awt/Modal/PrintDialogsTest/PrintDialogsTest.java +index 989c48295..8a07d284a 100644 +--- a/test/jdk/java/awt/Modal/PrintDialogsTest/PrintDialogsTest.java ++++ b/test/jdk/java/awt/Modal/PrintDialogsTest/PrintDialogsTest.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -25,21 +25,75 @@ + /* + * @test + * @bug 8055836 8057694 8055752 +- * @summary Check if Print and Page Setup dialogs lock other windows; ++ * @summary Check if Print and Page Setup dialogs block other windows; + * check also correctness of modal behavior for other dialogs. +- * +- * @run applet/manual=yesno PrintDialogsTest.html ++ * @library /java/awt/regtesthelpers ++ * @run main/manual PrintDialogsTest + */ + + +-import java.applet.Applet; +-import java.awt.*; ++import java.awt.BorderLayout; ++import java.awt.Button; ++import java.awt.Checkbox; ++import java.awt.CheckboxGroup; ++import java.awt.Dialog; ++import java.awt.Frame; ++import java.awt.EventQueue; ++import java.awt.GridLayout; ++import java.awt.Label; ++import java.awt.Panel; + + import java.awt.event.ActionEvent; + import java.awt.event.ActionListener; + + +-public class PrintDialogsTest extends Applet implements ActionListener { ++public class PrintDialogsTest extends Panel implements ActionListener { + -+ @Override -+ public RegisterArray getCalleeSaveRegisters() { -+ return null; -+ } ++ static final String INSTRUCTIONS = ++ "This test is free format, which means there is no enforced or guided sequence." + "\n" + + -+ @Override -+ public boolean areAllAllocatableRegistersCallerSaved() { -+ return allAllocatableAreCallerSaved; -+ } ++ "Please select each of " + "\n" + ++ "(a) The dialog parent type." + "\n" + ++ "(b) The dialog modality type" + "\n" + ++ "(c) The print dialog type (Print dialog or Page Setup dialog)" + "\n" + + -+ @Override -+ public CallingConvention getCallingConvention(Type type, JavaType returnType, JavaType[] parameterTypes, ValueKindFactory valueKindFactory) { -+ HotSpotCallingConventionType hotspotType = (HotSpotCallingConventionType) type; -+ if (type == HotSpotCallingConventionType.NativeCall) { -+ return callingConvention(nativeGeneralParameterRegisters, returnType, parameterTypes, hotspotType, valueKindFactory); -+ } -+ // On x64, parameter locations are the same whether viewed -+ // from the caller or callee perspective -+ return callingConvention(javaGeneralParameterRegisters, returnType, parameterTypes, hotspotType, valueKindFactory); -+ } ++ "Once the choices have been made click the \"Start test\" button." + "\n" + + -+ @Override -+ public RegisterArray getCallingConventionRegisters(Type type, JavaKind kind) { -+ HotSpotCallingConventionType hotspotType = (HotSpotCallingConventionType) type; -+ switch (kind) { -+ case Boolean: -+ case Byte: -+ case Short: -+ case Char: -+ case Int: -+ case Long: -+ case Object: -+ return hotspotType == HotSpotCallingConventionType.NativeCall ? nativeGeneralParameterRegisters : javaGeneralParameterRegisters; -+ case Float: -+ case Double: -+ return floatParameterRegisters; -+ default: -+ throw JVMCIError.shouldNotReachHere(); -+ } -+ } ++ "Three windows will appear" + "\n" + ++ "(1) A Frame or a Dialog - in the case you selected \"Dialog\" as the parent type" + "\n" + ++ "(2) a Window (ie an undecorated top-level)" + "\n" + ++ "(3) A dialog with two buttons \"Open\" and \"Finish\"" + "\n" + + -+ private CallingConvention callingConvention(RegisterArray generalParameterRegisters, JavaType returnType, JavaType[] parameterTypes, HotSpotCallingConventionType type, -+ ValueKindFactory valueKindFactory) { -+ AllocatableValue[] locations = new AllocatableValue[parameterTypes.length]; ++ "Now check as follows whether modal blocking works as expected." + "\n" + ++ "Windows (1) and (2) contain a button which you should be able to press" + "\n" + ++ "ONLY if you selected \"Non-modal\", or \"Modeless\" for modality type." + "\n" + ++ "In other cases window (3) will block input to (1) and (2)" + "\n" + + -+ int currentGeneral = 0; -+ int currentFloat = 0; -+ int currentStackOffset = 0; ++ "Then push the \"Open\" button on the Dialog to show the printing dialog and check" + "\n" + ++ "if it blocks the rest of the application - ie all of windows (1), (2) and (3)" + "\n" + ++ "should ALWAYS be blocked when the print dialog is showing." + "\n" + ++ "Now cancel the printing dialog and check the correctness of modal blocking" + "\n" + ++ "behavior for the Dialog again." + "\n" + ++ "To close all the 3 test windows please push the \"Finish\" button." + "\n" + + -+ for (int i = 0; i < parameterTypes.length; i++) { -+ final JavaKind kind = parameterTypes[i].getJavaKind().getStackKind(); ++ "Repeat all the above for different combinations, which should include" + "\n" + ++ "using all of the Dialog parent choices and all of the Dialog Modality types." + "\n" + + -+ switch (kind) { -+ case Byte: -+ case Boolean: -+ case Short: -+ case Char: -+ case Int: -+ case Long: -+ case Object: -+ if (currentGeneral < generalParameterRegisters.size()) { -+ Register register = generalParameterRegisters.get(currentGeneral++); -+ locations[i] = register.asValue(valueKindFactory.getValueKind(kind)); -+ } -+ break; -+ case Float: -+ case Double: -+ if (currentFloat < floatParameterRegisters.size()) { -+ Register register = floatParameterRegisters.get(currentFloat++); -+ locations[i] = register.asValue(valueKindFactory.getValueKind(kind)); -+ } else if (currentGeneral < generalParameterRegisters.size()) { -+ Register register = generalParameterRegisters.get(currentGeneral++); -+ locations[i] = register.asValue(valueKindFactory.getValueKind(kind)); -+ } -+ break; -+ default: -+ throw JVMCIError.shouldNotReachHere(); -+ } ++ "If any behave incorrectly, note the combination of choices and press Fail." + "\n" + + -+ if (locations[i] == null) { -+ ValueKind valueKind = valueKindFactory.getValueKind(kind); -+ locations[i] = StackSlot.get(valueKind, currentStackOffset, !type.out); -+ currentStackOffset += Math.max(valueKind.getPlatformKind().getSizeInBytes(), target.wordSize); -+ } -+ } ++ "If all behave correctly, press Pass."; + -+ JavaKind returnKind = returnType == null ? JavaKind.Void : returnType.getJavaKind(); -+ AllocatableValue returnLocation = returnKind == JavaKind.Void ? Value.ILLEGAL : getReturnRegister(returnKind).asValue(valueKindFactory.getValueKind(returnKind.getStackKind())); -+ return new CallingConvention(currentStackOffset, returnLocation, locations); -+ } ++ public static void main(String[] args) throws Exception { + -+ @Override -+ public Register getReturnRegister(JavaKind kind) { -+ switch (kind) { -+ case Boolean: -+ case Byte: -+ case Char: -+ case Short: -+ case Int: -+ case Long: -+ case Object: -+ return v0; -+ case Float: -+ case Double: -+ return fv0; -+ case Void: -+ case Illegal: -+ return null; -+ default: -+ throw new UnsupportedOperationException("no return register for type " + kind); -+ } ++ PassFailJFrame.builder() ++ .instructions(INSTRUCTIONS) ++ .rows(35) ++ .columns(60) ++ .testUI(PrintDialogsTest::createUI) ++ .testTimeOut(10) ++ .build() ++ .awaitAndCheck(); + } -+ -+ @Override -+ public Register getFrameRegister() { -+ return sp; + + private Button btnTest; + private Checkbox cbPage, cbPrint, +@@ -48,6 +102,14 @@ public class PrintDialogsTest extends Applet implements ActionListener { + + private CheckboxGroup groupDialog, groupParent, groupModType; + ++ private static Frame createUI() { ++ Frame frame = new Frame("Dialog Modality Testing"); ++ PrintDialogsTest test = new PrintDialogsTest(); ++ test.createGUI(); ++ frame.add(test); ++ frame.pack(); ++ return frame; + } + + public void actionPerformed(ActionEvent e) { + +@@ -99,13 +161,13 @@ public class PrintDialogsTest extends Applet implements ActionListener { + + setLayout(new BorderLayout()); + +- setSize(350, 200); + Panel panel = new Panel(); +- panel.setLayout(new GridLayout(18, 1)); ++ panel.setLayout(new GridLayout(21, 1)); + + btnTest = new Button("Start test"); + btnTest.addActionListener(this); + panel.add(btnTest); ++ panel.add(new Label(" ")); // spacing + + + panel.add(new Label("Dialog parent:")); +@@ -123,6 +185,7 @@ public class PrintDialogsTest extends Applet implements ActionListener { + panel.add(cbHiddFrm); + panel.add(cbDlg); + panel.add(cbFrm); ++ panel.add(new Label(" ")); // spacing + + panel.add(new Label("Dialog modality type:")); + groupModType = new CheckboxGroup(); +@@ -139,7 +202,7 @@ public class PrintDialogsTest extends Applet implements ActionListener { + panel.add(cbDocModal); + panel.add(cbTKModal); + panel.add(cbModeless); +- add(panel); ++ panel.add(new Label(" ")); // spacing + + panel.add(new Label("Print dialog type:")); + groupDialog = new CheckboxGroup(); +@@ -148,13 +211,6 @@ public class PrintDialogsTest extends Applet implements ActionListener { + panel.add(cbPage); + panel.add(cbPrint); + +- validate(); +- setVisible(true); +- } +- +- public void start() { +- try { +- EventQueue.invokeAndWait(this::createGUI); +- } catch (Exception e) {} ++ add(panel); + } + } +diff --git a/test/jdk/java/awt/Toolkit/Headless/HeadlessToolkit.java b/test/jdk/java/awt/Toolkit/Headless/HeadlessToolkit.java +index 0076bdb20..ebf4c598a 100644 +--- a/test/jdk/java/awt/Toolkit/Headless/HeadlessToolkit.java ++++ b/test/jdk/java/awt/Toolkit/Headless/HeadlessToolkit.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -21,8 +21,20 @@ + * questions. + */ + +-import javax.imageio.ImageIO; +-import java.awt.*; ++import java.awt.AWTEvent; ++import java.awt.Cursor; ++import java.awt.Dimension; ++import java.awt.EventQueue; ++import java.awt.Font; ++import java.awt.FontMetrics; ++import java.awt.Graphics2D; ++import java.awt.GraphicsConfiguration; ++import java.awt.GraphicsEnvironment; ++import java.awt.HeadlessException; ++import java.awt.Image; ++import java.awt.Insets; ++import java.awt.Point; ++import java.awt.Toolkit; + import java.awt.datatransfer.Clipboard; + import java.awt.event.AWTEventListener; + import java.awt.event.KeyEvent; +@@ -35,16 +47,16 @@ import java.beans.PropertyChangeListener; + import java.io.File; + import java.io.FileInputStream; + import java.io.IOException; +-import java.net.URL; + import java.util.Map; + ++import javax.imageio.ImageIO; + -+ @Override -+ public String toString() { -+ return String.format("Allocatable: " + getAllocatableRegisters() + "%n" + "CallerSave: " + getCallerSaveRegisters() + "%n"); -+ } -+} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot.loongarch64/src/jdk/vm/ci/hotspot/loongarch64/LoongArch64HotSpotVMConfig.java jdk11u-ls/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot.loongarch64/src/jdk/vm/ci/hotspot/loongarch64/LoongArch64HotSpotVMConfig.java ---- openjdk/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot.loongarch64/src/jdk/vm/ci/hotspot/loongarch64/LoongArch64HotSpotVMConfig.java 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot.loongarch64/src/jdk/vm/ci/hotspot/loongarch64/LoongArch64HotSpotVMConfig.java 2023-09-12 13:54:26.497575942 +0800 -@@ -0,0 +1,77 @@ + /* + * @test + * @summary Check that Toolkit methods do not throw unexpected exceptions + * in headless mode + * @run main/othervm -Djava.awt.headless=true HeadlessToolkit + */ +- + public class HeadlessToolkit { + + class awtEventListener implements AWTEventListener { +@@ -275,13 +287,12 @@ public class HeadlessToolkit { + im = tk.createImage(image.getAbsolutePath()); + im.flush(); + +- } +- +- im = tk.getImage(new URL("http://openjdk.java.net/images/openjdk.png")); +- im.flush(); ++ im = tk.getImage(image.toURI().toURL()); ++ im.flush(); + +- im = tk.createImage(new URL("http://openjdk.java.net/images/openjdk.png")); +- im.flush(); ++ im = tk.createImage(image.toURI().toURL()); ++ im.flush(); ++ } + + MemoryImageSource mis; + int pixels[] = new int[50 * 50]; +diff --git a/test/jdk/java/awt/color/NonICCFilterTest.java b/test/jdk/java/awt/color/NonICCFilterTest.java +new file mode 100644 +index 000000000..1c7b2f8d4 +--- /dev/null ++++ b/test/jdk/java/awt/color/NonICCFilterTest.java +@@ -0,0 +1,153 @@ +/* -+ * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2022, Loongson Technology. All rights reserved. ++ * Copyright (c) 2024, 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 @@ -119528,67 +205507,440 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.internal.vm.ci/sha + * or visit www.oracle.com if you need additional information or have any + * questions. + */ -+package jdk.vm.ci.hotspot.loongarch64; + -+import jdk.vm.ci.hotspot.HotSpotVMConfigAccess; -+import jdk.vm.ci.hotspot.HotSpotVMConfigStore; -+import jdk.vm.ci.services.Services; ++import java.awt.Color; ++import java.awt.GradientPaint; ++import java.awt.Graphics2D; ++import java.awt.Transparency; ++import java.awt.color.ColorSpace; ++import java.awt.image.BufferedImage; ++import java.awt.image.ColorConvertOp; ++import java.awt.image.ComponentColorModel; ++import java.awt.image.DataBuffer; ++import java.awt.image.WritableRaster; + -+/** -+ * Used to access native configuration details. -+ * -+ * All non-static, public fields in this class are so that they can be compiled as constants. ++/* ++ * @test ++ * @bug 8316497 ++ * @summary Verifies Color filter on non-ICC profile + */ -+class LoongArch64HotSpotVMConfig extends HotSpotVMConfigAccess { ++public final class NonICCFilterTest { ++ private static final int WIDTH = 100; ++ private static final int HEIGHT = 100; + -+ LoongArch64HotSpotVMConfig(HotSpotVMConfigStore config) { -+ super(config); ++ private enum ColorSpaceSelector { ++ GRAY, ++ RGB, ++ PYCC, ++ WRAPPED_GRAY, ++ WRAPPED_RGB, ++ WRAPPED_PYCC + } + -+ final boolean useCompressedOops = getFlag("UseCompressedOops", Boolean.class); ++ private static final class TestColorSpace extends ColorSpace { + -+ // CPU Capabilities ++ private final ColorSpace cs; + -+ /* -+ * These flags are set based on the corresponding command line flags. ++ TestColorSpace(ColorSpace cs) { ++ super(cs.getType(), cs.getNumComponents()); ++ this.cs = cs; ++ } ++ ++ @Override ++ public float[] toRGB(float[] colorvalue) { ++ return cs.toRGB(colorvalue); ++ } ++ ++ @Override ++ public float[] fromRGB(float[] rgbvalue) { ++ return cs.fromRGB(rgbvalue); ++ } ++ ++ @Override ++ public float[] toCIEXYZ(float[] colorvalue) { ++ return cs.toCIEXYZ(colorvalue); ++ } ++ ++ @Override ++ public float[] fromCIEXYZ(float[] xyzvalue) { ++ return cs.fromCIEXYZ(xyzvalue); ++ } ++ } ++ ++ private static BufferedImage createTestImage(final ColorSpace cs) { ++ ComponentColorModel cm = new ComponentColorModel(cs, false, false, ++ Transparency.OPAQUE, DataBuffer.TYPE_BYTE); ++ WritableRaster raster = cm.createCompatibleWritableRaster(WIDTH, HEIGHT); ++ BufferedImage img = new BufferedImage(cm, raster, false, null); ++ ++ Graphics2D g = img.createGraphics(); ++ GradientPaint gp = new GradientPaint(0, 0, Color.GREEN, ++ raster.getWidth(), raster.getHeight(), Color.BLUE); ++ g.setPaint(gp); ++ g.fillRect(0, 0, raster.getWidth(), raster.getHeight()); ++ g.dispose(); ++ ++ return img; ++ } ++ ++ private static ColorSpace createCS(ColorSpaceSelector selector) { ++ switch (selector) { ++ case GRAY: return ColorSpace.getInstance(ColorSpace.CS_GRAY); ++ case WRAPPED_GRAY: return new TestColorSpace(ColorSpace.getInstance(ColorSpace.CS_GRAY)); ++ ++ case RGB: return ColorSpace.getInstance(ColorSpace.CS_sRGB); ++ case WRAPPED_RGB: return new TestColorSpace(ColorSpace.getInstance(ColorSpace.CS_sRGB)); ++ ++ case PYCC: return ColorSpace.getInstance(ColorSpace.CS_PYCC); ++ case WRAPPED_PYCC: return new TestColorSpace(ColorSpace.getInstance(ColorSpace.CS_PYCC)); ++ ++ default: throw new IllegalArgumentException(); ++ } ++ } ++ ++ private static boolean areImagesEqual(BufferedImage destTest, BufferedImage destGold) { ++ for (int x = 0; x < destTest.getWidth(); x++) { ++ for (int y = 0; y < destTest.getHeight(); y++) { ++ int rgb1 = destTest.getRGB(x, y); ++ int rgb2 = destGold.getRGB(x, y); ++ if (rgb1 != rgb2) { ++ System.err.println("x = " + x + ", y = " + y); ++ System.err.println("rgb1 = " + Integer.toHexString(rgb1)); ++ System.err.println("rgb2 = " + Integer.toHexString(rgb2)); ++ return false; ++ } ++ } ++ } ++ return true; ++ } ++ ++ public static void main(String[] args) { ++ BufferedImage srcTest = createTestImage(createCS(ColorSpaceSelector.WRAPPED_GRAY)); ++ BufferedImage destTest = createTestImage(createCS(ColorSpaceSelector.WRAPPED_RGB)); ++ ++ BufferedImage srcGold = createTestImage(createCS(ColorSpaceSelector.GRAY)); ++ BufferedImage destGold = createTestImage(createCS(ColorSpaceSelector.RGB)); ++ ++ ColorConvertOp gold = new ColorConvertOp(createCS(ColorSpaceSelector.PYCC), null); ++ gold.filter(srcTest, destTest); ++ gold.filter(srcGold, destGold); ++ ++ if (!areImagesEqual(destTest, destGold)) { ++ throw new RuntimeException("ICC test failed"); ++ } ++ ++ ColorConvertOp test = new ColorConvertOp(createCS(ColorSpaceSelector.WRAPPED_PYCC), null); ++ test.filter(srcTest, destTest); ++ test.filter(srcGold, destGold); ++ ++ if (!areImagesEqual(destTest, destGold)) { ++ throw new RuntimeException("Wrapper test failed"); ++ } ++ } ++} +diff --git a/test/jdk/java/awt/regtesthelpers/PassFailJFrame.java b/test/jdk/java/awt/regtesthelpers/PassFailJFrame.java +index 6290d14b4..a4ede3714 100644 +--- a/test/jdk/java/awt/regtesthelpers/PassFailJFrame.java ++++ b/test/jdk/java/awt/regtesthelpers/PassFailJFrame.java +@@ -53,6 +53,7 @@ import java.util.concurrent.TimeUnit; + import java.util.concurrent.atomic.AtomicInteger; + + import javax.imageio.ImageIO; ++import javax.swing.Box; + import javax.swing.JButton; + import javax.swing.JComboBox; + import javax.swing.JComponent; +@@ -155,6 +156,7 @@ import static javax.swing.SwingUtilities.isEventDispatchThread; + *
  • the title of the instruction UI,
  • + *
  • the timeout of the test,
  • + *
  • the size of the instruction UI via rows and columns, and
  • ++ *
  • to add a log area
  • , + *
  • to enable screenshots.
  • + * + */ +@@ -204,6 +206,8 @@ public final class PassFailJFrame { + + private static Robot robot; + ++ private static JTextArea logArea; ++ + public enum Position {HORIZONTAL, VERTICAL, TOP_LEFT_CORNER} + + public PassFailJFrame(String instructions) throws InterruptedException, +@@ -373,6 +377,20 @@ public final class PassFailJFrame { + } + } + ++ /** ++ * Does the same as {@link #invokeOnEDT(Runnable)}, but does not throw ++ * any checked exceptions. ++ * ++ * @param doRun an operation to run on EDT + */ -+ final boolean useLSX = getFlag("UseLSX", Boolean.class); -+ final boolean useLASX = getFlag("UseLASX", Boolean.class); ++ private static void invokeOnEDTUncheckedException(Runnable doRun) { ++ try { ++ invokeOnEDT(doRun); ++ } catch (InterruptedException | InvocationTargetException e) { ++ throw new RuntimeException(e); ++ } ++ } + -+ final long vmVersionFeatures = getFieldValue("Abstract_VM_Version::_features", Long.class, "uint64_t"); + private static void createUI(String title, String instructions, + long testTimeOut, int rows, int columns, + boolean enableScreenCapture) { +@@ -384,7 +402,8 @@ public final class PassFailJFrame { + frame.add(createInstructionUIPanel(instructions, + testTimeOut, + rows, columns, +- enableScreenCapture), ++ enableScreenCapture, ++ false, 0), + BorderLayout.CENTER); + frame.pack(); + frame.setLocationRelativeTo(null); +@@ -401,8 +420,9 @@ public final class PassFailJFrame { + createInstructionUIPanel(builder.instructions, + builder.testTimeOut, + builder.rows, builder.columns, +- builder.screenCapture); +- ++ builder.screenCapture, ++ builder.addLogArea, ++ builder.logAreaRows); + if (builder.splitUI) { + JSplitPane splitPane = new JSplitPane( + builder.splitUIOrientation, +@@ -421,7 +441,9 @@ public final class PassFailJFrame { + private static JComponent createInstructionUIPanel(String instructions, + long testTimeOut, + int rows, int columns, +- boolean enableScreenCapture) { ++ boolean enableScreenCapture, ++ boolean addLogArea, ++ int logAreaRows) { + JPanel main = new JPanel(new BorderLayout()); + + JLabel testTimeoutLabel = new JLabel("", JLabel.CENTER); +@@ -455,7 +477,20 @@ public final class PassFailJFrame { + buttonsPanel.add(createCapturePanel()); + } + +- main.add(buttonsPanel, BorderLayout.SOUTH); ++ if (addLogArea) { ++ logArea = new JTextArea(logAreaRows, columns); ++ logArea.setEditable(false); + -+ /* -+ * These flags are set if the corresponding support is in the hardware. ++ Box buttonsLogPanel = Box.createVerticalBox(); ++ ++ buttonsLogPanel.add(buttonsPanel); ++ buttonsLogPanel.add(new JScrollPane(logArea)); ++ ++ main.add(buttonsLogPanel, BorderLayout.SOUTH); ++ } else { ++ main.add(buttonsPanel, BorderLayout.SOUTH); ++ } ++ + main.setMinimumSize(main.getPreferredSize()); + + return main; +@@ -1039,6 +1074,36 @@ public final class PassFailJFrame { + latch.countDown(); + } + ++ /** ++ * Adds a {@code message} to the log area, if enabled by ++ * {@link Builder#logArea()} or {@link Builder#logArea(int)}. ++ * ++ * @param message to log + */ -+ // Checkstyle: stop -+ final long loongarch64LA32 = getConstant("VM_Version::CPU_LA32", Long.class); -+ final long loongarch64LA64 = getConstant("VM_Version::CPU_LA64", Long.class); -+ final long loongarch64LLEXC = getConstant("VM_Version::CPU_LLEXC", Long.class); -+ final long loongarch64SCDLY = getConstant("VM_Version::CPU_SCDLY", Long.class); -+ final long loongarch64LLDBAR = getConstant("VM_Version::CPU_LLDBAR", Long.class); -+ final long loongarch64LBT_X86 = getConstant("VM_Version::CPU_LBT_X86", Long.class); -+ final long loongarch64LBT_ARM = getConstant("VM_Version::CPU_LBT_ARM", Long.class); -+ final long loongarch64LBT_MIPS = getConstant("VM_Version::CPU_LBT_MIPS", Long.class); -+ final long loongarch64CCDMA = getConstant("VM_Version::CPU_CCDMA", Long.class); -+ final long loongarch64COMPLEX = getConstant("VM_Version::CPU_COMPLEX", Long.class); -+ final long loongarch64FP = getConstant("VM_Version::CPU_FP", Long.class); -+ final long loongarch64CRYPTO = getConstant("VM_Version::CPU_CRYPTO", Long.class); -+ final long loongarch64LSX = getConstant("VM_Version::CPU_LSX", Long.class); -+ final long loongarch64LASX = getConstant("VM_Version::CPU_LASX", Long.class); -+ final long loongarch64LAM = getConstant("VM_Version::CPU_LAM", Long.class); -+ final long loongarch64LLSYNC = getConstant("VM_Version::CPU_LLSYNC", Long.class); -+ final long loongarch64TGTSYNC = getConstant("VM_Version::CPU_TGTSYNC", Long.class); -+ final long loongarch64ULSYNC = getConstant("VM_Version::CPU_ULSYNC", Long.class); -+ final long loongarch64UAL = getConstant("VM_Version::CPU_UAL", Long.class); -+ // Checkstyle: resume -+} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot.loongarch64/src/jdk/vm/ci/hotspot/loongarch64/package-info.java jdk11u-ls/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot.loongarch64/src/jdk/vm/ci/hotspot/loongarch64/package-info.java ---- openjdk/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot.loongarch64/src/jdk/vm/ci/hotspot/loongarch64/package-info.java 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot.loongarch64/src/jdk/vm/ci/hotspot/loongarch64/package-info.java 2023-09-12 13:54:26.501575947 +0800 -@@ -0,0 +1,28 @@ ++ public static void log(String message) { ++ System.out.println("PassFailJFrame: " + message); ++ invokeOnEDTUncheckedException(() -> logArea.append(message + "\n")); ++ } ++ ++ /** ++ * Clears the log area, if enabled by ++ * {@link Builder#logArea()} or {@link Builder#logArea(int)}. ++ */ ++ public static void logClear() { ++ System.out.println("\nPassFailJFrame: log cleared\n"); ++ invokeOnEDTUncheckedException(() -> logArea.setText("")); ++ } ++ ++ /** ++ * Replaces the log area content with provided {@code text}, if enabled by ++ * {@link Builder#logArea()} or {@link Builder#logArea(int)}. ++ * @param text new text for the log area ++ */ ++ public static void logSet(String text) { ++ System.out.println("\nPassFailJFrame: log set to:\n" + text + "\n"); ++ invokeOnEDTUncheckedException(() -> logArea.setText(text)); ++ } ++ + public static final class Builder { + private String title; + private String instructions; +@@ -1046,6 +1111,8 @@ public final class PassFailJFrame { + private int rows; + private int columns; + private boolean screenCapture; ++ private boolean addLogArea; ++ private int logAreaRows = 10; + + private List testWindows; + private WindowListCreator windowListCreator; +@@ -1087,6 +1154,37 @@ public final class PassFailJFrame { + return this; + } + ++ /** ++ * Adds a log area below the "Pass", "Fail" buttons. ++ *

    ++ * The log area can be controlled by {@link #log(String)}, ++ * {@link #logClear()} and {@link #logSet(String)}. ++ * ++ * @return this builder ++ */ ++ public Builder logArea() { ++ this.addLogArea = true; ++ return this; ++ } ++ ++ /** ++ * Adds a log area below the "Pass", "Fail" buttons. ++ *

    ++ * The log area can be controlled by {@link #log(String)}, ++ * {@link #logClear()} and {@link #logSet(String)}. ++ *

    ++ * The number of columns is taken from the number of ++ * columns in the instructional JTextArea. ++ * ++ * @param rows of the log area ++ * @return this builder ++ */ ++ public Builder logArea(int rows) { ++ this.addLogArea = true; ++ this.logAreaRows = rows; ++ return this; ++ } ++ + /** + * Adds a {@code WindowCreator} which the framework will use + * to create the test UI window. +diff --git a/test/jdk/java/lang/invoke/PrivateInvokeTest.java b/test/jdk/java/lang/invoke/PrivateInvokeTest.java +index 12edf8e32..8ae78d967 100644 +--- a/test/jdk/java/lang/invoke/PrivateInvokeTest.java ++++ b/test/jdk/java/lang/invoke/PrivateInvokeTest.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2009, 2024, 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 +@@ -67,8 +67,6 @@ public class PrivateInvokeTest { + String vstr = System.getProperty(THIS_CLASS.getSimpleName()+".verbose"); + if (vstr == null) + vstr = System.getProperty(THIS_CLASS.getName()+".verbose"); +- if (vstr == null) +- vstr = System.getProperty("test.verbose"); + if (vstr != null) verbose = Integer.parseInt(vstr); + } + private static int referenceKind(Method m) { +diff --git a/test/jdk/java/net/CookieHandler/B6644726.java b/test/jdk/java/net/CookieHandler/B6644726.java +index b1caa182d..cc31f64c1 100644 +--- a/test/jdk/java/net/CookieHandler/B6644726.java ++++ b/test/jdk/java/net/CookieHandler/B6644726.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -46,8 +46,8 @@ public class B6644726 { + // Let's test the default path + lst.add("myCookie1=foo"); + // Then some alternate expires format +- lst.add("myCookie2=bar; path=/dir; expires=Tue, 19 Aug 2025 16:00:00 GMT"); +- lst.add("myCookie3=test; path=/dir; expires=Tue Aug 19 2025 16:00:00 GMT-0100"); ++ lst.add("myCookie2=bar; path=/dir; expires=Fri, 19 Aug 4242 16:00:00 GMT"); ++ lst.add("myCookie3=test; path=/dir; expires=Fri Aug 19 4242 16:00:00 GMT-0100"); + // Then Netscape draft cookies and domains + lst.add("myCookie4=test; domain=.sun.com; path=/dir/foo"); + HashMap> map = new HashMap>(); +@@ -64,7 +64,8 @@ public class B6644726 { + List cookies = cs.getCookies(); + // There should be 5 cookies if all dates parsed correctly + if (cookies.size() != 5) { +- fail("Should have 5 cookies. Got only "+ cookies.size() + ", expires probably didn't parse correctly"); ++ fail("unexpected cookies: " + cookies + ", should have 5 cookies. Got only " ++ + cookies.size() + ", expires probably didn't parse correctly"); + } + // Check Path for first Cookie + for (HttpCookie c : cookies) { +diff --git a/test/jdk/java/net/Socket/B8312065.java b/test/jdk/java/net/Socket/B8312065.java +index 272e53c8c..57ba99b10 100644 +--- a/test/jdk/java/net/Socket/B8312065.java ++++ b/test/jdk/java/net/Socket/B8312065.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2023, Alibaba Group Holding Limited. All Rights Reserved. ++ * Copyright (c) 2023, 2025, Alibaba Group Holding Limited. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -26,6 +26,8 @@ + * @bug 8312065 + * @summary Socket.connect does not timeout as expected when profiling (i.e. keep receiving signal) + * @requires (os.family != "windows") ++ * @library /test/lib ++ * @build jtreg.SkippedException + * @compile NativeThread.java + * @run main/othervm/native/timeout=120 B8312065 + */ +@@ -37,6 +39,8 @@ import java.net.Socket; + import java.net.SocketTimeoutException; + import java.util.concurrent.TimeUnit; + ++import jtreg.SkippedException; ++ + public class B8312065 { + public static void main(String[] args) throws Exception { + System.loadLibrary("NativeThread"); +@@ -83,6 +87,8 @@ public class B8312065 { + System.out.println("Test FAILED: duration " + duration + " ms, expected >= " + timeoutMillis + " ms"); + System.exit(1); + } ++ } catch (java.net.ConnectException e) { ++ throw new SkippedException("Network setup issue, skip this test", e); + } + } + } +diff --git a/test/jdk/java/net/httpclient/DigestEchoClient.java b/test/jdk/java/net/httpclient/DigestEchoClient.java +index a3321dc3b..53b945d70 100644 +--- a/test/jdk/java/net/httpclient/DigestEchoClient.java ++++ b/test/jdk/java/net/httpclient/DigestEchoClient.java +@@ -264,8 +264,9 @@ public class DigestEchoClient { + } + try { + for (DigestEchoServer.HttpAuthType authType : types) { +- // The test server does not support PROXY305 properly +- if (authType == DigestEchoServer.HttpAuthType.PROXY305) continue; ++ // The test server does not support PROXY305 or SERVER307 properly ++ if (authType == DigestEchoServer.HttpAuthType.PROXY305 || ++ authType == DigestEchoServer.HttpAuthType.SERVER307) continue; + EnumSet basics = + EnumSet.of(DigestEchoServer.HttpAuthSchemeType.BASICSERVER, + DigestEchoServer.HttpAuthSchemeType.BASIC); +diff --git a/test/jdk/java/net/httpclient/HttpRedirectTest.java b/test/jdk/java/net/httpclient/HttpRedirectTest.java +new file mode 100644 +index 000000000..34ec95f77 +--- /dev/null ++++ b/test/jdk/java/net/httpclient/HttpRedirectTest.java +@@ -0,0 +1,457 @@ +/* -+ * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2022, Loongson Technology. All rights reserved. ++ * Copyright (c) 2019, 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 @@ -119609,269 +205961,1522 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.internal.vm.ci/sha + * or visit www.oracle.com if you need additional information or have any + * questions. + */ ++import com.sun.net.httpserver.HttpServer; ++import com.sun.net.httpserver.HttpsConfigurator; ++import com.sun.net.httpserver.HttpsServer; ++import jdk.test.lib.net.SimpleSSLContext; ++import org.testng.annotations.BeforeClass; ++import org.testng.annotations.AfterClass; ++import org.testng.annotations.DataProvider; ++import org.testng.annotations.Test; ++import static org.testng.Assert.*; ++ ++import javax.net.ssl.SSLContext; ++import java.io.IOException; ++import java.io.InputStream; ++import java.io.OutputStream; ++import java.net.InetAddress; ++import java.net.InetSocketAddress; ++import java.net.Proxy; ++import java.net.ProxySelector; ++import java.net.SocketAddress; ++import java.net.URI; ++import java.net.URISyntaxException; ++import java.net.http.HttpClient; ++import java.net.http.HttpRequest; ++import java.net.http.HttpResponse; ++import java.nio.charset.StandardCharsets; ++import java.util.List; ++import java.util.Map; ++import java.util.Random; ++import java.util.Set; ++import java.util.concurrent.CompletableFuture; ++import java.util.concurrent.CopyOnWriteArrayList; ++import java.util.concurrent.CopyOnWriteArraySet; ++import java.util.concurrent.ExecutorService; ++import java.util.concurrent.LinkedBlockingQueue; ++import java.util.concurrent.ThreadPoolExecutor; ++import java.util.concurrent.TimeUnit; ++import java.util.concurrent.atomic.AtomicLong; + +/** -+ * The LoongArch64 HotSpot specific portions of the JVMCI API. -+ */ -+package jdk.vm.ci.hotspot.loongarch64; -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.loongarch64/src/jdk/vm/ci/loongarch64/LoongArch64.java jdk11u-ls/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.loongarch64/src/jdk/vm/ci/loongarch64/LoongArch64.java ---- openjdk/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.loongarch64/src/jdk/vm/ci/loongarch64/LoongArch64.java 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.loongarch64/src/jdk/vm/ci/loongarch64/LoongArch64.java 2023-09-12 13:54:26.513575962 +0800 -@@ -0,0 +1,247 @@ -+/* -+ * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2022, Loongson Technology. 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. ++ * @test ++ * @bug 8232625 ++ * @summary This test verifies that the HttpClient works correctly when redirecting a post request. ++ * @library /test/lib http2/server ++ * @build jdk.test.lib.net.SimpleSSLContext HttpServerAdapters DigestEchoServer HttpRedirectTest ++ * @modules java.net.http/jdk.internal.net.http.common ++ * java.net.http/jdk.internal.net.http.frame ++ * java.net.http/jdk.internal.net.http.hpack ++ * java.logging ++ * java.base/sun.net.www.http ++ * java.base/sun.net.www ++ * java.base/sun.net ++ * @run testng/othervm -Dtest.requiresHost=true ++ * -Djdk.httpclient.HttpClient.log=headers ++ * -Djdk.internal.httpclient.debug=false ++ * HttpRedirectTest + * -+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -+ * or visit www.oracle.com if you need additional information or have any -+ * questions. + */ -+package jdk.vm.ci.loongarch64; ++public class HttpRedirectTest implements HttpServerAdapters { ++ static final String GET_RESPONSE_BODY = "Lorem ipsum dolor sit amet"; ++ static final String REQUEST_BODY = "Here it goes"; ++ static final SSLContext context; ++ static { ++ try { ++ context = new SimpleSSLContext().get(); ++ SSLContext.setDefault(context); ++ } catch (Exception x) { ++ throw new ExceptionInInitializerError(x); ++ } ++ } + -+import java.nio.ByteOrder; -+import java.util.EnumSet; ++ final AtomicLong requestCounter = new AtomicLong(); ++ final AtomicLong responseCounter = new AtomicLong(); ++ HttpTestServer http1Server; ++ HttpTestServer http2Server; ++ HttpTestServer https1Server; ++ HttpTestServer https2Server; ++ DigestEchoServer.TunnelingProxy proxy; ++ ++ URI http1URI; ++ URI https1URI; ++ URI http2URI; ++ URI https2URI; ++ InetSocketAddress proxyAddress; ++ ProxySelector proxySelector; ++ HttpClient client; ++ List> futures = new CopyOnWriteArrayList<>(); ++ Set pending = new CopyOnWriteArraySet<>(); ++ ++ final ExecutorService executor = new ThreadPoolExecutor(12, 60, 10, ++ TimeUnit.SECONDS, new LinkedBlockingQueue<>()); // Shared by HTTP/1.1 servers ++ final ExecutorService clientexec = new ThreadPoolExecutor(6, 12, 1, ++ TimeUnit.SECONDS, new LinkedBlockingQueue<>()); // Used by the client ++ ++ public HttpClient newHttpClient(ProxySelector ps) { ++ HttpClient.Builder builder = HttpClient ++ .newBuilder() ++ .sslContext(context) ++ .executor(clientexec) ++ .followRedirects(HttpClient.Redirect.ALWAYS) ++ .proxy(ps); ++ return builder.build(); ++ } ++ ++ @DataProvider(name="uris") ++ Object[][] testURIs() throws URISyntaxException { ++ List uris = List.of( ++ http1URI.resolve("direct/orig/"), ++ https1URI.resolve("direct/orig/"), ++ https1URI.resolve("proxy/orig/"), ++ http2URI.resolve("direct/orig/"), ++ https2URI.resolve("direct/orig/"), ++ https2URI.resolve("proxy/orig/")); ++ List> redirects = List.of( ++ Map.entry(301, "GET"), ++ Map.entry(308, "POST"), ++ Map.entry(302, "GET"), ++ Map.entry(303, "GET"), ++ Map.entry(307, "POST"), ++ Map.entry(300, "DO_NOT_FOLLOW"), ++ Map.entry(304, "DO_NOT_FOLLOW"), ++ Map.entry(305, "DO_NOT_FOLLOW"), ++ Map.entry(306, "DO_NOT_FOLLOW"), ++ Map.entry(309, "DO_NOT_FOLLOW"), ++ Map.entry(new Random().nextInt(90) + 310, "DO_NOT_FOLLOW") ++ ); ++ Object[][] tests = new Object[redirects.size() * uris.size()][3]; ++ int count = 0; ++ for (int i=0; i < uris.size(); i++) { ++ URI u = uris.get(i); ++ for (int j=0; j < redirects.size() ; j++) { ++ int code = redirects.get(j).getKey(); ++ String m = redirects.get(j).getValue(); ++ tests[count][0] = u.resolve(code +"/"); ++ tests[count][1] = code; ++ tests[count][2] = m; ++ count++; ++ } ++ } ++ return tests; ++ } ++ ++ @BeforeClass ++ public void setUp() throws Exception { ++ try { ++ InetSocketAddress sa = new InetSocketAddress(InetAddress.getLoopbackAddress(), 0); ++ ++ // HTTP/1.1 ++ HttpServer server1 = HttpServer.create(sa, 0); ++ server1.setExecutor(executor); ++ http1Server = HttpTestServer.of(server1); ++ http1Server.addHandler(new HttpTestRedirectHandler("http", http1Server), ++ "/HttpRedirectTest/http1/"); ++ http1Server.start(); ++ http1URI = new URI("http://" + http1Server.serverAuthority() + "/HttpRedirectTest/http1/"); ++ ++ ++ // HTTPS/1.1 ++ HttpsServer sserver1 = HttpsServer.create(sa, 100); ++ sserver1.setExecutor(executor); ++ sserver1.setHttpsConfigurator(new HttpsConfigurator(context)); ++ https1Server = HttpTestServer.of(sserver1); ++ https1Server.addHandler(new HttpTestRedirectHandler("https", https1Server), ++ "/HttpRedirectTest/https1/"); ++ https1Server.start(); ++ https1URI = new URI("https://" + https1Server.serverAuthority() + "/HttpRedirectTest/https1/"); ++ ++ // HTTP/2.0 ++ http2Server = HttpTestServer.of( ++ new Http2TestServer("localhost", false, 0)); ++ http2Server.addHandler(new HttpTestRedirectHandler("http", http2Server), ++ "/HttpRedirectTest/http2/"); ++ http2Server.start(); ++ http2URI = new URI("http://" + http2Server.serverAuthority() + "/HttpRedirectTest/http2/"); ++ ++ // HTTPS/2.0 ++ https2Server = HttpTestServer.of( ++ new Http2TestServer("localhost", true, 0)); ++ https2Server.addHandler(new HttpTestRedirectHandler("https", https2Server), ++ "/HttpRedirectTest/https2/"); ++ https2Server.start(); ++ https2URI = new URI("https://" + https2Server.serverAuthority() + "/HttpRedirectTest/https2/"); ++ ++ proxy = DigestEchoServer.createHttpsProxyTunnel( ++ DigestEchoServer.HttpAuthSchemeType.NONE); ++ proxyAddress = proxy.getProxyAddress(); ++ proxySelector = new HttpProxySelector(proxyAddress); ++ client = newHttpClient(proxySelector); ++ System.out.println("Setup: done"); ++ } catch (Exception x) { ++ tearDown(); throw x; ++ } catch (Error e) { ++ tearDown(); throw e; ++ } ++ } + -+import jdk.vm.ci.code.Architecture; -+import jdk.vm.ci.code.Register; -+import jdk.vm.ci.code.Register.RegisterCategory; -+import jdk.vm.ci.code.RegisterArray; -+import jdk.vm.ci.meta.JavaKind; -+import jdk.vm.ci.meta.PlatformKind; ++ private void testNonIdempotent(URI u, HttpRequest request, ++ int code, String method) throws Exception { ++ System.out.println("Testing with " + u); ++ CompletableFuture> respCf = ++ client.sendAsync(request, HttpResponse.BodyHandlers.ofString()); ++ HttpResponse resp = respCf.join(); ++ if (method.equals("DO_NOT_FOLLOW")) { ++ assertEquals(resp.statusCode(), code, u + ": status code"); ++ } else { ++ assertEquals(resp.statusCode(), 200, u + ": status code"); ++ } ++ if (method.equals("POST")) { ++ assertEquals(resp.body(), REQUEST_BODY, u + ": body"); ++ } else if (code == 304) { ++ assertEquals(resp.body(), "", u + ": body"); ++ } else if (method.equals("DO_NOT_FOLLOW")) { ++ assertNotEquals(resp.body(), GET_RESPONSE_BODY, u + ": body"); ++ assertNotEquals(resp.body(), REQUEST_BODY, u + ": body"); ++ } else { ++ assertEquals(resp.body(), GET_RESPONSE_BODY, u + ": body"); ++ } ++ } + -+/** -+ * Represents the LoongArch64 architecture. -+ */ -+public class LoongArch64 extends Architecture { ++ public void testIdempotent(URI u, HttpRequest request, ++ int code, String method) throws Exception { ++ CompletableFuture> respCf = ++ client.sendAsync(request, HttpResponse.BodyHandlers.ofString()); ++ HttpResponse resp = respCf.join(); ++ if (method.equals("DO_NOT_FOLLOW")) { ++ assertEquals(resp.statusCode(), code, u + ": status code"); ++ } else { ++ assertEquals(resp.statusCode(), 200, u + ": status code"); ++ } ++ if (method.equals("POST")) { ++ assertEquals(resp.body(), REQUEST_BODY, u + ": body"); ++ } else if (code == 304) { ++ assertEquals(resp.body(), "", u + ": body"); ++ } else if (method.equals("DO_NOT_FOLLOW")) { ++ assertNotEquals(resp.body(), GET_RESPONSE_BODY, u + ": body"); ++ assertNotEquals(resp.body(), REQUEST_BODY, u + ": body"); ++ } else if (code == 303) { ++ assertEquals(resp.body(), GET_RESPONSE_BODY, u + ": body"); ++ } else { ++ assertEquals(resp.body(), REQUEST_BODY, u + ": body"); ++ } ++ } + -+ public static final RegisterCategory CPU = new RegisterCategory("CPU"); ++ @Test(dataProvider = "uris") ++ public void testPOST(URI uri, int code, String method) throws Exception { ++ URI u = uri.resolve("foo?n=" + requestCounter.incrementAndGet()); ++ HttpRequest request = HttpRequest.newBuilder(u) ++ .POST(HttpRequest.BodyPublishers.ofString(REQUEST_BODY)).build(); ++ // POST is not considered idempotent. ++ testNonIdempotent(u, request, code, method); ++ } ++ ++ @Test(dataProvider = "uris") ++ public void testPUT(URI uri, int code, String method) throws Exception { ++ URI u = uri.resolve("foo?n=" + requestCounter.incrementAndGet()); ++ System.out.println("Testing with " + u); ++ HttpRequest request = HttpRequest.newBuilder(u) ++ .PUT(HttpRequest.BodyPublishers.ofString(REQUEST_BODY)).build(); ++ // PUT is considered idempotent. ++ testIdempotent(u, request, code, method); ++ } ++ ++ @Test(dataProvider = "uris") ++ public void testFoo(URI uri, int code, String method) throws Exception { ++ URI u = uri.resolve("foo?n=" + requestCounter.incrementAndGet()); ++ System.out.println("Testing with " + u); ++ HttpRequest request = HttpRequest.newBuilder(u) ++ .method("FOO", ++ HttpRequest.BodyPublishers.ofString(REQUEST_BODY)).build(); ++ // FOO is considered idempotent. ++ testIdempotent(u, request, code, method); ++ } ++ ++ @Test(dataProvider = "uris") ++ public void testGet(URI uri, int code, String method) throws Exception { ++ URI u = uri.resolve("foo?n=" + requestCounter.incrementAndGet()); ++ System.out.println("Testing with " + u); ++ HttpRequest request = HttpRequest.newBuilder(u) ++ .method("GET", ++ HttpRequest.BodyPublishers.ofString(REQUEST_BODY)).build(); ++ CompletableFuture> respCf = ++ client.sendAsync(request, HttpResponse.BodyHandlers.ofString()); ++ HttpResponse resp = respCf.join(); ++ // body will be preserved except for 304 and 303: this is a GET. ++ if (method.equals("DO_NOT_FOLLOW")) { ++ assertEquals(resp.statusCode(), code, u + ": status code"); ++ } else { ++ assertEquals(resp.statusCode(), 200, u + ": status code"); ++ } ++ if (code == 304) { ++ assertEquals(resp.body(), "", u + ": body"); ++ } else if (method.equals("DO_NOT_FOLLOW")) { ++ assertNotEquals(resp.body(), GET_RESPONSE_BODY, u + ": body"); ++ assertNotEquals(resp.body(), REQUEST_BODY, u + ": body"); ++ } else if (code == 303) { ++ assertEquals(resp.body(), GET_RESPONSE_BODY, u + ": body"); ++ } else { ++ assertEquals(resp.body(), REQUEST_BODY, u + ": body"); ++ } ++ } + -+ // General purpose CPU registers -+ public static final Register zero = new Register(0, 0, "r0", CPU); -+ public static final Register ra = new Register(1, 1, "r1", CPU); -+ public static final Register tp = new Register(2, 2, "r2", CPU); -+ public static final Register sp = new Register(3, 3, "r3", CPU); -+ public static final Register a0 = new Register(4, 4, "r4", CPU); -+ public static final Register a1 = new Register(5, 5, "r5", CPU); -+ public static final Register a2 = new Register(6, 6, "r6", CPU); -+ public static final Register a3 = new Register(7, 7, "r7", CPU); -+ public static final Register a4 = new Register(8, 8, "r8", CPU); -+ public static final Register a5 = new Register(9, 9, "r9", CPU); -+ public static final Register a6 = new Register(10, 10, "r10", CPU); -+ public static final Register a7 = new Register(11, 11, "r11", CPU); -+ public static final Register t0 = new Register(12, 12, "r12", CPU); -+ public static final Register t1 = new Register(13, 13, "r13", CPU); -+ public static final Register t2 = new Register(14, 14, "r14", CPU); -+ public static final Register t3 = new Register(15, 15, "r15", CPU); -+ public static final Register t4 = new Register(16, 16, "r16", CPU); -+ public static final Register t5 = new Register(17, 17, "r17", CPU); -+ public static final Register t6 = new Register(18, 18, "r18", CPU); -+ public static final Register t7 = new Register(19, 19, "r19", CPU); -+ public static final Register t8 = new Register(20, 20, "r20", CPU); -+ public static final Register rx = new Register(21, 21, "r21", CPU); -+ public static final Register fp = new Register(22, 22, "r22", CPU); -+ public static final Register s0 = new Register(23, 23, "r23", CPU); -+ public static final Register s1 = new Register(24, 24, "r24", CPU); -+ public static final Register s2 = new Register(25, 25, "r25", CPU); -+ public static final Register s3 = new Register(26, 26, "r26", CPU); -+ public static final Register s4 = new Register(27, 27, "r27", CPU); -+ public static final Register s5 = new Register(28, 28, "r28", CPU); -+ public static final Register s6 = new Register(29, 29, "r29", CPU); -+ public static final Register s7 = new Register(30, 30, "r30", CPU); -+ public static final Register s8 = new Register(31, 31, "r31", CPU); ++ @AfterClass ++ public void tearDown() { ++ proxy = stop(proxy, DigestEchoServer.TunnelingProxy::stop); ++ http1Server = stop(http1Server, HttpTestServer::stop); ++ https1Server = stop(https1Server, HttpTestServer::stop); ++ http2Server = stop(http2Server, HttpTestServer::stop); ++ https2Server = stop(https2Server, HttpTestServer::stop); ++ client = null; ++ try { ++ executor.awaitTermination(2000, TimeUnit.MILLISECONDS); ++ } catch (Throwable x) { ++ } finally { ++ executor.shutdownNow(); ++ } ++ try { ++ clientexec.awaitTermination(2000, TimeUnit.MILLISECONDS); ++ } catch (Throwable x) { ++ } finally { ++ clientexec.shutdownNow(); ++ } ++ System.out.println("Teardown: done"); ++ } + -+ public static final Register SCR1 = t7; -+ public static final Register SCR2 = t4; -+ public static final Register v0 = a0; ++ private interface Stoppable { public void stop(T service) throws Exception; } + -+ // @formatter:off -+ public static final RegisterArray cpuRegisters = new RegisterArray( -+ zero, ra, tp, sp, a0, a1, a2, a3, -+ a4, a5, a6, a7, t0, t1, t2, t3, -+ t4, t5, t6, t7, t8, rx, fp, s0, -+ s1, s2, s3, s4, s5, s6, s7, s8 -+ ); -+ // @formatter:on ++ static T stop(T service, Stoppable stop) { ++ try { if (service != null) stop.stop(service); } catch (Throwable x) { }; ++ return null; ++ } + -+ public static final RegisterCategory SIMD = new RegisterCategory("SIMD"); ++ static class HttpProxySelector extends ProxySelector { ++ private static final List NO_PROXY = List.of(Proxy.NO_PROXY); ++ private final List proxyList; ++ HttpProxySelector(InetSocketAddress proxyAddress) { ++ proxyList = List.of(new Proxy(Proxy.Type.HTTP, proxyAddress)); ++ } + -+ // Simd registers -+ public static final Register f0 = new Register(32, 0, "f0", SIMD); -+ public static final Register f1 = new Register(33, 1, "f1", SIMD); -+ public static final Register f2 = new Register(34, 2, "f2", SIMD); -+ public static final Register f3 = new Register(35, 3, "f3", SIMD); -+ public static final Register f4 = new Register(36, 4, "f4", SIMD); -+ public static final Register f5 = new Register(37, 5, "f5", SIMD); -+ public static final Register f6 = new Register(38, 6, "f6", SIMD); -+ public static final Register f7 = new Register(39, 7, "f7", SIMD); -+ public static final Register f8 = new Register(40, 8, "f8", SIMD); -+ public static final Register f9 = new Register(41, 9, "f9", SIMD); -+ public static final Register f10 = new Register(42, 10, "f10", SIMD); -+ public static final Register f11 = new Register(43, 11, "f11", SIMD); -+ public static final Register f12 = new Register(44, 12, "f12", SIMD); -+ public static final Register f13 = new Register(45, 13, "f13", SIMD); -+ public static final Register f14 = new Register(46, 14, "f14", SIMD); -+ public static final Register f15 = new Register(47, 15, "f15", SIMD); -+ public static final Register f16 = new Register(48, 16, "f16", SIMD); -+ public static final Register f17 = new Register(49, 17, "f17", SIMD); -+ public static final Register f18 = new Register(50, 18, "f18", SIMD); -+ public static final Register f19 = new Register(51, 19, "f19", SIMD); -+ public static final Register f20 = new Register(52, 20, "f20", SIMD); -+ public static final Register f21 = new Register(53, 21, "f21", SIMD); -+ public static final Register f22 = new Register(54, 22, "f22", SIMD); -+ public static final Register f23 = new Register(55, 23, "f23", SIMD); -+ public static final Register f24 = new Register(56, 24, "f24", SIMD); -+ public static final Register f25 = new Register(57, 25, "f25", SIMD); -+ public static final Register f26 = new Register(58, 26, "f26", SIMD); -+ public static final Register f27 = new Register(59, 27, "f27", SIMD); -+ public static final Register f28 = new Register(60, 28, "f28", SIMD); -+ public static final Register f29 = new Register(61, 29, "f29", SIMD); -+ public static final Register f30 = new Register(62, 30, "f30", SIMD); -+ public static final Register f31 = new Register(63, 31, "f31", SIMD); ++ @Override ++ public List select(URI uri) { ++ // our proxy only supports tunneling ++ if (uri.getScheme().equalsIgnoreCase("https")) { ++ if (uri.getPath().contains("/proxy/")) { ++ return proxyList; ++ } ++ } ++ return NO_PROXY; ++ } + -+ public static final Register fv0 = f0; ++ @Override ++ public void connectFailed(URI uri, SocketAddress sa, IOException ioe) { ++ System.err.println("Connection to proxy failed: " + ioe); ++ System.err.println("Proxy: " + sa); ++ System.err.println("\tURI: " + uri); ++ ioe.printStackTrace(); ++ } ++ } + -+ // @formatter:off -+ public static final RegisterArray simdRegisters = new RegisterArray( -+ f0, f1, f2, f3, f4, f5, f6, f7, -+ f8, f9, f10, f11, f12, f13, f14, f15, -+ f16, f17, f18, f19, f20, f21, f22, f23, -+ f24, f25, f26, f27, f28, f29, f30, f31 -+ ); -+ // @formatter:on ++ public static class HttpTestRedirectHandler implements HttpTestHandler { ++ static final AtomicLong respCounter = new AtomicLong(); ++ final String scheme; ++ final HttpTestServer server; ++ HttpTestRedirectHandler(String scheme, HttpTestServer server) { ++ this.scheme = scheme; ++ this.server = server; ++ } ++ ++ @Override ++ public void handle(HttpTestExchange t) throws IOException { ++ try (InputStream is = t.getRequestBody()) { ++ byte[] bytes = is.readAllBytes(); ++ URI u = t.getRequestURI(); ++ long responseID = Long.parseLong(u.getQuery().substring(2)); ++ String path = u.getPath(); ++ int i = path.lastIndexOf('/'); ++ String file = path.substring(i+1); ++ String parent = path.substring(0, i); ++ int code = 200; ++ if (file.equals("foo")) { ++ i = parent.lastIndexOf("/"); ++ code = Integer.parseInt(parent.substring(i+1)); ++ } ++ String response; ++ if (code == 200) { ++ if (t.getRequestMethod().equals("GET")) { ++ if (bytes.length == 0) { ++ response = GET_RESPONSE_BODY; ++ } else { ++ response = new String(bytes, StandardCharsets.UTF_8); ++ } ++ } else if (t.getRequestMethod().equals("POST")) { ++ response = new String(bytes, StandardCharsets.UTF_8); ++ } else { ++ response = new String(bytes, StandardCharsets.UTF_8); ++ } ++ } else if (code < 300 || code > 399) { ++ response = "Unexpected code: " + code; ++ code = 400; ++ } else { ++ try { ++ URI reloc = new URI(scheme, server.serverAuthority(), parent + "/bar", u.getQuery(), null); ++ t.getResponseHeaders().addHeader("Location", reloc.toASCIIString()); ++ if (code != 304) { ++ response = "Code: " + code; ++ } else response = null; ++ } catch (URISyntaxException x) { ++ x.printStackTrace(); ++ x.printStackTrace(System.out); ++ code = 400; ++ response = x.toString(); ++ } ++ } ++ ++ System.out.println("Server " + t.getRequestURI() + " sending response " + responseID); ++ System.out.println("code: " + code + " body: " + response); ++ t.sendResponseHeaders(code, code == 304 ? 0: -1); ++ if (code != 304) { ++ try (OutputStream os = t.getResponseBody()) { ++ bytes = response.getBytes(StandardCharsets.UTF_8); ++ os.write(bytes); ++ os.flush(); ++ } ++ } else { ++ bytes = new byte[0]; ++ } ++ ++ System.out.println("\tresp:" + responseID + ": wrote " + bytes.length + " bytes"); ++ } catch (Throwable e) { ++ e.printStackTrace(); ++ e.printStackTrace(System.out); ++ throw e; ++ } ++ } ++ } ++ ++} +diff --git a/test/jdk/java/net/httpclient/http2/RedirectTest.java b/test/jdk/java/net/httpclient/http2/RedirectTest.java +index bf8865029..b51c4df42 100644 +--- a/test/jdk/java/net/httpclient/http2/RedirectTest.java ++++ b/test/jdk/java/net/httpclient/http2/RedirectTest.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2015, 2019, 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 +@@ -87,6 +87,11 @@ public class RedirectTest { + } + } + ++ @Override ++ protected int redirectCode() { ++ return 308; // we need to use a code that preserves the body ++ } ++ + public synchronized boolean error() { + return error; + } +diff --git a/test/jdk/java/net/httpclient/http2/server/Http2RedirectHandler.java b/test/jdk/java/net/httpclient/http2/server/Http2RedirectHandler.java +index 42d269de8..97ea94b7b 100644 +--- a/test/jdk/java/net/httpclient/http2/server/Http2RedirectHandler.java ++++ b/test/jdk/java/net/httpclient/http2/server/Http2RedirectHandler.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -42,11 +42,11 @@ public class Http2RedirectHandler implements Http2Handler { + is.readAllBytes(); + String location = supplier.get(); + System.err.printf("RedirectHandler request to %s from %s\n", +- t.getRequestURI().toString(), t.getRemoteAddress().toString()); ++ t.getRequestURI().toString(), t.getRemoteAddress().toString()); + System.err.println("Redirecting to: " + location); + HttpHeadersBuilder headersBuilder = t.getResponseHeaders(); + headersBuilder.addHeader("Location", location); +- t.sendResponseHeaders(301, 1024); ++ t.sendResponseHeaders(redirectCode(), 1024); + byte[] bb = new byte[1024]; + OutputStream os = t.getResponseBody(); + os.write(bb); +@@ -55,6 +55,10 @@ public class Http2RedirectHandler implements Http2Handler { + } + } + ++ protected int redirectCode() { ++ return 301; ++ } ++ + // override in sub-class to examine the exchange, but don't + // alter transaction state by reading the request body etc. + protected void examineExchange(Http2TestExchange t) { +diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/SubscriberWhiteboxVerification.java b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/SubscriberWhiteboxVerification.java +index 10874f00f..5f07ae2cc 100644 +--- a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/SubscriberWhiteboxVerification.java ++++ b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/SubscriberWhiteboxVerification.java +@@ -278,8 +278,9 @@ public abstract class SubscriberWhiteboxVerification extends WithHelperPublis + @Override + public void run(WhiteboxTestStage stage) throws InterruptedException { + stage.puppet().triggerRequest(1); +- stage.puppet().signalCancel(); + stage.expectRequest(); ++ stage.puppet().signalCancel(); ++ stage.expectCancelling(); + stage.signalNext(); + + stage.puppet().triggerRequest(1); +@@ -824,11 +825,17 @@ public abstract class SubscriberWhiteboxVerification extends WithHelperPublis + * Before sending any element to the subscriber, the TCK must wait for the subscriber to request that element, and + * must be prepared for the subscriber to only request one element at a time, it is not enough for the TCK to + * simply invoke this method before sending elements. ++ *

    ++ * An invocation of {@link #signalCancel()} may be coalesced into any elements that have not yet been requested, ++ * such that only a cancel signal is emitted. + */ + void triggerRequest(long elements); + + /** +- * Trigger {@code cancel()} on your {@link Subscriber} ++ * Trigger {@code cancel()} on your {@link Subscriber}. ++ *

    ++ * An invocation of this method may be coalesced into any outstanding requests, as requested by ++ *{@link #triggerRequest(long)}, such that only a cancel signal is emitted. + */ + void signalCancel(); + } +diff --git a/test/jdk/java/nio/channels/DatagramChannel/StressNativeSignal.java b/test/jdk/java/nio/channels/DatagramChannel/StressNativeSignal.java +index b21d68ab1..d6d2f083e 100644 +--- a/test/jdk/java/nio/channels/DatagramChannel/StressNativeSignal.java ++++ b/test/jdk/java/nio/channels/DatagramChannel/StressNativeSignal.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -26,68 +26,111 @@ + * @summary Attempt to provoke error 316 on OS X in NativeSignal.signal() + */ + +-import java.io.*; +-import java.net.*; ++import java.io.IOException; ++import java.net.InetSocketAddress; ++import java.net.ServerSocket; ++import java.net.Socket; ++import java.net.StandardSocketOptions; + import java.nio.ByteBuffer; + import java.nio.channels.DatagramChannel; ++import java.util.concurrent.CountDownLatch; + + public class StressNativeSignal { + private UDPThread udpThread; + private ServerSocketThread serverSocketThread; + + StressNativeSignal() { +- try { +- serverSocketThread = new ServerSocketThread(); ++ serverSocketThread = initServerSocketThread(); ++ if (serverSocketThread != null) { + serverSocketThread.start(); ++ } + +- udpThread = new UDPThread(); ++ udpThread = initUDPThread(); ++ if (udpThread != null) { + udpThread.start(); ++ } ++ } ++ ++ private UDPThread initUDPThread() { ++ UDPThread aUDPThread = null; ++ try { ++ aUDPThread = new UDPThread(); + } catch (Exception z) { ++ System.err.println("failed to create and start a UDPThread"); + z.printStackTrace(); + } ++ return aUDPThread; + } + +- public static void main(String[] args) throws Throwable { +- StressNativeSignal test = new StressNativeSignal(); ++ private ServerSocketThread initServerSocketThread() { ++ ServerSocketThread aServerSocketThread = null; + try { +- Thread.sleep(3000); ++ aServerSocketThread = new ServerSocketThread(); ++ + } catch (Exception z) { +- z.printStackTrace(System.err); ++ System.err.println("failed to create and start a ServerSocketThread"); ++ z.printStackTrace(); + } ++ return aServerSocketThread; ++ } + ++ public static void main(String[] args) throws Throwable { ++ StressNativeSignal test = new StressNativeSignal(); ++ test.waitForTestThreadsToStart(); + test.shutdown(); + } + + public void shutdown() { +- udpThread.terminate(); +- try { +- udpThread.join(); +- } catch (Exception z) { +- z.printStackTrace(System.err); ++ if ((udpThread != null) && udpThread.isAlive()) { ++ udpThread.terminate(); ++ try { ++ udpThread.join(); ++ } catch (Exception z) { ++ z.printStackTrace(System.err); ++ } ++ } else { ++ System.out.println("UDPThread test scenario was not run"); + } + +- serverSocketThread.terminate(); +- try { +- serverSocketThread.join(); +- } catch (Exception z) { +- z.printStackTrace(System.err); ++ if ((serverSocketThread != null) && (serverSocketThread.isAlive())) { ++ serverSocketThread.terminate(); ++ try { ++ serverSocketThread.join(); ++ } catch (Exception z) { ++ z.printStackTrace(System.err); ++ } ++ } else { ++ System.out.println("ServerSocketThread test scenario was not run"); ++ } ++ } ++ ++ public void waitForTestThreadsToStart() { ++ if ((udpThread != null) && udpThread.isAlive()) { ++ udpThread.waitTestThreadStart(); ++ } ++ if ((serverSocketThread != null) && (serverSocketThread.isAlive())) { ++ serverSocketThread.waitTestThreadStart(); + } + } + + public class ServerSocketThread extends Thread { + private volatile boolean shouldTerminate; + private ServerSocket socket; ++ private final CountDownLatch threadStarted = new CountDownLatch(1); ++ ++ public ServerSocketThread () throws Exception { ++ socket = new ServerSocket(1122); ++ } + + public void run() { ++ + try { +- socket = new ServerSocket(1122); ++ threadStarted.countDown(); + Socket client = socket.accept(); +- BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream())); +- shouldTerminate = false; +- while (!shouldTerminate) { +- String msg = reader.readLine(); +- } ++ client.close(); ++ throw new RuntimeException("Unexpected return from accept call"); + } catch (Exception z) { ++ System.err.println("ServerSocketThread: caught exception " + z.getClass().getName()); + if (!shouldTerminate) { + z.printStackTrace(System.err); + } +@@ -103,40 +146,61 @@ public class StressNativeSignal { + // ignore + } + } ++ ++ public void waitTestThreadStart() { ++ try { ++ threadStarted.await(); ++ } catch (Exception z) { ++ z.printStackTrace(System.err); ++ // ignore ++ } ++ } + } + + public class UDPThread extends Thread { + private DatagramChannel channel; + private volatile boolean shouldTerminate; ++ private final CountDownLatch threadStarted = new CountDownLatch(1); ++ ++ public UDPThread () throws Exception { ++ ++ channel = DatagramChannel.open(); ++ channel.setOption(StandardSocketOptions.SO_RCVBUF, 6553600); ++ channel.bind(new InetSocketAddress(19870)); ++ } + + @Override + public void run() { +- try { +- channel = DatagramChannel.open(); +- channel.setOption(StandardSocketOptions.SO_RCVBUF, 6553600); +- channel.bind(new InetSocketAddress(19870)); +- } catch (IOException z) { +- z.printStackTrace(System.err); +- } + + ByteBuffer buf = ByteBuffer.allocate(6553600); +- shouldTerminate = false; +- while (!shouldTerminate) { ++ threadStarted.countDown(); ++ do { + try { + buf.rewind(); + channel.receive(buf); + } catch (IOException z) { ++ System.err.println("UDPThread: caught exception " + z.getClass().getName()); + if (!shouldTerminate) { + z.printStackTrace(System.err); + } + } +- } ++ } while (!shouldTerminate); + } + + public void terminate() { + shouldTerminate = true; + try { + channel.close(); ++ } catch (Exception z) { ++ System.err.println("UDPThread: caught exception " + z.getClass().getName()); ++ z.printStackTrace(System.err); ++ // ignore ++ } ++ } ++ ++ public void waitTestThreadStart() { ++ try { ++ threadStarted.await(); + } catch (Exception z) { + z.printStackTrace(System.err); + // ignore +diff --git a/test/jdk/java/security/testlibrary/CertificateBuilder.java b/test/jdk/java/security/testlibrary/CertificateBuilder.java +index b2c39b8ab..008c01a7f 100644 +--- a/test/jdk/java/security/testlibrary/CertificateBuilder.java ++++ b/test/jdk/java/security/testlibrary/CertificateBuilder.java +@@ -53,6 +53,7 @@ import sun.security.x509.SerialNumber; + import sun.security.x509.SubjectAlternativeNameExtension; + import sun.security.x509.URIName; + import sun.security.x509.KeyIdentifier; ++import sun.security.x509.X500Name; + + /** + * Helper class that builds and signs X.509 certificates. +@@ -89,7 +90,7 @@ import sun.security.x509.KeyIdentifier; + public class CertificateBuilder { + private final CertificateFactory factory; + +- private X500Principal subjectName = null; ++ private X500Name subjectName = null; + private BigInteger serialNumber = null; + private PublicKey publicKey = null; + private Date notBefore = null; +@@ -114,8 +115,9 @@ public class CertificateBuilder { + * @param name An {@link X500Principal} to be used as the subject name + * on this certificate. + */ +- public void setSubjectName(X500Principal name) { +- subjectName = name; ++ public CertificateBuilder setSubjectName(X500Principal name) { ++ subjectName = X500Name.asX500Name(name); ++ return this; + } + + /** +@@ -123,8 +125,25 @@ public class CertificateBuilder { + * + * @param name The subject name in RFC 2253 format + */ +- public void setSubjectName(String name) { +- subjectName = new X500Principal(name); ++ public CertificateBuilder setSubjectName(String name) { ++ try { ++ subjectName = new X500Name(name); ++ } catch (IOException ioe) { ++ throw new IllegalArgumentException(ioe); ++ } ++ return this; ++ } ++ ++ /** ++ * Set the subject name for the certificate. This method is useful when ++ * you need more control over the contents of the subject name. ++ * ++ * @param name an {@code X500Name} to be used as the subject name ++ * on this certificate ++ */ ++ public CertificateBuilder setSubjectName(X500Name name) { ++ subjectName = name; ++ return this; + } + + /** +diff --git a/test/jdk/java/text/Format/DateFormat/DateFormatRegression.java b/test/jdk/java/text/Format/DateFormat/DateFormatRegression.java +index d4230fb2c..b3cce5e8d 100644 +--- a/test/jdk/java/text/Format/DateFormat/DateFormatRegression.java ++++ b/test/jdk/java/text/Format/DateFormat/DateFormatRegression.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -1067,7 +1067,7 @@ public class DateFormatRegression extends IntlTest { + TimeZone.setDefault(TimeZone.getTimeZone("PST")); + SimpleDateFormat fmt = new SimpleDateFormat("yy/MM/dd hh:ss zzz", Locale.JAPAN); + @SuppressWarnings("deprecation") +- String result = fmt.format(new Date(1999, 0, 1)); ++ String result = fmt.format(new Date(1999 - 1900, 0, 1)); + logln("format()=>" + result); + if (!result.endsWith("PST")) { + errln("FAIL: SimpleDataFormat.format() did not retrun PST"); +diff --git a/test/jdk/java/time/tck/java/time/format/TCKLocalizedPrinterParser.java b/test/jdk/java/time/tck/java/time/format/TCKLocalizedPrinterParser.java +index 27c057599..bd9c79ddc 100644 +--- a/test/jdk/java/time/tck/java/time/format/TCKLocalizedPrinterParser.java ++++ b/test/jdk/java/time/tck/java/time/format/TCKLocalizedPrinterParser.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2012, 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 +@@ -180,7 +180,7 @@ public class TCKLocalizedPrinterParser { + @Test(dataProvider="time") + public void test_time_print(LocalTime time, FormatStyle timeStyle, int timeStyleOld, Locale locale) { + DateFormat old = DateFormat.getTimeInstance(timeStyleOld, locale); +- Date oldDate = new Date(1970, 0, 0, time.getHour(), time.getMinute(), time.getSecond()); ++ Date oldDate = new Date(1970 - 1900, 0, 0, time.getHour(), time.getMinute(), time.getSecond()); + String text = old.format(oldDate); + + DateTimeFormatter f = builder.appendLocalized(null, timeStyle).toFormatter(locale); +@@ -192,7 +192,7 @@ public class TCKLocalizedPrinterParser { + @Test(dataProvider="time") + public void test_time_parse(LocalTime time, FormatStyle timeStyle, int timeStyleOld, Locale locale) { + DateFormat old = DateFormat.getTimeInstance(timeStyleOld, locale); +- Date oldDate = new Date(1970, 0, 0, time.getHour(), time.getMinute(), time.getSecond()); ++ Date oldDate = new Date(1970 - 1900, 0, 0, time.getHour(), time.getMinute(), time.getSecond()); + String text = old.format(oldDate); + + DateTimeFormatter f = builder.appendLocalized(null, timeStyle).toFormatter(locale); +diff --git a/test/jdk/java/util/Calendar/FieldStateTest.java b/test/jdk/java/util/Calendar/FieldStateTest.java +index 34ab9e807..9fe5e7fc4 100644 +--- a/test/jdk/java/util/Calendar/FieldStateTest.java ++++ b/test/jdk/java/util/Calendar/FieldStateTest.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -147,7 +147,7 @@ public class FieldStateTest extends IntlTest { + + "Then, getTime and set week of year to 43."); + + @SuppressWarnings("deprecation") +- Date d = new Date(2003 - 1990, OCTOBER, 31); ++ Date d = new Date(2003 - 1900, OCTOBER, 31); + cal.setTime(d); + cal.set(DAY_OF_WEEK, SUNDAY); + cal.set(2003, OCTOBER, 31); // 2003/10/31 is Friday. +diff --git a/test/jdk/java/util/Currency/ISO4217-list-one.txt b/test/jdk/java/util/Currency/ISO4217-list-one.txt +index 1912b5cc7..ca4bfd6dc 100644 +--- a/test/jdk/java/util/Currency/ISO4217-list-one.txt ++++ b/test/jdk/java/util/Currency/ISO4217-list-one.txt +@@ -1,12 +1,12 @@ + # + # +-# Amendments up until ISO 4217 AMENDMENT NUMBER 177 +-# (As of 20 June 2024) ++# Amendments up until ISO 4217 AMENDMENT NUMBER 180 ++# (As of 22 September 2025) + # + + # Version + FILEVERSION=3 +-DATAVERSION=177 ++DATAVERSION=180 + + # ISO 4217 currency data + AF AFN 971 2 +@@ -44,7 +44,7 @@ BV NOK 578 2 + BR BRL 986 2 + IO USD 840 2 + BN BND 96 2 +-BG BGN 975 2 ++BG BGN 975 2 2025-12-31-22-00-00 EUR 978 2 + BF XOF 952 0 + BI BIF 108 0 + KH KHR 116 2 +@@ -69,7 +69,7 @@ CR CRC 188 2 + CI XOF 952 0 + HR EUR 978 2 + CU CUP 192 2 +-CW ANG 532 2 2025-04-01-04-00-00 XCG 532 2 ++CW XCG 532 2 + CY EUR 978 2 + CZ CZK 203 2 + DK DKK 208 2 +@@ -233,7 +233,7 @@ LK LKR 144 2 + SD SDG 938 2 + SR SRD 968 2 + SJ NOK 578 2 +-SX ANG 532 2 2025-04-01-04-00-00 XCG 532 2 ++SX XCG 532 2 + SZ SZL 748 2 + SE SEK 752 2 + CH CHF 756 2 +diff --git a/test/jdk/java/util/Currency/ValidateISO4217.java b/test/jdk/java/util/Currency/ValidateISO4217.java +index 01c225e53..24b81f895 100644 +--- a/test/jdk/java/util/Currency/ValidateISO4217.java ++++ b/test/jdk/java/util/Currency/ValidateISO4217.java +@@ -26,6 +26,7 @@ + * @bug 4691089 4819436 4942982 5104960 6544471 6627549 7066203 7195759 + * 8039317 8074350 8074351 8145952 8187946 8193552 8202026 8204269 + * 8208746 8209775 8264792 8274658 8283277 8296239 8321480 8334653 ++ * 8356096 8368308 + * @summary Validate ISO 4217 data for Currency class. + * @modules java.base/java.util:open + * jdk.localedata +@@ -86,10 +87,10 @@ public class ValidateISO4217 { + private static final Set testCurrencies = new HashSet<>(); + // Codes that are obsolete, do not have related country, extra currency + private static final String otherCodes = +- "ADP-AFA-ATS-AYM-AZM-BEF-BGL-BOV-BYB-BYR-CHE-CHW-CLF-COU-CUC-CYP-" ++ "ADP-AFA-ATS-AYM-AZM-BEF-BGL-BGN-BOV-BYB-BYR-CHE-CHW-CLF-COU-CUC-CYP-" + + "DEM-EEK-ESP-FIM-FRF-GHC-GRD-GWP-HRK-IEP-ITL-LTL-LUF-LVL-MGF-MRO-MTL-MXV-MZM-NLG-" + + "PTE-ROL-RUR-SDD-SIT-SLL-SKK-SRG-STD-TMM-TPE-TRL-VEF-UYI-USN-USS-VEB-VED-" +- + "XAG-XAU-XBA-XBB-XBC-XBD-XDR-XFO-XFU-XPD-XPT-XSU-XTS-XUA-XXX-" ++ + "XAD-XAG-XAU-XBA-XBB-XBC-XBD-XDR-XFO-XFU-XPD-XPT-XSU-XTS-XUA-XXX-" + + "YUM-ZMK-ZWD-ZWL-ZWN-ZWR"; + private static final String[][] extraCodes = { + /* Defined in ISO 4217 list, but don't have code and minor unit info. */ +diff --git a/test/jdk/java/util/Locale/LanguageSubtagRegistryTest.java b/test/jdk/java/util/Locale/LanguageSubtagRegistryTest.java +index cb3d4dde9..12f5a96d3 100644 +--- a/test/jdk/java/util/Locale/LanguageSubtagRegistryTest.java ++++ b/test/jdk/java/util/Locale/LanguageSubtagRegistryTest.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -25,9 +25,9 @@ + * @test + * @bug 8025703 8040211 8191404 8203872 8222980 8225435 8241082 8242010 8247432 + * 8258795 8267038 8287180 8302512 8304761 8306031 8308021 8313702 8318322 +- * 8327631 8332424 8334418 ++ * 8327631 8332424 8334418 8344589 8348328 + * @summary Checks the IANA language subtag registry data update +- * (LSR Revision: 2024-06-14) with Locale and Locale.LanguageRange ++ * (LSR Revision: 2025-05-15) with Locale and Locale.LanguageRange + * class methods. + * @run main LanguageSubtagRegistryTest + */ +@@ -45,9 +45,9 @@ public class LanguageSubtagRegistryTest { + static boolean err = false; + + private static final String ACCEPT_LANGUAGE = +- "Accept-Language: aam, adp, aeb, ajs, aog, apc, ajp, aue, bcg, bic, bpp, cey, cbr, cnp, cqu, crr, csp, csx, dif, dmw, dsz, ehs, ema," +- + " en-gb-oed, gti, iba, ilw, jks, kdz, kjh, kmb, koj, kru, ksp, kwq, kxe, kzk, lgs, lii, lmm, lsb, lsc, lsn, lsv, lsw, lvi, meg, mtm," +- + " ngv, nns, ola, oyb, pat, pcr, phr, plu, pnd, pub, rib, rnb, rsn, scv, snz, sqx, suj, szy, taj, tdg, tjj, tjp, tpn, tvx," ++ "Accept-Language: aam, adp, aeb, ajs, aog, apc, ajp, aue, bcg, bic, bpp, cey, cbr, cnp, cqu, crr, csp, csx, dif, dmw, dsz, ehs, eko, ema," ++ + " en-gb-oed, gti, hnm, iba, ilw, jks, kdz, kjh, kmb, koj, kru, ksp, kwq, kxe, kzk, lgs, lii, lmm, lsb, lsc, lsn, lsv, lsw, luh, lvi, meg, mtm," ++ + " ngv, nns, ola, oyb, pat, pcr, phr, plu, pnd, pub, rib, rnb, rsn, scv, sjc, snz, sqm, sqx, suj, szy, taj, tdg, tjj, tjp, tpn, tvx," + + " umi, uss, uth, xia, yos, ysm, zko, wkr;q=0.9, ar-hyw;q=0.8, yug;q=0.5, gfx;q=0.4"; + private static final List EXPECTED_RANGE_LIST = List.of( + new LanguageRange("aam", 1.0), +@@ -94,12 +94,16 @@ public class LanguageSubtagRegistryTest { + new LanguageRange("sgn-dsz", 1.0), + new LanguageRange("ehs", 1.0), + new LanguageRange("sgn-ehs", 1.0), ++ new LanguageRange("eko", 1.0), ++ new LanguageRange("nte", 1.0), + new LanguageRange("ema", 1.0), + new LanguageRange("uok", 1.0), + new LanguageRange("en-gb-oed", 1.0), + new LanguageRange("en-gb-oxendict", 1.0), + new LanguageRange("gti", 1.0), + new LanguageRange("nyc", 1.0), ++ new LanguageRange("hnm", 1.0), ++ new LanguageRange("zh-hnm", 1.0), + new LanguageRange("iba", 1.0), + new LanguageRange("snb", 1.0), + new LanguageRange("blg", 1.0), +@@ -142,6 +146,8 @@ public class LanguageSubtagRegistryTest { + new LanguageRange("sgn-lsv", 1.0), + new LanguageRange("lsw", 1.0), + new LanguageRange("sgn-lsw", 1.0), ++ new LanguageRange("luh", 1.0), ++ new LanguageRange("zh-luh", 1.0), + new LanguageRange("lvi", 1.0), + new LanguageRange("meg", 1.0), + new LanguageRange("cir", 1.0), +@@ -176,8 +182,12 @@ public class LanguageSubtagRegistryTest { + new LanguageRange("sgn-rsn", 1.0), + new LanguageRange("scv", 1.0), + new LanguageRange("zir", 1.0), ++ new LanguageRange("sjc", 1.0), ++ new LanguageRange("zh-sjc", 1.0), + new LanguageRange("snz", 1.0), + new LanguageRange("asd", 1.0), ++ new LanguageRange("sqm", 1.0), ++ new LanguageRange("dek", 1.0), + new LanguageRange("sqx", 1.0), + new LanguageRange("sgn-sqx", 1.0), + new LanguageRange("suj", 1.0), +@@ -264,12 +274,18 @@ public class LanguageSubtagRegistryTest { + + System.err.println(" Expected size=" + expectedSize); + for (LanguageRange lr : expected) { ++ if (!got.contains(lr)) { ++ System.err.print("Error - Actual does not contain:"); ++ } + System.err.println(" range=" + lr.getRange() + + ", weight=" + lr.getWeight()); + } + + System.err.println(" Actual size=" + actualSize); + for (LanguageRange lr : got) { ++ if (!expected.contains(lr)) { ++ System.err.print("Error - Expected does not contain:"); ++ } + System.err.println(" range=" + lr.getRange() + + ", weight=" + lr.getWeight()); + } +diff --git a/test/jdk/java/util/TimeZone/TimeZoneData/VERSION b/test/jdk/java/util/TimeZone/TimeZoneData/VERSION +index bf027918c..750d9fae2 100644 +--- a/test/jdk/java/util/TimeZone/TimeZoneData/VERSION ++++ b/test/jdk/java/util/TimeZone/TimeZoneData/VERSION +@@ -1 +1 @@ +-tzdata2024a ++tzdata2025b +diff --git a/test/jdk/java/util/TimeZone/TimeZoneData/aliases.txt b/test/jdk/java/util/TimeZone/TimeZoneData/aliases.txt +index 82bad17c5..0f9eef913 100644 +--- a/test/jdk/java/util/TimeZone/TimeZoneData/aliases.txt ++++ b/test/jdk/java/util/TimeZone/TimeZoneData/aliases.txt +@@ -1,6 +1,3 @@ +-Link Asia/Riyadh87 Mideast/Riyadh87 +-Link Asia/Riyadh88 Mideast/Riyadh88 +-Link Asia/Riyadh89 Mideast/Riyadh89 + Link Australia/Sydney Australia/ACT #= Australia/Canberra + Link Australia/Lord_Howe Australia/LHI + Link Australia/Sydney Australia/NSW +@@ -53,6 +50,7 @@ Link America/Tijuana Mexico/BajaNorte + Link America/Mazatlan Mexico/BajaSur + Link America/Mexico_City Mexico/General + Link Pacific/Auckland NZ ++Link Asia/Ulaanbaatar Asia/Choibalsan + Link Pacific/Chatham NZ-CHAT + Link America/Denver Navajo #= America/Shiprock + Link Asia/Shanghai PRC +diff --git a/test/jdk/java/util/zip/DataDescriptorSignatureMissing.java b/test/jdk/java/util/zip/DataDescriptorSignatureMissing.java +index f7a2ae2f8..db641ccba 100644 +--- a/test/jdk/java/util/zip/DataDescriptorSignatureMissing.java ++++ b/test/jdk/java/util/zip/DataDescriptorSignatureMissing.java +@@ -1,5 +1,6 @@ + /* + * Copyright 2012 Google, Inc. All Rights Reserved. ++ * Copyright (c) 2023, 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,124 +25,137 @@ + /** + * @test + * @bug 8056934 +- * @summary Check ability to read zip files created by python zipfile +- * implementation, which fails to write optional (but recommended) data +- * descriptor signatures. Repro scenario is a Java -> Python -> Java round trip: +- * - ZipOutputStream creates zip file with DEFLATED entries and data +- * descriptors with optional signature "PK0x0708". +- * - Python reads those entries, preserving the 0x08 flag byte +- * - Python outputs those entries with data descriptors lacking the +- * optional signature. +- * - ZipInputStream cannot handle the missing signature +- * ++ * @summary Verify the ability to read zip files whose local header ++ * data descriptor is missing the optional signature ++ *

    + * No way to adapt the technique in this test to get a ZIP64 zip file + * without data descriptors was found. +- * +- * @ignore This test has brittle dependencies on an external working python. ++ * @run junit DataDescriptorSignatureMissing + */ + + -+ // @formatter:off -+ public static final RegisterArray allRegisters = new RegisterArray( -+ zero, ra, tp, sp, a0, a1, a2, a3, -+ a4, a5, a6, a7, t0, t1, t2, t3, -+ t4, t5, t6, t7, t8, rx, fp, s0, -+ s1, s2, s3, s4, s5, s6, s7, s8, ++import org.junit.jupiter.api.Test; + -+ f0, f1, f2, f3, f4, f5, f6, f7, -+ f8, f9, f10, f11, f12, f13, f14, f15, -+ f16, f17, f18, f19, f20, f21, f22, f23, -+ f24, f25, f26, f27, f28, f29, f30, f31 -+ ); -+ // @formatter:on + import java.io.*; ++import java.nio.ByteBuffer; ++import java.nio.ByteOrder; ++import java.nio.charset.StandardCharsets; + import java.util.zip.*; + +-public class DataDescriptorSignatureMissing { +- void printStream(InputStream is) throws IOException { +- Reader r = new InputStreamReader(is); +- StringBuilder sb = new StringBuilder(); +- char[] buf = new char[1024]; +- int n; +- while ((n = r.read(buf)) > 0) { +- sb.append(buf, 0, n); +- } +- System.out.print(sb); +- } ++import static org.junit.jupiter.api.Assertions.*; ++ ++public class DataDescriptorSignatureMissing { + + /** -+ * Basic set of CPU features mirroring what is returned from the cpuid instruction. See: -+ * {@code VM_Version::cpuFeatureFlags}. ++ * Verify that ZipInputStream correctly parses a ZIP with a Data Descriptor without ++ * the recommended but optional signature. + */ -+ public enum CPUFeature { -+ LA32, -+ LA64, -+ LLEXC, -+ SCDLY, -+ LLDBAR, -+ LBT_X86, -+ LBT_ARM, -+ LBT_MIPS, -+ CCDMA, -+ COMPLEX, -+ FP, -+ CRYPTO, -+ LSX, -+ LASX, -+ LAM, -+ LLSYNC, -+ TGTSYNC, -+ ULSYNC, -+ UAL -+ } -+ -+ private final EnumSet features; ++ @Test ++ public void shouldParseSignaturelessDescriptor() throws IOException { ++ // The ZIP with a signature-less descriptor ++ byte[] zip = makeZipWithSignaturelessDescriptor(); + +- int entryCount(File zipFile) throws IOException { +- try (FileInputStream fis = new FileInputStream(zipFile); +- ZipInputStream zis = new ZipInputStream(fis)) { +- for (int count = 0;; count++) +- if (zis.getNextEntry() == null) +- return count; ++ // ZipInputStream should read the signature-less data descriptor ++ try (ZipInputStream in = new ZipInputStream( ++ new ByteArrayInputStream(zip))) { ++ ZipEntry first = in.getNextEntry(); ++ assertNotNull(first, "Zip file is unexpectedly missing first entry"); ++ assertEquals("first", first.getName()); ++ assertArrayEquals("first".getBytes(StandardCharsets.UTF_8), in.readAllBytes()); ++ ++ ZipEntry second = in.getNextEntry(); ++ assertNotNull(second, "Zip file is unexpectedly missing second entry"); ++ assertEquals("second", second.getName()); ++ assertArrayEquals("second".getBytes(StandardCharsets.UTF_8), in.readAllBytes()); + } + + } + +- void test(String[] args) throws Throwable { +- if (! new File("/usr/bin/python").canExecute()) +- return; +- +- // Create a java zip file with DEFLATED entries and data +- // descriptors with signatures. +- final File in = new File("in.zip"); +- final File out = new File("out.zip"); +- final int count = 3; +- try (FileOutputStream fos = new FileOutputStream(in); +- ZipOutputStream zos = new ZipOutputStream(fos)) { +- for (int i = 0; i < count; i++) { +- ZipEntry ze = new ZipEntry("hello.python" + i); +- ze.setMethod(ZipEntry.DEFLATED); +- zos.putNextEntry(ze); +- zos.write(new byte[10]); +- zos.closeEntry(); +- } + /** -+ * Set of flags to control code emission. ++ * The 'Data descriptor' record is used to facilitate ZIP streaming. If the size of an ++ * entry is unknown at the time the LOC header is written, bit 3 of the General Purpose Bit Flag ++ * is set, and the File data is immediately followed by the 'Data descriptor' record. This record ++ * then contains the compressed and uncompressed sizes of the entry and also the CRC value. ++ * ++ * The 'Data descriptor' record is usually preceded by the recommended, but optional ++ * signature value 0x08074b50. ++ * ++ * A ZIP entry in streaming mode has the following structure: ++ * ++ * ------ Local File Header ------ ++ * 000000 signature 0x04034b50 ++ * 000004 version 20 ++ * 000006 flags 0x0808 # Notice bit 3 is set ++ * [..] Omitted for brevity ++ * ++ * ------ File Data ------ ++ * 000035 data 7 bytes ++ * ++ * ------ Data Descriptor ------ ++ * 000042 signature 0x08074b50 ++ * 000046 crc 0x3610a686 ++ * 000050 csize 7 ++ * 000054 size 5 ++ * ++ * A signature-less data descriptor will look like the following: ++ * ++ * ------ Data Descriptor ------ ++ * 000042 crc 0x3610a686 ++ * 000046 csize 7 ++ * 000050 size 5 ++ * ++ * This method produces a ZIP with two entries, where the first entry ++ * is made signature-less. + */ -+ public enum Flag { -+ useLSX, -+ useLASX -+ } -+ -+ private final EnumSet flags; -+ -+ public LoongArch64(EnumSet features, EnumSet flags) { -+ super("loongarch64", LoongArch64Kind.QWORD, ByteOrder.LITTLE_ENDIAN, true, allRegisters, 0, 0, 0); -+ this.features = features; -+ this.flags = flags; -+ } -+ -+ public EnumSet getFeatures() { -+ return features; -+ } -+ -+ public EnumSet getFlags() { -+ return flags; ++ private static byte[] makeZipWithSignaturelessDescriptor() throws IOException { ++ // Offset of the signed data descriptor ++ int sigOffset; ++ ++ ByteArrayOutputStream out = new ByteArrayOutputStream(); ++ try (ZipOutputStream zo = new ZipOutputStream(out)) { ++ // Write a first entry ++ zo.putNextEntry(new ZipEntry("first")); ++ zo.write("first".getBytes(StandardCharsets.UTF_8)); ++ // Force the data descriptor to be written out ++ zo.closeEntry(); ++ // Signed data descriptor starts 16 bytes before current offset ++ sigOffset = out.size() - 4 * Integer.BYTES; ++ // Add a second entry ++ zo.putNextEntry(new ZipEntry("second")); ++ zo.write("second".getBytes(StandardCharsets.UTF_8)); + } + +- // Copy the zip file using python's zipfile module +- String[] python_program_lines = { +- "import os", +- "import zipfile", +- "input_zip = zipfile.ZipFile('in.zip', mode='r')", +- "output_zip = zipfile.ZipFile('out.zip', mode='w')", +- "count08 = 0", +- "for input_info in input_zip.infolist():", +- " output_info = input_info", +- " if output_info.flag_bits & 0x08 == 0x08:", +- " count08 += 1", +- " output_zip.writestr(output_info, input_zip.read(input_info))", +- "output_zip.close()", +- "if count08 == 0:", +- " raise ValueError('Expected to see entries with 0x08 flag_bits set')", +- }; +- StringBuilder python_program_builder = new StringBuilder(); +- for (String line : python_program_lines) +- python_program_builder.append(line).append('\n'); +- String python_program = python_program_builder.toString(); +- String[] cmdline = { "/usr/bin/python", "-c", python_program }; +- ProcessBuilder pb = new ProcessBuilder(cmdline); +- pb.redirectErrorStream(true); +- Process p = pb.start(); +- printStream(p.getInputStream()); +- p.waitFor(); +- equal(p.exitValue(), 0); +- +- File pythonZipFile = new File("out.zip"); +- check(pythonZipFile.exists()); +- +- equal(entryCount(in), +- entryCount(out)); +- +- // We expect out to be identical to in, except for the removal of +- // the optional data descriptor signatures. +- final int SIG_LENGTH = 4; // length of a zip signature - PKxx +- equal(in.length(), +- out.length() + SIG_LENGTH * count); +- +- in.delete(); +- out.delete(); +- } ++ // The generated ZIP file with a signed data descriptor ++ byte[] sigZip = out.toByteArray(); ++ ++ // The offset of the CRC immediately following the 4-byte signature ++ int crcOffset = sigOffset + Integer.BYTES; ++ ++ // Create a ZIP file with a signature-less data descriptor for the first entry ++ ByteArrayOutputStream sigLess = new ByteArrayOutputStream(); ++ sigLess.write(sigZip, 0, sigOffset); ++ // Skip the signature ++ sigLess.write(sigZip, crcOffset, sigZip.length - crcOffset); ++ ++ byte[] siglessZip = sigLess.toByteArray(); + +- //--------------------- Infrastructure --------------------------- +- volatile int passed = 0, failed = 0; +- void pass() {passed++;} +- void fail() {failed++; Thread.dumpStack();} +- void fail(String msg) {System.err.println(msg); fail();} +- void unexpected(Throwable t) {failed++; t.printStackTrace();} +- void check(boolean cond) {if (cond) pass(); else fail();} +- void equal(Object x, Object y) { +- if (x == null ? y == null : x.equals(y)) pass(); +- else fail(x + " not equal to " + y);} +- public static void main(String[] args) throws Throwable { +- new DataDescriptorSignatureMissing().instanceMain(args);} +- public void instanceMain(String[] args) throws Throwable { +- try {test(args);} catch (Throwable t) {unexpected(t);} +- System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); +- if (failed > 0) throw new AssertionError("Some tests failed");} ++ // Adjust the CEN offset in the END header ++ ByteBuffer buffer = ByteBuffer.wrap(siglessZip).order(ByteOrder.LITTLE_ENDIAN); ++ // Reduce cenOffset by 4 bytes ++ int cenOff = siglessZip.length - ZipFile.ENDHDR + ZipFile.ENDOFF; ++ int realCenOff = buffer.getInt(cenOff) - Integer.BYTES; ++ buffer.putInt(cenOff, realCenOff); ++ ++ // Adjust the LOC offset in the second CEN header ++ int cen = realCenOff; ++ // Skip past the first CEN header ++ int nlen = buffer.getShort(cen + ZipFile.CENNAM); ++ cen += ZipFile.CENHDR + nlen; ++ ++ // Reduce LOC offset by 4 bytes ++ int locOff = cen + ZipFile.CENOFF; ++ buffer.putInt(locOff, buffer.getInt(locOff) - Integer.BYTES); ++ ++ return siglessZip; + } + } +diff --git a/test/jdk/javax/accessibility/TestJMenuItemShortcutAccessibility.java b/test/jdk/javax/accessibility/TestJMenuItemShortcutAccessibility.java +new file mode 100644 +index 000000000..0eb3c0fc2 +--- /dev/null ++++ b/test/jdk/javax/accessibility/TestJMenuItemShortcutAccessibility.java +@@ -0,0 +1,111 @@ ++/* ++ * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. ++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. ++ * ++ * This code is free software; you can redistribute it and/or modify it ++ * 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. ++ */ + -+ @Override -+ public PlatformKind getPlatformKind(JavaKind javaKind) { -+ switch (javaKind) { -+ case Boolean: -+ case Byte: -+ return LoongArch64Kind.BYTE; -+ case Short: -+ case Char: -+ return LoongArch64Kind.WORD; -+ case Int: -+ return LoongArch64Kind.DWORD; -+ case Long: -+ case Object: -+ return LoongArch64Kind.QWORD; -+ case Float: -+ return LoongArch64Kind.SINGLE; -+ case Double: -+ return LoongArch64Kind.DOUBLE; -+ default: -+ return null; -+ } -+ } ++import java.awt.event.InputEvent; ++import java.awt.event.KeyEvent; ++import javax.swing.JFrame; ++import javax.swing.JMenu; ++import javax.swing.JMenuBar; ++import javax.swing.JMenuItem; ++import javax.swing.KeyStroke; + -+ @Override -+ public boolean canStoreValue(RegisterCategory category, PlatformKind platformKind) { -+ LoongArch64Kind kind = (LoongArch64Kind) platformKind; -+ if (kind.isInteger()) { -+ return category.equals(CPU); -+ } else if (kind.isSIMD()) { -+ return category.equals(SIMD); -+ } -+ return false; -+ } ++/* ++ * @test ++ * @bug 8339728 ++ * @summary Tests that JAWS announce the shortcuts for JMenuItems. ++ * @requires os.family == "windows" ++ * @library /java/awt/regtesthelpers ++ * @build PassFailJFrame ++ * @run main/manual TestJMenuItemShortcutAccessibility ++ */ + -+ @Override -+ public LoongArch64Kind getLargestStorableKind(RegisterCategory category) { -+ if (category.equals(CPU)) { -+ return LoongArch64Kind.QWORD; -+ } else if (category.equals(SIMD)) { -+ return LoongArch64Kind.V256_QWORD; -+ } else { -+ return null; -+ } -+ } -+} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.loongarch64/src/jdk/vm/ci/loongarch64/LoongArch64Kind.java jdk11u-ls/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.loongarch64/src/jdk/vm/ci/loongarch64/LoongArch64Kind.java ---- openjdk/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.loongarch64/src/jdk/vm/ci/loongarch64/LoongArch64Kind.java 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.loongarch64/src/jdk/vm/ci/loongarch64/LoongArch64Kind.java 2023-09-12 13:54:26.513575962 +0800 -@@ -0,0 +1,163 @@ ++public class TestJMenuItemShortcutAccessibility { ++ public static void main(String[] args) throws Exception { ++ String INSTRUCTIONS = "" ++ + "1. Start the JAWS application\n" ++ + "2. Press Alt + M to open application Menu\n" ++ + "3. Navigate the Menu Items by using UP / DOWN arrow key\n" ++ + "4. Press Pass if you are able to hear correct JAWS announcements\n" ++ + " (JAWS should read full shortcut text and not only the 1st\n" ++ + " character of shortcut text for each menu item) else Fail\n"; ++ ++ PassFailJFrame.builder() ++ .title("TestJMenuItemShortcutAccessibility Instruction") ++ .instructions(INSTRUCTIONS) ++ .columns(35) ++ .testUI(TestJMenuItemShortcutAccessibility::createUI) ++ .build() ++ .awaitAndCheck(); ++ } ++ ++ private static JFrame createUI() { ++ JFrame frame = new JFrame("A Frame with Menu"); ++ ++ JMenuBar menuBar = new JMenuBar(); ++ JMenu menu = new JMenu("Menu with shortcuts"); ++ menu.setMnemonic(KeyEvent.VK_M); ++ menuBar.add(menu); ++ ++ KeyStroke keyStroke1 = KeyStroke.getKeyStroke(KeyEvent.VK_F, ++ InputEvent.CTRL_DOWN_MASK); ++ KeyStroke keyStroke2 = KeyStroke.getKeyStroke(KeyEvent.VK_2, ++ InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK); ++ KeyStroke keyStroke3 = KeyStroke.getKeyStroke(KeyEvent.VK_F1, ++ InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK); ++ KeyStroke keyStroke4 = KeyStroke.getKeyStroke(KeyEvent.VK_COMMA, ++ InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK); ++ KeyStroke keyStroke5 = KeyStroke.getKeyStroke(KeyEvent.VK_PERIOD, ++ InputEvent.CTRL_DOWN_MASK | InputEvent.ALT_DOWN_MASK); ++ KeyStroke keyStroke6 = KeyStroke.getKeyStroke(KeyEvent.VK_TAB, ++ InputEvent.CTRL_DOWN_MASK); ++ KeyStroke keyStroke7 = KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, ++ InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK); ++ ++ JMenuItem menuItem1 = new JMenuItem("First Menu Item"); ++ menuItem1.setAccelerator(keyStroke1); ++ JMenuItem menuItem2 = new JMenuItem("Second Menu Item"); ++ menuItem2.setAccelerator(keyStroke2); ++ JMenuItem menuItem3 = new JMenuItem("Third Menu Item"); ++ menuItem3.setAccelerator(keyStroke3); ++ JMenuItem menuItem4 = new JMenuItem("Fourth Menu Item"); ++ menuItem4.setAccelerator(keyStroke4); ++ JMenuItem menuItem5 = new JMenuItem("Fifth Menu Item"); ++ menuItem5.setAccelerator(keyStroke5); ++ JMenuItem menuItem6 = new JMenuItem("Sixth Menu Item"); ++ menuItem6.setAccelerator(keyStroke6); ++ JMenuItem menuItem7 = new JMenuItem("Seventh Menu Item"); ++ menuItem7.setAccelerator(keyStroke7); ++ ++ menu.add(menuItem1); ++ menu.add(menuItem2); ++ menu.add(menuItem3); ++ menu.add(menuItem4); ++ menu.add(menuItem5); ++ menu.add(menuItem6); ++ menu.add(menuItem7); ++ ++ frame.setJMenuBar(menuBar); ++ frame.setSize(300, 200); ++ return frame; ++ } ++} +diff --git a/test/jdk/javax/swing/JInternalFrame/8146321/JInternalFrameIconTest.java b/test/jdk/javax/swing/JInternalFrame/8146321/JInternalFrameIconTest.java +index 4db711c9d..0e36063bc 100644 +--- a/test/jdk/javax/swing/JInternalFrame/8146321/JInternalFrameIconTest.java ++++ b/test/jdk/javax/swing/JInternalFrame/8146321/JInternalFrameIconTest.java +@@ -30,6 +30,7 @@ + * @build Util + * @run main JInternalFrameIconTest + */ ++import java.io.File; + import java.awt.BorderLayout; + import java.awt.Component; + import java.awt.Graphics; +@@ -37,6 +38,7 @@ import java.awt.Point; + import java.awt.Rectangle; + import java.awt.Robot; + import java.awt.image.BufferedImage; ++import javax.imageio.ImageIO; + import javax.swing.Icon; + import javax.swing.ImageIcon; + import javax.swing.JDesktopPane; +@@ -61,7 +63,6 @@ public class JInternalFrameIconTest { + + public static void main(String[] args) throws Exception { + robot = new Robot(); +- robot.delay(2000); + UIManager.LookAndFeelInfo[] lookAndFeelArray + = UIManager.getInstalledLookAndFeels(); + for (UIManager.LookAndFeelInfo lookAndFeelItem : lookAndFeelArray) { +@@ -76,21 +77,28 @@ public class JInternalFrameIconTest { + private static void executeCase(String lookAndFeelString) throws Exception { + if (tryLookAndFeel(lookAndFeelString)) { + createImageIconUI(lookAndFeelString); ++ robot.waitForIdle(); + robot.delay(1000); + getImageIconBufferedImage(); ++ robot.waitForIdle(); + robot.delay(1000); + cleanUp(); + robot.waitForIdle(); ++ robot.delay(1000); + + createIconUI(lookAndFeelString); ++ robot.waitForIdle(); + robot.delay(1000); + getIconBufferedImage(); ++ robot.waitForIdle(); + robot.delay(1000); + cleanUp(); + robot.waitForIdle(); ++ robot.delay(1000); + + testIfSame(lookAndFeelString); + robot.waitForIdle(); ++ robot.delay(1000); + } + + } +@@ -208,6 +216,8 @@ public class JInternalFrameIconTest { + private static void testIfSame(final String lookAndFeelString) + throws Exception { + if (!bufferedImagesEqual(imageIconImage, iconImage)) { ++ ImageIO.write(imageIconImage, "png", new File("imageicon-fail.png")); ++ ImageIO.write(iconImage, "png", new File("iconImage-fail.png")); + String error ="[" + lookAndFeelString + + "] : ERROR: icon and imageIcon not same."; + errorString += error; +diff --git a/test/jdk/javax/swing/JMenuItem/TestRadioAndCheckMenuItemWithIcon.java b/test/jdk/javax/swing/JMenuItem/TestRadioAndCheckMenuItemWithIcon.java +new file mode 100644 +index 000000000..17e88ceba +--- /dev/null ++++ b/test/jdk/javax/swing/JMenuItem/TestRadioAndCheckMenuItemWithIcon.java +@@ -0,0 +1,155 @@ +/* -+ * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2022, Loongson Technology. All rights reserved. ++ * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it @@ -119892,153 +207497,1873 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.internal.vm.ci/sha + * or visit www.oracle.com if you need additional information or have any + * questions. + */ -+package jdk.vm.ci.loongarch64; + -+import jdk.vm.ci.meta.PlatformKind; -+ -+public enum LoongArch64Kind implements PlatformKind { ++/* ++ * @test ++ * @bug 8348760 ++ * @summary Verify if RadioButtonMenuItem bullet and ++ * JCheckboxMenuItem checkmark is shown if ++ * JRadioButtonMenuItem and JCheckboxMenuItem ++ * is rendered with ImageIcon in WindowsLookAndFeel ++ * @requires (os.family == "windows") ++ * @library /java/awt/regtesthelpers ++ * @build PassFailJFrame ++ * @run main/manual TestRadioAndCheckMenuItemWithIcon ++ */ + -+ // scalar -+ BYTE(1), -+ WORD(2), -+ DWORD(4), -+ QWORD(8), -+ UBYTE(1), -+ UWORD(2), -+ UDWORD(4), -+ SINGLE(4), -+ DOUBLE(8), ++import java.awt.Color; ++import java.awt.Graphics; ++import java.awt.event.ActionEvent; ++import java.awt.event.KeyEvent; ++import java.awt.image.BufferedImage; ++ ++import javax.swing.AbstractButton; ++import javax.swing.ButtonGroup; ++import javax.swing.ImageIcon; ++import javax.swing.JCheckBoxMenuItem; ++import javax.swing.JFrame; ++import javax.swing.JMenu; ++import javax.swing.JMenuBar; ++import javax.swing.JMenuItem; ++import javax.swing.JPanel; ++import javax.swing.JRadioButtonMenuItem; ++import javax.swing.KeyStroke; ++import javax.swing.UIManager; ++ ++public class TestRadioAndCheckMenuItemWithIcon { ++ ++ private static final String INSTRUCTIONS = ++ "A top level Menu will be shown.\n" ++ + "\n" ++ + "Clicking on the Menu will show a\n" ++ + "JRadioButtonMenuItem group with 3 radiobutton menuitems\n" ++ + "and a JCheckBoxMenuItem group with 3 checkbox menuitems.\n" ++ + "\n" ++ + "First radiobutton menuitem is selected with imageicon of a red square.\n" ++ + "Second radiobutton menuitem is unselected with imageicon.\n" ++ + "Third radiobutton menuItem is unselected without imageicon.\n" ++ + "\n" ++ + "First checkbox menuitem is selected with imageicon.\n" ++ + "Second checkbox menuitem is unselected with imageicon.\n" ++ + "Third checkbox menuItem is unselected without imageicon.\n" ++ + "\n" ++ + "Verify that for first JRadioButtonMenuItem with imageicon,\n" ++ + "a bullet is shown alongside the imageicon and\n" ++ + "for first JCheckBoxMenuItem with imageicon\n" ++ + "a checkmark is shown alongside the imageicon.\n" ++ + "\n" ++ + "If bullet and checkmark is shown, test passes else fails."; ++ ++ public static void main(String[] args) throws Exception { ++ UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); ++ PassFailJFrame.builder() ++ .title("JRadioButtonMenuItem Instructions") ++ .instructions(INSTRUCTIONS) ++ .columns(60) ++ .testUI(TestRadioAndCheckMenuItemWithIcon::doTest) ++ .build() ++ .awaitAndCheck(); ++ } ++ ++ public static JFrame doTest() { ++ BufferedImage img = new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB); ++ Graphics g = img.getGraphics(); ++ g.setColor(Color.red); ++ g.fillRect(0, 0, img.getWidth(), img.getHeight()); ++ g.dispose(); ++ ++ BufferedImage img2 = new BufferedImage(64, 64, BufferedImage.TYPE_INT_ARGB); ++ Graphics g2 = img2.getGraphics(); ++ g2.setColor(Color.red); ++ g2.fillRect(0, 0, img2.getWidth(), img2.getHeight()); ++ g2.dispose(); ++ ++ JFrame frame = new JFrame("RadioButtonWithImageIcon"); ++ ImageIcon imageIcon1 = new ImageIcon(img); ++ ImageIcon imageIcon2 = new ImageIcon(img2); ++ AbstractButton button1; ++ JRadioButtonMenuItem m1 = new JRadioButtonMenuItem("JRadioButtonMenuItem 1", ++ imageIcon1); ++ m1.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F4, ActionEvent.ALT_MASK|ActionEvent.CTRL_MASK|ActionEvent.SHIFT_MASK)); ++ button1 = m1; ++ button1.setSelected(true); ++ AbstractButton button2 = new JRadioButtonMenuItem("JRadioButtonMenuItem 2", imageIcon2); ++ AbstractButton button3 = new JRadioButtonMenuItem("JRadioButtonMenuItem 3"); ++ ++ ButtonGroup buttonGroup = new ButtonGroup(); ++ buttonGroup.add(button1); ++ buttonGroup.add(button2); ++ buttonGroup.add(button3); ++ ++ AbstractButton check1 = new JCheckBoxMenuItem("JCheckBoxMenuItem 1", ++ imageIcon1); ++ check1.setSelected(true); ++ AbstractButton check2 = new JCheckBoxMenuItem("JCheckBoxMenuItem 2", imageIcon1); ++ JCheckBoxMenuItem c3; ++ AbstractButton check3 = c3 = new JCheckBoxMenuItem("JCheckBoxMenuItem 3"); ++ c3.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F5, ActionEvent.ALT_MASK|ActionEvent.CTRL_MASK|ActionEvent.SHIFT_MASK)); ++ ++ JMenu topLevel = new JMenu("Menu"); ++ ++ topLevel.add(button1); ++ topLevel.add(button2); ++ topLevel.add(button3); ++ ++ topLevel.addSeparator(); ++ ++ topLevel.add(check1); ++ topLevel.add(check2); ++ topLevel.add(check3); ++ ++ AbstractButton menuitem1 = new JMenuItem("MenuItem1"); ++ AbstractButton menuitem2 = new JMenuItem("MenuItem2", imageIcon1); ++ topLevel.addSeparator(); ++ topLevel.add(menuitem1); ++ topLevel.add(menuitem2); ++ ++ JMenuBar menuBar = new JMenuBar(); ++ menuBar.add(topLevel); ++ ++ frame.setJMenuBar(menuBar); ++ frame.setSize(300, 300); ++ return frame; ++ ++ } ++} +diff --git a/test/jdk/javax/swing/JTabbedPane/8134116/Bug8134116.java b/test/jdk/javax/swing/JTabbedPane/8134116/Bug8134116.java +index 97164c253..6a39d7b96 100644 +--- a/test/jdk/javax/swing/JTabbedPane/8134116/Bug8134116.java ++++ b/test/jdk/javax/swing/JTabbedPane/8134116/Bug8134116.java +@@ -1,13 +1,43 @@ ++/* ++ * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. ++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. ++ * ++ * This code is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 only, as ++ * published by the Free Software Foundation. ++ * ++ * This code is distributed in the hope that it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * version 2 for more details (a copy is included in the LICENSE file that ++ * accompanied this code). ++ * ++ * You should have received a copy of the GNU General Public License version ++ * 2 along with this work; if not, write to the Free Software Foundation, ++ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA ++ * or visit www.oracle.com if you need additional information or have any ++ * questions. ++ */ + +-import java.awt.*; ++import java.awt.Component; ++import java.awt.Rectangle; + import java.awt.event.KeyEvent; + import java.util.ArrayList; + import java.util.List; + -+ // SIMD -+ V128_BYTE(16, BYTE), -+ V128_WORD(16, WORD), -+ V128_DWORD(16, DWORD), -+ V128_QWORD(16, QWORD), -+ V128_SINGLE(16, SINGLE), -+ V128_DOUBLE(16, DOUBLE), -+ V256_BYTE(32, BYTE), -+ V256_WORD(32, WORD), -+ V256_DWORD(32, DWORD), -+ V256_QWORD(32, QWORD), -+ V256_SINGLE(32, SINGLE), -+ V256_DOUBLE(32, DOUBLE); + import javax.accessibility.Accessible; + import javax.accessibility.AccessibleContext; + import javax.accessibility.AccessibleState; + import javax.accessibility.AccessibleStateSet; +-import javax.swing.*; ++import javax.swing.Icon; ++import javax.swing.JFrame; ++import javax.swing.JLabel; ++import javax.swing.JPanel; ++import javax.swing.JTabbedPane; ++import javax.swing.SwingUtilities; ++import javax.swing.UIManager; + import javax.swing.plaf.nimbus.NimbusLookAndFeel; + + /* +@@ -22,7 +52,7 @@ public class Bug8134116 { + private static volatile Exception exception = null; + private static JFrame frame; + +- public static void main(String args[]) throws Exception { ++ public static void main(String[] args) throws Exception { + + try { + UIManager.setLookAndFeel(new NimbusLookAndFeel()); +diff --git a/test/jdk/jdk/internal/jline/AbstractWindowsTerminalTest.java b/test/jdk/jdk/internal/jline/AbstractWindowsTerminalTest.java +index d53c9b203..3e4011008 100644 +--- a/test/jdk/jdk/internal/jline/AbstractWindowsTerminalTest.java ++++ b/test/jdk/jdk/internal/jline/AbstractWindowsTerminalTest.java +@@ -27,6 +27,7 @@ + * @summary Verify the wrapper input stream is used when using Terminal.reader() + * @modules jdk.internal.le/jdk.internal.org.jline.terminal + * jdk.internal.le/jdk.internal.org.jline.terminal.impl ++ * jdk.internal.le/jdk.internal.org.jline.terminal.spi + * jdk.internal.le/jdk.internal.org.jline.utils + */ + +@@ -39,6 +40,7 @@ import java.util.function.Function; + import jdk.internal.org.jline.terminal.Size; + import jdk.internal.org.jline.terminal.Terminal.SignalHandler; + import jdk.internal.org.jline.terminal.impl.AbstractWindowsTerminal; ++import jdk.internal.org.jline.terminal.spi.SystemStream; + + + public class AbstractWindowsTerminalTest { +@@ -56,14 +58,17 @@ public class AbstractWindowsTerminalTest { + return is.read(); + } + }; +- var t = new AbstractWindowsTerminal(out, "test", "vt100", null, false, SignalHandler.SIG_DFL, isWrapper) { ++ var t = new AbstractWindowsTerminal(null, SystemStream.Output, out, ++ "test", "vt100", null, false, ++ SignalHandler.SIG_DFL, "", 0, ++ "", 0, isWrapper) { + @Override +- protected int getConsoleMode() { ++ protected int getConsoleMode(String console) { + return -1; + } + + @Override +- protected void setConsoleMode(int mode) { ++ protected void setConsoleMode(String console, int mode) { + throw new UnsupportedOperationException("unexpected."); + } + +diff --git a/test/jdk/jdk/internal/jline/KeyConversionTest.java b/test/jdk/jdk/internal/jline/KeyConversionTest.java +index aed9a7267..ffd116dbb 100644 +--- a/test/jdk/jdk/internal/jline/KeyConversionTest.java ++++ b/test/jdk/jdk/internal/jline/KeyConversionTest.java +@@ -27,6 +27,7 @@ + * @summary Verify the conversion from key events to escape sequences works properly. + * @modules jdk.internal.le/jdk.internal.org.jline.terminal + * jdk.internal.le/jdk.internal.org.jline.terminal.impl ++ * jdk.internal.le/jdk.internal.org.jline.terminal.spi + */ + + import java.io.IOException; +@@ -36,6 +37,7 @@ import java.nio.charset.Charset; + import jdk.internal.org.jline.terminal.Size; + import jdk.internal.org.jline.terminal.Terminal.SignalHandler; + import jdk.internal.org.jline.terminal.impl.AbstractWindowsTerminal; ++import jdk.internal.org.jline.terminal.spi.SystemStream; + + public class KeyConversionTest { + public static void main(String... args) throws Exception { +@@ -58,14 +60,17 @@ public class KeyConversionTest { + + void checkKeyConversion(KeyEvent event, String expected) throws IOException { + StringBuilder result = new StringBuilder(); +- new AbstractWindowsTerminal(new StringWriter(), "", "windows", Charset.forName("UTF-8"), +- true, SignalHandler.SIG_DFL, in -> in) { ++ new AbstractWindowsTerminal(null, SystemStream.Output, ++ new StringWriter(), "", "windows", ++ Charset.forName("UTF-8"), true, ++ SignalHandler.SIG_DFL, "", 0, ++ "", 0, in -> in) { + @Override +- protected int getConsoleMode() { ++ protected int getConsoleMode(String console) { + return 0; + } + @Override +- protected void setConsoleMode(int mode) { ++ protected void setConsoleMode(String console, int mode) { + throw new UnsupportedOperationException("Not supported yet."); + } + @Override +diff --git a/test/jdk/jdk/jfr/event/gc/stacktrace/AllocationStackTrace.java b/test/jdk/jdk/jfr/event/gc/stacktrace/AllocationStackTrace.java +index 1ed20f83a..0445c6edf 100644 +--- a/test/jdk/jdk/jfr/event/gc/stacktrace/AllocationStackTrace.java ++++ b/test/jdk/jdk/jfr/event/gc/stacktrace/AllocationStackTrace.java +@@ -81,7 +81,7 @@ class HumongousMemoryAllocator extends MemoryAllocator { + class OldGenMemoryAllocator extends MemoryAllocator { + + private List list = new ArrayList(); +- private int counter = 6000; ++ private int counter = 5000; + + @Override + public void allocate() { +@@ -89,7 +89,7 @@ class OldGenMemoryAllocator extends MemoryAllocator { + list.add(new byte[10 * KB]); + } else { + list = new ArrayList(); +- counter = 6000; ++ counter = 5000; + } + + garbage = list; +diff --git a/test/jdk/jdk/jfr/event/oldobject/TestListenerLeak.java b/test/jdk/jdk/jfr/event/oldobject/TestListenerLeak.java +index a275eda51..2cb092e60 100644 +--- a/test/jdk/jdk/jfr/event/oldobject/TestListenerLeak.java ++++ b/test/jdk/jdk/jfr/event/oldobject/TestListenerLeak.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -74,15 +74,17 @@ public class TestListenerLeak { + + public static void main(String[] args) throws Exception { + WhiteBox.setWriteAllObjectSamples(true); +- +- try (Recording r = new Recording()) { +- r.enable(EventNames.OldObjectSample).withStackTrace().with("cutoff", "infinity"); +- r.start(); +- listenerLeak(); +- r.stop(); +- List events = Events.fromRecording(r); +- if (OldObjects.countMatchingEvents(events, Stuff[].class, null, null, -1, "listenerLeak") == 0) { +- throw new Exception("Could not find leak with " + Stuff[].class); ++ while (true) { ++ try (Recording r = new Recording()) { ++ r.enable(EventNames.OldObjectSample).withStackTrace().with("cutoff", "infinity"); ++ r.start(); ++ listenerLeak(); ++ r.stop(); ++ List events = Events.fromRecording(r); ++ if (OldObjects.countMatchingEvents(events, Stuff[].class, null, null, -1, "listenerLeak") != 0) { ++ return; // Success ++ } ++ System.out.println("Could not find leak with " + Stuff[].class + ". Retrying."); + } + } + } +diff --git a/test/jdk/jdk/jfr/event/os/TestCPUInformation.java b/test/jdk/jdk/jfr/event/os/TestCPUInformation.java +index 7990c49a1..025048c6b 100644 +--- a/test/jdk/jdk/jfr/event/os/TestCPUInformation.java ++++ b/test/jdk/jdk/jfr/event/os/TestCPUInformation.java +@@ -23,6 +23,12 @@ + * questions. + */ + ++/* ++ * This file has been modified by Loongson Technology in 2021, These ++ * modifications are Copyright (c) 2021, Loongson Technology, and are made ++ * available on the same license terms set forth above. ++ */ + -+ private final int size; -+ private final int vectorLength; + package jdk.jfr.event.os; + + import java.util.List; +@@ -54,8 +60,8 @@ public class TestCPUInformation { + Events.assertField(event, "hwThreads").atLeast(1); + Events.assertField(event, "cores").atLeast(1); + Events.assertField(event, "sockets").atLeast(1); +- Events.assertField(event, "cpu").containsAny("Intel", "AMD", "Unknown x86", "sparc", "ARM", "PPC", "PowerPC", "AArch64", "s390"); +- Events.assertField(event, "description").containsAny("Intel", "AMD", "Unknown x86", "SPARC", "ARM", "PPC", "PowerPC", "AArch64", "s390"); ++ Events.assertField(event, "cpu").containsAny("Intel", "AMD", "Unknown x86", "sparc", "ARM", "PPC", "PowerPC", "AArch64", "s390", "MIPS", "LoongArch"); ++ Events.assertField(event, "description").containsAny("Intel", "AMD", "Unknown x86", "SPARC", "ARM", "PPC", "PowerPC", "AArch64", "s390", "MIPS", "LoongArch"); + } + } + } +diff --git a/test/jdk/jdk/jfr/startupargs/TestMemoryOptions.java b/test/jdk/jdk/jfr/startupargs/TestMemoryOptions.java +index 03411a1e6..47b32f1c9 100644 +--- a/test/jdk/jdk/jfr/startupargs/TestMemoryOptions.java ++++ b/test/jdk/jdk/jfr/startupargs/TestMemoryOptions.java +@@ -487,6 +487,7 @@ public class TestMemoryOptions { + if (flightRecorderOptions != null) { + pb = ProcessTools.createTestJvm("--add-exports=jdk.jfr/jdk.jfr.internal=ALL-UNNAMED", + "--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED", ++ "-Xmx256m", + flightRecorderOptions, + "-XX:StartFlightRecording", + SUT.class.getName(), +@@ -495,6 +496,7 @@ public class TestMemoryOptions { + // default, no FlightRecorderOptions passed + pb = ProcessTools.createTestJvm("--add-exports=jdk.jfr/jdk.jfr.internal=ALL-UNNAMED", + "--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED", ++ "-Xmx256m", + "-XX:StartFlightRecording", + SUT.class.getName(), + tc.getTestName()); +diff --git a/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java b/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java +index 33f777d64..0614f0806 100644 +--- a/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java ++++ b/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -375,46 +375,6 @@ + * @run main/othervm/manual -Djava.security.debug=certpath CAInterop certignarootca CRL + */ + +-/* +- * @test id=affirmtrustcommercialca +- * @bug 8040012 +- * @summary Interoperability tests with AffirmTrust Commercial CA +- * @library /test/lib +- * @build jtreg.SkippedException ValidatePathWithURL CAInterop +- * @run main/othervm/manual -Djava.security.debug=certpath,ocsp CAInterop affirmtrustcommercialca OCSP +- * @run main/othervm/manual -Djava.security.debug=certpath CAInterop affirmtrustcommercialca CRL +- */ +- +-/* +- * @test id=affirmtrustnetworkingca +- * @bug 8040012 +- * @summary Interoperability tests with AffirmTrust Networking CA +- * @library /test/lib +- * @build jtreg.SkippedException ValidatePathWithURL CAInterop +- * @run main/othervm/manual -Djava.security.debug=certpath,ocsp CAInterop affirmtrustnetworkingca OCSP +- * @run main/othervm/manual -Djava.security.debug=certpath CAInterop affirmtrustnetworkingca CRL +- */ +- +-/* +- * @test id=affirmtrustpremiumca +- * @bug 8040012 +- * @summary Interoperability tests with AffirmTrust Premium CA +- * @library /test/lib +- * @build jtreg.SkippedException ValidatePathWithURL CAInterop +- * @run main/othervm/manual -Djava.security.debug=certpath,ocsp CAInterop affirmtrustpremiumca OCSP +- * @run main/othervm/manual -Djava.security.debug=certpath CAInterop affirmtrustpremiumca CRL +- */ +- +-/* +- * @test id=affirmtrustpremiumeccca +- * @bug 8040012 +- * @summary Interoperability tests with AffirmTrust Premium ECC CA +- * @library /test/lib +- * @build jtreg.SkippedException ValidatePathWithURL CAInterop +- * @run main/othervm/manual -Djava.security.debug=certpath,ocsp CAInterop affirmtrustpremiumeccca OCSP +- * @run main/othervm/manual -Djava.security.debug=certpath CAInterop affirmtrustpremiumeccca CRL +- */ +- + /* + * @test id=teliarootcav2 + * @bug 8317373 +@@ -505,6 +465,36 @@ + * @run main/othervm/manual -Djava.security.debug=certpath CAInterop ssltlsrootrsa2022 CRL + */ + ++/* ++ * @test id=sectigotlsrootr46 ++ * @bug 8359170 ++ * @summary Interoperability tests with Sectigo Public Server Authentication ++ * Root R46 ++ * @library /test/lib ++ * @build jtreg.SkippedException ValidatePathWithURL CAInterop ++ * @run main/othervm/manual -Djava.security.debug=certpath,ocsp CAInterop ++ * sectigotlsrootr46 OCSP ++ * @run main/othervm/manual -Djava.security.debug=certpath,ocsp ++ * -Dcom.sun.security.ocsp.useget=false CAInterop sectigotlsrootr46 OCSP ++ * @run main/othervm/manual -Djava.security.debug=certpath CAInterop ++ * sectigotlsrootr46 CRL ++ */ + -+ private final LoongArch64Kind scalar; -+ private final EnumKey key = new EnumKey<>(this); ++/* ++ * @test id=sectigotlsroote46 ++ * @bug 8359170 ++ * @summary Interoperability tests with Sectigo Public Server Authentication ++ * Root E46 ++ * @library /test/lib ++ * @build jtreg.SkippedException ValidatePathWithURL CAInterop ++ * @run main/othervm/manual -Djava.security.debug=certpath,ocsp CAInterop ++ * sectigotlsroote46 OCSP ++ * @run main/othervm/manual -Djava.security.debug=certpath,ocsp ++ * -Dcom.sun.security.ocsp.useget=false CAInterop sectigotlsroote46 OCSP ++ * @run main/othervm/manual -Djava.security.debug=certpath CAInterop ++ * sectigotlsroote46 CRL ++ */ + -+ LoongArch64Kind(int size) { -+ this.size = size; -+ this.scalar = this; -+ this.vectorLength = 1; -+ } + /** + * Collection of certificate validation tests for interoperability with external CAs. + * These tests are marked as manual as they depend on external infrastructure and may fail +@@ -583,20 +573,20 @@ public class CAInterop { + "https://revoked.sfig2.catest.starfieldtech.com"); + + case "globalsigneccrootcar4": +- return new CATestURLs("https://good.gsr4.demo.pki.goog", +- "https://revoked.gsr4.demo.pki.goog"); ++ return new CATestURLs("https://good.gsr4.demosite.pki.goog", ++ "https://revoked.gsr4.demosite.pki.goog"); + case "gtsrootcar1": +- return new CATestURLs("https://good.gtsr1.demo.pki.goog", +- "https://revoked.gtsr1.demo.pki.goog"); ++ return new CATestURLs("https://good.gtsr1.demosite.pki.goog", ++ "https://revoked.gtsr1.demosite.pki.goog"); + case "gtsrootcar2": +- return new CATestURLs("https://good.gtsr2.demo.pki.goog", +- "https://revoked.gtsr2.demo.pki.goog"); ++ return new CATestURLs("https://good.gtsr2.demosite.pki.goog", ++ "https://revoked.gtsr2.demosite.pki.goog"); + case "gtsrootecccar3": +- return new CATestURLs("https://good.gtsr3.demo.pki.goog", +- "https://revoked.gtsr3.demo.pki.goog"); ++ return new CATestURLs("https://good.gtsr3.demosite.pki.goog", ++ "https://revoked.gtsr3.demosite.pki.goog"); + case "gtsrootecccar4": +- return new CATestURLs("https://good.gtsr4.demo.pki.goog", +- "https://revoked.gtsr4.demo.pki.goog"); ++ return new CATestURLs("https://good.gtsr4.demosite.pki.goog", ++ "https://revoked.gtsr4.demosite.pki.goog"); + + case "microsoftecc2017": + return new CATestURLs("https://acteccroot2017.pki.microsoft.com", +@@ -648,20 +638,6 @@ public class CAInterop { + return new CATestURLs("https://juolukka.cover.telia.fi:10600", + "https://juolukka.cover.telia.fi:10601"); + +- // These are listed at https://www.affirmtrust.com/resources/ +- case "affirmtrustcommercialca": +- return new CATestURLs("https://validcommercial.affirmtrust.com", +- "https://revokedcommercial.affirmtrust.com"); +- case "affirmtrustnetworkingca": +- return new CATestURLs("https://validnetworking.affirmtrust.com", +- "https://revokednetworking.affirmtrust.com"); +- case "affirmtrustpremiumca": +- return new CATestURLs("https://validpremium.affirmtrust.com", +- "https://revokedpremium.affirmtrust.com"); +- case "affirmtrustpremiumeccca": +- return new CATestURLs("https://validpremiumecc.affirmtrust.com", +- "https://revokedpremiumecc.affirmtrust.com"); +- + case "emsignrootcag1": + return new CATestURLs("https://testovg1.emsign.com/RootOVG1.html", + "https://testovg1r.emsign.com/RootOVG1MR.html"); +@@ -690,6 +666,13 @@ public class CAInterop { + return new CATestURLs("https://test-root-2022-rsa.ssl.com", + "https://revoked-root-2022-rsa.ssl.com"); + ++ case "sectigotlsrootr46": ++ return new CATestURLs("https://sectigopublicserverauthenticationrootr46-ev.sectigo.com", ++ "https://sectigopublicserverauthenticationrootr46-ev.sectigo.com:444"); ++ case "sectigotlsroote46": ++ return new CATestURLs("https://sectigopublicserverauthenticationroote46-ev.sectigo.com", ++ "https://sectigopublicserverauthenticationroote46-ev.sectigo.com:444"); ++ + default: throw new RuntimeException("No test setup found for: " + alias); + } + } +diff --git a/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/SectigoCSRootCAs.java b/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/SectigoCSRootCAs.java +new file mode 100644 +index 000000000..80cd1d41c +--- /dev/null ++++ b/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/SectigoCSRootCAs.java +@@ -0,0 +1,310 @@ ++/* ++ * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. ++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. ++ * ++ * This code is free software; you can redistribute it and/or modify it ++ * 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. ++ */ + -+ LoongArch64Kind(int size, LoongArch64Kind scalar) { -+ this.size = size; -+ this.scalar = scalar; ++/* ++ * @test ++ * @bug 8359170 ++ * @summary Interoperability tests with Sectigo Public Code Signing Root CAs ++ * @build ValidatePathWithParams ++ * @run main/othervm/manual -Djava.security.debug=ocsp,certpath SectigoCSRootCAs OCSP ++ * @run main/othervm/manual -Djava.security.debug=certpath SectigoCSRootCAs CRL ++ */ + -+ assert size % scalar.size == 0; -+ this.vectorLength = size / scalar.size; -+ } ++public class SectigoCSRootCAs { + -+ public LoongArch64Kind getScalar() { -+ return scalar; -+ } ++ public static void main(String[] args) throws Exception { + -+ @Override -+ public int getSizeInBytes() { -+ return size; -+ } ++ ValidatePathWithParams pathValidator = new ValidatePathWithParams(null); + -+ @Override -+ public int getVectorLength() { -+ return vectorLength; -+ } ++ if (args.length >= 1 && "CRL".equalsIgnoreCase(args[0])) { ++ pathValidator.enableCRLCheck(); ++ } else { ++ // OCSP check by default ++ pathValidator.enableOCSPCheck(); ++ } + -+ @Override -+ public Key getKey() { -+ return key; -+ } ++ new SectigoCSRootCA_R46().runTest(pathValidator); ++ new SectigoCSRootCA_E46().runTest(pathValidator); ++ } ++} ++ ++class SectigoCSRootCA_R46 { ++ ++ // Owner: CN=Sectigo Public Code Signing CA R36, O=Sectigo Limited, C=GB ++ // Issuer: CN=Sectigo Public Code Signing Root R46, O=Sectigo Limited, C=GB ++ // Serial number: 621d6d0c52019e3b9079152089211c0a ++ // Valid from: Sun Mar 21 17:00:00 PDT 2021 until: Fri Mar 21 16:59:59 ++ // PDT 2036 ++ private static final String INT = "-----BEGIN CERTIFICATE-----\n" + ++ "MIIGGjCCBAKgAwIBAgIQYh1tDFIBnjuQeRUgiSEcCjANBgkqhkiG9w0BAQwFADBW\n" + ++ "MQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMS0wKwYDVQQD\n" + ++ "EyRTZWN0aWdvIFB1YmxpYyBDb2RlIFNpZ25pbmcgUm9vdCBSNDYwHhcNMjEwMzIy\n" + ++ "MDAwMDAwWhcNMzYwMzIxMjM1OTU5WjBUMQswCQYDVQQGEwJHQjEYMBYGA1UEChMP\n" + ++ "U2VjdGlnbyBMaW1pdGVkMSswKQYDVQQDEyJTZWN0aWdvIFB1YmxpYyBDb2RlIFNp\n" + ++ "Z25pbmcgQ0EgUjM2MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAmyud\n" + ++ "U/o1P45gBkNqwM/1f/bIU1MYyM7TbH78WAeVF3llMwsRHgBGRmxDeEDIArCS2VCo\n" + ++ "Vk4Y/8j6stIkmYV5Gej4NgNjVQ4BYoDjGMwdjioXan1hlaGFt4Wk9vT0k2oWJMJj\n" + ++ "L9G//N523hAm4jF4UjrW2pvv9+hdPX8tbbAfI3v0VdJiJPFy/7XwiunD7mBxNtec\n" + ++ "M6ytIdUlh08T2z7mJEXZD9OWcJkZk5wDuf2q52PN43jc4T9OkoXZ0arWZVeffvMr\n" + ++ "/iiIROSCzKoDmWABDRzV/UiQ5vqsaeFaqQdzFf4ed8peNWh1OaZXnYvZQgWx/SXi\n" + ++ "JDRSAolRzZEZquE6cbcH747FHncs/Kzcn0Ccv2jrOW+LPmnOyB+tAfiWu01TPhCr\n" + ++ "9VrkxsHC5qFNxaThTG5j4/Kc+ODD2dX/fmBECELcvzUHf9shoFvrn35XGf2RPaNT\n" + ++ "O2uSZ6n9otv7jElspkfK9qEATHZcodp+R4q2OIypxR//YEb3fkDn3UayWW9bAgMB\n" + ++ "AAGjggFkMIIBYDAfBgNVHSMEGDAWgBQy65Ka/zWWSC8oQEJwIDaRXBeF5jAdBgNV\n" + ++ "HQ4EFgQUDyrLIIcouOxvSK4rVKYpqhekzQwwDgYDVR0PAQH/BAQDAgGGMBIGA1Ud\n" + ++ "EwEB/wQIMAYBAf8CAQAwEwYDVR0lBAwwCgYIKwYBBQUHAwMwGwYDVR0gBBQwEjAG\n" + ++ "BgRVHSAAMAgGBmeBDAEEATBLBgNVHR8ERDBCMECgPqA8hjpodHRwOi8vY3JsLnNl\n" + ++ "Y3RpZ28uY29tL1NlY3RpZ29QdWJsaWNDb2RlU2lnbmluZ1Jvb3RSNDYuY3JsMHsG\n" + ++ "CCsGAQUFBwEBBG8wbTBGBggrBgEFBQcwAoY6aHR0cDovL2NydC5zZWN0aWdvLmNv\n" + ++ "bS9TZWN0aWdvUHVibGljQ29kZVNpZ25pbmdSb290UjQ2LnA3YzAjBggrBgEFBQcw\n" + ++ "AYYXaHR0cDovL29jc3Auc2VjdGlnby5jb20wDQYJKoZIhvcNAQEMBQADggIBAAb/\n" + ++ "guF3YzZue6EVIJsT/wT+mHVEYcNWlXHRkT+FoetAQLHI1uBy/YXKZDk8+Y1LoNqH\n" + ++ "rp22AKMGxQtgCivnDHFyAQ9GXTmlk7MjcgQbDCx6mn7yIawsppWkvfPkKaAQsiqa\n" + ++ "T9DnMWBHVNIabGqgQSGTrQWo43MOfsPynhbz2Hyxf5XWKZpRvr3dMapandPfYgoZ\n" + ++ "8iDL2OR3sYztgJrbG6VZ9DoTXFm1g0Rf97Aaen1l4c+w3DC+IkwFkvjFV3jS49ZS\n" + ++ "c4lShKK6BrPTJYs4NG1DGzmpToTnwoqZ8fAmi2XlZnuchC4NPSZaPATHvNIzt+z1\n" + ++ "PHo35D/f7j2pO1S8BCysQDHCbM5Mnomnq5aYcKCsdbh0czchOm8bkinLrYrKpii+\n" + ++ "Tk7pwL7TjRKLXkomm5D1Umds++pip8wH2cQpf93at3VDcOK4N7EwoIJB0kak6pSz\n" + ++ "Eu4I64U6gZs7tS/dGNSljf2OSSnRr7KWzq03zl8l75jy+hOds9TWSenLbjBQUGR9\n" + ++ "6cFr6lEUfAIEHVC1L68Y1GGxx4/eRI82ut83axHMViw1+sVpbPxg51Tbnio1lB93\n" + ++ "079WPFnYaOvfGAA0e0zcfF/M9gXr+korwQTh2Prqooq2bYNMvUoUKD85gnJ+t0sm\n" + ++ "rWrb8dee2CvYZXD5laGtaAxOfy/VKNmwuWuAh9kc\n" + ++ "-----END CERTIFICATE-----"; ++ ++ // Owner: CN=Sectigo Limited, O=Sectigo Limited, ST=West Yorkshire, C=GB ++ // Issuer: CN=Sectigo Public Code Signing CA R36, O=Sectigo Limited, C=GB ++ // Serial number: c1de046377578f1605414f3fa91bf5f6 ++ // Valid from: Wed Jun 04 17:00:00 PDT 2025 until: Fri Jun 05 16:59:59 ++ // PDT 2026 ++ private static final String VALID = "-----BEGIN CERTIFICATE-----\n" + ++ "MIIGRDCCBKygAwIBAgIRAMHeBGN3V48WBUFPP6kb9fYwDQYJKoZIhvcNAQEMBQAw\n" + ++ "VDELMAkGA1UEBhMCR0IxGDAWBgNVBAoTD1NlY3RpZ28gTGltaXRlZDErMCkGA1UE\n" + ++ "AxMiU2VjdGlnbyBQdWJsaWMgQ29kZSBTaWduaW5nIENBIFIzNjAeFw0yNTA2MDUw\n" + ++ "MDAwMDBaFw0yNjA2MDUyMzU5NTlaMFoxCzAJBgNVBAYTAkdCMRcwFQYDVQQIDA5X\n" + ++ "ZXN0IFlvcmtzaGlyZTEYMBYGA1UECgwPU2VjdGlnbyBMaW1pdGVkMRgwFgYDVQQD\n" + ++ "DA9TZWN0aWdvIExpbWl0ZWQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC\n" + ++ "AQDCYjakgsoYkqVpENW0MuN5hBZDdIM60WJgBXU7zTAXORntSu/Grn/SQywwTg4o\n" + ++ "ltRcKuCp0Cd5zLAIjtgpVDDACWHgxKUtxerjjBZeGp0+viR+biLL0mVNPXgZZ5bQ\n" + ++ "AnDYVKJaGnPsXQD8l+Bn/R2c4cw7mXjBYp2KrTuqOBkPzk4LmdgpKXjxiw1yYb+n\n" + ++ "WKZ+3BMLIU6/k+LB9+WB6Odrl4Lff1jB4C6XhQELGjZAbpkFB2+Qr0ajIA3ZFXqU\n" + ++ "IMh0j5oD5juuXxryOvCgSBkEwxPHnlXxZBNd3DmrZ9NGClBIGE2f9FOjzo5Rl7lV\n" + ++ "KlzFdFmcH8LaLtWjniF+iT+YZw3Ld1O9VMK7RaHePsS4JYfbjeapoCEgudecmIz4\n" + ++ "5Q2tTjCdR5s/SxiVbynfEw+cAGeiv4sRXNSg0uhZ2eGMHh6mPley2pUoRMR8Qx1U\n" + ++ "0Uzg2NtPsHAo0DIH3jKEWU2zP5UPwCfqKYGaZLNLeGh07NZHBCp3TGp9kPVen5Ib\n" + ++ "tnJssu+pab7fixvbpDM4/r9MkKU6C1IsE6lffyON0PA6LaywwecYTJGpieXqoz03\n" + ++ "5UmQXvAzkb9omIAcQ6yWMZNrqwwG9XRKQEhvG3v7sbFkck1KZOz4r/KHkLx9sIxm\n" + ++ "vngdD/qLFebxPIvPT0GKnvSzuGcdQXVTdkZBBBrunv+XpQIDAQABo4IBiTCCAYUw\n" + ++ "HwYDVR0jBBgwFoAUDyrLIIcouOxvSK4rVKYpqhekzQwwHQYDVR0OBBYEFGMpbbJO\n" + ++ "xiuD6t+HEyA3hjp4devXMA4GA1UdDwEB/wQEAwIHgDAMBgNVHRMBAf8EAjAAMBMG\n" + ++ "A1UdJQQMMAoGCCsGAQUFBwMDMEoGA1UdIARDMEEwNQYMKwYBBAGyMQECAQMCMCUw\n" + ++ "IwYIKwYBBQUHAgEWF2h0dHBzOi8vc2VjdGlnby5jb20vQ1BTMAgGBmeBDAEEATBJ\n" + ++ "BgNVHR8EQjBAMD6gPKA6hjhodHRwOi8vY3JsLnNlY3RpZ28uY29tL1NlY3RpZ29Q\n" + ++ "dWJsaWNDb2RlU2lnbmluZ0NBUjM2LmNybDB5BggrBgEFBQcBAQRtMGswRAYIKwYB\n" + ++ "BQUHMAKGOGh0dHA6Ly9jcnQuc2VjdGlnby5jb20vU2VjdGlnb1B1YmxpY0NvZGVT\n" + ++ "aWduaW5nQ0FSMzYuY3J0MCMGCCsGAQUFBzABhhdodHRwOi8vb2NzcC5zZWN0aWdv\n" + ++ "LmNvbTANBgkqhkiG9w0BAQwFAAOCAYEAP2OCzJ+0hrg4XK3w+Ypoe0G5hKfzZ9RH\n" + ++ "nDcgY8BjgWYVOlN9ad2bU70RfgkZzylkaSt02KHOpkXmYpgfjZsovmyUchvlZ4fU\n" + ++ "RmivZleuO3G/ZvDFX373S40QFDd+lC1LYYUolRVz7/ZU2Vzql4FxsM1psRaW17xj\n" + ++ "jf9qaAvDlOH45eEEkfRUbIDdn1UYqDxdCN+90jtD1vRWkYINvE1T6mq3rHpEVoTS\n" + ++ "dIOgmcSL3MAKMB0LxWUPfoVdhnoUuoIxIAcV1SuR6zej4wHjClEaR8ReT/C23Jr3\n" + ++ "hQ4VDbfGu3gvlZG8/+lNmT+t4WaNPECxbFP0BgbD70FP594mSVH3fgptYiiRN7ez\n" + ++ "iUfOSBeCZpSMm7Z5P0KkxkagyFIR3vzgvqbJS/iaomvd9ZIkd9AwMEhugJpITeZj\n" + ++ "lKSXs+2q2UHQdLTPGVoOjmqyPhDGKAeVVF+jLIUWwtAaAoJm6ooXSp8sAeLA+e+K\n" + ++ "6RUFETVxhCefCjkbWq64OYLXriDb0l+W\n" + ++ "-----END CERTIFICATE-----"; ++ ++ // Owner: CN=Sectigo Limited, O=Sectigo Limited, ST=West Yorkshire, C=GB ++ // Issuer: CN=Sectigo Public Code Signing CA R36, O=Sectigo Limited, C=GB ++ // Serial number: 5ca6fb60da04db99dedbbc0c37131ec ++ // Valid from: Wed Jun 04 17:00:00 PDT 2025 until: Sun Jun 04 16:59:59 ++ // PDT 2028 ++ private static final String REVOKED = "-----BEGIN CERTIFICATE-----\n" + ++ "MIIGQzCCBKugAwIBAgIQBcpvtg2gTbmd7bvAw3Ex7DANBgkqhkiG9w0BAQwFADBU\n" + ++ "MQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMSswKQYDVQQD\n" + ++ "EyJTZWN0aWdvIFB1YmxpYyBDb2RlIFNpZ25pbmcgQ0EgUjM2MB4XDTI1MDYwNTAw\n" + ++ "MDAwMFoXDTI4MDYwNDIzNTk1OVowWjELMAkGA1UEBhMCR0IxFzAVBgNVBAgMDldl\n" + ++ "c3QgWW9ya3NoaXJlMRgwFgYDVQQKDA9TZWN0aWdvIExpbWl0ZWQxGDAWBgNVBAMM\n" + ++ "D1NlY3RpZ28gTGltaXRlZDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB\n" + ++ "ALDjoFCMN16zlrcv/saieSYT7FXEhTVDPLNzGAbNdBEX09FoL5EIkiN3biVIbDki\n" + ++ "bIocCFpo/yTrjARG/zz82AjdWHyomdtDjL35CQmgiUX7V8tu64xUfUAgadqm+0PL\n" + ++ "by1LRddKE7chpdJu+EDEmeYDPqcRGM+u8suPgosFf6XfVNFy/FZJiD1c7q6JNZ8i\n" + ++ "5NrvTs0zA9HckKE3uvPO9rw56EyF3SfUz9+zHKHwSElv8nCYpREudUf4yCzPNisK\n" + ++ "MVovzeCo36nzJFEdWTnDOr4mtvfCEGvJOU3mgzpECK7QF+yFifr90SG4lvrwzkig\n" + ++ "wYQymukXmB2gxN1tGOvgLig3Q/b4vljBiEeRPEba/L8YQnaXpR/BnPze8yb2t39l\n" + ++ "bzmnghkWkGA0PAB2vrzpi7pq12fGOD0+ErtAzAl/TAD/UFWwXDQLWX9LXRRKi5E+\n" + ++ "ScTlqLl9U1q9HsWYfM6CvLbc32TByaQ8yBytvsSRB0C0blp7CtP5MAc8j9xJdwAs\n" + ++ "Mj2bvSOfA+NJ0Kdg/tqdHHU6hex2HnGzDiEhovm6u/oAfDp/i2bBKLgARglMfGaC\n" + ++ "hFWeHLL6GAyBezMv+AQNCDCTYDMlqAihVMRUAfYgoHcVCfvTSETTTGdRUDFzIdCA\n" + ++ "wNwSVfykpadsev43I2IF+F3aNgJYuXnpxSCLPngemcgxAgMBAAGjggGJMIIBhTAf\n" + ++ "BgNVHSMEGDAWgBQPKssghyi47G9IritUpimqF6TNDDAdBgNVHQ4EFgQUlff/C/GC\n" + ++ "faJ+Y7ua3hKsCsrW9y4wDgYDVR0PAQH/BAQDAgeAMAwGA1UdEwEB/wQCMAAwEwYD\n" + ++ "VR0lBAwwCgYIKwYBBQUHAwMwSgYDVR0gBEMwQTA1BgwrBgEEAbIxAQIBAwIwJTAj\n" + ++ "BggrBgEFBQcCARYXaHR0cHM6Ly9zZWN0aWdvLmNvbS9DUFMwCAYGZ4EMAQQBMEkG\n" + ++ "A1UdHwRCMEAwPqA8oDqGOGh0dHA6Ly9jcmwuc2VjdGlnby5jb20vU2VjdGlnb1B1\n" + ++ "YmxpY0NvZGVTaWduaW5nQ0FSMzYuY3JsMHkGCCsGAQUFBwEBBG0wazBEBggrBgEF\n" + ++ "BQcwAoY4aHR0cDovL2NydC5zZWN0aWdvLmNvbS9TZWN0aWdvUHVibGljQ29kZVNp\n" + ++ "Z25pbmdDQVIzNi5jcnQwIwYIKwYBBQUHMAGGF2h0dHA6Ly9vY3NwLnNlY3RpZ28u\n" + ++ "Y29tMA0GCSqGSIb3DQEBDAUAA4IBgQAfVq3mY7ggMcTJeWKKrGxs9RUiuAY0p4Xv\n" + ++ "CHNQViM/tHAn0t/nkPp+d2Ji3Zr6PefN+1F6zmsxsbZHse52JNHWYUwCb/Dx4Vw6\n" + ++ "3Wnc1zhXtZnvUTUfgrivuIsMjUG8yzTdEt/taMKEO0KqlKPsBPgFKveDVVaq9UZa\n" + ++ "FfxTWqgrnvkvP/Lag/YeKKj4cJG+a/MJZJm7kvyaBNKXVAamr/bumoxKDzpD67ds\n" + ++ "n9qwBi2Mv0rRXvZ2SHQXzsJ/zjNKWUhpPVrpypaER7EUxjNuSgC4L8AmfvHiO67v\n" + ++ "9EVIEud+beP3FtCXl/cSHhVeDxiC0KBXXBl9zLBaYvCH+8iABnZLStLgBDtfdkfk\n" + ++ "TZEAGbrNOXJDMnKRxr8y377Zq+KHwfiTnyizACHyMMTi+CCwg1ZFGcLOHa5shByc\n" + ++ "Ln9lYysM1/5vrEjt3ZUw11+pDqbPCGS++xgAwcftKfJ0TZrW/g6NZ9URg+11H9ad\n" + ++ "WalBv2VkhJAFJam9P2Y+pi9luk85sGo=\n" + ++ "-----END CERTIFICATE-----"; ++ ++ public void runTest(ValidatePathWithParams pathValidator) throws Exception { ++ // Validate valid ++ pathValidator.validate(new String[]{VALID, INT}, ++ ValidatePathWithParams.Status.GOOD, null, System.out); ++ ++ // Validate Revoked ++ pathValidator.validate(new String[]{REVOKED, INT}, ++ ValidatePathWithParams.Status.REVOKED, ++ "Thu Jun 05 10:27:45 PDT 2025", System.out); ++ } ++} ++ ++class SectigoCSRootCA_E46 { ++ ++ // Owner: CN=Sectigo Public Code Signing CA EV E36, O=Sectigo Limited, C=GB ++ // Issuer: CN=Sectigo Public Code Signing Root E46, O=Sectigo Limited, C=GB ++ // Serial number: 3774434f9eb40e221f9236ca1f2f2717 ++ // Valid from: Sun Mar 21 17:00:00 PDT 2021 until: Fri Mar 21 16:59:59 ++ // PDT 2036 ++ private static final String INT_VALID = "-----BEGIN CERTIFICATE-----\n" + ++ "MIIDMDCCAragAwIBAgIQN3RDT560DiIfkjbKHy8nFzAKBggqhkjOPQQDAzBWMQsw\n" + ++ "CQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMS0wKwYDVQQDEyRT\n" + ++ "ZWN0aWdvIFB1YmxpYyBDb2RlIFNpZ25pbmcgUm9vdCBFNDYwHhcNMjEwMzIyMDAw\n" + ++ "MDAwWhcNMzYwMzIxMjM1OTU5WjBXMQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2Vj\n" + ++ "dGlnbyBMaW1pdGVkMS4wLAYDVQQDEyVTZWN0aWdvIFB1YmxpYyBDb2RlIFNpZ25p\n" + ++ "bmcgQ0EgRVYgRTM2MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE3mMV9nNViYoH\n" + ++ "4aSrPwFjpbbeXHw2pMbqezwDGb45uEZQr3qI9Hgt0k4R26o5upfXzJt03F8efu0r\n" + ++ "RNEs4yDDz6OCAWMwggFfMB8GA1UdIwQYMBaAFM99LKCQepgd3bZehcLg2hVx0uVe\n" + ++ "MB0GA1UdDgQWBBQadKQ417m2DrNb+txerj+28HM9iDAOBgNVHQ8BAf8EBAMCAYYw\n" + ++ "EgYDVR0TAQH/BAgwBgEB/wIBADATBgNVHSUEDDAKBggrBgEFBQcDAzAaBgNVHSAE\n" + ++ "EzARMAYGBFUdIAAwBwYFZ4EMAQMwSwYDVR0fBEQwQjBAoD6gPIY6aHR0cDovL2Ny\n" + ++ "bC5zZWN0aWdvLmNvbS9TZWN0aWdvUHVibGljQ29kZVNpZ25pbmdSb290RTQ2LmNy\n" + ++ "bDB7BggrBgEFBQcBAQRvMG0wRgYIKwYBBQUHMAKGOmh0dHA6Ly9jcnQuc2VjdGln\n" + ++ "by5jb20vU2VjdGlnb1B1YmxpY0NvZGVTaWduaW5nUm9vdEU0Ni5wN2MwIwYIKwYB\n" + ++ "BQUHMAGGF2h0dHA6Ly9vY3NwLnNlY3RpZ28uY29tMAoGCCqGSM49BAMDA2gAMGUC\n" + ++ "MQCger3L4CYx2W7HyHzvLaAnNee9QVqOwOrBYZyyqXERLtZg1DscsdoYZ2gszEW3\n" + ++ "zaUCMAaLtcwdoV35ADpru29wChS7kFgXt599Ex27wmL++uJCJth6xYr3nyF2b2YJ\n" + ++ "DAatOw==\n" + ++ "-----END CERTIFICATE-----"; ++ ++ // Owner: CN=Sectigo Public Code Signing CA E36, O=Sectigo Limited, C=GB ++ // Issuer: CN=Sectigo Public Code Signing Root E46, O=Sectigo Limited, C=GB ++ // Serial number: 3602617636e7034b9cc1fc5ffeac2d54 ++ // Valid from: Sun Mar 21 17:00:00 PDT 2021 until: Fri Mar 21 16:59:59 ++ // PDT 2036 ++ private static final String INT_REVOKED = "-----BEGIN CERTIFICATE-----\n" + ++ "MIIDLjCCArSgAwIBAgIQNgJhdjbnA0ucwfxf/qwtVDAKBggqhkjOPQQDAzBWMQsw\n" + ++ "CQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMS0wKwYDVQQDEyRT\n" + ++ "ZWN0aWdvIFB1YmxpYyBDb2RlIFNpZ25pbmcgUm9vdCBFNDYwHhcNMjEwMzIyMDAw\n" + ++ "MDAwWhcNMzYwMzIxMjM1OTU5WjBUMQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2Vj\n" + ++ "dGlnbyBMaW1pdGVkMSswKQYDVQQDEyJTZWN0aWdvIFB1YmxpYyBDb2RlIFNpZ25p\n" + ++ "bmcgQ0EgRTM2MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAElDe1m6jawDhrwMxJ\n" + ++ "yFPhKYf8EGu+lBw3bF5CzmfaH1I7Zi+WAmkeEwS3tiNxzPh8GbBBLtdaRuqGuyWc\n" + ++ "W6ERmaOCAWQwggFgMB8GA1UdIwQYMBaAFM99LKCQepgd3bZehcLg2hVx0uVeMB0G\n" + ++ "A1UdDgQWBBQlDZtt2Bh3t4rDOFFW5cfytf+DajAOBgNVHQ8BAf8EBAMCAYYwEgYD\n" + ++ "VR0TAQH/BAgwBgEB/wIBADATBgNVHSUEDDAKBggrBgEFBQcDAzAbBgNVHSAEFDAS\n" + ++ "MAYGBFUdIAAwCAYGZ4EMAQQBMEsGA1UdHwREMEIwQKA+oDyGOmh0dHA6Ly9jcmwu\n" + ++ "c2VjdGlnby5jb20vU2VjdGlnb1B1YmxpY0NvZGVTaWduaW5nUm9vdEU0Ni5jcmww\n" + ++ "ewYIKwYBBQUHAQEEbzBtMEYGCCsGAQUFBzAChjpodHRwOi8vY3J0LnNlY3RpZ28u\n" + ++ "Y29tL1NlY3RpZ29QdWJsaWNDb2RlU2lnbmluZ1Jvb3RFNDYucDdjMCMGCCsGAQUF\n" + ++ "BzABhhdodHRwOi8vb2NzcC5zZWN0aWdvLmNvbTAKBggqhkjOPQQDAwNoADBlAjBM\n" + ++ "ykNTSVvegC1m17yIi87qgx6QIGbw1Mw2bQ4gtOWBVb/C8ALByC1YK7yQJNLJFTkC\n" + ++ "MQCNBv3fe1eLrGELS5KQD0cEFbXGlzQ5r1mnOHePMqlK5d+rmMxff58/t6bo3QEb\n" + ++ "8SQ=\n" + ++ "-----END CERTIFICATE-----"; ++ ++ // Owner: CN=Sectigo Limited, O=Sectigo Limited, ST=West Yorkshire, C=GB, ++ // OID.2.5.4.15=Private Organization, OID.1.3.6.1.4.1.311.60.2.1.3=GB, ++ // SERIALNUMBER=04058690 ++ // Issuer: CN=Sectigo Public Code Signing CA EV E36, O=Sectigo Limited, C=GB ++ // Serial number: fa2aa131f36b337717ac73f606a6ec49 ++ // Valid from: Tue Feb 13 16:00:00 PST 2024 until: Sat Feb 13 15:59:59 ++ // PST 2027 ++ private static final String VALID = "-----BEGIN CERTIFICATE-----\n" + ++ "MIIDrjCCA1SgAwIBAgIRAPoqoTHzazN3F6xz9gam7EkwCgYIKoZIzj0EAwIwVzEL\n" + ++ "MAkGA1UEBhMCR0IxGDAWBgNVBAoTD1NlY3RpZ28gTGltaXRlZDEuMCwGA1UEAxMl\n" + ++ "U2VjdGlnbyBQdWJsaWMgQ29kZSBTaWduaW5nIENBIEVWIEUzNjAeFw0yNDAyMTQw\n" + ++ "MDAwMDBaFw0yNzAyMTMyMzU5NTlaMIGhMREwDwYDVQQFEwgwNDA1ODY5MDETMBEG\n" + ++ "CysGAQQBgjc8AgEDEwJHQjEdMBsGA1UEDxMUUHJpdmF0ZSBPcmdhbml6YXRpb24x\n" + ++ "CzAJBgNVBAYTAkdCMRcwFQYDVQQIDA5XZXN0IFlvcmtzaGlyZTEYMBYGA1UECgwP\n" + ++ "U2VjdGlnbyBMaW1pdGVkMRgwFgYDVQQDDA9TZWN0aWdvIExpbWl0ZWQwWTATBgcq\n" + ++ "hkjOPQIBBggqhkjOPQMBBwNCAASwXGEU01WkW/hWNYza08ZT7i0ZeZ9M1s93JYEB\n" + ++ "rZ/f1Ho1YzxtToqgIK2o+32afablPFYWlE6wGyuL/TYggBpKo4IBtDCCAbAwHwYD\n" + ++ "VR0jBBgwFoAUGnSkONe5tg6zW/rcXq4/tvBzPYgwHQYDVR0OBBYEFHEcsJgcYuDO\n" + ++ "dv1raL6h83a6j9C/MA4GA1UdDwEB/wQEAwIHgDAMBgNVHRMBAf8EAjAAMBMGA1Ud\n" + ++ "JQQMMAoGCCsGAQUFBwMDMEkGA1UdIARCMEAwNQYMKwYBBAGyMQECAQYBMCUwIwYI\n" + ++ "KwYBBQUHAgEWF2h0dHBzOi8vc2VjdGlnby5jb20vQ1BTMAcGBWeBDAEDMEsGA1Ud\n" + ++ "HwREMEIwQKA+oDyGOmh0dHA6Ly9jcmwuc2VjdGlnby5jb20vU2VjdGlnb1B1Ymxp\n" + ++ "Y0NvZGVTaWduaW5nQ0FFVkUzNi5jcmwwewYIKwYBBQUHAQEEbzBtMEYGCCsGAQUF\n" + ++ "BzAChjpodHRwOi8vY3J0LnNlY3RpZ28uY29tL1NlY3RpZ29QdWJsaWNDb2RlU2ln\n" + ++ "bmluZ0NBRVZFMzYuY3J0MCMGCCsGAQUFBzABhhdodHRwOi8vb2NzcC5zZWN0aWdv\n" + ++ "LmNvbTAmBgNVHREEHzAdoBsGCCsGAQUFBwgDoA8wDQwLR0ItMDQwNTg2OTAwCgYI\n" + ++ "KoZIzj0EAwIDSAAwRQIgQVp7IIkEZNmC7GfmT1MSEhDebIjjzd75ZVEEbPP/4ocC\n" + ++ "IQDSyfPDKNMbKNOKrweDLwSE2GZV6nDWbiLz6ZmSZHob8w==\n" + ++ "-----END CERTIFICATE-----"; ++ ++ // Owner: CN=Sectigo Limited, O=Sectigo Limited, ST=West Yorkshire, C=GB ++ // Issuer: CN=Sectigo Public Code Signing CA E36, O=Sectigo Limited, C=GB ++ // Serial number: a1f601514271f24ca0a31c0d7b856705 ++ // Valid from: Wed Jun 04 17:00:00 PDT 2025 until: Sun Jun 04 16:59:59 ++ // PDT 2028 ++ private static final String REVOKED = "-----BEGIN CERTIFICATE-----\n" + ++ "MIIDOTCCAt6gAwIBAgIRAKH2AVFCcfJMoKMcDXuFZwUwCgYIKoZIzj0EAwIwVDEL\n" + ++ "MAkGA1UEBhMCR0IxGDAWBgNVBAoTD1NlY3RpZ28gTGltaXRlZDErMCkGA1UEAxMi\n" + ++ "U2VjdGlnbyBQdWJsaWMgQ29kZSBTaWduaW5nIENBIEUzNjAeFw0yNTA2MDUwMDAw\n" + ++ "MDBaFw0yODA2MDQyMzU5NTlaMFoxCzAJBgNVBAYTAkdCMRcwFQYDVQQIDA5XZXN0\n" + ++ "IFlvcmtzaGlyZTEYMBYGA1UECgwPU2VjdGlnbyBMaW1pdGVkMRgwFgYDVQQDDA9T\n" + ++ "ZWN0aWdvIExpbWl0ZWQwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASwXGEU01Wk\n" + ++ "W/hWNYza08ZT7i0ZeZ9M1s93JYEBrZ/f1Ho1YzxtToqgIK2o+32afablPFYWlE6w\n" + ++ "GyuL/TYggBpKo4IBiTCCAYUwHwYDVR0jBBgwFoAUJQ2bbdgYd7eKwzhRVuXH8rX/\n" + ++ "g2owHQYDVR0OBBYEFHEcsJgcYuDOdv1raL6h83a6j9C/MA4GA1UdDwEB/wQEAwIH\n" + ++ "gDAMBgNVHRMBAf8EAjAAMBMGA1UdJQQMMAoGCCsGAQUFBwMDMEoGA1UdIARDMEEw\n" + ++ "NQYMKwYBBAGyMQECAQMCMCUwIwYIKwYBBQUHAgEWF2h0dHBzOi8vc2VjdGlnby5j\n" + ++ "b20vQ1BTMAgGBmeBDAEEATBJBgNVHR8EQjBAMD6gPKA6hjhodHRwOi8vY3JsLnNl\n" + ++ "Y3RpZ28uY29tL1NlY3RpZ29QdWJsaWNDb2RlU2lnbmluZ0NBRTM2LmNybDB5Bggr\n" + ++ "BgEFBQcBAQRtMGswRAYIKwYBBQUHMAKGOGh0dHA6Ly9jcnQuc2VjdGlnby5jb20v\n" + ++ "U2VjdGlnb1B1YmxpY0NvZGVTaWduaW5nQ0FFMzYuY3J0MCMGCCsGAQUFBzABhhdo\n" + ++ "dHRwOi8vb2NzcC5zZWN0aWdvLmNvbTAKBggqhkjOPQQDAgNJADBGAiEAlEkiISLz\n" + ++ "PdJsFmVzJ2VZ8hnnVsOBXKbqISFQvIdguJoCIQCH4T0vwxn6uVkJpMvtxiMG/rYg\n" + ++ "jRFhfbxDcVee6likOw==\n" + ++ "-----END CERTIFICATE-----"; ++ ++ public void runTest(ValidatePathWithParams pathValidator) throws Exception { ++ // Validate valid ++ pathValidator.validate(new String[]{VALID, INT_VALID}, ++ ValidatePathWithParams.Status.GOOD, null, System.out); ++ ++ // Validate Revoked ++ pathValidator.validate(new String[]{REVOKED, INT_REVOKED}, ++ ValidatePathWithParams.Status.REVOKED, ++ "Thu Jun 05 10:27:19 PDT 2025", System.out); ++ } ++} +diff --git a/test/jdk/sun/net/www/B8185898.java b/test/jdk/sun/net/www/B8185898.java +index cfa54e15a..c78df56f7 100644 +--- a/test/jdk/sun/net/www/B8185898.java ++++ b/test/jdk/sun/net/www/B8185898.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2019, 2024, 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,7 +23,7 @@ + + /** + * @test +- * @bug 8185898 8163921 ++ * @bug 8185898 8163921 8339470 + * @modules java.base/sun.net.www + * @library /test/lib + * @run main/othervm B8185898 +@@ -143,32 +143,32 @@ public class B8185898 { + // {{inputString1, expectedToString1, expectedPrint1}, {...}} + String[][] strings = { + {"HTTP/1.1 200 OK\r\n" +- + "Accept: */*\r\n" ++ + "Accept: text/html, image/gif, image/jpeg, */*; q=0.2\r\n" + + "Connection: keep-alive\r\n" + + "Host: 127.0.0.1:12345\r\n" + + "User-agent: Java/12\r\n\r\nfoooo", + "pairs: {null: HTTP/1.1 200 OK}" +- + "{Accept: */*}" ++ + "{Accept: text/html, image/gif, image/jpeg, */*; q=0.2}" + + "{Connection: keep-alive}" + + "{Host: 127.0.0.1:12345}" + + "{User-agent: Java/12}", +- "Accept: */*\r\n" ++ "Accept: text/html, image/gif, image/jpeg, */*; q=0.2\r\n" + + "Connection: keep-alive\r\n" + + "Host: 127.0.0.1:12345\r\n" + + "User-agent: Java/12\r\n\r\n"}, + {"HTTP/1.1 200 OK\r\n" +- + "Accept: */*\r\n" ++ + "Accept: text/html, image/gif, image/jpeg, */*; q=0.2\r\n" + + "Connection: keep-alive\r\n" + + "Host: 127.0.0.1:12345\r\n" + + "User-agent: Java/12\r\n" + + "X-Header:\r\n\r\n", + "pairs: {null: HTTP/1.1 200 OK}" +- + "{Accept: */*}" ++ + "{Accept: text/html, image/gif, image/jpeg, */*; q=0.2}" + + "{Connection: keep-alive}" + + "{Host: 127.0.0.1:12345}" + + "{User-agent: Java/12}" + + "{X-Header: }", +- "Accept: */*\r\n" ++ "Accept: text/html, image/gif, image/jpeg, */*; q=0.2\r\n" + + "Connection: keep-alive\r\n" + + "Host: 127.0.0.1:12345\r\n" + + "User-agent: Java/12\r\n" +diff --git a/test/jdk/sun/security/lib/cacerts/VerifyCACerts.java b/test/jdk/sun/security/lib/cacerts/VerifyCACerts.java +index a0e02b323..e325d400c 100644 +--- a/test/jdk/sun/security/lib/cacerts/VerifyCACerts.java ++++ b/test/jdk/sun/security/lib/cacerts/VerifyCACerts.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -28,7 +28,7 @@ + * 8223499 8225392 8232019 8234245 8233223 8225068 8225069 8243321 8243320 + * 8243559 8225072 8258630 8259312 8256421 8225081 8225082 8225083 8245654 + * 8305975 8304760 8307134 8295894 8314960 8317373 8317374 8318759 8319187 +- * 8321408 8316138 8341057 ++ * 8321408 8316138 8341057 8303770 8350498 8359170 8361212 + * @summary Check root CA entries in cacerts file + */ + import java.io.ByteArrayInputStream; +@@ -47,12 +47,12 @@ public class VerifyCACerts { + + File.separator + "security" + File.separator + "cacerts"; + + // The numbers of certs now. +- private static final int COUNT = 112; ++ private static final int COUNT = 109; + + // SHA-256 of cacerts, can be generated with + // shasum -a 256 cacerts | sed -e 's/../&:/g' | tr '[:lower:]' '[:upper:]' | cut -c1-95 + private static final String CHECKSUM +- = "8F:E0:6F:7F:21:59:33:A6:43:F3:48:FD:A3:4A:8E:28:35:AA:DD:6E:A5:43:56:F1:28:34:48:DF:5C:D2:7C:72"; ++ = "F2:0C:60:47:49:FA:13:2A:03:A4:52:20:AD:46:7C:D0:3F:3D:A7:59:D6:27:E9:9B:CC:D4:5A:04:8D:2A:DE:9F"; + + // map of cert alias to SHA-256 fingerprint + @SuppressWarnings("serial") +@@ -66,10 +66,6 @@ public class VerifyCACerts { + "ED:F7:EB:BC:A2:7A:2A:38:4D:38:7B:7D:40:10:C6:66:E2:ED:B4:84:3E:4C:29:B4:AE:1D:5B:93:32:E6:B2:4D"); + put("camerfirmachambersca [jdk]", + "06:3E:4A:FA:C4:91:DF:D3:32:F3:08:9B:85:42:E9:46:17:D8:93:D7:FE:94:4E:10:A7:93:7E:E2:9D:96:93:C0"); +- put("camerfirmachambersignca [jdk]", +- "13:63:35:43:93:34:A7:69:80:16:A0:D3:24:DE:72:28:4E:07:9D:7B:52:20:BB:8F:BD:74:78:16:EE:BE:BA:CA"); +- put("camerfirmachamberscommerceca [jdk]", +- "0C:25:8A:12:A5:67:4A:EF:25:F2:8B:A7:DC:FA:EC:EE:A3:48:E5:41:E6:F5:CC:4E:E6:3B:71:B3:61:60:6A:C3"); + put("certumca [jdk]", + "D8:E0:FE:BC:1D:B2:E3:8D:00:94:0F:37:D2:7D:41:34:4D:99:3E:73:4B:99:D5:65:6D:97:78:D4:D8:14:36:24"); + put("certumtrustednetworkca [jdk]", +@@ -92,8 +88,6 @@ public class VerifyCACerts { + "68:7F:A4:51:38:22:78:FF:F0:C8:B1:1F:8D:43:D5:76:67:1C:6E:B2:BC:EA:B4:13:FB:83:D9:65:D0:6D:2F:F2"); + put("addtrustqualifiedca [jdk]", + "80:95:21:08:05:DB:4B:BC:35:5E:44:28:D8:FD:6E:C2:CD:E3:AB:5F:B9:7A:99:42:98:8E:B8:F4:DC:D0:60:16"); +- put("baltimorecybertrustca [jdk]", +- "16:AF:57:A9:F6:76:B0:AB:12:60:95:AA:5E:BA:DE:F2:2A:B3:11:19:D6:44:AC:95:CD:4B:93:DB:F3:F2:6A:EB"); + put("digicertglobalrootca [jdk]", + "43:48:A0:E9:44:4C:78:CB:26:5E:05:8D:5E:89:44:B4:D8:4F:96:62:BD:26:DB:25:7F:89:34:A4:43:C7:01:61"); + put("digicertglobalrootg2 [jdk]", +@@ -196,14 +190,6 @@ public class VerifyCACerts { + "43:DF:57:74:B0:3E:7F:EF:5F:E4:0D:93:1A:7B:ED:F1:BB:2E:6B:42:73:8C:4E:6D:38:41:10:3D:3A:A7:F3:39"); + put("entrustevca [jdk]", + "73:C1:76:43:4F:1B:C6:D5:AD:F4:5B:0E:76:E7:27:28:7C:8D:E5:76:16:C1:E6:E6:14:1A:2B:2C:BC:7D:8E:4C"); +- put("affirmtrustnetworkingca [jdk]", +- "0A:81:EC:5A:92:97:77:F1:45:90:4A:F3:8D:5D:50:9F:66:B5:E2:C5:8F:CD:B5:31:05:8B:0E:17:F3:F0:B4:1B"); +- put("affirmtrustpremiumca [jdk]", +- "70:A7:3F:7F:37:6B:60:07:42:48:90:45:34:B1:14:82:D5:BF:0E:69:8E:CC:49:8D:F5:25:77:EB:F2:E9:3B:9A"); +- put("affirmtrustcommercialca [jdk]", +- "03:76:AB:1D:54:C5:F9:80:3C:E4:B2:E2:01:A0:EE:7E:EF:7B:57:B6:36:E8:A9:3C:9B:8D:48:60:C9:6F:5F:A7"); +- put("affirmtrustpremiumeccca [jdk]", +- "BD:71:FD:F6:DA:97:E4:CF:62:D1:64:7A:DD:25:81:B0:7D:79:AD:F8:39:7E:B4:EC:BA:9C:5E:84:88:82:14:23"); + put("ttelesecglobalrootclass3ca [jdk]", + "FD:73:DA:D3:1C:64:4F:F1:B4:3B:EF:0C:CD:DA:96:71:0B:9C:D9:87:5E:CA:7E:31:70:7A:F3:E9:6D:52:2B:BD"); + put("ttelesecglobalrootclass2ca [jdk]", +@@ -282,6 +268,14 @@ public class VerifyCACerts { + "C3:2F:FD:9F:46:F9:36:D1:6C:36:73:99:09:59:43:4B:9A:D6:0A:AF:BB:9E:7C:F3:36:54:F1:44:CC:1B:A1:43"); + put("ssltlsrootrsa2022 [jdk]", + "8F:AF:7D:2E:2C:B4:70:9B:B8:E0:B3:36:66:BF:75:A5:DD:45:B5:DE:48:0F:8E:A8:D4:BF:E6:BE:BC:17:F2:ED"); ++ put("sectigotlsrootr46 [jdk]", ++ "7B:B6:47:A6:2A:EE:AC:88:BF:25:7A:A5:22:D0:1F:FE:A3:95:E0:AB:45:C7:3F:93:F6:56:54:EC:38:F2:5A:06"); ++ put("sectigotlsroote46 [jdk]", ++ "C9:0F:26:F0:FB:1B:40:18:B2:22:27:51:9B:5C:A2:B5:3E:2C:A5:B3:BE:5C:F1:8E:FE:1B:EF:47:38:0C:53:83"); ++ put("sectigocodesignrootr46 [jdk]", ++ "7E:76:26:0A:E6:9A:55:D3:F0:60:B0:FD:18:B2:A8:C0:14:43:C8:7B:60:79:10:30:C9:FA:0B:05:85:10:1A:38"); ++ put("sectigocodesignroote46 [jdk]", ++ "8F:63:71:D8:CC:5A:A7:CA:14:96:67:A9:8B:54:96:39:89:51:E4:31:9F:7A:FB:CC:6A:66:0D:67:3E:43:8D:0B"); + } + }; + +diff --git a/test/jdk/sun/security/pkcs11/KeyStore/ClientAuthData/cert9.db b/test/jdk/sun/security/pkcs11/KeyStore/ClientAuthData/cert9.db +new file mode 100644 +index 000000000..f701c4fc2 +Binary files /dev/null and b/test/jdk/sun/security/pkcs11/KeyStore/ClientAuthData/cert9.db differ +diff --git a/test/jdk/sun/security/pkcs11/KeyStore/ClientAuthData/key4.db b/test/jdk/sun/security/pkcs11/KeyStore/ClientAuthData/key4.db +new file mode 100644 +index 000000000..3c489989b +Binary files /dev/null and b/test/jdk/sun/security/pkcs11/KeyStore/ClientAuthData/key4.db differ +diff --git a/test/jdk/sun/security/pkcs11/PKCS11Test.java b/test/jdk/sun/security/pkcs11/PKCS11Test.java +index 1c0c8d6dc..97e9ffe81 100644 +--- a/test/jdk/sun/security/pkcs11/PKCS11Test.java ++++ b/test/jdk/sun/security/pkcs11/PKCS11Test.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2003, 2024, 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 +@@ -56,9 +56,7 @@ import java.util.Properties; + import java.util.ServiceConfigurationError; + import java.util.ServiceLoader; + import java.util.Set; +-import java.util.regex.Matcher; +-import java.util.regex.Pattern; +-import java.util.stream.Collectors; ++import java.util.stream.Stream; + + import jdk.test.lib.Platform; + import jdk.test.lib.artifacts.Artifact; +@@ -383,19 +381,13 @@ public abstract class PKCS11Test { + + static Path getNSSLibPath(String library) throws Exception { + String osid = getOsId(); +- String nssLibDir = fetchNssLib(osid); +- if (nssLibDir == null) { ++ Path libraryName = Path.of(System.mapLibraryName(library)); ++ Path nssLibPath = fetchNssLib(osid, libraryName); ++ if (nssLibPath == null) { + throw new SkippedException("Warning: unsupported OS: " + osid + + ", please initialize NSS library location, skipping test"); + } +- +- String libraryName = System.mapLibraryName(library); +- Path libPath = Paths.get(nssLibDir).resolve(libraryName); +- if (!Files.exists(libPath)) { +- throw new SkippedException("NSS library \"" + libraryName + "\" was not found in " + nssLibDir); +- } +- +- return libPath; ++ return nssLibPath; + } + + private static String getOsId() { +@@ -834,42 +826,42 @@ public abstract class PKCS11Test { + return data; + } + +- private static String fetchNssLib(String osId) { ++ private static Path fetchNssLib(String osId, Path libraryName) { + switch (osId) { + case "Windows-amd64-64": +- return fetchNssLib(WINDOWS_X64.class); ++ return fetchNssLib(WINDOWS_X64.class, libraryName); + + case "MacOSX-x86_64-64": +- return fetchNssLib(MACOSX_X64.class); ++ return fetchNssLib(MACOSX_X64.class, libraryName); + + case "MacOSX-aarch64-64": +- return fetchNssLib(MACOSX_AARCH64.class); ++ return fetchNssLib(MACOSX_AARCH64.class, libraryName); + + case "Linux-amd64-64": + if (Platform.isOracleLinux7()) { + throw new SkippedException("Skipping Oracle Linux prior to v8"); + } else { +- return fetchNssLib(LINUX_X64.class); ++ return fetchNssLib(LINUX_X64.class, libraryName); + } + + case "Linux-aarch64-64": + if (Platform.isOracleLinux7()) { + throw new SkippedException("Skipping Oracle Linux prior to v8"); + } else { +- return fetchNssLib(LINUX_AARCH64.class); ++ return fetchNssLib(LINUX_AARCH64.class, libraryName); + } + default: + return null; + } + } + +- private static String fetchNssLib(Class clazz) { +- String path = null; ++ private static Path fetchNssLib(Class clazz, Path libraryName) { ++ Path path = null; + try { +- path = ArtifactResolver.resolve(clazz).entrySet().stream() +- .findAny().get().getValue() + File.separator + "nss" +- + File.separator + "lib" + File.separator; +- } catch (ArtifactResolverException e) { ++ Path p = ArtifactResolver.resolve(clazz).entrySet().stream() ++ .findAny().get().getValue(); ++ path = findNSSLibrary(p, libraryName); ++ } catch (ArtifactResolverException | IOException e) { + Throwable cause = e.getCause(); + if (cause == null) { + System.out.println("Cannot resolve artifact, " +@@ -883,6 +875,16 @@ public abstract class PKCS11Test { + return path; + } + ++ private static Path findNSSLibrary(Path path, Path libraryName) throws IOException { ++ try(Stream files = Files.find(path, 10, ++ (tp, attr) -> tp.getFileName().equals(libraryName))) { + -+ public boolean isInteger() { -+ switch (this) { -+ case BYTE: -+ case WORD: -+ case DWORD: -+ case QWORD: -+ case UBYTE: -+ case UWORD: -+ case UDWORD: -+ return true; -+ default: -+ return false; ++ return files.findAny() ++ .orElseThrow(() -> new SkippedException( ++ "NSS library \"" + libraryName + "\" was not found in " + path)); + } + } + -+ public boolean isSIMD() { -+ switch (this) { -+ case SINGLE: -+ case DOUBLE: -+ case V128_BYTE: -+ case V128_WORD: -+ case V128_DWORD: -+ case V128_QWORD: -+ case V128_SINGLE: -+ case V128_DOUBLE: -+ case V256_BYTE: -+ case V256_WORD: -+ case V256_DWORD: -+ case V256_QWORD: -+ case V256_SINGLE: -+ case V256_DOUBLE: -+ return true; -+ default: -+ return false; -+ } -+ } + public abstract void main(Provider p) throws Exception; + + protected boolean skipTest(Provider p) { +@@ -949,14 +951,22 @@ public abstract class PKCS11Test { + + protected void copyNssCertKeyToClassesDir(Path dbPath) throws IOException { + Path destinationPath = Path.of(TEST_CLASSES); +- String keyDbFile = "key3.db"; +- String certDbFile = "cert8.db"; ++ String keyDbFile3 = "key3.db"; ++ String keyDbFile4 = "key4.db"; ++ String certDbFile8 = "cert8.db"; ++ String certDbFile9 = "cert9.db"; + +- Files.copy(dbPath.resolve(certDbFile), +- destinationPath.resolve(certDbFile), ++ Files.copy(dbPath.resolve(certDbFile8), ++ destinationPath.resolve(certDbFile8), ++ StandardCopyOption.REPLACE_EXISTING); ++ Files.copy(dbPath.resolve(certDbFile9), ++ destinationPath.resolve(certDbFile9), ++ StandardCopyOption.REPLACE_EXISTING); ++ Files.copy(dbPath.resolve(keyDbFile3), ++ destinationPath.resolve(keyDbFile3), + StandardCopyOption.REPLACE_EXISTING); +- Files.copy(dbPath.resolve(keyDbFile), +- destinationPath.resolve(keyDbFile), ++ Files.copy(dbPath.resolve(keyDbFile4), ++ destinationPath.resolve(keyDbFile4), + StandardCopyOption.REPLACE_EXISTING); + } + +diff --git a/test/jdk/sun/security/pkcs11/Provider/MultipleLogins.sh b/test/jdk/sun/security/pkcs11/Provider/MultipleLogins.sh +index c768834da..4a50e6782 100644 +--- a/test/jdk/sun/security/pkcs11/Provider/MultipleLogins.sh ++++ b/test/jdk/sun/security/pkcs11/Provider/MultipleLogins.sh +@@ -99,6 +99,12 @@ esac + + # first make cert/key DBs writable + ++${CP} ${TESTSRC}${FS}..${FS}nss${FS}db${FS}cert9.db ${TESTCLASSES} ++${CHMOD} +w ${TESTCLASSES}${FS}cert9.db + -+ @Override -+ public char getTypeChar() { -+ switch (this) { -+ case BYTE: -+ return 'b'; -+ case WORD: -+ return 'w'; -+ case DWORD: -+ return 'd'; -+ case QWORD: -+ return 'q'; -+ case SINGLE: -+ return 'S'; -+ case DOUBLE: -+ return 'D'; -+ case V128_BYTE: -+ case V128_WORD: -+ case V128_DWORD: -+ case V128_QWORD: -+ case V128_SINGLE: -+ case V128_DOUBLE: -+ case V256_BYTE: -+ case V256_WORD: -+ case V256_DWORD: -+ case V256_QWORD: -+ case V256_SINGLE: -+ case V256_DOUBLE: -+ return 'v'; -+ default: -+ return '-'; -+ } -+ } -+} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.loongarch64/src/jdk/vm/ci/loongarch64/package-info.java jdk11u-ls/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.loongarch64/src/jdk/vm/ci/loongarch64/package-info.java ---- openjdk/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.loongarch64/src/jdk/vm/ci/loongarch64/package-info.java 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.loongarch64/src/jdk/vm/ci/loongarch64/package-info.java 2023-09-12 13:54:26.513575962 +0800 -@@ -0,0 +1,28 @@ ++${CP} ${TESTSRC}${FS}..${FS}nss${FS}db${FS}key4.db ${TESTCLASSES} ++${CHMOD} +w ${TESTCLASSES}${FS}key4.db ++ + ${CP} ${TESTSRC}${FS}..${FS}nss${FS}db${FS}cert8.db ${TESTCLASSES} + ${CHMOD} +w ${TESTCLASSES}${FS}cert8.db + +diff --git a/test/jdk/sun/security/pkcs11/Secmod/cert9.db b/test/jdk/sun/security/pkcs11/Secmod/cert9.db +index a202bea21..b823a7986 100644 +Binary files a/test/jdk/sun/security/pkcs11/Secmod/cert9.db and b/test/jdk/sun/security/pkcs11/Secmod/cert9.db differ +diff --git a/test/jdk/sun/security/pkcs11/Secmod/key4.db b/test/jdk/sun/security/pkcs11/Secmod/key4.db +index 222adb322..8ddfc4c0f 100644 +Binary files a/test/jdk/sun/security/pkcs11/Secmod/key4.db and b/test/jdk/sun/security/pkcs11/Secmod/key4.db differ +diff --git a/test/jdk/sun/security/pkcs11/Secmod/pkcs11.txt b/test/jdk/sun/security/pkcs11/Secmod/pkcs11.txt +index 60cc1c565..d697da076 100644 +--- a/test/jdk/sun/security/pkcs11/Secmod/pkcs11.txt ++++ b/test/jdk/sun/security/pkcs11/Secmod/pkcs11.txt +@@ -1,4 +1,8 @@ + library= + name=NSS Internal PKCS #11 Module +-parameters=configdir='sql:./tmpdb' certPrefix='' keyPrefix='' secmod='' flags= updatedir='' updateCertPrefix='' updateKeyPrefix='' updateid='' updateTokenDescription='' +-NSS=Flags=internal,critical trustOrder=75 cipherOrder=100 slotParams=(1={slotFlags=[RSA,DSA,DH,RC2,RC4,DES,RANDOM,SHA1,MD5,MD2,SSL,TLS,AES,Camellia,SEED,SHA256,SHA512] askpw=any timeout=30}) ++parameters=configdir='sql:./tmpdb' certPrefix='' keyPrefix='' secmod='secmod.db' flags= updatedir='' updateCertPrefix='' updateKeyPrefix='' updateid='' updateTokenDescription='' ++NSS=trustOrder=75 cipherOrder=100 slotParams={0x00000001=[slotFlags=RSA,RC4,RC2,DES,DH,SHA1,MD5,MD2,SSL,TLS,AES,RANDOM askpw=any timeout=30 ] } Flags=internal,critical ++ ++library=libnssckbi.so ++name=Builtin Roots Module ++NSS=trustOrder=100 +diff --git a/test/jdk/sun/security/pkcs11/SecmodTest.java b/test/jdk/sun/security/pkcs11/SecmodTest.java +index c5a01b0a7..c1b5e4471 100644 +--- a/test/jdk/sun/security/pkcs11/SecmodTest.java ++++ b/test/jdk/sun/security/pkcs11/SecmodTest.java +@@ -36,7 +36,7 @@ public class SecmodTest extends PKCS11Test { + static String DBDIR; + static char[] password = "test12".toCharArray(); + static String keyAlias = "mykey"; +- static boolean useSqlite = false; ++ static boolean useSqlite = true; + + static void useSqlite(boolean b) { + useSqlite = b; +diff --git a/test/jdk/sun/security/pkcs11/fips/cert9.db b/test/jdk/sun/security/pkcs11/fips/cert9.db +new file mode 100644 +index 000000000..247bdad0a +Binary files /dev/null and b/test/jdk/sun/security/pkcs11/fips/cert9.db differ +diff --git a/test/jdk/sun/security/pkcs11/fips/key4.db b/test/jdk/sun/security/pkcs11/fips/key4.db +new file mode 100644 +index 000000000..580dd2ebd +Binary files /dev/null and b/test/jdk/sun/security/pkcs11/fips/key4.db differ +diff --git a/test/jdk/sun/security/pkcs11/fips/pkcs11.txt b/test/jdk/sun/security/pkcs11/fips/pkcs11.txt +new file mode 100644 +index 000000000..ba339b25c +--- /dev/null ++++ b/test/jdk/sun/security/pkcs11/fips/pkcs11.txt +@@ -0,0 +1,9 @@ ++library= ++name=NSS Internal PKCS #11 Module ++parameters=configdir='sql:./tmpdb' certPrefix='' keyPrefix='' secmod='secmod.db' flags= updatedir='' updateCertPrefix='' updateKeyPrefix='' updateid='' updateTokenDescription='' ++NSS=trustOrder=75 cipherOrder=100 slotParams={0x00000001=[slotFlags=RSA,RC4,RC2,DES,DH,SHA1,MD5,MD2,SSL,TLS,AES,RANDOM askpw=any timeout=30 ] } Flags=internal,critical ++ ++library=libnssckbi.so ++name=Builtin Roots Module ++NSS=trustOrder=100 ++ +diff --git a/test/jdk/sun/security/ssl/X509TrustManagerImpl/Entrust/affirmtrustcommercialca-chain.pem b/test/jdk/sun/security/ssl/X509TrustManagerImpl/Entrust/affirmtrustcommercialca-chain.pem +deleted file mode 100644 +index 76aa6d143..000000000 +--- a/test/jdk/sun/security/ssl/X509TrustManagerImpl/Entrust/affirmtrustcommercialca-chain.pem ++++ /dev/null +@@ -1,77 +0,0 @@ +-Root Certificate: +- Version: 3 (0x2) +- Serial Number: 8608355977964138876 (0x7777062726a9b17c) +- Signature Algorithm: sha256WithRSAEncryption +- Issuer: C=US, O=AffirmTrust, CN=AffirmTrust Commercial +- Validity +- Not Before: Jan 29 14:06:06 2010 GMT +- Not After : Dec 31 14:06:06 2030 GMT +- +------BEGIN CERTIFICATE----- +-MIIHHjCCBgagAwIBAgIQAWZjFOyCvT00u/gtkCvS2TANBgkqhkiG9w0BAQsFADCB +-gzELMAkGA1UEBhMCQ0ExFDASBgNVBAoTC0FmZmlybVRydXN0MSswKQYDVQQLEyJT +-ZWUgd3d3LmFmZmlybXRydXN0LmNvbS9yZXBvc2l0b3J5MTEwLwYDVQQDEyhBZmZp +-cm1UcnVzdCBFeHRlbmRlZCBWYWxpZGF0aW9uIENBIC0gRVYxMB4XDTI0MDYyODIx +-MzgwNVoXDTI1MDcyODIxMzgwNFowgdgxCzAJBgNVBAYTAkNBMRAwDgYDVQQIEwdP +-bnRhcmlvMQ8wDQYDVQQHEwZPdHRhd2ExEzARBgsrBgEEAYI3PAIBAxMCQ0ExGDAW +-BgsrBgEEAYI3PAIBAhMHT250YXJpbzEcMBoGA1UEChMTQWZmaXJtdHJ1c3QgTGlt +-aXRlZDEdMBsGA1UEDxMUUHJpdmF0ZSBPcmdhbml6YXRpb24xEDAOBgNVBAUTBzI1 +-NDA1NDcxKDAmBgNVBAMTH3ZhbGlkY29tbWVyY2lhbC5hZmZpcm10cnVzdC5jb20w +-ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDeIT2XO0hJ5wDSbIiIcMvs +-P3NpQc7O7v5DqldpME6+Qn2sF5b9hc6j72hgTXREa77uUcP5u1JcMWCSWwYQHMpJ +-kFzmIzijhS60wW1epb5QyTgM3ZYh1WKvttFCbHUcrTtd+LoPFYsjw9ZK//K9tPp+ +-ddn06/ivWvUO5y5vn0wrCaB9tuLdDn4RCQzK2XoZdDuqhPlBBogJX0vM6lsXjgLy +-EbvE+/sKYps/In6VtRvCoYavg3OqaIMeaA7gTiYTb1ZGFOAiltnq7fcp6SZUohK3 +-QNihv1DadVc+n8LnEUKKDkgG2YgWEFczaE3qwG3ef6L3MzLGrkgVY+qGHyyv2IE7 +-AgMBAAGjggM1MIIDMTAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBT4ARNL47hAsOpa +-96VMgKEY3sLIAjAfBgNVHSMEGDAWgBTb72U3C+VHyzXRkB8DwbyIx6fqgDBsBggr +-BgEFBQcBAQRgMF4wJwYIKwYBBQUHMAGGG2h0dHA6Ly9vY3NwLmFmZmlybXRydXN0 +-LmNvbTAzBggrBgEFBQcwAoYnaHR0cDovL2FpYS5hZmZpcm10cnVzdC5jb20vYWZ0 +-ZXYxY2EuY3J0MDwGA1UdHwQ1MDMwMaAvoC2GK2h0dHA6Ly9jcmwuYWZmaXJtdHJ1 +-c3QuY29tL2NybC9hZnRldjFjYS5jcmwwKgYDVR0RBCMwIYIfdmFsaWRjb21tZXJj +-aWFsLmFmZmlybXRydXN0LmNvbTAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYI +-KwYBBQUHAwEGCCsGAQUFBwMCMFYGA1UdIARPME0wBwYFZ4EMAQEwQgYKKwYBBAGC +-jwkCATA0MDIGCCsGAQUFBwIBFiZodHRwczovL3d3dy5hZmZpcm10cnVzdC5jb20v +-cmVwb3NpdG9yeTCCAYAGCisGAQQB1nkCBAIEggFwBIIBbAFqAHcAEvFONL1TckyE +-BhnDjz96E/jntWKHiJxtMAWE6+WGJjoAAAGQYMi3wQAABAMASDBGAiEAjvdsU4G2 +-o4BZSOOjaH6gOp7zhKtXQByQUvfHfsi2ePcCIQDnnIO2qlHBm+sskUDlXfR0lCUW +-yFPVr9nFZ0L9YPpozgB2AA3h8jAr0w3BQGISCepVLvxHdHyx1+kw7w5CHrR+Tqo0 +-AAABkGDIt9MAAAQDAEcwRQIhANh1zS3Qeo9yKF+j3G52JhmDRYBS+1TM0wykoXCY +-llpxAiAG+LAlKSbwwgrboUSTDDXWNeoRYZ7fKbU72kKfHrpZvwB3ABoE/0nQVB1A +-r/agw7/x2MRnL07s7iNAaJhrF0Au3Il9AAABkGDIt9sAAAQDAEgwRgIhAN8OoC4I +-zw8bFJy8ACgK40c9ZfsIfFhePTc9CyrL5uDsAiEA4Jn/IqBB9L5DeTgqw9hBaYag +-FmY/2gWDip36ga0WUsAwDQYJKoZIhvcNAQELBQADggEBABywPLJP097Emz6LNeFU +-/HvfhaUKv2pgIHf/Kvjs5x78RK9G605THPEHr/TeUjNZ4PBd48WBNVWzyd/8FuOt +-r+FsYkRJb9CnrOhZHuCwlcdWXvuY8PiuBmT+xB16BWR5yhYbbiGe4hea0Pf6CfHh +-jJoGJw4dQKfgneZOV7IcaWnNTKYawlcZOgxvEwFvj+iZM31WphEPKRAV+N+Tp+ZR +-nxlEdjmdbOjqBydlYIEzuFIgxgtnPdK5wqCOWb+z2cARUAO/AkiWrOLTPDc7ydQK +-GcfDrSqffHOlwaee08C6STFaJWIcpqxZdXE6Jc+8/85bfPEAG1UepgfnBTqW9RGT +-Q3s= +------END CERTIFICATE----- +------BEGIN CERTIFICATE----- +-MIIEqDCCA5CgAwIBAgIQFylVHtaOf7Ht9XMA811/1TANBgkqhkiG9w0BAQsFADBE +-MQswCQYDVQQGEwJVUzEUMBIGA1UECgwLQWZmaXJtVHJ1c3QxHzAdBgNVBAMMFkFm +-ZmlybVRydXN0IENvbW1lcmNpYWwwHhcNMTkwMzIxMjAyNzU0WhcNMzAxMjAyMDQw +-MDAwWjCBgzELMAkGA1UEBhMCQ0ExFDASBgNVBAoTC0FmZmlybVRydXN0MSswKQYD +-VQQLEyJTZWUgd3d3LmFmZmlybXRydXN0LmNvbS9yZXBvc2l0b3J5MTEwLwYDVQQD +-EyhBZmZpcm1UcnVzdCBFeHRlbmRlZCBWYWxpZGF0aW9uIENBIC0gRVYxMIIBIjAN +-BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuPBMIa9VuXJGAw0MHvieGciPFA11 +-b9T49YJ7T+zVpoMMQO+ueUKVHb2l26oeCiwIhXMQ5LquOVcx+rofouzcKXY3wKDZ +-zHIOnAkU+23Ucn/3dRH7aHJULsBufZq+NvwgYSgJJEDKfqvIV/c5HiRyZ2H+nAI5 +-10Q2xC0UxgSBsufccQ+Fwkg6BAGDlTXrvi8wi75UaGue6jv/qcKLybeVUrgqKE64 +-d9oa9PG5/g89QwSdsIQEdVSFzFvFpOG9YhJbJ177Zg6DGCxU0lWwFrVpyH/2vnXl +-jhMQScn8UxzCJdDg3EDqjgaV0JH2yoLug+QVYgURPu5BEb5ut9vAdP7cLwIDAQAB +-o4IBVDCCAVAwNwYIKwYBBQUHAQEEKzApMCcGCCsGAQUFBzABhhtodHRwOi8vb2Nz +-cC5hZmZpcm10cnVzdC5jb20wHQYDVR0OBBYEFNvvZTcL5UfLNdGQHwPBvIjHp+qA +-MBIGA1UdEwEB/wQIMAYBAf8CAQAwHwYDVR0jBBgwFoAUnZPGU4teyq8/nx4P5ZmV +-vCT2lI8wRwYDVR0gBEAwPjA8BgRVHSAAMDQwMgYIKwYBBQUHAgEWJmh0dHBzOi8v +-d3d3LmFmZmlybXRydXN0LmNvbS9yZXBvc2l0b3J5MEkGA1UdHwRCMEAwPqA8oDqG +-OGh0dHA6Ly9jcmwuYWZmaXJtdHJ1c3QuY29tL2NybC9BZmZpcm1UcnVzdENvbW1l +-cmNpYWwuY3JsMA4GA1UdDwEB/wQEAwIBhjAdBgNVHSUEFjAUBggrBgEFBQcDAQYI +-KwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAATH11fMrINGmQGQqQW0ATteVnUG +-LrmRSN2OlmRm+dkUwKXhcQQEfYYlEggPqgvxSUpw13fXSOqVHqAcj3BIqF957kh+ +-m3DmC0RX9KaEKD165pf77P5nZcRmZpBl9cctvzIxN19uzcminchusYwLyeWhBtTZ +-xpER9LbrfMNaQ7GnrgalMx54QvdjOhw/GJs9/SqEzYmPshL+DzgZX/oAzY63rQIh +-rBblf6/2talZqci96oFzNst8rGfPy/xQ7lgkki1hwIYbORMfloBhP+vAZJo0mxdM +-ipu3Z0ToK+KU2iqnBxXVr2/kod+CpkHnjUHa1wnQuSaefng3XwZ/vqtSL9c= +------END CERTIFICATE----- +diff --git a/test/jdk/sun/security/ssl/X509TrustManagerImpl/Entrust/affirmtrustnetworkingca-chain.pem b/test/jdk/sun/security/ssl/X509TrustManagerImpl/Entrust/affirmtrustnetworkingca-chain.pem +deleted file mode 100644 +index 7384d3115..000000000 +--- a/test/jdk/sun/security/ssl/X509TrustManagerImpl/Entrust/affirmtrustnetworkingca-chain.pem ++++ /dev/null +@@ -1,76 +0,0 @@ +-Root Certificate: +- Version: 3 (0x2) +- Serial Number: 8957382827206547757 (0x7c4f04391cd4992d) +- Signature Algorithm: sha1WithRSAEncryption +- Issuer: C=US, O=AffirmTrust, CN=AffirmTrust Networking +- Validity +- Not Before: Jan 29 14:08:24 2010 GMT +- Not After : Dec 31 14:08:24 2030 GMT +- +------BEGIN CERTIFICATE----- +-MIIHGjCCBgKgAwIBAgIQX2vGPaCJ1tS0ncp2OlBMFjANBgkqhkiG9w0BAQsFADCB +-gzELMAkGA1UEBhMCQ0ExFDASBgNVBAoTC0FmZmlybVRydXN0MSswKQYDVQQLEyJT +-ZWUgd3d3LmFmZmlybXRydXN0LmNvbS9yZXBvc2l0b3J5MTEwLwYDVQQDEyhBZmZp +-cm1UcnVzdCBFeHRlbmRlZCBWYWxpZGF0aW9uIENBIC0gRVYzMB4XDTI0MDYyODIx +-NDU0OVoXDTI1MDcyODIxNDU0OFowgdgxCzAJBgNVBAYTAkNBMRAwDgYDVQQIEwdP +-bnRhcmlvMQ8wDQYDVQQHEwZPdHRhd2ExEzARBgsrBgEEAYI3PAIBAxMCQ0ExGDAW +-BgsrBgEEAYI3PAIBAhMHT250YXJpbzEcMBoGA1UEChMTQWZmaXJtdHJ1c3QgTGlt +-aXRlZDEdMBsGA1UEDxMUUHJpdmF0ZSBPcmdhbml6YXRpb24xEDAOBgNVBAUTBzI1 +-NDA1NDcxKDAmBgNVBAMTH3ZhbGlkbmV0d29ya2luZy5hZmZpcm10cnVzdC5jb20w +-ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCkGknE8kFr+CaIybQrDPRw +-z9OKXq77p4CnrkF1/g9w/HiIs6Ps8YqTjsiTKM3wYLbvPA+TbO9DpCSyCP2bVyLf +-AjUE617KZSpfy9RqzvGjn/1qH/cBKohhEliMfDj4ZHfY4x+1WYTZPVK/g0Ny5RAP +-wz9lJHR2SsVGLvpqXzWaVoxifJ8HZWD7n5z/75WeYko+Hubx3WvzJZcN2Xjn+q6a +-7wkDaXPayrvn5uWGPlOLQHqJ5z7wts21jASMTfJAToFyzH6dGwvqxkP3bVJGJ8AF +-vtMfqVjcOcjWgmmOEHMPAAqs5QKrYuSLccH6hFTwFEUCdMwVqfloznt2sNUSBoKj +-AgMBAAGjggMxMIIDLTAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBTrE0z4fRyx9P9M +-0FfA6VgGkJiYVDAfBgNVHSMEGDAWgBR5HrHJF8cerLHHFNfD6H+8uVCbFTBsBggr +-BgEFBQcBAQRgMF4wJwYIKwYBBQUHMAGGG2h0dHA6Ly9vY3NwLmFmZmlybXRydXN0 +-LmNvbTAzBggrBgEFBQcwAoYnaHR0cDovL2FpYS5hZmZpcm10cnVzdC5jb20vYWZ0 +-ZXYzY2EuY3J0MDwGA1UdHwQ1MDMwMaAvoC2GK2h0dHA6Ly9jcmwuYWZmaXJtdHJ1 +-c3QuY29tL2NybC9hZnRldjNjYS5jcmwwKgYDVR0RBCMwIYIfdmFsaWRuZXR3b3Jr +-aW5nLmFmZmlybXRydXN0LmNvbTAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYI +-KwYBBQUHAwEGCCsGAQUFBwMCMFYGA1UdIARPME0wBwYFZ4EMAQEwQgYKKwYBBAGC +-jwkCAjA0MDIGCCsGAQUFBwIBFiZodHRwczovL3d3dy5hZmZpcm10cnVzdC5jb20v +-cmVwb3NpdG9yeTCCAXwGCisGAQQB1nkCBAIEggFsBIIBaAFmAHYADeHyMCvTDcFA +-YhIJ6lUu/Ed0fLHX6TDvDkIetH5OqjQAAAGQYM/MjQAABAMARzBFAiBjnehs1mvh +-5Xm3uXZ7Bq8gijwiXThwnLSYROQxnWrnbAIhALbgJG+PRZQfzTBbgM/zAwNsBjhe +-F5iENnaajJCxzOhaAHUAEvFONL1TckyEBhnDjz96E/jntWKHiJxtMAWE6+WGJjoA +-AAGQYM/MgQAABAMARjBEAiAsWOm1IIjaxQP9uaPI9tQmkiJPUOTrBTsTDO+jkgiG +-+QIgVNhND82rsFGjrtAAHzzgCVzLDUM3zaHxnP/z3BNuO4QAdQAaBP9J0FQdQK/2 +-oMO/8djEZy9O7O4jQGiYaxdALtyJfQAAAZBgz8zLAAAEAwBGMEQCIBIGxtjk7Lw8 +-i+oggK7VrPMNTB632t321cwhEm517BbZAiBws3+uytwh59N6qGJUuSFQnOZNPOPj +-eQnH2fSdT1J2sDANBgkqhkiG9w0BAQsFAAOCAQEAcSzitESRKlbcUvxvUB7FjK0I +-CaBU1Nyu0xDFCoG2pmp7GASJz34wtPYfsiX5+j4hDh/noMcgk7WlD8pzgWYw15Rk +-+5kTv2v4U85y/JFjzMOHbz64KjQdGebqhjvC/E/EXxK+AZf4H574/w7rbyJ30vFL +-gNvPF9AxS1MuYIO55jXrHMByKnFoQZgPsmAY/x+n+OzMxWOdR18PupypCB5TyJZ8 +-pQzwoxmX7qeZHiXyJ8jQUwe1qoQc2SbwfQxfwSPUPSJuQo90N+5nyQMe7vvPBM0Y +-/CXaFpfPqh71D4C0Ey+0hYxSt99gYs4P9twUByjIlP0wTyhaoEpt3zw9DdZypQ== +------END CERTIFICATE----- +------BEGIN CERTIFICATE----- +-MIIEqDCCA5CgAwIBAgIQNCSh7Pjwo1/nRrcBHEPoRDANBgkqhkiG9w0BAQsFADBE +-MQswCQYDVQQGEwJVUzEUMBIGA1UECgwLQWZmaXJtVHJ1c3QxHzAdBgNVBAMMFkFm +-ZmlybVRydXN0IE5ldHdvcmtpbmcwHhcNMTkwMzIxMjAzODU5WhcNMzAxMjAyMDQw +-MDAwWjCBgzELMAkGA1UEBhMCQ0ExFDASBgNVBAoTC0FmZmlybVRydXN0MSswKQYD +-VQQLEyJTZWUgd3d3LmFmZmlybXRydXN0LmNvbS9yZXBvc2l0b3J5MTEwLwYDVQQD +-EyhBZmZpcm1UcnVzdCBFeHRlbmRlZCBWYWxpZGF0aW9uIENBIC0gRVYzMIIBIjAN +-BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmHDl/3xr1qiHoe0Rzb3AGLw56e9J +-l2a3X59+PAfI5wGBHuK9Dl7XsyoH65X6QIC/rXyVpuNgKbbwIGHB+rCSplyHzGyC +-WeM3LXa2q1US7VteeFDS959nxJVRFfwATR9xAK6YTUWQ/yWdw0dZSm0lQNmEMBwS +-qi0ufWokiWXZUzWHOu7A6driCohu9sFDwe1INJUPH6uIlovmzGvG3UYbUSymJcjs +-Ka0fXXX9zukco8exlOIKWRJSNLxKtSSPDVASrGLQ1xi3qkiLTKci3+jKMNDFf1vw +-foZN99HhUcWKXfr2KlWfANdjTMlsTKCfuhfWl1OBVNHGRrACAQCXI/ji0wIDAQAB +-o4IBVDCCAVAwNwYIKwYBBQUHAQEEKzApMCcGCCsGAQUFBzABhhtodHRwOi8vb2Nz +-cC5hZmZpcm10cnVzdC5jb20wHQYDVR0OBBYEFHkesckXxx6ssccU18Pof7y5UJsV +-MBIGA1UdEwEB/wQIMAYBAf8CAQAwHwYDVR0jBBgwFoAUBx/S55zawm6iQLSwelAQ +-UHTEyL0wRwYDVR0gBEAwPjA8BgRVHSAAMDQwMgYIKwYBBQUHAgEWJmh0dHBzOi8v +-d3d3LmFmZmlybXRydXN0LmNvbS9yZXBvc2l0b3J5MEkGA1UdHwRCMEAwPqA8oDqG +-OGh0dHA6Ly9jcmwuYWZmaXJtdHJ1c3QuY29tL2NybC9BZmZpcm1UcnVzdE5ldHdv +-cmtpbmcuY3JsMA4GA1UdDwEB/wQEAwIBhjAdBgNVHSUEFjAUBggrBgEFBQcDAQYI +-KwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAAhmE4I56hNpnWXQ2Si8a/TgQUZr +-X5Jlv1LDvl3rkDyfEIHNZ8dth17SakJYJBWHExph/iIYjCJ9YmeyhghV5rPqT+wF +-4yyE2ngenIusfnWT2bTpT9u2VZbCNeACE5XnN2UHSA0J9idPjfLuthViWEvSZZUh +-DJ53bX+exO366nDY4AI7owIyhz8hdsWyhZ/0ST+eD+kbgd8osd+GdxzRmyKcfl84 +-D1K1uff01T9w2dyUaZglQsFljkaO6xmeXZJsPnhwCp/HlMHWzhAneUQ7I9FZSOW+ +-WiYbt4RitmBpysadBReikWM4knECzJQ/fMT9vC0k9BLlqUYRwCH9vr0UnZo= +------END CERTIFICATE----- +diff --git a/test/jdk/sun/security/ssl/X509TrustManagerImpl/Entrust/affirmtrustpremiumca-chain.pem b/test/jdk/sun/security/ssl/X509TrustManagerImpl/Entrust/affirmtrustpremiumca-chain.pem +deleted file mode 100644 +index 6f108bc12..000000000 +--- a/test/jdk/sun/security/ssl/X509TrustManagerImpl/Entrust/affirmtrustpremiumca-chain.pem ++++ /dev/null +@@ -1,88 +0,0 @@ +-Root Certificate: +- Version: 3 (0x2) +- Serial Number: 7893706540734352110 (0x6d8c1446b1a60aee) +- Signature Algorithm: sha384WithRSAEncryption +- Issuer: C=US, O=AffirmTrust, CN=AffirmTrust Premium +- Validity +- Not Before: Jan 29 14:10:36 2010 GMT +- Not After : Dec 31 14:10:36 2040 GMT +- +------BEGIN CERTIFICATE----- +-MIIIFjCCBv6gAwIBAgIQQVOTWr7tEAJXmRDkCSxkajANBgkqhkiG9w0BAQsFADCB +-gzELMAkGA1UEBhMCQ0ExFDASBgNVBAoTC0FmZmlybVRydXN0MSswKQYDVQQLEyJT +-ZWUgd3d3LmFmZmlybXRydXN0LmNvbS9yZXBvc2l0b3J5MTEwLwYDVQQDEyhBZmZp +-cm1UcnVzdCBFeHRlbmRlZCBWYWxpZGF0aW9uIENBIC0gRVYyMB4XDTI0MDYyODIx +-NDgyN1oXDTI1MDcyODIxNDgyNlowgdUxCzAJBgNVBAYTAkNBMRAwDgYDVQQIEwdP +-bnRhcmlvMQ8wDQYDVQQHEwZPdHRhd2ExEzARBgsrBgEEAYI3PAIBAxMCQ0ExGDAW +-BgsrBgEEAYI3PAIBAhMHT250YXJpbzEcMBoGA1UEChMTQWZmaXJtdHJ1c3QgTGlt +-aXRlZDEdMBsGA1UEDxMUUHJpdmF0ZSBPcmdhbml6YXRpb24xEDAOBgNVBAUTBzI1 +-NDA1NDcxJTAjBgNVBAMTHHZhbGlkcHJlbWl1bS5hZmZpcm10cnVzdC5jb20wggIi +-MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDVRMzwbDq47ivHOKqJdiEJNL2+ +-g9Snj/BRctqcQTrIV99RP0pmAh5fHg7vnhVsHqc9sRLVcQWTJk9NuRJ2VnDKWsBa +-Xrp5UWaNjS0vaFA4jzCi1gWzTTZgPTQn3VRG3JP1F5CZb405/mtWDaw/CfWkcUqQ +-VSilqFlJRsjcPCzQh7ZaXAo+FmzJxNSwjxdP6JSYMeTDRCUpSb3T8PypVI1CEmLZ +-jsxrg5oIZn25591g/pzgLE56N0stNY4d3q4YD1t5x46RsqYAJYSkk8rcTN+kHzsY +-VSqaRDyPkGbmuCeJUvW24wJ30yQtXQWA+U0dMYLe7LyglJ7dkOzvWNbqrIcvM8My +-hxH/wwVH7e4dL/1E58yr1BHENUk7Mp9rzIXj496eLkF5G1lMkNnuVRQqCAOW0rPY +-V0rI8yrCMTK52s4mNjQo2J7JOYdTUvAWZ92MKvEjjhQlMH8eK72Km/+mkxpsgGmr +-3c6u+Gom7oI5VaLZ+3p2uWaOsutk1tkzWjhzY4L27hwmIdWujfrWMRx8uxcfoJxX +-gQ40d1QiSN51BtCPE5UnpLU/YUxMdzWmtUoGUfYIGVqDVToBnunIFMdmFjC0IrNl +-hquDQi/OGMpzuOvxX1FoXb+rRwOhhdrcR0BQqUVRTV0U5LlcsDeNMqmqPE9mzGtJ +-W69Fsh7crntng/L72wIDAQABo4IDMDCCAywwDAYDVR0TAQH/BAIwADAdBgNVHQ4E +-FgQU3PWyi/4usZghgahc/Tj+Q60QLOcwHwYDVR0jBBgwFoAUc3yaOGg8UXxBCP6h +-HyoetGHbzTwwbAYIKwYBBQUHAQEEYDBeMCcGCCsGAQUFBzABhhtodHRwOi8vb2Nz +-cC5hZmZpcm10cnVzdC5jb20wMwYIKwYBBQUHMAKGJ2h0dHA6Ly9haWEuYWZmaXJt +-dHJ1c3QuY29tL2FmdGV2MmNhLmNydDA8BgNVHR8ENTAzMDGgL6AthitodHRwOi8v +-Y3JsLmFmZmlybXRydXN0LmNvbS9jcmwvYWZ0ZXYyY2EuY3JsMCcGA1UdEQQgMB6C +-HHZhbGlkcHJlbWl1bS5hZmZpcm10cnVzdC5jb20wDgYDVR0PAQH/BAQDAgWgMB0G +-A1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjBWBgNVHSAETzBNMAcGBWeBDAEB +-MEIGCisGAQQBgo8JAgMwNDAyBggrBgEFBQcCARYmaHR0cHM6Ly93d3cuYWZmaXJt +-dHJ1c3QuY29tL3JlcG9zaXRvcnkwggF+BgorBgEEAdZ5AgQCBIIBbgSCAWoBaAB2 +-ABoE/0nQVB1Ar/agw7/x2MRnL07s7iNAaJhrF0Au3Il9AAABkGDSN7EAAAQDAEcw +-RQIgVDWwhv7yG6RNnkMZnVq1YYA7ypn/GSH0ibUKnESHRpYCIQCY8gyCX7VFONUI +-QuR8daz7ra2FCUI9TwylrR3eFfIgGgB3AN3cyjSV1+EWBeeVMvrHn/g9HFDf2wA6 +-FBJ2Ciysu8gqAAABkGDSN5cAAAQDAEgwRgIhAM1edsSyFUKU0Dj1WxTGwziE6fCW +-g2ByfL8kDrP260YXAiEA6YQOpJf04N13Nn263BxAl+laH9Ar0eo03fArlv743TQA +-dQAN4fIwK9MNwUBiEgnqVS78R3R8sdfpMO8OQh60fk6qNAAAAZBg0je+AAAEAwBG +-MEQCIExqK4katETAQo+H0+ImuNJCSeFEI9C+9wrjhl6ZnWb9AiBwkC1vpLYOIm/1 +-YCLCQIOmTdg2wf8LITlrQNJA8vbBljANBgkqhkiG9w0BAQsFAAOCAQEASOmPu7ot +-yl6MoMns19uI6H2KSUjMFh3/fKMcY/ettmEYalgrytexFMrLnD2UniBlD+nJEshp +-5/z7o0YDiRoiLhMAs7VqIdX3erNu/ghNh7P2bDnoMWShSoAKxez1XOGL3rRE0NAi +-DsWCaNRHH9rnC97275sbGnua7ZYg+8BiF62vpJlqjrxDHjGiej8qAWSjztbB43Af +-bwRscpXTxNkMvOBuRFMH+rSxB8CrOV68W+yxmzPuPxVjM7oJH8Qk5BC53NRqFsVz +-JhbNfot0+/drj7JT3jlacUVQcD/BzDuC3+qczQlLjLdHgQM2/e4fXsD6C5S6B11d +-BDx6ipGpaASofA== +------END CERTIFICATE----- +------BEGIN CERTIFICATE----- +-MIIFojCCA4qgAwIBAgIQU3HI6weE/VEI5dTz4yPsRjANBgkqhkiG9w0BAQsFADBB +-MQswCQYDVQQGEwJVUzEUMBIGA1UECgwLQWZmaXJtVHJ1c3QxHDAaBgNVBAMME0Fm +-ZmlybVRydXN0IFByZW1pdW0wHhcNMTkwMzIxMjA0NjM1WhcNMzAxMjAyMDQwMDAw +-WjCBgzELMAkGA1UEBhMCQ0ExFDASBgNVBAoTC0FmZmlybVRydXN0MSswKQYDVQQL +-EyJTZWUgd3d3LmFmZmlybXRydXN0LmNvbS9yZXBvc2l0b3J5MTEwLwYDVQQDEyhB +-ZmZpcm1UcnVzdCBFeHRlbmRlZCBWYWxpZGF0aW9uIENBIC0gRVYyMIIBIjANBgkq +-hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvDDZHfxkB1nAGFKdw0VCgV+B/eBtW1o+ +-bXzwRcpeFh5saDI+tv1RAMrYFq+AJkXCCJopgMF2Wqfv5myE3JMgxEHuuKUpJz7H +-FprrFckVOGCtJKH8Iy9AWPjBwt8lKmxGJF7EZst+QoVt4hMe0qhL0WEKbATFPe41 +-DcM7UsyQv6Bvpn424uePy3/1ATIsVL3YmvAbUNR0aqVxYAJzTefvyIet/761bKGc +-NyqdOVWFFeTDtr8iL1TBXToAgl0GJ39bFQZsP19VcCpfk9Zj3YHTPRPq5wZOZuUN +-F7jiBUEi6DaVOi3Wy4vdySHtWPeBHRYif1I6fcUfdCNORMc4ee6KewIDAQABo4IB +-UTCCAU0wNwYIKwYBBQUHAQEEKzApMCcGCCsGAQUFBzABhhtodHRwOi8vb2NzcC5h +-ZmZpcm10cnVzdC5jb20wHQYDVR0OBBYEFHN8mjhoPFF8QQj+oR8qHrRh2808MBIG +-A1UdEwEB/wQIMAYBAf8CAQAwHwYDVR0jBBgwFoAUncBnpgwi2Sb1RaumZVIRJ9hF +-rGMwRwYDVR0gBEAwPjA8BgRVHSAAMDQwMgYIKwYBBQUHAgEWJmh0dHBzOi8vd3d3 +-LmFmZmlybXRydXN0LmNvbS9yZXBvc2l0b3J5MEYGA1UdHwQ/MD0wO6A5oDeGNWh0 +-dHA6Ly9jcmwuYWZmaXJtdHJ1c3QuY29tL2NybC9BZmZpcm1UcnVzdFByZW1pdW0u +-Y3JsMA4GA1UdDwEB/wQEAwIBhjAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUH +-AwIwDQYJKoZIhvcNAQELBQADggIBABi64UEwl3l0yIiuSACyVQQIBI60BUmhseac +-4BzCAsJrR5tE/2U9QAa2y6JpR1nqm76DJvw1QQgvFcNe+fkwpvoViCaSTbZkGGwD +-mQe2xRSYJcDSMQUc/GgzLcX2c1CrexQXE1vwV/q33af1en5s1GzLl915aNS/k1ch +-G7EMruJ/D4cuH9j4j2i+b+llmVBzavBwelN5rc693o+Ot9id/1sTWNugwAu3uXGb +-VlhETMnjXGIciegOLdWYhWBln0izYlt9IwlDEpjMVaZ0HZlj2JBGaSe4PfEFpJPO +-beuPcQpLQGw2XpW2ZMG5JcRYaoKWjixXAGktRA3H9nvVW92jvzx/RX484w2ZM5Rt +-E+I1ikAuQLAyWG7clht387e2RuC3NZTtefSyjE3L9gQDOPC+Z9ycwr0WJHRsxFvh +-FJQi3JnxgFZf5mc5n2mh3qAgALTNOUHuDiHrerjTOWbpF/1/NJmo/c/YZ63vZIhc +-EaER4HuhbBqlpf6z3WOIQdZm1ChwXYHrEcLDgfwm9cXoaVK2HZapkMwQbPffPlT1 +-E+AxRFB4YmT1y2WzdaHfhFA9nH6ByUdL5+FfrDoIIUO2e8OLOAcrJsf5+unhAhc0 +-v7N48JWdmpstjkXCaCIaidrZLJxS+pikNgHB1dXF/TxokLTiPB9jcYKdGaYs3XHb +-YKLdwubu +------END CERTIFICATE----- +diff --git a/test/jdk/sun/security/ssl/X509TrustManagerImpl/Entrust/affirmtrustpremiumeccca-chain.pem b/test/jdk/sun/security/ssl/X509TrustManagerImpl/Entrust/affirmtrustpremiumeccca-chain.pem +deleted file mode 100644 +index 37b1b7870..000000000 +--- a/test/jdk/sun/security/ssl/X509TrustManagerImpl/Entrust/affirmtrustpremiumeccca-chain.pem ++++ /dev/null +@@ -1,63 +0,0 @@ +-Root Certificate: +- Version: 3 (0x2) +- Serial Number: 8401224907861490260 (0x7497258ac73f7a54) +- Signature Algorithm: ecdsa-with-SHA384 +- Issuer: C=US, O=AffirmTrust, CN=AffirmTrust Premium ECC +- Validity +- Not Before: Jan 29 14:20:24 2010 GMT +- Not After : Dec 31 14:20:24 2040 GMT +- +------BEGIN CERTIFICATE----- +-MIIF0zCCBVmgAwIBAgIQFVwk9nYUM5SYOnBd+IoGtzAKBggqhkjOPQQDAzCBhTEL +-MAkGA1UEBhMCQ0ExFDASBgNVBAoTC0FmZmlybVRydXN0MSswKQYDVQQLEyJTZWUg +-d3d3LmFmZmlybXRydXN0LmNvbS9yZXBvc2l0b3J5MTMwMQYDVQQDEypBZmZpcm1U +-cnVzdCBFeHRlbmRlZCBWYWxpZGF0aW9uIENBIC0gRVZFQzEwHhcNMjQwNjI4MjE0 +-OTUwWhcNMjUwNzI4MjE0OTQ4WjCB2DELMAkGA1UEBhMCQ0ExEDAOBgNVBAgTB09u +-dGFyaW8xDzANBgNVBAcTBk90dGF3YTETMBEGCysGAQQBgjc8AgEDEwJDQTEYMBYG +-CysGAQQBgjc8AgECEwdPbnRhcmlvMRwwGgYDVQQKExNBZmZpcm10cnVzdCBMaW1p +-dGVkMR0wGwYDVQQPExRQcml2YXRlIE9yZ2FuaXphdGlvbjEQMA4GA1UEBRMHMjU0 +-MDU0NzEoMCYGA1UEAxMfdmFsaWRwcmVtaXVtZWNjLmFmZmlybXRydXN0LmNvbTB2 +-MBAGByqGSM49AgEGBSuBBAAiA2IABEkLBzBYSJPRENKDaA1iBPQz+jZUV+OoM9nJ +-sr9sMfmHaqr3nlWxAMM99b9/usVfYyUxqyi+YL2Z3ZSxjX2dpyhwMtPpIQkL1pMW +-Iv55XBIcYRyl2NjcADS9B06G+nnix6OCAzcwggMzMAwGA1UdEwEB/wQCMAAwHQYD +-VR0OBBYEFP+37ywf2YJJ/4CEVy1GY4ioGm1yMB8GA1UdIwQYMBaAFMaQjAKD113j +-vjucLtVlfSoQYO7lMG4GCCsGAQUFBwEBBGIwYDAnBggrBgEFBQcwAYYbaHR0cDov +-L29jc3AuYWZmaXJtdHJ1c3QuY29tMDUGCCsGAQUFBzAChilodHRwOi8vYWlhLmFm +-ZmlybXRydXN0LmNvbS9hZnRldmVjMWNhLmNydDA+BgNVHR8ENzA1MDOgMaAvhi1o +-dHRwOi8vY3JsLmFmZmlybXRydXN0LmNvbS9jcmwvYWZ0ZXZlYzFjYS5jcmwwKgYD +-VR0RBCMwIYIfdmFsaWRwcmVtaXVtZWNjLmFmZmlybXRydXN0LmNvbTAOBgNVHQ8B +-Af8EBAMCB4AwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMFYGA1UdIARP +-ME0wBwYFZ4EMAQEwQgYKKwYBBAGCjwkCBDA0MDIGCCsGAQUFBwIBFiZodHRwczov +-L3d3dy5hZmZpcm10cnVzdC5jb20vcmVwb3NpdG9yeTCCAX4GCisGAQQB1nkCBAIE +-ggFuBIIBagFoAHUA5tIxY0B3jMEQQQbXcbnOwdJA9paEhvu6hzId/R43jlAAAAGQ +-YNN5tQAABAMARjBEAiAnainEoBGI9czVh+c9QLPL30S3Rtov8zrnhlXfeKLzZQIg +-UGkntBMux0MqHt9Aj60qMsS/C4ZWF7AihVVaUKcrEVgAdgAN4fIwK9MNwUBiEgnq +-VS78R3R8sdfpMO8OQh60fk6qNAAAAZBg03m1AAAEAwBHMEUCIGI9kBByoozH4cfS +-ECW/O2N/ElkdATkt7EwQ52kcc4ICAiEA9QTh8JlJTb/ytYC1ECX0vQbrYVexg+fu +-dw7dfToF9nAAdwAS8U40vVNyTIQGGcOPP3oT+Oe1YoeInG0wBYTr5YYmOgAAAZBg +-03ndAAAEAwBIMEYCIQCox5nSCcVB2AfNYXco77zsJnYP7KAU2I4VA2GNL7I4wQIh +-AP6WEzyfBoGpYYqFmNnJUavyhKBmeNiR7eNtaFwpSc+UMAoGCCqGSM49BAMDA2gA +-MGUCMAGSNMXAAKDRk0ZOtydN95Rkja97+70TatCIIxEAsJD8Hu7lfj2LHCYFQjVY +-oaWTrQIxAKUudx7E/JnjsthuL6sNqKVHfD3iLUJyQNK9wE0SVt1xAm7Cu1JXZORE +-M64KMKoQFQ== +------END CERTIFICATE----- +------BEGIN CERTIFICATE----- +-MIIDXDCCAuKgAwIBAgIQAgKlhME0Bk3J8y0gfqNymDAKBggqhkjOPQQDAzBFMQsw +-CQYDVQQGEwJVUzEUMBIGA1UECgwLQWZmaXJtVHJ1c3QxIDAeBgNVBAMMF0FmZmly +-bVRydXN0IFByZW1pdW0gRUNDMB4XDTE5MDMyMTIwNTUwN1oXDTMwMTIwMjA0MDAw +-MFowgYUxCzAJBgNVBAYTAkNBMRQwEgYDVQQKEwtBZmZpcm1UcnVzdDErMCkGA1UE +-CxMiU2VlIHd3dy5hZmZpcm10cnVzdC5jb20vcmVwb3NpdG9yeTEzMDEGA1UEAxMq +-QWZmaXJtVHJ1c3QgRXh0ZW5kZWQgVmFsaWRhdGlvbiBDQSAtIEVWRUMxMHYwEAYH +-KoZIzj0CAQYFK4EEACIDYgAEu9f5NkumdaVlmaNaxpDB+rBk/S6lhqcUU1zTLcRz +-4G0dr4290hezjrvZJxGJ/X15aexpdD2V9cwaPD/yuEJcaaz+rg/qDoqQF3+AFqVc +-41jw1E0S59+57XVKLtXI7Xh6o4IBVDCCAVAwNwYIKwYBBQUHAQEEKzApMCcGCCsG +-AQUFBzABhhtodHRwOi8vb2NzcC5hZmZpcm10cnVzdC5jb20wHQYDVR0OBBYEFMaQ +-jAKD113jvjucLtVlfSoQYO7lMBIGA1UdEwEB/wQIMAYBAf8CAQAwHwYDVR0jBBgw +-FoAUmq8pesARNTUmUTAAw2r+QNWu1jwwRwYDVR0gBEAwPjA8BgRVHSAAMDQwMgYI +-KwYBBQUHAgEWJmh0dHBzOi8vd3d3LmFmZmlybXRydXN0LmNvbS9yZXBvc2l0b3J5 +-MEkGA1UdHwRCMEAwPqA8oDqGOGh0dHA6Ly9jcmwuYWZmaXJtdHJ1c3QuY29tL2Ny +-bC9BZmZpcm1UcnVzdFByZW1pdW1FQ0MuY3JsMA4GA1UdDwEB/wQEAwIBhjAdBgNV +-HSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwCgYIKoZIzj0EAwMDaAAwZQIwHJ5g +-a6sHvQ51DGr0bWq34awuwlWbybC2grHoNp5uYapcXr/qTJusb/6n+dczqFdaAjEA +-7VQY06fE9ifMnTgT9824jc3+H6kfhMk4PoIj9ouWdYfc1DyTBS/low9Hb8liQyFr +------END CERTIFICATE----- +diff --git a/test/jdk/sun/security/ssl/X509TrustManagerImpl/Symantec/Distrust.java b/test/jdk/sun/security/ssl/X509TrustManagerImpl/Symantec/Distrust.java +deleted file mode 100644 +index ba008c68c..000000000 +--- a/test/jdk/sun/security/ssl/X509TrustManagerImpl/Symantec/Distrust.java ++++ /dev/null +@@ -1,292 +0,0 @@ +-/* +- * 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 +- * under the terms of the GNU General Public License version 2 only, as +- * published by the Free Software Foundation. +- * +- * This code is distributed in the hope that it will be useful, but WITHOUT +- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +- * version 2 for more details (a copy is included in the LICENSE file that +- * accompanied this code). +- * +- * You should have received a copy of the GNU General Public License version +- * 2 along with this work; if not, write to the Free Software Foundation, +- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +- * +- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +- * or visit www.oracle.com if you need additional information or have any +- * questions. +- */ +- +-import java.io.*; +-import java.math.BigInteger; +-import java.security.*; +-import java.security.cert.*; +-import java.time.*; +-import java.util.*; +-import javax.net.ssl.*; +-import sun.security.validator.Validator; +-import sun.security.validator.ValidatorException; +- +-import jdk.test.lib.security.SecurityUtils; +- +-/** +- * @test +- * @bug 8207258 8216280 +- * @summary Check that TLS Server certificates chaining back to distrusted +- * Symantec roots are invalid +- * @library /test/lib +- * @modules java.base/sun.security.validator +- * @run main/othervm Distrust after policyOn invalid +- * @run main/othervm Distrust after policyOff valid +- * @run main/othervm Distrust before policyOn valid +- * @run main/othervm Distrust before policyOff valid +- */ +- +-public class Distrust { +- +- private static final String TEST_SRC = System.getProperty("test.src", "."); +- private static CertificateFactory cf; +- +- // Each of the roots have a test certificate chain stored in a file +- // named "-chain.pem". +- private static String[] rootsToTest = new String[] { +- "geotrustprimarycag2", "geotrustprimarycag3", +- "geotrustuniversalca", "thawteprimaryrootca", "thawteprimaryrootcag2", +- "thawteprimaryrootcag3", "verisignclass3g3ca", "verisignclass3g4ca", +- "verisignclass3g5ca", "verisignuniversalrootca" }; +- +- // Each of the subCAs with a delayed distrust date have a test certificate +- // chain stored in a file named "-chain.pem". +- private static String[] subCAsToTest = new String[]{"appleistca8g1"}; +- +- // A date that is after the restrictions take affect +- private static final Date APRIL_17_2019 = +- Date.from(LocalDate.of(2019, 4, 17) +- .atStartOfDay(ZoneOffset.UTC) +- .toInstant()); +- +- // A date that is a second before the restrictions take affect +- private static final Date BEFORE_APRIL_17_2019 = +- Date.from(LocalDate.of(2019, 4, 17) +- .atStartOfDay(ZoneOffset.UTC) +- .minusSeconds(1) +- .toInstant()); +- +- // A date that is after the subCA restrictions take affect +- private static final Date JANUARY_1_2020 = +- Date.from(LocalDate.of(2020, 1, 1) +- .atStartOfDay(ZoneOffset.UTC) +- .toInstant()); +- +- // A date that is a second before the subCA restrictions take affect +- private static final Date BEFORE_JANUARY_1_2020 = +- Date.from(LocalDate.of(2020, 1, 1) +- .atStartOfDay(ZoneOffset.UTC) +- .minusSeconds(1) +- .toInstant()); +- +- public static void main(String[] args) throws Exception { +- +- cf = CertificateFactory.getInstance("X.509"); +- +- boolean before = args[0].equals("before"); +- boolean policyOn = args[1].equals("policyOn"); +- boolean isValid = args[2].equals("valid"); +- +- if (!policyOn) { +- // disable policy (default is on) +- Security.setProperty("jdk.security.caDistrustPolicies", ""); +- } +- +- Date notBefore = before ? BEFORE_APRIL_17_2019 : APRIL_17_2019; +- +- X509TrustManager pkixTM = getTMF("PKIX", null); +- X509TrustManager sunX509TM = getTMF("SunX509", null); +- for (String test : rootsToTest) { +- System.err.println("Testing " + test); +- X509Certificate[] chain = loadCertificateChain(test); +- +- testTM(sunX509TM, chain, notBefore, isValid); +- testTM(pkixTM, chain, notBefore, isValid); +- } +- +- // test chain if params are passed to TrustManager +- System.err.println("Testing verisignuniversalrootca with params"); +- testTM(getTMF("PKIX", getParams()), +- loadCertificateChain("verisignuniversalrootca"), +- notBefore, isValid); +- +- // test code-signing chain (should be valid as restrictions don't apply) +- System.err.println("Testing verisignclass3g5ca code-signing chain"); +- Validator v = Validator.getInstance(Validator.TYPE_PKIX, +- Validator.VAR_CODE_SIGNING, +- getParams()); +- // set validation date so this will still pass when cert expires +- v.setValidationDate(new Date(1544197375493l)); +- v.validate(loadCertificateChain("verisignclass3g5ca-codesigning")); +- +- // test chains issued through subCAs +- notBefore = before ? BEFORE_JANUARY_1_2020 : JANUARY_1_2020; +- for (String test : subCAsToTest) { +- System.err.println("Testing " + test); +- X509Certificate[] chain = loadCertificateChain(test); +- +- testTM(sunX509TM, chain, notBefore, isValid); +- testTM(pkixTM, chain, notBefore, isValid); +- } +- } +- +- private static X509TrustManager getTMF(String type, +- PKIXBuilderParameters params) throws Exception { +- TrustManagerFactory tmf = TrustManagerFactory.getInstance(type); +- if (params == null) { +- tmf.init((KeyStore)null); +- } else { +- tmf.init(new CertPathTrustManagerParameters(params)); +- } +- TrustManager[] tms = tmf.getTrustManagers(); +- for (TrustManager tm : tms) { +- X509TrustManager xtm = (X509TrustManager)tm; +- return xtm; +- } +- throw new Exception("No TrustManager for " + type); +- } +- +- private static PKIXBuilderParameters getParams() throws Exception { +- PKIXBuilderParameters pbp = +- new PKIXBuilderParameters(SecurityUtils.getCacertsKeyStore(), +- new X509CertSelector()); +- pbp.setRevocationEnabled(false); +- return pbp; +- } +- +- private static void testTM(X509TrustManager xtm, X509Certificate[] chain, +- Date notBefore, boolean valid) throws Exception { +- // Check if TLS Server certificate (the first element of the chain) +- // is issued after the specified notBefore date (should be rejected +- // unless distrust property is false). To do this, we need to +- // fake the notBefore date since none of the test certs are issued +- // after then. +- chain[0] = new DistrustedTLSServerCert(chain[0], notBefore); +- +- try { +- xtm.checkServerTrusted(chain, "ECDHE_RSA"); +- if (!valid) { +- throw new Exception("chain should be invalid"); +- } +- } catch (CertificateException ce) { +- // expired TLS certificates should not be treated as failure +- if (expired(ce)) { +- System.err.println("Test is N/A, chain is expired"); +- return; +- } +- if (valid) { +- throw new Exception("Unexpected exception, chain " + +- "should be valid", ce); +- } +- if (ce instanceof ValidatorException) { +- ValidatorException ve = (ValidatorException)ce; +- if (ve.getErrorType() != ValidatorException.T_UNTRUSTED_CERT) { +- ce.printStackTrace(System.err); +- throw new Exception("Unexpected exception: " + ce); +- } +- } else { +- throw new Exception("Unexpected exception: " + ce); +- } +- } +- } +- +- // check if a cause of exception is an expired cert +- private static boolean expired(CertificateException ce) { +- if (ce instanceof CertificateExpiredException) { +- return true; +- } +- Throwable t = ce.getCause(); +- while (t != null) { +- if (t instanceof CertificateExpiredException) { +- return true; +- } +- t = t.getCause(); +- } +- return false; +- } +- +- private static X509Certificate[] loadCertificateChain(String name) +- throws Exception { +- try (InputStream in = new FileInputStream(TEST_SRC + File.separator + +- name + "-chain.pem")) { +- Collection certs = +- (Collection)cf.generateCertificates(in); +- return certs.toArray(new X509Certificate[0]); +- } +- } +- +- private static class DistrustedTLSServerCert extends X509Certificate { +- private final X509Certificate cert; +- private final Date notBefore; +- DistrustedTLSServerCert(X509Certificate cert, Date notBefore) { +- this.cert = cert; +- this.notBefore = notBefore; +- } +- public Set getCriticalExtensionOIDs() { +- return cert.getCriticalExtensionOIDs(); +- } +- public byte[] getExtensionValue(String oid) { +- return cert.getExtensionValue(oid); +- } +- public Set getNonCriticalExtensionOIDs() { +- return cert.getNonCriticalExtensionOIDs(); +- } +- public boolean hasUnsupportedCriticalExtension() { +- return cert.hasUnsupportedCriticalExtension(); +- } +- public void checkValidity() throws CertificateExpiredException, +- CertificateNotYetValidException { +- // always pass +- } +- public void checkValidity(Date date) throws CertificateExpiredException, +- CertificateNotYetValidException { +- // always pass +- } +- public int getVersion() { return cert.getVersion(); } +- public BigInteger getSerialNumber() { return cert.getSerialNumber(); } +- public Principal getIssuerDN() { return cert.getIssuerDN(); } +- public Principal getSubjectDN() { return cert.getSubjectDN(); } +- public Date getNotBefore() { return notBefore; } +- public Date getNotAfter() { return cert.getNotAfter(); } +- public byte[] getTBSCertificate() throws CertificateEncodingException { +- return cert.getTBSCertificate(); +- } +- public byte[] getSignature() { return cert.getSignature(); } +- public String getSigAlgName() { return cert.getSigAlgName(); } +- public String getSigAlgOID() { return cert.getSigAlgOID(); } +- public byte[] getSigAlgParams() { return cert.getSigAlgParams(); } +- public boolean[] getIssuerUniqueID() { +- return cert.getIssuerUniqueID(); +- } +- public boolean[] getSubjectUniqueID() { +- return cert.getSubjectUniqueID(); +- } +- public boolean[] getKeyUsage() { return cert.getKeyUsage(); } +- public int getBasicConstraints() { return cert.getBasicConstraints(); } +- public byte[] getEncoded() throws CertificateEncodingException { +- return cert.getEncoded(); +- } +- public void verify(PublicKey key) throws CertificateException, +- InvalidKeyException, NoSuchAlgorithmException, +- NoSuchProviderException, SignatureException { +- cert.verify(key); +- } +- public void verify(PublicKey key, String sigProvider) throws +- CertificateException, InvalidKeyException, NoSuchAlgorithmException, +- NoSuchProviderException, SignatureException { +- cert.verify(key, sigProvider); +- } +- public PublicKey getPublicKey() { return cert.getPublicKey(); } +- public String toString() { return cert.toString(); } +- } +-} +diff --git a/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/Camerfirma.java b/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/Camerfirma.java +new file mode 100644 +index 000000000..8d9dfe1ef +--- /dev/null ++++ b/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/Camerfirma.java +@@ -0,0 +1,75 @@ +/* -+ * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2022, Loongson Technology. All rights reserved. ++ * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it @@ -120060,217 +209385,382 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.internal.vm.ci/sha + * questions. + */ + -+/** -+ * The LoongArch64 platform independent portions of the JVMCI API. -+ */ -+package jdk.vm.ci.loongarch64; -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/jdk.internal.vm.ci/share/classes/module-info.java jdk11u-ls/src/jdk.internal.vm.ci/share/classes/module-info.java ---- openjdk/src/jdk.internal.vm.ci/share/classes/module-info.java 2022-10-12 23:00:03.000000000 +0800 -+++ jdk11u-ls/src/jdk.internal.vm.ci/share/classes/module-info.java 2023-09-12 13:54:26.521575972 +0800 -@@ -23,6 +23,12 @@ - * questions. - */ - ++import javax.net.ssl.X509TrustManager; ++import java.io.File; ++import java.security.Security; ++import java.time.LocalDate; ++import java.time.ZoneOffset; ++import java.time.ZonedDateTime; ++import java.util.Date; ++ +/* -+ * This file has been modified by Loongson Technology in 2022, These -+ * modifications are Copyright (c) 2022, Loongson Technology, and are made -+ * available on the same license terms set forth above. ++ * @test ++ * @bug 8346587 8350498 ++ * @summary Check that TLS Server certificates chaining back to distrusted ++ * Camerfirma root are invalid ++ * @library /test/lib ++ * @modules java.base/sun.security.validator ++ * @run main/othervm Camerfirma after policyOn invalid ++ * @run main/othervm Camerfirma after policyOff valid ++ * @run main/othervm Camerfirma before policyOn valid ++ * @run main/othervm Camerfirma before policyOff valid + */ + - module jdk.internal.vm.ci { - exports jdk.vm.ci.services to jdk.internal.vm.compiler; - exports jdk.vm.ci.runtime to -@@ -37,6 +43,7 @@ - - provides jdk.vm.ci.hotspot.HotSpotJVMCIBackendFactory with - jdk.vm.ci.hotspot.aarch64.AArch64HotSpotJVMCIBackendFactory, -+ jdk.vm.ci.hotspot.loongarch64.LoongArch64HotSpotJVMCIBackendFactory, - jdk.vm.ci.hotspot.amd64.AMD64HotSpotJVMCIBackendFactory, - jdk.vm.ci.hotspot.sparc.SPARCHotSpotJVMCIBackendFactory; - } -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/src/utils/hsdis/Makefile jdk11u-ls/src/utils/hsdis/Makefile ---- openjdk/src/utils/hsdis/Makefile 2022-10-12 23:00:04.000000000 +0800 -+++ jdk11u-ls/src/utils/hsdis/Makefile 2023-09-12 13:54:27.413577093 +0800 -@@ -94,6 +94,9 @@ - endif - CFLAGS += -O - DLDFLAGS += -shared -+ifeq ($(ARCH), mips64) -+DLDFLAGS += -Wl,-z,noexecstack -+endif - LDFLAGS += -ldl - OUTFLAGS += -o $@ - else -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/.src-rev jdk11u-ls/.src-rev ---- openjdk/.src-rev 2022-10-12 23:00:15.000000000 +0800 -+++ jdk11u-ls/.src-rev 1970-01-01 08:00:00.000000000 +0800 -@@ -1 +0,0 @@ --.:git:69ce82b96fce+ -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/test/hotspot/jtreg/compiler/cpuflags/TestAESIntrinsicsOnSupportedConfig.java jdk11u-ls/test/hotspot/jtreg/compiler/cpuflags/TestAESIntrinsicsOnSupportedConfig.java ---- openjdk/test/hotspot/jtreg/compiler/cpuflags/TestAESIntrinsicsOnSupportedConfig.java 2022-10-12 23:00:04.000000000 +0800 -+++ jdk11u-ls/test/hotspot/jtreg/compiler/cpuflags/TestAESIntrinsicsOnSupportedConfig.java 2023-09-12 13:54:27.665577410 +0800 -@@ -22,11 +22,17 @@ - */ - - /* -+ * This file has been modified by Loongson Technology in 2021, These -+ * modifications are Copyright (c) 2021, Loongson Technology, and are made -+ * available on the same license terms set forth above. -+ */ ++public class Camerfirma { + -+/* - * @test - * @library /test/lib / - * @modules java.base/jdk.internal.misc - * java.management -- * @requires vm.cpu.features ~= ".*aes.*" & !vm.graal.enabled -+ * @requires (vm.cpu.features ~= ".*aes.*" | os.arch == "loongarch64") & !vm.graal.enabled - * @build sun.hotspot.WhiteBox - * @run driver ClassFileInstaller sun.hotspot.WhiteBox - * sun.hotspot.WhiteBox$WhiteBoxPermission -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/test/hotspot/jtreg/compiler/cpuflags/TestAESIntrinsicsOnUnsupportedConfig.java jdk11u-ls/test/hotspot/jtreg/compiler/cpuflags/TestAESIntrinsicsOnUnsupportedConfig.java ---- openjdk/test/hotspot/jtreg/compiler/cpuflags/TestAESIntrinsicsOnUnsupportedConfig.java 2022-10-12 23:00:04.000000000 +0800 -+++ jdk11u-ls/test/hotspot/jtreg/compiler/cpuflags/TestAESIntrinsicsOnUnsupportedConfig.java 2023-09-12 13:54:27.665577410 +0800 -@@ -22,13 +22,19 @@ - */ - - /* -+ * This file has been modified by Loongson Technology in 2021, These -+ * modifications are Copyright (c) 2021, Loongson Technology, and are made -+ * available on the same license terms set forth above. -+ */ ++ private static final String CERT_PATH = "chains" + File.separator + "camerfirma"; + -+/* - * @test - * @library /test/lib / - * @modules java.base/jdk.internal.misc - * java.management ++ // Each of the roots have a test certificate chain stored in a file ++ // named "-chain.pem". ++ private static final String ROOT_TO_TEST = "camerfirmachambersca"; ++ ++ // Date after the restrictions take effect ++ private static final ZonedDateTime DISTRUST_DATE = ++ LocalDate.of(2025, 04, 16).atStartOfDay(ZoneOffset.UTC); ++ ++ public static void main(String[] args) throws Exception { ++ ++ // All the test certificates are signed with SHA-1, so we need ++ // to remove the constraint that disallows SHA-1 certificates. ++ String prop = Security.getProperty("jdk.certpath.disabledAlgorithms"); ++ String newProp = prop.replace(", SHA1 jdkCA & usage TLSServer", ""); ++ Security.setProperty("jdk.certpath.disabledAlgorithms", newProp); ++ ++ Distrust distrust = new Distrust(args); ++ ++ X509TrustManager[] tms = new X509TrustManager[]{ ++ distrust.getTMF("PKIX", null), ++ distrust.getTMF("SunX509", null) ++ }; ++ ++ Date notBefore = distrust.getNotBefore(DISTRUST_DATE); ++ distrust.testCertificateChain(CERT_PATH, notBefore, tms, ROOT_TO_TEST); ++ } ++} +diff --git a/test/jdk/sun/security/ssl/X509TrustManagerImpl/Entrust/Distrust.java b/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/Distrust.java +similarity index 53% +rename from test/jdk/sun/security/ssl/X509TrustManagerImpl/Entrust/Distrust.java +rename to test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/Distrust.java +index 1c1fcee36..3430a1b82 100644 +--- a/test/jdk/sun/security/ssl/X509TrustManagerImpl/Entrust/Distrust.java ++++ b/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/Distrust.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * - * @build sun.hotspot.WhiteBox -- * @requires !(vm.cpu.features ~= ".*aes.*") -+ * @requires !(vm.cpu.features ~= ".*aes.*" | os.arch == "loongarch64") - * @requires vm.compiler1.enabled | !vm.graal.enabled - * @run driver ClassFileInstaller sun.hotspot.WhiteBox - * sun.hotspot.WhiteBox$WhiteBoxPermission -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/test/hotspot/jtreg/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForOtherCPU.java jdk11u-ls/test/hotspot/jtreg/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForOtherCPU.java ---- openjdk/test/hotspot/jtreg/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForOtherCPU.java 2022-10-12 23:00:04.000000000 +0800 -+++ jdk11u-ls/test/hotspot/jtreg/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForOtherCPU.java 2023-09-12 13:54:27.717577475 +0800 -@@ -21,6 +21,12 @@ - * questions. + * This code is free software; you can redistribute it and/or modify it +@@ -25,7 +25,7 @@ import java.io.*; + import java.math.BigInteger; + import java.security.*; + import java.security.cert.*; +-import java.time.*; ++import java.time.ZonedDateTime; + import java.util.*; + import javax.net.ssl.*; + import sun.security.validator.Validator; +@@ -34,95 +34,80 @@ import sun.security.validator.ValidatorException; + import jdk.test.lib.security.SecurityUtils; + + /** +- * @test +- * @bug 8337664 8341059 +- * @summary Check that TLS Server certificates chaining back to distrusted +- * Entrust roots are invalid +- * @library /test/lib +- * @modules java.base/sun.security.validator +- * @run main/othervm Distrust after policyOn invalid +- * @run main/othervm Distrust after policyOff valid +- * @run main/othervm Distrust before policyOn valid +- * @run main/othervm Distrust before policyOff valid ++ * Helper class that provides methods to facilitate testing of distrusted roots. */ +- +-public class Distrust { ++public final class Distrust { -+/* -+ * This file has been modified by Loongson Technology in 2021, These -+ * modifications are Copyright (c) 2021, Loongson Technology, and are made -+ * available on the same license terms set forth above. -+ */ + private static final String TEST_SRC = System.getProperty("test.src", "."); + private static CertificateFactory cf; + +- // Each of the roots have a test certificate chain stored in a file +- // named "-chain.pem". +- private static String[] rootsToTest = new String[] { +- "entrustevca", "entrustrootcaec1", "entrustrootcag2", "entrustrootcag4", +- "entrust2048ca", "affirmtrustcommercialca", "affirmtrustnetworkingca", +- "affirmtrustpremiumca", "affirmtrustpremiumeccca" }; +- +- // A date that is after the restrictions take effect +- private static final Date NOVEMBER_12_2024 = +- Date.from(LocalDate.of(2024, 11, 12) +- .atStartOfDay(ZoneOffset.UTC) +- .toInstant()); +- +- // A date that is a second before the restrictions take effect +- private static final Date BEFORE_NOVEMBER_12_2024 = +- Date.from(LocalDate.of(2024, 11, 12) +- .atStartOfDay(ZoneOffset.UTC) +- .minusSeconds(1) +- .toInstant()); +- +- public static void main(String[] args) throws Exception { ++ private final boolean before; ++ private final boolean policyOn; ++ private final boolean isValid; + +- cf = CertificateFactory.getInstance("X.509"); +- +- boolean before = args[0].equals("before"); +- boolean policyOn = args[1].equals("policyOn"); +- boolean isValid = args[2].equals("valid"); ++ public Distrust(String[] args) { ++ before = args[0].equals("before"); ++ policyOn = args[1].equals("policyOn"); ++ isValid = args[2].equals("valid"); + + if (!policyOn) { + // disable policy (default is on) + Security.setProperty("jdk.security.caDistrustPolicies", ""); + } ++ } + - package compiler.intrinsics.sha.cli.testcases; ++ public Date getNotBefore(ZonedDateTime distrustDate) { ++ ZonedDateTime notBefore = before ? distrustDate.minusSeconds(1) : distrustDate; ++ return Date.from(notBefore.toInstant()); ++ } - import compiler.intrinsics.sha.cli.SHAOptionsBase; -@@ -32,19 +38,20 @@ +- Date notBefore = before ? BEFORE_NOVEMBER_12_2024 : NOVEMBER_12_2024; ++ public void testCodeSigningChain(String certPath, String name, Date validationDate) ++ throws Exception { ++ System.err.println("Testing " + name + " code-signing chain"); ++ Validator v = Validator.getInstance(Validator.TYPE_PKIX, ++ Validator.VAR_CODE_SIGNING, ++ getParams()); ++ // set validation date so this will still pass when cert expires ++ v.setValidationDate(validationDate); ++ v.validate(loadCertificateChain(certPath, name)); ++ } - /** - * Generic test case for SHA-related options targeted to any CPU except -- * AArch64, PPC, S390x, SPARC and X86. -+ * AArch64, PPC, S390x, SPARC, LoongArch64 and X86. - */ - public class GenericTestCaseForOtherCPU extends - SHAOptionsBase.TestCase { - public GenericTestCaseForOtherCPU(String optionName) { -- // Execute the test case on any CPU except AArch64, PPC, S390x, SPARC and X86. -+ // Execute the test case on any CPU except AArch64, PPC, S390x, SPARC, LoongArch64 and X86. - super(optionName, new NotPredicate( - new OrPredicate(Platform::isAArch64, - new OrPredicate(Platform::isS390x, - new OrPredicate(Platform::isSparc, - new OrPredicate(Platform::isPPC, -+ new OrPredicate(Platform::isLoongArch64, - new OrPredicate(Platform::isX64, -- Platform::isX86))))))); -+ Platform::isX86)))))))); - } +- X509TrustManager pkixTM = getTMF("PKIX", null); +- X509TrustManager sunX509TM = getTMF("SunX509", null); +- for (String test : rootsToTest) { ++ public void testCertificateChain(String certPath, Date notBefore, X509TrustManager[] tms, ++ String... tests) throws Exception { ++ for (String test : tests) { + System.err.println("Testing " + test); +- X509Certificate[] chain = loadCertificateChain(test); ++ X509Certificate[] chain = loadCertificateChain(certPath, test); - @Override -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/CodeInstallationTest.java jdk11u-ls/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/CodeInstallationTest.java ---- openjdk/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/CodeInstallationTest.java 2022-10-12 23:00:04.000000000 +0800 -+++ jdk11u-ls/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/CodeInstallationTest.java 2023-09-12 13:54:27.749577516 +0800 -@@ -29,6 +29,7 @@ - import jdk.vm.ci.code.TargetDescription; - import jdk.vm.ci.code.test.amd64.AMD64TestAssembler; - import jdk.vm.ci.code.test.sparc.SPARCTestAssembler; -+import jdk.vm.ci.code.test.loongarch64.LoongArch64TestAssembler; - import jdk.vm.ci.hotspot.HotSpotCompiledCode; - import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; - import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; -@@ -37,6 +38,7 @@ - import jdk.vm.ci.runtime.JVMCI; - import jdk.vm.ci.runtime.JVMCIBackend; - import jdk.vm.ci.sparc.SPARC; -+import jdk.vm.ci.loongarch64.LoongArch64; - import org.junit.Assert; +- testTM(sunX509TM, chain, notBefore, isValid); +- testTM(pkixTM, chain, notBefore, isValid); ++ for (X509TrustManager tm : tms) { ++ testTM(tm, chain, notBefore, isValid); ++ } + } + } - import java.lang.reflect.Method; -@@ -72,6 +74,8 @@ - return new AMD64TestAssembler(codeCache, config); - } else if (arch instanceof SPARC) { - return new SPARCTestAssembler(codeCache, config); -+ } else if (arch instanceof LoongArch64) { -+ return new LoongArch64TestAssembler(codeCache, config); +- private static X509TrustManager getTMF(String type, +- PKIXBuilderParameters params) throws Exception { ++ public X509TrustManager getTMF(String type, PKIXBuilderParameters params) throws Exception { + TrustManagerFactory tmf = TrustManagerFactory.getInstance(type); + if (params == null) { +- tmf.init((KeyStore)null); ++ tmf.init((KeyStore) null); } else { - Assert.fail("unsupported architecture"); - return null; -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/DataPatchTest.java jdk11u-ls/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/DataPatchTest.java ---- openjdk/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/DataPatchTest.java 2022-10-12 23:00:04.000000000 +0800 -+++ jdk11u-ls/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/DataPatchTest.java 2023-09-12 13:54:27.749577516 +0800 -@@ -23,7 +23,7 @@ + tmf.init(new CertPathTrustManagerParameters(params)); + } + TrustManager[] tms = tmf.getTrustManagers(); + for (TrustManager tm : tms) { +- X509TrustManager xtm = (X509TrustManager)tm; +- return xtm; ++ return (X509TrustManager) tm; + } +- throw new Exception("No TrustManager for " + type); ++ throw new RuntimeException("No TrustManager for " + type); + } - /** - * @test -- * @requires vm.jvmci & (vm.simpleArch == "x64" | vm.simpleArch == "sparcv9") -+ * @requires vm.jvmci & (vm.simpleArch == "x64" | vm.simpleArch == "sparcv9" | vm.simpleArch == "loongarch64") - * @library / - * @modules jdk.internal.vm.ci/jdk.vm.ci.hotspot - * jdk.internal.vm.ci/jdk.vm.ci.meta -@@ -32,7 +32,8 @@ - * jdk.internal.vm.ci/jdk.vm.ci.runtime - * jdk.internal.vm.ci/jdk.vm.ci.amd64 - * jdk.internal.vm.ci/jdk.vm.ci.sparc -- * @compile CodeInstallationTest.java DebugInfoTest.java TestAssembler.java TestHotSpotVMConfig.java amd64/AMD64TestAssembler.java sparc/SPARCTestAssembler.java -+ * jdk.internal.vm.ci/jdk.vm.ci.loongarch64 -+ * @compile CodeInstallationTest.java DebugInfoTest.java TestAssembler.java TestHotSpotVMConfig.java amd64/AMD64TestAssembler.java sparc/SPARCTestAssembler.java loongarch64/LoongArch64TestAssembler.java - * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -Djvmci.Compiler=null jdk.vm.ci.code.test.DataPatchTest - */ +- private static PKIXBuilderParameters getParams() throws Exception { ++ public PKIXBuilderParameters getParams() throws Exception { + PKIXBuilderParameters pbp = +- new PKIXBuilderParameters(SecurityUtils.getCacertsKeyStore(), +- new X509CertSelector()); ++ new PKIXBuilderParameters(SecurityUtils.getCacertsKeyStore(), ++ new X509CertSelector()); + pbp.setRevocationEnabled(false); + return pbp; + } -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/InterpreterFrameSizeTest.java jdk11u-ls/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/InterpreterFrameSizeTest.java ---- openjdk/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/InterpreterFrameSizeTest.java 2022-10-12 23:00:04.000000000 +0800 -+++ jdk11u-ls/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/InterpreterFrameSizeTest.java 2023-09-12 13:54:27.749577516 +0800 -@@ -23,7 +23,7 @@ +- private static void testTM(X509TrustManager xtm, X509Certificate[] chain, +- Date notBefore, boolean valid) throws Exception { ++ public void testTM(X509TrustManager xtm, X509Certificate[] chain, ++ Date notBefore, boolean valid) { + // Check if TLS Server certificate (the first element of the chain) + // is issued after the specified notBefore date (should be rejected + // unless distrust property is false). To do this, we need to +@@ -130,67 +115,54 @@ public class Distrust { + // after then. + chain[0] = new DistrustedTLSServerCert(chain[0], notBefore); - /** - * @test -- * @requires vm.jvmci & (vm.simpleArch == "x64" | vm.simpleArch == "sparcv9") -+ * @requires vm.jvmci & (vm.simpleArch == "x64" | vm.simpleArch == "sparcv9" | vm.simpleArch == "loongarch64") - * @modules jdk.internal.vm.ci/jdk.vm.ci.hotspot - * jdk.internal.vm.ci/jdk.vm.ci.code - * jdk.internal.vm.ci/jdk.vm.ci.code.site -@@ -32,7 +32,8 @@ - * jdk.internal.vm.ci/jdk.vm.ci.common - * jdk.internal.vm.ci/jdk.vm.ci.amd64 - * jdk.internal.vm.ci/jdk.vm.ci.sparc -- * @compile CodeInstallationTest.java TestAssembler.java TestHotSpotVMConfig.java amd64/AMD64TestAssembler.java sparc/SPARCTestAssembler.java -+ * jdk.internal.vm.ci/jdk.vm.ci.loongarch64 -+ * @compile CodeInstallationTest.java TestAssembler.java TestHotSpotVMConfig.java amd64/AMD64TestAssembler.java sparc/SPARCTestAssembler.java loongarch64/LoongArch64TestAssembler.java - * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -Djvmci.Compiler=null jdk.vm.ci.code.test.InterpreterFrameSizeTest - */ ++ // Wrap the intermediate and root CA certs in NonExpiringTLSServerCert ++ // so it will never throw a CertificateExpiredException ++ for (int i = 1; i < chain.length; i++) { ++ chain[i] = new NonExpiringTLSServerCert(chain[i]); ++ } ++ + try { + xtm.checkServerTrusted(chain, "ECDHE_RSA"); + if (!valid) { +- throw new Exception("chain should be invalid"); ++ throw new RuntimeException("chain should be invalid"); + } + } catch (CertificateException ce) { +- // expired TLS certificates should not be treated as failure +- if (expired(ce)) { +- System.err.println("Test is N/A, chain is expired"); +- return; +- } + if (valid) { +- throw new Exception("Unexpected exception, chain " + +- "should be valid", ce); ++ throw new RuntimeException("Unexpected exception, chain " + ++ "should be valid", ce); + } + if (ce instanceof ValidatorException) { +- ValidatorException ve = (ValidatorException)ce; ++ ValidatorException ve = (ValidatorException) ce; + if (ve.getErrorType() != ValidatorException.T_UNTRUSTED_CERT) { + ce.printStackTrace(System.err); +- throw new Exception("Unexpected exception: " + ce); ++ throw new RuntimeException("Unexpected exception: " + ce); + } + } else { +- throw new Exception("Unexpected exception: " + ce); +- } +- } +- } +- +- // check if a cause of exception is an expired cert +- private static boolean expired(CertificateException ce) { +- if (ce instanceof CertificateExpiredException) { +- return true; +- } +- Throwable t = ce.getCause(); +- while (t != null) { +- if (t instanceof CertificateExpiredException) { +- return true; ++ throw new RuntimeException(ce); + } +- t = t.getCause(); + } +- return false; + } -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/loongarch64/LoongArch64TestAssembler.java jdk11u-ls/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/loongarch64/LoongArch64TestAssembler.java ---- openjdk/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/loongarch64/LoongArch64TestAssembler.java 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/loongarch64/LoongArch64TestAssembler.java 2023-09-12 13:54:27.753577521 +0800 -@@ -0,0 +1,568 @@ +- private static X509Certificate[] loadCertificateChain(String name) ++ private X509Certificate[] loadCertificateChain(String certPath, String name) + throws Exception { +- try (InputStream in = new FileInputStream(TEST_SRC + File.separator + +- name + "-chain.pem")) { ++ if (cf == null) { ++ cf = CertificateFactory.getInstance("X.509"); ++ } ++ try (InputStream in = new FileInputStream(TEST_SRC + File.separator + certPath + ++ File.separator + name + "-chain.pem")) { + Collection certs = +- (Collection)cf.generateCertificates(in); ++ (Collection) cf.generateCertificates(in); + return certs.toArray(new X509Certificate[0]); + } + } + +- private static class DistrustedTLSServerCert extends X509Certificate { ++ private static class NonExpiringTLSServerCert extends X509Certificate { + private final X509Certificate cert; +- private final Date notBefore; +- DistrustedTLSServerCert(X509Certificate cert, Date notBefore) { ++ NonExpiringTLSServerCert(X509Certificate cert) { + this.cert = cert; +- this.notBefore = notBefore; + } + public Set getCriticalExtensionOIDs() { +- return cert.getCriticalExtensionOIDs(); ++ return cert.getCriticalExtensionOIDs(); + } + public byte[] getExtensionValue(String oid) { + return cert.getExtensionValue(oid); +@@ -201,19 +173,17 @@ public class Distrust { + public boolean hasUnsupportedCriticalExtension() { + return cert.hasUnsupportedCriticalExtension(); + } +- public void checkValidity() throws CertificateExpiredException, +- CertificateNotYetValidException { ++ public void checkValidity() { + // always pass + } +- public void checkValidity(Date date) throws CertificateExpiredException, +- CertificateNotYetValidException { ++ public void checkValidity(Date date) { + // always pass + } + public int getVersion() { return cert.getVersion(); } + public BigInteger getSerialNumber() { return cert.getSerialNumber(); } + public Principal getIssuerDN() { return cert.getIssuerDN(); } + public Principal getSubjectDN() { return cert.getSubjectDN(); } +- public Date getNotBefore() { return notBefore; } ++ public Date getNotBefore() { return cert.getNotBefore(); } + public Date getNotAfter() { return cert.getNotAfter(); } + public byte[] getTBSCertificate() throws CertificateEncodingException { + return cert.getTBSCertificate(); +@@ -228,22 +198,37 @@ public class Distrust { + public boolean[] getSubjectUniqueID() { + return cert.getSubjectUniqueID(); + } +- public boolean[] getKeyUsage() { return cert.getKeyUsage(); } ++ public boolean[] getKeyUsage() { ++ // Turn on the Digital Signature bit. Some certs that we want ++ // to use as test certs don't have this bit turned on. ++ boolean[] withDigitalSignature = cert.getKeyUsage(); ++ withDigitalSignature[0] = true; ++ return withDigitalSignature; ++ } + public int getBasicConstraints() { return cert.getBasicConstraints(); } + public byte[] getEncoded() throws CertificateEncodingException { + return cert.getEncoded(); + } + public void verify(PublicKey key) throws CertificateException, +- InvalidKeyException, NoSuchAlgorithmException, +- NoSuchProviderException, SignatureException { ++ InvalidKeyException, NoSuchAlgorithmException, ++ NoSuchProviderException, SignatureException { + cert.verify(key); + } + public void verify(PublicKey key, String sigProvider) throws +- CertificateException, InvalidKeyException, NoSuchAlgorithmException, +- NoSuchProviderException, SignatureException { ++ CertificateException, InvalidKeyException, NoSuchAlgorithmException, ++ NoSuchProviderException, SignatureException { + cert.verify(key, sigProvider); + } + public PublicKey getPublicKey() { return cert.getPublicKey(); } + public String toString() { return cert.toString(); } + } ++ ++ private static class DistrustedTLSServerCert extends NonExpiringTLSServerCert { ++ private final Date notBefore; ++ DistrustedTLSServerCert(X509Certificate cert, Date notBefore) { ++ super(cert); ++ this.notBefore = notBefore; ++ } ++ public Date getNotBefore() { return notBefore; } ++ } + } +diff --git a/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/Entrust.java b/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/Entrust.java +new file mode 100644 +index 000000000..0e7617d1b +--- /dev/null ++++ b/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/Entrust.java +@@ -0,0 +1,67 @@ +/* -+ * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2022, Loongson Technology. All rights reserved. ++ * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it @@ -120292,754 +209782,1506 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/test/hotspot/jtreg/compile + * questions. + */ + -+package jdk.vm.ci.code.test.loongarch64; -+ -+import jdk.vm.ci.loongarch64.LoongArch64; -+import jdk.vm.ci.loongarch64.LoongArch64Kind; -+import jdk.vm.ci.code.CallingConvention; -+import jdk.vm.ci.code.CodeCacheProvider; -+import jdk.vm.ci.code.DebugInfo; -+import jdk.vm.ci.code.Register; -+import jdk.vm.ci.code.RegisterArray; -+import jdk.vm.ci.code.RegisterValue; -+import jdk.vm.ci.code.StackSlot; -+import jdk.vm.ci.code.site.ConstantReference; -+import jdk.vm.ci.code.site.DataSectionReference; -+import jdk.vm.ci.code.test.TestAssembler; -+import jdk.vm.ci.code.test.TestHotSpotVMConfig; -+import jdk.vm.ci.hotspot.HotSpotCallingConventionType; -+import jdk.vm.ci.hotspot.HotSpotConstant; -+import jdk.vm.ci.hotspot.HotSpotForeignCallTarget; -+import jdk.vm.ci.meta.AllocatableValue; -+import jdk.vm.ci.meta.JavaKind; -+import jdk.vm.ci.meta.VMConstant; -+ -+public class LoongArch64TestAssembler extends TestAssembler { -+ -+ private static final Register scratchRegister = LoongArch64.SCR1; -+ private static final Register doubleScratch = LoongArch64.f23; -+ private static final RegisterArray nativeGeneralParameterRegisters = new RegisterArray(LoongArch64.a0, -+ LoongArch64.a1, LoongArch64.a2, -+ LoongArch64.a3, LoongArch64.a4, -+ LoongArch64.a5, LoongArch64.a6, -+ LoongArch64.a7); -+ private static final RegisterArray floatParameterRegisters = new RegisterArray(LoongArch64.f0, -+ LoongArch64.f1, LoongArch64.f2, -+ LoongArch64.f3, LoongArch64.f4, -+ LoongArch64.f5, LoongArch64.f6, -+ LoongArch64.f7); -+ private static int currentGeneral = 0; -+ private static int currentFloat = 0; -+ public LoongArch64TestAssembler(CodeCacheProvider codeCache, TestHotSpotVMConfig config) { -+ super(codeCache, config, -+ 16 /* initialFrameSize */, 16 /* stackAlignment */, -+ LoongArch64Kind.UDWORD /* narrowOopKind */, -+ /* registers */ -+ LoongArch64.a0, LoongArch64.a1, LoongArch64.a2, LoongArch64.a3, -+ LoongArch64.a4, LoongArch64.a5, LoongArch64.a6, LoongArch64.a7); -+ } -+ -+ private static int low(int x, int l) { -+ assert l < 32; -+ return (x >> 0) & ((1 << l)-1); -+ } -+ -+ private static int low16(int x) { -+ return low(x, 16); -+ } -+ -+ private void emitNop() { -+ code.emitInt(0x3400000); -+ } -+ -+ private void emitPcaddu12i(Register rj, int si20) { -+ // pcaddu12i -+ code.emitInt((0b0001110 << 25) -+ | (low(si20, 20) << 5) -+ | rj.encoding); -+ } -+ -+ private void emitAdd(Register rd, Register rj, Register rk) { -+ // add_d -+ code.emitInt((0b00000000000100001 << 15) -+ | (rk.encoding << 10) -+ | (rj.encoding << 5) -+ | rd.encoding); -+ } -+ -+ private void emitAdd(Register rd, Register rj, int si12) { -+ // addi_d -+ code.emitInt((0b0000001011 << 22) -+ | (low(si12, 12) << 10) -+ | (rj.encoding << 5) -+ | rd.encoding); -+ } -+ -+ private void emitSub(Register rd, Register rj, Register rk) { -+ // sub_d -+ code.emitInt((0b00000000000100011 << 15) -+ | (rk.encoding << 10) -+ | (rj.encoding << 5) -+ | rd.encoding); -+ } -+ -+ private void emitShiftLeft(Register rd, Register rj, int shift) { -+ // slli_d -+ code.emitInt((0b00000000010000 << 18) -+ | (low(( (0b01 << 6) | shift ), 8) << 10) -+ | (rj.encoding << 5) -+ | rd.encoding); -+ } -+ -+ private void emitLu12i_w(Register rj, int imm20) { -+ // lu12i_w -+ code.emitInt((0b0001010 << 25) -+ | (low(imm20, 20)<<5) -+ | rj.encoding); -+ } -+ -+ private void emitOri(Register rd, Register rj, int ui12) { -+ // ori -+ code.emitInt((0b0000001110 << 22) -+ | (low(ui12, 12) << 10) -+ | (rj.encoding << 5) -+ | rd.encoding); -+ } -+ -+ private void emitLu32i_d(Register rj, int imm20) { -+ // lu32i_d -+ code.emitInt((0b0001011 << 25) -+ | (low(imm20, 20)<<5) -+ | rj.encoding); -+ } -+ -+ private void emitLu52i_d(Register rd, Register rj, int imm12) { -+ // lu52i_d -+ code.emitInt((0b0000001100 << 22) -+ | (low(imm12, 12) << 10) -+ | (rj.encoding << 5) -+ | rd.encoding); -+ } -+ -+ private void emitLoadImmediate(Register rd, int imm32) { -+ emitLu12i_w(rd, (imm32 >> 12) & 0xfffff); -+ emitOri(rd, rd, imm32 & 0xfff); -+ } -+ -+ private void emitLi52(Register rj, long imm) { -+ emitLu12i_w(rj, (int) ((imm >> 12) & 0xfffff)); -+ emitOri(rj, rj, (int) (imm & 0xfff)); -+ emitLu32i_d(rj, (int) ((imm >> 32) & 0xfffff)); -+ } ++import java.io.File; ++import java.time.*; ++import java.util.*; ++import javax.net.ssl.*; + -+ private void emitLi64(Register rj, long imm) { -+ emitLu12i_w(rj, (int) ((imm >> 12) & 0xfffff)); -+ emitOri(rj, rj, (int) (imm & 0xfff)); -+ emitLu32i_d(rj, (int) ((imm >> 32) & 0xfffff)); -+ emitLu52i_d(rj, rj, (int) ((imm >> 52) & 0xfff)); -+ } ++/** ++ * @test ++ * @bug 8337664 8341059 8361212 ++ * @summary Check that TLS Server certificates chaining back to distrusted ++ * Entrust roots are invalid ++ * @library /test/lib ++ * @modules java.base/sun.security.validator ++ * @run main/othervm Entrust after policyOn invalid ++ * @run main/othervm Entrust after policyOff valid ++ * @run main/othervm Entrust before policyOn valid ++ * @run main/othervm Entrust before policyOff valid ++ */ + -+ private void emitOr(Register rd, Register rj, Register rk) { -+ // orr -+ code.emitInt((0b00000000000101010 << 15) -+ | (rk.encoding << 10) -+ | (rj.encoding << 5) -+ | rd.encoding); -+ } ++public class Entrust { + -+ private void emitMove(Register rd, Register rs) { -+ // move -+ emitOr(rd, rs, LoongArch64.zero); -+ } ++ private static final String CERT_PATH = "chains" + File.separator + "entrust"; + -+ private void emitMovfr2gr(Register rd, LoongArch64Kind kind, Register rj) { -+ // movfr2gr_s/movfr2gr_d -+ int opc = 0; -+ switch (kind) { -+ case SINGLE: opc = 0b0000000100010100101101; break; -+ case DOUBLE: opc = 0b0000000100010100101110; break; -+ default: throw new IllegalArgumentException(); -+ } -+ code.emitInt((opc << 10) -+ | (rj.encoding << 5) -+ | rd.encoding); -+ } ++ // Each of the roots have a test certificate chain stored in a file ++ // named "-chain.pem". ++ private static final String[] ROOTS_TO_TEST = new String[]{ ++ "entrustevca", "entrustrootcaec1", "entrustrootcag2", ++ "entrustrootcag4", "entrust2048ca"}; + -+ private void emitLoadRegister(Register rd, LoongArch64Kind kind, Register rj, int offset) { -+ // load -+ assert offset >= 0; -+ int opc = 0; -+ switch (kind) { -+ case BYTE: opc = 0b0010100000; break; -+ case WORD: opc = 0b0010100001; break; -+ case DWORD: opc = 0b0010100010; break; -+ case QWORD: opc = 0b0010100011; break; -+ case UDWORD: opc = 0b0010101010; break; -+ case SINGLE: opc = 0b0010101100; break; -+ case DOUBLE: opc = 0b0010101110; break; -+ default: throw new IllegalArgumentException(); -+ } -+ code.emitInt((opc << 22) -+ | (low(offset, 12) << 10) -+ | (rj.encoding << 5) -+ | rd.encoding); -+ } ++ // Date when the restrictions take effect ++ private static final ZonedDateTime DISTRUST_DATE = ++ LocalDate.of(2024, 11, 12).atStartOfDay(ZoneOffset.UTC); + -+ private void emitStoreRegister(Register rd, LoongArch64Kind kind, Register rj, int offset) { -+ // store -+ assert offset >= 0; -+ int opc = 0; -+ switch (kind) { -+ case BYTE: opc = 0b0010100100; break; -+ case WORD: opc = 0b0010100101; break; -+ case DWORD: opc = 0b0010100110; break; -+ case QWORD: opc = 0b0010100111; break; -+ case SINGLE: opc = 0b0010101101; break; -+ case DOUBLE: opc = 0b0010101111; break; -+ default: throw new IllegalArgumentException(); -+ } -+ code.emitInt((opc << 22) -+ | (low(offset, 12) << 10) -+ | (rj.encoding << 5) -+ | rd.encoding); -+ } ++ public static void main(String[] args) throws Exception { ++ Distrust distrust = new Distrust(args); + -+ private void emitJirl(Register rd, Register rj, int offs) { -+ // jirl -+ code.emitInt((0b010011 << 26) -+ | (low16(offs >> 2) << 10) -+ | (rj.encoding << 5) -+ | rd.encoding); -+ } ++ X509TrustManager[] tms = new X509TrustManager[]{ ++ distrust.getTMF("PKIX", null), ++ distrust.getTMF("SunX509", null) ++ }; + -+ @Override -+ public void emitGrowStack(int size) { -+ assert size % 16 == 0; -+ if (size > -4096 && size < 0) { -+ emitAdd(LoongArch64.sp, LoongArch64.sp, -size); -+ } else if (size == 0) { -+ // No-op -+ } else if (size < 4096) { -+ emitAdd(LoongArch64.sp, LoongArch64.sp, -size); -+ } else if (size < 65535) { -+ emitLoadImmediate(scratchRegister, size); -+ emitSub(LoongArch64.sp, LoongArch64.sp, scratchRegister); -+ } else { -+ throw new IllegalArgumentException(); -+ } ++ Date notBefore = distrust.getNotBefore(DISTRUST_DATE); ++ distrust.testCertificateChain(CERT_PATH, notBefore, tms, ROOTS_TO_TEST); + } ++} +diff --git a/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/Symantec.java b/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/Symantec.java +new file mode 100644 +index 000000000..4e099a8de +--- /dev/null ++++ b/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/Symantec.java +@@ -0,0 +1,95 @@ ++/* ++ * Copyright (c) 2018, 2024, 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. ++ */ + -+ @Override -+ public void emitPrologue() { -+ // Must be patchable by NativeJump::patch_verified_entry -+ emitNop(); -+ emitGrowStack(32); -+ emitStoreRegister(LoongArch64.ra, LoongArch64Kind.QWORD, LoongArch64.sp, 24); -+ emitStoreRegister(LoongArch64.fp, LoongArch64Kind.QWORD, LoongArch64.sp, 16); -+ emitGrowStack(-16); -+ emitMove(LoongArch64.fp, LoongArch64.sp); -+ setDeoptRescueSlot(newStackSlot(LoongArch64Kind.QWORD)); -+ } ++import javax.net.ssl.X509TrustManager; ++import java.io.File; ++import java.time.*; ++import java.util.*; + -+ @Override -+ public void emitEpilogue() { -+ recordMark(config.MARKID_DEOPT_HANDLER_ENTRY); -+ recordCall(new HotSpotForeignCallTarget(config.handleDeoptStub), 4*4, true, null); -+ emitCall(0xdeaddeaddeadL); -+ } + -+ @Override -+ public void emitCallPrologue(CallingConvention cc, Object... prim) { -+ emitGrowStack(cc.getStackSize()); -+ frameSize += cc.getStackSize(); -+ AllocatableValue[] args = cc.getArguments(); -+ for (int i = 0; i < args.length; i++) { -+ emitLoad(args[i], prim[i]); -+ } -+ currentGeneral = 0; -+ currentFloat = 0; -+ } ++/** ++ * @test ++ * @bug 8207258 8216280 ++ * @summary Check that TLS Server certificates chaining back to distrusted ++ * Symantec roots are invalid ++ * @library /test/lib ++ * @modules java.base/sun.security.validator ++ * @run main/othervm Symantec after policyOn invalid ++ * @run main/othervm Symantec after policyOff valid ++ * @run main/othervm Symantec before policyOn valid ++ * @run main/othervm Symantec before policyOff valid ++ */ + -+ @Override -+ public void emitCallEpilogue(CallingConvention cc) { -+ emitGrowStack(-cc.getStackSize()); -+ frameSize -= cc.getStackSize(); -+ } ++public class Symantec { + -+ @Override -+ public void emitCall(long addr) { -+ // long call (absolute) -+ // lu12i_w(T4, split_low20(value >> 12)); -+ // lu32i_d(T4, split_low20(value >> 32)); -+ // jirl(RA, T4, split_low12(value)); -+ emitLu12i_w(LoongArch64.t4, (int) ((addr >> 12) & 0xfffff)); -+ emitLu32i_d(LoongArch64.t4, (int) ((addr >> 32) & 0xfffff)); -+ emitJirl(LoongArch64.ra, LoongArch64.t4, (int) (addr & 0xfff)); -+ } ++ private static final String certPath = "chains" + File.separator + "symantec"; + -+ @Override -+ public void emitLoad(AllocatableValue av, Object prim) { -+ if (av instanceof RegisterValue) { -+ Register reg = ((RegisterValue) av).getRegister(); -+ if (prim instanceof Float) { -+ if (currentFloat < floatParameterRegisters.size()) { -+ currentFloat++; -+ emitLoadFloat(reg, (Float) prim); -+ } else if (currentGeneral < nativeGeneralParameterRegisters.size()) { -+ currentGeneral++; -+ emitLoadFloat(doubleScratch, (Float) prim); -+ emitMovfr2gr(reg, LoongArch64Kind.SINGLE, doubleScratch); -+ } -+ } else if (prim instanceof Double) { -+ if (currentFloat < floatParameterRegisters.size()) { -+ currentFloat++; -+ emitLoadDouble(reg, (Double) prim); -+ } else if (currentGeneral < nativeGeneralParameterRegisters.size()) { -+ currentGeneral++; -+ emitLoadDouble(doubleScratch, (Double) prim); -+ emitMovfr2gr(reg, LoongArch64Kind.DOUBLE, doubleScratch); -+ } -+ } else if (prim instanceof Integer) { -+ emitLoadInt(reg, (Integer) prim); -+ } else if (prim instanceof Long) { -+ emitLoadLong(reg, (Long) prim); -+ } -+ } else if (av instanceof StackSlot) { -+ StackSlot slot = (StackSlot) av; -+ if (prim instanceof Float) { -+ emitFloatToStack(slot, emitLoadFloat(doubleScratch, (Float) prim)); -+ } else if (prim instanceof Double) { -+ emitDoubleToStack(slot, emitLoadDouble(doubleScratch, (Double) prim)); -+ } else if (prim instanceof Integer) { -+ emitIntToStack(slot, emitLoadInt(scratchRegister, (Integer) prim)); -+ } else if (prim instanceof Long) { -+ emitLongToStack(slot, emitLoadLong(scratchRegister, (Long) prim)); -+ } else { -+ assert false : "Unimplemented"; -+ } -+ } else { -+ throw new IllegalArgumentException("Unknown value " + av); -+ } -+ } ++ // Each of the roots have a test certificate chain stored in a file ++ // named "-chain.pem". ++ private static final String[] rootsToTest = new String[]{ ++ "geotrustprimarycag2", "geotrustprimarycag3", "geotrustuniversalca", ++ "thawteprimaryrootca", "thawteprimaryrootcag2", "thawteprimaryrootcag3", ++ "verisignclass3g3ca", "verisignclass3g4ca", "verisignclass3g5ca", ++ "verisignuniversalrootca" ++ }; + -+ @Override -+ public Register emitLoadPointer(HotSpotConstant c) { -+ recordDataPatchInCode(new ConstantReference((VMConstant) c)); ++ // Each of the subCAs with a delayed distrust date have a test certificate ++ // chain stored in a file named "-chain.pem". ++ private static String[] subCAsToTest = new String[]{"appleistca8g1"}; + -+ Register ret = newRegister(); -+ // need to match patchable_li52 instruction sequence -+ // lu12i_ori_lu32i -+ emitLi52(ret, 0xdeaddead); -+ return ret; -+ } ++ // Date when the restrictions take effect ++ private static final ZonedDateTime ROOTS_DISTRUST_DATE = ++ LocalDate.of(2019, 4, 17).atStartOfDay(ZoneOffset.UTC); + -+ @Override -+ public Register emitLoadPointer(Register b, int offset) { -+ Register ret = newRegister(); -+ emitLoadRegister(ret, LoongArch64Kind.QWORD, b, offset); -+ return ret; -+ } ++ // Date when the subCA restrictions take effect ++ private static final ZonedDateTime SUBCA_DISTRUST_DATE = ++ LocalDate.of(2020, 1, 1).atStartOfDay(ZoneOffset.UTC); + -+ @Override -+ public Register emitLoadNarrowPointer(DataSectionReference ref) { -+ recordDataPatchInCode(ref); ++ public static void main(String[] args) throws Exception { ++ Distrust distrust = new Distrust(args); ++ X509TrustManager[] tms = new X509TrustManager[]{ ++ distrust.getTMF("PKIX", null), ++ distrust.getTMF("SunX509", null) ++ }; + -+ Register ret = newRegister(); -+ emitPcaddu12i(ret, 0xdead >> 12); -+ emitAdd(ret, ret, 0xdead & 0xfff); -+ emitLoadRegister(ret, LoongArch64Kind.UDWORD, ret, 0); -+ return ret; -+ } ++ // test chains issued through roots ++ Date notBefore = distrust.getNotBefore(ROOTS_DISTRUST_DATE); ++ distrust.testCertificateChain(certPath, notBefore, tms, rootsToTest); + -+ @Override -+ public Register emitLoadPointer(DataSectionReference ref) { -+ recordDataPatchInCode(ref); ++ // test chain if params are passed to TrustManager ++ System.err.println("Testing verisignuniversalrootca with params"); ++ X509TrustManager[] tmsParams = new X509TrustManager[]{ ++ distrust.getTMF("PKIX", distrust.getParams()) ++ }; ++ distrust.testCertificateChain(certPath, notBefore, tmsParams, ++ "verisignuniversalrootca"); ++ ++ // test code-signing chain (should be valid as restrictions don't apply) ++ Date validationDate = new Date(1544197375493L); ++ distrust.testCodeSigningChain(certPath, "verisignclass3g5ca-codesigning", validationDate); ++ ++ // test chains issued through subCAs ++ notBefore = distrust.getNotBefore(SUBCA_DISTRUST_DATE); ++ distrust.testCertificateChain(certPath, notBefore, tms, subCAsToTest); ++ } ++} +diff --git a/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/camerfirma/camerfirmachambersca-chain.pem b/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/camerfirma/camerfirmachambersca-chain.pem +new file mode 100644 +index 000000000..f23c6dafe +--- /dev/null ++++ b/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/camerfirma/camerfirmachambersca-chain.pem +@@ -0,0 +1,64 @@ ++Owner: CN=Camerfirma Corporate Server II - 2015, ++ L=Madrid (see current address at https://www.camerfirma.com/address), ++ SERIALNUMBER=A82743287, ++ O=AC Camerfirma S.A., OU=AC CAMERFIRMA, C=ES ++Issuer: CN=Chambers of Commerce Root - 2008, ++ O=AC Camerfirma S.A., SERIALNUMBER=A82743287, ++ L=Madrid (see current address at www.camerfirma.com/address), C=EU ++Serial number: 621ff31c489ba136 ++Valid from: Thu Jan 15 01:21:16 PST 2015 until: Tue Dec 15 01:21:16 PST 2037 ++Certificate fingerprints: ++ SHA1: FE:72:7A:78:EA:0C:03:35:CD:DA:9C:2E:D7:5F:D4:D4:6F:35:C2:EF ++ SHA256: 66:EA:E2:70:9B:54:CD:D1:69:31:77:B1:33:2F:F0:36:CD:D0:F7:23:DB:30:39:ED:31:15:55:A6:CB:F5:FF:3E ++Signature algorithm name: SHA256withRSA ++Subject Public Key Algorithm: 4096-bit RSA key ++Version: 3 ++ ++-----BEGIN CERTIFICATE----- ++MIIIkzCCBnugAwIBAgIIYh/zHEiboTYwDQYJKoZIhvcNAQELBQAwga4xCzAJBgNV ++BAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNlZSBjdXJyZW50IGFkZHJlc3MgYXQg ++d3d3LmNhbWVyZmlybWEuY29tL2FkZHJlc3MpMRIwEAYDVQQFEwlBODI3NDMyODcx ++GzAZBgNVBAoTEkFDIENhbWVyZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJlcnMg ++b2YgQ29tbWVyY2UgUm9vdCAtIDIwMDgwHhcNMTUwMTE1MDkyMTE2WhcNMzcxMjE1 ++MDkyMTE2WjCB0zELMAkGA1UEBhMCRVMxFjAUBgNVBAsMDUFDIENBTUVSRklSTUEx ++GzAZBgNVBAoMEkFDIENhbWVyZmlybWEgUy5BLjESMBAGA1UEBRMJQTgyNzQzMjg3 ++MUswSQYDVQQHDEJNYWRyaWQgKHNlZSBjdXJyZW50IGFkZHJlc3MgYXQgaHR0cHM6 ++Ly93d3cuY2FtZXJmaXJtYS5jb20vYWRkcmVzcykxLjAsBgNVBAMMJUNhbWVyZmly ++bWEgQ29ycG9yYXRlIFNlcnZlciBJSSAtIDIwMTUwggIiMA0GCSqGSIb3DQEBAQUA ++A4ICDwAwggIKAoICAQC3ndKNpFufVq9v+15dRoT9oVkgwEfDdsPw0Ly0R+eM5MOk ++35zEil/+hqEMbQmcvosAh6I8iAskkXasqh+SMbMIjvXbDyNILeGzsoP0uz3btHM7 ++oN3yHXDhhd1NGNocP54Wehe9+RE3WP0yEEo+D2YmMwUHuv4KiXtveiPksv+Xkkz5 ++auqppPMaYlD6y49AEsGY2zOEUI8PO4+tOxUKhvsiMuW817vH3VdmMwOjRe0SdYAi ++YLQIiyqJGNdEo3u+fw8UXxaJSRXhmF+jUn5DvdzWWNAxxwAKy95EPlpLQsx/7t2W ++2ntoELPHGJk4V+/yA0d2olLEqBADkRtP2HiC0wly+zp7OGmjtfjbqLrVjmo/mLP3 ++zpmYbpUtubrHiY0rlW6wo5FZLcTUvcAxFjxLWVIELPjnTebOuHvoJTb97rhA1Oqq ++woq5FWJHFI9idzXzFLO0LX/4ugI9LZWxmvWW0O4CePtnhp0aNE/GgAw6lMx7bjZe ++DXxxQnUDEE/mAqOHRUCnvRUSKVbuBBE0oz5fz3nUwcWVVgrm/jkgqTX4EqnZe+yB ++mKV6hFEYV+1oVh7kzNN4Hg7nzGuByS7cCuBEwULFhfUja1Bu9EqgndJ3CV0XCWIA ++XVhJnPNPi6y4W11jLJ7XSGSz3sCh21g0Gpgi2pXHGDB65Jc/QJHZ5ZaHCrzFnwID ++AQABo4ICjDCCAogwEgYDVR0TAQH/BAgwBgEB/wIBAjAdBgNVHQ4EFgQUY+nw8FYA ++aGWwIWwOXNcZCJ0INGUwgeMGA1UdIwSB2zCB2IAU+SSsD7K1+HnA+mCIG8TZTQKe ++FxmhgbSkgbEwga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNlZSBj ++dXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29tL2FkZHJlc3MpMRIw ++EAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVyZmlybWEgUy5BLjEp ++MCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDiCCQCj2kJ+ ++pLGu2jB6BggrBgEFBQcBAQRuMGwwQgYIKwYBBQUHMAKGNmh0dHA6Ly93d3cuY2Ft ++ZXJmaXJtYS5jb20vY2VydHMvcm9vdF9jaGFtYmVycy0yMDA4LmNydDAmBggrBgEF ++BQcwAYYaaHR0cDovL29jc3AuY2FtZXJmaXJtYS5jb20wDgYDVR0PAQH/BAQDAgEG ++MCcGA1UdJQQgMB4GCCsGAQUFBwMEBggrBgEFBQcDAgYIKwYBBQUHAwEwPgYDVR0g ++BDcwNTAzBgRVHSAAMCswKQYIKwYBBQUHAgEWHWh0dHBzOi8vcG9saWN5LmNhbWVy ++ZmlybWEuY29tMHgGA1UdHwRxMG8wNaAzoDGGL2h0dHA6Ly9jcmwuY2FtZXJmaXJt ++YS5jb20vY2hhbWJlcnNyb290LTIwMDguY3JsMDagNKAyhjBodHRwOi8vY3JsMS5j ++YW1lcmZpcm1hLmNvbS9jaGFtYmVyc3Jvb3QtMjAwOC5jcmwwDQYJKoZIhvcNAQEL ++BQADggIBAKhqaZwalwf89f4wPqfcE/lrsHdx8+q9RG46ouBXhTJMqXjwstXOZSL4 ++3Dqs3GaVuMPIM9OG7CK0I93mAt+FWtr49ACFTyPBxPg/knrZ4RHyEto+/6w0WZ9H ++owNw0aUg3ZAkhIvMRPVou8PrVukqj2lGKIh3hRdrbHwYwwmKKNlWBoC9gWk3mTYU ++zfNt/KTzQCCl5+s6YDa+XInMLWaGd/pE/e++a22vY24cv7kN3NAFMjAMELPwh9ic ++zLoPX8B52r+GgwpKY0c0hZdVTii6psLQ+BenyMlh+6lHRBOlTCSRtNi16o7H8fRq ++CY2wyQi7N+EmdY1DhvECCi1nLbOnIx1bSAW0cVwPVrjQ/vsAxPNc3SGe/Xnanm3a ++zAgFspzeuAhxxG0VKOvtPBnPQNsQ0cK664+IrWRsfa6aYhEfKvfsn5o4HpBWDobf ++zrtNbqjjOuiM6JkT+DxXo5UK7t2q75KCJiimTtAuPcZ5wErZISLvZ34BodIHL2xK ++b3Vww7K2FE1QaNsuQkGbUk++B9/+vV3H57vzskObdFWeWKSCpxIil4vZwIIH17zn ++WU+O2WIY1F0aO9zp3E7qwfmYT4MJ38NF9R7FSlxRlgVc1uUHu/iyUU4N1O6F3VdX ++P2Y+tgLFZLYV4kApfXk5l9h94dgKyfVcIpvS6yVpLfONPnlCNOxy ++-----END CERTIFICATE----- +diff --git a/test/jdk/sun/security/ssl/X509TrustManagerImpl/Entrust/entrust2048ca-chain.pem b/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/entrust/entrust2048ca-chain.pem +similarity index 100% +rename from test/jdk/sun/security/ssl/X509TrustManagerImpl/Entrust/entrust2048ca-chain.pem +rename to test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/entrust/entrust2048ca-chain.pem +diff --git a/test/jdk/sun/security/ssl/X509TrustManagerImpl/Entrust/entrustevca-chain.pem b/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/entrust/entrustevca-chain.pem +similarity index 100% +rename from test/jdk/sun/security/ssl/X509TrustManagerImpl/Entrust/entrustevca-chain.pem +rename to test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/entrust/entrustevca-chain.pem +diff --git a/test/jdk/sun/security/ssl/X509TrustManagerImpl/Entrust/entrustrootcaec1-chain.pem b/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/entrust/entrustrootcaec1-chain.pem +similarity index 100% +rename from test/jdk/sun/security/ssl/X509TrustManagerImpl/Entrust/entrustrootcaec1-chain.pem +rename to test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/entrust/entrustrootcaec1-chain.pem +diff --git a/test/jdk/sun/security/ssl/X509TrustManagerImpl/Entrust/entrustrootcag2-chain.pem b/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/entrust/entrustrootcag2-chain.pem +similarity index 100% +rename from test/jdk/sun/security/ssl/X509TrustManagerImpl/Entrust/entrustrootcag2-chain.pem +rename to test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/entrust/entrustrootcag2-chain.pem +diff --git a/test/jdk/sun/security/ssl/X509TrustManagerImpl/Entrust/entrustrootcag4-chain.pem b/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/entrust/entrustrootcag4-chain.pem +similarity index 100% +rename from test/jdk/sun/security/ssl/X509TrustManagerImpl/Entrust/entrustrootcag4-chain.pem +rename to test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/entrust/entrustrootcag4-chain.pem +diff --git a/test/jdk/sun/security/ssl/X509TrustManagerImpl/Symantec/appleistca8g1-chain.pem b/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/symantec/appleistca8g1-chain.pem +similarity index 100% +rename from test/jdk/sun/security/ssl/X509TrustManagerImpl/Symantec/appleistca8g1-chain.pem +rename to test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/symantec/appleistca8g1-chain.pem +diff --git a/test/jdk/sun/security/ssl/X509TrustManagerImpl/Symantec/geotrustprimarycag2-chain.pem b/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/symantec/geotrustprimarycag2-chain.pem +similarity index 100% +rename from test/jdk/sun/security/ssl/X509TrustManagerImpl/Symantec/geotrustprimarycag2-chain.pem +rename to test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/symantec/geotrustprimarycag2-chain.pem +diff --git a/test/jdk/sun/security/ssl/X509TrustManagerImpl/Symantec/geotrustprimarycag3-chain.pem b/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/symantec/geotrustprimarycag3-chain.pem +similarity index 100% +rename from test/jdk/sun/security/ssl/X509TrustManagerImpl/Symantec/geotrustprimarycag3-chain.pem +rename to test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/symantec/geotrustprimarycag3-chain.pem +diff --git a/test/jdk/sun/security/ssl/X509TrustManagerImpl/Symantec/geotrustuniversalca-chain.pem b/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/symantec/geotrustuniversalca-chain.pem +similarity index 100% +rename from test/jdk/sun/security/ssl/X509TrustManagerImpl/Symantec/geotrustuniversalca-chain.pem +rename to test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/symantec/geotrustuniversalca-chain.pem +diff --git a/test/jdk/sun/security/ssl/X509TrustManagerImpl/Symantec/thawteprimaryrootca-chain.pem b/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/symantec/thawteprimaryrootca-chain.pem +similarity index 100% +rename from test/jdk/sun/security/ssl/X509TrustManagerImpl/Symantec/thawteprimaryrootca-chain.pem +rename to test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/symantec/thawteprimaryrootca-chain.pem +diff --git a/test/jdk/sun/security/ssl/X509TrustManagerImpl/Symantec/thawteprimaryrootcag2-chain.pem b/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/symantec/thawteprimaryrootcag2-chain.pem +similarity index 100% +rename from test/jdk/sun/security/ssl/X509TrustManagerImpl/Symantec/thawteprimaryrootcag2-chain.pem +rename to test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/symantec/thawteprimaryrootcag2-chain.pem +diff --git a/test/jdk/sun/security/ssl/X509TrustManagerImpl/Symantec/thawteprimaryrootcag3-chain.pem b/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/symantec/thawteprimaryrootcag3-chain.pem +similarity index 100% +rename from test/jdk/sun/security/ssl/X509TrustManagerImpl/Symantec/thawteprimaryrootcag3-chain.pem +rename to test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/symantec/thawteprimaryrootcag3-chain.pem +diff --git a/test/jdk/sun/security/ssl/X509TrustManagerImpl/Symantec/verisignclass3g3ca-chain.pem b/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/symantec/verisignclass3g3ca-chain.pem +similarity index 100% +rename from test/jdk/sun/security/ssl/X509TrustManagerImpl/Symantec/verisignclass3g3ca-chain.pem +rename to test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/symantec/verisignclass3g3ca-chain.pem +diff --git a/test/jdk/sun/security/ssl/X509TrustManagerImpl/Symantec/verisignclass3g4ca-chain.pem b/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/symantec/verisignclass3g4ca-chain.pem +similarity index 100% +rename from test/jdk/sun/security/ssl/X509TrustManagerImpl/Symantec/verisignclass3g4ca-chain.pem +rename to test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/symantec/verisignclass3g4ca-chain.pem +diff --git a/test/jdk/sun/security/ssl/X509TrustManagerImpl/Symantec/verisignclass3g5ca-chain.pem b/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/symantec/verisignclass3g5ca-chain.pem +similarity index 100% +rename from test/jdk/sun/security/ssl/X509TrustManagerImpl/Symantec/verisignclass3g5ca-chain.pem +rename to test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/symantec/verisignclass3g5ca-chain.pem +diff --git a/test/jdk/sun/security/ssl/X509TrustManagerImpl/Symantec/verisignclass3g5ca-codesigning-chain.pem b/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/symantec/verisignclass3g5ca-codesigning-chain.pem +similarity index 100% +rename from test/jdk/sun/security/ssl/X509TrustManagerImpl/Symantec/verisignclass3g5ca-codesigning-chain.pem +rename to test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/symantec/verisignclass3g5ca-codesigning-chain.pem +diff --git a/test/jdk/sun/security/ssl/X509TrustManagerImpl/Symantec/verisignuniversalrootca-chain.pem b/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/symantec/verisignuniversalrootca-chain.pem +similarity index 100% +rename from test/jdk/sun/security/ssl/X509TrustManagerImpl/Symantec/verisignuniversalrootca-chain.pem +rename to test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/symantec/verisignuniversalrootca-chain.pem +diff --git a/test/jdk/sun/security/tools/jarsigner/RemovedFiles.java b/test/jdk/sun/security/tools/jarsigner/RemovedFiles.java +new file mode 100644 +index 000000000..1b65c4340 +--- /dev/null ++++ b/test/jdk/sun/security/tools/jarsigner/RemovedFiles.java +@@ -0,0 +1,94 @@ ++/* ++ * Copyright (c) 2024, 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. ++ */ + -+ Register ret = newRegister(); -+ emitPcaddu12i(ret, 0xdead >> 12); -+ emitAdd(ret, ret, 0xdead & 0xfff); -+ emitLoadRegister(ret, LoongArch64Kind.QWORD, ret, 0); -+ return ret; -+ } ++/* ++ * @test ++ * @bug 8309841 ++ * @summary Jarsigner should print a warning if an entry is removed ++ * @library /test/lib ++ */ + -+ private Register emitLoadDouble(Register reg, double c) { -+ DataSectionReference ref = new DataSectionReference(); -+ ref.setOffset(data.position()); -+ data.emitDouble(c); ++import jdk.test.lib.SecurityTools; ++import jdk.test.lib.util.JarUtils; ++ ++import java.nio.file.Files; ++import java.nio.file.Path; ++import java.util.jar.Attributes; ++import java.util.jar.Manifest; ++ ++public class RemovedFiles { ++ ++ private static final String NONEXISTENT_ENTRIES_FOUND ++ = "This jar contains signed entries for files that do not exist. See the -verbose output for more details."; ++ ++ public static void main(String[] args) throws Exception { ++ JarUtils.createJarFile( ++ Path.of("a.jar"), ++ Path.of("."), ++ Files.writeString(Path.of("a"), "a"), ++ Files.writeString(Path.of("b"), "b")); ++ SecurityTools.keytool("-genkeypair -storepass changeit -keystore ks -alias x -dname CN=x -keyalg RSA"); ++ SecurityTools.jarsigner("-storepass changeit -keystore ks a.jar x"); ++ ++ // All is fine at the beginning. ++ SecurityTools.jarsigner("-verify a.jar") ++ .shouldNotContain(NONEXISTENT_ENTRIES_FOUND); ++ ++ // Remove an entry after signing. There will be a warning. ++ JarUtils.deleteEntries(Path.of("a.jar"), "a"); ++ SecurityTools.jarsigner("-verify a.jar") ++ .shouldContain(NONEXISTENT_ENTRIES_FOUND); ++ SecurityTools.jarsigner("-verify -verbose a.jar") ++ .shouldContain(NONEXISTENT_ENTRIES_FOUND) ++ .shouldContain("Warning: nonexistent signed entries: [a]"); ++ ++ // Remove one more entry. ++ JarUtils.deleteEntries(Path.of("a.jar"), "b"); ++ SecurityTools.jarsigner("-verify a.jar") ++ .shouldContain(NONEXISTENT_ENTRIES_FOUND); ++ SecurityTools.jarsigner("-verify -verbose a.jar") ++ .shouldContain(NONEXISTENT_ENTRIES_FOUND) ++ .shouldContain("Warning: nonexistent signed entries: [a, b]"); ++ ++ // Re-sign will not clear the warning. ++ SecurityTools.jarsigner("-storepass changeit -keystore ks a.jar x"); ++ SecurityTools.jarsigner("-verify a.jar") ++ .shouldContain(NONEXISTENT_ENTRIES_FOUND); ++ ++ // Unfortunately, if there is a non-file entry in manifest, there will be ++ // a false alarm. See https://bugs.openjdk.org/browse/JDK-8334261. ++ var man = new Manifest(); ++ man.getMainAttributes().putValue("Manifest-Version", "1.0"); ++ man.getEntries().computeIfAbsent("Hello", key -> new Attributes()) ++ .putValue("Foo", "Bar"); ++ JarUtils.createJarFile(Path.of("b.jar"), ++ man, ++ Path.of("."), ++ Path.of("a")); ++ SecurityTools.jarsigner("-storepass changeit -keystore ks b.jar x"); ++ SecurityTools.jarsigner("-verbose -verify b.jar") ++ .shouldContain("Warning: nonexistent signed entries: [Hello]") ++ .shouldContain(NONEXISTENT_ENTRIES_FOUND); ++ ++ } ++} +diff --git a/test/jdk/sun/security/tools/jarsigner/TimestampCheck.java b/test/jdk/sun/security/tools/jarsigner/TimestampCheck.java +index eac97a941..d206ba878 100644 +--- a/test/jdk/sun/security/tools/jarsigner/TimestampCheck.java ++++ b/test/jdk/sun/security/tools/jarsigner/TimestampCheck.java +@@ -865,7 +865,7 @@ public class TimestampCheck { + } + + gencert("tsold", "-ext eku:critical=ts -startdate -40d -validity 500"); +- gencert("tsbefore2019", "-ext eku:critical=ts -startdate 2018/01/01 -validity 3000"); ++ gencert("tsbefore2019", "-ext eku:critical=ts -startdate 2018/01/01 -validity 5000"); + + gencert("tsweak", "-ext eku:critical=ts"); + gencert("tsdisabled", "-ext eku:critical=ts"); +diff --git a/test/jdk/sun/security/tools/jarsigner/TsacertOptionTest.java b/test/jdk/sun/security/tools/jarsigner/TsacertOptionTest.java +index bb5289553..3655c01b5 100644 +--- a/test/jdk/sun/security/tools/jarsigner/TsacertOptionTest.java ++++ b/test/jdk/sun/security/tools/jarsigner/TsacertOptionTest.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2013, 2024, 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 +@@ -103,6 +103,7 @@ public class TsacertOptionTest extends Test { + "-alias", CA_KEY_ALIAS, + "-keystore", KEYSTORE, + "-storepass", PASSWORD, ++ "-startdate", "-1M", + "-keypass", PASSWORD, + "-validity", Integer.toString(VALIDITY), + "-infile", "certreq", +diff --git a/test/jdk/sun/util/calendar/zi/Month.java b/test/jdk/sun/util/calendar/zi/Month.java +index cb60b8d44..bab909f76 100644 +--- a/test/jdk/sun/util/calendar/zi/Month.java ++++ b/test/jdk/sun/util/calendar/zi/Month.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2000, 2024, 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 +@@ -21,11 +21,6 @@ + * questions. + */ + +-import java.util.ArrayList; +-import java.util.HashMap; +-import java.util.List; +-import java.util.Map; +- + /** + * Month enum handles month related manipulation. + * +@@ -47,15 +42,6 @@ enum Month { + + private final String abbr; + +- private static final Map abbreviations +- = new HashMap(12); +- +- static { +- for (Month m : Month.values()) { +- abbreviations.put(m.abbr, m); +- } +- } +- + private Month(String abbr) { + this.abbr = abbr; + } +@@ -70,11 +56,22 @@ enum Month { + * @return the Month value + */ + static Month parse(String name) { +- Month m = abbreviations.get(name); +- if (m != null) { +- return m; +- } +- return null; ++ int len = name.length(); ++ ++ if (name.regionMatches(true, 0, "January", 0, len)) return Month.JANUARY; ++ if (name.regionMatches(true, 0, "February", 0, len)) return Month.FEBRUARY; ++ if (name.regionMatches(true, 0, "March", 0, len)) return Month.MARCH; ++ if (name.regionMatches(true, 0, "April", 0, len)) return Month.APRIL; ++ if (name.regionMatches(true, 0, "May", 0, len)) return Month.MAY; ++ if (name.regionMatches(true, 0, "June", 0, len)) return Month.JUNE; ++ if (name.regionMatches(true, 0, "July", 0, len)) return Month.JULY; ++ if (name.regionMatches(true, 0, "August", 0, len)) return Month.AUGUST; ++ if (name.regionMatches(true, 0, "September", 0, len)) return Month.SEPTEMBER; ++ if (name.regionMatches(true, 0, "October", 0, len)) return Month.OCTOBER; ++ if (name.regionMatches(true, 0, "November", 0, len)) return Month.NOVEMBER; ++ if (name.regionMatches(true, 0, "December", 0, len)) return Month.DECEMBER; ++ ++ throw new IllegalArgumentException("Unknown month: " + name); + } + + /** +diff --git a/test/jdk/sun/util/calendar/zi/RuleDay.java b/test/jdk/sun/util/calendar/zi/RuleDay.java +index bc730944b..9cd81c1e5 100644 +--- a/test/jdk/sun/util/calendar/zi/RuleDay.java ++++ b/test/jdk/sun/util/calendar/zi/RuleDay.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2000, 2024, 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 +@@ -21,11 +21,6 @@ + * questions. + */ + +-import java.util.ArrayList; +-import java.util.HashMap; +-import java.util.List; +-import java.util.Map; +- + /** + * RuleDay class represents the value of the "ON" field. The day of + * week values start from 1 following the {@link java.util.Calendar} +@@ -34,13 +29,6 @@ import java.util.Map; + * @since 1.4 + */ + class RuleDay { +- private static final Map abbreviations = new HashMap(7); +- static { +- for (DayOfWeek day : DayOfWeek.values()) { +- abbreviations.put(day.getAbbr(), day); +- } +- } +- + private String dayName = null; + private DayOfWeek dow; + private boolean lastOne = false; +@@ -166,13 +154,23 @@ class RuleDay { + return sign + toString(d); + } + +- private static DayOfWeek getDOW(String abbr) { +- return abbreviations.get(abbr); ++ private static DayOfWeek getDOW(String name) { ++ int len = name.length(); ++ ++ if (name.regionMatches(true, 0, "Monday", 0, len)) return DayOfWeek.MONDAY; ++ if (name.regionMatches(true, 0, "Tuesday", 0, len)) return DayOfWeek.TUESDAY; ++ if (name.regionMatches(true, 0, "Wednesday", 0, len)) return DayOfWeek.WEDNESDAY; ++ if (name.regionMatches(true, 0, "Thursday", 0, len)) return DayOfWeek.THURSDAY; ++ if (name.regionMatches(true, 0, "Friday", 0, len)) return DayOfWeek.FRIDAY; ++ if (name.regionMatches(true, 0, "Saturday", 0, len)) return DayOfWeek.SATURDAY; ++ if (name.regionMatches(true, 0, "Sunday", 0, len)) return DayOfWeek.SUNDAY; ++ ++ throw new IllegalArgumentException("Unknown day-of-week: " + name); + } + + /** + * Converts the specified day of week value to the day-of-week +- * name defined in {@link java.util.Calenda}. ++ * name defined in {@link java.util.Calendar}. + * @param dow 1-based day of week value + * @return the Calendar day of week name with "Calendar." prefix. + * @throws IllegalArgumentException if the specified dow value is out of range. +diff --git a/test/jdk/sun/util/calendar/zi/RuleRec.java b/test/jdk/sun/util/calendar/zi/RuleRec.java +index 6d9d4905d..e6e18773d 100644 +--- a/test/jdk/sun/util/calendar/zi/RuleRec.java ++++ b/test/jdk/sun/util/calendar/zi/RuleRec.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2000, 2024, 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 +@@ -168,12 +168,13 @@ class RuleRec { + rec.toYear = Integer.parseInt(token); + } catch (NumberFormatException e) { + // it's not integer +- if ("min".equals(token) || "minimum".equals(token)) { ++ int len = token.length(); ++ if (token.regionMatches(true, 0, "minimum", 0, len)) { + rec.fromYear = Zoneinfo.getMinYear(); +- } else if ("max".equals(token) || "maximum".equals(token)) { ++ } else if (token.regionMatches(true, 0, "maximum", 0, len)) { + rec.toYear = Integer.MAX_VALUE; + rec.isLastRule = true; +- } else if ("only".equals(token)) { ++ } else if (token.regionMatches(true, 0, "only", 0, len)) { + rec.toYear = rec.fromYear; + } else { + Main.panic("invalid year value: "+token); +diff --git a/test/jdk/sun/util/calendar/zi/TestZoneInfo310.java b/test/jdk/sun/util/calendar/zi/TestZoneInfo310.java +index a7d14f1aa..aaced7bbf 100644 +--- a/test/jdk/sun/util/calendar/zi/TestZoneInfo310.java ++++ b/test/jdk/sun/util/calendar/zi/TestZoneInfo310.java +@@ -50,7 +50,9 @@ public class TestZoneInfo310 { + "..", "..", "make", "data", "tzdata"); + String tzfiles = "africa antarctica asia australasia europe northamerica southamerica backward etcetera gmt"; + Path jdk_tzdir = Paths.get(System.getProperty("test.src"), "tzdata_jdk"); +- String jdk_tzfiles = "jdk11_backward"; ++ // tz2024b_overridden_zones file is created to preserve the behaviour of ++ // "EST", "MST", and "HST" when timezone 2024b changes are applied ++ String jdk_tzfiles = "jdk11_backward tz2024b_overridden_zones"; + String zidir = TESTDIR + File.separator + "zi"; + File fZidir = new File(zidir); + if (!fZidir.exists()) { +diff --git a/test/jdk/sun/util/calendar/zi/Zoneinfo.java b/test/jdk/sun/util/calendar/zi/Zoneinfo.java +index 6b21bfb5c..a68aa7826 100644 +--- a/test/jdk/sun/util/calendar/zi/Zoneinfo.java ++++ b/test/jdk/sun/util/calendar/zi/Zoneinfo.java +@@ -240,8 +240,9 @@ class Zoneinfo { + continue; + } + String token = tokens.nextToken(); ++ int len = token.length(); + +- if (continued || "Zone".equals(token)) { ++ if (continued || token.regionMatches(true, 0, "Zone", 0, len)){ + if (zone == null) { + if (!tokens.hasMoreTokens()) { + panic("syntax error: zone no more token"); +@@ -268,7 +269,7 @@ class Zoneinfo { + } + zone = null; + } +- } else if ("Rule".equals(token)) { ++ } else if (token.regionMatches(true, 0, "Rule", 0, len)) { + if (!tokens.hasMoreTokens()) { + panic("syntax error: rule no more token"); + } +@@ -281,7 +282,7 @@ class Zoneinfo { + RuleRec rrec = RuleRec.parse(tokens); + rrec.setLine(line); + rule.add(rrec); +- } else if ("Link".equals(token)) { ++ } else if (token.regionMatches(true, 0, "Link", 0, len)) { + // Link + try { + String name1 = tokens.nextToken(); +diff --git a/test/hotspot/jtreg/vmTestbase/nsk/stress/stack/TEST.properties b/test/jdk/sun/util/calendar/zi/tzdata_jdk/tz2024b_overridden_zones +similarity index 52% +rename from test/hotspot/jtreg/vmTestbase/nsk/stress/stack/TEST.properties +rename to test/jdk/sun/util/calendar/zi/tzdata_jdk/tz2024b_overridden_zones +index 8b51b2a91..ab468100d 100644 +--- a/test/hotspot/jtreg/vmTestbase/nsk/stress/stack/TEST.properties ++++ b/test/jdk/sun/util/calendar/zi/tzdata_jdk/tz2024b_overridden_zones +@@ -1,5 +1,5 @@ + # +-# Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. ++# Copyright (c) 2024, 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 +@@ -19,6 +19,18 @@ + # 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. +-# + +-exclusiveAccess.dirs=. ++# TZdata2024b changes announced on 5th September 2024 includes changes to ++# "EST", "MST", and "HST", i.e., changing those time zones from distinct ++# time zones to links to other time zones. Previously ++# they were defined as fixed offset zones, ++# e.g., "EST" is "-05:00" without any DST transitions. ++# With 2024b, "EST" is now a link to "America/Panama." ++# This change has Java 8+ specification implications in java.time.ZoneId.SHORT_IDS field ++# Solution for jdk24+ to modify the mappings in ZoneId class which requires modification of the spec. ++# Update releases will not make the ZoneId changes due to current specification. ++ ++# Zone NAME GMTOFF RULES/SAVE FORMAT [UNTIL] ++Zone EST -5:00 - EST ++Zone MST -7:00 - MST ++Zone HST -10:00 - HST +\ No newline at end of file +diff --git a/test/jdk/tools/jar/ExtractFilesTest.java b/test/jdk/tools/jar/ExtractFilesTest.java +new file mode 100644 +index 000000000..b829b770f +--- /dev/null ++++ b/test/jdk/tools/jar/ExtractFilesTest.java +@@ -0,0 +1,265 @@ ++/* ++ * Copyright (c) 2024, 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. ++ */ + -+ recordDataPatchInCode(ref); -+ emitPcaddu12i(scratchRegister, 0xdead >> 12); -+ emitAdd(scratchRegister, scratchRegister, 0xdead & 0xfff); -+ emitLoadRegister(reg, LoongArch64Kind.DOUBLE, scratchRegister, 0); -+ return reg; -+ } ++/* ++ * @test ++ * @bug 8335912 ++ * @summary test extract jar files overwrite existing files behavior ++ * @library /test/lib ++ * @modules jdk.jartool ++ * @build jdk.test.lib.Platform ++ * jdk.test.lib.util.FileUtils ++ * @run junit/othervm ExtractFilesTest ++ */ + -+ private Register emitLoadFloat(Register reg, float c) { -+ DataSectionReference ref = new DataSectionReference(); -+ ref.setOffset(data.position()); -+ data.emitFloat(c); ++import org.junit.jupiter.api.AfterAll; ++import org.junit.jupiter.api.Assertions; ++import org.junit.jupiter.api.BeforeAll; ++import org.junit.jupiter.api.Test; ++import org.junit.jupiter.api.TestInstance; ++import org.junit.jupiter.api.TestInstance.Lifecycle; ++ ++import java.io.ByteArrayOutputStream; ++import java.io.IOException; ++import java.io.PrintStream; ++import java.io.UncheckedIOException; ++import java.nio.file.Files; ++import java.nio.file.Path; ++import java.util.Arrays; ++import java.util.spi.ToolProvider; ++import java.util.stream.Stream; ++ ++import jdk.test.lib.util.FileUtils; ++ ++ @TestInstance(Lifecycle.PER_CLASS) ++ public class ExtractFilesTest { ++ private static final ToolProvider JAR_TOOL = ToolProvider.findFirst("jar") ++ .orElseThrow(() -> ++ new RuntimeException("jar tool not found") ++ ); + -+ recordDataPatchInCode(ref); -+ emitPcaddu12i(scratchRegister, 0xdead >> 12); -+ emitAdd(scratchRegister, scratchRegister, 0xdead & 0xfff); -+ emitLoadRegister(reg, LoongArch64Kind.SINGLE, scratchRegister, 0); -+ return reg; -+ } ++ private final String nl = System.lineSeparator(); ++ private final ByteArrayOutputStream baos = new ByteArrayOutputStream(); ++ private final PrintStream out = new PrintStream(baos); + -+ @Override -+ public Register emitLoadFloat(float c) { -+ Register ret = LoongArch64.fv0; -+ return emitLoadFloat(ret, c); ++ @BeforeAll ++ public void setupJar() throws IOException { ++ mkdir("test1 test2"); ++ echo("testfile1", "test1/testfile1"); ++ echo("testfile2", "test2/testfile2"); ++ jar("cf test.jar -C test1 . -C test2 ."); ++ rm("test1 test2"); + } + -+ private Register emitLoadLong(Register reg, long c) { -+ emitLi64(reg, c); -+ return reg; ++ @AfterAll ++ public void cleanup() { ++ rm("test.jar"); + } + -+ @Override -+ public Register emitLoadLong(long c) { -+ Register ret = newRegister(); -+ return emitLoadLong(ret, c); ++ /** ++ * Regular clean extract with expected output. ++ */ ++ @Test ++ public void testExtract() throws IOException { ++ jar("xvf test.jar"); ++ println(); ++ String output = " created: META-INF/" + nl + ++ " inflated: META-INF/MANIFEST.MF" + nl + ++ " inflated: testfile1" + nl + ++ " inflated: testfile2" + nl; ++ rm("META-INF testfile1 testfile2"); ++ Assertions.assertArrayEquals(baos.toByteArray(), output.getBytes()); + } + -+ private Register emitLoadInt(Register reg, int c) { -+ emitLoadImmediate(reg, c); -+ return reg; ++ /** ++ * Extract should overwrite existing file as default behavior. ++ */ ++ @Test ++ public void testOverwrite() throws IOException { ++ touch("testfile1"); ++ jar("xvf test.jar"); ++ println(); ++ String output = " created: META-INF/" + nl + ++ " inflated: META-INF/MANIFEST.MF" + nl + ++ " inflated: testfile1" + nl + ++ " inflated: testfile2" + nl; ++ Assertions.assertEquals("testfile1", cat("testfile1")); ++ rm("META-INF testfile1 testfile2"); ++ Assertions.assertArrayEquals(baos.toByteArray(), output.getBytes()); + } + -+ @Override -+ public Register emitLoadInt(int c) { -+ Register ret = newRegister(); -+ return emitLoadInt(ret, c); ++ /** ++ * Extract with legacy style option `k` should preserve existing files. ++ */ ++ @Test ++ public void testKeptOldFile() throws IOException { ++ touch("testfile1"); ++ jar("xkvf test.jar"); ++ println(); ++ String output = " created: META-INF/" + nl + ++ " inflated: META-INF/MANIFEST.MF" + nl + ++ " skipped: testfile1 exists" + nl + ++ " inflated: testfile2" + nl; ++ Assertions.assertEquals("", cat("testfile1")); ++ Assertions.assertEquals("testfile2", cat("testfile2")); ++ rm("META-INF testfile1 testfile2"); ++ Assertions.assertArrayEquals(baos.toByteArray(), output.getBytes()); + } + -+ @Override -+ public Register emitIntArg0() { -+ return codeCache.getRegisterConfig() -+ .getCallingConventionRegisters(HotSpotCallingConventionType.JavaCall, JavaKind.Int) -+ .get(0); ++ /** ++ * Extract with gnu style -k should preserve existing files. ++ */ ++ @Test ++ public void testGnuOptionsKeptOldFile() throws IOException { ++ touch("testfile1 testfile2"); ++ jar("-x -k -v -f test.jar"); ++ println(); ++ String output = " created: META-INF/" + nl + ++ " inflated: META-INF/MANIFEST.MF" + nl + ++ " skipped: testfile1 exists" + nl + ++ " skipped: testfile2 exists" + nl; ++ Assertions.assertEquals("", cat("testfile1")); ++ Assertions.assertEquals("", cat("testfile2")); ++ rm("META-INF testfile1 testfile2"); ++ Assertions.assertArrayEquals(baos.toByteArray(), output.getBytes()); + } + -+ @Override -+ public Register emitIntArg1() { -+ return codeCache.getRegisterConfig() -+ .getCallingConventionRegisters(HotSpotCallingConventionType.JavaCall, JavaKind.Int) -+ .get(1); ++ /** ++ * Extract with gnu style long option --keep-old-files should preserve existing files. ++ */ ++ @Test ++ public void testGnuLongOptionsKeptOldFile() throws IOException { ++ touch("testfile2"); ++ jar("-x --keep-old-files -v -f test.jar"); ++ println(); ++ String output = " created: META-INF/" + nl + ++ " inflated: META-INF/MANIFEST.MF" + nl + ++ " inflated: testfile1" + nl + ++ " skipped: testfile2 exists" + nl; ++ Assertions.assertEquals("testfile1", cat("testfile1")); ++ Assertions.assertEquals("", cat("testfile2")); ++ rm("META-INF testfile1 testfile2"); ++ Assertions.assertArrayEquals(baos.toByteArray(), output.getBytes()); + } + -+ @Override -+ public Register emitIntAdd(Register a, Register b) { -+ emitAdd(a, a, b); -+ return a; -+ } ++ /** ++ * Test jar will issue warning when use keep option in non-extraction mode. ++ */ ++ @Test ++ public void testWarningOnInvalidKeepOption() throws IOException { ++ var err = jar("tkf test.jar"); ++ println(); + -+ @Override -+ public void emitTrap(DebugInfo info) { -+ // Dereference null pointer -+ emitMove(scratchRegister, LoongArch64.zero); -+ recordImplicitException(info); -+ emitLoadRegister(LoongArch64.zero, LoongArch64Kind.QWORD, scratchRegister, 0); -+ } ++ String output = "META-INF/" + nl + ++ "META-INF/MANIFEST.MF" + nl + ++ "testfile1" + nl + ++ "testfile2" + nl; + -+ @Override -+ public void emitIntRet(Register a) { -+ emitMove(LoongArch64.v0, a); -+ emitMove(LoongArch64.sp, LoongArch64.fp); -+ emitLoadRegister(LoongArch64.ra, LoongArch64Kind.QWORD, LoongArch64.sp, 8); -+ emitLoadRegister(LoongArch64.fp, LoongArch64Kind.QWORD, LoongArch64.sp, 0); -+ emitGrowStack(-16); -+ emitJirl(LoongArch64.zero, LoongArch64.ra, 0); ++ Assertions.assertArrayEquals(baos.toByteArray(), output.getBytes()); ++ Assertions.assertEquals("Warning: The --keep-old-files/-k/k option is not valid with current usage, will be ignored." + nl, err); + } + -+ @Override -+ public void emitFloatRet(Register a) { -+ assert a == LoongArch64.fv0 : "Unimplemented move " + a; -+ emitMove(LoongArch64.sp, LoongArch64.fp); -+ emitLoadRegister(LoongArch64.ra, LoongArch64Kind.QWORD, LoongArch64.sp, 8); -+ emitLoadRegister(LoongArch64.fp, LoongArch64Kind.QWORD, LoongArch64.sp, 0); -+ emitGrowStack(-16); -+ emitJirl(LoongArch64.zero, LoongArch64.ra, 0); ++ private Stream mkpath(String... args) { ++ return Arrays.stream(args).map(d -> Path.of(".", d.split("/"))); + } + -+ @Override -+ public void emitPointerRet(Register a) { -+ emitIntRet(a); ++ private void mkdir(String cmdline) { ++ System.out.println("mkdir -p " + cmdline); ++ mkpath(cmdline.split(" +")).forEach(p -> { ++ try { ++ Files.createDirectories(p); ++ } catch (IOException x) { ++ throw new UncheckedIOException(x); ++ } ++ }); + } + -+ @Override -+ public StackSlot emitPointerToStack(Register a) { -+ return emitLongToStack(a); ++ private void touch(String cmdline) { ++ System.out.println("touch " + cmdline); ++ mkpath(cmdline.split(" +")).forEach(p -> { ++ try { ++ Files.createFile(p); ++ } catch (IOException x) { ++ throw new UncheckedIOException(x); ++ } ++ }); + } + -+ @Override -+ public StackSlot emitNarrowPointerToStack(Register a) { -+ return emitIntToStack(a); ++ private void echo(String text, String path) { ++ System.out.println("echo '" + text + "' > " + path); ++ try { ++ var p = Path.of(".", path.split("/")); ++ Files.writeString(p, text); ++ } catch (IOException x) { ++ throw new UncheckedIOException(x); ++ } + } + -+ @Override -+ public Register emitUncompressPointer(Register compressed, long base, int shift) { -+ if (shift > 0) { -+ emitShiftLeft(compressed, compressed, shift); ++ private String cat(String path) { ++ System.out.println("cat " + path); ++ try { ++ return Files.readString(Path.of(path)); ++ } catch (IOException x) { ++ throw new UncheckedIOException(x); + } ++ } + -+ if (base != 0) { -+ emitLoadLong(scratchRegister, base); -+ emitAdd(compressed, compressed, scratchRegister); ++ private void rm(String cmdline) { ++ System.out.println("rm -rf " + cmdline); ++ mkpath(cmdline.split(" +")).forEach(p -> { ++ try { ++ if (Files.isDirectory(p)) { ++ FileUtils.deleteFileTreeWithRetry(p); ++ } else { ++ FileUtils.deleteFileIfExistsWithRetry(p); ++ } ++ } catch (IOException x) { ++ throw new UncheckedIOException(x); ++ } ++ }); ++ } ++ ++ private String jar(String cmdline) throws IOException { ++ System.out.println("jar " + cmdline); ++ baos.reset(); ++ ++ // the run method catches IOExceptions, we need to expose them ++ ByteArrayOutputStream baes = new ByteArrayOutputStream(); ++ PrintStream err = new PrintStream(baes); ++ PrintStream saveErr = System.err; ++ System.setErr(err); ++ try { ++ int rc = JAR_TOOL.run(out, err, cmdline.split(" +")); ++ if (rc != 0) { ++ throw new IOException(baes.toString()); ++ } ++ } finally { ++ System.setErr(saveErr); + } ++ return baes.toString(); ++ } + -+ return compressed; ++ private void println() throws IOException { ++ System.out.println(new String(baos.toByteArray())); + } ++} +diff --git a/test/jdk/tools/jar/MultipleManifestTest.java b/test/jdk/tools/jar/MultipleManifestTest.java +new file mode 100644 +index 000000000..951ce4bb8 +--- /dev/null ++++ b/test/jdk/tools/jar/MultipleManifestTest.java +@@ -0,0 +1,224 @@ ++/* ++ * Copyright (c) 2024, 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. ++ */ + -+ private StackSlot emitDoubleToStack(StackSlot slot, Register a) { -+ emitStoreRegister(a, LoongArch64Kind.DOUBLE, LoongArch64.sp, slot.getOffset(frameSize)); -+ return slot; ++/* ++ * @test ++ * @bug 8335912 ++ * @summary test extract jar with multpile manifest files ++ * @library /test/lib ++ * @modules jdk.jartool ++ * @build jdk.test.lib.Platform ++ * jdk.test.lib.util.FileUtils ++ * @run junit/othervm MultipleManifestTest ++ */ ++ ++import java.io.ByteArrayOutputStream; ++ ++import org.junit.jupiter.api.AfterAll; ++import org.junit.jupiter.api.AfterEach; ++import org.junit.jupiter.api.Assertions; ++import org.junit.jupiter.api.BeforeAll; ++import org.junit.jupiter.api.Test; ++import org.junit.jupiter.api.TestInstance; ++import org.junit.jupiter.api.TestInstance.Lifecycle; ++ ++import java.io.IOException; ++import java.io.PrintStream; ++import java.io.UncheckedIOException; ++import java.nio.charset.StandardCharsets; ++import java.nio.file.Files; ++import java.nio.file.Path; ++import java.util.Arrays; ++import java.util.jar.Attributes; ++import java.util.jar.JarFile; ++import java.util.jar.Manifest; ++import java.util.spi.ToolProvider; ++import java.util.stream.Stream; ++import java.util.zip.ZipEntry; ++import java.util.zip.ZipOutputStream; ++ ++import jdk.test.lib.util.FileUtils; ++ ++@TestInstance(Lifecycle.PER_CLASS) ++class MultipleManifestTest { ++ private static final ToolProvider JAR_TOOL = ToolProvider.findFirst("jar") ++ .orElseThrow(() -> ++ new RuntimeException("jar tool not found") ++ ); ++ ++ private final String nl = System.lineSeparator(); ++ private final ByteArrayOutputStream baos = new ByteArrayOutputStream(); ++ private final PrintStream jarOut = new PrintStream(baos); ++ ++ static final Path zip = Path.of("MultipleManifestTest.jar"); ++ static final String jdkVendor = System.getProperty("java.vendor"); ++ static final String jdkVersion = System.getProperty("java.version"); ++ static final String MANIFEST1 = "Manifest-Version: 1.0" ++ + System.lineSeparator() ++ + "Created-By: " + jdkVersion + " (" + jdkVendor + ")"; ++ static final String MANIFEST2 = "Manifest-Version: 2.0" ++ + System.lineSeparator() ++ + "Created-By: " + jdkVersion + " (" + jdkVendor + ")"; ++ static final String MANIFEST3 = "Manifest-Version: 3.0" ++ + System.lineSeparator() ++ + "Created-By: " + jdkVersion + " (" + jdkVendor + ")"; ++ private static final String META_INF = "META-INF/"; ++ ++ /** ++ * Delete the ZIP file produced by this test ++ * ++ * @throws IOException if an unexpected IOException occurs ++ */ ++ @AfterAll ++ public void cleanup() throws IOException { ++ Files.deleteIfExists(zip); + } + -+ @Override -+ public StackSlot emitDoubleToStack(Register a) { -+ StackSlot ret = newStackSlot(LoongArch64Kind.DOUBLE); -+ return emitDoubleToStack(ret, a); ++ /** ++ * Create a JAR with the Manifest as the 1st, 2nd and 4th entry ++ * ++ * @throws IOException if an error occurs ++ */ ++ @BeforeAll ++ public void writeManifestAsFirstSecondAndFourthEntry() throws IOException { ++ int locPosA, locPosB, cenPos; ++ System.out.printf("%n%n*****Creating Jar with the Manifest as the 1st, 2nd and 4th entry*****%n%n"); ++ var out = new ByteArrayOutputStream(1024); ++ try (var zos = new ZipOutputStream(out)) { ++ zos.putNextEntry(new ZipEntry(JarFile.MANIFEST_NAME)); ++ zos.write(MANIFEST1.getBytes(StandardCharsets.UTF_8)); ++ zos.closeEntry(); ++ locPosA = out.size(); ++ zos.putNextEntry(new ZipEntry(META_INF + "AANIFEST.MF")); ++ zos.write(MANIFEST2.getBytes(StandardCharsets.UTF_8)); ++ zos.putNextEntry(new ZipEntry("entry1.txt")); ++ zos.write("entry1".getBytes(StandardCharsets.UTF_8)); ++ zos.closeEntry(); ++ locPosB = out.size(); ++ zos.putNextEntry(new ZipEntry(META_INF + "BANIFEST.MF")); ++ zos.write(MANIFEST3.getBytes(StandardCharsets.UTF_8)); ++ zos.putNextEntry(new ZipEntry("entry2.txt")); ++ zos.write("hello entry2".getBytes(StandardCharsets.UTF_8)); ++ zos.flush(); ++ cenPos = out.size(); ++ } ++ var template = out.toByteArray(); ++ // ISO_8859_1 to keep the 8-bit value ++ var s = new String(template, StandardCharsets.ISO_8859_1); ++ // change META-INF/AANIFEST.MF to META-INF/MANIFEST.MF ++ var loc = s.indexOf("AANIFEST.MF", locPosA); ++ var cen = s.indexOf("AANIFEST.MF", cenPos); ++ template[loc] = template[cen] = (byte) 'M'; ++ // change META-INF/BANIFEST.MF to META-INF/MANIFEST.MF ++ loc = s.indexOf("BANIFEST.MF", locPosB); ++ cen = s.indexOf("BANIFEST.MF", cenPos); ++ template[loc] = template[cen] = (byte) 'M'; ++ Files.write(zip, template); + } + -+ private StackSlot emitFloatToStack(StackSlot slot, Register a) { -+ emitStoreRegister(a, LoongArch64Kind.SINGLE, LoongArch64.sp, slot.getOffset(frameSize)); -+ return slot; ++ @AfterEach ++ public void removeExtractedFiles() { ++ rm("META-INF entry1.txt entry2.txt"); + } + -+ @Override -+ public StackSlot emitFloatToStack(Register a) { -+ StackSlot ret = newStackSlot(LoongArch64Kind.SINGLE); -+ return emitFloatToStack(ret, a); ++ /** ++ * Extract by default should have the last manifest. ++ */ ++ @Test ++ public void testOverwrite() throws IOException { ++ jar("xvf " + zip.toString()); ++ println(); ++ Assertions.assertEquals("3.0", getManifestVersion()); ++ String output = " inflated: META-INF/MANIFEST.MF" + nl + ++ " inflated: META-INF/MANIFEST.MF" + nl + ++ " inflated: entry1.txt" + nl + ++ " inflated: META-INF/MANIFEST.MF" + nl + ++ " inflated: entry2.txt" + nl; ++ Assertions.assertArrayEquals(baos.toByteArray(), output.getBytes()); + } + -+ private StackSlot emitIntToStack(StackSlot slot, Register a) { -+ emitStoreRegister(a, LoongArch64Kind.DWORD, LoongArch64.sp, slot.getOffset(frameSize)); -+ return slot; ++ /** ++ * Extract with k option should have first manifest. ++ */ ++ @Test ++ public void testKeptOldFile() throws IOException { ++ jar("xkvf " + zip.toString()); ++ println(); ++ Assertions.assertEquals("1.0", getManifestVersion()); ++ String output = " inflated: META-INF/MANIFEST.MF" + nl + ++ " skipped: META-INF/MANIFEST.MF exists" + nl + ++ " inflated: entry1.txt" + nl + ++ " skipped: META-INF/MANIFEST.MF exists" + nl + ++ " inflated: entry2.txt" + nl; ++ Assertions.assertArrayEquals(baos.toByteArray(), output.getBytes()); ++ } ++ ++ private String getManifestVersion() throws IOException { ++ try (var is = Files.newInputStream(Path.of(JarFile.MANIFEST_NAME))) { ++ var manifest = new Manifest(is); ++ return manifest.getMainAttributes().getValue(Attributes.Name.MANIFEST_VERSION); ++ } + } + -+ @Override -+ public StackSlot emitIntToStack(Register a) { -+ StackSlot ret = newStackSlot(LoongArch64Kind.DWORD); -+ return emitIntToStack(ret, a); ++ private void jar(String cmdline) throws IOException { ++ System.out.println("jar " + cmdline); ++ baos.reset(); ++ ++ // the run method catches IOExceptions, we need to expose them ++ ByteArrayOutputStream baes = new ByteArrayOutputStream(); ++ PrintStream err = new PrintStream(baes); ++ PrintStream saveErr = System.err; ++ System.setErr(err); ++ try { ++ int rc = JAR_TOOL.run(jarOut, err, cmdline.split(" +")); ++ if (rc != 0) { ++ throw new IOException(baes.toString()); ++ } ++ } finally { ++ System.setErr(saveErr); ++ } + } + -+ private StackSlot emitLongToStack(StackSlot slot, Register a) { -+ emitStoreRegister(a, LoongArch64Kind.QWORD, LoongArch64.sp, slot.getOffset(frameSize)); -+ return slot; ++ private void println() throws IOException { ++ System.out.println(new String(baos.toByteArray())); + } + -+ @Override -+ public StackSlot emitLongToStack(Register a) { -+ StackSlot ret = newStackSlot(LoongArch64Kind.QWORD); -+ return emitLongToStack(ret, a); ++ private Stream mkpath(String... args) { ++ return Arrays.stream(args).map(d -> Path.of(".", d.split("/"))); + } + ++ private void rm(String cmdline) { ++ System.out.println("rm -rf " + cmdline); ++ mkpath(cmdline.split(" +")).forEach(p -> { ++ try { ++ if (Files.isDirectory(p)) { ++ FileUtils.deleteFileTreeWithRetry(p); ++ } else { ++ FileUtils.deleteFileIfExistsWithRetry(p); ++ } ++ } catch (IOException x) { ++ throw new UncheckedIOException(x); ++ } ++ }); ++ } +} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/MaxOopMapStackOffsetTest.java jdk11u-ls/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/MaxOopMapStackOffsetTest.java ---- openjdk/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/MaxOopMapStackOffsetTest.java 2022-10-12 23:00:04.000000000 +0800 -+++ jdk11u-ls/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/MaxOopMapStackOffsetTest.java 2023-09-12 13:54:27.749577516 +0800 -@@ -23,7 +23,7 @@ +\ No newline at end of file +diff --git a/test/jdk/tools/jar/modularJar/Basic.java b/test/jdk/tools/jar/modularJar/Basic.java +index ffc58eec9..cf16358ae 100644 +--- a/test/jdk/tools/jar/modularJar/Basic.java ++++ b/test/jdk/tools/jar/modularJar/Basic.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -24,7 +24,9 @@ + import java.io.*; + import java.lang.module.ModuleDescriptor; + import java.lang.reflect.Method; +-import java.nio.file.*; ++import java.nio.file.Files; ++import java.nio.file.Path; ++import java.nio.file.Paths; + import java.util.*; + import java.util.function.Consumer; + import java.util.jar.JarEntry; +@@ -32,6 +34,7 @@ import java.util.jar.JarFile; + import java.util.jar.JarInputStream; + import java.util.jar.Manifest; + import java.util.regex.Pattern; ++import java.util.spi.ToolProvider; + import java.util.stream.Collectors; + import java.util.stream.Stream; - /** - * @test -- * @requires vm.jvmci & (vm.simpleArch == "x64" | vm.simpleArch == "sparcv9") -+ * @requires vm.jvmci & (vm.simpleArch == "x64" | vm.simpleArch == "sparcv9" | vm.simpleArch == "loongarch64") - * @library / - * @modules jdk.internal.vm.ci/jdk.vm.ci.hotspot - * jdk.internal.vm.ci/jdk.vm.ci.meta -@@ -33,7 +33,8 @@ - * jdk.internal.vm.ci/jdk.vm.ci.runtime - * jdk.internal.vm.ci/jdk.vm.ci.amd64 - * jdk.internal.vm.ci/jdk.vm.ci.sparc -- * @compile CodeInstallationTest.java DebugInfoTest.java TestAssembler.java TestHotSpotVMConfig.java amd64/AMD64TestAssembler.java sparc/SPARCTestAssembler.java -+ * jdk.internal.vm.ci/jdk.vm.ci.loongarch64 -+ * @compile CodeInstallationTest.java DebugInfoTest.java TestAssembler.java TestHotSpotVMConfig.java amd64/AMD64TestAssembler.java sparc/SPARCTestAssembler.java loongarch64/LoongArch64TestAssembler.java - * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -Djvmci.Compiler=null jdk.vm.ci.code.test.MaxOopMapStackOffsetTest +@@ -59,6 +62,16 @@ import static java.lang.System.out; */ -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/NativeCallTest.java jdk11u-ls/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/NativeCallTest.java ---- openjdk/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/NativeCallTest.java 2022-10-12 23:00:04.000000000 +0800 -+++ jdk11u-ls/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/NativeCallTest.java 2023-09-12 13:54:27.749577516 +0800 -@@ -23,7 +23,7 @@ + public class Basic { ++ ++ private static final ToolProvider JAR_TOOL = ToolProvider.findFirst("jar") ++ .orElseThrow(() ++ -> new RuntimeException("jar tool not found") ++ ); ++ private static final ToolProvider JAVAC_TOOL = ToolProvider.findFirst("javac") ++ .orElseThrow(() ++ -> new RuntimeException("javac tool not found") ++ ); ++ + static final Path TEST_SRC = Paths.get(System.getProperty("test.src", ".")); + static final Path TEST_CLASSES = Paths.get(System.getProperty("test.classes", ".")); + static final Path MODULE_CLASSES = TEST_CLASSES.resolve("build"); +@@ -933,13 +946,14 @@ public class Basic { + } + Stream.of(args).forEach(commands::add); + ProcessBuilder p = new ProcessBuilder(commands); +- if (stdinSource != null) ++ if (stdinSource != null) { + p.redirectInput(stdinSource); ++ } + return run(p); + } - /** - * @test -- * @requires vm.jvmci & (vm.simpleArch == "x64" | vm.simpleArch == "sparcv9") -+ * @requires vm.jvmci & (vm.simpleArch == "x64" | vm.simpleArch == "sparcv9" | vm.simpleArch == "loongarch64") - * @library /test/lib / - * @modules jdk.internal.vm.ci/jdk.vm.ci.hotspot - * jdk.internal.vm.ci/jdk.vm.ci.code -@@ -33,7 +33,8 @@ - * jdk.internal.vm.ci/jdk.vm.ci.common - * jdk.internal.vm.ci/jdk.vm.ci.amd64 - * jdk.internal.vm.ci/jdk.vm.ci.sparc -- * @compile CodeInstallationTest.java TestHotSpotVMConfig.java NativeCallTest.java TestAssembler.java sparc/SPARCTestAssembler.java amd64/AMD64TestAssembler.java -+ * jdk.internal.vm.ci/jdk.vm.ci.loongarch64 -+ * @compile CodeInstallationTest.java TestHotSpotVMConfig.java NativeCallTest.java TestAssembler.java sparc/SPARCTestAssembler.java amd64/AMD64TestAssembler.java loongarch64/LoongArch64TestAssembler.java - * @run junit/othervm/native -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -Xbootclasspath/a:. jdk.vm.ci.code.test.NativeCallTest - */ - package jdk.vm.ci.code.test; -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/SimpleCodeInstallationTest.java jdk11u-ls/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/SimpleCodeInstallationTest.java ---- openjdk/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/SimpleCodeInstallationTest.java 2022-10-12 23:00:04.000000000 +0800 -+++ jdk11u-ls/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/SimpleCodeInstallationTest.java 2023-09-12 13:54:27.749577516 +0800 -@@ -23,7 +23,7 @@ + static Result jar(String... args) { +- return jarWithStdin(null, args); ++ return run(JAR_TOOL, args); + } - /** - * @test -- * @requires vm.jvmci & (vm.simpleArch == "x64" | vm.simpleArch == "sparcv9") -+ * @requires vm.jvmci & (vm.simpleArch == "x64" | vm.simpleArch == "sparcv9" | vm.simpleArch == "loongarch64") - * @library / - * @modules jdk.internal.vm.ci/jdk.vm.ci.hotspot - * jdk.internal.vm.ci/jdk.vm.ci.meta -@@ -32,7 +32,8 @@ - * jdk.internal.vm.ci/jdk.vm.ci.runtime - * jdk.internal.vm.ci/jdk.vm.ci.amd64 - * jdk.internal.vm.ci/jdk.vm.ci.sparc -- * @compile CodeInstallationTest.java DebugInfoTest.java TestAssembler.java TestHotSpotVMConfig.java amd64/AMD64TestAssembler.java sparc/SPARCTestAssembler.java -+ * jdk.internal.vm.ci/jdk.vm.ci.loongarch64 -+ * @compile CodeInstallationTest.java DebugInfoTest.java TestAssembler.java TestHotSpotVMConfig.java amd64/AMD64TestAssembler.java sparc/SPARCTestAssembler.java loongarch64/LoongArch64TestAssembler.java - * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -Djvmci.Compiler=null jdk.vm.ci.code.test.SimpleCodeInstallationTest - */ + static Path compileModule(String mn) throws IOException { +@@ -1027,10 +1041,8 @@ public class Basic { + static void javac(Path dest, Path modulePath, Path... sourceFiles) + throws IOException + { +- String javac = getJDKTool("javac"); -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/SimpleDebugInfoTest.java jdk11u-ls/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/SimpleDebugInfoTest.java ---- openjdk/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/SimpleDebugInfoTest.java 2022-10-12 23:00:04.000000000 +0800 -+++ jdk11u-ls/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/SimpleDebugInfoTest.java 2023-09-12 13:54:27.749577516 +0800 -@@ -23,7 +23,7 @@ + List commands = new ArrayList<>(); +- commands.add(javac); + if (!TOOL_VM_OPTIONS.isEmpty()) { + commands.addAll(Arrays.asList(TOOL_VM_OPTIONS.split("\\s+", -1))); + } +@@ -1048,7 +1060,13 @@ public class Basic { + } + Stream.of(sourceFiles).map(Object::toString).forEach(x -> commands.add(x)); - /** - * @test -- * @requires vm.jvmci & (vm.simpleArch == "x64" | vm.simpleArch == "sparcv9") -+ * @requires vm.jvmci & (vm.simpleArch == "x64" | vm.simpleArch == "sparcv9" | vm.simpleArch == "loongarch64") - * @library / - * @modules jdk.internal.vm.ci/jdk.vm.ci.hotspot - * jdk.internal.vm.ci/jdk.vm.ci.meta -@@ -32,7 +32,8 @@ - * jdk.internal.vm.ci/jdk.vm.ci.runtime - * jdk.internal.vm.ci/jdk.vm.ci.amd64 - * jdk.internal.vm.ci/jdk.vm.ci.sparc -- * @compile CodeInstallationTest.java DebugInfoTest.java TestAssembler.java TestHotSpotVMConfig.java amd64/AMD64TestAssembler.java sparc/SPARCTestAssembler.java -+ * jdk.internal.vm.ci/jdk.vm.ci.loongarch64 -+ * @compile CodeInstallationTest.java DebugInfoTest.java TestAssembler.java TestHotSpotVMConfig.java amd64/AMD64TestAssembler.java sparc/SPARCTestAssembler.java loongarch64/LoongArch64TestAssembler.java - * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -Djvmci.Compiler=null jdk.vm.ci.code.test.SimpleDebugInfoTest - */ +- quickFail(run(new ProcessBuilder(commands))); ++ StringWriter sw = new StringWriter(); ++ try (PrintWriter pw = new PrintWriter(sw)) { ++ int rc = JAVAC_TOOL.run(pw, pw, commands.toArray(new String[0])); ++ if(rc != 0) { ++ throw new RuntimeException(sw.toString()); ++ } ++ } + } -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/VirtualObjectDebugInfoTest.java jdk11u-ls/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/VirtualObjectDebugInfoTest.java ---- openjdk/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/VirtualObjectDebugInfoTest.java 2022-10-12 23:00:04.000000000 +0800 -+++ jdk11u-ls/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/VirtualObjectDebugInfoTest.java 2023-09-12 13:54:27.749577516 +0800 -@@ -23,7 +23,7 @@ + static Result java(Path modulePath, String entryPoint, String... args) { +@@ -1094,9 +1112,13 @@ public class Basic { + return false; + } - /** +- static void quickFail(Result r) { +- if (r.ec != 0) +- throw new RuntimeException(r.output); ++ static Result run(ToolProvider tp, String[] commands) { ++ int rc = 0; ++ StringWriter sw = new StringWriter(); ++ try (PrintWriter pw = new PrintWriter(sw)) { ++ rc = tp.run(pw, pw, commands); ++ } ++ return new Result(rc, sw.toString()); + } + + static Result run(ProcessBuilder pb) { +diff --git a/test/langtools/TEST.ROOT b/test/langtools/TEST.ROOT +index da089df72..b5503c4f7 100644 +--- a/test/langtools/TEST.ROOT ++++ b/test/langtools/TEST.ROOT +@@ -22,3 +22,7 @@ useNewOptions=true + + # Use --patch-module instead of -Xmodule: + useNewPatchModule=true ++ ++# Path to libraries in the topmost test directory. This is needed so @library ++# does not need ../../ notation to reach them ++external.lib.roots = ../../ +diff --git a/test/langtools/jdk/javadoc/doclet/testIOException/TestIOException.java b/test/langtools/jdk/javadoc/doclet/testIOException/TestIOException.java +index 9db41724a..b0bfc3c4a 100644 +--- a/test/langtools/jdk/javadoc/doclet/testIOException/TestIOException.java ++++ b/test/langtools/jdk/javadoc/doclet/testIOException/TestIOException.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2016, 2024, 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,9 +23,9 @@ + + /* * @test -- * @requires vm.jvmci & (vm.simpleArch == "x64" | vm.simpleArch == "sparcv9") -+ * @requires vm.jvmci & (vm.simpleArch == "x64" | vm.simpleArch == "sparcv9" | vm.simpleArch == "loongarch64") - * @library / - * @modules jdk.internal.vm.ci/jdk.vm.ci.hotspot - * jdk.internal.vm.ci/jdk.vm.ci.meta -@@ -32,7 +32,8 @@ - * jdk.internal.vm.ci/jdk.vm.ci.runtime - * jdk.internal.vm.ci/jdk.vm.ci.amd64 - * jdk.internal.vm.ci/jdk.vm.ci.sparc -- * @compile CodeInstallationTest.java DebugInfoTest.java TestAssembler.java TestHotSpotVMConfig.java amd64/AMD64TestAssembler.java sparc/SPARCTestAssembler.java -+ * jdk.internal.vm.ci/jdk.vm.ci.loongarch64 -+ * @compile CodeInstallationTest.java DebugInfoTest.java TestAssembler.java TestHotSpotVMConfig.java amd64/AMD64TestAssembler.java sparc/SPARCTestAssembler.java loongarch64/LoongArch64TestAssembler.java - * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -Djvmci.Compiler=null jdk.vm.ci.code.test.VirtualObjectDebugInfoTest - */ +- * @bug 8164130 ++ * @bug 8164130 8334332 + * @summary test IOException handling +- * @library ../lib ++ * @library ../lib /test/lib + * @modules jdk.javadoc/jdk.javadoc.internal.tool + * @build JavadocTester + * @run main TestIOException +@@ -33,7 +33,18 @@ -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/test/hotspot/jtreg/compiler/runtime/criticalnatives/argumentcorruption/CheckLongArgs.java jdk11u-ls/test/hotspot/jtreg/compiler/runtime/criticalnatives/argumentcorruption/CheckLongArgs.java ---- openjdk/test/hotspot/jtreg/compiler/runtime/criticalnatives/argumentcorruption/CheckLongArgs.java 2022-10-12 23:00:04.000000000 +0800 -+++ jdk11u-ls/test/hotspot/jtreg/compiler/runtime/criticalnatives/argumentcorruption/CheckLongArgs.java 2023-09-12 13:54:27.849577641 +0800 -@@ -21,10 +21,17 @@ - * questions. - */ + import java.io.File; + import java.io.FileWriter; ++import java.nio.file.Path; ++import java.nio.file.Files; ++import java.util.Map; -+/* -+ * This file has been modified by Loongson Technology in 2021, These -+ * modifications are Copyright (c) 2021, Loongson Technology, and are made -+ * available on the same license terms set forth above. -+ */ ++import jtreg.SkippedException; + ++/** ++ * Tests IO Exception handling. ++ * ++ * Update: Windows does not permit setting folder to be readonly. ++ * https://support.microsoft.com/en-us/help/326549/you-cannot-view-or-change-the-read-only-or-the-system-attributes-of-fo ++ */ + public class TestIOException extends JavadocTester { - /* @test - * @bug 8167409 - * @requires (os.arch != "aarch64") & (os.arch != "arm") -+ * @requires (os.arch != "mips64el") & (os.arch != "loongarch64") - * @run main/othervm/native -Xcomp -XX:+CriticalJNINatives compiler.runtime.criticalnatives.argumentcorruption.CheckLongArgs - */ - package compiler.runtime.criticalnatives.argumentcorruption; -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/test/hotspot/jtreg/compiler/runtime/criticalnatives/lookup/LookUp.java jdk11u-ls/test/hotspot/jtreg/compiler/runtime/criticalnatives/lookup/LookUp.java ---- openjdk/test/hotspot/jtreg/compiler/runtime/criticalnatives/lookup/LookUp.java 2022-10-12 23:00:04.000000000 +0800 -+++ jdk11u-ls/test/hotspot/jtreg/compiler/runtime/criticalnatives/lookup/LookUp.java 2023-09-12 13:54:27.849577641 +0800 -@@ -21,10 +21,17 @@ - * questions. - */ + public static void main(String... args) throws Exception { +@@ -45,13 +56,13 @@ public class TestIOException extends JavadocTester { + void testReadOnlyDirectory() { + File outDir = new File("out1"); + if (!outDir.mkdir()) { +- throw new Error("Cannot create directory"); ++ throw skip(outDir, "Cannot create directory"); + } + if (!outDir.setReadOnly()) { +- throw new Error("could not set directory read-only"); ++ throw skip(outDir, "could not set directory read-only"); + } + if (outDir.canWrite()) { +- throw new Error("directory is writable"); ++ throw skip(outDir, "directory is writable"); + } -+/* -+ * This file has been modified by Loongson Technology in 2021, These -+ * modifications are Copyright (c) 2021, Loongson Technology, and are made -+ * available on the same license terms set forth above. -+ */ + try { +@@ -69,15 +80,15 @@ public class TestIOException extends JavadocTester { + void testReadOnlyFile() throws Exception { + File outDir = new File("out2"); + if (!outDir.mkdir()) { +- throw new Error("Cannot create directory"); ++ throw skip(outDir, "Cannot create directory"); + } + File index = new File(outDir, "index.html"); + try (FileWriter fw = new FileWriter(index)) { } + if (!index.setReadOnly()) { +- throw new Error("could not set index read-only"); ++ throw skip(index, "could not set index read-only"); + } + if (index.canWrite()) { +- throw new Error("index is writable"); ++ throw skip(index, "index is writable"); + } + + try { +@@ -109,13 +120,13 @@ public class TestIOException extends JavadocTester { + File outDir = new File("out3"); + File pkgOutDir = new File(outDir, "p"); + if (!pkgOutDir.mkdirs()) { +- throw new Error("Cannot create directory"); ++ throw skip(pkgOutDir, "Cannot create directory"); + } + if (!pkgOutDir.setReadOnly()) { +- throw new Error("could not set directory read-only"); ++ throw skip(pkgOutDir, "could not set directory read-only"); + } + if (pkgOutDir.canWrite()) { +- throw new Error("directory is writable"); ++ throw skip(pkgOutDir, "directory is writable"); + } + + // run javadoc and check results +@@ -153,13 +164,13 @@ public class TestIOException extends JavadocTester { + File pkgOutDir = new File(outDir, "p"); + File docFilesOutDir = new File(pkgOutDir, "doc-files"); + if (!docFilesOutDir.mkdirs()) { +- throw new Error("Cannot create directory"); ++ throw skip(docFilesOutDir, "Cannot create directory"); + } + if (!docFilesOutDir.setReadOnly()) { +- throw new Error("could not set directory read-only"); ++ throw skip(docFilesOutDir, "could not set directory read-only"); + } + if (docFilesOutDir.canWrite()) { +- throw new Error("directory is writable"); ++ throw skip(docFilesOutDir, "directory is writable"); + } + + try { +@@ -175,5 +186,30 @@ public class TestIOException extends JavadocTester { + docFilesOutDir.setWritable(true); + } + } ++ ++ private Error skip(File f, String message) { ++ out.print(System.getProperty("user.name")); ++ out.println(f + ": " + message); ++ showAllAttributes(f.toPath()); ++ throw new SkippedException(f + ": " + message); ++ } ++ ++ private void showAllAttributes(Path p) { ++ showAttributes(p, "*"); ++ showAttributes(p, "posix:*"); ++ showAttributes(p, "dos:*"); ++ } + ++ private void showAttributes(Path p, String attributes) { ++ out.println("Attributes: " + attributes); ++ try { ++ Map map = Files.readAttributes(p, attributes); ++ map.forEach((n, v) -> out.format(" %-10s: %s%n", n, v)); ++ } catch (UnsupportedOperationException e) { ++ out.println("Attributes not available " + attributes); ++ } catch (Throwable t) { ++ out.println("Error accessing attributes " + attributes + ": " + t); ++ } ++ } + } - /* @test - * @bug 8167408 - * @requires (os.arch != "aarch64") & (os.arch != "arm") -+ * @requires (os.arch != "mips64el") & (os.arch != "loongarch64") - * @run main/othervm/native -Xcomp -XX:+CriticalJNINatives compiler.runtime.criticalnatives.lookup.LookUp - */ - package compiler.runtime.criticalnatives.lookup; -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/test/hotspot/jtreg/compiler/testlibrary/sha/predicate/IntrinsicPredicates.java jdk11u-ls/test/hotspot/jtreg/compiler/testlibrary/sha/predicate/IntrinsicPredicates.java ---- openjdk/test/hotspot/jtreg/compiler/testlibrary/sha/predicate/IntrinsicPredicates.java 2022-10-12 23:00:04.000000000 +0800 -+++ jdk11u-ls/test/hotspot/jtreg/compiler/testlibrary/sha/predicate/IntrinsicPredicates.java 2023-09-12 13:54:27.857577651 +0800 -@@ -21,6 +21,12 @@ - * questions. +diff --git a/test/langtools/jdk/jshell/ExecPtyGetFlagsToSetTest.java b/test/langtools/jdk/jshell/ExecPtyGetFlagsToSetTest.java +index 36f966449..efd1cd010 100644 +--- a/test/langtools/jdk/jshell/ExecPtyGetFlagsToSetTest.java ++++ b/test/langtools/jdk/jshell/ExecPtyGetFlagsToSetTest.java +@@ -26,7 +26,7 @@ + * @bug 8224184 + * @summary Control Char check for pty + * @modules jdk.internal.le/jdk.internal.org.jline.terminal +- * jdk.internal.le/jdk.internal.org.jline.terminal.impl ++ * jdk.internal.le/jdk.internal.org.jline.terminal.impl.exec + * jdk.internal.le/jdk.internal.org.jline.terminal.spi + * @requires (os.family == "linux") | (os.family == "aix") */ +@@ -35,12 +35,13 @@ import java.util.List; + import jdk.internal.org.jline.terminal.Attributes; + import jdk.internal.org.jline.terminal.Attributes.ControlChar; + import jdk.internal.org.jline.terminal.Attributes.LocalFlag; +-import jdk.internal.org.jline.terminal.impl.ExecPty; ++import jdk.internal.org.jline.terminal.impl.exec.ExecPty; ++import jdk.internal.org.jline.terminal.spi.SystemStream; + import jdk.internal.org.jline.terminal.spi.TerminalProvider; -+/* -+ * This file has been modified by Loongson Technology in 2021, These -+ * modifications are Copyright (c) 2021, Loongson Technology, and are made -+ * available on the same license terms set forth above. -+ */ -+ - package compiler.testlibrary.sha.predicate; + public class ExecPtyGetFlagsToSetTest extends ExecPty { +- public ExecPtyGetFlagsToSetTest(String name, TerminalProvider.Stream stream) { +- super(name, stream); ++ public ExecPtyGetFlagsToSetTest(TerminalProvider provider, SystemStream stream, String name) { ++ super(provider, stream, name); + } - import jdk.test.lib.Platform; -@@ -63,10 +69,12 @@ - = new OrPredicate(new CPUSpecificPredicate("aarch64.*", new String[] { "sha1" }, null), - new OrPredicate(new CPUSpecificPredicate("s390.*", new String[] { "sha1" }, null), - new OrPredicate(new CPUSpecificPredicate("sparc.*", new String[] { "sha1" }, null), -+ // Basic instructions are used to implement SHA1 Intrinsics on LA, so "sha1" feature is not needed. -+ new OrPredicate(new CPUSpecificPredicate("loongarch64.*", null, null), - // x86 variants - new OrPredicate(new CPUSpecificPredicate("amd64.*", new String[] { "sha" }, null), - new OrPredicate(new CPUSpecificPredicate("i386.*", new String[] { "sha" }, null), -- new CPUSpecificPredicate("x86.*", new String[] { "sha" }, null)))))); -+ new CPUSpecificPredicate("x86.*", new String[] { "sha" }, null))))))); + @Override +@@ -50,7 +51,7 @@ public class ExecPtyGetFlagsToSetTest extends ExecPty { - public static final BooleanSupplier SHA256_INSTRUCTION_AVAILABLE - = new OrPredicate(new CPUSpecificPredicate("aarch64.*", new String[] { "sha256" }, null), -@@ -74,12 +82,14 @@ - new OrPredicate(new CPUSpecificPredicate("sparc.*", new String[] { "sha256" }, null), - new OrPredicate(new CPUSpecificPredicate("ppc64.*", new String[] { "sha" }, null), - new OrPredicate(new CPUSpecificPredicate("ppc64le.*", new String[] { "sha" }, null), -+ // Basic instructions are used to implement SHA256 Intrinsics on LA, so "sha256" feature is not needed. -+ new OrPredicate(new CPUSpecificPredicate("loongarch64.*", null, null), - // x86 variants - new OrPredicate(new CPUSpecificPredicate("amd64.*", new String[] { "sha" }, null), - new OrPredicate(new CPUSpecificPredicate("i386.*", new String[] { "sha" }, null), - new OrPredicate(new CPUSpecificPredicate("x86.*", new String[] { "sha" }, null), - new OrPredicate(new CPUSpecificPredicate("amd64.*", new String[] { "avx2", "bmi2" }, null), -- new CPUSpecificPredicate("x86_64", new String[] { "avx2", "bmi2" }, null)))))))))); -+ new CPUSpecificPredicate("x86_64", new String[] { "avx2", "bmi2" }, null))))))))))); + public static void main(String[] args) { + ExecPtyGetFlagsToSetTest testPty = +- new ExecPtyGetFlagsToSetTest("stty", TerminalProvider.Stream.Output); ++ new ExecPtyGetFlagsToSetTest(null, SystemStream.Output, "stty"); - public static final BooleanSupplier SHA512_INSTRUCTION_AVAILABLE - = new OrPredicate(new CPUSpecificPredicate("aarch64.*", new String[] { "sha512" }, null), -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/test/hotspot/jtreg/loongson/25443/Test25443.java jdk11u-ls/test/hotspot/jtreg/loongson/25443/Test25443.java ---- openjdk/test/hotspot/jtreg/loongson/25443/Test25443.java 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/test/hotspot/jtreg/loongson/25443/Test25443.java 2023-09-12 13:54:27.933577747 +0800 -@@ -0,0 +1,58 @@ + Attributes attr = new Attributes(); + Attributes current = new Attributes(); +diff --git a/test/langtools/jdk/jshell/FailOverDirectExecutionControlTest.java b/test/langtools/jdk/jshell/FailOverDirectExecutionControlTest.java +index a094ed4a8..99457ea2c 100644 +--- a/test/langtools/jdk/jshell/FailOverDirectExecutionControlTest.java ++++ b/test/langtools/jdk/jshell/FailOverDirectExecutionControlTest.java +@@ -62,6 +62,7 @@ public class FailOverDirectExecutionControlTest extends ExecutionControlTestBase + + ClassLoader ccl; + ExecutionControlProvider provider; ++ Logger logger; + LogTestHandler hndlr; + Map> logged; + +@@ -95,7 +96,7 @@ public class FailOverDirectExecutionControlTest extends ExecutionControlTestBase + @BeforeMethod + @Override + public void setUp() { +- Logger logger = Logger.getLogger("jdk.jshell.execution"); ++ logger = Logger.getLogger("jdk.jshell.execution"); + logger.setLevel(Level.ALL); + hndlr = new LogTestHandler(); + logger.addHandler(hndlr); +@@ -137,8 +138,8 @@ public class FailOverDirectExecutionControlTest extends ExecutionControlTestBase + @Override + public void tearDown() { + super.tearDown(); +- Logger logger = Logger.getLogger("jdk.jshell.execution"); + logger.removeHandler(hndlr); ++ logger = null; + Thread.currentThread().setContextClassLoader(ccl); + } + +diff --git a/test/langtools/tools/javac/StringConcat/StringAppendEvaluatesInOrder.java b/test/langtools/tools/javac/StringConcat/StringAppendEvaluatesInOrder.java +new file mode 100644 +index 000000000..b2bd47acd +--- /dev/null ++++ b/test/langtools/tools/javac/StringConcat/StringAppendEvaluatesInOrder.java +@@ -0,0 +1,66 @@ +/* -+ * Copyright (c) 2015, 2022, Loongson Technology. All rights reserved. ++ * Copyright (c) 2021, Google LLC. 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 @@ -121059,49 +211301,59 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/test/hotspot/jtreg/loongso + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. -+ * + */ + -+/** ++/* + * @test -+ * @summary test c2 or2s ++ * @bug 8273914 ++ * @summary Indy string concat changes order of operations + * -+ * @run main/othervm -Xcomp -XX:-TieredCompilation Test25443 ++ * @clean * ++ * @compile -XDstringConcat=indy StringAppendEvaluatesInOrder.java ++ * @run main StringAppendEvaluatesInOrder ++ * ++ * @clean * ++ * @compile -XDstringConcat=indyWithConstants StringAppendEvaluatesInOrder.java ++ * @run main StringAppendEvaluatesInOrder ++ * ++ * @clean * ++ * @compile -XDstringConcat=inline StringAppendEvaluatesInOrder.java ++ * @run main StringAppendEvaluatesInOrder + */ -+public class Test25443 { -+ static short test_ori2s(int v1) { -+ short t = (short)(v1 | 0x14); -+ return t; ++ ++public class StringAppendEvaluatesInOrder { ++ static String test() { ++ StringBuilder builder = new StringBuilder("foo"); ++ int i = 15; ++ return "Test: " + i + " " + (++i) + builder + builder.append("bar"); + } + -+ static short test_or2s(int v1, int v2) { -+ short t = (short)(v1 | v2); -+ return t; ++ static String compoundAssignment() { ++ StringBuilder builder2 = new StringBuilder("foo"); ++ Object oo = builder2; ++ oo += "" + builder2.append("bar"); ++ return oo.toString(); + } + -+ static short ret; -+ public static void main(String[] args) { -+ for (int i = 0; i < 12000; i++) { //warmup -+ test_ori2s(0x333300); -+ test_or2s(0x333300, 0x14); -+ } ++ public static void main(String[] args) throws Exception { ++ assertEquals(test(), "Test: 15 16foofoobar"); ++ assertEquals(compoundAssignment(), "foofoobar"); ++ } + -+ if ( (test_ori2s(0x333300) == 0x3314) -+ && (test_or2s(0x333300, 0x14) == 0x3314) -+ && (test_or2s(0x333300, 0x1000) == 0x3300) -+ && (test_or2s(0x333300, 0x8000) == 0xffffb300)) { -+ System.out.println("TEST PASSED"); -+ } else { -+ throw new AssertionError("Not be expected results"); -+ } ++ private static void assertEquals(String actual, String expected) { ++ if (!actual.equals(expected)) { ++ throw new AssertionError("expected: " + expected + ", actual: " + actual); ++ } + } +} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/test/hotspot/jtreg/loongson/7432/Test7423.java jdk11u-ls/test/hotspot/jtreg/loongson/7432/Test7423.java ---- openjdk/test/hotspot/jtreg/loongson/7432/Test7423.java 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/test/hotspot/jtreg/loongson/7432/Test7423.java 2023-09-12 13:54:27.933577747 +0800 -@@ -0,0 +1,61 @@ +diff --git a/test/langtools/tools/javac/StringConcat/WellKnownTypeSignatures.java b/test/langtools/tools/javac/StringConcat/WellKnownTypeSignatures.java +new file mode 100644 +index 000000000..07cdeef49 +--- /dev/null ++++ b/test/langtools/tools/javac/StringConcat/WellKnownTypeSignatures.java +@@ -0,0 +1,119 @@ +/* -+ * Copyright (c) 2015, 2018, Loongson Technology. All rights reserved. ++ * Copyright (c) 2021, Google LLC. 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 @@ -121121,1089 +211373,343 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/test/hotspot/jtreg/loongso + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. -+ * + */ + -+/** ++import com.sun.tools.classfile.*; ++import com.sun.tools.classfile.ConstantPool.*; ++ ++import java.io.File; ++import java.util.ArrayList; ++import java.util.List; ++ ++/* + * @test -+ * @summary Divide by zero ++ * @bug 8273914 ++ * @summary Indy string concat changes order of operations ++ * @modules jdk.jdeps/com.sun.tools.classfile + * -+ * @run main/othervm -Xint Test7423 -+ * @run main/othervm -Xcomp Test7423 ++ * @clean * ++ * @compile -XDstringConcat=indy WellKnownTypeSignatures.java ++ * @run main WellKnownTypeSignatures ++ * ++ * @clean * ++ * @compile -XDstringConcat=indyWithConstants WellKnownTypeSignatures.java ++ * @run main WellKnownTypeSignatures + */ -+public class Test7423 { + -+ private static int divInt(int n) { -+ int a = 1 / n; -+ return a; -+ } ++public class WellKnownTypeSignatures { ++ static List actualTypes; ++ ++ static int idx = 0; ++ ++ static boolean z = true; ++ static char c = (char) 42; ++ static short s = (short) 42; ++ static byte b = (byte) 42; ++ static int i = 42; ++ static long l = 42L; ++ static float f = 42.0f; ++ static double d = 42.0; ++ ++ public static void main(String[] argv) throws Exception { ++ readIndyTypes(); ++ ++ test("" + WellKnownTypeSignatures.class, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); ++ test("" + Boolean.valueOf(z), idx++, "(Ljava/lang/Boolean;)Ljava/lang/String;"); ++ test("" + Character.valueOf(c), idx++, "(Ljava/lang/Character;)Ljava/lang/String;"); ++ test("" + Byte.valueOf(b), idx++, "(Ljava/lang/Byte;)Ljava/lang/String;"); ++ test("" + Short.valueOf(s), idx++, "(Ljava/lang/Short;)Ljava/lang/String;"); ++ test("" + Integer.valueOf(i), idx++, "(Ljava/lang/Integer;)Ljava/lang/String;"); ++ test("" + Long.valueOf(l), idx++, "(Ljava/lang/Long;)Ljava/lang/String;"); ++ test("" + Double.valueOf(d), idx++, "(Ljava/lang/Double;)Ljava/lang/String;"); ++ test("" + Float.valueOf(f), idx++, "(Ljava/lang/Float;)Ljava/lang/String;"); ++ test("" + z, idx++, "(Z)Ljava/lang/String;"); ++ test("" + c, idx++, "(C)Ljava/lang/String;"); ++ test("" + b, idx++, "(B)Ljava/lang/String;"); ++ test("" + s, idx++, "(S)Ljava/lang/String;"); ++ test("" + i, idx++, "(I)Ljava/lang/String;"); ++ test("" + l, idx++, "(J)Ljava/lang/String;"); ++ test("" + d, idx++, "(D)Ljava/lang/String;"); ++ test("" + f, idx++, "(F)Ljava/lang/String;"); ++ } ++ ++ public static void test(String actual, int index, String expectedType) { ++ String actualType = actualTypes.get(index); ++ if (!actualType.equals(expectedType)) { ++ throw new IllegalStateException( ++ index ++ + " Unexpected type: expected = " ++ + expectedType ++ + ", actual = " ++ + actualType); ++ } ++ } + -+ private static long divLong(long n) { -+ long a = (long)1 / n; -+ return a; -+ } ++ public static void readIndyTypes() throws Exception { ++ actualTypes = new ArrayList(); ++ ++ ClassFile classFile = ++ ClassFile.read( ++ new File( ++ System.getProperty("test.classes", "."), ++ WellKnownTypeSignatures.class.getName() + ".class")); ++ ConstantPool constantPool = classFile.constant_pool; ++ ++ for (Method method : classFile.methods) { ++ if (method.getName(constantPool).equals("main")) { ++ Code_attribute code = (Code_attribute) method.attributes.get(Attribute.Code); ++ for (Instruction i : code.getInstructions()) { ++ if (i.getOpcode() == Opcode.INVOKEDYNAMIC) { ++ CONSTANT_InvokeDynamic_info indyInfo = ++ (CONSTANT_InvokeDynamic_info) ++ constantPool.get(i.getUnsignedShort(1)); ++ CONSTANT_NameAndType_info natInfo = indyInfo.getNameAndTypeInfo(); ++ actualTypes.add(natInfo.getType()); ++ } ++ } ++ } ++ } ++ } ++} +diff --git a/test/langtools/tools/javac/StringConcat/WellKnownTypes.java b/test/langtools/tools/javac/StringConcat/WellKnownTypes.java +new file mode 100644 +index 000000000..39150cfc4 +--- /dev/null ++++ b/test/langtools/tools/javac/StringConcat/WellKnownTypes.java +@@ -0,0 +1,81 @@ ++/* ++ * Copyright (c) 2021, Google LLC. 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. ++ */ + -+ public static void main(String[] args) throws Exception { ++import com.sun.tools.classfile.*; ++import com.sun.tools.classfile.ConstantPool.*; + -+ try { -+ for (int i = 0; i < 20000; i++) { -+ if (i == 18000) { -+ divInt(0); -+ divLong((long)0); -+ } else { -+ divInt(1); -+ divLong((long)1); ++/* ++ * @test ++ * @bug 8273914 ++ * @summary Indy string concat changes order of operations ++ * @modules jdk.jdeps/com.sun.tools.classfile ++ * ++ * @compile -XDstringConcat=indy WellKnownTypes.java ++ * @run main WellKnownTypes ++ * ++ * @compile -XDstringConcat=indyWithConstants WellKnownTypes.java ++ * @run main WellKnownTypes ++ * ++ * @compile -XDstringConcat=inline WellKnownTypes.java ++ * @run main WellKnownTypes ++ */ ++ ++public class WellKnownTypes { ++ static int idx = 0; ++ ++ static boolean z = true; ++ static char c = (char) 42; ++ static byte b = (byte) 43; ++ static short s = (short) 44; ++ static int i = 45; ++ static long l = 46L; ++ static float f = 47.0f; ++ static double d = 48.0; ++ ++ public static void main(String[] argv) throws Exception { ++ test("" + WellKnownTypes.class, idx++, "class WellKnownTypes"); ++ test("" + Boolean.valueOf(z), idx++, "true"); ++ test("" + Character.valueOf(c), idx++, "*"); ++ test("" + Byte.valueOf(b), idx++, "43"); ++ test("" + Short.valueOf(s), idx++, "44"); ++ test("" + Integer.valueOf(i), idx++, "45"); ++ test("" + Long.valueOf(l), idx++, "46"); ++ test("" + Float.valueOf(f), idx++, "47.0"); ++ test("" + Double.valueOf(d), idx++, "48.0"); ++ test("" + z, idx++, "true"); ++ test("" + c, idx++, "*"); ++ test("" + b, idx++, "43"); ++ test("" + s, idx++, "44"); ++ test("" + i, idx++, "45"); ++ test("" + l, idx++, "46"); ++ test("" + f, idx++, "47.0"); ++ test("" + d, idx++, "48.0"); ++ } ++ ++ public static void test(String actual, int index, String expected) { ++ if (!actual.equals(expected)) { ++ throw new IllegalStateException( ++ index + " Unexpected: expected = " + expected + ", actual = " + actual); + } -+ } -+ } catch (java.lang.ArithmeticException exc) { -+ System.out.println("expected-exception " + exc); + } -+ } -+ +} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/test/hotspot/jtreg/ProblemList.txt jdk11u-ls/test/hotspot/jtreg/ProblemList.txt ---- openjdk/test/hotspot/jtreg/ProblemList.txt 2022-10-12 23:00:04.000000000 +0800 -+++ jdk11u-ls/test/hotspot/jtreg/ProblemList.txt 2023-11-01 09:34:26.513946398 +0800 -@@ -21,6 +21,12 @@ - # questions. - # +diff --git a/test/langtools/tools/javac/StringConcat/access/Test.java b/test/langtools/tools/javac/StringConcat/access/Test.java +index 72237e8b4..578bbddb1 100644 +--- a/test/langtools/tools/javac/StringConcat/access/Test.java ++++ b/test/langtools/tools/javac/StringConcat/access/Test.java +@@ -56,109 +56,109 @@ public class Test { + // ---------------------------------------------------------------------------- -+# -+# This file has been modified by Loongson Technology in 2022. These -+# modifications are Copyright (c) 2019, 2022, Loongson Technology, and are made -+# available on the same license terms set forth above. -+# -+ - ############################################################################# - # - # List of quarantined tests -- tests that should not be run by default, because -@@ -234,3 +240,40 @@ - vmTestbase/nsk/jdwp/ThreadReference/ForceEarlyReturn/forceEarlyReturn001/forceEarlyReturn001.java 7199837 generic-all - - ############################################################################# -+ -+# loongson added -+compiler/loopopts/TestSkeletonPredicateNegation.java #25538 generic-loongarch64 -+compiler/profiling/TestTypeProfiling.java #25171 generic-loongarch64 -+compiler/tiered/Level2RecompilationTest.java #10070 generic-mips64el,generic-loongarch64 -+containers/cgroup/PlainRead.java #20028 generic-mips64el -+gc/cms/TestBubbleUpRef.java #17221 generic-mips64el -+gc/stress/gcbasher/TestGCBasherWithCMS.java #17221 generic-mips64el -+resourcehogs/serviceability/sa/ClhsdbRegionDetailsScanOopsForG1.java #24312 generic-loongarch64 -+resourcehogs/serviceability/sa/TestHeapDumpForLargeArray.java #9797 generic-mips64el -+runtime/classFileParserBug/TestEmptyBootstrapMethodsAttr.java generic-all -+runtime/NMT/CheckForProperDetailStackTrace.java #9499 generic-mips64el,generic-loongarch64 -+serviceability/sa/CDSJMapClstats.java #9797 generic-mips64el -+serviceability/sa/ClhsdbCDSJstackPrintAll.java #9797 generic-mips64el -+serviceability/sa/ClhsdbInspect.java #9797 generic-mips64el -+serviceability/sa/ClhsdbJdis.java #9797 generic-mips64el -+serviceability/sa/ClhsdbJstack.java #9797 generic-mips64el -+serviceability/sa/ClhsdbJstackXcompStress.java #10632 generic-mips64el -+serviceability/sa/ClhsdbPrintAs.java #9797 generic-mips64el -+serviceability/sa/ClhsdbPstack.java #9797 generic-mips64el -+serviceability/sa/ClhsdbSource.java #9797 generic-mips64el -+serviceability/sa/ClhsdbThread.java #9797 generic-mips64el -+serviceability/sa/ClhsdbWhere.java #9797 generic-mips64el -+serviceability/sa/DeadlockDetectionTest.java #9797 generic-mips64el -+serviceability/sa/JhsdbThreadInfoTest.java #9797 generic-mips64el -+serviceability/sa/jmap-hprof/JMapHProfLargeHeapTest.java #9797 generic-mips64el -+serviceability/sa/sadebugd/DebugdConnectTest.java #9797 generic-mips64el -+serviceability/sa/TestClhsdbJstackLock.java #9797 generic-mips64el -+serviceability/sa/TestHeapDumpForInvokeDynamic.java #9797 generic-mips64el -+serviceability/sa/TestHeapDumpForLargeArray.java #9797 generic-mips64el -+serviceability/sa/TestInstanceKlassSize.java #9797 generic-mips64el -+serviceability/sa/TestJhsdbJstackLock.java #9797 generic-mips64el -+serviceability/sa/TestJhsdbJstackMixed.java #9797 generic-mips64el -+serviceability/sa/TestJmapCore.java #9797 generic-mips64el -+serviceability/sa/TestJmapCoreMetaspace.java #9797 generic-mips64el -+serviceability/sa/TestPrintMdo.java #9797,#25534 generic-mips64el,generic-loongarch64 -+vmTestbase/jit/tiered/Test.java generic-mips64el -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/test/hotspot/jtreg/ProblemList-Xcomp.txt jdk11u-ls/test/hotspot/jtreg/ProblemList-Xcomp.txt ---- openjdk/test/hotspot/jtreg/ProblemList-Xcomp.txt 2022-10-12 23:00:04.000000000 +0800 -+++ jdk11u-ls/test/hotspot/jtreg/ProblemList-Xcomp.txt 2023-09-12 13:54:27.489577189 +0800 -@@ -29,3 +29,6 @@ - - vmTestbase/vm/mlvm/meth/stress/jni/nativeAndMH/Test.java 8208235 solaris-all - runtime/appcds/cacheObject/DifferentHeapSizes.java 8210102 solaris-all -+ -+# loongson added -+compiler/intrinsics/bigInteger/TestMultiplyToLenReturnProfile.java generic-mips64el -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/test/hotspot/jtreg/runtime/ReservedStack/ReservedStackTest.java jdk11u-ls/test/hotspot/jtreg/runtime/ReservedStack/ReservedStackTest.java ---- openjdk/test/hotspot/jtreg/runtime/ReservedStack/ReservedStackTest.java 2022-10-12 23:00:04.000000000 +0800 -+++ jdk11u-ls/test/hotspot/jtreg/runtime/ReservedStack/ReservedStackTest.java 2023-09-12 13:54:27.981577807 +0800 -@@ -22,6 +22,12 @@ - */ + // public Private_PublicClass c1 = new Private_PublicClass(); +- test("" + holder.c1, idx++, "(Lp1/PublicClass;)Ljava/lang/String;"); ++ test("" + holder.c1, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); - /* -+ * This file has been modified by Loongson Technology in 2021, These -+ * modifications are Copyright (c) 2021, Loongson Technology, and are made -+ * available on the same license terms set forth above. -+ */ -+ -+/* - * @test ReservedStackTest - * - * @requires vm.opt.DeoptimizeALot != true -@@ -239,7 +245,7 @@ - return Platform.isAix() || - (Platform.isLinux() && - (Platform.isPPC() || Platform.isS390x() || Platform.isX64() || -- Platform.isX86())) || -+ Platform.isX86() || Platform.isMIPS() || Platform.isLoongArch64())) || - Platform.isOSX() || - Platform.isSolaris(); - } -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/test/hotspot/jtreg/testlibrary_tests/TestMutuallyExclusivePlatformPredicates.java jdk11u-ls/test/hotspot/jtreg/testlibrary_tests/TestMutuallyExclusivePlatformPredicates.java ---- openjdk/test/hotspot/jtreg/testlibrary_tests/TestMutuallyExclusivePlatformPredicates.java 2022-10-12 23:00:04.000000000 +0800 -+++ jdk11u-ls/test/hotspot/jtreg/testlibrary_tests/TestMutuallyExclusivePlatformPredicates.java 2023-09-12 13:54:28.141578008 +0800 -@@ -45,7 +45,7 @@ - */ - public class TestMutuallyExclusivePlatformPredicates { - private static enum MethodGroup { -- ARCH("isAArch64", "isARM", "isPPC", "isS390x", "isSparc", "isX64", "isX86"), -+ ARCH("isAArch64", "isARM", "isPPC", "isS390x", "isSparc", "isX64", "isX86", "isMIPS", "isLoongArch64"), - BITNESS("is32bit", "is64bit"), - OS("isAix", "isLinux", "isOSX", "isSolaris", "isWindows"), - VM_TYPE("isClient", "isServer", "isGraal", "isMinimal", "isZero", "isEmbedded"), -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/test/jdk/java/security/KeyAgreement/KeyAgreementTest.java jdk11u-ls/test/jdk/java/security/KeyAgreement/KeyAgreementTest.java ---- openjdk/test/jdk/java/security/KeyAgreement/KeyAgreementTest.java 2022-10-12 23:00:07.000000000 +0800 -+++ jdk11u-ls/test/jdk/java/security/KeyAgreement/KeyAgreementTest.java 2023-09-12 13:54:29.981580321 +0800 -@@ -67,9 +67,27 @@ - // EC curve supported for KeyGeneration can found between intersection - // of curves define in - // "java.base/share/classes/sun/security/util/CurveDB.java" -- -- ECDH("secp256k1", "secp256r1", "secp384r1", "secp521r1"), -- XDH("X25519", "X448", "x25519"), -+ // and -+ // "jdk.crypto.ec/share/native/libsunec/impl/ecdecode.c" -+ ECDH( -+ // SEC2 prime curves -+ "secp112r1", "secp112r2", "secp128r1", "secp128r2", "secp160k1", -+ "secp160r1", "secp192k1", "secp192r1", "secp224k1", "secp224r1", -+ "secp256k1", "secp256r1", "secp384r1", "secp521r1", -+ // ANSI X9.62 prime curves -+ "X9.62 prime192v2", "X9.62 prime192v3", "X9.62 prime239v1", -+ "X9.62 prime239v2", "X9.62 prime239v3", -+ // SEC2 binary curves -+ "sect113r1", "sect113r2", "sect131r1", "sect131r2", "sect163k1", -+ "sect163r1", "sect163r2", "sect193r1", "sect193r2", "sect233k1", -+ "sect233r1", "sect239k1", "sect283k1", "sect283r1", "sect409k1", -+ "sect409r1", "sect571k1", "sect571r1", -+ // ANSI X9.62 binary curves -+ "X9.62 c2tnb191v1", "X9.62 c2tnb191v2", "X9.62 c2tnb191v3", -+ "X9.62 c2tnb239v1", "X9.62 c2tnb239v2", "X9.62 c2tnb239v3", -+ "X9.62 c2tnb359v1", "X9.62 c2tnb431r1" -+ ), -+ XDH("X25519", "X448"), - // There is no curve for DiffieHellman - DiffieHellman(new String[]{}); - -@@ -101,7 +119,7 @@ - } + // public Private_PublicInterface c2 = new Private_PublicInterface(); +- test("" + holder.c2, idx++, "(Ljava/lang/Object;)Ljava/lang/String;"); ++ test("" + holder.c2, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); - /** -- * Perform KeyAgreement operation -+ * Perform KeyAgreement operation using native as well as JCE provider. - */ - private static void testKeyAgreement(String provider, String kaAlgo, - String kpgAlgo, AlgorithmParameterSpec spec) throws Exception { -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/test/jdk/java/security/KeyAgreement/KeySizeTest.java jdk11u-ls/test/jdk/java/security/KeyAgreement/KeySizeTest.java ---- openjdk/test/jdk/java/security/KeyAgreement/KeySizeTest.java 2022-10-12 23:00:07.000000000 +0800 -+++ jdk11u-ls/test/jdk/java/security/KeyAgreement/KeySizeTest.java 2023-09-12 13:54:29.981580321 +0800 -@@ -37,9 +37,9 @@ - * @run main KeySizeTest DiffieHellman SunJCE DiffieHellman 4096 - * @run main KeySizeTest DiffieHellman SunJCE DiffieHellman 6144 - * @run main KeySizeTest DiffieHellman SunJCE DiffieHellman 8192 -- * @run main/othervm KeySizeTest ECDH SunEC EC 256 -- * @run main/othervm KeySizeTest ECDH SunEC EC 384 -- * @run main/othervm KeySizeTest ECDH SunEC EC 521 -+ * @run main KeySizeTest ECDH SunEC EC 128 -+ * @run main KeySizeTest ECDH SunEC EC 192 -+ * @run main KeySizeTest ECDH SunEC EC 256 - * @run main KeySizeTest XDH SunEC XDH 255 - * @run main KeySizeTest XDH SunEC XDH 448 - */ -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/test/jdk/javax/net/ssl/templates/SSLSocketTemplate.java jdk11u-ls/test/jdk/javax/net/ssl/templates/SSLSocketTemplate.java ---- openjdk/test/jdk/javax/net/ssl/templates/SSLSocketTemplate.java 2022-10-12 23:00:07.000000000 +0800 -+++ jdk11u-ls/test/jdk/javax/net/ssl/templates/SSLSocketTemplate.java 2023-09-12 13:54:30.401580849 +0800 -@@ -358,12 +358,14 @@ - // Trusted certificates. - protected final static Cert[] TRUSTED_CERTS = { - Cert.CA_ECDSA_SECP256R1, -+ Cert.CA_ECDSA_SECT283R1, - Cert.CA_RSA_2048, - Cert.CA_DSA_2048 }; - - // End entity certificate. - protected final static Cert[] END_ENTITY_CERTS = { - Cert.EE_ECDSA_SECP256R1, -+ Cert.EE_ECDSA_SECT283R1, - Cert.EE_RSA_2048, - Cert.EE_EC_RSA_SECP256R1, - Cert.EE_DSA_2048 }; -@@ -697,6 +699,32 @@ - "p1YdWENftmDoNTJ3O6TNlXb90jKWgAirCXNBUompPtHKkO592eDyGcT1h8qjrKlm\n" + - "Kw=="), - -+ CA_ECDSA_SECT283R1( -+ "EC", -+ // SHA1withECDSA, curve sect283r1 -+ // Validity -+ // Not Before: May 26 06:06:52 2020 GMT -+ // Not After : May 21 06:06:52 2040 GMT -+ // Subject Key Identifier: -+ // CF:A3:99:ED:4C:6E:04:41:09:21:31:33:B6:80:D5:A7:BF:2B:98:04 -+ "-----BEGIN CERTIFICATE-----\n" + -+ "MIIB8TCCAY+gAwIBAgIJANQFsBngZ3iMMAsGByqGSM49BAEFADBdMQswCQYDVQQG\n" + -+ "EwJVUzELMAkGA1UECBMCQ0ExCzAJBgNVBAcTAlNBMQ8wDQYDVQQKEwZPcmFjbGUx\n" + -+ "DzANBgNVBAsTBkpQR1NRRTESMBAGA1UEAxMJc2VjdDI4M3IxMB4XDTIwMDUyNjE4\n" + -+ "MDY1MloXDTQwMDUyMTE4MDY1MlowXTELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNB\n" + -+ "MQswCQYDVQQHEwJTQTEPMA0GA1UEChMGT3JhY2xlMQ8wDQYDVQQLEwZKUEdTUUUx\n" + -+ "EjAQBgNVBAMTCXNlY3QyODNyMTBeMBAGByqGSM49AgEGBSuBBAARA0oABALatmDt\n" + -+ "QIhjpK4vJjv4GgC8CUH/VAWLUSQRU7yGGQ3NF8rVBARv0aehiII0nzjDVX5KrP/A\n" + -+ "w/DmW7q8PfEAIktuaA/tcKv/OKMyMDAwHQYDVR0OBBYEFM+jme1MbgRBCSExM7aA\n" + -+ "1ae/K5gEMA8GA1UdEwEB/wQFMAMBAf8wCwYHKoZIzj0EAQUAA08AMEwCJAGHsAP8\n" + -+ "HlcVqszra+fxq35juTxHJIfxTKIr7f54Ywtz7AJowgIkAxydv8g+dkuniOUAj0Xt\n" + -+ "FnGVp6HzKX5KM1zLpfqmix8ZPP/A\n" + -+ "-----END CERTIFICATE-----", -+ "MIGQAgEAMBAGByqGSM49AgEGBSuBBAARBHkwdwIBAQQkAdcyn/FxiNvuTsSgDehq\n" + -+ "SGFiTxAKNMMJfmsO6GHekzszFqjPoUwDSgAEAtq2YO1AiGOkri8mO/gaALwJQf9U\n" + -+ "BYtRJBFTvIYZDc0XytUEBG/Rp6GIgjSfOMNVfkqs/8DD8OZburw98QAiS25oD+1w\n" + -+ "q/84"), -+ - CA_RSA_2048( - "RSA", - // SHA256withRSA, 2048 bits -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/test/jdk/jdk/jfr/event/os/TestCPUInformation.java jdk11u-ls/test/jdk/jdk/jfr/event/os/TestCPUInformation.java ---- openjdk/test/jdk/jdk/jfr/event/os/TestCPUInformation.java 2022-10-12 23:00:06.000000000 +0800 -+++ jdk11u-ls/test/jdk/jdk/jfr/event/os/TestCPUInformation.java 2023-09-12 13:54:30.669581186 +0800 -@@ -23,6 +23,12 @@ - * questions. - */ + // public Private_PrivateInterface1 c3 = new Private_PrivateInterface1(); +- test("" + holder.c3, idx++, "(Ljava/lang/Object;)Ljava/lang/String;"); ++ test("" + holder.c3, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); -+/* -+ * This file has been modified by Loongson Technology in 2021, These -+ * modifications are Copyright (c) 2021, Loongson Technology, and are made -+ * available on the same license terms set forth above. -+ */ -+ - package jdk.jfr.event.os; + // public Private_PrivateInterface2 c4 = new Private_PrivateInterface2(); +- test("" + holder.c4, idx++, "(Ljava/lang/Object;)Ljava/lang/String;"); ++ test("" + holder.c4, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); - import java.util.List; -@@ -54,8 +60,8 @@ - Events.assertField(event, "hwThreads").atLeast(1); - Events.assertField(event, "cores").atLeast(1); - Events.assertField(event, "sockets").atLeast(1); -- Events.assertField(event, "cpu").containsAny("Intel", "AMD", "Unknown x86", "sparc", "ARM", "PPC", "PowerPC", "AArch64", "s390"); -- Events.assertField(event, "description").containsAny("Intel", "AMD", "Unknown x86", "SPARC", "ARM", "PPC", "PowerPC", "AArch64", "s390"); -+ Events.assertField(event, "cpu").containsAny("Intel", "AMD", "Unknown x86", "sparc", "ARM", "PPC", "PowerPC", "AArch64", "s390", "MIPS", "LoongArch"); -+ Events.assertField(event, "description").containsAny("Intel", "AMD", "Unknown x86", "SPARC", "ARM", "PPC", "PowerPC", "AArch64", "s390", "MIPS", "LoongArch"); - } - } - } -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/test/jdk/jdk/security/jarsigner/Spec.java jdk11u-ls/test/jdk/jdk/security/jarsigner/Spec.java ---- openjdk/test/jdk/jdk/security/jarsigner/Spec.java 2022-10-12 23:00:07.000000000 +0800 -+++ jdk11u-ls/test/jdk/jdk/security/jarsigner/Spec.java 2023-09-12 13:54:30.713581241 +0800 -@@ -31,7 +31,7 @@ - * jdk.jartool - * jdk.crypto.ec - * @build jdk.test.lib.util.JarUtils -- * @run main/othervm Spec -+ * @run main Spec - */ + // public Public_PublicClass c5 = new Public_PublicClass(); +- test("" + holder.c5, idx++, "(Lp1/Public_PublicClass;)Ljava/lang/String;"); ++ test("" + holder.c5, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); - import com.sun.jarsigner.ContentSigner; -@@ -190,7 +190,7 @@ - .equals("SHA256withDSA")); - - kpg = KeyPairGenerator.getInstance("EC"); -- kpg.initialize(256); -+ kpg.initialize(192); - assertTrue(JarSigner.Builder - .getDefaultSignatureAlgorithm(kpg.generateKeyPair().getPrivate()) - .equals("SHA256withECDSA")); -@@ -198,7 +198,7 @@ - assertTrue(JarSigner.Builder - .getDefaultSignatureAlgorithm(kpg.generateKeyPair().getPrivate()) - .equals("SHA384withECDSA")); -- kpg.initialize(521); -+ kpg.initialize(571); - assertTrue(JarSigner.Builder - .getDefaultSignatureAlgorithm(kpg.generateKeyPair().getPrivate()) - .equals("SHA512withECDSA")); -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/test/jdk/ProblemList.txt jdk11u-ls/test/jdk/ProblemList.txt ---- openjdk/test/jdk/ProblemList.txt 2022-10-12 23:00:05.000000000 +0800 -+++ jdk11u-ls/test/jdk/ProblemList.txt 2023-11-01 09:34:26.661946562 +0800 -@@ -21,6 +21,12 @@ - # or visit www.oracle.com if you need additional information or have any - # questions. - # -+ -+# -+# This file has been modified by Loongson Technology in 2022. These -+# modifications are Copyright (c) 2019, 2022, Loongson Technology, and are made -+# available on the same license terms set forth above. -+# - ########################################################################### - # - # List of tests that should not be run by test/Makefile, for various reasons: -@@ -622,7 +628,7 @@ - - sun/security/tools/keytool/ListKeychainStore.sh 8156889 macosx-all - --sun/security/tools/jarsigner/compatibility/SignTwice.java 8217375 windows-all -+sun/security/tools/jarsigner/compatibility/SignTwice.java 8217375,#24291 windows-all,generic-mips64el,generic-loongarch64 - sun/security/tools/jarsigner/warnings/BadKeyUsageTest.java 8026393 generic-all - - javax/net/ssl/ServerName/SSLEngineExplorerMatchedSNI.java 8212096 generic-all -@@ -886,3 +892,40 @@ - - ############################################################################ - -+# loongson added -+java/awt/font/GlyphVector/NLGlyphTest.java #21476 generic-all -+java/lang/System/LoggerFinder/internal/BootstrapLogger/BootstrapLoggerTest.java generic-all -+java/rmi/server/UnicastRemoteObject/exportObject/GcDuringExport.java #10949 generic-mips64el,generic-loongarch64 -+java/util/logging/LocalizedLevelName.java generic-all -+java/util/logging/SimpleFormatterFormat.java generic-all -+jdk/jfr/api/consumer/TestRecordedFrame.java #10010 generic-mips64el,generic-loongarch64 -+jdk/jfr/jcmd/TestJcmdStartWithSettings.java #24259 generic-mips64el,generic-loongarch64 -+jdk/jfr/jvm/TestJFRIntrinsic.java #10011,JDK-8239423 generic-mips64el,generic-loongarch64 -+security/infra/java/security/cert/CertPathValidator/certification/LetsEncryptCA.java #24472 generic-loongarch64 -+sun/tools/jhsdb/BasicLauncherTest.java #9381 generic-mips64el -+sun/tools/jhsdb/HeapDumpTest.java #9381 generic-mips64el -+sun/tools/jhsdb/JShellHeapDumpTest.java #23705 generic-mips64el -+sun/util/logging/SourceClassName.java generic-all -+tools/pack200/DeprecatePack200.java generic-all -+tools/jpackage/linux/AppAboutUrlTest.java#id0 #24942 generic-loongarch64 -+tools/jpackage/linux/AppCategoryTest.java #24942 generic-loongarch64 -+tools/jpackage/linux/jdk/jpackage/tests/UsrTreeTest.java #24942 generic-loongarch64 -+tools/jpackage/linux/LicenseTypeTest.java #24942 generic-loongarch64 -+tools/jpackage/linux/LinuxBundleNameTest.java #24942 generic-loongarch64 -+tools/jpackage/linux/LinuxResourceTest.java #24942 generic-loongarch64 -+tools/jpackage/linux/PackageDepsTest.java #24942 generic-loongarch64 -+tools/jpackage/linux/ReleaseTest.java#id0 #24942 generic-loongarch64 -+tools/jpackage/linux/ShortcutHintTest.java#id0 #24942 generic-loongarch64 -+tools/jpackage/share/AddLauncherTest.java#id1 #24942 generic-loongarch64 -+tools/jpackage/share/AddLShortcutTest.java #24942 generic-loongarch64 -+tools/jpackage/share/AppContentTest.java #24942 generic-loongarch64 -+tools/jpackage/share/AppImagePackageTest.java #24942 generic-loongarch64 -+tools/jpackage/share/EmptyFolderPackageTest.java #24942 generic-loongarch64 -+tools/jpackage/share/FileAssociationsTest.java#id0 #24942 generic-loongarch64 -+tools/jpackage/share/IconTest.java #24942 generic-loongarch64 -+tools/jpackage/share/InstallDirTest.java#id0 #24942 generic-loongarch64 -+tools/jpackage/share/jdk/jpackage/tests/VendorTest.java#id1 #24942 generic-loongarch64 -+tools/jpackage/share/MultiLauncherTwoPhaseTest.java #24942 generic-loongarch64 -+tools/jpackage/share/MultiNameTwoPhaseTest.java #24942 generic-loongarch64 -+tools/jpackage/share/RuntimePackageTest.java#id0 #24942 generic-loongarch64 -+tools/jpackage/share/SimplePackageTest.java #24942 generic-loongarch64 -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/test/jdk/ProblemList-Xcomp.txt jdk11u-ls/test/jdk/ProblemList-Xcomp.txt ---- openjdk/test/jdk/ProblemList-Xcomp.txt 2022-10-12 23:00:05.000000000 +0800 -+++ jdk11u-ls/test/jdk/ProblemList-Xcomp.txt 2023-09-12 13:54:29.105579220 +0800 -@@ -21,6 +21,12 @@ - # questions. - # + // public Public_PublicInterface c6 = new Public_PublicInterface(); +- test("" + holder.c6, idx++, "(Lp1/Public_PublicInterface;)Ljava/lang/String;"); ++ test("" + holder.c6, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); -+# -+# This file has been modified by Loongson Technology in 2022. These -+# modifications are Copyright (c) 2020, 2022, Loongson Technology, and are made -+# available on the same license terms set forth above. -+# -+ - ############################################################################# - # - # List of quarantined tests for testing in Xcomp mode. -@@ -29,3 +35,70 @@ - - java/lang/invoke/MethodHandles/CatchExceptionTest.java 8146623 generic-all - java/lang/Class/forName/modules/TestDriver.java 8208212 solaris-all -+ -+# loongson added -+com/sun/jndi/ldap/LdapCBPropertiesTest.java generic-mips64el,generic-loongarch64 -+com/sun/net/httpserver/bugs/6725892/Test.java #uos generic-mips64el -+com/sun/net/httpserver/bugs/B6393710.java generic-mips64el -+com/sun/net/httpserver/bugs/B6529200.java generic-mips64el -+com/sun/net/httpserver/Test10.java generic-mips64el -+com/sun/net/httpserver/Test1.java generic-mips64el -+java/lang/annotation/loaderLeak/Main.java generic-all -+java/lang/Thread/UncaughtExceptions.sh generic-mips64el -+java/net/httpclient/MaxStreams.java generic-mips64el,generic-loongarch64 -+java/net/httpclient/ShortRequestBody.java #uos generic-mips64el -+java/net/httpclient/TimeoutOrdering.java generic-mips64el -+java/net/Socket/DeadlockTest.java #uos generic-mips64el -+java/net/Socket/LingerTest.java #uos generic-mips64el -+java/net/Socket/RejectIPv6.java generic-mips64el -+java/rmi/activation/Activatable/forceLogSnapshot/ForceLogSnapshot.java generic-all -+java/rmi/activation/Activatable/nestedActivate/NestedActivate.java generic-all -+java/rmi/server/RMISocketFactory/useSocketFactory/activatable/UseCustomSocketFactory.java generic-all -+java/rmi/server/RMISocketFactory/useSocketFactory/unicast/UseCustomSocketFactory.java generic-all -+java/rmi/server/Unreferenced/leaseCheckInterval/LeaseCheckInterval.java generic-all -+java/rmi/transport/acceptLoop/CloseServerSocketOnTermination.java generic-all -+java/security/Security/ClassLoaderDeadlock/ClassLoaderDeadlock.sh #uos generic-mips64el -+javax/management/monitor/DerivedGaugeMonitorTest.java generic-mips64el,generic-loongarch64 -+javax/management/remote/mandatory/connection/MultiThreadDeadLockTest.java #27495 generic-mips64el,generic-loongarch64 -+javax/management/rete/mandatory/connection/MultiThreadDeadLockTest.java generic-mips64el,generic-loongarch64 -+javax/net/ssl/ServerName/SSLSocketSNISensitive.java generic-mips64el,generic-loongarch64 -+javax/net/ssl/SSLSession/SessionCacheSizeTests.java #uos generic-mips64el -+javax/net/ssl/SSLSession/SessionTimeOutTests.java generic-mips64el,generic-loongarch64 -+javax/net/ssl/Stapling/HttpsUrlConnClient.java generic-mips64el,generic-loongarch64 -+javax/net/ssl/Stapling/SSLEngineWithStapling.java generic-mips64el -+javax/net/ssl/Stapling/SSLSocketWithStapling.java generic-mips64el -+javax/net/ssl/Stapling/StapleEnableProps.java generic-mips64el -+javax/net/ssl/TLSCommon/TestSessionLocalPrincipal.java generic-mips64el -+javax/net/ssl/TLS/TestJSSEClientProtocol.java #uos generic-mips64el -+javax/net/ssl/TLS/TestJSSEServerProtocol.java #uos generic-mips64el -+jdk/jfr/api/consumer/TestRecordedFullStackTrace.java generic-all -+jdk/jfr/api/metadata/eventtype/TestUnloadingEventClass.java generic-all -+jdk/jfr/event/compiler/TestCompilerInlining.java generic-all -+jdk/jfr/event/profiling/TestFullStackTrace.java generic-all -+jdk/security/logging/TestTLSHandshakeLog.java #uos generic-mips64el -+sun/net/InetAddress/nameservice/simple/DefaultCaching.java #uos generic-mips64el -+sun/net/www/http/HttpClient/B8209178.java generic-all -+sun/net/www/protocol/https/HttpsURLConnection/CookieHttpsClientTest.java generic-mips64el,generic-loongarch64 -+sun/net/www/protocol/https/HttpsURLConnection/PostThruProxy.java #uos generic-mips64el -+sun/net/www/protocol/https/HttpsURLConnection/ReadTimeout.java generic-mips64el,generic-loongarch64 -+sun/security/ec/TestEC.java #uos generic-mips64el -+sun/security/krb5/auto/BogusKDC.java #uos generic-mips64el -+sun/security/krb5/auto/NullRenewUntil.java generic-mips64el -+sun/security/krb5/auto/rcache_usemd5.sh #uos generic-mips64el -+sun/security/krb5/auto/RefreshKrb5Config.java #uos generic-mips64el -+sun/security/krb5/auto/ReplayCacheTestProc.java #uos generic-mips64el -+sun/security/krb5/auto/Unreachable.java generic-mips64el -+sun/security/ssl/SSLSocketImpl/SSLSocketBruceForceClose.java generic-mips64el,generic-loongarch64 -+sun/security/ssl/SSLSocketImpl/SSLSocketCloseHang.java generic-all -+sun/security/ssl/Stapling/StatusResponseManager.java generic-mips64el -+sun/security/tools/jarsigner/certpolicy.sh #uos generic-mips64el -+sun/security/tools/jarsigner/checkusage.sh #uos generic-mips64el -+sun/security/tools/jarsigner/concise_jarsigner.sh generic-mips64el -+sun/security/tools/jarsigner/ec.sh #uos generic-mips64el -+sun/security/tools/keytool/selfissued.sh #uos generic-mips64el -+sun/security/tools/keytool/StorePasswordsByShell.sh #uos generic-mips64el -+sun/security/validator/certreplace.sh #uos generic-mips64el -+sun/security/validator/samedn.sh #uos generic-mips64el -+tools/jar/compat/CLICompatibility.java generic-mips64el -+tools/jar/modularJar/Basic.java generic-mips64el -+tools/jar/multiRelease/Basic.java generic-mips64el -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/test/jdk/sun/security/ec/keystore jdk11u-ls/test/jdk/sun/security/ec/keystore ---- openjdk/test/jdk/sun/security/ec/keystore 2022-10-12 23:00:07.000000000 +0800 -+++ jdk11u-ls/test/jdk/sun/security/ec/keystore 2023-09-12 13:54:31.037581648 +0800 -@@ -1,4 +1,4 @@ --vajraԐr00 -+vajraԐr00 - +*oxF?ұ" - bi;=A5WHi1GBYt}u/`gX[:}kū?\gX< m}܁ sܡ݋]`qH:0=Rpեpm)W 9N{$(R# o"'g7"R}&c5kVJxXS?Mr? - 2jz0'2A#WS'2ָ)g7e1 3XٻUi$T.[1(jcXtvQisohjl/=T1I:SM5X/1uO4/h!U4w'gVc6]Q?9Z#DI KSXjxXӟSԩ?/UF0KEM^rJÙL6UĴH"bwڤ;oc๋XTלNܩ5+^GN|f@G7Y1-(!3W>+дm)\sf}92zY!Ed2糵JKx:Δ岶B2ټ*0xX8Cygvajradsaԑ3'00 -+ boWo;>*0xX8Cygsect193r1server-rsa1024ca G=Et0r0 -++*` phjj/L_wm1a%]XAù1S 3zZ܁ Fߛ~p[qZռQ#vT@}JF 캝 -\ 文件尾没有换行符 -+Sun Microsystems, Inc.10U  Java Software10Uvajra.eng.sun.com00,*H80Su)RJ.RqZȄ$ 'u)7a -\ 文件尾没有换行符 -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/test/jdk/sun/security/ec/pkcs12/sect193r1server-rsa1024ca.p12 jdk11u-ls/test/jdk/sun/security/ec/pkcs12/sect193r1server-rsa1024ca.p12 ---- openjdk/test/jdk/sun/security/ec/pkcs12/sect193r1server-rsa1024ca.p12 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/test/jdk/sun/security/ec/pkcs12/sect193r1server-rsa1024ca.p12 2023-09-12 13:54:31.037581648 +0800 -@@ -0,0 +1,10 @@ -+00 *H 00W *H H0D0= *H 0 -+*H  0o5Kx⹇fčS)*jB.~t%Se/> DSch3zlڬ*^TCM;=.eBjdAy2OSO4_X0j)`Uoq.S!uBQ=jУQD f5dP(˸7JJ5) ZQoa7\!H$nLd]($r1 c -+!9K=e44UNbķy:AMN1ׁ2kYUsD:az`8[  ôL wxoknc -+r0؆~5m Y)R,ISD}iR&S7 -+8P[vFqJFzV}(ftğ{jGeрǙ<߈Q/x_tLQEc~ݏAC)@;EԭJɧ*8od߈*ei..i}աނT=?8Y8~^f.dxdkAoL-؆Ϩ 00 *H !00 *H  -+00 -+*H  0:6 -+xl)_{N9}*bw{~JxΛp~L4&ZeP)ÜbWoY&TjoL ⊬F\2bht1h0# *H  16k[n7X&iqΨ0A *H  142sect193r1server-rsa1024ca010!0 +J٠ӈ?AĬg$E]̝8 -\ 文件尾没有换行符 -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/test/jdk/sun/security/ec/SignatureDigestTruncate.java jdk11u-ls/test/jdk/sun/security/ec/SignatureDigestTruncate.java ---- openjdk/test/jdk/sun/security/ec/SignatureDigestTruncate.java 2022-10-12 23:00:07.000000000 +0800 -+++ jdk11u-ls/test/jdk/sun/security/ec/SignatureDigestTruncate.java 2023-09-12 13:54:31.037581648 +0800 -@@ -36,7 +36,7 @@ - * group order. - * @library /test/lib - * @build jdk.test.lib.Convert -- * @run main/othervm SignatureDigestTruncate -+ * @run main SignatureDigestTruncate - */ - public class SignatureDigestTruncate { + // public Public_PrivateInterface1 c7 = new Public_PrivateInterface1(); +- test("" + holder.c7, idx++, "(Lp1/Public_PrivateInterface1;)Ljava/lang/String;"); ++ test("" + holder.c7, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); -@@ -117,12 +117,12 @@ - } + // public Public_PrivateInterface2 c8 = new Public_PrivateInterface2(); +- test("" + holder.c8, idx++, "(Lp1/Public_PrivateInterface2;)Ljava/lang/String;"); ++ test("" + holder.c8, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); - public static void main(String[] args) throws Exception { -- runTest("SHA384withECDSAinP1363Format", "secp256r1", -+ runTest("SHA384withECDSAinP1363Format", "sect283r1", - "abcdef10234567", "010203040506070809", - "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d" + -- "1e1f20212223", -- "d83534beccde787f9a4c6b0408337d9b9ca2e0a0259228526c15cc17a1d6" + -- "4da6b34bf21b3bc4488c591d8ac9c33d93c7c6137e2ab4c503a42da7" + -- "2fe0b6dda4c4"); -+ "1e1f20212223", -+ "01d7544b5d3935216bd45e2f8042537e1e0296a11e0eb96666199281b409" + -+ "42abccd5358a035de8a314d3e6c2a97614daebf5fb1313540eec3f9a3272" + -+ "068aa10922ccae87d255c84c"); - } - } -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/test/jdk/sun/security/ec/TestEC.java jdk11u-ls/test/jdk/sun/security/ec/TestEC.java ---- openjdk/test/jdk/sun/security/ec/TestEC.java 2022-10-12 23:00:07.000000000 +0800 -+++ jdk11u-ls/test/jdk/sun/security/ec/TestEC.java 2023-09-12 13:54:31.037581648 +0800 -@@ -37,8 +37,8 @@ - * @library ../../../java/security/testlibrary - * @library ../../../javax/net/ssl/TLSCommon - * @modules jdk.crypto.cryptoki/sun.security.pkcs11.wrapper -- * @run main/othervm -Djdk.tls.namedGroups="secp256r1" TestEC -- * @run main/othervm/java.security.policy=TestEC.policy -Djdk.tls.namedGroups="secp256r1" TestEC -+ * @run main/othervm -Djdk.tls.namedGroups="secp256r1,sect193r1" TestEC -+ * @run main/othervm/java.security.policy=TestEC.policy -Djdk.tls.namedGroups="secp256r1,sect193r1" TestEC - */ + // ---------------------------------------------------------------------------- - import java.security.NoSuchProviderException; -@@ -48,12 +48,13 @@ - /* - * Leverage the collection of EC tests used by PKCS11 - * -- * NOTE: the following 5 files were copied here from the PKCS11 EC Test area -+ * NOTE: the following 6 files were copied here from the PKCS11 EC Test area - * and must be kept in sync with the originals: - * - * ../pkcs11/ec/p12passwords.txt - * ../pkcs11/ec/certs/sunlabscerts.pem - * ../pkcs11/ec/pkcs12/secp256r1server-secp384r1ca.p12 -+ * ../pkcs11/ec/pkcs12/sect193r1server-rsa1024ca.p12 - * ../pkcs11/sslecc/keystore - * ../pkcs11/sslecc/truststore - */ -@@ -98,26 +99,18 @@ - * The entry point used for each test is its instance method - * called main (not its static method called main). - */ -- System.out.println("TestECDH"); - new TestECDH().main(p); -- System.out.println("TestECDSA"); - new TestECDSA().main(p); -- System.out.println("TestCurves"); - new TestCurves().main(p); -- System.out.println("TestKeyFactory"); - new TestKeyFactory().main(p); -- System.out.println("TestECGenSpec"); - new TestECGenSpec().main(p); -- System.out.println("ReadPKCS12"); - new ReadPKCS12().main(p); -- System.out.println("ReadCertificate"); - new ReadCertificates().main(p); - - // ClientJSSEServerJSSE fails on Solaris 11 when both SunEC and - // SunPKCS11-Solaris providers are enabled. - // Workaround: - // Security.removeProvider("SunPKCS11-Solaris"); -- System.out.println("ClientJSSEServerJSSE"); - new ClientJSSEServerJSSE().main(p); - - long stop = System.currentTimeMillis(); -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/test/jdk/sun/security/pkcs11/ec/pkcs12/sect193r1server-rsa1024ca.p12 jdk11u-ls/test/jdk/sun/security/pkcs11/ec/pkcs12/sect193r1server-rsa1024ca.p12 ---- openjdk/test/jdk/sun/security/pkcs11/ec/pkcs12/sect193r1server-rsa1024ca.p12 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/test/jdk/sun/security/pkcs11/ec/pkcs12/sect193r1server-rsa1024ca.p12 2023-09-12 13:54:31.097581723 +0800 -@@ -0,0 +1,10 @@ -+00 *H 00W *H H0D0= *H 0 -+*H  0o5Kx⹇fčS)*jB.~t%Se/> DSch3zlڬ*^TCM;=.eBjdAy2OSO4_X0j)`Uoq.S!uBQ=jУQD f5dP(˸7JJ5) ZQoa7\!H$nLd]($r1 c -+!9K=e44UNbķy:AMN1ׁ2kYUsD:az`8[  ôL wxoknc -+r0؆~5m Y)R,ISD}iR&S7 -+8P[vFqJFzV}(ftğ{jGeрǙ<߈Q/x_tLQEc~ݏAC)@;EԭJɧ*8od߈*ei..i}աނT=?8Y8~^f.dxdkAoL-؆Ϩ 00 *H !00 *H  -+00 -+*H  0:6 -+xl)_{N9}*bw{~JxΛp~L4&ZeP)ÜbWoY&TjoL ⊬F\2bht1h0# *H  16k[n7X&iqΨ0A *H  142sect193r1server-rsa1024ca010!0 +J٠ӈ?AĬg$E]̝8 -\ 文件尾没有换行符 -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/test/jdk/sun/security/pkcs11/ec/ReadPKCS12.java jdk11u-ls/test/jdk/sun/security/pkcs11/ec/ReadPKCS12.java ---- openjdk/test/jdk/sun/security/pkcs11/ec/ReadPKCS12.java 2022-10-12 23:00:07.000000000 +0800 -+++ jdk11u-ls/test/jdk/sun/security/pkcs11/ec/ReadPKCS12.java 2023-09-12 13:54:31.097581723 +0800 -@@ -29,7 +29,7 @@ - * @library /test/lib .. - * @library ../../../../java/security/testlibrary - * @key randomness -- * @modules jdk.crypto.cryptoki jdk.crypto.ec/sun.security.ec -+ * @modules jdk.crypto.cryptoki - * @run main/othervm ReadPKCS12 - * @run main/othervm ReadPKCS12 sm policy - */ -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/test/jdk/sun/security/pkcs11/ec/TestECDH.java jdk11u-ls/test/jdk/sun/security/pkcs11/ec/TestECDH.java ---- openjdk/test/jdk/sun/security/pkcs11/ec/TestECDH.java 2022-10-12 23:00:07.000000000 +0800 -+++ jdk11u-ls/test/jdk/sun/security/pkcs11/ec/TestECDH.java 2023-09-12 13:54:31.097581723 +0800 -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it -@@ -124,12 +124,9 @@ - return; - } + // public Private_PublicClass[] ac1 = new Private_PublicClass[0]; +- test("" + holder.ac1, idx++, "([Lp1/PublicClass;)Ljava/lang/String;"); ++ test("" + holder.ac1, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); -- if (getSupportedECParameterSpec("secp192r1", p).isPresent()) { -- test(p, pub192a, priv192a, pub192b, priv192b, secret192); -- } -- if (getSupportedECParameterSpec("sect163r1", p).isPresent()) { -- test(p, pub163a, priv163a, pub163b, priv163b, secret163); -- } -+ test(p, pub192a, priv192a, pub192b, priv192b, secret192); -+ test(p, pub163a, priv163a, pub163b, priv163b, secret163); -+ - if (getSupportedECParameterSpec("brainpoolP256r1", p).isPresent()) { - test(p, pubBrainpoolP256r1a, privBrainpoolP256r1a, pubBrainpoolP256r1b, privBrainpoolP256r1b, secretBrainpoolP256r1); - } -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/test/jdk/sun/security/pkcs11/ec/TestECDSA.java jdk11u-ls/test/jdk/sun/security/pkcs11/ec/TestECDSA.java ---- openjdk/test/jdk/sun/security/pkcs11/ec/TestECDSA.java 2022-10-12 23:00:07.000000000 +0800 -+++ jdk11u-ls/test/jdk/sun/security/pkcs11/ec/TestECDSA.java 2023-09-12 13:54:31.097581723 +0800 -@@ -156,14 +156,12 @@ - return; - } + // public Private_PublicInterface[] ac2 = new Private_PublicInterface[0]; +- test("" + holder.ac2, idx++, "([Ljava/lang/Object;)Ljava/lang/String;"); ++ test("" + holder.ac2, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); -- if (getSupportedECParameterSpec("secp192r1", provider).isPresent()) { -+ if (getNSSECC() != ECCState.Basic) { - test(provider, pub192, priv192, sig192); -- } -- if (getSupportedECParameterSpec("sect163r1", provider).isPresent()) { - test(provider, pub163, priv163, sig163); -- } -- if (getSupportedECParameterSpec("sect571r1", provider).isPresent()) { - test(provider, pub571, priv571, sig571); -+ } else { -+ System.out.println("ECC Basic only, skipping 192, 163 and 571."); - } - test(provider, pub521, priv521, sig521); + // public Private_PrivateInterface1[] ac3 = new Private_PrivateInterface1[0]; +- test("" + holder.ac3, idx++, "([Ljava/lang/Object;)Ljava/lang/String;"); ++ test("" + holder.ac3, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/test/jdk/sun/security/pkcs11/ec/TestKeyFactory.java jdk11u-ls/test/jdk/sun/security/pkcs11/ec/TestKeyFactory.java ---- openjdk/test/jdk/sun/security/pkcs11/ec/TestKeyFactory.java 2022-10-12 23:00:07.000000000 +0800 -+++ jdk11u-ls/test/jdk/sun/security/pkcs11/ec/TestKeyFactory.java 2023-09-12 13:54:31.097581723 +0800 -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it -@@ -130,12 +130,17 @@ - System.out.println("Provider does not support EC, skipping"); - return; - } -- int[] keyLengths = {256, 521}; -+ int[] keyLengths = {192, 163, 409, 521}; -+ int len = 0; -+ if (getNSSECC() == ECCState.Basic) { -+ System.out.println("NSS Basic ECC only. Skipping 192, 163, & 409"); -+ len = 3; -+ } - KeyFactory kf = KeyFactory.getInstance("EC", p); -- for (int len : keyLengths) { -- System.out.println("Length " + len); -+ for (; keyLengths.length > len ; len++) { -+ System.out.println("Length "+keyLengths[len]); - KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC", p); -- kpg.initialize(len); -+ kpg.initialize(keyLengths[len]); - KeyPair kp = kpg.generateKeyPair(); - test(kf, kp.getPrivate()); - test(kf, kp.getPublic()); -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/test/jdk/sun/security/pkcs11/PKCS11Test.java jdk11u-ls/test/jdk/sun/security/pkcs11/PKCS11Test.java ---- openjdk/test/jdk/sun/security/pkcs11/PKCS11Test.java 2022-10-12 23:00:06.000000000 +0800 -+++ jdk11u-ls/test/jdk/sun/security/pkcs11/PKCS11Test.java 2023-11-01 09:34:26.881946806 +0800 -@@ -21,6 +21,12 @@ - * questions. - */ + // public Private_PrivateInterface2[] ac4 = new Private_PrivateInterface2[0]; +- test("" + holder.ac4, idx++, "([Ljava/lang/Object;)Ljava/lang/String;"); ++ test("" + holder.ac4, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); -+/* -+ * This file has been modified by Loongson Technology in 2022, These -+ * modifications are Copyright (c) 2021, 2022, Loongson Technology, and are made -+ * available on the same license terms set forth above. -+ */ -+ - // common infrastructure for SunPKCS11 tests + // public Public_PublicClass[] ac5 = new Public_PublicClass[0]; +- test("" + holder.ac5, idx++, "([Lp1/Public_PublicClass;)Ljava/lang/String;"); ++ test("" + holder.ac5, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); - import java.io.BufferedReader; -@@ -732,6 +738,9 @@ - "/usr/lib64/" }); - osMap.put("Linux-ppc64-64", new String[] { "/usr/lib64/" }); - osMap.put("Linux-ppc64le-64", new String[] { "/usr/lib64/" }); -+ osMap.put("Linux-mips64el-64", new String[]{"/usr/lib64/"}); -+ osMap.put("Linux-loongarch64-64", new String[]{"/usr/lib/loongarch64-linux-gnu/", -+ "/usr/lib64/" }); - osMap.put("Linux-s390x-64", new String[] { "/usr/lib64/" }); - osMap.put("Windows-x86-32", new String[] {}); - osMap.put("Windows-amd64-64", new String[] {}); -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/test/jdk/sun/security/pkcs11/sslecc/ClientJSSEServerJSSE.java jdk11u-ls/test/jdk/sun/security/pkcs11/sslecc/ClientJSSEServerJSSE.java ---- openjdk/test/jdk/sun/security/pkcs11/sslecc/ClientJSSEServerJSSE.java 2022-10-12 23:00:07.000000000 +0800 -+++ jdk11u-ls/test/jdk/sun/security/pkcs11/sslecc/ClientJSSEServerJSSE.java 2023-09-12 13:54:31.105581733 +0800 -@@ -34,9 +34,9 @@ - * @library /test/lib .. ../../../../javax/net/ssl/TLSCommon - * @library ../../../../java/security/testlibrary - * @modules jdk.crypto.cryptoki -- * @run main/othervm -Djdk.tls.namedGroups="secp256r1" -+ * @run main/othervm -Djdk.tls.namedGroups="secp256r1,sect193r1" - * ClientJSSEServerJSSE -- * @run main/othervm -Djdk.tls.namedGroups="secp256r1" -+ * @run main/othervm -Djdk.tls.namedGroups="secp256r1,sect193r1" - * ClientJSSEServerJSSE sm policy - */ + // public Public_PublicInterface[] ac6 = new Public_PublicInterface[0]; +- test("" + holder.ac6, idx++, "([Lp1/Public_PublicInterface;)Ljava/lang/String;"); ++ test("" + holder.ac6, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/test/jdk/sun/security/pkcs11/sslecc/keystore jdk11u-ls/test/jdk/sun/security/pkcs11/sslecc/keystore ---- openjdk/test/jdk/sun/security/pkcs11/sslecc/keystore 2022-10-12 23:00:07.000000000 +0800 -+++ jdk11u-ls/test/jdk/sun/security/pkcs11/sslecc/keystore 2023-09-12 13:54:31.105581733 +0800 -@@ -1,4 +1,4 @@ --vajraԐr00 -+vajraԐr00 - +*oxF?ұ" - bi;=A5WHi1GBYt}u/`gX[:}kū?\gX< m}܁ sܡ݋]`qH:0=Rpեpm)W 9N{$(R# o"'g7"R}&c5kVJxXS?Mr? - 2jz0'2A#WS'2ָ)g7e1 3XٻUi$T.[1(jcXtvQisohjl/=T1I:SM5X/1uO4/h!U4w'gVc6]Q?9Z#DI KSXjxXӟSԩ?/UF0KEM^rJÙL6UĴH"bwڤ;oc๋XTלNܩ5+^GN|f@G7Y1-(!3W>+дm)\sf}92zY!Ed2糵JKx:Δ岶B2ټ*0xX8Cygvajradsaԑ3'00 -+ boWo;>*0xX8Cygsect193r1server-rsa1024ca G=Et0r0 -++*` phjj/L_wm1a%]XAù1S 3zZ܁ Fߛ~p[qZռQ#vT@}JF 캝 -\ 文件尾没有换行符 -+Sun Microsystems, Inc.10U  Java Software10Uvajra.eng.sun.com00,*H80Su)RJ.RqZȄ$ 'u)7a -\ 文件尾没有换行符 -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/test/jdk/sun/security/provider/KeyStore/DKSTest.java jdk11u-ls/test/jdk/sun/security/provider/KeyStore/DKSTest.java ---- openjdk/test/jdk/sun/security/provider/KeyStore/DKSTest.java 2022-10-12 23:00:07.000000000 +0800 -+++ jdk11u-ls/test/jdk/sun/security/provider/KeyStore/DKSTest.java 2023-09-12 13:54:31.113581744 +0800 -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it -@@ -52,6 +52,8 @@ - new KeyStore.PasswordProtection("test12".toCharArray())); - put("eckeystore1", - new KeyStore.PasswordProtection("password".toCharArray())); -+ put("eckeystore2", -+ new KeyStore.PasswordProtection("password".toCharArray())); - put("truststore", - new KeyStore.PasswordProtection("changeit".toCharArray())); - put("empty", -@@ -67,6 +69,8 @@ - new KeyStore.PasswordProtection("wrong".toCharArray())); - put("eckeystore1", - new KeyStore.PasswordProtection("wrong".toCharArray())); -+ put("eckeystore2", -+ new KeyStore.PasswordProtection("wrong".toCharArray())); - }}; + // public Public_PrivateInterface1[] ac7 = new Public_PrivateInterface1[0]; +- test("" + holder.ac7, idx++, "([Lp1/Public_PrivateInterface1;)Ljava/lang/String;"); ++ test("" + holder.ac7, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); - public static void main(String[] args) throws Exception { -@@ -150,7 +154,7 @@ - * domain keystore: keystores - */ - config = new URI(CONFIG + "#keystores"); -- expected = 2 + 1 + 1; -+ expected = 2 + 1 + 1 + 1; - keystore = KeyStore.getInstance("DKS"); - // load entries - keystore.load(new DomainLoadStoreParameter(config, PASSWORDS)); -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/test/jdk/sun/security/provider/KeyStore/domains.cfg jdk11u-ls/test/jdk/sun/security/provider/KeyStore/domains.cfg ---- openjdk/test/jdk/sun/security/provider/KeyStore/domains.cfg 2022-10-12 23:00:07.000000000 +0800 -+++ jdk11u-ls/test/jdk/sun/security/provider/KeyStore/domains.cfg 2023-09-12 13:54:31.113581744 +0800 -@@ -25,6 +25,8 @@ - keystoreType="CaseExactJKS" - keystoreURI="${test.src}/pw.jks"; - keystore eckeystore1 -+ keystoreURI="${test.src}/../../pkcs11/ec/pkcs12/sect193r1server-rsa1024ca.p12"; -+ keystore eckeystore2 - keystoreURI="${test.src}/../../pkcs11/ec/pkcs12/secp256r1server-secp384r1ca.p12"; - }; + // public Public_PrivateInterface2[] ac8 = new Public_PrivateInterface2[0]; +- test("" + holder.ac8, idx++, "([Lp1/Public_PrivateInterface2;)Ljava/lang/String;"); ++ test("" + holder.ac8, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); -@@ -38,6 +40,8 @@ - keystoreType="CaseExactJKS" - keystoreURI="${user.dir}/pw.jks_tmp"; - keystore eckeystore1 -+ keystoreURI="${user.dir}/sect193r1server-rsa1024ca.p12_tmp"; -+ keystore eckeystore2 - keystoreURI="${user.dir}/secp256r1server-secp384r1ca.p12_tmp"; - }; + // ---------------------------------------------------------------------------- -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/test/jdk/sun/security/ssl/CipherSuite/DisabledCurve.java jdk11u-ls/test/jdk/sun/security/ssl/CipherSuite/DisabledCurve.java ---- openjdk/test/jdk/sun/security/ssl/CipherSuite/DisabledCurve.java 2022-10-12 23:00:07.000000000 +0800 -+++ jdk11u-ls/test/jdk/sun/security/ssl/CipherSuite/DisabledCurve.java 2023-09-12 13:54:31.145581784 +0800 -@@ -25,10 +25,10 @@ - * @test - * @bug 8246330 - * @library /javax/net/ssl/templates /test/lib -- * @run main/othervm -Djdk.tls.namedGroups="secp384r1" -+ * @run main/othervm -Djdk.tls.namedGroups="sect283r1" - DisabledCurve DISABLE_NONE PASS -- * @run main/othervm -Djdk.tls.namedGroups="secp384r1" -- DisabledCurve secp384r1 FAIL -+ * @run main/othervm -Djdk.tls.namedGroups="sect283r1" -+ DisabledCurve sect283r1 FAIL - */ - import java.security.Security; - import java.util.Arrays; -@@ -51,18 +51,18 @@ - protected SSLContext createClientSSLContext() throws Exception { - return createSSLContext( - new SSLSocketTemplate.Cert[] { -- SSLSocketTemplate.Cert.CA_ECDSA_SECP384R1 }, -+ SSLSocketTemplate.Cert.CA_ECDSA_SECT283R1 }, - new SSLSocketTemplate.Cert[] { -- SSLSocketTemplate.Cert.EE_ECDSA_SECP384R1 }, -+ SSLSocketTemplate.Cert.EE_ECDSA_SECT283R1 }, - getClientContextParameters()); - } - - protected SSLContext createServerSSLContext() throws Exception { - return createSSLContext( - new SSLSocketTemplate.Cert[] { -- SSLSocketTemplate.Cert.CA_ECDSA_SECP384R1 }, -+ SSLSocketTemplate.Cert.CA_ECDSA_SECT283R1 }, - new SSLSocketTemplate.Cert[] { -- SSLSocketTemplate.Cert.EE_ECDSA_SECP384R1 }, -+ SSLSocketTemplate.Cert.EE_ECDSA_SECT283R1 }, - getServerContextParameters()); - } - -@@ -91,13 +91,10 @@ - public static void main(String[] args) throws Exception { - String expected = args[1]; - String disabledName = ("DISABLE_NONE".equals(args[0]) ? "" : args[0]); -- boolean disabled = false; - if (disabledName.equals("")) { - Security.setProperty("jdk.disabled.namedCurves", ""); -- } else { -- disabled = true; -- Security.setProperty("jdk.certpath.disabledAlgorithms", "secp384r1"); - } -+ System.setProperty("jdk.sunec.disableNative", "false"); - - // Re-enable TLSv1 and TLSv1.1 since test depends on it. - SecurityUtils.removeFromDisabledTlsAlgs("TLSv1", "TLSv1.1"); -@@ -107,10 +104,12 @@ - (new DisabledCurve()).run(); - if (expected.equals("FAIL")) { - throw new RuntimeException( -- "Expected test to fail, but it passed"); -+ "The test case should not reach here"); - } - } catch (SSLException | IllegalStateException ssle) { -- if (expected.equals("FAIL") && disabled) { -+ if ((expected.equals("FAIL")) -+ && Security.getProperty("jdk.disabled.namedCurves") -+ .contains(disabledName)) { - System.out.println( - "Expected exception was thrown: TEST PASSED"); - } else { -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/test/jdk/sun/security/tools/jarsigner/RestrictedAlgo.java jdk11u-ls/test/jdk/sun/security/tools/jarsigner/RestrictedAlgo.java ---- openjdk/test/jdk/sun/security/tools/jarsigner/RestrictedAlgo.java 2022-10-12 23:00:07.000000000 +0800 -+++ jdk11u-ls/test/jdk/sun/security/tools/jarsigner/RestrictedAlgo.java 2023-09-12 13:54:31.185581834 +0800 -@@ -93,6 +93,11 @@ - System.out.println("\nTesting DSA Keysize: DSA keySize < 1024\n"); - test("DSA", "SHA256withDSA", "KeySizeDSA", "SHA-256", true, - "-keysize", "512"); -+ -+ System.out.println("\nTesting Native Curve:" -+ + " include jdk.disabled.namedCurves\n"); -+ test("EC", "SHA256withECDSA", "curve", "SHA-256", true, -+ "-groupname", "secp112r1"); - } - - private static void test(String keyAlg, String sigAlg, String aliasPrefix, -@@ -118,7 +123,8 @@ - "-ext", "bc:c", - "-keyalg", keyAlg, - "-sigalg", sigAlg, -- "-alias", alias); -+ "-alias", alias, -+ "-J-Djdk.sunec.disableNative=false"); - for (String additionalCMDArg : additionalCmdArgs) { - cmd.add(additionalCMDArg); - } -@@ -141,7 +147,8 @@ - "-digestalg", digestAlg, - "-signedjar", SIGNED_JARFILE, - UNSIGNED_JARFILE, -- alias); -+ alias, -+ "-J-Djdk.sunec.disableNative=false"); - - OutputAnalyzer analyzer = SecurityTools.jarsigner(cmd) - .shouldHaveExitValue(0); -@@ -155,7 +162,8 @@ - System.out.println("\nTesting JarSigner Verification\n"); - List cmd = prepareCommand( - "-verify", -- SIGNED_JARFILE); -+ SIGNED_JARFILE, -+ "-J-Djdk.sunec.disableNative=false"); - - OutputAnalyzer analyzer = SecurityTools.jarsigner(cmd) - .shouldHaveExitValue(0); -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/test/jdk/sun/security/tools/keytool/fakegen/DefaultSignatureAlgorithm.java jdk11u-ls/test/jdk/sun/security/tools/keytool/fakegen/DefaultSignatureAlgorithm.java ---- openjdk/test/jdk/sun/security/tools/keytool/fakegen/DefaultSignatureAlgorithm.java 2022-10-12 23:00:07.000000000 +0800 -+++ jdk11u-ls/test/jdk/sun/security/tools/keytool/fakegen/DefaultSignatureAlgorithm.java 2023-09-12 13:54:31.197581849 +0800 -@@ -60,9 +60,11 @@ - check("DSA", 1024, null, "SHA256withDSA"); - check("DSA", 3072, null, "SHA256withDSA"); - -+ check("EC", 192, null, "SHA256withECDSA"); - check("EC", 384, null, "SHA384withECDSA"); -+ check("EC", 571, null, "SHA512withECDSA"); - -- check("EC", 384, "SHA256withECDSA", "SHA256withECDSA"); -+ check("EC", 571, "SHA256withECDSA", "SHA256withECDSA"); - } - - private static void check(String keyAlg, int keySize, -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/test/jdk/sun/security/tools/keytool/fakegen/jdk.crypto.ec/sun/security/ec/ECKeyPairGenerator.java jdk11u-ls/test/jdk/sun/security/tools/keytool/fakegen/jdk.crypto.ec/sun/security/ec/ECKeyPairGenerator.java ---- openjdk/test/jdk/sun/security/tools/keytool/fakegen/jdk.crypto.ec/sun/security/ec/ECKeyPairGenerator.java 2022-10-12 23:00:07.000000000 +0800 -+++ jdk11u-ls/test/jdk/sun/security/tools/keytool/fakegen/jdk.crypto.ec/sun/security/ec/ECKeyPairGenerator.java 2023-09-12 13:54:31.197581849 +0800 -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2019, 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 -@@ -58,6 +58,14 @@ - public KeyPair generateKeyPair() { - BigInteger s, x, y; - switch (keySize) { -+ case 192: -+ s = new BigInteger("144089953963995451666433763881605261867377" -+ + "0287449914970417"); -+ x = new BigInteger("527580219290493448707803038403444129676461" -+ + "560927008883862"); -+ y = new BigInteger("171489247081620145247240656640887886126295" -+ + "376102134763235"); -+ break; - case 384: - s = new BigInteger("230878276322370828604837367594276033697165" - + "328633328282930557390817326627704675451851870430805" -@@ -69,10 +77,22 @@ - + "792287657810480793861620950159864617021540168828129" - + "97920015041145259782242"); - break; -+ case 571: -+ s = new BigInteger("102950007413729156017516513076331886543538" -+ + "947044937190140406420556321983301533699021909556189" -+ + "150601557539520495361099574425100081169640300555562" -+ + "4280643194744140660275077121"); -+ x = new BigInteger("640598847385582251482893323029655037929442" -+ + "593800810090252942944624854811134311418807076811195" -+ + "132373308708007447666896675761104237802118413642543" -+ + "8277858107132017492037336593"); -+ y = new BigInteger("254271270803422773271985083014247202480077" -+ + "131823713050110789460550383275777195766342550786766" -+ + "080401402424961690914429074822281551140068729472439" -+ + "477216613432839953714415981"); -+ break; - default: -- throw new AssertionError("SunEC ECKeyPairGenerator" + -- "has been patched. Key size " + keySize + -- " is not supported"); -+ throw new AssertionError("Unsupported keysize " + keySize); - } - ECParameterSpec ecParams = ECUtil.getECParameterSpec(null, keySize); - try { -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/test/jdk/sun/security/tools/keytool/GroupName.java jdk11u-ls/test/jdk/sun/security/tools/keytool/GroupName.java ---- openjdk/test/jdk/sun/security/tools/keytool/GroupName.java 2022-10-12 23:00:07.000000000 +0800 -+++ jdk11u-ls/test/jdk/sun/security/tools/keytool/GroupName.java 2023-09-12 13:54:31.193581844 +0800 -@@ -65,9 +65,10 @@ - .shouldNotContain("Specifying -keysize for generating EC keys is deprecated"); - checkCurveName("e", "secp256r1"); - -- kt("-list -v") -+ gen("f", "-keyalg EC -groupname brainpoolP256r1") - .shouldHaveExitValue(0) -- .shouldContain("Subject Public Key Algorithm: 256-bit EC (secp256r1) key"); -+ .shouldNotContain("Specifying -keysize for generating EC keys is deprecated"); -+ checkCurveName("f", "brainpoolP256r1"); - } - - private static void checkCurveName(String a, String name) -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/test/langtools/ProblemList.txt jdk11u-ls/test/langtools/ProblemList.txt ---- openjdk/test/langtools/ProblemList.txt 2022-10-12 23:00:06.000000000 +0800 -+++ jdk11u-ls/test/langtools/ProblemList.txt 2023-09-12 13:54:31.321582005 +0800 -@@ -21,6 +21,12 @@ - # or visit www.oracle.com if you need additional information or have any - # questions. - # -+ -+# -+# This file has been modified by Loongson Technology in 2021. These -+# modifications are Copyright (c) 2019, 2021, Loongson Technology, and are made -+# available on the same license terms set forth above. -+# - ########################################################################### + // public Private_PublicClass[][] aac1 = new Private_PublicClass[0][]; +- test("" + holder.aac1, idx++, "([[Lp1/PublicClass;)Ljava/lang/String;"); ++ test("" + holder.aac1, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); - ########################################################################### -@@ -78,3 +84,4 @@ - # - # jdeps + // public Private_PublicInterface[][] aac2 = new Private_PublicInterface[0][]; +- test("" + holder.aac2, idx++, "([[Ljava/lang/Object;)Ljava/lang/String;"); ++ test("" + holder.aac2, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); -+# loongson added -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/test/langtools/ProblemList-Xcomp.txt jdk11u-ls/test/langtools/ProblemList-Xcomp.txt ---- openjdk/test/langtools/ProblemList-Xcomp.txt 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/test/langtools/ProblemList-Xcomp.txt 2023-09-12 13:54:31.321582005 +0800 -@@ -0,0 +1,35 @@ -+# -+# Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. -+# Copyright (c) 2021, 2022, Loongson Technology. 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. -+# -+ -+############################################################################# -+# loongson added -+jdk/jshell/FailOverExecutionControlTest.java generic-mips64el -+jdk/jshell/JdiBadOptionLaunchExecutionControlTest.java generic-mips64el -+jdk/jshell/JdiFailingLaunchExecutionControlTest.java generic-mips64el -+jdk/jshell/JdiFailingListenExecutionControlTest.java generic-mips64el -+jdk/jshell/JdiHangingLaunchExecutionControlTest.java generic-mips64el,generic-loongarch64 -+tools/javac/completionDeps/DepsAndAnno.java #error generic-mips64el -+tools/javac/Paths/Class-Path.sh #error generic-mips64el -+tools/javac/Paths/Diagnostics.sh #error generic-mips64el -+tools/javac/Paths/wcMineField.sh #error generic-mips64el -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/test/langtools/tools/javadoc/api/basic/taglets/UnderlineTaglet.java jdk11u-ls/test/langtools/tools/javadoc/api/basic/taglets/UnderlineTaglet.java ---- openjdk/test/langtools/tools/javadoc/api/basic/taglets/UnderlineTaglet.java 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/test/langtools/tools/javadoc/api/basic/taglets/UnderlineTaglet.java 2023-09-12 13:54:31.901582734 +0800 + // public Private_PrivateInterface1[][] aac3 = new Private_PrivateInterface1[0][]; +- test("" + holder.aac3, idx++, "([[Ljava/lang/Object;)Ljava/lang/String;"); ++ test("" + holder.aac3, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); + + // public Private_PrivateInterface2[][] aac4 = new Private_PrivateInterface2[0][]; +- test("" + holder.aac4, idx++, "([[Ljava/lang/Object;)Ljava/lang/String;"); ++ test("" + holder.aac4, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); + + // public Public_PublicClass[][] aac5 = new Public_PublicClass[0][]; +- test("" + holder.aac5, idx++, "([[Lp1/Public_PublicClass;)Ljava/lang/String;"); ++ test("" + holder.aac5, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); + + // public Public_PublicInterface[][] aac6 = new Public_PublicInterface[0][]; +- test("" + holder.aac6, idx++, "([[Lp1/Public_PublicInterface;)Ljava/lang/String;"); ++ test("" + holder.aac6, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); + + // public Public_PrivateInterface1[][] aac7 = new Public_PrivateInterface1[0][]; +- test("" + holder.aac7, idx++, "([[Lp1/Public_PrivateInterface1;)Ljava/lang/String;"); ++ test("" + holder.aac7, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); + + // public Public_PrivateInterface2[][] aac8 = new Public_PrivateInterface2[0][]; +- test("" + holder.aac8, idx++, "([[Lp1/Public_PrivateInterface2;)Ljava/lang/String;"); ++ test("" + holder.aac8, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); + + // ---------------------------------------------------------------------------- + + // public PublicInterface i1 = new Private_PublicInterface(); +- test("" + holder.i1, idx++, "(Lp1/PublicInterface;)Ljava/lang/String;"); ++ test("" + holder.i1, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); + + // public PrivateInterface1 i2 = new Private_PrivateInterface1(); +- test("" + holder.i2, idx++, "(Ljava/lang/Object;)Ljava/lang/String;"); ++ test("" + holder.i2, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); + + // public PrivateInterface2 i3 = new Private_PrivateInterface2(); +- test("" + holder.i3, idx++, "(Ljava/lang/Object;)Ljava/lang/String;"); ++ test("" + holder.i3, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); + + // public PublicInterface[] ai1 = new Private_PublicInterface[0]; +- test("" + holder.ai1, idx++, "([Lp1/PublicInterface;)Ljava/lang/String;"); ++ test("" + holder.ai1, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); + + // public PrivateInterface1[] ai2 = new Private_PrivateInterface1[0]; +- test("" + holder.ai2, idx++, "([Ljava/lang/Object;)Ljava/lang/String;"); ++ test("" + holder.ai2, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); + + // public PrivateInterface2[] ai3 = new Private_PrivateInterface2[0]; +- test("" + holder.ai3, idx++, "([Ljava/lang/Object;)Ljava/lang/String;"); ++ test("" + holder.ai3, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); + + // public PublicInterface[][] aai1 = new Private_PublicInterface[0][]; +- test("" + holder.aai1, idx++, "([[Lp1/PublicInterface;)Ljava/lang/String;"); ++ test("" + holder.aai1, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); + + // public PrivateInterface1[][] aai2 = new Private_PrivateInterface1[0][]; +- test("" + holder.aai2, idx++, "([[Ljava/lang/Object;)Ljava/lang/String;"); ++ test("" + holder.aai2, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); + + // public PrivateInterface2[][] aai3 = new Private_PrivateInterface2[0][]; +- test("" + holder.aai3, idx++, "([[Ljava/lang/Object;)Ljava/lang/String;"); ++ test("" + holder.aai3, idx++, "(Ljava/lang/String;)Ljava/lang/String;"); + + } + +diff --git a/test/langtools/tools/javadoc/api/basic/taglets/UnderlineTaglet.java b/test/langtools/tools/javadoc/api/basic/taglets/UnderlineTaglet.java +new file mode 100644 +index 000000000..426b0db85 +--- /dev/null ++++ b/test/langtools/tools/javadoc/api/basic/taglets/UnderlineTaglet.java @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. @@ -122357,9 +211863,93 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/test/langtools/tools/javad + } +} + -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/test/lib/jdk/test/lib/Platform.java jdk11u-ls/test/lib/jdk/test/lib/Platform.java ---- openjdk/test/lib/jdk/test/lib/Platform.java 2022-10-12 23:00:07.000000000 +0800 -+++ jdk11u-ls/test/lib/jdk/test/lib/Platform.java 2023-11-01 09:34:27.001946939 +0800 +diff --git a/test/lib-test/jdk/test/lib/util/JarUtilsTest.java b/test/lib-test/jdk/test/lib/util/JarUtilsTest.java +new file mode 100644 +index 000000000..eb9dced32 +--- /dev/null ++++ b/test/lib-test/jdk/test/lib/util/JarUtilsTest.java +@@ -0,0 +1,77 @@ ++/* ++ * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. ++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. ++ * ++ * This code is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 only, as ++ * published by the Free Software Foundation. ++ * ++ * This code is distributed in the hope that it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * version 2 for more details (a copy is included in the LICENSE file that ++ * accompanied this code). ++ * ++ * You should have received a copy of the GNU General Public License version ++ * 2 along with this work; if not, write to the Free Software Foundation, ++ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA ++ * or visit www.oracle.com if you need additional information or have any ++ * questions. ++ */ ++ ++/* @test ++ * @bug 8309841 ++ * @summary Unit Test for a common Test API in jdk.test.lib.util.JarUtils ++ * @library /test/lib ++ */ ++ ++import jdk.test.lib.Asserts; ++import jdk.test.lib.util.JarUtils; ++ ++import java.io.IOException; ++import java.nio.file.Files; ++import java.nio.file.Path; ++import java.util.Set; ++import java.util.jar.JarEntry; ++import java.util.jar.JarFile; ++import java.util.stream.Collectors; ++ ++public class JarUtilsTest { ++ public static void main(String[] args) throws Exception { ++ Files.createDirectory(Path.of("bx")); ++ JarUtils.createJarFile(Path.of("a.jar"), ++ Path.of("."), ++ Files.writeString(Path.of("a"), ""), ++ Files.writeString(Path.of("b1"), ""), ++ Files.writeString(Path.of("b2"), ""), ++ Files.writeString(Path.of("bx/x"), ""), ++ Files.writeString(Path.of("c"), ""), ++ Files.writeString(Path.of("e1"), ""), ++ Files.writeString(Path.of("e2"), "")); ++ checkContent("a", "b1", "b2", "bx/x", "c", "e1", "e2"); ++ ++ JarUtils.deleteEntries(Path.of("a.jar"), "a"); ++ checkContent("b1", "b2", "bx/x", "c", "e1", "e2"); ++ ++ // Note: b* covers everything starting with b, even bx/x ++ JarUtils.deleteEntries(Path.of("a.jar"), "b*"); ++ checkContent("c", "e1", "e2"); ++ ++ // d* does not match ++ JarUtils.deleteEntries(Path.of("a.jar"), "d*"); ++ checkContent("c", "e1", "e2"); ++ ++ // multiple patterns ++ JarUtils.deleteEntries(Path.of("a.jar"), "d*", "e*"); ++ checkContent("c"); ++ } ++ ++ static void checkContent(String... expected) throws IOException { ++ try (var jf = new JarFile("a.jar")) { ++ Asserts.assertEquals(Set.of(expected), ++ jf.stream().map(JarEntry::getName).collect(Collectors.toSet())); ++ } ++ } ++} +diff --git a/test/lib/jdk/test/lib/Platform.java b/test/lib/jdk/test/lib/Platform.java +index 6269373c2..440ec4664 100644 +--- a/test/lib/jdk/test/lib/Platform.java ++++ b/test/lib/jdk/test/lib/Platform.java @@ -21,6 +21,12 @@ * questions. */ @@ -122372,8 +211962,8 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/test/lib/jdk/test/lib/Plat + package jdk.test.lib; - import java.io.FileNotFoundException; -@@ -225,6 +231,14 @@ + import java.io.BufferedReader; +@@ -229,6 +235,14 @@ public class Platform { return isArch("(i386)|(x86(?!_64))"); } @@ -122388,9 +211978,187 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/test/lib/jdk/test/lib/Plat public static String getOsArch() { return osArch; } -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/test/micro/org/openjdk/bench/java/lang/RotateBenchmark.java jdk11u-ls/test/micro/org/openjdk/bench/java/lang/RotateBenchmark.java ---- openjdk/test/micro/org/openjdk/bench/java/lang/RotateBenchmark.java 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/test/micro/org/openjdk/bench/java/lang/RotateBenchmark.java 2023-09-12 13:54:31.981582834 +0800 +diff --git a/test/lib/jdk/test/lib/process/ProcessTools.java b/test/lib/jdk/test/lib/process/ProcessTools.java +index 8a8e80436..9e3da6590 100644 +--- a/test/lib/jdk/test/lib/process/ProcessTools.java ++++ b/test/lib/jdk/test/lib/process/ProcessTools.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2013, 2024, 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 +@@ -453,7 +453,7 @@ public final class ProcessTools { + * @param cmds The command line to execute. + * @return The output from the process. + */ +- public static OutputAnalyzer executeProcess(String... cmds) throws Throwable { ++ public static OutputAnalyzer executeProcess(String... cmds) throws Exception { + return executeProcess(new ProcessBuilder(cmds)); + } + +@@ -498,8 +498,7 @@ public final class ProcessTools { + * @param cmds The command line to execute. + * @return The {@linkplain OutputAnalyzer} instance wrapping the process. + */ +- public static OutputAnalyzer executeCommand(String... cmds) +- throws Throwable { ++ public static OutputAnalyzer executeCommand(String... cmds) throws Exception { + String cmdLine = String.join(" ", cmds); + System.out.println("Command line: [" + cmdLine + "]"); + OutputAnalyzer analyzer = ProcessTools.executeProcess(cmds); +@@ -516,8 +515,7 @@ public final class ProcessTools { + * @param pb The ProcessBuilder to execute. + * @return The {@linkplain OutputAnalyzer} instance wrapping the process. + */ +- public static OutputAnalyzer executeCommand(ProcessBuilder pb) +- throws Throwable { ++ public static OutputAnalyzer executeCommand(ProcessBuilder pb) throws Exception { + String cmdLine = pb.command().stream() + .map(x -> (x.contains(" ") || x.contains("$")) + ? ("'" + x + "'") : x) +diff --git a/test/lib/jdk/test/lib/util/JarUtils.java b/test/lib/jdk/test/lib/util/JarUtils.java +index b1cc74f52..7a50e0bd4 100644 +--- a/test/lib/jdk/test/lib/util/JarUtils.java ++++ b/test/lib/jdk/test/lib/util/JarUtils.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2015, 2024, 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 +@@ -318,6 +318,57 @@ public final class JarUtils { + updateJar(src, dest, Map.of(JarFile.MANIFEST_NAME, bout.toByteArray())); + } + ++ /** ++ * Remove entries from a ZIP file. ++ * ++ * Each entry can be a name or a name ending with "*". ++ * ++ * @return number of removed entries ++ * @throws IOException if there is any I/O error ++ */ ++ public static int deleteEntries(Path jarfile, String... patterns) ++ throws IOException { ++ Path tmpfile = Files.createTempFile("jar", "jar"); ++ int count = 0; ++ ++ try (OutputStream out = Files.newOutputStream(tmpfile); ++ JarOutputStream jos = new JarOutputStream(out)) { ++ try (JarFile jf = new JarFile(jarfile.toString())) { ++ Enumeration jentries = jf.entries(); ++ top: while (jentries.hasMoreElements()) { ++ JarEntry jentry = jentries.nextElement(); ++ String name = jentry.getName(); ++ for (String pattern : patterns) { ++ if (pattern.endsWith("*")) { ++ if (name.startsWith(pattern.substring( ++ 0, pattern.length() - 1))) { ++ // Go directly to next entry. This ++ // one is not written into `jos` and ++ // therefore removed. ++ count++; ++ continue top; ++ } ++ } else { ++ if (name.equals(pattern)) { ++ // Same as above ++ count++; ++ continue top; ++ } ++ } ++ } ++ // No pattern matched, file retained ++ jos.putNextEntry(copyEntry(jentry)); ++ jf.getInputStream(jentry).transferTo(jos); ++ } ++ } ++ } ++ ++ // replace the original JAR file ++ Files.move(tmpfile, jarfile, StandardCopyOption.REPLACE_EXISTING); ++ ++ return count; ++ } ++ + private static void updateEntry(JarOutputStream jos, String name, Object content) + throws IOException { + if (content instanceof Boolean) { +diff --git a/test/make/TestMakeBase.gmk b/test/make/TestMakeBase.gmk +index ccd0a89cd..953bae328 100644 +--- a/test/make/TestMakeBase.gmk ++++ b/test/make/TestMakeBase.gmk +@@ -158,6 +158,62 @@ ifneq ($(READ_WRITE_VALUE), $(READ_WRITE_RESULT)) + $(error Expected: >$(READ_WRITE_VALUE)< - Result: >$(READ_WRITE_RESULT)<) + endif + ++TEST_STRING_1 := 1234 ++TEST_STRING_2 := 1234$(NEWLINE) ++TEST_STRING_3 := 1234$(NEWLINE)$(NEWLINE) ++ ++# Writing a string ending in newline should not add a newline, but if it does ++# not, a newline should be added. We check this by verifying that the size of the ++# file is 5 characters for both test strings. ++TEST_FILE_1 := $(OUTPUT_DIR)/write-file-1 ++TEST_FILE_2 := $(OUTPUT_DIR)/write-file-2 ++TEST_FILE_3 := $(OUTPUT_DIR)/write-file-3 ++ ++$(call WriteFile, $(TEST_STRING_1), $(TEST_FILE_1)) ++$(call WriteFile, $(TEST_STRING_2), $(TEST_FILE_2)) ++$(call WriteFile, $(TEST_STRING_3), $(TEST_FILE_3)) ++ ++TEST_FILE_1_SIZE := $(strip $(shell $(WC) -c < $(TEST_FILE_1))) ++TEST_FILE_2_SIZE := $(strip $(shell $(WC) -c < $(TEST_FILE_2))) ++TEST_FILE_3_SIZE := $(strip $(shell $(WC) -c < $(TEST_FILE_3))) ++ ++ifneq ($(TEST_FILE_1_SIZE), 5) ++ $(error Expected file size 5 for WriteFile 1, got $(TEST_FILE_1_SIZE)) ++endif ++ifneq ($(TEST_FILE_2_SIZE), 5) ++ $(error Expected file size 5 for WriteFile 2, got $(TEST_FILE_2_SIZE)) ++endif ++ifneq ($(TEST_FILE_3_SIZE), 5) ++ $(error Expected file size 5 for WriteFile 3, got $(TEST_FILE_3_SIZE)) ++endif ++ ++# Also test append (assumes WriteFile works as expected) ++$(call WriteFile, $(TEST_STRING_1), $(TEST_FILE_1)) ++$(call AppendFile, $(TEST_STRING_1), $(TEST_FILE_1)) ++$(call AppendFile, $(TEST_STRING_1), $(TEST_FILE_1)) ++ ++$(call WriteFile, $(TEST_STRING_2), $(TEST_FILE_2)) ++$(call AppendFile, $(TEST_STRING_2), $(TEST_FILE_2)) ++$(call AppendFile, $(TEST_STRING_2), $(TEST_FILE_2)) ++ ++$(call WriteFile, $(TEST_STRING_3), $(TEST_FILE_3)) ++$(call AppendFile, $(TEST_STRING_3), $(TEST_FILE_3)) ++$(call AppendFile, $(TEST_STRING_3), $(TEST_FILE_3)) ++ ++TEST_FILE_1_SIZE := $(strip $(shell $(WC) -c < $(TEST_FILE_1))) ++TEST_FILE_2_SIZE := $(strip $(shell $(WC) -c < $(TEST_FILE_2))) ++TEST_FILE_3_SIZE := $(strip $(shell $(WC) -c < $(TEST_FILE_3))) ++ ++ifneq ($(TEST_FILE_1_SIZE), 15) ++ $(error Expected file size 15 for AppendFile 1, got $(TEST_FILE_1_SIZE)) ++endif ++ifneq ($(TEST_FILE_2_SIZE), 15) ++ $(error Expected file size 15 for AppendFile 2, got $(TEST_FILE_2_SIZE)) ++endif ++ifneq ($(TEST_FILE_3_SIZE), 15) ++ $(error Expected file size 15 for AppendFile 3, got $(TEST_FILE_3_SIZE)) ++endif ++ + ################################################################################ + # Test creating dependencies on make variables + +diff --git a/test/micro/org/openjdk/bench/java/lang/RotateBenchmark.java b/test/micro/org/openjdk/bench/java/lang/RotateBenchmark.java +new file mode 100644 +index 000000000..81fd956a4 +--- /dev/null ++++ b/test/micro/org/openjdk/bench/java/lang/RotateBenchmark.java @@ -0,0 +1,87 @@ +// +// Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. @@ -122479,80 +212247,11 @@ diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/test/micro/org/openjdk/ben + } + +} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/test/micro/org/openjdk/bench/loongarch/C2Memory.java jdk11u-ls/test/micro/org/openjdk/bench/loongarch/C2Memory.java ---- openjdk/test/micro/org/openjdk/bench/loongarch/C2Memory.java 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/test/micro/org/openjdk/bench/loongarch/C2Memory.java 2023-09-12 13:54:32.005582864 +0800 -@@ -0,0 +1,67 @@ -+/* -+ * Copyright (c) 2021, Loongson Technology. 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.loongarch; -+ -+import org.openjdk.jmh.annotations.Benchmark; -+ -+public class C2Memory { -+ public static int sum; -+ public static int array1[] = new int[0x8000]; -+ public static int array2[] = new int[0x8000]; -+ -+ @Benchmark -+ public void testMethod() { -+ for (int i = 0; i<10000;i++) { -+ sum = array1[0x7fff] + array2[0x1f0]; -+ array1[0x7fff] += array2[0x1f0]; -+ } -+ } -+ -+ @Benchmark -+ public void testBasePosIndexOffset() { -+ int xstart = 30000; -+ long carry = 63; -+ -+ for (int j=xstart; j >= 0; j--) { -+ array2[j] = array1[xstart]; -+ } -+ -+ array2[xstart] = (int)carry; -+ } -+ -+ public static byte b_array1[] = new byte[0x8000]; -+ public static byte b_array2[] = new byte[0x8000]; -+ -+ @Benchmark -+ public void testBaseIndexOffset() { -+ int xstart = 10000; -+ byte carry = 63; -+ -+ for (int j=xstart; j >= 0; j--) { -+ b_array2[j] = b_array1[xstart]; -+ } -+ -+ b_array2[xstart] = carry; -+ } -+} -diff -x '.git*' -x .jcheck -x .workflow -Naur openjdk/test/micro/org/openjdk/bench/vm/compiler/MacroLogicOpt.java jdk11u-ls/test/micro/org/openjdk/bench/vm/compiler/MacroLogicOpt.java ---- openjdk/test/micro/org/openjdk/bench/vm/compiler/MacroLogicOpt.java 1970-01-01 08:00:00.000000000 +0800 -+++ jdk11u-ls/test/micro/org/openjdk/bench/vm/compiler/MacroLogicOpt.java 2023-09-12 13:54:32.009582869 +0800 +diff --git a/test/micro/org/openjdk/bench/vm/compiler/MacroLogicOpt.java b/test/micro/org/openjdk/bench/vm/compiler/MacroLogicOpt.java +new file mode 100644 +index 000000000..58400cadf +--- /dev/null ++++ b/test/micro/org/openjdk/bench/vm/compiler/MacroLogicOpt.java @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. diff --git a/rh1750419-redhat_alt_java.patch b/rh1750419-redhat_alt_java.patch index e6355f2..37d600a 100644 --- a/rh1750419-redhat_alt_java.patch +++ b/rh1750419-redhat_alt_java.patch @@ -1,7 +1,8 @@ -diff -r 1356affa5e44 make/launcher/Launcher-java.base.gmk ---- openjdk/make/launcher/Launcher-java.base.gmk Wed Nov 25 08:27:15 2020 +0100 -+++ openjdk/make/launcher/Launcher-java.base.gmk Tue Dec 01 12:29:30 2020 +0100 -@@ -41,6 +41,16 @@ +diff --git openjdk.orig/make/launcher/Launcher-java.base.gmk openjdk/make/launcher/Launcher-java.base.gmk +index a8990dd0ef..320fec6e51 100644 +--- openjdk.orig/make/launcher/Launcher-java.base.gmk ++++ openjdk/make/launcher/Launcher-java.base.gmk +@@ -41,6 +41,16 @@ $(eval $(call SetupBuildLauncher, java, \ OPTIMIZATION := HIGH, \ )) @@ -15,13 +16,14 @@ diff -r 1356affa5e44 make/launcher/Launcher-java.base.gmk + OPTIMIZATION := HIGH, \ +)) + - ifeq ($(OPENJDK_TARGET_OS), windows) + ifeq ($(call isTargetOs, windows), true) $(eval $(call SetupBuildLauncher, javaw, \ CFLAGS := -DJAVAW -DEXPAND_CLASSPATH_WILDCARDS -DENABLE_ARG_FILES, \ - -diff -r 25e94aa812b2 src/share/bin/alt_main.h ---- /dev/null Thu Jan 01 00:00:00 1970 +0000 -+++ openjdk/src/java.base/share/native/launcher/alt_main.h Tue Jun 02 17:15:28 2020 +0100 +diff --git openjdk.orig/src/java.base/share/native/launcher/alt_main.h openjdk/src/java.base/share/native/launcher/alt_main.h +new file mode 100644 +index 0000000000..697df2898a +--- /dev/null ++++ openjdk/src/java.base/share/native/launcher/alt_main.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2019, Red Hat, Inc. All rights reserved. @@ -96,9 +98,10 @@ diff -r 25e94aa812b2 src/share/bin/alt_main.h +} + +#endif // REDHAT_ALT_JAVA -diff -r 25e94aa812b2 src/share/bin/main.c ---- openjdk/src/java.base/share/native/launcher/main.c Wed Feb 05 12:20:36 2020 -0300 -+++ openjdk/src/java.base/share/native/launcher/main.c Tue Jun 02 17:15:28 2020 +0100 +diff --git openjdk.orig/src/java.base/share/native/launcher/main.c openjdk/src/java.base/share/native/launcher/main.c +index b734fe2ba7..79dc830765 100644 +--- openjdk.orig/src/java.base/share/native/launcher/main.c ++++ openjdk/src/java.base/share/native/launcher/main.c @@ -34,6 +34,14 @@ #include "jli_util.h" #include "jni.h" -- Gitee

    TargetDebian treeDebian arch--openjdk-target=...TargetDebian treeDebian arch--openjdk-target=...--with-jvm-variants=...
    x86busteri386i386-linux-gnux86busteri386i386-linux-gnu(all)
    armbusterarmhfarm-linux-gnueabihfarmbusterarmhfarm-linux-gnueabihf(all)
    aarch64busterarm64aarch64-linux-gnuaarch64busterarm64aarch64-linux-gnu(all)
    ppc64lebusterppc64elpowerpc64le-linux-gnuppc64lebusterppc64elpowerpc64le-linux-gnu(all)
    s390xbusters390xs390x-linux-gnus390xbusters390xs390x-linux-gnu(all)
    mipslebustermipselmipsel-linux-gnumipslebustermipselmipsel-linux-gnuzero
    mips64lebustermips64elmips64el-linux-gnueabi64mips64lebustermips64elmips64el-linux-gnueabi64zero
    armelbusterarmarm-linux-gnueabiarmelbusterarmarm-linux-gnueabizero
    ppcsidpowerpcpowerpc-linux-gnuppcsidpowerpcpowerpc-linux-gnuzero
    ppc64besidppc64powerpc64-linux-gnuppc64besidppc64powerpc64-linux-gnu(all)
    m68ksidm68km68k-linux-gnum68ksidm68km68k-linux-gnuzero
    alphasidalphaalpha-linux-gnualphasidalphaalpha-linux-gnuzero
    sh4sidsh4sh4-linux-gnush4sidsh4sh4-linux-gnuzero