OpenJDK / amber / amber
changeset 54239:760293737af0
Merge
author | psadhukhan |
---|---|
date | Wed, 12 Dec 2018 15:07:56 +0530 |
parents | 818b7bf2af49 ddbd9744a3d5 |
children | 2a39d5fc7e58 |
files | make/scripts/pandoc-manpage-filter.js make/scripts/pandoc-manpage-filter.sh.template src/jdk.internal.le/share/classes/jdk/internal/jline/DefaultTerminal2.java src/jdk.internal.le/share/classes/jdk/internal/jline/NoInterruptUnixTerminal.java src/jdk.internal.le/share/classes/jdk/internal/jline/OSvTerminal.java src/jdk.internal.le/share/classes/jdk/internal/jline/Terminal.java src/jdk.internal.le/share/classes/jdk/internal/jline/Terminal2.java src/jdk.internal.le/share/classes/jdk/internal/jline/TerminalFactory.java src/jdk.internal.le/share/classes/jdk/internal/jline/TerminalSupport.java src/jdk.internal.le/share/classes/jdk/internal/jline/UnixTerminal.java src/jdk.internal.le/share/classes/jdk/internal/jline/UnsupportedTerminal.java src/jdk.internal.le/share/classes/jdk/internal/jline/WindowsTerminal.java src/jdk.internal.le/share/classes/jdk/internal/jline/console/ConsoleKeys.java src/jdk.internal.le/share/classes/jdk/internal/jline/console/ConsoleReader.java src/jdk.internal.le/share/classes/jdk/internal/jline/console/CursorBuffer.java src/jdk.internal.le/share/classes/jdk/internal/jline/console/KeyMap.java src/jdk.internal.le/share/classes/jdk/internal/jline/console/KillRing.java src/jdk.internal.le/share/classes/jdk/internal/jline/console/Operation.java src/jdk.internal.le/share/classes/jdk/internal/jline/console/UserInterruptException.java src/jdk.internal.le/share/classes/jdk/internal/jline/console/WCWidth.java src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/AggregateCompleter.java src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/AnsiStringsCompleter.java src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/ArgumentCompleter.java src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/CandidateListCompletionHandler.java src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/CandidateListCompletionHandler.properties src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/Completer.java src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/CompletionHandler.java src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/EnumCompleter.java src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/FileNameCompleter.java src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/NullCompleter.java src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/StringsCompleter.java src/jdk.internal.le/share/classes/jdk/internal/jline/console/completer/package-info.java src/jdk.internal.le/share/classes/jdk/internal/jline/console/history/FileHistory.java src/jdk.internal.le/share/classes/jdk/internal/jline/console/history/History.java src/jdk.internal.le/share/classes/jdk/internal/jline/console/history/MemoryHistory.java src/jdk.internal.le/share/classes/jdk/internal/jline/console/history/PersistentHistory.java src/jdk.internal.le/share/classes/jdk/internal/jline/console/history/package-info.java src/jdk.internal.le/share/classes/jdk/internal/jline/console/internal/ConsoleReaderInputStream.java src/jdk.internal.le/share/classes/jdk/internal/jline/console/internal/ConsoleRunner.java src/jdk.internal.le/share/classes/jdk/internal/jline/console/package-info.java src/jdk.internal.le/share/classes/jdk/internal/jline/extra/AnsiInterpretingOutputStream.java src/jdk.internal.le/share/classes/jdk/internal/jline/extra/EditingHistory.java src/jdk.internal.le/share/classes/jdk/internal/jline/internal/Ansi.java src/jdk.internal.le/share/classes/jdk/internal/jline/internal/Configuration.java src/jdk.internal.le/share/classes/jdk/internal/jline/internal/Curses.java src/jdk.internal.le/share/classes/jdk/internal/jline/internal/InfoCmp.java src/jdk.internal.le/share/classes/jdk/internal/jline/internal/InputStreamReader.java src/jdk.internal.le/share/classes/jdk/internal/jline/internal/Log.java src/jdk.internal.le/share/classes/jdk/internal/jline/internal/NonBlockingInputStream.java src/jdk.internal.le/share/classes/jdk/internal/jline/internal/Nullable.java src/jdk.internal.le/share/classes/jdk/internal/jline/internal/Preconditions.java src/jdk.internal.le/share/classes/jdk/internal/jline/internal/ShutdownHooks.java src/jdk.internal.le/share/classes/jdk/internal/jline/internal/TerminalLineSettings.java src/jdk.internal.le/share/classes/jdk/internal/jline/internal/TestAccessible.java src/jdk.internal.le/share/classes/jdk/internal/jline/internal/Urls.java src/jdk.internal.le/share/classes/jdk/internal/jline/internal/package-info.java src/jdk.internal.le/share/classes/jdk/internal/jline/package-info.java src/jdk.internal.le/windows/native/lible/WindowsTerminal.cpp src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/UnsafeAccess.java src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/jquery/images/ui-bg_flat_0_aaaaaa_40x100.png src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/jquery/images/ui-bg_flat_75_ffffff_40x100.png src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/jquery/images/ui-bg_glass_65_ffffff_1x400.png test/jdk/jdk/internal/jline/console/StripAnsiTest.java test/jdk/jdk/internal/jline/extra/AnsiInterpretingOutputStreamTest.java test/jdk/jdk/internal/jline/extra/HistoryTest.java |
diffstat | 506 files changed, 40099 insertions(+), 16418 deletions(-) [+] |
line wrap: on
line diff
--- a/doc/building.html Tue Dec 11 14:11:57 2018 +0000 +++ b/doc/building.html Wed Dec 12 15:07:56 2018 +0530 @@ -1,19 +1,24 @@ <!DOCTYPE html> -<html> +<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang=""> <head> - <meta charset="utf-8"> - <meta name="generator" content="pandoc"> - <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes"> + <meta charset="utf-8" /> + <meta name="generator" content="pandoc" /> + <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" /> <title>Building the JDK</title> - <style type="text/css">code{white-space: pre;}</style> - <link rel="stylesheet" href="../make/data/docs-resources/resources/jdk-default.css"> + <style type="text/css"> + code{white-space: pre-wrap;} + span.smallcaps{font-variant: small-caps;} + span.underline{text-decoration: underline;} + div.column{display: inline-block; vertical-align: top; width: 50%;} + </style> + <link rel="stylesheet" href="../make/data/docs-resources/resources/jdk-default.css" /> <!--[if lt IE 9]> <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script> <![endif]--> <style type="text/css">pre, code, tt { color: #1d6ae5; }</style> </head> <body> -<header> +<header id="title-block-header"> <h1 class="title">Building the JDK</h1> </header> <nav id="TOC"> @@ -640,11 +645,13 @@ <p>Note that alsa is needed even if you only want to build a headless JDK.</p> <ul> <li><p>Go to <a href="https://www.debian.org/distrib/packages">Debian Package Search</a> and search for the <code>libasound2</code> and <code>libasound2-dev</code> packages for your <em>target</em> system. Download them to /tmp.</p></li> -<li><p>Install the libraries into the cross-compilation toolchain. For instance:</p> +<li>Install the libraries into the cross-compilation toolchain. For instance:</li> +</ul> <pre><code>cd /tools/gcc-linaro-arm-linux-gnueabihf-raspbian-2012.09-20120921_linux/arm-linux-gnueabihf/libc dpkg-deb -x /tmp/libasound2_1.0.25-4_armhf.deb . -dpkg-deb -x /tmp/libasound2-dev_1.0.25-4_armhf.deb .</code></pre></li> -<li><p>If alsa is not properly detected by <code>configure</code>, you can point it out by <code>--with-alsa</code>.</p></li> +dpkg-deb -x /tmp/libasound2-dev_1.0.25-4_armhf.deb .</code></pre> +<ul> +<li>If alsa is not properly detected by <code>configure</code>, you can point it out by <code>--with-alsa</code>.</li> </ul> <h4 id="x11-1">X11</h4> <p>You will need X11 libraries suitable for your <em>target</em> system. For most cases, using Debian's pre-built libraries work fine.</p> @@ -690,17 +697,21 @@ <p>Fortunately, you can create sysroots for foreign architectures with tools provided by your OS. On Debian/Ubuntu systems, one could use <code>qemu-deboostrap</code> to create the <em>target</em> system chroot, which would have the native libraries and headers specific to that <em>target</em> system. After that, we can use the cross-compiler on the <em>build</em> system, pointing into chroot to get the build dependencies right. This allows building for foreign architectures with native compilation speed.</p> <p>For example, cross-compiling to AArch64 from x86_64 could be done like this:</p> <ul> -<li><p>Install cross-compiler on the <em>build</em> system:</p> -<pre><code>apt install g++-aarch64-linux-gnu gcc-aarch64-linux-gnu</code></pre></li> -<li><p>Create chroot on the <em>build</em> system, configuring it for <em>target</em> system:</p> +<li>Install cross-compiler on the <em>build</em> system:</li> +</ul> +<pre><code>apt install g++-aarch64-linux-gnu gcc-aarch64-linux-gnu</code></pre> +<ul> +<li>Create chroot on the <em>build</em> system, configuring it for <em>target</em> system:</li> +</ul> <pre><code>sudo qemu-debootstrap --arch=arm64 --verbose \ - --include=fakeroot,build-essential,libx11-dev,libxext-dev,libxrender-dev,libxrandr-dev,libxtst-dev,libxt-dev,libcups2-dev,libfontconfig1-dev,libasound2-dev,libfreetype6-dev,libpng12-dev \ - --resolve-deps jessie /chroots/arm64 http://httpredir.debian.org/debian/</code></pre></li> -<li><p>Configure and build with newly created chroot as sysroot/toolchain-path:</p> + --include=fakeroot,build-essential,libx11-dev,libxext-dev,libxrender-dev,libxrandr-dev,libxtst-dev,libxt-dev,libcups2-dev,libfontconfig1-dev,libasound2-dev,libfreetype6-dev,libpng12-dev \ + --resolve-deps jessie /chroots/arm64 http://httpredir.debian.org/debian/</code></pre> +<ul> +<li>Configure and build with newly created chroot as sysroot/toolchain-path:</li> +</ul> <pre><code>CC=aarch64-linux-gnu-gcc CXX=aarch64-linux-gnu-g++ sh ./configure --openjdk-target=aarch64-linux-gnu --with-sysroot=/chroots/arm64/ --with-toolchain-path=/chroots/arm64/ make images -ls build/linux-aarch64-normal-server-release/</code></pre></li> -</ul> +ls build/linux-aarch64-normal-server-release/</code></pre> <p>The build does not create new files in that chroot, so it can be reused for multiple builds without additional cleanup.</p> <p>Architectures that are known to successfully cross-compile like this are:</p> <table> @@ -860,12 +871,7 @@ spawn failed</code></pre> <p>This can be a sign of a Cygwin problem. See the information about solving problems in the <a href="#cygwin">Cygwin</a> section. Rebooting the computer might help temporarily.</p> <h3 id="getting-help">Getting Help</h3> -<p>If none of the suggestions in this document helps you, or if you find what you believe is a bug in the build system, please contact the Build Group by sending a mail to <script type="text/javascript"> -<!-- -h='openjdk.java.net';a='@';n='build-dev';e=n+a+h; -document.write('<a h'+'ref'+'="ma'+'ilto'+':'+e+'" clas'+'s="em' + 'ail">'+e+'<\/'+'a'+'>'); -// --> -</script><noscript>build-dev at openjdk dot java dot net</noscript>. Please include the relevant parts of the configure and/or build log.</p> +<p>If none of the suggestions in this document helps you, or if you find what you believe is a bug in the build system, please contact the Build Group by sending a mail to <a href="mailto:build-dev@openjdk.java.net">build-dev@openjdk.java.net</a>. Please include the relevant parts of the configure and/or build log.</p> <p>If you need general help or advice about developing for the JDK, you can also contact the Adoption Group. See the section on <a href="#contributing-to-openjdk">Contributing to OpenJDK</a> for more information.</p> <h2 id="hints-and-suggestions-for-advanced-users">Hints and Suggestions for Advanced Users</h2> <h3 id="setting-up-a-repository-for-pushing-changes-defpath">Setting Up a Repository for Pushing Changes (defpath)</h3>
--- a/doc/building.md Tue Dec 11 14:11:57 2018 +0000 +++ b/doc/building.md Wed Dec 12 15:07:56 2018 +0530 @@ -918,7 +918,7 @@ created. Currently, at least the following targets are known to work: Supported devkit targets - ------------------------ + ------------------------- x86_64-linux-gnu aarch64-linux-gnu arm-linux-gnueabihf @@ -1129,13 +1129,13 @@ Architectures that are known to successfully cross-compile like this are: - Target `CC` `CXX` `--arch=...` `--openjdk-target=...` - ------------ ------------------------- --------------------------- ------------ ---------------------- - x86 default default i386 i386-linux-gnu - armhf gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf armhf arm-linux-gnueabihf - aarch64 gcc-aarch64-linux-gnu g++-aarch64-linux-gnu arm64 aarch64-linux-gnu - ppc64el gcc-powerpc64le-linux-gnu g++-powerpc64le-linux-gnu ppc64el powerpc64le-linux-gnu - s390x gcc-s390x-linux-gnu g++-s390x-linux-gnu s390x s390x-linux-gnu + Target `CC` `CXX` `--arch=...` `--openjdk-target=...` + ------------ ------------------------- --------------------------- ------------- ----------------------- + x86 default default i386 i386-linux-gnu + armhf gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf armhf arm-linux-gnueabihf + aarch64 gcc-aarch64-linux-gnu g++-aarch64-linux-gnu arm64 aarch64-linux-gnu + ppc64el gcc-powerpc64le-linux-gnu g++-powerpc64le-linux-gnu ppc64el powerpc64le-linux-gnu + s390x gcc-s390x-linux-gnu g++-s390x-linux-gnu s390x s390x-linux-gnu Additional architectures might be supported by Debian/Ubuntu Ports.
--- a/doc/testing.html Tue Dec 11 14:11:57 2018 +0000 +++ b/doc/testing.html Wed Dec 12 15:07:56 2018 +0530 @@ -1,19 +1,24 @@ <!DOCTYPE html> -<html> +<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang=""> <head> - <meta charset="utf-8"> - <meta name="generator" content="pandoc"> - <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes"> + <meta charset="utf-8" /> + <meta name="generator" content="pandoc" /> + <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" /> <title>Testing the JDK</title> - <style type="text/css">code{white-space: pre;}</style> - <link rel="stylesheet" href="../make/data/docs-resources/resources/jdk-default.css"> + <style type="text/css"> + code{white-space: pre-wrap;} + span.smallcaps{font-variant: small-caps;} + span.underline{text-decoration: underline;} + div.column{display: inline-block; vertical-align: top; width: 50%;} + </style> + <link rel="stylesheet" href="../make/data/docs-resources/resources/jdk-default.css" /> <!--[if lt IE 9]> <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script> <![endif]--> <style type="text/css">pre, code, tt { color: #1d6ae5; }</style> </head> <body> -<header> +<header id="title-block-header"> <h1 class="title">Testing the JDK</h1> </header> <nav id="TOC">
--- a/make/CompileJavaModules.gmk Tue Dec 11 14:11:57 2018 +0000 +++ b/make/CompileJavaModules.gmk Wed Dec 12 15:07:56 2018 +0530 @@ -321,7 +321,7 @@ ################################################################################ -jdk.internal.le_COPY += .properties +jdk.internal.le_COPY += .properties .caps .txt ################################################################################
--- a/make/CompileToolsJdk.gmk Tue Dec 11 14:11:57 2018 +0000 +++ b/make/CompileToolsJdk.gmk Wed Dec 12 15:07:56 2018 +0530 @@ -91,15 +91,17 @@ # To be able to call the javascript filter when generating man pages using # pandoc, we need to create this executable wrapper script. ifneq ($(PANDOC), ) - # PANDOC_FILTER is duplicated for export in ToolsJdk.gmk. - PANDOC_FILTER := $(BUILDTOOLS_OUTPUTDIR)/manpages/pandoc-manpage-filter - PANDOC_FILTER_SETUP := $(BUILDTOOLS_OUTPUTDIR)/manpages/_pandoc_filter_setup.marker + # PANDOC_TROFF_MANPAGE_FILTER is duplicated for export in ToolsJdk.gmk. + PANDOC_TROFF_MANPAGE_FILTER := \ + $(BUILDTOOLS_OUTPUTDIR)/manpages/pandoc-troff-manpage-filter + PANDOC_TROFF_MANPAGE_FILTER_SETUP := \ + $(BUILDTOOLS_OUTPUTDIR)/manpages/_pandoc_troff_manpage_filter_setup.marker # Create a usable instance of the wrapper script that calls the pandoc filter # (which is written in javascript). - $(eval $(call SetupTextFileProcessing, CREATE_PANDOC_FILTER, \ - SOURCE_FILES := $(TOPDIR)/make/scripts/pandoc-manpage-filter.sh.template, \ - OUTPUT_FILE := $(PANDOC_FILTER), \ + $(eval $(call SetupTextFileProcessing, CREATE_PANDOC_TROFF_MANPAGE_FILTER, \ + SOURCE_FILES := $(TOPDIR)/make/scripts/pandoc-troff-manpage-filter.sh.template, \ + OUTPUT_FILE := $(PANDOC_TROFF_MANPAGE_FILTER), \ REPLACEMENTS := \ @@BOOT_JDK@@ => $(BOOT_JDK) ; \ @@TOPDIR@@ => $(TOPDIR) ; \ @@ -107,11 +109,35 @@ )) # Created script must be made executable - $(PANDOC_FILTER_SETUP): $(CREATE_PANDOC_FILTER) - $(CHMOD) a+rx $(PANDOC_FILTER) + $(PANDOC_TROFF_MANPAGE_FILTER_SETUP): $(CREATE_PANDOC_TROFF_MANPAGE_FILTER) + $(CHMOD) a+rx $(PANDOC_TROFF_MANPAGE_FILTER) $(TOUCH) $@ - TARGETS += $(PANDOC_FILTER_SETUP) + TARGETS += $(PANDOC_TROFF_MANPAGE_FILTER_SETUP) + + # PANDOC_HTML_MANPAGE_FILTER is duplicated for export in ToolsJdk.gmk. + PANDOC_HTML_MANPAGE_FILTER := \ + $(BUILDTOOLS_OUTPUTDIR)/manpages/pandoc-html-manpage-filter + PANDOC_HTML_MANPAGE_FILTER_SETUP := \ + $(BUILDTOOLS_OUTPUTDIR)/manpages/_pandoc_html_manpage_filter_setup.marker + + # Create a usable instance of the wrapper script that calls the pandoc filter + # (which is written in javascript). + $(eval $(call SetupTextFileProcessing, CREATE_PANDOC_HTML_MANPAGE_FILTER, \ + SOURCE_FILES := $(TOPDIR)/make/scripts/pandoc-html-manpage-filter.sh.template, \ + OUTPUT_FILE := $(PANDOC_HTML_MANPAGE_FILTER), \ + REPLACEMENTS := \ + @@BOOT_JDK@@ => $(BOOT_JDK) ; \ + @@TOPDIR@@ => $(TOPDIR) ; \ + @@JJS_FLAGS@@ => $(addprefix -J, $(JAVA_FLAGS_SMALL)), \ + )) + + # Created script must be made executable + $(PANDOC_HTML_MANPAGE_FILTER_SETUP): $(CREATE_PANDOC_HTML_MANPAGE_FILTER) + $(CHMOD) a+rx $(PANDOC_HTML_MANPAGE_FILTER) + $(TOUCH) $@ + + TARGETS += $(PANDOC_HTML_MANPAGE_FILTER_SETUP) endif all: $(TARGETS)
--- a/make/Docs.gmk Tue Dec 11 14:11:57 2018 +0000 +++ b/make/Docs.gmk Wed Dec 12 15:07:56 2018 +0530 @@ -27,10 +27,10 @@ include $(SPEC) include MakeBase.gmk include Modules.gmk +include ModuleTools.gmk include ProcessMarkdown.gmk +include ToolsJdk.gmk include ZipArchive.gmk -include $(TOPDIR)/make/ToolsJdk.gmk -include $(TOPDIR)/make/ModuleTools.gmk # This is needed to properly setup DOCS_MODULES. $(eval $(call ReadImportMetaData)) @@ -556,6 +556,15 @@ # For all markdown files in $module/share/man directories, convert them to # html. + + # Create dynamic man pages from markdown using pandoc. We need + # PANDOC_HTML_MANPAGE_FILTER, a wrapper around + # PANDOC_HTML_MANPAGE_FILTER_JAVASCRIPT. This is created by buildtools-jdk. + + # We should also depend on the source javascript filter + PANDOC_HTML_MANPAGE_FILTER_JAVASCRIPT := \ + $(TOPDIR)/make/scripts/pandoc-html-manpage-filter.js + $(foreach m, $(ALL_MODULES), \ $(eval MAN_$m := $(call FindModuleManDirs, $m)) \ $(foreach d, $(MAN_$m), \ @@ -565,8 +574,11 @@ SRC := $d, \ FILES := $(filter %.md, $(call CacheFind, $d)), \ DEST := $(DOCS_OUTPUTDIR)/specs/man, \ + FILTER := $(PANDOC_HTML_MANPAGE_FILTER), \ CSS := $(GLOBAL_SPECS_DEFAULT_CSS_FILE), \ REPLACEMENTS := @@VERSION_SHORT@@ => $(VERSION_SHORT), \ + EXTRA_DEPS := $(PANDOC_HTML_MANPAGE_FILTER) \ + $(PANDOC_HTML_MANPAGE_FILTER_JAVASCRIPT), \ )) \ $(eval JDK_SPECS_TARGETS += $($($m_$d_NAME))) \ ) \
--- a/make/ToolsJdk.gmk Tue Dec 11 14:11:57 2018 +0000 +++ b/make/ToolsJdk.gmk Wed Dec 12 15:07:56 2018 +0530 @@ -118,7 +118,8 @@ # Executable javascript filter for man page generation using pandoc. -PANDOC_FILTER := $(BUILDTOOLS_OUTPUTDIR)/manpages/pandoc-manpage-filter +PANDOC_TROFF_MANPAGE_FILTER := $(BUILDTOOLS_OUTPUTDIR)/manpages/pandoc-troff-manpage-filter +PANDOC_HTML_MANPAGE_FILTER := $(BUILDTOOLS_OUTPUTDIR)/manpages/pandoc-html-manpage-filter ##########################################################################################
--- a/make/common/ProcessMarkdown.gmk Tue Dec 11 14:11:57 2018 +0000 +++ b/make/common/ProcessMarkdown.gmk Wed Dec 12 15:07:56 2018 +0530 @@ -80,7 +80,7 @@ $$(call LogInfo, Converting $2 to $$($1_FORMAT)) $$(call MakeDir, $$(SUPPORT_OUTPUTDIR)/markdown $$(dir $$($1_$2_PANDOC_OUTPUT))) $$(call ExecuteWithLog, $$(SUPPORT_OUTPUTDIR)/markdown/$$($1_$2_MARKER), \ - $$(PANDOC) $$($1_OPTIONS) -f markdown -t $$($1_FORMAT) --standalone \ + $$(PANDOC) $$($1_OPTIONS) -f markdown-smart -t $$($1_FORMAT) --standalone \ $$($1_$2_CSS_OPTION) $$($1_$2_OPTIONS) '$$($1_$2_PANDOC_INPUT)' \ -o '$$($1_$2_PANDOC_OUTPUT)') ifneq ($$(findstring $$(LOG_LEVEL), debug trace),)
--- a/make/launcher/LauncherCommon.gmk Tue Dec 11 14:11:57 2018 +0000 +++ b/make/launcher/LauncherCommon.gmk Wed Dec 12 15:07:56 2018 +0530 @@ -207,11 +207,12 @@ $(info Warning: pandoc not found. Not generating man pages) else # Create dynamic man pages from markdown using pandoc. We need - # PANDOC_FILTER, a wrapper around PANDOC_FILTER_JAVASCRIPT. This is - # created by buildtools-jdk. + # PANDOC_TROFF_MANPAGE_FILTER, a wrapper around + # PANDOC_TROFF_MANPAGE_FILTER_JAVASCRIPT. This is created by buildtools-jdk. # We should also depend on the source javascript filter - PANDOC_FILTER_JAVASCRIPT := $(TOPDIR)/make/scripts/pandoc-manpage-filter.js + PANDOC_TROFF_MANPAGE_FILTER_JAVASCRIPT := \ + $(TOPDIR)/make/scripts/pandoc-troff-manpage-filter.js # The norm in man pages is to display code literals as bold, but pandoc # "correctly" converts these constructs (encoded in markdown using `...` @@ -234,10 +235,11 @@ DEST := $(SUPPORT_OUTPUTDIR)/modules_man/$(MODULE)/man1, \ FILES := $(MAN_FILES_MD), \ FORMAT := man, \ - FILTER := $(PANDOC_FILTER), \ + FILTER := $(PANDOC_TROFF_MANPAGE_FILTER), \ POST_PROCESS := $(MAN_POST_PROCESS), \ REPLACEMENTS := @@VERSION_SHORT@@ => $(VERSION_SHORT), \ - EXTRA_DEPS := $(PANDOC_FILTER) $(PANDOC_FILTER_JAVASCRIPT), \ + EXTRA_DEPS := $(PANDOC_TROFF_MANPAGE_FILTER) \ + $(PANDOC_TROFF_MANPAGE_FILTER_JAVASCRIPT), \ )) TARGETS += $(BUILD_MAN_PAGES)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/scripts/pandoc-html-manpage-filter.js Wed Dec 12 15:07:56 2018 +0530 @@ -0,0 +1,125 @@ +// +// Copyright (c) 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. +// + +// +// Traverse a tree of pandoc format objects, calling callback on each +// element, and replacing it if callback returns a new object. +// +// Inspired by the walk method in +// https://github.com/jgm/pandocfilters/blob/master/pandocfilters.py +// +function traverse(obj, callback) { + if (Array.isArray(obj)) { + var processed_array = []; + obj.forEach(function(elem) { + if (elem === Object(elem) && elem.t) { + var replacement = callback(elem.t, elem.c || []); + if (!replacement) { + // no replacement object returned, use original + processed_array.push(traverse(elem, callback)); + } else if (Array.isArray(replacement)) { + // array of objects returned, splice all elements into array + replacement.forEach(function(repl_elem) { + processed_array.push(traverse(repl_elem, callback)); + }) + } else { + // replacement object given, traverse it + processed_array.push(traverse(replacement, callback)); + } + } else { + processed_array.push(traverse(elem, callback)); + } + }) + return processed_array; + } else if (obj === Object(obj)) { + if (obj.t) { + var replacement = callback(obj.t, obj.c || []); + if (replacement) { + return replacement; + } + } + var processed_obj = {}; + Object.keys(obj).forEach(function(key) { + processed_obj[key] = traverse(obj[key], callback); + }) + return processed_obj; + } else { + return obj; + } +} + +// +// Helper constructors to create pandoc format objects +// +function Space() { + return { 't': 'Space' }; +} + +function Str(value) { + return { 't': 'Str', 'c': value }; +} + +function MetaInlines(value) { + return { 't': 'MetaInlines', 'c': value }; +} + +function change_title(type, value) { + if (type === 'MetaInlines') { + if (value[0].t === 'Str') { + var match = value[0].c.match(/^([A-Z]+)\([0-9]+\)$/); + if (match) { + return MetaInlines([ + Str("The"), Space(), + Str(match[1].toLowerCase()), + Space(), Str("Command") + ]); + } + } + } +} + +// +// Main function +// +function main() { + var input = ""; + while (line = readLine()) { + input = input.concat(line); + } + + var json = JSON.parse(input); + + var meta = json.meta; + if (meta) { + meta.date = undefined; + var title = meta.title; + if (meta.title) { + meta.title = traverse(meta.title, change_title); + } + } + + print(JSON.stringify(json)); +} + +// ... and execute it +main();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/scripts/pandoc-html-manpage-filter.sh.template Wed Dec 12 15:07:56 2018 +0530 @@ -0,0 +1,28 @@ +#!/bin/bash +# +# Copyright (c) 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. +# + +# Simple wrapper script to call Nashorn with the javascript pandoc filter + +@@BOOT_JDK@@/bin/jjs @@JJS_FLAGS@@ -scripting \ + "@@TOPDIR@@/make/scripts/pandoc-html-manpage-filter.js" 2> /dev/null
--- a/make/scripts/pandoc-manpage-filter.js Tue Dec 11 14:11:57 2018 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,142 +0,0 @@ -// -// Copyright (c) 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. -// - -// -// Traverse a tree of pandoc format objects, calling callback on each -// element, and replacing it if callback returns a new object. -// -// Inspired by the walk method in -// https://github.com/jgm/pandocfilters/blob/master/pandocfilters.py -// -function traverse(obj, callback) { - if (Array.isArray(obj)) { - var processed_array = []; - obj.forEach(function(elem) { - if (elem === Object(elem) && elem.t) { - var replacement = callback(elem.t, elem.c || []); - if (!replacement) { - // no replacement object returned, use original - processed_array.push(traverse(elem, callback)); - } else if (Array.isArray(replacement)) { - // array of objects returned, splice all elements into array - replacement.forEach(function(repl_elem) { - processed_array.push(traverse(repl_elem, callback)); - }) - } else { - // replacement object given, traverse it - processed_array.push(traverse(replacement, callback)); - } - } else { - processed_array.push(traverse(elem, callback)); - } - }) - return processed_array; - } else if (obj === Object(obj)) { - var processed_obj = {}; - Object.keys(obj).forEach(function(key) { - processed_obj[key] = traverse(obj[key], callback); - }) - return processed_obj; - } else { - return obj; - } -} - -// -// Helper constructors to create pandoc format objects -// -function Space() { - return { 't': 'Space', 'c': [] }; -} - -function Str(value) { - return { 't': 'Str', 'c': value }; -} - -function Strong(value) { - return { 't': 'Strong', 'c': value }; -} - -function Header(value) { - return { 't': 'Header', 'c': value }; -} - -// -// Callback to change all Str texts to upper case -// -function uppercase(type, value) { - if (type === 'Str') { - return Str(value.toUpperCase()); - } -} - -// -// Main callback function that performs our man page AST rewrites -// -function manpage_filter(type, value) { - // If it is a header, decrease the heading level by one, and - // if it is a level 1 header, convert it to upper case. - if (type === 'Header') { - value[0] = Math.max(1, value[0] - 1); - if (value[0] == 1) { - return Header(traverse(value, uppercase)); - } - } - - // Man pages does not have superscript. We use it for footnotes, so - // enclose in [...] for best representation. - if (type === 'Superscript') { - return [ Str('['), value[0], Str(']') ]; - } - - // If it is a link, put the link name in bold. If it is an external - // link, put it in brackets. Otherwise, it is either an internal link - // (like "#next-heading"), or a relative link to another man page - // (like "java.html"), so remove it for man pages. - if (type === 'Link') { - var target = value[2][0]; - if (target.match(/^http[s]?:/)) { - return [ Strong(value[1]), Space(), Str('[' + target + ']') ]; - } else { - return Strong(value[1]); - } - } -} - -// -// Main function -// -function main() { - var input = ""; - while (line = readLine()) { - input = input.concat(line); - } - var json = JSON.parse(input); - - var transformed_json = traverse(json, manpage_filter); - - print(JSON.stringify(transformed_json)); -} - -// ... and execute it -main();
--- a/make/scripts/pandoc-manpage-filter.sh.template Tue Dec 11 14:11:57 2018 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,28 +0,0 @@ -#!/bin/bash -# -# Copyright (c) 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. -# - -# Simple wrapper script to call Nashorn with the javascript pandoc filter - -@@BOOT_JDK@@/bin/jjs @@JJS_FLAGS@@ -scripting \ - "@@TOPDIR@@/make/scripts/pandoc-manpage-filter.js" 2> /dev/null
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/scripts/pandoc-troff-manpage-filter.js Wed Dec 12 15:07:56 2018 +0530 @@ -0,0 +1,142 @@ +// +// Copyright (c) 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. +// + +// +// Traverse a tree of pandoc format objects, calling callback on each +// element, and replacing it if callback returns a new object. +// +// Inspired by the walk method in +// https://github.com/jgm/pandocfilters/blob/master/pandocfilters.py +// +function traverse(obj, callback) { + if (Array.isArray(obj)) { + var processed_array = []; + obj.forEach(function(elem) { + if (elem === Object(elem) && elem.t) { + var replacement = callback(elem.t, elem.c || []); + if (!replacement) { + // no replacement object returned, use original + processed_array.push(traverse(elem, callback)); + } else if (Array.isArray(replacement)) { + // array of objects returned, splice all elements into array + replacement.forEach(function(repl_elem) { + processed_array.push(traverse(repl_elem, callback)); + }) + } else { + // replacement object given, traverse it + processed_array.push(traverse(replacement, callback)); + } + } else { + processed_array.push(traverse(elem, callback)); + } + }) + return processed_array; + } else if (obj === Object(obj)) { + var processed_obj = {}; + Object.keys(obj).forEach(function(key) { + processed_obj[key] = traverse(obj[key], callback); + }) + return processed_obj; + } else { + return obj; + } +} + +// +// Helper constructors to create pandoc format objects +// +function Space() { + return { 't': 'Space', 'c': [] }; +} + +function Str(value) { + return { 't': 'Str', 'c': value }; +} + +function Strong(value) { + return { 't': 'Strong', 'c': value }; +} + +function Header(value) { + return { 't': 'Header', 'c': value }; +} + +// +// Callback to change all Str texts to upper case +// +function uppercase(type, value) { + if (type === 'Str') { + return Str(value.toUpperCase()); + } +} + +// +// Main callback function that performs our man page AST rewrites +// +function manpage_filter(type, value) { + // If it is a header, decrease the heading level by one, and + // if it is a level 1 header, convert it to upper case. + if (type === 'Header') { + value[0] = Math.max(1, value[0] - 1); + if (value[0] == 1) { + return Header(traverse(value, uppercase)); + } + } + + // Man pages does not have superscript. We use it for footnotes, so + // enclose in [...] for best representation. + if (type === 'Superscript') { + return [ Str('['), value[0], Str(']') ]; + } + + // If it is a link, put the link name in bold. If it is an external + // link, put it in brackets. Otherwise, it is either an internal link + // (like "#next-heading"), or a relative link to another man page + // (like "java.html"), so remove it for man pages. + if (type === 'Link') { + var target = value[2][0]; + if (target.match(/^http[s]?:/)) { + return [ Strong(value[1]), Space(), Str('[' + target + ']') ]; + } else { + return Strong(value[1]); + } + } +} + +// +// Main function +// +function main() { + var input = ""; + while (line = readLine()) { + input = input.concat(line); + } + var json = JSON.parse(input); + + var transformed_json = traverse(json, manpage_filter); + + print(JSON.stringify(transformed_json)); +} + +// ... and execute it +main();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/scripts/pandoc-troff-manpage-filter.sh.template Wed Dec 12 15:07:56 2018 +0530 @@ -0,0 +1,28 @@ +#!/bin/bash +# +# Copyright (c) 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. +# + +# Simple wrapper script to call Nashorn with the javascript pandoc filter + +@@BOOT_JDK@@/bin/jjs @@JJS_FLAGS@@ -scripting \ + "@@TOPDIR@@/make/scripts/pandoc-troff-manpage-filter.js" 2> /dev/null
--- a/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp Tue Dec 11 14:11:57 2018 +0000 +++ b/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp Wed Dec 12 15:07:56 2018 +0530 @@ -2273,7 +2273,7 @@ ) { // make sure arguments make sense assert_different_registers(obj, var_size_in_bytes, t1); - assert(0 <= con_size_in_bytes && is_simm13(con_size_in_bytes), "illegal object size"); + assert(0 <= con_size_in_bytes && is_simm16(con_size_in_bytes), "illegal object size"); assert((con_size_in_bytes & MinObjAlignmentInBytesMask) == 0, "object size is not multiple of alignment"); const Register new_top = t1;
--- a/src/hotspot/os/linux/globals_linux.hpp Tue Dec 11 14:11:57 2018 +0000 +++ b/src/hotspot/os/linux/globals_linux.hpp Wed Dec 12 15:07:56 2018 +0530 @@ -67,6 +67,11 @@ " of quotas (if set), when true. Otherwise, use the CPU" \ " shares value, provided it is less than quota.") \ \ + diagnostic(bool, DumpPrivateMappingsInCore, true, \ + "If true, sets bit 2 of /proc/PID/coredump_filter, thus " \ + "resulting in file-backed private mappings of the process to "\ + "be dumped into the corefile, if UseSharedSpaces is true.") \ + \ diagnostic(bool, UseCpuAllocPath, false, \ "Use CPU_ALLOC code path in os::active_processor_count ")
--- a/src/hotspot/os/linux/os_linux.cpp Tue Dec 11 14:11:57 2018 +0000 +++ b/src/hotspot/os/linux/os_linux.cpp Wed Dec 12 15:07:56 2018 +0530 @@ -128,8 +128,12 @@ // for timer info max values which include all bits #define ALL_64_BITS CONST64(0xFFFFFFFFFFFFFFFF) -#define LARGEPAGES_BIT (1 << 6) -#define DAX_SHARED_BIT (1 << 8) +enum CoredumpFilterBit { + FILE_BACKED_PVT_BIT = 1 << 2, + LARGEPAGES_BIT = 1 << 6, + DAX_SHARED_BIT = 1 << 8 +}; + //////////////////////////////////////////////////////////////////////////////// // global variables julong os::Linux::_physical_memory = 0; @@ -1350,6 +1354,9 @@ void os::abort(bool dump_core, void* siginfo, const void* context) { os::shutdown(); if (dump_core) { + if (UseSharedSpaces && DumpPrivateMappingsInCore) { + ClassLoader::close_jrt_image(); + } #ifndef PRODUCT fdStream out(defaultStream::output_fd()); out.print_raw("Current thread is "); @@ -3401,10 +3408,9 @@ // - (bit 7) dax private memory // - (bit 8) dax shared memory // -static void set_coredump_filter(bool largepages, bool dax_shared) { +static void set_coredump_filter(CoredumpFilterBit bit) { FILE *f; long cdm; - bool filter_changed = false; if ((f = fopen("/proc/self/coredump_filter", "r+")) == NULL) { return; @@ -3415,17 +3421,11 @@ return; } + long saved_cdm = cdm; rewind(f); - - if (largepages && (cdm & LARGEPAGES_BIT) == 0) { - cdm |= LARGEPAGES_BIT; - filter_changed = true; - } - if (dax_shared && (cdm & DAX_SHARED_BIT) == 0) { - cdm |= DAX_SHARED_BIT; - filter_changed = true; - } - if (filter_changed) { + cdm |= bit; + + if (cdm != saved_cdm) { fprintf(f, "%#lx", cdm); } @@ -3564,7 +3564,7 @@ size_t large_page_size = Linux::setup_large_page_size(); UseLargePages = Linux::setup_large_page_type(large_page_size); - set_coredump_filter(true /*largepages*/, false /*dax_shared*/); + set_coredump_filter(LARGEPAGES_BIT); } #ifndef SHM_HUGETLB @@ -5072,8 +5072,13 @@ prio_init(); if (!FLAG_IS_DEFAULT(AllocateHeapAt)) { - set_coredump_filter(false /*largepages*/, true /*dax_shared*/); - } + set_coredump_filter(DAX_SHARED_BIT); + } + + if (UseSharedSpaces && DumpPrivateMappingsInCore) { + set_coredump_filter(FILE_BACKED_PVT_BIT); + } + return JNI_OK; }
--- a/src/hotspot/os_cpu/linux_x86/gc/z/zGlobals_linux_x86.hpp Tue Dec 11 14:11:57 2018 +0000 +++ b/src/hotspot/os_cpu/linux_x86/gc/z/zGlobals_linux_x86.hpp Wed Dec 12 15:07:56 2018 +0530 @@ -74,15 +74,17 @@ // * 63-47 Fixed (17-bits, always zero) // -const size_t ZPlatformPageSizeSmallShift = 21; // 2M +const size_t ZPlatformPageSizeSmallShift = 21; // 2M -const size_t ZPlatformAddressOffsetBits = 42; // 4TB +const size_t ZPlatformAddressOffsetBits = 42; // 4TB + +const uintptr_t ZPlatformAddressMetadataShift = ZPlatformAddressOffsetBits; -const uintptr_t ZPlatformAddressMetadataShift = ZPlatformAddressOffsetBits; +const uintptr_t ZPlatformAddressSpaceStart = (uintptr_t)1 << ZPlatformAddressOffsetBits; +const uintptr_t ZPlatformAddressSpaceSize = ((uintptr_t)1 << ZPlatformAddressOffsetBits) * 4; -const uintptr_t ZPlatformAddressSpaceStart = (uintptr_t)1 << ZPlatformAddressOffsetBits; -const uintptr_t ZPlatformAddressSpaceSize = ((uintptr_t)1 << ZPlatformAddressOffsetBits) * 4; +const size_t ZPlatformNMethodDisarmedOffset = 4; -const size_t ZPlatformCacheLineSize = 64; +const size_t ZPlatformCacheLineSize = 64; #endif // OS_CPU_LINUX_X86_ZGLOBALS_LINUX_X86_HPP
--- a/src/hotspot/share/classfile/classFileParser.cpp Tue Dec 11 14:11:57 2018 +0000 +++ b/src/hotspot/share/classfile/classFileParser.cpp Wed Dec 12 15:07:56 2018 +0530 @@ -5733,7 +5733,8 @@ ik->major_version() != JAVA_MIN_SUPPORTED_VERSION && log_is_enabled(Info, class, preview)) { ResourceMark rm; - log_info(class, preview)("Loading preview feature type %s", ik->external_name()); + log_info(class, preview)("Loading class %s that depends on preview features (class file version %d.65535)", + ik->external_name(), ik->major_version()); } if (log_is_enabled(Debug, class, resolve)) {
--- a/src/hotspot/share/classfile/classLoader.cpp Tue Dec 11 14:11:57 2018 +0000 +++ b/src/hotspot/share/classfile/classLoader.cpp Wed Dec 12 15:07:56 2018 +0530 @@ -363,6 +363,13 @@ } } +void ClassPathImageEntry::close_jimage() { + if (_jimage != NULL) { + (*JImageClose)(_jimage); + _jimage = NULL; + } +} + ClassPathImageEntry::ClassPathImageEntry(JImageFile* jimage, const char* name) : ClassPathEntry(), _jimage(jimage) { @@ -614,6 +621,12 @@ void ClassLoader::setup_module_search_path(const char* path, TRAPS) { update_module_path_entry_list(path, THREAD); } + +void ClassLoader::close_jrt_image() { + assert(ClassLoader::has_jrt_entry(), "Not applicable for exploded builds"); + _jrt_entry->close_jimage(); +} + #endif // INCLUDE_CDS // Construct the array of module/path pairs as specified to --patch-module
--- a/src/hotspot/share/classfile/classLoader.hpp Tue Dec 11 14:11:57 2018 +0000 +++ b/src/hotspot/share/classfile/classLoader.hpp Wed Dec 12 15:07:56 2018 +0530 @@ -55,6 +55,7 @@ virtual bool is_jar_file() const = 0; virtual const char* name() const = 0; virtual JImageFile* jimage() const = 0; + virtual void close_jimage() = 0; // Constructor ClassPathEntry() : _next(NULL) {} // Attempt to locate file_name through this class path entry. @@ -70,6 +71,7 @@ bool is_jar_file() const { return false; } const char* name() const { return _dir; } JImageFile* jimage() const { return NULL; } + void close_jimage() {} ClassPathDirEntry(const char* dir); virtual ~ClassPathDirEntry() {} ClassFileStream* open_stream(const char* name, TRAPS); @@ -98,6 +100,7 @@ bool is_jar_file() const { return true; } const char* name() const { return _zip_name; } JImageFile* jimage() const { return NULL; } + void close_jimage() {} ClassPathZipEntry(jzfile* zip, const char* zip_name, bool is_boot_append); virtual ~ClassPathZipEntry(); u1* open_entry(const char* name, jint* filesize, bool nul_terminate, TRAPS); @@ -117,6 +120,7 @@ bool is_open() const { return _jimage != NULL; } const char* name() const { return _name == NULL ? "" : _name; } JImageFile* jimage() const { return _jimage; } + void close_jimage(); ClassPathImageEntry(JImageFile* jimage, const char* name); virtual ~ClassPathImageEntry(); ClassFileStream* open_stream(const char* name, TRAPS); @@ -333,6 +337,7 @@ // Modular java runtime image is present vs. a build with exploded modules static bool has_jrt_entry() { return (_jrt_entry != NULL); } static ClassPathEntry* get_jrt_entry() { return _jrt_entry; } + static void close_jrt_image(); // Add a module's exploded directory to the boot loader's exploded module build list static void add_to_exploded_build_list(Symbol* module_name, TRAPS);
--- a/src/hotspot/share/classfile/symbolTable.cpp Tue Dec 11 14:11:57 2018 +0000 +++ b/src/hotspot/share/classfile/symbolTable.cpp Wed Dec 12 15:07:56 2018 +0530 @@ -116,14 +116,17 @@ return SymbolTableHash::BaseConfig::allocate_node(size, value); } static void free_node(void* memory, Symbol* const& value) { - // We get here either because #1 some threads lost a race - // to insert a newly created Symbol, or #2 we are freeing - // a symbol during normal cleanup deletion. - // If #1, then the symbol can be a permanent (refcount==PERM_REFCOUNT), - // or regular newly created one but with refcount==0 (see SymbolTableCreateEntry) - // If #2, then the symbol must have refcount==0 - assert((value->refcount() == PERM_REFCOUNT) || (value->refcount() == 0), + // We get here because #1 some threads lost a race to insert a newly created Symbol + // or #2 we're cleaning up unused symbol. + // If #1, then the symbol can be either permanent (refcount==PERM_REFCOUNT), + // or regular newly created one (refcount==1) + // If #2, then the symbol is dead (refcount==0) + assert((value->refcount() == PERM_REFCOUNT) || (value->refcount() == 1) || (value->refcount() == 0), "refcount %d", value->refcount()); + if (value->refcount() == 1) { + value->decrement_refcount(); + assert(value->refcount() == 0, "expected dead symbol"); + } SymbolTable::delete_symbol(value); SymbolTableHash::BaseConfig::free_node(memory, value); SymbolTable::item_removed(); @@ -162,6 +165,12 @@ } } +void SymbolTable::update_needs_rehash(bool rehash) { + if (rehash) { + _needs_rehashing = true; + } +} + void SymbolTable::item_added() { Atomic::inc(&(SymbolTable::the_table()->_items_count)); } @@ -398,9 +407,7 @@ SymbolTableGet stg; bool rehash_warning = false; _local_table->get(thread, lookup, stg, &rehash_warning); - if (rehash_warning) { - _needs_rehashing = true; - } + update_needs_rehash(rehash_warning); Symbol* sym = stg.get_res_sym(); assert((sym == NULL) || sym->refcount() != 0, "found dead symbol"); return sym; @@ -462,71 +469,26 @@ } } -class SymbolTableCreateEntry : public StackObj { -private: - Thread* _thread; - const char* _name; - int _len; - bool _heap; - Symbol* _return; - Symbol* _created; - - void assert_for_name(Symbol* sym, const char* where) const { -#ifdef ASSERT - assert(sym->utf8_length() == _len, "%s [%d,%d]", where, sym->utf8_length(), _len); - for (int i = 0; i < _len; i++) { - assert(sym->char_at(i) == _name[i], - "%s [%d,%d,%d]", where, i, sym->char_at(i), _name[i]); - } -#endif - } - -public: - SymbolTableCreateEntry(Thread* thread, const char* name, int len, bool heap) - : _thread(thread), _name(name) , _len(len), _heap(heap), _return(NULL) , _created(NULL) { - assert(_name != NULL, "expected valid name"); - } - Symbol* operator()() { - _created = SymbolTable::the_table()->allocate_symbol(_name, _len, _heap, _thread); - assert(_created != NULL, "expected created symbol"); - assert_for_name(_created, "operator()()"); - assert(_created->equals(_name, _len), - "symbol must be properly initialized [%p,%d,%d]", _name, _len, (int)_heap); - return _created; - } - void operator()(bool inserted, Symbol** value) { - assert(value != NULL, "expected valid value"); - assert(*value != NULL, "value should point to a symbol"); - if (!inserted && (_created != NULL)) { - // We created our symbol, but someone else inserted - // theirs first, so ours will be destroyed. - // Since symbols are created with refcount of 1, - // we must decrement it here to 0 to delete, - // unless it's a permanent one. - if (_created->refcount() != PERM_REFCOUNT) { - assert(_created->refcount() == 1, "expected newly created symbol"); - _created->decrement_refcount(); - assert(_created->refcount() == 0, "expected dead symbol"); - } - } - _return = *value; - assert_for_name(_return, "operator()"); - } - Symbol* get_new_sym() const { - assert_for_name(_return, "get_new_sym"); - return _return; - } -}; - Symbol* SymbolTable::do_add_if_needed(const char* name, int len, uintx hash, bool heap, TRAPS) { SymbolTableLookup lookup(THREAD, name, len, hash); - SymbolTableCreateEntry stce(THREAD, name, len, heap); - bool rehash_warning = false; + SymbolTableGet stg; bool clean_hint = false; - _local_table->get_insert_lazy(THREAD, lookup, stce, stce, &rehash_warning, &clean_hint); - if (rehash_warning) { - _needs_rehashing = true; - } + bool rehash_warning = false; + Symbol* sym = NULL; + + do { + if (_local_table->get(THREAD, lookup, stg, &rehash_warning)) { + sym = stg.get_res_sym(); + break; + } + sym = SymbolTable::the_table()->allocate_symbol(name, len, heap, THREAD); + if (_local_table->insert(THREAD, lookup, sym, &rehash_warning, &clean_hint)) { + break; + } + } while(true); + + update_needs_rehash(rehash_warning); + if (clean_hint) { // we just found out that there is a dead item, // which we were unable to clean right now, @@ -536,8 +498,8 @@ mark_item_clean_count(); check_concurrent_work(); } - Symbol* sym = stce.get_new_sym(); - assert(sym->refcount() != 0, "zero is invalid"); + + assert((sym == NULL) || sym->refcount() != 0, "found dead symbol"); return sym; }
--- a/src/hotspot/share/classfile/symbolTable.hpp Tue Dec 11 14:11:57 2018 +0000 +++ b/src/hotspot/share/classfile/symbolTable.hpp Wed Dec 12 15:07:56 2018 +0530 @@ -169,6 +169,7 @@ void try_rehash_table(); bool do_rehash(); + inline void update_needs_rehash(bool rehash); public: // The symbol table
--- a/src/hotspot/share/gc/cms/cmsHeap.cpp Tue Dec 11 14:11:57 2018 +0000 +++ b/src/hotspot/share/gc/cms/cmsHeap.cpp Wed Dec 12 15:07:56 2018 +0530 @@ -70,19 +70,24 @@ Generation::ParNew, Generation::ConcurrentMarkSweep, "ParNew:CMS"), + _workers(NULL), _eden_pool(NULL), _survivor_pool(NULL), _old_pool(NULL) { - _workers = new WorkGang("GC Thread", ParallelGCThreads, - /* are_GC_task_threads */true, - /* are_ConcurrentGC_threads */false); - _workers->initialize_workers(); } jint CMSHeap::initialize() { jint status = GenCollectedHeap::initialize(); if (status != JNI_OK) return status; + _workers = new WorkGang("GC Thread", ParallelGCThreads, + /* are_GC_task_threads */true, + /* are_ConcurrentGC_threads */false); + if (_workers == NULL) { + return JNI_ENOMEM; + } + _workers->initialize_workers(); + // If we are running CMS, create the collector responsible // for collecting the CMS generations. if (!create_cms_collector()) {
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp Tue Dec 11 14:11:57 2018 +0000 +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp Wed Dec 12 15:07:56 2018 +0530 @@ -1531,10 +1531,6 @@ _is_subject_to_discovery_cm(this), _in_cset_fast_test() { - _workers = new WorkGang("GC Thread", ParallelGCThreads, - true /* are_GC_task_threads */, - false /* are_ConcurrentGC_threads */); - _workers->initialize_workers(); _verifier = new G1HeapVerifier(this); _allocator = new G1Allocator(this); @@ -1767,6 +1763,14 @@ _humongous_reclaim_candidates.initialize(start, end, granularity); } + _workers = new WorkGang("GC Thread", ParallelGCThreads, + true /* are_GC_task_threads */, + false /* are_ConcurrentGC_threads */); + if (_workers == NULL) { + return JNI_ENOMEM; + } + _workers->initialize_workers(); + // Create the G1ConcurrentMark data structure and thread. // (Must do this late, so that "max_regions" is defined.) _cm = new G1ConcurrentMark(this, prev_bitmap_storage, next_bitmap_storage);
--- a/src/hotspot/share/gc/shared/barrierSet.cpp Tue Dec 11 14:11:57 2018 +0000 +++ b/src/hotspot/share/gc/shared/barrierSet.cpp Wed Dec 12 15:07:56 2018 +0530 @@ -26,47 +26,24 @@ #include "gc/shared/barrierSet.hpp" #include "gc/shared/barrierSetAssembler.hpp" #include "runtime/thread.hpp" +#include "utilities/debug.hpp" #include "utilities/macros.hpp" BarrierSet* BarrierSet::_barrier_set = NULL; -class SetBarrierSetNonJavaThread : public ThreadClosure { - BarrierSet* _barrier_set; - size_t _count; - -public: - SetBarrierSetNonJavaThread(BarrierSet* barrier_set) : - _barrier_set(barrier_set), _count(0) {} - - virtual void do_thread(Thread* thread) { - _barrier_set->on_thread_create(thread); - ++_count; - } - - size_t count() const { return _count; } -}; - void BarrierSet::set_barrier_set(BarrierSet* barrier_set) { assert(_barrier_set == NULL, "Already initialized"); _barrier_set = barrier_set; - // Some threads are created before the barrier set, so the call to - // BarrierSet::on_thread_create had to be deferred for them. Now that - // we have the barrier set, do those deferred calls. - - // First do any non-JavaThreads. - SetBarrierSetNonJavaThread njt_closure(_barrier_set); - Threads::non_java_threads_do(&njt_closure); - - // Do the current (main) thread. Ensure it's the one and only - // JavaThread so far. Also verify that it isn't yet on the thread + // Notify barrier set of the current (main) thread. Normally the + // Thread constructor deals with this, but the main thread is + // created before we get here. Verify it isn't yet on the thread // list, else we'd also need to call BarrierSet::on_thread_attach. + // This is the only thread that can exist at this point; the Thread + // constructor objects to other threads being created before the + // barrier set is available. assert(Thread::current()->is_Java_thread(), "Expected main thread to be a JavaThread"); - assert((njt_closure.count() + 1) == Threads::threads_before_barrier_set(), - "Unexpected JavaThreads before barrier set initialization: " - "Non-JavaThreads: " SIZE_FORMAT ", all: " SIZE_FORMAT, - njt_closure.count(), Threads::threads_before_barrier_set()); assert(!JavaThread::current()->on_thread_list(), "Main thread already on thread list."); _barrier_set->on_thread_create(Thread::current());
--- a/src/hotspot/share/gc/z/zArguments.cpp Tue Dec 11 14:11:57 2018 +0000 +++ b/src/hotspot/share/gc/z/zArguments.cpp Wed Dec 12 15:07:56 2018 +0530 @@ -80,10 +80,6 @@ FLAG_SET_DEFAULT(UseCompressedOops, false); FLAG_SET_DEFAULT(UseCompressedClassPointers, false); - // ClassUnloading not (yet) supported - FLAG_SET_DEFAULT(ClassUnloading, false); - FLAG_SET_DEFAULT(ClassUnloadingWithConcurrentMark, false); - // Verification before startup and after exit not (yet) supported FLAG_SET_DEFAULT(VerifyDuringStartup, false); FLAG_SET_DEFAULT(VerifyBeforeExit, false);
--- a/src/hotspot/share/gc/z/zBarrier.hpp Tue Dec 11 14:11:57 2018 +0000 +++ b/src/hotspot/share/gc/z/zBarrier.hpp Wed Dec 12 15:07:56 2018 +0530 @@ -81,6 +81,7 @@ static void load_barrier_on_oop_fields(oop o); static oop load_barrier_on_weak_oop_field_preloaded(volatile oop* p, oop o); static oop load_barrier_on_phantom_oop_field_preloaded(volatile oop* p, oop o); + static void load_barrier_on_root_oop_field(oop* p); // Weak load barrier static oop weak_load_barrier_on_oop_field(volatile oop* p); @@ -99,6 +100,7 @@ // Keep alive barrier static void keep_alive_barrier_on_weak_oop_field(volatile oop* p); static void keep_alive_barrier_on_phantom_oop_field(volatile oop* p); + static void keep_alive_barrier_on_phantom_root_oop_field(oop* p); // Mark barrier static void mark_barrier_on_oop_field(volatile oop* p, bool finalizable);
--- a/src/hotspot/share/gc/z/zBarrier.inline.hpp Tue Dec 11 14:11:57 2018 +0000 +++ b/src/hotspot/share/gc/z/zBarrier.inline.hpp Wed Dec 12 15:07:56 2018 +0530 @@ -111,11 +111,12 @@ const uintptr_t good_addr = slow_path(addr); // Non-atomic healing helps speed up root scanning. This is safe to do - // since we are always healing roots in a safepoint, which means we are - // never racing with mutators modifying roots while we are healing them. - // It's also safe in case multiple GC threads try to heal the same root, - // since they would always heal the root in the same way and it does not - // matter in which order it happens. + // since we are always healing roots in a safepoint, or under a lock, + // which ensures we are never racing with mutators modifying roots while + // we are healing them. It's also safe in case multiple GC threads try + // to heal the same root if it is aligned, since they would always heal + // the root in the same way and it does not matter in which order it + // happens. For misaligned oops, there needs to be mutual exclusion. *p = ZOop::to_oop(good_addr); } @@ -188,6 +189,11 @@ return load_barrier_on_oop_field_preloaded(p, o); } +inline void ZBarrier::load_barrier_on_root_oop_field(oop* p) { + const oop o = *p; + root_barrier<is_good_or_null_fast_path, load_barrier_on_oop_slow_path>(p, o); +} + // // Weak load barrier // @@ -269,6 +275,13 @@ barrier<is_good_or_null_fast_path, keep_alive_barrier_on_phantom_oop_slow_path>(p, o); } +inline void ZBarrier::keep_alive_barrier_on_phantom_root_oop_field(oop* p) { + // This operation is only valid when resurrection is blocked. + assert(ZResurrection::is_blocked(), "Invalid phase"); + const oop o = *p; + root_barrier<is_good_or_null_fast_path, keep_alive_barrier_on_phantom_oop_slow_path>(p, o); +} + // // Mark barrier //
--- a/src/hotspot/share/gc/z/zBarrierSet.cpp Tue Dec 11 14:11:57 2018 +0000 +++ b/src/hotspot/share/gc/z/zBarrierSet.cpp Wed Dec 12 15:07:56 2018 +0530 @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "gc/z/zBarrierSet.hpp" #include "gc/z/zBarrierSetAssembler.hpp" +#include "gc/z/zBarrierSetNMethod.hpp" #include "gc/z/zGlobals.hpp" #include "gc/z/zHeap.inline.hpp" #include "gc/z/zThreadLocalData.hpp" @@ -39,11 +40,20 @@ class ZBarrierSetC1; class ZBarrierSetC2; +static BarrierSetNMethod* make_barrier_set_nmethod() { + // NMethod barriers are only used when class unloading is enabled + if (!ClassUnloading) { + return NULL; + } + + return new ZBarrierSetNMethod(); +} + ZBarrierSet::ZBarrierSet() : BarrierSet(make_barrier_set_assembler<ZBarrierSetAssembler>(), make_barrier_set_c1<ZBarrierSetC1>(), make_barrier_set_c2<ZBarrierSetC2>(), - NULL /* barrier_set_nmethod */, + make_barrier_set_nmethod(), BarrierSet::FakeRtti(BarrierSet::ZBarrierSet)) {} ZBarrierSetAssembler* ZBarrierSet::assembler() {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/hotspot/share/gc/z/zBarrierSetNMethod.cpp Wed Dec 12 15:07:56 2018 +0530 @@ -0,0 +1,73 @@ +/* + * Copyright (c) 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. + */ + +#include "precompiled.hpp" +#include "code/nmethod.hpp" +#include "gc/z/zBarrierSetNMethod.hpp" +#include "gc/z/zGlobals.hpp" +#include "gc/z/zLock.inline.hpp" +#include "gc/z/zOopClosures.hpp" +#include "gc/z/zNMethodTable.hpp" +#include "gc/z/zThreadLocalData.hpp" +#include "logging/log.hpp" + +bool ZBarrierSetNMethod::nmethod_entry_barrier(nmethod* nm) { + ZLocker<ZReentrantLock> locker(ZNMethodTable::lock_for_nmethod(nm)); + log_trace(nmethod, barrier)("Entered critical zone for %p", nm); + + if (!is_armed(nm)) { + // Some other thread got here first and healed the oops + // and disarmed the nmethod. + return true; + } + + if (nm->is_unloading()) { + // We can end up calling nmethods that are unloading + // since we clear compiled ICs lazily. Returning false + // will re-resovle the call and update the compiled IC. + return false; + } + + // Heal oops and disarm + ZNMethodOopClosure cl; + nm->oops_do(&cl); + nm->fix_oop_relocations(); + + OrderAccess::release(); + + disarm(nm); + + return true; +} + +int ZBarrierSetNMethod::disarmed_value() const { + // We override the default BarrierSetNMethod::disarmed_value() since + // this can be called by GC threads, which doesn't keep an up to date + // address_bad_mask. + const uintptr_t disarmed_addr = ((uintptr_t)&ZAddressBadMask) + ZNMethodDisarmedOffset; + return *((int*)disarmed_addr); +} + +ByteSize ZBarrierSetNMethod::thread_disarmed_offset() const { + return ZThreadLocalData::nmethod_disarmed_offset(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/hotspot/share/gc/z/zBarrierSetNMethod.hpp Wed Dec 12 15:07:56 2018 +0530 @@ -0,0 +1,41 @@ +/* + * Copyright (c) 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. + */ + +#ifndef SHARE_GC_Z_ZBARRIERSETNMETHOD_HPP +#define SHARE_GC_Z_ZBARRIERSETNMETHOD_HPP + +#include "gc/shared/barrierSetNMethod.hpp" +#include "memory/allocation.hpp" + +class nmethod; + +class ZBarrierSetNMethod : public BarrierSetNMethod { +protected: + virtual int disarmed_value() const; + virtual bool nmethod_entry_barrier(nmethod* nm); + +public: + virtual ByteSize thread_disarmed_offset() const; +}; + +#endif // SHARE_GC_Z_ZBARRIERSETNMETHOD_HPP
--- a/src/hotspot/share/gc/z/zCollectedHeap.cpp Tue Dec 11 14:11:57 2018 +0000 +++ b/src/hotspot/share/gc/z/zCollectedHeap.cpp Wed Dec 12 15:07:56 2018 +0530 @@ -259,12 +259,10 @@ } void ZCollectedHeap::register_nmethod(nmethod* nm) { - assert_locked_or_safepoint(CodeCache_lock); ZNMethodTable::register_nmethod(nm); } void ZCollectedHeap::unregister_nmethod(nmethod* nm) { - assert_locked_or_safepoint(CodeCache_lock); ZNMethodTable::unregister_nmethod(nm); }
--- a/src/hotspot/share/gc/z/zGlobals.hpp Tue Dec 11 14:11:57 2018 +0000 +++ b/src/hotspot/share/gc/z/zGlobals.hpp Wed Dec 12 15:07:56 2018 +0530 @@ -91,6 +91,9 @@ const uintptr_t ZAddressSpaceSize = ZPlatformAddressSpaceSize; const uintptr_t ZAddressSpaceEnd = ZAddressSpaceStart + ZAddressSpaceSize; +// NMethod entry barrier +const size_t ZNMethodDisarmedOffset = ZPlatformNMethodDisarmedOffset; + // Cache line size const size_t ZCacheLineSize = ZPlatformCacheLineSize;
--- a/src/hotspot/share/gc/z/zHeap.cpp Tue Dec 11 14:11:57 2018 +0000 +++ b/src/hotspot/share/gc/z/zHeap.cpp Wed Dec 12 15:07:56 2018 +0530 @@ -69,6 +69,7 @@ _weak_roots_processor(&_workers), _relocate(&_workers), _relocation_set(), + _unload(&_workers), _serviceability(heap_min_size(), heap_max_size()) { // Install global heap instance assert(_heap == NULL, "Already initialized"); @@ -353,9 +354,6 @@ // Enter mark completed phase ZGlobalPhase = ZPhaseMarkCompleted; - // Resize metaspace - MetaspaceGC::compute_new_size(); - // Update statistics ZStatSample(ZSamplerHeapUsedAfterMark, used()); ZStatHeap::set_at_mark_end(capacity(), allocated(), used()); @@ -366,6 +364,9 @@ // Process weak roots _weak_roots_processor.process_weak_roots(); + // Prepare to unload unused classes and code + _unload.prepare(); + return true; } @@ -380,6 +381,9 @@ // Process concurrent weak roots _weak_roots_processor.process_concurrent_weak_roots(); + // Unload unused classes and code + _unload.unload(); + // Unblock resurrection of weak/phantom references ZResurrection::unblock(); @@ -463,8 +467,8 @@ void ZHeap::relocate_start() { assert(SafepointSynchronize::is_at_safepoint(), "Should be at safepoint"); - // Update statistics - ZStatSample(ZSamplerHeapUsedBeforeRelocation, used()); + // Finish unloading of classes and code + _unload.finish(); // Flip address view ZAddressMasks::flip_to_remapped(); @@ -474,6 +478,7 @@ ZGlobalPhase = ZPhaseRelocate; // Update statistics + ZStatSample(ZSamplerHeapUsedBeforeRelocation, used()); ZStatHeap::set_at_relocate_start(capacity(), allocated(), used()); // Remap/Relocate roots
--- a/src/hotspot/share/gc/z/zHeap.hpp Tue Dec 11 14:11:57 2018 +0000 +++ b/src/hotspot/share/gc/z/zHeap.hpp Wed Dec 12 15:07:56 2018 +0530 @@ -41,6 +41,7 @@ #include "gc/z/zRootsIterator.hpp" #include "gc/z/zWeakRootsProcessor.hpp" #include "gc/z/zServiceability.hpp" +#include "gc/z/zUnload.hpp" #include "gc/z/zWorkers.hpp" #include "memory/allocation.hpp" @@ -59,6 +60,7 @@ ZWeakRootsProcessor _weak_roots_processor; ZRelocate _relocate; ZRelocationSet _relocation_set; + ZUnload _unload; ZServiceability _serviceability; size_t heap_min_size() const;
--- a/src/hotspot/share/gc/z/zMark.cpp Tue Dec 11 14:11:57 2018 +0000 +++ b/src/hotspot/share/gc/z/zMark.cpp Wed Dec 12 15:07:56 2018 +0530 @@ -287,6 +287,14 @@ } void ZMark::follow_array_object(objArrayOop obj, bool finalizable) { + if (finalizable) { + ZMarkBarrierOopClosure<true /* finalizable */> cl; + cl.do_klass(obj->klass()); + } else { + ZMarkBarrierOopClosure<false /* finalizable */> cl; + cl.do_klass(obj->klass()); + } + const uintptr_t addr = (uintptr_t)obj->base(); const size_t size = (size_t)obj->length() * oopSize;
--- a/src/hotspot/share/gc/z/zNMethodTable.cpp Tue Dec 11 14:11:57 2018 +0000 +++ b/src/hotspot/share/gc/z/zNMethodTable.cpp Wed Dec 12 15:07:56 2018 +0530 @@ -23,45 +23,62 @@ #include "precompiled.hpp" #include "code/relocInfo.hpp" -#include "code/nativeInst.hpp" #include "code/nmethod.hpp" +#include "code/icBuffer.hpp" +#include "gc/shared/barrierSet.hpp" +#include "gc/shared/barrierSetNMethod.hpp" +#include "gc/z/zArray.inline.hpp" #include "gc/z/zGlobals.hpp" #include "gc/z/zHash.inline.hpp" +#include "gc/z/zLock.inline.hpp" #include "gc/z/zNMethodTable.hpp" +#include "gc/z/zOopClosures.inline.hpp" +#include "gc/z/zTask.hpp" +#include "gc/z/zWorkers.hpp" #include "logging/log.hpp" #include "memory/allocation.inline.hpp" #include "memory/resourceArea.hpp" -#include "oops/oop.inline.hpp" #include "runtime/atomic.hpp" +#include "runtime/orderAccess.hpp" +#include "runtime/os.hpp" #include "utilities/debug.hpp" -class ZNMethodWithImmediateOops { +class ZNMethodDataImmediateOops { private: - nmethod* const _nm; - const size_t _nimmediate_oops; + const size_t _nimmediate_oops; static size_t header_size(); - ZNMethodWithImmediateOops(nmethod* nm, const GrowableArray<oop*>& immediate_oops); + ZNMethodDataImmediateOops(const GrowableArray<oop*>& immediate_oops); public: - static ZNMethodWithImmediateOops* create(nmethod* nm, const GrowableArray<oop*>& immediate_oops); - static void destroy(ZNMethodWithImmediateOops* nmi); + static ZNMethodDataImmediateOops* create(const GrowableArray<oop*>& immediate_oops); + static void destroy(ZNMethodDataImmediateOops* data_immediate_oops); - nmethod* method() const; size_t immediate_oops_count() const; oop** immediate_oops_begin() const; oop** immediate_oops_end() const; }; -size_t ZNMethodWithImmediateOops::header_size() { - const size_t size = sizeof(ZNMethodWithImmediateOops); +size_t ZNMethodDataImmediateOops::header_size() { + const size_t size = sizeof(ZNMethodDataImmediateOops); assert(is_aligned(size, sizeof(oop*)), "Header misaligned"); return size; } -ZNMethodWithImmediateOops::ZNMethodWithImmediateOops(nmethod* nm, const GrowableArray<oop*>& immediate_oops) : - _nm(nm), +ZNMethodDataImmediateOops* ZNMethodDataImmediateOops::create(const GrowableArray<oop*>& immediate_oops) { + // Allocate memory for the ZNMethodDataImmediateOops object + // plus the immediate oop* array that follows right after. + const size_t size = ZNMethodDataImmediateOops::header_size() + (sizeof(oop*) * immediate_oops.length()); + void* const data_immediate_oops = NEW_C_HEAP_ARRAY(uint8_t, size, mtGC); + return ::new (data_immediate_oops) ZNMethodDataImmediateOops(immediate_oops); +} + +void ZNMethodDataImmediateOops::destroy(ZNMethodDataImmediateOops* data_immediate_oops) { + ZNMethodTable::safe_delete(data_immediate_oops); +} + +ZNMethodDataImmediateOops::ZNMethodDataImmediateOops(const GrowableArray<oop*>& immediate_oops) : _nimmediate_oops(immediate_oops.length()) { // Save all immediate oops for (size_t i = 0; i < _nimmediate_oops; i++) { @@ -69,41 +86,97 @@ } } -ZNMethodWithImmediateOops* ZNMethodWithImmediateOops::create(nmethod* nm, const GrowableArray<oop*>& immediate_oops) { - // Allocate memory for the ZNMethodWithImmediateOops object - // plus the immediate oop* array that follows right after. - const size_t size = header_size() + (sizeof(oop*) * immediate_oops.length()); - void* const method_with_immediate_oops = NEW_C_HEAP_ARRAY(uint8_t, size, mtGC); - return ::new (method_with_immediate_oops) ZNMethodWithImmediateOops(nm, immediate_oops); -} - -void ZNMethodWithImmediateOops::destroy(ZNMethodWithImmediateOops* nmi) { - FREE_C_HEAP_ARRAY(uint8_t, nmi); -} - -nmethod* ZNMethodWithImmediateOops::method() const { - return _nm; -} - -size_t ZNMethodWithImmediateOops::immediate_oops_count() const { +size_t ZNMethodDataImmediateOops::immediate_oops_count() const { return _nimmediate_oops; } -oop** ZNMethodWithImmediateOops::immediate_oops_begin() const { +oop** ZNMethodDataImmediateOops::immediate_oops_begin() const { // The immediate oop* array starts immediately after this object return (oop**)((uintptr_t)this + header_size()); } -oop** ZNMethodWithImmediateOops::immediate_oops_end() const { +oop** ZNMethodDataImmediateOops::immediate_oops_end() const { return immediate_oops_begin() + immediate_oops_count(); } +class ZNMethodData { +private: + ZReentrantLock _lock; + ZNMethodDataImmediateOops* volatile _immediate_oops; + + ZNMethodData(nmethod* nm); + +public: + static ZNMethodData* create(nmethod* nm); + static void destroy(ZNMethodData* data); + + ZReentrantLock* lock(); + + ZNMethodDataImmediateOops* immediate_oops() const; + ZNMethodDataImmediateOops* swap_immediate_oops(const GrowableArray<oop*>& immediate_oops); +}; + +ZNMethodData* ZNMethodData::create(nmethod* nm) { + void* const method = NEW_C_HEAP_ARRAY(uint8_t, sizeof(ZNMethodData), mtGC); + return ::new (method) ZNMethodData(nm); +} + +void ZNMethodData::destroy(ZNMethodData* data) { + ZNMethodDataImmediateOops::destroy(data->immediate_oops()); + ZNMethodTable::safe_delete(data); +} + +ZNMethodData::ZNMethodData(nmethod* nm) : + _lock(), + _immediate_oops(NULL) {} + +ZReentrantLock* ZNMethodData::lock() { + return &_lock; +} + +ZNMethodDataImmediateOops* ZNMethodData::immediate_oops() const { + return OrderAccess::load_acquire(&_immediate_oops); +} + +ZNMethodDataImmediateOops* ZNMethodData::swap_immediate_oops(const GrowableArray<oop*>& immediate_oops) { + ZNMethodDataImmediateOops* const data_immediate_oops = + immediate_oops.is_empty() ? NULL : ZNMethodDataImmediateOops::create(immediate_oops); + return Atomic::xchg(data_immediate_oops, &_immediate_oops); +} + +static ZNMethodData* gc_data(const nmethod* nm) { + return nm->gc_data<ZNMethodData>(); +} + +static void set_gc_data(nmethod* nm, ZNMethodData* data) { + return nm->set_gc_data<ZNMethodData>(data); +} + ZNMethodTableEntry* ZNMethodTable::_table = NULL; size_t ZNMethodTable::_size = 0; +ZLock ZNMethodTable::_iter_lock; +ZNMethodTableEntry* ZNMethodTable::_iter_table = NULL; +size_t ZNMethodTable::_iter_table_size = 0; +ZArray<void*> ZNMethodTable::_iter_deferred_deletes; size_t ZNMethodTable::_nregistered = 0; size_t ZNMethodTable::_nunregistered = 0; volatile size_t ZNMethodTable::_claimed = 0; +void ZNMethodTable::safe_delete(void* data) { + if (data == NULL) { + return; + } + + ZLocker<ZLock> locker(&_iter_lock); + if (_iter_table != NULL) { + // Iteration in progress, defer delete + _iter_deferred_deletes.add(data); + } else { + // Iteration not in progress, delete now + FREE_C_HEAP_ARRAY(uint8_t, data); + } +} + ZNMethodTableEntry ZNMethodTable::create_entry(nmethod* nm) { GrowableArray<oop*> immediate_oops; bool non_immediate_oops = false; @@ -132,29 +205,27 @@ } } - // oops_count() returns the number of oops in the oop table plus one - if (immediate_oops.is_empty() && nm->oops_count() == 1) { - // No oops found, return empty entry - return ZNMethodTableEntry(); - } - - if (immediate_oops.is_empty()) { - // No immediate oops found, return entry without immediate oops - return ZNMethodTableEntry(nm, non_immediate_oops); + // Attach GC data to nmethod + ZNMethodData* data = gc_data(nm); + if (data == NULL) { + data = ZNMethodData::create(nm); + set_gc_data(nm, data); } - // Return entry with immediate oops - return ZNMethodTableEntry(ZNMethodWithImmediateOops::create(nm, immediate_oops), non_immediate_oops); + // Attach immediate oops in GC data + ZNMethodDataImmediateOops* const old_data_immediate_oops = data->swap_immediate_oops(immediate_oops); + ZNMethodDataImmediateOops::destroy(old_data_immediate_oops); + + // Create entry + return ZNMethodTableEntry(nm, non_immediate_oops, !immediate_oops.is_empty()); } -void ZNMethodTable::destroy_entry(ZNMethodTableEntry entry) { - if (entry.immediate_oops()) { - ZNMethodWithImmediateOops::destroy(entry.method_with_immediate_oops()); +ZReentrantLock* ZNMethodTable::lock_for_nmethod(nmethod* nm) { + ZNMethodData* const data = gc_data(nm); + if (data == NULL) { + return NULL; } -} - -nmethod* ZNMethodTable::method(ZNMethodTableEntry entry) { - return entry.immediate_oops() ? entry.method_with_immediate_oops()->method() : entry.method(); + return data->lock(); } size_t ZNMethodTable::first_index(const nmethod* nm, size_t size) { @@ -171,7 +242,7 @@ } bool ZNMethodTable::register_entry(ZNMethodTableEntry* table, size_t size, ZNMethodTableEntry entry) { - const nmethod* const nm = method(entry); + const nmethod* const nm = entry.method(); size_t index = first_index(nm, size); for (;;) { @@ -183,9 +254,8 @@ return true; } - if (table_entry.registered() && method(table_entry) == nm) { + if (table_entry.registered() && table_entry.method() == nm) { // Replace existing entry - destroy_entry(table_entry); table[index] = entry; return false; } @@ -194,7 +264,7 @@ } } -bool ZNMethodTable::unregister_entry(ZNMethodTableEntry* table, size_t size, const nmethod* nm) { +bool ZNMethodTable::unregister_entry(ZNMethodTableEntry* table, size_t size, nmethod* nm) { if (size == 0) { // Table is empty return false; @@ -210,10 +280,13 @@ return false; } - if (table_entry.registered() && method(table_entry) == nm) { + if (table_entry.registered() && table_entry.method() == nm) { // Remove entry - destroy_entry(table_entry); table[index] = ZNMethodTableEntry(true /* unregistered */); + + // Destroy GC data + ZNMethodData::destroy(gc_data(nm)); + set_gc_data(nm, NULL); return true; } @@ -222,6 +295,7 @@ } void ZNMethodTable::rebuild(size_t new_size) { + ZLocker<ZLock> locker(&_iter_lock); assert(is_power_of_2(new_size), "Invalid size"); log_debug(gc, nmethod)("Rebuilding NMethod Table: " @@ -243,8 +317,10 @@ } } - // Delete old table - delete [] _table; + if (_iter_table != _table) { + // Delete old table + delete [] _table; + } // Install new table _table = new_table; @@ -294,8 +370,8 @@ p2i(nm), nm->compiler_name(), nm->oops_count() - 1, - entry.immediate_oops() ? entry.method_with_immediate_oops()->immediate_oops_count() : 0, - BOOL_TO_STR(entry.non_immediate_oops())); + entry.immediate_oops() ? gc_data(nm)->immediate_oops()->immediate_oops_count() : 0, + entry.non_immediate_oops() ? "Yes" : "No"); LogTarget(Trace, gc, nmethod, oops) log_oops; if (!log_oops.is_enabled()) { @@ -312,12 +388,14 @@ if (entry.immediate_oops()) { // Print nmethod immediate oops - const ZNMethodWithImmediateOops* const nmi = entry.method_with_immediate_oops(); - oop** const begin = nmi->immediate_oops_begin(); - oop** const end = nmi->immediate_oops_end(); - for (oop** p = begin; p < end; p++) { - log_oops.print(" ImmediateOop[" SIZE_FORMAT "] " PTR_FORMAT " @ " PTR_FORMAT " (%s)", - (p - begin), p2i(**p), p2i(*p), (**p)->klass()->external_name()); + const ZNMethodDataImmediateOops* const nmi = gc_data(nm)->immediate_oops(); + if (nmi != NULL) { + oop** const begin = nmi->immediate_oops_begin(); + oop** const end = nmi->immediate_oops_end(); + for (oop** p = begin; p < end; p++) { + log_oops.print(" ImmediateOop[" SIZE_FORMAT "] " PTR_FORMAT " @ " PTR_FORMAT " (%s)", + (p - begin), p2i(**p), p2i(*p), (**p)->klass()->external_name()); + } } } } @@ -343,21 +421,17 @@ } void ZNMethodTable::register_nmethod(nmethod* nm) { + assert(CodeCache_lock->owned_by_self(), "Lock must be held"); ResourceMark rm; + // Grow/Shrink/Prune table if needed + rebuild_if_needed(); + // Create entry const ZNMethodTableEntry entry = create_entry(nm); log_register(nm, entry); - if (!entry.registered()) { - // Method doesn't have any oops, ignore it - return; - } - - // Grow/Shrink/Prune table if needed - rebuild_if_needed(); - // Insert new entry if (register_entry(_table, _size, entry)) { // New entry registered. When register_entry() instead returns @@ -365,11 +439,31 @@ // to increase number of registered entries in that case. _nregistered++; } + + // Disarm nmethod entry barrier + disarm_nmethod(nm); +} + +void ZNMethodTable::sweeper_wait_for_iteration() { + // The sweeper must wait for any ongoing iteration to complete + // before it can unregister an nmethod. + if (!Thread::current()->is_Code_cache_sweeper_thread()) { + return; + } + + assert(CodeCache_lock->owned_by_self(), "Lock must be held"); + + while (_iter_table != NULL) { + MutexUnlockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); + os::naked_short_sleep(1); + } } void ZNMethodTable::unregister_nmethod(nmethod* nm) { ResourceMark rm; + sweeper_wait_for_iteration(); + log_unregister(nm); // Remove entry @@ -383,20 +477,45 @@ } } -void ZNMethodTable::gc_prologue() { +void ZNMethodTable::disarm_nmethod(nmethod* nm) { + BarrierSetNMethod* const bs = BarrierSet::barrier_set()->barrier_set_nmethod(); + if (bs != NULL) { + bs->disarm(nm); + } +} + +void ZNMethodTable::nmethod_entries_do_begin() { + MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); + ZLocker<ZLock> locker(&_iter_lock); + + // Prepare iteration + _iter_table = _table; + _iter_table_size = _size; _claimed = 0; + assert(_iter_deferred_deletes.is_empty(), "Should be emtpy"); } -void ZNMethodTable::gc_epilogue() { - assert(_claimed >= _size, "Failed to claim all table entries"); +void ZNMethodTable::nmethod_entries_do_end() { + MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); + ZLocker<ZLock> locker(&_iter_lock); + + // Finish iteration + if (_iter_table != _table) { + delete [] _iter_table; + } + _iter_table = NULL; + assert(_claimed >= _iter_table_size, "Failed to claim all table entries"); + + // Process deferred deletes + ZArrayIterator<void*> iter(&_iter_deferred_deletes); + for (void* data; iter.next(&data);) { + FREE_C_HEAP_ARRAY(uint8_t, data); + } + _iter_deferred_deletes.clear(); } void ZNMethodTable::entry_oops_do(ZNMethodTableEntry entry, OopClosure* cl) { - nmethod* const nm = method(entry); - if (!nm->is_alive()) { - // No need to visit oops - return; - } + nmethod* const nm = entry.method(); // Process oops table oop* const begin = nm->oops_begin(); @@ -407,29 +526,52 @@ } } + // Process immediate oops if (entry.immediate_oops()) { - // Process immediate oops - const ZNMethodWithImmediateOops* const nmi = entry.method_with_immediate_oops(); - oop** const begin = nmi->immediate_oops_begin(); - oop** const end = nmi->immediate_oops_end(); - for (oop** p = begin; p < end; p++) { - cl->do_oop(*p); + const ZNMethodDataImmediateOops* const nmi = gc_data(nm)->immediate_oops(); + if (nmi != NULL) { + oop** const begin = nmi->immediate_oops_begin(); + oop** const end = nmi->immediate_oops_end(); + for (oop** p = begin; p < end; p++) { + if (**p != Universe::non_oop_word()) { + cl->do_oop(*p); + } + } } } + // Process non-immediate oops if (entry.non_immediate_oops()) { - // Process non-immediate oops + nmethod* const nm = entry.method(); nm->fix_oop_relocations(); } } +class ZNMethodTableEntryToOopsDo : public ZNMethodTableEntryClosure { +private: + OopClosure* _cl; + +public: + ZNMethodTableEntryToOopsDo(OopClosure* cl) : + _cl(cl) {} + + void do_nmethod_entry(ZNMethodTableEntry entry) { + ZNMethodTable::entry_oops_do(entry, _cl); + } +}; + void ZNMethodTable::oops_do(OopClosure* cl) { + ZNMethodTableEntryToOopsDo entry_cl(cl); + nmethod_entries_do(&entry_cl); +} + +void ZNMethodTable::nmethod_entries_do(ZNMethodTableEntryClosure* cl) { for (;;) { // Claim table partition. Each partition is currently sized to span // two cache lines. This number is just a guess, but seems to work well. const size_t partition_size = (ZCacheLineSize * 2) / sizeof(ZNMethodTableEntry); - const size_t partition_start = MIN2(Atomic::add(partition_size, &_claimed) - partition_size, _size); - const size_t partition_end = MIN2(partition_start + partition_size, _size); + const size_t partition_start = MIN2(Atomic::add(partition_size, &_claimed) - partition_size, _iter_table_size); + const size_t partition_end = MIN2(partition_start + partition_size, _iter_table_size); if (partition_start == partition_end) { // End of table break; @@ -437,10 +579,141 @@ // Process table partition for (size_t i = partition_start; i < partition_end; i++) { - const ZNMethodTableEntry entry = _table[i]; + const ZNMethodTableEntry entry = _iter_table[i]; if (entry.registered()) { - entry_oops_do(entry, cl); + cl->do_nmethod_entry(entry); } } } } + +class ZNMethodTableUnlinkClosure : public ZNMethodTableEntryClosure { +private: + bool _unloading_occurred; + volatile bool _failed; + + void set_failed() { + Atomic::store(true, &_failed); + } + +public: + ZNMethodTableUnlinkClosure(bool unloading_occurred) : + _unloading_occurred(unloading_occurred), + _failed(false) {} + + virtual void do_nmethod_entry(ZNMethodTableEntry entry) { + if (failed()) { + return; + } + + nmethod* const nm = entry.method(); + if (!nm->is_alive()) { + return; + } + + if (nm->is_unloading()) { + // Unlinking of the dependencies must happen before the + // handshake separating unlink and purge. + nm->flush_dependencies(false /* delete_immediately */); + return; + } + + ZLocker<ZReentrantLock> locker(ZNMethodTable::lock_for_nmethod(nm)); + + // Heal oops and disarm + ZNMethodOopClosure cl; + ZNMethodTable::entry_oops_do(entry, &cl); + ZNMethodTable::disarm_nmethod(nm); + + // Clear compiled ICs and exception caches + if (!nm->unload_nmethod_caches(_unloading_occurred)) { + set_failed(); + } + } + + bool failed() const { + return Atomic::load(&_failed); + } +}; + +class ZNMethodTableUnlinkTask : public ZTask { +private: + ZNMethodTableUnlinkClosure _cl; + ICRefillVerifier* _verifier; + +public: + ZNMethodTableUnlinkTask(bool unloading_occurred, ICRefillVerifier* verifier) : + ZTask("ZNMethodTableUnlinkTask"), + _cl(unloading_occurred), + _verifier(verifier) { + ZNMethodTable::nmethod_entries_do_begin(); + } + + ~ZNMethodTableUnlinkTask() { + ZNMethodTable::nmethod_entries_do_end(); + } + + virtual void work() { + ICRefillVerifierMark mark(_verifier); + ZNMethodTable::nmethod_entries_do(&_cl); + } + + bool success() const { + return !_cl.failed(); + } +}; + +void ZNMethodTable::unlink(ZWorkers* workers, bool unloading_occurred) { + for (;;) { + ICRefillVerifier verifier; + + { + ZNMethodTableUnlinkTask task(unloading_occurred, &verifier); + workers->run_concurrent(&task); + if (task.success()) { + return; + } + } + + // Cleaning failed because we ran out of transitional IC stubs, + // so we have to refill and try again. Refilling requires taking + // a safepoint, so we temporarily leave the suspendible thread set. + SuspendibleThreadSetLeaver sts; + InlineCacheBuffer::refill_ic_stubs(); + } +} + +class ZNMethodTablePurgeClosure : public ZNMethodTableEntryClosure { +public: + virtual void do_nmethod_entry(ZNMethodTableEntry entry) { + nmethod* const nm = entry.method(); + if (nm->is_alive() && nm->is_unloading()) { + nm->make_unloaded(); + } + } +}; + +class ZNMethodTablePurgeTask : public ZTask { +private: + ZNMethodTablePurgeClosure _cl; + +public: + ZNMethodTablePurgeTask() : + ZTask("ZNMethodTablePurgeTask"), + _cl() { + ZNMethodTable::nmethod_entries_do_begin(); + } + + ~ZNMethodTablePurgeTask() { + ZNMethodTable::nmethod_entries_do_end(); + } + + virtual void work() { + ZNMethodTable::nmethod_entries_do(&_cl); + } +}; + +void ZNMethodTable::purge(ZWorkers* workers) { + ZNMethodTablePurgeTask task; + workers->run_concurrent(&task); +}
--- a/src/hotspot/share/gc/z/zNMethodTable.hpp Tue Dec 11 14:11:57 2018 +0000 +++ b/src/hotspot/share/gc/z/zNMethodTable.hpp Wed Dec 12 15:07:56 2018 +0530 @@ -24,28 +24,40 @@ #ifndef SHARE_GC_Z_ZNMETHODTABLE_HPP #define SHARE_GC_Z_ZNMETHODTABLE_HPP +#include "gc/z/zArray.hpp" #include "gc/z/zGlobals.hpp" +#include "gc/z/zLock.hpp" #include "gc/z/zNMethodTableEntry.hpp" #include "memory/allocation.hpp" +class ZWorkers; + +class ZNMethodTableEntryClosure { +public: + virtual void do_nmethod_entry(ZNMethodTableEntry entry) = 0; +}; + class ZNMethodTable : public AllStatic { private: static ZNMethodTableEntry* _table; static size_t _size; + static ZLock _iter_lock; + static ZNMethodTableEntry* _iter_table; + static size_t _iter_table_size; + static ZArray<void*> _iter_deferred_deletes; static size_t _nregistered; static size_t _nunregistered; static volatile size_t _claimed ATTRIBUTE_ALIGNED(ZCacheLineSize); static ZNMethodTableEntry create_entry(nmethod* nm); - static void destroy_entry(ZNMethodTableEntry entry); - - static nmethod* method(ZNMethodTableEntry entry); static size_t first_index(const nmethod* nm, size_t size); static size_t next_index(size_t prev_index, size_t size); + static void sweeper_wait_for_iteration(); + static bool register_entry(ZNMethodTableEntry* table, size_t size, ZNMethodTableEntry entry); - static bool unregister_entry(ZNMethodTableEntry* table, size_t size, const nmethod* nm); + static bool unregister_entry(ZNMethodTableEntry* table, size_t size, nmethod* nm); static void rebuild(size_t new_size); static void rebuild_if_needed(); @@ -53,19 +65,28 @@ static void log_register(const nmethod* nm, ZNMethodTableEntry entry); static void log_unregister(const nmethod* nm); - static void entry_oops_do(ZNMethodTableEntry entry, OopClosure* cl); +public: + static void safe_delete(void* data); -public: static size_t registered_nmethods(); static size_t unregistered_nmethods(); static void register_nmethod(nmethod* nm); static void unregister_nmethod(nmethod* nm); + static void disarm_nmethod(nmethod* nm); - static void gc_prologue(); - static void gc_epilogue(); + static ZReentrantLock* lock_for_nmethod(nmethod* nm); static void oops_do(OopClosure* cl); + + static void entry_oops_do(ZNMethodTableEntry entry, OopClosure* cl); + + static void nmethod_entries_do_begin(); + static void nmethod_entries_do_end(); + static void nmethod_entries_do(ZNMethodTableEntryClosure* cl); + + static void unlink(ZWorkers* workers, bool unloading_occurred); + static void purge(ZWorkers* workers); }; #endif // SHARE_GC_Z_ZNMETHODTABLE_HPP
--- a/src/hotspot/share/gc/z/zNMethodTableEntry.hpp Tue Dec 11 14:11:57 2018 +0000 +++ b/src/hotspot/share/gc/z/zNMethodTableEntry.hpp Wed Dec 12 15:07:56 2018 +0530 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -43,38 +43,30 @@ // | | // | 0-0 Registered Flag (1-bits) * // | -// * 63-3 NMethod/ZNMethodWithImmediateOops Address (61-bits) +// * 63-3 NMethod Address (61-bits) // class nmethod; -class ZNMethodWithImmediateOops; class ZNMethodTableEntry : public CHeapObj<mtGC> { private: - typedef ZBitField<uint64_t, bool, 0, 1> field_registered; - typedef ZBitField<uint64_t, bool, 1, 1> field_unregistered; - typedef ZBitField<uint64_t, bool, 1, 1> field_immediate_oops; - typedef ZBitField<uint64_t, bool, 2, 1> field_non_immediate_oops; - typedef ZBitField<uint64_t, nmethod*, 3, 61, 3> field_method; - typedef ZBitField<uint64_t, ZNMethodWithImmediateOops*, 3, 61, 3> field_method_with_immediate_oops; + typedef ZBitField<uint64_t, bool, 0, 1> field_registered; + typedef ZBitField<uint64_t, bool, 1, 1> field_unregistered; + typedef ZBitField<uint64_t, bool, 1, 1> field_immediate_oops; + typedef ZBitField<uint64_t, bool, 2, 1> field_non_immediate_oops; + typedef ZBitField<uint64_t, nmethod*, 3, 61, 3> field_method; uint64_t _entry; public: - ZNMethodTableEntry(bool unregistered = false) : + explicit ZNMethodTableEntry(bool unregistered = false) : _entry(field_unregistered::encode(unregistered) | field_registered::encode(false)) {} - ZNMethodTableEntry(nmethod* method, bool non_immediate_oops) : + ZNMethodTableEntry(nmethod* method, bool non_immediate_oops, bool immediate_oops) : _entry(field_method::encode(method) | field_non_immediate_oops::encode(non_immediate_oops) | - field_immediate_oops::encode(false) | - field_registered::encode(true)) {} - - ZNMethodTableEntry(ZNMethodWithImmediateOops* method_with_immediate_oops, bool non_immediate_oops) : - _entry(field_method_with_immediate_oops::encode(method_with_immediate_oops) | - field_non_immediate_oops::encode(non_immediate_oops) | - field_immediate_oops::encode(true) | + field_immediate_oops::encode(immediate_oops) | field_registered::encode(true)) {} bool registered() const { @@ -96,10 +88,6 @@ nmethod* method() const { return field_method::decode(_entry); } - - ZNMethodWithImmediateOops* method_with_immediate_oops() const { - return field_method_with_immediate_oops::decode(_entry); - } }; #endif // SHARE_GC_Z_ZNMETHODTABLEENTRY_HPP
--- a/src/hotspot/share/gc/z/zOopClosures.hpp Tue Dec 11 14:11:57 2018 +0000 +++ b/src/hotspot/share/gc/z/zOopClosures.hpp Wed Dec 12 15:07:56 2018 +0530 @@ -39,14 +39,23 @@ #endif }; +class ZNMethodOopClosure : public OopClosure { +public: + virtual void do_oop(oop* p); + virtual void do_oop(narrowOop* p); +}; + template <bool finalizable> -class ZMarkBarrierOopClosure : public BasicOopIterateClosure { +class ZMarkBarrierOopClosure : public MetadataVisitingOopIterateClosure { public: ZMarkBarrierOopClosure(); virtual void do_oop(oop* p); virtual void do_oop(narrowOop* p); + virtual void do_klass(Klass* k); + virtual void do_cld(ClassLoaderData* cld); + #ifdef ASSERT virtual bool should_verify_oops() { return false;
--- a/src/hotspot/share/gc/z/zOopClosures.inline.hpp Tue Dec 11 14:11:57 2018 +0000 +++ b/src/hotspot/share/gc/z/zOopClosures.inline.hpp Wed Dec 12 15:07:56 2018 +0530 @@ -24,6 +24,7 @@ #ifndef SHARE_GC_Z_ZOOPCLOSURES_INLINE_HPP #define SHARE_GC_Z_ZOOPCLOSURES_INLINE_HPP +#include "classfile/classLoaderData.hpp" #include "gc/z/zBarrier.inline.hpp" #include "gc/z/zHeap.inline.hpp" #include "gc/z/zOop.inline.hpp" @@ -40,9 +41,21 @@ ShouldNotReachHere(); } +inline void ZNMethodOopClosure::do_oop(oop* p) { + if (ZResurrection::is_blocked()) { + ZBarrier::keep_alive_barrier_on_phantom_root_oop_field(p); + } else { + ZBarrier::load_barrier_on_root_oop_field(p); + } +} + +inline void ZNMethodOopClosure::do_oop(narrowOop* p) { + ShouldNotReachHere(); +} + template <bool finalizable> inline ZMarkBarrierOopClosure<finalizable>::ZMarkBarrierOopClosure() : - BasicOopIterateClosure(finalizable ? NULL : ZHeap::heap()->reference_discoverer()) {} + MetadataVisitingOopIterateClosure(finalizable ? NULL : ZHeap::heap()->reference_discoverer()) {} template <bool finalizable> inline void ZMarkBarrierOopClosure<finalizable>::do_oop(oop* p) { @@ -54,6 +67,18 @@ ShouldNotReachHere(); } +template <bool finalizable> +inline void ZMarkBarrierOopClosure<finalizable>::do_klass(Klass* k) { + ClassLoaderData* const cld = k->class_loader_data(); + ZMarkBarrierOopClosure<finalizable>::do_cld(cld); +} + +template <bool finalizable> +inline void ZMarkBarrierOopClosure<finalizable>::do_cld(ClassLoaderData* cld) { + const int claim = finalizable ? ClassLoaderData::_claim_finalizable : ClassLoaderData::_claim_strong; + cld->oops_do(this, claim); +} + inline bool ZPhantomIsAliveObjectClosure::do_object_b(oop o) { return ZBarrier::is_alive_barrier_on_phantom_oop(o); }
--- a/src/hotspot/share/gc/z/zRootsIterator.cpp Tue Dec 11 14:11:57 2018 +0000 +++ b/src/hotspot/share/gc/z/zRootsIterator.cpp Wed Dec 12 15:07:56 2018 +0530 @@ -27,8 +27,11 @@ #include "classfile/systemDictionary.hpp" #include "code/codeCache.hpp" #include "compiler/oopMap.hpp" +#include "gc/shared/barrierSet.hpp" +#include "gc/shared/barrierSetNMethod.hpp" #include "gc/shared/oopStorageParState.inline.hpp" #include "gc/shared/suspendibleThreadSet.hpp" +#include "gc/z/zBarrierSetNMethod.hpp" #include "gc/z/zGlobals.hpp" #include "gc/z/zNMethodTable.hpp" #include "gc/z/zOopClosures.inline.hpp" @@ -132,6 +135,30 @@ } } +class ZCodeBlobClosure : public CodeBlobToOopClosure { +private: + BarrierSetNMethod* _bs; + +public: + ZCodeBlobClosure(OopClosure* cl) : + CodeBlobToOopClosure(cl, true /* fix_relocations */), + _bs(BarrierSet::barrier_set()->barrier_set_nmethod()) {} + + virtual void do_code_blob(CodeBlob* cb) { + nmethod* const nm = cb->as_nmethod_or_null(); + if (nm == NULL || nm->test_set_oops_do_mark()) { + return; + } + CodeBlobToOopClosure::do_code_blob(cb); + _bs->disarm(nm); + } +}; + +void ZRootsIteratorClosure::do_thread(Thread* thread) { + ZCodeBlobClosure code_cl(this); + thread->oops_do(this, ClassUnloading ? &code_cl : NULL); +} + ZRootsIterator::ZRootsIterator() : _universe(this), _object_synchronizer(this), @@ -145,16 +172,23 @@ ZStatTimer timer(ZSubPhasePauseRootsSetup); Threads::change_thread_claim_parity(); COMPILER2_PRESENT(DerivedPointerTable::clear()); - CodeCache::gc_prologue(); - ZNMethodTable::gc_prologue(); + if (ClassUnloading) { + nmethod::oops_do_marking_prologue(); + } else { + ZNMethodTable::nmethod_entries_do_begin(); + } } ZRootsIterator::~ZRootsIterator() { ZStatTimer timer(ZSubPhasePauseRootsTeardown); ResourceMark rm; - ZNMethodTable::gc_epilogue(); - CodeCache::gc_epilogue(); + if (ClassUnloading) { + nmethod::oops_do_marking_epilogue(); + } else { + ZNMethodTable::nmethod_entries_do_end(); + } JvmtiExport::gc_epilogue(); + COMPILER2_PRESENT(DerivedPointerTable::update_pointers()); Threads::assert_all_threads_claimed(); } @@ -209,7 +243,9 @@ _jvmti_export.oops_do(cl); _system_dictionary.oops_do(cl); _threads.oops_do(cl); - _code_cache.oops_do(cl); + if (!ClassUnloading) { + _code_cache.oops_do(cl); + } if (visit_jvmti_weak_export) { _jvmti_weak_export.oops_do(cl); } @@ -242,8 +278,13 @@ void ZConcurrentRootsIterator::do_class_loader_data_graph(ZRootsIteratorClosure* cl) { ZStatTimer timer(ZSubPhaseConcurrentRootsClassLoaderDataGraph); - CLDToOopClosure cld_cl(cl, _marking ? ClassLoaderData::_claim_strong : ClassLoaderData::_claim_none); - ClassLoaderDataGraph::cld_do(&cld_cl); + if (_marking) { + CLDToOopClosure cld_cl(cl, ClassLoaderData::_claim_strong); + ClassLoaderDataGraph::always_strong_cld_do(&cld_cl); + } else { + CLDToOopClosure cld_cl(cl, ClassLoaderData::_claim_none); + ClassLoaderDataGraph::cld_do(&cld_cl); + } } void ZConcurrentRootsIterator::oops_do(ZRootsIteratorClosure* cl) {
--- a/src/hotspot/share/gc/z/zRootsIterator.hpp Tue Dec 11 14:11:57 2018 +0000 +++ b/src/hotspot/share/gc/z/zRootsIterator.hpp Wed Dec 12 15:07:56 2018 +0530 @@ -33,9 +33,7 @@ class ZRootsIteratorClosure : public OopClosure, public ThreadClosure { public: - virtual void do_thread(Thread* thread) { - thread->oops_do(this, NULL); - } + virtual void do_thread(Thread* thread); }; typedef OopStorage::ParState<true /* concurrent */, false /* is_const */> ZOopStorageIterator;
--- a/src/hotspot/share/gc/z/zThreadLocalData.hpp Tue Dec 11 14:11:57 2018 +0000 +++ b/src/hotspot/share/gc/z/zThreadLocalData.hpp Wed Dec 12 15:07:56 2018 +0530 @@ -25,6 +25,7 @@ #define SHARE_GC_Z_ZTHREADLOCALDATA_HPP #include "gc/z/zMarkStack.hpp" +#include "gc/z/zGlobals.hpp" #include "runtime/thread.hpp" #include "utilities/debug.hpp" #include "utilities/sizes.hpp" @@ -62,6 +63,10 @@ static ByteSize address_bad_mask_offset() { return Thread::gc_data_offset() + byte_offset_of(ZThreadLocalData, _address_bad_mask); } + + static ByteSize nmethod_disarmed_offset() { + return address_bad_mask_offset() + in_ByteSize(ZNMethodDisarmedOffset); + } }; #endif // SHARE_GC_Z_ZTHREADLOCALDATA_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/hotspot/share/gc/z/zUnload.cpp Wed Dec 12 15:07:56 2018 +0530 @@ -0,0 +1,194 @@ +/* + * Copyright (c) 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. + */ + +#include "precompiled.hpp" +#include "classfile/classLoaderDataGraph.hpp" +#include "classfile/systemDictionary.hpp" +#include "code/codeBehaviours.hpp" +#include "code/codeCache.hpp" +#include "code/dependencyContext.hpp" +#include "gc/shared/gcBehaviours.hpp" +#include "gc/shared/suspendibleThreadSet.hpp" +#include "gc/z/zLock.inline.hpp" +#include "gc/z/zNMethodTable.hpp" +#include "gc/z/zOopClosures.hpp" +#include "gc/z/zStat.hpp" +#include "gc/z/zUnload.hpp" +#include "oops/access.inline.hpp" + +static const ZStatSubPhase ZSubPhaseConcurrentClassesUnload("Concurrent Classes Unload"); + +class ZIsUnloadingOopClosure : public OopClosure { +private: + ZPhantomIsAliveObjectClosure _is_alive; + bool _is_unloading; + +public: + ZIsUnloadingOopClosure() : + _is_alive(), + _is_unloading(false) {} + + virtual void do_oop(oop* p) { + const oop o = RawAccess<>::oop_load(p); + if (o != NULL && !_is_alive.do_object_b(o)) { + _is_unloading = true; + } + } + + virtual void do_oop(narrowOop* p) { + ShouldNotReachHere(); + } + + bool is_unloading() const { + return _is_unloading; + } +}; + +class ZIsUnloadingBehaviour : public IsUnloadingBehaviour { +private: + bool is_unloading(nmethod* nm) const { + ZIsUnloadingOopClosure cl; + nm->oops_do(&cl, true /* allow_zombie */); + return cl.is_unloading(); + } + +public: + virtual bool is_unloading(CompiledMethod* method) const { + nmethod* const nm = method->as_nmethod(); + ZReentrantLock* const lock = ZNMethodTable::lock_for_nmethod(nm); + if (lock == NULL) { + return is_unloading(nm); + } else { + ZLocker<ZReentrantLock> locker(lock); + return is_unloading(nm); + } + } +}; + +class ZCompiledICProtectionBehaviour : public CompiledICProtectionBehaviour { +public: + virtual bool lock(CompiledMethod* method) { + nmethod* const nm = method->as_nmethod(); + ZReentrantLock* const lock = ZNMethodTable::lock_for_nmethod(nm); + if (lock != NULL) { + lock->lock(); + } + return true; + } + + virtual void unlock(CompiledMethod* method) { + nmethod* const nm = method->as_nmethod(); + ZReentrantLock* const lock = ZNMethodTable::lock_for_nmethod(nm); + if (lock != NULL) { + lock->unlock(); + } + } + + virtual bool is_safe(CompiledMethod* method) { + if (SafepointSynchronize::is_at_safepoint()) { + return true; + } + + nmethod* const nm = method->as_nmethod(); + ZReentrantLock* const lock = ZNMethodTable::lock_for_nmethod(nm); + return lock == NULL || lock->is_owned(); + } +}; + +ZUnload::ZUnload(ZWorkers* workers) : + _workers(workers) { + + if (!ClassUnloading) { + return; + } + + static ZIsUnloadingBehaviour is_unloading_behaviour; + IsUnloadingBehaviour::set_current(&is_unloading_behaviour); + + static ZCompiledICProtectionBehaviour ic_protection_behaviour; + CompiledICProtectionBehaviour::set_current(&ic_protection_behaviour); +} + +void ZUnload::prepare() { + if (!ClassUnloading) { + return; + } + + CodeCache::increment_unloading_cycle(); + DependencyContext::cleaning_start(); +} + +void ZUnload::unlink() { + SuspendibleThreadSetJoiner sts; + bool unloading_occurred; + + { + MutexLockerEx ml(ClassLoaderDataGraph_lock); + unloading_occurred = SystemDictionary::do_unloading(ZStatPhase::timer()); + } + + Klass::clean_weak_klass_links(unloading_occurred); + + ZNMethodTable::unlink(_workers, unloading_occurred); + + DependencyContext::cleaning_end(); +} + +void ZUnload::purge() { + { + SuspendibleThreadSetJoiner sts; + ZNMethodTable::purge(_workers); + } + + ClassLoaderDataGraph::purge(); + CodeCache::purge_exception_caches(); +} + +class ZUnloadRendezvousClosure : public ThreadClosure { +public: + void do_thread(Thread* thread) {} +}; + +void ZUnload::unload() { + if (!ClassUnloading) { + return; + } + + ZStatTimer timer(ZSubPhaseConcurrentClassesUnload); + + // Unlink stale metadata and nmethods + unlink(); + + // Make sure stale metadata and nmethods are no longer observable + ZUnloadRendezvousClosure cl; + Handshake::execute(&cl); + + // Purge stale metadata and nmethods that were unlinked + purge(); +} + +void ZUnload::finish() { + // Resize and verify metaspace + MetaspaceGC::compute_new_size(); + MetaspaceUtils::verify_metrics(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/hotspot/share/gc/z/zUnload.hpp Wed Dec 12 15:07:56 2018 +0530 @@ -0,0 +1,44 @@ +/* + * Copyright (c) 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. + */ + +#ifndef SHARE_GC_Z_ZUNLOAD_HPP +#define SHARE_GC_Z_ZUNLOAD_HPP + +class ZWorkers; + +class ZUnload { +private: + ZWorkers* const _workers; + + void unlink(); + void purge(); + +public: + ZUnload(ZWorkers* workers); + + void prepare(); + void unload(); + void finish(); +}; + +#endif // SHARE_GC_Z_ZUNLOAD_HPP
--- a/src/hotspot/share/runtime/thread.cpp Tue Dec 11 14:11:57 2018 +0000 +++ b/src/hotspot/share/runtime/thread.cpp Wed Dec 12 15:07:56 2018 +0530 @@ -306,15 +306,19 @@ } #endif // ASSERT - // Notify the barrier set that a thread is being created. Note that some - // threads are created before a barrier set is available. The call to - // BarrierSet::on_thread_create() for these threads is therefore deferred + // Notify the barrier set that a thread is being created. The initial + // thread is created before the barrier set is available. The call to + // BarrierSet::on_thread_create() for this thread is therefore deferred // to BarrierSet::set_barrier_set(). BarrierSet* const barrier_set = BarrierSet::barrier_set(); if (barrier_set != NULL) { barrier_set->on_thread_create(this); } else { - DEBUG_ONLY(Threads::inc_threads_before_barrier_set();) +#ifdef ASSERT + static bool initial_thread_created = false; + assert(!initial_thread_created, "creating thread before barrier set"); + initial_thread_created = true; +#endif // ASSERT } } @@ -3395,7 +3399,6 @@ #ifdef ASSERT bool Threads::_vm_complete = false; -size_t Threads::_threads_before_barrier_set = 0; #endif static inline void *prefetch_and_load_ptr(void **addr, intx prefetch_interval) {
--- a/src/hotspot/share/runtime/thread.hpp Tue Dec 11 14:11:57 2018 +0000 +++ b/src/hotspot/share/runtime/thread.hpp Wed Dec 12 15:07:56 2018 +0530 @@ -2156,7 +2156,6 @@ static int _thread_claim_parity; #ifdef ASSERT static bool _vm_complete; - static size_t _threads_before_barrier_set; #endif static void initialize_java_lang_classes(JavaThread* main_thread, TRAPS); @@ -2226,14 +2225,6 @@ #ifdef ASSERT static bool is_vm_complete() { return _vm_complete; } - - static size_t threads_before_barrier_set() { - return _threads_before_barrier_set; - } - - static void inc_threads_before_barrier_set() { - ++_threads_before_barrier_set; - } #endif // ASSERT // Verification
--- a/src/java.base/share/classes/java/lang/Character.java Tue Dec 11 14:11:57 2018 +0000 +++ b/src/java.base/share/classes/java/lang/Character.java Wed Dec 12 15:07:56 2018 +0530 @@ -681,11 +681,12 @@ */ public static final class UnicodeBlock extends Subset { /** - * 649 - the expected number of entities + * 667 - the expected number of entities * 0.75 - the default load factor of HashMap */ + private static final int NUM_ENTITIES = 667; private static Map<String, UnicodeBlock> map = - new HashMap<>((int)(649 / 0.75f + 1.0f)); + new HashMap<>((int)(NUM_ENTITIES / 0.75f + 1.0f)); /** * Creates a UnicodeBlock with the given identifier name.
--- a/src/java.base/share/classes/java/lang/Object.java Tue Dec 11 14:11:57 2018 +0000 +++ b/src/java.base/share/classes/java/lang/Object.java Wed Dec 12 15:07:56 2018 +0530 @@ -94,12 +94,10 @@ * programmer should be aware that producing distinct integer results * for unequal objects may improve the performance of hash tables. * </ul> - * <p> - * As much as is reasonably practical, the hashCode method defined - * by class {@code Object} does return distinct integers for - * distinct objects. (The hashCode may or may not be implemented - * as some function of an object's memory address at some point - * in time.) + * + * @implSpec + * As far as is reasonably practical, the {@code hashCode} method defined + * by class {@code Object} returns distinct integers for distinct objects. * * @return a hash code value for this object. * @see java.lang.Object#equals(java.lang.Object)
--- a/src/java.base/share/classes/java/net/URI.java Tue Dec 11 14:11:57 2018 +0000 +++ b/src/java.base/share/classes/java/net/URI.java Wed Dec 12 15:07:56 2018 +0530 @@ -25,6 +25,7 @@ package java.net; +import java.io.File; import java.io.IOException; import java.io.InvalidObjectException; import java.io.ObjectInputStream; @@ -36,6 +37,7 @@ import java.nio.charset.CoderResult; import java.nio.charset.CodingErrorAction; import java.nio.charset.CharacterCodingException; +import java.nio.file.Path; import java.text.Normalizer; import jdk.internal.access.JavaNetUriAccess; import jdk.internal.access.SharedSecrets; @@ -458,6 +460,27 @@ * resolution as well as the network I/O operations of looking up the host and * opening a connection to the specified resource. * + * @apiNote + * + * Applications working with file paths and file URIs should take great + * care to use the appropriate methods to convert between the two. + * The {@link Path#of(URI)} factory method and the {@link File#File(URI)} + * constructor can be used to create {@link Path} or {@link File} + * objects from a file URI. {@link Path#toUri()} and {@link File#toURI()} + * can be used to create a {@link URI} from a file path. + * Applications should never try to {@linkplain + * #URI(String, String, String, int, String, String, String) + * construct}, {@linkplain #URI(String) parse}, or + * {@linkplain #resolve(String) resolve} a {@code URI} + * from the direct string representation of a {@code File} or {@code Path} + * instance. + * <p> + * Some components of a URL or URI, such as <i>userinfo</i>, may + * be abused to construct misleading URLs or URIs. Applications + * that deal with URLs or URIs should take into account + * the recommendations advised in <a + * href="https://tools.ietf.org/html/rfc3986#section-7">RFC3986, + * Section 7, Security Considerations</a>. * * @author Mark Reinhold * @since 1.4
--- a/src/java.base/share/classes/java/net/URL.java Tue Dec 11 14:11:57 2018 +0000 +++ b/src/java.base/share/classes/java/net/URL.java Wed Dec 12 15:07:56 2018 +0530 @@ -25,9 +25,11 @@ package java.net; +import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.spi.URLStreamHandlerProvider; +import java.nio.file.Path; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.Hashtable; @@ -145,6 +147,27 @@ * used, but only for HTML form encoding, which is not the same * as the encoding scheme defined in RFC2396. * + * @apiNote + * + * Applications working with file paths and file URIs should take great + * care to use the appropriate methods to convert between the two. + * The {@link Path#of(URI)} factory method and the {@link File#File(URI)} + * constructor can be used to create {@link Path} or {@link File} + * objects from a file URI. {@link Path#toUri()} and {@link File#toURI()} + * can be used to create a {@link URI} from a file path, which can be + * converted to URL using {@link URI#toURL()}. + * Applications should never try to {@linkplain #URL(String, String, String) + * construct} or {@linkplain #URL(String) parse} a {@code URL} + * from the direct string representation of a {@code File} or {@code Path} + * instance. + * <p> + * Some components of a URL or URI, such as <i>userinfo</i>, may + * be abused to construct misleading URLs or URIs. Applications + * that deal with URLs or URIs should take into account + * the recommendations advised in <a + * href="https://tools.ietf.org/html/rfc3986#section-7">RFC3986, + * Section 7, Security Considerations</a>. + * * @author James Gosling * @since 1.0 */
--- a/src/java.base/share/classes/java/util/SplittableRandom.java Tue Dec 11 14:11:57 2018 +0000 +++ b/src/java.base/share/classes/java/util/SplittableRandom.java Wed Dec 12 15:07:56 2018 +0530 @@ -80,7 +80,7 @@ * in security-sensitive applications. Additionally, * default-constructed instances do not use a cryptographically random * seed unless the {@linkplain System#getProperty system property} - * {@code java.util.secureRandomSeed} is set to {@code true}. + * {@systemProperty java.util.secureRandomSeed} is set to {@code true}. * * @author Guy Steele * @author Doug Lea
--- a/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java Tue Dec 11 14:11:57 2018 +0000 +++ b/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java Wed Dec 12 15:07:56 2018 +0530 @@ -2334,17 +2334,15 @@ Node<K,V>[] tab, nt; int n, sc; while (s >= (long)(sc = sizeCtl) && (tab = table) != null && (n = tab.length) < MAXIMUM_CAPACITY) { - int rs = resizeStamp(n); + int rs = resizeStamp(n) << RESIZE_STAMP_SHIFT; if (sc < 0) { - if ((sc >>> RESIZE_STAMP_SHIFT) != rs || sc == rs + 1 || - sc == rs + MAX_RESIZERS || (nt = nextTable) == null || - transferIndex <= 0) + if (sc == rs + MAX_RESIZERS || sc == rs + 1 || + (nt = nextTable) == null || transferIndex <= 0) break; if (U.compareAndSetInt(this, SIZECTL, sc, sc + 1)) transfer(tab, nt); } - else if (U.compareAndSetInt(this, SIZECTL, sc, - (rs << RESIZE_STAMP_SHIFT) + 2)) + else if (U.compareAndSetInt(this, SIZECTL, sc, rs + 2)) transfer(tab, null); s = sumCount(); } @@ -2358,11 +2356,11 @@ Node<K,V>[] nextTab; int sc; if (tab != null && (f instanceof ForwardingNode) && (nextTab = ((ForwardingNode<K,V>)f).nextTable) != null) { - int rs = resizeStamp(tab.length); + int rs = resizeStamp(tab.length) << RESIZE_STAMP_SHIFT; while (nextTab == nextTable && table == tab && (sc = sizeCtl) < 0) { - if ((sc >>> RESIZE_STAMP_SHIFT) != rs || sc == rs + 1 || - sc == rs + MAX_RESIZERS || transferIndex <= 0) + if (sc == rs + MAX_RESIZERS || sc == rs + 1 || + transferIndex <= 0) break; if (U.compareAndSetInt(this, SIZECTL, sc, sc + 1)) { transfer(tab, nextTab);
--- a/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java Tue Dec 11 14:11:57 2018 +0000 +++ b/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java Wed Dec 12 15:07:56 2018 +0530 @@ -136,17 +136,17 @@ * <p>The parameters used to construct the common pool may be controlled by * setting the following {@linkplain System#getProperty system properties}: * <ul> - * <li>{@code java.util.concurrent.ForkJoinPool.common.parallelism} + * <li>{@systemProperty java.util.concurrent.ForkJoinPool.common.parallelism} * - the parallelism level, a non-negative integer - * <li>{@code java.util.concurrent.ForkJoinPool.common.threadFactory} + * <li>{@systemProperty java.util.concurrent.ForkJoinPool.common.threadFactory} * - the class name of a {@link ForkJoinWorkerThreadFactory}. * The {@linkplain ClassLoader#getSystemClassLoader() system class loader} * is used to load this class. - * <li>{@code java.util.concurrent.ForkJoinPool.common.exceptionHandler} + * <li>{@systemProperty java.util.concurrent.ForkJoinPool.common.exceptionHandler} * - the class name of a {@link UncaughtExceptionHandler}. * The {@linkplain ClassLoader#getSystemClassLoader() system class loader} * is used to load this class. - * <li>{@code java.util.concurrent.ForkJoinPool.common.maximumSpares} + * <li>{@systemProperty java.util.concurrent.ForkJoinPool.common.maximumSpares} * - the maximum number of allowed extra threads to maintain target * parallelism (default 256). * </ul> @@ -445,8 +445,7 @@ * if to its current value). This would be extremely costly. So * we relax it in several ways: (1) Producers only signal when * their queue is possibly empty at some point during a push - * operation (which requires conservatively checking size zero or - * one to cover races). (2) Other workers propagate this signal + * operation. (2) Other workers propagate this signal * when they find tasks in a queue with size greater than one. (3) * Workers only enqueue after scanning (see below) and not finding * any tasks. (4) Rather than CASing ctl to its current value in @@ -762,10 +761,8 @@ /** * The maximum number of top-level polls per worker before - * checking other queues, expressed as a bit shift to, in effect, - * multiply by pool size, and then use as random value mask, so - * average bound is about poolSize*(1<<TOP_BOUND_SHIFT). See - * above for rationale. + * checking other queues, expressed as a bit shift. See above for + * rationale. */ static final int TOP_BOUND_SHIFT = 10; @@ -841,18 +838,17 @@ */ final void push(ForkJoinTask<?> task) { ForkJoinTask<?>[] a; - int s = top, d, cap, m; + int s = top, d = s - base, cap, m; ForkJoinPool p = pool; if ((a = array) != null && (cap = a.length) > 0) { QA.setRelease(a, (m = cap - 1) & s, task); top = s + 1; - if (((d = s - (int)BASE.getAcquire(this)) & ~1) == 0 && - p != null) { // size 0 or 1 - VarHandle.fullFence(); - p.signalWork(); + if (d == m) + growArray(false); + else if (QA.getAcquire(a, m & (s - 1)) == null && p != null) { + VarHandle.fullFence(); // was empty + p.signalWork(null); } - else if (d == m) - growArray(false); } } @@ -863,16 +859,16 @@ final boolean lockedPush(ForkJoinTask<?> task) { ForkJoinTask<?>[] a; boolean signal = false; - int s = top, b = base, cap, d; + int s = top, d = s - base, cap, m; if ((a = array) != null && (cap = a.length) > 0) { - a[(cap - 1) & s] = task; + a[(m = (cap - 1)) & s] = task; top = s + 1; - if (b - s + cap - 1 == 0) + if (d == m) growArray(true); else { phase = 0; // full volatile unlock - if (((s - base) & ~1) == 0) // size 0 or 1 - signal = true; + if (a[m & (s - 1)] == null) + signal = true; // was empty } } return signal; @@ -1014,25 +1010,30 @@ * queue, up to bound n (to avoid infinite unfairness). */ final void topLevelExec(ForkJoinTask<?> t, WorkQueue q, int n) { - if (t != null && q != null) { // hoist checks - int nstolen = 1; - for (;;) { + int nstolen = 1; + for (int j = 0;;) { + if (t != null) t.doExec(); - if (n-- < 0) + if (j++ <= n) + t = nextLocalTask(); + else { + j = 0; + t = null; + } + if (t == null) { + if (q != null && (t = q.poll()) != null) { + ++nstolen; + j = 0; + } + else if (j != 0) break; - else if ((t = nextLocalTask()) == null) { - if ((t = q.poll()) == null) - break; - else - ++nstolen; - } } - ForkJoinWorkerThread thread = owner; - nsteals += nstolen; - source = 0; - if (thread != null) - thread.afterTopLevelExec(); } + ForkJoinWorkerThread thread = owner; + nsteals += nstolen; + source = 0; + if (thread != null) + thread.afterTopLevelExec(); } /** @@ -1455,7 +1456,7 @@ if (!tryTerminate(false, false) && // possibly replace worker w != null && w.array != null) // avoid repeated failures - signalWork(); + signalWork(null); if (ex == null) // help clean on way out ForkJoinTask.helpExpungeStaleExceptions(); @@ -1465,8 +1466,9 @@ /** * Tries to create or release a worker if too few are running. + * @param q if non-null recheck if empty on CAS failure */ - final void signalWork() { + final void signalWork(WorkQueue q) { for (;;) { long c; int sp; WorkQueue[] ws; int i; WorkQueue v; if ((c = ctl) >= 0L) // enough workers @@ -1493,6 +1495,8 @@ LockSupport.unpark(vt); break; } + else if (q != null && q.isEmpty()) // no need to retry + break; } } } @@ -1613,19 +1617,24 @@ else if (rc <= 0 && (md & SHUTDOWN) != 0 && tryTerminate(false, false)) break; // quiescent shutdown - else if (rc <= 0 && pred != 0 && phase == (int)c) { - long nc = (UC_MASK & (c - TC_UNIT)) | (SP_MASK & pred); - long d = keepAlive + System.currentTimeMillis(); - LockSupport.parkUntil(this, d); - if (ctl == c && // drop on timeout if all idle - d - System.currentTimeMillis() <= TIMEOUT_SLOP && - CTL.compareAndSet(this, c, nc)) { - w.phase = QUIET; - break; + else if (w.phase < 0) { + if (rc <= 0 && pred != 0 && phase == (int)c) { + long nc = (UC_MASK & (c - TC_UNIT)) | (SP_MASK & pred); + long d = keepAlive + System.currentTimeMillis(); + LockSupport.parkUntil(this, d); + if (ctl == c && // drop on timeout if all idle + d - System.currentTimeMillis() <= TIMEOUT_SLOP && + CTL.compareAndSet(this, c, nc)) { + w.phase = QUIET; + break; + } + } + else { + LockSupport.park(this); + if (w.phase < 0) // one spurious wakeup check + LockSupport.park(this); } } - else if (w.phase < 0) - LockSupport.park(this); // OK if spuriously woken w.source = 0; // disable signal } } @@ -1641,8 +1650,8 @@ WorkQueue[] ws; int n; if ((ws = workQueues) != null && (n = ws.length) > 0 && w != null) { for (int m = n - 1, j = r & m;;) { - WorkQueue q; int b; - if ((q = ws[j]) != null && q.top != (b = q.base)) { + WorkQueue q; int b, s; + if ((q = ws[j]) != null && (s = q.top) != (b = q.base)) { int qid = q.id; ForkJoinTask<?>[] a; int cap, k; ForkJoinTask<?> t; if ((a = q.array) != null && (cap = a.length) > 0) { @@ -1651,10 +1660,10 @@ QA.compareAndSet(a, k, t, null)) { q.base = b; w.source = qid; - if (q.top - b > 0) - signalWork(); + if (s != b && a[(cap - 1) & b] != null) + signalWork(q); // help signal if more tasks w.topLevelExec(t, q, // random fairness bound - r & ((n << TOP_BOUND_SHIFT) - 1)); + (r | (1 << TOP_BOUND_SHIFT)) & SMASK); } } return true; @@ -1900,7 +1909,7 @@ r = ThreadLocalRandom.advanceProbe(r); else { if (q.lockedPush(task)) - signalWork(); + signalWork(null); return; } }
--- a/src/java.base/share/classes/java/util/concurrent/locks/Lock.java Tue Dec 11 14:11:57 2018 +0000 +++ b/src/java.base/share/classes/java/util/concurrent/locks/Lock.java Wed Dec 12 15:07:56 2018 +0530 @@ -122,7 +122,7 @@ * <p>All {@code Lock} implementations <em>must</em> enforce the same * memory synchronization semantics as provided by the built-in monitor * lock, as described in - * <a href="https://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html#jls-17.4"> + * <a href="https://docs.oracle.com/javase/specs/jls/se11/html/jls-17.html#jls-17.4"> * Chapter 17 of * <cite>The Java™ Language Specification</cite></a>: * <ul>
--- a/src/java.base/share/classes/java/util/concurrent/locks/StampedLock.java Tue Dec 11 14:11:57 2018 +0000 +++ b/src/java.base/share/classes/java/util/concurrent/locks/StampedLock.java Wed Dec 12 15:07:56 2018 +0530 @@ -133,7 +133,7 @@ * <p><b>Memory Synchronization.</b> Methods with the effect of * successfully locking in any mode have the same memory * synchronization effects as a <em>Lock</em> action described in - * <a href="https://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html#jls-17.4"> + * <a href="https://docs.oracle.com/javase/specs/jls/se11/html/jls-17.html#jls-17.4"> * Chapter 17 of <cite>The Java™ Language Specification</cite></a>. * Methods successfully unlocking in write mode have the same memory * synchronization effects as an <em>Unlock</em> action. In optimistic
--- a/src/java.base/share/classes/java/util/concurrent/package-info.java Tue Dec 11 14:11:57 2018 +0000 +++ b/src/java.base/share/classes/java/util/concurrent/package-info.java Wed Dec 12 15:07:56 2018 +0530 @@ -226,7 +226,7 @@ * * <h2 id="MemoryVisibility">Memory Consistency Properties</h2> * - * <a href="https://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html#jls-17.4.5"> + * <a href="https://docs.oracle.com/javase/specs/jls/se11/html/jls-17.html#jls-17.4.5"> * Chapter 17 of * <cite>The Java™ Language Specification</cite></a> defines the * <i>happens-before</i> relation on memory operations such as reads and
--- a/src/java.base/share/classes/sun/security/ssl/ClientHandshakeContext.java Tue Dec 11 14:11:57 2018 +0000 +++ b/src/java.base/share/classes/sun/security/ssl/ClientHandshakeContext.java Wed Dec 12 15:07:56 2018 +0530 @@ -90,6 +90,9 @@ ClientHelloMessage initialClientHelloMsg = null; + // PSK identity is selected in first Hello and used again after HRR + byte[] pskIdentity; + ClientHandshakeContext(SSLContextImpl sslContext, TransportContext conContext) throws IOException { super(sslContext, conContext);
--- a/src/java.base/share/classes/sun/security/ssl/PreSharedKeyExtension.java Tue Dec 11 14:11:57 2018 +0000 +++ b/src/java.base/share/classes/sun/security/ssl/PreSharedKeyExtension.java Wed Dec 12 15:07:56 2018 +0530 @@ -656,7 +656,11 @@ return null; } SecretKey psk = pskOpt.get(); - Optional<byte[]> pskIdOpt = chc.resumingSession.consumePskIdentity(); + // The PSK ID can only be used in one connections, but this method + // may be called twice in a connection if the server sends HRR. + // ID is saved in the context so it can be used in the second call. + Optional<byte[]> pskIdOpt = Optional.ofNullable(chc.pskIdentity) + .or(chc.resumingSession::consumePskIdentity); if (!pskIdOpt.isPresent()) { if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { SSLLogger.fine( @@ -664,7 +668,7 @@ } return null; } - byte[] pskId = pskIdOpt.get(); + chc.pskIdentity = pskIdOpt.get(); //The session cannot be used again. Remove it from the cache. SSLSessionContextImpl sessionCache = (SSLSessionContextImpl) @@ -681,7 +685,7 @@ chc.resumingSession.getTicketCreationTime()); int obfuscatedAge = ageMillis + chc.resumingSession.getTicketAgeAdd(); - identities.add(new PskIdentity(pskId, obfuscatedAge)); + identities.add(new PskIdentity(chc.pskIdentity, obfuscatedAge)); SecretKey binderKey = deriveBinderKey(psk, chc.resumingSession); ClientHelloMessage clientHello = (ClientHelloMessage)message;
--- a/src/java.base/share/classes/sun/security/util/ArrayUtil.java Tue Dec 11 14:11:57 2018 +0000 +++ b/src/java.base/share/classes/sun/security/util/ArrayUtil.java Wed Dec 12 15:07:56 2018 +0530 @@ -52,4 +52,21 @@ // NPE is thrown when array is null Preconditions.checkFromIndexSize(offset, len, array.length, AIOOBE_SUPPLIER); } + + private static void swap(byte[] arr, int i, int j) { + byte tmp = arr[i]; + arr[i] = arr[j]; + arr[j] = tmp; + } + + public static void reverse(byte [] arr) { + int i = 0; + int j = arr.length - 1; + + while (i < j) { + swap(arr, i, j); + i++; + j--; + } + } }
--- a/src/java.base/share/classes/sun/security/util/math/MutableIntegerModuloP.java Tue Dec 11 14:11:57 2018 +0000 +++ b/src/java.base/share/classes/sun/security/util/math/MutableIntegerModuloP.java Wed Dec 12 15:07:56 2018 +0530 @@ -41,6 +41,18 @@ public interface MutableIntegerModuloP extends IntegerModuloP { /** + * Set this value to the value of b when set has the value 1. + * No change is made to this element when set has the value 0. The + * result is undefined when set has a value other than 0 or 1. The set + * parameter is an int (rather than boolean) to allow the implementation + * to perform the assignment using branch-free integer arithmetic. + * + * @param b the element to conditionally swap with + * @param set an int that determines whether to set + */ + void conditionalSet(IntegerModuloP b, int set); + + /** * Swap the value of this with the value of b when swap has the value 1. * No change is made to either element when swap has the value 0. The * result is undefined when swap has a value other than 0 or 1. The swap @@ -131,5 +143,20 @@ * @return this */ MutableIntegerModuloP setProduct(SmallValue v); + + /** + * Set the value of this element equal to 0 - this. + * + * @return this + */ + MutableIntegerModuloP setAdditiveInverse(); + + /** + * Some implementations required reduction operations to be requested + * by the client at certain times. This method reduces the representation. + * + * @return this + */ + MutableIntegerModuloP setReduced(); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/java.base/share/classes/sun/security/util/math/intpoly/FieldGen.jsh Wed Dec 12 15:07:56 2018 +0530 @@ -0,0 +1,851 @@ +/* + * Copyright (c) 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. + */ + + +/* + * This file is used to generated optimized finite field implementations. + * Required settings are included in the file. To generate, use jshell: + * jshell < FieldGen.jsh + */ + +import java.io.*; +import java.math.BigInteger; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.*; + +public class FieldGen { + + static FieldParams Curve25519 = new FieldParams("IntegerPolynomial25519", 26, 10, 1, 255, + Arrays.asList( + new Term(0, -19) + ), + Curve25519CrSequence(), simpleSmallCrSequence(10) + ); + + private static List<CarryReduce> Curve25519CrSequence() { + List<CarryReduce> result = new ArrayList<CarryReduce>(); + + // reduce(7,2) + result.add(new Reduce(17)); + result.add(new Reduce(18)); + + // carry(8,2) + result.add(new Carry(8)); + result.add(new Carry(9)); + + // reduce(0,7) + for (int i = 10; i < 17; i++) { + result.add(new Reduce(i)); + } + + // carry(0,9) + result.addAll(fullCarry(10)); + + return result; + } + + static FieldParams Curve448 = new FieldParams("IntegerPolynomial448", 28, 16, 1, 448, + Arrays.asList( + new Term(224, -1), + new Term(0, -1) + ), + Curve448CrSequence(), simpleSmallCrSequence(16) + ); + + private static List<CarryReduce> Curve448CrSequence() { + List<CarryReduce> result = new ArrayList<CarryReduce>(); + + // reduce(8, 7) + for (int i = 24; i < 31; i++) { + result.add(new Reduce(i)); + } + // reduce(4, 4) + for (int i = 20; i < 24; i++) { + result.add(new Reduce(i)); + } + + //carry(14, 2) + result.add(new Carry(14)); + result.add(new Carry(15)); + + // reduce(0, 4) + for (int i = 16; i < 20; i++) { + result.add(new Reduce(i)); + } + + // carry(0, 15) + result.addAll(fullCarry(16)); + + return result; + } + + static FieldParams P256 = new FieldParams("IntegerPolynomialP256", 26, 10, 2, 256, + Arrays.asList( + new Term(224, -1), + new Term(192, 1), + new Term(96, 1), + new Term(0, -1) + ), + P256CrSequence(), simpleSmallCrSequence(10) + ); + + private static List<CarryReduce> P256CrSequence() { + List<CarryReduce> result = new ArrayList<CarryReduce>(); + result.addAll(fullReduce(10)); + result.addAll(simpleSmallCrSequence(10)); + return result; + } + + static FieldParams P384 = new FieldParams("IntegerPolynomialP384", 28, 14, 2, 384, + Arrays.asList( + new Term(128, -1), + new Term(96, -1), + new Term(32, 1), + new Term(0, -1) + ), + P384CrSequence(), simpleSmallCrSequence(14) + ); + + private static List<CarryReduce> P384CrSequence() { + List<CarryReduce> result = new ArrayList<CarryReduce>(); + result.addAll(fullReduce(14)); + result.addAll(simpleSmallCrSequence(14)); + return result; + } + + static FieldParams P521 = new FieldParams("IntegerPolynomialP521", 28, 19, 2, 521, + Arrays.asList(new Term(0, -1)), P521CrSequence(), simpleSmallCrSequence(19) + ); + + private static List<CarryReduce> P521CrSequence() { + List<CarryReduce> result = new ArrayList<CarryReduce>(); + result.addAll(fullReduce(19)); + result.addAll(simpleSmallCrSequence(19)); + return result; + } + + static FieldParams O256 = new FieldParams("P256OrderField", 26, 10, 1, 256, + new BigInteger("26959946660873538059280334323273029441504803697035324946844617595567"), + orderFieldCrSequence(10), orderFieldSmallCrSequence(10) + ); + + static FieldParams O384 = new FieldParams("P384OrderField", 28, 14, 1, 384, + new BigInteger("1388124618062372383947042015309946732620727252194336364173"), + orderFieldCrSequence(14), orderFieldSmallCrSequence(14) + ); + + static FieldParams O521 = new FieldParams("P521OrderField", 28, 19, 1, 521, + new BigInteger("657877501894328237357444332315020117536923257219387276263472201219398408051703"), + o521crSequence(19), orderFieldSmallCrSequence(19) + ); + + private static List<CarryReduce> o521crSequence(int numLimbs) { + + // split the full reduce in half, with a carry in between + List<CarryReduce> result = new ArrayList<CarryReduce>(); + result.addAll(fullCarry(2 * numLimbs)); + for (int i = 2 * numLimbs - 1; i >= numLimbs + numLimbs/2; i--) { + result.add(new Reduce(i)); + } + // carry + for (int i = numLimbs; i < numLimbs + numLimbs / 2 - 1; i++) { + result.add(new Carry(i)); + } + // rest of reduce + for (int i = numLimbs + numLimbs/2 - 1; i >= numLimbs; i--) { + result.add(new Reduce(i)); + } + result.addAll(orderFieldSmallCrSequence(numLimbs)); + + return result; + } + + private static List<CarryReduce> orderFieldCrSequence(int numLimbs) { + List<CarryReduce> result = new ArrayList<CarryReduce>(); + result.addAll(fullCarry(2 * numLimbs)); + result.add(new Reduce(2 * numLimbs - 1)); + result.addAll(fullReduce(numLimbs)); + result.addAll(fullCarry(numLimbs + 1)); + result.add(new Reduce(numLimbs)); + result.addAll(fullCarry(numLimbs)); + + return result; + } + private static List<CarryReduce> orderFieldSmallCrSequence(int numLimbs) { + List<CarryReduce> result = new ArrayList<CarryReduce>(); + result.addAll(fullCarry(numLimbs + 1)); + result.add(new Reduce(numLimbs)); + result.addAll(fullCarry(numLimbs)); + return result; + } + + static final FieldParams[] ALL_FIELDS = {P256, P384, P521, O256, O384, O521}; + + public static class Term { + private final int power; + private final int coefficient; + + public Term(int power, int coefficient) { + this.power = power; + this.coefficient = coefficient; + } + + public int getPower() { + return power; + } + + public int getCoefficient() { + return coefficient; + } + + public BigInteger getValue() { + return BigInteger.valueOf(2).pow(power).multiply(BigInteger.valueOf(coefficient)); + } + + } + + static abstract class CarryReduce { + private final int index; + + protected CarryReduce(int index) { + this.index = index; + } + + public int getIndex() { + return index; + } + + public abstract void write(CodeBuffer out, FieldParams params, String prefix, Iterable<CarryReduce> remaining); + } + + static class Carry extends CarryReduce { + public Carry(int index) { + super(index); + } + + public void write(CodeBuffer out, FieldParams params, String prefix, Iterable<CarryReduce> remaining) { + carry(out, params, prefix, getIndex()); + } + } + + static class Reduce extends CarryReduce { + public Reduce(int index) { + super(index); + } + + public void write(CodeBuffer out, FieldParams params, String prefix, Iterable<CarryReduce> remaining) { + reduce(out, params, prefix, getIndex(), remaining); + } + } + + static class FieldParams { + private final String className; + private final int bitsPerLimb; + private final int numLimbs; + private final int maxAdds; + private final int power; + private final Iterable<Term> terms; + private final List<CarryReduce> crSequence; + private final List<CarryReduce> smallCrSequence; + + public FieldParams(String className, int bitsPerLimb, int numLimbs, int maxAdds, int power, + Iterable<Term> terms, List<CarryReduce> crSequence, List<CarryReduce> smallCrSequence) { + this.className = className; + this.bitsPerLimb = bitsPerLimb; + this.numLimbs = numLimbs; + this.maxAdds = maxAdds; + this.power = power; + this.terms = terms; + this.crSequence = crSequence; + this.smallCrSequence = smallCrSequence; + } + + public FieldParams(String className, int bitsPerLimb, int numLimbs, int maxAdds, int power, + BigInteger term, List<CarryReduce> crSequence, List<CarryReduce> smallCrSequence) { + this.className = className; + this.bitsPerLimb = bitsPerLimb; + this.numLimbs = numLimbs; + this.maxAdds = maxAdds; + this.power = power; + this.crSequence = crSequence; + this.smallCrSequence = smallCrSequence; + + terms = buildTerms(term); + } + + private Iterable<Term> buildTerms(BigInteger sub) { + // split a large subtrahend into smaller terms that are aligned with limbs + List<Term> result = new ArrayList<Term>(); + BigInteger mod = BigInteger.valueOf(1 << bitsPerLimb); + int termIndex = 0; + while (!sub.equals(BigInteger.ZERO)) { + int coef = sub.mod(mod).intValue(); + boolean plusOne = false; + if (coef > (1 << (bitsPerLimb - 1))) { + coef = coef - (1 << bitsPerLimb); + plusOne = true; + } + if (coef != 0) { + int pow = termIndex * bitsPerLimb; + result.add(new Term(pow, -coef)); + } + sub = sub.shiftRight(bitsPerLimb); + if (plusOne) { + sub = sub.add(BigInteger.ONE); + } + ++termIndex; + } + return result; + } + + public String getClassName() { + return className; + } + + public int getBitsPerLimb() { + return bitsPerLimb; + } + + public int getNumLimbs() { + return numLimbs; + } + + public int getMaxAdds() { + return maxAdds; + } + + public int getPower() { + return power; + } + + public Iterable<Term> getTerms() { + return terms; + } + + public List<CarryReduce> getCrSequence() { + return crSequence; + } + + public List<CarryReduce> getSmallCrSequence() { + return smallCrSequence; + } + } + + static Collection<Carry> fullCarry(int numLimbs) { + List<Carry> result = new ArrayList<Carry>(); + for (int i = 0; i < numLimbs - 1; i++) { + result.add(new Carry(i)); + } + return result; + } + + static Collection<Reduce> fullReduce(int numLimbs) { + List<Reduce> result = new ArrayList<Reduce>(); + for (int i = numLimbs - 2; i >= 0; i--) { + result.add(new Reduce(i + numLimbs)); + } + return result; + } + + static List<CarryReduce> simpleCrSequence(int numLimbs) { + List<CarryReduce> result = new ArrayList<CarryReduce>(); + for(int i = 0; i < 4; i++) { + result.addAll(fullCarry(2 * numLimbs - 1)); + result.addAll(fullReduce(numLimbs)); + } + + return result; + } + + static List<CarryReduce> simpleSmallCrSequence(int numLimbs) { + List<CarryReduce> result = new ArrayList<CarryReduce>(); + // carry a few positions at the end + for (int i = numLimbs - 2; i < numLimbs; i++) { + result.add(new Carry(i)); + } + // this carries out a single value that must be reduced back in + result.add(new Reduce(numLimbs)); + // finish with a full carry + result.addAll(fullCarry(numLimbs)); + return result; + } + + private final String packageName; + private final String parentName; + + public FieldGen(String packageName, String parentName) { + this.packageName = packageName; + this.parentName = parentName; + } + + public static void main(String[] args) throws Exception { + + FieldGen gen = new FieldGen("sun.security.util.math.intpoly", "IntegerPolynomial"); + for(FieldParams p : ALL_FIELDS) { + gen.generateFile(p); + } + } + + private void generateFile(FieldParams params) throws IOException { + String text = generate(params); + String fileName = params.getClassName() + ".java"; + PrintWriter out = new PrintWriter(new FileWriter(fileName)); + out.println(text); + out.close(); + } + + static class CodeBuffer { + + private int nextTemporary = 0; + private Set<String> temporaries = new HashSet<String>(); + private StringBuffer buffer = new StringBuffer(); + private int indent = 0; + private Class lastCR; + private int lastCrCount = 0; + private int crMethodBreakCount = 0; + private int crNumLimbs = 0; + + public void incrIndent() { + indent++; + } + + public void decrIndent() { + indent--; + } + + public void newTempScope() { + nextTemporary = 0; + temporaries.clear(); + } + + public void appendLine(String s) { + appendIndent(); + buffer.append(s + "\n"); + } + + public void appendLine() { + buffer.append("\n"); + } + + public String toString() { + return buffer.toString(); + } + + public void startCrSequence(int numLimbs) { + this.crNumLimbs = numLimbs; + lastCrCount = 0; + crMethodBreakCount = 0; + lastCR = null; + } + /* + * Record a carry/reduce of the specified type. This method is used to + * break up large carry/reduce sequences into multiple methods to make + * JIT/optimization easier + */ + public void record(Class type) { + if (type == lastCR) { + lastCrCount++; + } else { + + if (lastCrCount >= 8) { + insertCrMethodBreak(); + } + + lastCR = type; + lastCrCount = 0; + } + } + + private void insertCrMethodBreak() { + + appendLine(); + + // call the new method + appendIndent(); + append("carryReduce" + crMethodBreakCount + "(r"); + for(int i = 0; i < crNumLimbs; i++) { + append(", c" + i); + } + // temporaries are not live between operations, no need to send + append(");\n"); + + decrIndent(); + appendLine("}"); + + // make the method + appendIndent(); + append("void carryReduce" + crMethodBreakCount + "(long[] r"); + for(int i = 0; i < crNumLimbs; i++) { + append (", long c" + i); + } + append(") {\n"); + incrIndent(); + // declare temporaries + for(String temp : temporaries) { + appendLine("long " + temp + ";"); + } + append("\n"); + + crMethodBreakCount++; + } + + public String getTemporary(String type, String value) { + Iterator<String> iter = temporaries.iterator(); + if(iter.hasNext()) { + String result = iter.next(); + iter.remove(); + appendLine(result + " = " + value + ";"); + return result; + } else { + String result = "t" + (nextTemporary++); + appendLine(type + " " + result + " = " + value + ";"); + return result; + } + } + + public void freeTemporary(String temp) { + temporaries.add(temp); + } + + public void appendIndent() { + for(int i = 0; i < indent; i++) { + buffer.append(" "); + } + } + + public void append(String s) { + buffer.append(s); + } + } + + private String generate(FieldParams params) throws IOException { + CodeBuffer result = new CodeBuffer(); + String header = readHeader(); + result.appendLine(header); + + if (packageName != null) { + result.appendLine("package " + packageName + ";"); + result.appendLine(); + } + result.appendLine("import java.math.BigInteger;"); + + result.appendLine("public class " + params.getClassName() + " extends " + this.parentName + " {"); + result.incrIndent(); + + result.appendLine("private static final int BITS_PER_LIMB = " + params.getBitsPerLimb() + ";"); + result.appendLine("private static final int NUM_LIMBS = " + params.getNumLimbs() + ";"); + result.appendLine("private static final int MAX_ADDS = " + params.getMaxAdds() + ";"); + result.appendLine("public static final BigInteger MODULUS = evaluateModulus();"); + result.appendLine("private static final long CARRY_ADD = 1 << " + (params.getBitsPerLimb() - 1) + ";"); + if (params.getBitsPerLimb() * params.getNumLimbs() != params.getPower()) { + result.appendLine("private static final int LIMB_MASK = -1 >>> (64 - BITS_PER_LIMB);"); + } + int termIndex = 0; + + result.appendLine("public " + params.getClassName() + "() {"); + result.appendLine(); + result.appendLine(" super(BITS_PER_LIMB, NUM_LIMBS, MAX_ADDS, MODULUS);"); + result.appendLine(); + result.appendLine("}"); + + result.appendLine("private static BigInteger evaluateModulus() {"); + result.incrIndent(); + result.appendLine("BigInteger result = BigInteger.valueOf(2).pow(" + params.getPower() + ");"); + for(Term t : params.getTerms()) { + boolean subtract = false; + int coefValue = t.getCoefficient(); + if (coefValue < 0) { + coefValue = 0 - coefValue; + subtract = true; + } + String coefExpr = "BigInteger.valueOf(" + coefValue + ")"; + String powExpr = "BigInteger.valueOf(2).pow(" + t.getPower() + ")"; + String termExpr = "ERROR"; + if (t.getPower() == 0) { + termExpr = coefExpr; + } else if (coefValue == 1) { + termExpr = powExpr; + } else { + termExpr = powExpr + ".multiply(" + coefExpr + ")"; + } + if (subtract) { + result.appendLine("result = result.subtract(" + termExpr + ");"); + } else { + result.appendLine("result = result.add(" + termExpr + ");"); + } + } + result.appendLine("return result;"); + result.decrIndent(); + result.appendLine("}"); + + result.appendLine("@Override"); + result.appendLine("protected void finalCarryReduceLast(long[] limbs) {"); + result.incrIndent(); + int extraBits = params.getBitsPerLimb() * params.getNumLimbs() - params.getPower(); + int highBits = params.getBitsPerLimb() - extraBits; + result.appendLine("long c = limbs[" + (params.getNumLimbs() - 1) + "] >> " + highBits + ";"); + result.appendLine("limbs[" + (params.getNumLimbs() - 1) + "] -= c << " + highBits + ";"); + for (Term t : params.getTerms()) { + int reduceBits = params.getPower() + extraBits - t.getPower(); + int negatedCoefficient = -1 * t.getCoefficient(); + modReduceInBits(result, params, true, "limbs", params.getNumLimbs(), reduceBits, negatedCoefficient, "c"); + } + result.decrIndent(); + result.appendLine("}"); + + // full carry/reduce sequence + result.appendIndent(); + result.append("private void carryReduce(long[] r, "); + for(int i = 0; i < 2 * params.getNumLimbs() - 1; i++) { + result.append ("long c" + i); + if (i < 2 * params.getNumLimbs() - 2) { + result.append(", "); + } + } + result.append(") {\n"); + result.newTempScope(); + result.incrIndent(); + result.appendLine("long c" + (2 * params.getNumLimbs() - 1) + " = 0;"); + write(result, params.getCrSequence(), params, "c", 2 * params.getNumLimbs()); + result.appendLine(); + for (int i = 0; i < params.getNumLimbs(); i++) { + result.appendLine("r[" + i + "] = c" + i + ";"); + } + result.decrIndent(); + result.appendLine("}"); + + // small carry/reduce sequence + result.appendIndent(); + result.append("private void carryReduce(long[] r, "); + for(int i = 0; i < params.getNumLimbs(); i++) { + result.append ("long c" + i); + if (i < params.getNumLimbs() - 1) { + result.append(", "); + } + } + result.append(") {\n"); + result.newTempScope(); + result.incrIndent(); + result.appendLine("long c" + params.getNumLimbs() + " = 0;"); + write(result, params.getSmallCrSequence(), params, "c", params.getNumLimbs() + 1); + result.appendLine(); + for (int i = 0; i < params.getNumLimbs(); i++) { + result.appendLine("r[" + i + "] = c" + i + ";"); + } + result.decrIndent(); + result.appendLine("}"); + + result.appendLine("@Override"); + result.appendLine("protected void mult(long[] a, long[] b, long[] r) {"); + result.incrIndent(); + for (int i = 0; i < 2 * params.getNumLimbs() - 1; i++) { + result.appendIndent(); + result.append("long c" + i + " = "); + int startJ = Math.max(i + 1 - params.getNumLimbs(), 0); + int endJ = Math.min(params.getNumLimbs(), i + 1); + for (int j = startJ; j < endJ; j++) { + int bIndex = i - j; + result.append("(a[" + j + "] * b[" + bIndex + "])"); + if (j < endJ - 1) { + result.append(" + "); + } + } + result.append(";\n"); + } + result.appendLine(); + result.appendIndent(); + result.append("carryReduce(r, "); + for (int i = 0; i < 2 * params.getNumLimbs() - 1; i++) { + result.append("c" + i); + if (i < 2 * params.getNumLimbs() - 2) { + result.append(", "); + } + } + result.append(");\n"); + result.decrIndent(); + result.appendLine("}"); + + result.appendLine("@Override"); + result.appendLine("protected void reduce(long[] a) {"); + result.incrIndent(); + result.appendIndent(); + result.append("carryReduce(a, "); + for (int i = 0; i < params.getNumLimbs(); i++) { + result.append("a[" + i + "]"); + if (i < params.getNumLimbs() - 1) { + result.append(", "); + } + } + result.append(");\n"); + result.decrIndent(); + result.appendLine("}"); + + result.appendLine("@Override"); + result.appendLine("protected void square(long[] a, long[] r) {"); + result.incrIndent(); + for (int i = 0; i < 2 * params.getNumLimbs() - 1; i++) { + result.appendIndent(); + result.append("long c" + i + " = "); + int startJ = Math.max(i + 1 - params.getNumLimbs(), 0); + int endJ = Math.min(params.getNumLimbs(), i + 1); + int jDiff = endJ - startJ; + if (jDiff > 1) { + result.append("2 * ("); + } + for (int j = 0; j < jDiff / 2; j++) { + int aIndex = j + startJ; + int bIndex = i - aIndex; + result.append("(a[" + aIndex + "] * a[" + bIndex + "])"); + if (j < (jDiff / 2) - 1) { + result.append(" + "); + } + } + if (jDiff > 1) { + result.append(")"); + } + if (jDiff % 2 == 1) { + int aIndex = i / 2; + if (jDiff > 1) { + result.append (" + "); + } + result.append("(a[" + aIndex + "] * a[" + aIndex + "])"); + } + result.append(";\n"); + } + result.appendLine(); + result.appendIndent(); + result.append("carryReduce(r, "); + for (int i = 0; i < 2 * params.getNumLimbs() - 1; i++) { + result.append("c" + i); + if (i < 2 * params.getNumLimbs() - 2) { + result.append(", "); + } + } + result.append(");\n"); + result.decrIndent(); + result.appendLine("}"); + + result.decrIndent(); + result.appendLine("}"); // end class + + return result.toString(); + } + + private static void write(CodeBuffer out, List<CarryReduce> sequence, FieldParams params, String prefix, int numLimbs) { + + out.startCrSequence(numLimbs); + for (int i = 0; i < sequence.size(); i++) { + CarryReduce cr = sequence.get(i); + Iterator<CarryReduce> remainingIter = sequence.listIterator(i + 1); + List<CarryReduce> remaining = new ArrayList<CarryReduce>(); + remainingIter.forEachRemaining(remaining::add); + cr.write(out, params, prefix, remaining); + } + } + + private static void reduce(CodeBuffer out, FieldParams params, String prefix, int index, Iterable<CarryReduce> remaining) { + + out.record(Reduce.class); + + out.appendLine("//reduce from position " + index); + String reduceFrom = indexedExpr(false, prefix, index); + boolean referenced = false; + for (CarryReduce cr : remaining) { + if(cr.index == index) { + referenced = true; + } + } + for (Term t : params.getTerms()) { + int reduceBits = params.getPower() - t.getPower(); + int negatedCoefficient = -1 * t.getCoefficient(); + modReduceInBits(out, params, false, prefix, index, reduceBits, negatedCoefficient, reduceFrom); + } + if (referenced) { + out.appendLine(reduceFrom + " = 0;"); + } + } + + private static void carry(CodeBuffer out, FieldParams params, String prefix, int index) { + + out.record(Carry.class); + + out.appendLine("//carry from position " + index); + String carryFrom = prefix + index; + String carryTo = prefix + (index + 1); + String carry = "(" + carryFrom + " + CARRY_ADD) >> " + params.getBitsPerLimb(); + String temp = out.getTemporary("long", carry); + out.appendLine(carryFrom + " -= (" + temp + " << " + params.getBitsPerLimb() + ");"); + out.appendLine(carryTo + " += " + temp + ";"); + out.freeTemporary(temp); + } + + private static String indexedExpr(boolean isArray, String prefix, int index) { + String result = prefix + index; + if (isArray) { + result = prefix + "[" + index + "]"; + } + return result; + } + + private static void modReduceInBits(CodeBuffer result, FieldParams params, boolean isArray, String prefix, int index, int reduceBits, int coefficient, String c) { + + String x = coefficient + " * " + c; + String accOp = "+="; + String temp = null; + if (coefficient == 1) { + x = c; + } else if (coefficient == -1) { + x = c; + accOp = "-="; + } else { + temp = result.getTemporary("long", x); + x = temp; + } + + if (reduceBits % params.getBitsPerLimb() == 0) { + int pos = reduceBits / params.getBitsPerLimb(); + result.appendLine(indexedExpr(isArray, prefix, (index - pos)) + " " + accOp + " " + x + ";"); + } else { + int secondPos = reduceBits / params.getBitsPerLimb(); + int bitOffset = (secondPos + 1) * params.getBitsPerLimb() - reduceBits; + int rightBitOffset = params.getBitsPerLimb() - bitOffset; + result.appendLine(indexedExpr(isArray, prefix, (index - (secondPos + 1))) + " " + accOp + " (" + x + " << " + bitOffset + ") & LIMB_MASK;"); + result.appendLine(indexedExpr(isArray, prefix, (index - secondPos)) + " " + accOp + " " + x + " >> " + rightBitOffset + ";"); + } + + if (temp != null) { + result.freeTemporary(temp); + } + } + + private String readHeader() throws IOException { + BufferedReader reader = Files.newBufferedReader(Paths.get("header.txt")); + StringBuffer result = new StringBuffer(); + reader.lines().forEach(s -> result.append(s + "\n")); + return result.toString(); + } +} + +FieldGen.main(null); +
--- a/src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomial.java Tue Dec 11 14:11:57 2018 +0000 +++ b/src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomial.java Wed Dec 12 15:07:56 2018 +0530 @@ -69,14 +69,25 @@ private final BigInteger modulus; protected final int bitsPerLimb; private final long[] posModLimbs; + private final int maxAdds; + + /** + * Reduce an IntegerPolynomial representation (a) and store the result + * in a. Requires that a.length == numLimbs. + */ + protected abstract void reduce(long[] a); /** * Multiply an IntegerPolynomial representation (a) with a long (b) and - * store the result in an IntegerPolynomial representation (r). Requires - * that a.length == r.length == numLimbs. It is allowed for a and r to be - * the same array. + * store the result in an IntegerPolynomial representation in a. Requires + * that a.length == numLimbs. */ - protected abstract void multByInt(long[] a, long b, long[] r); + protected void multByInt(long[] a, long b) { + for (int i = 0; i < a.length; i++) { + a[i] *= b; + } + reduce(a); + } /** * Multiply two IntegerPolynomial representations (a and b) and store the @@ -96,12 +107,14 @@ IntegerPolynomial(int bitsPerLimb, int numLimbs, + int maxAdds, BigInteger modulus) { this.numLimbs = numLimbs; this.modulus = modulus; this.bitsPerLimb = bitsPerLimb; + this.maxAdds = maxAdds; posModLimbs = setPosModLimbs(); } @@ -116,6 +129,10 @@ return numLimbs; } + public int getMaxAdds() { + return maxAdds; + } + @Override public BigInteger getSize() { return modulus; @@ -155,12 +172,22 @@ */ protected void encode(ByteBuffer buf, int length, byte highByte, long[] result) { + int numHighBits = 32 - Integer.numberOfLeadingZeros(highByte); int numBits = 8 * length + numHighBits; - int maxBits = bitsPerLimb * result.length; - if (numBits > maxBits) { - throw new ArithmeticException("Value is too large."); + int requiredLimbs = (numBits + bitsPerLimb - 1) / bitsPerLimb; + if (requiredLimbs > numLimbs) { + long[] temp = new long[requiredLimbs]; + encodeSmall(buf, length, highByte, temp); + // encode does a full carry/reduce + System.arraycopy(temp, 0, result, 0, result.length); + } else { + encodeSmall(buf, length, highByte, result); } + } + + protected void encodeSmall(ByteBuffer buf, int length, byte highByte, + long[] result) { int limbIndex = 0; long curLimbValue = 0; @@ -195,10 +222,10 @@ } } - if (limbIndex < numLimbs) { + if (limbIndex < result.length) { result[limbIndex++] = curLimbValue; } - Arrays.fill(result, limbIndex, numLimbs, 0); + Arrays.fill(result, limbIndex, result.length, 0); postEncodeCarry(result); } @@ -211,8 +238,10 @@ encode(buf, length, highByte, result); } + // Encode does not produce compressed limbs. A simplified carry/reduce + // operation can be used to compress the limbs. protected void postEncodeCarry(long[] v) { - carry(v); + reduce(v); } public ImmutableElement getElement(byte[] v, int offset, int length, @@ -222,7 +251,7 @@ encode(v, offset, length, highByte, result); - return new ImmutableElement(result, true); + return new ImmutableElement(result, 0); } protected BigInteger evaluate(long[] limbs) { @@ -387,6 +416,20 @@ } /** + * Branch-free conditional assignment of b to a. Requires that set is 0 or + * 1, and that a.length == b.length. If set==0, then the values of a and b + * will be unchanged. If set==1, then the values of b will be assigned to a. + * The behavior is undefined if swap has any value other than 0 or 1. + */ + protected static void conditionalAssign(int set, long[] a, long[] b) { + int maskValue = 0 - set; + for (int i = 0; i < a.length; i++) { + long dummyLimbs = maskValue & (a[i] ^ b[i]); + a[i] = dummyLimbs ^ a[i]; + } + } + + /** * Branch-free conditional swap of a and b. Requires that swap is 0 or 1, * and that a.length == b.length. If swap==0, then the values of a and b * will be unchanged. If swap==1, then the values of a and b will be @@ -442,7 +485,7 @@ private abstract class Element implements IntegerModuloP { protected long[] limbs; - protected boolean summand = false; + protected int numAdds; public Element(BigInteger v) { limbs = new long[numLimbs]; @@ -450,19 +493,19 @@ } public Element(boolean v) { - limbs = new long[numLimbs]; - limbs[0] = v ? 1l : 0l; - summand = true; + this.limbs = new long[numLimbs]; + this.limbs[0] = v ? 1l : 0l; + this.numAdds = 0; } - private Element(long[] limbs, boolean summand) { + private Element(long[] limbs, int numAdds) { this.limbs = limbs; - this.summand = summand; + this.numAdds = numAdds; } private void setValue(BigInteger v) { setLimbsValue(v, limbs); - summand = true; + this.numAdds = 0; } @Override @@ -477,14 +520,18 @@ @Override public MutableElement mutable() { - return new MutableElement(limbs.clone(), summand); + return new MutableElement(limbs.clone(), numAdds); + } + + protected boolean isSummand() { + return numAdds < maxAdds; } @Override public ImmutableElement add(IntegerModuloP genB) { Element b = (Element) genB; - if (!(summand && b.summand)) { + if (!(isSummand() && b.isSummand())) { throw new ArithmeticException("Not a valid summand"); } @@ -493,7 +540,8 @@ newLimbs[i] = limbs[i] + b.limbs[i]; } - return new ImmutableElement(newLimbs, false); + int newNumAdds = Math.max(numAdds, b.numAdds) + 1; + return new ImmutableElement(newLimbs, newNumAdds); } @Override @@ -504,7 +552,7 @@ newLimbs[i] = -limbs[i]; } - ImmutableElement result = new ImmutableElement(newLimbs, summand); + ImmutableElement result = new ImmutableElement(newLimbs, numAdds); return result; } @@ -524,43 +572,52 @@ long[] newLimbs = new long[limbs.length]; mult(limbs, b.limbs, newLimbs); - return new ImmutableElement(newLimbs, true); + return new ImmutableElement(newLimbs, 0); } @Override public ImmutableElement square() { long[] newLimbs = new long[limbs.length]; IntegerPolynomial.this.square(limbs, newLimbs); - return new ImmutableElement(newLimbs, true); + return new ImmutableElement(newLimbs, 0); } public void addModPowerTwo(IntegerModuloP arg, byte[] result) { Element other = (Element) arg; - if (!(summand && other.summand)) { + if (!(isSummand() && other.isSummand())) { throw new ArithmeticException("Not a valid summand"); } addLimbsModPowerTwo(limbs, other.limbs, result); } public void asByteArray(byte[] result) { - if (!summand) { + if (!isSummand()) { throw new ArithmeticException("Not a valid summand"); } limbsToByteArray(limbs, result); } } - private class MutableElement extends Element + protected class MutableElement extends Element implements MutableIntegerModuloP { - protected MutableElement(long[] limbs, boolean summand) { - super(limbs, summand); + protected MutableElement(long[] limbs, int numAdds) { + super(limbs, numAdds); } @Override public ImmutableElement fixed() { - return new ImmutableElement(limbs.clone(), summand); + return new ImmutableElement(limbs.clone(), numAdds); + } + + @Override + public void conditionalSet(IntegerModuloP b, int set) { + + Element other = (Element) b; + + conditionalAssign(set, limbs, other.limbs); + numAdds = other.numAdds; } @Override @@ -569,9 +626,9 @@ MutableElement other = (MutableElement) b; conditionalSwap(swap, limbs, other.limbs); - boolean summandTemp = summand; - summand = other.summand; - other.summand = summandTemp; + int numAddsTemp = numAdds; + numAdds = other.numAdds; + other.numAdds = numAddsTemp; } @@ -580,7 +637,7 @@ Element other = (Element) v; System.arraycopy(other.limbs, 0, limbs, 0, other.limbs.length); - summand = other.summand; + numAdds = other.numAdds; return this; } @@ -589,7 +646,7 @@ int length, byte highByte) { encode(arr, offset, length, highByte, limbs); - summand = true; + this.numAdds = 0; return this; } @@ -599,7 +656,7 @@ byte highByte) { encode(buf, length, highByte, limbs); - summand = true; + numAdds = 0; return this; } @@ -608,15 +665,15 @@ public MutableElement setProduct(IntegerModuloP genB) { Element b = (Element) genB; mult(limbs, b.limbs, limbs); - summand = true; + numAdds = 0; return this; } @Override public MutableElement setProduct(SmallValue v) { int value = ((Limb) v).value; - multByInt(limbs, value, limbs); - summand = true; + multByInt(limbs, value); + numAdds = 0; return this; } @@ -624,7 +681,7 @@ public MutableElement setSum(IntegerModuloP genB) { Element b = (Element) genB; - if (!(summand && b.summand)) { + if (!(isSummand() && b.isSummand())) { throw new ArithmeticException("Not a valid summand"); } @@ -632,7 +689,7 @@ limbs[i] = limbs[i] + b.limbs[i]; } - summand = false; + numAdds = Math.max(numAdds, b.numAdds) + 1; return this; } @@ -640,7 +697,7 @@ public MutableElement setDifference(IntegerModuloP genB) { Element b = (Element) genB; - if (!(summand && b.summand)) { + if (!(isSummand() && b.isSummand())) { throw new ArithmeticException("Not a valid summand"); } @@ -648,16 +705,33 @@ limbs[i] = limbs[i] - b.limbs[i]; } + numAdds = Math.max(numAdds, b.numAdds) + 1; return this; } @Override public MutableElement setSquare() { IntegerPolynomial.this.square(limbs, limbs); - summand = true; + numAdds = 0; return this; } + @Override + public MutableElement setAdditiveInverse() { + + for (int i = 0; i < limbs.length; i++) { + limbs[i] = -limbs[i]; + } + return this; + } + + @Override + public MutableElement setReduced() { + + reduce(limbs); + numAdds = 0; + return this; + } } class ImmutableElement extends Element implements ImmutableIntegerModuloP { @@ -670,8 +744,8 @@ super(v); } - protected ImmutableElement(long[] limbs, boolean summand) { - super(limbs, summand); + protected ImmutableElement(long[] limbs, int numAdds) { + super(limbs, numAdds); } @Override
--- a/src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomial1305.java Tue Dec 11 14:11:57 2018 +0000 +++ b/src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomial1305.java Wed Dec 12 15:07:56 2018 +0530 @@ -45,7 +45,7 @@ = TWO.pow(POWER).subtract(BigInteger.valueOf(SUBTRAHEND)); public IntegerPolynomial1305() { - super(BITS_PER_LIMB, NUM_LIMBS, MODULUS); + super(BITS_PER_LIMB, NUM_LIMBS, 1, MODULUS); } protected void mult(long[] a, long[] b, long[] r) { @@ -96,15 +96,6 @@ carry(r); } - protected void multByInt(long[] a, long b, long[] r) { - - for (int i = 0; i < a.length; i++) { - r[i] = a[i] * b; - } - - reduce(r); - } - @Override protected void square(long[] a, long[] r) { // Use grade-school multiplication with a simple squaring optimization. @@ -199,7 +190,12 @@ return x >> BITS_PER_LIMB; } + @Override + protected void postEncodeCarry(long[] v) { + // not needed because carry is unsigned + } + @Override protected void reduce(long[] limbs) { long carry3 = carryOut(limbs, 3); long new4 = carry3 + limbs[4];
--- a/src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomial25519.java Tue Dec 11 14:11:57 2018 +0000 +++ b/src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomial25519.java Wed Dec 12 15:07:56 2018 +0530 @@ -48,7 +48,7 @@ private static final int RIGHT_BIT_OFFSET = BITS_PER_LIMB - BIT_OFFSET; public IntegerPolynomial25519() { - super(BITS_PER_LIMB, NUM_LIMBS, MODULUS); + super(BITS_PER_LIMB, NUM_LIMBS, 1, MODULUS); } @Override @@ -60,6 +60,26 @@ } @Override + protected void reduce(long[] a) { + + // carry(8, 2) + long carry8 = carryValue(a[8]); + a[8] -= (carry8 << BITS_PER_LIMB); + a[9] += carry8; + + long carry9 = carryValue(a[9]); + a[9] -= (carry9 << BITS_PER_LIMB); + + // reduce(0, 1) + long reducedValue10 = (carry9 * SUBTRAHEND); + a[0] += ((reducedValue10 << BIT_OFFSET) & LIMB_MASK); + a[1] += reducedValue10 >> RIGHT_BIT_OFFSET; + + // carry(0, 9) + carry(a, 0, 9); + } + + @Override protected void mult(long[] a, long[] b, long[] r) { // Use grade-school multiplication into primitives to avoid the @@ -153,28 +173,6 @@ carry(r, 0, 9); } - protected void multByInt(long[] a, long b, long[] r) { - for (int i = 0; i < a.length; i++) { - r[i] = a[i] * b; - } - - // carry(8, 2) - long carry8 = carryValue(r[8]); - r[8] -= (carry8 << BITS_PER_LIMB); - r[9] += carry8; - - long carry9 = carryValue(r[9]); - r[9] -= (carry9 << BITS_PER_LIMB); - - // reduce(0, 1) - long reducedValue10 = (carry9 * SUBTRAHEND); - r[0] += ((reducedValue10 << BIT_OFFSET) & LIMB_MASK); - r[1] += reducedValue10 >> RIGHT_BIT_OFFSET; - - // carry(0, 9) - carry(r, 0, 9); - } - @Override protected void square(long[] a, long[] r) {
--- a/src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomial448.java Tue Dec 11 14:11:57 2018 +0000 +++ b/src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomial448.java Wed Dec 12 15:07:56 2018 +0530 @@ -42,7 +42,7 @@ .subtract(BigInteger.valueOf(1)); public IntegerPolynomial448() { - super(BITS_PER_LIMB, NUM_LIMBS, MODULUS); + super(BITS_PER_LIMB, NUM_LIMBS, 1, MODULUS); } private void modReduceIn(long[] limbs, int index, long x) { @@ -58,6 +58,25 @@ } @Override + protected void reduce(long[] a) { + + // carry(14, 2) + long carry14 = carryValue(a[14]); + a[14] -= (carry14 << BITS_PER_LIMB); + a[15] += carry14; + + long carry15 = carryValue(a[15]); + a[15] -= (carry15 << BITS_PER_LIMB); + + // reduce(0, 1) + a[0] += carry15; + a[8] += carry15; + + // carry(0, 15) + carry(a, 0, 15); + } + + @Override protected void mult(long[] a, long[] b, long[] r) { // Use grade-school multiplication into primitives to avoid the @@ -176,27 +195,6 @@ carry(r, 0, 15); } - protected void multByInt(long[] a, long b, long[] r) { - for (int i = 0; i < a.length; i++) { - r[i] = a[i] * b; - } - - // carry(14, 2) - long carry14 = carryValue(r[14]); - r[14] -= (carry14 << BITS_PER_LIMB); - r[15] += carry14; - - long carry15 = carryValue(r[15]); - r[15] -= (carry15 << BITS_PER_LIMB); - - // reduce(0, 1) - r[0] += carry15; - r[8] += carry15; - - // carry(0, 15) - carry(r, 0, 15); - } - @Override protected void square(long[] a, long[] r) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomialP256.java Wed Dec 12 15:07:56 2018 +0530 @@ -0,0 +1,339 @@ +/* + * Copyright (c) 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is generated by FieldGen.jsh. Do not modify it directly. + */ + +package sun.security.util.math.intpoly; + +import java.math.BigInteger; +public class IntegerPolynomialP256 extends IntegerPolynomial { + private static final int BITS_PER_LIMB = 26; + private static final int NUM_LIMBS = 10; + private static final int MAX_ADDS = 2; + public static final BigInteger MODULUS = evaluateModulus(); + private static final long CARRY_ADD = 1 << 25; + private static final int LIMB_MASK = -1 >>> (64 - BITS_PER_LIMB); + public IntegerPolynomialP256() { + + super(BITS_PER_LIMB, NUM_LIMBS, MAX_ADDS, MODULUS); + + } + private static BigInteger evaluateModulus() { + BigInteger result = BigInteger.valueOf(2).pow(256); + result = result.subtract(BigInteger.valueOf(2).pow(224)); + result = result.add(BigInteger.valueOf(2).pow(192)); + result = result.add(BigInteger.valueOf(2).pow(96)); + result = result.subtract(BigInteger.valueOf(1)); + return result; + } + @Override + protected void finalCarryReduceLast(long[] limbs) { + long c = limbs[9] >> 22; + limbs[9] -= c << 22; + limbs[8] += (c << 16) & LIMB_MASK; + limbs[9] += c >> 10; + limbs[7] -= (c << 10) & LIMB_MASK; + limbs[8] -= c >> 16; + limbs[3] -= (c << 18) & LIMB_MASK; + limbs[4] -= c >> 8; + limbs[0] += c; + } + private void carryReduce(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18) { + long c19 = 0; + //reduce from position 18 + c16 += (c18 << 20) & LIMB_MASK; + c17 += c18 >> 6; + c15 -= (c18 << 14) & LIMB_MASK; + c16 -= c18 >> 12; + c11 -= (c18 << 22) & LIMB_MASK; + c12 -= c18 >> 4; + c8 += (c18 << 4) & LIMB_MASK; + c9 += c18 >> 22; + //reduce from position 17 + c15 += (c17 << 20) & LIMB_MASK; + c16 += c17 >> 6; + c14 -= (c17 << 14) & LIMB_MASK; + c15 -= c17 >> 12; + c10 -= (c17 << 22) & LIMB_MASK; + c11 -= c17 >> 4; + c7 += (c17 << 4) & LIMB_MASK; + c8 += c17 >> 22; + //reduce from position 16 + c14 += (c16 << 20) & LIMB_MASK; + c15 += c16 >> 6; + c13 -= (c16 << 14) & LIMB_MASK; + c14 -= c16 >> 12; + c9 -= (c16 << 22) & LIMB_MASK; + c10 -= c16 >> 4; + c6 += (c16 << 4) & LIMB_MASK; + c7 += c16 >> 22; + //reduce from position 15 + c13 += (c15 << 20) & LIMB_MASK; + c14 += c15 >> 6; + c12 -= (c15 << 14) & LIMB_MASK; + c13 -= c15 >> 12; + c8 -= (c15 << 22) & LIMB_MASK; + c9 -= c15 >> 4; + c5 += (c15 << 4) & LIMB_MASK; + c6 += c15 >> 22; + //reduce from position 14 + c12 += (c14 << 20) & LIMB_MASK; + c13 += c14 >> 6; + c11 -= (c14 << 14) & LIMB_MASK; + c12 -= c14 >> 12; + c7 -= (c14 << 22) & LIMB_MASK; + c8 -= c14 >> 4; + c4 += (c14 << 4) & LIMB_MASK; + c5 += c14 >> 22; + //reduce from position 13 + c11 += (c13 << 20) & LIMB_MASK; + c12 += c13 >> 6; + c10 -= (c13 << 14) & LIMB_MASK; + c11 -= c13 >> 12; + c6 -= (c13 << 22) & LIMB_MASK; + c7 -= c13 >> 4; + c3 += (c13 << 4) & LIMB_MASK; + c4 += c13 >> 22; + //reduce from position 12 + c10 += (c12 << 20) & LIMB_MASK; + c11 += c12 >> 6; + c9 -= (c12 << 14) & LIMB_MASK; + c10 -= c12 >> 12; + c5 -= (c12 << 22) & LIMB_MASK; + c6 -= c12 >> 4; + c2 += (c12 << 4) & LIMB_MASK; + c3 += c12 >> 22; + //reduce from position 11 + c9 += (c11 << 20) & LIMB_MASK; + c10 += c11 >> 6; + c8 -= (c11 << 14) & LIMB_MASK; + c9 -= c11 >> 12; + c4 -= (c11 << 22) & LIMB_MASK; + c5 -= c11 >> 4; + c1 += (c11 << 4) & LIMB_MASK; + c2 += c11 >> 22; + //reduce from position 10 + c8 += (c10 << 20) & LIMB_MASK; + c9 += c10 >> 6; + c7 -= (c10 << 14) & LIMB_MASK; + c8 -= c10 >> 12; + c3 -= (c10 << 22) & LIMB_MASK; + c4 -= c10 >> 4; + c0 += (c10 << 4) & LIMB_MASK; + c1 += c10 >> 22; + c10 = 0; + + carryReduce0(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19); + } + void carryReduce0(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19) { + + //carry from position 8 + long t0 = (c8 + CARRY_ADD) >> 26; + c8 -= (t0 << 26); + c9 += t0; + //carry from position 9 + t0 = (c9 + CARRY_ADD) >> 26; + c9 -= (t0 << 26); + c10 += t0; + //reduce from position 10 + c8 += (c10 << 20) & LIMB_MASK; + c9 += c10 >> 6; + c7 -= (c10 << 14) & LIMB_MASK; + c8 -= c10 >> 12; + c3 -= (c10 << 22) & LIMB_MASK; + c4 -= c10 >> 4; + c0 += (c10 << 4) & LIMB_MASK; + c1 += c10 >> 22; + //carry from position 0 + t0 = (c0 + CARRY_ADD) >> 26; + c0 -= (t0 << 26); + c1 += t0; + //carry from position 1 + t0 = (c1 + CARRY_ADD) >> 26; + c1 -= (t0 << 26); + c2 += t0; + //carry from position 2 + t0 = (c2 + CARRY_ADD) >> 26; + c2 -= (t0 << 26); + c3 += t0; + //carry from position 3 + t0 = (c3 + CARRY_ADD) >> 26; + c3 -= (t0 << 26); + c4 += t0; + //carry from position 4 + t0 = (c4 + CARRY_ADD) >> 26; + c4 -= (t0 << 26); + c5 += t0; + //carry from position 5 + t0 = (c5 + CARRY_ADD) >> 26; + c5 -= (t0 << 26); + c6 += t0; + //carry from position 6 + t0 = (c6 + CARRY_ADD) >> 26; + c6 -= (t0 << 26); + c7 += t0; + //carry from position 7 + t0 = (c7 + CARRY_ADD) >> 26; + c7 -= (t0 << 26); + c8 += t0; + //carry from position 8 + t0 = (c8 + CARRY_ADD) >> 26; + c8 -= (t0 << 26); + c9 += t0; + + r[0] = c0; + r[1] = c1; + r[2] = c2; + r[3] = c3; + r[4] = c4; + r[5] = c5; + r[6] = c6; + r[7] = c7; + r[8] = c8; + r[9] = c9; + } + private void carryReduce(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9) { + long c10 = 0; + //carry from position 8 + long t0 = (c8 + CARRY_ADD) >> 26; + c8 -= (t0 << 26); + c9 += t0; + //carry from position 9 + t0 = (c9 + CARRY_ADD) >> 26; + c9 -= (t0 << 26); + c10 += t0; + //reduce from position 10 + c8 += (c10 << 20) & LIMB_MASK; + c9 += c10 >> 6; + c7 -= (c10 << 14) & LIMB_MASK; + c8 -= c10 >> 12; + c3 -= (c10 << 22) & LIMB_MASK; + c4 -= c10 >> 4; + c0 += (c10 << 4) & LIMB_MASK; + c1 += c10 >> 22; + //carry from position 0 + t0 = (c0 + CARRY_ADD) >> 26; + c0 -= (t0 << 26); + c1 += t0; + //carry from position 1 + t0 = (c1 + CARRY_ADD) >> 26; + c1 -= (t0 << 26); + c2 += t0; + //carry from position 2 + t0 = (c2 + CARRY_ADD) >> 26; + c2 -= (t0 << 26); + c3 += t0; + //carry from position 3 + t0 = (c3 + CARRY_ADD) >> 26; + c3 -= (t0 << 26); + c4 += t0; + //carry from position 4 + t0 = (c4 + CARRY_ADD) >> 26; + c4 -= (t0 << 26); + c5 += t0; + //carry from position 5 + t0 = (c5 + CARRY_ADD) >> 26; + c5 -= (t0 << 26); + c6 += t0; + //carry from position 6 + t0 = (c6 + CARRY_ADD) >> 26; + c6 -= (t0 << 26); + c7 += t0; + //carry from position 7 + t0 = (c7 + CARRY_ADD) >> 26; + c7 -= (t0 << 26); + c8 += t0; + //carry from position 8 + t0 = (c8 + CARRY_ADD) >> 26; + c8 -= (t0 << 26); + c9 += t0; + + r[0] = c0; + r[1] = c1; + r[2] = c2; + r[3] = c3; + r[4] = c4; + r[5] = c5; + r[6] = c6; + r[7] = c7; + r[8] = c8; + r[9] = c9; + } + @Override + protected void mult(long[] a, long[] b, long[] r) { + long c0 = (a[0] * b[0]); + long c1 = (a[0] * b[1]) + (a[1] * b[0]); + long c2 = (a[0] * b[2]) + (a[1] * b[1]) + (a[2] * b[0]); + long c3 = (a[0] * b[3]) + (a[1] * b[2]) + (a[2] * b[1]) + (a[3] * b[0]); + long c4 = (a[0] * b[4]) + (a[1] * b[3]) + (a[2] * b[2]) + (a[3] * b[1]) + (a[4] * b[0]); + long c5 = (a[0] * b[5]) + (a[1] * b[4]) + (a[2] * b[3]) + (a[3] * b[2]) + (a[4] * b[1]) + (a[5] * b[0]); + long c6 = (a[0] * b[6]) + (a[1] * b[5]) + (a[2] * b[4]) + (a[3] * b[3]) + (a[4] * b[2]) + (a[5] * b[1]) + (a[6] * b[0]); + long c7 = (a[0] * b[7]) + (a[1] * b[6]) + (a[2] * b[5]) + (a[3] * b[4]) + (a[4] * b[3]) + (a[5] * b[2]) + (a[6] * b[1]) + (a[7] * b[0]); + long c8 = (a[0] * b[8]) + (a[1] * b[7]) + (a[2] * b[6]) + (a[3] * b[5]) + (a[4] * b[4]) + (a[5] * b[3]) + (a[6] * b[2]) + (a[7] * b[1]) + (a[8] * b[0]); + long c9 = (a[0] * b[9]) + (a[1] * b[8]) + (a[2] * b[7]) + (a[3] * b[6]) + (a[4] * b[5]) + (a[5] * b[4]) + (a[6] * b[3]) + (a[7] * b[2]) + (a[8] * b[1]) + (a[9] * b[0]); + long c10 = (a[1] * b[9]) + (a[2] * b[8]) + (a[3] * b[7]) + (a[4] * b[6]) + (a[5] * b[5]) + (a[6] * b[4]) + (a[7] * b[3]) + (a[8] * b[2]) + (a[9] * b[1]); + long c11 = (a[2] * b[9]) + (a[3] * b[8]) + (a[4] * b[7]) + (a[5] * b[6]) + (a[6] * b[5]) + (a[7] * b[4]) + (a[8] * b[3]) + (a[9] * b[2]); + long c12 = (a[3] * b[9]) + (a[4] * b[8]) + (a[5] * b[7]) + (a[6] * b[6]) + (a[7] * b[5]) + (a[8] * b[4]) + (a[9] * b[3]); + long c13 = (a[4] * b[9]) + (a[5] * b[8]) + (a[6] * b[7]) + (a[7] * b[6]) + (a[8] * b[5]) + (a[9] * b[4]); + long c14 = (a[5] * b[9]) + (a[6] * b[8]) + (a[7] * b[7]) + (a[8] * b[6]) + (a[9] * b[5]); + long c15 = (a[6] * b[9]) + (a[7] * b[8]) + (a[8] * b[7]) + (a[9] * b[6]); + long c16 = (a[7] * b[9]) + (a[8] * b[8]) + (a[9] * b[7]); + long c17 = (a[8] * b[9]) + (a[9] * b[8]); + long c18 = (a[9] * b[9]); + + carryReduce(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18); + } + @Override + protected void reduce(long[] a) { + carryReduce(a, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9]); + } + @Override + protected void square(long[] a, long[] r) { + long c0 = (a[0] * a[0]); + long c1 = 2 * ((a[0] * a[1])); + long c2 = 2 * ((a[0] * a[2])) + (a[1] * a[1]); + long c3 = 2 * ((a[0] * a[3]) + (a[1] * a[2])); + long c4 = 2 * ((a[0] * a[4]) + (a[1] * a[3])) + (a[2] * a[2]); + long c5 = 2 * ((a[0] * a[5]) + (a[1] * a[4]) + (a[2] * a[3])); + long c6 = 2 * ((a[0] * a[6]) + (a[1] * a[5]) + (a[2] * a[4])) + (a[3] * a[3]); + long c7 = 2 * ((a[0] * a[7]) + (a[1] * a[6]) + (a[2] * a[5]) + (a[3] * a[4])); + long c8 = 2 * ((a[0] * a[8]) + (a[1] * a[7]) + (a[2] * a[6]) + (a[3] * a[5])) + (a[4] * a[4]); + long c9 = 2 * ((a[0] * a[9]) + (a[1] * a[8]) + (a[2] * a[7]) + (a[3] * a[6]) + (a[4] * a[5])); + long c10 = 2 * ((a[1] * a[9]) + (a[2] * a[8]) + (a[3] * a[7]) + (a[4] * a[6])) + (a[5] * a[5]); + long c11 = 2 * ((a[2] * a[9]) + (a[3] * a[8]) + (a[4] * a[7]) + (a[5] * a[6])); + long c12 = 2 * ((a[3] * a[9]) + (a[4] * a[8]) + (a[5] * a[7])) + (a[6] * a[6]); + long c13 = 2 * ((a[4] * a[9]) + (a[5] * a[8]) + (a[6] * a[7])); + long c14 = 2 * ((a[5] * a[9]) + (a[6] * a[8])) + (a[7] * a[7]); + long c15 = 2 * ((a[6] * a[9]) + (a[7] * a[8])); + long c16 = 2 * ((a[7] * a[9])) + (a[8] * a[8]); + long c17 = 2 * ((a[8] * a[9])); + long c18 = (a[9] * a[9]); + + carryReduce(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18); + } +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomialP384.java Wed Dec 12 15:07:56 2018 +0530 @@ -0,0 +1,431 @@ +/* + * Copyright (c) 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is generated by FieldGen.jsh. Do not modify it directly. + */ + +package sun.security.util.math.intpoly; + +import java.math.BigInteger; +public class IntegerPolynomialP384 extends IntegerPolynomial { + private static final int BITS_PER_LIMB = 28; + private static final int NUM_LIMBS = 14; + private static final int MAX_ADDS = 2; + public static final BigInteger MODULUS = evaluateModulus(); + private static final long CARRY_ADD = 1 << 27; + private static final int LIMB_MASK = -1 >>> (64 - BITS_PER_LIMB); + public IntegerPolynomialP384() { + + super(BITS_PER_LIMB, NUM_LIMBS, MAX_ADDS, MODULUS); + + } + private static BigInteger evaluateModulus() { + BigInteger result = BigInteger.valueOf(2).pow(384); + result = result.subtract(BigInteger.valueOf(2).pow(128)); + result = result.subtract(BigInteger.valueOf(2).pow(96)); + result = result.add(BigInteger.valueOf(2).pow(32)); + result = result.subtract(BigInteger.valueOf(1)); + return result; + } + @Override + protected void finalCarryReduceLast(long[] limbs) { + long c = limbs[13] >> 20; + limbs[13] -= c << 20; + limbs[4] += (c << 16) & LIMB_MASK; + limbs[5] += c >> 12; + limbs[3] += (c << 12) & LIMB_MASK; + limbs[4] += c >> 16; + limbs[1] -= (c << 4) & LIMB_MASK; + limbs[2] -= c >> 24; + limbs[0] += c; + } + private void carryReduce(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19, long c20, long c21, long c22, long c23, long c24, long c25, long c26) { + long c27 = 0; + //reduce from position 26 + c16 += (c26 << 24) & LIMB_MASK; + c17 += c26 >> 4; + c15 += (c26 << 20) & LIMB_MASK; + c16 += c26 >> 8; + c13 -= (c26 << 12) & LIMB_MASK; + c14 -= c26 >> 16; + c12 += (c26 << 8) & LIMB_MASK; + c13 += c26 >> 20; + //reduce from position 25 + c15 += (c25 << 24) & LIMB_MASK; + c16 += c25 >> 4; + c14 += (c25 << 20) & LIMB_MASK; + c15 += c25 >> 8; + c12 -= (c25 << 12) & LIMB_MASK; + c13 -= c25 >> 16; + c11 += (c25 << 8) & LIMB_MASK; + c12 += c25 >> 20; + //reduce from position 24 + c14 += (c24 << 24) & LIMB_MASK; + c15 += c24 >> 4; + c13 += (c24 << 20) & LIMB_MASK; + c14 += c24 >> 8; + c11 -= (c24 << 12) & LIMB_MASK; + c12 -= c24 >> 16; + c10 += (c24 << 8) & LIMB_MASK; + c11 += c24 >> 20; + //reduce from position 23 + c13 += (c23 << 24) & LIMB_MASK; + c14 += c23 >> 4; + c12 += (c23 << 20) & LIMB_MASK; + c13 += c23 >> 8; + c10 -= (c23 << 12) & LIMB_MASK; + c11 -= c23 >> 16; + c9 += (c23 << 8) & LIMB_MASK; + c10 += c23 >> 20; + //reduce from position 22 + c12 += (c22 << 24) & LIMB_MASK; + c13 += c22 >> 4; + c11 += (c22 << 20) & LIMB_MASK; + c12 += c22 >> 8; + c9 -= (c22 << 12) & LIMB_MASK; + c10 -= c22 >> 16; + c8 += (c22 << 8) & LIMB_MASK; + c9 += c22 >> 20; + //reduce from position 21 + c11 += (c21 << 24) & LIMB_MASK; + c12 += c21 >> 4; + c10 += (c21 << 20) & LIMB_MASK; + c11 += c21 >> 8; + c8 -= (c21 << 12) & LIMB_MASK; + c9 -= c21 >> 16; + c7 += (c21 << 8) & LIMB_MASK; + c8 += c21 >> 20; + //reduce from position 20 + c10 += (c20 << 24) & LIMB_MASK; + c11 += c20 >> 4; + c9 += (c20 << 20) & LIMB_MASK; + c10 += c20 >> 8; + c7 -= (c20 << 12) & LIMB_MASK; + c8 -= c20 >> 16; + c6 += (c20 << 8) & LIMB_MASK; + c7 += c20 >> 20; + //reduce from position 19 + c9 += (c19 << 24) & LIMB_MASK; + c10 += c19 >> 4; + c8 += (c19 << 20) & LIMB_MASK; + c9 += c19 >> 8; + c6 -= (c19 << 12) & LIMB_MASK; + c7 -= c19 >> 16; + c5 += (c19 << 8) & LIMB_MASK; + c6 += c19 >> 20; + //reduce from position 18 + c8 += (c18 << 24) & LIMB_MASK; + c9 += c18 >> 4; + c7 += (c18 << 20) & LIMB_MASK; + c8 += c18 >> 8; + c5 -= (c18 << 12) & LIMB_MASK; + c6 -= c18 >> 16; + c4 += (c18 << 8) & LIMB_MASK; + c5 += c18 >> 20; + //reduce from position 17 + c7 += (c17 << 24) & LIMB_MASK; + c8 += c17 >> 4; + c6 += (c17 << 20) & LIMB_MASK; + c7 += c17 >> 8; + c4 -= (c17 << 12) & LIMB_MASK; + c5 -= c17 >> 16; + c3 += (c17 << 8) & LIMB_MASK; + c4 += c17 >> 20; + //reduce from position 16 + c6 += (c16 << 24) & LIMB_MASK; + c7 += c16 >> 4; + c5 += (c16 << 20) & LIMB_MASK; + c6 += c16 >> 8; + c3 -= (c16 << 12) & LIMB_MASK; + c4 -= c16 >> 16; + c2 += (c16 << 8) & LIMB_MASK; + c3 += c16 >> 20; + //reduce from position 15 + c5 += (c15 << 24) & LIMB_MASK; + c6 += c15 >> 4; + c4 += (c15 << 20) & LIMB_MASK; + c5 += c15 >> 8; + c2 -= (c15 << 12) & LIMB_MASK; + c3 -= c15 >> 16; + c1 += (c15 << 8) & LIMB_MASK; + c2 += c15 >> 20; + //reduce from position 14 + c4 += (c14 << 24) & LIMB_MASK; + c5 += c14 >> 4; + c3 += (c14 << 20) & LIMB_MASK; + c4 += c14 >> 8; + c1 -= (c14 << 12) & LIMB_MASK; + c2 -= c14 >> 16; + c0 += (c14 << 8) & LIMB_MASK; + c1 += c14 >> 20; + c14 = 0; + + carryReduce0(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26, c27); + } + void carryReduce0(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19, long c20, long c21, long c22, long c23, long c24, long c25, long c26, long c27) { + + //carry from position 12 + long t0 = (c12 + CARRY_ADD) >> 28; + c12 -= (t0 << 28); + c13 += t0; + //carry from position 13 + t0 = (c13 + CARRY_ADD) >> 28; + c13 -= (t0 << 28); + c14 += t0; + //reduce from position 14 + c4 += (c14 << 24) & LIMB_MASK; + c5 += c14 >> 4; + c3 += (c14 << 20) & LIMB_MASK; + c4 += c14 >> 8; + c1 -= (c14 << 12) & LIMB_MASK; + c2 -= c14 >> 16; + c0 += (c14 << 8) & LIMB_MASK; + c1 += c14 >> 20; + //carry from position 0 + t0 = (c0 + CARRY_ADD) >> 28; + c0 -= (t0 << 28); + c1 += t0; + //carry from position 1 + t0 = (c1 + CARRY_ADD) >> 28; + c1 -= (t0 << 28); + c2 += t0; + //carry from position 2 + t0 = (c2 + CARRY_ADD) >> 28; + c2 -= (t0 << 28); + c3 += t0; + //carry from position 3 + t0 = (c3 + CARRY_ADD) >> 28; + c3 -= (t0 << 28); + c4 += t0; + //carry from position 4 + t0 = (c4 + CARRY_ADD) >> 28; + c4 -= (t0 << 28); + c5 += t0; + //carry from position 5 + t0 = (c5 + CARRY_ADD) >> 28; + c5 -= (t0 << 28); + c6 += t0; + //carry from position 6 + t0 = (c6 + CARRY_ADD) >> 28; + c6 -= (t0 << 28); + c7 += t0; + //carry from position 7 + t0 = (c7 + CARRY_ADD) >> 28; + c7 -= (t0 << 28); + c8 += t0; + //carry from position 8 + t0 = (c8 + CARRY_ADD) >> 28; + c8 -= (t0 << 28); + c9 += t0; + //carry from position 9 + t0 = (c9 + CARRY_ADD) >> 28; + c9 -= (t0 << 28); + c10 += t0; + //carry from position 10 + t0 = (c10 + CARRY_ADD) >> 28; + c10 -= (t0 << 28); + c11 += t0; + //carry from position 11 + t0 = (c11 + CARRY_ADD) >> 28; + c11 -= (t0 << 28); + c12 += t0; + //carry from position 12 + t0 = (c12 + CARRY_ADD) >> 28; + c12 -= (t0 << 28); + c13 += t0; + + r[0] = c0; + r[1] = c1; + r[2] = c2; + r[3] = c3; + r[4] = c4; + r[5] = c5; + r[6] = c6; + r[7] = c7; + r[8] = c8; + r[9] = c9; + r[10] = c10; + r[11] = c11; + r[12] = c12; + r[13] = c13; + } + private void carryReduce(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13) { + long c14 = 0; + //carry from position 12 + long t0 = (c12 + CARRY_ADD) >> 28; + c12 -= (t0 << 28); + c13 += t0; + //carry from position 13 + t0 = (c13 + CARRY_ADD) >> 28; + c13 -= (t0 << 28); + c14 += t0; + //reduce from position 14 + c4 += (c14 << 24) & LIMB_MASK; + c5 += c14 >> 4; + c3 += (c14 << 20) & LIMB_MASK; + c4 += c14 >> 8; + c1 -= (c14 << 12) & LIMB_MASK; + c2 -= c14 >> 16; + c0 += (c14 << 8) & LIMB_MASK; + c1 += c14 >> 20; + //carry from position 0 + t0 = (c0 + CARRY_ADD) >> 28; + c0 -= (t0 << 28); + c1 += t0; + //carry from position 1 + t0 = (c1 + CARRY_ADD) >> 28; + c1 -= (t0 << 28); + c2 += t0; + //carry from position 2 + t0 = (c2 + CARRY_ADD) >> 28; + c2 -= (t0 << 28); + c3 += t0; + //carry from position 3 + t0 = (c3 + CARRY_ADD) >> 28; + c3 -= (t0 << 28); + c4 += t0; + //carry from position 4 + t0 = (c4 + CARRY_ADD) >> 28; + c4 -= (t0 << 28); + c5 += t0; + //carry from position 5 + t0 = (c5 + CARRY_ADD) >> 28; + c5 -= (t0 << 28); + c6 += t0; + //carry from position 6 + t0 = (c6 + CARRY_ADD) >> 28; + c6 -= (t0 << 28); + c7 += t0; + //carry from position 7 + t0 = (c7 + CARRY_ADD) >> 28; + c7 -= (t0 << 28); + c8 += t0; + //carry from position 8 + t0 = (c8 + CARRY_ADD) >> 28; + c8 -= (t0 << 28); + c9 += t0; + //carry from position 9 + t0 = (c9 + CARRY_ADD) >> 28; + c9 -= (t0 << 28); + c10 += t0; + //carry from position 10 + t0 = (c10 + CARRY_ADD) >> 28; + c10 -= (t0 << 28); + c11 += t0; + //carry from position 11 + t0 = (c11 + CARRY_ADD) >> 28; + c11 -= (t0 << 28); + c12 += t0; + //carry from position 12 + t0 = (c12 + CARRY_ADD) >> 28; + c12 -= (t0 << 28); + c13 += t0; + + r[0] = c0; + r[1] = c1; + r[2] = c2; + r[3] = c3; + r[4] = c4; + r[5] = c5; + r[6] = c6; + r[7] = c7; + r[8] = c8; + r[9] = c9; + r[10] = c10; + r[11] = c11; + r[12] = c12; + r[13] = c13; + } + @Override + protected void mult(long[] a, long[] b, long[] r) { + long c0 = (a[0] * b[0]); + long c1 = (a[0] * b[1]) + (a[1] * b[0]); + long c2 = (a[0] * b[2]) + (a[1] * b[1]) + (a[2] * b[0]); + long c3 = (a[0] * b[3]) + (a[1] * b[2]) + (a[2] * b[1]) + (a[3] * b[0]); + long c4 = (a[0] * b[4]) + (a[1] * b[3]) + (a[2] * b[2]) + (a[3] * b[1]) + (a[4] * b[0]); + long c5 = (a[0] * b[5]) + (a[1] * b[4]) + (a[2] * b[3]) + (a[3] * b[2]) + (a[4] * b[1]) + (a[5] * b[0]); + long c6 = (a[0] * b[6]) + (a[1] * b[5]) + (a[2] * b[4]) + (a[3] * b[3]) + (a[4] * b[2]) + (a[5] * b[1]) + (a[6] * b[0]); + long c7 = (a[0] * b[7]) + (a[1] * b[6]) + (a[2] * b[5]) + (a[3] * b[4]) + (a[4] * b[3]) + (a[5] * b[2]) + (a[6] * b[1]) + (a[7] * b[0]); + long c8 = (a[0] * b[8]) + (a[1] * b[7]) + (a[2] * b[6]) + (a[3] * b[5]) + (a[4] * b[4]) + (a[5] * b[3]) + (a[6] * b[2]) + (a[7] * b[1]) + (a[8] * b[0]); + long c9 = (a[0] * b[9]) + (a[1] * b[8]) + (a[2] * b[7]) + (a[3] * b[6]) + (a[4] * b[5]) + (a[5] * b[4]) + (a[6] * b[3]) + (a[7] * b[2]) + (a[8] * b[1]) + (a[9] * b[0]); + long c10 = (a[0] * b[10]) + (a[1] * b[9]) + (a[2] * b[8]) + (a[3] * b[7]) + (a[4] * b[6]) + (a[5] * b[5]) + (a[6] * b[4]) + (a[7] * b[3]) + (a[8] * b[2]) + (a[9] * b[1]) + (a[10] * b[0]); + long c11 = (a[0] * b[11]) + (a[1] * b[10]) + (a[2] * b[9]) + (a[3] * b[8]) + (a[4] * b[7]) + (a[5] * b[6]) + (a[6] * b[5]) + (a[7] * b[4]) + (a[8] * b[3]) + (a[9] * b[2]) + (a[10] * b[1]) + (a[11] * b[0]); + long c12 = (a[0] * b[12]) + (a[1] * b[11]) + (a[2] * b[10]) + (a[3] * b[9]) + (a[4] * b[8]) + (a[5] * b[7]) + (a[6] * b[6]) + (a[7] * b[5]) + (a[8] * b[4]) + (a[9] * b[3]) + (a[10] * b[2]) + (a[11] * b[1]) + (a[12] * b[0]); + long c13 = (a[0] * b[13]) + (a[1] * b[12]) + (a[2] * b[11]) + (a[3] * b[10]) + (a[4] * b[9]) + (a[5] * b[8]) + (a[6] * b[7]) + (a[7] * b[6]) + (a[8] * b[5]) + (a[9] * b[4]) + (a[10] * b[3]) + (a[11] * b[2]) + (a[12] * b[1]) + (a[13] * b[0]); + long c14 = (a[1] * b[13]) + (a[2] * b[12]) + (a[3] * b[11]) + (a[4] * b[10]) + (a[5] * b[9]) + (a[6] * b[8]) + (a[7] * b[7]) + (a[8] * b[6]) + (a[9] * b[5]) + (a[10] * b[4]) + (a[11] * b[3]) + (a[12] * b[2]) + (a[13] * b[1]); + long c15 = (a[2] * b[13]) + (a[3] * b[12]) + (a[4] * b[11]) + (a[5] * b[10]) + (a[6] * b[9]) + (a[7] * b[8]) + (a[8] * b[7]) + (a[9] * b[6]) + (a[10] * b[5]) + (a[11] * b[4]) + (a[12] * b[3]) + (a[13] * b[2]); + long c16 = (a[3] * b[13]) + (a[4] * b[12]) + (a[5] * b[11]) + (a[6] * b[10]) + (a[7] * b[9]) + (a[8] * b[8]) + (a[9] * b[7]) + (a[10] * b[6]) + (a[11] * b[5]) + (a[12] * b[4]) + (a[13] * b[3]); + long c17 = (a[4] * b[13]) + (a[5] * b[12]) + (a[6] * b[11]) + (a[7] * b[10]) + (a[8] * b[9]) + (a[9] * b[8]) + (a[10] * b[7]) + (a[11] * b[6]) + (a[12] * b[5]) + (a[13] * b[4]); + long c18 = (a[5] * b[13]) + (a[6] * b[12]) + (a[7] * b[11]) + (a[8] * b[10]) + (a[9] * b[9]) + (a[10] * b[8]) + (a[11] * b[7]) + (a[12] * b[6]) + (a[13] * b[5]); + long c19 = (a[6] * b[13]) + (a[7] * b[12]) + (a[8] * b[11]) + (a[9] * b[10]) + (a[10] * b[9]) + (a[11] * b[8]) + (a[12] * b[7]) + (a[13] * b[6]); + long c20 = (a[7] * b[13]) + (a[8] * b[12]) + (a[9] * b[11]) + (a[10] * b[10]) + (a[11] * b[9]) + (a[12] * b[8]) + (a[13] * b[7]); + long c21 = (a[8] * b[13]) + (a[9] * b[12]) + (a[10] * b[11]) + (a[11] * b[10]) + (a[12] * b[9]) + (a[13] * b[8]); + long c22 = (a[9] * b[13]) + (a[10] * b[12]) + (a[11] * b[11]) + (a[12] * b[10]) + (a[13] * b[9]); + long c23 = (a[10] * b[13]) + (a[11] * b[12]) + (a[12] * b[11]) + (a[13] * b[10]); + long c24 = (a[11] * b[13]) + (a[12] * b[12]) + (a[13] * b[11]); + long c25 = (a[12] * b[13]) + (a[13] * b[12]); + long c26 = (a[13] * b[13]); + + carryReduce(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26); + } + @Override + protected void reduce(long[] a) { + carryReduce(a, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13]); + } + @Override + protected void square(long[] a, long[] r) { + long c0 = (a[0] * a[0]); + long c1 = 2 * ((a[0] * a[1])); + long c2 = 2 * ((a[0] * a[2])) + (a[1] * a[1]); + long c3 = 2 * ((a[0] * a[3]) + (a[1] * a[2])); + long c4 = 2 * ((a[0] * a[4]) + (a[1] * a[3])) + (a[2] * a[2]); + long c5 = 2 * ((a[0] * a[5]) + (a[1] * a[4]) + (a[2] * a[3])); + long c6 = 2 * ((a[0] * a[6]) + (a[1] * a[5]) + (a[2] * a[4])) + (a[3] * a[3]); + long c7 = 2 * ((a[0] * a[7]) + (a[1] * a[6]) + (a[2] * a[5]) + (a[3] * a[4])); + long c8 = 2 * ((a[0] * a[8]) + (a[1] * a[7]) + (a[2] * a[6]) + (a[3] * a[5])) + (a[4] * a[4]); + long c9 = 2 * ((a[0] * a[9]) + (a[1] * a[8]) + (a[2] * a[7]) + (a[3] * a[6]) + (a[4] * a[5])); + long c10 = 2 * ((a[0] * a[10]) + (a[1] * a[9]) + (a[2] * a[8]) + (a[3] * a[7]) + (a[4] * a[6])) + (a[5] * a[5]); + long c11 = 2 * ((a[0] * a[11]) + (a[1] * a[10]) + (a[2] * a[9]) + (a[3] * a[8]) + (a[4] * a[7]) + (a[5] * a[6])); + long c12 = 2 * ((a[0] * a[12]) + (a[1] * a[11]) + (a[2] * a[10]) + (a[3] * a[9]) + (a[4] * a[8]) + (a[5] * a[7])) + (a[6] * a[6]); + long c13 = 2 * ((a[0] * a[13]) + (a[1] * a[12]) + (a[2] * a[11]) + (a[3] * a[10]) + (a[4] * a[9]) + (a[5] * a[8]) + (a[6] * a[7])); + long c14 = 2 * ((a[1] * a[13]) + (a[2] * a[12]) + (a[3] * a[11]) + (a[4] * a[10]) + (a[5] * a[9]) + (a[6] * a[8])) + (a[7] * a[7]); + long c15 = 2 * ((a[2] * a[13]) + (a[3] * a[12]) + (a[4] * a[11]) + (a[5] * a[10]) + (a[6] * a[9]) + (a[7] * a[8])); + long c16 = 2 * ((a[3] * a[13]) + (a[4] * a[12]) + (a[5] * a[11]) + (a[6] * a[10]) + (a[7] * a[9])) + (a[8] * a[8]); + long c17 = 2 * ((a[4] * a[13]) + (a[5] * a[12]) + (a[6] * a[11]) + (a[7] * a[10]) + (a[8] * a[9])); + long c18 = 2 * ((a[5] * a[13]) + (a[6] * a[12]) + (a[7] * a[11]) + (a[8] * a[10])) + (a[9] * a[9]); + long c19 = 2 * ((a[6] * a[13]) + (a[7] * a[12]) + (a[8] * a[11]) + (a[9] * a[10])); + long c20 = 2 * ((a[7] * a[13]) + (a[8] * a[12]) + (a[9] * a[11])) + (a[10] * a[10]); + long c21 = 2 * ((a[8] * a[13]) + (a[9] * a[12]) + (a[10] * a[11])); + long c22 = 2 * ((a[9] * a[13]) + (a[10] * a[12])) + (a[11] * a[11]); + long c23 = 2 * ((a[10] * a[13]) + (a[11] * a[12])); + long c24 = 2 * ((a[11] * a[13])) + (a[12] * a[12]); + long c25 = 2 * ((a[12] * a[13])); + long c26 = (a[13] * a[13]); + + carryReduce(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26); + } +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/java.base/share/classes/sun/security/util/math/intpoly/IntegerPolynomialP521.java Wed Dec 12 15:07:56 2018 +0530 @@ -0,0 +1,417 @@ +/* + * Copyright (c) 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is generated by FieldGen.jsh. Do not modify it directly. + */ + +package sun.security.util.math.intpoly; + +import java.math.BigInteger; +public class IntegerPolynomialP521 extends IntegerPolynomial { + private static final int BITS_PER_LIMB = 28; + private static final int NUM_LIMBS = 19; + private static final int MAX_ADDS = 2; + public static final BigInteger MODULUS = evaluateModulus(); + private static final long CARRY_ADD = 1 << 27; + private static final int LIMB_MASK = -1 >>> (64 - BITS_PER_LIMB); + public IntegerPolynomialP521() { + + super(BITS_PER_LIMB, NUM_LIMBS, MAX_ADDS, MODULUS); + + } + private static BigInteger evaluateModulus() { + BigInteger result = BigInteger.valueOf(2).pow(521); + result = result.subtract(BigInteger.valueOf(1)); + return result; + } + @Override + protected void finalCarryReduceLast(long[] limbs) { + long c = limbs[18] >> 17; + limbs[18] -= c << 17; + limbs[0] += c; + } + private void carryReduce(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19, long c20, long c21, long c22, long c23, long c24, long c25, long c26, long c27, long c28, long c29, long c30, long c31, long c32, long c33, long c34, long c35, long c36) { + long c37 = 0; + //reduce from position 36 + c17 += (c36 << 11) & LIMB_MASK; + c18 += c36 >> 17; + //reduce from position 35 + c16 += (c35 << 11) & LIMB_MASK; + c17 += c35 >> 17; + //reduce from position 34 + c15 += (c34 << 11) & LIMB_MASK; + c16 += c34 >> 17; + //reduce from position 33 + c14 += (c33 << 11) & LIMB_MASK; + c15 += c33 >> 17; + //reduce from position 32 + c13 += (c32 << 11) & LIMB_MASK; + c14 += c32 >> 17; + //reduce from position 31 + c12 += (c31 << 11) & LIMB_MASK; + c13 += c31 >> 17; + //reduce from position 30 + c11 += (c30 << 11) & LIMB_MASK; + c12 += c30 >> 17; + //reduce from position 29 + c10 += (c29 << 11) & LIMB_MASK; + c11 += c29 >> 17; + //reduce from position 28 + c9 += (c28 << 11) & LIMB_MASK; + c10 += c28 >> 17; + //reduce from position 27 + c8 += (c27 << 11) & LIMB_MASK; + c9 += c27 >> 17; + //reduce from position 26 + c7 += (c26 << 11) & LIMB_MASK; + c8 += c26 >> 17; + //reduce from position 25 + c6 += (c25 << 11) & LIMB_MASK; + c7 += c25 >> 17; + //reduce from position 24 + c5 += (c24 << 11) & LIMB_MASK; + c6 += c24 >> 17; + //reduce from position 23 + c4 += (c23 << 11) & LIMB_MASK; + c5 += c23 >> 17; + //reduce from position 22 + c3 += (c22 << 11) & LIMB_MASK; + c4 += c22 >> 17; + //reduce from position 21 + c2 += (c21 << 11) & LIMB_MASK; + c3 += c21 >> 17; + //reduce from position 20 + c1 += (c20 << 11) & LIMB_MASK; + c2 += c20 >> 17; + //reduce from position 19 + c0 += (c19 << 11) & LIMB_MASK; + c1 += c19 >> 17; + c19 = 0; + + carryReduce0(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26, c27, c28, c29, c30, c31, c32, c33, c34, c35, c36, c37); + } + void carryReduce0(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19, long c20, long c21, long c22, long c23, long c24, long c25, long c26, long c27, long c28, long c29, long c30, long c31, long c32, long c33, long c34, long c35, long c36, long c37) { + + //carry from position 17 + long t0 = (c17 + CARRY_ADD) >> 28; + c17 -= (t0 << 28); + c18 += t0; + //carry from position 18 + t0 = (c18 + CARRY_ADD) >> 28; + c18 -= (t0 << 28); + c19 += t0; + //reduce from position 19 + c0 += (c19 << 11) & LIMB_MASK; + c1 += c19 >> 17; + //carry from position 0 + t0 = (c0 + CARRY_ADD) >> 28; + c0 -= (t0 << 28); + c1 += t0; + //carry from position 1 + t0 = (c1 + CARRY_ADD) >> 28; + c1 -= (t0 << 28); + c2 += t0; + //carry from position 2 + t0 = (c2 + CARRY_ADD) >> 28; + c2 -= (t0 << 28); + c3 += t0; + //carry from position 3 + t0 = (c3 + CARRY_ADD) >> 28; + c3 -= (t0 << 28); + c4 += t0; + //carry from position 4 + t0 = (c4 + CARRY_ADD) >> 28; + c4 -= (t0 << 28); + c5 += t0; + //carry from position 5 + t0 = (c5 + CARRY_ADD) >> 28; + c5 -= (t0 << 28); + c6 += t0; + //carry from position 6 + t0 = (c6 + CARRY_ADD) >> 28; + c6 -= (t0 << 28); + c7 += t0; + //carry from position 7 + t0 = (c7 + CARRY_ADD) >> 28; + c7 -= (t0 << 28); + c8 += t0; + //carry from position 8 + t0 = (c8 + CARRY_ADD) >> 28; + c8 -= (t0 << 28); + c9 += t0; + //carry from position 9 + t0 = (c9 + CARRY_ADD) >> 28; + c9 -= (t0 << 28); + c10 += t0; + //carry from position 10 + t0 = (c10 + CARRY_ADD) >> 28; + c10 -= (t0 << 28); + c11 += t0; + //carry from position 11 + t0 = (c11 + CARRY_ADD) >> 28; + c11 -= (t0 << 28); + c12 += t0; + //carry from position 12 + t0 = (c12 + CARRY_ADD) >> 28; + c12 -= (t0 << 28); + c13 += t0; + //carry from position 13 + t0 = (c13 + CARRY_ADD) >> 28; + c13 -= (t0 << 28); + c14 += t0; + //carry from position 14 + t0 = (c14 + CARRY_ADD) >> 28; + c14 -= (t0 << 28); + c15 += t0; + //carry from position 15 + t0 = (c15 + CARRY_ADD) >> 28; + c15 -= (t0 << 28); + c16 += t0; + //carry from position 16 + t0 = (c16 + CARRY_ADD) >> 28; + c16 -= (t0 << 28); + c17 += t0; + //carry from position 17 + t0 = (c17 + CARRY_ADD) >> 28; + c17 -= (t0 << 28); + c18 += t0; + + r[0] = c0; + r[1] = c1; + r[2] = c2; + r[3] = c3; + r[4] = c4; + r[5] = c5; + r[6] = c6; + r[7] = c7; + r[8] = c8; + r[9] = c9; + r[10] = c10; + r[11] = c11; + r[12] = c12; + r[13] = c13; + r[14] = c14; + r[15] = c15; + r[16] = c16; + r[17] = c17; + r[18] = c18; + } + private void carryReduce(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18) { + long c19 = 0; + //carry from position 17 + long t0 = (c17 + CARRY_ADD) >> 28; + c17 -= (t0 << 28); + c18 += t0; + //carry from position 18 + t0 = (c18 + CARRY_ADD) >> 28; + c18 -= (t0 << 28); + c19 += t0; + //reduce from position 19 + c0 += (c19 << 11) & LIMB_MASK; + c1 += c19 >> 17; + //carry from position 0 + t0 = (c0 + CARRY_ADD) >> 28; + c0 -= (t0 << 28); + c1 += t0; + //carry from position 1 + t0 = (c1 + CARRY_ADD) >> 28; + c1 -= (t0 << 28); + c2 += t0; + //carry from position 2 + t0 = (c2 + CARRY_ADD) >> 28; + c2 -= (t0 << 28); + c3 += t0; + //carry from position 3 + t0 = (c3 + CARRY_ADD) >> 28; + c3 -= (t0 << 28); + c4 += t0; + //carry from position 4 + t0 = (c4 + CARRY_ADD) >> 28; + c4 -= (t0 << 28); + c5 += t0; + //carry from position 5 + t0 = (c5 + CARRY_ADD) >> 28; + c5 -= (t0 << 28); + c6 += t0; + //carry from position 6 + t0 = (c6 + CARRY_ADD) >> 28; + c6 -= (t0 << 28); + c7 += t0; + //carry from position 7 + t0 = (c7 + CARRY_ADD) >> 28; + c7 -= (t0 << 28); + c8 += t0; + //carry from position 8 + t0 = (c8 + CARRY_ADD) >> 28; + c8 -= (t0 << 28); + c9 += t0; + //carry from position 9 + t0 = (c9 + CARRY_ADD) >> 28; + c9 -= (t0 << 28); + c10 += t0; + //carry from position 10 + t0 = (c10 + CARRY_ADD) >> 28; + c10 -= (t0 << 28); + c11 += t0; + //carry from position 11 + t0 = (c11 + CARRY_ADD) >> 28; + c11 -= (t0 << 28); + c12 += t0; + //carry from position 12 + t0 = (c12 + CARRY_ADD) >> 28; + c12 -= (t0 << 28); + c13 += t0; + //carry from position 13 + t0 = (c13 + CARRY_ADD) >> 28; + c13 -= (t0 << 28); + c14 += t0; + //carry from position 14 + t0 = (c14 + CARRY_ADD) >> 28; + c14 -= (t0 << 28); + c15 += t0; + //carry from position 15 + t0 = (c15 + CARRY_ADD) >> 28; + c15 -= (t0 << 28); + c16 += t0; + //carry from position 16 + t0 = (c16 + CARRY_ADD) >> 28; + c16 -= (t0 << 28); + c17 += t0; + //carry from position 17 + t0 = (c17 + CARRY_ADD) >> 28; + c17 -= (t0 << 28); + c18 += t0; + + r[0] = c0; + r[1] = c1; + r[2] = c2; + r[3] = c3; + r[4] = c4; + r[5] = c5; + r[6] = c6; + r[7] = c7; + r[8] = c8; + r[9] = c9; + r[10] = c10; + r[11] = c11; + r[12] = c12; + r[13] = c13; + r[14] = c14; + r[15] = c15; + r[16] = c16; + r[17] = c17; + r[18] = c18; + } + @Override + protected void mult(long[] a, long[] b, long[] r) { + long c0 = (a[0] * b[0]); + long c1 = (a[0] * b[1]) + (a[1] * b[0]); + long c2 = (a[0] * b[2]) + (a[1] * b[1]) + (a[2] * b[0]); + long c3 = (a[0] * b[3]) + (a[1] * b[2]) + (a[2] * b[1]) + (a[3] * b[0]); + long c4 = (a[0] * b[4]) + (a[1] * b[3]) + (a[2] * b[2]) + (a[3] * b[1]) + (a[4] * b[0]); + long c5 = (a[0] * b[5]) + (a[1] * b[4]) + (a[2] * b[3]) + (a[3] * b[2]) + (a[4] * b[1]) + (a[5] * b[0]); + long c6 = (a[0] * b[6]) + (a[1] * b[5]) + (a[2] * b[4]) + (a[3] * b[3]) + (a[4] * b[2]) + (a[5] * b[1]) + (a[6] * b[0]); + long c7 = (a[0] * b[7]) + (a[1] * b[6]) + (a[2] * b[5]) + (a[3] * b[4]) + (a[4] * b[3]) + (a[5] * b[2]) + (a[6] * b[1]) + (a[7] * b[0]); + long c8 = (a[0] * b[8]) + (a[1] * b[7]) + (a[2] * b[6]) + (a[3] * b[5]) + (a[4] * b[4]) + (a[5] * b[3]) + (a[6] * b[2]) + (a[7] * b[1]) + (a[8] * b[0]); + long c9 = (a[0] * b[9]) + (a[1] * b[8]) + (a[2] * b[7]) + (a[3] * b[6]) + (a[4] * b[5]) + (a[5] * b[4]) + (a[6] * b[3]) + (a[7] * b[2]) + (a[8] * b[1]) + (a[9] * b[0]); + long c10 = (a[0] * b[10]) + (a[1] * b[9]) + (a[2] * b[8]) + (a[3] * b[7]) + (a[4] * b[6]) + (a[5] * b[5]) + (a[6] * b[4]) + (a[7] * b[3]) + (a[8] * b[2]) + (a[9] * b[1]) + (a[10] * b[0]); + long c11 = (a[0] * b[11]) + (a[1] * b[10]) + (a[2] * b[9]) + (a[3] * b[8]) + (a[4] * b[7]) + (a[5] * b[6]) + (a[6] * b[5]) + (a[7] * b[4]) + (a[8] * b[3]) + (a[9] * b[2]) + (a[10] * b[1]) + (a[11] * b[0]); + long c12 = (a[0] * b[12]) + (a[1] * b[11]) + (a[2] * b[10]) + (a[3] * b[9]) + (a[4] * b[8]) + (a[5] * b[7]) + (a[6] * b[6]) + (a[7] * b[5]) + (a[8] * b[4]) + (a[9] * b[3]) + (a[10] * b[2]) + (a[11] * b[1]) + (a[12] * b[0]); + long c13 = (a[0] * b[13]) + (a[1] * b[12]) + (a[2] * b[11]) + (a[3] * b[10]) + (a[4] * b[9]) + (a[5] * b[8]) + (a[6] * b[7]) + (a[7] * b[6]) + (a[8] * b[5]) + (a[9] * b[4]) + (a[10] * b[3]) + (a[11] * b[2]) + (a[12] * b[1]) + (a[13] * b[0]); + long c14 = (a[0] * b[14]) + (a[1] * b[13]) + (a[2] * b[12]) + (a[3] * b[11]) + (a[4] * b[10]) + (a[5] * b[9]) + (a[6] * b[8]) + (a[7] * b[7]) + (a[8] * b[6]) + (a[9] * b[5]) + (a[10] * b[4]) + (a[11] * b[3]) + (a[12] * b[2]) + (a[13] * b[1]) + (a[14] * b[0]); + long c15 = (a[0] * b[15]) + (a[1] * b[14]) + (a[2] * b[13]) + (a[3] * b[12]) + (a[4] * b[11]) + (a[5] * b[10]) + (a[6] * b[9]) + (a[7] * b[8]) + (a[8] * b[7]) + (a[9] * b[6]) + (a[10] * b[5]) + (a[11] * b[4]) + (a[12] * b[3]) + (a[13] * b[2]) + (a[14] * b[1]) + (a[15] * b[0]); + long c16 = (a[0] * b[16]) + (a[1] * b[15]) + (a[2] * b[14]) + (a[3] * b[13]) + (a[4] * b[12]) + (a[5] * b[11]) + (a[6] * b[10]) + (a[7] * b[9]) + (a[8] * b[8]) + (a[9] * b[7]) + (a[10] * b[6]) + (a[11] * b[5]) + (a[12] * b[4]) + (a[13] * b[3]) + (a[14] * b[2]) + (a[15] * b[1]) + (a[16] * b[0]); + long c17 = (a[0] * b[17]) + (a[1] * b[16]) + (a[2] * b[15]) + (a[3] * b[14]) + (a[4] * b[13]) + (a[5] * b[12]) + (a[6] * b[11]) + (a[7] * b[10]) + (a[8] * b[9]) + (a[9] * b[8]) + (a[10] * b[7]) + (a[11] * b[6]) + (a[12] * b[5]) + (a[13] * b[4]) + (a[14] * b[3]) + (a[15] * b[2]) + (a[16] * b[1]) + (a[17] * b[0]); + long c18 = (a[0] * b[18]) + (a[1] * b[17]) + (a[2] * b[16]) + (a[3] * b[15]) + (a[4] * b[14]) + (a[5] * b[13]) + (a[6] * b[12]) + (a[7] * b[11]) + (a[8] * b[10]) + (a[9] * b[9]) + (a[10] * b[8]) + (a[11] * b[7]) + (a[12] * b[6]) + (a[13] * b[5]) + (a[14] * b[4]) + (a[15] * b[3]) + (a[16] * b[2]) + (a[17] * b[1]) + (a[18] * b[0]); + long c19 = (a[1] * b[18]) + (a[2] * b[17]) + (a[3] * b[16]) + (a[4] * b[15]) + (a[5] * b[14]) + (a[6] * b[13]) + (a[7] * b[12]) + (a[8] * b[11]) + (a[9] * b[10]) + (a[10] * b[9]) + (a[11] * b[8]) + (a[12] * b[7]) + (a[13] * b[6]) + (a[14] * b[5]) + (a[15] * b[4]) + (a[16] * b[3]) + (a[17] * b[2]) + (a[18] * b[1]); + long c20 = (a[2] * b[18]) + (a[3] * b[17]) + (a[4] * b[16]) + (a[5] * b[15]) + (a[6] * b[14]) + (a[7] * b[13]) + (a[8] * b[12]) + (a[9] * b[11]) + (a[10] * b[10]) + (a[11] * b[9]) + (a[12] * b[8]) + (a[13] * b[7]) + (a[14] * b[6]) + (a[15] * b[5]) + (a[16] * b[4]) + (a[17] * b[3]) + (a[18] * b[2]); + long c21 = (a[3] * b[18]) + (a[4] * b[17]) + (a[5] * b[16]) + (a[6] * b[15]) + (a[7] * b[14]) + (a[8] * b[13]) + (a[9] * b[12]) + (a[10] * b[11]) + (a[11] * b[10]) + (a[12] * b[9]) + (a[13] * b[8]) + (a[14] * b[7]) + (a[15] * b[6]) + (a[16] * b[5]) + (a[17] * b[4]) + (a[18] * b[3]); + long c22 = (a[4] * b[18]) + (a[5] * b[17]) + (a[6] * b[16]) + (a[7] * b[15]) + (a[8] * b[14]) + (a[9] * b[13]) + (a[10] * b[12]) + (a[11] * b[11]) + (a[12] * b[10]) + (a[13] * b[9]) + (a[14] * b[8]) + (a[15] * b[7]) + (a[16] * b[6]) + (a[17] * b[5]) + (a[18] * b[4]); + long c23 = (a[5] * b[18]) + (a[6] * b[17]) + (a[7] * b[16]) + (a[8] * b[15]) + (a[9] * b[14]) + (a[10] * b[13]) + (a[11] * b[12]) + (a[12] * b[11]) + (a[13] * b[10]) + (a[14] * b[9]) + (a[15] * b[8]) + (a[16] * b[7]) + (a[17] * b[6]) + (a[18] * b[5]); + long c24 = (a[6] * b[18]) + (a[7] * b[17]) + (a[8] * b[16]) + (a[9] * b[15]) + (a[10] * b[14]) + (a[11] * b[13]) + (a[12] * b[12]) + (a[13] * b[11]) + (a[14] * b[10]) + (a[15] * b[9]) + (a[16] * b[8]) + (a[17] * b[7]) + (a[18] * b[6]); + long c25 = (a[7] * b[18]) + (a[8] * b[17]) + (a[9] * b[16]) + (a[10] * b[15]) + (a[11] * b[14]) + (a[12] * b[13]) + (a[13] * b[12]) + (a[14] * b[11]) + (a[15] * b[10]) + (a[16] * b[9]) + (a[17] * b[8]) + (a[18] * b[7]); + long c26 = (a[8] * b[18]) + (a[9] * b[17]) + (a[10] * b[16]) + (a[11] * b[15]) + (a[12] * b[14]) + (a[13] * b[13]) + (a[14] * b[12]) + (a[15] * b[11]) + (a[16] * b[10]) + (a[17] * b[9]) + (a[18] * b[8]); + long c27 = (a[9] * b[18]) + (a[10] * b[17]) + (a[11] * b[16]) + (a[12] * b[15]) + (a[13] * b[14]) + (a[14] * b[13]) + (a[15] * b[12]) + (a[16] * b[11]) + (a[17] * b[10]) + (a[18] * b[9]); + long c28 = (a[10] * b[18]) + (a[11] * b[17]) + (a[12] * b[16]) + (a[13] * b[15]) + (a[14] * b[14]) + (a[15] * b[13]) + (a[16] * b[12]) + (a[17] * b[11]) + (a[18] * b[10]); + long c29 = (a[11] * b[18]) + (a[12] * b[17]) + (a[13] * b[16]) + (a[14] * b[15]) + (a[15] * b[14]) + (a[16] * b[13]) + (a[17] * b[12]) + (a[18] * b[11]); + long c30 = (a[12] * b[18]) + (a[13] * b[17]) + (a[14] * b[16]) + (a[15] * b[15]) + (a[16] * b[14]) + (a[17] * b[13]) + (a[18] * b[12]); + long c31 = (a[13] * b[18]) + (a[14] * b[17]) + (a[15] * b[16]) + (a[16] * b[15]) + (a[17] * b[14]) + (a[18] * b[13]); + long c32 = (a[14] * b[18]) + (a[15] * b[17]) + (a[16] * b[16]) + (a[17] * b[15]) + (a[18] * b[14]); + long c33 = (a[15] * b[18]) + (a[16] * b[17]) + (a[17] * b[16]) + (a[18] * b[15]); + long c34 = (a[16] * b[18]) + (a[17] * b[17]) + (a[18] * b[16]); + long c35 = (a[17] * b[18]) + (a[18] * b[17]); + long c36 = (a[18] * b[18]); + + carryReduce(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26, c27, c28, c29, c30, c31, c32, c33, c34, c35, c36); + } + @Override + protected void reduce(long[] a) { + carryReduce(a, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15], a[16], a[17], a[18]); + } + @Override + protected void square(long[] a, long[] r) { + long c0 = (a[0] * a[0]); + long c1 = 2 * ((a[0] * a[1])); + long c2 = 2 * ((a[0] * a[2])) + (a[1] * a[1]); + long c3 = 2 * ((a[0] * a[3]) + (a[1] * a[2])); + long c4 = 2 * ((a[0] * a[4]) + (a[1] * a[3])) + (a[2] * a[2]); + long c5 = 2 * ((a[0] * a[5]) + (a[1] * a[4]) + (a[2] * a[3])); + long c6 = 2 * ((a[0] * a[6]) + (a[1] * a[5]) + (a[2] * a[4])) + (a[3] * a[3]); + long c7 = 2 * ((a[0] * a[7]) + (a[1] * a[6]) + (a[2] * a[5]) + (a[3] * a[4])); + long c8 = 2 * ((a[0] * a[8]) + (a[1] * a[7]) + (a[2] * a[6]) + (a[3] * a[5])) + (a[4] * a[4]); + long c9 = 2 * ((a[0] * a[9]) + (a[1] * a[8]) + (a[2] * a[7]) + (a[3] * a[6]) + (a[4] * a[5])); + long c10 = 2 * ((a[0] * a[10]) + (a[1] * a[9]) + (a[2] * a[8]) + (a[3] * a[7]) + (a[4] * a[6])) + (a[5] * a[5]); + long c11 = 2 * ((a[0] * a[11]) + (a[1] * a[10]) + (a[2] * a[9]) + (a[3] * a[8]) + (a[4] * a[7]) + (a[5] * a[6])); + long c12 = 2 * ((a[0] * a[12]) + (a[1] * a[11]) + (a[2] * a[10]) + (a[3] * a[9]) + (a[4] * a[8]) + (a[5] * a[7])) + (a[6] * a[6]); + long c13 = 2 * ((a[0] * a[13]) + (a[1] * a[12]) + (a[2] * a[11]) + (a[3] * a[10]) + (a[4] * a[9]) + (a[5] * a[8]) + (a[6] * a[7])); + long c14 = 2 * ((a[0] * a[14]) + (a[1] * a[13]) + (a[2] * a[12]) + (a[3] * a[11]) + (a[4] * a[10]) + (a[5] * a[9]) + (a[6] * a[8])) + (a[7] * a[7]); + long c15 = 2 * ((a[0] * a[15]) + (a[1] * a[14]) + (a[2] * a[13]) + (a[3] * a[12]) + (a[4] * a[11]) + (a[5] * a[10]) + (a[6] * a[9]) + (a[7] * a[8])); + long c16 = 2 * ((a[0] * a[16]) + (a[1] * a[15]) + (a[2] * a[14]) + (a[3] * a[13]) + (a[4] * a[12]) + (a[5] * a[11]) + (a[6] * a[10]) + (a[7] * a[9])) + (a[8] * a[8]); + long c17 = 2 * ((a[0] * a[17]) + (a[1] * a[16]) + (a[2] * a[15]) + (a[3] * a[14]) + (a[4] * a[13]) + (a[5] * a[12]) + (a[6] * a[11]) + (a[7] * a[10]) + (a[8] * a[9])); + long c18 = 2 * ((a[0] * a[18]) + (a[1] * a[17]) + (a[2] * a[16]) + (a[3] * a[15]) + (a[4] * a[14]) + (a[5] * a[13]) + (a[6] * a[12]) + (a[7] * a[11]) + (a[8] * a[10])) + (a[9] * a[9]); + long c19 = 2 * ((a[1] * a[18]) + (a[2] * a[17]) + (a[3] * a[16]) + (a[4] * a[15]) + (a[5] * a[14]) + (a[6] * a[13]) + (a[7] * a[12]) + (a[8] * a[11]) + (a[9] * a[10])); + long c20 = 2 * ((a[2] * a[18]) + (a[3] * a[17]) + (a[4] * a[16]) + (a[5] * a[15]) + (a[6] * a[14]) + (a[7] * a[13]) + (a[8] * a[12]) + (a[9] * a[11])) + (a[10] * a[10]); + long c21 = 2 * ((a[3] * a[18]) + (a[4] * a[17]) + (a[5] * a[16]) + (a[6] * a[15]) + (a[7] * a[14]) + (a[8] * a[13]) + (a[9] * a[12]) + (a[10] * a[11])); + long c22 = 2 * ((a[4] * a[18]) + (a[5] * a[17]) + (a[6] * a[16]) + (a[7] * a[15]) + (a[8] * a[14]) + (a[9] * a[13]) + (a[10] * a[12])) + (a[11] * a[11]); + long c23 = 2 * ((a[5] * a[18]) + (a[6] * a[17]) + (a[7] * a[16]) + (a[8] * a[15]) + (a[9] * a[14]) + (a[10] * a[13]) + (a[11] * a[12])); + long c24 = 2 * ((a[6] * a[18]) + (a[7] * a[17]) + (a[8] * a[16]) + (a[9] * a[15]) + (a[10] * a[14]) + (a[11] * a[13])) + (a[12] * a[12]); + long c25 = 2 * ((a[7] * a[18]) + (a[8] * a[17]) + (a[9] * a[16]) + (a[10] * a[15]) + (a[11] * a[14]) + (a[12] * a[13])); + long c26 = 2 * ((a[8] * a[18]) + (a[9] * a[17]) + (a[10] * a[16]) + (a[11] * a[15]) + (a[12] * a[14])) + (a[13] * a[13]); + long c27 = 2 * ((a[9] * a[18]) + (a[10] * a[17]) + (a[11] * a[16]) + (a[12] * a[15]) + (a[13] * a[14])); + long c28 = 2 * ((a[10] * a[18]) + (a[11] * a[17]) + (a[12] * a[16]) + (a[13] * a[15])) + (a[14] * a[14]); + long c29 = 2 * ((a[11] * a[18]) + (a[12] * a[17]) + (a[13] * a[16]) + (a[14] * a[15])); + long c30 = 2 * ((a[12] * a[18]) + (a[13] * a[17]) + (a[14] * a[16])) + (a[15] * a[15]); + long c31 = 2 * ((a[13] * a[18]) + (a[14] * a[17]) + (a[15] * a[16])); + long c32 = 2 * ((a[14] * a[18]) + (a[15] * a[17])) + (a[16] * a[16]); + long c33 = 2 * ((a[15] * a[18]) + (a[16] * a[17])); + long c34 = 2 * ((a[16] * a[18])) + (a[17] * a[17]); + long c35 = 2 * ((a[17] * a[18])); + long c36 = (a[18] * a[18]); + + carryReduce(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26, c27, c28, c29, c30, c31, c32, c33, c34, c35, c36); + } +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/java.base/share/classes/sun/security/util/math/intpoly/P256OrderField.java Wed Dec 12 15:07:56 2018 +0530 @@ -0,0 +1,673 @@ +/* + * Copyright (c) 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is generated by FieldGen.jsh. Do not modify it directly. + */ + +package sun.security.util.math.intpoly; + +import java.math.BigInteger; +public class P256OrderField extends IntegerPolynomial { + private static final int BITS_PER_LIMB = 26; + private static final int NUM_LIMBS = 10; + private static final int MAX_ADDS = 1; + public static final BigInteger MODULUS = evaluateModulus(); + private static final long CARRY_ADD = 1 << 25; + private static final int LIMB_MASK = -1 >>> (64 - BITS_PER_LIMB); + public P256OrderField() { + + super(BITS_PER_LIMB, NUM_LIMBS, MAX_ADDS, MODULUS); + + } + private static BigInteger evaluateModulus() { + BigInteger result = BigInteger.valueOf(2).pow(256); + result = result.add(BigInteger.valueOf(6497617)); + result = result.subtract(BigInteger.valueOf(2).pow(26).multiply(BigInteger.valueOf(26038081))); + result = result.add(BigInteger.valueOf(2).pow(52).multiply(BigInteger.valueOf(32001852))); + result = result.subtract(BigInteger.valueOf(2).pow(78).multiply(BigInteger.valueOf(21586850))); + result = result.subtract(BigInteger.valueOf(2).pow(104).multiply(BigInteger.valueOf(4397317))); + result = result.add(BigInteger.valueOf(2).pow(182).multiply(BigInteger.valueOf(1024))); + result = result.subtract(BigInteger.valueOf(2).pow(208).multiply(BigInteger.valueOf(65536))); + return result; + } + @Override + protected void finalCarryReduceLast(long[] limbs) { + long c = limbs[9] >> 22; + limbs[9] -= c << 22; + long t0 = -6497617 * c; + limbs[0] += t0; + t0 = 26038081 * c; + limbs[1] += t0; + t0 = -32001852 * c; + limbs[2] += t0; + t0 = 21586850 * c; + limbs[3] += t0; + t0 = 4397317 * c; + limbs[4] += t0; + t0 = -1024 * c; + limbs[7] += t0; + t0 = 65536 * c; + limbs[8] += t0; + } + private void carryReduce(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18) { + long c19 = 0; + //carry from position 0 + long t0 = (c0 + CARRY_ADD) >> 26; + c0 -= (t0 << 26); + c1 += t0; + //carry from position 1 + t0 = (c1 + CARRY_ADD) >> 26; + c1 -= (t0 << 26); + c2 += t0; + //carry from position 2 + t0 = (c2 + CARRY_ADD) >> 26; + c2 -= (t0 << 26); + c3 += t0; + //carry from position 3 + t0 = (c3 + CARRY_ADD) >> 26; + c3 -= (t0 << 26); + c4 += t0; + //carry from position 4 + t0 = (c4 + CARRY_ADD) >> 26; + c4 -= (t0 << 26); + c5 += t0; + //carry from position 5 + t0 = (c5 + CARRY_ADD) >> 26; + c5 -= (t0 << 26); + c6 += t0; + //carry from position 6 + t0 = (c6 + CARRY_ADD) >> 26; + c6 -= (t0 << 26); + c7 += t0; + //carry from position 7 + t0 = (c7 + CARRY_ADD) >> 26; + c7 -= (t0 << 26); + c8 += t0; + //carry from position 8 + t0 = (c8 + CARRY_ADD) >> 26; + c8 -= (t0 << 26); + c9 += t0; + //carry from position 9 + t0 = (c9 + CARRY_ADD) >> 26; + c9 -= (t0 << 26); + c10 += t0; + //carry from position 10 + t0 = (c10 + CARRY_ADD) >> 26; + c10 -= (t0 << 26); + c11 += t0; + //carry from position 11 + t0 = (c11 + CARRY_ADD) >> 26; + c11 -= (t0 << 26); + c12 += t0; + //carry from position 12 + t0 = (c12 + CARRY_ADD) >> 26; + c12 -= (t0 << 26); + c13 += t0; + //carry from position 13 + t0 = (c13 + CARRY_ADD) >> 26; + c13 -= (t0 << 26); + c14 += t0; + //carry from position 14 + t0 = (c14 + CARRY_ADD) >> 26; + c14 -= (t0 << 26); + c15 += t0; + //carry from position 15 + t0 = (c15 + CARRY_ADD) >> 26; + c15 -= (t0 << 26); + c16 += t0; + //carry from position 16 + t0 = (c16 + CARRY_ADD) >> 26; + c16 -= (t0 << 26); + c17 += t0; + //carry from position 17 + t0 = (c17 + CARRY_ADD) >> 26; + c17 -= (t0 << 26); + c18 += t0; + //carry from position 18 + t0 = (c18 + CARRY_ADD) >> 26; + c18 -= (t0 << 26); + c19 += t0; + + carryReduce0(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19); + } + void carryReduce0(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19) { + long t0; + + //reduce from position 19 + t0 = -6497617 * c19; + c9 += (t0 << 4) & LIMB_MASK; + c10 += t0 >> 22; + t0 = 26038081 * c19; + c10 += (t0 << 4) & LIMB_MASK; + c11 += t0 >> 22; + t0 = -32001852 * c19; + c11 += (t0 << 4) & LIMB_MASK; + c12 += t0 >> 22; + t0 = 21586850 * c19; + c12 += (t0 << 4) & LIMB_MASK; + c13 += t0 >> 22; + t0 = 4397317 * c19; + c13 += (t0 << 4) & LIMB_MASK; + c14 += t0 >> 22; + t0 = -1024 * c19; + c16 += (t0 << 4) & LIMB_MASK; + c17 += t0 >> 22; + t0 = 65536 * c19; + c17 += (t0 << 4) & LIMB_MASK; + c18 += t0 >> 22; + //reduce from position 18 + t0 = -6497617 * c18; + c8 += (t0 << 4) & LIMB_MASK; + c9 += t0 >> 22; + t0 = 26038081 * c18; + c9 += (t0 << 4) & LIMB_MASK; + c10 += t0 >> 22; + t0 = -32001852 * c18; + c10 += (t0 << 4) & LIMB_MASK; + c11 += t0 >> 22; + t0 = 21586850 * c18; + c11 += (t0 << 4) & LIMB_MASK; + c12 += t0 >> 22; + t0 = 4397317 * c18; + c12 += (t0 << 4) & LIMB_MASK; + c13 += t0 >> 22; + t0 = -1024 * c18; + c15 += (t0 << 4) & LIMB_MASK; + c16 += t0 >> 22; + t0 = 65536 * c18; + c16 += (t0 << 4) & LIMB_MASK; + c17 += t0 >> 22; + //reduce from position 17 + t0 = -6497617 * c17; + c7 += (t0 << 4) & LIMB_MASK; + c8 += t0 >> 22; + t0 = 26038081 * c17; + c8 += (t0 << 4) & LIMB_MASK; + c9 += t0 >> 22; + t0 = -32001852 * c17; + c9 += (t0 << 4) & LIMB_MASK; + c10 += t0 >> 22; + t0 = 21586850 * c17; + c10 += (t0 << 4) & LIMB_MASK; + c11 += t0 >> 22; + t0 = 4397317 * c17; + c11 += (t0 << 4) & LIMB_MASK; + c12 += t0 >> 22; + t0 = -1024 * c17; + c14 += (t0 << 4) & LIMB_MASK; + c15 += t0 >> 22; + t0 = 65536 * c17; + c15 += (t0 << 4) & LIMB_MASK; + c16 += t0 >> 22; + //reduce from position 16 + t0 = -6497617 * c16; + c6 += (t0 << 4) & LIMB_MASK; + c7 += t0 >> 22; + t0 = 26038081 * c16; + c7 += (t0 << 4) & LIMB_MASK; + c8 += t0 >> 22; + t0 = -32001852 * c16; + c8 += (t0 << 4) & LIMB_MASK; + c9 += t0 >> 22; + t0 = 21586850 * c16; + c9 += (t0 << 4) & LIMB_MASK; + c10 += t0 >> 22; + t0 = 4397317 * c16; + c10 += (t0 << 4) & LIMB_MASK; + c11 += t0 >> 22; + t0 = -1024 * c16; + c13 += (t0 << 4) & LIMB_MASK; + c14 += t0 >> 22; + t0 = 65536 * c16; + c14 += (t0 << 4) & LIMB_MASK; + c15 += t0 >> 22; + //reduce from position 15 + t0 = -6497617 * c15; + c5 += (t0 << 4) & LIMB_MASK; + c6 += t0 >> 22; + t0 = 26038081 * c15; + c6 += (t0 << 4) & LIMB_MASK; + c7 += t0 >> 22; + t0 = -32001852 * c15; + c7 += (t0 << 4) & LIMB_MASK; + c8 += t0 >> 22; + t0 = 21586850 * c15; + c8 += (t0 << 4) & LIMB_MASK; + c9 += t0 >> 22; + t0 = 4397317 * c15; + c9 += (t0 << 4) & LIMB_MASK; + c10 += t0 >> 22; + t0 = -1024 * c15; + c12 += (t0 << 4) & LIMB_MASK; + c13 += t0 >> 22; + t0 = 65536 * c15; + c13 += (t0 << 4) & LIMB_MASK; + c14 += t0 >> 22; + //reduce from position 14 + t0 = -6497617 * c14; + c4 += (t0 << 4) & LIMB_MASK; + c5 += t0 >> 22; + t0 = 26038081 * c14; + c5 += (t0 << 4) & LIMB_MASK; + c6 += t0 >> 22; + t0 = -32001852 * c14; + c6 += (t0 << 4) & LIMB_MASK; + c7 += t0 >> 22; + t0 = 21586850 * c14; + c7 += (t0 << 4) & LIMB_MASK; + c8 += t0 >> 22; + t0 = 4397317 * c14; + c8 += (t0 << 4) & LIMB_MASK; + c9 += t0 >> 22; + t0 = -1024 * c14; + c11 += (t0 << 4) & LIMB_MASK; + c12 += t0 >> 22; + t0 = 65536 * c14; + c12 += (t0 << 4) & LIMB_MASK; + c13 += t0 >> 22; + //reduce from position 13 + t0 = -6497617 * c13; + c3 += (t0 << 4) & LIMB_MASK; + c4 += t0 >> 22; + t0 = 26038081 * c13; + c4 += (t0 << 4) & LIMB_MASK; + c5 += t0 >> 22; + t0 = -32001852 * c13; + c5 += (t0 << 4) & LIMB_MASK; + c6 += t0 >> 22; + t0 = 21586850 * c13; + c6 += (t0 << 4) & LIMB_MASK; + c7 += t0 >> 22; + t0 = 4397317 * c13; + c7 += (t0 << 4) & LIMB_MASK; + c8 += t0 >> 22; + t0 = -1024 * c13; + c10 += (t0 << 4) & LIMB_MASK; + c11 += t0 >> 22; + t0 = 65536 * c13; + c11 += (t0 << 4) & LIMB_MASK; + c12 += t0 >> 22; + //reduce from position 12 + t0 = -6497617 * c12; + c2 += (t0 << 4) & LIMB_MASK; + c3 += t0 >> 22; + t0 = 26038081 * c12; + c3 += (t0 << 4) & LIMB_MASK; + c4 += t0 >> 22; + t0 = -32001852 * c12; + c4 += (t0 << 4) & LIMB_MASK; + c5 += t0 >> 22; + t0 = 21586850 * c12; + c5 += (t0 << 4) & LIMB_MASK; + c6 += t0 >> 22; + t0 = 4397317 * c12; + c6 += (t0 << 4) & LIMB_MASK; + c7 += t0 >> 22; + t0 = -1024 * c12; + c9 += (t0 << 4) & LIMB_MASK; + c10 += t0 >> 22; + t0 = 65536 * c12; + c10 += (t0 << 4) & LIMB_MASK; + c11 += t0 >> 22; + //reduce from position 11 + t0 = -6497617 * c11; + c1 += (t0 << 4) & LIMB_MASK; + c2 += t0 >> 22; + t0 = 26038081 * c11; + c2 += (t0 << 4) & LIMB_MASK; + c3 += t0 >> 22; + t0 = -32001852 * c11; + c3 += (t0 << 4) & LIMB_MASK; + c4 += t0 >> 22; + t0 = 21586850 * c11; + c4 += (t0 << 4) & LIMB_MASK; + c5 += t0 >> 22; + t0 = 4397317 * c11; + c5 += (t0 << 4) & LIMB_MASK; + c6 += t0 >> 22; + t0 = -1024 * c11; + c8 += (t0 << 4) & LIMB_MASK; + c9 += t0 >> 22; + t0 = 65536 * c11; + c9 += (t0 << 4) & LIMB_MASK; + c10 += t0 >> 22; + //reduce from position 10 + t0 = -6497617 * c10; + c0 += (t0 << 4) & LIMB_MASK; + c1 += t0 >> 22; + t0 = 26038081 * c10; + c1 += (t0 << 4) & LIMB_MASK; + c2 += t0 >> 22; + t0 = -32001852 * c10; + c2 += (t0 << 4) & LIMB_MASK; + c3 += t0 >> 22; + t0 = 21586850 * c10; + c3 += (t0 << 4) & LIMB_MASK; + c4 += t0 >> 22; + t0 = 4397317 * c10; + c4 += (t0 << 4) & LIMB_MASK; + c5 += t0 >> 22; + t0 = -1024 * c10; + c7 += (t0 << 4) & LIMB_MASK; + c8 += t0 >> 22; + t0 = 65536 * c10; + c8 += (t0 << 4) & LIMB_MASK; + c9 += t0 >> 22; + c10 = 0; + + carryReduce1(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19); + } + void carryReduce1(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19) { + long t0; + + //carry from position 0 + t0 = (c0 + CARRY_ADD) >> 26; + c0 -= (t0 << 26); + c1 += t0; + //carry from position 1 + t0 = (c1 + CARRY_ADD) >> 26; + c1 -= (t0 << 26); + c2 += t0; + //carry from position 2 + t0 = (c2 + CARRY_ADD) >> 26; + c2 -= (t0 << 26); + c3 += t0; + //carry from position 3 + t0 = (c3 + CARRY_ADD) >> 26; + c3 -= (t0 << 26); + c4 += t0; + //carry from position 4 + t0 = (c4 + CARRY_ADD) >> 26; + c4 -= (t0 << 26); + c5 += t0; + //carry from position 5 + t0 = (c5 + CARRY_ADD) >> 26; + c5 -= (t0 << 26); + c6 += t0; + //carry from position 6 + t0 = (c6 + CARRY_ADD) >> 26; + c6 -= (t0 << 26); + c7 += t0; + //carry from position 7 + t0 = (c7 + CARRY_ADD) >> 26; + c7 -= (t0 << 26); + c8 += t0; + //carry from position 8 + t0 = (c8 + CARRY_ADD) >> 26; + c8 -= (t0 << 26); + c9 += t0; + //carry from position 9 + t0 = (c9 + CARRY_ADD) >> 26; + c9 -= (t0 << 26); + c10 += t0; + + carryReduce2(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19); + } + void carryReduce2(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19) { + long t0; + + //reduce from position 10 + t0 = -6497617 * c10; + c0 += (t0 << 4) & LIMB_MASK; + c1 += t0 >> 22; + t0 = 26038081 * c10; + c1 += (t0 << 4) & LIMB_MASK; + c2 += t0 >> 22; + t0 = -32001852 * c10; + c2 += (t0 << 4) & LIMB_MASK; + c3 += t0 >> 22; + t0 = 21586850 * c10; + c3 += (t0 << 4) & LIMB_MASK; + c4 += t0 >> 22; + t0 = 4397317 * c10; + c4 += (t0 << 4) & LIMB_MASK; + c5 += t0 >> 22; + t0 = -1024 * c10; + c7 += (t0 << 4) & LIMB_MASK; + c8 += t0 >> 22; + t0 = 65536 * c10; + c8 += (t0 << 4) & LIMB_MASK; + c9 += t0 >> 22; + //carry from position 0 + t0 = (c0 + CARRY_ADD) >> 26; + c0 -= (t0 << 26); + c1 += t0; + //carry from position 1 + t0 = (c1 + CARRY_ADD) >> 26; + c1 -= (t0 << 26); + c2 += t0; + //carry from position 2 + t0 = (c2 + CARRY_ADD) >> 26; + c2 -= (t0 << 26); + c3 += t0; + //carry from position 3 + t0 = (c3 + CARRY_ADD) >> 26; + c3 -= (t0 << 26); + c4 += t0; + //carry from position 4 + t0 = (c4 + CARRY_ADD) >> 26; + c4 -= (t0 << 26); + c5 += t0; + //carry from position 5 + t0 = (c5 + CARRY_ADD) >> 26; + c5 -= (t0 << 26); + c6 += t0; + //carry from position 6 + t0 = (c6 + CARRY_ADD) >> 26; + c6 -= (t0 << 26); + c7 += t0; + //carry from position 7 + t0 = (c7 + CARRY_ADD) >> 26; + c7 -= (t0 << 26); + c8 += t0; + //carry from position 8 + t0 = (c8 + CARRY_ADD) >> 26; + c8 -= (t0 << 26); + c9 += t0; + + r[0] = c0; + r[1] = c1; + r[2] = c2; + r[3] = c3; + r[4] = c4; + r[5] = c5; + r[6] = c6; + r[7] = c7; + r[8] = c8; + r[9] = c9; + } + private void carryReduce(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9) { + long c10 = 0; + //carry from position 0 + long t0 = (c0 + CARRY_ADD) >> 26; + c0 -= (t0 << 26); + c1 += t0; + //carry from position 1 + t0 = (c1 + CARRY_ADD) >> 26; + c1 -= (t0 << 26); + c2 += t0; + //carry from position 2 + t0 = (c2 + CARRY_ADD) >> 26; + c2 -= (t0 << 26); + c3 += t0; + //carry from position 3 + t0 = (c3 + CARRY_ADD) >> 26; + c3 -= (t0 << 26); + c4 += t0; + //carry from position 4 + t0 = (c4 + CARRY_ADD) >> 26; + c4 -= (t0 << 26); + c5 += t0; + //carry from position 5 + t0 = (c5 + CARRY_ADD) >> 26; + c5 -= (t0 << 26); + c6 += t0; + //carry from position 6 + t0 = (c6 + CARRY_ADD) >> 26; + c6 -= (t0 << 26); + c7 += t0; + //carry from position 7 + t0 = (c7 + CARRY_ADD) >> 26; + c7 -= (t0 << 26); + c8 += t0; + //carry from position 8 + t0 = (c8 + CARRY_ADD) >> 26; + c8 -= (t0 << 26); + c9 += t0; + //carry from position 9 + t0 = (c9 + CARRY_ADD) >> 26; + c9 -= (t0 << 26); + c10 += t0; + + carryReduce0(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10); + } + void carryReduce0(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10) { + long t0; + + //reduce from position 10 + t0 = -6497617 * c10; + c0 += (t0 << 4) & LIMB_MASK; + c1 += t0 >> 22; + t0 = 26038081 * c10; + c1 += (t0 << 4) & LIMB_MASK; + c2 += t0 >> 22; + t0 = -32001852 * c10; + c2 += (t0 << 4) & LIMB_MASK; + c3 += t0 >> 22; + t0 = 21586850 * c10; + c3 += (t0 << 4) & LIMB_MASK; + c4 += t0 >> 22; + t0 = 4397317 * c10; + c4 += (t0 << 4) & LIMB_MASK; + c5 += t0 >> 22; + t0 = -1024 * c10; + c7 += (t0 << 4) & LIMB_MASK; + c8 += t0 >> 22; + t0 = 65536 * c10; + c8 += (t0 << 4) & LIMB_MASK; + c9 += t0 >> 22; + //carry from position 0 + t0 = (c0 + CARRY_ADD) >> 26; + c0 -= (t0 << 26); + c1 += t0; + //carry from position 1 + t0 = (c1 + CARRY_ADD) >> 26; + c1 -= (t0 << 26); + c2 += t0; + //carry from position 2 + t0 = (c2 + CARRY_ADD) >> 26; + c2 -= (t0 << 26); + c3 += t0; + //carry from position 3 + t0 = (c3 + CARRY_ADD) >> 26; + c3 -= (t0 << 26); + c4 += t0; + //carry from position 4 + t0 = (c4 + CARRY_ADD) >> 26; + c4 -= (t0 << 26); + c5 += t0; + //carry from position 5 + t0 = (c5 + CARRY_ADD) >> 26; + c5 -= (t0 << 26); + c6 += t0; + //carry from position 6 + t0 = (c6 + CARRY_ADD) >> 26; + c6 -= (t0 << 26); + c7 += t0; + //carry from position 7 + t0 = (c7 + CARRY_ADD) >> 26; + c7 -= (t0 << 26); + c8 += t0; + //carry from position 8 + t0 = (c8 + CARRY_ADD) >> 26; + c8 -= (t0 << 26); + c9 += t0; + + r[0] = c0; + r[1] = c1; + r[2] = c2; + r[3] = c3; + r[4] = c4; + r[5] = c5; + r[6] = c6; + r[7] = c7; + r[8] = c8; + r[9] = c9; + } + @Override + protected void mult(long[] a, long[] b, long[] r) { + long c0 = (a[0] * b[0]); + long c1 = (a[0] * b[1]) + (a[1] * b[0]); + long c2 = (a[0] * b[2]) + (a[1] * b[1]) + (a[2] * b[0]); + long c3 = (a[0] * b[3]) + (a[1] * b[2]) + (a[2] * b[1]) + (a[3] * b[0]); + long c4 = (a[0] * b[4]) + (a[1] * b[3]) + (a[2] * b[2]) + (a[3] * b[1]) + (a[4] * b[0]); + long c5 = (a[0] * b[5]) + (a[1] * b[4]) + (a[2] * b[3]) + (a[3] * b[2]) + (a[4] * b[1]) + (a[5] * b[0]); + long c6 = (a[0] * b[6]) + (a[1] * b[5]) + (a[2] * b[4]) + (a[3] * b[3]) + (a[4] * b[2]) + (a[5] * b[1]) + (a[6] * b[0]); + long c7 = (a[0] * b[7]) + (a[1] * b[6]) + (a[2] * b[5]) + (a[3] * b[4]) + (a[4] * b[3]) + (a[5] * b[2]) + (a[6] * b[1]) + (a[7] * b[0]); + long c8 = (a[0] * b[8]) + (a[1] * b[7]) + (a[2] * b[6]) + (a[3] * b[5]) + (a[4] * b[4]) + (a[5] * b[3]) + (a[6] * b[2]) + (a[7] * b[1]) + (a[8] * b[0]); + long c9 = (a[0] * b[9]) + (a[1] * b[8]) + (a[2] * b[7]) + (a[3] * b[6]) + (a[4] * b[5]) + (a[5] * b[4]) + (a[6] * b[3]) + (a[7] * b[2]) + (a[8] * b[1]) + (a[9] * b[0]); + long c10 = (a[1] * b[9]) + (a[2] * b[8]) + (a[3] * b[7]) + (a[4] * b[6]) + (a[5] * b[5]) + (a[6] * b[4]) + (a[7] * b[3]) + (a[8] * b[2]) + (a[9] * b[1]); + long c11 = (a[2] * b[9]) + (a[3] * b[8]) + (a[4] * b[7]) + (a[5] * b[6]) + (a[6] * b[5]) + (a[7] * b[4]) + (a[8] * b[3]) + (a[9] * b[2]); + long c12 = (a[3] * b[9]) + (a[4] * b[8]) + (a[5] * b[7]) + (a[6] * b[6]) + (a[7] * b[5]) + (a[8] * b[4]) + (a[9] * b[3]); + long c13 = (a[4] * b[9]) + (a[5] * b[8]) + (a[6] * b[7]) + (a[7] * b[6]) + (a[8] * b[5]) + (a[9] * b[4]); + long c14 = (a[5] * b[9]) + (a[6] * b[8]) + (a[7] * b[7]) + (a[8] * b[6]) + (a[9] * b[5]); + long c15 = (a[6] * b[9]) + (a[7] * b[8]) + (a[8] * b[7]) + (a[9] * b[6]); + long c16 = (a[7] * b[9]) + (a[8] * b[8]) + (a[9] * b[7]); + long c17 = (a[8] * b[9]) + (a[9] * b[8]); + long c18 = (a[9] * b[9]); + + carryReduce(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18); + } + @Override + protected void reduce(long[] a) { + carryReduce(a, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9]); + } + @Override + protected void square(long[] a, long[] r) { + long c0 = (a[0] * a[0]); + long c1 = 2 * ((a[0] * a[1])); + long c2 = 2 * ((a[0] * a[2])) + (a[1] * a[1]); + long c3 = 2 * ((a[0] * a[3]) + (a[1] * a[2])); + long c4 = 2 * ((a[0] * a[4]) + (a[1] * a[3])) + (a[2] * a[2]); + long c5 = 2 * ((a[0] * a[5]) + (a[1] * a[4]) + (a[2] * a[3])); + long c6 = 2 * ((a[0] * a[6]) + (a[1] * a[5]) + (a[2] * a[4])) + (a[3] * a[3]); + long c7 = 2 * ((a[0] * a[7]) + (a[1] * a[6]) + (a[2] * a[5]) + (a[3] * a[4])); + long c8 = 2 * ((a[0] * a[8]) + (a[1] * a[7]) + (a[2] * a[6]) + (a[3] * a[5])) + (a[4] * a[4]); + long c9 = 2 * ((a[0] * a[9]) + (a[1] * a[8]) + (a[2] * a[7]) + (a[3] * a[6]) + (a[4] * a[5])); + long c10 = 2 * ((a[1] * a[9]) + (a[2] * a[8]) + (a[3] * a[7]) + (a[4] * a[6])) + (a[5] * a[5]); + long c11 = 2 * ((a[2] * a[9]) + (a[3] * a[8]) + (a[4] * a[7]) + (a[5] * a[6])); + long c12 = 2 * ((a[3] * a[9]) + (a[4] * a[8]) + (a[5] * a[7])) + (a[6] * a[6]); + long c13 = 2 * ((a[4] * a[9]) + (a[5] * a[8]) + (a[6] * a[7])); + long c14 = 2 * ((a[5] * a[9]) + (a[6] * a[8])) + (a[7] * a[7]); + long c15 = 2 * ((a[6] * a[9]) + (a[7] * a[8])); + long c16 = 2 * ((a[7] * a[9])) + (a[8] * a[8]); + long c17 = 2 * ((a[8] * a[9])); + long c18 = (a[9] * a[9]); + + carryReduce(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18); + } +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/java.base/share/classes/sun/security/util/math/intpoly/P384OrderField.java Wed Dec 12 15:07:56 2018 +0530 @@ -0,0 +1,881 @@ +/* + * Copyright (c) 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is generated by FieldGen.jsh. Do not modify it directly. + */ + +package sun.security.util.math.intpoly; + +import java.math.BigInteger; +public class P384OrderField extends IntegerPolynomial { + private static final int BITS_PER_LIMB = 28; + private static final int NUM_LIMBS = 14; + private static final int MAX_ADDS = 1; + public static final BigInteger MODULUS = evaluateModulus(); + private static final long CARRY_ADD = 1 << 27; + private static final int LIMB_MASK = -1 >>> (64 - BITS_PER_LIMB); + public P384OrderField() { + + super(BITS_PER_LIMB, NUM_LIMBS, MAX_ADDS, MODULUS); + + } + private static BigInteger evaluateModulus() { + BigInteger result = BigInteger.valueOf(2).pow(384); + result = result.subtract(BigInteger.valueOf(54187661)); + result = result.subtract(BigInteger.valueOf(2).pow(28).multiply(BigInteger.valueOf(20867411))); + result = result.add(BigInteger.valueOf(2).pow(56).multiply(BigInteger.valueOf(10975981))); + result = result.add(BigInteger.valueOf(2).pow(84).multiply(BigInteger.valueOf(14361739))); + result = result.subtract(BigInteger.valueOf(2).pow(112).multiply(BigInteger.valueOf(35694566))); + result = result.subtract(BigInteger.valueOf(2).pow(140).multiply(BigInteger.valueOf(132168845))); + result = result.subtract(BigInteger.valueOf(2).pow(168).multiply(BigInteger.valueOf(3710130))); + return result; + } + @Override + protected void finalCarryReduceLast(long[] limbs) { + long c = limbs[13] >> 20; + limbs[13] -= c << 20; + long t0 = 54187661 * c; + limbs[0] += t0; + t0 = 20867411 * c; + limbs[1] += t0; + t0 = -10975981 * c; + limbs[2] += t0; + t0 = -14361739 * c; + limbs[3] += t0; + t0 = 35694566 * c; + limbs[4] += t0; + t0 = 132168845 * c; + limbs[5] += t0; + t0 = 3710130 * c; + limbs[6] += t0; + } + private void carryReduce(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19, long c20, long c21, long c22, long c23, long c24, long c25, long c26) { + long c27 = 0; + //carry from position 0 + long t0 = (c0 + CARRY_ADD) >> 28; + c0 -= (t0 << 28); + c1 += t0; + //carry from position 1 + t0 = (c1 + CARRY_ADD) >> 28; + c1 -= (t0 << 28); + c2 += t0; + //carry from position 2 + t0 = (c2 + CARRY_ADD) >> 28; + c2 -= (t0 << 28); + c3 += t0; + //carry from position 3 + t0 = (c3 + CARRY_ADD) >> 28; + c3 -= (t0 << 28); + c4 += t0; + //carry from position 4 + t0 = (c4 + CARRY_ADD) >> 28; + c4 -= (t0 << 28); + c5 += t0; + //carry from position 5 + t0 = (c5 + CARRY_ADD) >> 28; + c5 -= (t0 << 28); + c6 += t0; + //carry from position 6 + t0 = (c6 + CARRY_ADD) >> 28; + c6 -= (t0 << 28); + c7 += t0; + //carry from position 7 + t0 = (c7 + CARRY_ADD) >> 28; + c7 -= (t0 << 28); + c8 += t0; + //carry from position 8 + t0 = (c8 + CARRY_ADD) >> 28; + c8 -= (t0 << 28); + c9 += t0; + //carry from position 9 + t0 = (c9 + CARRY_ADD) >> 28; + c9 -= (t0 << 28); + c10 += t0; + //carry from position 10 + t0 = (c10 + CARRY_ADD) >> 28; + c10 -= (t0 << 28); + c11 += t0; + //carry from position 11 + t0 = (c11 + CARRY_ADD) >> 28; + c11 -= (t0 << 28); + c12 += t0; + //carry from position 12 + t0 = (c12 + CARRY_ADD) >> 28; + c12 -= (t0 << 28); + c13 += t0; + //carry from position 13 + t0 = (c13 + CARRY_ADD) >> 28; + c13 -= (t0 << 28); + c14 += t0; + //carry from position 14 + t0 = (c14 + CARRY_ADD) >> 28; + c14 -= (t0 << 28); + c15 += t0; + //carry from position 15 + t0 = (c15 + CARRY_ADD) >> 28; + c15 -= (t0 << 28); + c16 += t0; + //carry from position 16 + t0 = (c16 + CARRY_ADD) >> 28; + c16 -= (t0 << 28); + c17 += t0; + //carry from position 17 + t0 = (c17 + CARRY_ADD) >> 28; + c17 -= (t0 << 28); + c18 += t0; + //carry from position 18 + t0 = (c18 + CARRY_ADD) >> 28; + c18 -= (t0 << 28); + c19 += t0; + //carry from position 19 + t0 = (c19 + CARRY_ADD) >> 28; + c19 -= (t0 << 28); + c20 += t0; + //carry from position 20 + t0 = (c20 + CARRY_ADD) >> 28; + c20 -= (t0 << 28); + c21 += t0; + //carry from position 21 + t0 = (c21 + CARRY_ADD) >> 28; + c21 -= (t0 << 28); + c22 += t0; + //carry from position 22 + t0 = (c22 + CARRY_ADD) >> 28; + c22 -= (t0 << 28); + c23 += t0; + //carry from position 23 + t0 = (c23 + CARRY_ADD) >> 28; + c23 -= (t0 << 28); + c24 += t0; + //carry from position 24 + t0 = (c24 + CARRY_ADD) >> 28; + c24 -= (t0 << 28); + c25 += t0; + //carry from position 25 + t0 = (c25 + CARRY_ADD) >> 28; + c25 -= (t0 << 28); + c26 += t0; + //carry from position 26 + t0 = (c26 + CARRY_ADD) >> 28; + c26 -= (t0 << 28); + c27 += t0; + + carryReduce0(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26, c27); + } + void carryReduce0(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19, long c20, long c21, long c22, long c23, long c24, long c25, long c26, long c27) { + long t0; + + //reduce from position 27 + t0 = 54187661 * c27; + c13 += (t0 << 8) & LIMB_MASK; + c14 += t0 >> 20; + t0 = 20867411 * c27; + c14 += (t0 << 8) & LIMB_MASK; + c15 += t0 >> 20; + t0 = -10975981 * c27; + c15 += (t0 << 8) & LIMB_MASK; + c16 += t0 >> 20; + t0 = -14361739 * c27; + c16 += (t0 << 8) & LIMB_MASK; + c17 += t0 >> 20; + t0 = 35694566 * c27; + c17 += (t0 << 8) & LIMB_MASK; + c18 += t0 >> 20; + t0 = 132168845 * c27; + c18 += (t0 << 8) & LIMB_MASK; + c19 += t0 >> 20; + t0 = 3710130 * c27; + c19 += (t0 << 8) & LIMB_MASK; + c20 += t0 >> 20; + //reduce from position 26 + t0 = 54187661 * c26; + c12 += (t0 << 8) & LIMB_MASK; + c13 += t0 >> 20; + t0 = 20867411 * c26; + c13 += (t0 << 8) & LIMB_MASK; + c14 += t0 >> 20; + t0 = -10975981 * c26; + c14 += (t0 << 8) & LIMB_MASK; + c15 += t0 >> 20; + t0 = -14361739 * c26; + c15 += (t0 << 8) & LIMB_MASK; + c16 += t0 >> 20; + t0 = 35694566 * c26; + c16 += (t0 << 8) & LIMB_MASK; + c17 += t0 >> 20; + t0 = 132168845 * c26; + c17 += (t0 << 8) & LIMB_MASK; + c18 += t0 >> 20; + t0 = 3710130 * c26; + c18 += (t0 << 8) & LIMB_MASK; + c19 += t0 >> 20; + //reduce from position 25 + t0 = 54187661 * c25; + c11 += (t0 << 8) & LIMB_MASK; + c12 += t0 >> 20; + t0 = 20867411 * c25; + c12 += (t0 << 8) & LIMB_MASK; + c13 += t0 >> 20; + t0 = -10975981 * c25; + c13 += (t0 << 8) & LIMB_MASK; + c14 += t0 >> 20; + t0 = -14361739 * c25; + c14 += (t0 << 8) & LIMB_MASK; + c15 += t0 >> 20; + t0 = 35694566 * c25; + c15 += (t0 << 8) & LIMB_MASK; + c16 += t0 >> 20; + t0 = 132168845 * c25; + c16 += (t0 << 8) & LIMB_MASK; + c17 += t0 >> 20; + t0 = 3710130 * c25; + c17 += (t0 << 8) & LIMB_MASK; + c18 += t0 >> 20; + //reduce from position 24 + t0 = 54187661 * c24; + c10 += (t0 << 8) & LIMB_MASK; + c11 += t0 >> 20; + t0 = 20867411 * c24; + c11 += (t0 << 8) & LIMB_MASK; + c12 += t0 >> 20; + t0 = -10975981 * c24; + c12 += (t0 << 8) & LIMB_MASK; + c13 += t0 >> 20; + t0 = -14361739 * c24; + c13 += (t0 << 8) & LIMB_MASK; + c14 += t0 >> 20; + t0 = 35694566 * c24; + c14 += (t0 << 8) & LIMB_MASK; + c15 += t0 >> 20; + t0 = 132168845 * c24; + c15 += (t0 << 8) & LIMB_MASK; + c16 += t0 >> 20; + t0 = 3710130 * c24; + c16 += (t0 << 8) & LIMB_MASK; + c17 += t0 >> 20; + //reduce from position 23 + t0 = 54187661 * c23; + c9 += (t0 << 8) & LIMB_MASK; + c10 += t0 >> 20; + t0 = 20867411 * c23; + c10 += (t0 << 8) & LIMB_MASK; + c11 += t0 >> 20; + t0 = -10975981 * c23; + c11 += (t0 << 8) & LIMB_MASK; + c12 += t0 >> 20; + t0 = -14361739 * c23; + c12 += (t0 << 8) & LIMB_MASK; + c13 += t0 >> 20; + t0 = 35694566 * c23; + c13 += (t0 << 8) & LIMB_MASK; + c14 += t0 >> 20; + t0 = 132168845 * c23; + c14 += (t0 << 8) & LIMB_MASK; + c15 += t0 >> 20; + t0 = 3710130 * c23; + c15 += (t0 << 8) & LIMB_MASK; + c16 += t0 >> 20; + //reduce from position 22 + t0 = 54187661 * c22; + c8 += (t0 << 8) & LIMB_MASK; + c9 += t0 >> 20; + t0 = 20867411 * c22; + c9 += (t0 << 8) & LIMB_MASK; + c10 += t0 >> 20; + t0 = -10975981 * c22; + c10 += (t0 << 8) & LIMB_MASK; + c11 += t0 >> 20; + t0 = -14361739 * c22; + c11 += (t0 << 8) & LIMB_MASK; + c12 += t0 >> 20; + t0 = 35694566 * c22; + c12 += (t0 << 8) & LIMB_MASK; + c13 += t0 >> 20; + t0 = 132168845 * c22; + c13 += (t0 << 8) & LIMB_MASK; + c14 += t0 >> 20; + t0 = 3710130 * c22; + c14 += (t0 << 8) & LIMB_MASK; + c15 += t0 >> 20; + //reduce from position 21 + t0 = 54187661 * c21; + c7 += (t0 << 8) & LIMB_MASK; + c8 += t0 >> 20; + t0 = 20867411 * c21; + c8 += (t0 << 8) & LIMB_MASK; + c9 += t0 >> 20; + t0 = -10975981 * c21; + c9 += (t0 << 8) & LIMB_MASK; + c10 += t0 >> 20; + t0 = -14361739 * c21; + c10 += (t0 << 8) & LIMB_MASK; + c11 += t0 >> 20; + t0 = 35694566 * c21; + c11 += (t0 << 8) & LIMB_MASK; + c12 += t0 >> 20; + t0 = 132168845 * c21; + c12 += (t0 << 8) & LIMB_MASK; + c13 += t0 >> 20; + t0 = 3710130 * c21; + c13 += (t0 << 8) & LIMB_MASK; + c14 += t0 >> 20; + //reduce from position 20 + t0 = 54187661 * c20; + c6 += (t0 << 8) & LIMB_MASK; + c7 += t0 >> 20; + t0 = 20867411 * c20; + c7 += (t0 << 8) & LIMB_MASK; + c8 += t0 >> 20; + t0 = -10975981 * c20; + c8 += (t0 << 8) & LIMB_MASK; + c9 += t0 >> 20; + t0 = -14361739 * c20; + c9 += (t0 << 8) & LIMB_MASK; + c10 += t0 >> 20; + t0 = 35694566 * c20; + c10 += (t0 << 8) & LIMB_MASK; + c11 += t0 >> 20; + t0 = 132168845 * c20; + c11 += (t0 << 8) & LIMB_MASK; + c12 += t0 >> 20; + t0 = 3710130 * c20; + c12 += (t0 << 8) & LIMB_MASK; + c13 += t0 >> 20; + //reduce from position 19 + t0 = 54187661 * c19; + c5 += (t0 << 8) & LIMB_MASK; + c6 += t0 >> 20; + t0 = 20867411 * c19; + c6 += (t0 << 8) & LIMB_MASK; + c7 += t0 >> 20; + t0 = -10975981 * c19; + c7 += (t0 << 8) & LIMB_MASK; + c8 += t0 >> 20; + t0 = -14361739 * c19; + c8 += (t0 << 8) & LIMB_MASK; + c9 += t0 >> 20; + t0 = 35694566 * c19; + c9 += (t0 << 8) & LIMB_MASK; + c10 += t0 >> 20; + t0 = 132168845 * c19; + c10 += (t0 << 8) & LIMB_MASK; + c11 += t0 >> 20; + t0 = 3710130 * c19; + c11 += (t0 << 8) & LIMB_MASK; + c12 += t0 >> 20; + //reduce from position 18 + t0 = 54187661 * c18; + c4 += (t0 << 8) & LIMB_MASK; + c5 += t0 >> 20; + t0 = 20867411 * c18; + c5 += (t0 << 8) & LIMB_MASK; + c6 += t0 >> 20; + t0 = -10975981 * c18; + c6 += (t0 << 8) & LIMB_MASK; + c7 += t0 >> 20; + t0 = -14361739 * c18; + c7 += (t0 << 8) & LIMB_MASK; + c8 += t0 >> 20; + t0 = 35694566 * c18; + c8 += (t0 << 8) & LIMB_MASK; + c9 += t0 >> 20; + t0 = 132168845 * c18; + c9 += (t0 << 8) & LIMB_MASK; + c10 += t0 >> 20; + t0 = 3710130 * c18; + c10 += (t0 << 8) & LIMB_MASK; + c11 += t0 >> 20; + //reduce from position 17 + t0 = 54187661 * c17; + c3 += (t0 << 8) & LIMB_MASK; + c4 += t0 >> 20; + t0 = 20867411 * c17; + c4 += (t0 << 8) & LIMB_MASK; + c5 += t0 >> 20; + t0 = -10975981 * c17; + c5 += (t0 << 8) & LIMB_MASK; + c6 += t0 >> 20; + t0 = -14361739 * c17; + c6 += (t0 << 8) & LIMB_MASK; + c7 += t0 >> 20; + t0 = 35694566 * c17; + c7 += (t0 << 8) & LIMB_MASK; + c8 += t0 >> 20; + t0 = 132168845 * c17; + c8 += (t0 << 8) & LIMB_MASK; + c9 += t0 >> 20; + t0 = 3710130 * c17; + c9 += (t0 << 8) & LIMB_MASK; + c10 += t0 >> 20; + //reduce from position 16 + t0 = 54187661 * c16; + c2 += (t0 << 8) & LIMB_MASK; + c3 += t0 >> 20; + t0 = 20867411 * c16; + c3 += (t0 << 8) & LIMB_MASK; + c4 += t0 >> 20; + t0 = -10975981 * c16; + c4 += (t0 << 8) & LIMB_MASK; + c5 += t0 >> 20; + t0 = -14361739 * c16; + c5 += (t0 << 8) & LIMB_MASK; + c6 += t0 >> 20; + t0 = 35694566 * c16; + c6 += (t0 << 8) & LIMB_MASK; + c7 += t0 >> 20; + t0 = 132168845 * c16; + c7 += (t0 << 8) & LIMB_MASK; + c8 += t0 >> 20; + t0 = 3710130 * c16; + c8 += (t0 << 8) & LIMB_MASK; + c9 += t0 >> 20; + //reduce from position 15 + t0 = 54187661 * c15; + c1 += (t0 << 8) & LIMB_MASK; + c2 += t0 >> 20; + t0 = 20867411 * c15; + c2 += (t0 << 8) & LIMB_MASK; + c3 += t0 >> 20; + t0 = -10975981 * c15; + c3 += (t0 << 8) & LIMB_MASK; + c4 += t0 >> 20; + t0 = -14361739 * c15; + c4 += (t0 << 8) & LIMB_MASK; + c5 += t0 >> 20; + t0 = 35694566 * c15; + c5 += (t0 << 8) & LIMB_MASK; + c6 += t0 >> 20; + t0 = 132168845 * c15; + c6 += (t0 << 8) & LIMB_MASK; + c7 += t0 >> 20; + t0 = 3710130 * c15; + c7 += (t0 << 8) & LIMB_MASK; + c8 += t0 >> 20; + //reduce from position 14 + t0 = 54187661 * c14; + c0 += (t0 << 8) & LIMB_MASK; + c1 += t0 >> 20; + t0 = 20867411 * c14; + c1 += (t0 << 8) & LIMB_MASK; + c2 += t0 >> 20; + t0 = -10975981 * c14; + c2 += (t0 << 8) & LIMB_MASK; + c3 += t0 >> 20; + t0 = -14361739 * c14; + c3 += (t0 << 8) & LIMB_MASK; + c4 += t0 >> 20; + t0 = 35694566 * c14; + c4 += (t0 << 8) & LIMB_MASK; + c5 += t0 >> 20; + t0 = 132168845 * c14; + c5 += (t0 << 8) & LIMB_MASK; + c6 += t0 >> 20; + t0 = 3710130 * c14; + c6 += (t0 << 8) & LIMB_MASK; + c7 += t0 >> 20; + c14 = 0; + + carryReduce1(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26, c27); + } + void carryReduce1(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19, long c20, long c21, long c22, long c23, long c24, long c25, long c26, long c27) { + long t0; + + //carry from position 0 + t0 = (c0 + CARRY_ADD) >> 28; + c0 -= (t0 << 28); + c1 += t0; + //carry from position 1 + t0 = (c1 + CARRY_ADD) >> 28; + c1 -= (t0 << 28); + c2 += t0; + //carry from position 2 + t0 = (c2 + CARRY_ADD) >> 28; + c2 -= (t0 << 28); + c3 += t0; + //carry from position 3 + t0 = (c3 + CARRY_ADD) >> 28; + c3 -= (t0 << 28); + c4 += t0; + //carry from position 4 + t0 = (c4 + CARRY_ADD) >> 28; + c4 -= (t0 << 28); + c5 += t0; + //carry from position 5 + t0 = (c5 + CARRY_ADD) >> 28; + c5 -= (t0 << 28); + c6 += t0; + //carry from position 6 + t0 = (c6 + CARRY_ADD) >> 28; + c6 -= (t0 << 28); + c7 += t0; + //carry from position 7 + t0 = (c7 + CARRY_ADD) >> 28; + c7 -= (t0 << 28); + c8 += t0; + //carry from position 8 + t0 = (c8 + CARRY_ADD) >> 28; + c8 -= (t0 << 28); + c9 += t0; + //carry from position 9 + t0 = (c9 + CARRY_ADD) >> 28; + c9 -= (t0 << 28); + c10 += t0; + //carry from position 10 + t0 = (c10 + CARRY_ADD) >> 28; + c10 -= (t0 << 28); + c11 += t0; + //carry from position 11 + t0 = (c11 + CARRY_ADD) >> 28; + c11 -= (t0 << 28); + c12 += t0; + //carry from position 12 + t0 = (c12 + CARRY_ADD) >> 28; + c12 -= (t0 << 28); + c13 += t0; + //carry from position 13 + t0 = (c13 + CARRY_ADD) >> 28; + c13 -= (t0 << 28); + c14 += t0; + + carryReduce2(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26, c27); + } + void carryReduce2(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19, long c20, long c21, long c22, long c23, long c24, long c25, long c26, long c27) { + long t0; + + //reduce from position 14 + t0 = 54187661 * c14; + c0 += (t0 << 8) & LIMB_MASK; + c1 += t0 >> 20; + t0 = 20867411 * c14; + c1 += (t0 << 8) & LIMB_MASK; + c2 += t0 >> 20; + t0 = -10975981 * c14; + c2 += (t0 << 8) & LIMB_MASK; + c3 += t0 >> 20; + t0 = -14361739 * c14; + c3 += (t0 << 8) & LIMB_MASK; + c4 += t0 >> 20; + t0 = 35694566 * c14; + c4 += (t0 << 8) & LIMB_MASK; + c5 += t0 >> 20; + t0 = 132168845 * c14; + c5 += (t0 << 8) & LIMB_MASK; + c6 += t0 >> 20; + t0 = 3710130 * c14; + c6 += (t0 << 8) & LIMB_MASK; + c7 += t0 >> 20; + //carry from position 0 + t0 = (c0 + CARRY_ADD) >> 28; + c0 -= (t0 << 28); + c1 += t0; + //carry from position 1 + t0 = (c1 + CARRY_ADD) >> 28; + c1 -= (t0 << 28); + c2 += t0; + //carry from position 2 + t0 = (c2 + CARRY_ADD) >> 28; + c2 -= (t0 << 28); + c3 += t0; + //carry from position 3 + t0 = (c3 + CARRY_ADD) >> 28; + c3 -= (t0 << 28); + c4 += t0; + //carry from position 4 + t0 = (c4 + CARRY_ADD) >> 28; + c4 -= (t0 << 28); + c5 += t0; + //carry from position 5 + t0 = (c5 + CARRY_ADD) >> 28; + c5 -= (t0 << 28); + c6 += t0; + //carry from position 6 + t0 = (c6 + CARRY_ADD) >> 28; + c6 -= (t0 << 28); + c7 += t0; + //carry from position 7 + t0 = (c7 + CARRY_ADD) >> 28; + c7 -= (t0 << 28); + c8 += t0; + //carry from position 8 + t0 = (c8 + CARRY_ADD) >> 28; + c8 -= (t0 << 28); + c9 += t0; + //carry from position 9 + t0 = (c9 + CARRY_ADD) >> 28; + c9 -= (t0 << 28); + c10 += t0; + //carry from position 10 + t0 = (c10 + CARRY_ADD) >> 28; + c10 -= (t0 << 28); + c11 += t0; + //carry from position 11 + t0 = (c11 + CARRY_ADD) >> 28; + c11 -= (t0 << 28); + c12 += t0; + //carry from position 12 + t0 = (c12 + CARRY_ADD) >> 28; + c12 -= (t0 << 28); + c13 += t0; + + r[0] = c0; + r[1] = c1; + r[2] = c2; + r[3] = c3; + r[4] = c4; + r[5] = c5; + r[6] = c6; + r[7] = c7; + r[8] = c8; + r[9] = c9; + r[10] = c10; + r[11] = c11; + r[12] = c12; + r[13] = c13; + } + private void carryReduce(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13) { + long c14 = 0; + //carry from position 0 + long t0 = (c0 + CARRY_ADD) >> 28; + c0 -= (t0 << 28); + c1 += t0; + //carry from position 1 + t0 = (c1 + CARRY_ADD) >> 28; + c1 -= (t0 << 28); + c2 += t0; + //carry from position 2 + t0 = (c2 + CARRY_ADD) >> 28; + c2 -= (t0 << 28); + c3 += t0; + //carry from position 3 + t0 = (c3 + CARRY_ADD) >> 28; + c3 -= (t0 << 28); + c4 += t0; + //carry from position 4 + t0 = (c4 + CARRY_ADD) >> 28; + c4 -= (t0 << 28); + c5 += t0; + //carry from position 5 + t0 = (c5 + CARRY_ADD) >> 28; + c5 -= (t0 << 28); + c6 += t0; + //carry from position 6 + t0 = (c6 + CARRY_ADD) >> 28; + c6 -= (t0 << 28); + c7 += t0; + //carry from position 7 + t0 = (c7 + CARRY_ADD) >> 28; + c7 -= (t0 << 28); + c8 += t0; + //carry from position 8 + t0 = (c8 + CARRY_ADD) >> 28; + c8 -= (t0 << 28); + c9 += t0; + //carry from position 9 + t0 = (c9 + CARRY_ADD) >> 28; + c9 -= (t0 << 28); + c10 += t0; + //carry from position 10 + t0 = (c10 + CARRY_ADD) >> 28; + c10 -= (t0 << 28); + c11 += t0; + //carry from position 11 + t0 = (c11 + CARRY_ADD) >> 28; + c11 -= (t0 << 28); + c12 += t0; + //carry from position 12 + t0 = (c12 + CARRY_ADD) >> 28; + c12 -= (t0 << 28); + c13 += t0; + //carry from position 13 + t0 = (c13 + CARRY_ADD) >> 28; + c13 -= (t0 << 28); + c14 += t0; + + carryReduce0(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14); + } + void carryReduce0(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14) { + long t0; + + //reduce from position 14 + t0 = 54187661 * c14; + c0 += (t0 << 8) & LIMB_MASK; + c1 += t0 >> 20; + t0 = 20867411 * c14; + c1 += (t0 << 8) & LIMB_MASK; + c2 += t0 >> 20; + t0 = -10975981 * c14; + c2 += (t0 << 8) & LIMB_MASK; + c3 += t0 >> 20; + t0 = -14361739 * c14; + c3 += (t0 << 8) & LIMB_MASK; + c4 += t0 >> 20; + t0 = 35694566 * c14; + c4 += (t0 << 8) & LIMB_MASK; + c5 += t0 >> 20; + t0 = 132168845 * c14; + c5 += (t0 << 8) & LIMB_MASK; + c6 += t0 >> 20; + t0 = 3710130 * c14; + c6 += (t0 << 8) & LIMB_MASK; + c7 += t0 >> 20; + //carry from position 0 + t0 = (c0 + CARRY_ADD) >> 28; + c0 -= (t0 << 28); + c1 += t0; + //carry from position 1 + t0 = (c1 + CARRY_ADD) >> 28; + c1 -= (t0 << 28); + c2 += t0; + //carry from position 2 + t0 = (c2 + CARRY_ADD) >> 28; + c2 -= (t0 << 28); + c3 += t0; + //carry from position 3 + t0 = (c3 + CARRY_ADD) >> 28; + c3 -= (t0 << 28); + c4 += t0; + //carry from position 4 + t0 = (c4 + CARRY_ADD) >> 28; + c4 -= (t0 << 28); + c5 += t0; + //carry from position 5 + t0 = (c5 + CARRY_ADD) >> 28; + c5 -= (t0 << 28); + c6 += t0; + //carry from position 6 + t0 = (c6 + CARRY_ADD) >> 28; + c6 -= (t0 << 28); + c7 += t0; + //carry from position 7 + t0 = (c7 + CARRY_ADD) >> 28; + c7 -= (t0 << 28); + c8 += t0; + //carry from position 8 + t0 = (c8 + CARRY_ADD) >> 28; + c8 -= (t0 << 28); + c9 += t0; + //carry from position 9 + t0 = (c9 + CARRY_ADD) >> 28; + c9 -= (t0 << 28); + c10 += t0; + //carry from position 10 + t0 = (c10 + CARRY_ADD) >> 28; + c10 -= (t0 << 28); + c11 += t0; + //carry from position 11 + t0 = (c11 + CARRY_ADD) >> 28; + c11 -= (t0 << 28); + c12 += t0; + //carry from position 12 + t0 = (c12 + CARRY_ADD) >> 28; + c12 -= (t0 << 28); + c13 += t0; + + r[0] = c0; + r[1] = c1; + r[2] = c2; + r[3] = c3; + r[4] = c4; + r[5] = c5; + r[6] = c6; + r[7] = c7; + r[8] = c8; + r[9] = c9; + r[10] = c10; + r[11] = c11; + r[12] = c12; + r[13] = c13; + } + @Override + protected void mult(long[] a, long[] b, long[] r) { + long c0 = (a[0] * b[0]); + long c1 = (a[0] * b[1]) + (a[1] * b[0]); + long c2 = (a[0] * b[2]) + (a[1] * b[1]) + (a[2] * b[0]); + long c3 = (a[0] * b[3]) + (a[1] * b[2]) + (a[2] * b[1]) + (a[3] * b[0]); + long c4 = (a[0] * b[4]) + (a[1] * b[3]) + (a[2] * b[2]) + (a[3] * b[1]) + (a[4] * b[0]); + long c5 = (a[0] * b[5]) + (a[1] * b[4]) + (a[2] * b[3]) + (a[3] * b[2]) + (a[4] * b[1]) + (a[5] * b[0]); + long c6 = (a[0] * b[6]) + (a[1] * b[5]) + (a[2] * b[4]) + (a[3] * b[3]) + (a[4] * b[2]) + (a[5] * b[1]) + (a[6] * b[0]); + long c7 = (a[0] * b[7]) + (a[1] * b[6]) + (a[2] * b[5]) + (a[3] * b[4]) + (a[4] * b[3]) + (a[5] * b[2]) + (a[6] * b[1]) + (a[7] * b[0]); + long c8 = (a[0] * b[8]) + (a[1] * b[7]) + (a[2] * b[6]) + (a[3] * b[5]) + (a[4] * b[4]) + (a[5] * b[3]) + (a[6] * b[2]) + (a[7] * b[1]) + (a[8] * b[0]); + long c9 = (a[0] * b[9]) + (a[1] * b[8]) + (a[2] * b[7]) + (a[3] * b[6]) + (a[4] * b[5]) + (a[5] * b[4]) + (a[6] * b[3]) + (a[7] * b[2]) + (a[8] * b[1]) + (a[9] * b[0]); + long c10 = (a[0] * b[10]) + (a[1] * b[9]) + (a[2] * b[8]) + (a[3] * b[7]) + (a[4] * b[6]) + (a[5] * b[5]) + (a[6] * b[4]) + (a[7] * b[3]) + (a[8] * b[2]) + (a[9] * b[1]) + (a[10] * b[0]); + long c11 = (a[0] * b[11]) + (a[1] * b[10]) + (a[2] * b[9]) + (a[3] * b[8]) + (a[4] * b[7]) + (a[5] * b[6]) + (a[6] * b[5]) + (a[7] * b[4]) + (a[8] * b[3]) + (a[9] * b[2]) + (a[10] * b[1]) + (a[11] * b[0]); + long c12 = (a[0] * b[12]) + (a[1] * b[11]) + (a[2] * b[10]) + (a[3] * b[9]) + (a[4] * b[8]) + (a[5] * b[7]) + (a[6] * b[6]) + (a[7] * b[5]) + (a[8] * b[4]) + (a[9] * b[3]) + (a[10] * b[2]) + (a[11] * b[1]) + (a[12] * b[0]); + long c13 = (a[0] * b[13]) + (a[1] * b[12]) + (a[2] * b[11]) + (a[3] * b[10]) + (a[4] * b[9]) + (a[5] * b[8]) + (a[6] * b[7]) + (a[7] * b[6]) + (a[8] * b[5]) + (a[9] * b[4]) + (a[10] * b[3]) + (a[11] * b[2]) + (a[12] * b[1]) + (a[13] * b[0]); + long c14 = (a[1] * b[13]) + (a[2] * b[12]) + (a[3] * b[11]) + (a[4] * b[10]) + (a[5] * b[9]) + (a[6] * b[8]) + (a[7] * b[7]) + (a[8] * b[6]) + (a[9] * b[5]) + (a[10] * b[4]) + (a[11] * b[3]) + (a[12] * b[2]) + (a[13] * b[1]); + long c15 = (a[2] * b[13]) + (a[3] * b[12]) + (a[4] * b[11]) + (a[5] * b[10]) + (a[6] * b[9]) + (a[7] * b[8]) + (a[8] * b[7]) + (a[9] * b[6]) + (a[10] * b[5]) + (a[11] * b[4]) + (a[12] * b[3]) + (a[13] * b[2]); + long c16 = (a[3] * b[13]) + (a[4] * b[12]) + (a[5] * b[11]) + (a[6] * b[10]) + (a[7] * b[9]) + (a[8] * b[8]) + (a[9] * b[7]) + (a[10] * b[6]) + (a[11] * b[5]) + (a[12] * b[4]) + (a[13] * b[3]); + long c17 = (a[4] * b[13]) + (a[5] * b[12]) + (a[6] * b[11]) + (a[7] * b[10]) + (a[8] * b[9]) + (a[9] * b[8]) + (a[10] * b[7]) + (a[11] * b[6]) + (a[12] * b[5]) + (a[13] * b[4]); + long c18 = (a[5] * b[13]) + (a[6] * b[12]) + (a[7] * b[11]) + (a[8] * b[10]) + (a[9] * b[9]) + (a[10] * b[8]) + (a[11] * b[7]) + (a[12] * b[6]) + (a[13] * b[5]); + long c19 = (a[6] * b[13]) + (a[7] * b[12]) + (a[8] * b[11]) + (a[9] * b[10]) + (a[10] * b[9]) + (a[11] * b[8]) + (a[12] * b[7]) + (a[13] * b[6]); + long c20 = (a[7] * b[13]) + (a[8] * b[12]) + (a[9] * b[11]) + (a[10] * b[10]) + (a[11] * b[9]) + (a[12] * b[8]) + (a[13] * b[7]); + long c21 = (a[8] * b[13]) + (a[9] * b[12]) + (a[10] * b[11]) + (a[11] * b[10]) + (a[12] * b[9]) + (a[13] * b[8]); + long c22 = (a[9] * b[13]) + (a[10] * b[12]) + (a[11] * b[11]) + (a[12] * b[10]) + (a[13] * b[9]); + long c23 = (a[10] * b[13]) + (a[11] * b[12]) + (a[12] * b[11]) + (a[13] * b[10]); + long c24 = (a[11] * b[13]) + (a[12] * b[12]) + (a[13] * b[11]); + long c25 = (a[12] * b[13]) + (a[13] * b[12]); + long c26 = (a[13] * b[13]); + + carryReduce(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26); + } + @Override + protected void reduce(long[] a) { + carryReduce(a, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13]); + } + @Override + protected void square(long[] a, long[] r) { + long c0 = (a[0] * a[0]); + long c1 = 2 * ((a[0] * a[1])); + long c2 = 2 * ((a[0] * a[2])) + (a[1] * a[1]); + long c3 = 2 * ((a[0] * a[3]) + (a[1] * a[2])); + long c4 = 2 * ((a[0] * a[4]) + (a[1] * a[3])) + (a[2] * a[2]); + long c5 = 2 * ((a[0] * a[5]) + (a[1] * a[4]) + (a[2] * a[3])); + long c6 = 2 * ((a[0] * a[6]) + (a[1] * a[5]) + (a[2] * a[4])) + (a[3] * a[3]); + long c7 = 2 * ((a[0] * a[7]) + (a[1] * a[6]) + (a[2] * a[5]) + (a[3] * a[4])); + long c8 = 2 * ((a[0] * a[8]) + (a[1] * a[7]) + (a[2] * a[6]) + (a[3] * a[5])) + (a[4] * a[4]); + long c9 = 2 * ((a[0] * a[9]) + (a[1] * a[8]) + (a[2] * a[7]) + (a[3] * a[6]) + (a[4] * a[5])); + long c10 = 2 * ((a[0] * a[10]) + (a[1] * a[9]) + (a[2] * a[8]) + (a[3] * a[7]) + (a[4] * a[6])) + (a[5] * a[5]); + long c11 = 2 * ((a[0] * a[11]) + (a[1] * a[10]) + (a[2] * a[9]) + (a[3] * a[8]) + (a[4] * a[7]) + (a[5] * a[6])); + long c12 = 2 * ((a[0] * a[12]) + (a[1] * a[11]) + (a[2] * a[10]) + (a[3] * a[9]) + (a[4] * a[8]) + (a[5] * a[7])) + (a[6] * a[6]); + long c13 = 2 * ((a[0] * a[13]) + (a[1] * a[12]) + (a[2] * a[11]) + (a[3] * a[10]) + (a[4] * a[9]) + (a[5] * a[8]) + (a[6] * a[7])); + long c14 = 2 * ((a[1] * a[13]) + (a[2] * a[12]) + (a[3] * a[11]) + (a[4] * a[10]) + (a[5] * a[9]) + (a[6] * a[8])) + (a[7] * a[7]); + long c15 = 2 * ((a[2] * a[13]) + (a[3] * a[12]) + (a[4] * a[11]) + (a[5] * a[10]) + (a[6] * a[9]) + (a[7] * a[8])); + long c16 = 2 * ((a[3] * a[13]) + (a[4] * a[12]) + (a[5] * a[11]) + (a[6] * a[10]) + (a[7] * a[9])) + (a[8] * a[8]); + long c17 = 2 * ((a[4] * a[13]) + (a[5] * a[12]) + (a[6] * a[11]) + (a[7] * a[10]) + (a[8] * a[9])); + long c18 = 2 * ((a[5] * a[13]) + (a[6] * a[12]) + (a[7] * a[11]) + (a[8] * a[10])) + (a[9] * a[9]); + long c19 = 2 * ((a[6] * a[13]) + (a[7] * a[12]) + (a[8] * a[11]) + (a[9] * a[10])); + long c20 = 2 * ((a[7] * a[13]) + (a[8] * a[12]) + (a[9] * a[11])) + (a[10] * a[10]); + long c21 = 2 * ((a[8] * a[13]) + (a[9] * a[12]) + (a[10] * a[11])); + long c22 = 2 * ((a[9] * a[13]) + (a[10] * a[12])) + (a[11] * a[11]); + long c23 = 2 * ((a[10] * a[13]) + (a[11] * a[12])); + long c24 = 2 * ((a[11] * a[13])) + (a[12] * a[12]); + long c25 = 2 * ((a[12] * a[13])); + long c26 = (a[13] * a[13]); + + carryReduce(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26); + } +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/java.base/share/classes/sun/security/util/math/intpoly/P521OrderField.java Wed Dec 12 15:07:56 2018 +0530 @@ -0,0 +1,1377 @@ +/* + * Copyright (c) 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is generated by FieldGen.jsh. Do not modify it directly. + */ + +package sun.security.util.math.intpoly; + +import java.math.BigInteger; +public class P521OrderField extends IntegerPolynomial { + private static final int BITS_PER_LIMB = 28; + private static final int NUM_LIMBS = 19; + private static final int MAX_ADDS = 1; + public static final BigInteger MODULUS = evaluateModulus(); + private static final long CARRY_ADD = 1 << 27; + private static final int LIMB_MASK = -1 >>> (64 - BITS_PER_LIMB); + public P521OrderField() { + + super(BITS_PER_LIMB, NUM_LIMBS, MAX_ADDS, MODULUS); + + } + private static BigInteger evaluateModulus() { + BigInteger result = BigInteger.valueOf(2).pow(521); + result = result.add(BigInteger.valueOf(20472841)); + result = result.add(BigInteger.valueOf(2).pow(28).multiply(BigInteger.valueOf(117141993))); + result = result.subtract(BigInteger.valueOf(2).pow(56).multiply(BigInteger.valueOf(62411077))); + result = result.subtract(BigInteger.valueOf(2).pow(84).multiply(BigInteger.valueOf(56915814))); + result = result.add(BigInteger.valueOf(2).pow(112).multiply(BigInteger.valueOf(97532854))); + result = result.add(BigInteger.valueOf(2).pow(140).multiply(BigInteger.valueOf(76509338))); + result = result.subtract(BigInteger.valueOf(2).pow(168).multiply(BigInteger.valueOf(75510783))); + result = result.subtract(BigInteger.valueOf(2).pow(196).multiply(BigInteger.valueOf(67962521))); + result = result.add(BigInteger.valueOf(2).pow(224).multiply(BigInteger.valueOf(25593732))); + result = result.subtract(BigInteger.valueOf(2).pow(252).multiply(BigInteger.valueOf(91))); + return result; + } + @Override + protected void finalCarryReduceLast(long[] limbs) { + long c = limbs[18] >> 17; + limbs[18] -= c << 17; + long t0 = -20472841 * c; + limbs[0] += t0; + t0 = -117141993 * c; + limbs[1] += t0; + t0 = 62411077 * c; + limbs[2] += t0; + t0 = 56915814 * c; + limbs[3] += t0; + t0 = -97532854 * c; + limbs[4] += t0; + t0 = -76509338 * c; + limbs[5] += t0; + t0 = 75510783 * c; + limbs[6] += t0; + t0 = 67962521 * c; + limbs[7] += t0; + t0 = -25593732 * c; + limbs[8] += t0; + t0 = 91 * c; + limbs[9] += t0; + } + private void carryReduce(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19, long c20, long c21, long c22, long c23, long c24, long c25, long c26, long c27, long c28, long c29, long c30, long c31, long c32, long c33, long c34, long c35, long c36) { + long c37 = 0; + //carry from position 0 + long t0 = (c0 + CARRY_ADD) >> 28; + c0 -= (t0 << 28); + c1 += t0; + //carry from position 1 + t0 = (c1 + CARRY_ADD) >> 28; + c1 -= (t0 << 28); + c2 += t0; + //carry from position 2 + t0 = (c2 + CARRY_ADD) >> 28; + c2 -= (t0 << 28); + c3 += t0; + //carry from position 3 + t0 = (c3 + CARRY_ADD) >> 28; + c3 -= (t0 << 28); + c4 += t0; + //carry from position 4 + t0 = (c4 + CARRY_ADD) >> 28; + c4 -= (t0 << 28); + c5 += t0; + //carry from position 5 + t0 = (c5 + CARRY_ADD) >> 28; + c5 -= (t0 << 28); + c6 += t0; + //carry from position 6 + t0 = (c6 + CARRY_ADD) >> 28; + c6 -= (t0 << 28); + c7 += t0; + //carry from position 7 + t0 = (c7 + CARRY_ADD) >> 28; + c7 -= (t0 << 28); + c8 += t0; + //carry from position 8 + t0 = (c8 + CARRY_ADD) >> 28; + c8 -= (t0 << 28); + c9 += t0; + //carry from position 9 + t0 = (c9 + CARRY_ADD) >> 28; + c9 -= (t0 << 28); + c10 += t0; + //carry from position 10 + t0 = (c10 + CARRY_ADD) >> 28; + c10 -= (t0 << 28); + c11 += t0; + //carry from position 11 + t0 = (c11 + CARRY_ADD) >> 28; + c11 -= (t0 << 28); + c12 += t0; + //carry from position 12 + t0 = (c12 + CARRY_ADD) >> 28; + c12 -= (t0 << 28); + c13 += t0; + //carry from position 13 + t0 = (c13 + CARRY_ADD) >> 28; + c13 -= (t0 << 28); + c14 += t0; + //carry from position 14 + t0 = (c14 + CARRY_ADD) >> 28; + c14 -= (t0 << 28); + c15 += t0; + //carry from position 15 + t0 = (c15 + CARRY_ADD) >> 28; + c15 -= (t0 << 28); + c16 += t0; + //carry from position 16 + t0 = (c16 + CARRY_ADD) >> 28; + c16 -= (t0 << 28); + c17 += t0; + //carry from position 17 + t0 = (c17 + CARRY_ADD) >> 28; + c17 -= (t0 << 28); + c18 += t0; + //carry from position 18 + t0 = (c18 + CARRY_ADD) >> 28; + c18 -= (t0 << 28); + c19 += t0; + //carry from position 19 + t0 = (c19 + CARRY_ADD) >> 28; + c19 -= (t0 << 28); + c20 += t0; + //carry from position 20 + t0 = (c20 + CARRY_ADD) >> 28; + c20 -= (t0 << 28); + c21 += t0; + //carry from position 21 + t0 = (c21 + CARRY_ADD) >> 28; + c21 -= (t0 << 28); + c22 += t0; + //carry from position 22 + t0 = (c22 + CARRY_ADD) >> 28; + c22 -= (t0 << 28); + c23 += t0; + //carry from position 23 + t0 = (c23 + CARRY_ADD) >> 28; + c23 -= (t0 << 28); + c24 += t0; + //carry from position 24 + t0 = (c24 + CARRY_ADD) >> 28; + c24 -= (t0 << 28); + c25 += t0; + //carry from position 25 + t0 = (c25 + CARRY_ADD) >> 28; + c25 -= (t0 << 28); + c26 += t0; + //carry from position 26 + t0 = (c26 + CARRY_ADD) >> 28; + c26 -= (t0 << 28); + c27 += t0; + //carry from position 27 + t0 = (c27 + CARRY_ADD) >> 28; + c27 -= (t0 << 28); + c28 += t0; + //carry from position 28 + t0 = (c28 + CARRY_ADD) >> 28; + c28 -= (t0 << 28); + c29 += t0; + //carry from position 29 + t0 = (c29 + CARRY_ADD) >> 28; + c29 -= (t0 << 28); + c30 += t0; + //carry from position 30 + t0 = (c30 + CARRY_ADD) >> 28; + c30 -= (t0 << 28); + c31 += t0; + //carry from position 31 + t0 = (c31 + CARRY_ADD) >> 28; + c31 -= (t0 << 28); + c32 += t0; + //carry from position 32 + t0 = (c32 + CARRY_ADD) >> 28; + c32 -= (t0 << 28); + c33 += t0; + //carry from position 33 + t0 = (c33 + CARRY_ADD) >> 28; + c33 -= (t0 << 28); + c34 += t0; + //carry from position 34 + t0 = (c34 + CARRY_ADD) >> 28; + c34 -= (t0 << 28); + c35 += t0; + //carry from position 35 + t0 = (c35 + CARRY_ADD) >> 28; + c35 -= (t0 << 28); + c36 += t0; + //carry from position 36 + t0 = (c36 + CARRY_ADD) >> 28; + c36 -= (t0 << 28); + c37 += t0; + + carryReduce0(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26, c27, c28, c29, c30, c31, c32, c33, c34, c35, c36, c37); + } + void carryReduce0(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19, long c20, long c21, long c22, long c23, long c24, long c25, long c26, long c27, long c28, long c29, long c30, long c31, long c32, long c33, long c34, long c35, long c36, long c37) { + long t0; + + //reduce from position 37 + t0 = -20472841 * c37; + c18 += (t0 << 11) & LIMB_MASK; + c19 += t0 >> 17; + t0 = -117141993 * c37; + c19 += (t0 << 11) & LIMB_MASK; + c20 += t0 >> 17; + t0 = 62411077 * c37; + c20 += (t0 << 11) & LIMB_MASK; + c21 += t0 >> 17; + t0 = 56915814 * c37; + c21 += (t0 << 11) & LIMB_MASK; + c22 += t0 >> 17; + t0 = -97532854 * c37; + c22 += (t0 << 11) & LIMB_MASK; + c23 += t0 >> 17; + t0 = -76509338 * c37; + c23 += (t0 << 11) & LIMB_MASK; + c24 += t0 >> 17; + t0 = 75510783 * c37; + c24 += (t0 << 11) & LIMB_MASK; + c25 += t0 >> 17; + t0 = 67962521 * c37; + c25 += (t0 << 11) & LIMB_MASK; + c26 += t0 >> 17; + t0 = -25593732 * c37; + c26 += (t0 << 11) & LIMB_MASK; + c27 += t0 >> 17; + t0 = 91 * c37; + c27 += (t0 << 11) & LIMB_MASK; + c28 += t0 >> 17; + //reduce from position 36 + t0 = -20472841 * c36; + c17 += (t0 << 11) & LIMB_MASK; + c18 += t0 >> 17; + t0 = -117141993 * c36; + c18 += (t0 << 11) & LIMB_MASK; + c19 += t0 >> 17; + t0 = 62411077 * c36; + c19 += (t0 << 11) & LIMB_MASK; + c20 += t0 >> 17; + t0 = 56915814 * c36; + c20 += (t0 << 11) & LIMB_MASK; + c21 += t0 >> 17; + t0 = -97532854 * c36; + c21 += (t0 << 11) & LIMB_MASK; + c22 += t0 >> 17; + t0 = -76509338 * c36; + c22 += (t0 << 11) & LIMB_MASK; + c23 += t0 >> 17; + t0 = 75510783 * c36; + c23 += (t0 << 11) & LIMB_MASK; + c24 += t0 >> 17; + t0 = 67962521 * c36; + c24 += (t0 << 11) & LIMB_MASK; + c25 += t0 >> 17; + t0 = -25593732 * c36; + c25 += (t0 << 11) & LIMB_MASK; + c26 += t0 >> 17; + t0 = 91 * c36; + c26 += (t0 << 11) & LIMB_MASK; + c27 += t0 >> 17; + //reduce from position 35 + t0 = -20472841 * c35; + c16 += (t0 << 11) & LIMB_MASK; + c17 += t0 >> 17; + t0 = -117141993 * c35; + c17 += (t0 << 11) & LIMB_MASK; + c18 += t0 >> 17; + t0 = 62411077 * c35; + c18 += (t0 << 11) & LIMB_MASK; + c19 += t0 >> 17; + t0 = 56915814 * c35; + c19 += (t0 << 11) & LIMB_MASK; + c20 += t0 >> 17; + t0 = -9