mirror of
https://github.com/JetBrains/JetBrainsRuntime.git
synced 2026-01-06 00:21:41 +01:00
Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9461ec3274 | ||
|
|
6fd267c039 | ||
|
|
9c5f77562e | ||
|
|
edfd215b26 | ||
|
|
2752e57a65 | ||
|
|
a6c4eb7a49 | ||
|
|
0c2e94d7e3 | ||
|
|
e56dfb248d | ||
|
|
3e86311463 | ||
|
|
d15962b3eb | ||
|
|
a4ec50ccc7 | ||
|
|
6f12724349 | ||
|
|
3e7633ad1b | ||
|
|
ef2820f42b | ||
|
|
e791a1bd35 | ||
|
|
88c5ba27f9 | ||
|
|
8219a0d106 | ||
|
|
ca9d792284 | ||
|
|
bf7a80983c | ||
|
|
673c30bf37 | ||
|
|
95aaab9698 | ||
|
|
c5764c0bd4 | ||
|
|
24f3906f0c | ||
|
|
5e0f345c27 |
1
.gitattributes
vendored
1
.gitattributes
vendored
@@ -1 +0,0 @@
|
||||
* -text
|
||||
9
.hgtags
9
.hgtags
@@ -652,13 +652,4 @@ a32f58c6b8be81877411767de7ba9c4cf087c1b5 jdk-15+31
|
||||
4a8fd81d64bafa523cddb45f82805536edace106 jdk-16+6
|
||||
6b65f4e7a975628df51ef755b02642075390041d jdk-15+33
|
||||
c3a4a7ea7c304cabdacdc31741eb94c51351668d jdk-16+7
|
||||
b0817631d2f4395508cb10e81c3858a94d9ae4de jdk-15+34
|
||||
0a73d6f3aab48ff6d7e61e47f0bc2d87a054f217 jdk-16+8
|
||||
fd60c3146a024037cdd9be34c645bb793995a7cc jdk-15+35
|
||||
c075a286cc7df767cce28e8057d6ec5051786490 jdk-16+9
|
||||
b01985b4f88f554f97901e53e1ba314681dd9c19 jdk-16+10
|
||||
e3f940bd3c8fcdf4ca704c6eb1ac745d155859d5 jdk-15+36
|
||||
5c18d696c7ce724ca36df13933aa53f50e12b9e0 jdk-16+11
|
||||
fc8e62b399bd93d06e8d13dc3b384c450e853dcd jdk-16+12
|
||||
fd07cdb26fc70243ef23d688b545514f4ddf1c2b jdk-16+13
|
||||
36b29df125dc88f11657ce93b4998aa9ff5f5d41 jdk-16+14
|
||||
|
||||
33
.jcheck/conf
33
.jcheck/conf
@@ -1,33 +1,2 @@
|
||||
[general]
|
||||
project=jdk
|
||||
jbs=JDK
|
||||
|
||||
[checks]
|
||||
error=author,committer,reviewers,merge,issues,executable,symlink,message,hg-tag,whitespace,problemlists
|
||||
|
||||
[repository]
|
||||
tags=(?:jdk-(?:[1-9]([0-9]*)(?:\.(?:0|[1-9][0-9]*)){0,4})(?:\+(?:(?:[0-9]+))|(?:-ga)))|(?:jdk[4-9](?:u\d{1,3})?-(?:(?:b\d{2,3})|(?:ga)))|(?:hs\d\d(?:\.\d{1,2})?-b\d\d)
|
||||
branches=
|
||||
|
||||
[census]
|
||||
version=0
|
||||
domain=openjdk.org
|
||||
|
||||
[checks "whitespace"]
|
||||
files=.*\.cpp|.*\.hpp|.*\.c|.*\.h|.*\.java|.*\.cc|.*\.hh|.*\.m|.*\.mm
|
||||
|
||||
[checks "merge"]
|
||||
message=Merge
|
||||
|
||||
[checks "reviewers"]
|
||||
reviewers=1
|
||||
ignore=duke
|
||||
|
||||
[checks "committer"]
|
||||
role=committer
|
||||
|
||||
[checks "issues"]
|
||||
pattern=^([124-8][0-9]{6}): (\S.*)$
|
||||
|
||||
[checks "problemlists"]
|
||||
dirs=test/jdk|test/langtools|test/lib-test|test/hotspot/jtreg|test/jaxp
|
||||
bugids=dup
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
# Contributing to the JDK
|
||||
|
||||
Please see <https://openjdk.java.net/contribute/> for how to contribute.
|
||||
12
README
Normal file
12
README
Normal file
@@ -0,0 +1,12 @@
|
||||
|
||||
Welcome to the JDK!
|
||||
===================
|
||||
|
||||
For build instructions, please see either of these files:
|
||||
|
||||
* doc/building.html (html version)
|
||||
* doc/building.md (markdown version)
|
||||
|
||||
See https://openjdk.java.net/ for more information about
|
||||
the OpenJDK Community and the JDK.
|
||||
|
||||
11
README.md
11
README.md
@@ -1,11 +0,0 @@
|
||||
# Welcome to the JDK!
|
||||
|
||||
For build instructions please see the
|
||||
[online documentation](https://openjdk.java.net/groups/build/doc/building.html),
|
||||
or either of these files:
|
||||
|
||||
- [doc/building.html](doc/building.html) (html version)
|
||||
- [doc/building.md](doc/building.md) (markdown version)
|
||||
|
||||
See <https://openjdk.java.net/> for more information about
|
||||
the OpenJDK Community and the JDK.
|
||||
13
bin/idea.sh
13
bin/idea.sh
@@ -184,18 +184,7 @@ for root in $MODULE_ROOTS; do
|
||||
elif [ "x$WSL_DISTRO_NAME" != "x" ]; then
|
||||
root=`wslpath -am $root`
|
||||
fi
|
||||
|
||||
VM_CI="jdk.internal.vm.ci/share/classes"
|
||||
VM_COMPILER="src/jdk.internal.vm.compiler/share/classes"
|
||||
if test "${root#*$VM_CI}" != "$root" || test "${root#*$VM_COMPILER}" != "$root"; then
|
||||
for subdir in "$root"/*; do
|
||||
if [ -d "$subdir" ]; then
|
||||
SOURCES=$SOURCES" $SOURCE_PREFIX""$subdir"/src"$SOURCE_POSTFIX"
|
||||
fi
|
||||
done
|
||||
else
|
||||
SOURCES=$SOURCES" $SOURCE_PREFIX""$root""$SOURCE_POSTFIX"
|
||||
fi
|
||||
SOURCES=$SOURCES" $SOURCE_PREFIX""$root""$SOURCE_POSTFIX"
|
||||
done
|
||||
|
||||
add_replacement "###SOURCE_ROOTS###" "$SOURCES"
|
||||
|
||||
@@ -28,8 +28,7 @@
|
||||
</ul></li>
|
||||
<li><a href="#structure-and-formatting">Structure and Formatting</a><ul>
|
||||
<li><a href="#factoring-and-class-design">Factoring and Class Design</a></li>
|
||||
<li><a href="#source-files">Source Files</a></li>
|
||||
<li><a href="#jtreg-tests">JTReg Tests</a></li>
|
||||
<li><a href="#files">Files</a></li>
|
||||
<li><a href="#naming">Naming</a></li>
|
||||
<li><a href="#commenting">Commenting</a></li>
|
||||
<li><a href="#macros">Macros</a></li>
|
||||
@@ -88,7 +87,7 @@
|
||||
<li><p>Don't use the Copy and Paste keys to replicate more than a couple lines of code. Name what you must repeat.</p></li>
|
||||
<li><p>If a class needs a member function to change a user-visible attribute, the change should be done with a "setter" accessor matched to the simple "getter".</p></li>
|
||||
</ul>
|
||||
<h3 id="source-files">Source Files</h3>
|
||||
<h3 id="files">Files</h3>
|
||||
<ul>
|
||||
<li><p>All source files must have a globally unique basename. The build system depends on this uniqueness.</p></li>
|
||||
<li><p>Do not put non-trivial function implementations in .hpp files. If the implementation depends on other .hpp files, put it in a .cpp or a .inline.hpp file.</p></li>
|
||||
@@ -98,15 +97,6 @@
|
||||
<li><p>Keep the include lines alphabetically sorted.</p></li>
|
||||
<li><p>Put conditional inclusions (<code>#if ...</code>) at the end of the include list.</p></li>
|
||||
</ul>
|
||||
<h3 id="jtreg-tests">JTReg Tests</h3>
|
||||
<ul>
|
||||
<li><p>JTReg tests should have meaningful names.</p></li>
|
||||
<li><p>JTReg tests associated with specific bugs should be tagged with the <code>@bug</code> keyword in the test description.</p></li>
|
||||
<li><p>JTReg tests should be organized by component or feature under <code>test/</code>, in a directory hierarchy that generally follows that of the <code>src/</code> directory. There may be additional subdirectories to further categorize tests by feature. This structure makes it easy to run a collection of tests associated with a specific feature by specifying the associated directory as the source of the tests to run.</p>
|
||||
<ul>
|
||||
<li>Some (older) tests use the associated bug number in the directory name, the test name, or both. That naming style should no longer be used, with existing tests using that style being candidates for migration.</li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
<h3 id="naming">Naming</h3>
|
||||
<ul>
|
||||
<li><p>The length of a name may be correlated to the size of its scope. In particular, short names (even single letter names) may be fine in a small scope, but are usually inappropriate for larger scopes.</p></li>
|
||||
|
||||
@@ -126,7 +126,7 @@ lines of code. Name what you must repeat.
|
||||
change should be done with a "setter" accessor matched to the simple
|
||||
"getter".
|
||||
|
||||
### Source Files
|
||||
### Files
|
||||
|
||||
* All source files must have a globally unique basename. The build
|
||||
system depends on this uniqueness.
|
||||
@@ -147,24 +147,6 @@ it to resolve include problems.
|
||||
|
||||
* Put conditional inclusions (`#if ...`) at the end of the include list.
|
||||
|
||||
### JTReg Tests
|
||||
|
||||
* JTReg tests should have meaningful names.
|
||||
|
||||
* JTReg tests associated with specific bugs should be tagged with the
|
||||
`@bug` keyword in the test description.
|
||||
|
||||
* JTReg tests should be organized by component or feature under
|
||||
`test/`, in a directory hierarchy that generally follows that of the
|
||||
`src/` directory. There may be additional subdirectories to further
|
||||
categorize tests by feature. This structure makes it easy to run a
|
||||
collection of tests associated with a specific feature by specifying
|
||||
the associated directory as the source of the tests to run.
|
||||
|
||||
* Some (older) tests use the associated bug number in the directory
|
||||
name, the test name, or both. That naming style should no longer be
|
||||
used, with existing tests using that style being candidates for migration.
|
||||
|
||||
### Naming
|
||||
|
||||
* The length of a name may be correlated to the size of its scope. In
|
||||
|
||||
@@ -1,223 +0,0 @@
|
||||
<!DOCTYPE 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" />
|
||||
<title>Native/Unit Test Development Guidelines</title>
|
||||
<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]-->
|
||||
</head>
|
||||
<body>
|
||||
<header id="title-block-header">
|
||||
<h1 class="title">Native/Unit Test Development Guidelines</h1>
|
||||
</header>
|
||||
<nav id="TOC">
|
||||
<ul>
|
||||
<li><a href="#good-test-properties">Good test properties</a><ul>
|
||||
<li><a href="#lightness">Lightness</a></li>
|
||||
<li><a href="#isolation">Isolation</a></li>
|
||||
<li><a href="#atomicity-and-self-containment">Atomicity and self-containment</a></li>
|
||||
<li><a href="#repeatability">Repeatability</a></li>
|
||||
<li><a href="#informativeness">Informativeness</a></li>
|
||||
<li><a href="#testing-instead-of-visiting">Testing instead of visiting</a></li>
|
||||
<li><a href="#nearness">Nearness</a></li>
|
||||
</ul></li>
|
||||
<li><a href="#asserts">Asserts</a><ul>
|
||||
<li><a href="#several-checks">Several checks</a></li>
|
||||
<li><a href="#first-parameter-is-expected-value">First parameter is expected value</a></li>
|
||||
<li><a href="#floating-point-comparison">Floating-point comparison</a></li>
|
||||
<li><a href="#c-string-comparison">C string comparison</a></li>
|
||||
<li><a href="#error-messages">Error messages</a></li>
|
||||
<li><a href="#uncluttered-output">Uncluttered output</a></li>
|
||||
<li><a href="#failures-propagation">Failures propagation</a></li>
|
||||
</ul></li>
|
||||
<li><a href="#naming-and-grouping">Naming and Grouping</a><ul>
|
||||
<li><a href="#test-group-names">Test group names</a></li>
|
||||
<li><a href="#filename">Filename</a></li>
|
||||
<li><a href="#file-location">File location</a></li>
|
||||
<li><a href="#test-names">Test names</a></li>
|
||||
<li><a href="#fixture-classes">Fixture classes</a></li>
|
||||
<li><a href="#friend-classes">Friend classes</a></li>
|
||||
<li><a href="#oscpu-specific-tests">OS/CPU specific tests</a></li>
|
||||
</ul></li>
|
||||
<li><a href="#miscellaneous">Miscellaneous</a><ul>
|
||||
<li><a href="#hotspot-style">Hotspot style</a></li>
|
||||
<li><a href="#codetest-metrics">Code/test metrics</a></li>
|
||||
<li><a href="#access-to-non-public-members">Access to non-public members</a></li>
|
||||
<li><a href="#death-tests">Death tests</a></li>
|
||||
<li><a href="#external-flags">External flags</a></li>
|
||||
<li><a href="#test-specific-flags">Test-specific flags</a></li>
|
||||
<li><a href="#flag-restoring">Flag restoring</a></li>
|
||||
<li><a href="#googletest-documentation">GoogleTest documentation</a></li>
|
||||
</ul></li>
|
||||
<li><a href="#todo">TODO</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
<p>The purpose of these guidelines is to establish a shared vision on what kind of native tests and how we want to develop them for Hotspot using GoogleTest. Hence these guidelines include style items as well as test approach items.</p>
|
||||
<p>First section of this document describes properties of good tests which are common for almost all types of test regardless of language, framework, etc. Further sections provide recommendations to achieve those properties and other HotSpot and/or GoogleTest specific guidelines.</p>
|
||||
<h2 id="good-test-properties">Good test properties</h2>
|
||||
<h3 id="lightness">Lightness</h3>
|
||||
<p>Use the most lightweight type of tests.</p>
|
||||
<p>In Hotspot, there are 3 different types of tests regarding their dependency on a JVM, each next level is slower than previous</p>
|
||||
<ul>
|
||||
<li><p><code>TEST</code> : a test does not depend on a JVM</p></li>
|
||||
<li><p><code>TEST_VM</code> : a test does depend on an initialized JVM, but are supposed not to break a JVM, i.e. leave it in a workable state.</p></li>
|
||||
<li><p><code>TEST_OTHER_VM</code> : a test depends on a JVM and requires a freshly initialized JVM or leaves a JVM in non-workable state</p></li>
|
||||
</ul>
|
||||
<h3 id="isolation">Isolation</h3>
|
||||
<p>Tests have to be isolated: not to have visible side-effects, influences on other tests results.</p>
|
||||
<p>Results of one test should not depend on test execution order, other tests, otherwise it is becoming almost impossible to find out why a test failed. Due to hotspot-specific, it is not so easy to get a full isolation, e.g. we share an initialized JVM between all <code>TEST_VM</code> tests, so if your test changes JVM's state too drastically and does not change it back, you had better consider <code>TEST_OTHER_VM</code>.</p>
|
||||
<h3 id="atomicity-and-self-containment">Atomicity and self-containment</h3>
|
||||
<p>Tests should be <em>atomic</em> and <em>self-contained</em> at the same time.</p>
|
||||
<p>One test should check a particular part of a class, subsystem, functionality, etc. Then it is quite easy to determine what parts of a product are broken basing on test failures. On the other hand, a test should test that part more-or-less entirely, because when one sees a test <code>FooTest::bar</code>, they assume all aspects of bar from <code>Foo</code> are tested.</p>
|
||||
<p>However, it is impossible to cover all aspects even of a method, not to mention a subsystem. In such cases, it is recommended to have several tests, one for each aspect of a thing under test. For example one test to tests how <code>Foo::bar</code> works if an argument is <code>null</code>, another test to test how it works if an argument is acceptable but <code>Foo</code> is not in the right state to accept it and so on. This helps not only to make tests atomic, self-contained but also makes test name self-descriptive (discussed in more details in <a href="#test-names">Test names</a>).</p>
|
||||
<h3 id="repeatability">Repeatability</h3>
|
||||
<p>Tests have to be repeatable.</p>
|
||||
<p>Reproducibility is very crucial for a test. No one likes sporadic test failures, they are hard to investigate, fix and verify a fix.</p>
|
||||
<p>In some cases, it is quite hard to write a 100% repeatable test, since besides a test there can be other moving parts, e.g. in case of <code>TEST_VM</code> there are several concurrently running threads. Despite this, we should try to make a test as reproducible as possible.</p>
|
||||
<h3 id="informativeness">Informativeness</h3>
|
||||
<p>In case of a failure, a test should be as <em>informative</em> as possible.</p>
|
||||
<p>Having more information about a test failure than just compared values can be very useful for failure troubleshooting, it can reduce or even completely eliminate debugging hours. This is even more important in case of not 100% reproducible failures.</p>
|
||||
<p>Achieving this property, one can easily make a test too verbose, so it will be really hard to find useful information in the ocean of useless information. Hence they should not only think about how to provide <a href="#error-messages">good information</a>, but also <a href="#uncluttered-output">when to do it</a>.</p>
|
||||
<h3 id="testing-instead-of-visiting">Testing instead of visiting</h3>
|
||||
<p>Tests should <em>test</em>.</p>
|
||||
<p>It is not enough just to "visit" some code, a test should check that code does that it has to do, compare return values with expected values, check that desired side effects are done, and undesired are not, and so on. In other words, a test should contain at least one GoogleTest assertion and do not rely on JVM asserts.</p>
|
||||
<p>Generally speaking to write a good test, one should create a model of the system under tests, a model of possible bugs (or bugs which one wants to find) and design tests using those models.</p>
|
||||
<h3 id="nearness">Nearness</h3>
|
||||
<p>Prefer having checks inside test code.</p>
|
||||
<p>Not only does having test logic outside, e.g. verification method, depending on asserts in product code contradict with several items above but also decreases test’s readability and stability. It is much easier to understand that a test is testing when all testing logic is located inside a test or nearby in shared test libraries. As a rule of thumb, the closer a check to a test, the better.</p>
|
||||
<h2 id="asserts">Asserts</h2>
|
||||
<h3 id="several-checks">Several checks</h3>
|
||||
<p>Prefer <code>EXPECT</code> over <code>ASSERT</code> if possible.</p>
|
||||
<p>This is related to the <a href="#informativeness">informativeness</a> property of tests, information for other checks can help to better localize a defect’s root-cause. One should use <code>ASSERT</code> if it is impossible to continue test execution or if it does not make much sense. Later in the text, <code>EXPECT</code> forms will be used to refer to both <code>ASSERT/EXPECT</code>.</p>
|
||||
<p>When it is possible to make several different checks, but impossible to continue test execution if at least one check fails, you can use <code>::testing::Test::HasNonfatalFailure()</code> function. The recommended way to express that is <code>ASSERT_FALSE(::testing::Test::HasNonfatalFailure())</code>. Besides making it clear why a test is aborted, it also allows you to provide more information about a failure.</p>
|
||||
<h3 id="first-parameter-is-expected-value">First parameter is expected value</h3>
|
||||
<p>In all equality assertions, expected values should be passed as the first parameter.</p>
|
||||
<p>This convention is adopted by GoogleTest, and there is a slight difference in how GoogleTest treats parameters, the most important one is <code>null</code> detection. Due to different reasons, <code>null</code> detection is enabled only for the first parameter, that is to said <code>EXPECT_EQ(NULL, object)</code> checks that object is <code>null</code>, while <code>EXPECT_EQ(object, NULL)</code> checks that object equals to <code>NULL</code>, GoogleTest is very strict regarding types of compared values so the latter will generates a compile-time error.</p>
|
||||
<h3 id="floating-point-comparison">Floating-point comparison</h3>
|
||||
<p>Use floating-point special macros to compare <code>float/double</code> values.</p>
|
||||
<p>Because of floating-point number representations and round-off errors, regular equality comparison will not return true in most cases. There are special <code>EXPECT_FLOAT_EQ/EXPECT_DOUBLE_EQ</code> assertions which check that the distance between compared values is not more than 4 ULPs, there is also <code>EXPECT_NEAR(v1, v2, eps)</code> which checks that the absolute value of the difference between <code>v1</code> and <code>v2</code> is not greater than <code>eps</code>.</p>
|
||||
<h3 id="c-string-comparison">C string comparison</h3>
|
||||
<p>Use string special macros for C strings comparisons.</p>
|
||||
<p><code>EXPECT_EQ</code> just compares pointers’ values, which is hardly what one wants comparing C strings. GoogleTest provides <code>EXPECT_STREQ</code> and <code>EXPECT_STRNE</code> macros to compare C string contents. There are also case-insensitive versions <code>EXPECT_STRCASEEQ</code>, <code>EXPECT_STRCASENE</code>.</p>
|
||||
<h3 id="error-messages">Error messages</h3>
|
||||
<p>Provide informative, but not too verbose error messages.</p>
|
||||
<p>All GoogleTest asserts print compared expressions and their values, so there is no need to have them in error messages. Asserts print only compared values, they do not print any of interim variables, e.g. <code>ASSERT_TRUE((val1 == val2 && isFail(foo(8)) || i == 18)</code> prints only one value. If you use some complex predicates, please consider <code>EXPECT_PRED*</code> or <code>EXPECT_FORMAT_PRED</code> assertions family, they check that a predicate returns true/success and print out all parameters values.</p>
|
||||
<p>However in some cases, default information is not enough, a commonly used example is an assert inside a loop, GoogleTest will not print iteration values (unless it is an assert's parameter). Other demonstrative examples are printing error code and a corresponding error message; printing internal states which might have an impact on results. One should add this information to assert message using <code><<</code> operator.</p>
|
||||
<h3 id="uncluttered-output">Uncluttered output</h3>
|
||||
<p>Print information only if it is needed.</p>
|
||||
<p>Too verbose tests which print all information even if they pass are very bad practice. They just pollute output, so it becomes harder to find useful information. In order not print information till it is really needed, one should consider saving it to a temporary buffer and pass to an assert. <a href="https://hg.openjdk.java.net/jdk/jdk/file/tip/test/hotspot/gtest/gc/shared/test_memset_with_concurrent_readers.cpp" class="uri">https://hg.openjdk.java.net/jdk/jdk/file/tip/test/hotspot/gtest/gc/shared/test_memset_with_concurrent_readers.cpp</a> has a good example how to do that.</p>
|
||||
<h3 id="failures-propagation">Failures propagation</h3>
|
||||
<p>Wrap a subroutine call into <code>EXPECT_NO_FATAL_FAILURE</code> macro to propagate failures.</p>
|
||||
<p><code>ASSERT</code> and <code>FAIL</code> abort only the current function, so if you have them in a subroutine, a test will not be aborted after the subroutine even if <code>ASSERT</code> or <code>FAIL</code> fails. You should call such subroutines in <code>ASSERT_NO_FATAL_FAILURE</code> macro to propagate fatal failures and abort a test. <code>(EXPECT|ASSERT)_NO_FATAL_FAILURE</code> can also be used to provide more information.</p>
|
||||
<p>Due to obvious reasons, there are no <code>(EXPECT|ASSERT)_NO_NONFATAL_FAILURE</code> macros. However, if you need to check if a subroutine generated a nonfatal failure (failed an <code>EXPECT</code>), you can use <code>::testing::Test::HasNonfatalFailure</code> function, or <code>::testing::Test::HasFailure</code> function to check if a subroutine generated any failures, see <a href="#several-checks">Several checks</a>.</p>
|
||||
<h2 id="naming-and-grouping">Naming and Grouping</h2>
|
||||
<h3 id="test-group-names">Test group names</h3>
|
||||
<p>Test group names should be in CamelCase, start and end with a letter. A test group should be named after tested class, functionality, subsystem, etc.</p>
|
||||
<p>This naming scheme helps to find tests, filter them and simplifies test failure analysis. For example, class <code>Foo</code> - test group <code>Foo</code>, compiler logging subsystem - test group <code>CompilerLogging</code>, G1 GC — test group <code>G1GC</code>, and so forth.</p>
|
||||
<h3 id="filename">Filename</h3>
|
||||
<p>A test file must have <code>test_</code> prefix and <code>.cpp</code> suffix.</p>
|
||||
<p>Both are actually requirements from the current build system to recognize your tests.</p>
|
||||
<h3 id="file-location">File location</h3>
|
||||
<p>Test file location should reflect a location of the tested part of the product.</p>
|
||||
<ul>
|
||||
<li><p>All unit tests for a class from <code>foo/bar/baz.cpp</code> should be placed <code>foo/bar/test_baz.cpp</code> in <code>hotspot/test/native/</code> directory. Having all tests for a class in one file is a common practice for unit tests, it helps to see all existing tests at once, share functions and/or resources without losing encapsulation.</p></li>
|
||||
<li><p>For tests which test more than one class, directory hierarchy should be the same as product hierarchy, and file name should reflect the name of the tested subsystem/functionality. For example, if a sub-system under tests belongs to <code>gc/g1</code>, tests should be placed in <code>gc/g1</code> directory.</p></li>
|
||||
</ul>
|
||||
<p>Please note that framework prepends directory name to a test group name. For example, if <code>TEST(foo, check_this)</code> and <code>TEST(bar, check_that)</code> are defined in <code>hotspot/test/native/gc/shared/test_foo.cpp</code> file, they will be reported as <code>gc/shared/foo::check_this</code> and <code>gc/shared/bar::check_that</code>.</p>
|
||||
<h3 id="test-names">Test names</h3>
|
||||
<p>Test names should be in small_snake_case, start and end with a letter. A test name should reflect that a test checks.</p>
|
||||
<p>Such naming makes tests self-descriptive and helps a lot during the whole test life cycle. It is easy to do test planning, test inventory, to see what things are not tested, to review tests, to analyze test failures, to evolve a test, etc. For example <code>foo_return_0_if_name_is_null</code> is better than <code>foo_sanity</code> or <code>foo_basic</code> or just <code>foo</code>, <code>humongous_objects_can_not_be_moved_by_young_gc</code> is better than <code>ho_young_gc</code>.</p>
|
||||
<p>Actually using underscore is against GoogleTest project convention, because it can lead to illegal identifiers, however, this is too strict. Restricting usage of underscore for test names only and prohibiting test name starts or ends with an underscore are enough to be safe.</p>
|
||||
<h3 id="fixture-classes">Fixture classes</h3>
|
||||
<p>Fixture classes should be named after tested classes, subsystems, etc (follow <a href="#test-group-names">Test group names rule</a>) and have <code>Test</code> suffix to prevent class name conflicts.</p>
|
||||
<h3 id="friend-classes">Friend classes</h3>
|
||||
<p>All test purpose friends should have either <code>Test</code> or <code>Testable</code> suffix.</p>
|
||||
<p>It greatly simplifies understanding of friendship’s purpose and allows statically check that private members are not exposed unexpectedly. Having <code>FooTest</code> as a friend of <code>Foo</code> without any comments will be understood as a necessary evil to get testability.</p>
|
||||
<h3 id="oscpu-specific-tests">OS/CPU specific tests</h3>
|
||||
<p>Guard OS/CPU specific tests by <code>#ifdef</code> and have OS/CPU name in filename.</p>
|
||||
<p>For the time being, we do not support separate directories for OS, CPU, OS-CPU specific tests, in case we will have lots of such tests, we will change directory layout and build system to support that in the same way it is done in hotspot.</p>
|
||||
<h2 id="miscellaneous">Miscellaneous</h2>
|
||||
<h3 id="hotspot-style">Hotspot style</h3>
|
||||
<p>Abide the norms and rules accepted in Hotspot style guide.</p>
|
||||
<p>Tests are a part of Hotspot, so everything (if applicable) we use for Hotspot, should be used for tests as well. Those guidelines cover test-specific things.</p>
|
||||
<h3 id="codetest-metrics">Code/test metrics</h3>
|
||||
<p>Coverage information and other code/test metrics are quite useful to decide what tests should be written, what tests should be improved and what can be removed.</p>
|
||||
<p>For unit tests, widely used and well-known coverage metric is branch coverage, which provides good quality of tests with relatively easy test development process. For other levels of testing, branch coverage is not as good, and one should consider others metrics, e.g. transaction flow coverage, data flow coverage.</p>
|
||||
<h3 id="access-to-non-public-members">Access to non-public members</h3>
|
||||
<p>Use explicit friend class to get access to non-public members.</p>
|
||||
<p>We do not use GoogleTest macro to declare friendship relation, because, from our point of view, it is less clear than an explicit declaration.</p>
|
||||
<p>Declaring a test fixture class as a friend class of a tested test is the easiest and the clearest way to get access. However, it has some disadvantages, here is some of them:</p>
|
||||
<ul>
|
||||
<li>Each test has to be declared as a friend</li>
|
||||
<li>Subclasses do not inheritance friendship relation</li>
|
||||
</ul>
|
||||
<p>In other words, it is harder to share code between tests. Hence if you want to share code or expect it to be useful in other tests, you should consider making members in a tested class protected and introduce a shared test-only class which expose those members via public functions, or even making members publicly accessible right away in a product class. If it is not an option to change members visibility, one can create a friend class which exposes members.</p>
|
||||
<h3 id="death-tests">Death tests</h3>
|
||||
<p>You can not use death tests inside <code>TEST_OTHER_VM</code> and <code>TEST_VM_ASSERT*</code>.</p>
|
||||
<p>We tried to make Hotspot-GoogleTest integration as transparent as possible, however, due to the current implementation of <code>TEST_OTHER_VM</code> and <code>TEST_VM_ASSERT*</code> tests, you cannot use death test functionality in them. These tests are implemented as GoogleTest death tests, and GoogleTest does not allow to have a death test inside another death test.</p>
|
||||
<h3 id="external-flags">External flags</h3>
|
||||
<p>Passing external flags to a tested JVM is not supported.</p>
|
||||
<p>The rationality of such design decision is to simplify both tests and a test framework and to avoid failures related to incompatible flags combination till there is a good solution for that. However there are cases when one wants to test a JVM with specific flags combination, <code>_JAVA_OPTIONS</code> environment variable can be used to do that. Flags from <code>_JAVA_OPTIONS</code> will be used in <code>TEST_VM</code>, <code>TEST_OTHER_VM</code> and <code>TEST_VM_ASSERT*</code> tests.</p>
|
||||
<h3 id="test-specific-flags">Test-specific flags</h3>
|
||||
<p>Passing flags to a tested JVM in <code>TEST_OTHER_VM</code> and <code>TEST_VM_ASSERT*</code> should be possible, but is not implemented yet.</p>
|
||||
<p>Facility to pass test-specific flags is needed for system, regression or other types of tests which require a fully initialized JVM in some particular configuration, e.g. with Serial GC selected. There is no support for such tests now, however, there is a plan to add that in upcoming releases.</p>
|
||||
<p>For now, if a test depends on flags values, it should have <code>if (!<flag>) { return }</code> guards in the very beginning and <code>@requires</code> comment similar to jtreg <code>@requires</code> directive right before test macros. <a href="https://hg.openjdk.java.net/jdk/jdk/file/tip/test/hotspot/gtest/gc/g1/test_g1IHOPControl.cpp" class="uri">https://hg.openjdk.java.net/jdk/jdk/file/tip/test/hotspot/gtest/gc/g1/test_g1IHOPControl.cpp</a> ha an example of this temporary workaround. It is important to follow that pattern as it allows us to easily find all such tests and update them as soon as there is an implementation of flag passing facility.</p>
|
||||
<p>In long-term, we expect jtreg to support GoogleTest tests as first class citizens, that is to say, jtreg will parse <span class="citation" data-cites="requires">@requires</span> comments and filter out inapplicable tests.</p>
|
||||
<h3 id="flag-restoring">Flag restoring</h3>
|
||||
<p>Restore changed flags.</p>
|
||||
<p>It is quite common for tests to configure JVM in a certain way changing flags’ values. GoogleTest provides two ways to set up environment before a test and restore it afterward: using either constructor and destructor or <code>SetUp</code> and <code>TearDown</code> functions. Both ways require to use a test fixture class, which sometimes is too wordy. The simpler facilities like <code>FLAG_GUARD</code> macro or <code>*FlagSetting</code> classes could be used in such cases to restore/set values.</p>
|
||||
<p>Caveats:</p>
|
||||
<ul>
|
||||
<li><p>Changing a flag’s value could break the invariants between flags' values and hence could lead to unexpected/unsupported JVM state.</p></li>
|
||||
<li><p><code>FLAG_SET_*</code> macros can change more than one flag (in order to maintain invariants) so it is hard to predict what flags will be changed and it makes restoring all changed flags a nontrivial task. Thus in case one uses <code>FLAG_SET_*</code> macros, they should use <code>TEST_OTHER_VM</code> test type.</p></li>
|
||||
</ul>
|
||||
<h3 id="googletest-documentation">GoogleTest documentation</h3>
|
||||
<p>In case you have any questions regarding GoogleTest itself, its asserts, test declaration macros, other macros, etc, please consult its documentation.</p>
|
||||
<h2 id="todo">TODO</h2>
|
||||
<p>Although this document provides guidelines on the most important parts of test development using GTest, it still misses a few items:</p>
|
||||
<ul>
|
||||
<li><p>Examples, esp for <a href="#access-to-non-public-members">access to non-public members</a></p></li>
|
||||
<li>test types: purpose, drawbacks, limitation
|
||||
<ul>
|
||||
<li><code>TEST_VM</code></li>
|
||||
<li><code>TEST_VM_F</code></li>
|
||||
<li><code>TEST_OTHER_VM</code></li>
|
||||
<li><code>TEST_VM_ASSERT</code></li>
|
||||
<li><code>TEST_VM_ASSERT_MSG</code></li>
|
||||
</ul></li>
|
||||
<li>Miscellaneous
|
||||
<ul>
|
||||
<li>Test libraries
|
||||
<ul>
|
||||
<li>where to place</li>
|
||||
<li>how to write</li>
|
||||
<li>how to use</li>
|
||||
</ul></li>
|
||||
<li>test your tests
|
||||
<ul>
|
||||
<li>how to run tests in random order</li>
|
||||
<li>how to run only specific tests</li>
|
||||
<li>how to run each test separately</li>
|
||||
<li>check that a test can find bugs it is supposed to by introducing them</li>
|
||||
</ul></li>
|
||||
<li>mocks/stubs/dependency injection</li>
|
||||
<li>setUp/tearDown
|
||||
<ul>
|
||||
<li>vs c-tor/d-tor</li>
|
||||
<li>empty test to test them</li>
|
||||
</ul></li>
|
||||
<li>internal (declared in .cpp) struct/classes</li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,451 +0,0 @@
|
||||
% Native/Unit Test Development Guidelines
|
||||
|
||||
The purpose of these guidelines is to establish a shared vision on
|
||||
what kind of native tests and how we want to develop them for Hotspot
|
||||
using GoogleTest. Hence these guidelines include style items as well
|
||||
as test approach items.
|
||||
|
||||
First section of this document describes properties of good tests
|
||||
which are common for almost all types of test regardless of language,
|
||||
framework, etc. Further sections provide recommendations to achieve
|
||||
those properties and other HotSpot and/or GoogleTest specific
|
||||
guidelines.
|
||||
|
||||
## Good test properties
|
||||
|
||||
### Lightness
|
||||
|
||||
Use the most lightweight type of tests.
|
||||
|
||||
In Hotspot, there are 3 different types of tests regarding their
|
||||
dependency on a JVM, each next level is slower than previous
|
||||
|
||||
* `TEST` : a test does not depend on a JVM
|
||||
|
||||
* `TEST_VM` : a test does depend on an initialized JVM, but are
|
||||
supposed not to break a JVM, i.e. leave it in a workable state.
|
||||
|
||||
* `TEST_OTHER_VM` : a test depends on a JVM and requires a freshly
|
||||
initialized JVM or leaves a JVM in non-workable state
|
||||
|
||||
### Isolation
|
||||
|
||||
Tests have to be isolated: not to have visible side-effects,
|
||||
influences on other tests results.
|
||||
|
||||
Results of one test should not depend on test execution order, other
|
||||
tests, otherwise it is becoming almost impossible to find out why a
|
||||
test failed. Due to hotspot-specific, it is not so easy to get a full
|
||||
isolation, e.g. we share an initialized JVM between all `TEST_VM` tests,
|
||||
so if your test changes JVM's state too drastically and does not
|
||||
change it back, you had better consider `TEST_OTHER_VM`.
|
||||
|
||||
### Atomicity and self-containment
|
||||
|
||||
Tests should be *atomic* and *self-contained* at the same time.
|
||||
|
||||
One test should check a particular part of a class, subsystem,
|
||||
functionality, etc. Then it is quite easy to determine what parts of a
|
||||
product are broken basing on test failures. On the other hand, a test
|
||||
should test that part more-or-less entirely, because when one sees a
|
||||
test `FooTest::bar`, they assume all aspects of bar from `Foo` are tested.
|
||||
|
||||
However, it is impossible to cover all aspects even of a method, not
|
||||
to mention a subsystem. In such cases, it is recommended to have
|
||||
several tests, one for each aspect of a thing under test. For example
|
||||
one test to tests how `Foo::bar` works if an argument is `null`, another
|
||||
test to test how it works if an argument is acceptable but `Foo` is not
|
||||
in the right state to accept it and so on. This helps not only to make
|
||||
tests atomic, self-contained but also makes test name self-descriptive
|
||||
(discussed in more details in [Test names](#test-names)).
|
||||
|
||||
### Repeatability
|
||||
|
||||
Tests have to be repeatable.
|
||||
|
||||
Reproducibility is very crucial for a test. No one likes sporadic test
|
||||
failures, they are hard to investigate, fix and verify a fix.
|
||||
|
||||
In some cases, it is quite hard to write a 100% repeatable test, since
|
||||
besides a test there can be other moving parts, e.g. in case of
|
||||
`TEST_VM` there are several concurrently running threads. Despite this,
|
||||
we should try to make a test as reproducible as possible.
|
||||
|
||||
### Informativeness
|
||||
|
||||
In case of a failure, a test should be as *informative* as possible.
|
||||
|
||||
Having more information about a test failure than just compared values
|
||||
can be very useful for failure troubleshooting, it can reduce or even
|
||||
completely eliminate debugging hours. This is even more important in
|
||||
case of not 100% reproducible failures.
|
||||
|
||||
Achieving this property, one can easily make a test too verbose, so it
|
||||
will be really hard to find useful information in the ocean of useless
|
||||
information. Hence they should not only think about how to provide
|
||||
[good information](#error-messages), but also
|
||||
[when to do it](#uncluttered-output).
|
||||
|
||||
### Testing instead of visiting
|
||||
|
||||
Tests should *test*.
|
||||
|
||||
It is not enough just to "visit" some code, a test should check that
|
||||
code does that it has to do, compare return values with expected
|
||||
values, check that desired side effects are done, and undesired are
|
||||
not, and so on. In other words, a test should contain at least one
|
||||
GoogleTest assertion and do not rely on JVM asserts.
|
||||
|
||||
Generally speaking to write a good test, one should create a model of
|
||||
the system under tests, a model of possible bugs (or bugs which one
|
||||
wants to find) and design tests using those models.
|
||||
|
||||
### Nearness
|
||||
|
||||
Prefer having checks inside test code.
|
||||
|
||||
Not only does having test logic outside, e.g. verification method,
|
||||
depending on asserts in product code contradict with several items
|
||||
above but also decreases test’s readability and stability. It is much
|
||||
easier to understand that a test is testing when all testing logic is
|
||||
located inside a test or nearby in shared test libraries. As a rule of
|
||||
thumb, the closer a check to a test, the better.
|
||||
|
||||
## Asserts
|
||||
|
||||
### Several checks
|
||||
|
||||
Prefer `EXPECT` over `ASSERT` if possible.
|
||||
|
||||
This is related to the [informativeness](#informativeness) property of
|
||||
tests, information for other checks can help to better localize a
|
||||
defect’s root-cause. One should use `ASSERT` if it is impossible to
|
||||
continue test execution or if it does not make much sense. Later in
|
||||
the text, `EXPECT` forms will be used to refer to both
|
||||
`ASSERT/EXPECT`.
|
||||
|
||||
When it is possible to make several different checks, but impossible
|
||||
to continue test execution if at least one check fails, you can
|
||||
use `::testing::Test::HasNonfatalFailure()` function. The recommended
|
||||
way to express that is
|
||||
`ASSERT_FALSE(::testing::Test::HasNonfatalFailure())`. Besides making it
|
||||
clear why a test is aborted, it also allows you to provide more
|
||||
information about a failure.
|
||||
|
||||
### First parameter is expected value
|
||||
|
||||
In all equality assertions, expected values should be passed as the
|
||||
first parameter.
|
||||
|
||||
This convention is adopted by GoogleTest, and there is a slight
|
||||
difference in how GoogleTest treats parameters, the most important one
|
||||
is `null` detection. Due to different reasons, `null` detection is enabled
|
||||
only for the first parameter, that is to said `EXPECT_EQ(NULL, object)`
|
||||
checks that object is `null`, while `EXPECT_EQ(object, NULL)` checks that
|
||||
object equals to `NULL`, GoogleTest is very strict regarding types of
|
||||
compared values so the latter will generates a compile-time error.
|
||||
|
||||
### Floating-point comparison
|
||||
|
||||
Use floating-point special macros to compare `float/double` values.
|
||||
|
||||
Because of floating-point number representations and round-off errors,
|
||||
regular equality comparison will not return true in most cases. There
|
||||
are special `EXPECT_FLOAT_EQ/EXPECT_DOUBLE_EQ` assertions which check
|
||||
that the distance between compared values is not more than 4 ULPs,
|
||||
there is also `EXPECT_NEAR(v1, v2, eps)` which checks that the absolute
|
||||
value of the difference between `v1` and `v2` is not greater than `eps`.
|
||||
|
||||
### C string comparison
|
||||
|
||||
Use string special macros for C strings comparisons.
|
||||
|
||||
`EXPECT_EQ` just compares pointers’ values, which is hardly what one
|
||||
wants comparing C strings. GoogleTest provides `EXPECT_STREQ` and
|
||||
`EXPECT_STRNE` macros to compare C string contents. There are also
|
||||
case-insensitive versions `EXPECT_STRCASEEQ`, `EXPECT_STRCASENE`.
|
||||
|
||||
### Error messages
|
||||
|
||||
Provide informative, but not too verbose error messages.
|
||||
|
||||
All GoogleTest asserts print compared expressions and their values, so
|
||||
there is no need to have them in error messages. Asserts print only
|
||||
compared values, they do not print any of interim variables, e.g.
|
||||
`ASSERT_TRUE((val1 == val2 && isFail(foo(8)) || i == 18)` prints only
|
||||
one value. If you use some complex predicates, please consider
|
||||
`EXPECT_PRED*` or `EXPECT_FORMAT_PRED` assertions family, they check that
|
||||
a predicate returns true/success and print out all parameters values.
|
||||
|
||||
However in some cases, default information is not enough, a commonly
|
||||
used example is an assert inside a loop, GoogleTest will not print
|
||||
iteration values (unless it is an assert's parameter). Other
|
||||
demonstrative examples are printing error code and a corresponding
|
||||
error message; printing internal states which might have an impact on
|
||||
results. One should add this information to assert message using `<<`
|
||||
operator.
|
||||
|
||||
### Uncluttered output
|
||||
|
||||
Print information only if it is needed.
|
||||
|
||||
Too verbose tests which print all information even if they pass are
|
||||
very bad practice. They just pollute output, so it becomes harder to
|
||||
find useful information. In order not print information till it is
|
||||
really needed, one should consider saving it to a temporary buffer and
|
||||
pass to an assert.
|
||||
<https://hg.openjdk.java.net/jdk/jdk/file/tip/test/hotspot/gtest/gc/shared/test_memset_with_concurrent_readers.cpp>
|
||||
has a good example how to do that.
|
||||
|
||||
### Failures propagation
|
||||
|
||||
Wrap a subroutine call into `EXPECT_NO_FATAL_FAILURE` macro to
|
||||
propagate failures.
|
||||
|
||||
`ASSERT` and `FAIL` abort only the current function, so if you have them
|
||||
in a subroutine, a test will not be aborted after the subroutine even
|
||||
if `ASSERT` or `FAIL` fails. You should call such subroutines in
|
||||
`ASSERT_NO_FATAL_FAILURE` macro to propagate fatal failures and abort a
|
||||
test. `(EXPECT|ASSERT)_NO_FATAL_FAILURE` can also be used to provide
|
||||
more information.
|
||||
|
||||
Due to obvious reasons, there are no
|
||||
`(EXPECT|ASSERT)_NO_NONFATAL_FAILURE` macros. However, if you need to
|
||||
check if a subroutine generated a nonfatal failure (failed an `EXPECT`),
|
||||
you can use `::testing::Test::HasNonfatalFailure` function,
|
||||
or `::testing::Test::HasFailure` function to check if a subroutine
|
||||
generated any failures, see [Several checks](#several-checks).
|
||||
|
||||
## Naming and Grouping
|
||||
|
||||
### Test group names
|
||||
|
||||
Test group names should be in CamelCase, start and end with a letter.
|
||||
A test group should be named after tested class, functionality,
|
||||
subsystem, etc.
|
||||
|
||||
This naming scheme helps to find tests, filter them and simplifies
|
||||
test failure analysis. For example, class `Foo` - test group `Foo`,
|
||||
compiler logging subsystem - test group `CompilerLogging`, G1 GC — test
|
||||
group `G1GC`, and so forth.
|
||||
|
||||
### Filename
|
||||
|
||||
A test file must have `test_` prefix and `.cpp` suffix.
|
||||
|
||||
Both are actually requirements from the current build system to
|
||||
recognize your tests.
|
||||
|
||||
### File location
|
||||
|
||||
Test file location should reflect a location of the tested part of the product.
|
||||
|
||||
* All unit tests for a class from `foo/bar/baz.cpp` should be placed
|
||||
`foo/bar/test_baz.cpp` in `hotspot/test/native/` directory. Having all
|
||||
tests for a class in one file is a common practice for unit tests, it
|
||||
helps to see all existing tests at once, share functions and/or
|
||||
resources without losing encapsulation.
|
||||
|
||||
* For tests which test more than one class, directory hierarchy should
|
||||
be the same as product hierarchy, and file name should reflect the
|
||||
name of the tested subsystem/functionality. For example, if a
|
||||
sub-system under tests belongs to `gc/g1`, tests should be placed in
|
||||
`gc/g1` directory.
|
||||
|
||||
Please note that framework prepends directory name to a test group
|
||||
name. For example, if `TEST(foo, check_this)` and `TEST(bar, check_that)`
|
||||
are defined in `hotspot/test/native/gc/shared/test_foo.cpp` file, they
|
||||
will be reported as `gc/shared/foo::check_this` and
|
||||
`gc/shared/bar::check_that`.
|
||||
|
||||
### Test names
|
||||
|
||||
Test names should be in small_snake_case, start and end with a letter.
|
||||
A test name should reflect that a test checks.
|
||||
|
||||
Such naming makes tests self-descriptive and helps a lot during the
|
||||
whole test life cycle. It is easy to do test planning, test inventory,
|
||||
to see what things are not tested, to review tests, to analyze test
|
||||
failures, to evolve a test, etc. For example
|
||||
`foo_return_0_if_name_is_null` is better than `foo_sanity` or `foo_basic` or
|
||||
just `foo`, `humongous_objects_can_not_be_moved_by_young_gc` is better
|
||||
than `ho_young_gc`.
|
||||
|
||||
Actually using underscore is against GoogleTest project convention,
|
||||
because it can lead to illegal identifiers, however, this is too
|
||||
strict. Restricting usage of underscore for test names only and
|
||||
prohibiting test name starts or ends with an underscore are enough to
|
||||
be safe.
|
||||
|
||||
### Fixture classes
|
||||
|
||||
Fixture classes should be named after tested classes, subsystems, etc
|
||||
(follow [Test group names rule](#test-group-names)) and have
|
||||
`Test` suffix to prevent class name conflicts.
|
||||
|
||||
### Friend classes
|
||||
|
||||
All test purpose friends should have either `Test` or `Testable` suffix.
|
||||
|
||||
It greatly simplifies understanding of friendship’s purpose and allows
|
||||
statically check that private members are not exposed unexpectedly.
|
||||
Having `FooTest` as a friend of `Foo` without any comments will be
|
||||
understood as a necessary evil to get testability.
|
||||
|
||||
### OS/CPU specific tests
|
||||
|
||||
Guard OS/CPU specific tests by `#ifdef` and have OS/CPU name in filename.
|
||||
|
||||
For the time being, we do not support separate directories for OS,
|
||||
CPU, OS-CPU specific tests, in case we will have lots of such tests,
|
||||
we will change directory layout and build system to support that in
|
||||
the same way it is done in hotspot.
|
||||
|
||||
## Miscellaneous
|
||||
|
||||
### Hotspot style
|
||||
|
||||
Abide the norms and rules accepted in Hotspot style guide.
|
||||
|
||||
Tests are a part of Hotspot, so everything (if applicable) we use for
|
||||
Hotspot, should be used for tests as well. Those guidelines cover
|
||||
test-specific things.
|
||||
|
||||
### Code/test metrics
|
||||
|
||||
Coverage information and other code/test metrics are quite useful to
|
||||
decide what tests should be written, what tests should be improved and
|
||||
what can be removed.
|
||||
|
||||
For unit tests, widely used and well-known coverage metric is branch
|
||||
coverage, which provides good quality of tests with relatively easy
|
||||
test development process. For other levels of testing, branch coverage
|
||||
is not as good, and one should consider others metrics, e.g.
|
||||
transaction flow coverage, data flow coverage.
|
||||
|
||||
### Access to non-public members
|
||||
|
||||
Use explicit friend class to get access to non-public members.
|
||||
|
||||
We do not use GoogleTest macro to declare friendship relation,
|
||||
because, from our point of view, it is less clear than an explicit
|
||||
declaration.
|
||||
|
||||
Declaring a test fixture class as a friend class of a tested test is
|
||||
the easiest and the clearest way to get access. However, it has some
|
||||
disadvantages, here is some of them:
|
||||
|
||||
* Each test has to be declared as a friend
|
||||
* Subclasses do not inheritance friendship relation
|
||||
|
||||
In other words, it is harder to share code between tests. Hence if you
|
||||
want to share code or expect it to be useful in other tests, you
|
||||
should consider making members in a tested class protected and
|
||||
introduce a shared test-only class which expose those members via
|
||||
public functions, or even making members publicly accessible right
|
||||
away in a product class. If it is not an option to change members
|
||||
visibility, one can create a friend class which exposes members.
|
||||
|
||||
### Death tests
|
||||
|
||||
You can not use death tests inside `TEST_OTHER_VM` and `TEST_VM_ASSERT*`.
|
||||
|
||||
We tried to make Hotspot-GoogleTest integration as transparent as
|
||||
possible, however, due to the current implementation of `TEST_OTHER_VM`
|
||||
and `TEST_VM_ASSERT*` tests, you cannot use death test functionality in
|
||||
them. These tests are implemented as GoogleTest death tests, and
|
||||
GoogleTest does not allow to have a death test inside another death
|
||||
test.
|
||||
|
||||
### External flags
|
||||
|
||||
Passing external flags to a tested JVM is not supported.
|
||||
|
||||
The rationality of such design decision is to simplify both tests and
|
||||
a test framework and to avoid failures related to incompatible flags
|
||||
combination till there is a good solution for that. However there are
|
||||
cases when one wants to test a JVM with specific flags combination,
|
||||
`_JAVA_OPTIONS` environment variable can be used to do that. Flags from
|
||||
`_JAVA_OPTIONS` will be used in `TEST_VM`, `TEST_OTHER_VM` and
|
||||
`TEST_VM_ASSERT*` tests.
|
||||
|
||||
### Test-specific flags
|
||||
|
||||
Passing flags to a tested JVM in `TEST_OTHER_VM` and `TEST_VM_ASSERT*`
|
||||
should be possible, but is not implemented yet.
|
||||
|
||||
Facility to pass test-specific flags is needed for system, regression
|
||||
or other types of tests which require a fully initialized JVM in some
|
||||
particular configuration, e.g. with Serial GC selected. There is no
|
||||
support for such tests now, however, there is a plan to add that in
|
||||
upcoming releases.
|
||||
|
||||
For now, if a test depends on flags values, it should have `if
|
||||
(!<flag>) { return }` guards in the very beginning and `@requires`
|
||||
comment similar to jtreg `@requires` directive right before test macros.
|
||||
<https://hg.openjdk.java.net/jdk/jdk/file/tip/test/hotspot/gtest/gc/g1/test_g1IHOPControl.cpp>
|
||||
ha an example of this temporary workaround. It is important to follow
|
||||
that pattern as it allows us to easily find all such tests and update
|
||||
them as soon as there is an implementation of flag passing facility.
|
||||
|
||||
In long-term, we expect jtreg to support GoogleTest tests as first
|
||||
class citizens, that is to say, jtreg will parse @requires comments
|
||||
and filter out inapplicable tests.
|
||||
|
||||
### Flag restoring
|
||||
|
||||
Restore changed flags.
|
||||
|
||||
It is quite common for tests to configure JVM in a certain way
|
||||
changing flags’ values. GoogleTest provides two ways to set up
|
||||
environment before a test and restore it afterward: using either
|
||||
constructor and destructor or `SetUp` and `TearDown` functions. Both ways
|
||||
require to use a test fixture class, which sometimes is too wordy. The
|
||||
simpler facilities like `FLAG_GUARD` macro or `*FlagSetting` classes could
|
||||
be used in such cases to restore/set values.
|
||||
|
||||
Caveats:
|
||||
|
||||
* Changing a flag’s value could break the invariants between flags' values and hence could lead to unexpected/unsupported JVM state.
|
||||
|
||||
* `FLAG_SET_*` macros can change more than one flag (in order to
|
||||
maintain invariants) so it is hard to predict what flags will be
|
||||
changed and it makes restoring all changed flags a nontrivial task.
|
||||
Thus in case one uses `FLAG_SET_*` macros, they should use `TEST_OTHER_VM`
|
||||
test type.
|
||||
|
||||
### GoogleTest documentation
|
||||
|
||||
In case you have any questions regarding GoogleTest itself, its
|
||||
asserts, test declaration macros, other macros, etc, please consult
|
||||
its documentation.
|
||||
|
||||
## TODO
|
||||
|
||||
Although this document provides guidelines on the most important parts
|
||||
of test development using GTest, it still misses a few items:
|
||||
|
||||
* Examples, esp for [access to non-public members](#access-to-non-public-members)
|
||||
|
||||
* test types: purpose, drawbacks, limitation
|
||||
* `TEST_VM`
|
||||
* `TEST_VM_F`
|
||||
* `TEST_OTHER_VM`
|
||||
* `TEST_VM_ASSERT`
|
||||
* `TEST_VM_ASSERT_MSG`
|
||||
|
||||
* Miscellaneous
|
||||
* Test libraries
|
||||
* where to place
|
||||
* how to write
|
||||
* how to use
|
||||
* test your tests
|
||||
* how to run tests in random order
|
||||
* how to run only specific tests
|
||||
* how to run each test separately
|
||||
* check that a test can find bugs it is supposed to by introducing them
|
||||
* mocks/stubs/dependency injection
|
||||
* setUp/tearDown
|
||||
* vs c-tor/d-tor
|
||||
* empty test to test them
|
||||
* internal (declared in .cpp) struct/classes
|
||||
@@ -242,6 +242,16 @@ ifneq ($(filter product-bundles% legacy-bundles, $(MAKECMDGOALS)), )
|
||||
)
|
||||
|
||||
JDK_SYMBOLS_BUNDLE_FILES := \
|
||||
$(filter \
|
||||
$(JDK_SYMBOLS_EXCLUDE_PATTERN) \
|
||||
$(SYMBOLS_EXCLUDE_PATTERN) \
|
||||
, \
|
||||
$(filter-out \
|
||||
$(JDK_IMAGE_HOMEDIR)/demo/% %.stripped.pdb \
|
||||
, \
|
||||
$(ALL_JDK_SYMBOLS_FILES) \
|
||||
) \
|
||||
) \
|
||||
$(call FindFiles, $(SYMBOLS_IMAGE_DIR))
|
||||
|
||||
TEST_DEMOS_BUNDLE_FILES := $(filter $(JDK_DEMOS_IMAGE_HOMEDIR)/demo/%, \
|
||||
@@ -373,7 +383,7 @@ ifneq ($(filter product-bundles% legacy-bundles, $(MAKECMDGOALS)), )
|
||||
$(eval $(call SetupBundleFile, BUILD_JDK_SYMBOLS_BUNDLE, \
|
||||
BUNDLE_NAME := $(JDK_SYMBOLS_BUNDLE_NAME), \
|
||||
FILES := $(JDK_SYMBOLS_BUNDLE_FILES), \
|
||||
BASE_DIRS := $(SYMBOLS_IMAGE_DIR), \
|
||||
BASE_DIRS := $(JDK_SYMBOLS_IMAGE_DIR) $(wildcard $(SYMBOLS_IMAGE_DIR)), \
|
||||
SUBDIR := $(JDK_BUNDLE_SUBDIR), \
|
||||
UNZIP_DEBUGINFO := true, \
|
||||
))
|
||||
|
||||
@@ -76,7 +76,6 @@ java.datatransfer_COPY += flavormap.properties
|
||||
|
||||
################################################################################
|
||||
|
||||
java.desktop_DISABLED_WARNINGS += missing-explicit-ctor
|
||||
java.desktop_DOCLINT += -Xdoclint:all/protected,-reference \
|
||||
'-Xdoclint/package:java.*,javax.*'
|
||||
java.desktop_COPY += .gif .png .wav .txt .xml .css .pf
|
||||
@@ -299,10 +298,6 @@ java.xml.crypto_CLEAN += .properties
|
||||
|
||||
################################################################################
|
||||
|
||||
jdk.accessibility_DISABLED_WARNINGS += missing-explicit-ctor
|
||||
|
||||
################################################################################
|
||||
|
||||
jdk.charsets_COPY += .dat
|
||||
|
||||
################################################################################
|
||||
@@ -352,19 +347,10 @@ jdk.javadoc_COPY += .xml .css .js .png
|
||||
|
||||
################################################################################
|
||||
|
||||
jdk.jartool_DISABLED_WARNINGS += missing-explicit-ctor
|
||||
jdk.jartool_JAVAC_FLAGS += -XDstringConcat=inline
|
||||
|
||||
################################################################################
|
||||
|
||||
jdk.httpserver_DISABLED_WARNINGS += missing-explicit-ctor
|
||||
|
||||
################################################################################
|
||||
|
||||
jdk.unsupported.desktop_DISABLED_WARNINGS += missing-explicit-ctor
|
||||
|
||||
################################################################################
|
||||
|
||||
# No SCTP implementation on Mac OS X or AIX. These classes should be excluded.
|
||||
SCTP_IMPL_CLASSES = \
|
||||
$(TOPDIR)/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/AssociationChange.java \
|
||||
|
||||
@@ -298,8 +298,6 @@ define SetupApiDocsGenerationBody
|
||||
# Create a string like "-Xdoclint:all,-syntax,-html,..."
|
||||
$1_OPTIONS += -Xdoclint:all,$$(call CommaList, $$(addprefix -, \
|
||||
$$(JAVADOC_DISABLED_DOCLINT)))
|
||||
# Ignore the doclint warnings in the W3C DOM package
|
||||
$1_OPTIONS += -Xdoclint/package:-org.w3c.*
|
||||
|
||||
$1_DOC_TITLE := $$($1_LONG_NAME)<br>Version $$(VERSION_SPECIFICATION) API \
|
||||
Specification
|
||||
|
||||
@@ -238,7 +238,6 @@ endif
|
||||
ALL_JDK_MODULES := $(JDK_MODULES)
|
||||
ALL_JRE_MODULES := $(sort $(JRE_MODULES), $(foreach m, $(JRE_MODULES), \
|
||||
$(call FindTransitiveDepsForModule, $m)))
|
||||
ALL_SYMBOLS_MODULES := $(JDK_MODULES)
|
||||
|
||||
ifeq ($(call isTargetOs, windows), true)
|
||||
LIBS_TARGET_SUBDIR := bin
|
||||
@@ -294,7 +293,6 @@ SetupCopyDebuginfo = \
|
||||
# implementation above.
|
||||
$(call SetupCopyDebuginfo,JDK)
|
||||
$(call SetupCopyDebuginfo,JRE)
|
||||
$(call SetupCopyDebuginfo,SYMBOLS)
|
||||
|
||||
################################################################################
|
||||
|
||||
|
||||
@@ -38,8 +38,11 @@ ifeq ($(call isTargetOs, macosx), true)
|
||||
|
||||
MACOSX_PLIST_SRC := $(TOPDIR)/make/data/bundle
|
||||
|
||||
BUNDLE_ID := $(MACOSX_BUNDLE_ID_BASE).$(VERSION_SHORT)
|
||||
BUNDLE_NAME := $(MACOSX_BUNDLE_NAME_BASE) $(VERSION_SHORT)
|
||||
BUNDLE_INFO := $(MACOSX_BUNDLE_NAME_BASE) $(VERSION_STRING)
|
||||
BUNDLE_PLATFORM_VERSION := $(VERSION_FEATURE).$(VERSION_INTERIM)
|
||||
BUNDLE_VERSION := $(VERSION_NUMBER)
|
||||
ifeq ($(COMPANY_NAME), N/A)
|
||||
BUNDLE_VENDOR := UNDEFINED
|
||||
else
|
||||
@@ -72,26 +75,24 @@ ifeq ($(call isTargetOs, macosx), true)
|
||||
SOURCE_FILES := $(MACOSX_PLIST_SRC)/JDK-Info.plist, \
|
||||
OUTPUT_FILE := $(JDK_MACOSX_CONTENTS_DIR)/Info.plist, \
|
||||
REPLACEMENTS := \
|
||||
@@ID@@ => $(MACOSX_BUNDLE_ID_BASE).jdk ; \
|
||||
@@ID@@ => $(BUNDLE_ID).jdk ; \
|
||||
@@NAME@@ => $(BUNDLE_NAME) ; \
|
||||
@@INFO@@ => $(BUNDLE_INFO) ; \
|
||||
@@VERSION@@ => $(VERSION_NUMBER) ; \
|
||||
@@BUILD_VERSION@@ => $(MACOSX_BUNDLE_BUILD_VERSION) ; \
|
||||
@@VENDOR@@ => $(BUNDLE_VENDOR) ; \
|
||||
@@MACOSX_VERSION_MIN@@ => $(MACOSX_VERSION_MIN) , \
|
||||
@@PLATFORM_VERSION@@ => $(BUNDLE_PLATFORM_VERSION) ; \
|
||||
@@VERSION@@ => $(BUNDLE_VERSION) ; \
|
||||
@@VENDOR@@ => $(BUNDLE_VENDOR) , \
|
||||
))
|
||||
|
||||
$(eval $(call SetupTextFileProcessing, BUILD_JRE_PLIST, \
|
||||
SOURCE_FILES := $(MACOSX_PLIST_SRC)/JRE-Info.plist, \
|
||||
OUTPUT_FILE := $(JRE_MACOSX_CONTENTS_DIR)/Info.plist, \
|
||||
REPLACEMENTS := \
|
||||
@@ID@@ => $(MACOSX_BUNDLE_ID_BASE).jre ; \
|
||||
@@ID@@ => $(BUNDLE_ID).jre ; \
|
||||
@@NAME@@ => $(BUNDLE_NAME) ; \
|
||||
@@INFO@@ => $(BUNDLE_INFO) ; \
|
||||
@@VERSION@@ => $(VERSION_NUMBER) ; \
|
||||
@@BUILD_VERSION@@ => $(BUNDLE_BUILD_VERSION) ; \
|
||||
@@VENDOR@@ => $(BUNDLE_VENDOR) ; \
|
||||
@@MACOSX_VERSION_MIN@@ => $(MACOSX_VERSION_MIN) , \
|
||||
@@PLATFORM_VERSION@@ => $(BUNDLE_PLATFORM_VERSION) ; \
|
||||
@@VERSION@@ => $(BUNDLE_VERSION) ; \
|
||||
@@VENDOR@@ => $(BUNDLE_VENDOR) , \
|
||||
))
|
||||
|
||||
$(SUPPORT_OUTPUTDIR)/images/_jdk_bundle_attribute_set: $(COPY_JDK_IMAGE)
|
||||
|
||||
@@ -172,10 +172,6 @@ define SetupAotModuleBody
|
||||
$1_JAOTC_OPTS += --compile-with-assertions
|
||||
endif
|
||||
|
||||
ifneq ($$(filter -XX:+VerifyOops, $$($1_VM_OPTIONS)), )
|
||||
$1_JAOTC_OPTS += -J-Dgraal.AOTVerifyOops=true
|
||||
endif
|
||||
|
||||
$$($1_AOT_LIB): $$(JDK_UNDER_TEST)/release \
|
||||
$$(call DependOnVariable, $1_JAOTC_OPTS) \
|
||||
$$(call DependOnVariable, JDK_UNDER_TEST)
|
||||
|
||||
@@ -72,6 +72,7 @@ AC_DEFUN_ONCE([BASIC_SETUP_FUNDAMENTAL_TOOLS],
|
||||
UTIL_REQUIRE_PROGS(UNAME, uname)
|
||||
UTIL_REQUIRE_PROGS(UNIQ, uniq)
|
||||
UTIL_REQUIRE_PROGS(WC, wc)
|
||||
UTIL_REQUIRE_PROGS(WHICH, which)
|
||||
UTIL_REQUIRE_PROGS(XARGS, xargs)
|
||||
|
||||
# Then required tools that require some special treatment.
|
||||
|
||||
12
make/autoconf/configure
vendored
12
make/autoconf/configure
vendored
@@ -78,11 +78,11 @@ generated_script="$build_support_dir/generated-configure.sh"
|
||||
###
|
||||
|
||||
autoconf_missing_help() {
|
||||
APT_GET="`type -p apt-get 2> /dev/null`"
|
||||
YUM="`type -p yum 2> /dev/null`"
|
||||
BREW="`type -p brew 2> /dev/null`"
|
||||
ZYPPER="`type -p zypper 2> /dev/null`"
|
||||
CYGWIN="`type -p cygpath 2> /dev/null`"
|
||||
APT_GET="`which apt-get 2> /dev/null | grep -v '^no apt-get in'`"
|
||||
YUM="`which yum 2> /dev/null | grep -v '^no yum in'`"
|
||||
BREW="`which brew 2> /dev/null | grep -v '^no brew in'`"
|
||||
ZYPPER="`which zypper 2> /dev/null | grep -v '^no zypper in'`"
|
||||
CYGWIN="`which cygpath 2> /dev/null | grep -v '^no cygpath in'`"
|
||||
|
||||
if test "x$ZYPPER" != x; then
|
||||
PKGHANDLER_COMMAND="sudo zypper install autoconf"
|
||||
@@ -111,7 +111,7 @@ generate_configure_script() {
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
AUTOCONF="`type -p autoconf 2> /dev/null`"
|
||||
AUTOCONF="`which autoconf 2> /dev/null | grep -v '^no autoconf in'`"
|
||||
if test "x$AUTOCONF" = x; then
|
||||
echo
|
||||
echo "Autoconf is not found on the PATH, and AUTOCONF is not set."
|
||||
|
||||
@@ -134,10 +134,6 @@ AC_DEFUN([FLAGS_SETUP_WARNINGS],
|
||||
|
||||
WARNINGS_ENABLE_ALL="-W3"
|
||||
DISABLED_WARNINGS="4800"
|
||||
if test "x$TOOLCHAIN_VERSION" = x2017; then
|
||||
# VS2017 incorrectly triggers this warning for constexpr
|
||||
DISABLED_WARNINGS+=" 4307"
|
||||
fi
|
||||
;;
|
||||
|
||||
gcc)
|
||||
|
||||
@@ -218,12 +218,10 @@ AC_DEFUN([FLAGS_SETUP_SYSROOT_FLAGS],
|
||||
# We also need -iframework<path>/System/Library/Frameworks
|
||||
$1SYSROOT_CFLAGS="[$]$1SYSROOT_CFLAGS -iframework [$]$1SYSROOT/System/Library/Frameworks"
|
||||
$1SYSROOT_LDFLAGS="[$]$1SYSROOT_LDFLAGS -iframework [$]$1SYSROOT/System/Library/Frameworks"
|
||||
if test -d "[$]$1SYSROOT/System/Library/Frameworks/JavaVM.framework/Frameworks" ; then
|
||||
# These always need to be set on macOS 10.X, or we can't find the frameworks embedded in JavaVM.framework
|
||||
# set this here so it doesn't have to be peppered throughout the forest
|
||||
$1SYSROOT_CFLAGS="[$]$1SYSROOT_CFLAGS -F [$]$1SYSROOT/System/Library/Frameworks/JavaVM.framework/Frameworks"
|
||||
$1SYSROOT_LDFLAGS="[$]$1SYSROOT_LDFLAGS -F [$]$1SYSROOT/System/Library/Frameworks/JavaVM.framework/Frameworks"
|
||||
fi
|
||||
# These always need to be set, or we can't find the frameworks embedded in JavaVM.framework
|
||||
# set this here so it doesn't have to be peppered throughout the forest
|
||||
$1SYSROOT_CFLAGS="[$]$1SYSROOT_CFLAGS -F [$]$1SYSROOT/System/Library/Frameworks/JavaVM.framework/Frameworks"
|
||||
$1SYSROOT_LDFLAGS="[$]$1SYSROOT_LDFLAGS -F [$]$1SYSROOT/System/Library/Frameworks/JavaVM.framework/Frameworks"
|
||||
fi
|
||||
|
||||
AC_SUBST($1SYSROOT_CFLAGS)
|
||||
|
||||
@@ -101,8 +101,6 @@ apt_help() {
|
||||
PKGHANDLER_COMMAND="sudo apt-get install libfontconfig1-dev" ;;
|
||||
freetype)
|
||||
PKGHANDLER_COMMAND="sudo apt-get install libfreetype6-dev" ;;
|
||||
harfbuzz)
|
||||
PKGHANDLER_COMMAND="sudo apt-get install libharfbuzz-dev" ;;
|
||||
ffi)
|
||||
PKGHANDLER_COMMAND="sudo apt-get install libffi-dev" ;;
|
||||
x11)
|
||||
@@ -126,8 +124,6 @@ zypper_help() {
|
||||
PKGHANDLER_COMMAND="sudo zypper install fontconfig-devel" ;;
|
||||
freetype)
|
||||
PKGHANDLER_COMMAND="sudo zypper install freetype-devel" ;;
|
||||
harfbuzz)
|
||||
PKGHANDLER_COMMAND="sudo zypper install harfbuzz-devel" ;;
|
||||
x11)
|
||||
PKGHANDLER_COMMAND="sudo zypper install libX11-devel libXext-devel libXrender-devel libXrandr-devel libXtst-devel libXt-devel libXi-devel" ;;
|
||||
ccache)
|
||||
@@ -147,8 +143,6 @@ yum_help() {
|
||||
PKGHANDLER_COMMAND="sudo yum install fontconfig-devel" ;;
|
||||
freetype)
|
||||
PKGHANDLER_COMMAND="sudo yum install freetype-devel" ;;
|
||||
harfbuzz)
|
||||
PKGHANDLER_COMMAND="sudo yum install harfbuzz-devel" ;;
|
||||
x11)
|
||||
PKGHANDLER_COMMAND="sudo yum install libXtst-devel libXt-devel libXrender-devel libXrandr-devel libXi-devel" ;;
|
||||
ccache)
|
||||
|
||||
@@ -67,6 +67,34 @@ AC_DEFUN_ONCE([JDKVER_SETUP_JDK_VERSION_NUMBERS],
|
||||
AC_SUBST(JDK_RC_PLATFORM_NAME)
|
||||
AC_SUBST(HOTSPOT_VM_DISTRO)
|
||||
|
||||
# Set the MACOSX Bundle Name base
|
||||
AC_ARG_WITH(macosx-bundle-name-base, [AS_HELP_STRING([--with-macosx-bundle-name-base],
|
||||
[Set the MacOSX Bundle Name base. This is the base name for calculating MacOSX Bundle Names.
|
||||
@<:@not specified@:>@])])
|
||||
if test "x$with_macosx_bundle_name_base" = xyes; then
|
||||
AC_MSG_ERROR([--with-macosx-bundle-name-base must have a value])
|
||||
elif [ ! [[ $with_macosx_bundle_name_base =~ ^[[:print:]]*$ ]] ]; then
|
||||
AC_MSG_ERROR([--with-macosx-bundle-name-base contains non-printing characters: $with_macosx_bundle_name_base])
|
||||
elif test "x$with_macosx_bundle_name_base" != x; then
|
||||
# Set MACOSX_BUNDLE_NAME_BASE to the configured value.
|
||||
MACOSX_BUNDLE_NAME_BASE="$with_macosx_bundle_name_base"
|
||||
fi
|
||||
AC_SUBST(MACOSX_BUNDLE_NAME_BASE)
|
||||
|
||||
# Set the MACOSX Bundle ID base
|
||||
AC_ARG_WITH(macosx-bundle-id-base, [AS_HELP_STRING([--with-macosx-bundle-id-base],
|
||||
[Set the MacOSX Bundle ID base. This is the base ID for calculating MacOSX Bundle IDs.
|
||||
@<:@not specified@:>@])])
|
||||
if test "x$with_macosx_bundle_id_base" = xyes; then
|
||||
AC_MSG_ERROR([--with-macosx-bundle-id-base must have a value])
|
||||
elif [ ! [[ $with_macosx_bundle_id_base =~ ^[[:print:]]*$ ]] ]; then
|
||||
AC_MSG_ERROR([--with-macosx-bundle-id-base contains non-printing characters: $with_macosx_bundle_id_base])
|
||||
elif test "x$with_macosx_bundle_id_base" != x; then
|
||||
# Set MACOSX_BUNDLE_ID_BASE to the configured value.
|
||||
MACOSX_BUNDLE_ID_BASE="$with_macosx_bundle_id_base"
|
||||
fi
|
||||
AC_SUBST(MACOSX_BUNDLE_ID_BASE)
|
||||
|
||||
# Set the JDK RC name
|
||||
AC_ARG_WITH(jdk-rc-name, [AS_HELP_STRING([--with-jdk-rc-name],
|
||||
[Set JDK RC name. This is used for FileDescription and ProductName properties
|
||||
@@ -474,60 +502,6 @@ AC_DEFUN_ONCE([JDKVER_SETUP_JDK_VERSION_NUMBERS],
|
||||
VENDOR_VERSION_STRING="$with_vendor_version_string"
|
||||
fi
|
||||
|
||||
# Set the MACOSX Bundle Name base
|
||||
AC_ARG_WITH(macosx-bundle-name-base, [AS_HELP_STRING([--with-macosx-bundle-name-base],
|
||||
[Set the MacOSX Bundle Name base. This is the base name for calculating MacOSX Bundle Names.
|
||||
@<:@not specified@:>@])])
|
||||
if test "x$with_macosx_bundle_name_base" = xyes; then
|
||||
AC_MSG_ERROR([--with-macosx-bundle-name-base must have a value])
|
||||
elif [ ! [[ $with_macosx_bundle_name_base =~ ^[[:print:]]*$ ]] ]; then
|
||||
AC_MSG_ERROR([--with-macosx-bundle-name-base contains non-printing characters: $with_macosx_bundle_name_base])
|
||||
elif test "x$with_macosx_bundle_name_base" != x; then
|
||||
# Set MACOSX_BUNDLE_NAME_BASE to the configured value.
|
||||
MACOSX_BUNDLE_NAME_BASE="$with_macosx_bundle_name_base"
|
||||
fi
|
||||
AC_SUBST(MACOSX_BUNDLE_NAME_BASE)
|
||||
|
||||
# Set the MACOSX Bundle ID base
|
||||
AC_ARG_WITH(macosx-bundle-id-base, [AS_HELP_STRING([--with-macosx-bundle-id-base],
|
||||
[Set the MacOSX Bundle ID base. This is the base ID for calculating MacOSX Bundle IDs.
|
||||
@<:@not specified@:>@])])
|
||||
if test "x$with_macosx_bundle_id_base" = xyes; then
|
||||
AC_MSG_ERROR([--with-macosx-bundle-id-base must have a value])
|
||||
elif [ ! [[ $with_macosx_bundle_id_base =~ ^[[:print:]]*$ ]] ]; then
|
||||
AC_MSG_ERROR([--with-macosx-bundle-id-base contains non-printing characters: $with_macosx_bundle_id_base])
|
||||
elif test "x$with_macosx_bundle_id_base" != x; then
|
||||
# Set MACOSX_BUNDLE_ID_BASE to the configured value.
|
||||
MACOSX_BUNDLE_ID_BASE="$with_macosx_bundle_id_base"
|
||||
else
|
||||
# If using the default value, append the VERSION_PRE if there is one
|
||||
# to make it possible to tell official builds apart from developer builds
|
||||
if test "x$VERSION_PRE" != x; then
|
||||
MACOSX_BUNDLE_ID_BASE="$MACOSX_BUNDLE_ID_BASE-$VERSION_PRE"
|
||||
fi
|
||||
fi
|
||||
AC_SUBST(MACOSX_BUNDLE_ID_BASE)
|
||||
|
||||
# Set the MACOSX CFBundleVersion field
|
||||
AC_ARG_WITH(macosx-bundle-build-version, [AS_HELP_STRING([--with-macosx-bundle-build-version],
|
||||
[Set the MacOSX Bundle CFBundleVersion field. This key is a machine-readable
|
||||
string composed of one to three period-separated integers and should represent the
|
||||
build version. Defaults to the build number.])])
|
||||
if test "x$with_macosx_bundle_build_version" = xyes; then
|
||||
AC_MSG_ERROR([--with-macosx-bundle-build-version must have a value])
|
||||
elif [ ! [[ $with_macosx_bundle_build_version =~ ^[0-9\.]*$ ]] ]; then
|
||||
AC_MSG_ERROR([--with-macosx-bundle-build-version contains non numbers and periods: $with_macosx_bundle_build_version])
|
||||
elif test "x$with_macosx_bundle_build_version" != x; then
|
||||
MACOSX_BUNDLE_BUILD_VERSION="$with_macosx_bundle_build_version"
|
||||
else
|
||||
MACOSX_BUNDLE_BUILD_VERSION="$VERSION_BUILD"
|
||||
# If VERSION_OPT consists of only numbers and periods, add it.
|
||||
if [ [[ $VERSION_OPT =~ ^[0-9\.]+$ ]] ]; then
|
||||
MACOSX_BUNDLE_BUILD_VERSION+=".$VERSION_OPT"
|
||||
fi
|
||||
fi
|
||||
AC_SUBST(MACOSX_BUNDLE_BUILD_VERSION)
|
||||
|
||||
# We could define --with flags for these, if really needed
|
||||
VERSION_CLASSFILE_MAJOR="$DEFAULT_VERSION_CLASSFILE_MAJOR"
|
||||
VERSION_CLASSFILE_MINOR="$DEFAULT_VERSION_CLASSFILE_MINOR"
|
||||
|
||||
@@ -395,14 +395,8 @@ AC_DEFUN_ONCE([JVM_FEATURES_CHECK_ZGC],
|
||||
AC_MSG_RESULT([no, $OPENJDK_TARGET_OS-$OPENJDK_TARGET_CPU])
|
||||
AVAILABLE=false
|
||||
fi
|
||||
elif test "x$OPENJDK_TARGET_CPU" = "xaarch64"; then
|
||||
if test "x$OPENJDK_TARGET_OS" = "xlinux" || \
|
||||
test "x$OPENJDK_TARGET_OS" = "xwindows"; then
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no, $OPENJDK_TARGET_OS-$OPENJDK_TARGET_CPU])
|
||||
AVAILABLE=false
|
||||
fi
|
||||
elif test "x$OPENJDK_TARGET_OS-$OPENJDK_TARGET_CPU" = "xlinux-aarch64"; then
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no, $OPENJDK_TARGET_OS-$OPENJDK_TARGET_CPU])
|
||||
AVAILABLE=false
|
||||
|
||||
@@ -40,7 +40,6 @@ AC_DEFUN_ONCE([LIB_SETUP_BUNDLED_LIBS],
|
||||
LIB_SETUP_LIBPNG
|
||||
LIB_SETUP_ZLIB
|
||||
LIB_SETUP_LCMS
|
||||
LIB_SETUP_HARFBUZZ
|
||||
])
|
||||
|
||||
################################################################################
|
||||
@@ -264,43 +263,3 @@ AC_DEFUN_ONCE([LIB_SETUP_LCMS],
|
||||
AC_SUBST(LCMS_CFLAGS)
|
||||
AC_SUBST(LCMS_LIBS)
|
||||
])
|
||||
|
||||
################################################################################
|
||||
# Setup harfbuzz
|
||||
################################################################################
|
||||
AC_DEFUN_ONCE([LIB_SETUP_HARFBUZZ],
|
||||
[
|
||||
AC_ARG_WITH(harfbuzz, [AS_HELP_STRING([--with-harfbuzz],
|
||||
[use harfbuzz from build system or OpenJDK source (system, bundled) @<:@bundled@:>@])])
|
||||
|
||||
AC_MSG_CHECKING([for which harfbuzz to use])
|
||||
|
||||
DEFAULT_HARFBUZZ=bundled
|
||||
# If user didn't specify, use DEFAULT_HARFBUZZ
|
||||
if test "x${with_harfbuzz}" = "x"; then
|
||||
with_harfbuzz=${DEFAULT_HARFBUZZ}
|
||||
fi
|
||||
|
||||
if test "x${with_harfbuzz}" = "xbundled"; then
|
||||
USE_EXTERNAL_HARFBUZZ=false
|
||||
HARFBUZZ_CFLAGS=""
|
||||
HARFBUZZ_LIBS=""
|
||||
AC_MSG_RESULT([bundled])
|
||||
elif test "x${with_harfbuzz}" = "xsystem"; then
|
||||
AC_MSG_RESULT([system])
|
||||
PKG_CHECK_MODULES([HARFBUZZ], [harfbuzz], [HARFBUZZ_FOUND=yes], [HARFBUZZ_FOUND=no])
|
||||
if test "x${HARFBUZZ_FOUND}" = "xyes"; then
|
||||
# PKG_CHECK_MODULES will set HARFBUZZ_CFLAGS and HARFBUZZ_LIBS
|
||||
USE_EXTERNAL_HARFBUZZ=true
|
||||
else
|
||||
HELP_MSG_MISSING_DEPENDENCY([harfbuzz])
|
||||
AC_MSG_ERROR([--with-harfbuzz=system specified, but no harfbuzz found! $HELP_MSG])
|
||||
fi
|
||||
else
|
||||
AC_MSG_ERROR([Invalid value for --with-harfbuzz: ${with_harfbuzz}, use 'system' or 'bundled'])
|
||||
fi
|
||||
|
||||
AC_SUBST(USE_EXTERNAL_HARFBUZZ)
|
||||
AC_SUBST(HARFBUZZ_CFLAGS)
|
||||
AC_SUBST(HARFBUZZ_LIBS)
|
||||
])
|
||||
|
||||
@@ -170,7 +170,6 @@ COMPANY_NAME:=@COMPANY_NAME@
|
||||
HOTSPOT_VM_DISTRO:=@HOTSPOT_VM_DISTRO@
|
||||
MACOSX_BUNDLE_NAME_BASE=@MACOSX_BUNDLE_NAME_BASE@
|
||||
MACOSX_BUNDLE_ID_BASE=@MACOSX_BUNDLE_ID_BASE@
|
||||
MACOSX_BUNDLE_BUILD_VERSION=@MACOSX_BUNDLE_BUILD_VERSION@
|
||||
USERNAME:=@USERNAME@
|
||||
VENDOR_URL:=@VENDOR_URL@
|
||||
VENDOR_URL_BUG:=@VENDOR_URL_BUG@
|
||||
@@ -825,10 +824,6 @@ USE_EXTERNAL_LCMS:=@USE_EXTERNAL_LCMS@
|
||||
LCMS_CFLAGS:=@LCMS_CFLAGS@
|
||||
LCMS_LIBS:=@LCMS_LIBS@
|
||||
|
||||
USE_EXTERNAL_HARFBUZZ:=@USE_EXTERNAL_HARFBUZZ@
|
||||
HARFBUZZ_CFLAGS:=@HARFBUZZ_CFLAGS@
|
||||
HARFBUZZ_LIBS:=@HARFBUZZ_LIBS@
|
||||
|
||||
USE_EXTERNAL_LIBPNG:=@USE_EXTERNAL_LIBPNG@
|
||||
PNG_LIBS:=@PNG_LIBS@
|
||||
PNG_CFLAGS:=@PNG_CFLAGS@
|
||||
|
||||
@@ -902,14 +902,9 @@ AC_DEFUN_ONCE([TOOLCHAIN_SETUP_BUILD_COMPILERS],
|
||||
# FIXME: we should list the discovered compilers as an exclude pattern!
|
||||
# If we do that, we can do this detection before POST_DETECTION, and still
|
||||
# find the build compilers in the tools dir, if needed.
|
||||
if test "x$OPENJDK_BUILD_OS" = xmacosx; then
|
||||
UTIL_REQUIRE_PROGS(BUILD_CC, [clang cl cc gcc])
|
||||
UTIL_REQUIRE_PROGS(BUILD_CXX, [clang++ cl CC g++])
|
||||
else
|
||||
UTIL_REQUIRE_PROGS(BUILD_CC, [cl cc gcc])
|
||||
UTIL_REQUIRE_PROGS(BUILD_CXX, [cl CC g++])
|
||||
fi
|
||||
UTIL_REQUIRE_PROGS(BUILD_CC, [cl cc gcc])
|
||||
UTIL_FIXUP_EXECUTABLE(BUILD_CC)
|
||||
UTIL_REQUIRE_PROGS(BUILD_CXX, [cl CC g++])
|
||||
UTIL_FIXUP_EXECUTABLE(BUILD_CXX)
|
||||
UTIL_PATH_PROGS(BUILD_NM, nm gcc-nm)
|
||||
UTIL_FIXUP_EXECUTABLE(BUILD_NM)
|
||||
|
||||
@@ -601,7 +601,7 @@ AC_DEFUN([UTIL_REQUIRE_BUILTIN_PROGS],
|
||||
UTIL_SETUP_TOOL($1, [AC_PATH_PROGS($1, $2, , $3)])
|
||||
if test "x[$]$1" = x; then
|
||||
AC_MSG_NOTICE([Required tool $2 not found in PATH, checking built-in])
|
||||
if type -p $2 > /dev/null 2>&1; then
|
||||
if command -v $2 > /dev/null 2>&1; then
|
||||
AC_MSG_NOTICE([Found $2 as shell built-in. Using it])
|
||||
$1="$2"
|
||||
else
|
||||
|
||||
@@ -242,7 +242,7 @@ AC_DEFUN([UTIL_FIXUP_EXECUTABLE_CYGWIN],
|
||||
new_path=`$CYGPATH -u "$path"`
|
||||
|
||||
# Now try to locate executable using which
|
||||
new_path=`type -p "$new_path" 2> /dev/null`
|
||||
new_path=`$WHICH "$new_path" 2> /dev/null`
|
||||
# bat and cmd files are not always considered executable in cygwin causing which
|
||||
# to not find them
|
||||
if test "x$new_path" = x \
|
||||
@@ -258,7 +258,7 @@ AC_DEFUN([UTIL_FIXUP_EXECUTABLE_CYGWIN],
|
||||
path="$complete"
|
||||
arguments="EOL"
|
||||
new_path=`$CYGPATH -u "$path"`
|
||||
new_path=`type -p "$new_path" 2> /dev/null`
|
||||
new_path=`$WHICH "$new_path" 2> /dev/null`
|
||||
# bat and cmd files are not always considered executable in cygwin causing which
|
||||
# to not find them
|
||||
if test "x$new_path" = x \
|
||||
@@ -324,7 +324,7 @@ AC_DEFUN([UTIL_FIXUP_EXECUTABLE_MSYS],
|
||||
UTIL_REWRITE_AS_UNIX_PATH(new_path)
|
||||
|
||||
# Now try to locate executable using which
|
||||
new_path=`type -p "$new_path" 2> /dev/null`
|
||||
new_path=`$WHICH "$new_path" 2> /dev/null`
|
||||
|
||||
if test "x$new_path" = x; then
|
||||
# Oops. Which didn't find the executable.
|
||||
@@ -336,7 +336,7 @@ AC_DEFUN([UTIL_FIXUP_EXECUTABLE_MSYS],
|
||||
new_path="$path"
|
||||
UTIL_REWRITE_AS_UNIX_PATH(new_path)
|
||||
|
||||
new_path=`type -p "$new_path" 2> /dev/null`
|
||||
new_path=`$WHICH "$new_path" 2> /dev/null`
|
||||
# bat and cmd files are not always considered executable in MSYS causing which
|
||||
# to not find them
|
||||
if test "x$new_path" = x \
|
||||
@@ -392,7 +392,7 @@ AC_DEFUN([UTIL_FIXUP_EXECUTABLE_WSL],
|
||||
|
||||
# Now try to locate executable using which
|
||||
new_path_bak="$new_path"
|
||||
new_path=`type -p "$new_path" 2> /dev/null`
|
||||
new_path=`$WHICH "$new_path" 2> /dev/null`
|
||||
# bat and cmd files are not considered executable in WSL
|
||||
if test "x$new_path" = x \
|
||||
&& test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \
|
||||
@@ -409,7 +409,7 @@ AC_DEFUN([UTIL_FIXUP_EXECUTABLE_WSL],
|
||||
new_path="$path"
|
||||
UTIL_REWRITE_AS_UNIX_PATH([new_path])
|
||||
new_path_bak="$new_path"
|
||||
new_path=`type -p "$new_path" 2> /dev/null`
|
||||
new_path=`$WHICH "$new_path" 2> /dev/null`
|
||||
# bat and cmd files are not considered executable in WSL
|
||||
if test "x$new_path" = x \
|
||||
&& test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \
|
||||
|
||||
@@ -346,7 +346,7 @@ $(MODULE_DEPS_MAKEFILE): $(MODULE_INFOS) \
|
||||
sub(/\/\*.*\*\//, ""); \
|
||||
gsub(/^ +\*.*/, ""); \
|
||||
gsub(/ /, ""); \
|
||||
gsub(/\r/, ""); \
|
||||
gsub(/\r/, ""); \
|
||||
printf(" %s", $$0) } \
|
||||
END { printf("\n") }' $m && \
|
||||
$(PRINTF) "TRANSITIVE_MODULES_$(call GetModuleNameFromModuleInfo, $m) :=" && \
|
||||
@@ -360,7 +360,7 @@ $(MODULE_DEPS_MAKEFILE): $(MODULE_INFOS) \
|
||||
sub(/\/\*.*\*\//, ""); \
|
||||
gsub(/^ +\*.*/, ""); \
|
||||
gsub(/ /, ""); \
|
||||
gsub(/\r/, ""); \
|
||||
gsub(/\r/, ""); \
|
||||
printf(" %s", $$0) } \
|
||||
END { printf("\n") }' $m \
|
||||
) >> $@ $(NEWLINE))
|
||||
|
||||
@@ -102,19 +102,19 @@ define SetupBuildLauncherBody
|
||||
|
||||
ifeq ($(call isTargetOs, macosx), true)
|
||||
ifeq ($$($1_MACOSX_PRIVILEGED), true)
|
||||
$1_PLIST_EXTRA := <key>SecTaskAccess</key><string>allowed</string>
|
||||
$1_PLIST_SRC_FILE := Info-privileged.plist
|
||||
else
|
||||
$1_PLIST_SRC_FILE := Info-cmdline.plist
|
||||
endif
|
||||
|
||||
$1_PLIST_FILE := $$(SUPPORT_OUTPUTDIR)/native/$$(MODULE)/$1/Info.plist
|
||||
|
||||
$$(eval $$(call SetupTextFileProcessing, BUILD_PLIST_$1, \
|
||||
SOURCE_FILES := $(TOPDIR)/make/data/bundle/cmdline-Info.plist, \
|
||||
SOURCE_FILES := $$(TOPDIR)/src/java.base/macosx/native/launcher/$$($1_PLIST_SRC_FILE), \
|
||||
OUTPUT_FILE := $$($1_PLIST_FILE), \
|
||||
REPLACEMENTS := \
|
||||
@@ID@@ => $(MACOSX_BUNDLE_ID_BASE).$1 ; \
|
||||
@@ID@@ => $(MACOSX_BUNDLE_ID_BASE).$(VERSION_SHORT).$1 ; \
|
||||
@@VERSION@@ => $(VERSION_NUMBER) ; \
|
||||
@@BUILD_VERSION@@ => $(MACOSX_BUNDLE_BUILD_VERSION) ; \
|
||||
@@EXTRA@@ => $$($1_PLIST_EXTRA), \
|
||||
))
|
||||
|
||||
$1_LDFLAGS += -sectcreate __TEXT __info_plist $$($1_PLIST_FILE)
|
||||
@@ -187,10 +187,6 @@ define SetupBuildLauncherBody
|
||||
$$(BUILD_LAUNCHER_$1): $(call FindStaticLib, java.base, java, /libjava) \
|
||||
$$($1_WINDOWS_JLI_LIB)
|
||||
endif
|
||||
|
||||
ifeq ($(call isTargetOs, macosx), true)
|
||||
$$(BUILD_LAUNCHER_$1): $$($1_PLIST_FILE)
|
||||
endif
|
||||
endef
|
||||
|
||||
################################################################################
|
||||
|
||||
@@ -1339,17 +1339,13 @@ var versionArgs = function(input, common) {
|
||||
"--with-version-pre=" + version_numbers.get("DEFAULT_PROMOTED_VERSION_PRE"),
|
||||
"--without-version-opt");
|
||||
} else if (input.build_type == "ci") {
|
||||
var ciBuildNumber = input.build_id_data.ciBuildNumber;
|
||||
var optString = input.build_id_data.ciBuildNumber;
|
||||
var preString = input.build_id_data.projectName;
|
||||
if (preString == "jdk") {
|
||||
preString = version_numbers.get("DEFAULT_PROMOTED_VERSION_PRE");
|
||||
}
|
||||
args = concat(args, "--with-version-pre=" + preString,
|
||||
"--with-version-opt=" + ciBuildNumber);
|
||||
if (input.target_os == "macosx") {
|
||||
args = concat(args, "--with-macosx-bundle-build-version="
|
||||
+ common.build_number + "." + ciBuildNumber);
|
||||
}
|
||||
"--with-version-opt=" + optString);
|
||||
} else {
|
||||
args = concat(args, "--with-version-opt=" + common.build_id);
|
||||
}
|
||||
|
||||
@@ -17,11 +17,11 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>BNDL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>@@VERSION@@</string>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>@@BUILD_VERSION@@</string>
|
||||
<string>@@VERSION@@</string>
|
||||
<key>NSMicrophoneUsageDescription</key>
|
||||
<string>The application is requesting access to the microphone.</string>
|
||||
<key>JavaVM</key>
|
||||
@@ -33,9 +33,9 @@
|
||||
<key>JVMMinimumFrameworkVersion</key>
|
||||
<string>13.2.9</string>
|
||||
<key>JVMMinimumSystemVersion</key>
|
||||
<string>@@MACOSX_VERSION_MIN@@</string>
|
||||
<string>10.6.0</string>
|
||||
<key>JVMPlatformVersion</key>
|
||||
<string>@@VERSION@@</string>
|
||||
<string>@@PLATFORM_VERSION@@</string>
|
||||
<key>JVMVendor</key>
|
||||
<string>@@VENDOR@@</string>
|
||||
<key>JVMVersion</key>
|
||||
|
||||
@@ -17,11 +17,11 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>BNDL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>@@VERSION@@</string>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>@@BUILD_VERSION@@</string>
|
||||
<string>@@VERSION@@</string>
|
||||
<key>NSMicrophoneUsageDescription</key>
|
||||
<string>The application is requesting access to the microphone.</string>
|
||||
<key>JavaVM</key>
|
||||
@@ -29,9 +29,9 @@
|
||||
<key>JVMMinimumFrameworkVersion</key>
|
||||
<string>13.2.9</string>
|
||||
<key>JVMMinimumSystemVersion</key>
|
||||
<string>@@MACOSX_VERSION_MIN@@</string>
|
||||
<string>10.6.0</string>
|
||||
<key>JVMPlatformVersion</key>
|
||||
<string>@@VERSION@@</string>
|
||||
<string>@@PLATFORM_VERSION@@</string>
|
||||
<key>JVMVendor</key>
|
||||
<string>@@VENDOR@@</string>
|
||||
<key>JVMVersion</key>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2000, 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
|
||||
@@ -50,7 +50,7 @@ all=ADP020-AED784-AFA004-AFN971-ALL008-AMD051-ANG532-AOA973-ARS032-ATS040-AUD036
|
||||
LVL428-LYD434-MAD504-MDL498-MGA969-MGF450-MKD807-MMK104-MNT496-MOP446-MRO478-MRU929-\
|
||||
MTL470-MUR480-MVR462-MWK454-MXN484-MXV979-MYR458-MZM508-MZN943-NAD516-NGN566-\
|
||||
NIO558-NLG528-NOK578-NPR524-NZD554-OMR512-PAB590-PEN604-PGK598-PHP608-\
|
||||
PKR586-PLN985-PTE620-PYG600-QAR634-ROL642-RON946-RSD941-RUB643-RUR810-RWF646-SAR682-\
|
||||
PKR586-PLN985-PTE620-PYG600-QAR634-ROL946-RON946-RSD941-RUB643-RUR810-RWF646-SAR682-\
|
||||
SBD090-SCR690-SDD736-SDG938-SEK752-SGD702-SHP654-SIT705-SKK703-SLL694-SOS706-\
|
||||
SRD968-SRG740-SSP728-STD678-STN930-SVC222-SYP760-SZL748-THB764-TJS972-TMM795-TMT934-TND788-TOP776-\
|
||||
TPE626-TRL792-TRY949-TTD780-TWD901-TZS834-UAH980-UGX800-USD840-USN997-USS998-UYI940-\
|
||||
@@ -588,7 +588,7 @@ ZW=ZWL
|
||||
|
||||
minor0=\
|
||||
ADP-BEF-BIF-BYB-BYR-CLP-DJF-ESP-GNF-\
|
||||
GRD-ISK-ITL-JPY-KMF-KRW-LUF-MGF-PYG-PTE-ROL-RWF-\
|
||||
GRD-ISK-ITL-JPY-KMF-KRW-LUF-MGF-PYG-PTE-RWF-\
|
||||
TPE-TRL-UGX-UYI-VND-VUV-XAF-XOF-XPF
|
||||
minor3=\
|
||||
BHD-IQD-JOD-KWD-LYD-OMR-TND
|
||||
|
||||
@@ -125,7 +125,7 @@ else
|
||||
endif
|
||||
|
||||
GCC := http://ftp.gnu.org/pub/gnu/gcc/$(gcc_ver)/$(gcc_ver).tar.xz
|
||||
BINUTILS := http://ftp.gnu.org/pub/gnu/binutils/$(binutils_ver).tar.gz
|
||||
BINUTILS := http://ftp.gnu.org/pub/gnu/binutils/$(binutils_ver).tar.xz
|
||||
CCACHE := https://github.com/ccache/ccache/releases/download/v$(ccache_ver)/ccache-$(ccache_ver).tar.xz
|
||||
MPFR := https://www.mpfr.org/${mpfr_ver}/${mpfr_ver}.tar.bz2
|
||||
GMP := http://ftp.gnu.org/pub/gnu/gmp/${gmp_ver}.tar.bz2
|
||||
|
||||
@@ -129,12 +129,6 @@ ifeq ($(call check-jvm-feature, compiler2), true)
|
||||
$d/os_cpu/$(HOTSPOT_TARGET_OS)_$(HOTSPOT_TARGET_CPU_ARCH)/$(HOTSPOT_TARGET_OS)_$(HOTSPOT_TARGET_CPU_ARCH).ad \
|
||||
)))
|
||||
|
||||
ifeq ($(HOTSPOT_TARGET_CPU_ARCH), aarch64)
|
||||
AD_SRC_FILES += $(call uniq, $(wildcard $(foreach d, $(AD_SRC_ROOTS), \
|
||||
$d/cpu/$(HOTSPOT_TARGET_CPU_ARCH)/$(HOTSPOT_TARGET_CPU_ARCH)_sve.ad \
|
||||
)))
|
||||
endif
|
||||
|
||||
ifeq ($(call check-jvm-feature, shenandoahgc), true)
|
||||
AD_SRC_FILES += $(call uniq, $(wildcard $(foreach d, $(AD_SRC_ROOTS), \
|
||||
$d/cpu/$(HOTSPOT_TARGET_CPU_ARCH)/gc/shenandoah/shenandoah_$(HOTSPOT_TARGET_CPU).ad \
|
||||
|
||||
@@ -250,14 +250,14 @@ ifneq ($(GENERATE_COMPILE_COMMANDS_ONLY), true)
|
||||
|
||||
define SetupOperatorNewDeleteCheck
|
||||
$1.op_check: $1
|
||||
$$(call ExecuteWithLog, $1.op_check, \
|
||||
$$(NM) $$< 2>&1 | $$(GREP) $$(addprefix -e , $$(MANGLED_SYMS)) | $$(GREP) $$(UNDEF_PATTERN) > $1.op_check || true)
|
||||
if [ -s $1.op_check ]; then \
|
||||
$$(ECHO) "$$(notdir $$<): Error: Use of global operators new and delete is not allowed in Hotspot:"; \
|
||||
$$(NM) $$< | $$(CXXFILT) | $$(EGREP) '$$(DEMANGLED_REGEXP)' | $$(GREP) $$(UNDEF_PATTERN); \
|
||||
$$(ECHO) "See: $$(TOPDIR)/make/hotspot/lib/CompileJvm.gmk"; \
|
||||
if [ -n "`$(NM) $$< | $(GREP) $(addprefix -e , $(MANGLED_SYMS)) \
|
||||
| $(GREP) $(UNDEF_PATTERN)`" ]; then \
|
||||
$(ECHO) "$$<: Error: Use of global operators new and delete is not allowed in Hotspot:"; \
|
||||
$(NM) $$< | $(CXXFILT) | $(EGREP) '$(DEMANGLED_REGEXP)' | $(GREP) $(UNDEF_PATTERN); \
|
||||
$(ECHO) "See: $(TOPDIR)/make/hotspot/lib/CompileJvm.gmk"; \
|
||||
exit 1; \
|
||||
fi
|
||||
$(TOUCH) $$@
|
||||
|
||||
TARGETS += $1.op_check
|
||||
endef
|
||||
|
||||
@@ -116,13 +116,8 @@ endif
|
||||
ifneq ($(call check-jvm-feature, cds), true)
|
||||
JVM_CFLAGS_FEATURES += -DINCLUDE_CDS=0
|
||||
JVM_EXCLUDE_FILES += \
|
||||
archiveBuilder.cpp \
|
||||
archiveUtils.cpp \
|
||||
classListParser.cpp \
|
||||
classLoaderDataShared.cpp \
|
||||
classLoaderExt.cpp \
|
||||
cppVtables.cpp \
|
||||
dumpAllocStats.cpp \
|
||||
dynamicArchive.cpp \
|
||||
filemap.cpp \
|
||||
heapShared.cpp \
|
||||
@@ -131,7 +126,8 @@ ifneq ($(call check-jvm-feature, cds), true)
|
||||
metaspaceShared_$(HOTSPOT_TARGET_CPU_ARCH).cpp \
|
||||
sharedClassUtil.cpp \
|
||||
sharedPathsMiscInfo.cpp \
|
||||
systemDictionaryShared.cpp
|
||||
systemDictionaryShared.cpp \
|
||||
#
|
||||
endif
|
||||
|
||||
ifneq ($(call check-jvm-feature, nmt), true)
|
||||
|
||||
@@ -198,6 +198,5 @@ JVM_AddModuleExports
|
||||
JVM_AddModuleExportsToAll
|
||||
JVM_AddModuleExportsToAllUnnamed
|
||||
JVM_AddReadsModule
|
||||
JVM_DefineArchivedModules
|
||||
JVM_DefineModule
|
||||
JVM_SetBootLoaderUnnamedModule
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Configure cpptools IntelliSense
|
||||
"C_Cpp.intelliSenseCachePath": "{{OUTPUTDIR}}/.vscode",
|
||||
"C_Cpp.default.compileCommands": "{{OUTPUTDIR}}/compile_commands.json",
|
||||
"C_Cpp.default.cppStandard": "c++14",
|
||||
"C_Cpp.default.cppStandard": "c++03",
|
||||
"C_Cpp.default.compilerPath": "{{COMPILER}}",
|
||||
|
||||
// Configure ccls
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Configure cpptools IntelliSense
|
||||
"C_Cpp.intelliSenseCachePath": "{{OUTPUTDIR}}/.vscode",
|
||||
"C_Cpp.default.compileCommands": "{{OUTPUTDIR}}/compile_commands.json",
|
||||
"C_Cpp.default.cppStandard": "c++14",
|
||||
"C_Cpp.default.cppStandard": "c++03",
|
||||
"C_Cpp.default.compilerPath": "{{COMPILER}}",
|
||||
|
||||
// Configure clangd
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Configure cpptools IntelliSense
|
||||
"C_Cpp.intelliSenseCachePath": "{{OUTPUTDIR}}/.vscode",
|
||||
"C_Cpp.default.compileCommands": "{{OUTPUTDIR}}/compile_commands.json",
|
||||
"C_Cpp.default.cppStandard": "c++14",
|
||||
"C_Cpp.default.cppStandard": "c++03",
|
||||
"C_Cpp.default.compilerPath": "{{COMPILER}}",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Configure cpptools IntelliSense
|
||||
"C_Cpp.intelliSenseCachePath": "{{OUTPUTDIR}}/.vscode",
|
||||
"C_Cpp.default.compileCommands": "{{OUTPUTDIR}}/compile_commands.json",
|
||||
"C_Cpp.default.cppStandard": "c++14",
|
||||
"C_Cpp.default.cppStandard": "c++03",
|
||||
"C_Cpp.default.compilerPath": "{{COMPILER}}",
|
||||
|
||||
// Configure RTags
|
||||
|
||||
@@ -157,6 +157,7 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBJIMAGE, \
|
||||
LDFLAGS := $(LDFLAGS_JDKLIB) $(LDFLAGS_CXX_JDK) \
|
||||
$(call SET_SHARED_LIBRARY_ORIGIN), \
|
||||
LIBS_unix := -ljvm -ldl $(LIBCXX), \
|
||||
LIBS_macosx := -lc++, \
|
||||
LIBS_windows := jvm.lib, \
|
||||
))
|
||||
|
||||
|
||||
@@ -71,10 +71,6 @@ ifeq ($(FREETYPE_TO_USE), system)
|
||||
LEGAL_EXCLUDES += freetype.md
|
||||
endif
|
||||
|
||||
ifeq ($(USE_EXTERNAL_HARFBUZZ), true)
|
||||
LEGAL_EXCLUDES += harfbuzz.md
|
||||
endif
|
||||
|
||||
$(eval $(call SetupCopyLegalFiles, COPY_LEGAL, \
|
||||
EXCLUDES := $(LEGAL_EXCLUDES), \
|
||||
))
|
||||
|
||||
@@ -432,87 +432,82 @@ endif
|
||||
|
||||
###########################################################################
|
||||
|
||||
ifeq ($(USE_EXTERNAL_HARFBUZZ), true)
|
||||
LIBHARFBUZZ_LIBS := $(HARFBUZZ_LIBS)
|
||||
else
|
||||
HARFBUZZ_CFLAGS := -DHAVE_OT -DHAVE_FALLBACK -DHAVE_UCDN -DHAVE_ROUND
|
||||
HARFBUZZ_CFLAGS := -DHAVE_OT -DHAVE_FALLBACK -DHAVE_UCDN -DHAVE_ROUND
|
||||
|
||||
# This is better than adding EXPORT_ALL_SYMBOLS
|
||||
ifneq ($(filter $(TOOLCHAIN_TYPE), gcc clang), )
|
||||
HARFBUZZ_CFLAGS += -DHB_EXTERN=__attribute__\(\(visibility\(\"default\"\)\)\)
|
||||
else ifeq ($(TOOLCHAIN_TYPE), microsoft)
|
||||
HARFBUZZ_CFLAGS += -DHB_EXTERN=__declspec\(dllexport\)
|
||||
endif
|
||||
# This is better than adding EXPORT_ALL_SYMBOLS
|
||||
ifneq ($(filter $(TOOLCHAIN_TYPE), gcc clang), )
|
||||
HARFBUZZ_CFLAGS += -DHB_EXTERN=__attribute__\(\(visibility\(\"default\"\)\)\)
|
||||
else ifeq ($(TOOLCHAIN_TYPE), microsoft)
|
||||
HARFBUZZ_CFLAGS += -DHB_EXTERN=__declspec\(dllexport\)
|
||||
endif
|
||||
|
||||
ifeq ($(call isTargetOs, windows), false)
|
||||
HARFBUZZ_CFLAGS += -DGETPAGESIZE -DHAVE_MPROTECT -DHAVE_PTHREAD \
|
||||
ifeq ($(call isTargetOs, windows), false)
|
||||
HARFBUZZ_CFLAGS += -DGETPAGESIZE -DHAVE_MPROTECT -DHAVE_PTHREAD \
|
||||
-DHAVE_SYSCONF -DHAVE_SYS_MMAN_H -DHAVE_UNISTD_H \
|
||||
-DHB_NO_PRAGMA_GCC_DIAGNOSTIC
|
||||
endif
|
||||
ifeq ($(call isTargetOs, linux macosx), true)
|
||||
HARFBUZZ_CFLAGS += -DHAVE_INTEL_ATOMIC_PRIMITIVES
|
||||
endif
|
||||
ifeq ($(call isTargetOs, macosx), true)
|
||||
HARFBUZZ_CFLAGS += -DHAVE_CORETEXT
|
||||
endif
|
||||
ifeq ($(call isTargetOs, macosx), false)
|
||||
LIBHARFBUZZ_EXCLUDE_FILES += libharfbuzz/hb-coretext.cc
|
||||
endif
|
||||
# hb-ft.cc is not presently needed, and requires freetype 2.4.2 or later.
|
||||
LIBHARFBUZZ_EXCLUDE_FILES += libharfbuzz/hb-ft.cc
|
||||
endif
|
||||
ifeq ($(call isTargetOs, linux macosx), true)
|
||||
HARFBUZZ_CFLAGS += -DHAVE_INTEL_ATOMIC_PRIMITIVES
|
||||
endif
|
||||
ifeq ($(call isTargetOs, macosx), true)
|
||||
HARFBUZZ_CFLAGS += -DHAVE_CORETEXT
|
||||
endif
|
||||
ifeq ($(call isTargetOs, macosx), false)
|
||||
LIBHARFBUZZ_EXCLUDE_FILES += harfbuzz/hb-coretext.cc
|
||||
endif
|
||||
# hb-ft.cc is not presently needed, and requires freetype 2.4.2 or later.
|
||||
LIBHARFBUZZ_EXCLUDE_FILES += harfbuzz/hb-ft.cc
|
||||
|
||||
LIBHARFBUZZ_CFLAGS += $(HARFBUZZ_CFLAGS)
|
||||
LIBHARFBUZZ_CFLAGS += $(HARFBUZZ_CFLAGS)
|
||||
|
||||
# For use by libfontmanager:
|
||||
ifeq ($(call isTargetOs, windows), true)
|
||||
LIBHARFBUZZ_LIBS := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libharfbuzz/harfbuzz.lib
|
||||
else
|
||||
LIBHARFBUZZ_LIBS := -lharfbuzz
|
||||
endif
|
||||
# For use by libfontmanager:
|
||||
ifeq ($(call isTargetOs, windows), true)
|
||||
LIBHARFBUZZ_LIBS := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libharfbuzz/harfbuzz.lib
|
||||
else
|
||||
LIBHARFBUZZ_LIBS := -lharfbuzz
|
||||
endif
|
||||
|
||||
LIBHARFBUZZ_EXTRA_HEADER_DIRS := \
|
||||
LIBHARFBUZZ_EXTRA_HEADER_DIRS := \
|
||||
libharfbuzz/hb-ucdn \
|
||||
#
|
||||
|
||||
LIBHARFBUZZ_OPTIMIZATION := HIGH
|
||||
LIBHARFBUZZ_OPTIMIZATION := HIGH
|
||||
|
||||
LIBHARFBUZZ_CFLAGS += $(X_CFLAGS) -DLE_STANDALONE -DHEADLESS
|
||||
LIBHARFBUZZ_CFLAGS += $(X_CFLAGS) -DLE_STANDALONE -DHEADLESS
|
||||
|
||||
$(eval $(call SetupJdkLibrary, BUILD_LIBHARFBUZZ, \
|
||||
NAME := harfbuzz, \
|
||||
EXCLUDE_FILES := $(LIBHARFBUZZ_EXCLUDE_FILES), \
|
||||
TOOLCHAIN := TOOLCHAIN_LINK_CXX, \
|
||||
CFLAGS := $(CFLAGS_JDKLIB) $(LIBHARFBUZZ_CFLAGS), \
|
||||
CXXFLAGS := $(CXXFLAGS_JDKLIB) $(LIBHARFBUZZ_CFLAGS), \
|
||||
OPTIMIZATION := $(LIBHARFBUZZ_OPTIMIZATION), \
|
||||
CFLAGS_windows = -DCC_NOEX, \
|
||||
EXTRA_HEADER_DIRS := $(LIBHARFBUZZ_EXTRA_HEADER_DIRS), \
|
||||
WARNINGS_AS_ERRORS_xlc := false, \
|
||||
DISABLED_WARNINGS_gcc := type-limits missing-field-initializers strict-aliasing, \
|
||||
DISABLED_WARNINGS_CXX_gcc := reorder delete-non-virtual-dtor strict-overflow \
|
||||
$(eval $(call SetupJdkLibrary, BUILD_LIBHARFBUZZ, \
|
||||
NAME := harfbuzz, \
|
||||
EXCLUDE_FILES := $(LIBHARFBUZZ_EXCLUDE_FILES), \
|
||||
TOOLCHAIN := TOOLCHAIN_LINK_CXX, \
|
||||
CFLAGS := $(CFLAGS_JDKLIB) $(LIBHARFBUZZ_CFLAGS), \
|
||||
CXXFLAGS := $(CXXFLAGS_JDKLIB) $(LIBHARFBUZZ_CFLAGS), \
|
||||
OPTIMIZATION := $(LIBHARFBUZZ_OPTIMIZATION), \
|
||||
CFLAGS_windows = -DCC_NOEX, \
|
||||
EXTRA_HEADER_DIRS := $(LIBHARFBUZZ_EXTRA_HEADER_DIRS), \
|
||||
WARNINGS_AS_ERRORS_xlc := false, \
|
||||
DISABLED_WARNINGS_gcc := type-limits missing-field-initializers strict-aliasing, \
|
||||
DISABLED_WARNINGS_CXX_gcc := reorder delete-non-virtual-dtor strict-overflow \
|
||||
maybe-uninitialized class-memaccess, \
|
||||
DISABLED_WARNINGS_clang := unused-value incompatible-pointer-types \
|
||||
DISABLED_WARNINGS_clang := unused-value incompatible-pointer-types \
|
||||
tautological-constant-out-of-range-compare int-to-pointer-cast \
|
||||
undef missing-field-initializers, \
|
||||
DISABLED_WARNINGS_microsoft := 4267 4244 4090 4146 4334 4819 4101 4068 4805 4138, \
|
||||
LDFLAGS := $(LDFLAGS_JDKLIB) \
|
||||
DISABLED_WARNINGS_microsoft := 4267 4244 4090 4146 4334 4819 4101 4068 4805 4138, \
|
||||
LDFLAGS := $(LDFLAGS_JDKLIB) \
|
||||
$(call SET_SHARED_LIBRARY_ORIGIN), \
|
||||
LDFLAGS_unix := -L$(INSTALL_LIBRARIES_HERE), \
|
||||
LDFLAGS_aix := -Wl$(COMMA)-berok, \
|
||||
LIBS := $(BUILD_LIBHARFBUZZ), \
|
||||
LIBS_unix := $(LIBM) $(LIBCXX), \
|
||||
LIBS_macosx := -framework CoreText -framework CoreFoundation -framework CoreGraphics, \
|
||||
LIBS_windows := user32.lib, \
|
||||
))
|
||||
|
||||
ifeq ($(FREETYPE_TO_USE), bundled)
|
||||
$(BUILD_LIBHARFBUZZ): $(BUILD_LIBFREETYPE)
|
||||
endif
|
||||
|
||||
TARGETS += $(BUILD_LIBHARFBUZZ)
|
||||
LDFLAGS_unix := -L$(INSTALL_LIBRARIES_HERE), \
|
||||
LDFLAGS_aix := -Wl$(COMMA)-berok, \
|
||||
LIBS := $(BUILD_LIBHARFBUZZ), \
|
||||
LIBS_unix := $(LIBM) $(LIBCXX), \
|
||||
LIBS_macosx := -framework CoreText -framework CoreFoundation -framework CoreGraphics, \
|
||||
LIBS_windows := user32.lib, \
|
||||
))
|
||||
|
||||
ifeq ($(FREETYPE_TO_USE), bundled)
|
||||
$(BUILD_LIBHARFBUZZ): $(BUILD_LIBFREETYPE)
|
||||
endif
|
||||
|
||||
TARGETS += $(BUILD_LIBHARFBUZZ)
|
||||
|
||||
###########################################################################
|
||||
|
||||
LIBFONTMANAGER_EXTRA_HEADER_DIRS := \
|
||||
@@ -566,6 +561,9 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBFONTMANAGER, \
|
||||
CFLAGS_windows = -DCC_NOEX, \
|
||||
EXTRA_HEADER_DIRS := $(LIBFONTMANAGER_EXTRA_HEADER_DIRS), \
|
||||
WARNINGS_AS_ERRORS_xlc := false, \
|
||||
DISABLED_WARNINGS_gcc := sign-compare unused-function int-to-pointer-cast, \
|
||||
DISABLED_WARNINGS_clang := sign-compare, \
|
||||
DISABLED_WARNINGS_microsoft := 4018 4146 4244 4996, \
|
||||
LDFLAGS := $(subst -Xlinker -z -Xlinker defs,, \
|
||||
$(subst -Wl$(COMMA)-z$(COMMA)defs,,$(LDFLAGS_JDKLIB))) $(LDFLAGS_CXX_JDK) \
|
||||
$(call SET_SHARED_LIBRARY_ORIGIN), \
|
||||
@@ -578,11 +576,7 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBFONTMANAGER, \
|
||||
$(WIN_AWT_LIB), \
|
||||
))
|
||||
|
||||
$(BUILD_LIBFONTMANAGER): $(BUILD_LIBAWT)
|
||||
|
||||
ifeq ($(USE_EXTERNAL_HARFBUZZ), false)
|
||||
$(BUILD_LIBFONTMANAGER): $(BUILD_LIBHARFBUZZ)
|
||||
endif
|
||||
$(BUILD_LIBFONTMANAGER): $(BUILD_LIBAWT) $(BUILD_LIBHARFBUZZ)
|
||||
|
||||
ifeq ($(call isTargetOs, macosx), true)
|
||||
$(BUILD_LIBFONTMANAGER): $(call FindLib, $(MODULE), awt_lwawt)
|
||||
|
||||
@@ -63,7 +63,7 @@ if [ ! -f symbols ] ; then
|
||||
exit 1
|
||||
fi;
|
||||
|
||||
if [ "`git status --porcelain=v1 .`x" != "x" ] ; then
|
||||
if [ "`hg status .`x" != "x" ] ; then
|
||||
echo "The make/data/symbols directory contains local changes!" >&2
|
||||
exit 1
|
||||
fi;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2002, 2007, Oracle and/or its affiliates. All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
@@ -120,7 +120,7 @@ $(CLASSES):
|
||||
mkdirs: $(DIST) $(CLASSES)
|
||||
|
||||
$(CLASSES)/j2dbench/%.class: $(SOURCEPATH)/j2dbench/%.java
|
||||
javac -g:none -source 1.7 -target 1.7 -d $(CLASSES) -sourcepath $(SOURCEPATH) $<
|
||||
javac -g:none -source 1.6 -target 1.6 -d $(CLASSES) -sourcepath $(SOURCEPATH) $<
|
||||
|
||||
clean:
|
||||
rm -rf $(CLASSES)
|
||||
|
||||
@@ -20,9 +20,8 @@ Minimum requirements
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
The benchmark requires at least jdk1.4 to compile and run. Note that
|
||||
source/target is set to 1.7 in the makefile and build.xml, because of
|
||||
support in jdk 14 compiler. To check compatibility with jdk1.4 you can
|
||||
use "-source 1.4 -target 1.4" options and jdk1.7.
|
||||
source/target is set to 1.6 in the makefile and build.xml, because of
|
||||
support in jdk 9 compiler.
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
How To Compile
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!--
|
||||
Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@@ -49,7 +49,7 @@
|
||||
<target name="compile" depends="init"
|
||||
description="compile the source " >
|
||||
<!-- Compile the java code from ${src} into ${build} -->
|
||||
<javac debug="off" source="1.7" target="1.7" srcdir="${src}" destdir="${build}"/>
|
||||
<javac debug="off" source="1.6" target="1.6" srcdir="${src}" destdir="${build}"/>
|
||||
</target>
|
||||
|
||||
<target name="run" depends="dist"
|
||||
|
||||
@@ -8,11 +8,8 @@ global.env.testtime=2500
|
||||
global.results.workunits=units
|
||||
global.results.timeunits=sec
|
||||
global.results.ratio=unitspersec
|
||||
global.dest.screen=disabled
|
||||
global.dest.offscreen=disabled
|
||||
global.dest.frame.defaultframe=disabled
|
||||
global.dest.frame.transframe=disabled
|
||||
global.dest.frame.shapedframe=disabled
|
||||
global.dest.frame.shapedtransframe=disabled
|
||||
global.dest.compatimg.compatimg=disabled
|
||||
global.dest.compatimg.opqcompatimg=disabled
|
||||
global.dest.compatimg.bmcompatimg=disabled
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@@ -40,11 +40,9 @@
|
||||
|
||||
package j2dbench;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Frame;
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.awt.Image;
|
||||
import java.awt.Polygon;
|
||||
import java.awt.Component;
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.awt.Transparency;
|
||||
import java.awt.color.ColorSpace;
|
||||
import java.awt.image.BufferedImage;
|
||||
@@ -52,14 +50,11 @@ import java.awt.image.ComponentColorModel;
|
||||
import java.awt.image.DataBuffer;
|
||||
import java.awt.image.WritableRaster;
|
||||
|
||||
import javax.swing.SwingUtilities;
|
||||
|
||||
import j2dbench.tests.GraphicsTests;
|
||||
import j2dbench.tests.ImageTests;
|
||||
|
||||
public abstract class Destinations extends Option.Enable {
|
||||
public static Group.EnableSet destroot;
|
||||
public static Group frameroot;
|
||||
public static Group bufimgdestroot;
|
||||
public static Group compatimgdestroot;
|
||||
public static Group volimgdestroot;
|
||||
@@ -68,22 +63,9 @@ public abstract class Destinations extends Option.Enable {
|
||||
destroot = new Group.EnableSet(TestEnvironment.globaloptroot,
|
||||
"dest", "Output Destination Options");
|
||||
|
||||
new Screen();
|
||||
new OffScreen();
|
||||
|
||||
frameroot = new Group.EnableSet(destroot, "frame", "Output to Frame");
|
||||
frameroot.setHorizontal();
|
||||
|
||||
new Screen(false, false);
|
||||
if (ImageTests.hasOpacityWindow) {
|
||||
new Screen(true, false);
|
||||
}
|
||||
if (ImageTests.hasShapedWindow) {
|
||||
new Screen(false, true);
|
||||
}
|
||||
if (ImageTests.hasShapedWindow && ImageTests.hasOpacityWindow) {
|
||||
new Screen(true, true);
|
||||
}
|
||||
|
||||
if (GraphicsTests.hasGraphics2D) {
|
||||
if (ImageTests.hasCompatImage) {
|
||||
compatimgdestroot =
|
||||
@@ -147,95 +129,17 @@ public abstract class Destinations extends Option.Enable {
|
||||
public abstract void setDestination(TestEnvironment env);
|
||||
|
||||
public static class Screen extends Destinations {
|
||||
|
||||
private boolean opacity;
|
||||
private boolean shaped;
|
||||
|
||||
public Screen(boolean opacity, boolean shaped) {
|
||||
super(frameroot, getDescription(opacity,shaped),
|
||||
getLongDescription(opacity,shaped), false);
|
||||
this.opacity = opacity;
|
||||
this.shaped = shaped;
|
||||
}
|
||||
|
||||
private static String getDescription(boolean opacity, boolean shaped){
|
||||
if (opacity && shaped) {
|
||||
return "shapedtransframe";
|
||||
}
|
||||
if (shaped) {
|
||||
return "shapedframe";
|
||||
}
|
||||
if (opacity) {
|
||||
return "transframe";
|
||||
}
|
||||
return "defaultframe";
|
||||
}
|
||||
|
||||
private static String getLongDescription(boolean opacity, boolean shaped){
|
||||
if (opacity && shaped) {
|
||||
return "Translucent and Shaped";
|
||||
}
|
||||
if (shaped) {
|
||||
return "Shaped";
|
||||
}
|
||||
if (opacity) {
|
||||
return "Translucent";
|
||||
}
|
||||
return "Default";
|
||||
public Screen() {
|
||||
super(destroot, "screen", "Output to Screen", false);
|
||||
}
|
||||
|
||||
public String getModifierValueName(Object val) {
|
||||
if (opacity && shaped) {
|
||||
return "Translucent and Shaped Frame";
|
||||
}
|
||||
if (shaped) {
|
||||
return "Shaped Frame";
|
||||
}
|
||||
if (opacity) {
|
||||
return "Translucent Frame";
|
||||
}
|
||||
return "Default Frame";
|
||||
return "Screen";
|
||||
}
|
||||
|
||||
public void setDestination(TestEnvironment env) {
|
||||
env.setTestImage(null);
|
||||
}
|
||||
|
||||
public void modifyTest(TestEnvironment env) {
|
||||
setDestination(env);
|
||||
Frame frame = (Frame) SwingUtilities.getWindowAncestor(env.comp);
|
||||
if (frame != null && (opacity || shaped)) {
|
||||
frame.dispose();
|
||||
frame.setUndecorated(true);
|
||||
int w = frame.getWidth();
|
||||
int h = frame.getHeight();
|
||||
if (shaped) {
|
||||
Polygon p = new Polygon();
|
||||
p.addPoint(0, 0);
|
||||
p.addPoint(w, 0);
|
||||
p.addPoint(0, h);
|
||||
p.addPoint(w, h);
|
||||
p.addPoint(0, 0);
|
||||
frame.setShape(p);
|
||||
}
|
||||
if (opacity) {
|
||||
frame.setOpacity(0.5f);
|
||||
}
|
||||
frame.setVisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void restoreTest(TestEnvironment env) {
|
||||
env.setTestImage(null);
|
||||
Frame frame = (Frame) SwingUtilities.getWindowAncestor(env.comp);
|
||||
if (frame != null && (opacity || shaped)) {
|
||||
frame.dispose();
|
||||
frame.setShape(null);
|
||||
frame.setOpacity(1);
|
||||
frame.setUndecorated(false);
|
||||
frame.setVisible(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class OffScreen extends Destinations {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@@ -40,8 +40,6 @@
|
||||
|
||||
package j2dbench;
|
||||
|
||||
import java.awt.GraphicsEnvironment;
|
||||
import java.awt.Rectangle;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
@@ -782,10 +780,7 @@ public class J2DBench {
|
||||
f.getContentPane().add(p, BorderLayout.SOUTH);
|
||||
f.pack();
|
||||
f.setLocationRelativeTo(null);
|
||||
Rectangle usable = GraphicsEnvironment.getLocalGraphicsEnvironment()
|
||||
.getMaximumWindowBounds().intersection(f.getBounds());
|
||||
f.setBounds(usable);
|
||||
f.setVisible(true);
|
||||
f.show();
|
||||
}
|
||||
|
||||
public static void runTests(boolean showresults) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@@ -53,9 +53,7 @@ import java.awt.Canvas;
|
||||
import java.awt.AlphaComposite;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.Window;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.BufferedImageOp;
|
||||
import java.awt.image.ByteLookupTable;
|
||||
@@ -81,8 +79,6 @@ import javax.swing.JComponent;
|
||||
public abstract class ImageTests extends GraphicsTests {
|
||||
public static boolean hasVolatileImage;
|
||||
public static boolean hasTransparentVolatileImage;
|
||||
public static boolean hasShapedWindow;
|
||||
public static boolean hasOpacityWindow;
|
||||
public static boolean hasCompatImage;
|
||||
|
||||
static {
|
||||
@@ -100,16 +96,6 @@ public abstract class ImageTests extends GraphicsTests {
|
||||
hasTransparentVolatileImage = true;
|
||||
} catch (NoSuchMethodError e) {
|
||||
}
|
||||
try {
|
||||
new Window(null).setShape(new Rectangle());
|
||||
hasShapedWindow = true;
|
||||
} catch (Exception e) {
|
||||
}
|
||||
try {
|
||||
new Window(null).setOpacity(0.5f);
|
||||
hasOpacityWindow = true;
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
|
||||
static Group imageroot;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2006, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@@ -184,7 +184,7 @@ abstract class InputImageTests extends InputTests {
|
||||
String klass = spi.getClass().getName();
|
||||
String format = spi.getFormatNames()[0].toLowerCase();
|
||||
String suffix = spi.getFileSuffixes()[0].toLowerCase();
|
||||
if (suffix == null || suffix.equals("")) {
|
||||
if (suffix == null || suffix.isEmpty()) {
|
||||
suffix = format;
|
||||
}
|
||||
String shortName;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2006, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@@ -143,7 +143,7 @@ abstract class OutputImageTests extends OutputTests {
|
||||
String klass = spi.getClass().getName();
|
||||
String format = spi.getFormatNames()[0].toLowerCase();
|
||||
String suffix = spi.getFileSuffixes()[0].toLowerCase();
|
||||
if (suffix == null || suffix.equals("")) {
|
||||
if (suffix == null || suffix.isEmpty()) {
|
||||
suffix = format;
|
||||
}
|
||||
String shortName;
|
||||
|
||||
@@ -68,49 +68,6 @@ class GeneralRegisterOrSp(Register):
|
||||
else:
|
||||
return self.astr("r")
|
||||
|
||||
class SVEVectorRegister(FloatRegister):
|
||||
def __str__(self):
|
||||
return self.astr("z")
|
||||
|
||||
class SVEPRegister(Register):
|
||||
def __str__(self):
|
||||
return self.astr("p")
|
||||
|
||||
def generate(self):
|
||||
self.number = random.randint(0, 15)
|
||||
return self
|
||||
|
||||
class SVEGoverningPRegister(Register):
|
||||
def __str__(self):
|
||||
return self.astr("p")
|
||||
def generate(self):
|
||||
self.number = random.randint(0, 7)
|
||||
return self
|
||||
|
||||
class RegVariant(object):
|
||||
def __init__(self, low, high):
|
||||
self.number = random.randint(low, high)
|
||||
|
||||
def astr(self):
|
||||
nameMap = {
|
||||
0: ".b",
|
||||
1: ".h",
|
||||
2: ".s",
|
||||
3: ".d",
|
||||
4: ".q"
|
||||
}
|
||||
return nameMap.get(self.number)
|
||||
|
||||
def cstr(self):
|
||||
nameMap = {
|
||||
0: "__ B",
|
||||
1: "__ H",
|
||||
2: "__ S",
|
||||
3: "__ D",
|
||||
4: "__ Q"
|
||||
}
|
||||
return nameMap.get(self.number)
|
||||
|
||||
class FloatZero(Operand):
|
||||
|
||||
def __str__(self):
|
||||
@@ -125,10 +82,7 @@ class OperandFactory:
|
||||
'w' : GeneralRegister,
|
||||
's' : FloatRegister,
|
||||
'd' : FloatRegister,
|
||||
'z' : FloatZero,
|
||||
'p' : SVEPRegister,
|
||||
'P' : SVEGoverningPRegister,
|
||||
'Z' : SVEVectorRegister}
|
||||
'z' : FloatZero}
|
||||
|
||||
@classmethod
|
||||
def create(cls, mode):
|
||||
@@ -787,9 +741,6 @@ class LoadStoreOp(InstructionWithModes):
|
||||
|
||||
regMode = FloatRegister if isFloat else GeneralRegister
|
||||
self.reg = regMode().generate()
|
||||
kindStr = Address.kindToStr(self.kind);
|
||||
if (not isFloat) and (kindStr is "pre" or kindStr is "post"):
|
||||
(self.reg.number, self.adr.base.number) = random.sample(range(31), 2)
|
||||
return self
|
||||
|
||||
def cstr(self):
|
||||
@@ -826,14 +777,6 @@ class LoadStorePairOp(InstructionWithModes):
|
||||
self.reg = [OperandFactory.create(self.mode).generate()
|
||||
for i in range(self.numRegs)]
|
||||
self.base = OperandFactory.create('x').generate()
|
||||
kindStr = Address.kindToStr(self.kind);
|
||||
if kindStr is "pre" or kindStr is "post":
|
||||
if self._name.startswith("ld"):
|
||||
(self.reg[0].number, self.reg[1].number, self.base.number) = random.sample(range(31), 3)
|
||||
if self._name.startswith("st"):
|
||||
self.base.number = random.choice(list(set(range(31)) - set([self.reg[0].number, self.reg[1].number])))
|
||||
elif self._name.startswith("ld"):
|
||||
(self.reg[0].number, self.reg[1].number) = random.sample(range(31), 2)
|
||||
return self
|
||||
|
||||
def astr(self):
|
||||
@@ -885,100 +828,6 @@ class FloatInstruction(Instruction):
|
||||
% tuple([Instruction.astr(self)] +
|
||||
[(self.reg[i].astr(self.modes[i])) for i in range(self.numRegs)]))
|
||||
|
||||
class SVEVectorOp(Instruction):
|
||||
def __init__(self, args):
|
||||
name = args[0]
|
||||
regTypes = args[1]
|
||||
regs = []
|
||||
for c in regTypes:
|
||||
regs.append(OperandFactory.create(c).generate())
|
||||
self.reg = regs
|
||||
self.numRegs = len(regs)
|
||||
if regTypes[0] != "p" and regTypes[1] == 'P':
|
||||
self._isPredicated = True
|
||||
self._merge = "/m"
|
||||
else:
|
||||
self._isPredicated = False
|
||||
self._merge =""
|
||||
|
||||
self._bitwiseop = False
|
||||
if name[0] == 'f':
|
||||
self._width = RegVariant(2, 3)
|
||||
elif not self._isPredicated and (name == "and" or name == "eor" or name == "orr"):
|
||||
self._width = RegVariant(3, 3)
|
||||
self._bitwiseop = True
|
||||
else:
|
||||
self._width = RegVariant(0, 3)
|
||||
if len(args) > 2:
|
||||
self._dnm = args[2]
|
||||
else:
|
||||
self._dnm = None
|
||||
Instruction.__init__(self, name)
|
||||
|
||||
def cstr(self):
|
||||
formatStr = "%s%s" + ''.join([", %s" for i in range(0, self.numRegs)] + [");"])
|
||||
if self._bitwiseop:
|
||||
width = []
|
||||
formatStr = "%s%s" + ''.join([", %s" for i in range(1, self.numRegs)] + [");"])
|
||||
else:
|
||||
width = [self._width.cstr()]
|
||||
return (formatStr
|
||||
% tuple(["__ sve_" + self._name + "("] +
|
||||
[str(self.reg[0])] +
|
||||
width +
|
||||
[str(self.reg[i]) for i in range(1, self.numRegs)]))
|
||||
def astr(self):
|
||||
formatStr = "%s%s" + ''.join([", %s" for i in range(1, self.numRegs)])
|
||||
if self._dnm == 'dn':
|
||||
formatStr += ", %s"
|
||||
dnReg = [str(self.reg[0]) + self._width.astr()]
|
||||
else:
|
||||
dnReg = []
|
||||
|
||||
if self._isPredicated:
|
||||
restRegs = [str(self.reg[1]) + self._merge] + dnReg + [str(self.reg[i]) + self._width.astr() for i in range(2, self.numRegs)]
|
||||
else:
|
||||
restRegs = dnReg + [str(self.reg[i]) + self._width.astr() for i in range(1, self.numRegs)]
|
||||
return (formatStr
|
||||
% tuple([Instruction.astr(self)] +
|
||||
[str(self.reg[0]) + self._width.astr()] +
|
||||
restRegs))
|
||||
def generate(self):
|
||||
return self
|
||||
|
||||
class SVEReductionOp(Instruction):
|
||||
def __init__(self, args):
|
||||
name = args[0]
|
||||
lowRegType = args[1]
|
||||
self.reg = []
|
||||
Instruction.__init__(self, name)
|
||||
self.reg.append(OperandFactory.create('s').generate())
|
||||
self.reg.append(OperandFactory.create('P').generate())
|
||||
self.reg.append(OperandFactory.create('Z').generate())
|
||||
self._width = RegVariant(lowRegType, 3)
|
||||
def cstr(self):
|
||||
return "__ sve_%s(%s, %s, %s, %s);" % (self.name(),
|
||||
str(self.reg[0]),
|
||||
self._width.cstr(),
|
||||
str(self.reg[1]),
|
||||
str(self.reg[2]))
|
||||
def astr(self):
|
||||
if self.name() == "uaddv":
|
||||
dstRegName = "d" + str(self.reg[0].number)
|
||||
else:
|
||||
dstRegName = self._width.astr()[1] + str(self.reg[0].number)
|
||||
formatStr = "%s %s, %s, %s"
|
||||
if self.name() == "fadda":
|
||||
formatStr += ", %s"
|
||||
moreReg = [dstRegName]
|
||||
else:
|
||||
moreReg = []
|
||||
return formatStr % tuple([self.name()] +
|
||||
[dstRegName] +
|
||||
[str(self.reg[1])] +
|
||||
moreReg +
|
||||
[str(self.reg[2]) + self._width.astr()])
|
||||
|
||||
class LdStSIMDOp(Instruction):
|
||||
def __init__(self, args):
|
||||
self._name, self.regnum, self.arrangement, self.addresskind = args
|
||||
@@ -1016,37 +865,6 @@ class LdStSIMDOp(Instruction):
|
||||
def aname(self):
|
||||
return self._name
|
||||
|
||||
class SHA512SIMDOp(Instruction):
|
||||
|
||||
def generate(self):
|
||||
if (self._name == 'sha512su0'):
|
||||
self.reg = [FloatRegister().generate(), FloatRegister().generate()]
|
||||
else:
|
||||
self.reg = [FloatRegister().generate(), FloatRegister().generate(),
|
||||
FloatRegister().generate()]
|
||||
return self
|
||||
|
||||
def cstr(self):
|
||||
if (self._name == 'sha512su0'):
|
||||
return (super(SHA512SIMDOp, self).cstr()
|
||||
+ ('%s, __ T2D, %s);' % (self.reg[0], self.reg[1])))
|
||||
else:
|
||||
return (super(SHA512SIMDOp, self).cstr()
|
||||
+ ('%s, __ T2D, %s, %s);' % (self.reg[0], self.reg[1], self.reg[2])))
|
||||
|
||||
def astr(self):
|
||||
if (self._name == 'sha512su0'):
|
||||
return (super(SHA512SIMDOp, self).astr()
|
||||
+ ('\t%s.2D, %s.2D' % (self.reg[0].astr("v"), self.reg[1].astr("v"))))
|
||||
elif (self._name == 'sha512su1'):
|
||||
return (super(SHA512SIMDOp, self).astr()
|
||||
+ ('\t%s.2D, %s.2D, %s.2D' % (self.reg[0].astr("v"),
|
||||
self.reg[1].astr("v"), self.reg[2].astr("v"))))
|
||||
else:
|
||||
return (super(SHA512SIMDOp, self).astr()
|
||||
+ ('\t%s, %s, %s.2D' % (self.reg[0].astr("q"),
|
||||
self.reg[1].astr("q"), self.reg[2].astr("v"))))
|
||||
|
||||
class LSEOp(Instruction):
|
||||
def __init__(self, args):
|
||||
self._name, self.asmname, self.size, self.suffix = args
|
||||
@@ -1123,8 +941,6 @@ def generate(kind, names):
|
||||
|
||||
outfile = open("aarch64ops.s", "w")
|
||||
|
||||
random.seed(0)
|
||||
|
||||
print "// BEGIN Generated code -- do not edit"
|
||||
print "// Generated by aarch64-asmtest.py"
|
||||
|
||||
@@ -1284,8 +1100,6 @@ generate(LdStSIMDOp, [["ld1", 1, "8B", Address.base_only],
|
||||
["ld4r", 4, "2S", Address.post_reg],
|
||||
])
|
||||
|
||||
generate(SHA512SIMDOp, ["sha512h", "sha512h2", "sha512su0", "sha512su1"])
|
||||
|
||||
generate(SpecialCases, [["ccmn", "__ ccmn(zr, zr, 3u, Assembler::LE);", "ccmn\txzr, xzr, #3, LE"],
|
||||
["ccmnw", "__ ccmnw(zr, zr, 5u, Assembler::EQ);", "ccmn\twzr, wzr, #5, EQ"],
|
||||
["ccmp", "__ ccmp(zr, 1, 4u, Assembler::NE);", "ccmp\txzr, 1, #4, NE"],
|
||||
@@ -1300,42 +1114,7 @@ generate(SpecialCases, [["ccmn", "__ ccmn(zr, zr, 3u, Assembler::LE);",
|
||||
["mov", "__ mov(v1, __ T2S, 1, zr);", "mov\tv1.s[1], wzr"],
|
||||
["mov", "__ mov(v1, __ T4H, 2, zr);", "mov\tv1.h[2], wzr"],
|
||||
["mov", "__ mov(v1, __ T8B, 3, zr);", "mov\tv1.b[3], wzr"],
|
||||
["ld1", "__ ld1(v31, v0, __ T2D, Address(__ post(r1, r0)));", "ld1\t{v31.2d, v0.2d}, [x1], x0"],
|
||||
# SVE instructions
|
||||
["cpy", "__ sve_cpy(z0, __ S, p0, v1);", "mov\tz0.s, p0/m, s1"],
|
||||
["inc", "__ sve_inc(r0, __ S);", "incw\tx0"],
|
||||
["dec", "__ sve_dec(r1, __ H);", "dech\tx1"],
|
||||
["lsl", "__ sve_lsl(z0, __ B, z1, 7);", "lsl\tz0.b, z1.b, #7"],
|
||||
["lsl", "__ sve_lsl(z21, __ H, z1, 15);", "lsl\tz21.h, z1.h, #15"],
|
||||
["lsl", "__ sve_lsl(z0, __ S, z1, 31);", "lsl\tz0.s, z1.s, #31"],
|
||||
["lsl", "__ sve_lsl(z0, __ D, z1, 63);", "lsl\tz0.d, z1.d, #63"],
|
||||
["lsr", "__ sve_lsr(z0, __ B, z1, 7);", "lsr\tz0.b, z1.b, #7"],
|
||||
["asr", "__ sve_asr(z0, __ H, z11, 15);", "asr\tz0.h, z11.h, #15"],
|
||||
["lsr", "__ sve_lsr(z30, __ S, z1, 31);", "lsr\tz30.s, z1.s, #31"],
|
||||
["asr", "__ sve_asr(z0, __ D, z1, 63);", "asr\tz0.d, z1.d, #63"],
|
||||
["addvl", "__ sve_addvl(sp, r0, 31);", "addvl\tsp, x0, #31"],
|
||||
["addpl", "__ sve_addpl(r1, sp, -32);", "addpl\tx1, sp, -32"],
|
||||
["cntp", "__ sve_cntp(r8, __ B, p0, p1);", "cntp\tx8, p0, p1.b"],
|
||||
["dup", "__ sve_dup(z0, __ B, 127);", "dup\tz0.b, 127"],
|
||||
["dup", "__ sve_dup(z1, __ H, -128);", "dup\tz1.h, -128"],
|
||||
["dup", "__ sve_dup(z2, __ S, 32512);", "dup\tz2.s, 32512"],
|
||||
["dup", "__ sve_dup(z7, __ D, -32768);", "dup\tz7.d, -32768"],
|
||||
["ld1b", "__ sve_ld1b(z0, __ B, p0, Address(sp));", "ld1b\t{z0.b}, p0/z, [sp]"],
|
||||
["ld1h", "__ sve_ld1h(z10, __ H, p1, Address(sp, -8));", "ld1h\t{z10.h}, p1/z, [sp, #-8, MUL VL]"],
|
||||
["ld1w", "__ sve_ld1w(z20, __ S, p2, Address(r0, 7));", "ld1w\t{z20.s}, p2/z, [x0, #7, MUL VL]"],
|
||||
["ld1b", "__ sve_ld1b(z30, __ B, p3, Address(sp, r8));", "ld1b\t{z30.b}, p3/z, [sp, x8]"],
|
||||
["ld1w", "__ sve_ld1w(z0, __ S, p4, Address(sp, r28));", "ld1w\t{z0.s}, p4/z, [sp, x28, LSL #2]"],
|
||||
["ld1d", "__ sve_ld1d(z11, __ D, p5, Address(r0, r1));", "ld1d\t{z11.d}, p5/z, [x0, x1, LSL #3]"],
|
||||
["st1b", "__ sve_st1b(z22, __ B, p6, Address(sp));", "st1b\t{z22.b}, p6, [sp]"],
|
||||
["st1b", "__ sve_st1b(z31, __ B, p7, Address(sp, -8));", "st1b\t{z31.b}, p7, [sp, #-8, MUL VL]"],
|
||||
["st1w", "__ sve_st1w(z0, __ S, p1, Address(r0, 7));", "st1w\t{z0.s}, p1, [x0, #7, MUL VL]"],
|
||||
["st1b", "__ sve_st1b(z0, __ B, p2, Address(sp, r1));", "st1b\t{z0.b}, p2, [sp, x1]"],
|
||||
["st1h", "__ sve_st1h(z0, __ H, p3, Address(sp, r8));", "st1h\t{z0.h}, p3, [sp, x8, LSL #1]"],
|
||||
["st1d", "__ sve_st1d(z0, __ D, p4, Address(r0, r18));", "st1d\t{z0.d}, p4, [x0, x18, LSL #3]"],
|
||||
["ldr", "__ sve_ldr(z0, Address(sp));", "ldr\tz0, [sp]"],
|
||||
["ldr", "__ sve_ldr(z31, Address(sp, -256));", "ldr\tz31, [sp, #-256, MUL VL]"],
|
||||
["str", "__ sve_str(z8, Address(r8, 255));", "str\tz8, [x8, #255, MUL VL]"],
|
||||
])
|
||||
["ld1", "__ ld1(v31, v0, __ T2D, Address(__ post(r1, r0)));", "ld1\t{v31.2d, v0.2d}, [x1], x0"]])
|
||||
|
||||
print "\n// FloatImmediateOp"
|
||||
for float in ("2.0", "2.125", "4.0", "4.25", "8.0", "8.5", "16.0", "17.0", "0.125",
|
||||
@@ -1360,49 +1139,6 @@ for size in ("x", "w"):
|
||||
["ldumin", "ldumin", size, suffix],
|
||||
["ldumax", "ldumax", size, suffix]]);
|
||||
|
||||
generate(SVEVectorOp, [["add", "ZZZ"],
|
||||
["sub", "ZZZ"],
|
||||
["fadd", "ZZZ"],
|
||||
["fmul", "ZZZ"],
|
||||
["fsub", "ZZZ"],
|
||||
["abs", "ZPZ"],
|
||||
["add", "ZPZ", "dn"],
|
||||
["asr", "ZPZ", "dn"],
|
||||
["cnt", "ZPZ"],
|
||||
["lsl", "ZPZ", "dn"],
|
||||
["lsr", "ZPZ", "dn"],
|
||||
["mul", "ZPZ", "dn"],
|
||||
["neg", "ZPZ"],
|
||||
["not", "ZPZ"],
|
||||
["smax", "ZPZ", "dn"],
|
||||
["smin", "ZPZ", "dn"],
|
||||
["sub", "ZPZ", "dn"],
|
||||
["fabs", "ZPZ"],
|
||||
["fadd", "ZPZ", "dn"],
|
||||
["fdiv", "ZPZ", "dn"],
|
||||
["fmax", "ZPZ", "dn"],
|
||||
["fmin", "ZPZ", "dn"],
|
||||
["fmul", "ZPZ", "dn"],
|
||||
["fneg", "ZPZ"],
|
||||
["frintm", "ZPZ"],
|
||||
["frintn", "ZPZ"],
|
||||
["frintp", "ZPZ"],
|
||||
["fsqrt", "ZPZ"],
|
||||
["fsub", "ZPZ", "dn"],
|
||||
["fmla", "ZPZZ"],
|
||||
["fmls", "ZPZZ"],
|
||||
["fnmla", "ZPZZ"],
|
||||
["fnmls", "ZPZZ"],
|
||||
["mla", "ZPZZ"],
|
||||
["mls", "ZPZZ"],
|
||||
["and", "ZZZ"],
|
||||
["eor", "ZZZ"],
|
||||
["orr", "ZZZ"],
|
||||
])
|
||||
|
||||
generate(SVEReductionOp, [["andv", 0], ["orv", 0], ["eorv", 0], ["smaxv", 0], ["sminv", 0],
|
||||
["fminv", 2], ["fmaxv", 2], ["fadda", 2], ["uaddv", 0]])
|
||||
|
||||
print "\n __ bind(forth);"
|
||||
outfile.write("forth:\n")
|
||||
|
||||
@@ -1411,8 +1147,8 @@ outfile.close()
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
# compile for sve with 8.1 and sha2 because of lse atomics and sha512 crypto extension.
|
||||
subprocess.check_call([AARCH64_AS, "-march=armv8.1-a+sha2+sve", "aarch64ops.s", "-o", "aarch64ops.o"])
|
||||
# compile for 8.1 because of lse atomics
|
||||
subprocess.check_call([AARCH64_AS, "-march=armv8.1-a", "aarch64ops.s", "-o", "aarch64ops.o"])
|
||||
|
||||
print
|
||||
print "/*",
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,767 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
// Copyright (c) 2020, Arm Limited. All rights reserved.
|
||||
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
//
|
||||
// This code is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU General Public License version 2 only, as
|
||||
// published by the Free Software Foundation.
|
||||
//
|
||||
// This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
// version 2 for more details (a copy is included in the LICENSE file that
|
||||
// accompanied this code).
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License version
|
||||
// 2 along with this work; if not, write to the Free Software Foundation,
|
||||
// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
//
|
||||
// Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
// or visit www.oracle.com if you need additional information or have any
|
||||
// questions.
|
||||
//
|
||||
//
|
||||
|
||||
dnl Generate the warning
|
||||
// This file is automatically generated by running "m4 aarch64_sve_ad.m4". Do not edit ----
|
||||
dnl
|
||||
|
||||
// AArch64 SVE Architecture Description File
|
||||
|
||||
dnl
|
||||
dnl OPERAND_VMEMORYA_IMMEDIATE_OFFSET($1, $2, $3 )
|
||||
dnl OPERAND_VMEMORYA_IMMEDIATE_OFFSET(imm_type_abbr, imm_type, imm_len)
|
||||
define(`OPERAND_VMEMORYA_IMMEDIATE_OFFSET', `
|
||||
operand vmemA_imm$1Offset$3()
|
||||
%{
|
||||
predicate(Address::offset_ok_for_sve_immed(n->get_$2(), $3,
|
||||
Matcher::scalable_vector_reg_size(T_BYTE)));
|
||||
match(Con$1);
|
||||
|
||||
op_cost(0);
|
||||
format %{ %}
|
||||
interface(CONST_INTER);
|
||||
%}')
|
||||
dnl
|
||||
// 4 bit signed offset -- for predicated load/store
|
||||
OPERAND_VMEMORYA_IMMEDIATE_OFFSET(I, int, 4)
|
||||
OPERAND_VMEMORYA_IMMEDIATE_OFFSET(L, long, 4)
|
||||
dnl
|
||||
dnl OPERAND_VMEMORYA_INDIRECT_OFFSET($1, $2 )
|
||||
dnl OPERAND_VMEMORYA_INDIRECT_OFFSET(imm_type_abbr, imm_len)
|
||||
define(`OPERAND_VMEMORYA_INDIRECT_OFFSET', `
|
||||
operand vmemA_indOff$1$2(iRegP reg, vmemA_imm$1Offset$2 off)
|
||||
%{
|
||||
constraint(ALLOC_IN_RC(ptr_reg));
|
||||
match(AddP reg off);
|
||||
op_cost(0);
|
||||
format %{ "[$reg, $off, MUL VL]" %}
|
||||
interface(MEMORY_INTER) %{
|
||||
base($reg);
|
||||
`index'(0xffffffff);
|
||||
scale(0x0);
|
||||
disp($off);
|
||||
%}
|
||||
%}')
|
||||
dnl
|
||||
OPERAND_VMEMORYA_INDIRECT_OFFSET(I, 4)
|
||||
OPERAND_VMEMORYA_INDIRECT_OFFSET(L, 4)
|
||||
|
||||
opclass vmemA(indirect, vmemA_indOffI4, vmemA_indOffL4);
|
||||
|
||||
source_hpp %{
|
||||
bool op_sve_supported(int opcode);
|
||||
%}
|
||||
|
||||
source %{
|
||||
|
||||
static inline BasicType vector_element_basic_type(const MachNode* n) {
|
||||
const TypeVect* vt = n->bottom_type()->is_vect();
|
||||
return vt->element_basic_type();
|
||||
}
|
||||
|
||||
static inline BasicType vector_element_basic_type(const MachNode* use, const MachOper* opnd) {
|
||||
int def_idx = use->operand_index(opnd);
|
||||
Node* def = use->in(def_idx);
|
||||
const TypeVect* vt = def->bottom_type()->is_vect();
|
||||
return vt->element_basic_type();
|
||||
}
|
||||
|
||||
typedef void (C2_MacroAssembler::* sve_mem_insn_predicate)(FloatRegister Rt, Assembler::SIMD_RegVariant T,
|
||||
PRegister Pg, const Address &adr);
|
||||
|
||||
// Predicated load/store, with optional ptrue to all elements of given predicate register.
|
||||
static void loadStoreA_predicate(C2_MacroAssembler masm, bool is_store,
|
||||
FloatRegister reg, PRegister pg, BasicType bt,
|
||||
int opcode, Register base, int index, int size, int disp) {
|
||||
sve_mem_insn_predicate insn;
|
||||
Assembler::SIMD_RegVariant type;
|
||||
int esize = type2aelembytes(bt);
|
||||
if (index == -1) {
|
||||
assert(size == 0, "unsupported address mode: scale size = %d", size);
|
||||
switch(esize) {
|
||||
case 1:
|
||||
insn = is_store ? &C2_MacroAssembler::sve_st1b : &C2_MacroAssembler::sve_ld1b;
|
||||
type = Assembler::B;
|
||||
break;
|
||||
case 2:
|
||||
insn = is_store ? &C2_MacroAssembler::sve_st1h : &C2_MacroAssembler::sve_ld1h;
|
||||
type = Assembler::H;
|
||||
break;
|
||||
case 4:
|
||||
insn = is_store ? &C2_MacroAssembler::sve_st1w : &C2_MacroAssembler::sve_ld1w;
|
||||
type = Assembler::S;
|
||||
break;
|
||||
case 8:
|
||||
insn = is_store ? &C2_MacroAssembler::sve_st1d : &C2_MacroAssembler::sve_ld1d;
|
||||
type = Assembler::D;
|
||||
break;
|
||||
default:
|
||||
assert(false, "unsupported");
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
(masm.*insn)(reg, type, pg, Address(base, disp / Matcher::scalable_vector_reg_size(T_BYTE)));
|
||||
} else {
|
||||
assert(false, "unimplemented");
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
}
|
||||
|
||||
bool op_sve_supported(int opcode) {
|
||||
switch (opcode) {
|
||||
case Op_MulAddVS2VI:
|
||||
// No multiply reduction instructions
|
||||
case Op_MulReductionVD:
|
||||
case Op_MulReductionVF:
|
||||
case Op_MulReductionVI:
|
||||
case Op_MulReductionVL:
|
||||
// Others
|
||||
case Op_Extract:
|
||||
case Op_ExtractB:
|
||||
case Op_ExtractC:
|
||||
case Op_ExtractD:
|
||||
case Op_ExtractF:
|
||||
case Op_ExtractI:
|
||||
case Op_ExtractL:
|
||||
case Op_ExtractS:
|
||||
case Op_ExtractUB:
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
%}
|
||||
|
||||
definitions %{
|
||||
int_def SVE_COST (200, 200);
|
||||
%}
|
||||
|
||||
|
||||
dnl
|
||||
dnl ELEMENT_SHORT_CHART($1, $2)
|
||||
dnl ELEMENT_SHORT_CHART(etype, node)
|
||||
define(`ELEMENT_SHORT_CHAR',`ifelse(`$1', `T_SHORT',
|
||||
`($2->bottom_type()->is_vect()->element_basic_type() == T_SHORT ||
|
||||
($2->bottom_type()->is_vect()->element_basic_type() == T_CHAR))',
|
||||
`($2->bottom_type()->is_vect()->element_basic_type() == $1)')')
|
||||
dnl
|
||||
|
||||
// All SVE instructions
|
||||
|
||||
// vector load/store
|
||||
|
||||
// Use predicated vector load/store
|
||||
instruct loadV(vReg dst, vmemA mem) %{
|
||||
predicate(UseSVE > 0 && n->as_LoadVector()->memory_size() >= 16);
|
||||
match(Set dst (LoadVector mem));
|
||||
ins_cost(SVE_COST);
|
||||
format %{ "sve_ldr $dst, $mem\t # vector (sve)" %}
|
||||
ins_encode %{
|
||||
FloatRegister dst_reg = as_FloatRegister($dst$$reg);
|
||||
loadStoreA_predicate(C2_MacroAssembler(&cbuf), false, dst_reg, ptrue,
|
||||
vector_element_basic_type(this), $mem->opcode(),
|
||||
as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp);
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
instruct storeV(vReg src, vmemA mem) %{
|
||||
predicate(UseSVE > 0 && n->as_StoreVector()->memory_size() >= 16);
|
||||
match(Set mem (StoreVector mem src));
|
||||
ins_cost(SVE_COST);
|
||||
format %{ "sve_str $mem, $src\t # vector (sve)" %}
|
||||
ins_encode %{
|
||||
FloatRegister src_reg = as_FloatRegister($src$$reg);
|
||||
loadStoreA_predicate(C2_MacroAssembler(&cbuf), true, src_reg, ptrue,
|
||||
vector_element_basic_type(this, $src), $mem->opcode(),
|
||||
as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp);
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
dnl
|
||||
dnl UNARY_OP_TRUE_PREDICATE_ETYPE($1, $2, $3, $4, $5, %6 )
|
||||
dnl UNARY_OP_TRUE_PREDICATE_ETYPE(insn_name, op_name, element_type, size, min_vec_len, insn)
|
||||
define(`UNARY_OP_TRUE_PREDICATE_ETYPE', `
|
||||
instruct $1(vReg dst, vReg src) %{
|
||||
predicate(UseSVE > 0 && n->as_Vector()->length() >= $5 &&
|
||||
n->bottom_type()->is_vect()->element_basic_type() == $3);
|
||||
match(Set dst ($2 src));
|
||||
ins_cost(SVE_COST);
|
||||
format %{ "$6 $dst, $src\t# vector (sve) ($4)" %}
|
||||
ins_encode %{
|
||||
__ $6(as_FloatRegister($dst$$reg), __ $4,
|
||||
ptrue, as_FloatRegister($src$$reg));
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}')dnl
|
||||
|
||||
// vector abs
|
||||
UNARY_OP_TRUE_PREDICATE_ETYPE(vabsB, AbsVB, T_BYTE, B, 16, sve_abs)
|
||||
UNARY_OP_TRUE_PREDICATE_ETYPE(vabsS, AbsVS, T_SHORT, H, 8, sve_abs)
|
||||
UNARY_OP_TRUE_PREDICATE_ETYPE(vabsI, AbsVI, T_INT, S, 4, sve_abs)
|
||||
UNARY_OP_TRUE_PREDICATE_ETYPE(vabsL, AbsVL, T_LONG, D, 2, sve_abs)
|
||||
UNARY_OP_TRUE_PREDICATE_ETYPE(vabsF, AbsVF, T_FLOAT, S, 4, sve_fabs)
|
||||
UNARY_OP_TRUE_PREDICATE_ETYPE(vabsD, AbsVD, T_DOUBLE, D, 2, sve_fabs)
|
||||
dnl
|
||||
dnl BINARY_OP_UNPREDICATED($1, $2 $3, $4 $5 )
|
||||
dnl BINARY_OP_UNPREDICATED(insn_name, op_name, size, min_vec_len, insn)
|
||||
define(`BINARY_OP_UNPREDICATED', `
|
||||
instruct $1(vReg dst, vReg src1, vReg src2) %{
|
||||
predicate(UseSVE > 0 && n->as_Vector()->length() >= $4);
|
||||
match(Set dst ($2 src1 src2));
|
||||
ins_cost(SVE_COST);
|
||||
format %{ "$5 $dst, $src1, $src2\t # vector (sve) ($3)" %}
|
||||
ins_encode %{
|
||||
__ $5(as_FloatRegister($dst$$reg), __ $3,
|
||||
as_FloatRegister($src1$$reg),
|
||||
as_FloatRegister($src2$$reg));
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}')dnl
|
||||
|
||||
// vector add
|
||||
BINARY_OP_UNPREDICATED(vaddB, AddVB, B, 16, sve_add)
|
||||
BINARY_OP_UNPREDICATED(vaddS, AddVS, H, 8, sve_add)
|
||||
BINARY_OP_UNPREDICATED(vaddI, AddVI, S, 4, sve_add)
|
||||
BINARY_OP_UNPREDICATED(vaddL, AddVL, D, 2, sve_add)
|
||||
BINARY_OP_UNPREDICATED(vaddF, AddVF, S, 4, sve_fadd)
|
||||
BINARY_OP_UNPREDICATED(vaddD, AddVD, D, 2, sve_fadd)
|
||||
dnl
|
||||
dnl BINARY_OP_UNSIZED($1, $2, $3, $4 )
|
||||
dnl BINARY_OP_UNSIZED(insn_name, op_name, min_vec_len, insn)
|
||||
define(`BINARY_OP_UNSIZED', `
|
||||
instruct $1(vReg dst, vReg src1, vReg src2) %{
|
||||
predicate(UseSVE > 0 && n->as_Vector()->length_in_bytes() >= $3);
|
||||
match(Set dst ($2 src1 src2));
|
||||
ins_cost(SVE_COST);
|
||||
format %{ "$4 $dst, $src1, $src2\t# vector (sve)" %}
|
||||
ins_encode %{
|
||||
__ $4(as_FloatRegister($dst$$reg),
|
||||
as_FloatRegister($src1$$reg),
|
||||
as_FloatRegister($src2$$reg));
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}')dnl
|
||||
|
||||
// vector and
|
||||
BINARY_OP_UNSIZED(vand, AndV, 16, sve_and)
|
||||
|
||||
// vector or
|
||||
BINARY_OP_UNSIZED(vor, OrV, 16, sve_orr)
|
||||
|
||||
// vector xor
|
||||
BINARY_OP_UNSIZED(vxor, XorV, 16, sve_eor)
|
||||
dnl
|
||||
dnl VDIVF($1, $2 , $3 )
|
||||
dnl VDIVF(name_suffix, size, min_vec_len)
|
||||
define(`VDIVF', `
|
||||
instruct vdiv$1(vReg dst_src1, vReg src2) %{
|
||||
predicate(UseSVE > 0 && n->as_Vector()->length() >= $3);
|
||||
match(Set dst_src1 (DivV$1 dst_src1 src2));
|
||||
ins_cost(SVE_COST);
|
||||
format %{ "sve_fdiv $dst_src1, $dst_src1, $src2\t# vector (sve) ($2)" %}
|
||||
ins_encode %{
|
||||
__ sve_fdiv(as_FloatRegister($dst_src1$$reg), __ $2,
|
||||
ptrue, as_FloatRegister($src2$$reg));
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}')dnl
|
||||
|
||||
// vector float div
|
||||
VDIVF(F, S, 4)
|
||||
VDIVF(D, D, 2)
|
||||
|
||||
dnl
|
||||
dnl BINARY_OP_TRUE_PREDICATE_ETYPE($1, $2, $3, $4, $5, $6 )
|
||||
dnl BINARY_OP_TRUE_PREDICATE_ETYPE(insn_name, op_name, element_type, size, min_vec_len, insn)
|
||||
define(`BINARY_OP_TRUE_PREDICATE_ETYPE', `
|
||||
instruct $1(vReg dst_src1, vReg src2) %{
|
||||
predicate(UseSVE > 0 && n->as_Vector()->length() >= $5 &&
|
||||
n->bottom_type()->is_vect()->element_basic_type() == $3);
|
||||
match(Set dst_src1 ($2 dst_src1 src2));
|
||||
ins_cost(SVE_COST);
|
||||
format %{ "$6 $dst_src1, $dst_src1, $src2\t # vector (sve) ($4)" %}
|
||||
ins_encode %{
|
||||
__ $6(as_FloatRegister($dst_src1$$reg), __ $4,
|
||||
ptrue, as_FloatRegister($src2$$reg));
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}')dnl
|
||||
dnl
|
||||
// vector max
|
||||
BINARY_OP_TRUE_PREDICATE_ETYPE(vmaxF, MaxV, T_FLOAT, S, 4, sve_fmax)
|
||||
BINARY_OP_TRUE_PREDICATE_ETYPE(vmaxD, MaxV, T_DOUBLE, D, 2, sve_fmax)
|
||||
BINARY_OP_TRUE_PREDICATE_ETYPE(vminF, MinV, T_FLOAT, S, 4, sve_fmin)
|
||||
BINARY_OP_TRUE_PREDICATE_ETYPE(vminD, MinV, T_DOUBLE, D, 2, sve_fmin)
|
||||
|
||||
dnl
|
||||
dnl VFMLA($1 $2 $3 )
|
||||
dnl VFMLA(name_suffix, size, min_vec_len)
|
||||
define(`VFMLA', `
|
||||
// dst_src1 = dst_src1 + src2 * src3
|
||||
instruct vfmla$1(vReg dst_src1, vReg src2, vReg src3) %{
|
||||
predicate(UseFMA && UseSVE > 0 && n->as_Vector()->length() >= $3);
|
||||
match(Set dst_src1 (FmaV$1 dst_src1 (Binary src2 src3)));
|
||||
ins_cost(SVE_COST);
|
||||
format %{ "sve_fmla $dst_src1, $src2, $src3\t # vector (sve) ($2)" %}
|
||||
ins_encode %{
|
||||
__ sve_fmla(as_FloatRegister($dst_src1$$reg), __ $2,
|
||||
ptrue, as_FloatRegister($src2$$reg), as_FloatRegister($src3$$reg));
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}')dnl
|
||||
dnl
|
||||
// vector fmla
|
||||
VFMLA(F, S, 4)
|
||||
VFMLA(D, D, 2)
|
||||
|
||||
dnl
|
||||
dnl VFMLS($1 $2 $3 )
|
||||
dnl VFMLS(name_suffix, size, min_vec_len)
|
||||
define(`VFMLS', `
|
||||
// dst_src1 = dst_src1 + -src2 * src3
|
||||
// dst_src1 = dst_src1 + src2 * -src3
|
||||
instruct vfmls$1(vReg dst_src1, vReg src2, vReg src3) %{
|
||||
predicate(UseFMA && UseSVE > 0 && n->as_Vector()->length() >= $3);
|
||||
match(Set dst_src1 (FmaV$1 dst_src1 (Binary (NegV$1 src2) src3)));
|
||||
match(Set dst_src1 (FmaV$1 dst_src1 (Binary src2 (NegV$1 src3))));
|
||||
ins_cost(SVE_COST);
|
||||
format %{ "sve_fmls $dst_src1, $src2, $src3\t # vector (sve) ($2)" %}
|
||||
ins_encode %{
|
||||
__ sve_fmls(as_FloatRegister($dst_src1$$reg), __ $2,
|
||||
ptrue, as_FloatRegister($src2$$reg), as_FloatRegister($src3$$reg));
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}')dnl
|
||||
dnl
|
||||
// vector fmls
|
||||
VFMLS(F, S, 4)
|
||||
VFMLS(D, D, 2)
|
||||
|
||||
dnl
|
||||
dnl VFNMLA($1 $2 $3 )
|
||||
dnl VFNMLA(name_suffix, size, min_vec_len)
|
||||
define(`VFNMLA', `
|
||||
// dst_src1 = -dst_src1 + -src2 * src3
|
||||
// dst_src1 = -dst_src1 + src2 * -src3
|
||||
instruct vfnmla$1(vReg dst_src1, vReg src2, vReg src3) %{
|
||||
predicate(UseFMA && UseSVE > 0 && n->as_Vector()->length() >= $3);
|
||||
match(Set dst_src1 (FmaV$1 (NegV$1 dst_src1) (Binary (NegV$1 src2) src3)));
|
||||
match(Set dst_src1 (FmaV$1 (NegV$1 dst_src1) (Binary src2 (NegV$1 src3))));
|
||||
ins_cost(SVE_COST);
|
||||
format %{ "sve_fnmla $dst_src1, $src2, $src3\t # vector (sve) ($2)" %}
|
||||
ins_encode %{
|
||||
__ sve_fnmla(as_FloatRegister($dst_src1$$reg), __ $2,
|
||||
ptrue, as_FloatRegister($src2$$reg), as_FloatRegister($src3$$reg));
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}')dnl
|
||||
dnl
|
||||
// vector fnmla
|
||||
VFNMLA(F, S, 4)
|
||||
VFNMLA(D, D, 2)
|
||||
|
||||
dnl
|
||||
dnl VFNMLS($1 $2 $3 )
|
||||
dnl VFNMLS(name_suffix, size, min_vec_len)
|
||||
define(`VFNMLS', `
|
||||
// dst_src1 = -dst_src1 + src2 * src3
|
||||
instruct vfnmls$1(vReg dst_src1, vReg src2, vReg src3) %{
|
||||
predicate(UseFMA && UseSVE > 0 && n->as_Vector()->length() >= $3);
|
||||
match(Set dst_src1 (FmaV$1 (NegV$1 dst_src1) (Binary src2 src3)));
|
||||
ins_cost(SVE_COST);
|
||||
format %{ "sve_fnmls $dst_src1, $src2, $src3\t # vector (sve) ($2)" %}
|
||||
ins_encode %{
|
||||
__ sve_fnmls(as_FloatRegister($dst_src1$$reg), __ $2,
|
||||
ptrue, as_FloatRegister($src2$$reg), as_FloatRegister($src3$$reg));
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}')dnl
|
||||
dnl
|
||||
// vector fnmls
|
||||
VFNMLS(F, S, 4)
|
||||
VFNMLS(D, D, 2)
|
||||
|
||||
dnl
|
||||
dnl VMLA($1 $2 $3 )
|
||||
dnl VMLA(name_suffix, size, min_vec_len)
|
||||
define(`VMLA', `
|
||||
// dst_src1 = dst_src1 + src2 * src3
|
||||
instruct vmla$1(vReg dst_src1, vReg src2, vReg src3)
|
||||
%{
|
||||
predicate(UseSVE > 0 && n->as_Vector()->length() >= $3);
|
||||
match(Set dst_src1 (AddV$1 dst_src1 (MulV$1 src2 src3)));
|
||||
ins_cost(SVE_COST);
|
||||
format %{ "sve_mla $dst_src1, src2, src3\t # vector (sve) ($2)" %}
|
||||
ins_encode %{
|
||||
__ sve_mla(as_FloatRegister($dst_src1$$reg), __ $2,
|
||||
ptrue, as_FloatRegister($src2$$reg), as_FloatRegister($src3$$reg));
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}')dnl
|
||||
dnl
|
||||
// vector mla
|
||||
VMLA(B, B, 16)
|
||||
VMLA(S, H, 8)
|
||||
VMLA(I, S, 4)
|
||||
VMLA(L, D, 2)
|
||||
|
||||
dnl
|
||||
dnl VMLS($1 $2 $3 )
|
||||
dnl VMLS(name_suffix, size, min_vec_len)
|
||||
define(`VMLS', `
|
||||
// dst_src1 = dst_src1 - src2 * src3
|
||||
instruct vmls$1(vReg dst_src1, vReg src2, vReg src3)
|
||||
%{
|
||||
predicate(UseSVE > 0 && n->as_Vector()->length() >= $3);
|
||||
match(Set dst_src1 (SubV$1 dst_src1 (MulV$1 src2 src3)));
|
||||
ins_cost(SVE_COST);
|
||||
format %{ "sve_mls $dst_src1, src2, src3\t # vector (sve) ($2)" %}
|
||||
ins_encode %{
|
||||
__ sve_mls(as_FloatRegister($dst_src1$$reg), __ $2,
|
||||
ptrue, as_FloatRegister($src2$$reg), as_FloatRegister($src3$$reg));
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}')dnl
|
||||
dnl
|
||||
// vector mls
|
||||
VMLS(B, B, 16)
|
||||
VMLS(S, H, 8)
|
||||
VMLS(I, S, 4)
|
||||
VMLS(L, D, 2)
|
||||
|
||||
dnl
|
||||
dnl BINARY_OP_TRUE_PREDICATE($1, $2, $3, $4, $5 )
|
||||
dnl BINARY_OP_TRUE_PREDICATE(insn_name, op_name, size, min_vec_len, insn)
|
||||
define(`BINARY_OP_TRUE_PREDICATE', `
|
||||
instruct $1(vReg dst_src1, vReg src2) %{
|
||||
predicate(UseSVE > 0 && n->as_Vector()->length() >= $4);
|
||||
match(Set dst_src1 ($2 dst_src1 src2));
|
||||
ins_cost(SVE_COST);
|
||||
format %{ "$5 $dst_src1, $dst_src1, $src2\t # vector (sve) ($3)" %}
|
||||
ins_encode %{
|
||||
__ $5(as_FloatRegister($dst_src1$$reg), __ $3,
|
||||
ptrue, as_FloatRegister($src2$$reg));
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}')dnl
|
||||
|
||||
// vector mul
|
||||
BINARY_OP_TRUE_PREDICATE(vmulB, MulVB, B, 16, sve_mul)
|
||||
BINARY_OP_TRUE_PREDICATE(vmulS, MulVS, H, 8, sve_mul)
|
||||
BINARY_OP_TRUE_PREDICATE(vmulI, MulVI, S, 4, sve_mul)
|
||||
BINARY_OP_TRUE_PREDICATE(vmulL, MulVL, D, 2, sve_mul)
|
||||
BINARY_OP_UNPREDICATED(vmulF, MulVF, S, 4, sve_fmul)
|
||||
BINARY_OP_UNPREDICATED(vmulD, MulVD, D, 2, sve_fmul)
|
||||
|
||||
dnl
|
||||
dnl UNARY_OP_TRUE_PREDICATE($1, $2, $3, $4, $5 )
|
||||
dnl UNARY_OP_TRUE_PREDICATE(insn_name, op_name, size, min_vec_bytes, insn)
|
||||
define(`UNARY_OP_TRUE_PREDICATE', `
|
||||
instruct $1(vReg dst, vReg src) %{
|
||||
predicate(UseSVE > 0 && n->as_Vector()->length_in_bytes() >= $4);
|
||||
match(Set dst ($2 src));
|
||||
ins_cost(SVE_COST);
|
||||
format %{ "$5 $dst, $src\t# vector (sve) ($3)" %}
|
||||
ins_encode %{
|
||||
__ $5(as_FloatRegister($dst$$reg), __ $3,
|
||||
ptrue, as_FloatRegister($src$$reg));
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}')dnl
|
||||
dnl
|
||||
// vector fneg
|
||||
UNARY_OP_TRUE_PREDICATE(vnegF, NegVF, S, 16, sve_fneg)
|
||||
UNARY_OP_TRUE_PREDICATE(vnegD, NegVD, D, 16, sve_fneg)
|
||||
|
||||
// popcount vector
|
||||
|
||||
instruct vpopcountI(vReg dst, vReg src) %{
|
||||
predicate(UseSVE > 0 && n->as_Vector()->length() >= 4);
|
||||
match(Set dst (PopCountVI src));
|
||||
format %{ "sve_cnt $dst, $src\t# vector (sve) (S)\n\t" %}
|
||||
ins_encode %{
|
||||
__ sve_cnt(as_FloatRegister($dst$$reg), __ S, ptrue, as_FloatRegister($src$$reg));
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
dnl
|
||||
dnl REDUCE_ADD($1, $2, $3, $4, $5, $6, $7 )
|
||||
dnl REDUCE_ADD(insn_name, op_name, reg_dst, reg_src, size, elem_type, insn1)
|
||||
define(`REDUCE_ADD', `
|
||||
instruct $1($3 dst, $4 src1, vReg src2, vRegD tmp) %{
|
||||
predicate(UseSVE > 0 && n->in(2)->bottom_type()->is_vect()->length_in_bytes() >= 16 &&
|
||||
ELEMENT_SHORT_CHAR($6, n->in(2)));
|
||||
match(Set dst ($2 src1 src2));
|
||||
effect(TEMP_DEF dst, TEMP tmp);
|
||||
ins_cost(SVE_COST);
|
||||
format %{ "sve_uaddv $tmp, $src2\t# vector (sve) ($5)\n\t"
|
||||
"umov $dst, $tmp, $5, 0\n\t"
|
||||
"$7 $dst, $dst, $src1\t # add reduction $5" %}
|
||||
ins_encode %{
|
||||
__ sve_uaddv(as_FloatRegister($tmp$$reg), __ $5,
|
||||
ptrue, as_FloatRegister($src2$$reg));
|
||||
__ umov($dst$$Register, as_FloatRegister($tmp$$reg), __ $5, 0);
|
||||
__ $7($dst$$Register, $dst$$Register, $src1$$Register);
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}')dnl
|
||||
dnl
|
||||
dnl REDUCE_ADDF($1, $2, $3, $4 )
|
||||
dnl REDUCE_ADDF(insn_name, op_name, reg_dst, size)
|
||||
define(`REDUCE_ADDF', `
|
||||
instruct $1($3 src1_dst, vReg src2) %{
|
||||
predicate(UseSVE > 0 && n->in(2)->bottom_type()->is_vect()->length_in_bytes() >= 16);
|
||||
match(Set src1_dst ($2 src1_dst src2));
|
||||
ins_cost(SVE_COST);
|
||||
format %{ "sve_fadda $src1_dst, $src1_dst, $src2\t# vector (sve) ($4)" %}
|
||||
ins_encode %{
|
||||
__ sve_fadda(as_FloatRegister($src1_dst$$reg), __ $4,
|
||||
ptrue, as_FloatRegister($src2$$reg));
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}')dnl
|
||||
dnl
|
||||
// vector add reduction
|
||||
REDUCE_ADD(reduce_addI, AddReductionVI, iRegINoSp, iRegIorL2I, S, T_INT, addw)
|
||||
REDUCE_ADD(reduce_addL, AddReductionVL, iRegLNoSp, iRegL, D, T_LONG, add)
|
||||
REDUCE_ADDF(reduce_addF, AddReductionVF, vRegF, S)
|
||||
REDUCE_ADDF(reduce_addD, AddReductionVD, vRegD, D)
|
||||
|
||||
dnl
|
||||
dnl REDUCE_FMINMAX($1, $2, $3, $4, $5 )
|
||||
dnl REDUCE_FMINMAX(min_max, name_suffix, element_type, size, reg_src_dst)
|
||||
define(`REDUCE_FMINMAX', `
|
||||
instruct reduce_$1$2($5 dst, $5 src1, vReg src2) %{
|
||||
predicate(UseSVE > 0 && n->in(2)->bottom_type()->is_vect()->element_basic_type() == $3 &&
|
||||
n->in(2)->bottom_type()->is_vect()->length_in_bytes() >= 16);
|
||||
match(Set dst (translit($1, `m', `M')ReductionV src1 src2));
|
||||
ins_cost(INSN_COST);
|
||||
effect(TEMP_DEF dst);
|
||||
format %{ "sve_f$1v $dst, $src2 # vector (sve) (S)\n\t"
|
||||
"f$1s $dst, $dst, $src1\t # $1 reduction $2" %}
|
||||
ins_encode %{
|
||||
__ sve_f$1v(as_FloatRegister($dst$$reg), __ $4,
|
||||
ptrue, as_FloatRegister($src2$$reg));
|
||||
__ f`$1'translit($4, `SD', `sd')(as_FloatRegister($dst$$reg), as_FloatRegister($dst$$reg), as_FloatRegister($src1$$reg));
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}')dnl
|
||||
// vector max reduction
|
||||
REDUCE_FMINMAX(max, F, T_FLOAT, S, vRegF)
|
||||
REDUCE_FMINMAX(max, D, T_DOUBLE, D, vRegD)
|
||||
|
||||
// vector min reduction
|
||||
REDUCE_FMINMAX(min, F, T_FLOAT, S, vRegF)
|
||||
REDUCE_FMINMAX(min, D, T_DOUBLE, D, vRegD)
|
||||
|
||||
// vector Math.rint, floor, ceil
|
||||
|
||||
instruct vroundD(vReg dst, vReg src, immI rmode) %{
|
||||
predicate(UseSVE > 0 && n->as_Vector()->length() >= 2 &&
|
||||
n->bottom_type()->is_vect()->element_basic_type() == T_DOUBLE);
|
||||
match(Set dst (RoundDoubleModeV src rmode));
|
||||
format %{ "sve_frint $dst, $src, $rmode\t# vector (sve) (D)" %}
|
||||
ins_encode %{
|
||||
switch ($rmode$$constant) {
|
||||
case RoundDoubleModeNode::rmode_rint:
|
||||
__ sve_frintn(as_FloatRegister($dst$$reg), __ D,
|
||||
ptrue, as_FloatRegister($src$$reg));
|
||||
break;
|
||||
case RoundDoubleModeNode::rmode_floor:
|
||||
__ sve_frintm(as_FloatRegister($dst$$reg), __ D,
|
||||
ptrue, as_FloatRegister($src$$reg));
|
||||
break;
|
||||
case RoundDoubleModeNode::rmode_ceil:
|
||||
__ sve_frintp(as_FloatRegister($dst$$reg), __ D,
|
||||
ptrue, as_FloatRegister($src$$reg));
|
||||
break;
|
||||
}
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
dnl
|
||||
dnl REPLICATE($1, $2, $3, $4, $5 )
|
||||
dnl REPLICATE(insn_name, op_name, reg_src, size, min_vec_len)
|
||||
define(`REPLICATE', `
|
||||
instruct $1(vReg dst, $3 src) %{
|
||||
predicate(UseSVE > 0 && n->as_Vector()->length() >= $5);
|
||||
match(Set dst ($2 src));
|
||||
ins_cost(SVE_COST);
|
||||
format %{ "sve_dup $dst, $src\t# vector (sve) ($4)" %}
|
||||
ins_encode %{
|
||||
__ sve_dup(as_FloatRegister($dst$$reg), __ $4, as_Register($src$$reg));
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}')dnl
|
||||
dnl
|
||||
dnl REPLICATE_IMM8($1, $2, $3, $4, $5 )
|
||||
dnl REPLICATE_IMM8(insn_name, op_name, imm_type, size, min_vec_len)
|
||||
define(`REPLICATE_IMM8', `
|
||||
instruct $1(vReg dst, $3 con) %{
|
||||
predicate(UseSVE > 0 && n->as_Vector()->length() >= $5);
|
||||
match(Set dst ($2 con));
|
||||
ins_cost(SVE_COST);
|
||||
format %{ "sve_dup $dst, $con\t# vector (sve) ($4)" %}
|
||||
ins_encode %{
|
||||
__ sve_dup(as_FloatRegister($dst$$reg), __ $4, $con$$constant);
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}')dnl
|
||||
dnl
|
||||
dnl FREPLICATE($1, $2, $3, $4, $5 )
|
||||
dnl FREPLICATE(insn_name, op_name, reg_src, size, min_vec_len)
|
||||
define(`FREPLICATE', `
|
||||
instruct $1(vReg dst, $3 src) %{
|
||||
predicate(UseSVE > 0 && n->as_Vector()->length() >= $5);
|
||||
match(Set dst ($2 src));
|
||||
ins_cost(SVE_COST);
|
||||
format %{ "sve_cpy $dst, $src\t# vector (sve) ($4)" %}
|
||||
ins_encode %{
|
||||
__ sve_cpy(as_FloatRegister($dst$$reg), __ $4,
|
||||
ptrue, as_FloatRegister($src$$reg));
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}')dnl
|
||||
|
||||
// vector replicate
|
||||
REPLICATE(replicateB, ReplicateB, iRegIorL2I, B, 16)
|
||||
REPLICATE(replicateS, ReplicateS, iRegIorL2I, H, 8)
|
||||
REPLICATE(replicateI, ReplicateI, iRegIorL2I, S, 4)
|
||||
REPLICATE(replicateL, ReplicateL, iRegL, D, 2)
|
||||
|
||||
REPLICATE_IMM8(replicateB_imm8, ReplicateB, immI8, B, 16)
|
||||
REPLICATE_IMM8(replicateS_imm8, ReplicateS, immI8_shift8, H, 8)
|
||||
REPLICATE_IMM8(replicateI_imm8, ReplicateI, immI8_shift8, S, 4)
|
||||
REPLICATE_IMM8(replicateL_imm8, ReplicateL, immL8_shift8, D, 2)
|
||||
|
||||
FREPLICATE(replicateF, ReplicateF, vRegF, S, 4)
|
||||
FREPLICATE(replicateD, ReplicateD, vRegD, D, 2)
|
||||
dnl
|
||||
dnl VSHIFT_TRUE_PREDICATE($1, $2, $3, $4, $5 )
|
||||
dnl VSHIFT_TRUE_PREDICATE(insn_name, op_name, size, min_vec_len, insn)
|
||||
define(`VSHIFT_TRUE_PREDICATE', `
|
||||
instruct $1(vReg dst, vReg shift) %{
|
||||
predicate(UseSVE > 0 && n->as_Vector()->length() >= $4);
|
||||
match(Set dst ($2 dst shift));
|
||||
ins_cost(SVE_COST);
|
||||
format %{ "$5 $dst, $dst, $shift\t# vector (sve) ($3)" %}
|
||||
ins_encode %{
|
||||
__ $5(as_FloatRegister($dst$$reg), __ $3,
|
||||
ptrue, as_FloatRegister($shift$$reg));
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}')dnl
|
||||
dnl
|
||||
dnl VSHIFT_IMM_UNPREDICATE($1, $2, $3, $4, $5 )
|
||||
dnl VSHIFT_IMM_UNPREDICATE(insn_name, op_name, size, min_vec_len, insn)
|
||||
define(`VSHIFT_IMM_UNPREDICATE', `
|
||||
instruct $1(vReg dst, vReg src, immI shift) %{
|
||||
predicate(UseSVE > 0 && n->as_Vector()->length() >= $4);
|
||||
match(Set dst ($2 src shift));
|
||||
ins_cost(SVE_COST);
|
||||
format %{ "$5 $dst, $src, $shift\t# vector (sve) ($3)" %}
|
||||
ins_encode %{
|
||||
int con = (int)$shift$$constant;dnl
|
||||
ifelse(eval(index(`$1', `vasr') == 0 || index(`$1', `vlsr') == 0), 1, `
|
||||
if (con == 0) {
|
||||
__ sve_orr(as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg),
|
||||
as_FloatRegister($src$$reg));
|
||||
return;
|
||||
}')dnl
|
||||
ifelse(eval(index(`$1', `vasr') == 0), 1, `ifelse(eval(index(`$3', `B') == 0), 1, `
|
||||
if (con >= 8) con = 7;')ifelse(eval(index(`$3', `H') == 0), 1, `
|
||||
if (con >= 16) con = 15;')')dnl
|
||||
ifelse(eval((index(`$1', `vlsl') == 0 || index(`$1', `vlsr') == 0) && (index(`$3', `B') == 0 || index(`$3', `H') == 0)), 1, `
|
||||
if (con >= 8) {
|
||||
__ sve_eor(as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg),
|
||||
as_FloatRegister($src$$reg));
|
||||
return;
|
||||
}')
|
||||
__ $5(as_FloatRegister($dst$$reg), __ $3,
|
||||
as_FloatRegister($src$$reg), con);
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}')dnl
|
||||
dnl
|
||||
dnl VSHIFT_COUNT($1, $2, $3, $4 )
|
||||
dnl VSHIFT_COUNT(insn_name, size, min_vec_len, type)
|
||||
define(`VSHIFT_COUNT', `
|
||||
instruct $1(vReg dst, iRegIorL2I cnt) %{
|
||||
predicate(UseSVE > 0 && n->as_Vector()->length() >= $3 &&
|
||||
ELEMENT_SHORT_CHAR($4, n));
|
||||
match(Set dst (LShiftCntV cnt));
|
||||
match(Set dst (RShiftCntV cnt));
|
||||
format %{ "sve_dup $dst, $cnt\t# vector shift count (sve) ($2)" %}
|
||||
ins_encode %{
|
||||
__ sve_dup(as_FloatRegister($dst$$reg), __ $2, as_Register($cnt$$reg));
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}')dnl
|
||||
|
||||
// vector shift
|
||||
VSHIFT_TRUE_PREDICATE(vasrB, RShiftVB, B, 16, sve_asr)
|
||||
VSHIFT_TRUE_PREDICATE(vasrS, RShiftVS, H, 8, sve_asr)
|
||||
VSHIFT_TRUE_PREDICATE(vasrI, RShiftVI, S, 4, sve_asr)
|
||||
VSHIFT_TRUE_PREDICATE(vasrL, RShiftVL, D, 2, sve_asr)
|
||||
VSHIFT_TRUE_PREDICATE(vlslB, LShiftVB, B, 16, sve_lsl)
|
||||
VSHIFT_TRUE_PREDICATE(vlslS, LShiftVS, H, 8, sve_lsl)
|
||||
VSHIFT_TRUE_PREDICATE(vlslI, LShiftVI, S, 4, sve_lsl)
|
||||
VSHIFT_TRUE_PREDICATE(vlslL, LShiftVL, D, 2, sve_lsl)
|
||||
VSHIFT_TRUE_PREDICATE(vlsrB, URShiftVB, B, 16, sve_lsr)
|
||||
VSHIFT_TRUE_PREDICATE(vlsrS, URShiftVS, H, 8, sve_lsr)
|
||||
VSHIFT_TRUE_PREDICATE(vlsrI, URShiftVI, S, 4, sve_lsr)
|
||||
VSHIFT_TRUE_PREDICATE(vlsrL, URShiftVL, D, 2, sve_lsr)
|
||||
VSHIFT_IMM_UNPREDICATE(vasrB_imm, RShiftVB, B, 16, sve_asr)
|
||||
VSHIFT_IMM_UNPREDICATE(vasrS_imm, RShiftVS, H, 8, sve_asr)
|
||||
VSHIFT_IMM_UNPREDICATE(vasrI_imm, RShiftVI, S, 4, sve_asr)
|
||||
VSHIFT_IMM_UNPREDICATE(vasrL_imm, RShiftVL, D, 2, sve_asr)
|
||||
VSHIFT_IMM_UNPREDICATE(vlsrB_imm, URShiftVB, B, 16, sve_lsr)
|
||||
VSHIFT_IMM_UNPREDICATE(vlsrS_imm, URShiftVS, H, 8, sve_lsr)
|
||||
VSHIFT_IMM_UNPREDICATE(vlsrI_imm, URShiftVI, S, 4, sve_lsr)
|
||||
VSHIFT_IMM_UNPREDICATE(vlsrL_imm, URShiftVL, D, 2, sve_lsr)
|
||||
VSHIFT_IMM_UNPREDICATE(vlslB_imm, LShiftVB, B, 16, sve_lsl)
|
||||
VSHIFT_IMM_UNPREDICATE(vlslS_imm, LShiftVS, H, 8, sve_lsl)
|
||||
VSHIFT_IMM_UNPREDICATE(vlslI_imm, LShiftVI, S, 4, sve_lsl)
|
||||
VSHIFT_IMM_UNPREDICATE(vlslL_imm, LShiftVL, D, 2, sve_lsl)
|
||||
VSHIFT_COUNT(vshiftcntB, B, 16, T_BYTE)
|
||||
VSHIFT_COUNT(vshiftcntS, H, 8, T_SHORT)
|
||||
VSHIFT_COUNT(vshiftcntI, S, 4, T_INT)
|
||||
VSHIFT_COUNT(vshiftcntL, D, 2, T_LONG)
|
||||
|
||||
// vector sqrt
|
||||
UNARY_OP_TRUE_PREDICATE(vsqrtF, SqrtVF, S, 16, sve_fsqrt)
|
||||
UNARY_OP_TRUE_PREDICATE(vsqrtD, SqrtVD, D, 16, sve_fsqrt)
|
||||
|
||||
// vector sub
|
||||
BINARY_OP_UNPREDICATED(vsubB, SubVB, B, 16, sve_sub)
|
||||
BINARY_OP_UNPREDICATED(vsubS, SubVS, H, 8, sve_sub)
|
||||
BINARY_OP_UNPREDICATED(vsubI, SubVI, S, 4, sve_sub)
|
||||
BINARY_OP_UNPREDICATED(vsubL, SubVL, D, 2, sve_sub)
|
||||
BINARY_OP_UNPREDICATED(vsubF, SubVF, S, 4, sve_fsub)
|
||||
BINARY_OP_UNPREDICATED(vsubD, SubVD, D, 2, sve_fsub)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, Red Hat Inc. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@@ -136,20 +136,7 @@ void AbstractInterpreter::layout_activation(Method* method,
|
||||
// interpreter_frame_sender_sp interpreter_frame_sender_sp is
|
||||
// the original sp of the caller (the unextended_sp) and
|
||||
// sender_sp is fp+8/16 (32bit/64bit) XXX
|
||||
//
|
||||
// The interpreted method entry on AArch64 aligns SP to 16 bytes
|
||||
// before generating the fixed part of the activation frame. So there
|
||||
// may be a gap between the locals block and the saved sender SP. For
|
||||
// an interpreted caller we need to recreate this gap and exactly
|
||||
// align the incoming parameters with the caller's temporary
|
||||
// expression stack. For other types of caller frame it doesn't
|
||||
// matter.
|
||||
intptr_t* locals;
|
||||
if (caller->is_interpreted_frame()) {
|
||||
locals = caller->interpreter_frame_last_sp() + caller_actual_parameters - 1;
|
||||
} else {
|
||||
locals = interpreter_frame->sender_sp() + max_locals - 1;
|
||||
}
|
||||
intptr_t* locals = interpreter_frame->sender_sp() + max_locals - 1;
|
||||
|
||||
#ifdef ASSERT
|
||||
if (caller->is_interpreted_frame()) {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -139,9 +139,6 @@ REGISTER_DECLARATION(Register, rdispatch, r21);
|
||||
// Java stack pointer
|
||||
REGISTER_DECLARATION(Register, esp, r20);
|
||||
|
||||
// Preserved predicate register with all elements set TRUE.
|
||||
REGISTER_DECLARATION(PRegister, ptrue, p7);
|
||||
|
||||
#define assert_cond(ARG1) assert(ARG1, #ARG1)
|
||||
|
||||
namespace asm_util {
|
||||
@@ -276,14 +273,6 @@ public:
|
||||
f(r->encoding_nocheck(), lsb + 4, lsb);
|
||||
}
|
||||
|
||||
void prf(PRegister r, int lsb) {
|
||||
f(r->encoding_nocheck(), lsb + 3, lsb);
|
||||
}
|
||||
|
||||
void pgrf(PRegister r, int lsb) {
|
||||
f(r->encoding_nocheck(), lsb + 2, lsb);
|
||||
}
|
||||
|
||||
unsigned get(int msb = 31, int lsb = 0) {
|
||||
int nbits = msb - lsb + 1;
|
||||
unsigned mask = ((1U << nbits) - 1) << lsb;
|
||||
@@ -391,15 +380,9 @@ class Address {
|
||||
: _base(r), _index(noreg), _offset(0), _mode(base_plus_offset), _target(0) { }
|
||||
Address(Register r, int o)
|
||||
: _base(r), _index(noreg), _offset(o), _mode(base_plus_offset), _target(0) { }
|
||||
Address(Register r, long o)
|
||||
Address(Register r, int64_t o)
|
||||
: _base(r), _index(noreg), _offset(o), _mode(base_plus_offset), _target(0) { }
|
||||
Address(Register r, long long o)
|
||||
: _base(r), _index(noreg), _offset(o), _mode(base_plus_offset), _target(0) { }
|
||||
Address(Register r, unsigned int o)
|
||||
: _base(r), _index(noreg), _offset(o), _mode(base_plus_offset), _target(0) { }
|
||||
Address(Register r, unsigned long o)
|
||||
: _base(r), _index(noreg), _offset(o), _mode(base_plus_offset), _target(0) { }
|
||||
Address(Register r, unsigned long long o)
|
||||
Address(Register r, uint64_t o)
|
||||
: _base(r), _index(noreg), _offset(o), _mode(base_plus_offset), _target(0) { }
|
||||
#ifdef ASSERT
|
||||
Address(Register r, ByteSize disp)
|
||||
@@ -572,18 +555,6 @@ class Address {
|
||||
void lea(MacroAssembler *, Register) const;
|
||||
|
||||
static bool offset_ok_for_immed(int64_t offset, uint shift);
|
||||
|
||||
static bool offset_ok_for_sve_immed(long offset, int shift, int vl /* sve vector length */) {
|
||||
if (offset % vl == 0) {
|
||||
// Convert address offset into sve imm offset (MUL VL).
|
||||
int sve_offset = offset / vl;
|
||||
if (((-(1 << (shift - 1))) <= sve_offset) && (sve_offset < (1 << (shift - 1)))) {
|
||||
// sve_offset can be encoded
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
// Convience classes
|
||||
@@ -707,12 +678,6 @@ public:
|
||||
void rf(FloatRegister reg, int lsb) {
|
||||
current->rf(reg, lsb);
|
||||
}
|
||||
void prf(PRegister reg, int lsb) {
|
||||
current->prf(reg, lsb);
|
||||
}
|
||||
void pgrf(PRegister reg, int lsb) {
|
||||
current->pgrf(reg, lsb);
|
||||
}
|
||||
void fixed(unsigned value, unsigned mask) {
|
||||
current->fixed(value, mask);
|
||||
}
|
||||
@@ -2042,21 +2007,6 @@ public:
|
||||
#undef INSN
|
||||
#undef INSN1
|
||||
|
||||
// Floating-point compare. 3-registers versions (scalar).
|
||||
#define INSN(NAME, sz, e) \
|
||||
void NAME(FloatRegister Vd, FloatRegister Vn, FloatRegister Vm) { \
|
||||
starti; \
|
||||
f(0b01111110, 31, 24), f(e, 23), f(sz, 22), f(1, 21), rf(Vm, 16); \
|
||||
f(0b111011, 15, 10), rf(Vn, 5), rf(Vd, 0); \
|
||||
} \
|
||||
|
||||
INSN(facged, 1, 0); // facge-double
|
||||
INSN(facges, 0, 0); // facge-single
|
||||
INSN(facgtd, 1, 1); // facgt-double
|
||||
INSN(facgts, 0, 1); // facgt-single
|
||||
|
||||
#undef INSN
|
||||
|
||||
// Floating-point Move (immediate)
|
||||
private:
|
||||
unsigned pack(double value);
|
||||
@@ -2422,30 +2372,6 @@ public:
|
||||
|
||||
#undef INSN
|
||||
|
||||
#define INSN(NAME, opc) \
|
||||
void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn, FloatRegister Vm) { \
|
||||
starti; \
|
||||
assert(T == T2D, "arrangement must be T2D"); \
|
||||
f(0b11001110011, 31, 21), rf(Vm, 16), f(opc, 15, 10), rf(Vn, 5), rf(Vd, 0); \
|
||||
}
|
||||
|
||||
INSN(sha512h, 0b100000);
|
||||
INSN(sha512h2, 0b100001);
|
||||
INSN(sha512su1, 0b100010);
|
||||
|
||||
#undef INSN
|
||||
|
||||
#define INSN(NAME, opc) \
|
||||
void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn) { \
|
||||
starti; \
|
||||
assert(T == T2D, "arrangement must be T2D"); \
|
||||
f(opc, 31, 10), rf(Vn, 5), rf(Vd, 0); \
|
||||
}
|
||||
|
||||
INSN(sha512su0, 0b1100111011000000100000);
|
||||
|
||||
#undef INSN
|
||||
|
||||
#define INSN(NAME, opc) \
|
||||
void NAME(FloatRegister Vd, FloatRegister Vn) { \
|
||||
starti; \
|
||||
@@ -2502,18 +2428,13 @@ public:
|
||||
f(sidx<<(int)T, 14, 11), f(1, 10), rf(Vn, 5), rf(Vd, 0);
|
||||
}
|
||||
|
||||
#define INSN(NAME, op) \
|
||||
void NAME(Register Rd, FloatRegister Vn, SIMD_RegVariant T, int idx) { \
|
||||
starti; \
|
||||
f(0, 31), f(T==D ? 1:0, 30), f(0b001110000, 29, 21); \
|
||||
f(((idx<<1)|1)<<(int)T, 20, 16), f(op, 15, 10); \
|
||||
rf(Vn, 5), rf(Rd, 0); \
|
||||
void umov(Register Rd, FloatRegister Vn, SIMD_RegVariant T, int idx) {
|
||||
starti;
|
||||
f(0, 31), f(T==D ? 1:0, 30), f(0b001110000, 29, 21);
|
||||
f(((idx<<1)|1)<<(int)T, 20, 16), f(0b001111, 15, 10);
|
||||
rf(Vn, 5), rf(Rd, 0);
|
||||
}
|
||||
|
||||
INSN(umov, 0b001111);
|
||||
INSN(smov, 0b001011);
|
||||
#undef INSN
|
||||
|
||||
#define INSN(NAME, opc, opc2, isSHR) \
|
||||
void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn, int shift){ \
|
||||
starti; \
|
||||
@@ -2543,20 +2464,6 @@ public:
|
||||
|
||||
#undef INSN
|
||||
|
||||
#define INSN(NAME, opc, opc2, isSHR) \
|
||||
void NAME(FloatRegister Vd, FloatRegister Vn, int shift){ \
|
||||
starti; \
|
||||
int encodedShift = isSHR ? 128 - shift : 64 + shift; \
|
||||
f(0b01, 31, 30), f(opc, 29), f(0b111110, 28, 23), \
|
||||
f(encodedShift, 22, 16); f(opc2, 15, 10), rf(Vn, 5), rf(Vd, 0); \
|
||||
}
|
||||
|
||||
INSN(shld, 0, 0b010101, /* isSHR = */ false);
|
||||
INSN(sshrd, 0, 0b000001, /* isSHR = */ true);
|
||||
INSN(ushrd, 1, 0b000001, /* isSHR = */ true);
|
||||
|
||||
#undef INSN
|
||||
|
||||
private:
|
||||
void _ushll(FloatRegister Vd, SIMD_Arrangement Ta, FloatRegister Vn, SIMD_Arrangement Tb, int shift) {
|
||||
starti;
|
||||
@@ -2745,7 +2652,7 @@ public:
|
||||
|
||||
#undef INSN
|
||||
|
||||
void ext(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn, FloatRegister Vm, int index)
|
||||
void ext(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn, FloatRegister Vm, int index)
|
||||
{
|
||||
starti;
|
||||
assert(T == T8B || T == T16B, "invalid arrangement");
|
||||
@@ -2755,292 +2662,6 @@ public:
|
||||
f(0, 10), rf(Vn, 5), rf(Vd, 0);
|
||||
}
|
||||
|
||||
// SVE arithmetics - unpredicated
|
||||
#define INSN(NAME, opcode) \
|
||||
void NAME(FloatRegister Zd, SIMD_RegVariant T, FloatRegister Zn, FloatRegister Zm) { \
|
||||
starti; \
|
||||
assert(T != Q, "invalid register variant"); \
|
||||
f(0b00000100, 31, 24), f(T, 23, 22), f(1, 21), \
|
||||
rf(Zm, 16), f(0, 15, 13), f(opcode, 12, 10), rf(Zn, 5), rf(Zd, 0); \
|
||||
}
|
||||
INSN(sve_add, 0b000);
|
||||
INSN(sve_sub, 0b001);
|
||||
#undef INSN
|
||||
|
||||
// SVE floating-point arithmetic - unpredicated
|
||||
#define INSN(NAME, opcode) \
|
||||
void NAME(FloatRegister Zd, SIMD_RegVariant T, FloatRegister Zn, FloatRegister Zm) { \
|
||||
starti; \
|
||||
assert(T == S || T == D, "invalid register variant"); \
|
||||
f(0b01100101, 31, 24), f(T, 23, 22), f(0, 21), \
|
||||
rf(Zm, 16), f(0, 15, 13), f(opcode, 12, 10), rf(Zn, 5), rf(Zd, 0); \
|
||||
}
|
||||
|
||||
INSN(sve_fadd, 0b000);
|
||||
INSN(sve_fmul, 0b010);
|
||||
INSN(sve_fsub, 0b001);
|
||||
#undef INSN
|
||||
|
||||
private:
|
||||
void sve_predicate_reg_insn(unsigned op24, unsigned op13,
|
||||
FloatRegister Zd_or_Vd, SIMD_RegVariant T,
|
||||
PRegister Pg, FloatRegister Zn_or_Vn) {
|
||||
starti;
|
||||
f(op24, 31, 24), f(T, 23, 22), f(op13, 21, 13);
|
||||
pgrf(Pg, 10), rf(Zn_or_Vn, 5), rf(Zd_or_Vd, 0);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
// SVE integer arithmetics - predicate
|
||||
#define INSN(NAME, op1, op2) \
|
||||
void NAME(FloatRegister Zdn_or_Zd_or_Vd, SIMD_RegVariant T, PRegister Pg, FloatRegister Znm_or_Vn) { \
|
||||
assert(T != Q, "invalid register variant"); \
|
||||
sve_predicate_reg_insn(op1, op2, Zdn_or_Zd_or_Vd, T, Pg, Znm_or_Vn); \
|
||||
}
|
||||
|
||||
INSN(sve_abs, 0b00000100, 0b010110101); // vector abs, unary
|
||||
INSN(sve_add, 0b00000100, 0b000000000); // vector add
|
||||
INSN(sve_andv, 0b00000100, 0b011010001); // bitwise and reduction to scalar
|
||||
INSN(sve_asr, 0b00000100, 0b010000100); // vector arithmetic shift right
|
||||
INSN(sve_cnt, 0b00000100, 0b011010101) // count non-zero bits
|
||||
INSN(sve_cpy, 0b00000101, 0b100000100); // copy scalar to each active vector element
|
||||
INSN(sve_eorv, 0b00000100, 0b011001001); // bitwise xor reduction to scalar
|
||||
INSN(sve_lsl, 0b00000100, 0b010011100); // vector logical shift left
|
||||
INSN(sve_lsr, 0b00000100, 0b010001100); // vector logical shift right
|
||||
INSN(sve_mul, 0b00000100, 0b010000000); // vector mul
|
||||
INSN(sve_neg, 0b00000100, 0b010111101); // vector neg, unary
|
||||
INSN(sve_not, 0b00000100, 0b011110101); // bitwise invert vector, unary
|
||||
INSN(sve_orv, 0b00000100, 0b011000001); // bitwise or reduction to scalar
|
||||
INSN(sve_smax, 0b00000100, 0b001000000); // signed maximum vectors
|
||||
INSN(sve_smaxv, 0b00000100, 0b001000001); // signed maximum reduction to scalar
|
||||
INSN(sve_smin, 0b00000100, 0b001010000); // signed minimum vectors
|
||||
INSN(sve_sminv, 0b00000100, 0b001010001); // signed minimum reduction to scalar
|
||||
INSN(sve_sub, 0b00000100, 0b000001000); // vector sub
|
||||
INSN(sve_uaddv, 0b00000100, 0b000001001); // unsigned add reduction to scalar
|
||||
#undef INSN
|
||||
|
||||
// SVE floating-point arithmetics - predicate
|
||||
#define INSN(NAME, op1, op2) \
|
||||
void NAME(FloatRegister Zd_or_Zdn_or_Vd, SIMD_RegVariant T, PRegister Pg, FloatRegister Zn_or_Zm) { \
|
||||
assert(T == S || T == D, "invalid register variant"); \
|
||||
sve_predicate_reg_insn(op1, op2, Zd_or_Zdn_or_Vd, T, Pg, Zn_or_Zm); \
|
||||
}
|
||||
|
||||
INSN(sve_fabs, 0b00000100, 0b011100101);
|
||||
INSN(sve_fadd, 0b01100101, 0b000000100);
|
||||
INSN(sve_fadda, 0b01100101, 0b011000001); // add strictly-ordered reduction to scalar Vd
|
||||
INSN(sve_fdiv, 0b01100101, 0b001101100);
|
||||
INSN(sve_fmax, 0b01100101, 0b000110100); // floating-point maximum
|
||||
INSN(sve_fmaxv, 0b01100101, 0b000110001); // floating-point maximum recursive reduction to scalar
|
||||
INSN(sve_fmin, 0b01100101, 0b000111100); // floating-point minimum
|
||||
INSN(sve_fminv, 0b01100101, 0b000111001); // floating-point minimum recursive reduction to scalar
|
||||
INSN(sve_fmul, 0b01100101, 0b000010100);
|
||||
INSN(sve_fneg, 0b00000100, 0b011101101);
|
||||
INSN(sve_frintm, 0b01100101, 0b000010101); // floating-point round to integral value, toward minus infinity
|
||||
INSN(sve_frintn, 0b01100101, 0b000000101); // floating-point round to integral value, nearest with ties to even
|
||||
INSN(sve_frintp, 0b01100101, 0b000001101); // floating-point round to integral value, toward plus infinity
|
||||
INSN(sve_fsqrt, 0b01100101, 0b001101101);
|
||||
INSN(sve_fsub, 0b01100101, 0b000001100);
|
||||
#undef INSN
|
||||
|
||||
// SVE multiple-add/sub - predicated
|
||||
#define INSN(NAME, op0, op1, op2) \
|
||||
void NAME(FloatRegister Zda, SIMD_RegVariant T, PRegister Pg, FloatRegister Zn, FloatRegister Zm) { \
|
||||
starti; \
|
||||
assert(T != Q, "invalid size"); \
|
||||
f(op0, 31, 24), f(T, 23, 22), f(op1, 21), rf(Zm, 16); \
|
||||
f(op2, 15, 13), pgrf(Pg, 10), rf(Zn, 5), rf(Zda, 0); \
|
||||
}
|
||||
|
||||
INSN(sve_fmla, 0b01100101, 1, 0b000); // floating-point fused multiply-add: Zda = Zda + Zn * Zm
|
||||
INSN(sve_fmls, 0b01100101, 1, 0b001); // floating-point fused multiply-subtract: Zda = Zda + -Zn * Zm
|
||||
INSN(sve_fnmla, 0b01100101, 1, 0b010); // floating-point negated fused multiply-add: Zda = -Zda + -Zn * Zm
|
||||
INSN(sve_fnmls, 0b01100101, 1, 0b011); // floating-point negated fused multiply-subtract: Zda = -Zda + Zn * Zm
|
||||
INSN(sve_mla, 0b00000100, 0, 0b010); // multiply-add: Zda = Zda + Zn*Zm
|
||||
INSN(sve_mls, 0b00000100, 0, 0b011); // multiply-subtract: Zda = Zda + -Zn*Zm
|
||||
#undef INSN
|
||||
|
||||
// SVE bitwise logical - unpredicated
|
||||
#define INSN(NAME, opc) \
|
||||
void NAME(FloatRegister Zd, FloatRegister Zn, FloatRegister Zm) { \
|
||||
starti; \
|
||||
f(0b00000100, 31, 24), f(opc, 23, 22), f(1, 21), \
|
||||
rf(Zm, 16), f(0b001100, 15, 10), rf(Zn, 5), rf(Zd, 0); \
|
||||
}
|
||||
INSN(sve_and, 0b00);
|
||||
INSN(sve_eor, 0b10);
|
||||
INSN(sve_orr, 0b01);
|
||||
#undef INSN
|
||||
|
||||
// SVE shift immediate - unpredicated
|
||||
#define INSN(NAME, opc, isSHR) \
|
||||
void NAME(FloatRegister Zd, SIMD_RegVariant T, FloatRegister Zn, int shift) { \
|
||||
starti; \
|
||||
/* The encodings for the tszh:tszl:imm3 fields (bits 23:22 20:19 18:16) \
|
||||
* for shift right is calculated as: \
|
||||
* 0001 xxx B, shift = 16 - UInt(tszh:tszl:imm3) \
|
||||
* 001x xxx H, shift = 32 - UInt(tszh:tszl:imm3) \
|
||||
* 01xx xxx S, shift = 64 - UInt(tszh:tszl:imm3) \
|
||||
* 1xxx xxx D, shift = 128 - UInt(tszh:tszl:imm3) \
|
||||
* for shift left is calculated as: \
|
||||
* 0001 xxx B, shift = UInt(tszh:tszl:imm3) - 8 \
|
||||
* 001x xxx H, shift = UInt(tszh:tszl:imm3) - 16 \
|
||||
* 01xx xxx S, shift = UInt(tszh:tszl:imm3) - 32 \
|
||||
* 1xxx xxx D, shift = UInt(tszh:tszl:imm3) - 64 \
|
||||
*/ \
|
||||
assert(T != Q, "Invalid register variant"); \
|
||||
if (isSHR) { \
|
||||
assert(((1 << (T + 3)) >= shift) && (shift > 0) , "Invalid shift value"); \
|
||||
} else { \
|
||||
assert(((1 << (T + 3)) > shift) && (shift >= 0) , "Invalid shift value"); \
|
||||
} \
|
||||
int cVal = (1 << ((T + 3) + (isSHR ? 1 : 0))); \
|
||||
int encodedShift = isSHR ? cVal - shift : cVal + shift; \
|
||||
int tszh = encodedShift >> 5; \
|
||||
int tszl_imm = encodedShift & 0x1f; \
|
||||
f(0b00000100, 31, 24); \
|
||||
f(tszh, 23, 22), f(1,21), f(tszl_imm, 20, 16); \
|
||||
f(0b100, 15, 13), f(opc, 12, 10), rf(Zn, 5), rf(Zd, 0); \
|
||||
}
|
||||
|
||||
INSN(sve_asr, 0b100, /* isSHR = */ true);
|
||||
INSN(sve_lsl, 0b111, /* isSHR = */ false);
|
||||
INSN(sve_lsr, 0b101, /* isSHR = */ true);
|
||||
#undef INSN
|
||||
|
||||
private:
|
||||
|
||||
// Scalar base + immediate index
|
||||
void sve_ld_st1(FloatRegister Zt, Register Xn, int imm, PRegister Pg,
|
||||
SIMD_RegVariant T, int op1, int type, int op2) {
|
||||
starti;
|
||||
assert_cond(T >= type);
|
||||
f(op1, 31, 25), f(type, 24, 23), f(T, 22, 21);
|
||||
f(0, 20), sf(imm, 19, 16), f(op2, 15, 13);
|
||||
pgrf(Pg, 10), srf(Xn, 5), rf(Zt, 0);
|
||||
}
|
||||
|
||||
// Scalar base + scalar index
|
||||
void sve_ld_st1(FloatRegister Zt, Register Xn, Register Xm, PRegister Pg,
|
||||
SIMD_RegVariant T, int op1, int type, int op2) {
|
||||
starti;
|
||||
assert_cond(T >= type);
|
||||
f(op1, 31, 25), f(type, 24, 23), f(T, 22, 21);
|
||||
rf(Xm, 16), f(op2, 15, 13);
|
||||
pgrf(Pg, 10), srf(Xn, 5), rf(Zt, 0);
|
||||
}
|
||||
|
||||
void sve_ld_st1(FloatRegister Zt, PRegister Pg,
|
||||
SIMD_RegVariant T, const Address &a,
|
||||
int op1, int type, int imm_op2, int scalar_op2) {
|
||||
switch (a.getMode()) {
|
||||
case Address::base_plus_offset:
|
||||
sve_ld_st1(Zt, a.base(), a.offset(), Pg, T, op1, type, imm_op2);
|
||||
break;
|
||||
case Address::base_plus_offset_reg:
|
||||
sve_ld_st1(Zt, a.base(), a.index(), Pg, T, op1, type, scalar_op2);
|
||||
break;
|
||||
default:
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
// SVE load/store - predicated
|
||||
#define INSN(NAME, op1, type, imm_op2, scalar_op2) \
|
||||
void NAME(FloatRegister Zt, SIMD_RegVariant T, PRegister Pg, const Address &a) { \
|
||||
assert(T != Q, "invalid register variant"); \
|
||||
sve_ld_st1(Zt, Pg, T, a, op1, type, imm_op2, scalar_op2); \
|
||||
}
|
||||
|
||||
INSN(sve_ld1b, 0b1010010, 0b00, 0b101, 0b010);
|
||||
INSN(sve_st1b, 0b1110010, 0b00, 0b111, 0b010);
|
||||
INSN(sve_ld1h, 0b1010010, 0b01, 0b101, 0b010);
|
||||
INSN(sve_st1h, 0b1110010, 0b01, 0b111, 0b010);
|
||||
INSN(sve_ld1w, 0b1010010, 0b10, 0b101, 0b010);
|
||||
INSN(sve_st1w, 0b1110010, 0b10, 0b111, 0b010);
|
||||
INSN(sve_ld1d, 0b1010010, 0b11, 0b101, 0b010);
|
||||
INSN(sve_st1d, 0b1110010, 0b11, 0b111, 0b010);
|
||||
#undef INSN
|
||||
|
||||
// SVE load/store - unpredicated
|
||||
#define INSN(NAME, op1) \
|
||||
void NAME(FloatRegister Zt, const Address &a) { \
|
||||
starti; \
|
||||
assert(a.index() == noreg, "invalid address variant"); \
|
||||
f(op1, 31, 29), f(0b0010110, 28, 22), sf(a.offset() >> 3, 21, 16), \
|
||||
f(0b010, 15, 13), f(a.offset() & 0x7, 12, 10), srf(a.base(), 5), rf(Zt, 0); \
|
||||
}
|
||||
|
||||
INSN(sve_ldr, 0b100); // LDR (vector)
|
||||
INSN(sve_str, 0b111); // STR (vector)
|
||||
#undef INSN
|
||||
|
||||
#define INSN(NAME, op) \
|
||||
void NAME(Register Xd, Register Xn, int imm6) { \
|
||||
starti; \
|
||||
f(0b000001000, 31, 23), f(op, 22, 21); \
|
||||
srf(Xn, 16), f(0b01010, 15, 11), sf(imm6, 10, 5), srf(Xd, 0); \
|
||||
}
|
||||
|
||||
INSN(sve_addvl, 0b01);
|
||||
INSN(sve_addpl, 0b11);
|
||||
#undef INSN
|
||||
|
||||
// SVE inc/dec register by element count
|
||||
#define INSN(NAME, op) \
|
||||
void NAME(Register Xdn, SIMD_RegVariant T, unsigned imm4 = 1, int pattern = 0b11111) { \
|
||||
starti; \
|
||||
assert(T != Q, "invalid size"); \
|
||||
f(0b00000100,31, 24), f(T, 23, 22), f(0b11, 21, 20); \
|
||||
f(imm4 - 1, 19, 16), f(0b11100, 15, 11), f(op, 10), f(pattern, 9, 5), rf(Xdn, 0); \
|
||||
}
|
||||
|
||||
INSN(sve_inc, 0);
|
||||
INSN(sve_dec, 1);
|
||||
#undef INSN
|
||||
|
||||
// SVE predicate count
|
||||
void sve_cntp(Register Xd, SIMD_RegVariant T, PRegister Pg, PRegister Pn) {
|
||||
starti;
|
||||
assert(T != Q, "invalid size");
|
||||
f(0b00100101, 31, 24), f(T, 23, 22), f(0b10000010, 21, 14);
|
||||
prf(Pg, 10), f(0, 9), prf(Pn, 5), rf(Xd, 0);
|
||||
}
|
||||
|
||||
// SVE dup scalar
|
||||
void sve_dup(FloatRegister Zd, SIMD_RegVariant T, Register Rn) {
|
||||
starti;
|
||||
assert(T != Q, "invalid size");
|
||||
f(0b00000101, 31, 24), f(T, 23, 22), f(0b100000001110, 21, 10);
|
||||
srf(Rn, 5), rf(Zd, 0);
|
||||
}
|
||||
|
||||
// SVE dup imm
|
||||
void sve_dup(FloatRegister Zd, SIMD_RegVariant T, int imm8) {
|
||||
starti;
|
||||
assert(T != Q, "invalid size");
|
||||
int sh = 0;
|
||||
if (imm8 <= 127 && imm8 >= -128) {
|
||||
sh = 0;
|
||||
} else if (T != B && imm8 <= 32512 && imm8 >= -32768 && (imm8 & 0xff) == 0) {
|
||||
sh = 1;
|
||||
imm8 = (imm8 >> 8);
|
||||
} else {
|
||||
guarantee(false, "invalid immediate");
|
||||
}
|
||||
f(0b00100101, 31, 24), f(T, 23, 22), f(0b11100011, 21, 14);
|
||||
f(sh, 13), sf(imm8, 12, 5), rf(Zd, 0);
|
||||
}
|
||||
|
||||
void sve_ptrue(PRegister pd, SIMD_RegVariant esize, int pattern = 0b11111) {
|
||||
starti;
|
||||
f(0b00100101, 31, 24), f(esize, 23, 22), f(0b011000111000, 21, 10);
|
||||
f(pattern, 9, 5), f(0b0, 4), prf(pd, 0);
|
||||
}
|
||||
|
||||
Assembler(CodeBuffer* code) : AbstractAssembler(code) {
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, Red Hat Inc. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@@ -58,7 +58,7 @@ enum {
|
||||
|
||||
pd_nof_cpu_regs_linearscan = 32, // number of registers visible to linear scan
|
||||
pd_nof_fpu_regs_linearscan = pd_nof_fpu_regs_frame_map, // number of registers visible to linear scan
|
||||
pd_nof_xmm_regs_linearscan = 0, // don't have vector registers
|
||||
pd_nof_xmm_regs_linearscan = 0, // like sparc we don't have any of these
|
||||
pd_first_cpu_reg = 0,
|
||||
pd_last_cpu_reg = 16,
|
||||
pd_first_byte_reg = 0,
|
||||
|
||||
@@ -2072,7 +2072,7 @@ void LIR_Assembler::ic_call(LIR_OpJavaCall* op) {
|
||||
}
|
||||
|
||||
|
||||
/* vtable-dispatch is not enabled for aarch64 platform*/
|
||||
/* Currently, vtable-dispatch is only enabled for sparc platforms */
|
||||
void LIR_Assembler::vtable_call(LIR_OpJavaCall* op) {
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
|
||||
@@ -291,7 +291,7 @@ void LIRGenerator::cmp_reg_mem(LIR_Condition condition, LIR_Opr reg, LIR_Opr bas
|
||||
}
|
||||
|
||||
|
||||
bool LIRGenerator::strength_reduce_multiply(LIR_Opr left, jint c, LIR_Opr result, LIR_Opr tmp) {
|
||||
bool LIRGenerator::strength_reduce_multiply(LIR_Opr left, int c, LIR_Opr result, LIR_Opr tmp) {
|
||||
|
||||
if (is_power_of_2(c - 1)) {
|
||||
__ shift_left(left, exact_log2(c - 1), tmp);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@@ -48,7 +48,7 @@ LIR_Opr LIR_OprFact::double_fpu(int reg1, int reg2) {
|
||||
void LIR_Address::verify() const {
|
||||
assert(base()->is_cpu_register(), "wrong base operand");
|
||||
assert(index()->is_illegal() || index()->is_double_cpu() || index()->is_single_cpu(), "wrong index operand");
|
||||
assert(base()->type() == T_ADDRESS || base()->type() == T_OBJECT || base()->type() == T_LONG || base()->type() == T_METADATA,
|
||||
assert(base()->type() == T_OBJECT || base()->type() == T_LONG || base()->type() == T_METADATA,
|
||||
"wrong type for addresses");
|
||||
}
|
||||
#endif // PRODUCT
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, Red Hat Inc. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@@ -73,18 +73,11 @@ int C1_MacroAssembler::lock_object(Register hdr, Register obj, Register disp_hdr
|
||||
// save object being locked into the BasicObjectLock
|
||||
str(obj, Address(disp_hdr, BasicObjectLock::obj_offset_in_bytes()));
|
||||
|
||||
null_check_offset = offset();
|
||||
|
||||
if (DiagnoseSyncOnPrimitiveWrappers != 0) {
|
||||
load_klass(hdr, obj);
|
||||
ldrw(hdr, Address(hdr, Klass::access_flags_offset()));
|
||||
tstw(hdr, JVM_ACC_IS_BOX_CLASS);
|
||||
br(Assembler::NE, slow_case);
|
||||
}
|
||||
|
||||
if (UseBiasedLocking) {
|
||||
assert(scratch != noreg, "should have scratch register at this point");
|
||||
biased_locking_enter(disp_hdr, obj, hdr, scratch, false, done, &slow_case);
|
||||
null_check_offset = biased_locking_enter(disp_hdr, obj, hdr, scratch, false, done, &slow_case);
|
||||
} else {
|
||||
null_check_offset = offset();
|
||||
}
|
||||
|
||||
// Load object header
|
||||
|
||||
@@ -46,7 +46,7 @@ define_pd_global(intx, CompileThreshold, 10000);
|
||||
|
||||
define_pd_global(intx, OnStackReplacePercentage, 140);
|
||||
define_pd_global(intx, ConditionalMoveLimit, 3);
|
||||
define_pd_global(intx, FLOATPRESSURE, 32);
|
||||
define_pd_global(intx, FLOATPRESSURE, 64);
|
||||
define_pd_global(intx, FreqInlineSize, 325);
|
||||
define_pd_global(intx, MinJumpTableSize, 10);
|
||||
define_pd_global(intx, INTPRESSURE, 24);
|
||||
|
||||
@@ -61,7 +61,6 @@
|
||||
// [last sp ]
|
||||
// [oop temp ] (only for native calls)
|
||||
|
||||
// [padding ] (to preserve machine SP alignment)
|
||||
// [locals and parameters ]
|
||||
// <- sender sp
|
||||
// ------------------------------ Asm interpreter ----------------------------------------
|
||||
|
||||
@@ -101,7 +101,7 @@ void BarrierSetNMethod::deoptimize(nmethod* nm, address* return_address_ptr) {
|
||||
|
||||
frame_pointers_t *new_frame = (frame_pointers_t *)(return_address_ptr - 5);
|
||||
|
||||
JavaThread *thread = JavaThread::current();
|
||||
JavaThread *thread = (JavaThread*)Thread::current();
|
||||
RegisterMap reg_map(thread, false);
|
||||
frame frame = thread->last_frame();
|
||||
|
||||
@@ -111,11 +111,14 @@ void BarrierSetNMethod::deoptimize(nmethod* nm, address* return_address_ptr) {
|
||||
|
||||
LogTarget(Trace, nmethod, barrier) out;
|
||||
if (out.is_enabled()) {
|
||||
Thread* thread = Thread::current();
|
||||
assert(thread->is_Java_thread(), "must be JavaThread");
|
||||
JavaThread* jth = (JavaThread*) thread;
|
||||
ResourceMark mark;
|
||||
log_trace(nmethod, barrier)("deoptimize(nmethod: %s(%p), return_addr: %p, osr: %d, thread: %p(%s), making rsp: %p) -> %p",
|
||||
nm->method()->name_and_sig_as_C_string(),
|
||||
nm, *(address *) return_address_ptr, nm->is_osr_method(), thread,
|
||||
thread->get_thread_name(), frame.sp(), nm->verified_entry_point());
|
||||
nm, *(address *) return_address_ptr, nm->is_osr_method(), jth,
|
||||
jth->get_thread_name(), frame.sp(), nm->verified_entry_point());
|
||||
}
|
||||
|
||||
new_frame->sp = frame.sp();
|
||||
|
||||
@@ -302,9 +302,16 @@ void ShenandoahBarrierSetAssembler::load_reference_barrier_native(MacroAssembler
|
||||
|
||||
void ShenandoahBarrierSetAssembler::storeval_barrier(MacroAssembler* masm, Register dst, Register tmp) {
|
||||
if (ShenandoahStoreValEnqueueBarrier) {
|
||||
__ push_call_clobbered_registers();
|
||||
// Save possibly live regs.
|
||||
RegSet live_regs = RegSet::range(r0, r4) - dst;
|
||||
__ push(live_regs, sp);
|
||||
__ strd(v0, __ pre(sp, 2 * -wordSize));
|
||||
|
||||
satb_write_barrier_pre(masm, noreg, dst, rthread, tmp, true, false);
|
||||
__ pop_call_clobbered_registers();
|
||||
|
||||
// Restore possibly live regs.
|
||||
__ ldrd(v0, __ post(sp, 2 * wordSize));
|
||||
__ pop(live_regs, sp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -431,12 +431,8 @@ void ZBarrierSetAssembler::generate_c2_load_barrier_stub(MacroAssembler* masm, Z
|
||||
ZSetupArguments setup_arguments(masm, stub);
|
||||
__ mov(rscratch1, stub->slow_path());
|
||||
__ blr(rscratch1);
|
||||
if (UseSVE > 0) {
|
||||
// Reinitialize the ptrue predicate register, in case the external runtime
|
||||
// call clobbers ptrue reg, as we may return to SVE compiled code.
|
||||
__ reinitialize_ptrue();
|
||||
}
|
||||
}
|
||||
|
||||
// Stub exit
|
||||
__ b(*stub->continuation());
|
||||
}
|
||||
|
||||
@@ -22,17 +22,11 @@
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "gc/shared/gcLogPrecious.hpp"
|
||||
#include "gc/z/zGlobals.hpp"
|
||||
#include "runtime/globals.hpp"
|
||||
#include "runtime/os.hpp"
|
||||
#include "utilities/globalDefinitions.hpp"
|
||||
#include "utilities/powerOfTwo.hpp"
|
||||
|
||||
#ifdef LINUX
|
||||
#include <sys/mman.h>
|
||||
#endif // LINUX
|
||||
|
||||
//
|
||||
// The heap can have three different layouts, depending on the max heap size.
|
||||
//
|
||||
@@ -141,64 +135,9 @@
|
||||
// * 63-48 Fixed (16-bits, always zero)
|
||||
//
|
||||
|
||||
// Default value if probing is not implemented for a certain platform: 128TB
|
||||
static const size_t DEFAULT_MAX_ADDRESS_BIT = 47;
|
||||
// Minimum value returned, if probing fails: 64GB
|
||||
static const size_t MINIMUM_MAX_ADDRESS_BIT = 36;
|
||||
|
||||
static size_t probe_valid_max_address_bit() {
|
||||
#ifdef LINUX
|
||||
size_t max_address_bit = 0;
|
||||
const size_t page_size = os::vm_page_size();
|
||||
for (size_t i = DEFAULT_MAX_ADDRESS_BIT; i > MINIMUM_MAX_ADDRESS_BIT; --i) {
|
||||
const uintptr_t base_addr = ((uintptr_t) 1U) << i;
|
||||
if (msync((void*)base_addr, page_size, MS_ASYNC) == 0) {
|
||||
// msync suceeded, the address is valid, and maybe even already mapped.
|
||||
max_address_bit = i;
|
||||
break;
|
||||
}
|
||||
if (errno != ENOMEM) {
|
||||
// Some error occured. This should never happen, but msync
|
||||
// has some undefined behavior, hence ignore this bit.
|
||||
#ifdef ASSERT
|
||||
fatal("Received '%s' while probing the address space for the highest valid bit", os::errno_name(errno));
|
||||
#else // ASSERT
|
||||
log_warning_p(gc)("Received '%s' while probing the address space for the highest valid bit", os::errno_name(errno));
|
||||
#endif // ASSERT
|
||||
continue;
|
||||
}
|
||||
// Since msync failed with ENOMEM, the page might not be mapped.
|
||||
// Try to map it, to see if the address is valid.
|
||||
void* const result_addr = mmap((void*) base_addr, page_size, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0);
|
||||
if (result_addr != MAP_FAILED) {
|
||||
munmap(result_addr, page_size);
|
||||
}
|
||||
if ((uintptr_t) result_addr == base_addr) {
|
||||
// address is valid
|
||||
max_address_bit = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (max_address_bit == 0) {
|
||||
// probing failed, allocate a very high page and take that bit as the maximum
|
||||
const uintptr_t high_addr = ((uintptr_t) 1U) << DEFAULT_MAX_ADDRESS_BIT;
|
||||
void* const result_addr = mmap((void*) high_addr, page_size, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0);
|
||||
if (result_addr != MAP_FAILED) {
|
||||
max_address_bit = BitsPerSize_t - count_leading_zeros((size_t) result_addr) - 1;
|
||||
munmap(result_addr, page_size);
|
||||
}
|
||||
}
|
||||
log_info_p(gc, init)("Probing address space for the highest valid bit: " SIZE_FORMAT, max_address_bit);
|
||||
return MAX2(max_address_bit, MINIMUM_MAX_ADDRESS_BIT);
|
||||
#else // LINUX
|
||||
return DEFAULT_MAX_ADDRESS_BIT;
|
||||
#endif // LINUX
|
||||
}
|
||||
|
||||
size_t ZPlatformAddressOffsetBits() {
|
||||
const static size_t valid_max_address_offset_bits = probe_valid_max_address_bit() + 1;
|
||||
const size_t max_address_offset_bits = valid_max_address_offset_bits - 3;
|
||||
const size_t min_address_offset_bits = max_address_offset_bits - 2;
|
||||
const size_t min_address_offset_bits = 42; // 4TB
|
||||
const size_t max_address_offset_bits = 44; // 16TB
|
||||
const size_t address_offset = round_up_power_of_2(MaxHeapSize * ZVirtualToPhysicalRatio);
|
||||
const size_t address_offset_bits = log2_intptr(address_offset);
|
||||
return clamp(address_offset_bits, min_address_offset_bits, max_address_offset_bits);
|
||||
|
||||
@@ -75,11 +75,13 @@ define_pd_global(intx, InitArrayShortSize, BytesPerLong);
|
||||
define_pd_global(intx, InlineSmallCode, 1000);
|
||||
#endif
|
||||
|
||||
#define ARCH_FLAGS(develop, \
|
||||
product, \
|
||||
notproduct, \
|
||||
range, \
|
||||
constraint) \
|
||||
#define ARCH_FLAGS(develop, \
|
||||
product, \
|
||||
diagnostic, \
|
||||
experimental, \
|
||||
notproduct, \
|
||||
range, \
|
||||
constraint) \
|
||||
\
|
||||
product(bool, NearCpool, true, \
|
||||
"constant pool is close to instructions") \
|
||||
@@ -97,9 +99,6 @@ define_pd_global(intx, InlineSmallCode, 1000);
|
||||
"Avoid generating unaligned memory accesses") \
|
||||
product(bool, UseLSE, false, \
|
||||
"Use LSE instructions") \
|
||||
product(uint, UseSVE, 0, \
|
||||
"Highest supported SVE instruction set version") \
|
||||
range(0, 2) \
|
||||
product(bool, UseBlockZeroing, true, \
|
||||
"Use DC ZVA for block zeroing") \
|
||||
product(intx, BlockZeroingLowLimit, 256, \
|
||||
@@ -111,6 +110,4 @@ define_pd_global(intx, InlineSmallCode, 1000);
|
||||
"Value -1 means off.") \
|
||||
range(-1, 4096)
|
||||
|
||||
// end of ARCH_FLAGS
|
||||
|
||||
#endif // CPU_AARCH64_GLOBALS_AARCH64_HPP
|
||||
|
||||
@@ -725,13 +725,6 @@ void InterpreterMacroAssembler::lock_object(Register lock_reg)
|
||||
// Load object pointer into obj_reg %c_rarg3
|
||||
ldr(obj_reg, Address(lock_reg, obj_offset));
|
||||
|
||||
if (DiagnoseSyncOnPrimitiveWrappers != 0) {
|
||||
load_klass(tmp, obj_reg);
|
||||
ldrw(tmp, Address(tmp, Klass::access_flags_offset()));
|
||||
tstw(tmp, JVM_ACC_IS_BOX_CLASS);
|
||||
br(Assembler::NE, slow_case);
|
||||
}
|
||||
|
||||
if (UseBiasedLocking) {
|
||||
biased_locking_enter(lock_reg, obj_reg, swap_reg, tmp, false, done, &slow_case);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, Red Hat Inc. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@@ -39,7 +39,7 @@ class JNITypes : AllStatic {
|
||||
// I.e., they are functionally 'push' operations if they have a 'pos'
|
||||
// formal parameter. Note that jlong's and jdouble's are written
|
||||
// _in reverse_ of the order in which they appear in the interpreter
|
||||
// stack. This is because call stubs (see stubGenerator_arm.cpp)
|
||||
// stack. This is because call stubs (see stubGenerator_sparc.cpp)
|
||||
// reverse the argument list constructed by JavaCallArguments (see
|
||||
// javaCalls.hpp).
|
||||
|
||||
|
||||
@@ -389,7 +389,7 @@ void MacroAssembler::far_call(Address entry, CodeBuffer *cbuf, Register tmp) {
|
||||
assert(CodeCache::find_blob(entry.target()) != NULL,
|
||||
"destination of far call not found in code cache");
|
||||
if (far_branches()) {
|
||||
uint64_t offset;
|
||||
uintptr_t offset;
|
||||
// We can use ADRP here because we know that the total size of
|
||||
// the code cache cannot exceed 2Gb.
|
||||
adrp(tmp, entry, offset);
|
||||
@@ -407,7 +407,7 @@ void MacroAssembler::far_jump(Address entry, CodeBuffer *cbuf, Register tmp) {
|
||||
assert(CodeCache::find_blob(entry.target()) != NULL,
|
||||
"destination of far call not found in code cache");
|
||||
if (far_branches()) {
|
||||
uint64_t offset;
|
||||
uintptr_t offset;
|
||||
// We can use ADRP here because we know that the total size of
|
||||
// the code cache cannot exceed 2Gb.
|
||||
adrp(tmp, entry, offset);
|
||||
@@ -444,14 +444,14 @@ void MacroAssembler::reserved_stack_check() {
|
||||
bind(no_reserved_zone_enabling);
|
||||
}
|
||||
|
||||
void MacroAssembler::biased_locking_enter(Register lock_reg,
|
||||
Register obj_reg,
|
||||
Register swap_reg,
|
||||
Register tmp_reg,
|
||||
bool swap_reg_contains_mark,
|
||||
Label& done,
|
||||
Label* slow_case,
|
||||
BiasedLockingCounters* counters) {
|
||||
int MacroAssembler::biased_locking_enter(Register lock_reg,
|
||||
Register obj_reg,
|
||||
Register swap_reg,
|
||||
Register tmp_reg,
|
||||
bool swap_reg_contains_mark,
|
||||
Label& done,
|
||||
Label* slow_case,
|
||||
BiasedLockingCounters* counters) {
|
||||
assert(UseBiasedLocking, "why call this otherwise?");
|
||||
assert_different_registers(lock_reg, obj_reg, swap_reg);
|
||||
|
||||
@@ -471,7 +471,9 @@ void MacroAssembler::biased_locking_enter(Register lock_reg,
|
||||
// pointers to allow age to be placed into low bits
|
||||
// First check to see whether biasing is even enabled for this object
|
||||
Label cas_label;
|
||||
int null_check_offset = -1;
|
||||
if (!swap_reg_contains_mark) {
|
||||
null_check_offset = offset();
|
||||
ldr(swap_reg, mark_addr);
|
||||
}
|
||||
andr(tmp_reg, swap_reg, markWord::biased_lock_mask_in_place);
|
||||
@@ -599,6 +601,8 @@ void MacroAssembler::biased_locking_enter(Register lock_reg,
|
||||
}
|
||||
|
||||
bind(cas_label);
|
||||
|
||||
return null_check_offset;
|
||||
}
|
||||
|
||||
void MacroAssembler::biased_locking_exit(Register obj_reg, Register temp_reg, Label& done) {
|
||||
@@ -1004,22 +1008,27 @@ void MacroAssembler::lookup_interface_method(Register recv_klass,
|
||||
// }
|
||||
Label search, found_method;
|
||||
|
||||
ldr(method_result, Address(scan_temp, itableOffsetEntry::interface_offset_in_bytes()));
|
||||
cmp(intf_klass, method_result);
|
||||
br(Assembler::EQ, found_method);
|
||||
bind(search);
|
||||
// Check that the previous entry is non-null. A null entry means that
|
||||
// the receiver class doesn't implement the interface, and wasn't the
|
||||
// same as when the caller was compiled.
|
||||
cbz(method_result, L_no_such_interface);
|
||||
if (itableOffsetEntry::interface_offset_in_bytes() != 0) {
|
||||
add(scan_temp, scan_temp, scan_step);
|
||||
for (int peel = 1; peel >= 0; peel--) {
|
||||
ldr(method_result, Address(scan_temp, itableOffsetEntry::interface_offset_in_bytes()));
|
||||
} else {
|
||||
ldr(method_result, Address(pre(scan_temp, scan_step)));
|
||||
cmp(intf_klass, method_result);
|
||||
|
||||
if (peel) {
|
||||
br(Assembler::EQ, found_method);
|
||||
} else {
|
||||
br(Assembler::NE, search);
|
||||
// (invert the test to fall through to found_method...)
|
||||
}
|
||||
|
||||
if (!peel) break;
|
||||
|
||||
bind(search);
|
||||
|
||||
// Check that the previous entry is non-null. A null entry means that
|
||||
// the receiver class doesn't implement the interface, and wasn't the
|
||||
// same as when the caller was compiled.
|
||||
cbz(method_result, L_no_such_interface);
|
||||
add(scan_temp, scan_temp, scan_step);
|
||||
}
|
||||
cmp(intf_klass, method_result);
|
||||
br(Assembler::NE, search);
|
||||
|
||||
bind(found_method);
|
||||
|
||||
@@ -1494,7 +1503,7 @@ void MacroAssembler::movptr(Register r, uintptr_t imm64) {
|
||||
#ifndef PRODUCT
|
||||
{
|
||||
char buffer[64];
|
||||
snprintf(buffer, sizeof(buffer), "0x%" PRIX64, (uint64_t)imm64);
|
||||
snprintf(buffer, sizeof(buffer), "0x%" PRIX64, imm64);
|
||||
block_comment(buffer);
|
||||
}
|
||||
#endif
|
||||
@@ -2112,16 +2121,9 @@ int MacroAssembler::pop(unsigned int bitset, Register stack) {
|
||||
}
|
||||
|
||||
// Push lots of registers in the bit set supplied. Don't push sp.
|
||||
// Return the number of dwords pushed
|
||||
// Return the number of words pushed
|
||||
int MacroAssembler::push_fp(unsigned int bitset, Register stack) {
|
||||
int words_pushed = 0;
|
||||
bool use_sve = false;
|
||||
int sve_vector_size_in_bytes = 0;
|
||||
|
||||
#ifdef COMPILER2
|
||||
use_sve = Matcher::supports_scalable_vector();
|
||||
sve_vector_size_in_bytes = Matcher::scalable_vector_reg_size(T_BYTE);
|
||||
#endif
|
||||
|
||||
// Scan bitset to accumulate register pairs
|
||||
unsigned char regs[32];
|
||||
@@ -2136,19 +2138,9 @@ int MacroAssembler::push_fp(unsigned int bitset, Register stack) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// SVE
|
||||
if (use_sve && sve_vector_size_in_bytes > 16) {
|
||||
sub(stack, stack, sve_vector_size_in_bytes * count);
|
||||
for (int i = 0; i < count; i++) {
|
||||
sve_str(as_FloatRegister(regs[i]), Address(stack, i));
|
||||
}
|
||||
return count * sve_vector_size_in_bytes / 8;
|
||||
}
|
||||
|
||||
// NEON
|
||||
if (count == 1) {
|
||||
strq(as_FloatRegister(regs[0]), Address(pre(stack, -wordSize * 2)));
|
||||
return 2;
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool odd = (count & 1) == 1;
|
||||
@@ -2169,19 +2161,12 @@ int MacroAssembler::push_fp(unsigned int bitset, Register stack) {
|
||||
}
|
||||
|
||||
assert(words_pushed == count, "oops, pushed(%d) != count(%d)", words_pushed, count);
|
||||
return count * 2;
|
||||
return count;
|
||||
}
|
||||
|
||||
// Return the number of dwords poped
|
||||
int MacroAssembler::pop_fp(unsigned int bitset, Register stack) {
|
||||
int words_pushed = 0;
|
||||
bool use_sve = false;
|
||||
int sve_vector_size_in_bytes = 0;
|
||||
|
||||
#ifdef COMPILER2
|
||||
use_sve = Matcher::supports_scalable_vector();
|
||||
sve_vector_size_in_bytes = Matcher::scalable_vector_reg_size(T_BYTE);
|
||||
#endif
|
||||
// Scan bitset to accumulate register pairs
|
||||
unsigned char regs[32];
|
||||
int count = 0;
|
||||
@@ -2195,19 +2180,9 @@ int MacroAssembler::pop_fp(unsigned int bitset, Register stack) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// SVE
|
||||
if (use_sve && sve_vector_size_in_bytes > 16) {
|
||||
for (int i = count - 1; i >= 0; i--) {
|
||||
sve_ldr(as_FloatRegister(regs[i]), Address(stack, i));
|
||||
}
|
||||
add(stack, stack, sve_vector_size_in_bytes * count);
|
||||
return count * sve_vector_size_in_bytes / 8;
|
||||
}
|
||||
|
||||
// NEON
|
||||
if (count == 1) {
|
||||
ldrq(as_FloatRegister(regs[0]), Address(post(stack, wordSize * 2)));
|
||||
return 2;
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool odd = (count & 1) == 1;
|
||||
@@ -2228,7 +2203,7 @@ int MacroAssembler::pop_fp(unsigned int bitset, Register stack) {
|
||||
|
||||
assert(words_pushed == count, "oops, pushed(%d) != count(%d)", words_pushed, count);
|
||||
|
||||
return count * 2;
|
||||
return count;
|
||||
}
|
||||
|
||||
#ifdef ASSERT
|
||||
@@ -2608,43 +2583,43 @@ void MacroAssembler::debug64(char* msg, int64_t pc, int64_t regs[])
|
||||
#endif
|
||||
if (os::message_box(msg, "Execution stopped, print registers?")) {
|
||||
ttyLocker ttyl;
|
||||
tty->print_cr(" pc = 0x%016" PRIx64, pc);
|
||||
tty->print_cr(" pc = 0x%016lx", pc);
|
||||
#ifndef PRODUCT
|
||||
tty->cr();
|
||||
findpc(pc);
|
||||
tty->cr();
|
||||
#endif
|
||||
tty->print_cr(" r0 = 0x%016" PRIx64, regs[0]);
|
||||
tty->print_cr(" r1 = 0x%016" PRIx64, regs[1]);
|
||||
tty->print_cr(" r2 = 0x%016" PRIx64, regs[2]);
|
||||
tty->print_cr(" r3 = 0x%016" PRIx64, regs[3]);
|
||||
tty->print_cr(" r4 = 0x%016" PRIx64, regs[4]);
|
||||
tty->print_cr(" r5 = 0x%016" PRIx64, regs[5]);
|
||||
tty->print_cr(" r6 = 0x%016" PRIx64, regs[6]);
|
||||
tty->print_cr(" r7 = 0x%016" PRIx64, regs[7]);
|
||||
tty->print_cr(" r8 = 0x%016" PRIx64, regs[8]);
|
||||
tty->print_cr(" r9 = 0x%016" PRIx64, regs[9]);
|
||||
tty->print_cr("r10 = 0x%016" PRIx64, regs[10]);
|
||||
tty->print_cr("r11 = 0x%016" PRIx64, regs[11]);
|
||||
tty->print_cr("r12 = 0x%016" PRIx64, regs[12]);
|
||||
tty->print_cr("r13 = 0x%016" PRIx64, regs[13]);
|
||||
tty->print_cr("r14 = 0x%016" PRIx64, regs[14]);
|
||||
tty->print_cr("r15 = 0x%016" PRIx64, regs[15]);
|
||||
tty->print_cr("r16 = 0x%016" PRIx64, regs[16]);
|
||||
tty->print_cr("r17 = 0x%016" PRIx64, regs[17]);
|
||||
tty->print_cr("r18 = 0x%016" PRIx64, regs[18]);
|
||||
tty->print_cr("r19 = 0x%016" PRIx64, regs[19]);
|
||||
tty->print_cr("r20 = 0x%016" PRIx64, regs[20]);
|
||||
tty->print_cr("r21 = 0x%016" PRIx64, regs[21]);
|
||||
tty->print_cr("r22 = 0x%016" PRIx64, regs[22]);
|
||||
tty->print_cr("r23 = 0x%016" PRIx64, regs[23]);
|
||||
tty->print_cr("r24 = 0x%016" PRIx64, regs[24]);
|
||||
tty->print_cr("r25 = 0x%016" PRIx64, regs[25]);
|
||||
tty->print_cr("r26 = 0x%016" PRIx64, regs[26]);
|
||||
tty->print_cr("r27 = 0x%016" PRIx64, regs[27]);
|
||||
tty->print_cr("r28 = 0x%016" PRIx64, regs[28]);
|
||||
tty->print_cr("r30 = 0x%016" PRIx64, regs[30]);
|
||||
tty->print_cr("r31 = 0x%016" PRIx64, regs[31]);
|
||||
tty->print_cr(" r0 = 0x%016lx", regs[0]);
|
||||
tty->print_cr(" r1 = 0x%016lx", regs[1]);
|
||||
tty->print_cr(" r2 = 0x%016lx", regs[2]);
|
||||
tty->print_cr(" r3 = 0x%016lx", regs[3]);
|
||||
tty->print_cr(" r4 = 0x%016lx", regs[4]);
|
||||
tty->print_cr(" r5 = 0x%016lx", regs[5]);
|
||||
tty->print_cr(" r6 = 0x%016lx", regs[6]);
|
||||
tty->print_cr(" r7 = 0x%016lx", regs[7]);
|
||||
tty->print_cr(" r8 = 0x%016lx", regs[8]);
|
||||
tty->print_cr(" r9 = 0x%016lx", regs[9]);
|
||||
tty->print_cr("r10 = 0x%016lx", regs[10]);
|
||||
tty->print_cr("r11 = 0x%016lx", regs[11]);
|
||||
tty->print_cr("r12 = 0x%016lx", regs[12]);
|
||||
tty->print_cr("r13 = 0x%016lx", regs[13]);
|
||||
tty->print_cr("r14 = 0x%016lx", regs[14]);
|
||||
tty->print_cr("r15 = 0x%016lx", regs[15]);
|
||||
tty->print_cr("r16 = 0x%016lx", regs[16]);
|
||||
tty->print_cr("r17 = 0x%016lx", regs[17]);
|
||||
tty->print_cr("r18 = 0x%016lx", regs[18]);
|
||||
tty->print_cr("r19 = 0x%016lx", regs[19]);
|
||||
tty->print_cr("r20 = 0x%016lx", regs[20]);
|
||||
tty->print_cr("r21 = 0x%016lx", regs[21]);
|
||||
tty->print_cr("r22 = 0x%016lx", regs[22]);
|
||||
tty->print_cr("r23 = 0x%016lx", regs[23]);
|
||||
tty->print_cr("r24 = 0x%016lx", regs[24]);
|
||||
tty->print_cr("r25 = 0x%016lx", regs[25]);
|
||||
tty->print_cr("r26 = 0x%016lx", regs[26]);
|
||||
tty->print_cr("r27 = 0x%016lx", regs[27]);
|
||||
tty->print_cr("r28 = 0x%016lx", regs[28]);
|
||||
tty->print_cr("r30 = 0x%016lx", regs[30]);
|
||||
tty->print_cr("r31 = 0x%016lx", regs[31]);
|
||||
BREAKPOINT;
|
||||
}
|
||||
}
|
||||
@@ -2676,39 +2651,23 @@ void MacroAssembler::pop_call_clobbered_registers_except(RegSet exclude) {
|
||||
pop(RegSet::range(r0, r18) - RegSet::of(rscratch1, rscratch2) - exclude, sp);
|
||||
}
|
||||
|
||||
void MacroAssembler::push_CPU_state(bool save_vectors, bool use_sve,
|
||||
int sve_vector_size_in_bytes) {
|
||||
void MacroAssembler::push_CPU_state(bool save_vectors) {
|
||||
int step = (save_vectors ? 8 : 4) * wordSize;
|
||||
push(0x3fffffff, sp); // integer registers except lr & sp
|
||||
if (save_vectors && use_sve && sve_vector_size_in_bytes > 16) {
|
||||
sub(sp, sp, sve_vector_size_in_bytes * FloatRegisterImpl::number_of_registers);
|
||||
for (int i = 0; i < FloatRegisterImpl::number_of_registers; i++) {
|
||||
sve_str(as_FloatRegister(i), Address(sp, i));
|
||||
}
|
||||
} else {
|
||||
int step = (save_vectors ? 8 : 4) * wordSize;
|
||||
mov(rscratch1, -step);
|
||||
sub(sp, sp, step);
|
||||
for (int i = 28; i >= 4; i -= 4) {
|
||||
st1(as_FloatRegister(i), as_FloatRegister(i+1), as_FloatRegister(i+2),
|
||||
as_FloatRegister(i+3), save_vectors ? T2D : T1D, Address(post(sp, rscratch1)));
|
||||
}
|
||||
st1(v0, v1, v2, v3, save_vectors ? T2D : T1D, sp);
|
||||
mov(rscratch1, -step);
|
||||
sub(sp, sp, step);
|
||||
for (int i = 28; i >= 4; i -= 4) {
|
||||
st1(as_FloatRegister(i), as_FloatRegister(i+1), as_FloatRegister(i+2),
|
||||
as_FloatRegister(i+3), save_vectors ? T2D : T1D, Address(post(sp, rscratch1)));
|
||||
}
|
||||
st1(v0, v1, v2, v3, save_vectors ? T2D : T1D, sp);
|
||||
}
|
||||
|
||||
void MacroAssembler::pop_CPU_state(bool restore_vectors, bool use_sve,
|
||||
int sve_vector_size_in_bytes) {
|
||||
if (restore_vectors && use_sve && sve_vector_size_in_bytes > 16) {
|
||||
for (int i = FloatRegisterImpl::number_of_registers - 1; i >= 0; i--) {
|
||||
sve_ldr(as_FloatRegister(i), Address(sp, i));
|
||||
}
|
||||
add(sp, sp, sve_vector_size_in_bytes * FloatRegisterImpl::number_of_registers);
|
||||
} else {
|
||||
int step = (restore_vectors ? 8 : 4) * wordSize;
|
||||
for (int i = 0; i <= 28; i += 4)
|
||||
ld1(as_FloatRegister(i), as_FloatRegister(i+1), as_FloatRegister(i+2),
|
||||
as_FloatRegister(i+3), restore_vectors ? T2D : T1D, Address(post(sp, step)));
|
||||
}
|
||||
void MacroAssembler::pop_CPU_state(bool restore_vectors) {
|
||||
int step = (restore_vectors ? 8 : 4) * wordSize;
|
||||
for (int i = 0; i <= 28; i += 4)
|
||||
ld1(as_FloatRegister(i), as_FloatRegister(i+1), as_FloatRegister(i+2),
|
||||
as_FloatRegister(i+3), restore_vectors ? T2D : T1D, Address(post(sp, step)));
|
||||
pop(0x3fffffff, sp); // integer registers except lr & sp
|
||||
}
|
||||
|
||||
@@ -2757,21 +2716,6 @@ Address MacroAssembler::spill_address(int size, int offset, Register tmp)
|
||||
return Address(base, offset);
|
||||
}
|
||||
|
||||
Address MacroAssembler::sve_spill_address(int sve_reg_size_in_bytes, int offset, Register tmp) {
|
||||
assert(offset >= 0, "spill to negative address?");
|
||||
|
||||
Register base = sp;
|
||||
|
||||
// An immediate offset in the range 0 to 255 which is multiplied
|
||||
// by the current vector or predicate register size in bytes.
|
||||
if (offset % sve_reg_size_in_bytes == 0 && offset < ((1<<8)*sve_reg_size_in_bytes)) {
|
||||
return Address(base, offset / sve_reg_size_in_bytes);
|
||||
}
|
||||
|
||||
add(tmp, base, offset);
|
||||
return Address(tmp);
|
||||
}
|
||||
|
||||
// Checks whether offset is aligned.
|
||||
// Returns true if it is, else false.
|
||||
bool MacroAssembler::merge_alignment_check(Register base,
|
||||
@@ -5281,24 +5225,3 @@ void MacroAssembler::cache_wbsync(bool is_pre) {
|
||||
membar(Assembler::AnyAny);
|
||||
}
|
||||
}
|
||||
|
||||
void MacroAssembler::verify_sve_vector_length() {
|
||||
Label verify_ok;
|
||||
assert(UseSVE > 0, "should only be used for SVE");
|
||||
movw(rscratch1, zr);
|
||||
sve_inc(rscratch1, B);
|
||||
subsw(zr, rscratch1, VM_Version::get_initial_sve_vector_length());
|
||||
br(EQ, verify_ok);
|
||||
stop("Error: SVE vector length has changed since jvm startup");
|
||||
bind(verify_ok);
|
||||
}
|
||||
|
||||
void MacroAssembler::verify_ptrue() {
|
||||
Label verify_ok;
|
||||
assert(UseSVE > 0, "should only be used for SVE");
|
||||
sve_cntp(rscratch1, B, ptrue, ptrue); // get true elements count.
|
||||
sve_dec(rscratch1, B);
|
||||
cbz(rscratch1, verify_ok);
|
||||
stop("Error: the preserved predicate register (p7) elements are not all true");
|
||||
bind(verify_ok);
|
||||
}
|
||||
|
||||
@@ -111,11 +111,15 @@ class MacroAssembler: public Assembler {
|
||||
// tmp_reg must be supplied and must not be rscratch1 or rscratch2
|
||||
// Optional slow case is for implementations (interpreter and C1) which branch to
|
||||
// slow case directly. Leaves condition codes set for C2's Fast_Lock node.
|
||||
void biased_locking_enter(Register lock_reg, Register obj_reg,
|
||||
Register swap_reg, Register tmp_reg,
|
||||
bool swap_reg_contains_mark,
|
||||
Label& done, Label* slow_case = NULL,
|
||||
BiasedLockingCounters* counters = NULL);
|
||||
// Returns offset of first potentially-faulting instruction for null
|
||||
// check info (currently consumed only by C1). If
|
||||
// swap_reg_contains_mark is true then returns -1 as it is assumed
|
||||
// the calling code has already passed any potential faults.
|
||||
int biased_locking_enter(Register lock_reg, Register obj_reg,
|
||||
Register swap_reg, Register tmp_reg,
|
||||
bool swap_reg_contains_mark,
|
||||
Label& done, Label* slow_case = NULL,
|
||||
BiasedLockingCounters* counters = NULL);
|
||||
void biased_locking_exit (Register obj_reg, Register temp_reg, Label& done);
|
||||
|
||||
|
||||
@@ -489,20 +493,31 @@ public:
|
||||
// now mov instructions for loading absolute addresses and 32 or
|
||||
// 64 bit integers
|
||||
|
||||
inline void mov(Register dst, address addr) { mov_immediate64(dst, (uint64_t)addr); }
|
||||
inline void mov(Register dst, address addr)
|
||||
{
|
||||
mov_immediate64(dst, (uint64_t)addr);
|
||||
}
|
||||
|
||||
inline void mov(Register dst, int imm64) { mov_immediate64(dst, (uint64_t)imm64); }
|
||||
inline void mov(Register dst, long imm64) { mov_immediate64(dst, (uint64_t)imm64); }
|
||||
inline void mov(Register dst, long long imm64) { mov_immediate64(dst, (uint64_t)imm64); }
|
||||
inline void mov(Register dst, unsigned int imm64) { mov_immediate64(dst, (uint64_t)imm64); }
|
||||
inline void mov(Register dst, unsigned long imm64) { mov_immediate64(dst, (uint64_t)imm64); }
|
||||
inline void mov(Register dst, unsigned long long imm64) { mov_immediate64(dst, (uint64_t)imm64); }
|
||||
inline void mov(Register dst, uint64_t imm64)
|
||||
{
|
||||
mov_immediate64(dst, imm64);
|
||||
}
|
||||
|
||||
inline void movw(Register dst, uint32_t imm32)
|
||||
{
|
||||
mov_immediate32(dst, imm32);
|
||||
}
|
||||
|
||||
inline void mov(Register dst, int64_t l)
|
||||
{
|
||||
mov(dst, (uint64_t)l);
|
||||
}
|
||||
|
||||
inline void mov(Register dst, int i)
|
||||
{
|
||||
mov(dst, (int64_t)i);
|
||||
}
|
||||
|
||||
void mov(Register dst, RegisterOrConstant src) {
|
||||
if (src.is_register())
|
||||
mov(dst, src.as_register());
|
||||
@@ -873,10 +888,8 @@ public:
|
||||
|
||||
DEBUG_ONLY(void verify_heapbase(const char* msg);)
|
||||
|
||||
void push_CPU_state(bool save_vectors = false, bool use_sve = false,
|
||||
int sve_vector_size_in_bytes = 0);
|
||||
void pop_CPU_state(bool restore_vectors = false, bool use_sve = false,
|
||||
int sve_vector_size_in_bytes = 0);
|
||||
void push_CPU_state(bool save_vectors = false);
|
||||
void pop_CPU_state(bool restore_vectors = false) ;
|
||||
|
||||
// Round up to a power of two
|
||||
void round_to(Register reg, int modulus);
|
||||
@@ -956,11 +969,6 @@ public:
|
||||
|
||||
Address argument_address(RegisterOrConstant arg_slot, int extra_slot_offset = 0);
|
||||
|
||||
void verify_sve_vector_length();
|
||||
void reinitialize_ptrue() {
|
||||
sve_ptrue(ptrue, B);
|
||||
}
|
||||
void verify_ptrue();
|
||||
|
||||
// Debugging
|
||||
|
||||
@@ -1310,7 +1318,6 @@ private:
|
||||
// Returns an address on the stack which is reachable with a ldr/str of size
|
||||
// Uses rscratch2 if the address is not directly reachable
|
||||
Address spill_address(int size, int offset, Register tmp=rscratch2);
|
||||
Address sve_spill_address(int sve_reg_size_in_bytes, int offset, Register tmp=rscratch2);
|
||||
|
||||
bool merge_alignment_check(Register base, size_t size, int64_t cur_offset, int64_t prev_offset) const;
|
||||
|
||||
@@ -1334,9 +1341,6 @@ public:
|
||||
void spill(FloatRegister Vx, SIMD_RegVariant T, int offset) {
|
||||
str(Vx, T, spill_address(1 << (int)T, offset));
|
||||
}
|
||||
void spill_sve_vector(FloatRegister Zx, int offset, int vector_reg_size_in_bytes) {
|
||||
sve_str(Zx, sve_spill_address(vector_reg_size_in_bytes, offset));
|
||||
}
|
||||
void unspill(Register Rx, bool is64, int offset) {
|
||||
if (is64) {
|
||||
ldr(Rx, spill_address(8, offset));
|
||||
@@ -1347,9 +1351,6 @@ public:
|
||||
void unspill(FloatRegister Vx, SIMD_RegVariant T, int offset) {
|
||||
ldr(Vx, T, spill_address(1 << (int)T, offset));
|
||||
}
|
||||
void unspill_sve_vector(FloatRegister Zx, int offset, int vector_reg_size_in_bytes) {
|
||||
sve_ldr(Zx, sve_spill_address(vector_reg_size_in_bytes, offset));
|
||||
}
|
||||
void spill_copy128(int src_offset, int dst_offset,
|
||||
Register tmp1=rscratch1, Register tmp2=rscratch2) {
|
||||
if (src_offset < 512 && (src_offset & 7) == 0 &&
|
||||
@@ -1363,15 +1364,7 @@ public:
|
||||
spill(tmp1, true, dst_offset+8);
|
||||
}
|
||||
}
|
||||
void spill_copy_sve_vector_stack_to_stack(int src_offset, int dst_offset,
|
||||
int sve_vec_reg_size_in_bytes) {
|
||||
assert(sve_vec_reg_size_in_bytes % 16 == 0, "unexpected sve vector reg size");
|
||||
for (int i = 0; i < sve_vec_reg_size_in_bytes / 16; i++) {
|
||||
spill_copy128(src_offset, dst_offset);
|
||||
src_offset += 16;
|
||||
dst_offset += 16;
|
||||
}
|
||||
}
|
||||
|
||||
void cache_wb(Address line);
|
||||
void cache_wbsync(bool is_pre);
|
||||
};
|
||||
|
||||
@@ -53,7 +53,7 @@ class NativeCall;
|
||||
class NativeInstruction {
|
||||
friend class Relocation;
|
||||
friend bool is_NativeCallTrampolineStub_at(address);
|
||||
public:
|
||||
public:
|
||||
enum {
|
||||
instruction_size = 4
|
||||
};
|
||||
@@ -62,16 +62,12 @@ public:
|
||||
return uint_at(0);
|
||||
}
|
||||
|
||||
bool is_blr() const {
|
||||
// blr(register) or br(register)
|
||||
return (encoding() & 0xff9ffc1f) == 0xd61f0000;
|
||||
}
|
||||
bool is_adr_aligned() const {
|
||||
// adr Xn, <label>, where label is aligned to 4 bytes (address of instruction).
|
||||
return (encoding() & 0xff000000) == 0x10000000;
|
||||
}
|
||||
bool is_blr() const { return (encoding() & 0xff9ffc1f) == 0xd61f0000; } // blr(register) or br(register)
|
||||
bool is_adr_aligned() const { return (encoding() & 0xff000000) == 0x10000000; } // adr Xn, <label>, where label is aligned to 4 bytes (address of instruction).
|
||||
|
||||
inline bool is_nop();
|
||||
inline bool is_illegal();
|
||||
inline bool is_return();
|
||||
bool is_jump();
|
||||
bool is_general_jump();
|
||||
inline bool is_jump_or_nop();
|
||||
@@ -82,25 +78,29 @@ public:
|
||||
bool is_sigill_zombie_not_entrant();
|
||||
bool is_stop();
|
||||
|
||||
protected:
|
||||
address addr_at(int offset) const { return address(this) + offset; }
|
||||
protected:
|
||||
address addr_at(int offset) const { return address(this) + offset; }
|
||||
|
||||
s_char sbyte_at(int offset) const { return *(s_char*)addr_at(offset); }
|
||||
u_char ubyte_at(int offset) const { return *(u_char*)addr_at(offset); }
|
||||
jint int_at(int offset) const { return *(jint*)addr_at(offset); }
|
||||
juint uint_at(int offset) const { return *(juint*)addr_at(offset); }
|
||||
address ptr_at(int offset) const { return *(address*)addr_at(offset); }
|
||||
oop oop_at(int offset) const { return *(oop*)addr_at(offset); }
|
||||
s_char sbyte_at(int offset) const { return *(s_char*) addr_at(offset); }
|
||||
u_char ubyte_at(int offset) const { return *(u_char*) addr_at(offset); }
|
||||
|
||||
void set_char_at(int offset, char c) { *addr_at(offset) = (u_char)c; }
|
||||
void set_int_at(int offset, jint i) { *(jint*)addr_at(offset) = i; }
|
||||
void set_uint_at(int offset, jint i) { *(juint*)addr_at(offset) = i; }
|
||||
void set_ptr_at(int offset, address ptr) { *(address*)addr_at(offset) = ptr; }
|
||||
void set_oop_at(int offset, oop o) { *(oop*)addr_at(offset) = o; }
|
||||
jint int_at(int offset) const { return *(jint*) addr_at(offset); }
|
||||
juint uint_at(int offset) const { return *(juint*) addr_at(offset); }
|
||||
|
||||
address ptr_at(int offset) const { return *(address*) addr_at(offset); }
|
||||
|
||||
oop oop_at (int offset) const { return *(oop*) addr_at(offset); }
|
||||
|
||||
|
||||
void set_char_at(int offset, char c) { *addr_at(offset) = (u_char)c; }
|
||||
void set_int_at(int offset, jint i) { *(jint*)addr_at(offset) = i; }
|
||||
void set_uint_at(int offset, jint i) { *(juint*)addr_at(offset) = i; }
|
||||
void set_ptr_at (int offset, address ptr) { *(address*) addr_at(offset) = ptr; }
|
||||
void set_oop_at (int offset, oop o) { *(oop*) addr_at(offset) = o; }
|
||||
|
||||
void wrote(int offset);
|
||||
|
||||
public:
|
||||
public:
|
||||
|
||||
inline friend NativeInstruction* nativeInstruction_at(address address);
|
||||
|
||||
@@ -146,7 +146,7 @@ inline NativeInstruction* nativeInstruction_at(address address) {
|
||||
}
|
||||
|
||||
// The natural type of an AArch64 instruction is uint32_t
|
||||
inline NativeInstruction* nativeInstruction_at(uint32_t* address) {
|
||||
inline NativeInstruction* nativeInstruction_at(uint32_t *address) {
|
||||
return (NativeInstruction*)address;
|
||||
}
|
||||
|
||||
@@ -171,15 +171,17 @@ public:
|
||||
address plt_c2i_stub() const;
|
||||
void set_stub_to_clean();
|
||||
|
||||
void reset_to_plt_resolve_call();
|
||||
void set_destination_mt_safe(address dest);
|
||||
void reset_to_plt_resolve_call();
|
||||
void set_destination_mt_safe(address dest);
|
||||
|
||||
void verify() const;
|
||||
};
|
||||
|
||||
inline NativePltCall* nativePltCall_at(address address) {
|
||||
NativePltCall* call = (NativePltCall*)address;
|
||||
DEBUG_ONLY(call->verify());
|
||||
NativePltCall* call = (NativePltCall*) address;
|
||||
#ifdef ASSERT
|
||||
call->verify();
|
||||
#endif
|
||||
return call;
|
||||
}
|
||||
|
||||
@@ -194,7 +196,7 @@ inline NativeCall* nativeCall_at(address address);
|
||||
// DSO calls, etc.).
|
||||
|
||||
class NativeCall: public NativeInstruction {
|
||||
public:
|
||||
public:
|
||||
enum Aarch64_specific_constants {
|
||||
instruction_size = 4,
|
||||
instruction_offset = 0,
|
||||
@@ -202,14 +204,14 @@ public:
|
||||
return_address_offset = 4
|
||||
};
|
||||
|
||||
address instruction_address() const { return addr_at(instruction_offset); }
|
||||
address next_instruction_address() const { return addr_at(return_address_offset); }
|
||||
int displacement() const { return (int_at(displacement_offset) << 6) >> 4; }
|
||||
address displacement_address() const { return addr_at(displacement_offset); }
|
||||
address return_address() const { return addr_at(return_address_offset); }
|
||||
address instruction_address() const { return addr_at(instruction_offset); }
|
||||
address next_instruction_address() const { return addr_at(return_address_offset); }
|
||||
int displacement() const { return (int_at(displacement_offset) << 6) >> 4; }
|
||||
address displacement_address() const { return addr_at(displacement_offset); }
|
||||
address return_address() const { return addr_at(return_address_offset); }
|
||||
address destination() const;
|
||||
|
||||
void set_destination(address dest) {
|
||||
void set_destination(address dest) {
|
||||
int offset = dest - instruction_address();
|
||||
unsigned int insn = 0b100101 << 26;
|
||||
assert((offset & 3) == 0, "should be");
|
||||
@@ -219,8 +221,9 @@ public:
|
||||
set_int_at(displacement_offset, insn);
|
||||
}
|
||||
|
||||
void verify_alignment() { ; }
|
||||
void verify();
|
||||
void verify_alignment() { ; }
|
||||
void verify();
|
||||
void print();
|
||||
|
||||
// Creation
|
||||
inline friend NativeCall* nativeCall_at(address address);
|
||||
@@ -266,29 +269,32 @@ public:
|
||||
|
||||
inline NativeCall* nativeCall_at(address address) {
|
||||
NativeCall* call = (NativeCall*)(address - NativeCall::instruction_offset);
|
||||
DEBUG_ONLY(call->verify());
|
||||
#ifdef ASSERT
|
||||
call->verify();
|
||||
#endif
|
||||
return call;
|
||||
}
|
||||
|
||||
inline NativeCall* nativeCall_before(address return_address) {
|
||||
NativeCall* call = (NativeCall*)(return_address - NativeCall::return_address_offset);
|
||||
DEBUG_ONLY(call->verify());
|
||||
#ifdef ASSERT
|
||||
call->verify();
|
||||
#endif
|
||||
return call;
|
||||
}
|
||||
|
||||
// An interface for accessing/manipulating native mov reg, imm instructions.
|
||||
// (used to manipulate inlined 64-bit data calls, etc.)
|
||||
class NativeMovConstReg: public NativeInstruction {
|
||||
public:
|
||||
public:
|
||||
enum Aarch64_specific_constants {
|
||||
instruction_size = 3 * 4, // movz, movk, movk. See movptr().
|
||||
instruction_offset = 0,
|
||||
displacement_offset = 0,
|
||||
};
|
||||
|
||||
address instruction_address() const { return addr_at(instruction_offset); }
|
||||
|
||||
address next_instruction_address() const {
|
||||
address instruction_address() const { return addr_at(instruction_offset); }
|
||||
address next_instruction_address() const {
|
||||
if (nativeInstruction_at(instruction_address())->is_movz())
|
||||
// Assume movz, movk, movk
|
||||
return addr_at(instruction_size);
|
||||
@@ -301,7 +307,7 @@ public:
|
||||
}
|
||||
|
||||
intptr_t data() const;
|
||||
void set_data(intptr_t x);
|
||||
void set_data(intptr_t x);
|
||||
|
||||
void flush() {
|
||||
if (! maybe_cpool_ref(instruction_address())) {
|
||||
@@ -309,8 +315,8 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void verify();
|
||||
void print();
|
||||
void verify();
|
||||
void print();
|
||||
|
||||
// Creation
|
||||
inline friend NativeMovConstReg* nativeMovConstReg_at(address address);
|
||||
@@ -319,23 +325,29 @@ public:
|
||||
|
||||
inline NativeMovConstReg* nativeMovConstReg_at(address address) {
|
||||
NativeMovConstReg* test = (NativeMovConstReg*)(address - NativeMovConstReg::instruction_offset);
|
||||
DEBUG_ONLY(test->verify());
|
||||
#ifdef ASSERT
|
||||
test->verify();
|
||||
#endif
|
||||
return test;
|
||||
}
|
||||
|
||||
inline NativeMovConstReg* nativeMovConstReg_before(address address) {
|
||||
NativeMovConstReg* test = (NativeMovConstReg*)(address - NativeMovConstReg::instruction_size - NativeMovConstReg::instruction_offset);
|
||||
DEBUG_ONLY(test->verify());
|
||||
#ifdef ASSERT
|
||||
test->verify();
|
||||
#endif
|
||||
return test;
|
||||
}
|
||||
|
||||
class NativeMovConstRegPatching: public NativeMovConstReg {
|
||||
private:
|
||||
friend NativeMovConstRegPatching* nativeMovConstRegPatching_at(address address) {
|
||||
private:
|
||||
friend NativeMovConstRegPatching* nativeMovConstRegPatching_at(address address) {
|
||||
NativeMovConstRegPatching* test = (NativeMovConstRegPatching*)(address - instruction_offset);
|
||||
DEBUG_ONLY(test->verify());
|
||||
#ifdef ASSERT
|
||||
test->verify();
|
||||
#endif
|
||||
return test;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// An interface for accessing/manipulating native moves of the form:
|
||||
@@ -362,7 +374,7 @@ class NativeMovRegMem: public NativeInstruction {
|
||||
next_instruction_offset = 4
|
||||
};
|
||||
|
||||
public:
|
||||
public:
|
||||
// helper
|
||||
int instruction_start() const { return instruction_offset; }
|
||||
|
||||
@@ -370,32 +382,30 @@ public:
|
||||
|
||||
int num_bytes_to_end_of_patch() const { return instruction_offset + instruction_size; }
|
||||
|
||||
int offset() const;
|
||||
int offset() const;
|
||||
|
||||
void set_offset(int x);
|
||||
void set_offset(int x);
|
||||
|
||||
void add_offset_in_bytes(int add_offset) {
|
||||
set_offset(offset() + add_offset);
|
||||
}
|
||||
void add_offset_in_bytes(int add_offset) { set_offset ( ( offset() + add_offset ) ); }
|
||||
|
||||
void verify();
|
||||
void print ();
|
||||
|
||||
private:
|
||||
inline friend NativeMovRegMem* nativeMovRegMem_at(address address);
|
||||
private:
|
||||
inline friend NativeMovRegMem* nativeMovRegMem_at (address address);
|
||||
};
|
||||
|
||||
inline NativeMovRegMem* nativeMovRegMem_at(address address) {
|
||||
inline NativeMovRegMem* nativeMovRegMem_at (address address) {
|
||||
NativeMovRegMem* test = (NativeMovRegMem*)(address - NativeMovRegMem::instruction_offset);
|
||||
DEBUG_ONLY(test->verify());
|
||||
#ifdef ASSERT
|
||||
test->verify();
|
||||
#endif
|
||||
return test;
|
||||
}
|
||||
|
||||
class NativeMovRegMemPatching: public NativeMovRegMem {
|
||||
private:
|
||||
friend NativeMovRegMemPatching* nativeMovRegMemPatching_at(address address) {
|
||||
Unimplemented();
|
||||
return 0;
|
||||
}
|
||||
private:
|
||||
friend NativeMovRegMemPatching* nativeMovRegMemPatching_at (address address) {Unimplemented(); return 0; }
|
||||
};
|
||||
|
||||
// An interface for accessing/manipulating native leal instruction of form:
|
||||
@@ -409,8 +419,10 @@ class NativeLoadAddress: public NativeInstruction {
|
||||
next_instruction_offset = 4
|
||||
};
|
||||
|
||||
public:
|
||||
public:
|
||||
void verify();
|
||||
void print ();
|
||||
|
||||
};
|
||||
|
||||
// adrp x16, #page
|
||||
@@ -429,7 +441,7 @@ public:
|
||||
address next_instruction_address() const { return return_address(); }
|
||||
intptr_t data() const;
|
||||
void set_data(intptr_t data) {
|
||||
intptr_t* addr = (intptr_t*)got_address();
|
||||
intptr_t *addr = (intptr_t *) got_address();
|
||||
*addr = data;
|
||||
}
|
||||
|
||||
@@ -439,13 +451,15 @@ private:
|
||||
};
|
||||
|
||||
inline NativeLoadGot* nativeLoadGot_at(address addr) {
|
||||
NativeLoadGot* load = (NativeLoadGot*)addr;
|
||||
DEBUG_ONLY(load->verify());
|
||||
NativeLoadGot* load = (NativeLoadGot*) addr;
|
||||
#ifdef ASSERT
|
||||
load->verify();
|
||||
#endif
|
||||
return load;
|
||||
}
|
||||
|
||||
class NativeJump: public NativeInstruction {
|
||||
public:
|
||||
public:
|
||||
enum AArch64_specific_constants {
|
||||
instruction_size = 4,
|
||||
instruction_offset = 0,
|
||||
@@ -453,8 +467,8 @@ public:
|
||||
next_instruction_offset = 4
|
||||
};
|
||||
|
||||
address instruction_address() const { return addr_at(instruction_offset); }
|
||||
address next_instruction_address() const { return addr_at(instruction_size); }
|
||||
address instruction_address() const { return addr_at(instruction_offset); }
|
||||
address next_instruction_address() const { return addr_at(instruction_size); }
|
||||
address jump_destination() const;
|
||||
void set_jump_destination(address dest);
|
||||
|
||||
@@ -472,7 +486,9 @@ public:
|
||||
|
||||
inline NativeJump* nativeJump_at(address address) {
|
||||
NativeJump* jump = (NativeJump*)(address - NativeJump::instruction_offset);
|
||||
DEBUG_ONLY(jump->verify());
|
||||
#ifdef ASSERT
|
||||
jump->verify();
|
||||
#endif
|
||||
return jump;
|
||||
}
|
||||
|
||||
@@ -495,7 +511,7 @@ public:
|
||||
|
||||
inline NativeGeneralJump* nativeGeneralJump_at(address address) {
|
||||
NativeGeneralJump* jump = (NativeGeneralJump*)(address);
|
||||
DEBUG_ONLY(jump->verify());
|
||||
debug_only(jump->verify();)
|
||||
return jump;
|
||||
}
|
||||
|
||||
@@ -513,47 +529,46 @@ public:
|
||||
address next_instruction_address() const { return addr_at(instruction_size); }
|
||||
bool is_GotJump() const;
|
||||
|
||||
void set_jump_destination(address dest) {
|
||||
address* got = (address*)got_address();
|
||||
void set_jump_destination(address dest) {
|
||||
address* got = (address *)got_address();
|
||||
*got = dest;
|
||||
}
|
||||
};
|
||||
|
||||
inline NativeGotJump* nativeGotJump_at(address addr) {
|
||||
NativeGotJump* jump = (NativeGotJump*)(addr);
|
||||
DEBUG_ONLY(jump->verify());
|
||||
return jump;
|
||||
}
|
||||
|
||||
class NativePopReg : public NativeInstruction {
|
||||
public:
|
||||
public:
|
||||
// Insert a pop instruction
|
||||
static void insert(address code_pos, Register reg);
|
||||
};
|
||||
|
||||
|
||||
class NativeIllegalInstruction: public NativeInstruction {
|
||||
public:
|
||||
public:
|
||||
// Insert illegal opcode as specific address
|
||||
static void insert(address code_pos);
|
||||
};
|
||||
|
||||
// return instruction that does not pop values of the stack
|
||||
class NativeReturn: public NativeInstruction {
|
||||
public:
|
||||
public:
|
||||
};
|
||||
|
||||
// return instruction that does pop values of the stack
|
||||
class NativeReturnX: public NativeInstruction {
|
||||
public:
|
||||
public:
|
||||
};
|
||||
|
||||
// Simple test vs memory
|
||||
class NativeTstRegMem: public NativeInstruction {
|
||||
public:
|
||||
public:
|
||||
};
|
||||
|
||||
inline bool NativeInstruction::is_nop() {
|
||||
inline bool NativeInstruction::is_nop() {
|
||||
uint32_t insn = *(uint32_t*)addr_at(0);
|
||||
return insn == 0xd503201f;
|
||||
}
|
||||
@@ -583,7 +598,7 @@ inline bool NativeInstruction::is_jump_or_nop() {
|
||||
|
||||
// Call trampoline stubs.
|
||||
class NativeCallTrampolineStub : public NativeInstruction {
|
||||
public:
|
||||
public:
|
||||
|
||||
enum AArch64_specific_constants {
|
||||
instruction_size = 4 * 4,
|
||||
@@ -592,7 +607,7 @@ public:
|
||||
next_instruction_offset = 4 * 4
|
||||
};
|
||||
|
||||
address destination(nmethod* nm = NULL) const;
|
||||
address destination(nmethod *nm = NULL) const;
|
||||
void set_destination(address new_destination);
|
||||
ptrdiff_t destination_offset() const;
|
||||
};
|
||||
@@ -602,7 +617,7 @@ inline bool is_NativeCallTrampolineStub_at(address addr) {
|
||||
// ldr xscratch1, L
|
||||
// br xscratch1
|
||||
// L:
|
||||
uint32_t* i = (uint32_t*)addr;
|
||||
uint32_t *i = (uint32_t *)addr;
|
||||
return i[0] == 0x58000048 && i[1] == 0xd61f0100;
|
||||
}
|
||||
|
||||
@@ -617,7 +632,7 @@ public:
|
||||
void set_kind(int order_kind) { Instruction_aarch64::patch(addr_at(0), 11, 8, order_kind); }
|
||||
};
|
||||
|
||||
inline NativeMembar* NativeMembar_at(address addr) {
|
||||
inline NativeMembar *NativeMembar_at(address addr) {
|
||||
assert(nativeInstruction_at(addr)->is_Membar(), "no membar found");
|
||||
return (NativeMembar*)addr;
|
||||
}
|
||||
@@ -671,9 +686,8 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
inline NativeLdSt* NativeLdSt_at(address addr) {
|
||||
inline NativeLdSt *NativeLdSt_at(address addr) {
|
||||
assert(nativeInstruction_at(addr)->is_Imm_LdSt(), "no immediate load/store found");
|
||||
return (NativeLdSt*)addr;
|
||||
}
|
||||
|
||||
#endif // CPU_AARCH64_NATIVEINST_AARCH64_HPP
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, Red Hat Inc. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@@ -33,6 +33,8 @@
|
||||
// This is the hook for finding a register in an "well-known" location,
|
||||
// such as a register block of a predetermined format.
|
||||
// Since there is none, we just return NULL.
|
||||
// See registerMap_sparc.hpp for an example of grabbing registers
|
||||
// from register save areas of a standard layout.
|
||||
address pd_location(VMReg reg) const {return NULL;}
|
||||
|
||||
// no PD state to clear or copy:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved.
|
||||
* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, Red Hat Inc. All rights reserved.
|
||||
* 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,9 +33,6 @@ const int ConcreteRegisterImpl::max_fpr
|
||||
= ConcreteRegisterImpl::max_gpr +
|
||||
FloatRegisterImpl::number_of_registers * FloatRegisterImpl::max_slots_per_register;
|
||||
|
||||
const int ConcreteRegisterImpl::max_pr
|
||||
= ConcreteRegisterImpl::max_fpr + PRegisterImpl::number_of_registers;
|
||||
|
||||
const char* RegisterImpl::name() const {
|
||||
const char* names[number_of_registers] = {
|
||||
"c_rarg0", "c_rarg1", "c_rarg2", "c_rarg3", "c_rarg4", "c_rarg5", "c_rarg6", "c_rarg7",
|
||||
@@ -57,11 +54,3 @@ const char* FloatRegisterImpl::name() const {
|
||||
};
|
||||
return is_valid() ? names[encoding()] : "noreg";
|
||||
}
|
||||
|
||||
const char* PRegisterImpl::name() const {
|
||||
const char* names[number_of_registers] = {
|
||||
"p0", "p1", "p2", "p3", "p4", "p5", "p6", "p7",
|
||||
"p8", "p9", "p10", "p11", "p12", "p13", "p14", "p15"
|
||||
};
|
||||
return is_valid() ? names[encoding()] : "noreg";
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@@ -129,10 +129,9 @@ class FloatRegisterImpl: public AbstractRegisterImpl {
|
||||
public:
|
||||
enum {
|
||||
number_of_registers = 32,
|
||||
max_slots_per_register = 8,
|
||||
max_slots_per_register = 4,
|
||||
save_slots_per_register = 2,
|
||||
slots_per_neon_register = 4,
|
||||
extra_save_slots_per_neon_register = slots_per_neon_register - save_slots_per_register
|
||||
extra_save_slots_per_register = max_slots_per_register - save_slots_per_register
|
||||
};
|
||||
|
||||
// construction
|
||||
@@ -188,88 +187,6 @@ CONSTANT_REGISTER_DECLARATION(FloatRegister, v29 , (29));
|
||||
CONSTANT_REGISTER_DECLARATION(FloatRegister, v30 , (30));
|
||||
CONSTANT_REGISTER_DECLARATION(FloatRegister, v31 , (31));
|
||||
|
||||
// SVE vector registers, shared with the SIMD&FP v0-v31. Vn maps to Zn[127:0].
|
||||
CONSTANT_REGISTER_DECLARATION(FloatRegister, z0 , ( 0));
|
||||
CONSTANT_REGISTER_DECLARATION(FloatRegister, z1 , ( 1));
|
||||
CONSTANT_REGISTER_DECLARATION(FloatRegister, z2 , ( 2));
|
||||
CONSTANT_REGISTER_DECLARATION(FloatRegister, z3 , ( 3));
|
||||
CONSTANT_REGISTER_DECLARATION(FloatRegister, z4 , ( 4));
|
||||
CONSTANT_REGISTER_DECLARATION(FloatRegister, z5 , ( 5));
|
||||
CONSTANT_REGISTER_DECLARATION(FloatRegister, z6 , ( 6));
|
||||
CONSTANT_REGISTER_DECLARATION(FloatRegister, z7 , ( 7));
|
||||
CONSTANT_REGISTER_DECLARATION(FloatRegister, z8 , ( 8));
|
||||
CONSTANT_REGISTER_DECLARATION(FloatRegister, z9 , ( 9));
|
||||
CONSTANT_REGISTER_DECLARATION(FloatRegister, z10 , (10));
|
||||
CONSTANT_REGISTER_DECLARATION(FloatRegister, z11 , (11));
|
||||
CONSTANT_REGISTER_DECLARATION(FloatRegister, z12 , (12));
|
||||
CONSTANT_REGISTER_DECLARATION(FloatRegister, z13 , (13));
|
||||
CONSTANT_REGISTER_DECLARATION(FloatRegister, z14 , (14));
|
||||
CONSTANT_REGISTER_DECLARATION(FloatRegister, z15 , (15));
|
||||
CONSTANT_REGISTER_DECLARATION(FloatRegister, z16 , (16));
|
||||
CONSTANT_REGISTER_DECLARATION(FloatRegister, z17 , (17));
|
||||
CONSTANT_REGISTER_DECLARATION(FloatRegister, z18 , (18));
|
||||
CONSTANT_REGISTER_DECLARATION(FloatRegister, z19 , (19));
|
||||
CONSTANT_REGISTER_DECLARATION(FloatRegister, z20 , (20));
|
||||
CONSTANT_REGISTER_DECLARATION(FloatRegister, z21 , (21));
|
||||
CONSTANT_REGISTER_DECLARATION(FloatRegister, z22 , (22));
|
||||
CONSTANT_REGISTER_DECLARATION(FloatRegister, z23 , (23));
|
||||
CONSTANT_REGISTER_DECLARATION(FloatRegister, z24 , (24));
|
||||
CONSTANT_REGISTER_DECLARATION(FloatRegister, z25 , (25));
|
||||
CONSTANT_REGISTER_DECLARATION(FloatRegister, z26 , (26));
|
||||
CONSTANT_REGISTER_DECLARATION(FloatRegister, z27 , (27));
|
||||
CONSTANT_REGISTER_DECLARATION(FloatRegister, z28 , (28));
|
||||
CONSTANT_REGISTER_DECLARATION(FloatRegister, z29 , (29));
|
||||
CONSTANT_REGISTER_DECLARATION(FloatRegister, z30 , (30));
|
||||
CONSTANT_REGISTER_DECLARATION(FloatRegister, z31 , (31));
|
||||
|
||||
|
||||
class PRegisterImpl;
|
||||
typedef PRegisterImpl* PRegister;
|
||||
inline PRegister as_PRegister(int encoding) {
|
||||
return (PRegister)(intptr_t)encoding;
|
||||
}
|
||||
|
||||
// The implementation of predicate registers for the architecture
|
||||
class PRegisterImpl: public AbstractRegisterImpl {
|
||||
public:
|
||||
enum {
|
||||
number_of_registers = 16,
|
||||
max_slots_per_register = 1
|
||||
};
|
||||
|
||||
// construction
|
||||
inline friend PRegister as_PRegister(int encoding);
|
||||
|
||||
VMReg as_VMReg();
|
||||
|
||||
// derived registers, offsets, and addresses
|
||||
PRegister successor() const { return as_PRegister(encoding() + 1); }
|
||||
|
||||
// accessors
|
||||
int encoding() const { assert(is_valid(), "invalid register"); return (intptr_t)this; }
|
||||
int encoding_nocheck() const { return (intptr_t)this; }
|
||||
bool is_valid() const { return 0 <= (intptr_t)this && (intptr_t)this < number_of_registers; }
|
||||
const char* name() const;
|
||||
};
|
||||
|
||||
// The predicate registers of SVE.
|
||||
CONSTANT_REGISTER_DECLARATION(PRegister, p0, ( 0));
|
||||
CONSTANT_REGISTER_DECLARATION(PRegister, p1, ( 1));
|
||||
CONSTANT_REGISTER_DECLARATION(PRegister, p2, ( 2));
|
||||
CONSTANT_REGISTER_DECLARATION(PRegister, p3, ( 3));
|
||||
CONSTANT_REGISTER_DECLARATION(PRegister, p4, ( 4));
|
||||
CONSTANT_REGISTER_DECLARATION(PRegister, p5, ( 5));
|
||||
CONSTANT_REGISTER_DECLARATION(PRegister, p6, ( 6));
|
||||
CONSTANT_REGISTER_DECLARATION(PRegister, p7, ( 7));
|
||||
CONSTANT_REGISTER_DECLARATION(PRegister, p8, ( 8));
|
||||
CONSTANT_REGISTER_DECLARATION(PRegister, p9, ( 9));
|
||||
CONSTANT_REGISTER_DECLARATION(PRegister, p10, (10));
|
||||
CONSTANT_REGISTER_DECLARATION(PRegister, p11, (11));
|
||||
CONSTANT_REGISTER_DECLARATION(PRegister, p12, (12));
|
||||
CONSTANT_REGISTER_DECLARATION(PRegister, p13, (13));
|
||||
CONSTANT_REGISTER_DECLARATION(PRegister, p14, (14));
|
||||
CONSTANT_REGISTER_DECLARATION(PRegister, p15, (15));
|
||||
|
||||
// Need to know the total number of registers of all sorts for SharedInfo.
|
||||
// Define a class that exports it.
|
||||
class ConcreteRegisterImpl : public AbstractRegisterImpl {
|
||||
@@ -282,14 +199,12 @@ class ConcreteRegisterImpl : public AbstractRegisterImpl {
|
||||
|
||||
number_of_registers = (RegisterImpl::max_slots_per_register * RegisterImpl::number_of_registers +
|
||||
FloatRegisterImpl::max_slots_per_register * FloatRegisterImpl::number_of_registers +
|
||||
PRegisterImpl::max_slots_per_register * PRegisterImpl::number_of_registers +
|
||||
1) // flags
|
||||
};
|
||||
|
||||
// added to make it compile
|
||||
static const int max_gpr;
|
||||
static const int max_fpr;
|
||||
static const int max_pr;
|
||||
};
|
||||
|
||||
// A set of registers
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, Red Hat Inc. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@@ -154,55 +154,3 @@ REGISTER_DEFINITION(Register, rthread);
|
||||
REGISTER_DEFINITION(Register, rheapbase);
|
||||
|
||||
REGISTER_DEFINITION(Register, r31_sp);
|
||||
|
||||
REGISTER_DEFINITION(FloatRegister, z0);
|
||||
REGISTER_DEFINITION(FloatRegister, z1);
|
||||
REGISTER_DEFINITION(FloatRegister, z2);
|
||||
REGISTER_DEFINITION(FloatRegister, z3);
|
||||
REGISTER_DEFINITION(FloatRegister, z4);
|
||||
REGISTER_DEFINITION(FloatRegister, z5);
|
||||
REGISTER_DEFINITION(FloatRegister, z6);
|
||||
REGISTER_DEFINITION(FloatRegister, z7);
|
||||
REGISTER_DEFINITION(FloatRegister, z8);
|
||||
REGISTER_DEFINITION(FloatRegister, z9);
|
||||
REGISTER_DEFINITION(FloatRegister, z10);
|
||||
REGISTER_DEFINITION(FloatRegister, z11);
|
||||
REGISTER_DEFINITION(FloatRegister, z12);
|
||||
REGISTER_DEFINITION(FloatRegister, z13);
|
||||
REGISTER_DEFINITION(FloatRegister, z14);
|
||||
REGISTER_DEFINITION(FloatRegister, z15);
|
||||
REGISTER_DEFINITION(FloatRegister, z16);
|
||||
REGISTER_DEFINITION(FloatRegister, z17);
|
||||
REGISTER_DEFINITION(FloatRegister, z18);
|
||||
REGISTER_DEFINITION(FloatRegister, z19);
|
||||
REGISTER_DEFINITION(FloatRegister, z20);
|
||||
REGISTER_DEFINITION(FloatRegister, z21);
|
||||
REGISTER_DEFINITION(FloatRegister, z22);
|
||||
REGISTER_DEFINITION(FloatRegister, z23);
|
||||
REGISTER_DEFINITION(FloatRegister, z24);
|
||||
REGISTER_DEFINITION(FloatRegister, z25);
|
||||
REGISTER_DEFINITION(FloatRegister, z26);
|
||||
REGISTER_DEFINITION(FloatRegister, z27);
|
||||
REGISTER_DEFINITION(FloatRegister, z28);
|
||||
REGISTER_DEFINITION(FloatRegister, z29);
|
||||
REGISTER_DEFINITION(FloatRegister, z30);
|
||||
REGISTER_DEFINITION(FloatRegister, z31);
|
||||
|
||||
REGISTER_DEFINITION(PRegister, p0);
|
||||
REGISTER_DEFINITION(PRegister, p1);
|
||||
REGISTER_DEFINITION(PRegister, p2);
|
||||
REGISTER_DEFINITION(PRegister, p3);
|
||||
REGISTER_DEFINITION(PRegister, p4);
|
||||
REGISTER_DEFINITION(PRegister, p5);
|
||||
REGISTER_DEFINITION(PRegister, p6);
|
||||
REGISTER_DEFINITION(PRegister, p7);
|
||||
REGISTER_DEFINITION(PRegister, p8);
|
||||
REGISTER_DEFINITION(PRegister, p9);
|
||||
REGISTER_DEFINITION(PRegister, p10);
|
||||
REGISTER_DEFINITION(PRegister, p11);
|
||||
REGISTER_DEFINITION(PRegister, p12);
|
||||
REGISTER_DEFINITION(PRegister, p13);
|
||||
REGISTER_DEFINITION(PRegister, p14);
|
||||
REGISTER_DEFINITION(PRegister, p15);
|
||||
|
||||
REGISTER_DEFINITION(PRegister, ptrue);
|
||||
|
||||
@@ -115,28 +115,11 @@ class RegisterSaver {
|
||||
};
|
||||
|
||||
OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_frame_words, int* total_frame_words, bool save_vectors) {
|
||||
bool use_sve = false;
|
||||
int sve_vector_size_in_bytes = 0;
|
||||
int sve_vector_size_in_slots = 0;
|
||||
|
||||
#ifdef COMPILER2
|
||||
use_sve = Matcher::supports_scalable_vector();
|
||||
sve_vector_size_in_bytes = Matcher::scalable_vector_reg_size(T_BYTE);
|
||||
sve_vector_size_in_slots = Matcher::scalable_vector_reg_size(T_FLOAT);
|
||||
#endif
|
||||
|
||||
#if COMPILER2_OR_JVMCI
|
||||
if (save_vectors) {
|
||||
int vect_words = 0;
|
||||
int extra_save_slots_per_register = 0;
|
||||
// Save upper half of vector registers
|
||||
if (use_sve) {
|
||||
extra_save_slots_per_register = sve_vector_size_in_slots - FloatRegisterImpl::save_slots_per_register;
|
||||
} else {
|
||||
extra_save_slots_per_register = FloatRegisterImpl::extra_save_slots_per_neon_register;
|
||||
}
|
||||
vect_words = FloatRegisterImpl::number_of_registers * extra_save_slots_per_register /
|
||||
VMRegImpl::slots_per_word;
|
||||
int vect_words = FloatRegisterImpl::number_of_registers * FloatRegisterImpl::extra_save_slots_per_register /
|
||||
VMRegImpl::slots_per_word;
|
||||
additional_frame_words += vect_words;
|
||||
}
|
||||
#else
|
||||
@@ -155,7 +138,7 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_
|
||||
|
||||
// Save Integer and Float registers.
|
||||
__ enter();
|
||||
__ push_CPU_state(save_vectors, use_sve, sve_vector_size_in_bytes);
|
||||
__ push_CPU_state(save_vectors);
|
||||
|
||||
// Set an oopmap for the call site. This oopmap will map all
|
||||
// oop-registers and debug-info registers as callee-saved. This
|
||||
@@ -179,13 +162,8 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_
|
||||
|
||||
for (int i = 0; i < FloatRegisterImpl::number_of_registers; i++) {
|
||||
FloatRegister r = as_FloatRegister(i);
|
||||
int sp_offset = 0;
|
||||
if (save_vectors) {
|
||||
sp_offset = use_sve ? (sve_vector_size_in_slots * i) :
|
||||
(FloatRegisterImpl::slots_per_neon_register * i);
|
||||
} else {
|
||||
sp_offset = FloatRegisterImpl::save_slots_per_register * i;
|
||||
}
|
||||
int sp_offset = save_vectors ? (FloatRegisterImpl::max_slots_per_register * i) :
|
||||
(FloatRegisterImpl::save_slots_per_register * i);
|
||||
oop_map->set_callee_saved(VMRegImpl::stack2reg(sp_offset),
|
||||
r->as_VMReg());
|
||||
}
|
||||
@@ -194,15 +172,10 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_
|
||||
}
|
||||
|
||||
void RegisterSaver::restore_live_registers(MacroAssembler* masm, bool restore_vectors) {
|
||||
#ifdef COMPILER2
|
||||
__ pop_CPU_state(restore_vectors, Matcher::supports_scalable_vector(),
|
||||
Matcher::scalable_vector_reg_size(T_BYTE));
|
||||
#else
|
||||
#if !INCLUDE_JVMCI
|
||||
#if !COMPILER2_OR_JVMCI
|
||||
assert(!restore_vectors, "vectors are generated only by C2 and JVMCI");
|
||||
#endif
|
||||
__ pop_CPU_state(restore_vectors);
|
||||
#endif
|
||||
__ leave();
|
||||
|
||||
}
|
||||
@@ -850,7 +823,7 @@ int SharedRuntime::c_calling_convention(const BasicType *sig_bt,
|
||||
}
|
||||
|
||||
// On 64 bit we will store integer like items to the stack as
|
||||
// 64 bits items (Aarch64 abi) even though java would only store
|
||||
// 64 bits items (sparc abi) even though java would only store
|
||||
// 32bits for a parameter. On 32bit it will simply be 32 bits
|
||||
// So this routine will do 32->32 on 32bit and 32->64 on 64bit
|
||||
static void move32_64(MacroAssembler* masm, VMRegPair src, VMRegPair dst) {
|
||||
@@ -1869,11 +1842,6 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
|
||||
// Force this write out before the read below
|
||||
__ dmb(Assembler::ISH);
|
||||
|
||||
if (UseSVE > 0) {
|
||||
// Make sure that jni code does not change SVE vector length.
|
||||
__ verify_sve_vector_length();
|
||||
}
|
||||
|
||||
// check for safepoint operation in progress and/or pending suspend requests
|
||||
Label safepoint_in_progress, safepoint_in_progress_done;
|
||||
{
|
||||
@@ -2806,12 +2774,6 @@ SafepointBlob* SharedRuntime::generate_handler_blob(address call_ptr, int poll_t
|
||||
__ maybe_isb();
|
||||
__ membar(Assembler::LoadLoad | Assembler::LoadStore);
|
||||
|
||||
if (UseSVE > 0 && save_vectors) {
|
||||
// Reinitialize the ptrue predicate register, in case the external runtime
|
||||
// call clobbers ptrue reg, as we may return to SVE compiled code.
|
||||
__ reinitialize_ptrue();
|
||||
}
|
||||
|
||||
__ ldr(rscratch1, Address(rthread, Thread::pending_exception_offset()));
|
||||
__ cbz(rscratch1, noException);
|
||||
|
||||
|
||||
@@ -488,11 +488,6 @@ class StubGenerator: public StubCodeGenerator {
|
||||
__ call_VM_leaf(CAST_FROM_FN_PTR(address,
|
||||
SharedRuntime::exception_handler_for_return_address),
|
||||
rthread, c_rarg1);
|
||||
if (UseSVE > 0 ) {
|
||||
// Reinitialize the ptrue predicate register, in case the external runtime
|
||||
// call clobbers ptrue reg, as we may return to SVE compiled code.
|
||||
__ reinitialize_ptrue();
|
||||
}
|
||||
// we should not really care that lr is no longer the callee
|
||||
// address. we saved the value the handler needs in r19 so we can
|
||||
// just copy it to r3. however, the C2 handler will push its own
|
||||
@@ -3130,172 +3125,6 @@ class StubGenerator: public StubCodeGenerator {
|
||||
return start;
|
||||
}
|
||||
|
||||
// Arguments:
|
||||
//
|
||||
// Inputs:
|
||||
// c_rarg0 - byte[] source+offset
|
||||
// c_rarg1 - int[] SHA.state
|
||||
// c_rarg2 - int offset
|
||||
// c_rarg3 - int limit
|
||||
//
|
||||
address generate_sha512_implCompress(bool multi_block, const char *name) {
|
||||
static const uint64_t round_consts[80] = {
|
||||
0x428A2F98D728AE22L, 0x7137449123EF65CDL, 0xB5C0FBCFEC4D3B2FL,
|
||||
0xE9B5DBA58189DBBCL, 0x3956C25BF348B538L, 0x59F111F1B605D019L,
|
||||
0x923F82A4AF194F9BL, 0xAB1C5ED5DA6D8118L, 0xD807AA98A3030242L,
|
||||
0x12835B0145706FBEL, 0x243185BE4EE4B28CL, 0x550C7DC3D5FFB4E2L,
|
||||
0x72BE5D74F27B896FL, 0x80DEB1FE3B1696B1L, 0x9BDC06A725C71235L,
|
||||
0xC19BF174CF692694L, 0xE49B69C19EF14AD2L, 0xEFBE4786384F25E3L,
|
||||
0x0FC19DC68B8CD5B5L, 0x240CA1CC77AC9C65L, 0x2DE92C6F592B0275L,
|
||||
0x4A7484AA6EA6E483L, 0x5CB0A9DCBD41FBD4L, 0x76F988DA831153B5L,
|
||||
0x983E5152EE66DFABL, 0xA831C66D2DB43210L, 0xB00327C898FB213FL,
|
||||
0xBF597FC7BEEF0EE4L, 0xC6E00BF33DA88FC2L, 0xD5A79147930AA725L,
|
||||
0x06CA6351E003826FL, 0x142929670A0E6E70L, 0x27B70A8546D22FFCL,
|
||||
0x2E1B21385C26C926L, 0x4D2C6DFC5AC42AEDL, 0x53380D139D95B3DFL,
|
||||
0x650A73548BAF63DEL, 0x766A0ABB3C77B2A8L, 0x81C2C92E47EDAEE6L,
|
||||
0x92722C851482353BL, 0xA2BFE8A14CF10364L, 0xA81A664BBC423001L,
|
||||
0xC24B8B70D0F89791L, 0xC76C51A30654BE30L, 0xD192E819D6EF5218L,
|
||||
0xD69906245565A910L, 0xF40E35855771202AL, 0x106AA07032BBD1B8L,
|
||||
0x19A4C116B8D2D0C8L, 0x1E376C085141AB53L, 0x2748774CDF8EEB99L,
|
||||
0x34B0BCB5E19B48A8L, 0x391C0CB3C5C95A63L, 0x4ED8AA4AE3418ACBL,
|
||||
0x5B9CCA4F7763E373L, 0x682E6FF3D6B2B8A3L, 0x748F82EE5DEFB2FCL,
|
||||
0x78A5636F43172F60L, 0x84C87814A1F0AB72L, 0x8CC702081A6439ECL,
|
||||
0x90BEFFFA23631E28L, 0xA4506CEBDE82BDE9L, 0xBEF9A3F7B2C67915L,
|
||||
0xC67178F2E372532BL, 0xCA273ECEEA26619CL, 0xD186B8C721C0C207L,
|
||||
0xEADA7DD6CDE0EB1EL, 0xF57D4F7FEE6ED178L, 0x06F067AA72176FBAL,
|
||||
0x0A637DC5A2C898A6L, 0x113F9804BEF90DAEL, 0x1B710B35131C471BL,
|
||||
0x28DB77F523047D84L, 0x32CAAB7B40C72493L, 0x3C9EBE0A15C9BEBCL,
|
||||
0x431D67C49C100D4CL, 0x4CC5D4BECB3E42B6L, 0x597F299CFC657E2AL,
|
||||
0x5FCB6FAB3AD6FAECL, 0x6C44198C4A475817L
|
||||
};
|
||||
|
||||
// Double rounds for sha512.
|
||||
#define sha512_dround(dr, i0, i1, i2, i3, i4, rc0, rc1, in0, in1, in2, in3, in4) \
|
||||
if (dr < 36) \
|
||||
__ ld1(v##rc1, __ T2D, __ post(rscratch2, 16)); \
|
||||
__ addv(v5, __ T2D, v##rc0, v##in0); \
|
||||
__ ext(v6, __ T16B, v##i2, v##i3, 8); \
|
||||
__ ext(v5, __ T16B, v5, v5, 8); \
|
||||
__ ext(v7, __ T16B, v##i1, v##i2, 8); \
|
||||
__ addv(v##i3, __ T2D, v##i3, v5); \
|
||||
if (dr < 32) { \
|
||||
__ ext(v5, __ T16B, v##in3, v##in4, 8); \
|
||||
__ sha512su0(v##in0, __ T2D, v##in1); \
|
||||
} \
|
||||
__ sha512h(v##i3, __ T2D, v6, v7); \
|
||||
if (dr < 32) \
|
||||
__ sha512su1(v##in0, __ T2D, v##in2, v5); \
|
||||
__ addv(v##i4, __ T2D, v##i1, v##i3); \
|
||||
__ sha512h2(v##i3, __ T2D, v##i1, v##i0); \
|
||||
|
||||
__ align(CodeEntryAlignment);
|
||||
StubCodeMark mark(this, "StubRoutines", name);
|
||||
address start = __ pc();
|
||||
|
||||
Register buf = c_rarg0;
|
||||
Register state = c_rarg1;
|
||||
Register ofs = c_rarg2;
|
||||
Register limit = c_rarg3;
|
||||
|
||||
__ stpd(v8, v9, __ pre(sp, -64));
|
||||
__ stpd(v10, v11, Address(sp, 16));
|
||||
__ stpd(v12, v13, Address(sp, 32));
|
||||
__ stpd(v14, v15, Address(sp, 48));
|
||||
|
||||
Label sha512_loop;
|
||||
|
||||
// load state
|
||||
__ ld1(v8, v9, v10, v11, __ T2D, state);
|
||||
|
||||
// load first 4 round constants
|
||||
__ lea(rscratch1, ExternalAddress((address)round_consts));
|
||||
__ ld1(v20, v21, v22, v23, __ T2D, __ post(rscratch1, 64));
|
||||
|
||||
__ BIND(sha512_loop);
|
||||
// load 128B of data into v12..v19
|
||||
__ ld1(v12, v13, v14, v15, __ T2D, __ post(buf, 64));
|
||||
__ ld1(v16, v17, v18, v19, __ T2D, __ post(buf, 64));
|
||||
__ rev64(v12, __ T16B, v12);
|
||||
__ rev64(v13, __ T16B, v13);
|
||||
__ rev64(v14, __ T16B, v14);
|
||||
__ rev64(v15, __ T16B, v15);
|
||||
__ rev64(v16, __ T16B, v16);
|
||||
__ rev64(v17, __ T16B, v17);
|
||||
__ rev64(v18, __ T16B, v18);
|
||||
__ rev64(v19, __ T16B, v19);
|
||||
|
||||
__ mov(rscratch2, rscratch1);
|
||||
|
||||
__ mov(v0, __ T16B, v8);
|
||||
__ mov(v1, __ T16B, v9);
|
||||
__ mov(v2, __ T16B, v10);
|
||||
__ mov(v3, __ T16B, v11);
|
||||
|
||||
sha512_dround( 0, 0, 1, 2, 3, 4, 20, 24, 12, 13, 19, 16, 17);
|
||||
sha512_dround( 1, 3, 0, 4, 2, 1, 21, 25, 13, 14, 12, 17, 18);
|
||||
sha512_dround( 2, 2, 3, 1, 4, 0, 22, 26, 14, 15, 13, 18, 19);
|
||||
sha512_dround( 3, 4, 2, 0, 1, 3, 23, 27, 15, 16, 14, 19, 12);
|
||||
sha512_dround( 4, 1, 4, 3, 0, 2, 24, 28, 16, 17, 15, 12, 13);
|
||||
sha512_dround( 5, 0, 1, 2, 3, 4, 25, 29, 17, 18, 16, 13, 14);
|
||||
sha512_dround( 6, 3, 0, 4, 2, 1, 26, 30, 18, 19, 17, 14, 15);
|
||||
sha512_dround( 7, 2, 3, 1, 4, 0, 27, 31, 19, 12, 18, 15, 16);
|
||||
sha512_dround( 8, 4, 2, 0, 1, 3, 28, 24, 12, 13, 19, 16, 17);
|
||||
sha512_dround( 9, 1, 4, 3, 0, 2, 29, 25, 13, 14, 12, 17, 18);
|
||||
sha512_dround(10, 0, 1, 2, 3, 4, 30, 26, 14, 15, 13, 18, 19);
|
||||
sha512_dround(11, 3, 0, 4, 2, 1, 31, 27, 15, 16, 14, 19, 12);
|
||||
sha512_dround(12, 2, 3, 1, 4, 0, 24, 28, 16, 17, 15, 12, 13);
|
||||
sha512_dround(13, 4, 2, 0, 1, 3, 25, 29, 17, 18, 16, 13, 14);
|
||||
sha512_dround(14, 1, 4, 3, 0, 2, 26, 30, 18, 19, 17, 14, 15);
|
||||
sha512_dround(15, 0, 1, 2, 3, 4, 27, 31, 19, 12, 18, 15, 16);
|
||||
sha512_dround(16, 3, 0, 4, 2, 1, 28, 24, 12, 13, 19, 16, 17);
|
||||
sha512_dround(17, 2, 3, 1, 4, 0, 29, 25, 13, 14, 12, 17, 18);
|
||||
sha512_dround(18, 4, 2, 0, 1, 3, 30, 26, 14, 15, 13, 18, 19);
|
||||
sha512_dround(19, 1, 4, 3, 0, 2, 31, 27, 15, 16, 14, 19, 12);
|
||||
sha512_dround(20, 0, 1, 2, 3, 4, 24, 28, 16, 17, 15, 12, 13);
|
||||
sha512_dround(21, 3, 0, 4, 2, 1, 25, 29, 17, 18, 16, 13, 14);
|
||||
sha512_dround(22, 2, 3, 1, 4, 0, 26, 30, 18, 19, 17, 14, 15);
|
||||
sha512_dround(23, 4, 2, 0, 1, 3, 27, 31, 19, 12, 18, 15, 16);
|
||||
sha512_dround(24, 1, 4, 3, 0, 2, 28, 24, 12, 13, 19, 16, 17);
|
||||
sha512_dround(25, 0, 1, 2, 3, 4, 29, 25, 13, 14, 12, 17, 18);
|
||||
sha512_dround(26, 3, 0, 4, 2, 1, 30, 26, 14, 15, 13, 18, 19);
|
||||
sha512_dround(27, 2, 3, 1, 4, 0, 31, 27, 15, 16, 14, 19, 12);
|
||||
sha512_dround(28, 4, 2, 0, 1, 3, 24, 28, 16, 17, 15, 12, 13);
|
||||
sha512_dround(29, 1, 4, 3, 0, 2, 25, 29, 17, 18, 16, 13, 14);
|
||||
sha512_dround(30, 0, 1, 2, 3, 4, 26, 30, 18, 19, 17, 14, 15);
|
||||
sha512_dround(31, 3, 0, 4, 2, 1, 27, 31, 19, 12, 18, 15, 16);
|
||||
sha512_dround(32, 2, 3, 1, 4, 0, 28, 24, 12, 0, 0, 0, 0);
|
||||
sha512_dround(33, 4, 2, 0, 1, 3, 29, 25, 13, 0, 0, 0, 0);
|
||||
sha512_dround(34, 1, 4, 3, 0, 2, 30, 26, 14, 0, 0, 0, 0);
|
||||
sha512_dround(35, 0, 1, 2, 3, 4, 31, 27, 15, 0, 0, 0, 0);
|
||||
sha512_dround(36, 3, 0, 4, 2, 1, 24, 0, 16, 0, 0, 0, 0);
|
||||
sha512_dround(37, 2, 3, 1, 4, 0, 25, 0, 17, 0, 0, 0, 0);
|
||||
sha512_dround(38, 4, 2, 0, 1, 3, 26, 0, 18, 0, 0, 0, 0);
|
||||
sha512_dround(39, 1, 4, 3, 0, 2, 27, 0, 19, 0, 0, 0, 0);
|
||||
|
||||
__ addv(v8, __ T2D, v8, v0);
|
||||
__ addv(v9, __ T2D, v9, v1);
|
||||
__ addv(v10, __ T2D, v10, v2);
|
||||
__ addv(v11, __ T2D, v11, v3);
|
||||
|
||||
if (multi_block) {
|
||||
__ add(ofs, ofs, 128);
|
||||
__ cmp(ofs, limit);
|
||||
__ br(Assembler::LE, sha512_loop);
|
||||
__ mov(c_rarg0, ofs); // return ofs
|
||||
}
|
||||
|
||||
__ st1(v8, v9, v10, v11, __ T2D, state);
|
||||
|
||||
__ ldpd(v14, v15, Address(sp, 48));
|
||||
__ ldpd(v12, v13, Address(sp, 32));
|
||||
__ ldpd(v10, v11, Address(sp, 16));
|
||||
__ ldpd(v8, v9, __ post(sp, 64));
|
||||
|
||||
__ ret(lr);
|
||||
|
||||
return start;
|
||||
}
|
||||
|
||||
// Safefetch stubs.
|
||||
void generate_safefetch(const char* name, int size, address* entry,
|
||||
address* fault_pc, address* continuation_pc) {
|
||||
@@ -5023,12 +4852,6 @@ class StubGenerator: public StubCodeGenerator {
|
||||
__ reset_last_Java_frame(true);
|
||||
__ maybe_isb();
|
||||
|
||||
if (UseSVE > 0) {
|
||||
// Reinitialize the ptrue predicate register, in case the external runtime
|
||||
// call clobbers ptrue reg, as we may return to SVE compiled code.
|
||||
__ reinitialize_ptrue();
|
||||
}
|
||||
|
||||
__ leave();
|
||||
|
||||
// check for pending exceptions
|
||||
@@ -6029,10 +5852,6 @@ class StubGenerator: public StubCodeGenerator {
|
||||
StubRoutines::_sha256_implCompress = generate_sha256_implCompress(false, "sha256_implCompress");
|
||||
StubRoutines::_sha256_implCompressMB = generate_sha256_implCompress(true, "sha256_implCompressMB");
|
||||
}
|
||||
if (UseSHA512Intrinsics) {
|
||||
StubRoutines::_sha512_implCompress = generate_sha512_implCompress(false, "sha512_implCompress");
|
||||
StubRoutines::_sha512_implCompressMB = generate_sha512_implCompress(true, "sha512_implCompressMB");
|
||||
}
|
||||
|
||||
// generate Adler32 intrinsics code
|
||||
if (UseAdler32Intrinsics) {
|
||||
|
||||
@@ -1372,11 +1372,6 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) {
|
||||
__ push(dtos);
|
||||
__ push(ltos);
|
||||
|
||||
if (UseSVE > 0) {
|
||||
// Make sure that jni code does not change SVE vector length.
|
||||
__ verify_sve_vector_length();
|
||||
}
|
||||
|
||||
// change thread state
|
||||
__ mov(rscratch1, _thread_in_native_trans);
|
||||
__ lea(rscratch2, Address(rthread, JavaThread::thread_state_offset()));
|
||||
@@ -1585,9 +1580,6 @@ address TemplateInterpreterGenerator::generate_normal_entry(bool synchronized) {
|
||||
|
||||
// Make room for locals
|
||||
__ sub(rscratch1, esp, r3, ext::uxtx, 3);
|
||||
|
||||
// Padding between locals and fixed part of activation frame to ensure
|
||||
// SP is always 16-byte aligned.
|
||||
__ andr(sp, rscratch1, -16);
|
||||
|
||||
// r3 - # of additional locals
|
||||
|
||||
@@ -27,20 +27,16 @@
|
||||
#include "asm/macroAssembler.hpp"
|
||||
#include "asm/macroAssembler.inline.hpp"
|
||||
#include "memory/resourceArea.hpp"
|
||||
#include "runtime/arguments.hpp"
|
||||
#include "runtime/globals_extension.hpp"
|
||||
#include "runtime/java.hpp"
|
||||
#include "runtime/os.hpp"
|
||||
#include "runtime/stubCodeGenerator.hpp"
|
||||
#include "runtime/vm_version.hpp"
|
||||
#include "utilities/formatBuffer.hpp"
|
||||
#include "utilities/macros.hpp"
|
||||
|
||||
#include OS_HEADER_INLINE(os)
|
||||
|
||||
#include <asm/hwcap.h>
|
||||
#include <sys/auxv.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <asm/hwcap.h>
|
||||
|
||||
#ifndef HWCAP_AES
|
||||
#define HWCAP_AES (1<<3)
|
||||
@@ -66,24 +62,6 @@
|
||||
#define HWCAP_ATOMICS (1<<8)
|
||||
#endif
|
||||
|
||||
#ifndef HWCAP_SHA512
|
||||
#define HWCAP_SHA512 (1 << 21)
|
||||
#endif
|
||||
|
||||
#ifndef HWCAP_SVE
|
||||
#define HWCAP_SVE (1 << 22)
|
||||
#endif
|
||||
|
||||
#ifndef HWCAP2_SVE2
|
||||
#define HWCAP2_SVE2 (1 << 1)
|
||||
#endif
|
||||
|
||||
#ifndef PR_SVE_GET_VL
|
||||
// For old toolchains which do not have SVE related macros defined.
|
||||
#define PR_SVE_SET_VL 50
|
||||
#define PR_SVE_GET_VL 51
|
||||
#endif
|
||||
|
||||
int VM_Version::_cpu;
|
||||
int VM_Version::_model;
|
||||
int VM_Version::_model2;
|
||||
@@ -91,7 +69,6 @@ int VM_Version::_variant;
|
||||
int VM_Version::_revision;
|
||||
int VM_Version::_stepping;
|
||||
bool VM_Version::_dcpop;
|
||||
int VM_Version::_initial_sve_vector_length;
|
||||
VM_Version::PsrInfo VM_Version::_psr_info = { 0, };
|
||||
|
||||
static BufferBlob* stub_blob;
|
||||
@@ -134,6 +111,7 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void VM_Version::get_processor_features() {
|
||||
_supports_cx8 = true;
|
||||
_supports_atomic_getset4 = true;
|
||||
@@ -184,7 +162,6 @@ void VM_Version::get_processor_features() {
|
||||
}
|
||||
|
||||
uint64_t auxv = getauxval(AT_HWCAP);
|
||||
uint64_t auxv2 = getauxval(AT_HWCAP2);
|
||||
|
||||
char buf[512];
|
||||
|
||||
@@ -295,12 +272,6 @@ void VM_Version::get_processor_features() {
|
||||
}
|
||||
}
|
||||
|
||||
if (_cpu == CPU_ARM) {
|
||||
if (FLAG_IS_DEFAULT(UseSignumIntrinsic)) {
|
||||
FLAG_SET_DEFAULT(UseSignumIntrinsic, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (_cpu == CPU_ARM && (_model == 0xd07 || _model2 == 0xd07)) _features |= CPU_STXR_PREFETCH;
|
||||
// If an olde style /proc/cpuinfo (cpu_lines == 1) then if _model is an A57 (0xd07)
|
||||
// we assume the worst and assume we could be on a big little system and have
|
||||
@@ -314,10 +285,7 @@ void VM_Version::get_processor_features() {
|
||||
if (auxv & HWCAP_AES) strcat(buf, ", aes");
|
||||
if (auxv & HWCAP_SHA1) strcat(buf, ", sha1");
|
||||
if (auxv & HWCAP_SHA2) strcat(buf, ", sha256");
|
||||
if (auxv & HWCAP_SHA512) strcat(buf, ", sha512");
|
||||
if (auxv & HWCAP_ATOMICS) strcat(buf, ", lse");
|
||||
if (auxv & HWCAP_SVE) strcat(buf, ", sve");
|
||||
if (auxv2 & HWCAP2_SVE2) strcat(buf, ", sve2");
|
||||
|
||||
_features_string = os::strdup(buf);
|
||||
|
||||
@@ -390,11 +358,6 @@ void VM_Version::get_processor_features() {
|
||||
FLAG_SET_DEFAULT(UseFMA, true);
|
||||
}
|
||||
|
||||
if (UseMD5Intrinsics) {
|
||||
warning("MD5 intrinsics are not available on this CPU");
|
||||
FLAG_SET_DEFAULT(UseMD5Intrinsics, false);
|
||||
}
|
||||
|
||||
if (auxv & (HWCAP_SHA1 | HWCAP_SHA2)) {
|
||||
if (FLAG_IS_DEFAULT(UseSHA)) {
|
||||
FLAG_SET_DEFAULT(UseSHA, true);
|
||||
@@ -422,12 +385,7 @@ void VM_Version::get_processor_features() {
|
||||
FLAG_SET_DEFAULT(UseSHA256Intrinsics, false);
|
||||
}
|
||||
|
||||
if (UseSHA && (auxv & HWCAP_SHA512)) {
|
||||
// Do not auto-enable UseSHA512Intrinsics until it has been fully tested on hardware
|
||||
// if (FLAG_IS_DEFAULT(UseSHA512Intrinsics)) {
|
||||
// FLAG_SET_DEFAULT(UseSHA512Intrinsics, true);
|
||||
// }
|
||||
} else if (UseSHA512Intrinsics) {
|
||||
if (UseSHA512Intrinsics) {
|
||||
warning("Intrinsics for SHA-384 and SHA-512 crypto hash functions not available on this CPU.");
|
||||
FLAG_SET_DEFAULT(UseSHA512Intrinsics, false);
|
||||
}
|
||||
@@ -457,18 +415,6 @@ void VM_Version::get_processor_features() {
|
||||
FLAG_SET_DEFAULT(UseBlockZeroing, false);
|
||||
}
|
||||
|
||||
if (auxv & HWCAP_SVE) {
|
||||
if (FLAG_IS_DEFAULT(UseSVE)) {
|
||||
FLAG_SET_DEFAULT(UseSVE, (auxv2 & HWCAP2_SVE2) ? 2 : 1);
|
||||
}
|
||||
if (UseSVE > 0) {
|
||||
_initial_sve_vector_length = prctl(PR_SVE_GET_VL);
|
||||
}
|
||||
} else if (UseSVE > 0) {
|
||||
warning("UseSVE specified, but not supported on current CPU. Disabling SVE.");
|
||||
FLAG_SET_DEFAULT(UseSVE, 0);
|
||||
}
|
||||
|
||||
// This machine allows unaligned memory accesses
|
||||
if (FLAG_IS_DEFAULT(UseUnalignedAccesses)) {
|
||||
FLAG_SET_DEFAULT(UseUnalignedAccesses, true);
|
||||
@@ -503,50 +449,6 @@ void VM_Version::get_processor_features() {
|
||||
UseMontgomerySquareIntrinsic = true;
|
||||
}
|
||||
|
||||
if (UseSVE > 0) {
|
||||
if (FLAG_IS_DEFAULT(MaxVectorSize)) {
|
||||
MaxVectorSize = _initial_sve_vector_length;
|
||||
} else if (MaxVectorSize < 16) {
|
||||
warning("SVE does not support vector length less than 16 bytes. Disabling SVE.");
|
||||
UseSVE = 0;
|
||||
} else if ((MaxVectorSize % 16) == 0 && is_power_of_2(MaxVectorSize)) {
|
||||
int new_vl = prctl(PR_SVE_SET_VL, MaxVectorSize);
|
||||
_initial_sve_vector_length = new_vl;
|
||||
// If MaxVectorSize is larger than system largest supported SVE vector length, above prctl()
|
||||
// call will set task vector length to the system largest supported value. So, we also update
|
||||
// MaxVectorSize to that largest supported value.
|
||||
if (new_vl < 0) {
|
||||
vm_exit_during_initialization(
|
||||
err_msg("Current system does not support SVE vector length for MaxVectorSize: %d",
|
||||
(int)MaxVectorSize));
|
||||
} else if (new_vl != MaxVectorSize) {
|
||||
warning("Current system only supports max SVE vector length %d. Set MaxVectorSize to %d",
|
||||
new_vl, new_vl);
|
||||
}
|
||||
MaxVectorSize = new_vl;
|
||||
} else {
|
||||
vm_exit_during_initialization(err_msg("Unsupported MaxVectorSize: %d", (int)MaxVectorSize));
|
||||
}
|
||||
}
|
||||
|
||||
if (UseSVE == 0) { // NEON
|
||||
int min_vector_size = 8;
|
||||
int max_vector_size = 16;
|
||||
if (!FLAG_IS_DEFAULT(MaxVectorSize)) {
|
||||
if (!is_power_of_2(MaxVectorSize)) {
|
||||
vm_exit_during_initialization(err_msg("Unsupported MaxVectorSize: %d", (int)MaxVectorSize));
|
||||
} else if (MaxVectorSize < min_vector_size) {
|
||||
warning("MaxVectorSize must be at least %i on this platform", min_vector_size);
|
||||
FLAG_SET_DEFAULT(MaxVectorSize, min_vector_size);
|
||||
} else if (MaxVectorSize > max_vector_size) {
|
||||
warning("MaxVectorSize must be at most %i on this platform", max_vector_size);
|
||||
FLAG_SET_DEFAULT(MaxVectorSize, max_vector_size);
|
||||
}
|
||||
} else {
|
||||
FLAG_SET_DEFAULT(MaxVectorSize, 16);
|
||||
}
|
||||
}
|
||||
|
||||
if (FLAG_IS_DEFAULT(OptoScheduling)) {
|
||||
OptoScheduling = true;
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#define CPU_AARCH64_VM_VERSION_AARCH64_HPP
|
||||
|
||||
#include "runtime/abstract_vm_version.hpp"
|
||||
#include "runtime/globals_extension.hpp"
|
||||
#include "utilities/sizes.hpp"
|
||||
|
||||
class VM_Version : public Abstract_VM_Version {
|
||||
@@ -40,8 +41,6 @@ protected:
|
||||
static int _revision;
|
||||
static int _stepping;
|
||||
static bool _dcpop;
|
||||
static int _initial_sve_vector_length;
|
||||
|
||||
struct PsrInfo {
|
||||
uint32_t dczid_el0;
|
||||
uint32_t ctr_el0;
|
||||
@@ -107,7 +106,6 @@ public:
|
||||
static int cpu_variant() { return _variant; }
|
||||
static int cpu_revision() { return _revision; }
|
||||
static bool supports_dcpop() { return _dcpop; }
|
||||
static int get_initial_sve_vector_length() { return _initial_sve_vector_length; };
|
||||
static ByteSize dczid_el0_offset() { return byte_offset_of(PsrInfo, dczid_el0); }
|
||||
static ByteSize ctr_el0_offset() { return byte_offset_of(PsrInfo, ctr_el0); }
|
||||
static bool is_zva_enabled() {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved.
|
||||
* Copyright (c) 2006, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, Red Hat Inc. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@@ -36,8 +36,4 @@ inline VMReg FloatRegisterImpl::as_VMReg() {
|
||||
ConcreteRegisterImpl::max_gpr);
|
||||
}
|
||||
|
||||
inline VMReg PRegisterImpl::as_VMReg() {
|
||||
return VMRegImpl::as_VMReg(encoding() + ConcreteRegisterImpl::max_fpr);
|
||||
}
|
||||
|
||||
#endif // CPU_AARCH64_VMREG_AARCH64_INLINE_HPP
|
||||
|
||||
@@ -997,19 +997,15 @@ const int Matcher::float_pressure(int default_pressure_threshold) {
|
||||
return default_pressure_threshold;
|
||||
}
|
||||
|
||||
int Matcher::regnum_to_fpu_offset(int regnum) {
|
||||
return regnum - 32; // The FP registers are in the second chunk
|
||||
}
|
||||
|
||||
// Vector width in bytes
|
||||
const int Matcher::vector_width_in_bytes(BasicType bt) {
|
||||
return MaxVectorSize;
|
||||
}
|
||||
|
||||
const bool Matcher::supports_scalable_vector() {
|
||||
return false;
|
||||
}
|
||||
|
||||
const int Matcher::scalable_vector_reg_size(const BasicType bt) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Vector ideal reg corresponding to specified size in bytes
|
||||
const uint Matcher::vector_ideal_reg(int size) {
|
||||
assert(MaxVectorSize >= size, "");
|
||||
@@ -1660,10 +1656,13 @@ encode %{
|
||||
// the region from SP to FP meets the minimum stack alignment.
|
||||
|
||||
frame %{
|
||||
// What direction does stack grow in (assumed to be same for native & Java)
|
||||
stack_direction(TOWARDS_LOW);
|
||||
|
||||
// These two registers define part of the calling convention
|
||||
// between compiled code and the interpreter.
|
||||
inline_cache_reg(R_Ricklass); // Inline Cache Register or Method* for I2C
|
||||
interpreter_method_reg(R_Rmethod); // Method Register when calling interpreter
|
||||
interpreter_method_oop_reg(R_Rmethod); // Method Oop Register when calling interpreter
|
||||
|
||||
// Optional: name the operand used by cisc-spilling to access [stack_pointer + offset]
|
||||
cisc_spilling_operand_name(indOffset);
|
||||
@@ -2523,7 +2522,7 @@ operand inline_cache_regP(iRegP reg) %{
|
||||
interface(REG_INTER);
|
||||
%}
|
||||
|
||||
operand interpreter_method_regP(iRegP reg) %{
|
||||
operand interpreter_method_oop_regP(iRegP reg) %{
|
||||
constraint(ALLOC_IN_RC(Rmethod_regP));
|
||||
match(reg);
|
||||
format %{ %}
|
||||
|
||||
@@ -196,7 +196,7 @@ alloc_class chunk2(APSR, FPSCR);
|
||||
// Several register classes are automatically defined based upon information in
|
||||
// this architecture description.
|
||||
// 1) reg_class inline_cache_reg ( as defined in frame section )
|
||||
// 2) reg_class interpreter_method_reg ( as defined in frame section )
|
||||
// 2) reg_class interpreter_method_oop_reg ( as defined in frame section )
|
||||
// 3) reg_class stack_slots( /* one chunk of stack-based "registers" */ )
|
||||
//
|
||||
|
||||
|
||||
@@ -1941,7 +1941,7 @@ void LIR_Assembler::ic_call(LIR_OpJavaCall *op) {
|
||||
}
|
||||
|
||||
|
||||
/* vtable-dispatch is not enabled for arm platforms */
|
||||
/* Currently, vtable-dispatch is only enabled for sparc platforms */
|
||||
void LIR_Assembler::vtable_call(LIR_OpJavaCall* op) {
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
|
||||
@@ -326,7 +326,7 @@ void LIRGenerator::cmp_reg_mem(LIR_Condition condition, LIR_Opr reg, LIR_Opr bas
|
||||
}
|
||||
|
||||
|
||||
bool LIRGenerator::strength_reduce_multiply(LIR_Opr left, jint c, LIR_Opr result, LIR_Opr tmp) {
|
||||
bool LIRGenerator::strength_reduce_multiply(LIR_Opr left, int c, LIR_Opr result, LIR_Opr tmp) {
|
||||
assert(left != result, "should be different registers");
|
||||
if (is_power_of_2(c + 1)) {
|
||||
LIR_Address::Scale scale = (LIR_Address::Scale) log2_intptr(c + 1);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@@ -52,12 +52,12 @@ void LIR_Address::verify() const {
|
||||
// be handled by the back-end or will be rejected if not.
|
||||
#ifdef _LP64
|
||||
assert(index()->is_illegal() || index()->is_double_cpu(), "wrong index operand");
|
||||
assert(base()->type() == T_ADDRESS || base()->type() == T_OBJECT || base()->type() == T_LONG || base()->type() == T_METADATA,
|
||||
assert(base()->type() == T_OBJECT || base()->type() == T_LONG || base()->type() == T_METADATA,
|
||||
"wrong type for addresses");
|
||||
#else
|
||||
assert(base()->is_single_cpu(), "wrong base operand");
|
||||
assert(index()->is_illegal() || index()->is_single_cpu(), "wrong index operand");
|
||||
assert(base()->type() == T_ADDRESS || base()->type() == T_OBJECT || base()->type() == T_INT || base()->type() == T_METADATA,
|
||||
assert(base()->type() == T_OBJECT || base()->type() == T_INT || base()->type() == T_METADATA,
|
||||
"wrong type for addresses");
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 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
|
||||
@@ -200,29 +200,26 @@ int C1_MacroAssembler::lock_object(Register hdr, Register obj,
|
||||
const int obj_offset = BasicObjectLock::obj_offset_in_bytes();
|
||||
const int mark_offset = BasicLock::displaced_header_offset_in_bytes();
|
||||
|
||||
str(obj, Address(disp_hdr, obj_offset));
|
||||
|
||||
null_check_offset = offset();
|
||||
|
||||
if (DiagnoseSyncOnPrimitiveWrappers != 0) {
|
||||
load_klass(tmp1, obj);
|
||||
ldr_u32(tmp1, Address(tmp1, Klass::access_flags_offset()));
|
||||
tst(tmp1, JVM_ACC_IS_BOX_CLASS);
|
||||
b(slow_case, ne);
|
||||
}
|
||||
|
||||
if (UseBiasedLocking) {
|
||||
biased_locking_enter(obj, hdr/*scratched*/, tmp1, false, tmp2, done, slow_case);
|
||||
// load object
|
||||
str(obj, Address(disp_hdr, obj_offset));
|
||||
null_check_offset = biased_locking_enter(obj, hdr/*scratched*/, tmp1, false, tmp2, done, slow_case);
|
||||
}
|
||||
|
||||
assert(oopDesc::mark_offset_in_bytes() == 0, "Required by atomic instructions");
|
||||
|
||||
|
||||
if (!UseBiasedLocking) {
|
||||
null_check_offset = offset();
|
||||
}
|
||||
|
||||
// On MP platforms the next load could return a 'stale' value if the memory location has been modified by another thread.
|
||||
// That would be acceptable as ether CAS or slow case path is taken in that case.
|
||||
|
||||
// Must be the first instruction here, because implicit null check relies on it
|
||||
ldr(hdr, Address(obj, oopDesc::mark_offset_in_bytes()));
|
||||
|
||||
str(obj, Address(disp_hdr, obj_offset));
|
||||
tst(hdr, markWord::unlocked_value);
|
||||
b(fast_lock, ne);
|
||||
|
||||
|
||||
@@ -90,13 +90,6 @@ void C2_MacroAssembler::fast_lock(Register Roop, Register Rbox, Register Rscratc
|
||||
|
||||
Label fast_lock, done;
|
||||
|
||||
if (DiagnoseSyncOnPrimitiveWrappers != 0) {
|
||||
load_klass(Rscratch, Roop);
|
||||
ldr_u32(Rscratch, Address(Rscratch, Klass::access_flags_offset()));
|
||||
tst(Rscratch, JVM_ACC_IS_BOX_CLASS);
|
||||
b(done, ne);
|
||||
}
|
||||
|
||||
if (UseBiasedLocking && !UseOptoBiasInlining) {
|
||||
assert(scratch3 != noreg, "need extra temporary for -XX:-UseOptoBiasInlining");
|
||||
biased_locking_enter(Roop, Rmark, Rscratch, false, scratch3, done, done);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@@ -71,9 +71,9 @@
|
||||
// The interpreter and adapters will extend the frame of the caller.
|
||||
// Since oopMaps are based on the sp of the caller before extension
|
||||
// we need to know that value. However in order to compute the address
|
||||
// of the return address we need the real "raw" sp. By convention we
|
||||
// use sp() to mean "raw" sp and unextended_sp() to mean the caller's
|
||||
// original sp.
|
||||
// of the return address we need the real "raw" sp. Since sparc already
|
||||
// uses sp() to mean "raw" sp and unextended_sp() to mean the caller's
|
||||
// original sp we use that convention.
|
||||
|
||||
intptr_t* _unextended_sp;
|
||||
void adjust_unextended_sp();
|
||||
|
||||
@@ -55,4 +55,11 @@ const bool HaveVFP = true;
|
||||
#define AD_MD_HPP "adfiles/ad_arm_32.hpp"
|
||||
#define C1_LIRGENERATOR_MD_HPP "c1_LIRGenerator_arm.hpp"
|
||||
|
||||
#ifdef TARGET_COMPILER_gcc
|
||||
#ifdef ARM32
|
||||
#undef BREAKPOINT
|
||||
#define BREAKPOINT __asm__ volatile ("bkpt")
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif // CPU_ARM_GLOBALDEFINITIONS_ARM_HPP
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user