This commit is contained in:
Prasanta Sadhukhan 2018-12-12 15:07:56 +05:30
commit c83b55a9e2
488 changed files with 38649 additions and 14968 deletions

View File

@ -1,19 +1,24 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8" />
<meta name="generator" content="pandoc"> <meta name="generator" content="pandoc" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes"> <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
<title>Building the JDK</title> <title>Building the JDK</title>
<style type="text/css">code{white-space: pre;}</style> <style type="text/css">
<link rel="stylesheet" href="../make/data/docs-resources/resources/jdk-default.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]> <!--[if lt IE 9]>
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script> <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
<![endif]--> <![endif]-->
<style type="text/css">pre, code, tt { color: #1d6ae5; }</style> <style type="text/css">pre, code, tt { color: #1d6ae5; }</style>
</head> </head>
<body> <body>
<header> <header id="title-block-header">
<h1 class="title">Building the JDK</h1> <h1 class="title">Building the JDK</h1>
</header> </header>
<nav id="TOC"> <nav id="TOC">
@ -640,11 +645,13 @@ x86_64-linux-gnu-to-ppc64le-linux-gnu</code></pre>
<p>Note that alsa is needed even if you only want to build a headless JDK.</p> <p>Note that alsa is needed even if you only want to build a headless JDK.</p>
<ul> <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>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 <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_1.0.25-4_armhf.deb .
dpkg-deb -x /tmp/libasound2-dev_1.0.25-4_armhf.deb .</code></pre></li> dpkg-deb -x /tmp/libasound2-dev_1.0.25-4_armhf.deb .</code></pre>
<li><p>If alsa is not properly detected by <code>configure</code>, you can point it out by <code>--with-alsa</code>.</p></li> <ul>
<li>If alsa is not properly detected by <code>configure</code>, you can point it out by <code>--with-alsa</code>.</li>
</ul> </ul>
<h4 id="x11-1">X11</h4> <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> <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 @@ cp: cannot stat `arm-linux-gnueabihf/libXt.so&#39;: No such file or directory</c
<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>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> <p>For example, cross-compiling to AArch64 from x86_64 could be done like this:</p>
<ul> <ul>
<li><p>Install cross-compiler on the <em>build</em> system:</p> <li>Install cross-compiler on the <em>build</em> system:</li>
<pre><code>apt install g++-aarch64-linux-gnu gcc-aarch64-linux-gnu</code></pre></li> </ul>
<li><p>Create chroot on the <em>build</em> system, configuring it for <em>target</em> system:</p> <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 \ <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 \ --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> --resolve-deps jessie /chroots/arm64 http://httpredir.debian.org/debian/</code></pre>
<li><p>Configure and build with newly created chroot as sysroot/toolchain-path:</p> <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/ <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 make images
ls build/linux-aarch64-normal-server-release/</code></pre></li> ls build/linux-aarch64-normal-server-release/</code></pre>
</ul>
<p>The build does not create new files in that chroot, so it can be reused for multiple builds without additional cleanup.</p> <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> <p>Architectures that are known to successfully cross-compile like this are:</p>
<table> <table>
@ -860,12 +871,7 @@ cannot create ... Permission denied
spawn failed</code></pre> 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> <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> <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"> <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>
<!--
h='&#x6f;&#112;&#x65;&#110;&#106;&#100;&#x6b;&#46;&#106;&#x61;&#118;&#x61;&#46;&#110;&#x65;&#116;';a='&#64;';n='&#98;&#x75;&#x69;&#108;&#100;&#x2d;&#100;&#x65;&#118;';e=n+a+h;
document.write('<a h'+'ref'+'="ma'+'ilto'+':'+e+'" clas'+'s="em' + 'ail">'+e+'<\/'+'a'+'>');
// -->
</script><noscript>&#98;&#x75;&#x69;&#108;&#100;&#x2d;&#100;&#x65;&#118;&#32;&#x61;&#116;&#32;&#x6f;&#112;&#x65;&#110;&#106;&#100;&#x6b;&#32;&#100;&#x6f;&#116;&#32;&#106;&#x61;&#118;&#x61;&#32;&#100;&#x6f;&#116;&#32;&#110;&#x65;&#116;</noscript>. 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> <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> <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> <h3 id="setting-up-a-repository-for-pushing-changes-defpath">Setting Up a Repository for Pushing Changes (defpath)</h3>

View File

@ -918,7 +918,7 @@ targets are given, a native toolchain for the current platform will be
created. Currently, at least the following targets are known to work: created. Currently, at least the following targets are known to work:
Supported devkit targets Supported devkit targets
------------------------ -------------------------
x86_64-linux-gnu x86_64-linux-gnu
aarch64-linux-gnu aarch64-linux-gnu
arm-linux-gnueabihf arm-linux-gnueabihf
@ -1129,13 +1129,13 @@ without additional cleanup.
Architectures that are known to successfully cross-compile like this are: Architectures that are known to successfully cross-compile like this are:
Target `CC` `CXX` `--arch=...` `--openjdk-target=...` Target `CC` `CXX` `--arch=...` `--openjdk-target=...`
------------ ------------------------- --------------------------- ------------ ---------------------- ------------ ------------------------- --------------------------- ------------- -----------------------
x86 default default i386 i386-linux-gnu x86 default default i386 i386-linux-gnu
armhf gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf armhf arm-linux-gnueabihf 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 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 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 s390x gcc-s390x-linux-gnu g++-s390x-linux-gnu s390x s390x-linux-gnu
Additional architectures might be supported by Debian/Ubuntu Ports. Additional architectures might be supported by Debian/Ubuntu Ports.

View File

@ -1,19 +1,24 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8" />
<meta name="generator" content="pandoc"> <meta name="generator" content="pandoc" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes"> <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
<title>Testing the JDK</title> <title>Testing the JDK</title>
<style type="text/css">code{white-space: pre;}</style> <style type="text/css">
<link rel="stylesheet" href="../make/data/docs-resources/resources/jdk-default.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]> <!--[if lt IE 9]>
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script> <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
<![endif]--> <![endif]-->
<style type="text/css">pre, code, tt { color: #1d6ae5; }</style> <style type="text/css">pre, code, tt { color: #1d6ae5; }</style>
</head> </head>
<body> <body>
<header> <header id="title-block-header">
<h1 class="title">Testing the JDK</h1> <h1 class="title">Testing the JDK</h1>
</header> </header>
<nav id="TOC"> <nav id="TOC">

View File

@ -321,7 +321,7 @@ jdk.jshell_COPY += .jsh .properties
################################################################################ ################################################################################
jdk.internal.le_COPY += .properties jdk.internal.le_COPY += .properties .caps .txt
################################################################################ ################################################################################

View File

@ -91,15 +91,17 @@ TARGETS += $(COMPILE_DEPEND) $(DEPEND_SERVICE_PROVIDER)
# To be able to call the javascript filter when generating man pages using # To be able to call the javascript filter when generating man pages using
# pandoc, we need to create this executable wrapper script. # pandoc, we need to create this executable wrapper script.
ifneq ($(PANDOC), ) ifneq ($(PANDOC), )
# PANDOC_FILTER is duplicated for export in ToolsJdk.gmk. # PANDOC_TROFF_MANPAGE_FILTER is duplicated for export in ToolsJdk.gmk.
PANDOC_FILTER := $(BUILDTOOLS_OUTPUTDIR)/manpages/pandoc-manpage-filter PANDOC_TROFF_MANPAGE_FILTER := \
PANDOC_FILTER_SETUP := $(BUILDTOOLS_OUTPUTDIR)/manpages/_pandoc_filter_setup.marker $(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 # Create a usable instance of the wrapper script that calls the pandoc filter
# (which is written in javascript). # (which is written in javascript).
$(eval $(call SetupTextFileProcessing, CREATE_PANDOC_FILTER, \ $(eval $(call SetupTextFileProcessing, CREATE_PANDOC_TROFF_MANPAGE_FILTER, \
SOURCE_FILES := $(TOPDIR)/make/scripts/pandoc-manpage-filter.sh.template, \ SOURCE_FILES := $(TOPDIR)/make/scripts/pandoc-troff-manpage-filter.sh.template, \
OUTPUT_FILE := $(PANDOC_FILTER), \ OUTPUT_FILE := $(PANDOC_TROFF_MANPAGE_FILTER), \
REPLACEMENTS := \ REPLACEMENTS := \
@@BOOT_JDK@@ => $(BOOT_JDK) ; \ @@BOOT_JDK@@ => $(BOOT_JDK) ; \
@@TOPDIR@@ => $(TOPDIR) ; \ @@TOPDIR@@ => $(TOPDIR) ; \
@ -107,11 +109,35 @@ ifneq ($(PANDOC), )
)) ))
# Created script must be made executable # Created script must be made executable
$(PANDOC_FILTER_SETUP): $(CREATE_PANDOC_FILTER) $(PANDOC_TROFF_MANPAGE_FILTER_SETUP): $(CREATE_PANDOC_TROFF_MANPAGE_FILTER)
$(CHMOD) a+rx $(PANDOC_FILTER) $(CHMOD) a+rx $(PANDOC_TROFF_MANPAGE_FILTER)
$(TOUCH) $@ $(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 endif
all: $(TARGETS) all: $(TARGETS)

View File

@ -27,10 +27,10 @@ default: all
include $(SPEC) include $(SPEC)
include MakeBase.gmk include MakeBase.gmk
include Modules.gmk include Modules.gmk
include ModuleTools.gmk
include ProcessMarkdown.gmk include ProcessMarkdown.gmk
include ToolsJdk.gmk
include ZipArchive.gmk include ZipArchive.gmk
include $(TOPDIR)/make/ToolsJdk.gmk
include $(TOPDIR)/make/ModuleTools.gmk
# This is needed to properly setup DOCS_MODULES. # This is needed to properly setup DOCS_MODULES.
$(eval $(call ReadImportMetaData)) $(eval $(call ReadImportMetaData))
@ -556,6 +556,15 @@ ifeq ($(ENABLE_FULL_DOCS), true)
# For all markdown files in $module/share/man directories, convert them to # For all markdown files in $module/share/man directories, convert them to
# html. # 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), \ $(foreach m, $(ALL_MODULES), \
$(eval MAN_$m := $(call FindModuleManDirs, $m)) \ $(eval MAN_$m := $(call FindModuleManDirs, $m)) \
$(foreach d, $(MAN_$m), \ $(foreach d, $(MAN_$m), \
@ -565,8 +574,11 @@ ifeq ($(ENABLE_FULL_DOCS), true)
SRC := $d, \ SRC := $d, \
FILES := $(filter %.md, $(call CacheFind, $d)), \ FILES := $(filter %.md, $(call CacheFind, $d)), \
DEST := $(DOCS_OUTPUTDIR)/specs/man, \ DEST := $(DOCS_OUTPUTDIR)/specs/man, \
FILTER := $(PANDOC_HTML_MANPAGE_FILTER), \
CSS := $(GLOBAL_SPECS_DEFAULT_CSS_FILE), \ CSS := $(GLOBAL_SPECS_DEFAULT_CSS_FILE), \
REPLACEMENTS := @@VERSION_SHORT@@ => $(VERSION_SHORT), \ REPLACEMENTS := @@VERSION_SHORT@@ => $(VERSION_SHORT), \
EXTRA_DEPS := $(PANDOC_HTML_MANPAGE_FILTER) \
$(PANDOC_HTML_MANPAGE_FILTER_JAVASCRIPT), \
)) \ )) \
$(eval JDK_SPECS_TARGETS += $($($m_$d_NAME))) \ $(eval JDK_SPECS_TARGETS += $($($m_$d_NAME))) \
) \ ) \

View File

@ -118,7 +118,8 @@ TOOL_PUBLICSUFFIXLIST = $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_clas
# Executable javascript filter for man page generation using pandoc. # 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
########################################################################################## ##########################################################################################

View File

@ -80,7 +80,7 @@ define ProcessMarkdown
$$(call LogInfo, Converting $2 to $$($1_FORMAT)) $$(call LogInfo, Converting $2 to $$($1_FORMAT))
$$(call MakeDir, $$(SUPPORT_OUTPUTDIR)/markdown $$(dir $$($1_$2_PANDOC_OUTPUT))) $$(call MakeDir, $$(SUPPORT_OUTPUTDIR)/markdown $$(dir $$($1_$2_PANDOC_OUTPUT)))
$$(call ExecuteWithLog, $$(SUPPORT_OUTPUTDIR)/markdown/$$($1_$2_MARKER), \ $$(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)' \ $$($1_$2_CSS_OPTION) $$($1_$2_OPTIONS) '$$($1_$2_PANDOC_INPUT)' \
-o '$$($1_$2_PANDOC_OUTPUT)') -o '$$($1_$2_PANDOC_OUTPUT)')
ifneq ($$(findstring $$(LOG_LEVEL), debug trace),) ifneq ($$(findstring $$(LOG_LEVEL), debug trace),)

View File

@ -207,11 +207,12 @@ ifeq ($(OPENJDK_TARGET_OS_TYPE), unix)
$(info Warning: pandoc not found. Not generating man pages) $(info Warning: pandoc not found. Not generating man pages)
else else
# Create dynamic man pages from markdown using pandoc. We need # Create dynamic man pages from markdown using pandoc. We need
# PANDOC_FILTER, a wrapper around PANDOC_FILTER_JAVASCRIPT. This is # PANDOC_TROFF_MANPAGE_FILTER, a wrapper around
# created by buildtools-jdk. # PANDOC_TROFF_MANPAGE_FILTER_JAVASCRIPT. This is created by buildtools-jdk.
# We should also depend on the source javascript filter # 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 # The norm in man pages is to display code literals as bold, but pandoc
# "correctly" converts these constructs (encoded in markdown using `...` # "correctly" converts these constructs (encoded in markdown using `...`
@ -234,10 +235,11 @@ ifeq ($(OPENJDK_TARGET_OS_TYPE), unix)
DEST := $(SUPPORT_OUTPUTDIR)/modules_man/$(MODULE)/man1, \ DEST := $(SUPPORT_OUTPUTDIR)/modules_man/$(MODULE)/man1, \
FILES := $(MAN_FILES_MD), \ FILES := $(MAN_FILES_MD), \
FORMAT := man, \ FORMAT := man, \
FILTER := $(PANDOC_FILTER), \ FILTER := $(PANDOC_TROFF_MANPAGE_FILTER), \
POST_PROCESS := $(MAN_POST_PROCESS), \ POST_PROCESS := $(MAN_POST_PROCESS), \
REPLACEMENTS := @@VERSION_SHORT@@ => $(VERSION_SHORT), \ 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) TARGETS += $(BUILD_MAN_PAGES)

View File

@ -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();

View File

@ -25,4 +25,4 @@
# Simple wrapper script to call Nashorn with the javascript pandoc filter # Simple wrapper script to call Nashorn with the javascript pandoc filter
@@BOOT_JDK@@/bin/jjs @@JJS_FLAGS@@ -scripting \ @@BOOT_JDK@@/bin/jjs @@JJS_FLAGS@@ -scripting \
"@@TOPDIR@@/make/scripts/pandoc-manpage-filter.js" 2> /dev/null "@@TOPDIR@@/make/scripts/pandoc-html-manpage-filter.js" 2> /dev/null

View File

@ -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

View File

@ -2273,7 +2273,7 @@ void MacroAssembler::tlab_allocate(
) { ) {
// make sure arguments make sense // make sure arguments make sense
assert_different_registers(obj, var_size_in_bytes, t1); 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"); assert((con_size_in_bytes & MinObjAlignmentInBytesMask) == 0, "object size is not multiple of alignment");
const Register new_top = t1; const Register new_top = t1;

View File

@ -67,6 +67,11 @@
" of quotas (if set), when true. Otherwise, use the CPU" \ " of quotas (if set), when true. Otherwise, use the CPU" \
" shares value, provided it is less than quota.") \ " 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, \ diagnostic(bool, UseCpuAllocPath, false, \
"Use CPU_ALLOC code path in os::active_processor_count ") "Use CPU_ALLOC code path in os::active_processor_count ")

View File

@ -128,8 +128,12 @@
// for timer info max values which include all bits // for timer info max values which include all bits
#define ALL_64_BITS CONST64(0xFFFFFFFFFFFFFFFF) #define ALL_64_BITS CONST64(0xFFFFFFFFFFFFFFFF)
#define LARGEPAGES_BIT (1 << 6) enum CoredumpFilterBit {
#define DAX_SHARED_BIT (1 << 8) FILE_BACKED_PVT_BIT = 1 << 2,
LARGEPAGES_BIT = 1 << 6,
DAX_SHARED_BIT = 1 << 8
};
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// global variables // global variables
julong os::Linux::_physical_memory = 0; julong os::Linux::_physical_memory = 0;
@ -1350,6 +1354,9 @@ void os::shutdown() {
void os::abort(bool dump_core, void* siginfo, const void* context) { void os::abort(bool dump_core, void* siginfo, const void* context) {
os::shutdown(); os::shutdown();
if (dump_core) { if (dump_core) {
if (UseSharedSpaces && DumpPrivateMappingsInCore) {
ClassLoader::close_jrt_image();
}
#ifndef PRODUCT #ifndef PRODUCT
fdStream out(defaultStream::output_fd()); fdStream out(defaultStream::output_fd());
out.print_raw("Current thread is "); out.print_raw("Current thread is ");
@ -3401,10 +3408,9 @@ bool os::Linux::hugetlbfs_sanity_check(bool warn, size_t page_size) {
// - (bit 7) dax private memory // - (bit 7) dax private memory
// - (bit 8) dax shared 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; FILE *f;
long cdm; long cdm;
bool filter_changed = false;
if ((f = fopen("/proc/self/coredump_filter", "r+")) == NULL) { if ((f = fopen("/proc/self/coredump_filter", "r+")) == NULL) {
return; return;
@ -3415,17 +3421,11 @@ static void set_coredump_filter(bool largepages, bool dax_shared) {
return; return;
} }
long saved_cdm = cdm;
rewind(f); rewind(f);
cdm |= bit;
if (largepages && (cdm & LARGEPAGES_BIT) == 0) { if (cdm != saved_cdm) {
cdm |= LARGEPAGES_BIT;
filter_changed = true;
}
if (dax_shared && (cdm & DAX_SHARED_BIT) == 0) {
cdm |= DAX_SHARED_BIT;
filter_changed = true;
}
if (filter_changed) {
fprintf(f, "%#lx", cdm); fprintf(f, "%#lx", cdm);
} }
@ -3564,7 +3564,7 @@ void os::large_page_init() {
size_t large_page_size = Linux::setup_large_page_size(); size_t large_page_size = Linux::setup_large_page_size();
UseLargePages = Linux::setup_large_page_type(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 #ifndef SHM_HUGETLB
@ -5072,8 +5072,13 @@ jint os::init_2(void) {
prio_init(); prio_init();
if (!FLAG_IS_DEFAULT(AllocateHeapAt)) { 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; return JNI_OK;
} }

View File

@ -74,15 +74,17 @@
// * 63-47 Fixed (17-bits, always zero) // * 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 ZPlatformAddressSpaceStart = (uintptr_t)1 << ZPlatformAddressOffsetBits;
const uintptr_t ZPlatformAddressSpaceSize = ((uintptr_t)1 << ZPlatformAddressOffsetBits) * 4; const uintptr_t ZPlatformAddressSpaceSize = ((uintptr_t)1 << ZPlatformAddressOffsetBits) * 4;
const size_t ZPlatformCacheLineSize = 64; const size_t ZPlatformNMethodDisarmedOffset = 4;
const size_t ZPlatformCacheLineSize = 64;
#endif // OS_CPU_LINUX_X86_ZGLOBALS_LINUX_X86_HPP #endif // OS_CPU_LINUX_X86_ZGLOBALS_LINUX_X86_HPP

View File

@ -5733,7 +5733,8 @@ void ClassFileParser::fill_instance_klass(InstanceKlass* ik, bool changed_by_loa
ik->major_version() != JAVA_MIN_SUPPORTED_VERSION && ik->major_version() != JAVA_MIN_SUPPORTED_VERSION &&
log_is_enabled(Info, class, preview)) { log_is_enabled(Info, class, preview)) {
ResourceMark rm; 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)) { if (log_is_enabled(Debug, class, resolve)) {

View File

@ -363,6 +363,13 @@ void ClassPathZipEntry::contents_do(void f(const char* name, void* context), voi
} }
} }
void ClassPathImageEntry::close_jimage() {
if (_jimage != NULL) {
(*JImageClose)(_jimage);
_jimage = NULL;
}
}
ClassPathImageEntry::ClassPathImageEntry(JImageFile* jimage, const char* name) : ClassPathImageEntry::ClassPathImageEntry(JImageFile* jimage, const char* name) :
ClassPathEntry(), ClassPathEntry(),
_jimage(jimage) { _jimage(jimage) {
@ -614,6 +621,12 @@ void ClassLoader::update_module_path_entry_list(const char *path, TRAPS) {
void ClassLoader::setup_module_search_path(const char* path, TRAPS) { void ClassLoader::setup_module_search_path(const char* path, TRAPS) {
update_module_path_entry_list(path, THREAD); 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 #endif // INCLUDE_CDS
// Construct the array of module/path pairs as specified to --patch-module // Construct the array of module/path pairs as specified to --patch-module

View File

@ -55,6 +55,7 @@ public:
virtual bool is_jar_file() const = 0; virtual bool is_jar_file() const = 0;
virtual const char* name() const = 0; virtual const char* name() const = 0;
virtual JImageFile* jimage() const = 0; virtual JImageFile* jimage() const = 0;
virtual void close_jimage() = 0;
// Constructor // Constructor
ClassPathEntry() : _next(NULL) {} ClassPathEntry() : _next(NULL) {}
// Attempt to locate file_name through this class path entry. // Attempt to locate file_name through this class path entry.
@ -70,6 +71,7 @@ class ClassPathDirEntry: public ClassPathEntry {
bool is_jar_file() const { return false; } bool is_jar_file() const { return false; }
const char* name() const { return _dir; } const char* name() const { return _dir; }
JImageFile* jimage() const { return NULL; } JImageFile* jimage() const { return NULL; }
void close_jimage() {}
ClassPathDirEntry(const char* dir); ClassPathDirEntry(const char* dir);
virtual ~ClassPathDirEntry() {} virtual ~ClassPathDirEntry() {}
ClassFileStream* open_stream(const char* name, TRAPS); ClassFileStream* open_stream(const char* name, TRAPS);
@ -98,6 +100,7 @@ class ClassPathZipEntry: public ClassPathEntry {
bool is_jar_file() const { return true; } bool is_jar_file() const { return true; }
const char* name() const { return _zip_name; } const char* name() const { return _zip_name; }
JImageFile* jimage() const { return NULL; } JImageFile* jimage() const { return NULL; }
void close_jimage() {}
ClassPathZipEntry(jzfile* zip, const char* zip_name, bool is_boot_append); ClassPathZipEntry(jzfile* zip, const char* zip_name, bool is_boot_append);
virtual ~ClassPathZipEntry(); virtual ~ClassPathZipEntry();
u1* open_entry(const char* name, jint* filesize, bool nul_terminate, TRAPS); u1* open_entry(const char* name, jint* filesize, bool nul_terminate, TRAPS);
@ -117,6 +120,7 @@ public:
bool is_open() const { return _jimage != NULL; } bool is_open() const { return _jimage != NULL; }
const char* name() const { return _name == NULL ? "" : _name; } const char* name() const { return _name == NULL ? "" : _name; }
JImageFile* jimage() const { return _jimage; } JImageFile* jimage() const { return _jimage; }
void close_jimage();
ClassPathImageEntry(JImageFile* jimage, const char* name); ClassPathImageEntry(JImageFile* jimage, const char* name);
virtual ~ClassPathImageEntry(); virtual ~ClassPathImageEntry();
ClassFileStream* open_stream(const char* name, TRAPS); ClassFileStream* open_stream(const char* name, TRAPS);
@ -333,6 +337,7 @@ class ClassLoader: AllStatic {
// Modular java runtime image is present vs. a build with exploded modules // Modular java runtime image is present vs. a build with exploded modules
static bool has_jrt_entry() { return (_jrt_entry != NULL); } static bool has_jrt_entry() { return (_jrt_entry != NULL); }
static ClassPathEntry* get_jrt_entry() { return _jrt_entry; } 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 // 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); static void add_to_exploded_build_list(Symbol* module_name, TRAPS);

View File

@ -116,14 +116,17 @@ public:
return SymbolTableHash::BaseConfig::allocate_node(size, value); return SymbolTableHash::BaseConfig::allocate_node(size, value);
} }
static void free_node(void* memory, Symbol* const& value) { static void free_node(void* memory, Symbol* const& value) {
// We get here either because #1 some threads lost a race // We get here because #1 some threads lost a race to insert a newly created Symbol
// to insert a newly created Symbol, or #2 we are freeing // or #2 we're cleaning up unused symbol.
// a symbol during normal cleanup deletion. // If #1, then the symbol can be either permanent (refcount==PERM_REFCOUNT),
// If #1, then the symbol can be a permanent (refcount==PERM_REFCOUNT), // or regular newly created one (refcount==1)
// or regular newly created one but with refcount==0 (see SymbolTableCreateEntry) // If #2, then the symbol is dead (refcount==0)
// If #2, then the symbol must have refcount==0 assert((value->refcount() == PERM_REFCOUNT) || (value->refcount() == 1) || (value->refcount() == 0),
assert((value->refcount() == PERM_REFCOUNT) || (value->refcount() == 0),
"refcount %d", value->refcount()); "refcount %d", value->refcount());
if (value->refcount() == 1) {
value->decrement_refcount();
assert(value->refcount() == 0, "expected dead symbol");
}
SymbolTable::delete_symbol(value); SymbolTable::delete_symbol(value);
SymbolTableHash::BaseConfig::free_node(memory, value); SymbolTableHash::BaseConfig::free_node(memory, value);
SymbolTable::item_removed(); SymbolTable::item_removed();
@ -162,6 +165,12 @@ void SymbolTable::delete_symbol(Symbol* sym) {
} }
} }
void SymbolTable::update_needs_rehash(bool rehash) {
if (rehash) {
_needs_rehashing = true;
}
}
void SymbolTable::item_added() { void SymbolTable::item_added() {
Atomic::inc(&(SymbolTable::the_table()->_items_count)); Atomic::inc(&(SymbolTable::the_table()->_items_count));
} }
@ -398,9 +407,7 @@ Symbol* SymbolTable::do_lookup(const char* name, int len, uintx hash) {
SymbolTableGet stg; SymbolTableGet stg;
bool rehash_warning = false; bool rehash_warning = false;
_local_table->get(thread, lookup, stg, &rehash_warning); _local_table->get(thread, lookup, stg, &rehash_warning);
if (rehash_warning) { update_needs_rehash(rehash_warning);
_needs_rehashing = true;
}
Symbol* sym = stg.get_res_sym(); Symbol* sym = stg.get_res_sym();
assert((sym == NULL) || sym->refcount() != 0, "found dead symbol"); assert((sym == NULL) || sym->refcount() != 0, "found dead symbol");
return sym; return sym;
@ -462,71 +469,26 @@ void SymbolTable::add(ClassLoaderData* loader_data, const constantPoolHandle& cp
} }
} }
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) { Symbol* SymbolTable::do_add_if_needed(const char* name, int len, uintx hash, bool heap, TRAPS) {
SymbolTableLookup lookup(THREAD, name, len, hash); SymbolTableLookup lookup(THREAD, name, len, hash);
SymbolTableCreateEntry stce(THREAD, name, len, heap); SymbolTableGet stg;
bool rehash_warning = false;
bool clean_hint = false; bool clean_hint = false;
_local_table->get_insert_lazy(THREAD, lookup, stce, stce, &rehash_warning, &clean_hint); bool rehash_warning = false;
if (rehash_warning) { Symbol* sym = NULL;
_needs_rehashing = true;
} 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) { if (clean_hint) {
// we just found out that there is a dead item, // we just found out that there is a dead item,
// which we were unable to clean right now, // which we were unable to clean right now,
@ -536,8 +498,8 @@ Symbol* SymbolTable::do_add_if_needed(const char* name, int len, uintx hash, boo
mark_item_clean_count(); mark_item_clean_count();
check_concurrent_work(); 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; return sym;
} }

View File

@ -169,6 +169,7 @@ private:
void try_rehash_table(); void try_rehash_table();
bool do_rehash(); bool do_rehash();
inline void update_needs_rehash(bool rehash);
public: public:
// The symbol table // The symbol table

View File

@ -70,19 +70,24 @@ CMSHeap::CMSHeap(GenCollectorPolicy *policy) :
Generation::ParNew, Generation::ParNew,
Generation::ConcurrentMarkSweep, Generation::ConcurrentMarkSweep,
"ParNew:CMS"), "ParNew:CMS"),
_workers(NULL),
_eden_pool(NULL), _eden_pool(NULL),
_survivor_pool(NULL), _survivor_pool(NULL),
_old_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 CMSHeap::initialize() {
jint status = GenCollectedHeap::initialize(); jint status = GenCollectedHeap::initialize();
if (status != JNI_OK) return status; 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 // If we are running CMS, create the collector responsible
// for collecting the CMS generations. // for collecting the CMS generations.
if (!create_cms_collector()) { if (!create_cms_collector()) {

View File

@ -1531,10 +1531,6 @@ G1CollectedHeap::G1CollectedHeap(G1CollectorPolicy* collector_policy) :
_is_subject_to_discovery_cm(this), _is_subject_to_discovery_cm(this),
_in_cset_fast_test() { _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); _verifier = new G1HeapVerifier(this);
_allocator = new G1Allocator(this); _allocator = new G1Allocator(this);
@ -1767,6 +1763,14 @@ jint G1CollectedHeap::initialize() {
_humongous_reclaim_candidates.initialize(start, end, granularity); _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. // Create the G1ConcurrentMark data structure and thread.
// (Must do this late, so that "max_regions" is defined.) // (Must do this late, so that "max_regions" is defined.)
_cm = new G1ConcurrentMark(this, prev_bitmap_storage, next_bitmap_storage); _cm = new G1ConcurrentMark(this, prev_bitmap_storage, next_bitmap_storage);

View File

@ -26,47 +26,24 @@
#include "gc/shared/barrierSet.hpp" #include "gc/shared/barrierSet.hpp"
#include "gc/shared/barrierSetAssembler.hpp" #include "gc/shared/barrierSetAssembler.hpp"
#include "runtime/thread.hpp" #include "runtime/thread.hpp"
#include "utilities/debug.hpp"
#include "utilities/macros.hpp" #include "utilities/macros.hpp"
BarrierSet* BarrierSet::_barrier_set = NULL; 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) { void BarrierSet::set_barrier_set(BarrierSet* barrier_set) {
assert(_barrier_set == NULL, "Already initialized"); assert(_barrier_set == NULL, "Already initialized");
_barrier_set = barrier_set; _barrier_set = barrier_set;
// Some threads are created before the barrier set, so the call to // Notify barrier set of the current (main) thread. Normally the
// BarrierSet::on_thread_create had to be deferred for them. Now that // Thread constructor deals with this, but the main thread is
// we have the barrier set, do those deferred calls. // created before we get here. Verify it isn't yet on the thread
// 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
// list, else we'd also need to call BarrierSet::on_thread_attach. // 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(), assert(Thread::current()->is_Java_thread(),
"Expected main thread to be a JavaThread"); "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(), assert(!JavaThread::current()->on_thread_list(),
"Main thread already on thread list."); "Main thread already on thread list.");
_barrier_set->on_thread_create(Thread::current()); _barrier_set->on_thread_create(Thread::current());

View File

@ -80,10 +80,6 @@ void ZArguments::initialize() {
FLAG_SET_DEFAULT(UseCompressedOops, false); FLAG_SET_DEFAULT(UseCompressedOops, false);
FLAG_SET_DEFAULT(UseCompressedClassPointers, 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 // Verification before startup and after exit not (yet) supported
FLAG_SET_DEFAULT(VerifyDuringStartup, false); FLAG_SET_DEFAULT(VerifyDuringStartup, false);
FLAG_SET_DEFAULT(VerifyBeforeExit, false); FLAG_SET_DEFAULT(VerifyBeforeExit, false);

View File

@ -81,6 +81,7 @@ public:
static void load_barrier_on_oop_fields(oop o); 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_weak_oop_field_preloaded(volatile oop* p, oop o);
static oop load_barrier_on_phantom_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 // Weak load barrier
static oop weak_load_barrier_on_oop_field(volatile oop* p); static oop weak_load_barrier_on_oop_field(volatile oop* p);
@ -99,6 +100,7 @@ public:
// Keep alive barrier // Keep alive barrier
static void keep_alive_barrier_on_weak_oop_field(volatile oop* p); 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_oop_field(volatile oop* p);
static void keep_alive_barrier_on_phantom_root_oop_field(oop* p);
// Mark barrier // Mark barrier
static void mark_barrier_on_oop_field(volatile oop* p, bool finalizable); static void mark_barrier_on_oop_field(volatile oop* p, bool finalizable);

View File

@ -111,11 +111,12 @@ inline void ZBarrier::root_barrier(oop* p, oop o) {
const uintptr_t good_addr = slow_path(addr); const uintptr_t good_addr = slow_path(addr);
// Non-atomic healing helps speed up root scanning. This is safe to do // 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 // since we are always healing roots in a safepoint, or under a lock,
// never racing with mutators modifying roots while we are healing them. // which ensures we are never racing with mutators modifying roots while
// It's also safe in case multiple GC threads try to heal the same root, // we are healing them. It's also safe in case multiple GC threads try
// since they would always heal the root in the same way and it does not // to heal the same root if it is aligned, since they would always heal
// matter in which order it happens. // 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); *p = ZOop::to_oop(good_addr);
} }
@ -188,6 +189,11 @@ inline oop ZBarrier::load_barrier_on_phantom_oop_field_preloaded(volatile oop* p
return load_barrier_on_oop_field_preloaded(p, o); 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 // Weak load barrier
// //
@ -269,6 +275,13 @@ inline void ZBarrier::keep_alive_barrier_on_phantom_oop_field(volatile oop* p) {
barrier<is_good_or_null_fast_path, keep_alive_barrier_on_phantom_oop_slow_path>(p, o); 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 // Mark barrier
// //

View File

@ -24,6 +24,7 @@
#include "precompiled.hpp" #include "precompiled.hpp"
#include "gc/z/zBarrierSet.hpp" #include "gc/z/zBarrierSet.hpp"
#include "gc/z/zBarrierSetAssembler.hpp" #include "gc/z/zBarrierSetAssembler.hpp"
#include "gc/z/zBarrierSetNMethod.hpp"
#include "gc/z/zGlobals.hpp" #include "gc/z/zGlobals.hpp"
#include "gc/z/zHeap.inline.hpp" #include "gc/z/zHeap.inline.hpp"
#include "gc/z/zThreadLocalData.hpp" #include "gc/z/zThreadLocalData.hpp"
@ -39,11 +40,20 @@
class ZBarrierSetC1; class ZBarrierSetC1;
class ZBarrierSetC2; 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() : ZBarrierSet::ZBarrierSet() :
BarrierSet(make_barrier_set_assembler<ZBarrierSetAssembler>(), BarrierSet(make_barrier_set_assembler<ZBarrierSetAssembler>(),
make_barrier_set_c1<ZBarrierSetC1>(), make_barrier_set_c1<ZBarrierSetC1>(),
make_barrier_set_c2<ZBarrierSetC2>(), make_barrier_set_c2<ZBarrierSetC2>(),
NULL /* barrier_set_nmethod */, make_barrier_set_nmethod(),
BarrierSet::FakeRtti(BarrierSet::ZBarrierSet)) {} BarrierSet::FakeRtti(BarrierSet::ZBarrierSet)) {}
ZBarrierSetAssembler* ZBarrierSet::assembler() { ZBarrierSetAssembler* ZBarrierSet::assembler() {

View File

@ -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();
}

View File

@ -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

View File

@ -259,12 +259,10 @@ bool ZCollectedHeap::block_is_obj(const HeapWord* addr) const {
} }
void ZCollectedHeap::register_nmethod(nmethod* nm) { void ZCollectedHeap::register_nmethod(nmethod* nm) {
assert_locked_or_safepoint(CodeCache_lock);
ZNMethodTable::register_nmethod(nm); ZNMethodTable::register_nmethod(nm);
} }
void ZCollectedHeap::unregister_nmethod(nmethod* nm) { void ZCollectedHeap::unregister_nmethod(nmethod* nm) {
assert_locked_or_safepoint(CodeCache_lock);
ZNMethodTable::unregister_nmethod(nm); ZNMethodTable::unregister_nmethod(nm);
} }

View File

@ -91,6 +91,9 @@ const uintptr_t ZAddressSpaceStart = ZPlatformAddressSpaceStart;
const uintptr_t ZAddressSpaceSize = ZPlatformAddressSpaceSize; const uintptr_t ZAddressSpaceSize = ZPlatformAddressSpaceSize;
const uintptr_t ZAddressSpaceEnd = ZAddressSpaceStart + ZAddressSpaceSize; const uintptr_t ZAddressSpaceEnd = ZAddressSpaceStart + ZAddressSpaceSize;
// NMethod entry barrier
const size_t ZNMethodDisarmedOffset = ZPlatformNMethodDisarmedOffset;
// Cache line size // Cache line size
const size_t ZCacheLineSize = ZPlatformCacheLineSize; const size_t ZCacheLineSize = ZPlatformCacheLineSize;

View File

@ -69,6 +69,7 @@ ZHeap::ZHeap() :
_weak_roots_processor(&_workers), _weak_roots_processor(&_workers),
_relocate(&_workers), _relocate(&_workers),
_relocation_set(), _relocation_set(),
_unload(&_workers),
_serviceability(heap_min_size(), heap_max_size()) { _serviceability(heap_min_size(), heap_max_size()) {
// Install global heap instance // Install global heap instance
assert(_heap == NULL, "Already initialized"); assert(_heap == NULL, "Already initialized");
@ -353,9 +354,6 @@ bool ZHeap::mark_end() {
// Enter mark completed phase // Enter mark completed phase
ZGlobalPhase = ZPhaseMarkCompleted; ZGlobalPhase = ZPhaseMarkCompleted;
// Resize metaspace
MetaspaceGC::compute_new_size();
// Update statistics // Update statistics
ZStatSample(ZSamplerHeapUsedAfterMark, used()); ZStatSample(ZSamplerHeapUsedAfterMark, used());
ZStatHeap::set_at_mark_end(capacity(), allocated(), used()); ZStatHeap::set_at_mark_end(capacity(), allocated(), used());
@ -366,6 +364,9 @@ bool ZHeap::mark_end() {
// Process weak roots // Process weak roots
_weak_roots_processor.process_weak_roots(); _weak_roots_processor.process_weak_roots();
// Prepare to unload unused classes and code
_unload.prepare();
return true; return true;
} }
@ -380,6 +381,9 @@ void ZHeap::process_non_strong_references() {
// Process concurrent weak roots // Process concurrent weak roots
_weak_roots_processor.process_concurrent_weak_roots(); _weak_roots_processor.process_concurrent_weak_roots();
// Unload unused classes and code
_unload.unload();
// Unblock resurrection of weak/phantom references // Unblock resurrection of weak/phantom references
ZResurrection::unblock(); ZResurrection::unblock();
@ -463,8 +467,8 @@ void ZHeap::reset_relocation_set() {
void ZHeap::relocate_start() { void ZHeap::relocate_start() {
assert(SafepointSynchronize::is_at_safepoint(), "Should be at safepoint"); assert(SafepointSynchronize::is_at_safepoint(), "Should be at safepoint");
// Update statistics // Finish unloading of classes and code
ZStatSample(ZSamplerHeapUsedBeforeRelocation, used()); _unload.finish();
// Flip address view // Flip address view
ZAddressMasks::flip_to_remapped(); ZAddressMasks::flip_to_remapped();
@ -474,6 +478,7 @@ void ZHeap::relocate_start() {
ZGlobalPhase = ZPhaseRelocate; ZGlobalPhase = ZPhaseRelocate;
// Update statistics // Update statistics
ZStatSample(ZSamplerHeapUsedBeforeRelocation, used());
ZStatHeap::set_at_relocate_start(capacity(), allocated(), used()); ZStatHeap::set_at_relocate_start(capacity(), allocated(), used());
// Remap/Relocate roots // Remap/Relocate roots

View File

@ -41,6 +41,7 @@
#include "gc/z/zRootsIterator.hpp" #include "gc/z/zRootsIterator.hpp"
#include "gc/z/zWeakRootsProcessor.hpp" #include "gc/z/zWeakRootsProcessor.hpp"
#include "gc/z/zServiceability.hpp" #include "gc/z/zServiceability.hpp"
#include "gc/z/zUnload.hpp"
#include "gc/z/zWorkers.hpp" #include "gc/z/zWorkers.hpp"
#include "memory/allocation.hpp" #include "memory/allocation.hpp"
@ -59,6 +60,7 @@ private:
ZWeakRootsProcessor _weak_roots_processor; ZWeakRootsProcessor _weak_roots_processor;
ZRelocate _relocate; ZRelocate _relocate;
ZRelocationSet _relocation_set; ZRelocationSet _relocation_set;
ZUnload _unload;
ZServiceability _serviceability; ZServiceability _serviceability;
size_t heap_min_size() const; size_t heap_min_size() const;

View File

@ -287,6 +287,14 @@ void ZMark::follow_partial_array(ZMarkStackEntry entry, bool finalizable) {
} }
void ZMark::follow_array_object(objArrayOop obj, bool finalizable) { 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 uintptr_t addr = (uintptr_t)obj->base();
const size_t size = (size_t)obj->length() * oopSize; const size_t size = (size_t)obj->length() * oopSize;

View File

@ -23,45 +23,62 @@
#include "precompiled.hpp" #include "precompiled.hpp"
#include "code/relocInfo.hpp" #include "code/relocInfo.hpp"
#include "code/nativeInst.hpp"
#include "code/nmethod.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/zGlobals.hpp"
#include "gc/z/zHash.inline.hpp" #include "gc/z/zHash.inline.hpp"
#include "gc/z/zLock.inline.hpp"
#include "gc/z/zNMethodTable.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 "logging/log.hpp"
#include "memory/allocation.inline.hpp" #include "memory/allocation.inline.hpp"
#include "memory/resourceArea.hpp" #include "memory/resourceArea.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/atomic.hpp" #include "runtime/atomic.hpp"
#include "runtime/orderAccess.hpp"
#include "runtime/os.hpp"
#include "utilities/debug.hpp" #include "utilities/debug.hpp"
class ZNMethodWithImmediateOops { class ZNMethodDataImmediateOops {
private: private:
nmethod* const _nm; const size_t _nimmediate_oops;
const size_t _nimmediate_oops;
static size_t header_size(); static size_t header_size();
ZNMethodWithImmediateOops(nmethod* nm, const GrowableArray<oop*>& immediate_oops); ZNMethodDataImmediateOops(const GrowableArray<oop*>& immediate_oops);
public: public:
static ZNMethodWithImmediateOops* create(nmethod* nm, const GrowableArray<oop*>& immediate_oops); static ZNMethodDataImmediateOops* create(const GrowableArray<oop*>& immediate_oops);
static void destroy(ZNMethodWithImmediateOops* nmi); static void destroy(ZNMethodDataImmediateOops* data_immediate_oops);
nmethod* method() const;
size_t immediate_oops_count() const; size_t immediate_oops_count() const;
oop** immediate_oops_begin() const; oop** immediate_oops_begin() const;
oop** immediate_oops_end() const; oop** immediate_oops_end() const;
}; };
size_t ZNMethodWithImmediateOops::header_size() { size_t ZNMethodDataImmediateOops::header_size() {
const size_t size = sizeof(ZNMethodWithImmediateOops); const size_t size = sizeof(ZNMethodDataImmediateOops);
assert(is_aligned(size, sizeof(oop*)), "Header misaligned"); assert(is_aligned(size, sizeof(oop*)), "Header misaligned");
return size; return size;
} }
ZNMethodWithImmediateOops::ZNMethodWithImmediateOops(nmethod* nm, const GrowableArray<oop*>& immediate_oops) : ZNMethodDataImmediateOops* ZNMethodDataImmediateOops::create(const GrowableArray<oop*>& immediate_oops) {
_nm(nm), // 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()) { _nimmediate_oops(immediate_oops.length()) {
// Save all immediate oops // Save all immediate oops
for (size_t i = 0; i < _nimmediate_oops; i++) { for (size_t i = 0; i < _nimmediate_oops; i++) {
@ -69,41 +86,97 @@ ZNMethodWithImmediateOops::ZNMethodWithImmediateOops(nmethod* nm, const Growable
} }
} }
ZNMethodWithImmediateOops* ZNMethodWithImmediateOops::create(nmethod* nm, const GrowableArray<oop*>& immediate_oops) { size_t ZNMethodDataImmediateOops::immediate_oops_count() const {
// 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 {
return _nimmediate_oops; return _nimmediate_oops;
} }
oop** ZNMethodWithImmediateOops::immediate_oops_begin() const { oop** ZNMethodDataImmediateOops::immediate_oops_begin() const {
// The immediate oop* array starts immediately after this object // The immediate oop* array starts immediately after this object
return (oop**)((uintptr_t)this + header_size()); 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(); 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; ZNMethodTableEntry* ZNMethodTable::_table = NULL;
size_t ZNMethodTable::_size = 0; 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::_nregistered = 0;
size_t ZNMethodTable::_nunregistered = 0; size_t ZNMethodTable::_nunregistered = 0;
volatile size_t ZNMethodTable::_claimed = 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) { ZNMethodTableEntry ZNMethodTable::create_entry(nmethod* nm) {
GrowableArray<oop*> immediate_oops; GrowableArray<oop*> immediate_oops;
bool non_immediate_oops = false; bool non_immediate_oops = false;
@ -132,29 +205,27 @@ ZNMethodTableEntry ZNMethodTable::create_entry(nmethod* nm) {
} }
} }
// oops_count() returns the number of oops in the oop table plus one // Attach GC data to nmethod
if (immediate_oops.is_empty() && nm->oops_count() == 1) { ZNMethodData* data = gc_data(nm);
// No oops found, return empty entry if (data == NULL) {
return ZNMethodTableEntry(); data = ZNMethodData::create(nm);
set_gc_data(nm, data);
} }
if (immediate_oops.is_empty()) { // Attach immediate oops in GC data
// No immediate oops found, return entry without immediate oops ZNMethodDataImmediateOops* const old_data_immediate_oops = data->swap_immediate_oops(immediate_oops);
return ZNMethodTableEntry(nm, non_immediate_oops); ZNMethodDataImmediateOops::destroy(old_data_immediate_oops);
}
// Return entry with immediate oops // Create entry
return ZNMethodTableEntry(ZNMethodWithImmediateOops::create(nm, immediate_oops), non_immediate_oops); return ZNMethodTableEntry(nm, non_immediate_oops, !immediate_oops.is_empty());
} }
void ZNMethodTable::destroy_entry(ZNMethodTableEntry entry) { ZReentrantLock* ZNMethodTable::lock_for_nmethod(nmethod* nm) {
if (entry.immediate_oops()) { ZNMethodData* const data = gc_data(nm);
ZNMethodWithImmediateOops::destroy(entry.method_with_immediate_oops()); if (data == NULL) {
return NULL;
} }
} return data->lock();
nmethod* ZNMethodTable::method(ZNMethodTableEntry entry) {
return entry.immediate_oops() ? entry.method_with_immediate_oops()->method() : entry.method();
} }
size_t ZNMethodTable::first_index(const nmethod* nm, size_t size) { size_t ZNMethodTable::first_index(const nmethod* nm, size_t size) {
@ -171,7 +242,7 @@ size_t ZNMethodTable::next_index(size_t prev_index, size_t size) {
} }
bool ZNMethodTable::register_entry(ZNMethodTableEntry* table, size_t size, ZNMethodTableEntry entry) { 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); size_t index = first_index(nm, size);
for (;;) { for (;;) {
@ -183,9 +254,8 @@ bool ZNMethodTable::register_entry(ZNMethodTableEntry* table, size_t size, ZNMet
return true; return true;
} }
if (table_entry.registered() && method(table_entry) == nm) { if (table_entry.registered() && table_entry.method() == nm) {
// Replace existing entry // Replace existing entry
destroy_entry(table_entry);
table[index] = entry; table[index] = entry;
return false; return false;
} }
@ -194,7 +264,7 @@ bool ZNMethodTable::register_entry(ZNMethodTableEntry* table, size_t size, ZNMet
} }
} }
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) { if (size == 0) {
// Table is empty // Table is empty
return false; return false;
@ -210,10 +280,13 @@ bool ZNMethodTable::unregister_entry(ZNMethodTableEntry* table, size_t size, con
return false; return false;
} }
if (table_entry.registered() && method(table_entry) == nm) { if (table_entry.registered() && table_entry.method() == nm) {
// Remove entry // Remove entry
destroy_entry(table_entry);
table[index] = ZNMethodTableEntry(true /* unregistered */); table[index] = ZNMethodTableEntry(true /* unregistered */);
// Destroy GC data
ZNMethodData::destroy(gc_data(nm));
set_gc_data(nm, NULL);
return true; return true;
} }
@ -222,6 +295,7 @@ bool ZNMethodTable::unregister_entry(ZNMethodTableEntry* table, size_t size, con
} }
void ZNMethodTable::rebuild(size_t new_size) { void ZNMethodTable::rebuild(size_t new_size) {
ZLocker<ZLock> locker(&_iter_lock);
assert(is_power_of_2(new_size), "Invalid size"); assert(is_power_of_2(new_size), "Invalid size");
log_debug(gc, nmethod)("Rebuilding NMethod Table: " log_debug(gc, nmethod)("Rebuilding NMethod Table: "
@ -243,8 +317,10 @@ void ZNMethodTable::rebuild(size_t new_size) {
} }
} }
// Delete old table if (_iter_table != _table) {
delete [] _table; // Delete old table
delete [] _table;
}
// Install new table // Install new table
_table = new_table; _table = new_table;
@ -294,8 +370,8 @@ void ZNMethodTable::log_register(const nmethod* nm, ZNMethodTableEntry entry) {
p2i(nm), p2i(nm),
nm->compiler_name(), nm->compiler_name(),
nm->oops_count() - 1, nm->oops_count() - 1,
entry.immediate_oops() ? entry.method_with_immediate_oops()->immediate_oops_count() : 0, entry.immediate_oops() ? gc_data(nm)->immediate_oops()->immediate_oops_count() : 0,
BOOL_TO_STR(entry.non_immediate_oops())); entry.non_immediate_oops() ? "Yes" : "No");
LogTarget(Trace, gc, nmethod, oops) log_oops; LogTarget(Trace, gc, nmethod, oops) log_oops;
if (!log_oops.is_enabled()) { if (!log_oops.is_enabled()) {
@ -312,12 +388,14 @@ void ZNMethodTable::log_register(const nmethod* nm, ZNMethodTableEntry entry) {
if (entry.immediate_oops()) { if (entry.immediate_oops()) {
// Print nmethod immediate oops // Print nmethod immediate oops
const ZNMethodWithImmediateOops* const nmi = entry.method_with_immediate_oops(); const ZNMethodDataImmediateOops* const nmi = gc_data(nm)->immediate_oops();
oop** const begin = nmi->immediate_oops_begin(); if (nmi != NULL) {
oop** const end = nmi->immediate_oops_end(); oop** const begin = nmi->immediate_oops_begin();
for (oop** p = begin; p < end; p++) { oop** const end = nmi->immediate_oops_end();
log_oops.print(" ImmediateOop[" SIZE_FORMAT "] " PTR_FORMAT " @ " PTR_FORMAT " (%s)", for (oop** p = begin; p < end; p++) {
(p - begin), p2i(**p), p2i(*p), (**p)->klass()->external_name()); 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 @@ size_t ZNMethodTable::unregistered_nmethods() {
} }
void ZNMethodTable::register_nmethod(nmethod* nm) { void ZNMethodTable::register_nmethod(nmethod* nm) {
assert(CodeCache_lock->owned_by_self(), "Lock must be held");
ResourceMark rm; ResourceMark rm;
// Grow/Shrink/Prune table if needed
rebuild_if_needed();
// Create entry // Create entry
const ZNMethodTableEntry entry = create_entry(nm); const ZNMethodTableEntry entry = create_entry(nm);
log_register(nm, entry); 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 // Insert new entry
if (register_entry(_table, _size, entry)) { if (register_entry(_table, _size, entry)) {
// New entry registered. When register_entry() instead returns // New entry registered. When register_entry() instead returns
@ -365,11 +439,31 @@ void ZNMethodTable::register_nmethod(nmethod* nm) {
// to increase number of registered entries in that case. // to increase number of registered entries in that case.
_nregistered++; _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) { void ZNMethodTable::unregister_nmethod(nmethod* nm) {
ResourceMark rm; ResourceMark rm;
sweeper_wait_for_iteration();
log_unregister(nm); log_unregister(nm);
// Remove entry // Remove entry
@ -383,20 +477,45 @@ void ZNMethodTable::unregister_nmethod(nmethod* nm) {
} }
} }
void ZNMethodTable::gc_prologue() { void ZNMethodTable::disarm_nmethod(nmethod* nm) {
_claimed = 0; BarrierSetNMethod* const bs = BarrierSet::barrier_set()->barrier_set_nmethod();
if (bs != NULL) {
bs->disarm(nm);
}
} }
void ZNMethodTable::gc_epilogue() { void ZNMethodTable::nmethod_entries_do_begin() {
assert(_claimed >= _size, "Failed to claim all table entries"); 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::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) { void ZNMethodTable::entry_oops_do(ZNMethodTableEntry entry, OopClosure* cl) {
nmethod* const nm = method(entry); nmethod* const nm = entry.method();
if (!nm->is_alive()) {
// No need to visit oops
return;
}
// Process oops table // Process oops table
oop* const begin = nm->oops_begin(); oop* const begin = nm->oops_begin();
@ -407,29 +526,52 @@ void ZNMethodTable::entry_oops_do(ZNMethodTableEntry entry, OopClosure* cl) {
} }
} }
// Process immediate oops
if (entry.immediate_oops()) { if (entry.immediate_oops()) {
// Process immediate oops const ZNMethodDataImmediateOops* const nmi = gc_data(nm)->immediate_oops();
const ZNMethodWithImmediateOops* const nmi = entry.method_with_immediate_oops(); if (nmi != NULL) {
oop** const begin = nmi->immediate_oops_begin(); oop** const begin = nmi->immediate_oops_begin();
oop** const end = nmi->immediate_oops_end(); oop** const end = nmi->immediate_oops_end();
for (oop** p = begin; p < end; p++) { for (oop** p = begin; p < end; p++) {
cl->do_oop(*p); if (**p != Universe::non_oop_word()) {
cl->do_oop(*p);
}
}
} }
} }
// Process non-immediate oops
if (entry.non_immediate_oops()) { if (entry.non_immediate_oops()) {
// Process non-immediate oops nmethod* const nm = entry.method();
nm->fix_oop_relocations(); 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) { void ZNMethodTable::oops_do(OopClosure* cl) {
ZNMethodTableEntryToOopsDo entry_cl(cl);
nmethod_entries_do(&entry_cl);
}
void ZNMethodTable::nmethod_entries_do(ZNMethodTableEntryClosure* cl) {
for (;;) { for (;;) {
// Claim table partition. Each partition is currently sized to span // Claim table partition. Each partition is currently sized to span
// two cache lines. This number is just a guess, but seems to work well. // 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_size = (ZCacheLineSize * 2) / sizeof(ZNMethodTableEntry);
const size_t partition_start = MIN2(Atomic::add(partition_size, &_claimed) - 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, _size); const size_t partition_end = MIN2(partition_start + partition_size, _iter_table_size);
if (partition_start == partition_end) { if (partition_start == partition_end) {
// End of table // End of table
break; break;
@ -437,10 +579,141 @@ void ZNMethodTable::oops_do(OopClosure* cl) {
// Process table partition // Process table partition
for (size_t i = partition_start; i < partition_end; i++) { for (size_t i = partition_start; i < partition_end; i++) {
const ZNMethodTableEntry entry = _table[i]; const ZNMethodTableEntry entry = _iter_table[i];
if (entry.registered()) { 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);
}

View File

@ -24,28 +24,40 @@
#ifndef SHARE_GC_Z_ZNMETHODTABLE_HPP #ifndef SHARE_GC_Z_ZNMETHODTABLE_HPP
#define SHARE_GC_Z_ZNMETHODTABLE_HPP #define SHARE_GC_Z_ZNMETHODTABLE_HPP
#include "gc/z/zArray.hpp"
#include "gc/z/zGlobals.hpp" #include "gc/z/zGlobals.hpp"
#include "gc/z/zLock.hpp"
#include "gc/z/zNMethodTableEntry.hpp" #include "gc/z/zNMethodTableEntry.hpp"
#include "memory/allocation.hpp" #include "memory/allocation.hpp"
class ZWorkers;
class ZNMethodTableEntryClosure {
public:
virtual void do_nmethod_entry(ZNMethodTableEntry entry) = 0;
};
class ZNMethodTable : public AllStatic { class ZNMethodTable : public AllStatic {
private: private:
static ZNMethodTableEntry* _table; static ZNMethodTableEntry* _table;
static size_t _size; 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 _nregistered;
static size_t _nunregistered; static size_t _nunregistered;
static volatile size_t _claimed ATTRIBUTE_ALIGNED(ZCacheLineSize); static volatile size_t _claimed ATTRIBUTE_ALIGNED(ZCacheLineSize);
static ZNMethodTableEntry create_entry(nmethod* nm); 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 first_index(const nmethod* nm, size_t size);
static size_t next_index(size_t prev_index, 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 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(size_t new_size);
static void rebuild_if_needed(); static void rebuild_if_needed();
@ -53,19 +65,28 @@ private:
static void log_register(const nmethod* nm, ZNMethodTableEntry entry); static void log_register(const nmethod* nm, ZNMethodTableEntry entry);
static void log_unregister(const nmethod* nm); static void log_unregister(const nmethod* nm);
static void entry_oops_do(ZNMethodTableEntry entry, OopClosure* cl);
public: public:
static void safe_delete(void* data);
static size_t registered_nmethods(); static size_t registered_nmethods();
static size_t unregistered_nmethods(); static size_t unregistered_nmethods();
static void register_nmethod(nmethod* nm); static void register_nmethod(nmethod* nm);
static void unregister_nmethod(nmethod* nm); static void unregister_nmethod(nmethod* nm);
static void disarm_nmethod(nmethod* nm);
static void gc_prologue(); static ZReentrantLock* lock_for_nmethod(nmethod* nm);
static void gc_epilogue();
static void oops_do(OopClosure* cl); 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 #endif // SHARE_GC_Z_ZNMETHODTABLE_HPP

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -43,38 +43,30 @@
// | | // | |
// | 0-0 Registered Flag (1-bits) * // | 0-0 Registered Flag (1-bits) *
// | // |
// * 63-3 NMethod/ZNMethodWithImmediateOops Address (61-bits) // * 63-3 NMethod Address (61-bits)
// //
class nmethod; class nmethod;
class ZNMethodWithImmediateOops;
class ZNMethodTableEntry : public CHeapObj<mtGC> { class ZNMethodTableEntry : public CHeapObj<mtGC> {
private: private:
typedef ZBitField<uint64_t, bool, 0, 1> field_registered; 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_unregistered;
typedef ZBitField<uint64_t, bool, 1, 1> field_immediate_oops; 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, bool, 2, 1> field_non_immediate_oops;
typedef ZBitField<uint64_t, nmethod*, 3, 61, 3> field_method; typedef ZBitField<uint64_t, nmethod*, 3, 61, 3> field_method;
typedef ZBitField<uint64_t, ZNMethodWithImmediateOops*, 3, 61, 3> field_method_with_immediate_oops;
uint64_t _entry; uint64_t _entry;
public: public:
ZNMethodTableEntry(bool unregistered = false) : explicit ZNMethodTableEntry(bool unregistered = false) :
_entry(field_unregistered::encode(unregistered) | _entry(field_unregistered::encode(unregistered) |
field_registered::encode(false)) {} 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) | _entry(field_method::encode(method) |
field_non_immediate_oops::encode(non_immediate_oops) | field_non_immediate_oops::encode(non_immediate_oops) |
field_immediate_oops::encode(false) | field_immediate_oops::encode(immediate_oops) |
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_registered::encode(true)) {} field_registered::encode(true)) {}
bool registered() const { bool registered() const {
@ -96,10 +88,6 @@ public:
nmethod* method() const { nmethod* method() const {
return field_method::decode(_entry); 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 #endif // SHARE_GC_Z_ZNMETHODTABLEENTRY_HPP

View File

@ -39,14 +39,23 @@ public:
#endif #endif
}; };
class ZNMethodOopClosure : public OopClosure {
public:
virtual void do_oop(oop* p);
virtual void do_oop(narrowOop* p);
};
template <bool finalizable> template <bool finalizable>
class ZMarkBarrierOopClosure : public BasicOopIterateClosure { class ZMarkBarrierOopClosure : public MetadataVisitingOopIterateClosure {
public: public:
ZMarkBarrierOopClosure(); ZMarkBarrierOopClosure();
virtual void do_oop(oop* p); virtual void do_oop(oop* p);
virtual void do_oop(narrowOop* p); virtual void do_oop(narrowOop* p);
virtual void do_klass(Klass* k);
virtual void do_cld(ClassLoaderData* cld);
#ifdef ASSERT #ifdef ASSERT
virtual bool should_verify_oops() { virtual bool should_verify_oops() {
return false; return false;

View File

@ -24,6 +24,7 @@
#ifndef SHARE_GC_Z_ZOOPCLOSURES_INLINE_HPP #ifndef SHARE_GC_Z_ZOOPCLOSURES_INLINE_HPP
#define 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/zBarrier.inline.hpp"
#include "gc/z/zHeap.inline.hpp" #include "gc/z/zHeap.inline.hpp"
#include "gc/z/zOop.inline.hpp" #include "gc/z/zOop.inline.hpp"
@ -40,9 +41,21 @@ inline void ZLoadBarrierOopClosure::do_oop(narrowOop* p) {
ShouldNotReachHere(); 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> template <bool finalizable>
inline ZMarkBarrierOopClosure<finalizable>::ZMarkBarrierOopClosure() : inline ZMarkBarrierOopClosure<finalizable>::ZMarkBarrierOopClosure() :
BasicOopIterateClosure(finalizable ? NULL : ZHeap::heap()->reference_discoverer()) {} MetadataVisitingOopIterateClosure(finalizable ? NULL : ZHeap::heap()->reference_discoverer()) {}
template <bool finalizable> template <bool finalizable>
inline void ZMarkBarrierOopClosure<finalizable>::do_oop(oop* p) { inline void ZMarkBarrierOopClosure<finalizable>::do_oop(oop* p) {
@ -54,6 +67,18 @@ inline void ZMarkBarrierOopClosure<finalizable>::do_oop(narrowOop* p) {
ShouldNotReachHere(); 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) { inline bool ZPhantomIsAliveObjectClosure::do_object_b(oop o) {
return ZBarrier::is_alive_barrier_on_phantom_oop(o); return ZBarrier::is_alive_barrier_on_phantom_oop(o);
} }

View File

@ -27,8 +27,11 @@
#include "classfile/systemDictionary.hpp" #include "classfile/systemDictionary.hpp"
#include "code/codeCache.hpp" #include "code/codeCache.hpp"
#include "compiler/oopMap.hpp" #include "compiler/oopMap.hpp"
#include "gc/shared/barrierSet.hpp"
#include "gc/shared/barrierSetNMethod.hpp"
#include "gc/shared/oopStorageParState.inline.hpp" #include "gc/shared/oopStorageParState.inline.hpp"
#include "gc/shared/suspendibleThreadSet.hpp" #include "gc/shared/suspendibleThreadSet.hpp"
#include "gc/z/zBarrierSetNMethod.hpp"
#include "gc/z/zGlobals.hpp" #include "gc/z/zGlobals.hpp"
#include "gc/z/zNMethodTable.hpp" #include "gc/z/zNMethodTable.hpp"
#include "gc/z/zOopClosures.inline.hpp" #include "gc/z/zOopClosures.inline.hpp"
@ -132,6 +135,30 @@ void ZParallelWeakOopsDo<T, F>::weak_oops_do(BoolObjectClosure* is_alive, ZRoots
} }
} }
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() : ZRootsIterator::ZRootsIterator() :
_universe(this), _universe(this),
_object_synchronizer(this), _object_synchronizer(this),
@ -145,16 +172,23 @@ ZRootsIterator::ZRootsIterator() :
ZStatTimer timer(ZSubPhasePauseRootsSetup); ZStatTimer timer(ZSubPhasePauseRootsSetup);
Threads::change_thread_claim_parity(); Threads::change_thread_claim_parity();
COMPILER2_PRESENT(DerivedPointerTable::clear()); COMPILER2_PRESENT(DerivedPointerTable::clear());
CodeCache::gc_prologue(); if (ClassUnloading) {
ZNMethodTable::gc_prologue(); nmethod::oops_do_marking_prologue();
} else {
ZNMethodTable::nmethod_entries_do_begin();
}
} }
ZRootsIterator::~ZRootsIterator() { ZRootsIterator::~ZRootsIterator() {
ZStatTimer timer(ZSubPhasePauseRootsTeardown); ZStatTimer timer(ZSubPhasePauseRootsTeardown);
ResourceMark rm; ResourceMark rm;
ZNMethodTable::gc_epilogue(); if (ClassUnloading) {
CodeCache::gc_epilogue(); nmethod::oops_do_marking_epilogue();
} else {
ZNMethodTable::nmethod_entries_do_end();
}
JvmtiExport::gc_epilogue(); JvmtiExport::gc_epilogue();
COMPILER2_PRESENT(DerivedPointerTable::update_pointers()); COMPILER2_PRESENT(DerivedPointerTable::update_pointers());
Threads::assert_all_threads_claimed(); Threads::assert_all_threads_claimed();
} }
@ -209,7 +243,9 @@ void ZRootsIterator::oops_do(ZRootsIteratorClosure* cl, bool visit_jvmti_weak_ex
_jvmti_export.oops_do(cl); _jvmti_export.oops_do(cl);
_system_dictionary.oops_do(cl); _system_dictionary.oops_do(cl);
_threads.oops_do(cl); _threads.oops_do(cl);
_code_cache.oops_do(cl); if (!ClassUnloading) {
_code_cache.oops_do(cl);
}
if (visit_jvmti_weak_export) { if (visit_jvmti_weak_export) {
_jvmti_weak_export.oops_do(cl); _jvmti_weak_export.oops_do(cl);
} }
@ -242,8 +278,13 @@ void ZConcurrentRootsIterator::do_jni_handles(ZRootsIteratorClosure* cl) {
void ZConcurrentRootsIterator::do_class_loader_data_graph(ZRootsIteratorClosure* cl) { void ZConcurrentRootsIterator::do_class_loader_data_graph(ZRootsIteratorClosure* cl) {
ZStatTimer timer(ZSubPhaseConcurrentRootsClassLoaderDataGraph); ZStatTimer timer(ZSubPhaseConcurrentRootsClassLoaderDataGraph);
CLDToOopClosure cld_cl(cl, _marking ? ClassLoaderData::_claim_strong : ClassLoaderData::_claim_none); if (_marking) {
ClassLoaderDataGraph::cld_do(&cld_cl); 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) { void ZConcurrentRootsIterator::oops_do(ZRootsIteratorClosure* cl) {

View File

@ -33,9 +33,7 @@
class ZRootsIteratorClosure : public OopClosure, public ThreadClosure { class ZRootsIteratorClosure : public OopClosure, public ThreadClosure {
public: public:
virtual void do_thread(Thread* thread) { virtual void do_thread(Thread* thread);
thread->oops_do(this, NULL);
}
}; };
typedef OopStorage::ParState<true /* concurrent */, false /* is_const */> ZOopStorageIterator; typedef OopStorage::ParState<true /* concurrent */, false /* is_const */> ZOopStorageIterator;

View File

@ -25,6 +25,7 @@
#define SHARE_GC_Z_ZTHREADLOCALDATA_HPP #define SHARE_GC_Z_ZTHREADLOCALDATA_HPP
#include "gc/z/zMarkStack.hpp" #include "gc/z/zMarkStack.hpp"
#include "gc/z/zGlobals.hpp"
#include "runtime/thread.hpp" #include "runtime/thread.hpp"
#include "utilities/debug.hpp" #include "utilities/debug.hpp"
#include "utilities/sizes.hpp" #include "utilities/sizes.hpp"
@ -62,6 +63,10 @@ public:
static ByteSize address_bad_mask_offset() { static ByteSize address_bad_mask_offset() {
return Thread::gc_data_offset() + byte_offset_of(ZThreadLocalData, _address_bad_mask); 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 #endif // SHARE_GC_Z_ZTHREADLOCALDATA_HPP

View File

@ -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();
}

View File

@ -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

View File

@ -306,15 +306,19 @@ Thread::Thread() {
} }
#endif // ASSERT #endif // ASSERT
// Notify the barrier set that a thread is being created. Note that some // Notify the barrier set that a thread is being created. The initial
// threads are created before a barrier set is available. The call to // thread is created before the barrier set is available. The call to
// BarrierSet::on_thread_create() for these threads is therefore deferred // BarrierSet::on_thread_create() for this thread is therefore deferred
// to BarrierSet::set_barrier_set(). // to BarrierSet::set_barrier_set().
BarrierSet* const barrier_set = BarrierSet::barrier_set(); BarrierSet* const barrier_set = BarrierSet::barrier_set();
if (barrier_set != NULL) { if (barrier_set != NULL) {
barrier_set->on_thread_create(this); barrier_set->on_thread_create(this);
} else { } 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 @@ size_t JavaThread::_stack_size_at_create = 0;
#ifdef ASSERT #ifdef ASSERT
bool Threads::_vm_complete = false; bool Threads::_vm_complete = false;
size_t Threads::_threads_before_barrier_set = 0;
#endif #endif
static inline void *prefetch_and_load_ptr(void **addr, intx prefetch_interval) { static inline void *prefetch_and_load_ptr(void **addr, intx prefetch_interval) {

View File

@ -2156,7 +2156,6 @@ class Threads: AllStatic {
static int _thread_claim_parity; static int _thread_claim_parity;
#ifdef ASSERT #ifdef ASSERT
static bool _vm_complete; static bool _vm_complete;
static size_t _threads_before_barrier_set;
#endif #endif
static void initialize_java_lang_classes(JavaThread* main_thread, TRAPS); static void initialize_java_lang_classes(JavaThread* main_thread, TRAPS);
@ -2226,14 +2225,6 @@ class Threads: AllStatic {
#ifdef ASSERT #ifdef ASSERT
static bool is_vm_complete() { return _vm_complete; } 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 #endif // ASSERT
// Verification // Verification

View File

@ -681,11 +681,12 @@ class Character implements java.io.Serializable, Comparable<Character> {
*/ */
public static final class UnicodeBlock extends Subset { 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 * 0.75 - the default load factor of HashMap
*/ */
private static final int NUM_ENTITIES = 667;
private static Map<String, UnicodeBlock> map = 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. * Creates a UnicodeBlock with the given identifier name.

View File

@ -94,12 +94,10 @@ public class Object {
* programmer should be aware that producing distinct integer results * programmer should be aware that producing distinct integer results
* for unequal objects may improve the performance of hash tables. * for unequal objects may improve the performance of hash tables.
* </ul> * </ul>
* <p> *
* As much as is reasonably practical, the hashCode method defined * @implSpec
* by class {@code Object} does return distinct integers for * As far as is reasonably practical, the {@code hashCode} method defined
* distinct objects. (The hashCode may or may not be implemented * by class {@code Object} returns distinct integers for distinct objects.
* as some function of an object's memory address at some point
* in time.)
* *
* @return a hash code value for this object. * @return a hash code value for this object.
* @see java.lang.Object#equals(java.lang.Object) * @see java.lang.Object#equals(java.lang.Object)

View File

@ -25,6 +25,7 @@
package java.net; package java.net;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InvalidObjectException; import java.io.InvalidObjectException;
import java.io.ObjectInputStream; import java.io.ObjectInputStream;
@ -36,6 +37,7 @@ import java.nio.charset.CharsetDecoder;
import java.nio.charset.CoderResult; import java.nio.charset.CoderResult;
import java.nio.charset.CodingErrorAction; import java.nio.charset.CodingErrorAction;
import java.nio.charset.CharacterCodingException; import java.nio.charset.CharacterCodingException;
import java.nio.file.Path;
import java.text.Normalizer; import java.text.Normalizer;
import jdk.internal.access.JavaNetUriAccess; import jdk.internal.access.JavaNetUriAccess;
import jdk.internal.access.SharedSecrets; import jdk.internal.access.SharedSecrets;
@ -458,6 +460,27 @@ import java.lang.NullPointerException; // for javadoc
* resolution as well as the network I/O operations of looking up the host and * resolution as well as the network I/O operations of looking up the host and
* opening a connection to the specified resource. * 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 * @author Mark Reinhold
* @since 1.4 * @since 1.4

View File

@ -25,9 +25,11 @@
package java.net; package java.net;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.net.spi.URLStreamHandlerProvider; import java.net.spi.URLStreamHandlerProvider;
import java.nio.file.Path;
import java.security.AccessController; import java.security.AccessController;
import java.security.PrivilegedAction; import java.security.PrivilegedAction;
import java.util.Hashtable; import java.util.Hashtable;
@ -145,6 +147,27 @@ import sun.security.action.GetPropertyAction;
* used, but only for HTML form encoding, which is not the same * used, but only for HTML form encoding, which is not the same
* as the encoding scheme defined in RFC2396. * 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 * @author James Gosling
* @since 1.0 * @since 1.0
*/ */

View File

@ -80,7 +80,7 @@ import java.util.stream.StreamSupport;
* in security-sensitive applications. Additionally, * in security-sensitive applications. Additionally,
* default-constructed instances do not use a cryptographically random * default-constructed instances do not use a cryptographically random
* seed unless the {@linkplain System#getProperty system property} * 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 Guy Steele
* @author Doug Lea * @author Doug Lea

View File

@ -2334,17 +2334,15 @@ public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>
Node<K,V>[] tab, nt; int n, sc; Node<K,V>[] tab, nt; int n, sc;
while (s >= (long)(sc = sizeCtl) && (tab = table) != null && while (s >= (long)(sc = sizeCtl) && (tab = table) != null &&
(n = tab.length) < MAXIMUM_CAPACITY) { (n = tab.length) < MAXIMUM_CAPACITY) {
int rs = resizeStamp(n); int rs = resizeStamp(n) << RESIZE_STAMP_SHIFT;
if (sc < 0) { if (sc < 0) {
if ((sc >>> RESIZE_STAMP_SHIFT) != rs || sc == rs + 1 || if (sc == rs + MAX_RESIZERS || sc == rs + 1 ||
sc == rs + MAX_RESIZERS || (nt = nextTable) == null || (nt = nextTable) == null || transferIndex <= 0)
transferIndex <= 0)
break; break;
if (U.compareAndSetInt(this, SIZECTL, sc, sc + 1)) if (U.compareAndSetInt(this, SIZECTL, sc, sc + 1))
transfer(tab, nt); transfer(tab, nt);
} }
else if (U.compareAndSetInt(this, SIZECTL, sc, else if (U.compareAndSetInt(this, SIZECTL, sc, rs + 2))
(rs << RESIZE_STAMP_SHIFT) + 2))
transfer(tab, null); transfer(tab, null);
s = sumCount(); s = sumCount();
} }
@ -2358,11 +2356,11 @@ public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>
Node<K,V>[] nextTab; int sc; Node<K,V>[] nextTab; int sc;
if (tab != null && (f instanceof ForwardingNode) && if (tab != null && (f instanceof ForwardingNode) &&
(nextTab = ((ForwardingNode<K,V>)f).nextTable) != null) { (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 && while (nextTab == nextTable && table == tab &&
(sc = sizeCtl) < 0) { (sc = sizeCtl) < 0) {
if ((sc >>> RESIZE_STAMP_SHIFT) != rs || sc == rs + 1 || if (sc == rs + MAX_RESIZERS || sc == rs + 1 ||
sc == rs + MAX_RESIZERS || transferIndex <= 0) transferIndex <= 0)
break; break;
if (U.compareAndSetInt(this, SIZECTL, sc, sc + 1)) { if (U.compareAndSetInt(this, SIZECTL, sc, sc + 1)) {
transfer(tab, nextTab); transfer(tab, nextTab);

View File

@ -136,17 +136,17 @@ import java.util.concurrent.locks.LockSupport;
* <p>The parameters used to construct the common pool may be controlled by * <p>The parameters used to construct the common pool may be controlled by
* setting the following {@linkplain System#getProperty system properties}: * setting the following {@linkplain System#getProperty system properties}:
* <ul> * <ul>
* <li>{@code java.util.concurrent.ForkJoinPool.common.parallelism} * <li>{@systemProperty java.util.concurrent.ForkJoinPool.common.parallelism}
* - the parallelism level, a non-negative integer * - 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 class name of a {@link ForkJoinWorkerThreadFactory}.
* The {@linkplain ClassLoader#getSystemClassLoader() system class loader} * The {@linkplain ClassLoader#getSystemClassLoader() system class loader}
* is used to load this class. * 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 class name of a {@link UncaughtExceptionHandler}.
* The {@linkplain ClassLoader#getSystemClassLoader() system class loader} * The {@linkplain ClassLoader#getSystemClassLoader() system class loader}
* is used to load this class. * 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 * - the maximum number of allowed extra threads to maintain target
* parallelism (default 256). * parallelism (default 256).
* </ul> * </ul>
@ -445,8 +445,7 @@ public class ForkJoinPool extends AbstractExecutorService {
* if to its current value). This would be extremely costly. So * if to its current value). This would be extremely costly. So
* we relax it in several ways: (1) Producers only signal when * we relax it in several ways: (1) Producers only signal when
* their queue is possibly empty at some point during a push * their queue is possibly empty at some point during a push
* operation (which requires conservatively checking size zero or * operation. (2) Other workers propagate this signal
* one to cover races). (2) Other workers propagate this signal
* when they find tasks in a queue with size greater than one. (3) * when they find tasks in a queue with size greater than one. (3)
* Workers only enqueue after scanning (see below) and not finding * Workers only enqueue after scanning (see below) and not finding
* any tasks. (4) Rather than CASing ctl to its current value in * any tasks. (4) Rather than CASing ctl to its current value in
@ -762,10 +761,8 @@ public class ForkJoinPool extends AbstractExecutorService {
/** /**
* The maximum number of top-level polls per worker before * The maximum number of top-level polls per worker before
* checking other queues, expressed as a bit shift to, in effect, * checking other queues, expressed as a bit shift. See above for
* multiply by pool size, and then use as random value mask, so * rationale.
* average bound is about poolSize*(1<<TOP_BOUND_SHIFT). See
* above for rationale.
*/ */
static final int TOP_BOUND_SHIFT = 10; static final int TOP_BOUND_SHIFT = 10;
@ -841,18 +838,17 @@ public class ForkJoinPool extends AbstractExecutorService {
*/ */
final void push(ForkJoinTask<?> task) { final void push(ForkJoinTask<?> task) {
ForkJoinTask<?>[] a; ForkJoinTask<?>[] a;
int s = top, d, cap, m; int s = top, d = s - base, cap, m;
ForkJoinPool p = pool; ForkJoinPool p = pool;
if ((a = array) != null && (cap = a.length) > 0) { if ((a = array) != null && (cap = a.length) > 0) {
QA.setRelease(a, (m = cap - 1) & s, task); QA.setRelease(a, (m = cap - 1) & s, task);
top = s + 1; top = s + 1;
if (((d = s - (int)BASE.getAcquire(this)) & ~1) == 0 && if (d == m)
p != null) { // size 0 or 1
VarHandle.fullFence();
p.signalWork();
}
else if (d == m)
growArray(false); growArray(false);
else if (QA.getAcquire(a, m & (s - 1)) == null && p != null) {
VarHandle.fullFence(); // was empty
p.signalWork(null);
}
} }
} }
@ -863,16 +859,16 @@ public class ForkJoinPool extends AbstractExecutorService {
final boolean lockedPush(ForkJoinTask<?> task) { final boolean lockedPush(ForkJoinTask<?> task) {
ForkJoinTask<?>[] a; ForkJoinTask<?>[] a;
boolean signal = false; 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) { if ((a = array) != null && (cap = a.length) > 0) {
a[(cap - 1) & s] = task; a[(m = (cap - 1)) & s] = task;
top = s + 1; top = s + 1;
if (b - s + cap - 1 == 0) if (d == m)
growArray(true); growArray(true);
else { else {
phase = 0; // full volatile unlock phase = 0; // full volatile unlock
if (((s - base) & ~1) == 0) // size 0 or 1 if (a[m & (s - 1)] == null)
signal = true; signal = true; // was empty
} }
} }
return signal; return signal;
@ -1014,25 +1010,30 @@ public class ForkJoinPool extends AbstractExecutorService {
* queue, up to bound n (to avoid infinite unfairness). * queue, up to bound n (to avoid infinite unfairness).
*/ */
final void topLevelExec(ForkJoinTask<?> t, WorkQueue q, int n) { final void topLevelExec(ForkJoinTask<?> t, WorkQueue q, int n) {
if (t != null && q != null) { // hoist checks int nstolen = 1;
int nstolen = 1; for (int j = 0;;) {
for (;;) { if (t != null)
t.doExec(); t.doExec();
if (n-- < 0) if (j++ <= n)
break; t = nextLocalTask();
else if ((t = nextLocalTask()) == null) { else {
if ((t = q.poll()) == null) j = 0;
break; t = null;
else }
++nstolen; if (t == null) {
} if (q != null && (t = q.poll()) != null) {
++nstolen;
j = 0;
}
else if (j != 0)
break;
} }
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 @@ public class ForkJoinPool extends AbstractExecutorService {
if (!tryTerminate(false, false) && // possibly replace worker if (!tryTerminate(false, false) && // possibly replace worker
w != null && w.array != null) // avoid repeated failures w != null && w.array != null) // avoid repeated failures
signalWork(); signalWork(null);
if (ex == null) // help clean on way out if (ex == null) // help clean on way out
ForkJoinTask.helpExpungeStaleExceptions(); ForkJoinTask.helpExpungeStaleExceptions();
@ -1465,8 +1466,9 @@ public class ForkJoinPool extends AbstractExecutorService {
/** /**
* Tries to create or release a worker if too few are running. * 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 (;;) { for (;;) {
long c; int sp; WorkQueue[] ws; int i; WorkQueue v; long c; int sp; WorkQueue[] ws; int i; WorkQueue v;
if ((c = ctl) >= 0L) // enough workers if ((c = ctl) >= 0L) // enough workers
@ -1493,6 +1495,8 @@ public class ForkJoinPool extends AbstractExecutorService {
LockSupport.unpark(vt); LockSupport.unpark(vt);
break; break;
} }
else if (q != null && q.isEmpty()) // no need to retry
break;
} }
} }
} }
@ -1613,19 +1617,24 @@ public class ForkJoinPool extends AbstractExecutorService {
else if (rc <= 0 && (md & SHUTDOWN) != 0 && else if (rc <= 0 && (md & SHUTDOWN) != 0 &&
tryTerminate(false, false)) tryTerminate(false, false))
break; // quiescent shutdown break; // quiescent shutdown
else if (rc <= 0 && pred != 0 && phase == (int)c) { else if (w.phase < 0) {
long nc = (UC_MASK & (c - TC_UNIT)) | (SP_MASK & pred); if (rc <= 0 && pred != 0 && phase == (int)c) {
long d = keepAlive + System.currentTimeMillis(); long nc = (UC_MASK & (c - TC_UNIT)) | (SP_MASK & pred);
LockSupport.parkUntil(this, d); long d = keepAlive + System.currentTimeMillis();
if (ctl == c && // drop on timeout if all idle LockSupport.parkUntil(this, d);
d - System.currentTimeMillis() <= TIMEOUT_SLOP && if (ctl == c && // drop on timeout if all idle
CTL.compareAndSet(this, c, nc)) { d - System.currentTimeMillis() <= TIMEOUT_SLOP &&
w.phase = QUIET; CTL.compareAndSet(this, c, nc)) {
break; 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 w.source = 0; // disable signal
} }
} }
@ -1641,8 +1650,8 @@ public class ForkJoinPool extends AbstractExecutorService {
WorkQueue[] ws; int n; WorkQueue[] ws; int n;
if ((ws = workQueues) != null && (n = ws.length) > 0 && w != null) { if ((ws = workQueues) != null && (n = ws.length) > 0 && w != null) {
for (int m = n - 1, j = r & m;;) { for (int m = n - 1, j = r & m;;) {
WorkQueue q; int b; WorkQueue q; int b, s;
if ((q = ws[j]) != null && q.top != (b = q.base)) { if ((q = ws[j]) != null && (s = q.top) != (b = q.base)) {
int qid = q.id; int qid = q.id;
ForkJoinTask<?>[] a; int cap, k; ForkJoinTask<?> t; ForkJoinTask<?>[] a; int cap, k; ForkJoinTask<?> t;
if ((a = q.array) != null && (cap = a.length) > 0) { if ((a = q.array) != null && (cap = a.length) > 0) {
@ -1651,10 +1660,10 @@ public class ForkJoinPool extends AbstractExecutorService {
QA.compareAndSet(a, k, t, null)) { QA.compareAndSet(a, k, t, null)) {
q.base = b; q.base = b;
w.source = qid; w.source = qid;
if (q.top - b > 0) if (s != b && a[(cap - 1) & b] != null)
signalWork(); signalWork(q); // help signal if more tasks
w.topLevelExec(t, q, // random fairness bound w.topLevelExec(t, q, // random fairness bound
r & ((n << TOP_BOUND_SHIFT) - 1)); (r | (1 << TOP_BOUND_SHIFT)) & SMASK);
} }
} }
return true; return true;
@ -1900,7 +1909,7 @@ public class ForkJoinPool extends AbstractExecutorService {
r = ThreadLocalRandom.advanceProbe(r); r = ThreadLocalRandom.advanceProbe(r);
else { else {
if (q.lockedPush(task)) if (q.lockedPush(task))
signalWork(); signalWork(null);
return; return;
} }
} }

View File

@ -122,7 +122,7 @@ import java.util.concurrent.TimeUnit;
* <p>All {@code Lock} implementations <em>must</em> enforce the same * <p>All {@code Lock} implementations <em>must</em> enforce the same
* memory synchronization semantics as provided by the built-in monitor * memory synchronization semantics as provided by the built-in monitor
* lock, as described in * 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 * Chapter 17 of
* <cite>The Java&trade; Language Specification</cite></a>: * <cite>The Java&trade; Language Specification</cite></a>:
* <ul> * <ul>

View File

@ -133,7 +133,7 @@ import jdk.internal.vm.annotation.ReservedStackAccess;
* <p><b>Memory Synchronization.</b> Methods with the effect of * <p><b>Memory Synchronization.</b> Methods with the effect of
* successfully locking in any mode have the same memory * successfully locking in any mode have the same memory
* synchronization effects as a <em>Lock</em> action described in * 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&trade; Language Specification</cite></a>. * Chapter 17 of <cite>The Java&trade; Language Specification</cite></a>.
* Methods successfully unlocking in write mode have the same memory * Methods successfully unlocking in write mode have the same memory
* synchronization effects as an <em>Unlock</em> action. In optimistic * synchronization effects as an <em>Unlock</em> action. In optimistic

View File

@ -226,7 +226,7 @@
* *
* <h2 id="MemoryVisibility">Memory Consistency Properties</h2> * <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 * Chapter 17 of
* <cite>The Java&trade; Language Specification</cite></a> defines the * <cite>The Java&trade; Language Specification</cite></a> defines the
* <i>happens-before</i> relation on memory operations such as reads and * <i>happens-before</i> relation on memory operations such as reads and

View File

@ -90,6 +90,9 @@ class ClientHandshakeContext extends HandshakeContext {
ClientHelloMessage initialClientHelloMsg = null; ClientHelloMessage initialClientHelloMsg = null;
// PSK identity is selected in first Hello and used again after HRR
byte[] pskIdentity;
ClientHandshakeContext(SSLContextImpl sslContext, ClientHandshakeContext(SSLContextImpl sslContext,
TransportContext conContext) throws IOException { TransportContext conContext) throws IOException {
super(sslContext, conContext); super(sslContext, conContext);

View File

@ -656,7 +656,11 @@ final class PreSharedKeyExtension {
return null; return null;
} }
SecretKey psk = pskOpt.get(); 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 (!pskIdOpt.isPresent()) {
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
SSLLogger.fine( SSLLogger.fine(
@ -664,7 +668,7 @@ final class PreSharedKeyExtension {
} }
return null; return null;
} }
byte[] pskId = pskIdOpt.get(); chc.pskIdentity = pskIdOpt.get();
//The session cannot be used again. Remove it from the cache. //The session cannot be used again. Remove it from the cache.
SSLSessionContextImpl sessionCache = (SSLSessionContextImpl) SSLSessionContextImpl sessionCache = (SSLSessionContextImpl)
@ -681,7 +685,7 @@ final class PreSharedKeyExtension {
chc.resumingSession.getTicketCreationTime()); chc.resumingSession.getTicketCreationTime());
int obfuscatedAge = int obfuscatedAge =
ageMillis + chc.resumingSession.getTicketAgeAdd(); ageMillis + chc.resumingSession.getTicketAgeAdd();
identities.add(new PskIdentity(pskId, obfuscatedAge)); identities.add(new PskIdentity(chc.pskIdentity, obfuscatedAge));
SecretKey binderKey = deriveBinderKey(psk, chc.resumingSession); SecretKey binderKey = deriveBinderKey(psk, chc.resumingSession);
ClientHelloMessage clientHello = (ClientHelloMessage)message; ClientHelloMessage clientHello = (ClientHelloMessage)message;

View File

@ -52,4 +52,21 @@ public final class ArrayUtil {
// NPE is thrown when array is null // NPE is thrown when array is null
Preconditions.checkFromIndexSize(offset, len, array.length, AIOOBE_SUPPLIER); 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--;
}
}
} }

View File

@ -40,6 +40,18 @@ import java.nio.ByteBuffer;
public interface MutableIntegerModuloP extends IntegerModuloP { 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. * 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 * No change is made to either element when swap has the value 0. The
@ -131,5 +143,20 @@ public interface MutableIntegerModuloP extends IntegerModuloP {
* @return this * @return this
*/ */
MutableIntegerModuloP setProduct(SmallValue v); 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();
} }

View File

@ -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);

View File

@ -69,14 +69,25 @@ public abstract class IntegerPolynomial implements IntegerFieldModuloP {
private final BigInteger modulus; private final BigInteger modulus;
protected final int bitsPerLimb; protected final int bitsPerLimb;
private final long[] posModLimbs; 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 * Multiply an IntegerPolynomial representation (a) with a long (b) and
* store the result in an IntegerPolynomial representation (r). Requires * store the result in an IntegerPolynomial representation in a. Requires
* that a.length == r.length == numLimbs. It is allowed for a and r to be * that a.length == numLimbs.
* the same array.
*/ */
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 * Multiply two IntegerPolynomial representations (a and b) and store the
@ -96,12 +107,14 @@ public abstract class IntegerPolynomial implements IntegerFieldModuloP {
IntegerPolynomial(int bitsPerLimb, IntegerPolynomial(int bitsPerLimb,
int numLimbs, int numLimbs,
int maxAdds,
BigInteger modulus) { BigInteger modulus) {
this.numLimbs = numLimbs; this.numLimbs = numLimbs;
this.modulus = modulus; this.modulus = modulus;
this.bitsPerLimb = bitsPerLimb; this.bitsPerLimb = bitsPerLimb;
this.maxAdds = maxAdds;
posModLimbs = setPosModLimbs(); posModLimbs = setPosModLimbs();
} }
@ -116,6 +129,10 @@ public abstract class IntegerPolynomial implements IntegerFieldModuloP {
return numLimbs; return numLimbs;
} }
public int getMaxAdds() {
return maxAdds;
}
@Override @Override
public BigInteger getSize() { public BigInteger getSize() {
return modulus; return modulus;
@ -155,12 +172,22 @@ public abstract class IntegerPolynomial implements IntegerFieldModuloP {
*/ */
protected void encode(ByteBuffer buf, int length, byte highByte, protected void encode(ByteBuffer buf, int length, byte highByte,
long[] result) { long[] result) {
int numHighBits = 32 - Integer.numberOfLeadingZeros(highByte); int numHighBits = 32 - Integer.numberOfLeadingZeros(highByte);
int numBits = 8 * length + numHighBits; int numBits = 8 * length + numHighBits;
int maxBits = bitsPerLimb * result.length; int requiredLimbs = (numBits + bitsPerLimb - 1) / bitsPerLimb;
if (numBits > maxBits) { if (requiredLimbs > numLimbs) {
throw new ArithmeticException("Value is too large."); 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; int limbIndex = 0;
long curLimbValue = 0; long curLimbValue = 0;
@ -195,10 +222,10 @@ public abstract class IntegerPolynomial implements IntegerFieldModuloP {
} }
} }
if (limbIndex < numLimbs) { if (limbIndex < result.length) {
result[limbIndex++] = curLimbValue; result[limbIndex++] = curLimbValue;
} }
Arrays.fill(result, limbIndex, numLimbs, 0); Arrays.fill(result, limbIndex, result.length, 0);
postEncodeCarry(result); postEncodeCarry(result);
} }
@ -211,8 +238,10 @@ public abstract class IntegerPolynomial implements IntegerFieldModuloP {
encode(buf, length, highByte, result); 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) { protected void postEncodeCarry(long[] v) {
carry(v); reduce(v);
} }
public ImmutableElement getElement(byte[] v, int offset, int length, public ImmutableElement getElement(byte[] v, int offset, int length,
@ -222,7 +251,7 @@ public abstract class IntegerPolynomial implements IntegerFieldModuloP {
encode(v, offset, length, highByte, result); encode(v, offset, length, highByte, result);
return new ImmutableElement(result, true); return new ImmutableElement(result, 0);
} }
protected BigInteger evaluate(long[] limbs) { protected BigInteger evaluate(long[] limbs) {
@ -386,6 +415,20 @@ public abstract class IntegerPolynomial implements IntegerFieldModuloP {
} }
} }
/**
* 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, * 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 * and that a.length == b.length. If swap==0, then the values of a and b
@ -442,7 +485,7 @@ public abstract class IntegerPolynomial implements IntegerFieldModuloP {
private abstract class Element implements IntegerModuloP { private abstract class Element implements IntegerModuloP {
protected long[] limbs; protected long[] limbs;
protected boolean summand = false; protected int numAdds;
public Element(BigInteger v) { public Element(BigInteger v) {
limbs = new long[numLimbs]; limbs = new long[numLimbs];
@ -450,19 +493,19 @@ public abstract class IntegerPolynomial implements IntegerFieldModuloP {
} }
public Element(boolean v) { public Element(boolean v) {
limbs = new long[numLimbs]; this.limbs = new long[numLimbs];
limbs[0] = v ? 1l : 0l; this.limbs[0] = v ? 1l : 0l;
summand = true; this.numAdds = 0;
} }
private Element(long[] limbs, boolean summand) { private Element(long[] limbs, int numAdds) {
this.limbs = limbs; this.limbs = limbs;
this.summand = summand; this.numAdds = numAdds;
} }
private void setValue(BigInteger v) { private void setValue(BigInteger v) {
setLimbsValue(v, limbs); setLimbsValue(v, limbs);
summand = true; this.numAdds = 0;
} }
@Override @Override
@ -477,14 +520,18 @@ public abstract class IntegerPolynomial implements IntegerFieldModuloP {
@Override @Override
public MutableElement mutable() { public MutableElement mutable() {
return new MutableElement(limbs.clone(), summand); return new MutableElement(limbs.clone(), numAdds);
}
protected boolean isSummand() {
return numAdds < maxAdds;
} }
@Override @Override
public ImmutableElement add(IntegerModuloP genB) { public ImmutableElement add(IntegerModuloP genB) {
Element b = (Element) genB; Element b = (Element) genB;
if (!(summand && b.summand)) { if (!(isSummand() && b.isSummand())) {
throw new ArithmeticException("Not a valid summand"); throw new ArithmeticException("Not a valid summand");
} }
@ -493,7 +540,8 @@ public abstract class IntegerPolynomial implements IntegerFieldModuloP {
newLimbs[i] = limbs[i] + b.limbs[i]; 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 @Override
@ -504,7 +552,7 @@ public abstract class IntegerPolynomial implements IntegerFieldModuloP {
newLimbs[i] = -limbs[i]; newLimbs[i] = -limbs[i];
} }
ImmutableElement result = new ImmutableElement(newLimbs, summand); ImmutableElement result = new ImmutableElement(newLimbs, numAdds);
return result; return result;
} }
@ -524,43 +572,52 @@ public abstract class IntegerPolynomial implements IntegerFieldModuloP {
long[] newLimbs = new long[limbs.length]; long[] newLimbs = new long[limbs.length];
mult(limbs, b.limbs, newLimbs); mult(limbs, b.limbs, newLimbs);
return new ImmutableElement(newLimbs, true); return new ImmutableElement(newLimbs, 0);
} }
@Override @Override
public ImmutableElement square() { public ImmutableElement square() {
long[] newLimbs = new long[limbs.length]; long[] newLimbs = new long[limbs.length];
IntegerPolynomial.this.square(limbs, newLimbs); IntegerPolynomial.this.square(limbs, newLimbs);
return new ImmutableElement(newLimbs, true); return new ImmutableElement(newLimbs, 0);
} }
public void addModPowerTwo(IntegerModuloP arg, byte[] result) { public void addModPowerTwo(IntegerModuloP arg, byte[] result) {
Element other = (Element) arg; Element other = (Element) arg;
if (!(summand && other.summand)) { if (!(isSummand() && other.isSummand())) {
throw new ArithmeticException("Not a valid summand"); throw new ArithmeticException("Not a valid summand");
} }
addLimbsModPowerTwo(limbs, other.limbs, result); addLimbsModPowerTwo(limbs, other.limbs, result);
} }
public void asByteArray(byte[] result) { public void asByteArray(byte[] result) {
if (!summand) { if (!isSummand()) {
throw new ArithmeticException("Not a valid summand"); throw new ArithmeticException("Not a valid summand");
} }
limbsToByteArray(limbs, result); limbsToByteArray(limbs, result);
} }
} }
private class MutableElement extends Element protected class MutableElement extends Element
implements MutableIntegerModuloP { implements MutableIntegerModuloP {
protected MutableElement(long[] limbs, boolean summand) { protected MutableElement(long[] limbs, int numAdds) {
super(limbs, summand); super(limbs, numAdds);
} }
@Override @Override
public ImmutableElement fixed() { 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 @Override
@ -569,9 +626,9 @@ public abstract class IntegerPolynomial implements IntegerFieldModuloP {
MutableElement other = (MutableElement) b; MutableElement other = (MutableElement) b;
conditionalSwap(swap, limbs, other.limbs); conditionalSwap(swap, limbs, other.limbs);
boolean summandTemp = summand; int numAddsTemp = numAdds;
summand = other.summand; numAdds = other.numAdds;
other.summand = summandTemp; other.numAdds = numAddsTemp;
} }
@ -580,7 +637,7 @@ public abstract class IntegerPolynomial implements IntegerFieldModuloP {
Element other = (Element) v; Element other = (Element) v;
System.arraycopy(other.limbs, 0, limbs, 0, other.limbs.length); System.arraycopy(other.limbs, 0, limbs, 0, other.limbs.length);
summand = other.summand; numAdds = other.numAdds;
return this; return this;
} }
@ -589,7 +646,7 @@ public abstract class IntegerPolynomial implements IntegerFieldModuloP {
int length, byte highByte) { int length, byte highByte) {
encode(arr, offset, length, highByte, limbs); encode(arr, offset, length, highByte, limbs);
summand = true; this.numAdds = 0;
return this; return this;
} }
@ -599,7 +656,7 @@ public abstract class IntegerPolynomial implements IntegerFieldModuloP {
byte highByte) { byte highByte) {
encode(buf, length, highByte, limbs); encode(buf, length, highByte, limbs);
summand = true; numAdds = 0;
return this; return this;
} }
@ -608,15 +665,15 @@ public abstract class IntegerPolynomial implements IntegerFieldModuloP {
public MutableElement setProduct(IntegerModuloP genB) { public MutableElement setProduct(IntegerModuloP genB) {
Element b = (Element) genB; Element b = (Element) genB;
mult(limbs, b.limbs, limbs); mult(limbs, b.limbs, limbs);
summand = true; numAdds = 0;
return this; return this;
} }
@Override @Override
public MutableElement setProduct(SmallValue v) { public MutableElement setProduct(SmallValue v) {
int value = ((Limb) v).value; int value = ((Limb) v).value;
multByInt(limbs, value, limbs); multByInt(limbs, value);
summand = true; numAdds = 0;
return this; return this;
} }
@ -624,7 +681,7 @@ public abstract class IntegerPolynomial implements IntegerFieldModuloP {
public MutableElement setSum(IntegerModuloP genB) { public MutableElement setSum(IntegerModuloP genB) {
Element b = (Element) genB; Element b = (Element) genB;
if (!(summand && b.summand)) { if (!(isSummand() && b.isSummand())) {
throw new ArithmeticException("Not a valid summand"); throw new ArithmeticException("Not a valid summand");
} }
@ -632,7 +689,7 @@ public abstract class IntegerPolynomial implements IntegerFieldModuloP {
limbs[i] = limbs[i] + b.limbs[i]; limbs[i] = limbs[i] + b.limbs[i];
} }
summand = false; numAdds = Math.max(numAdds, b.numAdds) + 1;
return this; return this;
} }
@ -640,7 +697,7 @@ public abstract class IntegerPolynomial implements IntegerFieldModuloP {
public MutableElement setDifference(IntegerModuloP genB) { public MutableElement setDifference(IntegerModuloP genB) {
Element b = (Element) genB; Element b = (Element) genB;
if (!(summand && b.summand)) { if (!(isSummand() && b.isSummand())) {
throw new ArithmeticException("Not a valid summand"); throw new ArithmeticException("Not a valid summand");
} }
@ -648,16 +705,33 @@ public abstract class IntegerPolynomial implements IntegerFieldModuloP {
limbs[i] = limbs[i] - b.limbs[i]; limbs[i] = limbs[i] - b.limbs[i];
} }
numAdds = Math.max(numAdds, b.numAdds) + 1;
return this; return this;
} }
@Override @Override
public MutableElement setSquare() { public MutableElement setSquare() {
IntegerPolynomial.this.square(limbs, limbs); IntegerPolynomial.this.square(limbs, limbs);
summand = true; numAdds = 0;
return this; 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 { class ImmutableElement extends Element implements ImmutableIntegerModuloP {
@ -670,8 +744,8 @@ public abstract class IntegerPolynomial implements IntegerFieldModuloP {
super(v); super(v);
} }
protected ImmutableElement(long[] limbs, boolean summand) { protected ImmutableElement(long[] limbs, int numAdds) {
super(limbs, summand); super(limbs, numAdds);
} }
@Override @Override

View File

@ -45,7 +45,7 @@ public class IntegerPolynomial1305 extends IntegerPolynomial {
= TWO.pow(POWER).subtract(BigInteger.valueOf(SUBTRAHEND)); = TWO.pow(POWER).subtract(BigInteger.valueOf(SUBTRAHEND));
public IntegerPolynomial1305() { 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) { protected void mult(long[] a, long[] b, long[] r) {
@ -96,15 +96,6 @@ public class IntegerPolynomial1305 extends IntegerPolynomial {
carry(r); 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 @Override
protected void square(long[] a, long[] r) { protected void square(long[] a, long[] r) {
// Use grade-school multiplication with a simple squaring optimization. // Use grade-school multiplication with a simple squaring optimization.
@ -199,7 +190,12 @@ public class IntegerPolynomial1305 extends IntegerPolynomial {
return x >> BITS_PER_LIMB; return x >> BITS_PER_LIMB;
} }
@Override
protected void postEncodeCarry(long[] v) {
// not needed because carry is unsigned
}
@Override
protected void reduce(long[] limbs) { protected void reduce(long[] limbs) {
long carry3 = carryOut(limbs, 3); long carry3 = carryOut(limbs, 3);
long new4 = carry3 + limbs[4]; long new4 = carry3 + limbs[4];

View File

@ -48,7 +48,7 @@ public class IntegerPolynomial25519 extends IntegerPolynomial {
private static final int RIGHT_BIT_OFFSET = BITS_PER_LIMB - BIT_OFFSET; private static final int RIGHT_BIT_OFFSET = BITS_PER_LIMB - BIT_OFFSET;
public IntegerPolynomial25519() { public IntegerPolynomial25519() {
super(BITS_PER_LIMB, NUM_LIMBS, MODULUS); super(BITS_PER_LIMB, NUM_LIMBS, 1, MODULUS);
} }
@Override @Override
@ -59,6 +59,26 @@ public class IntegerPolynomial25519 extends IntegerPolynomial {
limbs[0] += reducedValue * SUBTRAHEND; limbs[0] += reducedValue * SUBTRAHEND;
} }
@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 @Override
protected void mult(long[] a, long[] b, long[] r) { protected void mult(long[] a, long[] b, long[] r) {
@ -153,28 +173,6 @@ public class IntegerPolynomial25519 extends IntegerPolynomial {
carry(r, 0, 9); 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 @Override
protected void square(long[] a, long[] r) { protected void square(long[] a, long[] r) {

View File

@ -42,7 +42,7 @@ public class IntegerPolynomial448 extends IntegerPolynomial {
.subtract(BigInteger.valueOf(1)); .subtract(BigInteger.valueOf(1));
public IntegerPolynomial448() { 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) { private void modReduceIn(long[] limbs, int index, long x) {
@ -57,6 +57,25 @@ public class IntegerPolynomial448 extends IntegerPolynomial {
modReduceIn(limbs, numLimbs, carry); modReduceIn(limbs, numLimbs, carry);
} }
@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 @Override
protected void mult(long[] a, long[] b, long[] r) { protected void mult(long[] a, long[] b, long[] r) {
@ -176,27 +195,6 @@ public class IntegerPolynomial448 extends IntegerPolynomial {
carry(r, 0, 15); 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 @Override
protected void square(long[] a, long[] r) { protected void square(long[] a, long[] r) {

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,28 @@
/*
* 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.
*/

View File

@ -0,0 +1,103 @@
/*
* 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.
*/
package sun.security.validator;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.Security;
import java.security.cert.X509Certificate;
import java.util.EnumSet;
import sun.security.util.Debug;
/**
* Policies for distrusting a certificate authority (CA). See the
* jdk.security.caDistrustPolicies security property for more information.
*/
enum CADistrustPolicy {
/**
* Distrust TLS Server certificates anchored by a Symantec root CA and
* issued after April 16, 2019. If enabled, this policy is currently
* enforced by the PKIX and SunX509 TrustManager implementations of the
* SunJSSE provider implementation.
*/
SYMANTEC_TLS {
void checkDistrust(String variant, X509Certificate anchor,
X509Certificate ee) throws ValidatorException {
if (!variant.equals(Validator.VAR_TLS_SERVER)) {
return;
}
SymantecTLSPolicy.checkDistrust(anchor, ee);
}
};
/**
* Checks if the end-entity certificate is distrusted.
*
* @param variant the type of certificate being checked
* @param anchor the trust anchor certificate
* @param ee the end-entity certificate to check
* @throws ValidatorException if the end-entity certificate is distrusted
*/
abstract void checkDistrust(String variant,
X509Certificate anchor,
X509Certificate ee) throws ValidatorException;
// The policies set in the jdk.security.caDistrustPolicies property.
static final EnumSet<CADistrustPolicy> POLICIES = parseProperty();
private static EnumSet<CADistrustPolicy> parseProperty() {
String property = AccessController.doPrivileged(
new PrivilegedAction<>() {
@Override
public String run() {
return Security.getProperty(
"jdk.security.caDistrustPolicies");
}
});
EnumSet<CADistrustPolicy> set = EnumSet.noneOf(CADistrustPolicy.class);
// if property is null or empty, the restrictions are not enforced
if (property == null || property.isEmpty()) {
return set;
}
String[] policies = property.split(",");
for (String policy : policies) {
policy = policy.trim();
try {
CADistrustPolicy caPolicy =
Enum.valueOf(CADistrustPolicy.class, policy);
set.add(caPolicy);
} catch (IllegalArgumentException iae) {
// ignore unknown values but log it
Debug debug = Debug.getInstance("certpath");
if (debug != null) {
debug.println("Unknown value for the " +
"jdk.security.caDistrustPolicies property: "
+ policy);
}
}
}
return set;
}
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -133,7 +133,9 @@ class EndEntityChecker {
} }
void check(X509Certificate cert, Object parameter, void check(X509Certificate cert, Object parameter,
boolean checkUnresolvedCritExts) throws CertificateException { boolean checkUnresolvedCritExts, X509Certificate anchor)
throws CertificateException {
if (variant.equals(Validator.VAR_GENERIC)) { if (variant.equals(Validator.VAR_GENERIC)) {
return; // no checks return; // no checks
} }
@ -159,6 +161,12 @@ class EndEntityChecker {
if (checkUnresolvedCritExts) { if (checkUnresolvedCritExts) {
checkRemainingExtensions(exts); checkRemainingExtensions(exts);
} }
// check if certificate should be distrusted according to policies
// set in the jdk.security.caDistrustPolicies security property
for (CADistrustPolicy policy : CADistrustPolicy.POLICIES) {
policy.checkDistrust(variant, anchor, cert);
}
} }
/** /**

View File

@ -0,0 +1,157 @@
/*
* 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.
*/
package sun.security.validator;
import java.security.cert.X509Certificate;
import java.time.LocalDate;
import java.time.Month;
import java.time.ZoneOffset;
import java.util.Date;
import java.util.Set;
import sun.security.x509.X509CertImpl;
/**
* This class checks if Symantec issued TLS Server certificates should be
* restricted.
*/
final class SymantecTLSPolicy {
// SHA-256 certificate fingerprints of distrusted roots
private static final Set<String> FINGERPRINTS = Set.of(
// cacerts alias: geotrustglobalca
// DN: CN=GeoTrust Global CA, O=GeoTrust Inc., C=US
"FF856A2D251DCD88D36656F450126798CFABAADE40799C722DE4D2B5DB36A73A",
// cacerts alias: geotrustprimaryca
// DN: CN=GeoTrust Primary Certification Authority,
// O=GeoTrust Inc., C=US
"37D51006C512EAAB626421F1EC8C92013FC5F82AE98EE533EB4619B8DEB4D06C",
// cacerts alias: geotrustprimarycag2
// DN: CN=GeoTrust Primary Certification Authority - G2,
// OU=(c) 2007 GeoTrust Inc. - For authorized use only,
// O=GeoTrust Inc., C=US
"5EDB7AC43B82A06A8761E8D7BE4979EBF2611F7DD79BF91C1C6B566A219ED766",
// cacerts alias: geotrustprimarycag3
// DN: CN=GeoTrust Primary Certification Authority - G3,
// OU=(c) 2008 GeoTrust Inc. - For authorized use only,
// O=GeoTrust Inc., C=US
"B478B812250DF878635C2AA7EC7D155EAA625EE82916E2CD294361886CD1FBD4",
// cacerts alias: geotrustuniversalca
// DN: CN=GeoTrust Universal CA, O=GeoTrust Inc., C=US
"A0459B9F63B22559F5FA5D4C6DB3F9F72FF19342033578F073BF1D1B46CBB912",
// cacerts alias: thawteprimaryrootca
// DN: CN=thawte Primary Root CA,
// OU="(c) 2006 thawte, Inc. - For authorized use only",
// OU=Certification Services Division, O="thawte, Inc.", C=US
"8D722F81A9C113C0791DF136A2966DB26C950A971DB46B4199F4EA54B78BFB9F",
// cacerts alias: thawteprimaryrootcag2
// DN: CN=thawte Primary Root CA - G2,
// OU="(c) 2007 thawte, Inc. - For authorized use only",
// O="thawte, Inc.", C=US
"A4310D50AF18A6447190372A86AFAF8B951FFB431D837F1E5688B45971ED1557",
// cacerts alias: thawteprimaryrootcag3
// DN: CN=thawte Primary Root CA - G3,
// OU="(c) 2008 thawte, Inc. - For authorized use only",
// OU=Certification Services Division, O="thawte, Inc.", C=US
"4B03F45807AD70F21BFC2CAE71C9FDE4604C064CF5FFB686BAE5DBAAD7FDD34C",
// cacerts alias: thawtepremiumserverca
// DN: EMAILADDRESS=premium-server@thawte.com,
// CN=Thawte Premium Server CA, OU=Certification Services Division,
// O=Thawte Consulting cc, L=Cape Town, ST=Western Cape, C=ZA
"3F9F27D583204B9E09C8A3D2066C4B57D3A2479C3693650880505698105DBCE9",
// cacerts alias: verisignclass2g2ca
// DN: OU=VeriSign Trust Network,
// OU="(c) 1998 VeriSign, Inc. - For authorized use only",
// OU=Class 2 Public Primary Certification Authority - G2,
// O="VeriSign, Inc.", C=US
"3A43E220FE7F3EA9653D1E21742EAC2B75C20FD8980305BC502CAF8C2D9B41A1",
// cacerts alias: verisignclass3ca
// DN: OU=Class 3 Public Primary Certification Authority,
// O="VeriSign, Inc.", C=US
"A4B6B3996FC2F306B3FD8681BD63413D8C5009CC4FA329C2CCF0E2FA1B140305",
// cacerts alias: verisignclass3g2ca
// DN: OU=VeriSign Trust Network,
// OU="(c) 1998 VeriSign, Inc. - For authorized use only",
// OU=Class 3 Public Primary Certification Authority - G2,
// O="VeriSign, Inc.", C=US
"83CE3C1229688A593D485F81973C0F9195431EDA37CC5E36430E79C7A888638B",
// cacerts alias: verisignclass3g3ca
// DN: CN=VeriSign Class 3 Public Primary Certification Authority - G3,
// OU="(c) 1999 VeriSign, Inc. - For authorized use only",
// OU=VeriSign Trust Network, O="VeriSign, Inc.", C=US
"EB04CF5EB1F39AFA762F2BB120F296CBA520C1B97DB1589565B81CB9A17B7244",
// cacerts alias: verisignclass3g4ca
// DN: CN=VeriSign Class 3 Public Primary Certification Authority - G4,
// OU="(c) 2007 VeriSign, Inc. - For authorized use only",
// OU=VeriSign Trust Network, O="VeriSign, Inc.", C=US
"69DDD7EA90BB57C93E135DC85EA6FCD5480B603239BDC454FC758B2A26CF7F79",
// cacerts alias: verisignclass3g5ca
// DN: CN=VeriSign Class 3 Public Primary Certification Authority - G5,
// OU="(c) 2006 VeriSign, Inc. - For authorized use only",
// OU=VeriSign Trust Network, O="VeriSign, Inc.", C=US
"9ACFAB7E43C8D880D06B262A94DEEEE4B4659989C3D0CAF19BAF6405E41AB7DF",
// cacerts alias: verisignuniversalrootca
// DN: CN=VeriSign Universal Root Certification Authority,
// OU="(c) 2008 VeriSign, Inc. - For authorized use only",
// OU=VeriSign Trust Network, O="VeriSign, Inc.", C=US
"2399561127A57125DE8CEFEA610DDF2FA078B5C8067F4E828290BFB860E84B3C"
);
// Any TLS Server certificate that is anchored by one of the Symantec
// roots above and is issued after this date will be distrusted.
private static final LocalDate APRIL_16_2019 =
LocalDate.of(2019, Month.APRIL, 16);
/**
* This method assumes the eeCert is a TLS Server Cert and chains back to
* the anchor.
*
* @param anchor the trust anchor certificate
* @param eeCert the certificate to check
* @throws ValidatorException if the certificate is distrusted
*/
static void checkDistrust(X509Certificate anchor,
X509Certificate eeCert)
throws ValidatorException {
String fp = (anchor instanceof X509CertImpl)
? ((X509CertImpl)anchor).getFingerprint("SHA-256")
: X509CertImpl.getFingerprint("SHA-256", anchor);
if (FINGERPRINTS.contains(fp)) {
// reject if certificate is issued after April 16, 2019
Date notBefore = eeCert.getNotBefore();
LocalDate ldNotBefore = LocalDate.ofInstant(notBefore.toInstant(),
ZoneOffset.UTC);
if (ldNotBefore.isAfter(APRIL_16_2019)) {
throw new ValidatorException
("TLS Server certificate issued after " + APRIL_16_2019 +
" and anchored by a distrusted legacy Symantec root CA: "
+ anchor.getSubjectX500Principal(),
ValidatorException.T_UNTRUSTED_CERT, anchor);
}
}
}
private SymantecTLSPolicy() {}
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -275,7 +275,8 @@ public abstract class Validator {
boolean checkUnresolvedCritExts = boolean checkUnresolvedCritExts =
(type == TYPE_PKIX) ? false : true; (type == TYPE_PKIX) ? false : true;
endEntityChecker.check(chain[0], parameter, endEntityChecker.check(chain[0], parameter,
checkUnresolvedCritExts); checkUnresolvedCritExts,
chain[chain.length-1]);
} }
return chain; return chain;

View File

@ -1088,3 +1088,26 @@ jceks.key.serialFilter = java.base/java.lang.Enum;java.base/java.security.KeyRep
# the same name, with the same syntax and possible values. # the same name, with the same syntax and possible values.
# #
#jdk.includeInExceptions=hostInfo,jar #jdk.includeInExceptions=hostInfo,jar
#
# Policies for distrusting Certificate Authorities (CAs).
#
# This is a comma separated value of one or more case-sensitive strings, each
# of which represents a policy for determining if a CA should be distrusted.
# The supported values are:
#
# SYMANTEC_TLS : Distrust TLS Server certificates anchored by
# a Symantec root CA and issued after April 16, 2019.
#
# Leading and trailing whitespace surrounding each value are ignored.
# Unknown values are ignored. If the property is commented out or set to the
# empty String, no policies are enforced.
#
# Note: This property is currently used by the JDK Reference implementation.
# It is not guaranteed to be supported by other SE implementations. Also, this
# property does not override other security properties which can restrict
# certificates such as jdk.tls.disabledAlgorithms or
# jdk.certpath.disabledAlgorithms; those restrictions are still enforced even
# if this property is not enabled.
#
jdk.security.caDistrustPolicies=SYMANTEC_TLS

View File

@ -412,7 +412,7 @@ final class ProcessImpl extends Process {
new BufferedOutputStream( new BufferedOutputStream(
new FileOutputStream(newFileDescriptor(fds[0]))); new FileOutputStream(newFileDescriptor(fds[0])));
stdout = (fds[1] == -1) ? stdout = (fds[1] == -1 || forceNullOutputStream) ?
ProcessBuilder.NullInputStream.INSTANCE : ProcessBuilder.NullInputStream.INSTANCE :
new BufferedInputStream( new BufferedInputStream(
stdout_inner_stream = stdout_inner_stream =
@ -446,7 +446,7 @@ final class ProcessImpl extends Process {
ProcessBuilder.NullOutputStream.INSTANCE : ProcessBuilder.NullOutputStream.INSTANCE :
new ProcessPipeOutputStream(fds[0]); new ProcessPipeOutputStream(fds[0]);
stdout = (fds[1] == -1) ? stdout = (fds[1] == -1 || forceNullOutputStream) ?
ProcessBuilder.NullInputStream.INSTANCE : ProcessBuilder.NullInputStream.INSTANCE :
new DeferredCloseProcessPipeInputStream(fds[1]); new DeferredCloseProcessPipeInputStream(fds[1]);

View File

@ -333,8 +333,7 @@ final class AOTCompiledClass {
AOTKlassData data = klassData.get(name); AOTKlassData data = klassData.get(name);
if (data != null) { if (data != null) {
HotSpotResolvedObjectType oldType = data.getType(); HotSpotResolvedObjectType oldType = data.getType();
assert oldType == type : "duplicate classes for name " + type.getName() + ", fingerprints old: " + oldType.getFingerprint() + ", new: " + type.getFingerprint() + assert oldType.equals(type) : "duplicate classes for name " + type.getName();
", klass pointers old: " + oldType.klass() + ", new: " + type.klass();
} }
return data; return data;
} }

View File

@ -1121,7 +1121,7 @@ public class Attr extends JCTree.Visitor {
public void visitVarDef(JCVariableDecl tree) { public void visitVarDef(JCVariableDecl tree) {
// Local variables have not been entered yet, so we need to do it now: // Local variables have not been entered yet, so we need to do it now:
if (env.info.scope.owner.kind == MTH) { if (env.info.scope.owner.kind == MTH || env.info.scope.owner.kind == VAR) {
if (tree.sym != null) { if (tree.sym != null) {
// parameters have already been entered // parameters have already been entered
env.info.scope.enter(tree.sym); env.info.scope.enter(tree.sym);

View File

@ -1633,7 +1633,7 @@ public class Flow {
protected boolean trackable(VarSymbol sym) { protected boolean trackable(VarSymbol sym) {
return return
sym.pos >= startPos && sym.pos >= startPos &&
((sym.owner.kind == MTH || ((sym.owner.kind == MTH || sym.owner.kind == VAR ||
isFinalUninitializedField(sym))); isFinalUninitializedField(sym)));
} }
@ -2009,7 +2009,7 @@ public class Flow {
lint = lint.augment(tree.sym); lint = lint.augment(tree.sym);
try{ try{
boolean track = trackable(tree.sym); boolean track = trackable(tree.sym);
if (track && tree.sym.owner.kind == MTH) { if (track && (tree.sym.owner.kind == MTH || tree.sym.owner.kind == VAR)) {
newVar(tree); newVar(tree);
} }
if (tree.init != null) { if (tree.init != null) {

View File

@ -25,8 +25,6 @@
package com.sun.tools.javac.jvm; package com.sun.tools.javac.jvm;
import java.util.function.BiConsumer;
import com.sun.tools.javac.tree.TreeInfo.PosKind; import com.sun.tools.javac.tree.TreeInfo.PosKind;
import com.sun.tools.javac.util.*; import com.sun.tools.javac.util.*;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
@ -166,6 +164,7 @@ public class Gen extends JCTree.Visitor {
boolean inCondSwitchExpression; boolean inCondSwitchExpression;
Chain switchExpressionTrueChain; Chain switchExpressionTrueChain;
Chain switchExpressionFalseChain; Chain switchExpressionFalseChain;
List<LocalItem> stackBeforeSwitchExpression;
/** Generate code to load an integer constant. /** Generate code to load an integer constant.
* @param n The integer to be loaded. * @param n The integer to be loaded.
@ -1178,13 +1177,59 @@ public class Gen extends JCTree.Visitor {
} }
private void doHandleSwitchExpression(JCSwitchExpression tree) { private void doHandleSwitchExpression(JCSwitchExpression tree) {
int prevLetExprStart = code.setLetExprStackPos(code.state.stacksize); List<LocalItem> prevStackBeforeSwitchExpression = stackBeforeSwitchExpression;
int limit = code.nextreg;
try { try {
handleSwitch(tree, tree.selector, tree.cases); stackBeforeSwitchExpression = List.nil();
if (hasTry(tree)) {
//if the switch expression contains try-catch, the catch handlers need to have
//an empty stack. So stash whole stack to local variables, and restore it before
//breaks:
while (code.state.stacksize > 0) {
Type type = code.state.peek();
Name varName = names.fromString(target.syntheticNameChar() +
"stack" +
target.syntheticNameChar() +
tree.pos +
target.syntheticNameChar() +
code.state.stacksize);
VarSymbol var = new VarSymbol(Flags.SYNTHETIC, varName, type,
this.env.enclMethod.sym);
LocalItem item = items.new LocalItem(type, code.newLocal(var));
stackBeforeSwitchExpression = stackBeforeSwitchExpression.prepend(item);
item.store();
}
}
int prevLetExprStart = code.setLetExprStackPos(code.state.stacksize);
try {
handleSwitch(tree, tree.selector, tree.cases);
} finally {
code.setLetExprStackPos(prevLetExprStart);
}
} finally { } finally {
code.setLetExprStackPos(prevLetExprStart); stackBeforeSwitchExpression = prevStackBeforeSwitchExpression;
code.endScopes(limit);
} }
} }
//where:
private boolean hasTry(JCSwitchExpression tree) {
boolean[] hasTry = new boolean[1];
new TreeScanner() {
@Override
public void visitTry(JCTry tree) {
hasTry[0] = true;
}
@Override
public void visitClassDef(JCClassDecl tree) {
}
@Override
public void visitLambda(JCLambda tree) {
}
}.scan(tree);
return hasTry[0];
}
private void handleSwitch(JCTree swtch, JCExpression selector, List<JCCase> cases) { private void handleSwitch(JCTree swtch, JCExpression selector, List<JCCase> cases) {
int limit = code.nextreg; int limit = code.nextreg;
@ -1659,14 +1704,17 @@ public class Gen extends JCTree.Visitor {
} }
public void visitBreak(JCBreak tree) { public void visitBreak(JCBreak tree) {
int tmpPos = code.pendingStatPos;
Assert.check(code.isStatementStart()); Assert.check(code.isStatementStart());
Env<GenContext> targetEnv = unwind(tree.target, env); final Env<GenContext> targetEnv;
code.pendingStatPos = tmpPos;
if (tree.isValueBreak()) { if (tree.isValueBreak()) {
//restore stack as it was before the switch expression:
for (LocalItem li : stackBeforeSwitchExpression) {
li.load();
}
if (inCondSwitchExpression) { if (inCondSwitchExpression) {
CondItem value = genCond(tree.value, CRT_FLOW_TARGET); CondItem value = genCond(tree.value, CRT_FLOW_TARGET);
Chain falseJumps = value.jumpFalse(); Chain falseJumps = value.jumpFalse();
targetEnv = unwindBreak(tree);
code.resolve(value.trueJumps); code.resolve(value.trueJumps);
Chain trueJumps = code.branch(goto_); Chain trueJumps = code.branch(goto_);
if (switchExpressionTrueChain == null) { if (switchExpressionTrueChain == null) {
@ -1684,13 +1732,22 @@ public class Gen extends JCTree.Visitor {
} else { } else {
genExpr(tree.value, pt).load(); genExpr(tree.value, pt).load();
code.state.forceStackTop(tree.target.type); code.state.forceStackTop(tree.target.type);
targetEnv = unwindBreak(tree);
targetEnv.info.addExit(code.branch(goto_)); targetEnv.info.addExit(code.branch(goto_));
} }
} else { } else {
targetEnv = unwindBreak(tree);
targetEnv.info.addExit(code.branch(goto_)); targetEnv.info.addExit(code.branch(goto_));
} }
endFinalizerGaps(env, targetEnv); endFinalizerGaps(env, targetEnv);
} }
//where:
private Env<GenContext> unwindBreak(JCBreak tree) {
int tmpPos = code.pendingStatPos;
Env<GenContext> targetEnv = unwind(tree.target, env);
code.pendingStatPos = tmpPos;
return targetEnv;
}
public void visitContinue(JCContinue tree) { public void visitContinue(JCContinue tree) {
int tmpPos = code.pendingStatPos; int tmpPos = code.pendingStatPos;
@ -2138,7 +2195,7 @@ public class Gen extends JCTree.Visitor {
res = items.makeMemberItem(sym, true); res = items.makeMemberItem(sym, true);
} }
result = res; result = res;
} else if (sym.kind == VAR && sym.owner.kind == MTH) { } else if (sym.kind == VAR && (sym.owner.kind == MTH || sym.owner.kind == VAR)) {
result = items.makeLocalItem((VarSymbol)sym); result = items.makeLocalItem((VarSymbol)sym);
} else if (isInvokeDynamic(sym)) { } else if (isInvokeDynamic(sym)) {
result = items.makeDynamicItem(sym); result = items.makeDynamicItem(sym);

View File

@ -25,14 +25,19 @@
package sun.security.ec; package sun.security.ec;
import java.math.*;
import java.security.*; import java.security.*;
import java.security.interfaces.*; import java.security.interfaces.*;
import java.security.spec.*; import java.security.spec.*;
import java.util.Optional;
import javax.crypto.*; import javax.crypto.*;
import javax.crypto.spec.*; import javax.crypto.spec.*;
import sun.security.util.ArrayUtil;
import sun.security.util.ECUtil; import sun.security.util.ECUtil;
import sun.security.util.math.*;
import sun.security.ec.point.*;
/** /**
* KeyAgreement implementation for ECDH. * KeyAgreement implementation for ECDH.
@ -44,8 +49,8 @@ public final class ECDHKeyAgreement extends KeyAgreementSpi {
// private key, if initialized // private key, if initialized
private ECPrivateKey privateKey; private ECPrivateKey privateKey;
// encoded public point, non-null between doPhase() & generateSecret() only // public key, non-null between doPhase() & generateSecret() only
private byte[] publicValue; private ECPublicKey publicKey;
// length of the secret to be derived // length of the secret to be derived
private int secretLen; private int secretLen;
@ -65,7 +70,7 @@ public final class ECDHKeyAgreement extends KeyAgreementSpi {
("Key must be instance of PrivateKey"); ("Key must be instance of PrivateKey");
} }
privateKey = (ECPrivateKey) ECKeyFactory.toECKey(key); privateKey = (ECPrivateKey) ECKeyFactory.toECKey(key);
publicValue = null; publicKey = null;
} }
// see JCE spec // see JCE spec
@ -87,7 +92,7 @@ public final class ECDHKeyAgreement extends KeyAgreementSpi {
if (privateKey == null) { if (privateKey == null) {
throw new IllegalStateException("Not initialized"); throw new IllegalStateException("Not initialized");
} }
if (publicValue != null) { if (publicKey != null) {
throw new IllegalStateException("Phase already executed"); throw new IllegalStateException("Phase already executed");
} }
if (!lastPhase) { if (!lastPhase) {
@ -99,42 +104,74 @@ public final class ECDHKeyAgreement extends KeyAgreementSpi {
("Key must be a PublicKey with algorithm EC"); ("Key must be a PublicKey with algorithm EC");
} }
ECPublicKey ecKey = (ECPublicKey)key; this.publicKey = (ECPublicKey) key;
ECParameterSpec params = ecKey.getParams();
if (ecKey instanceof ECPublicKeyImpl) { ECParameterSpec params = publicKey.getParams();
publicValue = ((ECPublicKeyImpl)ecKey).getEncodedPublicValue();
} else { // instanceof ECPublicKey
publicValue =
ECUtil.encodePoint(ecKey.getW(), params.getCurve());
}
int keyLenBits = params.getCurve().getField().getFieldSize(); int keyLenBits = params.getCurve().getField().getFieldSize();
secretLen = (keyLenBits + 7) >> 3; secretLen = (keyLenBits + 7) >> 3;
return null; return null;
} }
private static void validateCoordinate(BigInteger c, BigInteger mod) {
if (c.compareTo(BigInteger.ZERO) < 0) {
throw new ProviderException("invalid coordinate");
}
if (c.compareTo(mod) >= 0) {
throw new ProviderException("invalid coordinate");
}
}
/*
* Check whether a public key is valid. Throw ProviderException
* if it is not valid or could not be validated.
*/
private static void validate(ECOperations ops, ECPublicKey key) {
// ensure that integers are in proper range
BigInteger x = key.getW().getAffineX();
BigInteger y = key.getW().getAffineY();
BigInteger p = ops.getField().getSize();
validateCoordinate(x, p);
validateCoordinate(y, p);
// ensure the point is on the curve
EllipticCurve curve = key.getParams().getCurve();
BigInteger rhs = x.modPow(BigInteger.valueOf(3), p).add(curve.getA()
.multiply(x)).add(curve.getB()).mod(p);
BigInteger lhs = y.modPow(BigInteger.valueOf(2), p).mod(p);
if (!rhs.equals(lhs)) {
throw new ProviderException("point is not on curve");
}
// check the order of the point
ImmutableIntegerModuloP xElem = ops.getField().getElement(x);
ImmutableIntegerModuloP yElem = ops.getField().getElement(y);
AffinePoint affP = new AffinePoint(xElem, yElem);
byte[] order = key.getParams().getOrder().toByteArray();
ArrayUtil.reverse(order);
Point product = ops.multiply(affP, order);
if (!ops.isNeutral(product)) {
throw new ProviderException("point has incorrect order");
}
}
// see JCE spec // see JCE spec
@Override @Override
protected byte[] engineGenerateSecret() throws IllegalStateException { protected byte[] engineGenerateSecret() throws IllegalStateException {
if ((privateKey == null) || (publicValue == null)) { if ((privateKey == null) || (publicKey == null)) {
throw new IllegalStateException("Not initialized correctly"); throw new IllegalStateException("Not initialized correctly");
} }
byte[] s = privateKey.getS().toByteArray(); Optional<byte[]> resultOpt = deriveKeyImpl(privateKey, publicKey);
byte[] encodedParams = // DER OID byte[] result = resultOpt.orElseGet(
ECUtil.encodeECParameterSpec(null, privateKey.getParams()); () -> deriveKeyNative(privateKey, publicKey)
);
try { publicKey = null;
return result;
byte[] result = deriveKey(s, publicValue, encodedParams);
publicValue = null;
return result;
} catch (GeneralSecurityException e) {
throw new ProviderException("Could not derive key", e);
}
} }
// see JCE spec // see JCE spec
@ -143,7 +180,8 @@ public final class ECDHKeyAgreement extends KeyAgreementSpi {
offset) throws IllegalStateException, ShortBufferException { offset) throws IllegalStateException, ShortBufferException {
if (offset + secretLen > sharedSecret.length) { if (offset + secretLen > sharedSecret.length) {
throw new ShortBufferException("Need " + secretLen throw new ShortBufferException("Need " + secretLen
+ " bytes, only " + (sharedSecret.length - offset) + " available"); + " bytes, only " + (sharedSecret.length - offset)
+ " available");
} }
byte[] secret = engineGenerateSecret(); byte[] secret = engineGenerateSecret();
System.arraycopy(secret, 0, sharedSecret, offset, secret.length); System.arraycopy(secret, 0, sharedSecret, offset, secret.length);
@ -165,6 +203,78 @@ public final class ECDHKeyAgreement extends KeyAgreementSpi {
return new SecretKeySpec(engineGenerateSecret(), "TlsPremasterSecret"); return new SecretKeySpec(engineGenerateSecret(), "TlsPremasterSecret");
} }
private static
Optional<byte[]> deriveKeyImpl(ECPrivateKey priv, ECPublicKey pubKey) {
ECParameterSpec ecSpec = priv.getParams();
EllipticCurve curve = ecSpec.getCurve();
Optional<ECOperations> opsOpt = ECOperations.forParameters(ecSpec);
if (opsOpt.isEmpty()) {
return Optional.empty();
}
ECOperations ops = opsOpt.get();
if (! (priv instanceof ECPrivateKeyImpl)) {
return Optional.empty();
}
ECPrivateKeyImpl privImpl = (ECPrivateKeyImpl) priv;
byte[] sArr = privImpl.getArrayS();
// to match the native implementation, validate the public key here
// and throw ProviderException if it is invalid
validate(ops, pubKey);
IntegerFieldModuloP field = ops.getField();
// convert s array into field element and multiply by the cofactor
MutableIntegerModuloP scalar = field.getElement(sArr).mutable();
SmallValue cofactor =
field.getSmallValue(priv.getParams().getCofactor());
scalar.setProduct(cofactor);
int keySize = (curve.getField().getFieldSize() + 7) / 8;
byte[] privArr = scalar.asByteArray(keySize);
ImmutableIntegerModuloP x =
field.getElement(pubKey.getW().getAffineX());
ImmutableIntegerModuloP y =
field.getElement(pubKey.getW().getAffineY());
AffinePoint affPub = new AffinePoint(x, y);
Point product = ops.multiply(affPub, privArr);
if (ops.isNeutral(product)) {
throw new ProviderException("Product is zero");
}
AffinePoint affProduct = product.asAffine();
byte[] result = affProduct.getX().asByteArray(keySize);
ArrayUtil.reverse(result);
return Optional.of(result);
}
private static
byte[] deriveKeyNative(ECPrivateKey privateKey, ECPublicKey publicKey) {
ECParameterSpec params = privateKey.getParams();
byte[] s = privateKey.getS().toByteArray();
byte[] encodedParams = // DER OID
ECUtil.encodeECParameterSpec(null, params);
byte[] publicValue;
if (publicKey instanceof ECPublicKeyImpl) {
ECPublicKeyImpl ecPub = (ECPublicKeyImpl) publicKey;
publicValue = ecPub.getEncodedPublicValue();
} else { // instanceof ECPublicKey
publicValue =
ECUtil.encodePoint(publicKey.getW(), params.getCurve());
}
try {
return deriveKey(s, publicValue, encodedParams);
} catch (GeneralSecurityException e) {
throw new ProviderException("Could not derive key", e);
}
}
/** /**
* Generates a secret key using the public and private keys. * Generates a secret key using the public and private keys.
* *

View File

@ -0,0 +1,202 @@
/*
* 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.
*/
package sun.security.ec;
import sun.security.ec.point.*;
import sun.security.util.ArrayUtil;
import sun.security.util.math.*;
import static sun.security.ec.ECOperations.IntermediateValueException;
import java.security.ProviderException;
import java.security.spec.*;
import java.util.Optional;
public class ECDSAOperations {
public static class Seed {
private final byte[] seedValue;
public Seed(byte[] seedValue) {
this.seedValue = seedValue;
}
public byte[] getSeedValue() {
return seedValue;
}
}
public static class Nonce {
private final byte[] nonceValue;
public Nonce(byte[] nonceValue) {
this.nonceValue = nonceValue;
}
public byte[] getNonceValue() {
return nonceValue;
}
}
private final ECOperations ecOps;
private final AffinePoint basePoint;
public ECDSAOperations(ECOperations ecOps, ECPoint basePoint) {
this.ecOps = ecOps;
this.basePoint = toAffinePoint(basePoint, ecOps.getField());
}
public ECOperations getEcOperations() {
return ecOps;
}
public AffinePoint basePointMultiply(byte[] scalar) {
return ecOps.multiply(basePoint, scalar).asAffine();
}
public static AffinePoint toAffinePoint(ECPoint point,
IntegerFieldModuloP field) {
ImmutableIntegerModuloP affineX = field.getElement(point.getAffineX());
ImmutableIntegerModuloP affineY = field.getElement(point.getAffineY());
return new AffinePoint(affineX, affineY);
}
public static
Optional<ECDSAOperations> forParameters(ECParameterSpec ecParams) {
Optional<ECOperations> curveOps =
ECOperations.forParameters(ecParams);
return curveOps.map(
ops -> new ECDSAOperations(ops, ecParams.getGenerator())
);
}
/**
*
* Sign a digest using the provided private key and seed.
* IMPORTANT: The private key is a scalar represented using a
* little-endian byte array. This is backwards from the conventional
* representation in ECDSA. The routines that produce and consume this
* value uses little-endian, so this deviation from convention removes
* the requirement to swap the byte order. The returned signature is in
* the conventional byte order.
*
* @param privateKey the private key scalar as a little-endian byte array
* @param digest the digest to be signed
* @param seed the seed that will be used to produce the nonce. This object
* should contain an array that is at least 64 bits longer than
* the number of bits required to represent the group order.
* @return the ECDSA signature value
* @throws IntermediateValueException if the signature cannot be produced
* due to an unacceptable intermediate or final value. If this
* exception is thrown, then the caller should discard the nonnce and
* try again with an entirely new nonce value.
*/
public byte[] signDigest(byte[] privateKey, byte[] digest, Seed seed)
throws IntermediateValueException {
byte[] nonceArr = ecOps.seedToScalar(seed.getSeedValue());
Nonce nonce = new Nonce(nonceArr);
return signDigest(privateKey, digest, nonce);
}
/**
*
* Sign a digest using the provided private key and nonce.
* IMPORTANT: The private key and nonce are scalars represented by a
* little-endian byte array. This is backwards from the conventional
* representation in ECDSA. The routines that produce and consume these
* values use little-endian, so this deviation from convention removes
* the requirement to swap the byte order. The returned signature is in
* the conventional byte order.
*
* @param privateKey the private key scalar as a little-endian byte array
* @param digest the digest to be signed
* @param nonce the nonce object containing a little-endian scalar value.
* @return the ECDSA signature value
* @throws IntermediateValueException if the signature cannot be produced
* due to an unacceptable intermediate or final value. If this
* exception is thrown, then the caller should discard the nonnce and
* try again with an entirely new nonce value.
*/
public byte[] signDigest(byte[] privateKey, byte[] digest, Nonce nonce)
throws IntermediateValueException {
IntegerFieldModuloP orderField = ecOps.getOrderField();
int orderBits = orderField.getSize().bitLength();
if (orderBits % 8 != 0 && orderBits < digest.length * 8) {
// This implementation does not support truncating digests to
// a length that is not a multiple of 8.
throw new ProviderException("Invalid digest length");
}
byte[] k = nonce.getNonceValue();
// check nonce length
int length = (orderField.getSize().bitLength() + 7) / 8;
if (k.length != length) {
throw new ProviderException("Incorrect nonce length");
}
MutablePoint R = ecOps.multiply(basePoint, k);
IntegerModuloP r = R.asAffine().getX();
// put r into the correct field by fully reducing to an array
byte[] temp = new byte[length];
r.asByteArray(temp);
r = orderField.getElement(temp);
// store r in result
r.asByteArray(temp);
byte[] result = new byte[2 * length];
ArrayUtil.reverse(temp);
System.arraycopy(temp, 0, result, 0, length);
// compare r to 0
if (ECOperations.allZero(temp)) {
throw new IntermediateValueException();
}
IntegerModuloP dU = orderField.getElement(privateKey);
int lengthE = Math.min(length, digest.length);
byte[] E = new byte[lengthE];
System.arraycopy(digest, 0, E, 0, lengthE);
ArrayUtil.reverse(E);
IntegerModuloP e = orderField.getElement(E);
IntegerModuloP kElem = orderField.getElement(k);
IntegerModuloP kInv = kElem.multiplicativeInverse();
MutableIntegerModuloP s = r.mutable();
s.setProduct(dU).setSum(e).setProduct(kInv);
// store s in result
s.asByteArray(temp);
ArrayUtil.reverse(temp);
System.arraycopy(temp, 0, result, length, length);
// compare s to 0
if (ECOperations.allZero(temp)) {
throw new IntermediateValueException();
}
return result;
}
}

View File

@ -32,9 +32,11 @@ import java.math.BigInteger;
import java.security.*; import java.security.*;
import java.security.interfaces.*; import java.security.interfaces.*;
import java.security.spec.*; import java.security.spec.*;
import java.util.Optional;
import sun.security.jca.JCAUtil; import sun.security.jca.JCAUtil;
import sun.security.util.*; import sun.security.util.*;
import static sun.security.ec.ECOperations.IntermediateValueException;
/** /**
* ECDSA signature implementation. This class currently supports the * ECDSA signature implementation. This class currently supports the
@ -147,7 +149,7 @@ abstract class ECDSASignature extends SignatureSpi {
// Stores the precomputed message digest value. // Stores the precomputed message digest value.
@Override @Override
protected void engineUpdate(byte[] b, int off, int len) protected void engineUpdate(byte[] b, int off, int len)
throws SignatureException { throws SignatureException {
if (offset >= precomputedDigest.length) { if (offset >= precomputedDigest.length) {
offset = RAW_ECDSA_MAX + 1; offset = RAW_ECDSA_MAX + 1;
return; return;
@ -172,7 +174,7 @@ abstract class ECDSASignature extends SignatureSpi {
} }
@Override @Override
protected void resetDigest(){ protected void resetDigest() {
offset = 0; offset = 0;
} }
@ -222,14 +224,14 @@ abstract class ECDSASignature extends SignatureSpi {
// Nested class for SHA224withECDSA signatures // Nested class for SHA224withECDSA signatures
public static final class SHA224 extends ECDSASignature { public static final class SHA224 extends ECDSASignature {
public SHA224() { public SHA224() {
super("SHA-224"); super("SHA-224");
} }
} }
// Nested class for SHA224withECDSAinP1363Format signatures // Nested class for SHA224withECDSAinP1363Format signatures
public static final class SHA224inP1363Format extends ECDSASignature { public static final class SHA224inP1363Format extends ECDSASignature {
public SHA224inP1363Format() { public SHA224inP1363Format() {
super("SHA-224", true); super("SHA-224", true);
} }
} }
@ -278,7 +280,7 @@ abstract class ECDSASignature extends SignatureSpi {
// initialize for verification. See JCA doc // initialize for verification. See JCA doc
@Override @Override
protected void engineInitVerify(PublicKey publicKey) protected void engineInitVerify(PublicKey publicKey)
throws InvalidKeyException { throws InvalidKeyException {
this.publicKey = (ECPublicKey) ECKeyFactory.toECKey(publicKey); this.publicKey = (ECPublicKey) ECKeyFactory.toECKey(publicKey);
// Should check that the supplied key is appropriate for signature // Should check that the supplied key is appropriate for signature
@ -290,14 +292,14 @@ abstract class ECDSASignature extends SignatureSpi {
// initialize for signing. See JCA doc // initialize for signing. See JCA doc
@Override @Override
protected void engineInitSign(PrivateKey privateKey) protected void engineInitSign(PrivateKey privateKey)
throws InvalidKeyException { throws InvalidKeyException {
engineInitSign(privateKey, null); engineInitSign(privateKey, null);
} }
// initialize for signing. See JCA doc // initialize for signing. See JCA doc
@Override @Override
protected void engineInitSign(PrivateKey privateKey, SecureRandom random) protected void engineInitSign(PrivateKey privateKey, SecureRandom random)
throws InvalidKeyException { throws InvalidKeyException {
this.privateKey = (ECPrivateKey) ECKeyFactory.toECKey(privateKey); this.privateKey = (ECPrivateKey) ECKeyFactory.toECKey(privateKey);
// Should check that the supplied key is appropriate for signature // Should check that the supplied key is appropriate for signature
@ -337,7 +339,7 @@ abstract class ECDSASignature extends SignatureSpi {
// update the signature with the plaintext data. See JCA doc // update the signature with the plaintext data. See JCA doc
@Override @Override
protected void engineUpdate(byte[] b, int off, int len) protected void engineUpdate(byte[] b, int off, int len)
throws SignatureException { throws SignatureException {
messageDigest.update(b, off, len); messageDigest.update(b, off, len);
needsReset = true; needsReset = true;
} }
@ -354,20 +356,67 @@ abstract class ECDSASignature extends SignatureSpi {
needsReset = true; needsReset = true;
} }
// sign the data and return the signature. See JCA doc private byte[] signDigestImpl(ECDSAOperations ops, int seedBits,
@Override byte[] digest, ECPrivateKeyImpl privImpl, SecureRandom random)
protected byte[] engineSign() throws SignatureException { throws SignatureException {
byte[] seedBytes = new byte[(seedBits + 7) / 8];
byte[] s = privImpl.getArrayS();
// Attempt to create the signature in a loop that uses new random input
// each time. The chance of failure is very small assuming the
// implementation derives the nonce using extra bits
int numAttempts = 128;
for (int i = 0; i < numAttempts; i++) {
random.nextBytes(seedBytes);
ECDSAOperations.Seed seed = new ECDSAOperations.Seed(seedBytes);
try {
return ops.signDigest(s, digest, seed);
} catch (IntermediateValueException ex) {
// try again in the next iteration
}
}
throw new SignatureException("Unable to produce signature after "
+ numAttempts + " attempts");
}
private Optional<byte[]> signDigestImpl(ECPrivateKey privateKey,
byte[] digest, SecureRandom random) throws SignatureException {
if (! (privateKey instanceof ECPrivateKeyImpl)) {
return Optional.empty();
}
ECPrivateKeyImpl privImpl = (ECPrivateKeyImpl) privateKey;
ECParameterSpec params = privateKey.getParams();
// seed is the key size + 64 bits
int seedBits = params.getOrder().bitLength() + 64;
Optional<ECDSAOperations> opsOpt =
ECDSAOperations.forParameters(params);
if (opsOpt.isEmpty()) {
return Optional.empty();
} else {
byte[] sig = signDigestImpl(opsOpt.get(), seedBits, digest,
privImpl, random);
return Optional.of(sig);
}
}
private byte[] signDigestNative(ECPrivateKey privateKey, byte[] digest,
SecureRandom random) throws SignatureException {
byte[] s = privateKey.getS().toByteArray(); byte[] s = privateKey.getS().toByteArray();
ECParameterSpec params = privateKey.getParams(); ECParameterSpec params = privateKey.getParams();
// DER OID // DER OID
byte[] encodedParams = ECUtil.encodeECParameterSpec(null, params); byte[] encodedParams = ECUtil.encodeECParameterSpec(null, params);
int keySize = params.getCurve().getField().getFieldSize(); int keySize = params.getCurve().getField().getFieldSize();
// seed is twice the key size (in bytes) plus 1 // seed is twice the key size (in bytes) plus 1
byte[] seed = new byte[(((keySize + 7) >> 3) + 1) * 2]; byte[] seed = new byte[(((keySize + 7) >> 3) + 1) * 2];
if (random == null) {
random = JCAUtil.getSecureRandom();
}
random.nextBytes(seed); random.nextBytes(seed);
// random bits needed for timing countermeasures // random bits needed for timing countermeasures
@ -375,14 +424,32 @@ abstract class ECDSASignature extends SignatureSpi {
// values must be non-zero to enable countermeasures // values must be non-zero to enable countermeasures
timingArgument |= 1; timingArgument |= 1;
byte[] sig;
try { try {
sig = signDigest(getDigestValue(), s, encodedParams, seed, return signDigest(digest, s, encodedParams, seed,
timingArgument); timingArgument);
} catch (GeneralSecurityException e) { } catch (GeneralSecurityException e) {
throw new SignatureException("Could not sign data", e); throw new SignatureException("Could not sign data", e);
} }
}
// sign the data and return the signature. See JCA doc
@Override
protected byte[] engineSign() throws SignatureException {
if (random == null) {
random = JCAUtil.getSecureRandom();
}
byte[] digest = getDigestValue();
Optional<byte[]> sigOpt = signDigestImpl(privateKey, digest, random);
byte[] sig;
if (sigOpt.isPresent()) {
sig = sigOpt.get();
} else {
sig = signDigestNative(privateKey, digest, random);
}
if (p1363Format) { if (p1363Format) {
return sig; return sig;
} else { } else {
@ -400,7 +467,7 @@ abstract class ECDSASignature extends SignatureSpi {
byte[] encodedParams = ECUtil.encodeECParameterSpec(null, params); byte[] encodedParams = ECUtil.encodeECParameterSpec(null, params);
if (publicKey instanceof ECPublicKeyImpl) { if (publicKey instanceof ECPublicKeyImpl) {
w = ((ECPublicKeyImpl)publicKey).getEncodedPublicValue(); w = ((ECPublicKeyImpl) publicKey).getEncodedPublicValue();
} else { // instanceof ECPublicKey } else { // instanceof ECPublicKey
w = ECUtil.encodePoint(publicKey.getW(), params.getCurve()); w = ECUtil.encodePoint(publicKey.getW(), params.getCurve());
} }
@ -423,13 +490,13 @@ abstract class ECDSASignature extends SignatureSpi {
@Override @Override
@Deprecated @Deprecated
protected void engineSetParameter(String param, Object value) protected void engineSetParameter(String param, Object value)
throws InvalidParameterException { throws InvalidParameterException {
throw new UnsupportedOperationException("setParameter() not supported"); throw new UnsupportedOperationException("setParameter() not supported");
} }
@Override @Override
protected void engineSetParameter(AlgorithmParameterSpec params) protected void engineSetParameter(AlgorithmParameterSpec params)
throws InvalidAlgorithmParameterException { throws InvalidAlgorithmParameterException {
if (params != null) { if (params != null) {
throw new InvalidAlgorithmParameterException("No parameter accepted"); throw new InvalidAlgorithmParameterException("No parameter accepted");
} }
@ -439,7 +506,7 @@ abstract class ECDSASignature extends SignatureSpi {
@Override @Override
@Deprecated @Deprecated
protected Object engineGetParameter(String param) protected Object engineGetParameter(String param)
throws InvalidParameterException { throws InvalidParameterException {
throw new UnsupportedOperationException("getParameter() not supported"); throw new UnsupportedOperationException("getParameter() not supported");
} }
@ -464,7 +531,7 @@ abstract class ECDSASignature extends SignatureSpi {
out.putInteger(r); out.putInteger(r);
out.putInteger(s); out.putInteger(s);
DerValue result = DerValue result =
new DerValue(DerValue.tag_Sequence, out.toByteArray()); new DerValue(DerValue.tag_Sequence, out.toByteArray());
return result.toByteArray(); return result.toByteArray();
@ -497,9 +564,9 @@ abstract class ECDSASignature extends SignatureSpi {
// r and s each occupy half the array // r and s each occupy half the array
byte[] result = new byte[k << 1]; byte[] result = new byte[k << 1];
System.arraycopy(rBytes, 0, result, k - rBytes.length, System.arraycopy(rBytes, 0, result, k - rBytes.length,
rBytes.length); rBytes.length);
System.arraycopy(sBytes, 0, result, result.length - sBytes.length, System.arraycopy(sBytes, 0, result, result.length - sBytes.length,
sBytes.length); sBytes.length);
return result; return result;
} catch (Exception e) { } catch (Exception e) {
@ -539,13 +606,13 @@ abstract class ECDSASignature extends SignatureSpi {
* @return byte[] the signature. * @return byte[] the signature.
*/ */
private static native byte[] signDigest(byte[] digest, byte[] s, private static native byte[] signDigest(byte[] digest, byte[] s,
byte[] encodedParams, byte[] seed, int timing) byte[] encodedParams, byte[] seed, int timing)
throws GeneralSecurityException; throws GeneralSecurityException;
/** /**
* Verifies the signed digest using the public key. * Verifies the signed digest using the public key.
* *
* @param signedDigest the signature to be verified. It is encoded * @param signature the signature to be verified. It is encoded
* as a concatenation of the key's R and S values. * as a concatenation of the key's R and S values.
* @param digest the digest to be used. * @param digest the digest to be used.
* @param w the public key's W point (in uncompressed form). * @param w the public key's W point (in uncompressed form).
@ -554,6 +621,6 @@ abstract class ECDSASignature extends SignatureSpi {
* @return boolean true if the signature is successfully verified. * @return boolean true if the signature is successfully verified.
*/ */
private static native boolean verifySignedDigest(byte[] signature, private static native boolean verifySignedDigest(byte[] signature,
byte[] digest, byte[] w, byte[] encodedParams) byte[] digest, byte[] w, byte[] encodedParams)
throws GeneralSecurityException; throws GeneralSecurityException;
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -33,13 +33,15 @@ import java.security.spec.ECGenParameterSpec;
import java.security.spec.ECParameterSpec; import java.security.spec.ECParameterSpec;
import java.security.spec.ECPoint; import java.security.spec.ECPoint;
import java.security.spec.InvalidParameterSpecException; import java.security.spec.InvalidParameterSpecException;
import java.security.spec.*;
import java.util.Optional;
import sun.security.ec.ECPrivateKeyImpl;
import sun.security.ec.ECPublicKeyImpl;
import sun.security.jca.JCAUtil; import sun.security.jca.JCAUtil;
import sun.security.util.ECParameters;
import sun.security.util.ECUtil; import sun.security.util.ECUtil;
import sun.security.util.math.*;
import sun.security.ec.point.*;
import static sun.security.util.SecurityProviderConstants.DEF_EC_KEY_SIZE; import static sun.security.util.SecurityProviderConstants.DEF_EC_KEY_SIZE;
import static sun.security.ec.ECOperations.IntermediateValueException;
/** /**
* EC keypair generator. * EC keypair generator.
@ -90,14 +92,14 @@ public final class ECKeyPairGenerator extends KeyPairGeneratorSpi {
ECParameterSpec ecSpec = null; ECParameterSpec ecSpec = null;
if (params instanceof ECParameterSpec) { if (params instanceof ECParameterSpec) {
ecSpec = ECUtil.getECParameterSpec(null, ECParameterSpec ecParams = (ECParameterSpec) params;
(ECParameterSpec)params); ecSpec = ECUtil.getECParameterSpec(null, ecParams);
if (ecSpec == null) { if (ecSpec == null) {
throw new InvalidAlgorithmParameterException( throw new InvalidAlgorithmParameterException(
"Unsupported curve: " + params); "Unsupported curve: " + params);
} }
} else if (params instanceof ECGenParameterSpec) { } else if (params instanceof ECGenParameterSpec) {
String name = ((ECGenParameterSpec)params).getName(); String name = ((ECGenParameterSpec) params).getName();
ecSpec = ECUtil.getECParameterSpec(null, name); ecSpec = ECUtil.getECParameterSpec(null, name);
if (ecSpec == null) { if (ecSpec == null) {
throw new InvalidAlgorithmParameterException( throw new InvalidAlgorithmParameterException(
@ -112,8 +114,7 @@ public final class ECKeyPairGenerator extends KeyPairGeneratorSpi {
ensureCurveIsSupported(ecSpec); ensureCurveIsSupported(ecSpec);
this.params = ecSpec; this.params = ecSpec;
this.keySize = this.keySize = ecSpec.getCurve().getField().getFieldSize();
((ECParameterSpec)this.params).getCurve().getField().getFieldSize();
this.random = random; this.random = random;
} }
@ -141,41 +142,99 @@ public final class ECKeyPairGenerator extends KeyPairGeneratorSpi {
@Override @Override
public KeyPair generateKeyPair() { public KeyPair generateKeyPair() {
byte[] encodedParams =
ECUtil.encodeECParameterSpec(null, (ECParameterSpec)params);
// seed is twice the key size (in bytes) plus 1
byte[] seed = new byte[(((keySize + 7) >> 3) + 1) * 2];
if (random == null) { if (random == null) {
random = JCAUtil.getSecureRandom(); random = JCAUtil.getSecureRandom();
} }
random.nextBytes(seed);
try { try {
Optional<KeyPair> kp = generateKeyPairImpl(random);
Object[] keyBytes = generateECKeyPair(keySize, encodedParams, seed); if (kp.isPresent()) {
return kp.get();
// The 'params' object supplied above is equivalent to the native }
// one so there is no need to fetch it. return generateKeyPairNative(random);
// keyBytes[0] is the encoding of the native private key } catch (Exception ex) {
BigInteger s = new BigInteger(1, (byte[])keyBytes[0]); throw new ProviderException(ex);
PrivateKey privateKey =
new ECPrivateKeyImpl(s, (ECParameterSpec)params);
// keyBytes[1] is the encoding of the native public key
ECPoint w = ECUtil.decodePoint((byte[])keyBytes[1],
((ECParameterSpec)params).getCurve());
PublicKey publicKey =
new ECPublicKeyImpl(w, (ECParameterSpec)params);
return new KeyPair(publicKey, privateKey);
} catch (Exception e) {
throw new ProviderException(e);
} }
} }
private byte[] generatePrivateScalar(SecureRandom random,
ECOperations ecOps, int seedSize) {
// Attempt to create the private scalar in a loop that uses new random
// input each time. The chance of failure is very small assuming the
// implementation derives the nonce using extra bits
int numAttempts = 128;
byte[] seedArr = new byte[seedSize];
for (int i = 0; i < numAttempts; i++) {
random.nextBytes(seedArr);
try {
return ecOps.seedToScalar(seedArr);
} catch (IntermediateValueException ex) {
// try again in the next iteration
}
}
throw new ProviderException("Unable to produce private key after "
+ numAttempts + " attempts");
}
private Optional<KeyPair> generateKeyPairImpl(SecureRandom random)
throws InvalidKeyException {
ECParameterSpec ecParams = (ECParameterSpec) params;
Optional<ECOperations> opsOpt = ECOperations.forParameters(ecParams);
if (opsOpt.isEmpty()) {
return Optional.empty();
}
ECOperations ops = opsOpt.get();
IntegerFieldModuloP field = ops.getField();
int numBits = ecParams.getOrder().bitLength();
int seedBits = numBits + 64;
int seedSize = (seedBits + 7) / 8;
byte[] privArr = generatePrivateScalar(random, ops, seedSize);
ECPoint genPoint = ecParams.getGenerator();
ImmutableIntegerModuloP x = field.getElement(genPoint.getAffineX());
ImmutableIntegerModuloP y = field.getElement(genPoint.getAffineY());
AffinePoint affGen = new AffinePoint(x, y);
Point pub = ops.multiply(affGen, privArr);
AffinePoint affPub = pub.asAffine();
PrivateKey privateKey = new ECPrivateKeyImpl(privArr, ecParams);
ECPoint w = new ECPoint(affPub.getX().asBigInteger(),
affPub.getY().asBigInteger());
PublicKey publicKey = new ECPublicKeyImpl(w, ecParams);
return Optional.of(new KeyPair(publicKey, privateKey));
}
private KeyPair generateKeyPairNative(SecureRandom random)
throws Exception {
ECParameterSpec ecParams = (ECParameterSpec) params;
byte[] encodedParams = ECUtil.encodeECParameterSpec(null, ecParams);
// seed is twice the key size (in bytes) plus 1
byte[] seed = new byte[(((keySize + 7) >> 3) + 1) * 2];
random.nextBytes(seed);
Object[] keyBytes = generateECKeyPair(keySize, encodedParams, seed);
// The 'params' object supplied above is equivalent to the native
// one so there is no need to fetch it.
// keyBytes[0] is the encoding of the native private key
BigInteger s = new BigInteger(1, (byte[]) keyBytes[0]);
PrivateKey privateKey = new ECPrivateKeyImpl(s, ecParams);
// keyBytes[1] is the encoding of the native public key
byte[] pubKey = (byte[]) keyBytes[1];
ECPoint w = ECUtil.decodePoint(pubKey, ecParams.getCurve());
PublicKey publicKey = new ECPublicKeyImpl(w, ecParams);
return new KeyPair(publicKey, privateKey);
}
private void checkKeySize(int keySize) throws InvalidParameterException { private void checkKeySize(int keySize) throws InvalidParameterException {
if (keySize < KEY_SIZE_MIN) { if (keySize < KEY_SIZE_MIN) {
throw new InvalidParameterException throw new InvalidParameterException
@ -190,7 +249,9 @@ public final class ECKeyPairGenerator extends KeyPairGeneratorSpi {
/** /**
* Checks whether the curve in the encoded parameters is supported by the * Checks whether the curve in the encoded parameters is supported by the
* native implementation. * native implementation. Some curve operations will be performed by the
* Java implementation, but not all of them. So native support is still
* required for all curves.
* *
* @param encodedParams encoded parameters in the same form accepted * @param encodedParams encoded parameters in the same form accepted
* by generateECKeyPair * by generateECKeyPair

View File

@ -0,0 +1,493 @@
/*
* 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.
*/
package sun.security.ec;
import sun.security.ec.point.*;
import sun.security.util.math.*;
import sun.security.util.math.intpoly.*;
import java.math.BigInteger;
import java.security.ProviderException;
import java.security.spec.ECFieldFp;
import java.security.spec.ECParameterSpec;
import java.security.spec.EllipticCurve;
import java.util.Map;
import java.util.Optional;
/*
* Elliptic curve point arithmetic for prime-order curves where a=-3.
* Formulas are derived from "Complete addition formulas for prime order
* elliptic curves" by Renes, Costello, and Batina.
*/
public class ECOperations {
/*
* An exception indicating a problem with an intermediate value produced
* by some part of the computation. For example, the signing operation
* will throw this exception to indicate that the r or s value is 0, and
* that the signing operation should be tried again with a different nonce.
*/
static class IntermediateValueException extends Exception {
private static final long serialVersionUID = 1;
}
static final Map<BigInteger, IntegerFieldModuloP> fields = Map.of(
IntegerPolynomialP256.MODULUS, new IntegerPolynomialP256(),
IntegerPolynomialP384.MODULUS, new IntegerPolynomialP384(),
IntegerPolynomialP521.MODULUS, new IntegerPolynomialP521()
);
static final Map<BigInteger, IntegerFieldModuloP> orderFields = Map.of(
P256OrderField.MODULUS, new P256OrderField(),
P384OrderField.MODULUS, new P384OrderField(),
P521OrderField.MODULUS, new P521OrderField()
);
public static Optional<ECOperations> forParameters(ECParameterSpec params) {
EllipticCurve curve = params.getCurve();
if (!(curve.getField() instanceof ECFieldFp)) {
return Optional.empty();
}
ECFieldFp primeField = (ECFieldFp) curve.getField();
BigInteger three = BigInteger.valueOf(3);
if (!primeField.getP().subtract(curve.getA()).equals(three)) {
return Optional.empty();
}
IntegerFieldModuloP field = fields.get(primeField.getP());
if (field == null) {
return Optional.empty();
}
IntegerFieldModuloP orderField = orderFields.get(params.getOrder());
if (orderField == null) {
return Optional.empty();
}
ImmutableIntegerModuloP b = field.getElement(curve.getB());
ECOperations ecOps = new ECOperations(b, orderField);
return Optional.of(ecOps);
}
final ImmutableIntegerModuloP b;
final SmallValue one;
final SmallValue two;
final SmallValue three;
final SmallValue four;
final ProjectivePoint.Immutable neutral;
private final IntegerFieldModuloP orderField;
public ECOperations(IntegerModuloP b, IntegerFieldModuloP orderField) {
this.b = b.fixed();
this.orderField = orderField;
this.one = b.getField().getSmallValue(1);
this.two = b.getField().getSmallValue(2);
this.three = b.getField().getSmallValue(3);
this.four = b.getField().getSmallValue(4);
IntegerFieldModuloP field = b.getField();
this.neutral = new ProjectivePoint.Immutable(field.get0(),
field.get1(), field.get0());
}
public IntegerFieldModuloP getField() {
return b.getField();
}
public IntegerFieldModuloP getOrderField() {
return orderField;
}
protected ProjectivePoint.Immutable getNeutral() {
return neutral;
}
public boolean isNeutral(Point p) {
ProjectivePoint<?> pp = (ProjectivePoint<?>) p;
IntegerModuloP z = pp.getZ();
IntegerFieldModuloP field = z.getField();
int byteLength = (field.getSize().bitLength() + 7) / 8;
byte[] zBytes = z.asByteArray(byteLength);
return allZero(zBytes);
}
byte[] seedToScalar(byte[] seedBytes)
throws IntermediateValueException {
// Produce a nonce from the seed using FIPS 186-4,section B.5.1:
// Per-Message Secret Number Generation Using Extra Random Bits
// or
// Produce a scalar from the seed using FIPS 186-4, section B.4.1:
// Key Pair Generation Using Extra Random Bits
// To keep the implementation simple, sample in the range [0,n)
// and throw IntermediateValueException in the (unlikely) event
// that the result is 0.
// Get 64 extra bits and reduce in to the nonce
int seedBits = orderField.getSize().bitLength() + 64;
if (seedBytes.length * 8 < seedBits) {
throw new ProviderException("Incorrect seed length: " +
seedBytes.length * 8 + " < " + seedBits);
}
// input conversion only works on byte boundaries
// clear high-order bits of last byte so they don't influence nonce
int lastByteBits = seedBits % 8;
if (lastByteBits != 0) {
int lastByteIndex = seedBits / 8;
byte mask = (byte) (0xFF >>> (8 - lastByteBits));
seedBytes[lastByteIndex] &= mask;
}
int seedLength = (seedBits + 7) / 8;
IntegerModuloP scalarElem =
orderField.getElement(seedBytes, 0, seedLength, (byte) 0);
int scalarLength = (orderField.getSize().bitLength() + 7) / 8;
byte[] scalarArr = new byte[scalarLength];
scalarElem.asByteArray(scalarArr);
if (ECOperations.allZero(scalarArr)) {
throw new IntermediateValueException();
}
return scalarArr;
}
/*
* Compare all values in the array to 0 without branching on any value
*
*/
public static boolean allZero(byte[] arr) {
byte acc = 0;
for (int i = 0; i < arr.length; i++) {
acc |= arr[i];
}
return acc == 0;
}
/*
* 4-bit branchless array lookup for projective points.
*/
private void lookup4(ProjectivePoint.Immutable[] arr, int index,
ProjectivePoint.Mutable result, IntegerModuloP zero) {
for (int i = 0; i < 16; i++) {
int xor = index ^ i;
int bit3 = (xor & 0x8) >>> 3;
int bit2 = (xor & 0x4) >>> 2;
int bit1 = (xor & 0x2) >>> 1;
int bit0 = (xor & 0x1);
int inverse = bit0 | bit1 | bit2 | bit3;
int set = 1 - inverse;
ProjectivePoint.Immutable pi = arr[i];
result.conditionalSet(pi, set);
}
}
private void double4(ProjectivePoint.Mutable p, MutableIntegerModuloP t0,
MutableIntegerModuloP t1, MutableIntegerModuloP t2,
MutableIntegerModuloP t3, MutableIntegerModuloP t4) {
for (int i = 0; i < 4; i++) {
setDouble(p, t0, t1, t2, t3, t4);
}
}
/**
* Multiply an affine point by a scalar and return the result as a mutable
* point.
*
* @param affineP the point
* @param s the scalar as a little-endian array
* @return the product
*/
public MutablePoint multiply(AffinePoint affineP, byte[] s) {
// 4-bit windowed multiply with branchless lookup.
// The mixed addition is faster, so it is used to construct the array
// at the beginning of the operation.
IntegerFieldModuloP field = affineP.getX().getField();
ImmutableIntegerModuloP zero = field.get0();
// temporaries
MutableIntegerModuloP t0 = zero.mutable();
MutableIntegerModuloP t1 = zero.mutable();
MutableIntegerModuloP t2 = zero.mutable();
MutableIntegerModuloP t3 = zero.mutable();
MutableIntegerModuloP t4 = zero.mutable();
ProjectivePoint.Mutable result = new ProjectivePoint.Mutable(field);
result.getY().setValue(field.get1().mutable());
ProjectivePoint.Immutable[] pointMultiples =
new ProjectivePoint.Immutable[16];
// 0P is neutral---same as initial result value
pointMultiples[0] = result.fixed();
ProjectivePoint.Mutable ps = new ProjectivePoint.Mutable(field);
ps.setValue(affineP);
// 1P = P
pointMultiples[1] = ps.fixed();
// the rest are calculated using mixed point addition
for (int i = 2; i < 16; i++) {
setSum(ps, affineP, t0, t1, t2, t3, t4);
pointMultiples[i] = ps.fixed();
}
ProjectivePoint.Mutable lookupResult = ps.mutable();
for (int i = s.length - 1; i >= 0; i--) {
double4(result, t0, t1, t2, t3, t4);
int high = (0xFF & s[i]) >>> 4;
lookup4(pointMultiples, high, lookupResult, zero);
setSum(result, lookupResult, t0, t1, t2, t3, t4);
double4(result, t0, t1, t2, t3, t4);
int low = 0xF & s[i];
lookup4(pointMultiples, low, lookupResult, zero);
setSum(result, lookupResult, t0, t1, t2, t3, t4);
}
return result;
}
/*
* Point double
*/
private void setDouble(ProjectivePoint.Mutable p, MutableIntegerModuloP t0,
MutableIntegerModuloP t1, MutableIntegerModuloP t2,
MutableIntegerModuloP t3, MutableIntegerModuloP t4) {
t0.setValue(p.getX()).setSquare();
t1.setValue(p.getY()).setSquare();
t2.setValue(p.getZ()).setSquare();
t3.setValue(p.getX()).setProduct(p.getY());
t4.setValue(p.getY()).setProduct(p.getZ());
t3.setSum(t3);
p.getZ().setProduct(p.getX());
p.getZ().setProduct(two);
p.getY().setValue(t2).setProduct(b);
p.getY().setDifference(p.getZ());
p.getX().setValue(p.getY()).setProduct(two);
p.getY().setSum(p.getX());
p.getY().setReduced();
p.getX().setValue(t1).setDifference(p.getY());
p.getY().setSum(t1);
p.getY().setProduct(p.getX());
p.getX().setProduct(t3);
t3.setValue(t2).setProduct(two);
t2.setSum(t3);
p.getZ().setProduct(b);
t2.setReduced();
p.getZ().setDifference(t2);
p.getZ().setDifference(t0);
t3.setValue(p.getZ()).setProduct(two);
p.getZ().setReduced();
p.getZ().setSum(t3);
t0.setProduct(three);
t0.setDifference(t2);
t0.setProduct(p.getZ());
p.getY().setSum(t0);
t4.setSum(t4);
p.getZ().setProduct(t4);
p.getX().setDifference(p.getZ());
p.getZ().setValue(t4).setProduct(t1);
p.getZ().setProduct(four);
}
/*
* Mixed point addition. This method constructs new temporaries each time
* it is called. For better efficiency, the method that reuses temporaries
* should be used if more than one sum will be computed.
*/
public void setSum(MutablePoint p, AffinePoint p2) {
IntegerModuloP zero = p.getField().get0();
MutableIntegerModuloP t0 = zero.mutable();
MutableIntegerModuloP t1 = zero.mutable();
MutableIntegerModuloP t2 = zero.mutable();
MutableIntegerModuloP t3 = zero.mutable();
MutableIntegerModuloP t4 = zero.mutable();
setSum((ProjectivePoint.Mutable) p, p2, t0, t1, t2, t3, t4);
}
/*
* Mixed point addition
*/
private void setSum(ProjectivePoint.Mutable p, AffinePoint p2,
MutableIntegerModuloP t0, MutableIntegerModuloP t1,
MutableIntegerModuloP t2, MutableIntegerModuloP t3,
MutableIntegerModuloP t4) {
t0.setValue(p.getX()).setProduct(p2.getX());
t1.setValue(p.getY()).setProduct(p2.getY());
t3.setValue(p2.getX()).setSum(p2.getY());
t4.setValue(p.getX()).setSum(p.getY());
p.getX().setReduced();
t3.setProduct(t4);
t4.setValue(t0).setSum(t1);
t3.setDifference(t4);
t4.setValue(p2.getY()).setProduct(p.getZ());
t4.setSum(p.getY());
p.getY().setValue(p2.getX()).setProduct(p.getZ());
p.getY().setSum(p.getX());
t2.setValue(p.getZ());
p.getZ().setProduct(b);
p.getX().setValue(p.getY()).setDifference(p.getZ());
p.getX().setReduced();
p.getZ().setValue(p.getX()).setProduct(two);
p.getX().setSum(p.getZ());
p.getZ().setValue(t1).setDifference(p.getX());
p.getX().setSum(t1);
p.getY().setProduct(b);
t1.setValue(t2).setProduct(two);
t2.setSum(t1);
t2.setReduced();
p.getY().setDifference(t2);
p.getY().setDifference(t0);
p.getY().setReduced();
t1.setValue(p.getY()).setProduct(two);
p.getY().setSum(t1);
t1.setValue(t0).setProduct(two);
t0.setSum(t1);
t0.setDifference(t2);
t1.setValue(t4).setProduct(p.getY());
t2.setValue(t0).setProduct(p.getY());
p.getY().setValue(p.getX()).setProduct(p.getZ());
p.getY().setSum(t2);
p.getX().setProduct(t3);
p.getX().setDifference(t1);
p.getZ().setProduct(t4);
t1.setValue(t3).setProduct(t0);
p.getZ().setSum(t1);
}
/*
* Projective point addition
*/
private void setSum(ProjectivePoint.Mutable p, ProjectivePoint.Mutable p2,
MutableIntegerModuloP t0, MutableIntegerModuloP t1,
MutableIntegerModuloP t2, MutableIntegerModuloP t3,
MutableIntegerModuloP t4) {
t0.setValue(p.getX()).setProduct(p2.getX());
t1.setValue(p.getY()).setProduct(p2.getY());
t2.setValue(p.getZ()).setProduct(p2.getZ());
t3.setValue(p.getX()).setSum(p.getY());
t4.setValue(p2.getX()).setSum(p2.getY());
t3.setProduct(t4);
t4.setValue(t0).setSum(t1);
t3.setDifference(t4);
t4.setValue(p.getY()).setSum(p.getZ());
p.getY().setValue(p2.getY()).setSum(p2.getZ());
t4.setProduct(p.getY());
p.getY().setValue(t1).setSum(t2);
t4.setDifference(p.getY());
p.getX().setSum(p.getZ());
p.getY().setValue(p2.getX()).setSum(p2.getZ());
p.getX().setProduct(p.getY());
p.getY().setValue(t0).setSum(t2);
p.getY().setAdditiveInverse().setSum(p.getX());
p.getY().setReduced();
p.getZ().setValue(t2).setProduct(b);
p.getX().setValue(p.getY()).setDifference(p.getZ());
p.getZ().setValue(p.getX()).setProduct(two);
p.getX().setSum(p.getZ());
p.getX().setReduced();
p.getZ().setValue(t1).setDifference(p.getX());
p.getX().setSum(t1);
p.getY().setProduct(b);
t1.setValue(t2).setSum(t2);
t2.setSum(t1);
t2.setReduced();
p.getY().setDifference(t2);
p.getY().setDifference(t0);
p.getY().setReduced();
t1.setValue(p.getY()).setSum(p.getY());
p.getY().setSum(t1);
t1.setValue(t0).setProduct(two);
t0.setSum(t1);
t0.setDifference(t2);
t1.setValue(t4).setProduct(p.getY());
t2.setValue(t0).setProduct(p.getY());
p.getY().setValue(p.getX()).setProduct(p.getZ());
p.getY().setSum(t2);
p.getX().setProduct(t3);
p.getX().setDifference(t1);
p.getZ().setProduct(t4);
t1.setValue(t3).setProduct(t0);
p.getZ().setSum(t1);
}
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -32,11 +32,7 @@ import java.security.*;
import java.security.interfaces.*; import java.security.interfaces.*;
import java.security.spec.*; import java.security.spec.*;
import sun.security.util.DerInputStream; import sun.security.util.*;
import sun.security.util.DerOutputStream;
import sun.security.util.DerValue;
import sun.security.util.ECParameters;
import sun.security.util.ECUtil;
import sun.security.x509.AlgorithmId; import sun.security.x509.AlgorithmId;
import sun.security.pkcs.PKCS8Key; import sun.security.pkcs.PKCS8Key;
@ -68,6 +64,7 @@ public final class ECPrivateKeyImpl extends PKCS8Key implements ECPrivateKey {
private static final long serialVersionUID = 88695385615075129L; private static final long serialVersionUID = 88695385615075129L;
private BigInteger s; // private value private BigInteger s; // private value
private byte[] arrayS; // private value as a little-endian array
private ECParameterSpec params; private ECParameterSpec params;
/** /**
@ -85,13 +82,25 @@ public final class ECPrivateKeyImpl extends PKCS8Key implements ECPrivateKey {
throws InvalidKeyException { throws InvalidKeyException {
this.s = s; this.s = s;
this.params = params; this.params = params;
// generate the encoding makeEncoding(s);
}
ECPrivateKeyImpl(byte[] s, ECParameterSpec params)
throws InvalidKeyException {
this.arrayS = s.clone();
this.params = params;
makeEncoding(s);
}
private void makeEncoding(byte[] s) throws InvalidKeyException {
algid = new AlgorithmId algid = new AlgorithmId
(AlgorithmId.EC_oid, ECParameters.getAlgorithmParameters(params)); (AlgorithmId.EC_oid, ECParameters.getAlgorithmParameters(params));
try { try {
DerOutputStream out = new DerOutputStream(); DerOutputStream out = new DerOutputStream();
out.putInteger(1); // version 1 out.putInteger(1); // version 1
byte[] privBytes = ECUtil.trimZeroes(s.toByteArray()); byte[] privBytes = s.clone();
ArrayUtil.reverse(privBytes);
out.putOctetString(privBytes); out.putOctetString(privBytes);
DerValue val = DerValue val =
new DerValue(DerValue.tag_Sequence, out.toByteArray()); new DerValue(DerValue.tag_Sequence, out.toByteArray());
@ -102,6 +111,31 @@ public final class ECPrivateKeyImpl extends PKCS8Key implements ECPrivateKey {
} }
} }
private void makeEncoding(BigInteger s) throws InvalidKeyException {
algid = new AlgorithmId
(AlgorithmId.EC_oid, ECParameters.getAlgorithmParameters(params));
try {
byte[] sArr = s.toByteArray();
// convert to fixed-length array
int numOctets = (params.getOrder().bitLength() + 7) / 8;
byte[] sOctets = new byte[numOctets];
int inPos = Math.max(sArr.length - sOctets.length, 0);
int outPos = Math.max(sOctets.length - sArr.length, 0);
int length = Math.min(sArr.length, sOctets.length);
System.arraycopy(sArr, inPos, sOctets, outPos, length);
DerOutputStream out = new DerOutputStream();
out.putInteger(1); // version 1
out.putOctetString(sOctets);
DerValue val =
new DerValue(DerValue.tag_Sequence, out.toByteArray());
key = val.toByteArray();
} catch (IOException exc) {
// should never occur
throw new InvalidKeyException(exc);
}
}
// see JCA doc // see JCA doc
public String getAlgorithm() { public String getAlgorithm() {
return "EC"; return "EC";
@ -109,9 +143,26 @@ public final class ECPrivateKeyImpl extends PKCS8Key implements ECPrivateKey {
// see JCA doc // see JCA doc
public BigInteger getS() { public BigInteger getS() {
if (s == null) {
byte[] arrCopy = arrayS.clone();
ArrayUtil.reverse(arrCopy);
s = new BigInteger(1, arrCopy);
}
return s; return s;
} }
public byte[] getArrayS() {
if (arrayS == null) {
byte[] arr = getS().toByteArray();
ArrayUtil.reverse(arr);
int byteLength = (params.getOrder().bitLength() + 7) / 8;
arrayS = new byte[byteLength];
int length = Math.min(byteLength, arr.length);
System.arraycopy(arr, 0, arrayS, 0, length);
}
return arrayS.clone();
}
// see JCA doc // see JCA doc
public ECParameterSpec getParams() { public ECParameterSpec getParams() {
return params; return params;
@ -133,12 +184,13 @@ public final class ECPrivateKeyImpl extends PKCS8Key implements ECPrivateKey {
throw new IOException("Version must be 1"); throw new IOException("Version must be 1");
} }
byte[] privData = data.getOctetString(); byte[] privData = data.getOctetString();
s = new BigInteger(1, privData); ArrayUtil.reverse(privData);
arrayS = privData;
while (data.available() != 0) { while (data.available() != 0) {
DerValue value = data.getDerValue(); DerValue value = data.getDerValue();
if (value.isContextSpecific((byte)0)) { if (value.isContextSpecific((byte) 0)) {
// ignore for now // ignore for now
} else if (value.isContextSpecific((byte)1)) { } else if (value.isContextSpecific((byte) 1)) {
// ignore for now // ignore for now
} else { } else {
throw new InvalidKeyException("Unexpected value: " + value); throw new InvalidKeyException("Unexpected value: " + value);

View File

@ -0,0 +1,76 @@
/*
* 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.
*/
package sun.security.ec.point;
import sun.security.util.math.ImmutableIntegerModuloP;
import java.util.Objects;
/**
* Elliptic curve point represented using affine coordinates (x, y). This class
* is not part of the sun.security.ec.point.Point hierarchy because it is not
* used to hold intermediate values during point arithmetic, and so it does not
* have a mutable form.
*/
public class AffinePoint {
private final ImmutableIntegerModuloP x;
private final ImmutableIntegerModuloP y;
public AffinePoint(ImmutableIntegerModuloP x, ImmutableIntegerModuloP y) {
this.x = x;
this.y = y;
}
public ImmutableIntegerModuloP getX() {
return x;
}
public ImmutableIntegerModuloP getY() {
return y;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof AffinePoint)) {
return false;
}
AffinePoint p = (AffinePoint) obj;
boolean xEquals = x.asBigInteger().equals(p.x.asBigInteger());
boolean yEquals = y.asBigInteger().equals(p.y.asBigInteger());
return xEquals && yEquals;
}
@Override
public int hashCode() {
return Objects.hash(x, y);
}
@Override
public String toString() {
return "(" + x.asBigInteger().toString() + "," +
y.asBigInteger().toString() + ")";
}
}

View File

@ -0,0 +1,32 @@
/*
* 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.
*/
package sun.security.ec.point;
/**
* An interface for immutable points on an elliptic curve over a finite field.
*/
public interface ImmutablePoint extends Point {
}

View File

@ -0,0 +1,37 @@
/*
* 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.
*/
package sun.security.ec.point;
/**
* An interface for mutable points on an elliptic curve over a finite field.
*/
public interface MutablePoint extends Point {
MutablePoint setValue(AffinePoint p);
MutablePoint setValue(Point p);
MutablePoint conditionalSet(Point p, int set);
}

View File

@ -0,0 +1,45 @@
/*
* 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.
*/
package sun.security.ec.point;
import sun.security.util.math.IntegerFieldModuloP;
/**
* A base interface for points on an elliptic curve over a finite field.
* Implementations may use different representations for points, and this
* interface creates a common API for manipulating points. This API has no
* methods for point arithmetic, which depends on group structure and curve
* parameters in addition to point representation.
*/
public interface Point {
IntegerFieldModuloP getField();
AffinePoint asAffine();
ImmutablePoint fixed();
MutablePoint mutable();
}

View File

@ -0,0 +1,160 @@
/*
* 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.
*/
package sun.security.ec.point;
import sun.security.util.math.*;
/**
* Elliptic curve point in projective coordinates (X, Y, Z) where
* an affine point (x, y) is represented using any (X, Y, Z) s.t.
* x = X/Z and y = Y/Z.
*/
public abstract class ProjectivePoint
<T extends IntegerModuloP> implements Point {
protected final T x;
protected final T y;
protected final T z;
protected ProjectivePoint(T x, T y, T z) {
this.x = x;
this.y = y;
this.z = z;
}
@Override
public IntegerFieldModuloP getField() {
return this.x.getField();
}
@Override
public Immutable fixed() {
return new Immutable(x.fixed(), y.fixed(), z.fixed());
}
@Override
public Mutable mutable() {
return new Mutable(x.mutable(), y.mutable(), z.mutable());
}
public T getX() {
return x;
}
public T getY() {
return y;
}
public T getZ() {
return z;
}
public AffinePoint asAffine() {
IntegerModuloP zInv = z.multiplicativeInverse();
return new AffinePoint(x.multiply(zInv), y.multiply(zInv));
}
public static class Immutable
extends ProjectivePoint<ImmutableIntegerModuloP>
implements ImmutablePoint {
public Immutable(ImmutableIntegerModuloP x,
ImmutableIntegerModuloP y,
ImmutableIntegerModuloP z) {
super(x, y, z);
}
}
public static class Mutable
extends ProjectivePoint<MutableIntegerModuloP>
implements MutablePoint {
public Mutable(MutableIntegerModuloP x,
MutableIntegerModuloP y,
MutableIntegerModuloP z) {
super(x, y, z);
}
public Mutable(IntegerFieldModuloP field) {
super(field.get0().mutable(),
field.get0().mutable(),
field.get0().mutable());
}
@Override
public Mutable conditionalSet(Point p, int set) {
if (!(p instanceof ProjectivePoint)) {
throw new RuntimeException("Incompatible point");
}
@SuppressWarnings("unchecked")
ProjectivePoint<IntegerModuloP> pp =
(ProjectivePoint<IntegerModuloP>) p;
return conditionalSet(pp, set);
}
private <T extends IntegerModuloP>
Mutable conditionalSet(ProjectivePoint<T> pp, int set) {
x.conditionalSet(pp.x, set);
y.conditionalSet(pp.y, set);
z.conditionalSet(pp.z, set);
return this;
}
@Override
public Mutable setValue(AffinePoint p) {
x.setValue(p.getX());
y.setValue(p.getY());
z.setValue(p.getX().getField().get1());
return this;
}
@Override
public Mutable setValue(Point p) {
if (!(p instanceof ProjectivePoint)) {
throw new RuntimeException("Incompatible point");
}
@SuppressWarnings("unchecked")
ProjectivePoint<IntegerModuloP> pp =
(ProjectivePoint<IntegerModuloP>) p;
return setValue(pp);
}
private <T extends IntegerModuloP>
Mutable setValue(ProjectivePoint<T> pp) {
x.setValue(pp.x);
y.setValue(pp.y);
z.setValue(pp.z);
return this;
}
}
}

View File

@ -1,135 +0,0 @@
/*
* Copyright (c) 2002-2016, the original author or authors.
*
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
* http://www.opensource.org/licenses/bsd-license.php
*/
package jdk.internal.jline;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import jdk.internal.jline.internal.InfoCmp;
/**
* Terminal wrapper with default ansi capabilities
*/
public class DefaultTerminal2 implements Terminal2 {
private final Terminal terminal;
private final Set<String> bools = new HashSet<String>();
private final Map<String, String> strings = new HashMap<String, String>();
public DefaultTerminal2(Terminal terminal) {
this.terminal = terminal;
registerCap("key_backspace", "^H");
registerCap("bell", "^G");
registerCap("carriage_return", "^M");
if (true/*isSupported() && isAnsiSupported()*/) {
registerCap("clr_eol", "\\E[K");
registerCap("clr_bol", "\\E[1K");
registerCap("cursor_up", "\\E[A");
registerCap("cursor_down", "^J");
registerCap("column_address", "\\E[%i%p1%dG");
registerCap("clear_screen", "\\E[H\\E[2J");
registerCap("parm_down_cursor", "\\E[%p1%dB");
registerCap("cursor_left", "^H");
registerCap("cursor_right", "\\E[C");
}
if (hasWeirdWrap()) {
registerCap("eat_newline_glitch");
registerCap("auto_right_margin");
}
}
public void init() throws Exception {
terminal.init();
}
public void restore() throws Exception {
terminal.restore();
}
public void reset() throws Exception {
terminal.reset();
}
public boolean isSupported() {
return terminal.isSupported();
}
public int getWidth() {
return terminal.getWidth();
}
public int getHeight() {
return terminal.getHeight();
}
public boolean isAnsiSupported() {
return terminal.isAnsiSupported();
}
public OutputStream wrapOutIfNeeded(OutputStream out) {
return terminal.wrapOutIfNeeded(out);
}
public InputStream wrapInIfNeeded(InputStream in) throws IOException {
return terminal.wrapInIfNeeded(in);
}
public boolean hasWeirdWrap() {
return terminal.hasWeirdWrap();
}
public boolean isEchoEnabled() {
return terminal.isEchoEnabled();
}
public void setEchoEnabled(boolean enabled) {
terminal.setEchoEnabled(enabled);
}
public void disableInterruptCharacter() {
terminal.disableInterruptCharacter();
}
public void enableInterruptCharacter() {
terminal.enableInterruptCharacter();
}
public String getOutputEncoding() {
return terminal.getOutputEncoding();
}
private void registerCap(String cap, String value) {
for (String key : InfoCmp.getNames(cap)) {
strings.put(key, value);
}
}
private void registerCap(String cap) {
Collections.addAll(bools, InfoCmp.getNames(cap));
}
public boolean getBooleanCapability(String capability) {
return bools.contains(capability);
}
public Integer getNumericCapability(String capability) {
return null;
}
public String getStringCapability(String capability) {
return strings.get(capability);
}
}

View File

@ -1,46 +0,0 @@
/*
* Copyright (c) 2002-2016, the original author or authors.
*
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
* http://www.opensource.org/licenses/bsd-license.php
*/
package jdk.internal.jline;
// Based on Apache Karaf impl
/**
* Non-interruptible (via CTRL-C) {@link UnixTerminal}.
*
* @since 2.0
*/
public class NoInterruptUnixTerminal
extends UnixTerminal
{
private String intr;
public NoInterruptUnixTerminal() throws Exception {
super();
}
@Override
public void init() throws Exception {
super.init();
intr = getSettings().getPropertyAsString("intr");
if ("<undef>".equals(intr)) {
intr = null;
}
if (intr != null) {
getSettings().undef("intr");
}
}
@Override
public void restore() throws Exception {
if (intr != null) {
getSettings().set("intr", intr);
}
super.restore();
}
}

View File

@ -1,68 +0,0 @@
/*
* Copyright (c) 2002-2016, the original author or authors.
*
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
* http://www.opensource.org/licenses/bsd-license.php
*/
package jdk.internal.jline;
import jdk.internal.jline.internal.Log;
/**
* Terminal that is used for OSv. This is seperate to unix terminal
* implementation because exec cannot be used as currently used by UnixTerminal.
*
* This implimentation is derrived from the implementation at
* https://github.com/cloudius-systems/mgmt/blob/master/crash/src/main/java/com/cloudius/cli/OSvTerminal.java
* authored by Or Cohen.
*
* @author <a href-"mailto:orc@fewbytes.com">Or Cohen</a>
* @author <a href="mailto:arun.neelicattu@gmail.com">Arun Neelicattu</a>
* @since 2.13
*/
public class OSvTerminal
extends TerminalSupport
{
public Class<?> sttyClass = null;
public Object stty = null;
@SuppressWarnings("deprecation")
public OSvTerminal() {
super(true);
setAnsiSupported(true);
try {
if (stty == null) {
sttyClass = Class.forName("com.cloudius.util.Stty");
stty = sttyClass.newInstance();
}
} catch (Exception e) {
Log.warn("Failed to load com.cloudius.util.Stty", e);
}
}
@Override
public void init() throws Exception {
super.init();
if (stty != null) {
sttyClass.getMethod("jlineMode").invoke(stty);
}
}
@Override
public void restore() throws Exception {
if (stty != null) {
sttyClass.getMethod("reset").invoke(stty);
}
super.restore();
// Newline in end of restore like in jline.UnixTerminal
System.out.println();
}
}

View File

@ -1,68 +0,0 @@
/*
* Copyright (c) 2002-2016, the original author or authors.
*
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
* http://www.opensource.org/licenses/bsd-license.php
*/
package jdk.internal.jline;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
* Representation of the input terminal for a platform.
*
* @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
* @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
* @since 2.0
*/
public interface Terminal
{
void init() throws Exception;
void restore() throws Exception;
void reset() throws Exception;
boolean isSupported();
int getWidth();
int getHeight();
boolean isAnsiSupported();
/**
* When ANSI is not natively handled, the output will have to be wrapped.
*/
OutputStream wrapOutIfNeeded(OutputStream out);
/**
* When using native support, return the InputStream to use for reading characters
* else return the input stream passed as a parameter.
*
* @since 2.6
*/
InputStream wrapInIfNeeded(InputStream in) throws IOException;
/**
* For terminals that don't wrap when character is written in last column,
* only when the next character is written.
* These are the ones that have 'am' and 'xn' termcap attributes (xterm and
* rxvt flavors falls under that category)
*/
boolean hasWeirdWrap();
boolean isEchoEnabled();
void setEchoEnabled(boolean enabled);
void disableInterruptCharacter();
void enableInterruptCharacter();
String getOutputEncoding();
}

View File

@ -1,211 +0,0 @@
/*
* Copyright (c) 2002-2016, the original author or authors.
*
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
* http://www.opensource.org/licenses/bsd-license.php
*/
package jdk.internal.jline;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Map;
import jdk.internal.jline.internal.Configuration;
import jdk.internal.jline.internal.Log;
import static jdk.internal.jline.internal.Preconditions.checkNotNull;
/**
* Creates terminal instances.
*
* @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
* @since 2.0
*/
public class TerminalFactory
{
public static final String JLINE_TERMINAL = "jline.terminal";
public static final String AUTO = "auto";
public static final String UNIX = "unix";
public static final String OSV = "osv";
public static final String WIN = "win";
public static final String WINDOWS = "windows";
public static final String FREEBSD = "freebsd";
public static final String NONE = "none";
public static final String OFF = "off";
public static final String FALSE = "false";
private static Terminal term = null;
public static synchronized Terminal create() {
return create(null);
}
public static synchronized Terminal create(String ttyDevice) {
if (Log.TRACE) {
//noinspection ThrowableInstanceNeverThrown
Log.trace(new Throwable("CREATE MARKER"));
}
String defaultType = "dumb".equals(System.getenv("TERM")) ? NONE : AUTO;
String type = Configuration.getString(JLINE_TERMINAL, defaultType);
Log.debug("Creating terminal; type=", type);
Terminal t;
try {
String tmp = type.toLowerCase();
if (tmp.equals(UNIX)) {
t = getFlavor(Flavor.UNIX);
}
else if (tmp.equals(OSV)) {
t = getFlavor(Flavor.OSV);
}
else if (tmp.equals(WIN) || tmp.equals(WINDOWS)) {
t = getFlavor(Flavor.WINDOWS);
}
else if (tmp.equals(NONE) || tmp.equals(OFF) || tmp.equals(FALSE)) {
if (System.getenv("INSIDE_EMACS") != null) {
// emacs requires ansi on and echo off
t = new UnsupportedTerminal(true, false);
} else {
// others the other way round
t = new UnsupportedTerminal(false, true);
}
}
else {
if (tmp.equals(AUTO)) {
String os = Configuration.getOsName();
Flavor flavor = Flavor.UNIX;
if (os.contains(WINDOWS)) {
flavor = Flavor.WINDOWS;
} else if (System.getenv("OSV_CPUS") != null) {
flavor = Flavor.OSV;
}
t = getFlavor(flavor, ttyDevice);
}
else {
try {
@SuppressWarnings("deprecation")
Object o = Thread.currentThread().getContextClassLoader().loadClass(type).newInstance();
t = (Terminal) o;
}
catch (Exception e) {
throw new IllegalArgumentException(MessageFormat.format("Invalid terminal type: {0}", type), e);
}
}
}
}
catch (Exception e) {
Log.error("Failed to construct terminal; falling back to unsupported", e);
t = new UnsupportedTerminal();
}
Log.debug("Created Terminal: ", t);
try {
t.init();
}
catch (Throwable e) {
Log.error("Terminal initialization failed; falling back to unsupported", e);
return new UnsupportedTerminal();
}
return t;
}
public static synchronized void reset() {
term = null;
}
public static synchronized void resetIf(final Terminal t) {
if(t == term) {
reset();
}
}
public static enum Type
{
AUTO,
WINDOWS,
UNIX,
OSV,
NONE
}
public static synchronized void configure(final String type) {
checkNotNull(type);
System.setProperty(JLINE_TERMINAL, type);
}
public static synchronized void configure(final Type type) {
checkNotNull(type);
configure(type.name().toLowerCase());
}
//
// Flavor Support
//
public static enum Flavor
{
WINDOWS,
UNIX,
OSV
}
private static final Map<Flavor, TerminalConstructor> FLAVORS = new HashMap<>();
static {
registerFlavor(Flavor.WINDOWS, ttyDevice -> new WindowsTerminal());
registerFlavor(Flavor.UNIX, ttyDevice -> new UnixTerminal(ttyDevice));
registerFlavor(Flavor.OSV, ttyDevice -> new OSvTerminal());
}
public static synchronized Terminal get(String ttyDevice) {
// The code is assuming we've got only one terminal per process.
// Continuing this assumption, if this terminal is already initialized,
// we don't check if it's using the same tty line either. Both assumptions
// are a bit crude. TODO: check single terminal assumption.
if (term == null) {
term = create(ttyDevice);
}
return term;
}
public static synchronized Terminal get() {
return get(null);
}
public static Terminal getFlavor(final Flavor flavor) throws Exception {
return getFlavor(flavor, null);
}
@SuppressWarnings("deprecation")
public static Terminal getFlavor(final Flavor flavor, String ttyDevice) throws Exception {
TerminalConstructor factory = FLAVORS.get(flavor);
if (factory != null) {
return factory.createTerminal(ttyDevice);
} else {
throw new InternalError();
}
}
public static void registerFlavor(final Flavor flavor, final TerminalConstructor factory) {
FLAVORS.put(flavor, factory);
}
public interface TerminalConstructor {
public Terminal createTerminal(String str) throws Exception;
}
}

Some files were not shown because too many files have changed in this diff Show More