Merge
This commit is contained in:
commit
c83b55a9e2
@ -1,19 +1,24 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="generator" content="pandoc">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
|
||||
<meta charset="utf-8" />
|
||||
<meta name="generator" content="pandoc" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
|
||||
<title>Building the JDK</title>
|
||||
<style type="text/css">code{white-space: pre;}</style>
|
||||
<link rel="stylesheet" href="../make/data/docs-resources/resources/jdk-default.css">
|
||||
<style type="text/css">
|
||||
code{white-space: pre-wrap;}
|
||||
span.smallcaps{font-variant: small-caps;}
|
||||
span.underline{text-decoration: underline;}
|
||||
div.column{display: inline-block; vertical-align: top; width: 50%;}
|
||||
</style>
|
||||
<link rel="stylesheet" href="../make/data/docs-resources/resources/jdk-default.css" />
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
|
||||
<![endif]-->
|
||||
<style type="text/css">pre, code, tt { color: #1d6ae5; }</style>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<header id="title-block-header">
|
||||
<h1 class="title">Building the JDK</h1>
|
||||
</header>
|
||||
<nav id="TOC">
|
||||
@ -640,11 +645,13 @@ 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>
|
||||
<ul>
|
||||
<li><p>Go to <a href="https://www.debian.org/distrib/packages">Debian Package Search</a> and search for the <code>libasound2</code> and <code>libasound2-dev</code> packages for your <em>target</em> system. Download them to /tmp.</p></li>
|
||||
<li><p>Install the libraries into the cross-compilation toolchain. For instance:</p>
|
||||
<li>Install the libraries into the cross-compilation toolchain. For instance:</li>
|
||||
</ul>
|
||||
<pre><code>cd /tools/gcc-linaro-arm-linux-gnueabihf-raspbian-2012.09-20120921_linux/arm-linux-gnueabihf/libc
|
||||
dpkg-deb -x /tmp/libasound2_1.0.25-4_armhf.deb .
|
||||
dpkg-deb -x /tmp/libasound2-dev_1.0.25-4_armhf.deb .</code></pre></li>
|
||||
<li><p>If alsa is not properly detected by <code>configure</code>, you can point it out by <code>--with-alsa</code>.</p></li>
|
||||
dpkg-deb -x /tmp/libasound2-dev_1.0.25-4_armhf.deb .</code></pre>
|
||||
<ul>
|
||||
<li>If alsa is not properly detected by <code>configure</code>, you can point it out by <code>--with-alsa</code>.</li>
|
||||
</ul>
|
||||
<h4 id="x11-1">X11</h4>
|
||||
<p>You will need X11 libraries suitable for your <em>target</em> system. For most cases, using Debian's pre-built libraries work fine.</p>
|
||||
@ -690,17 +697,21 @@ cp: cannot stat `arm-linux-gnueabihf/libXt.so': 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>For example, cross-compiling to AArch64 from x86_64 could be done like this:</p>
|
||||
<ul>
|
||||
<li><p>Install cross-compiler on the <em>build</em> system:</p>
|
||||
<pre><code>apt install g++-aarch64-linux-gnu gcc-aarch64-linux-gnu</code></pre></li>
|
||||
<li><p>Create chroot on the <em>build</em> system, configuring it for <em>target</em> system:</p>
|
||||
<li>Install cross-compiler on the <em>build</em> system:</li>
|
||||
</ul>
|
||||
<pre><code>apt install g++-aarch64-linux-gnu gcc-aarch64-linux-gnu</code></pre>
|
||||
<ul>
|
||||
<li>Create chroot on the <em>build</em> system, configuring it for <em>target</em> system:</li>
|
||||
</ul>
|
||||
<pre><code>sudo qemu-debootstrap --arch=arm64 --verbose \
|
||||
--include=fakeroot,build-essential,libx11-dev,libxext-dev,libxrender-dev,libxrandr-dev,libxtst-dev,libxt-dev,libcups2-dev,libfontconfig1-dev,libasound2-dev,libfreetype6-dev,libpng12-dev \
|
||||
--resolve-deps jessie /chroots/arm64 http://httpredir.debian.org/debian/</code></pre></li>
|
||||
<li><p>Configure and build with newly created chroot as sysroot/toolchain-path:</p>
|
||||
--include=fakeroot,build-essential,libx11-dev,libxext-dev,libxrender-dev,libxrandr-dev,libxtst-dev,libxt-dev,libcups2-dev,libfontconfig1-dev,libasound2-dev,libfreetype6-dev,libpng12-dev \
|
||||
--resolve-deps jessie /chroots/arm64 http://httpredir.debian.org/debian/</code></pre>
|
||||
<ul>
|
||||
<li>Configure and build with newly created chroot as sysroot/toolchain-path:</li>
|
||||
</ul>
|
||||
<pre><code>CC=aarch64-linux-gnu-gcc CXX=aarch64-linux-gnu-g++ sh ./configure --openjdk-target=aarch64-linux-gnu --with-sysroot=/chroots/arm64/ --with-toolchain-path=/chroots/arm64/
|
||||
make images
|
||||
ls build/linux-aarch64-normal-server-release/</code></pre></li>
|
||||
</ul>
|
||||
ls build/linux-aarch64-normal-server-release/</code></pre>
|
||||
<p>The build does not create new files in that chroot, so it can be reused for multiple builds without additional cleanup.</p>
|
||||
<p>Architectures that are known to successfully cross-compile like this are:</p>
|
||||
<table>
|
||||
@ -860,12 +871,7 @@ cannot create ... Permission denied
|
||||
spawn failed</code></pre>
|
||||
<p>This can be a sign of a Cygwin problem. See the information about solving problems in the <a href="#cygwin">Cygwin</a> section. Rebooting the computer might help temporarily.</p>
|
||||
<h3 id="getting-help">Getting Help</h3>
|
||||
<p>If none of the suggestions in this document helps you, or if you find what you believe is a bug in the build system, please contact the Build Group by sending a mail to <script type="text/javascript">
|
||||
<!--
|
||||
h='openjdk.java.net';a='@';n='build-dev';e=n+a+h;
|
||||
document.write('<a h'+'ref'+'="ma'+'ilto'+':'+e+'" clas'+'s="em' + 'ail">'+e+'<\/'+'a'+'>');
|
||||
// -->
|
||||
</script><noscript>build-dev at openjdk dot java dot net</noscript>. Please include the relevant parts of the configure and/or build log.</p>
|
||||
<p>If none of the suggestions in this document helps you, or if you find what you believe is a bug in the build system, please contact the Build Group by sending a mail to <a href="mailto:build-dev@openjdk.java.net">build-dev@openjdk.java.net</a>. Please include the relevant parts of the configure and/or build log.</p>
|
||||
<p>If you need general help or advice about developing for the JDK, you can also contact the Adoption Group. See the section on <a href="#contributing-to-openjdk">Contributing to OpenJDK</a> for more information.</p>
|
||||
<h2 id="hints-and-suggestions-for-advanced-users">Hints and Suggestions for Advanced Users</h2>
|
||||
<h3 id="setting-up-a-repository-for-pushing-changes-defpath">Setting Up a Repository for Pushing Changes (defpath)</h3>
|
||||
|
@ -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:
|
||||
|
||||
Supported devkit targets
|
||||
------------------------
|
||||
-------------------------
|
||||
x86_64-linux-gnu
|
||||
aarch64-linux-gnu
|
||||
arm-linux-gnueabihf
|
||||
@ -1129,13 +1129,13 @@ without additional cleanup.
|
||||
|
||||
Architectures that are known to successfully cross-compile like this are:
|
||||
|
||||
Target `CC` `CXX` `--arch=...` `--openjdk-target=...`
|
||||
------------ ------------------------- --------------------------- ------------ ----------------------
|
||||
x86 default default i386 i386-linux-gnu
|
||||
armhf gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf armhf arm-linux-gnueabihf
|
||||
aarch64 gcc-aarch64-linux-gnu g++-aarch64-linux-gnu arm64 aarch64-linux-gnu
|
||||
ppc64el gcc-powerpc64le-linux-gnu g++-powerpc64le-linux-gnu ppc64el powerpc64le-linux-gnu
|
||||
s390x gcc-s390x-linux-gnu g++-s390x-linux-gnu s390x s390x-linux-gnu
|
||||
Target `CC` `CXX` `--arch=...` `--openjdk-target=...`
|
||||
------------ ------------------------- --------------------------- ------------- -----------------------
|
||||
x86 default default i386 i386-linux-gnu
|
||||
armhf gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf armhf arm-linux-gnueabihf
|
||||
aarch64 gcc-aarch64-linux-gnu g++-aarch64-linux-gnu arm64 aarch64-linux-gnu
|
||||
ppc64el gcc-powerpc64le-linux-gnu g++-powerpc64le-linux-gnu ppc64el powerpc64le-linux-gnu
|
||||
s390x gcc-s390x-linux-gnu g++-s390x-linux-gnu s390x s390x-linux-gnu
|
||||
|
||||
Additional architectures might be supported by Debian/Ubuntu Ports.
|
||||
|
||||
|
@ -1,19 +1,24 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="generator" content="pandoc">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
|
||||
<meta charset="utf-8" />
|
||||
<meta name="generator" content="pandoc" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
|
||||
<title>Testing the JDK</title>
|
||||
<style type="text/css">code{white-space: pre;}</style>
|
||||
<link rel="stylesheet" href="../make/data/docs-resources/resources/jdk-default.css">
|
||||
<style type="text/css">
|
||||
code{white-space: pre-wrap;}
|
||||
span.smallcaps{font-variant: small-caps;}
|
||||
span.underline{text-decoration: underline;}
|
||||
div.column{display: inline-block; vertical-align: top; width: 50%;}
|
||||
</style>
|
||||
<link rel="stylesheet" href="../make/data/docs-resources/resources/jdk-default.css" />
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
|
||||
<![endif]-->
|
||||
<style type="text/css">pre, code, tt { color: #1d6ae5; }</style>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<header id="title-block-header">
|
||||
<h1 class="title">Testing the JDK</h1>
|
||||
</header>
|
||||
<nav id="TOC">
|
||||
|
@ -321,7 +321,7 @@ jdk.jshell_COPY += .jsh .properties
|
||||
|
||||
################################################################################
|
||||
|
||||
jdk.internal.le_COPY += .properties
|
||||
jdk.internal.le_COPY += .properties .caps .txt
|
||||
|
||||
################################################################################
|
||||
|
||||
|
@ -91,15 +91,17 @@ TARGETS += $(COMPILE_DEPEND) $(DEPEND_SERVICE_PROVIDER)
|
||||
# To be able to call the javascript filter when generating man pages using
|
||||
# pandoc, we need to create this executable wrapper script.
|
||||
ifneq ($(PANDOC), )
|
||||
# PANDOC_FILTER is duplicated for export in ToolsJdk.gmk.
|
||||
PANDOC_FILTER := $(BUILDTOOLS_OUTPUTDIR)/manpages/pandoc-manpage-filter
|
||||
PANDOC_FILTER_SETUP := $(BUILDTOOLS_OUTPUTDIR)/manpages/_pandoc_filter_setup.marker
|
||||
# PANDOC_TROFF_MANPAGE_FILTER is duplicated for export in ToolsJdk.gmk.
|
||||
PANDOC_TROFF_MANPAGE_FILTER := \
|
||||
$(BUILDTOOLS_OUTPUTDIR)/manpages/pandoc-troff-manpage-filter
|
||||
PANDOC_TROFF_MANPAGE_FILTER_SETUP := \
|
||||
$(BUILDTOOLS_OUTPUTDIR)/manpages/_pandoc_troff_manpage_filter_setup.marker
|
||||
|
||||
# Create a usable instance of the wrapper script that calls the pandoc filter
|
||||
# (which is written in javascript).
|
||||
$(eval $(call SetupTextFileProcessing, CREATE_PANDOC_FILTER, \
|
||||
SOURCE_FILES := $(TOPDIR)/make/scripts/pandoc-manpage-filter.sh.template, \
|
||||
OUTPUT_FILE := $(PANDOC_FILTER), \
|
||||
$(eval $(call SetupTextFileProcessing, CREATE_PANDOC_TROFF_MANPAGE_FILTER, \
|
||||
SOURCE_FILES := $(TOPDIR)/make/scripts/pandoc-troff-manpage-filter.sh.template, \
|
||||
OUTPUT_FILE := $(PANDOC_TROFF_MANPAGE_FILTER), \
|
||||
REPLACEMENTS := \
|
||||
@@BOOT_JDK@@ => $(BOOT_JDK) ; \
|
||||
@@TOPDIR@@ => $(TOPDIR) ; \
|
||||
@ -107,11 +109,35 @@ ifneq ($(PANDOC), )
|
||||
))
|
||||
|
||||
# Created script must be made executable
|
||||
$(PANDOC_FILTER_SETUP): $(CREATE_PANDOC_FILTER)
|
||||
$(CHMOD) a+rx $(PANDOC_FILTER)
|
||||
$(PANDOC_TROFF_MANPAGE_FILTER_SETUP): $(CREATE_PANDOC_TROFF_MANPAGE_FILTER)
|
||||
$(CHMOD) a+rx $(PANDOC_TROFF_MANPAGE_FILTER)
|
||||
$(TOUCH) $@
|
||||
|
||||
TARGETS += $(PANDOC_FILTER_SETUP)
|
||||
TARGETS += $(PANDOC_TROFF_MANPAGE_FILTER_SETUP)
|
||||
|
||||
# PANDOC_HTML_MANPAGE_FILTER is duplicated for export in ToolsJdk.gmk.
|
||||
PANDOC_HTML_MANPAGE_FILTER := \
|
||||
$(BUILDTOOLS_OUTPUTDIR)/manpages/pandoc-html-manpage-filter
|
||||
PANDOC_HTML_MANPAGE_FILTER_SETUP := \
|
||||
$(BUILDTOOLS_OUTPUTDIR)/manpages/_pandoc_html_manpage_filter_setup.marker
|
||||
|
||||
# Create a usable instance of the wrapper script that calls the pandoc filter
|
||||
# (which is written in javascript).
|
||||
$(eval $(call SetupTextFileProcessing, CREATE_PANDOC_HTML_MANPAGE_FILTER, \
|
||||
SOURCE_FILES := $(TOPDIR)/make/scripts/pandoc-html-manpage-filter.sh.template, \
|
||||
OUTPUT_FILE := $(PANDOC_HTML_MANPAGE_FILTER), \
|
||||
REPLACEMENTS := \
|
||||
@@BOOT_JDK@@ => $(BOOT_JDK) ; \
|
||||
@@TOPDIR@@ => $(TOPDIR) ; \
|
||||
@@JJS_FLAGS@@ => $(addprefix -J, $(JAVA_FLAGS_SMALL)), \
|
||||
))
|
||||
|
||||
# Created script must be made executable
|
||||
$(PANDOC_HTML_MANPAGE_FILTER_SETUP): $(CREATE_PANDOC_HTML_MANPAGE_FILTER)
|
||||
$(CHMOD) a+rx $(PANDOC_HTML_MANPAGE_FILTER)
|
||||
$(TOUCH) $@
|
||||
|
||||
TARGETS += $(PANDOC_HTML_MANPAGE_FILTER_SETUP)
|
||||
endif
|
||||
|
||||
all: $(TARGETS)
|
||||
|
@ -27,10 +27,10 @@ default: all
|
||||
include $(SPEC)
|
||||
include MakeBase.gmk
|
||||
include Modules.gmk
|
||||
include ModuleTools.gmk
|
||||
include ProcessMarkdown.gmk
|
||||
include ToolsJdk.gmk
|
||||
include ZipArchive.gmk
|
||||
include $(TOPDIR)/make/ToolsJdk.gmk
|
||||
include $(TOPDIR)/make/ModuleTools.gmk
|
||||
|
||||
# This is needed to properly setup DOCS_MODULES.
|
||||
$(eval $(call ReadImportMetaData))
|
||||
@ -556,6 +556,15 @@ ifeq ($(ENABLE_FULL_DOCS), true)
|
||||
|
||||
# For all markdown files in $module/share/man directories, convert them to
|
||||
# html.
|
||||
|
||||
# Create dynamic man pages from markdown using pandoc. We need
|
||||
# PANDOC_HTML_MANPAGE_FILTER, a wrapper around
|
||||
# PANDOC_HTML_MANPAGE_FILTER_JAVASCRIPT. This is created by buildtools-jdk.
|
||||
|
||||
# We should also depend on the source javascript filter
|
||||
PANDOC_HTML_MANPAGE_FILTER_JAVASCRIPT := \
|
||||
$(TOPDIR)/make/scripts/pandoc-html-manpage-filter.js
|
||||
|
||||
$(foreach m, $(ALL_MODULES), \
|
||||
$(eval MAN_$m := $(call FindModuleManDirs, $m)) \
|
||||
$(foreach d, $(MAN_$m), \
|
||||
@ -565,8 +574,11 @@ ifeq ($(ENABLE_FULL_DOCS), true)
|
||||
SRC := $d, \
|
||||
FILES := $(filter %.md, $(call CacheFind, $d)), \
|
||||
DEST := $(DOCS_OUTPUTDIR)/specs/man, \
|
||||
FILTER := $(PANDOC_HTML_MANPAGE_FILTER), \
|
||||
CSS := $(GLOBAL_SPECS_DEFAULT_CSS_FILE), \
|
||||
REPLACEMENTS := @@VERSION_SHORT@@ => $(VERSION_SHORT), \
|
||||
EXTRA_DEPS := $(PANDOC_HTML_MANPAGE_FILTER) \
|
||||
$(PANDOC_HTML_MANPAGE_FILTER_JAVASCRIPT), \
|
||||
)) \
|
||||
$(eval JDK_SPECS_TARGETS += $($($m_$d_NAME))) \
|
||||
) \
|
||||
|
@ -118,7 +118,8 @@ TOOL_PUBLICSUFFIXLIST = $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_clas
|
||||
|
||||
# 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
|
||||
|
||||
##########################################################################################
|
||||
|
||||
|
@ -80,7 +80,7 @@ define ProcessMarkdown
|
||||
$$(call LogInfo, Converting $2 to $$($1_FORMAT))
|
||||
$$(call MakeDir, $$(SUPPORT_OUTPUTDIR)/markdown $$(dir $$($1_$2_PANDOC_OUTPUT)))
|
||||
$$(call ExecuteWithLog, $$(SUPPORT_OUTPUTDIR)/markdown/$$($1_$2_MARKER), \
|
||||
$$(PANDOC) $$($1_OPTIONS) -f markdown -t $$($1_FORMAT) --standalone \
|
||||
$$(PANDOC) $$($1_OPTIONS) -f markdown-smart -t $$($1_FORMAT) --standalone \
|
||||
$$($1_$2_CSS_OPTION) $$($1_$2_OPTIONS) '$$($1_$2_PANDOC_INPUT)' \
|
||||
-o '$$($1_$2_PANDOC_OUTPUT)')
|
||||
ifneq ($$(findstring $$(LOG_LEVEL), debug trace),)
|
||||
|
@ -207,11 +207,12 @@ ifeq ($(OPENJDK_TARGET_OS_TYPE), unix)
|
||||
$(info Warning: pandoc not found. Not generating man pages)
|
||||
else
|
||||
# Create dynamic man pages from markdown using pandoc. We need
|
||||
# PANDOC_FILTER, a wrapper around PANDOC_FILTER_JAVASCRIPT. This is
|
||||
# created by buildtools-jdk.
|
||||
# PANDOC_TROFF_MANPAGE_FILTER, a wrapper around
|
||||
# PANDOC_TROFF_MANPAGE_FILTER_JAVASCRIPT. This is created by buildtools-jdk.
|
||||
|
||||
# We should also depend on the source javascript filter
|
||||
PANDOC_FILTER_JAVASCRIPT := $(TOPDIR)/make/scripts/pandoc-manpage-filter.js
|
||||
PANDOC_TROFF_MANPAGE_FILTER_JAVASCRIPT := \
|
||||
$(TOPDIR)/make/scripts/pandoc-troff-manpage-filter.js
|
||||
|
||||
# The norm in man pages is to display code literals as bold, but pandoc
|
||||
# "correctly" converts these constructs (encoded in markdown using `...`
|
||||
@ -234,10 +235,11 @@ ifeq ($(OPENJDK_TARGET_OS_TYPE), unix)
|
||||
DEST := $(SUPPORT_OUTPUTDIR)/modules_man/$(MODULE)/man1, \
|
||||
FILES := $(MAN_FILES_MD), \
|
||||
FORMAT := man, \
|
||||
FILTER := $(PANDOC_FILTER), \
|
||||
FILTER := $(PANDOC_TROFF_MANPAGE_FILTER), \
|
||||
POST_PROCESS := $(MAN_POST_PROCESS), \
|
||||
REPLACEMENTS := @@VERSION_SHORT@@ => $(VERSION_SHORT), \
|
||||
EXTRA_DEPS := $(PANDOC_FILTER) $(PANDOC_FILTER_JAVASCRIPT), \
|
||||
EXTRA_DEPS := $(PANDOC_TROFF_MANPAGE_FILTER) \
|
||||
$(PANDOC_TROFF_MANPAGE_FILTER_JAVASCRIPT), \
|
||||
))
|
||||
|
||||
TARGETS += $(BUILD_MAN_PAGES)
|
||||
|
125
make/scripts/pandoc-html-manpage-filter.js
Normal file
125
make/scripts/pandoc-html-manpage-filter.js
Normal 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();
|
@ -25,4 +25,4 @@
|
||||
# Simple wrapper script to call Nashorn with the javascript pandoc filter
|
||||
|
||||
@@BOOT_JDK@@/bin/jjs @@JJS_FLAGS@@ -scripting \
|
||||
"@@TOPDIR@@/make/scripts/pandoc-manpage-filter.js" 2> /dev/null
|
||||
"@@TOPDIR@@/make/scripts/pandoc-html-manpage-filter.js" 2> /dev/null
|
28
make/scripts/pandoc-troff-manpage-filter.sh.template
Normal file
28
make/scripts/pandoc-troff-manpage-filter.sh.template
Normal 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
|
@ -2273,7 +2273,7 @@ void MacroAssembler::tlab_allocate(
|
||||
) {
|
||||
// make sure arguments make sense
|
||||
assert_different_registers(obj, var_size_in_bytes, t1);
|
||||
assert(0 <= con_size_in_bytes && is_simm13(con_size_in_bytes), "illegal object size");
|
||||
assert(0 <= con_size_in_bytes && is_simm16(con_size_in_bytes), "illegal object size");
|
||||
assert((con_size_in_bytes & MinObjAlignmentInBytesMask) == 0, "object size is not multiple of alignment");
|
||||
|
||||
const Register new_top = t1;
|
||||
|
@ -67,6 +67,11 @@
|
||||
" of quotas (if set), when true. Otherwise, use the CPU" \
|
||||
" shares value, provided it is less than quota.") \
|
||||
\
|
||||
diagnostic(bool, DumpPrivateMappingsInCore, true, \
|
||||
"If true, sets bit 2 of /proc/PID/coredump_filter, thus " \
|
||||
"resulting in file-backed private mappings of the process to "\
|
||||
"be dumped into the corefile, if UseSharedSpaces is true.") \
|
||||
\
|
||||
diagnostic(bool, UseCpuAllocPath, false, \
|
||||
"Use CPU_ALLOC code path in os::active_processor_count ")
|
||||
|
||||
|
@ -128,8 +128,12 @@
|
||||
// for timer info max values which include all bits
|
||||
#define ALL_64_BITS CONST64(0xFFFFFFFFFFFFFFFF)
|
||||
|
||||
#define LARGEPAGES_BIT (1 << 6)
|
||||
#define DAX_SHARED_BIT (1 << 8)
|
||||
enum CoredumpFilterBit {
|
||||
FILE_BACKED_PVT_BIT = 1 << 2,
|
||||
LARGEPAGES_BIT = 1 << 6,
|
||||
DAX_SHARED_BIT = 1 << 8
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// global variables
|
||||
julong os::Linux::_physical_memory = 0;
|
||||
@ -1350,6 +1354,9 @@ void os::shutdown() {
|
||||
void os::abort(bool dump_core, void* siginfo, const void* context) {
|
||||
os::shutdown();
|
||||
if (dump_core) {
|
||||
if (UseSharedSpaces && DumpPrivateMappingsInCore) {
|
||||
ClassLoader::close_jrt_image();
|
||||
}
|
||||
#ifndef PRODUCT
|
||||
fdStream out(defaultStream::output_fd());
|
||||
out.print_raw("Current thread is ");
|
||||
@ -3401,10 +3408,9 @@ bool os::Linux::hugetlbfs_sanity_check(bool warn, size_t page_size) {
|
||||
// - (bit 7) dax private memory
|
||||
// - (bit 8) dax shared memory
|
||||
//
|
||||
static void set_coredump_filter(bool largepages, bool dax_shared) {
|
||||
static void set_coredump_filter(CoredumpFilterBit bit) {
|
||||
FILE *f;
|
||||
long cdm;
|
||||
bool filter_changed = false;
|
||||
|
||||
if ((f = fopen("/proc/self/coredump_filter", "r+")) == NULL) {
|
||||
return;
|
||||
@ -3415,17 +3421,11 @@ static void set_coredump_filter(bool largepages, bool dax_shared) {
|
||||
return;
|
||||
}
|
||||
|
||||
long saved_cdm = cdm;
|
||||
rewind(f);
|
||||
cdm |= bit;
|
||||
|
||||
if (largepages && (cdm & LARGEPAGES_BIT) == 0) {
|
||||
cdm |= LARGEPAGES_BIT;
|
||||
filter_changed = true;
|
||||
}
|
||||
if (dax_shared && (cdm & DAX_SHARED_BIT) == 0) {
|
||||
cdm |= DAX_SHARED_BIT;
|
||||
filter_changed = true;
|
||||
}
|
||||
if (filter_changed) {
|
||||
if (cdm != saved_cdm) {
|
||||
fprintf(f, "%#lx", cdm);
|
||||
}
|
||||
|
||||
@ -3564,7 +3564,7 @@ void os::large_page_init() {
|
||||
size_t large_page_size = Linux::setup_large_page_size();
|
||||
UseLargePages = Linux::setup_large_page_type(large_page_size);
|
||||
|
||||
set_coredump_filter(true /*largepages*/, false /*dax_shared*/);
|
||||
set_coredump_filter(LARGEPAGES_BIT);
|
||||
}
|
||||
|
||||
#ifndef SHM_HUGETLB
|
||||
@ -5072,8 +5072,13 @@ jint os::init_2(void) {
|
||||
prio_init();
|
||||
|
||||
if (!FLAG_IS_DEFAULT(AllocateHeapAt)) {
|
||||
set_coredump_filter(false /*largepages*/, true /*dax_shared*/);
|
||||
set_coredump_filter(DAX_SHARED_BIT);
|
||||
}
|
||||
|
||||
if (UseSharedSpaces && DumpPrivateMappingsInCore) {
|
||||
set_coredump_filter(FILE_BACKED_PVT_BIT);
|
||||
}
|
||||
|
||||
return JNI_OK;
|
||||
}
|
||||
|
||||
|
@ -74,15 +74,17 @@
|
||||
// * 63-47 Fixed (17-bits, always zero)
|
||||
//
|
||||
|
||||
const size_t ZPlatformPageSizeSmallShift = 21; // 2M
|
||||
const size_t ZPlatformPageSizeSmallShift = 21; // 2M
|
||||
|
||||
const size_t ZPlatformAddressOffsetBits = 42; // 4TB
|
||||
const size_t ZPlatformAddressOffsetBits = 42; // 4TB
|
||||
|
||||
const uintptr_t ZPlatformAddressMetadataShift = ZPlatformAddressOffsetBits;
|
||||
const uintptr_t ZPlatformAddressMetadataShift = ZPlatformAddressOffsetBits;
|
||||
|
||||
const uintptr_t ZPlatformAddressSpaceStart = (uintptr_t)1 << ZPlatformAddressOffsetBits;
|
||||
const uintptr_t ZPlatformAddressSpaceSize = ((uintptr_t)1 << ZPlatformAddressOffsetBits) * 4;
|
||||
const uintptr_t ZPlatformAddressSpaceStart = (uintptr_t)1 << ZPlatformAddressOffsetBits;
|
||||
const uintptr_t ZPlatformAddressSpaceSize = ((uintptr_t)1 << ZPlatformAddressOffsetBits) * 4;
|
||||
|
||||
const size_t ZPlatformCacheLineSize = 64;
|
||||
const size_t ZPlatformNMethodDisarmedOffset = 4;
|
||||
|
||||
const size_t ZPlatformCacheLineSize = 64;
|
||||
|
||||
#endif // OS_CPU_LINUX_X86_ZGLOBALS_LINUX_X86_HPP
|
||||
|
@ -5733,7 +5733,8 @@ void ClassFileParser::fill_instance_klass(InstanceKlass* ik, bool changed_by_loa
|
||||
ik->major_version() != JAVA_MIN_SUPPORTED_VERSION &&
|
||||
log_is_enabled(Info, class, preview)) {
|
||||
ResourceMark rm;
|
||||
log_info(class, preview)("Loading preview feature type %s", ik->external_name());
|
||||
log_info(class, preview)("Loading class %s that depends on preview features (class file version %d.65535)",
|
||||
ik->external_name(), ik->major_version());
|
||||
}
|
||||
|
||||
if (log_is_enabled(Debug, class, resolve)) {
|
||||
|
@ -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) :
|
||||
ClassPathEntry(),
|
||||
_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) {
|
||||
update_module_path_entry_list(path, THREAD);
|
||||
}
|
||||
|
||||
void ClassLoader::close_jrt_image() {
|
||||
assert(ClassLoader::has_jrt_entry(), "Not applicable for exploded builds");
|
||||
_jrt_entry->close_jimage();
|
||||
}
|
||||
|
||||
#endif // INCLUDE_CDS
|
||||
|
||||
// Construct the array of module/path pairs as specified to --patch-module
|
||||
|
@ -55,6 +55,7 @@ public:
|
||||
virtual bool is_jar_file() const = 0;
|
||||
virtual const char* name() const = 0;
|
||||
virtual JImageFile* jimage() const = 0;
|
||||
virtual void close_jimage() = 0;
|
||||
// Constructor
|
||||
ClassPathEntry() : _next(NULL) {}
|
||||
// Attempt to locate file_name through this class path entry.
|
||||
@ -70,6 +71,7 @@ class ClassPathDirEntry: public ClassPathEntry {
|
||||
bool is_jar_file() const { return false; }
|
||||
const char* name() const { return _dir; }
|
||||
JImageFile* jimage() const { return NULL; }
|
||||
void close_jimage() {}
|
||||
ClassPathDirEntry(const char* dir);
|
||||
virtual ~ClassPathDirEntry() {}
|
||||
ClassFileStream* open_stream(const char* name, TRAPS);
|
||||
@ -98,6 +100,7 @@ class ClassPathZipEntry: public ClassPathEntry {
|
||||
bool is_jar_file() const { return true; }
|
||||
const char* name() const { return _zip_name; }
|
||||
JImageFile* jimage() const { return NULL; }
|
||||
void close_jimage() {}
|
||||
ClassPathZipEntry(jzfile* zip, const char* zip_name, bool is_boot_append);
|
||||
virtual ~ClassPathZipEntry();
|
||||
u1* open_entry(const char* name, jint* filesize, bool nul_terminate, TRAPS);
|
||||
@ -117,6 +120,7 @@ public:
|
||||
bool is_open() const { return _jimage != NULL; }
|
||||
const char* name() const { return _name == NULL ? "" : _name; }
|
||||
JImageFile* jimage() const { return _jimage; }
|
||||
void close_jimage();
|
||||
ClassPathImageEntry(JImageFile* jimage, const char* name);
|
||||
virtual ~ClassPathImageEntry();
|
||||
ClassFileStream* open_stream(const char* name, TRAPS);
|
||||
@ -333,6 +337,7 @@ class ClassLoader: AllStatic {
|
||||
// Modular java runtime image is present vs. a build with exploded modules
|
||||
static bool has_jrt_entry() { return (_jrt_entry != NULL); }
|
||||
static ClassPathEntry* get_jrt_entry() { return _jrt_entry; }
|
||||
static void close_jrt_image();
|
||||
|
||||
// Add a module's exploded directory to the boot loader's exploded module build list
|
||||
static void add_to_exploded_build_list(Symbol* module_name, TRAPS);
|
||||
|
@ -116,14 +116,17 @@ public:
|
||||
return SymbolTableHash::BaseConfig::allocate_node(size, value);
|
||||
}
|
||||
static void free_node(void* memory, Symbol* const& value) {
|
||||
// We get here either because #1 some threads lost a race
|
||||
// to insert a newly created Symbol, or #2 we are freeing
|
||||
// a symbol during normal cleanup deletion.
|
||||
// If #1, then the symbol can be a permanent (refcount==PERM_REFCOUNT),
|
||||
// or regular newly created one but with refcount==0 (see SymbolTableCreateEntry)
|
||||
// If #2, then the symbol must have refcount==0
|
||||
assert((value->refcount() == PERM_REFCOUNT) || (value->refcount() == 0),
|
||||
// We get here because #1 some threads lost a race to insert a newly created Symbol
|
||||
// or #2 we're cleaning up unused symbol.
|
||||
// If #1, then the symbol can be either permanent (refcount==PERM_REFCOUNT),
|
||||
// or regular newly created one (refcount==1)
|
||||
// If #2, then the symbol is dead (refcount==0)
|
||||
assert((value->refcount() == PERM_REFCOUNT) || (value->refcount() == 1) || (value->refcount() == 0),
|
||||
"refcount %d", value->refcount());
|
||||
if (value->refcount() == 1) {
|
||||
value->decrement_refcount();
|
||||
assert(value->refcount() == 0, "expected dead symbol");
|
||||
}
|
||||
SymbolTable::delete_symbol(value);
|
||||
SymbolTableHash::BaseConfig::free_node(memory, value);
|
||||
SymbolTable::item_removed();
|
||||
@ -162,6 +165,12 @@ void SymbolTable::delete_symbol(Symbol* sym) {
|
||||
}
|
||||
}
|
||||
|
||||
void SymbolTable::update_needs_rehash(bool rehash) {
|
||||
if (rehash) {
|
||||
_needs_rehashing = true;
|
||||
}
|
||||
}
|
||||
|
||||
void SymbolTable::item_added() {
|
||||
Atomic::inc(&(SymbolTable::the_table()->_items_count));
|
||||
}
|
||||
@ -398,9 +407,7 @@ Symbol* SymbolTable::do_lookup(const char* name, int len, uintx hash) {
|
||||
SymbolTableGet stg;
|
||||
bool rehash_warning = false;
|
||||
_local_table->get(thread, lookup, stg, &rehash_warning);
|
||||
if (rehash_warning) {
|
||||
_needs_rehashing = true;
|
||||
}
|
||||
update_needs_rehash(rehash_warning);
|
||||
Symbol* sym = stg.get_res_sym();
|
||||
assert((sym == NULL) || sym->refcount() != 0, "found dead symbol");
|
||||
return sym;
|
||||
@ -462,71 +469,26 @@ 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) {
|
||||
SymbolTableLookup lookup(THREAD, name, len, hash);
|
||||
SymbolTableCreateEntry stce(THREAD, name, len, heap);
|
||||
bool rehash_warning = false;
|
||||
SymbolTableGet stg;
|
||||
bool clean_hint = false;
|
||||
_local_table->get_insert_lazy(THREAD, lookup, stce, stce, &rehash_warning, &clean_hint);
|
||||
if (rehash_warning) {
|
||||
_needs_rehashing = true;
|
||||
}
|
||||
bool rehash_warning = false;
|
||||
Symbol* sym = NULL;
|
||||
|
||||
do {
|
||||
if (_local_table->get(THREAD, lookup, stg, &rehash_warning)) {
|
||||
sym = stg.get_res_sym();
|
||||
break;
|
||||
}
|
||||
sym = SymbolTable::the_table()->allocate_symbol(name, len, heap, THREAD);
|
||||
if (_local_table->insert(THREAD, lookup, sym, &rehash_warning, &clean_hint)) {
|
||||
break;
|
||||
}
|
||||
} while(true);
|
||||
|
||||
update_needs_rehash(rehash_warning);
|
||||
|
||||
if (clean_hint) {
|
||||
// we just found out that there is a dead item,
|
||||
// which we were unable to clean right now,
|
||||
@ -536,8 +498,8 @@ Symbol* SymbolTable::do_add_if_needed(const char* name, int len, uintx hash, boo
|
||||
mark_item_clean_count();
|
||||
check_concurrent_work();
|
||||
}
|
||||
Symbol* sym = stce.get_new_sym();
|
||||
assert(sym->refcount() != 0, "zero is invalid");
|
||||
|
||||
assert((sym == NULL) || sym->refcount() != 0, "found dead symbol");
|
||||
return sym;
|
||||
}
|
||||
|
||||
|
@ -169,6 +169,7 @@ private:
|
||||
|
||||
void try_rehash_table();
|
||||
bool do_rehash();
|
||||
inline void update_needs_rehash(bool rehash);
|
||||
|
||||
public:
|
||||
// The symbol table
|
||||
|
@ -70,19 +70,24 @@ CMSHeap::CMSHeap(GenCollectorPolicy *policy) :
|
||||
Generation::ParNew,
|
||||
Generation::ConcurrentMarkSweep,
|
||||
"ParNew:CMS"),
|
||||
_workers(NULL),
|
||||
_eden_pool(NULL),
|
||||
_survivor_pool(NULL),
|
||||
_old_pool(NULL) {
|
||||
_workers = new WorkGang("GC Thread", ParallelGCThreads,
|
||||
/* are_GC_task_threads */true,
|
||||
/* are_ConcurrentGC_threads */false);
|
||||
_workers->initialize_workers();
|
||||
}
|
||||
|
||||
jint CMSHeap::initialize() {
|
||||
jint status = GenCollectedHeap::initialize();
|
||||
if (status != JNI_OK) return status;
|
||||
|
||||
_workers = new WorkGang("GC Thread", ParallelGCThreads,
|
||||
/* are_GC_task_threads */true,
|
||||
/* are_ConcurrentGC_threads */false);
|
||||
if (_workers == NULL) {
|
||||
return JNI_ENOMEM;
|
||||
}
|
||||
_workers->initialize_workers();
|
||||
|
||||
// If we are running CMS, create the collector responsible
|
||||
// for collecting the CMS generations.
|
||||
if (!create_cms_collector()) {
|
||||
|
@ -1531,10 +1531,6 @@ G1CollectedHeap::G1CollectedHeap(G1CollectorPolicy* collector_policy) :
|
||||
_is_subject_to_discovery_cm(this),
|
||||
_in_cset_fast_test() {
|
||||
|
||||
_workers = new WorkGang("GC Thread", ParallelGCThreads,
|
||||
true /* are_GC_task_threads */,
|
||||
false /* are_ConcurrentGC_threads */);
|
||||
_workers->initialize_workers();
|
||||
_verifier = new G1HeapVerifier(this);
|
||||
|
||||
_allocator = new G1Allocator(this);
|
||||
@ -1767,6 +1763,14 @@ jint G1CollectedHeap::initialize() {
|
||||
_humongous_reclaim_candidates.initialize(start, end, granularity);
|
||||
}
|
||||
|
||||
_workers = new WorkGang("GC Thread", ParallelGCThreads,
|
||||
true /* are_GC_task_threads */,
|
||||
false /* are_ConcurrentGC_threads */);
|
||||
if (_workers == NULL) {
|
||||
return JNI_ENOMEM;
|
||||
}
|
||||
_workers->initialize_workers();
|
||||
|
||||
// Create the G1ConcurrentMark data structure and thread.
|
||||
// (Must do this late, so that "max_regions" is defined.)
|
||||
_cm = new G1ConcurrentMark(this, prev_bitmap_storage, next_bitmap_storage);
|
||||
|
@ -26,47 +26,24 @@
|
||||
#include "gc/shared/barrierSet.hpp"
|
||||
#include "gc/shared/barrierSetAssembler.hpp"
|
||||
#include "runtime/thread.hpp"
|
||||
#include "utilities/debug.hpp"
|
||||
#include "utilities/macros.hpp"
|
||||
|
||||
BarrierSet* BarrierSet::_barrier_set = NULL;
|
||||
|
||||
class SetBarrierSetNonJavaThread : public ThreadClosure {
|
||||
BarrierSet* _barrier_set;
|
||||
size_t _count;
|
||||
|
||||
public:
|
||||
SetBarrierSetNonJavaThread(BarrierSet* barrier_set) :
|
||||
_barrier_set(barrier_set), _count(0) {}
|
||||
|
||||
virtual void do_thread(Thread* thread) {
|
||||
_barrier_set->on_thread_create(thread);
|
||||
++_count;
|
||||
}
|
||||
|
||||
size_t count() const { return _count; }
|
||||
};
|
||||
|
||||
void BarrierSet::set_barrier_set(BarrierSet* barrier_set) {
|
||||
assert(_barrier_set == NULL, "Already initialized");
|
||||
_barrier_set = barrier_set;
|
||||
|
||||
// Some threads are created before the barrier set, so the call to
|
||||
// BarrierSet::on_thread_create had to be deferred for them. Now that
|
||||
// we have the barrier set, do those deferred calls.
|
||||
|
||||
// First do any non-JavaThreads.
|
||||
SetBarrierSetNonJavaThread njt_closure(_barrier_set);
|
||||
Threads::non_java_threads_do(&njt_closure);
|
||||
|
||||
// Do the current (main) thread. Ensure it's the one and only
|
||||
// JavaThread so far. Also verify that it isn't yet on the thread
|
||||
// Notify barrier set of the current (main) thread. Normally the
|
||||
// Thread constructor deals with this, but the main thread is
|
||||
// created before we get here. Verify it isn't yet on the thread
|
||||
// list, else we'd also need to call BarrierSet::on_thread_attach.
|
||||
// This is the only thread that can exist at this point; the Thread
|
||||
// constructor objects to other threads being created before the
|
||||
// barrier set is available.
|
||||
assert(Thread::current()->is_Java_thread(),
|
||||
"Expected main thread to be a JavaThread");
|
||||
assert((njt_closure.count() + 1) == Threads::threads_before_barrier_set(),
|
||||
"Unexpected JavaThreads before barrier set initialization: "
|
||||
"Non-JavaThreads: " SIZE_FORMAT ", all: " SIZE_FORMAT,
|
||||
njt_closure.count(), Threads::threads_before_barrier_set());
|
||||
assert(!JavaThread::current()->on_thread_list(),
|
||||
"Main thread already on thread list.");
|
||||
_barrier_set->on_thread_create(Thread::current());
|
||||
|
@ -80,10 +80,6 @@ void ZArguments::initialize() {
|
||||
FLAG_SET_DEFAULT(UseCompressedOops, false);
|
||||
FLAG_SET_DEFAULT(UseCompressedClassPointers, false);
|
||||
|
||||
// ClassUnloading not (yet) supported
|
||||
FLAG_SET_DEFAULT(ClassUnloading, false);
|
||||
FLAG_SET_DEFAULT(ClassUnloadingWithConcurrentMark, false);
|
||||
|
||||
// Verification before startup and after exit not (yet) supported
|
||||
FLAG_SET_DEFAULT(VerifyDuringStartup, false);
|
||||
FLAG_SET_DEFAULT(VerifyBeforeExit, false);
|
||||
|
@ -81,6 +81,7 @@ public:
|
||||
static void load_barrier_on_oop_fields(oop o);
|
||||
static oop load_barrier_on_weak_oop_field_preloaded(volatile oop* p, oop o);
|
||||
static oop load_barrier_on_phantom_oop_field_preloaded(volatile oop* p, oop o);
|
||||
static void load_barrier_on_root_oop_field(oop* p);
|
||||
|
||||
// Weak load barrier
|
||||
static oop weak_load_barrier_on_oop_field(volatile oop* p);
|
||||
@ -99,6 +100,7 @@ public:
|
||||
// Keep alive barrier
|
||||
static void keep_alive_barrier_on_weak_oop_field(volatile oop* p);
|
||||
static void keep_alive_barrier_on_phantom_oop_field(volatile oop* p);
|
||||
static void keep_alive_barrier_on_phantom_root_oop_field(oop* p);
|
||||
|
||||
// Mark barrier
|
||||
static void mark_barrier_on_oop_field(volatile oop* p, bool finalizable);
|
||||
|
@ -111,11 +111,12 @@ inline void ZBarrier::root_barrier(oop* p, oop o) {
|
||||
const uintptr_t good_addr = slow_path(addr);
|
||||
|
||||
// Non-atomic healing helps speed up root scanning. This is safe to do
|
||||
// since we are always healing roots in a safepoint, which means we are
|
||||
// never racing with mutators modifying roots while we are healing them.
|
||||
// It's also safe in case multiple GC threads try to heal the same root,
|
||||
// since they would always heal the root in the same way and it does not
|
||||
// matter in which order it happens.
|
||||
// since we are always healing roots in a safepoint, or under a lock,
|
||||
// which ensures we are never racing with mutators modifying roots while
|
||||
// we are healing them. It's also safe in case multiple GC threads try
|
||||
// to heal the same root if it is aligned, since they would always heal
|
||||
// the root in the same way and it does not matter in which order it
|
||||
// happens. For misaligned oops, there needs to be mutual exclusion.
|
||||
*p = ZOop::to_oop(good_addr);
|
||||
}
|
||||
|
||||
@ -188,6 +189,11 @@ inline oop ZBarrier::load_barrier_on_phantom_oop_field_preloaded(volatile oop* p
|
||||
return load_barrier_on_oop_field_preloaded(p, o);
|
||||
}
|
||||
|
||||
inline void ZBarrier::load_barrier_on_root_oop_field(oop* p) {
|
||||
const oop o = *p;
|
||||
root_barrier<is_good_or_null_fast_path, load_barrier_on_oop_slow_path>(p, o);
|
||||
}
|
||||
|
||||
//
|
||||
// Weak load barrier
|
||||
//
|
||||
@ -269,6 +275,13 @@ 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);
|
||||
}
|
||||
|
||||
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
|
||||
//
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "precompiled.hpp"
|
||||
#include "gc/z/zBarrierSet.hpp"
|
||||
#include "gc/z/zBarrierSetAssembler.hpp"
|
||||
#include "gc/z/zBarrierSetNMethod.hpp"
|
||||
#include "gc/z/zGlobals.hpp"
|
||||
#include "gc/z/zHeap.inline.hpp"
|
||||
#include "gc/z/zThreadLocalData.hpp"
|
||||
@ -39,11 +40,20 @@
|
||||
class ZBarrierSetC1;
|
||||
class ZBarrierSetC2;
|
||||
|
||||
static BarrierSetNMethod* make_barrier_set_nmethod() {
|
||||
// NMethod barriers are only used when class unloading is enabled
|
||||
if (!ClassUnloading) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return new ZBarrierSetNMethod();
|
||||
}
|
||||
|
||||
ZBarrierSet::ZBarrierSet() :
|
||||
BarrierSet(make_barrier_set_assembler<ZBarrierSetAssembler>(),
|
||||
make_barrier_set_c1<ZBarrierSetC1>(),
|
||||
make_barrier_set_c2<ZBarrierSetC2>(),
|
||||
NULL /* barrier_set_nmethod */,
|
||||
make_barrier_set_nmethod(),
|
||||
BarrierSet::FakeRtti(BarrierSet::ZBarrierSet)) {}
|
||||
|
||||
ZBarrierSetAssembler* ZBarrierSet::assembler() {
|
||||
|
73
src/hotspot/share/gc/z/zBarrierSetNMethod.cpp
Normal file
73
src/hotspot/share/gc/z/zBarrierSetNMethod.cpp
Normal 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();
|
||||
}
|
41
src/hotspot/share/gc/z/zBarrierSetNMethod.hpp
Normal file
41
src/hotspot/share/gc/z/zBarrierSetNMethod.hpp
Normal 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
|
@ -259,12 +259,10 @@ bool ZCollectedHeap::block_is_obj(const HeapWord* addr) const {
|
||||
}
|
||||
|
||||
void ZCollectedHeap::register_nmethod(nmethod* nm) {
|
||||
assert_locked_or_safepoint(CodeCache_lock);
|
||||
ZNMethodTable::register_nmethod(nm);
|
||||
}
|
||||
|
||||
void ZCollectedHeap::unregister_nmethod(nmethod* nm) {
|
||||
assert_locked_or_safepoint(CodeCache_lock);
|
||||
ZNMethodTable::unregister_nmethod(nm);
|
||||
}
|
||||
|
||||
|
@ -91,6 +91,9 @@ const uintptr_t ZAddressSpaceStart = ZPlatformAddressSpaceStart;
|
||||
const uintptr_t ZAddressSpaceSize = ZPlatformAddressSpaceSize;
|
||||
const uintptr_t ZAddressSpaceEnd = ZAddressSpaceStart + ZAddressSpaceSize;
|
||||
|
||||
// NMethod entry barrier
|
||||
const size_t ZNMethodDisarmedOffset = ZPlatformNMethodDisarmedOffset;
|
||||
|
||||
// Cache line size
|
||||
const size_t ZCacheLineSize = ZPlatformCacheLineSize;
|
||||
|
||||
|
@ -69,6 +69,7 @@ ZHeap::ZHeap() :
|
||||
_weak_roots_processor(&_workers),
|
||||
_relocate(&_workers),
|
||||
_relocation_set(),
|
||||
_unload(&_workers),
|
||||
_serviceability(heap_min_size(), heap_max_size()) {
|
||||
// Install global heap instance
|
||||
assert(_heap == NULL, "Already initialized");
|
||||
@ -353,9 +354,6 @@ bool ZHeap::mark_end() {
|
||||
// Enter mark completed phase
|
||||
ZGlobalPhase = ZPhaseMarkCompleted;
|
||||
|
||||
// Resize metaspace
|
||||
MetaspaceGC::compute_new_size();
|
||||
|
||||
// Update statistics
|
||||
ZStatSample(ZSamplerHeapUsedAfterMark, used());
|
||||
ZStatHeap::set_at_mark_end(capacity(), allocated(), used());
|
||||
@ -366,6 +364,9 @@ bool ZHeap::mark_end() {
|
||||
// Process weak roots
|
||||
_weak_roots_processor.process_weak_roots();
|
||||
|
||||
// Prepare to unload unused classes and code
|
||||
_unload.prepare();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -380,6 +381,9 @@ void ZHeap::process_non_strong_references() {
|
||||
// Process concurrent weak roots
|
||||
_weak_roots_processor.process_concurrent_weak_roots();
|
||||
|
||||
// Unload unused classes and code
|
||||
_unload.unload();
|
||||
|
||||
// Unblock resurrection of weak/phantom references
|
||||
ZResurrection::unblock();
|
||||
|
||||
@ -463,8 +467,8 @@ void ZHeap::reset_relocation_set() {
|
||||
void ZHeap::relocate_start() {
|
||||
assert(SafepointSynchronize::is_at_safepoint(), "Should be at safepoint");
|
||||
|
||||
// Update statistics
|
||||
ZStatSample(ZSamplerHeapUsedBeforeRelocation, used());
|
||||
// Finish unloading of classes and code
|
||||
_unload.finish();
|
||||
|
||||
// Flip address view
|
||||
ZAddressMasks::flip_to_remapped();
|
||||
@ -474,6 +478,7 @@ void ZHeap::relocate_start() {
|
||||
ZGlobalPhase = ZPhaseRelocate;
|
||||
|
||||
// Update statistics
|
||||
ZStatSample(ZSamplerHeapUsedBeforeRelocation, used());
|
||||
ZStatHeap::set_at_relocate_start(capacity(), allocated(), used());
|
||||
|
||||
// Remap/Relocate roots
|
||||
|
@ -41,6 +41,7 @@
|
||||
#include "gc/z/zRootsIterator.hpp"
|
||||
#include "gc/z/zWeakRootsProcessor.hpp"
|
||||
#include "gc/z/zServiceability.hpp"
|
||||
#include "gc/z/zUnload.hpp"
|
||||
#include "gc/z/zWorkers.hpp"
|
||||
#include "memory/allocation.hpp"
|
||||
|
||||
@ -59,6 +60,7 @@ private:
|
||||
ZWeakRootsProcessor _weak_roots_processor;
|
||||
ZRelocate _relocate;
|
||||
ZRelocationSet _relocation_set;
|
||||
ZUnload _unload;
|
||||
ZServiceability _serviceability;
|
||||
|
||||
size_t heap_min_size() const;
|
||||
|
@ -287,6 +287,14 @@ void ZMark::follow_partial_array(ZMarkStackEntry entry, 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 size_t size = (size_t)obj->length() * oopSize;
|
||||
|
||||
|
@ -23,45 +23,62 @@
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "code/relocInfo.hpp"
|
||||
#include "code/nativeInst.hpp"
|
||||
#include "code/nmethod.hpp"
|
||||
#include "code/icBuffer.hpp"
|
||||
#include "gc/shared/barrierSet.hpp"
|
||||
#include "gc/shared/barrierSetNMethod.hpp"
|
||||
#include "gc/z/zArray.inline.hpp"
|
||||
#include "gc/z/zGlobals.hpp"
|
||||
#include "gc/z/zHash.inline.hpp"
|
||||
#include "gc/z/zLock.inline.hpp"
|
||||
#include "gc/z/zNMethodTable.hpp"
|
||||
#include "gc/z/zOopClosures.inline.hpp"
|
||||
#include "gc/z/zTask.hpp"
|
||||
#include "gc/z/zWorkers.hpp"
|
||||
#include "logging/log.hpp"
|
||||
#include "memory/allocation.inline.hpp"
|
||||
#include "memory/resourceArea.hpp"
|
||||
#include "oops/oop.inline.hpp"
|
||||
#include "runtime/atomic.hpp"
|
||||
#include "runtime/orderAccess.hpp"
|
||||
#include "runtime/os.hpp"
|
||||
#include "utilities/debug.hpp"
|
||||
|
||||
class ZNMethodWithImmediateOops {
|
||||
class ZNMethodDataImmediateOops {
|
||||
private:
|
||||
nmethod* const _nm;
|
||||
const size_t _nimmediate_oops;
|
||||
const size_t _nimmediate_oops;
|
||||
|
||||
static size_t header_size();
|
||||
|
||||
ZNMethodWithImmediateOops(nmethod* nm, const GrowableArray<oop*>& immediate_oops);
|
||||
ZNMethodDataImmediateOops(const GrowableArray<oop*>& immediate_oops);
|
||||
|
||||
public:
|
||||
static ZNMethodWithImmediateOops* create(nmethod* nm, const GrowableArray<oop*>& immediate_oops);
|
||||
static void destroy(ZNMethodWithImmediateOops* nmi);
|
||||
static ZNMethodDataImmediateOops* create(const GrowableArray<oop*>& immediate_oops);
|
||||
static void destroy(ZNMethodDataImmediateOops* data_immediate_oops);
|
||||
|
||||
nmethod* method() const;
|
||||
size_t immediate_oops_count() const;
|
||||
oop** immediate_oops_begin() const;
|
||||
oop** immediate_oops_end() const;
|
||||
};
|
||||
|
||||
size_t ZNMethodWithImmediateOops::header_size() {
|
||||
const size_t size = sizeof(ZNMethodWithImmediateOops);
|
||||
size_t ZNMethodDataImmediateOops::header_size() {
|
||||
const size_t size = sizeof(ZNMethodDataImmediateOops);
|
||||
assert(is_aligned(size, sizeof(oop*)), "Header misaligned");
|
||||
return size;
|
||||
}
|
||||
|
||||
ZNMethodWithImmediateOops::ZNMethodWithImmediateOops(nmethod* nm, const GrowableArray<oop*>& immediate_oops) :
|
||||
_nm(nm),
|
||||
ZNMethodDataImmediateOops* ZNMethodDataImmediateOops::create(const GrowableArray<oop*>& immediate_oops) {
|
||||
// Allocate memory for the ZNMethodDataImmediateOops object
|
||||
// plus the immediate oop* array that follows right after.
|
||||
const size_t size = ZNMethodDataImmediateOops::header_size() + (sizeof(oop*) * immediate_oops.length());
|
||||
void* const data_immediate_oops = NEW_C_HEAP_ARRAY(uint8_t, size, mtGC);
|
||||
return ::new (data_immediate_oops) ZNMethodDataImmediateOops(immediate_oops);
|
||||
}
|
||||
|
||||
void ZNMethodDataImmediateOops::destroy(ZNMethodDataImmediateOops* data_immediate_oops) {
|
||||
ZNMethodTable::safe_delete(data_immediate_oops);
|
||||
}
|
||||
|
||||
ZNMethodDataImmediateOops::ZNMethodDataImmediateOops(const GrowableArray<oop*>& immediate_oops) :
|
||||
_nimmediate_oops(immediate_oops.length()) {
|
||||
// Save all immediate oops
|
||||
for (size_t i = 0; i < _nimmediate_oops; i++) {
|
||||
@ -69,41 +86,97 @@ ZNMethodWithImmediateOops::ZNMethodWithImmediateOops(nmethod* nm, const Growable
|
||||
}
|
||||
}
|
||||
|
||||
ZNMethodWithImmediateOops* ZNMethodWithImmediateOops::create(nmethod* nm, const GrowableArray<oop*>& immediate_oops) {
|
||||
// Allocate memory for the ZNMethodWithImmediateOops object
|
||||
// plus the immediate oop* array that follows right after.
|
||||
const size_t size = header_size() + (sizeof(oop*) * immediate_oops.length());
|
||||
void* const method_with_immediate_oops = NEW_C_HEAP_ARRAY(uint8_t, size, mtGC);
|
||||
return ::new (method_with_immediate_oops) ZNMethodWithImmediateOops(nm, immediate_oops);
|
||||
}
|
||||
|
||||
void ZNMethodWithImmediateOops::destroy(ZNMethodWithImmediateOops* nmi) {
|
||||
FREE_C_HEAP_ARRAY(uint8_t, nmi);
|
||||
}
|
||||
|
||||
nmethod* ZNMethodWithImmediateOops::method() const {
|
||||
return _nm;
|
||||
}
|
||||
|
||||
size_t ZNMethodWithImmediateOops::immediate_oops_count() const {
|
||||
size_t ZNMethodDataImmediateOops::immediate_oops_count() const {
|
||||
return _nimmediate_oops;
|
||||
}
|
||||
|
||||
oop** ZNMethodWithImmediateOops::immediate_oops_begin() const {
|
||||
oop** ZNMethodDataImmediateOops::immediate_oops_begin() const {
|
||||
// The immediate oop* array starts immediately after this object
|
||||
return (oop**)((uintptr_t)this + header_size());
|
||||
}
|
||||
|
||||
oop** ZNMethodWithImmediateOops::immediate_oops_end() const {
|
||||
oop** ZNMethodDataImmediateOops::immediate_oops_end() const {
|
||||
return immediate_oops_begin() + immediate_oops_count();
|
||||
}
|
||||
|
||||
class ZNMethodData {
|
||||
private:
|
||||
ZReentrantLock _lock;
|
||||
ZNMethodDataImmediateOops* volatile _immediate_oops;
|
||||
|
||||
ZNMethodData(nmethod* nm);
|
||||
|
||||
public:
|
||||
static ZNMethodData* create(nmethod* nm);
|
||||
static void destroy(ZNMethodData* data);
|
||||
|
||||
ZReentrantLock* lock();
|
||||
|
||||
ZNMethodDataImmediateOops* immediate_oops() const;
|
||||
ZNMethodDataImmediateOops* swap_immediate_oops(const GrowableArray<oop*>& immediate_oops);
|
||||
};
|
||||
|
||||
ZNMethodData* ZNMethodData::create(nmethod* nm) {
|
||||
void* const method = NEW_C_HEAP_ARRAY(uint8_t, sizeof(ZNMethodData), mtGC);
|
||||
return ::new (method) ZNMethodData(nm);
|
||||
}
|
||||
|
||||
void ZNMethodData::destroy(ZNMethodData* data) {
|
||||
ZNMethodDataImmediateOops::destroy(data->immediate_oops());
|
||||
ZNMethodTable::safe_delete(data);
|
||||
}
|
||||
|
||||
ZNMethodData::ZNMethodData(nmethod* nm) :
|
||||
_lock(),
|
||||
_immediate_oops(NULL) {}
|
||||
|
||||
ZReentrantLock* ZNMethodData::lock() {
|
||||
return &_lock;
|
||||
}
|
||||
|
||||
ZNMethodDataImmediateOops* ZNMethodData::immediate_oops() const {
|
||||
return OrderAccess::load_acquire(&_immediate_oops);
|
||||
}
|
||||
|
||||
ZNMethodDataImmediateOops* ZNMethodData::swap_immediate_oops(const GrowableArray<oop*>& immediate_oops) {
|
||||
ZNMethodDataImmediateOops* const data_immediate_oops =
|
||||
immediate_oops.is_empty() ? NULL : ZNMethodDataImmediateOops::create(immediate_oops);
|
||||
return Atomic::xchg(data_immediate_oops, &_immediate_oops);
|
||||
}
|
||||
|
||||
static ZNMethodData* gc_data(const nmethod* nm) {
|
||||
return nm->gc_data<ZNMethodData>();
|
||||
}
|
||||
|
||||
static void set_gc_data(nmethod* nm, ZNMethodData* data) {
|
||||
return nm->set_gc_data<ZNMethodData>(data);
|
||||
}
|
||||
|
||||
ZNMethodTableEntry* ZNMethodTable::_table = NULL;
|
||||
size_t ZNMethodTable::_size = 0;
|
||||
ZLock ZNMethodTable::_iter_lock;
|
||||
ZNMethodTableEntry* ZNMethodTable::_iter_table = NULL;
|
||||
size_t ZNMethodTable::_iter_table_size = 0;
|
||||
ZArray<void*> ZNMethodTable::_iter_deferred_deletes;
|
||||
size_t ZNMethodTable::_nregistered = 0;
|
||||
size_t ZNMethodTable::_nunregistered = 0;
|
||||
volatile size_t ZNMethodTable::_claimed = 0;
|
||||
|
||||
void ZNMethodTable::safe_delete(void* data) {
|
||||
if (data == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
ZLocker<ZLock> locker(&_iter_lock);
|
||||
if (_iter_table != NULL) {
|
||||
// Iteration in progress, defer delete
|
||||
_iter_deferred_deletes.add(data);
|
||||
} else {
|
||||
// Iteration not in progress, delete now
|
||||
FREE_C_HEAP_ARRAY(uint8_t, data);
|
||||
}
|
||||
}
|
||||
|
||||
ZNMethodTableEntry ZNMethodTable::create_entry(nmethod* nm) {
|
||||
GrowableArray<oop*> immediate_oops;
|
||||
bool non_immediate_oops = false;
|
||||
@ -132,29 +205,27 @@ ZNMethodTableEntry ZNMethodTable::create_entry(nmethod* nm) {
|
||||
}
|
||||
}
|
||||
|
||||
// oops_count() returns the number of oops in the oop table plus one
|
||||
if (immediate_oops.is_empty() && nm->oops_count() == 1) {
|
||||
// No oops found, return empty entry
|
||||
return ZNMethodTableEntry();
|
||||
// Attach GC data to nmethod
|
||||
ZNMethodData* data = gc_data(nm);
|
||||
if (data == NULL) {
|
||||
data = ZNMethodData::create(nm);
|
||||
set_gc_data(nm, data);
|
||||
}
|
||||
|
||||
if (immediate_oops.is_empty()) {
|
||||
// No immediate oops found, return entry without immediate oops
|
||||
return ZNMethodTableEntry(nm, non_immediate_oops);
|
||||
}
|
||||
// Attach immediate oops in GC data
|
||||
ZNMethodDataImmediateOops* const old_data_immediate_oops = data->swap_immediate_oops(immediate_oops);
|
||||
ZNMethodDataImmediateOops::destroy(old_data_immediate_oops);
|
||||
|
||||
// Return entry with immediate oops
|
||||
return ZNMethodTableEntry(ZNMethodWithImmediateOops::create(nm, immediate_oops), non_immediate_oops);
|
||||
// Create entry
|
||||
return ZNMethodTableEntry(nm, non_immediate_oops, !immediate_oops.is_empty());
|
||||
}
|
||||
|
||||
void ZNMethodTable::destroy_entry(ZNMethodTableEntry entry) {
|
||||
if (entry.immediate_oops()) {
|
||||
ZNMethodWithImmediateOops::destroy(entry.method_with_immediate_oops());
|
||||
ZReentrantLock* ZNMethodTable::lock_for_nmethod(nmethod* nm) {
|
||||
ZNMethodData* const data = gc_data(nm);
|
||||
if (data == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
nmethod* ZNMethodTable::method(ZNMethodTableEntry entry) {
|
||||
return entry.immediate_oops() ? entry.method_with_immediate_oops()->method() : entry.method();
|
||||
return data->lock();
|
||||
}
|
||||
|
||||
size_t ZNMethodTable::first_index(const nmethod* nm, size_t size) {
|
||||
@ -171,7 +242,7 @@ size_t ZNMethodTable::next_index(size_t prev_index, size_t size) {
|
||||
}
|
||||
|
||||
bool ZNMethodTable::register_entry(ZNMethodTableEntry* table, size_t size, ZNMethodTableEntry entry) {
|
||||
const nmethod* const nm = method(entry);
|
||||
const nmethod* const nm = entry.method();
|
||||
size_t index = first_index(nm, size);
|
||||
|
||||
for (;;) {
|
||||
@ -183,9 +254,8 @@ bool ZNMethodTable::register_entry(ZNMethodTableEntry* table, size_t size, ZNMet
|
||||
return true;
|
||||
}
|
||||
|
||||
if (table_entry.registered() && method(table_entry) == nm) {
|
||||
if (table_entry.registered() && table_entry.method() == nm) {
|
||||
// Replace existing entry
|
||||
destroy_entry(table_entry);
|
||||
table[index] = entry;
|
||||
return false;
|
||||
}
|
||||
@ -194,7 +264,7 @@ bool ZNMethodTable::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) {
|
||||
// Table is empty
|
||||
return false;
|
||||
@ -210,10 +280,13 @@ bool ZNMethodTable::unregister_entry(ZNMethodTableEntry* table, size_t size, con
|
||||
return false;
|
||||
}
|
||||
|
||||
if (table_entry.registered() && method(table_entry) == nm) {
|
||||
if (table_entry.registered() && table_entry.method() == nm) {
|
||||
// Remove entry
|
||||
destroy_entry(table_entry);
|
||||
table[index] = ZNMethodTableEntry(true /* unregistered */);
|
||||
|
||||
// Destroy GC data
|
||||
ZNMethodData::destroy(gc_data(nm));
|
||||
set_gc_data(nm, NULL);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -222,6 +295,7 @@ bool ZNMethodTable::unregister_entry(ZNMethodTableEntry* table, size_t size, con
|
||||
}
|
||||
|
||||
void ZNMethodTable::rebuild(size_t new_size) {
|
||||
ZLocker<ZLock> locker(&_iter_lock);
|
||||
assert(is_power_of_2(new_size), "Invalid size");
|
||||
|
||||
log_debug(gc, nmethod)("Rebuilding NMethod Table: "
|
||||
@ -243,8 +317,10 @@ void ZNMethodTable::rebuild(size_t new_size) {
|
||||
}
|
||||
}
|
||||
|
||||
// Delete old table
|
||||
delete [] _table;
|
||||
if (_iter_table != _table) {
|
||||
// Delete old table
|
||||
delete [] _table;
|
||||
}
|
||||
|
||||
// Install new table
|
||||
_table = new_table;
|
||||
@ -294,8 +370,8 @@ void ZNMethodTable::log_register(const nmethod* nm, ZNMethodTableEntry entry) {
|
||||
p2i(nm),
|
||||
nm->compiler_name(),
|
||||
nm->oops_count() - 1,
|
||||
entry.immediate_oops() ? entry.method_with_immediate_oops()->immediate_oops_count() : 0,
|
||||
BOOL_TO_STR(entry.non_immediate_oops()));
|
||||
entry.immediate_oops() ? gc_data(nm)->immediate_oops()->immediate_oops_count() : 0,
|
||||
entry.non_immediate_oops() ? "Yes" : "No");
|
||||
|
||||
LogTarget(Trace, gc, nmethod, oops) log_oops;
|
||||
if (!log_oops.is_enabled()) {
|
||||
@ -312,12 +388,14 @@ void ZNMethodTable::log_register(const nmethod* nm, ZNMethodTableEntry entry) {
|
||||
|
||||
if (entry.immediate_oops()) {
|
||||
// Print nmethod immediate oops
|
||||
const ZNMethodWithImmediateOops* const nmi = entry.method_with_immediate_oops();
|
||||
oop** const begin = nmi->immediate_oops_begin();
|
||||
oop** const end = nmi->immediate_oops_end();
|
||||
for (oop** p = begin; p < end; p++) {
|
||||
log_oops.print(" ImmediateOop[" SIZE_FORMAT "] " PTR_FORMAT " @ " PTR_FORMAT " (%s)",
|
||||
(p - begin), p2i(**p), p2i(*p), (**p)->klass()->external_name());
|
||||
const ZNMethodDataImmediateOops* const nmi = gc_data(nm)->immediate_oops();
|
||||
if (nmi != NULL) {
|
||||
oop** const begin = nmi->immediate_oops_begin();
|
||||
oop** const end = nmi->immediate_oops_end();
|
||||
for (oop** p = begin; p < end; p++) {
|
||||
log_oops.print(" ImmediateOop[" SIZE_FORMAT "] " PTR_FORMAT " @ " PTR_FORMAT " (%s)",
|
||||
(p - begin), p2i(**p), p2i(*p), (**p)->klass()->external_name());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -343,21 +421,17 @@ size_t ZNMethodTable::unregistered_nmethods() {
|
||||
}
|
||||
|
||||
void ZNMethodTable::register_nmethod(nmethod* nm) {
|
||||
assert(CodeCache_lock->owned_by_self(), "Lock must be held");
|
||||
ResourceMark rm;
|
||||
|
||||
// Grow/Shrink/Prune table if needed
|
||||
rebuild_if_needed();
|
||||
|
||||
// Create entry
|
||||
const ZNMethodTableEntry entry = create_entry(nm);
|
||||
|
||||
log_register(nm, entry);
|
||||
|
||||
if (!entry.registered()) {
|
||||
// Method doesn't have any oops, ignore it
|
||||
return;
|
||||
}
|
||||
|
||||
// Grow/Shrink/Prune table if needed
|
||||
rebuild_if_needed();
|
||||
|
||||
// Insert new entry
|
||||
if (register_entry(_table, _size, entry)) {
|
||||
// New entry registered. When register_entry() instead returns
|
||||
@ -365,11 +439,31 @@ void ZNMethodTable::register_nmethod(nmethod* nm) {
|
||||
// to increase number of registered entries in that case.
|
||||
_nregistered++;
|
||||
}
|
||||
|
||||
// Disarm nmethod entry barrier
|
||||
disarm_nmethod(nm);
|
||||
}
|
||||
|
||||
void ZNMethodTable::sweeper_wait_for_iteration() {
|
||||
// The sweeper must wait for any ongoing iteration to complete
|
||||
// before it can unregister an nmethod.
|
||||
if (!Thread::current()->is_Code_cache_sweeper_thread()) {
|
||||
return;
|
||||
}
|
||||
|
||||
assert(CodeCache_lock->owned_by_self(), "Lock must be held");
|
||||
|
||||
while (_iter_table != NULL) {
|
||||
MutexUnlockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
|
||||
os::naked_short_sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
void ZNMethodTable::unregister_nmethod(nmethod* nm) {
|
||||
ResourceMark rm;
|
||||
|
||||
sweeper_wait_for_iteration();
|
||||
|
||||
log_unregister(nm);
|
||||
|
||||
// Remove entry
|
||||
@ -383,20 +477,45 @@ void ZNMethodTable::unregister_nmethod(nmethod* nm) {
|
||||
}
|
||||
}
|
||||
|
||||
void ZNMethodTable::gc_prologue() {
|
||||
_claimed = 0;
|
||||
void ZNMethodTable::disarm_nmethod(nmethod* nm) {
|
||||
BarrierSetNMethod* const bs = BarrierSet::barrier_set()->barrier_set_nmethod();
|
||||
if (bs != NULL) {
|
||||
bs->disarm(nm);
|
||||
}
|
||||
}
|
||||
|
||||
void ZNMethodTable::gc_epilogue() {
|
||||
assert(_claimed >= _size, "Failed to claim all table entries");
|
||||
void ZNMethodTable::nmethod_entries_do_begin() {
|
||||
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
|
||||
ZLocker<ZLock> locker(&_iter_lock);
|
||||
|
||||
// Prepare iteration
|
||||
_iter_table = _table;
|
||||
_iter_table_size = _size;
|
||||
_claimed = 0;
|
||||
assert(_iter_deferred_deletes.is_empty(), "Should be emtpy");
|
||||
}
|
||||
|
||||
void ZNMethodTable::nmethod_entries_do_end() {
|
||||
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
|
||||
ZLocker<ZLock> locker(&_iter_lock);
|
||||
|
||||
// Finish iteration
|
||||
if (_iter_table != _table) {
|
||||
delete [] _iter_table;
|
||||
}
|
||||
_iter_table = NULL;
|
||||
assert(_claimed >= _iter_table_size, "Failed to claim all table entries");
|
||||
|
||||
// Process deferred deletes
|
||||
ZArrayIterator<void*> iter(&_iter_deferred_deletes);
|
||||
for (void* data; iter.next(&data);) {
|
||||
FREE_C_HEAP_ARRAY(uint8_t, data);
|
||||
}
|
||||
_iter_deferred_deletes.clear();
|
||||
}
|
||||
|
||||
void ZNMethodTable::entry_oops_do(ZNMethodTableEntry entry, OopClosure* cl) {
|
||||
nmethod* const nm = method(entry);
|
||||
if (!nm->is_alive()) {
|
||||
// No need to visit oops
|
||||
return;
|
||||
}
|
||||
nmethod* const nm = entry.method();
|
||||
|
||||
// Process oops table
|
||||
oop* const begin = nm->oops_begin();
|
||||
@ -407,29 +526,52 @@ void ZNMethodTable::entry_oops_do(ZNMethodTableEntry entry, OopClosure* cl) {
|
||||
}
|
||||
}
|
||||
|
||||
// Process immediate oops
|
||||
if (entry.immediate_oops()) {
|
||||
// Process immediate oops
|
||||
const ZNMethodWithImmediateOops* const nmi = entry.method_with_immediate_oops();
|
||||
oop** const begin = nmi->immediate_oops_begin();
|
||||
oop** const end = nmi->immediate_oops_end();
|
||||
for (oop** p = begin; p < end; p++) {
|
||||
cl->do_oop(*p);
|
||||
const ZNMethodDataImmediateOops* const nmi = gc_data(nm)->immediate_oops();
|
||||
if (nmi != NULL) {
|
||||
oop** const begin = nmi->immediate_oops_begin();
|
||||
oop** const end = nmi->immediate_oops_end();
|
||||
for (oop** p = begin; p < end; p++) {
|
||||
if (**p != Universe::non_oop_word()) {
|
||||
cl->do_oop(*p);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Process non-immediate oops
|
||||
if (entry.non_immediate_oops()) {
|
||||
// Process non-immediate oops
|
||||
nmethod* const nm = entry.method();
|
||||
nm->fix_oop_relocations();
|
||||
}
|
||||
}
|
||||
|
||||
class ZNMethodTableEntryToOopsDo : public ZNMethodTableEntryClosure {
|
||||
private:
|
||||
OopClosure* _cl;
|
||||
|
||||
public:
|
||||
ZNMethodTableEntryToOopsDo(OopClosure* cl) :
|
||||
_cl(cl) {}
|
||||
|
||||
void do_nmethod_entry(ZNMethodTableEntry entry) {
|
||||
ZNMethodTable::entry_oops_do(entry, _cl);
|
||||
}
|
||||
};
|
||||
|
||||
void ZNMethodTable::oops_do(OopClosure* cl) {
|
||||
ZNMethodTableEntryToOopsDo entry_cl(cl);
|
||||
nmethod_entries_do(&entry_cl);
|
||||
}
|
||||
|
||||
void ZNMethodTable::nmethod_entries_do(ZNMethodTableEntryClosure* cl) {
|
||||
for (;;) {
|
||||
// Claim table partition. Each partition is currently sized to span
|
||||
// two cache lines. This number is just a guess, but seems to work well.
|
||||
const size_t partition_size = (ZCacheLineSize * 2) / sizeof(ZNMethodTableEntry);
|
||||
const size_t partition_start = MIN2(Atomic::add(partition_size, &_claimed) - partition_size, _size);
|
||||
const size_t partition_end = MIN2(partition_start + partition_size, _size);
|
||||
const size_t partition_start = MIN2(Atomic::add(partition_size, &_claimed) - partition_size, _iter_table_size);
|
||||
const size_t partition_end = MIN2(partition_start + partition_size, _iter_table_size);
|
||||
if (partition_start == partition_end) {
|
||||
// End of table
|
||||
break;
|
||||
@ -437,10 +579,141 @@ void ZNMethodTable::oops_do(OopClosure* cl) {
|
||||
|
||||
// Process table partition
|
||||
for (size_t i = partition_start; i < partition_end; i++) {
|
||||
const ZNMethodTableEntry entry = _table[i];
|
||||
const ZNMethodTableEntry entry = _iter_table[i];
|
||||
if (entry.registered()) {
|
||||
entry_oops_do(entry, cl);
|
||||
cl->do_nmethod_entry(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ZNMethodTableUnlinkClosure : public ZNMethodTableEntryClosure {
|
||||
private:
|
||||
bool _unloading_occurred;
|
||||
volatile bool _failed;
|
||||
|
||||
void set_failed() {
|
||||
Atomic::store(true, &_failed);
|
||||
}
|
||||
|
||||
public:
|
||||
ZNMethodTableUnlinkClosure(bool unloading_occurred) :
|
||||
_unloading_occurred(unloading_occurred),
|
||||
_failed(false) {}
|
||||
|
||||
virtual void do_nmethod_entry(ZNMethodTableEntry entry) {
|
||||
if (failed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
nmethod* const nm = entry.method();
|
||||
if (!nm->is_alive()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (nm->is_unloading()) {
|
||||
// Unlinking of the dependencies must happen before the
|
||||
// handshake separating unlink and purge.
|
||||
nm->flush_dependencies(false /* delete_immediately */);
|
||||
return;
|
||||
}
|
||||
|
||||
ZLocker<ZReentrantLock> locker(ZNMethodTable::lock_for_nmethod(nm));
|
||||
|
||||
// Heal oops and disarm
|
||||
ZNMethodOopClosure cl;
|
||||
ZNMethodTable::entry_oops_do(entry, &cl);
|
||||
ZNMethodTable::disarm_nmethod(nm);
|
||||
|
||||
// Clear compiled ICs and exception caches
|
||||
if (!nm->unload_nmethod_caches(_unloading_occurred)) {
|
||||
set_failed();
|
||||
}
|
||||
}
|
||||
|
||||
bool failed() const {
|
||||
return Atomic::load(&_failed);
|
||||
}
|
||||
};
|
||||
|
||||
class ZNMethodTableUnlinkTask : public ZTask {
|
||||
private:
|
||||
ZNMethodTableUnlinkClosure _cl;
|
||||
ICRefillVerifier* _verifier;
|
||||
|
||||
public:
|
||||
ZNMethodTableUnlinkTask(bool unloading_occurred, ICRefillVerifier* verifier) :
|
||||
ZTask("ZNMethodTableUnlinkTask"),
|
||||
_cl(unloading_occurred),
|
||||
_verifier(verifier) {
|
||||
ZNMethodTable::nmethod_entries_do_begin();
|
||||
}
|
||||
|
||||
~ZNMethodTableUnlinkTask() {
|
||||
ZNMethodTable::nmethod_entries_do_end();
|
||||
}
|
||||
|
||||
virtual void work() {
|
||||
ICRefillVerifierMark mark(_verifier);
|
||||
ZNMethodTable::nmethod_entries_do(&_cl);
|
||||
}
|
||||
|
||||
bool success() const {
|
||||
return !_cl.failed();
|
||||
}
|
||||
};
|
||||
|
||||
void ZNMethodTable::unlink(ZWorkers* workers, bool unloading_occurred) {
|
||||
for (;;) {
|
||||
ICRefillVerifier verifier;
|
||||
|
||||
{
|
||||
ZNMethodTableUnlinkTask task(unloading_occurred, &verifier);
|
||||
workers->run_concurrent(&task);
|
||||
if (task.success()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Cleaning failed because we ran out of transitional IC stubs,
|
||||
// so we have to refill and try again. Refilling requires taking
|
||||
// a safepoint, so we temporarily leave the suspendible thread set.
|
||||
SuspendibleThreadSetLeaver sts;
|
||||
InlineCacheBuffer::refill_ic_stubs();
|
||||
}
|
||||
}
|
||||
|
||||
class ZNMethodTablePurgeClosure : public ZNMethodTableEntryClosure {
|
||||
public:
|
||||
virtual void do_nmethod_entry(ZNMethodTableEntry entry) {
|
||||
nmethod* const nm = entry.method();
|
||||
if (nm->is_alive() && nm->is_unloading()) {
|
||||
nm->make_unloaded();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class ZNMethodTablePurgeTask : public ZTask {
|
||||
private:
|
||||
ZNMethodTablePurgeClosure _cl;
|
||||
|
||||
public:
|
||||
ZNMethodTablePurgeTask() :
|
||||
ZTask("ZNMethodTablePurgeTask"),
|
||||
_cl() {
|
||||
ZNMethodTable::nmethod_entries_do_begin();
|
||||
}
|
||||
|
||||
~ZNMethodTablePurgeTask() {
|
||||
ZNMethodTable::nmethod_entries_do_end();
|
||||
}
|
||||
|
||||
virtual void work() {
|
||||
ZNMethodTable::nmethod_entries_do(&_cl);
|
||||
}
|
||||
};
|
||||
|
||||
void ZNMethodTable::purge(ZWorkers* workers) {
|
||||
ZNMethodTablePurgeTask task;
|
||||
workers->run_concurrent(&task);
|
||||
}
|
||||
|
@ -24,28 +24,40 @@
|
||||
#ifndef SHARE_GC_Z_ZNMETHODTABLE_HPP
|
||||
#define SHARE_GC_Z_ZNMETHODTABLE_HPP
|
||||
|
||||
#include "gc/z/zArray.hpp"
|
||||
#include "gc/z/zGlobals.hpp"
|
||||
#include "gc/z/zLock.hpp"
|
||||
#include "gc/z/zNMethodTableEntry.hpp"
|
||||
#include "memory/allocation.hpp"
|
||||
|
||||
class ZWorkers;
|
||||
|
||||
class ZNMethodTableEntryClosure {
|
||||
public:
|
||||
virtual void do_nmethod_entry(ZNMethodTableEntry entry) = 0;
|
||||
};
|
||||
|
||||
class ZNMethodTable : public AllStatic {
|
||||
private:
|
||||
static ZNMethodTableEntry* _table;
|
||||
static size_t _size;
|
||||
static ZLock _iter_lock;
|
||||
static ZNMethodTableEntry* _iter_table;
|
||||
static size_t _iter_table_size;
|
||||
static ZArray<void*> _iter_deferred_deletes;
|
||||
static size_t _nregistered;
|
||||
static size_t _nunregistered;
|
||||
static volatile size_t _claimed ATTRIBUTE_ALIGNED(ZCacheLineSize);
|
||||
|
||||
static ZNMethodTableEntry create_entry(nmethod* nm);
|
||||
static void destroy_entry(ZNMethodTableEntry entry);
|
||||
|
||||
static nmethod* method(ZNMethodTableEntry entry);
|
||||
|
||||
static size_t first_index(const nmethod* nm, size_t size);
|
||||
static size_t next_index(size_t prev_index, size_t size);
|
||||
|
||||
static void sweeper_wait_for_iteration();
|
||||
|
||||
static bool register_entry(ZNMethodTableEntry* table, size_t size, ZNMethodTableEntry entry);
|
||||
static bool unregister_entry(ZNMethodTableEntry* table, size_t size, const nmethod* nm);
|
||||
static bool unregister_entry(ZNMethodTableEntry* table, size_t size, nmethod* nm);
|
||||
|
||||
static void rebuild(size_t new_size);
|
||||
static void rebuild_if_needed();
|
||||
@ -53,19 +65,28 @@ private:
|
||||
static void log_register(const nmethod* nm, ZNMethodTableEntry entry);
|
||||
static void log_unregister(const nmethod* nm);
|
||||
|
||||
static void entry_oops_do(ZNMethodTableEntry entry, OopClosure* cl);
|
||||
|
||||
public:
|
||||
static void safe_delete(void* data);
|
||||
|
||||
static size_t registered_nmethods();
|
||||
static size_t unregistered_nmethods();
|
||||
|
||||
static void register_nmethod(nmethod* nm);
|
||||
static void unregister_nmethod(nmethod* nm);
|
||||
static void disarm_nmethod(nmethod* nm);
|
||||
|
||||
static void gc_prologue();
|
||||
static void gc_epilogue();
|
||||
static ZReentrantLock* lock_for_nmethod(nmethod* nm);
|
||||
|
||||
static void oops_do(OopClosure* cl);
|
||||
|
||||
static void entry_oops_do(ZNMethodTableEntry entry, OopClosure* cl);
|
||||
|
||||
static void nmethod_entries_do_begin();
|
||||
static void nmethod_entries_do_end();
|
||||
static void nmethod_entries_do(ZNMethodTableEntryClosure* cl);
|
||||
|
||||
static void unlink(ZWorkers* workers, bool unloading_occurred);
|
||||
static void purge(ZWorkers* workers);
|
||||
};
|
||||
|
||||
#endif // SHARE_GC_Z_ZNMETHODTABLE_HPP
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -43,38 +43,30 @@
|
||||
// | |
|
||||
// | 0-0 Registered Flag (1-bits) *
|
||||
// |
|
||||
// * 63-3 NMethod/ZNMethodWithImmediateOops Address (61-bits)
|
||||
// * 63-3 NMethod Address (61-bits)
|
||||
//
|
||||
|
||||
class nmethod;
|
||||
class ZNMethodWithImmediateOops;
|
||||
|
||||
class ZNMethodTableEntry : public CHeapObj<mtGC> {
|
||||
private:
|
||||
typedef ZBitField<uint64_t, bool, 0, 1> field_registered;
|
||||
typedef ZBitField<uint64_t, bool, 1, 1> field_unregistered;
|
||||
typedef ZBitField<uint64_t, bool, 1, 1> field_immediate_oops;
|
||||
typedef ZBitField<uint64_t, bool, 2, 1> field_non_immediate_oops;
|
||||
typedef ZBitField<uint64_t, nmethod*, 3, 61, 3> field_method;
|
||||
typedef ZBitField<uint64_t, ZNMethodWithImmediateOops*, 3, 61, 3> field_method_with_immediate_oops;
|
||||
typedef ZBitField<uint64_t, bool, 0, 1> field_registered;
|
||||
typedef ZBitField<uint64_t, bool, 1, 1> field_unregistered;
|
||||
typedef ZBitField<uint64_t, bool, 1, 1> field_immediate_oops;
|
||||
typedef ZBitField<uint64_t, bool, 2, 1> field_non_immediate_oops;
|
||||
typedef ZBitField<uint64_t, nmethod*, 3, 61, 3> field_method;
|
||||
|
||||
uint64_t _entry;
|
||||
|
||||
public:
|
||||
ZNMethodTableEntry(bool unregistered = false) :
|
||||
explicit ZNMethodTableEntry(bool unregistered = false) :
|
||||
_entry(field_unregistered::encode(unregistered) |
|
||||
field_registered::encode(false)) {}
|
||||
|
||||
ZNMethodTableEntry(nmethod* method, bool non_immediate_oops) :
|
||||
ZNMethodTableEntry(nmethod* method, bool non_immediate_oops, bool immediate_oops) :
|
||||
_entry(field_method::encode(method) |
|
||||
field_non_immediate_oops::encode(non_immediate_oops) |
|
||||
field_immediate_oops::encode(false) |
|
||||
field_registered::encode(true)) {}
|
||||
|
||||
ZNMethodTableEntry(ZNMethodWithImmediateOops* method_with_immediate_oops, bool non_immediate_oops) :
|
||||
_entry(field_method_with_immediate_oops::encode(method_with_immediate_oops) |
|
||||
field_non_immediate_oops::encode(non_immediate_oops) |
|
||||
field_immediate_oops::encode(true) |
|
||||
field_immediate_oops::encode(immediate_oops) |
|
||||
field_registered::encode(true)) {}
|
||||
|
||||
bool registered() const {
|
||||
@ -96,10 +88,6 @@ public:
|
||||
nmethod* method() const {
|
||||
return field_method::decode(_entry);
|
||||
}
|
||||
|
||||
ZNMethodWithImmediateOops* method_with_immediate_oops() const {
|
||||
return field_method_with_immediate_oops::decode(_entry);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // SHARE_GC_Z_ZNMETHODTABLEENTRY_HPP
|
||||
|
@ -39,14 +39,23 @@ public:
|
||||
#endif
|
||||
};
|
||||
|
||||
class ZNMethodOopClosure : public OopClosure {
|
||||
public:
|
||||
virtual void do_oop(oop* p);
|
||||
virtual void do_oop(narrowOop* p);
|
||||
};
|
||||
|
||||
template <bool finalizable>
|
||||
class ZMarkBarrierOopClosure : public BasicOopIterateClosure {
|
||||
class ZMarkBarrierOopClosure : public MetadataVisitingOopIterateClosure {
|
||||
public:
|
||||
ZMarkBarrierOopClosure();
|
||||
|
||||
virtual void do_oop(oop* p);
|
||||
virtual void do_oop(narrowOop* p);
|
||||
|
||||
virtual void do_klass(Klass* k);
|
||||
virtual void do_cld(ClassLoaderData* cld);
|
||||
|
||||
#ifdef ASSERT
|
||||
virtual bool should_verify_oops() {
|
||||
return false;
|
||||
|
@ -24,6 +24,7 @@
|
||||
#ifndef SHARE_GC_Z_ZOOPCLOSURES_INLINE_HPP
|
||||
#define SHARE_GC_Z_ZOOPCLOSURES_INLINE_HPP
|
||||
|
||||
#include "classfile/classLoaderData.hpp"
|
||||
#include "gc/z/zBarrier.inline.hpp"
|
||||
#include "gc/z/zHeap.inline.hpp"
|
||||
#include "gc/z/zOop.inline.hpp"
|
||||
@ -40,9 +41,21 @@ inline void ZLoadBarrierOopClosure::do_oop(narrowOop* p) {
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
|
||||
inline void ZNMethodOopClosure::do_oop(oop* p) {
|
||||
if (ZResurrection::is_blocked()) {
|
||||
ZBarrier::keep_alive_barrier_on_phantom_root_oop_field(p);
|
||||
} else {
|
||||
ZBarrier::load_barrier_on_root_oop_field(p);
|
||||
}
|
||||
}
|
||||
|
||||
inline void ZNMethodOopClosure::do_oop(narrowOop* p) {
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
|
||||
template <bool finalizable>
|
||||
inline ZMarkBarrierOopClosure<finalizable>::ZMarkBarrierOopClosure() :
|
||||
BasicOopIterateClosure(finalizable ? NULL : ZHeap::heap()->reference_discoverer()) {}
|
||||
MetadataVisitingOopIterateClosure(finalizable ? NULL : ZHeap::heap()->reference_discoverer()) {}
|
||||
|
||||
template <bool finalizable>
|
||||
inline void ZMarkBarrierOopClosure<finalizable>::do_oop(oop* p) {
|
||||
@ -54,6 +67,18 @@ inline void ZMarkBarrierOopClosure<finalizable>::do_oop(narrowOop* p) {
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
|
||||
template <bool finalizable>
|
||||
inline void ZMarkBarrierOopClosure<finalizable>::do_klass(Klass* k) {
|
||||
ClassLoaderData* const cld = k->class_loader_data();
|
||||
ZMarkBarrierOopClosure<finalizable>::do_cld(cld);
|
||||
}
|
||||
|
||||
template <bool finalizable>
|
||||
inline void ZMarkBarrierOopClosure<finalizable>::do_cld(ClassLoaderData* cld) {
|
||||
const int claim = finalizable ? ClassLoaderData::_claim_finalizable : ClassLoaderData::_claim_strong;
|
||||
cld->oops_do(this, claim);
|
||||
}
|
||||
|
||||
inline bool ZPhantomIsAliveObjectClosure::do_object_b(oop o) {
|
||||
return ZBarrier::is_alive_barrier_on_phantom_oop(o);
|
||||
}
|
||||
|
@ -27,8 +27,11 @@
|
||||
#include "classfile/systemDictionary.hpp"
|
||||
#include "code/codeCache.hpp"
|
||||
#include "compiler/oopMap.hpp"
|
||||
#include "gc/shared/barrierSet.hpp"
|
||||
#include "gc/shared/barrierSetNMethod.hpp"
|
||||
#include "gc/shared/oopStorageParState.inline.hpp"
|
||||
#include "gc/shared/suspendibleThreadSet.hpp"
|
||||
#include "gc/z/zBarrierSetNMethod.hpp"
|
||||
#include "gc/z/zGlobals.hpp"
|
||||
#include "gc/z/zNMethodTable.hpp"
|
||||
#include "gc/z/zOopClosures.inline.hpp"
|
||||
@ -132,6 +135,30 @@ 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() :
|
||||
_universe(this),
|
||||
_object_synchronizer(this),
|
||||
@ -145,16 +172,23 @@ ZRootsIterator::ZRootsIterator() :
|
||||
ZStatTimer timer(ZSubPhasePauseRootsSetup);
|
||||
Threads::change_thread_claim_parity();
|
||||
COMPILER2_PRESENT(DerivedPointerTable::clear());
|
||||
CodeCache::gc_prologue();
|
||||
ZNMethodTable::gc_prologue();
|
||||
if (ClassUnloading) {
|
||||
nmethod::oops_do_marking_prologue();
|
||||
} else {
|
||||
ZNMethodTable::nmethod_entries_do_begin();
|
||||
}
|
||||
}
|
||||
|
||||
ZRootsIterator::~ZRootsIterator() {
|
||||
ZStatTimer timer(ZSubPhasePauseRootsTeardown);
|
||||
ResourceMark rm;
|
||||
ZNMethodTable::gc_epilogue();
|
||||
CodeCache::gc_epilogue();
|
||||
if (ClassUnloading) {
|
||||
nmethod::oops_do_marking_epilogue();
|
||||
} else {
|
||||
ZNMethodTable::nmethod_entries_do_end();
|
||||
}
|
||||
JvmtiExport::gc_epilogue();
|
||||
|
||||
COMPILER2_PRESENT(DerivedPointerTable::update_pointers());
|
||||
Threads::assert_all_threads_claimed();
|
||||
}
|
||||
@ -209,7 +243,9 @@ void ZRootsIterator::oops_do(ZRootsIteratorClosure* cl, bool visit_jvmti_weak_ex
|
||||
_jvmti_export.oops_do(cl);
|
||||
_system_dictionary.oops_do(cl);
|
||||
_threads.oops_do(cl);
|
||||
_code_cache.oops_do(cl);
|
||||
if (!ClassUnloading) {
|
||||
_code_cache.oops_do(cl);
|
||||
}
|
||||
if (visit_jvmti_weak_export) {
|
||||
_jvmti_weak_export.oops_do(cl);
|
||||
}
|
||||
@ -242,8 +278,13 @@ void ZConcurrentRootsIterator::do_jni_handles(ZRootsIteratorClosure* cl) {
|
||||
|
||||
void ZConcurrentRootsIterator::do_class_loader_data_graph(ZRootsIteratorClosure* cl) {
|
||||
ZStatTimer timer(ZSubPhaseConcurrentRootsClassLoaderDataGraph);
|
||||
CLDToOopClosure cld_cl(cl, _marking ? ClassLoaderData::_claim_strong : ClassLoaderData::_claim_none);
|
||||
ClassLoaderDataGraph::cld_do(&cld_cl);
|
||||
if (_marking) {
|
||||
CLDToOopClosure cld_cl(cl, ClassLoaderData::_claim_strong);
|
||||
ClassLoaderDataGraph::always_strong_cld_do(&cld_cl);
|
||||
} else {
|
||||
CLDToOopClosure cld_cl(cl, ClassLoaderData::_claim_none);
|
||||
ClassLoaderDataGraph::cld_do(&cld_cl);
|
||||
}
|
||||
}
|
||||
|
||||
void ZConcurrentRootsIterator::oops_do(ZRootsIteratorClosure* cl) {
|
||||
|
@ -33,9 +33,7 @@
|
||||
|
||||
class ZRootsIteratorClosure : public OopClosure, public ThreadClosure {
|
||||
public:
|
||||
virtual void do_thread(Thread* thread) {
|
||||
thread->oops_do(this, NULL);
|
||||
}
|
||||
virtual void do_thread(Thread* thread);
|
||||
};
|
||||
|
||||
typedef OopStorage::ParState<true /* concurrent */, false /* is_const */> ZOopStorageIterator;
|
||||
|
@ -25,6 +25,7 @@
|
||||
#define SHARE_GC_Z_ZTHREADLOCALDATA_HPP
|
||||
|
||||
#include "gc/z/zMarkStack.hpp"
|
||||
#include "gc/z/zGlobals.hpp"
|
||||
#include "runtime/thread.hpp"
|
||||
#include "utilities/debug.hpp"
|
||||
#include "utilities/sizes.hpp"
|
||||
@ -62,6 +63,10 @@ public:
|
||||
static ByteSize address_bad_mask_offset() {
|
||||
return Thread::gc_data_offset() + byte_offset_of(ZThreadLocalData, _address_bad_mask);
|
||||
}
|
||||
|
||||
static ByteSize nmethod_disarmed_offset() {
|
||||
return address_bad_mask_offset() + in_ByteSize(ZNMethodDisarmedOffset);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // SHARE_GC_Z_ZTHREADLOCALDATA_HPP
|
||||
|
194
src/hotspot/share/gc/z/zUnload.cpp
Normal file
194
src/hotspot/share/gc/z/zUnload.cpp
Normal 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();
|
||||
}
|
44
src/hotspot/share/gc/z/zUnload.hpp
Normal file
44
src/hotspot/share/gc/z/zUnload.hpp
Normal 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
|
@ -306,15 +306,19 @@ Thread::Thread() {
|
||||
}
|
||||
#endif // ASSERT
|
||||
|
||||
// Notify the barrier set that a thread is being created. Note that some
|
||||
// threads are created before a barrier set is available. The call to
|
||||
// BarrierSet::on_thread_create() for these threads is therefore deferred
|
||||
// Notify the barrier set that a thread is being created. The initial
|
||||
// thread is created before the barrier set is available. The call to
|
||||
// BarrierSet::on_thread_create() for this thread is therefore deferred
|
||||
// to BarrierSet::set_barrier_set().
|
||||
BarrierSet* const barrier_set = BarrierSet::barrier_set();
|
||||
if (barrier_set != NULL) {
|
||||
barrier_set->on_thread_create(this);
|
||||
} else {
|
||||
DEBUG_ONLY(Threads::inc_threads_before_barrier_set();)
|
||||
#ifdef ASSERT
|
||||
static bool initial_thread_created = false;
|
||||
assert(!initial_thread_created, "creating thread before barrier set");
|
||||
initial_thread_created = true;
|
||||
#endif // ASSERT
|
||||
}
|
||||
}
|
||||
|
||||
@ -3395,7 +3399,6 @@ size_t JavaThread::_stack_size_at_create = 0;
|
||||
|
||||
#ifdef ASSERT
|
||||
bool Threads::_vm_complete = false;
|
||||
size_t Threads::_threads_before_barrier_set = 0;
|
||||
#endif
|
||||
|
||||
static inline void *prefetch_and_load_ptr(void **addr, intx prefetch_interval) {
|
||||
|
@ -2156,7 +2156,6 @@ class Threads: AllStatic {
|
||||
static int _thread_claim_parity;
|
||||
#ifdef ASSERT
|
||||
static bool _vm_complete;
|
||||
static size_t _threads_before_barrier_set;
|
||||
#endif
|
||||
|
||||
static void initialize_java_lang_classes(JavaThread* main_thread, TRAPS);
|
||||
@ -2226,14 +2225,6 @@ class Threads: AllStatic {
|
||||
|
||||
#ifdef ASSERT
|
||||
static bool is_vm_complete() { return _vm_complete; }
|
||||
|
||||
static size_t threads_before_barrier_set() {
|
||||
return _threads_before_barrier_set;
|
||||
}
|
||||
|
||||
static void inc_threads_before_barrier_set() {
|
||||
++_threads_before_barrier_set;
|
||||
}
|
||||
#endif // ASSERT
|
||||
|
||||
// Verification
|
||||
|
@ -681,11 +681,12 @@ class Character implements java.io.Serializable, Comparable<Character> {
|
||||
*/
|
||||
public static final class UnicodeBlock extends Subset {
|
||||
/**
|
||||
* 649 - the expected number of entities
|
||||
* 667 - the expected number of entities
|
||||
* 0.75 - the default load factor of HashMap
|
||||
*/
|
||||
private static final int NUM_ENTITIES = 667;
|
||||
private static Map<String, UnicodeBlock> map =
|
||||
new HashMap<>((int)(649 / 0.75f + 1.0f));
|
||||
new HashMap<>((int)(NUM_ENTITIES / 0.75f + 1.0f));
|
||||
|
||||
/**
|
||||
* Creates a UnicodeBlock with the given identifier name.
|
||||
|
@ -94,12 +94,10 @@ public class Object {
|
||||
* programmer should be aware that producing distinct integer results
|
||||
* for unequal objects may improve the performance of hash tables.
|
||||
* </ul>
|
||||
* <p>
|
||||
* As much as is reasonably practical, the hashCode method defined
|
||||
* by class {@code Object} does return distinct integers for
|
||||
* distinct objects. (The hashCode may or may not be implemented
|
||||
* as some function of an object's memory address at some point
|
||||
* in time.)
|
||||
*
|
||||
* @implSpec
|
||||
* As far as is reasonably practical, the {@code hashCode} method defined
|
||||
* by class {@code Object} returns distinct integers for distinct objects.
|
||||
*
|
||||
* @return a hash code value for this object.
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
package java.net;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InvalidObjectException;
|
||||
import java.io.ObjectInputStream;
|
||||
@ -36,6 +37,7 @@ import java.nio.charset.CharsetDecoder;
|
||||
import java.nio.charset.CoderResult;
|
||||
import java.nio.charset.CodingErrorAction;
|
||||
import java.nio.charset.CharacterCodingException;
|
||||
import java.nio.file.Path;
|
||||
import java.text.Normalizer;
|
||||
import jdk.internal.access.JavaNetUriAccess;
|
||||
import jdk.internal.access.SharedSecrets;
|
||||
@ -458,6 +460,27 @@ import java.lang.NullPointerException; // for javadoc
|
||||
* resolution as well as the network I/O operations of looking up the host and
|
||||
* opening a connection to the specified resource.
|
||||
*
|
||||
* @apiNote
|
||||
*
|
||||
* Applications working with file paths and file URIs should take great
|
||||
* care to use the appropriate methods to convert between the two.
|
||||
* The {@link Path#of(URI)} factory method and the {@link File#File(URI)}
|
||||
* constructor can be used to create {@link Path} or {@link File}
|
||||
* objects from a file URI. {@link Path#toUri()} and {@link File#toURI()}
|
||||
* can be used to create a {@link URI} from a file path.
|
||||
* Applications should never try to {@linkplain
|
||||
* #URI(String, String, String, int, String, String, String)
|
||||
* construct}, {@linkplain #URI(String) parse}, or
|
||||
* {@linkplain #resolve(String) resolve} a {@code URI}
|
||||
* from the direct string representation of a {@code File} or {@code Path}
|
||||
* instance.
|
||||
* <p>
|
||||
* Some components of a URL or URI, such as <i>userinfo</i>, may
|
||||
* be abused to construct misleading URLs or URIs. Applications
|
||||
* that deal with URLs or URIs should take into account
|
||||
* the recommendations advised in <a
|
||||
* href="https://tools.ietf.org/html/rfc3986#section-7">RFC3986,
|
||||
* Section 7, Security Considerations</a>.
|
||||
*
|
||||
* @author Mark Reinhold
|
||||
* @since 1.4
|
||||
|
@ -25,9 +25,11 @@
|
||||
|
||||
package java.net;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.spi.URLStreamHandlerProvider;
|
||||
import java.nio.file.Path;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.Hashtable;
|
||||
@ -145,6 +147,27 @@ import sun.security.action.GetPropertyAction;
|
||||
* used, but only for HTML form encoding, which is not the same
|
||||
* as the encoding scheme defined in RFC2396.
|
||||
*
|
||||
* @apiNote
|
||||
*
|
||||
* Applications working with file paths and file URIs should take great
|
||||
* care to use the appropriate methods to convert between the two.
|
||||
* The {@link Path#of(URI)} factory method and the {@link File#File(URI)}
|
||||
* constructor can be used to create {@link Path} or {@link File}
|
||||
* objects from a file URI. {@link Path#toUri()} and {@link File#toURI()}
|
||||
* can be used to create a {@link URI} from a file path, which can be
|
||||
* converted to URL using {@link URI#toURL()}.
|
||||
* Applications should never try to {@linkplain #URL(String, String, String)
|
||||
* construct} or {@linkplain #URL(String) parse} a {@code URL}
|
||||
* from the direct string representation of a {@code File} or {@code Path}
|
||||
* instance.
|
||||
* <p>
|
||||
* Some components of a URL or URI, such as <i>userinfo</i>, may
|
||||
* be abused to construct misleading URLs or URIs. Applications
|
||||
* that deal with URLs or URIs should take into account
|
||||
* the recommendations advised in <a
|
||||
* href="https://tools.ietf.org/html/rfc3986#section-7">RFC3986,
|
||||
* Section 7, Security Considerations</a>.
|
||||
*
|
||||
* @author James Gosling
|
||||
* @since 1.0
|
||||
*/
|
||||
|
@ -80,7 +80,7 @@ import java.util.stream.StreamSupport;
|
||||
* in security-sensitive applications. Additionally,
|
||||
* default-constructed instances do not use a cryptographically random
|
||||
* seed unless the {@linkplain System#getProperty system property}
|
||||
* {@code java.util.secureRandomSeed} is set to {@code true}.
|
||||
* {@systemProperty java.util.secureRandomSeed} is set to {@code true}.
|
||||
*
|
||||
* @author Guy Steele
|
||||
* @author Doug Lea
|
||||
|
@ -2334,17 +2334,15 @@ public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>
|
||||
Node<K,V>[] tab, nt; int n, sc;
|
||||
while (s >= (long)(sc = sizeCtl) && (tab = table) != null &&
|
||||
(n = tab.length) < MAXIMUM_CAPACITY) {
|
||||
int rs = resizeStamp(n);
|
||||
int rs = resizeStamp(n) << RESIZE_STAMP_SHIFT;
|
||||
if (sc < 0) {
|
||||
if ((sc >>> RESIZE_STAMP_SHIFT) != rs || sc == rs + 1 ||
|
||||
sc == rs + MAX_RESIZERS || (nt = nextTable) == null ||
|
||||
transferIndex <= 0)
|
||||
if (sc == rs + MAX_RESIZERS || sc == rs + 1 ||
|
||||
(nt = nextTable) == null || transferIndex <= 0)
|
||||
break;
|
||||
if (U.compareAndSetInt(this, SIZECTL, sc, sc + 1))
|
||||
transfer(tab, nt);
|
||||
}
|
||||
else if (U.compareAndSetInt(this, SIZECTL, sc,
|
||||
(rs << RESIZE_STAMP_SHIFT) + 2))
|
||||
else if (U.compareAndSetInt(this, SIZECTL, sc, rs + 2))
|
||||
transfer(tab, null);
|
||||
s = sumCount();
|
||||
}
|
||||
@ -2358,11 +2356,11 @@ public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>
|
||||
Node<K,V>[] nextTab; int sc;
|
||||
if (tab != null && (f instanceof ForwardingNode) &&
|
||||
(nextTab = ((ForwardingNode<K,V>)f).nextTable) != null) {
|
||||
int rs = resizeStamp(tab.length);
|
||||
int rs = resizeStamp(tab.length) << RESIZE_STAMP_SHIFT;
|
||||
while (nextTab == nextTable && table == tab &&
|
||||
(sc = sizeCtl) < 0) {
|
||||
if ((sc >>> RESIZE_STAMP_SHIFT) != rs || sc == rs + 1 ||
|
||||
sc == rs + MAX_RESIZERS || transferIndex <= 0)
|
||||
if (sc == rs + MAX_RESIZERS || sc == rs + 1 ||
|
||||
transferIndex <= 0)
|
||||
break;
|
||||
if (U.compareAndSetInt(this, SIZECTL, sc, sc + 1)) {
|
||||
transfer(tab, nextTab);
|
||||
|
@ -136,17 +136,17 @@ import java.util.concurrent.locks.LockSupport;
|
||||
* <p>The parameters used to construct the common pool may be controlled by
|
||||
* setting the following {@linkplain System#getProperty system properties}:
|
||||
* <ul>
|
||||
* <li>{@code java.util.concurrent.ForkJoinPool.common.parallelism}
|
||||
* <li>{@systemProperty java.util.concurrent.ForkJoinPool.common.parallelism}
|
||||
* - the parallelism level, a non-negative integer
|
||||
* <li>{@code java.util.concurrent.ForkJoinPool.common.threadFactory}
|
||||
* <li>{@systemProperty java.util.concurrent.ForkJoinPool.common.threadFactory}
|
||||
* - the class name of a {@link ForkJoinWorkerThreadFactory}.
|
||||
* The {@linkplain ClassLoader#getSystemClassLoader() system class loader}
|
||||
* is used to load this class.
|
||||
* <li>{@code java.util.concurrent.ForkJoinPool.common.exceptionHandler}
|
||||
* <li>{@systemProperty java.util.concurrent.ForkJoinPool.common.exceptionHandler}
|
||||
* - the class name of a {@link UncaughtExceptionHandler}.
|
||||
* The {@linkplain ClassLoader#getSystemClassLoader() system class loader}
|
||||
* is used to load this class.
|
||||
* <li>{@code java.util.concurrent.ForkJoinPool.common.maximumSpares}
|
||||
* <li>{@systemProperty java.util.concurrent.ForkJoinPool.common.maximumSpares}
|
||||
* - the maximum number of allowed extra threads to maintain target
|
||||
* parallelism (default 256).
|
||||
* </ul>
|
||||
@ -445,8 +445,7 @@ public class ForkJoinPool extends AbstractExecutorService {
|
||||
* if to its current value). This would be extremely costly. So
|
||||
* we relax it in several ways: (1) Producers only signal when
|
||||
* their queue is possibly empty at some point during a push
|
||||
* operation (which requires conservatively checking size zero or
|
||||
* one to cover races). (2) Other workers propagate this signal
|
||||
* operation. (2) Other workers propagate this signal
|
||||
* when they find tasks in a queue with size greater than one. (3)
|
||||
* Workers only enqueue after scanning (see below) and not finding
|
||||
* any tasks. (4) Rather than CASing ctl to its current value in
|
||||
@ -762,10 +761,8 @@ public class ForkJoinPool extends AbstractExecutorService {
|
||||
|
||||
/**
|
||||
* The maximum number of top-level polls per worker before
|
||||
* checking other queues, expressed as a bit shift to, in effect,
|
||||
* multiply by pool size, and then use as random value mask, so
|
||||
* average bound is about poolSize*(1<<TOP_BOUND_SHIFT). See
|
||||
* above for rationale.
|
||||
* checking other queues, expressed as a bit shift. See above for
|
||||
* rationale.
|
||||
*/
|
||||
static final int TOP_BOUND_SHIFT = 10;
|
||||
|
||||
@ -841,18 +838,17 @@ public class ForkJoinPool extends AbstractExecutorService {
|
||||
*/
|
||||
final void push(ForkJoinTask<?> task) {
|
||||
ForkJoinTask<?>[] a;
|
||||
int s = top, d, cap, m;
|
||||
int s = top, d = s - base, cap, m;
|
||||
ForkJoinPool p = pool;
|
||||
if ((a = array) != null && (cap = a.length) > 0) {
|
||||
QA.setRelease(a, (m = cap - 1) & s, task);
|
||||
top = s + 1;
|
||||
if (((d = s - (int)BASE.getAcquire(this)) & ~1) == 0 &&
|
||||
p != null) { // size 0 or 1
|
||||
VarHandle.fullFence();
|
||||
p.signalWork();
|
||||
}
|
||||
else if (d == m)
|
||||
if (d == m)
|
||||
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) {
|
||||
ForkJoinTask<?>[] a;
|
||||
boolean signal = false;
|
||||
int s = top, b = base, cap, d;
|
||||
int s = top, d = s - base, cap, m;
|
||||
if ((a = array) != null && (cap = a.length) > 0) {
|
||||
a[(cap - 1) & s] = task;
|
||||
a[(m = (cap - 1)) & s] = task;
|
||||
top = s + 1;
|
||||
if (b - s + cap - 1 == 0)
|
||||
if (d == m)
|
||||
growArray(true);
|
||||
else {
|
||||
phase = 0; // full volatile unlock
|
||||
if (((s - base) & ~1) == 0) // size 0 or 1
|
||||
signal = true;
|
||||
if (a[m & (s - 1)] == null)
|
||||
signal = true; // was empty
|
||||
}
|
||||
}
|
||||
return signal;
|
||||
@ -1014,25 +1010,30 @@ public class ForkJoinPool extends AbstractExecutorService {
|
||||
* queue, up to bound n (to avoid infinite unfairness).
|
||||
*/
|
||||
final void topLevelExec(ForkJoinTask<?> t, WorkQueue q, int n) {
|
||||
if (t != null && q != null) { // hoist checks
|
||||
int nstolen = 1;
|
||||
for (;;) {
|
||||
int nstolen = 1;
|
||||
for (int j = 0;;) {
|
||||
if (t != null)
|
||||
t.doExec();
|
||||
if (n-- < 0)
|
||||
break;
|
||||
else if ((t = nextLocalTask()) == null) {
|
||||
if ((t = q.poll()) == null)
|
||||
break;
|
||||
else
|
||||
++nstolen;
|
||||
}
|
||||
if (j++ <= n)
|
||||
t = nextLocalTask();
|
||||
else {
|
||||
j = 0;
|
||||
t = null;
|
||||
}
|
||||
if (t == null) {
|
||||
if (q != null && (t = q.poll()) != null) {
|
||||
++nstolen;
|
||||
j = 0;
|
||||
}
|
||||
else if (j != 0)
|
||||
break;
|
||||
}
|
||||
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
|
||||
w != null && w.array != null) // avoid repeated failures
|
||||
signalWork();
|
||||
signalWork(null);
|
||||
|
||||
if (ex == null) // help clean on way out
|
||||
ForkJoinTask.helpExpungeStaleExceptions();
|
||||
@ -1465,8 +1466,9 @@ public class ForkJoinPool extends AbstractExecutorService {
|
||||
|
||||
/**
|
||||
* Tries to create or release a worker if too few are running.
|
||||
* @param q if non-null recheck if empty on CAS failure
|
||||
*/
|
||||
final void signalWork() {
|
||||
final void signalWork(WorkQueue q) {
|
||||
for (;;) {
|
||||
long c; int sp; WorkQueue[] ws; int i; WorkQueue v;
|
||||
if ((c = ctl) >= 0L) // enough workers
|
||||
@ -1493,6 +1495,8 @@ public class ForkJoinPool extends AbstractExecutorService {
|
||||
LockSupport.unpark(vt);
|
||||
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 &&
|
||||
tryTerminate(false, false))
|
||||
break; // quiescent shutdown
|
||||
else if (rc <= 0 && pred != 0 && phase == (int)c) {
|
||||
long nc = (UC_MASK & (c - TC_UNIT)) | (SP_MASK & pred);
|
||||
long d = keepAlive + System.currentTimeMillis();
|
||||
LockSupport.parkUntil(this, d);
|
||||
if (ctl == c && // drop on timeout if all idle
|
||||
d - System.currentTimeMillis() <= TIMEOUT_SLOP &&
|
||||
CTL.compareAndSet(this, c, nc)) {
|
||||
w.phase = QUIET;
|
||||
break;
|
||||
else if (w.phase < 0) {
|
||||
if (rc <= 0 && pred != 0 && phase == (int)c) {
|
||||
long nc = (UC_MASK & (c - TC_UNIT)) | (SP_MASK & pred);
|
||||
long d = keepAlive + System.currentTimeMillis();
|
||||
LockSupport.parkUntil(this, d);
|
||||
if (ctl == c && // drop on timeout if all idle
|
||||
d - System.currentTimeMillis() <= TIMEOUT_SLOP &&
|
||||
CTL.compareAndSet(this, c, nc)) {
|
||||
w.phase = QUIET;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
LockSupport.park(this);
|
||||
if (w.phase < 0) // one spurious wakeup check
|
||||
LockSupport.park(this);
|
||||
}
|
||||
}
|
||||
else if (w.phase < 0)
|
||||
LockSupport.park(this); // OK if spuriously woken
|
||||
w.source = 0; // disable signal
|
||||
}
|
||||
}
|
||||
@ -1641,8 +1650,8 @@ public class ForkJoinPool extends AbstractExecutorService {
|
||||
WorkQueue[] ws; int n;
|
||||
if ((ws = workQueues) != null && (n = ws.length) > 0 && w != null) {
|
||||
for (int m = n - 1, j = r & m;;) {
|
||||
WorkQueue q; int b;
|
||||
if ((q = ws[j]) != null && q.top != (b = q.base)) {
|
||||
WorkQueue q; int b, s;
|
||||
if ((q = ws[j]) != null && (s = q.top) != (b = q.base)) {
|
||||
int qid = q.id;
|
||||
ForkJoinTask<?>[] a; int cap, k; ForkJoinTask<?> t;
|
||||
if ((a = q.array) != null && (cap = a.length) > 0) {
|
||||
@ -1651,10 +1660,10 @@ public class ForkJoinPool extends AbstractExecutorService {
|
||||
QA.compareAndSet(a, k, t, null)) {
|
||||
q.base = b;
|
||||
w.source = qid;
|
||||
if (q.top - b > 0)
|
||||
signalWork();
|
||||
if (s != b && a[(cap - 1) & b] != null)
|
||||
signalWork(q); // help signal if more tasks
|
||||
w.topLevelExec(t, q, // random fairness bound
|
||||
r & ((n << TOP_BOUND_SHIFT) - 1));
|
||||
(r | (1 << TOP_BOUND_SHIFT)) & SMASK);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@ -1900,7 +1909,7 @@ public class ForkJoinPool extends AbstractExecutorService {
|
||||
r = ThreadLocalRandom.advanceProbe(r);
|
||||
else {
|
||||
if (q.lockedPush(task))
|
||||
signalWork();
|
||||
signalWork(null);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -122,7 +122,7 @@ import java.util.concurrent.TimeUnit;
|
||||
* <p>All {@code Lock} implementations <em>must</em> enforce the same
|
||||
* memory synchronization semantics as provided by the built-in monitor
|
||||
* lock, as described in
|
||||
* <a href="https://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html#jls-17.4">
|
||||
* <a href="https://docs.oracle.com/javase/specs/jls/se11/html/jls-17.html#jls-17.4">
|
||||
* Chapter 17 of
|
||||
* <cite>The Java™ Language Specification</cite></a>:
|
||||
* <ul>
|
||||
|
@ -133,7 +133,7 @@ import jdk.internal.vm.annotation.ReservedStackAccess;
|
||||
* <p><b>Memory Synchronization.</b> Methods with the effect of
|
||||
* successfully locking in any mode have the same memory
|
||||
* synchronization effects as a <em>Lock</em> action described in
|
||||
* <a href="https://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html#jls-17.4">
|
||||
* <a href="https://docs.oracle.com/javase/specs/jls/se11/html/jls-17.html#jls-17.4">
|
||||
* Chapter 17 of <cite>The Java™ Language Specification</cite></a>.
|
||||
* Methods successfully unlocking in write mode have the same memory
|
||||
* synchronization effects as an <em>Unlock</em> action. In optimistic
|
||||
|
@ -226,7 +226,7 @@
|
||||
*
|
||||
* <h2 id="MemoryVisibility">Memory Consistency Properties</h2>
|
||||
*
|
||||
* <a href="https://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html#jls-17.4.5">
|
||||
* <a href="https://docs.oracle.com/javase/specs/jls/se11/html/jls-17.html#jls-17.4.5">
|
||||
* Chapter 17 of
|
||||
* <cite>The Java™ Language Specification</cite></a> defines the
|
||||
* <i>happens-before</i> relation on memory operations such as reads and
|
||||
|
@ -90,6 +90,9 @@ class ClientHandshakeContext extends HandshakeContext {
|
||||
|
||||
ClientHelloMessage initialClientHelloMsg = null;
|
||||
|
||||
// PSK identity is selected in first Hello and used again after HRR
|
||||
byte[] pskIdentity;
|
||||
|
||||
ClientHandshakeContext(SSLContextImpl sslContext,
|
||||
TransportContext conContext) throws IOException {
|
||||
super(sslContext, conContext);
|
||||
|
@ -656,7 +656,11 @@ final class PreSharedKeyExtension {
|
||||
return null;
|
||||
}
|
||||
SecretKey psk = pskOpt.get();
|
||||
Optional<byte[]> pskIdOpt = chc.resumingSession.consumePskIdentity();
|
||||
// The PSK ID can only be used in one connections, but this method
|
||||
// may be called twice in a connection if the server sends HRR.
|
||||
// ID is saved in the context so it can be used in the second call.
|
||||
Optional<byte[]> pskIdOpt = Optional.ofNullable(chc.pskIdentity)
|
||||
.or(chc.resumingSession::consumePskIdentity);
|
||||
if (!pskIdOpt.isPresent()) {
|
||||
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
|
||||
SSLLogger.fine(
|
||||
@ -664,7 +668,7 @@ final class PreSharedKeyExtension {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
byte[] pskId = pskIdOpt.get();
|
||||
chc.pskIdentity = pskIdOpt.get();
|
||||
|
||||
//The session cannot be used again. Remove it from the cache.
|
||||
SSLSessionContextImpl sessionCache = (SSLSessionContextImpl)
|
||||
@ -681,7 +685,7 @@ final class PreSharedKeyExtension {
|
||||
chc.resumingSession.getTicketCreationTime());
|
||||
int obfuscatedAge =
|
||||
ageMillis + chc.resumingSession.getTicketAgeAdd();
|
||||
identities.add(new PskIdentity(pskId, obfuscatedAge));
|
||||
identities.add(new PskIdentity(chc.pskIdentity, obfuscatedAge));
|
||||
|
||||
SecretKey binderKey = deriveBinderKey(psk, chc.resumingSession);
|
||||
ClientHelloMessage clientHello = (ClientHelloMessage)message;
|
||||
|
@ -52,4 +52,21 @@ public final class ArrayUtil {
|
||||
// NPE is thrown when array is null
|
||||
Preconditions.checkFromIndexSize(offset, len, array.length, AIOOBE_SUPPLIER);
|
||||
}
|
||||
|
||||
private static void swap(byte[] arr, int i, int j) {
|
||||
byte tmp = arr[i];
|
||||
arr[i] = arr[j];
|
||||
arr[j] = tmp;
|
||||
}
|
||||
|
||||
public static void reverse(byte [] arr) {
|
||||
int i = 0;
|
||||
int j = arr.length - 1;
|
||||
|
||||
while (i < j) {
|
||||
swap(arr, i, j);
|
||||
i++;
|
||||
j--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -40,6 +40,18 @@ import java.nio.ByteBuffer;
|
||||
|
||||
public interface MutableIntegerModuloP extends IntegerModuloP {
|
||||
|
||||
/**
|
||||
* Set this value to the value of b when set has the value 1.
|
||||
* No change is made to this element when set has the value 0. The
|
||||
* result is undefined when set has a value other than 0 or 1. The set
|
||||
* parameter is an int (rather than boolean) to allow the implementation
|
||||
* to perform the assignment using branch-free integer arithmetic.
|
||||
*
|
||||
* @param b the element to conditionally swap with
|
||||
* @param set an int that determines whether to set
|
||||
*/
|
||||
void conditionalSet(IntegerModuloP b, int set);
|
||||
|
||||
/**
|
||||
* Swap the value of this with the value of b when swap has the value 1.
|
||||
* No change is made to either element when swap has the value 0. The
|
||||
@ -131,5 +143,20 @@ public interface MutableIntegerModuloP extends IntegerModuloP {
|
||||
* @return this
|
||||
*/
|
||||
MutableIntegerModuloP setProduct(SmallValue v);
|
||||
|
||||
/**
|
||||
* Set the value of this element equal to 0 - this.
|
||||
*
|
||||
* @return this
|
||||
*/
|
||||
MutableIntegerModuloP setAdditiveInverse();
|
||||
|
||||
/**
|
||||
* Some implementations required reduction operations to be requested
|
||||
* by the client at certain times. This method reduces the representation.
|
||||
*
|
||||
* @return this
|
||||
*/
|
||||
MutableIntegerModuloP setReduced();
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -69,14 +69,25 @@ public abstract class IntegerPolynomial implements IntegerFieldModuloP {
|
||||
private final BigInteger modulus;
|
||||
protected final int bitsPerLimb;
|
||||
private final long[] posModLimbs;
|
||||
private final int maxAdds;
|
||||
|
||||
/**
|
||||
* Reduce an IntegerPolynomial representation (a) and store the result
|
||||
* in a. Requires that a.length == numLimbs.
|
||||
*/
|
||||
protected abstract void reduce(long[] a);
|
||||
|
||||
/**
|
||||
* Multiply an IntegerPolynomial representation (a) with a long (b) and
|
||||
* store the result in an IntegerPolynomial representation (r). Requires
|
||||
* that a.length == r.length == numLimbs. It is allowed for a and r to be
|
||||
* the same array.
|
||||
* store the result in an IntegerPolynomial representation in a. Requires
|
||||
* that a.length == numLimbs.
|
||||
*/
|
||||
protected abstract void multByInt(long[] a, long b, long[] r);
|
||||
protected void multByInt(long[] a, long b) {
|
||||
for (int i = 0; i < a.length; i++) {
|
||||
a[i] *= b;
|
||||
}
|
||||
reduce(a);
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiply two IntegerPolynomial representations (a and b) and store the
|
||||
@ -96,12 +107,14 @@ public abstract class IntegerPolynomial implements IntegerFieldModuloP {
|
||||
|
||||
IntegerPolynomial(int bitsPerLimb,
|
||||
int numLimbs,
|
||||
int maxAdds,
|
||||
BigInteger modulus) {
|
||||
|
||||
|
||||
this.numLimbs = numLimbs;
|
||||
this.modulus = modulus;
|
||||
this.bitsPerLimb = bitsPerLimb;
|
||||
this.maxAdds = maxAdds;
|
||||
|
||||
posModLimbs = setPosModLimbs();
|
||||
}
|
||||
@ -116,6 +129,10 @@ public abstract class IntegerPolynomial implements IntegerFieldModuloP {
|
||||
return numLimbs;
|
||||
}
|
||||
|
||||
public int getMaxAdds() {
|
||||
return maxAdds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigInteger getSize() {
|
||||
return modulus;
|
||||
@ -155,12 +172,22 @@ public abstract class IntegerPolynomial implements IntegerFieldModuloP {
|
||||
*/
|
||||
protected void encode(ByteBuffer buf, int length, byte highByte,
|
||||
long[] result) {
|
||||
|
||||
int numHighBits = 32 - Integer.numberOfLeadingZeros(highByte);
|
||||
int numBits = 8 * length + numHighBits;
|
||||
int maxBits = bitsPerLimb * result.length;
|
||||
if (numBits > maxBits) {
|
||||
throw new ArithmeticException("Value is too large.");
|
||||
int requiredLimbs = (numBits + bitsPerLimb - 1) / bitsPerLimb;
|
||||
if (requiredLimbs > numLimbs) {
|
||||
long[] temp = new long[requiredLimbs];
|
||||
encodeSmall(buf, length, highByte, temp);
|
||||
// encode does a full carry/reduce
|
||||
System.arraycopy(temp, 0, result, 0, result.length);
|
||||
} else {
|
||||
encodeSmall(buf, length, highByte, result);
|
||||
}
|
||||
}
|
||||
|
||||
protected void encodeSmall(ByteBuffer buf, int length, byte highByte,
|
||||
long[] result) {
|
||||
|
||||
int limbIndex = 0;
|
||||
long curLimbValue = 0;
|
||||
@ -195,10 +222,10 @@ public abstract class IntegerPolynomial implements IntegerFieldModuloP {
|
||||
}
|
||||
}
|
||||
|
||||
if (limbIndex < numLimbs) {
|
||||
if (limbIndex < result.length) {
|
||||
result[limbIndex++] = curLimbValue;
|
||||
}
|
||||
Arrays.fill(result, limbIndex, numLimbs, 0);
|
||||
Arrays.fill(result, limbIndex, result.length, 0);
|
||||
|
||||
postEncodeCarry(result);
|
||||
}
|
||||
@ -211,8 +238,10 @@ public abstract class IntegerPolynomial implements IntegerFieldModuloP {
|
||||
encode(buf, length, highByte, result);
|
||||
}
|
||||
|
||||
// Encode does not produce compressed limbs. A simplified carry/reduce
|
||||
// operation can be used to compress the limbs.
|
||||
protected void postEncodeCarry(long[] v) {
|
||||
carry(v);
|
||||
reduce(v);
|
||||
}
|
||||
|
||||
public ImmutableElement getElement(byte[] v, int offset, int length,
|
||||
@ -222,7 +251,7 @@ public abstract class IntegerPolynomial implements IntegerFieldModuloP {
|
||||
|
||||
encode(v, offset, length, highByte, result);
|
||||
|
||||
return new ImmutableElement(result, true);
|
||||
return new ImmutableElement(result, 0);
|
||||
}
|
||||
|
||||
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,
|
||||
* 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 {
|
||||
|
||||
protected long[] limbs;
|
||||
protected boolean summand = false;
|
||||
protected int numAdds;
|
||||
|
||||
public Element(BigInteger v) {
|
||||
limbs = new long[numLimbs];
|
||||
@ -450,19 +493,19 @@ public abstract class IntegerPolynomial implements IntegerFieldModuloP {
|
||||
}
|
||||
|
||||
public Element(boolean v) {
|
||||
limbs = new long[numLimbs];
|
||||
limbs[0] = v ? 1l : 0l;
|
||||
summand = true;
|
||||
this.limbs = new long[numLimbs];
|
||||
this.limbs[0] = v ? 1l : 0l;
|
||||
this.numAdds = 0;
|
||||
}
|
||||
|
||||
private Element(long[] limbs, boolean summand) {
|
||||
private Element(long[] limbs, int numAdds) {
|
||||
this.limbs = limbs;
|
||||
this.summand = summand;
|
||||
this.numAdds = numAdds;
|
||||
}
|
||||
|
||||
private void setValue(BigInteger v) {
|
||||
setLimbsValue(v, limbs);
|
||||
summand = true;
|
||||
this.numAdds = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -477,14 +520,18 @@ public abstract class IntegerPolynomial implements IntegerFieldModuloP {
|
||||
|
||||
@Override
|
||||
public MutableElement mutable() {
|
||||
return new MutableElement(limbs.clone(), summand);
|
||||
return new MutableElement(limbs.clone(), numAdds);
|
||||
}
|
||||
|
||||
protected boolean isSummand() {
|
||||
return numAdds < maxAdds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImmutableElement add(IntegerModuloP genB) {
|
||||
|
||||
Element b = (Element) genB;
|
||||
if (!(summand && b.summand)) {
|
||||
if (!(isSummand() && b.isSummand())) {
|
||||
throw new ArithmeticException("Not a valid summand");
|
||||
}
|
||||
|
||||
@ -493,7 +540,8 @@ public abstract class IntegerPolynomial implements IntegerFieldModuloP {
|
||||
newLimbs[i] = limbs[i] + b.limbs[i];
|
||||
}
|
||||
|
||||
return new ImmutableElement(newLimbs, false);
|
||||
int newNumAdds = Math.max(numAdds, b.numAdds) + 1;
|
||||
return new ImmutableElement(newLimbs, newNumAdds);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -504,7 +552,7 @@ public abstract class IntegerPolynomial implements IntegerFieldModuloP {
|
||||
newLimbs[i] = -limbs[i];
|
||||
}
|
||||
|
||||
ImmutableElement result = new ImmutableElement(newLimbs, summand);
|
||||
ImmutableElement result = new ImmutableElement(newLimbs, numAdds);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -524,43 +572,52 @@ public abstract class IntegerPolynomial implements IntegerFieldModuloP {
|
||||
|
||||
long[] newLimbs = new long[limbs.length];
|
||||
mult(limbs, b.limbs, newLimbs);
|
||||
return new ImmutableElement(newLimbs, true);
|
||||
return new ImmutableElement(newLimbs, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImmutableElement square() {
|
||||
long[] newLimbs = new long[limbs.length];
|
||||
IntegerPolynomial.this.square(limbs, newLimbs);
|
||||
return new ImmutableElement(newLimbs, true);
|
||||
return new ImmutableElement(newLimbs, 0);
|
||||
}
|
||||
|
||||
public void addModPowerTwo(IntegerModuloP arg, byte[] result) {
|
||||
|
||||
Element other = (Element) arg;
|
||||
if (!(summand && other.summand)) {
|
||||
if (!(isSummand() && other.isSummand())) {
|
||||
throw new ArithmeticException("Not a valid summand");
|
||||
}
|
||||
addLimbsModPowerTwo(limbs, other.limbs, result);
|
||||
}
|
||||
|
||||
public void asByteArray(byte[] result) {
|
||||
if (!summand) {
|
||||
if (!isSummand()) {
|
||||
throw new ArithmeticException("Not a valid summand");
|
||||
}
|
||||
limbsToByteArray(limbs, result);
|
||||
}
|
||||
}
|
||||
|
||||
private class MutableElement extends Element
|
||||
protected class MutableElement extends Element
|
||||
implements MutableIntegerModuloP {
|
||||
|
||||
protected MutableElement(long[] limbs, boolean summand) {
|
||||
super(limbs, summand);
|
||||
protected MutableElement(long[] limbs, int numAdds) {
|
||||
super(limbs, numAdds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImmutableElement fixed() {
|
||||
return new ImmutableElement(limbs.clone(), summand);
|
||||
return new ImmutableElement(limbs.clone(), numAdds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void conditionalSet(IntegerModuloP b, int set) {
|
||||
|
||||
Element other = (Element) b;
|
||||
|
||||
conditionalAssign(set, limbs, other.limbs);
|
||||
numAdds = other.numAdds;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -569,9 +626,9 @@ public abstract class IntegerPolynomial implements IntegerFieldModuloP {
|
||||
MutableElement other = (MutableElement) b;
|
||||
|
||||
conditionalSwap(swap, limbs, other.limbs);
|
||||
boolean summandTemp = summand;
|
||||
summand = other.summand;
|
||||
other.summand = summandTemp;
|
||||
int numAddsTemp = numAdds;
|
||||
numAdds = other.numAdds;
|
||||
other.numAdds = numAddsTemp;
|
||||
}
|
||||
|
||||
|
||||
@ -580,7 +637,7 @@ public abstract class IntegerPolynomial implements IntegerFieldModuloP {
|
||||
Element other = (Element) v;
|
||||
|
||||
System.arraycopy(other.limbs, 0, limbs, 0, other.limbs.length);
|
||||
summand = other.summand;
|
||||
numAdds = other.numAdds;
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -589,7 +646,7 @@ public abstract class IntegerPolynomial implements IntegerFieldModuloP {
|
||||
int length, byte highByte) {
|
||||
|
||||
encode(arr, offset, length, highByte, limbs);
|
||||
summand = true;
|
||||
this.numAdds = 0;
|
||||
|
||||
return this;
|
||||
}
|
||||
@ -599,7 +656,7 @@ public abstract class IntegerPolynomial implements IntegerFieldModuloP {
|
||||
byte highByte) {
|
||||
|
||||
encode(buf, length, highByte, limbs);
|
||||
summand = true;
|
||||
numAdds = 0;
|
||||
|
||||
return this;
|
||||
}
|
||||
@ -608,15 +665,15 @@ public abstract class IntegerPolynomial implements IntegerFieldModuloP {
|
||||
public MutableElement setProduct(IntegerModuloP genB) {
|
||||
Element b = (Element) genB;
|
||||
mult(limbs, b.limbs, limbs);
|
||||
summand = true;
|
||||
numAdds = 0;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutableElement setProduct(SmallValue v) {
|
||||
int value = ((Limb) v).value;
|
||||
multByInt(limbs, value, limbs);
|
||||
summand = true;
|
||||
multByInt(limbs, value);
|
||||
numAdds = 0;
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -624,7 +681,7 @@ public abstract class IntegerPolynomial implements IntegerFieldModuloP {
|
||||
public MutableElement setSum(IntegerModuloP genB) {
|
||||
|
||||
Element b = (Element) genB;
|
||||
if (!(summand && b.summand)) {
|
||||
if (!(isSummand() && b.isSummand())) {
|
||||
throw new ArithmeticException("Not a valid summand");
|
||||
}
|
||||
|
||||
@ -632,7 +689,7 @@ public abstract class IntegerPolynomial implements IntegerFieldModuloP {
|
||||
limbs[i] = limbs[i] + b.limbs[i];
|
||||
}
|
||||
|
||||
summand = false;
|
||||
numAdds = Math.max(numAdds, b.numAdds) + 1;
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -640,7 +697,7 @@ public abstract class IntegerPolynomial implements IntegerFieldModuloP {
|
||||
public MutableElement setDifference(IntegerModuloP genB) {
|
||||
|
||||
Element b = (Element) genB;
|
||||
if (!(summand && b.summand)) {
|
||||
if (!(isSummand() && b.isSummand())) {
|
||||
throw new ArithmeticException("Not a valid summand");
|
||||
}
|
||||
|
||||
@ -648,16 +705,33 @@ public abstract class IntegerPolynomial implements IntegerFieldModuloP {
|
||||
limbs[i] = limbs[i] - b.limbs[i];
|
||||
}
|
||||
|
||||
numAdds = Math.max(numAdds, b.numAdds) + 1;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutableElement setSquare() {
|
||||
IntegerPolynomial.this.square(limbs, limbs);
|
||||
summand = true;
|
||||
numAdds = 0;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutableElement setAdditiveInverse() {
|
||||
|
||||
for (int i = 0; i < limbs.length; i++) {
|
||||
limbs[i] = -limbs[i];
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutableElement setReduced() {
|
||||
|
||||
reduce(limbs);
|
||||
numAdds = 0;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
class ImmutableElement extends Element implements ImmutableIntegerModuloP {
|
||||
@ -670,8 +744,8 @@ public abstract class IntegerPolynomial implements IntegerFieldModuloP {
|
||||
super(v);
|
||||
}
|
||||
|
||||
protected ImmutableElement(long[] limbs, boolean summand) {
|
||||
super(limbs, summand);
|
||||
protected ImmutableElement(long[] limbs, int numAdds) {
|
||||
super(limbs, numAdds);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -45,7 +45,7 @@ public class IntegerPolynomial1305 extends IntegerPolynomial {
|
||||
= TWO.pow(POWER).subtract(BigInteger.valueOf(SUBTRAHEND));
|
||||
|
||||
public IntegerPolynomial1305() {
|
||||
super(BITS_PER_LIMB, NUM_LIMBS, MODULUS);
|
||||
super(BITS_PER_LIMB, NUM_LIMBS, 1, MODULUS);
|
||||
}
|
||||
|
||||
protected void mult(long[] a, long[] b, long[] r) {
|
||||
@ -96,15 +96,6 @@ public class IntegerPolynomial1305 extends IntegerPolynomial {
|
||||
carry(r);
|
||||
}
|
||||
|
||||
protected void multByInt(long[] a, long b, long[] r) {
|
||||
|
||||
for (int i = 0; i < a.length; i++) {
|
||||
r[i] = a[i] * b;
|
||||
}
|
||||
|
||||
reduce(r);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void square(long[] a, long[] r) {
|
||||
// Use grade-school multiplication with a simple squaring optimization.
|
||||
@ -199,7 +190,12 @@ public class IntegerPolynomial1305 extends IntegerPolynomial {
|
||||
return x >> BITS_PER_LIMB;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void postEncodeCarry(long[] v) {
|
||||
// not needed because carry is unsigned
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void reduce(long[] limbs) {
|
||||
long carry3 = carryOut(limbs, 3);
|
||||
long new4 = carry3 + limbs[4];
|
||||
|
@ -48,7 +48,7 @@ public class IntegerPolynomial25519 extends IntegerPolynomial {
|
||||
private static final int RIGHT_BIT_OFFSET = BITS_PER_LIMB - BIT_OFFSET;
|
||||
|
||||
public IntegerPolynomial25519() {
|
||||
super(BITS_PER_LIMB, NUM_LIMBS, MODULUS);
|
||||
super(BITS_PER_LIMB, NUM_LIMBS, 1, MODULUS);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -59,6 +59,26 @@ public class IntegerPolynomial25519 extends IntegerPolynomial {
|
||||
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
|
||||
protected void mult(long[] a, long[] b, long[] r) {
|
||||
|
||||
@ -153,28 +173,6 @@ public class IntegerPolynomial25519 extends IntegerPolynomial {
|
||||
carry(r, 0, 9);
|
||||
}
|
||||
|
||||
protected void multByInt(long[] a, long b, long[] r) {
|
||||
for (int i = 0; i < a.length; i++) {
|
||||
r[i] = a[i] * b;
|
||||
}
|
||||
|
||||
// carry(8, 2)
|
||||
long carry8 = carryValue(r[8]);
|
||||
r[8] -= (carry8 << BITS_PER_LIMB);
|
||||
r[9] += carry8;
|
||||
|
||||
long carry9 = carryValue(r[9]);
|
||||
r[9] -= (carry9 << BITS_PER_LIMB);
|
||||
|
||||
// reduce(0, 1)
|
||||
long reducedValue10 = (carry9 * SUBTRAHEND);
|
||||
r[0] += ((reducedValue10 << BIT_OFFSET) & LIMB_MASK);
|
||||
r[1] += reducedValue10 >> RIGHT_BIT_OFFSET;
|
||||
|
||||
// carry(0, 9)
|
||||
carry(r, 0, 9);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void square(long[] a, long[] r) {
|
||||
|
||||
|
@ -42,7 +42,7 @@ public class IntegerPolynomial448 extends IntegerPolynomial {
|
||||
.subtract(BigInteger.valueOf(1));
|
||||
|
||||
public IntegerPolynomial448() {
|
||||
super(BITS_PER_LIMB, NUM_LIMBS, MODULUS);
|
||||
super(BITS_PER_LIMB, NUM_LIMBS, 1, MODULUS);
|
||||
}
|
||||
|
||||
private void modReduceIn(long[] limbs, int index, long x) {
|
||||
@ -57,6 +57,25 @@ public class IntegerPolynomial448 extends IntegerPolynomial {
|
||||
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
|
||||
protected void mult(long[] a, long[] b, long[] r) {
|
||||
|
||||
@ -176,27 +195,6 @@ public class IntegerPolynomial448 extends IntegerPolynomial {
|
||||
carry(r, 0, 15);
|
||||
}
|
||||
|
||||
protected void multByInt(long[] a, long b, long[] r) {
|
||||
for (int i = 0; i < a.length; i++) {
|
||||
r[i] = a[i] * b;
|
||||
}
|
||||
|
||||
// carry(14, 2)
|
||||
long carry14 = carryValue(r[14]);
|
||||
r[14] -= (carry14 << BITS_PER_LIMB);
|
||||
r[15] += carry14;
|
||||
|
||||
long carry15 = carryValue(r[15]);
|
||||
r[15] -= (carry15 << BITS_PER_LIMB);
|
||||
|
||||
// reduce(0, 1)
|
||||
r[0] += carry15;
|
||||
r[8] += carry15;
|
||||
|
||||
// carry(0, 15)
|
||||
carry(r, 0, 15);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void square(long[] a, long[] r) {
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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
@ -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.
|
||||
*/
|
@ -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;
|
||||
}
|
||||
}
|
@ -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.
|
||||
*
|
||||
* 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,
|
||||
boolean checkUnresolvedCritExts) throws CertificateException {
|
||||
boolean checkUnresolvedCritExts, X509Certificate anchor)
|
||||
throws CertificateException {
|
||||
|
||||
if (variant.equals(Validator.VAR_GENERIC)) {
|
||||
return; // no checks
|
||||
}
|
||||
@ -159,6 +161,12 @@ class EndEntityChecker {
|
||||
if (checkUnresolvedCritExts) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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() {}
|
||||
}
|
@ -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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -275,7 +275,8 @@ public abstract class Validator {
|
||||
boolean checkUnresolvedCritExts =
|
||||
(type == TYPE_PKIX) ? false : true;
|
||||
endEntityChecker.check(chain[0], parameter,
|
||||
checkUnresolvedCritExts);
|
||||
checkUnresolvedCritExts,
|
||||
chain[chain.length-1]);
|
||||
}
|
||||
|
||||
return chain;
|
||||
|
@ -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.
|
||||
#
|
||||
#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
|
||||
|
@ -412,7 +412,7 @@ final class ProcessImpl extends Process {
|
||||
new BufferedOutputStream(
|
||||
new FileOutputStream(newFileDescriptor(fds[0])));
|
||||
|
||||
stdout = (fds[1] == -1) ?
|
||||
stdout = (fds[1] == -1 || forceNullOutputStream) ?
|
||||
ProcessBuilder.NullInputStream.INSTANCE :
|
||||
new BufferedInputStream(
|
||||
stdout_inner_stream =
|
||||
@ -446,7 +446,7 @@ final class ProcessImpl extends Process {
|
||||
ProcessBuilder.NullOutputStream.INSTANCE :
|
||||
new ProcessPipeOutputStream(fds[0]);
|
||||
|
||||
stdout = (fds[1] == -1) ?
|
||||
stdout = (fds[1] == -1 || forceNullOutputStream) ?
|
||||
ProcessBuilder.NullInputStream.INSTANCE :
|
||||
new DeferredCloseProcessPipeInputStream(fds[1]);
|
||||
|
||||
|
@ -333,8 +333,7 @@ final class AOTCompiledClass {
|
||||
AOTKlassData data = klassData.get(name);
|
||||
if (data != null) {
|
||||
HotSpotResolvedObjectType oldType = data.getType();
|
||||
assert oldType == type : "duplicate classes for name " + type.getName() + ", fingerprints old: " + oldType.getFingerprint() + ", new: " + type.getFingerprint() +
|
||||
", klass pointers old: " + oldType.klass() + ", new: " + type.klass();
|
||||
assert oldType.equals(type) : "duplicate classes for name " + type.getName();
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
@ -1121,7 +1121,7 @@ public class Attr extends JCTree.Visitor {
|
||||
|
||||
public void visitVarDef(JCVariableDecl tree) {
|
||||
// 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) {
|
||||
// parameters have already been entered
|
||||
env.info.scope.enter(tree.sym);
|
||||
|
@ -1633,7 +1633,7 @@ public class Flow {
|
||||
protected boolean trackable(VarSymbol sym) {
|
||||
return
|
||||
sym.pos >= startPos &&
|
||||
((sym.owner.kind == MTH ||
|
||||
((sym.owner.kind == MTH || sym.owner.kind == VAR ||
|
||||
isFinalUninitializedField(sym)));
|
||||
}
|
||||
|
||||
@ -2009,7 +2009,7 @@ public class Flow {
|
||||
lint = lint.augment(tree.sym);
|
||||
try{
|
||||
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);
|
||||
}
|
||||
if (tree.init != null) {
|
||||
|
@ -25,8 +25,6 @@
|
||||
|
||||
package com.sun.tools.javac.jvm;
|
||||
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
import com.sun.tools.javac.tree.TreeInfo.PosKind;
|
||||
import com.sun.tools.javac.util.*;
|
||||
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
|
||||
@ -166,6 +164,7 @@ public class Gen extends JCTree.Visitor {
|
||||
boolean inCondSwitchExpression;
|
||||
Chain switchExpressionTrueChain;
|
||||
Chain switchExpressionFalseChain;
|
||||
List<LocalItem> stackBeforeSwitchExpression;
|
||||
|
||||
/** Generate code to load an integer constant.
|
||||
* @param n The integer to be loaded.
|
||||
@ -1178,13 +1177,59 @@ public class Gen extends JCTree.Visitor {
|
||||
}
|
||||
|
||||
private void doHandleSwitchExpression(JCSwitchExpression tree) {
|
||||
int prevLetExprStart = code.setLetExprStackPos(code.state.stacksize);
|
||||
List<LocalItem> prevStackBeforeSwitchExpression = stackBeforeSwitchExpression;
|
||||
int limit = code.nextreg;
|
||||
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 {
|
||||
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) {
|
||||
int limit = code.nextreg;
|
||||
@ -1659,14 +1704,17 @@ public class Gen extends JCTree.Visitor {
|
||||
}
|
||||
|
||||
public void visitBreak(JCBreak tree) {
|
||||
int tmpPos = code.pendingStatPos;
|
||||
Assert.check(code.isStatementStart());
|
||||
Env<GenContext> targetEnv = unwind(tree.target, env);
|
||||
code.pendingStatPos = tmpPos;
|
||||
final Env<GenContext> targetEnv;
|
||||
if (tree.isValueBreak()) {
|
||||
//restore stack as it was before the switch expression:
|
||||
for (LocalItem li : stackBeforeSwitchExpression) {
|
||||
li.load();
|
||||
}
|
||||
if (inCondSwitchExpression) {
|
||||
CondItem value = genCond(tree.value, CRT_FLOW_TARGET);
|
||||
Chain falseJumps = value.jumpFalse();
|
||||
targetEnv = unwindBreak(tree);
|
||||
code.resolve(value.trueJumps);
|
||||
Chain trueJumps = code.branch(goto_);
|
||||
if (switchExpressionTrueChain == null) {
|
||||
@ -1684,13 +1732,22 @@ public class Gen extends JCTree.Visitor {
|
||||
} else {
|
||||
genExpr(tree.value, pt).load();
|
||||
code.state.forceStackTop(tree.target.type);
|
||||
targetEnv = unwindBreak(tree);
|
||||
targetEnv.info.addExit(code.branch(goto_));
|
||||
}
|
||||
} else {
|
||||
targetEnv = unwindBreak(tree);
|
||||
targetEnv.info.addExit(code.branch(goto_));
|
||||
}
|
||||
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) {
|
||||
int tmpPos = code.pendingStatPos;
|
||||
@ -2138,7 +2195,7 @@ public class Gen extends JCTree.Visitor {
|
||||
res = items.makeMemberItem(sym, true);
|
||||
}
|
||||
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);
|
||||
} else if (isInvokeDynamic(sym)) {
|
||||
result = items.makeDynamicItem(sym);
|
||||
|
@ -25,14 +25,19 @@
|
||||
|
||||
package sun.security.ec;
|
||||
|
||||
import java.math.*;
|
||||
import java.security.*;
|
||||
import java.security.interfaces.*;
|
||||
import java.security.spec.*;
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.crypto.*;
|
||||
import javax.crypto.spec.*;
|
||||
|
||||
import sun.security.util.ArrayUtil;
|
||||
import sun.security.util.ECUtil;
|
||||
import sun.security.util.math.*;
|
||||
import sun.security.ec.point.*;
|
||||
|
||||
/**
|
||||
* KeyAgreement implementation for ECDH.
|
||||
@ -44,8 +49,8 @@ public final class ECDHKeyAgreement extends KeyAgreementSpi {
|
||||
// private key, if initialized
|
||||
private ECPrivateKey privateKey;
|
||||
|
||||
// encoded public point, non-null between doPhase() & generateSecret() only
|
||||
private byte[] publicValue;
|
||||
// public key, non-null between doPhase() & generateSecret() only
|
||||
private ECPublicKey publicKey;
|
||||
|
||||
// length of the secret to be derived
|
||||
private int secretLen;
|
||||
@ -65,7 +70,7 @@ public final class ECDHKeyAgreement extends KeyAgreementSpi {
|
||||
("Key must be instance of PrivateKey");
|
||||
}
|
||||
privateKey = (ECPrivateKey) ECKeyFactory.toECKey(key);
|
||||
publicValue = null;
|
||||
publicKey = null;
|
||||
}
|
||||
|
||||
// see JCE spec
|
||||
@ -87,7 +92,7 @@ public final class ECDHKeyAgreement extends KeyAgreementSpi {
|
||||
if (privateKey == null) {
|
||||
throw new IllegalStateException("Not initialized");
|
||||
}
|
||||
if (publicValue != null) {
|
||||
if (publicKey != null) {
|
||||
throw new IllegalStateException("Phase already executed");
|
||||
}
|
||||
if (!lastPhase) {
|
||||
@ -99,42 +104,74 @@ public final class ECDHKeyAgreement extends KeyAgreementSpi {
|
||||
("Key must be a PublicKey with algorithm EC");
|
||||
}
|
||||
|
||||
ECPublicKey ecKey = (ECPublicKey)key;
|
||||
ECParameterSpec params = ecKey.getParams();
|
||||
this.publicKey = (ECPublicKey) key;
|
||||
|
||||
if (ecKey instanceof ECPublicKeyImpl) {
|
||||
publicValue = ((ECPublicKeyImpl)ecKey).getEncodedPublicValue();
|
||||
} else { // instanceof ECPublicKey
|
||||
publicValue =
|
||||
ECUtil.encodePoint(ecKey.getW(), params.getCurve());
|
||||
}
|
||||
ECParameterSpec params = publicKey.getParams();
|
||||
int keyLenBits = params.getCurve().getField().getFieldSize();
|
||||
secretLen = (keyLenBits + 7) >> 3;
|
||||
|
||||
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
|
||||
@Override
|
||||
protected byte[] engineGenerateSecret() throws IllegalStateException {
|
||||
if ((privateKey == null) || (publicValue == null)) {
|
||||
if ((privateKey == null) || (publicKey == null)) {
|
||||
throw new IllegalStateException("Not initialized correctly");
|
||||
}
|
||||
|
||||
byte[] s = privateKey.getS().toByteArray();
|
||||
byte[] encodedParams = // DER OID
|
||||
ECUtil.encodeECParameterSpec(null, privateKey.getParams());
|
||||
|
||||
try {
|
||||
|
||||
byte[] result = deriveKey(s, publicValue, encodedParams);
|
||||
publicValue = null;
|
||||
return result;
|
||||
|
||||
} catch (GeneralSecurityException e) {
|
||||
throw new ProviderException("Could not derive key", e);
|
||||
}
|
||||
|
||||
Optional<byte[]> resultOpt = deriveKeyImpl(privateKey, publicKey);
|
||||
byte[] result = resultOpt.orElseGet(
|
||||
() -> deriveKeyNative(privateKey, publicKey)
|
||||
);
|
||||
publicKey = null;
|
||||
return result;
|
||||
}
|
||||
|
||||
// see JCE spec
|
||||
@ -143,7 +180,8 @@ public final class ECDHKeyAgreement extends KeyAgreementSpi {
|
||||
offset) throws IllegalStateException, ShortBufferException {
|
||||
if (offset + secretLen > sharedSecret.length) {
|
||||
throw new ShortBufferException("Need " + secretLen
|
||||
+ " bytes, only " + (sharedSecret.length - offset) + " available");
|
||||
+ " bytes, only " + (sharedSecret.length - offset)
|
||||
+ " available");
|
||||
}
|
||||
byte[] secret = engineGenerateSecret();
|
||||
System.arraycopy(secret, 0, sharedSecret, offset, secret.length);
|
||||
@ -165,6 +203,78 @@ public final class ECDHKeyAgreement extends KeyAgreementSpi {
|
||||
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.
|
||||
*
|
||||
|
@ -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;
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -32,9 +32,11 @@ import java.math.BigInteger;
|
||||
import java.security.*;
|
||||
import java.security.interfaces.*;
|
||||
import java.security.spec.*;
|
||||
import java.util.Optional;
|
||||
|
||||
import sun.security.jca.JCAUtil;
|
||||
import sun.security.util.*;
|
||||
import static sun.security.ec.ECOperations.IntermediateValueException;
|
||||
|
||||
/**
|
||||
* ECDSA signature implementation. This class currently supports the
|
||||
@ -147,7 +149,7 @@ abstract class ECDSASignature extends SignatureSpi {
|
||||
// Stores the precomputed message digest value.
|
||||
@Override
|
||||
protected void engineUpdate(byte[] b, int off, int len)
|
||||
throws SignatureException {
|
||||
throws SignatureException {
|
||||
if (offset >= precomputedDigest.length) {
|
||||
offset = RAW_ECDSA_MAX + 1;
|
||||
return;
|
||||
@ -172,7 +174,7 @@ abstract class ECDSASignature extends SignatureSpi {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void resetDigest(){
|
||||
protected void resetDigest() {
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
@ -222,14 +224,14 @@ abstract class ECDSASignature extends SignatureSpi {
|
||||
// Nested class for SHA224withECDSA signatures
|
||||
public static final class SHA224 extends ECDSASignature {
|
||||
public SHA224() {
|
||||
super("SHA-224");
|
||||
super("SHA-224");
|
||||
}
|
||||
}
|
||||
|
||||
// Nested class for SHA224withECDSAinP1363Format signatures
|
||||
public static final class SHA224inP1363Format extends ECDSASignature {
|
||||
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
|
||||
@Override
|
||||
protected void engineInitVerify(PublicKey publicKey)
|
||||
throws InvalidKeyException {
|
||||
throws InvalidKeyException {
|
||||
this.publicKey = (ECPublicKey) ECKeyFactory.toECKey(publicKey);
|
||||
|
||||
// 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
|
||||
@Override
|
||||
protected void engineInitSign(PrivateKey privateKey)
|
||||
throws InvalidKeyException {
|
||||
throws InvalidKeyException {
|
||||
engineInitSign(privateKey, null);
|
||||
}
|
||||
|
||||
// initialize for signing. See JCA doc
|
||||
@Override
|
||||
protected void engineInitSign(PrivateKey privateKey, SecureRandom random)
|
||||
throws InvalidKeyException {
|
||||
throws InvalidKeyException {
|
||||
this.privateKey = (ECPrivateKey) ECKeyFactory.toECKey(privateKey);
|
||||
|
||||
// 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
|
||||
@Override
|
||||
protected void engineUpdate(byte[] b, int off, int len)
|
||||
throws SignatureException {
|
||||
throws SignatureException {
|
||||
messageDigest.update(b, off, len);
|
||||
needsReset = true;
|
||||
}
|
||||
@ -354,20 +356,67 @@ abstract class ECDSASignature extends SignatureSpi {
|
||||
needsReset = true;
|
||||
}
|
||||
|
||||
// sign the data and return the signature. See JCA doc
|
||||
@Override
|
||||
protected byte[] engineSign() throws SignatureException {
|
||||
private byte[] signDigestImpl(ECDSAOperations ops, int seedBits,
|
||||
byte[] digest, ECPrivateKeyImpl privImpl, SecureRandom random)
|
||||
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();
|
||||
ECParameterSpec params = privateKey.getParams();
|
||||
|
||||
// DER OID
|
||||
byte[] encodedParams = ECUtil.encodeECParameterSpec(null, params);
|
||||
int keySize = params.getCurve().getField().getFieldSize();
|
||||
|
||||
// seed is twice the key size (in bytes) plus 1
|
||||
byte[] seed = new byte[(((keySize + 7) >> 3) + 1) * 2];
|
||||
if (random == null) {
|
||||
random = JCAUtil.getSecureRandom();
|
||||
}
|
||||
|
||||
random.nextBytes(seed);
|
||||
|
||||
// random bits needed for timing countermeasures
|
||||
@ -375,14 +424,32 @@ abstract class ECDSASignature extends SignatureSpi {
|
||||
// values must be non-zero to enable countermeasures
|
||||
timingArgument |= 1;
|
||||
|
||||
byte[] sig;
|
||||
try {
|
||||
sig = signDigest(getDigestValue(), s, encodedParams, seed,
|
||||
return signDigest(digest, s, encodedParams, seed,
|
||||
timingArgument);
|
||||
} catch (GeneralSecurityException 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) {
|
||||
return sig;
|
||||
} else {
|
||||
@ -400,7 +467,7 @@ abstract class ECDSASignature extends SignatureSpi {
|
||||
byte[] encodedParams = ECUtil.encodeECParameterSpec(null, params);
|
||||
|
||||
if (publicKey instanceof ECPublicKeyImpl) {
|
||||
w = ((ECPublicKeyImpl)publicKey).getEncodedPublicValue();
|
||||
w = ((ECPublicKeyImpl) publicKey).getEncodedPublicValue();
|
||||
} else { // instanceof ECPublicKey
|
||||
w = ECUtil.encodePoint(publicKey.getW(), params.getCurve());
|
||||
}
|
||||
@ -423,13 +490,13 @@ abstract class ECDSASignature extends SignatureSpi {
|
||||
@Override
|
||||
@Deprecated
|
||||
protected void engineSetParameter(String param, Object value)
|
||||
throws InvalidParameterException {
|
||||
throws InvalidParameterException {
|
||||
throw new UnsupportedOperationException("setParameter() not supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void engineSetParameter(AlgorithmParameterSpec params)
|
||||
throws InvalidAlgorithmParameterException {
|
||||
throws InvalidAlgorithmParameterException {
|
||||
if (params != null) {
|
||||
throw new InvalidAlgorithmParameterException("No parameter accepted");
|
||||
}
|
||||
@ -439,7 +506,7 @@ abstract class ECDSASignature extends SignatureSpi {
|
||||
@Override
|
||||
@Deprecated
|
||||
protected Object engineGetParameter(String param)
|
||||
throws InvalidParameterException {
|
||||
throws InvalidParameterException {
|
||||
throw new UnsupportedOperationException("getParameter() not supported");
|
||||
}
|
||||
|
||||
@ -464,7 +531,7 @@ abstract class ECDSASignature extends SignatureSpi {
|
||||
out.putInteger(r);
|
||||
out.putInteger(s);
|
||||
DerValue result =
|
||||
new DerValue(DerValue.tag_Sequence, out.toByteArray());
|
||||
new DerValue(DerValue.tag_Sequence, out.toByteArray());
|
||||
|
||||
return result.toByteArray();
|
||||
|
||||
@ -497,9 +564,9 @@ abstract class ECDSASignature extends SignatureSpi {
|
||||
// r and s each occupy half the array
|
||||
byte[] result = new byte[k << 1];
|
||||
System.arraycopy(rBytes, 0, result, k - rBytes.length,
|
||||
rBytes.length);
|
||||
rBytes.length);
|
||||
System.arraycopy(sBytes, 0, result, result.length - sBytes.length,
|
||||
sBytes.length);
|
||||
sBytes.length);
|
||||
return result;
|
||||
|
||||
} catch (Exception e) {
|
||||
@ -539,13 +606,13 @@ abstract class ECDSASignature extends SignatureSpi {
|
||||
* @return byte[] the signature.
|
||||
*/
|
||||
private static native byte[] signDigest(byte[] digest, byte[] s,
|
||||
byte[] encodedParams, byte[] seed, int timing)
|
||||
throws GeneralSecurityException;
|
||||
byte[] encodedParams, byte[] seed, int timing)
|
||||
throws GeneralSecurityException;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* @param digest the digest to be used.
|
||||
* @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.
|
||||
*/
|
||||
private static native boolean verifySignedDigest(byte[] signature,
|
||||
byte[] digest, byte[] w, byte[] encodedParams)
|
||||
throws GeneralSecurityException;
|
||||
byte[] digest, byte[] w, byte[] encodedParams)
|
||||
throws GeneralSecurityException;
|
||||
}
|
||||
|
@ -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.
|
||||
*
|
||||
* 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.ECPoint;
|
||||
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.util.ECParameters;
|
||||
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.ec.ECOperations.IntermediateValueException;
|
||||
|
||||
/**
|
||||
* EC keypair generator.
|
||||
@ -90,14 +92,14 @@ public final class ECKeyPairGenerator extends KeyPairGeneratorSpi {
|
||||
ECParameterSpec ecSpec = null;
|
||||
|
||||
if (params instanceof ECParameterSpec) {
|
||||
ecSpec = ECUtil.getECParameterSpec(null,
|
||||
(ECParameterSpec)params);
|
||||
ECParameterSpec ecParams = (ECParameterSpec) params;
|
||||
ecSpec = ECUtil.getECParameterSpec(null, ecParams);
|
||||
if (ecSpec == null) {
|
||||
throw new InvalidAlgorithmParameterException(
|
||||
"Unsupported curve: " + params);
|
||||
}
|
||||
} else if (params instanceof ECGenParameterSpec) {
|
||||
String name = ((ECGenParameterSpec)params).getName();
|
||||
String name = ((ECGenParameterSpec) params).getName();
|
||||
ecSpec = ECUtil.getECParameterSpec(null, name);
|
||||
if (ecSpec == null) {
|
||||
throw new InvalidAlgorithmParameterException(
|
||||
@ -112,8 +114,7 @@ public final class ECKeyPairGenerator extends KeyPairGeneratorSpi {
|
||||
ensureCurveIsSupported(ecSpec);
|
||||
this.params = ecSpec;
|
||||
|
||||
this.keySize =
|
||||
((ECParameterSpec)this.params).getCurve().getField().getFieldSize();
|
||||
this.keySize = ecSpec.getCurve().getField().getFieldSize();
|
||||
this.random = random;
|
||||
}
|
||||
|
||||
@ -141,41 +142,99 @@ public final class ECKeyPairGenerator extends KeyPairGeneratorSpi {
|
||||
@Override
|
||||
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) {
|
||||
random = JCAUtil.getSecureRandom();
|
||||
}
|
||||
random.nextBytes(seed);
|
||||
|
||||
try {
|
||||
|
||||
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, (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);
|
||||
Optional<KeyPair> kp = generateKeyPairImpl(random);
|
||||
if (kp.isPresent()) {
|
||||
return kp.get();
|
||||
}
|
||||
return generateKeyPairNative(random);
|
||||
} catch (Exception ex) {
|
||||
throw new ProviderException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
if (keySize < KEY_SIZE_MIN) {
|
||||
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
|
||||
* 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
|
||||
* by generateECKeyPair
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -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.
|
||||
*
|
||||
* 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.spec.*;
|
||||
|
||||
import sun.security.util.DerInputStream;
|
||||
import sun.security.util.DerOutputStream;
|
||||
import sun.security.util.DerValue;
|
||||
import sun.security.util.ECParameters;
|
||||
import sun.security.util.ECUtil;
|
||||
import sun.security.util.*;
|
||||
import sun.security.x509.AlgorithmId;
|
||||
import sun.security.pkcs.PKCS8Key;
|
||||
|
||||
@ -68,6 +64,7 @@ public final class ECPrivateKeyImpl extends PKCS8Key implements ECPrivateKey {
|
||||
private static final long serialVersionUID = 88695385615075129L;
|
||||
|
||||
private BigInteger s; // private value
|
||||
private byte[] arrayS; // private value as a little-endian array
|
||||
private ECParameterSpec params;
|
||||
|
||||
/**
|
||||
@ -85,13 +82,25 @@ public final class ECPrivateKeyImpl extends PKCS8Key implements ECPrivateKey {
|
||||
throws InvalidKeyException {
|
||||
this.s = s;
|
||||
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
|
||||
(AlgorithmId.EC_oid, ECParameters.getAlgorithmParameters(params));
|
||||
(AlgorithmId.EC_oid, ECParameters.getAlgorithmParameters(params));
|
||||
try {
|
||||
DerOutputStream out = new DerOutputStream();
|
||||
out.putInteger(1); // version 1
|
||||
byte[] privBytes = ECUtil.trimZeroes(s.toByteArray());
|
||||
byte[] privBytes = s.clone();
|
||||
ArrayUtil.reverse(privBytes);
|
||||
out.putOctetString(privBytes);
|
||||
DerValue val =
|
||||
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
|
||||
public String getAlgorithm() {
|
||||
return "EC";
|
||||
@ -109,9 +143,26 @@ public final class ECPrivateKeyImpl extends PKCS8Key implements ECPrivateKey {
|
||||
|
||||
// see JCA doc
|
||||
public BigInteger getS() {
|
||||
if (s == null) {
|
||||
byte[] arrCopy = arrayS.clone();
|
||||
ArrayUtil.reverse(arrCopy);
|
||||
s = new BigInteger(1, arrCopy);
|
||||
}
|
||||
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
|
||||
public ECParameterSpec getParams() {
|
||||
return params;
|
||||
@ -133,12 +184,13 @@ public final class ECPrivateKeyImpl extends PKCS8Key implements ECPrivateKey {
|
||||
throw new IOException("Version must be 1");
|
||||
}
|
||||
byte[] privData = data.getOctetString();
|
||||
s = new BigInteger(1, privData);
|
||||
ArrayUtil.reverse(privData);
|
||||
arrayS = privData;
|
||||
while (data.available() != 0) {
|
||||
DerValue value = data.getDerValue();
|
||||
if (value.isContextSpecific((byte)0)) {
|
||||
if (value.isContextSpecific((byte) 0)) {
|
||||
// ignore for now
|
||||
} else if (value.isContextSpecific((byte)1)) {
|
||||
} else if (value.isContextSpecific((byte) 1)) {
|
||||
// ignore for now
|
||||
} else {
|
||||
throw new InvalidKeyException("Unexpected value: " + value);
|
||||
|
@ -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() + ")";
|
||||
}
|
||||
}
|
@ -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 {
|
||||
}
|
@ -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);
|
||||
|
||||
}
|
@ -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();
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
@ -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();
|
||||
|
||||
}
|
@ -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
Loading…
Reference in New Issue
Block a user