Merge branch 'master' into JDK-8344159 to fix conflicts.

This commit is contained in:
Archie L. Cobbs 2025-08-20 10:28:39 -05:00
commit 5c2e51877c
504 changed files with 9622 additions and 6011 deletions

View File

@ -125,7 +125,8 @@ if [ -d "$TOPLEVEL_DIR/.hg" ] ; then
VCS_TYPE="hg4idea"
fi
if [ -d "$TOPLEVEL_DIR/.git" ] ; then
# Git worktrees use a '.git' file rather than directory, so test both.
if [ -d "$TOPLEVEL_DIR/.git" -o -f "$TOPLEVEL_DIR/.git" ] ; then
VCS_TYPE="Git"
fi

View File

@ -1451,10 +1451,10 @@ of a cross-compiling toolchain and a sysroot environment which can
easily be used together with the <code>--with-devkit</code> configure
option to cross compile the JDK. On Linux/x86_64, the following
command:</p>
<pre><code>bash configure --with-devkit=&lt;devkit-path&gt; --openjdk-target=ppc64-linux-gnu &amp;&amp; make</code></pre>
<p>will configure and build the JDK for Linux/ppc64 assuming that
<code>&lt;devkit-path&gt;</code> points to a Linux/x86_64 to Linux/ppc64
devkit.</p>
<pre><code>bash configure --with-devkit=&lt;devkit-path&gt; --openjdk-target=ppc64le-linux-gnu &amp;&amp; make</code></pre>
<p>will configure and build the JDK for Linux/ppc64le assuming that
<code>&lt;devkit-path&gt;</code> points to a Linux/x86_64 to
Linux/ppc64le devkit.</p>
<p>Devkits can be created from the <code>make/devkit</code> directory by
executing:</p>
<pre><code>make [ TARGETS=&quot;&lt;TARGET_TRIPLET&gt;+&quot; ] [ BASE_OS=&lt;OS&gt; ] [ BASE_OS_VERSION=&lt;VER&gt; ]</code></pre>
@ -1481,10 +1481,10 @@ following targets are known to work:</p>
<td>arm-linux-gnueabihf</td>
</tr>
<tr class="even">
<td>ppc64-linux-gnu</td>
<td>ppc64le-linux-gnu</td>
</tr>
<tr class="odd">
<td>ppc64le-linux-gnu</td>
<td>riscv64-linux-gnu</td>
</tr>
<tr class="even">
<td>s390x-linux-gnu</td>

View File

@ -1258,11 +1258,11 @@ toolchain and a sysroot environment which can easily be used together with the
following command:
```
bash configure --with-devkit=<devkit-path> --openjdk-target=ppc64-linux-gnu && make
bash configure --with-devkit=<devkit-path> --openjdk-target=ppc64le-linux-gnu && make
```
will configure and build the JDK for Linux/ppc64 assuming that `<devkit-path>`
points to a Linux/x86_64 to Linux/ppc64 devkit.
will configure and build the JDK for Linux/ppc64le assuming that `<devkit-path>`
points to a Linux/x86_64 to Linux/ppc64le devkit.
Devkits can be created from the `make/devkit` directory by executing:
@ -1281,8 +1281,8 @@ at least the following targets are known to work:
| x86_64-linux-gnu |
| aarch64-linux-gnu |
| arm-linux-gnueabihf |
| ppc64-linux-gnu |
| ppc64le-linux-gnu |
| riscv64-linux-gnu |
| s390x-linux-gnu |
`BASE_OS` must be one of `OL` for Oracle Enterprise Linux or `Fedora`. If the

View File

@ -11,11 +11,8 @@
div.columns{display: flex; gap: min(4vw, 1.5em);}
div.column{flex: auto; overflow-x: auto;}
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
/* The extra [class] is a hack that increases specificity enough to
override a similar rule in reveal.js */
ul.task-list[class]{list-style: none;}
ul.task-list{list-style: none;}
ul.task-list li input[type="checkbox"] {
font-size: inherit;
width: 0.8em;
margin: 0 0.8em 0.2em -1.6em;
vertical-align: middle;

View File

@ -72,11 +72,9 @@ id="toc-notes-for-specific-tests">Notes for Specific Tests</a>
<li><a href="#non-us-locale" id="toc-non-us-locale">Non-US
locale</a></li>
<li><a href="#pkcs11-tests" id="toc-pkcs11-tests">PKCS11 Tests</a></li>
</ul></li>
<li><a href="#testing-ahead-of-time-optimizations"
id="toc-testing-ahead-of-time-optimizations">### Testing Ahead-of-time
Optimizations</a>
<ul>
id="toc-testing-ahead-of-time-optimizations">Testing Ahead-of-time
Optimizations</a></li>
<li><a href="#testing-with-alternative-security-providers"
id="toc-testing-with-alternative-security-providers">Testing with
alternative security providers</a></li>
@ -435,6 +433,9 @@ the diff between the specified revision and the repository tip.</p>
<p>The report is stored in
<code>build/$BUILD/test-results/jcov-output/diff_coverage_report</code>
file.</p>
<h4 id="aot_jdk">AOT_JDK</h4>
<p>See <a href="#testing-ahead-of-time-optimizations">Testing
Ahead-of-time optimizations</a>.</p>
<h3 id="jtreg-keywords">JTReg keywords</h3>
<h4 id="jobs-1">JOBS</h4>
<p>The test concurrency (<code>-concurrency</code>).</p>
@ -457,6 +458,12 @@ class, named Virtual, is currently part of the JDK build in the
<code>test/jtreg_test_thread_factory/</code> directory. This class gets
compiled during the test image build. The implementation of the Virtual
class creates a new virtual thread for executing each test class.</p>
<h4 id="jvmti_stress_agent">JVMTI_STRESS_AGENT</h4>
<p>Executes JTReg tests with JVM TI stress agent. The stress agent is
the part of test library and located in
<code>test/lib/jdk/test/lib/jvmti/libJvmtiStressAgent.cpp</code>. The
value of this argument is set as JVM TI agent options. This mode uses
ProblemList-jvmti-stress-agent.txt as an additional exclude list.</p>
<h4 id="test_mode">TEST_MODE</h4>
<p>The test mode (<code>agentvm</code> or <code>othervm</code>).</p>
<p>Defaults to <code>agentvm</code>.</p>
@ -556,6 +563,12 @@ each fork. Same as specifying <code>-wi &lt;num&gt;</code>.</p>
same values as <code>-rff</code>, i.e., <code>text</code>,
<code>csv</code>, <code>scsv</code>, <code>json</code>, or
<code>latex</code>.</p>
<h4 id="test_jdk">TEST_JDK</h4>
<p>The path to the JDK that will be used to run the benchmarks.</p>
<p>Defaults to <code>build/&lt;CONF-NAME&gt;/jdk</code>.</p>
<h4 id="benchmarks_jar">BENCHMARKS_JAR</h4>
<p>The path to the JAR containing the benchmarks.</p>
<p>Defaults to <code>test/micro/benchmarks.jar</code>.</p>
<h4 id="vm_options-2">VM_OPTIONS</h4>
<p>Additional VM arguments to provide to forked off VMs. Same as
<code>-jvmArgs &lt;args&gt;</code></p>
@ -601,8 +614,8 @@ element of the appropriate <code>@Artifact</code> class. (See
JTREG=&quot;JAVA_OPTIONS=-Djdk.test.lib.artifacts.nsslib-linux_aarch64=/path/to/NSS-libs&quot;</code></pre>
<p>For more notes about the PKCS11 tests, please refer to
test/jdk/sun/security/pkcs11/README.</p>
<h2 id="testing-ahead-of-time-optimizations">### Testing Ahead-of-time
Optimizations</h2>
<h3 id="testing-ahead-of-time-optimizations">Testing Ahead-of-time
Optimizations</h3>
<p>One way to improve test coverage of ahead-of-time (AOT) optimizations
in the JDK is to run existing jtreg test cases in a special "AOT_JDK"
mode. Example:</p>

View File

@ -367,6 +367,10 @@ between the specified revision and the repository tip.
The report is stored in
`build/$BUILD/test-results/jcov-output/diff_coverage_report` file.
#### AOT_JDK
See [Testing Ahead-of-time optimizations](#testing-ahead-of-time-optimizations).
### JTReg keywords
#### JOBS
@ -397,6 +401,13 @@ the `test/jtreg_test_thread_factory/` directory. This class gets compiled
during the test image build. The implementation of the Virtual class creates a
new virtual thread for executing each test class.
#### JVMTI_STRESS_AGENT
Executes JTReg tests with JVM TI stress agent. The stress agent is the part of
test library and located in `test/lib/jdk/test/lib/jvmti/libJvmtiStressAgent.cpp`.
The value of this argument is set as JVM TI agent options.
This mode uses ProblemList-jvmti-stress-agent.txt as an additional exclude list.
#### TEST_MODE
The test mode (`agentvm` or `othervm`).
@ -545,6 +556,18 @@ Amount of time to spend in each warmup iteration. Same as specifying `-w
Specify to have the test run save a log of the values. Accepts the same values
as `-rff`, i.e., `text`, `csv`, `scsv`, `json`, or `latex`.
#### TEST_JDK
The path to the JDK that will be used to run the benchmarks.
Defaults to `build/<CONF-NAME>/jdk`.
#### BENCHMARKS_JAR
The path to the JAR containing the benchmarks.
Defaults to `test/micro/benchmarks.jar`.
#### VM_OPTIONS
Additional VM arguments to provide to forked off VMs. Same as `-jvmArgs <args>`
@ -612,7 +635,7 @@ For more notes about the PKCS11 tests, please refer to
test/jdk/sun/security/pkcs11/README.
### Testing Ahead-of-time Optimizations
-------------------------------------------------------------------------------
One way to improve test coverage of ahead-of-time (AOT) optimizations in
the JDK is to run existing jtreg test cases in a special "AOT_JDK" mode.
Example:

View File

@ -204,8 +204,9 @@ $(eval $(call SetTestOpt,AOT_JDK,JTREG))
$(eval $(call ParseKeywordVariable, JTREG, \
SINGLE_KEYWORDS := JOBS TIMEOUT_FACTOR FAILURE_HANDLER_TIMEOUT \
TEST_MODE ASSERT VERBOSE RETAIN TEST_THREAD_FACTORY MAX_MEM RUN_PROBLEM_LISTS \
RETRY_COUNT REPEAT_COUNT MAX_OUTPUT REPORT AOT_JDK $(CUSTOM_JTREG_SINGLE_KEYWORDS), \
TEST_MODE ASSERT VERBOSE RETAIN TEST_THREAD_FACTORY JVMTI_STRESS_AGENT \
MAX_MEM RUN_PROBLEM_LISTS RETRY_COUNT REPEAT_COUNT MAX_OUTPUT REPORT \
AOT_JDK $(CUSTOM_JTREG_SINGLE_KEYWORDS), \
STRING_KEYWORDS := OPTIONS JAVA_OPTIONS VM_OPTIONS KEYWORDS \
EXTRA_PROBLEM_LISTS LAUNCHER_OPTIONS \
$(CUSTOM_JTREG_STRING_KEYWORDS), \
@ -876,6 +877,15 @@ define SetupRunJtregTestBody
))
endif
ifneq ($$(JTREG_JVMTI_STRESS_AGENT), )
AGENT := $$(LIBRARY_PREFIX)JvmtiStressAgent$$(SHARED_LIBRARY_SUFFIX)=$$(JTREG_JVMTI_STRESS_AGENT)
$1_JTREG_BASIC_OPTIONS += -javaoption:'-agentpath:$(TEST_IMAGE_DIR)/hotspot/jtreg/native/$$(AGENT)'
$1_JTREG_BASIC_OPTIONS += $$(addprefix $$(JTREG_PROBLEM_LIST_PREFIX), $$(wildcard \
$$(addprefix $$($1_TEST_ROOT)/, ProblemList-jvmti-stress-agent.txt) \
))
endif
ifneq ($$(JTREG_LAUNCHER_OPTIONS), )
$1_JTREG_LAUNCHER_OPTIONS += $$(JTREG_LAUNCHER_OPTIONS)
endif
@ -1243,7 +1253,7 @@ UseSpecialTestHandler = \
# Now process each test to run and setup a proper make rule
$(foreach test, $(TESTS_TO_RUN), \
$(eval TEST_ID := $(shell $(ECHO) $(strip $(test)) | \
$(TR) -cs '[a-z][A-Z][0-9]\n' '[_*1000]')) \
$(TR) -cs '[a-z][A-Z][0-9]\n' '_')) \
$(eval ALL_TEST_IDS += $(TEST_ID)) \
$(if $(call UseCustomTestHandler, $(test)), \
$(eval $(call SetupRunCustomTest, $(TEST_ID), \
@ -1323,9 +1333,9 @@ run-test-report: post-run-test
TEST TOTAL PASS FAIL ERROR SKIP " "
$(foreach test, $(TESTS_TO_RUN), \
$(eval TEST_ID := $(shell $(ECHO) $(strip $(test)) | \
$(TR) -cs '[a-z][A-Z][0-9]\n' '[_*1000]')) \
$(TR) -cs '[a-z][A-Z][0-9]\n' '_')) \
$(ECHO) >> $(TEST_LAST_IDS) $(TEST_ID) $(NEWLINE) \
$(eval NAME_PATTERN := $(shell $(ECHO) $(test) | $(TR) -c '\n' '[_*1000]')) \
$(eval NAME_PATTERN := $(shell $(ECHO) $(test) | $(TR) -c '\n' '_')) \
$(if $(filter __________________________________________________%, $(NAME_PATTERN)), \
$(eval TEST_NAME := ) \
$(PRINTF) >> $(TEST_SUMMARY) "%2s %-49s\n" " " "$(test)" $(NEWLINE) \

View File

@ -176,3 +176,19 @@ ULIMIT := ulimit
ifeq ($(OPENJDK_BUILD_OS), windows)
PATHTOOL := cygpath
endif
# These settings are needed to run testing with jvmti agent
ifeq ($(OPENJDK_BUILD_OS), linux)
LIBRARY_PREFIX := lib
SHARED_LIBRARY_SUFFIX := .so
endif
ifeq ($(OPENJDK_BUILD_OS), windows)
LIBRARY_PREFIX :=
SHARED_LIBRARY_SUFFIX := .dll
endif
ifeq ($(OPENJDK_BUILD_OS), macosx)
LIBRARY_PREFIX := lib
SHARED_LIBRARY_SUFFIX := .dylib
endif

View File

@ -36,7 +36,7 @@ $(eval $(call SetupJavaCompilation, BUILD_TOOLS_LANGTOOLS, \
COMPILER := bootjdk, \
TARGET_RELEASE := $(TARGET_RELEASE_BOOTJDK), \
SRC := $(TOPDIR)/make/langtools/tools, \
INCLUDES := compileproperties propertiesparser, \
INCLUDES := compileproperties flagsgenerator propertiesparser, \
COPY := .properties, \
BIN := $(BUILDTOOLS_OUTPUTDIR)/langtools_tools_classes, \
))

View File

@ -940,7 +940,7 @@ AC_DEFUN([FLAGS_SETUP_CFLAGS_CPU_DEP],
# ACLE and this flag are required to build the aarch64 SVE related functions in
# libvectormath. Apple Silicon does not support SVE; use macOS as a proxy for
# that check.
if test "x$OPENJDK_TARGET_CPU" = "xaarch64" && test "x$OPENJDK_TARGET_CPU" = "xlinux"; then
if test "x$OPENJDK_TARGET_CPU" = "xaarch64" && test "x$OPENJDK_TARGET_OS" = "xlinux"; then
if test "x$TOOLCHAIN_TYPE" = xgcc || test "x$TOOLCHAIN_TYPE" = xclang; then
AC_LANG_PUSH(C)
OLD_CFLAGS="$CFLAGS"
@ -954,6 +954,17 @@ AC_DEFUN([FLAGS_SETUP_CFLAGS_CPU_DEP],
[
AC_MSG_RESULT([yes])
$2SVE_CFLAGS="-march=armv8-a+sve"
# Switching the initialization mode with gcc from 'pattern' to 'zero'
# avoids the use of unsupported `__builtin_clear_padding` for variable
# length aggregates
if test "x$DEBUG_LEVEL" != xrelease && test "x$TOOLCHAIN_TYPE" = xgcc ; then
INIT_ZERO_FLAG="-ftrivial-auto-var-init=zero"
FLAGS_COMPILER_CHECK_ARGUMENTS(ARGUMENT: [$INIT_ZERO_FLAG],
IF_TRUE: [
$2SVE_CFLAGS="${$2SVE_CFLAGS} $INIT_ZERO_FLAG"
]
)
fi
],
[
AC_MSG_RESULT([no])

View File

@ -39,7 +39,7 @@
#
# make TARGETS="aarch64-linux-gnu" BASE_OS=Fedora
# or
# make TARGETS="arm-linux-gnueabihf ppc64-linux-gnu" BASE_OS=Fedora BASE_OS_VERSION=17
# make TARGETS="arm-linux-gnueabihf ppc64le-linux-gnu" BASE_OS=Fedora BASE_OS_VERSION=17
#
# to build several devkits for a specific OS version at once.
# You can find the final results under ../../build/devkit/result/<host>-to-<target>
@ -50,7 +50,7 @@
# makefile again for cross compilation. Ex:
#
# PATH=$PWD/../../build/devkit/result/x86_64-linux-gnu-to-x86_64-linux-gnu/bin:$PATH \
# make TARGETS="arm-linux-gnueabihf,ppc64-linux-gnu" BASE_OS=Fedora
# make TARGETS="arm-linux-gnueabihf ppc64le-linux-gnu" BASE_OS=Fedora
#
# This is the makefile which iterates over all host and target platforms.
#

View File

@ -69,15 +69,26 @@ else ifeq ($(BASE_OS), Fedora)
ifeq ($(BASE_OS_VERSION), )
BASE_OS_VERSION := $(DEFAULT_OS_VERSION)
endif
ifeq ($(filter aarch64 armhfp ppc64le riscv64 s390x x86_64, $(ARCH)), )
$(error Only "aarch64 armhfp ppc64le riscv64 s390x x86_64" architectures are supported for Fedora, but "$(ARCH)" was requested)
endif
ifeq ($(ARCH), riscv64)
ifeq ($(filter 38 39 40 41, $(BASE_OS_VERSION)), )
$(error Only Fedora 38-41 are supported for "$(ARCH)", but Fedora $(BASE_OS_VERSION) was requested)
endif
BASE_URL := http://fedora.riscv.rocks/repos-dist/f$(BASE_OS_VERSION)/latest/$(ARCH)/Packages/
else
LATEST_ARCHIVED_OS_VERSION := 35
ifeq ($(filter x86_64 armhfp, $(ARCH)), )
LATEST_ARCHIVED_OS_VERSION := 36
ifeq ($(filter aarch64 armhfp x86_64, $(ARCH)), )
FEDORA_TYPE := fedora-secondary
else
FEDORA_TYPE := fedora/linux
endif
ifeq ($(ARCH), armhfp)
ifneq ($(BASE_OS_VERSION), 36)
$(error Fedora 36 is the last release supporting "armhfp", but $(BASE_OS) was requested)
endif
endif
NOT_ARCHIVED := $(shell [ $(BASE_OS_VERSION) -gt $(LATEST_ARCHIVED_OS_VERSION) ] && echo true)
ifeq ($(NOT_ARCHIVED),true)
BASE_URL := https://dl.fedoraproject.org/pub/$(FEDORA_TYPE)/releases/$(BASE_OS_VERSION)/Everything/$(ARCH)/os/Packages/
@ -464,7 +475,7 @@ ifeq ($(ARCH), armhfp)
$(BUILDDIR)/$(gcc_ver)/Makefile : CONFIG += --with-float=hard
endif
ifneq ($(filter riscv64 ppc64 ppc64le s390x, $(ARCH)), )
ifneq ($(filter riscv64 ppc64le s390x, $(ARCH)), )
# We only support 64-bit on these platforms anyway
CONFIG += --disable-multilib
endif

View File

@ -12,12 +12,17 @@
],
"extensions": {
"recommendations": [
"oracle.oracle-java",
// {{INDEXER_EXTENSIONS}}
]
},
"settings": {
// {{INDEXER_SETTINGS}}
// Java extension
"jdk.project.jdkhome": "{{OUTPUTDIR}}/jdk",
"jdk.java.onSave.organizeImports": false, // prevents unnecessary changes
// Additional conventions
"files.associations": {
"*.gmk": "makefile"

View File

@ -0,0 +1,161 @@
/*
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package flagsgenerator;
import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.util.JavacTask;
import com.sun.source.util.TreePath;
import com.sun.source.util.Trees;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
import java.util.stream.Collectors;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.util.ElementFilter;
import javax.tools.ToolProvider;
public class FlagsGenerator {
public static void main(String... args) throws IOException {
var compiler = ToolProvider.getSystemJavaCompiler();
try (var fm = compiler.getStandardFileManager(null, null, null)) {
JavacTask task = (JavacTask) compiler.getTask(null, null, d -> {}, null, null, fm.getJavaFileObjects(args[0]));
Trees trees = Trees.instance(task);
CompilationUnitTree cut = task.parse().iterator().next();
task.analyze();
TypeElement clazz = (TypeElement) trees.getElement(new TreePath(new TreePath(cut), cut.getTypeDecls().get(0)));
Map<Integer, List<String>> flag2Names = new TreeMap<>();
Map<FlagTarget, Map<Integer, List<String>>> target2FlagBit2Fields = new EnumMap<>(FlagTarget.class);
Map<String, String> customToString = new HashMap<>();
Set<String> noToString = new HashSet<>();
for (VariableElement field : ElementFilter.fieldsIn(clazz.getEnclosedElements())) {
String flagName = field.getSimpleName().toString();
for (AnnotationMirror am : field.getAnnotationMirrors()) {
switch (am.getAnnotationType().toString()) {
case "com.sun.tools.javac.code.Flags.Use" -> {
long flagValue = ((Number) field.getConstantValue()).longValue();
int flagBit = 63 - Long.numberOfLeadingZeros(flagValue);
flag2Names.computeIfAbsent(flagBit, _ -> new ArrayList<>())
.add(flagName);
List<?> originalTargets = (List<?>) valueOfValueAttribute(am);
originalTargets.stream()
.map(value -> FlagTarget.valueOf(value.toString()))
.forEach(target -> target2FlagBit2Fields.computeIfAbsent(target, _ -> new HashMap<>())
.computeIfAbsent(flagBit, _ -> new ArrayList<>())
.add(flagName));
}
case "com.sun.tools.javac.code.Flags.CustomToStringValue" -> {
customToString.put(flagName, (String) valueOfValueAttribute(am));
}
case "com.sun.tools.javac.code.Flags.NoToStringValue" -> {
noToString.add(flagName);
}
}
}
}
//verify there are no flag overlaps:
for (Entry<FlagTarget, Map<Integer, List<String>>> targetAndFlag : target2FlagBit2Fields.entrySet()) {
for (Entry<Integer, List<String>> flagAndFields : targetAndFlag.getValue().entrySet()) {
if (flagAndFields.getValue().size() > 1) {
throw new AssertionError("duplicate flag for target: " + targetAndFlag.getKey() +
", flag: " + flagAndFields.getKey() +
", flags fields: " + flagAndFields.getValue());
}
}
}
try (PrintWriter out = new PrintWriter(Files.newBufferedWriter(Paths.get(args[1])))) {
out.println("""
package com.sun.tools.javac.code;
public enum FlagsEnum {
""");
for (Entry<Integer, List<String>> e : flag2Names.entrySet()) {
String constantName = e.getValue().stream().collect(Collectors.joining("_OR_"));
String toString = e.getValue()
.stream()
.filter(n -> !noToString.contains(n))
.map(n -> customToString.getOrDefault(n, n.toLowerCase(Locale.US)))
.collect(Collectors.joining(" or "));
out.println(" " + constantName + "(1L<<" + e.getKey() + ", \"" + toString + "\"),");
}
out.println("""
;
private final long value;
private final String toString;
private FlagsEnum(long value, String toString) {
this.value = value;
this.toString = toString;
}
public long value() {
return value;
}
public String toString() {
return toString;
}
}
""");
}
}
}
private static Object valueOfValueAttribute(AnnotationMirror am) {
return am.getElementValues()
.values()
.iterator()
.next()
.getValue();
}
private enum FlagTarget {
BLOCK,
CLASS,
METHOD,
MODULE,
PACKAGE,
TYPE_VAR,
VARIABLE;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -76,7 +76,7 @@ public interface MessageType {
ANNOTATION("annotation", "Compound", "com.sun.tools.javac.code.Attribute"),
BOOLEAN("boolean", "boolean", null),
COLLECTION("collection", "Collection", "java.util"),
FLAG("flag", "Flag", "com.sun.tools.javac.code.Flags"),
FLAG("flag", "FlagsEnum", "com.sun.tools.javac.code"),
FRAGMENT("fragment", "Fragment", null),
DIAGNOSTIC("diagnostic", "JCDiagnostic", "com.sun.tools.javac.util"),
MODIFIER("modifier", "Modifier", "javax.lang.model.element"),

View File

@ -41,17 +41,17 @@ $(eval $(call SetupCompileProperties, COMPILE_PROPERTIES, \
TARGETS += $(COMPILE_PROPERTIES)
################################################################################
#
# Compile properties files into enum-like classes using the propertiesparser tool
#
# To avoid reevaluating the compilation setup for the tools each time this file
# is included, the following trick is used to be able to declare a dependency on
# the built tools.
BUILD_TOOLS_LANGTOOLS := $(call SetupJavaCompilationCompileTarget, \
BUILD_TOOLS_LANGTOOLS, $(BUILDTOOLS_OUTPUTDIR)/langtools_tools_classes)
################################################################################
#
# Compile properties files into enum-like classes using the propertiesparser tool
#
TOOL_PARSEPROPERTIES_CMD := $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/langtools_tools_classes \
propertiesparser.PropertiesParser
@ -76,3 +76,26 @@ $(eval $(call SetupExecute, PARSEPROPERTIES, \
TARGETS += $(PARSEPROPERTIES)
################################################################################
#
# Generate FlagsEnum from Flags constants
#
TOOL_FLAGSGENERATOR_CMD := $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/langtools_tools_classes \
flagsgenerator.FlagsGenerator
FLAGS_SRC := \
$(MODULE_SRC)/share/classes/com/sun/tools/javac/code/Flags.java
FLAGS_OUT := \
$(SUPPORT_OUTPUTDIR)/gensrc/$(MODULE)/com/sun/tools/javac/code/FlagsEnum.java
$(eval $(call SetupExecute, FLAGSGENERATOR, \
WARN := Generating FlagsEnum, \
DEPS := $(FLAGS_SRC) $(BUILD_TOOLS_LANGTOOLS), \
OUTPUT_FILE := $(FLAGS_OUT), \
COMMAND := $(TOOL_FLAGSGENERATOR_CMD) $(FLAGS_SRC) $(FLAGS_OUT), \
))
TARGETS += $(FLAGSGENERATOR)
################################################################################

View File

@ -16281,41 +16281,8 @@ instruct branchLoopEnd(cmpOp cmp, rFlagsReg cr, label lbl)
// ============================================================================
// inlined locking and unlocking
instruct cmpFastLock(rFlagsReg cr, iRegP object, iRegP box, iRegPNoSp tmp, iRegPNoSp tmp2, iRegPNoSp tmp3)
%{
predicate(LockingMode != LM_LIGHTWEIGHT);
match(Set cr (FastLock object box));
effect(TEMP tmp, TEMP tmp2, TEMP tmp3);
ins_cost(5 * INSN_COST);
format %{ "fastlock $object,$box\t! kills $tmp,$tmp2,$tmp3" %}
ins_encode %{
__ fast_lock($object$$Register, $box$$Register, $tmp$$Register, $tmp2$$Register, $tmp3$$Register);
%}
ins_pipe(pipe_serial);
%}
instruct cmpFastUnlock(rFlagsReg cr, iRegP object, iRegP box, iRegPNoSp tmp, iRegPNoSp tmp2)
%{
predicate(LockingMode != LM_LIGHTWEIGHT);
match(Set cr (FastUnlock object box));
effect(TEMP tmp, TEMP tmp2);
ins_cost(5 * INSN_COST);
format %{ "fastunlock $object,$box\t! kills $tmp, $tmp2" %}
ins_encode %{
__ fast_unlock($object$$Register, $box$$Register, $tmp$$Register, $tmp2$$Register);
%}
ins_pipe(pipe_serial);
%}
instruct cmpFastLockLightweight(rFlagsReg cr, iRegP object, iRegP box, iRegPNoSp tmp, iRegPNoSp tmp2, iRegPNoSp tmp3)
%{
predicate(LockingMode == LM_LIGHTWEIGHT);
match(Set cr (FastLock object box));
effect(TEMP tmp, TEMP tmp2, TEMP tmp3);
@ -16331,7 +16298,6 @@ instruct cmpFastLockLightweight(rFlagsReg cr, iRegP object, iRegP box, iRegPNoSp
instruct cmpFastUnlockLightweight(rFlagsReg cr, iRegP object, iRegP box, iRegPNoSp tmp, iRegPNoSp tmp2, iRegPNoSp tmp3)
%{
predicate(LockingMode == LM_LIGHTWEIGHT);
match(Set cr (FastUnlock object box));
effect(TEMP tmp, TEMP tmp2, TEMP tmp3);

View File

@ -410,11 +410,7 @@ int LIR_Assembler::emit_unwind_handler() {
if (method()->is_synchronized()) {
monitor_address(0, FrameMap::r0_opr);
stub = new MonitorExitStub(FrameMap::r0_opr, true, 0);
if (LockingMode == LM_MONITOR) {
__ b(*stub->entry());
} else {
__ unlock_object(r5, r4, r0, r6, *stub->entry());
}
__ unlock_object(r5, r4, r0, r6, *stub->entry());
__ bind(*stub->continuation());
}
@ -2484,13 +2480,7 @@ void LIR_Assembler::emit_lock(LIR_OpLock* op) {
Register hdr = op->hdr_opr()->as_register();
Register lock = op->lock_opr()->as_register();
Register temp = op->scratch_opr()->as_register();
if (LockingMode == LM_MONITOR) {
if (op->info() != nullptr) {
add_debug_info_for_null_check_here(op->info());
__ null_check(obj, -1);
}
__ b(*op->stub()->entry());
} else if (op->code() == lir_lock) {
if (op->code() == lir_lock) {
assert(BasicLock::displaced_header_offset_in_bytes() == 0, "lock_reg must point to the displaced header");
// add debug info for NullPointerException only if one is possible
int null_check_offset = __ lock_object(hdr, obj, lock, temp, *op->stub()->entry());
@ -2823,7 +2813,7 @@ void LIR_Assembler::leal(LIR_Opr addr, LIR_Opr dest, LIR_PatchCode patch_code, C
return;
}
__ lea(dest->as_register_lo(), as_Address(addr->as_address_ptr()));
__ lea(dest->as_pointer_register(), as_Address(addr->as_address_ptr()));
}
@ -3133,7 +3123,9 @@ void LIR_Assembler::atomic_op(LIR_Code code, LIR_Opr src, LIR_Opr data, LIR_Opr
default:
ShouldNotReachHere();
}
__ membar(__ AnyAny);
if(!UseLSE) {
__ membar(__ AnyAny);
}
}
#undef __

View File

@ -981,7 +981,7 @@ void LIRGenerator::do_update_CRC32(Intrinsic* x) {
CallingConvention* cc = frame_map()->c_calling_convention(&signature);
const LIR_Opr result_reg = result_register_for(x->type());
LIR_Opr addr = new_pointer_register();
LIR_Opr addr = new_register(T_ADDRESS);
__ leal(LIR_OprFact::address(a), addr);
crc.load_item_force(cc->at(0));
@ -1058,7 +1058,7 @@ void LIRGenerator::do_update_CRC32C(Intrinsic* x) {
CallingConvention* cc = frame_map()->c_calling_convention(&signature);
const LIR_Opr result_reg = result_register_for(x->type());
LIR_Opr addr = new_pointer_register();
LIR_Opr addr = new_register(T_ADDRESS);
__ leal(LIR_OprFact::address(a), addr);
crc.load_item_force(cc->at(0));

View File

@ -60,8 +60,6 @@ void C1_MacroAssembler::float_cmp(bool is_float, int unordered_result,
}
int C1_MacroAssembler::lock_object(Register hdr, Register obj, Register disp_hdr, Register temp, Label& slow_case) {
const int aligned_mask = BytesPerWord -1;
const int hdr_offset = oopDesc::mark_offset_in_bytes();
assert_different_registers(hdr, obj, disp_hdr, temp, rscratch2);
int null_check_offset = -1;
@ -72,95 +70,20 @@ int C1_MacroAssembler::lock_object(Register hdr, Register obj, Register disp_hdr
null_check_offset = offset();
if (LockingMode == LM_LIGHTWEIGHT) {
lightweight_lock(disp_hdr, obj, hdr, temp, rscratch2, slow_case);
} else if (LockingMode == LM_LEGACY) {
lightweight_lock(disp_hdr, obj, hdr, temp, rscratch2, slow_case);
if (DiagnoseSyncOnValueBasedClasses != 0) {
load_klass(hdr, obj);
ldrb(hdr, Address(hdr, Klass::misc_flags_offset()));
tst(hdr, KlassFlags::_misc_is_value_based_class);
br(Assembler::NE, slow_case);
}
Label done;
// Load object header
ldr(hdr, Address(obj, hdr_offset));
// and mark it as unlocked
orr(hdr, hdr, markWord::unlocked_value);
// save unlocked object header into the displaced header location on the stack
str(hdr, Address(disp_hdr, 0));
// test if object header is still the same (i.e. unlocked), and if so, store the
// displaced header address in the object header - if it is not the same, get the
// object header instead
lea(rscratch2, Address(obj, hdr_offset));
cmpxchgptr(hdr, disp_hdr, rscratch2, rscratch1, done, /*fallthough*/nullptr);
// if the object header was the same, we're done
// if the object header was not the same, it is now in the hdr register
// => test if it is a stack pointer into the same stack (recursive locking), i.e.:
//
// 1) (hdr & aligned_mask) == 0
// 2) sp <= hdr
// 3) hdr <= sp + page_size
//
// these 3 tests can be done by evaluating the following expression:
//
// (hdr - sp) & (aligned_mask - page_size)
//
// assuming both the stack pointer and page_size have their least
// significant 2 bits cleared and page_size is a power of 2
mov(rscratch1, sp);
sub(hdr, hdr, rscratch1);
ands(hdr, hdr, aligned_mask - (int)os::vm_page_size());
// for recursive locking, the result is zero => save it in the displaced header
// location (null in the displaced hdr location indicates recursive locking)
str(hdr, Address(disp_hdr, 0));
// otherwise we don't care about the result and handle locking via runtime call
cbnz(hdr, slow_case);
// done
bind(done);
inc_held_monitor_count(rscratch1);
}
return null_check_offset;
}
void C1_MacroAssembler::unlock_object(Register hdr, Register obj, Register disp_hdr, Register temp, Label& slow_case) {
const int aligned_mask = BytesPerWord -1;
const int hdr_offset = oopDesc::mark_offset_in_bytes();
assert_different_registers(hdr, obj, disp_hdr, temp, rscratch2);
Label done;
if (LockingMode != LM_LIGHTWEIGHT) {
// load displaced header
ldr(hdr, Address(disp_hdr, 0));
// if the loaded hdr is null we had recursive locking
// if we had recursive locking, we are done
cbz(hdr, done);
}
// load object
ldr(obj, Address(disp_hdr, BasicObjectLock::obj_offset()));
verify_oop(obj);
if (LockingMode == LM_LIGHTWEIGHT) {
lightweight_unlock(obj, hdr, temp, rscratch2, slow_case);
} else if (LockingMode == LM_LEGACY) {
// test if object header is pointing to the displaced header, and if so, restore
// the displaced header in the object - if the object header is not pointing to
// the displaced header, get the object header instead
// if the object header was not pointing to the displaced header,
// we do unlocking via runtime call
if (hdr_offset) {
lea(rscratch1, Address(obj, hdr_offset));
cmpxchgptr(disp_hdr, hdr, rscratch1, rscratch2, done, &slow_case);
} else {
cmpxchgptr(disp_hdr, hdr, obj, rscratch2, done, &slow_case);
}
// done
bind(done);
dec_held_monitor_count(rscratch1);
}
lightweight_unlock(obj, hdr, temp, rscratch2, slow_case);
}

View File

@ -147,215 +147,8 @@ address C2_MacroAssembler::arrays_hashcode(Register ary, Register cnt, Register
return pc();
}
void C2_MacroAssembler::fast_lock(Register objectReg, Register boxReg, Register tmpReg,
Register tmp2Reg, Register tmp3Reg) {
Register oop = objectReg;
Register box = boxReg;
Register disp_hdr = tmpReg;
Register tmp = tmp2Reg;
Label cont;
Label object_has_monitor;
Label count, no_count;
assert(LockingMode != LM_LIGHTWEIGHT, "lightweight locking should use fast_lock_lightweight");
assert_different_registers(oop, box, tmp, disp_hdr, rscratch2);
// Load markWord from object into displaced_header.
ldr(disp_hdr, Address(oop, oopDesc::mark_offset_in_bytes()));
if (DiagnoseSyncOnValueBasedClasses != 0) {
load_klass(tmp, oop);
ldrb(tmp, Address(tmp, Klass::misc_flags_offset()));
tst(tmp, KlassFlags::_misc_is_value_based_class);
br(Assembler::NE, cont);
}
// Check for existing monitor
tbnz(disp_hdr, exact_log2(markWord::monitor_value), object_has_monitor);
if (LockingMode == LM_MONITOR) {
tst(oop, oop); // Set NE to indicate 'failure' -> take slow-path. We know that oop != 0.
b(cont);
} else {
assert(LockingMode == LM_LEGACY, "must be");
// Set tmp to be (markWord of object | UNLOCK_VALUE).
orr(tmp, disp_hdr, markWord::unlocked_value);
// Initialize the box. (Must happen before we update the object mark!)
str(tmp, Address(box, BasicLock::displaced_header_offset_in_bytes()));
// Compare object markWord with an unlocked value (tmp) and if
// equal exchange the stack address of our box with object markWord.
// On failure disp_hdr contains the possibly locked markWord.
cmpxchg(oop, tmp, box, Assembler::xword, /*acquire*/ true,
/*release*/ true, /*weak*/ false, disp_hdr);
br(Assembler::EQ, cont);
assert(oopDesc::mark_offset_in_bytes() == 0, "offset of _mark is not 0");
// If the compare-and-exchange succeeded, then we found an unlocked
// object, will have now locked it will continue at label cont
// Check if the owner is self by comparing the value in the
// markWord of object (disp_hdr) with the stack pointer.
mov(rscratch1, sp);
sub(disp_hdr, disp_hdr, rscratch1);
mov(tmp, (address) (~(os::vm_page_size()-1) | markWord::lock_mask_in_place));
// If condition is true we are cont and hence we can store 0 as the
// displaced header in the box, which indicates that it is a recursive lock.
ands(tmp/*==0?*/, disp_hdr, tmp); // Sets flags for result
str(tmp/*==0, perhaps*/, Address(box, BasicLock::displaced_header_offset_in_bytes()));
b(cont);
}
// Handle existing monitor.
bind(object_has_monitor);
// Try to CAS owner (no owner => current thread's _monitor_owner_id).
ldr(rscratch2, Address(rthread, JavaThread::monitor_owner_id_offset()));
add(tmp, disp_hdr, (in_bytes(ObjectMonitor::owner_offset())-markWord::monitor_value));
cmpxchg(tmp, zr, rscratch2, Assembler::xword, /*acquire*/ true,
/*release*/ true, /*weak*/ false, tmp3Reg); // Sets flags for result
// Store a non-null value into the box to avoid looking like a re-entrant
// lock. The fast-path monitor unlock code checks for
// markWord::monitor_value so use markWord::unused_mark which has the
// relevant bit set, and also matches ObjectSynchronizer::enter.
mov(tmp, (address)markWord::unused_mark().value());
str(tmp, Address(box, BasicLock::displaced_header_offset_in_bytes()));
br(Assembler::EQ, cont); // CAS success means locking succeeded
cmp(tmp3Reg, rscratch2);
br(Assembler::NE, cont); // Check for recursive locking
// Recursive lock case
increment(Address(disp_hdr, in_bytes(ObjectMonitor::recursions_offset()) - markWord::monitor_value), 1);
// flag == EQ still from the cmp above, checking if this is a reentrant lock
bind(cont);
// flag == EQ indicates success
// flag == NE indicates failure
br(Assembler::NE, no_count);
bind(count);
if (LockingMode == LM_LEGACY) {
inc_held_monitor_count(rscratch1);
}
bind(no_count);
}
void C2_MacroAssembler::fast_unlock(Register objectReg, Register boxReg, Register tmpReg,
Register tmp2Reg) {
Register oop = objectReg;
Register box = boxReg;
Register disp_hdr = tmpReg;
Register owner_addr = tmpReg;
Register tmp = tmp2Reg;
Label cont;
Label object_has_monitor;
Label count, no_count;
Label unlocked;
assert(LockingMode != LM_LIGHTWEIGHT, "lightweight locking should use fast_unlock_lightweight");
assert_different_registers(oop, box, tmp, disp_hdr);
if (LockingMode == LM_LEGACY) {
// Find the lock address and load the displaced header from the stack.
ldr(disp_hdr, Address(box, BasicLock::displaced_header_offset_in_bytes()));
// If the displaced header is 0, we have a recursive unlock.
cmp(disp_hdr, zr);
br(Assembler::EQ, cont);
}
// Handle existing monitor.
ldr(tmp, Address(oop, oopDesc::mark_offset_in_bytes()));
tbnz(tmp, exact_log2(markWord::monitor_value), object_has_monitor);
if (LockingMode == LM_MONITOR) {
tst(oop, oop); // Set NE to indicate 'failure' -> take slow-path. We know that oop != 0.
b(cont);
} else {
assert(LockingMode == LM_LEGACY, "must be");
// Check if it is still a light weight lock, this is is true if we
// see the stack address of the basicLock in the markWord of the
// object.
cmpxchg(oop, box, disp_hdr, Assembler::xword, /*acquire*/ false,
/*release*/ true, /*weak*/ false, tmp);
b(cont);
}
assert(oopDesc::mark_offset_in_bytes() == 0, "offset of _mark is not 0");
// Handle existing monitor.
bind(object_has_monitor);
STATIC_ASSERT(markWord::monitor_value <= INT_MAX);
add(tmp, tmp, -(int)markWord::monitor_value); // monitor
ldr(disp_hdr, Address(tmp, ObjectMonitor::recursions_offset()));
Label notRecursive;
cbz(disp_hdr, notRecursive);
// Recursive lock
sub(disp_hdr, disp_hdr, 1u);
str(disp_hdr, Address(tmp, ObjectMonitor::recursions_offset()));
cmp(disp_hdr, disp_hdr); // Sets flags for result
b(cont);
bind(notRecursive);
// Compute owner address.
lea(owner_addr, Address(tmp, ObjectMonitor::owner_offset()));
// Set owner to null.
// Release to satisfy the JMM
stlr(zr, owner_addr);
// We need a full fence after clearing owner to avoid stranding.
// StoreLoad achieves this.
membar(StoreLoad);
// Check if the entry_list is empty.
ldr(rscratch1, Address(tmp, ObjectMonitor::entry_list_offset()));
cmp(rscratch1, zr);
br(Assembler::EQ, cont); // If so we are done.
// Check if there is a successor.
ldr(rscratch1, Address(tmp, ObjectMonitor::succ_offset()));
cmp(rscratch1, zr);
br(Assembler::NE, unlocked); // If so we are done.
// Save the monitor pointer in the current thread, so we can try to
// reacquire the lock in SharedRuntime::monitor_exit_helper().
str(tmp, Address(rthread, JavaThread::unlocked_inflated_monitor_offset()));
cmp(zr, rthread); // Set Flag to NE => slow path
b(cont);
bind(unlocked);
cmp(zr, zr); // Set Flag to EQ => fast path
// Intentional fall-through
bind(cont);
// flag == EQ indicates success
// flag == NE indicates failure
br(Assembler::NE, no_count);
bind(count);
if (LockingMode == LM_LEGACY) {
dec_held_monitor_count(rscratch1);
}
bind(no_count);
}
void C2_MacroAssembler::fast_lock_lightweight(Register obj, Register box, Register t1,
Register t2, Register t3) {
assert(LockingMode == LM_LIGHTWEIGHT, "must be");
assert_different_registers(obj, box, t1, t2, t3, rscratch2);
// Handle inflated monitor.
@ -512,7 +305,6 @@ void C2_MacroAssembler::fast_lock_lightweight(Register obj, Register box, Regist
void C2_MacroAssembler::fast_unlock_lightweight(Register obj, Register box, Register t1,
Register t2, Register t3) {
assert(LockingMode == LM_LIGHTWEIGHT, "must be");
assert_different_registers(obj, box, t1, t2, t3);
// Handle inflated monitor.

View File

@ -51,9 +51,6 @@
FloatRegister vmul3, FloatRegister vpow, FloatRegister vpowm,
BasicType eltype);
// Code used by cmpFastLock and cmpFastUnlock mach instructions in .ad file.
void fast_lock(Register object, Register box, Register tmp, Register tmp2, Register tmp3);
void fast_unlock(Register object, Register box, Register tmp, Register tmp2);
// Code used by cmpFastLockLightweight and cmpFastUnlockLightweight mach instructions in .ad file.
void fast_lock_lightweight(Register object, Register box, Register t1, Register t2, Register t3);
void fast_unlock_lightweight(Register object, Register box, Register t1, Register t2, Register t3);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -101,9 +101,12 @@ frame FreezeBase::new_heap_frame(frame& f, frame& caller) {
*hf.addr_at(frame::interpreter_frame_locals_offset) = locals_offset;
return hf;
} else {
// We need to re-read fp out of the frame because it may be an oop and we might have
// had a safepoint in finalize_freeze, after constructing f.
fp = *(intptr_t**)(f.sp() - frame::sender_sp_offset);
// For a compiled frame we need to re-read fp out of the frame because it may be an
// oop and we might have had a safepoint in finalize_freeze, after constructing f.
// For stub/native frames the value is not used while frozen, and will be constructed again
// when thawing the frame (see ThawBase::new_stack_frame). We use a special bad address to
// help with debugging, particularly when inspecting frames and identifying invalid accesses.
fp = FKind::compiled ? *(intptr_t**)(f.sp() - frame::sender_sp_offset) : (intptr_t*)badAddressVal;
int fsize = FKind::size(f);
sp = caller.unextended_sp() - fsize;
@ -192,6 +195,11 @@ inline void FreezeBase::patch_pd(frame& hf, const frame& caller) {
}
}
inline void FreezeBase::patch_pd_unused(intptr_t* sp) {
intptr_t* fp_addr = sp - frame::sender_sp_offset;
*fp_addr = badAddressVal;
}
//////// Thaw
// Fast path

View File

@ -691,104 +691,27 @@ void InterpreterMacroAssembler::leave_jfr_critical_section() {
void InterpreterMacroAssembler::lock_object(Register lock_reg)
{
assert(lock_reg == c_rarg1, "The argument is only for looks. It must be c_rarg1");
if (LockingMode == LM_MONITOR) {
call_VM_preemptable(noreg,
CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorenter),
lock_reg);
} else {
Label count, done;
const Register swap_reg = r0;
const Register tmp = c_rarg2;
const Register obj_reg = c_rarg3; // Will contain the oop
const Register tmp2 = c_rarg4;
const Register tmp3 = c_rarg5;
const Register tmp = c_rarg2;
const Register obj_reg = c_rarg3; // Will contain the oop
const Register tmp2 = c_rarg4;
const Register tmp3 = c_rarg5;
const int obj_offset = in_bytes(BasicObjectLock::obj_offset());
const int lock_offset = in_bytes(BasicObjectLock::lock_offset());
const int mark_offset = lock_offset +
BasicLock::displaced_header_offset_in_bytes();
// Load object pointer into obj_reg %c_rarg3
ldr(obj_reg, Address(lock_reg, BasicObjectLock::obj_offset()));
Label slow_case;
Label slow_case, done;
lightweight_lock(lock_reg, obj_reg, tmp, tmp2, tmp3, slow_case);
b(done);
// Load object pointer into obj_reg %c_rarg3
ldr(obj_reg, Address(lock_reg, obj_offset));
bind(slow_case);
if (LockingMode == LM_LIGHTWEIGHT) {
lightweight_lock(lock_reg, obj_reg, tmp, tmp2, tmp3, slow_case);
b(done);
} else if (LockingMode == LM_LEGACY) {
// Call the runtime routine for slow case
call_VM_preemptable(noreg,
CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorenter),
lock_reg);
if (DiagnoseSyncOnValueBasedClasses != 0) {
load_klass(tmp, obj_reg);
ldrb(tmp, Address(tmp, Klass::misc_flags_offset()));
tst(tmp, KlassFlags::_misc_is_value_based_class);
br(Assembler::NE, slow_case);
}
// Load (object->mark() | 1) into swap_reg
ldr(rscratch1, Address(obj_reg, oopDesc::mark_offset_in_bytes()));
orr(swap_reg, rscratch1, 1);
// Save (object->mark() | 1) into BasicLock's displaced header
str(swap_reg, Address(lock_reg, mark_offset));
assert(lock_offset == 0,
"displached header must be first word in BasicObjectLock");
Label fail;
cmpxchg_obj_header(swap_reg, lock_reg, obj_reg, rscratch1, count, /*fallthrough*/nullptr);
// Fast check for recursive lock.
//
// Can apply the optimization only if this is a stack lock
// allocated in this thread. For efficiency, we can focus on
// recently allocated stack locks (instead of reading the stack
// base and checking whether 'mark' points inside the current
// thread stack):
// 1) (mark & 7) == 0, and
// 2) sp <= mark < mark + os::pagesize()
//
// Warning: sp + os::pagesize can overflow the stack base. We must
// neither apply the optimization for an inflated lock allocated
// just above the thread stack (this is why condition 1 matters)
// nor apply the optimization if the stack lock is inside the stack
// of another thread. The latter is avoided even in case of overflow
// because we have guard pages at the end of all stacks. Hence, if
// we go over the stack base and hit the stack of another thread,
// this should not be in a writeable area that could contain a
// stack lock allocated by that thread. As a consequence, a stack
// lock less than page size away from sp is guaranteed to be
// owned by the current thread.
//
// These 3 tests can be done by evaluating the following
// expression: ((mark - sp) & (7 - os::vm_page_size())),
// assuming both stack pointer and pagesize have their
// least significant 3 bits clear.
// NOTE: the mark is in swap_reg %r0 as the result of cmpxchg
// NOTE2: aarch64 does not like to subtract sp from rn so take a
// copy
mov(rscratch1, sp);
sub(swap_reg, swap_reg, rscratch1);
ands(swap_reg, swap_reg, (uint64_t)(7 - (int)os::vm_page_size()));
// Save the test result, for recursive case, the result is zero
str(swap_reg, Address(lock_reg, mark_offset));
br(Assembler::NE, slow_case);
bind(count);
inc_held_monitor_count(rscratch1);
b(done);
}
bind(slow_case);
// Call the runtime routine for slow case
call_VM_preemptable(noreg,
CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorenter),
lock_reg);
bind(done);
}
bind(done);
}
@ -807,57 +730,29 @@ void InterpreterMacroAssembler::unlock_object(Register lock_reg)
{
assert(lock_reg == c_rarg1, "The argument is only for looks. It must be rarg1");
if (LockingMode == LM_MONITOR) {
call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorexit), lock_reg);
} else {
Label count, done;
const Register swap_reg = r0;
const Register header_reg = c_rarg2; // Will contain the old oopMark
const Register obj_reg = c_rarg3; // Will contain the oop
const Register tmp_reg = c_rarg4; // Temporary used by lightweight_unlock
const Register swap_reg = r0;
const Register header_reg = c_rarg2; // Will contain the old oopMark
const Register obj_reg = c_rarg3; // Will contain the oop
const Register tmp_reg = c_rarg4; // Temporary used by lightweight_unlock
save_bcp(); // Save in case of exception
save_bcp(); // Save in case of exception
// Load oop into obj_reg(%c_rarg3)
ldr(obj_reg, Address(lock_reg, BasicObjectLock::obj_offset()));
if (LockingMode != LM_LIGHTWEIGHT) {
// Convert from BasicObjectLock structure to object and BasicLock
// structure Store the BasicLock address into %r0
lea(swap_reg, Address(lock_reg, BasicObjectLock::lock_offset()));
}
// Free entry
str(zr, Address(lock_reg, BasicObjectLock::obj_offset()));
// Load oop into obj_reg(%c_rarg3)
ldr(obj_reg, Address(lock_reg, BasicObjectLock::obj_offset()));
Label slow_case, done;
lightweight_unlock(obj_reg, header_reg, swap_reg, tmp_reg, slow_case);
b(done);
// Free entry
str(zr, Address(lock_reg, BasicObjectLock::obj_offset()));
Label slow_case;
if (LockingMode == LM_LIGHTWEIGHT) {
lightweight_unlock(obj_reg, header_reg, swap_reg, tmp_reg, slow_case);
b(done);
} else if (LockingMode == LM_LEGACY) {
// Load the old header from BasicLock structure
ldr(header_reg, Address(swap_reg,
BasicLock::displaced_header_offset_in_bytes()));
// Test for recursion
cbz(header_reg, count);
// Atomic swap back the old header
cmpxchg_obj_header(swap_reg, header_reg, obj_reg, rscratch1, count, &slow_case);
bind(count);
dec_held_monitor_count(rscratch1);
b(done);
}
bind(slow_case);
// Call the runtime routine for slow case.
str(obj_reg, Address(lock_reg, BasicObjectLock::obj_offset())); // restore obj
call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorexit), lock_reg);
bind(done);
restore_bcp();
}
bind(slow_case);
// Call the runtime routine for slow case.
str(obj_reg, Address(lock_reg, BasicObjectLock::obj_offset())); // restore obj
call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorexit), lock_reg);
bind(done);
restore_bcp();
}
void InterpreterMacroAssembler::test_method_data_pointer(Register mdp,

View File

@ -6421,10 +6421,14 @@ void MacroAssembler::fill_words(Register base, Register cnt, Register value)
// Intrinsic for
//
// - sun/nio/cs/ISO_8859_1$Encoder.implEncodeISOArray
// return the number of characters copied.
// - java/lang/StringUTF16.compress
// return index of non-latin1 character if copy fails, otherwise 'len'.
// - sun.nio.cs.ISO_8859_1.Encoder#encodeISOArray0(byte[] sa, int sp, byte[] da, int dp, int len)
// Encodes char[] to byte[] in ISO-8859-1
//
// - java.lang.StringCoding#encodeISOArray0(byte[] sa, int sp, byte[] da, int dp, int len)
// Encodes byte[] (containing UTF-16) to byte[] in ISO-8859-1
//
// - java.lang.StringCoding#encodeAsciiArray0(char[] sa, int sp, byte[] da, int dp, int len)
// Encodes char[] to byte[] in ASCII
//
// This version always returns the number of characters copied, and does not
// clobber the 'len' register. A successful copy will complete with the post-
@ -7097,7 +7101,6 @@ void MacroAssembler::double_move(VMRegPair src, VMRegPair dst, Register tmp) {
// - t1, t2, t3: temporary registers, will be destroyed
// - slow: branched to if locking fails, absolute offset may larger than 32KB (imm14 encoding).
void MacroAssembler::lightweight_lock(Register basic_lock, Register obj, Register t1, Register t2, Register t3, Label& slow) {
assert(LockingMode == LM_LIGHTWEIGHT, "only used with new lightweight locking");
assert_different_registers(basic_lock, obj, t1, t2, t3, rscratch1);
Label push;
@ -7157,7 +7160,6 @@ void MacroAssembler::lightweight_lock(Register basic_lock, Register obj, Registe
// - t1, t2, t3: temporary registers
// - slow: branched to if unlocking fails, absolute offset may larger than 32KB (imm14 encoding).
void MacroAssembler::lightweight_unlock(Register obj, Register t1, Register t2, Register t3, Label& slow) {
assert(LockingMode == LM_LIGHTWEIGHT, "only used with new lightweight locking");
// cmpxchg clobbers rscratch1.
assert_different_registers(obj, t1, t2, t3, rscratch1);

View File

@ -1721,7 +1721,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
// We use the same pc/oopMap repeatedly when we call out.
Label native_return;
if (LockingMode != LM_LEGACY && method->is_object_wait0()) {
if (method->is_object_wait0()) {
// For convenience we use the pc we want to resume to in case of preemption on Object.wait.
__ set_last_Java_frame(sp, noreg, native_return, rscratch1);
} else {
@ -1776,44 +1776,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
// Load the oop from the handle
__ ldr(obj_reg, Address(oop_handle_reg, 0));
if (LockingMode == LM_MONITOR) {
__ b(slow_path_lock);
} else if (LockingMode == LM_LEGACY) {
// Load (object->mark() | 1) into swap_reg %r0
__ ldr(rscratch1, Address(obj_reg, oopDesc::mark_offset_in_bytes()));
__ orr(swap_reg, rscratch1, 1);
// Save (object->mark() | 1) into BasicLock's displaced header
__ str(swap_reg, Address(lock_reg, mark_word_offset));
// src -> dest iff dest == r0 else r0 <- dest
__ cmpxchg_obj_header(r0, lock_reg, obj_reg, rscratch1, count, /*fallthrough*/nullptr);
// Hmm should this move to the slow path code area???
// Test if the oopMark is an obvious stack pointer, i.e.,
// 1) (mark & 3) == 0, and
// 2) sp <= mark < mark + os::pagesize()
// These 3 tests can be done by evaluating the following
// expression: ((mark - sp) & (3 - os::vm_page_size())),
// assuming both stack pointer and pagesize have their
// least significant 2 bits clear.
// NOTE: the oopMark is in swap_reg %r0 as the result of cmpxchg
__ sub(swap_reg, sp, swap_reg);
__ neg(swap_reg, swap_reg);
__ ands(swap_reg, swap_reg, 3 - (int)os::vm_page_size());
// Save the test result, for recursive case, the result is zero
__ str(swap_reg, Address(lock_reg, mark_word_offset));
__ br(Assembler::NE, slow_path_lock);
__ bind(count);
__ inc_held_monitor_count(rscratch1);
} else {
assert(LockingMode == LM_LIGHTWEIGHT, "must be");
__ lightweight_lock(lock_reg, obj_reg, swap_reg, tmp, lock_tmp, slow_path_lock);
}
__ lightweight_lock(lock_reg, obj_reg, swap_reg, tmp, lock_tmp, slow_path_lock);
// Slow path will re-enter here
__ bind(lock_done);
@ -1888,7 +1851,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
__ lea(rscratch2, Address(rthread, JavaThread::thread_state_offset()));
__ stlrw(rscratch1, rscratch2);
if (LockingMode != LM_LEGACY && method->is_object_wait0()) {
if (method->is_object_wait0()) {
// Check preemption for Object.wait()
__ ldr(rscratch1, Address(rthread, JavaThread::preempt_alternate_return_offset()));
__ cbz(rscratch1, native_return);
@ -1917,48 +1880,18 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
// Get locked oop from the handle we passed to jni
__ ldr(obj_reg, Address(oop_handle_reg, 0));
Label done, not_recursive;
if (LockingMode == LM_LEGACY) {
// Simple recursive lock?
__ ldr(rscratch1, Address(sp, lock_slot_offset * VMRegImpl::stack_slot_size));
__ cbnz(rscratch1, not_recursive);
__ dec_held_monitor_count(rscratch1);
__ b(done);
}
__ bind(not_recursive);
// Must save r0 if if it is live now because cmpxchg must use it
if (ret_type != T_FLOAT && ret_type != T_DOUBLE && ret_type != T_VOID) {
save_native_result(masm, ret_type, stack_slots);
}
if (LockingMode == LM_MONITOR) {
__ b(slow_path_unlock);
} else if (LockingMode == LM_LEGACY) {
// get address of the stack lock
__ lea(r0, Address(sp, lock_slot_offset * VMRegImpl::stack_slot_size));
// get old displaced header
__ ldr(old_hdr, Address(r0, 0));
// Atomic swap old header if oop still contains the stack lock
Label count;
__ cmpxchg_obj_header(r0, old_hdr, obj_reg, rscratch1, count, &slow_path_unlock);
__ bind(count);
__ dec_held_monitor_count(rscratch1);
} else {
assert(LockingMode == LM_LIGHTWEIGHT, "");
__ lightweight_unlock(obj_reg, old_hdr, swap_reg, lock_tmp, slow_path_unlock);
}
__ lightweight_unlock(obj_reg, old_hdr, swap_reg, lock_tmp, slow_path_unlock);
// slow path re-enters here
__ bind(unlock_done);
if (ret_type != T_FLOAT && ret_type != T_DOUBLE && ret_type != T_VOID) {
restore_native_result(masm, ret_type, stack_slots);
}
__ bind(done);
}
Label dtrace_method_exit, dtrace_method_exit_done;

View File

@ -1478,22 +1478,17 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) {
__ lea(rscratch2, Address(rthread, JavaThread::thread_state_offset()));
__ stlrw(rscratch1, rscratch2);
if (LockingMode != LM_LEGACY) {
// Check preemption for Object.wait()
Label not_preempted;
__ ldr(rscratch1, Address(rthread, JavaThread::preempt_alternate_return_offset()));
__ cbz(rscratch1, not_preempted);
__ str(zr, Address(rthread, JavaThread::preempt_alternate_return_offset()));
__ br(rscratch1);
__ bind(native_return);
__ restore_after_resume(true /* is_native */);
// reload result_handler
__ ldr(result_handler, Address(rfp, frame::interpreter_frame_result_handler_offset*wordSize));
__ bind(not_preempted);
} else {
// any pc will do so just use this one for LM_LEGACY to keep code together.
__ bind(native_return);
}
// Check preemption for Object.wait()
Label not_preempted;
__ ldr(rscratch1, Address(rthread, JavaThread::preempt_alternate_return_offset()));
__ cbz(rscratch1, not_preempted);
__ str(zr, Address(rthread, JavaThread::preempt_alternate_return_offset()));
__ br(rscratch1);
__ bind(native_return);
__ restore_after_resume(true /* is_native */);
// reload result_handler
__ ldr(result_handler, Address(rfp, frame::interpreter_frame_result_handler_offset*wordSize));
__ bind(not_preempted);
// reset_last_Java_frame
__ reset_last_Java_frame(true);

View File

@ -60,6 +60,10 @@ inline void FreezeBase::patch_pd(frame& hf, const frame& caller) {
Unimplemented();
}
inline void FreezeBase::patch_pd_unused(intptr_t* sp) {
Unimplemented();
}
inline void FreezeBase::patch_stack_pd(intptr_t* frame_sp, intptr_t* heap_sp) {
Unimplemented();
}

View File

@ -334,6 +334,9 @@ inline void FreezeBase::patch_pd(frame& hf, const frame& caller) {
#endif
}
inline void FreezeBase::patch_pd_unused(intptr_t* sp) {
}
//////// Thaw
// Fast path

View File

@ -339,11 +339,7 @@ int LIR_Assembler::emit_unwind_handler() {
if (method()->is_synchronized()) {
monitor_address(0, FrameMap::r10_opr);
stub = new MonitorExitStub(FrameMap::r10_opr, true, 0);
if (LockingMode == LM_MONITOR) {
__ j(*stub->entry());
} else {
__ unlock_object(x15, x14, x10, x16, *stub->entry());
}
__ unlock_object(x15, x14, x10, x16, *stub->entry());
__ bind(*stub->continuation());
}
@ -1497,13 +1493,7 @@ void LIR_Assembler::emit_lock(LIR_OpLock* op) {
Register hdr = op->hdr_opr()->as_register();
Register lock = op->lock_opr()->as_register();
Register temp = op->scratch_opr()->as_register();
if (LockingMode == LM_MONITOR) {
if (op->info() != nullptr) {
add_debug_info_for_null_check_here(op->info());
__ null_check(obj, -1);
}
__ j(*op->stub()->entry());
} else if (op->code() == lir_lock) {
if (op->code() == lir_lock) {
assert(BasicLock::displaced_header_offset_in_bytes() == 0, "lock_reg must point to the displaced header");
// add debug info for NullPointerException only if one is possible
int null_check_offset = __ lock_object(hdr, obj, lock, temp, *op->stub()->entry());
@ -1831,7 +1821,7 @@ void LIR_Assembler::leal(LIR_Opr addr, LIR_Opr dest, LIR_PatchCode patch_code, C
}
LIR_Address* adr = addr->as_address_ptr();
Register dst = dest->as_register_lo();
Register dst = dest->as_pointer_register();
assert_different_registers(dst, t0);
if (adr->base()->is_valid() && dst == adr->base()->as_pointer_register() && (!adr->index()->is_cpu_register())) {

View File

@ -837,7 +837,7 @@ void LIRGenerator::do_update_CRC32(Intrinsic* x) {
CallingConvention* cc = frame_map()->c_calling_convention(&signature);
const LIR_Opr result_reg = result_register_for(x->type());
LIR_Opr addr = new_pointer_register();
LIR_Opr addr = new_register(T_ADDRESS);
__ leal(LIR_OprFact::address(a), addr);
crc.load_item_force(cc->at(0));

View File

@ -49,8 +49,6 @@ void C1_MacroAssembler::float_cmp(bool is_float, int unordered_result,
}
int C1_MacroAssembler::lock_object(Register hdr, Register obj, Register disp_hdr, Register temp, Label& slow_case) {
const int aligned_mask = BytesPerWord - 1;
const int hdr_offset = oopDesc::mark_offset_in_bytes();
assert_different_registers(hdr, obj, disp_hdr, temp, t0, t1);
int null_check_offset = -1;
@ -61,97 +59,19 @@ int C1_MacroAssembler::lock_object(Register hdr, Register obj, Register disp_hdr
null_check_offset = offset();
if (LockingMode == LM_LIGHTWEIGHT) {
lightweight_lock(disp_hdr, obj, hdr, temp, t1, slow_case);
} else if (LockingMode == LM_LEGACY) {
if (DiagnoseSyncOnValueBasedClasses != 0) {
load_klass(hdr, obj);
lbu(hdr, Address(hdr, Klass::misc_flags_offset()));
test_bit(temp, hdr, exact_log2(KlassFlags::_misc_is_value_based_class));
bnez(temp, slow_case, /* is_far */ true);
}
Label done;
// Load object header
ld(hdr, Address(obj, hdr_offset));
// and mark it as unlocked
ori(hdr, hdr, markWord::unlocked_value);
// save unlocked object header into the displaced header location on the stack
sd(hdr, Address(disp_hdr, 0));
// test if object header is still the same (i.e. unlocked), and if so, store the
// displaced header address in the object header - if it is not the same, get the
// object header instead
la(temp, Address(obj, hdr_offset));
// if the object header was the same, we're done
cmpxchgptr(hdr, disp_hdr, temp, t1, done, /*fallthough*/nullptr);
// if the object header was not the same, it is now in the hdr register
// => test if it is a stack pointer into the same stack (recursive locking), i.e.:
//
// 1) (hdr & aligned_mask) == 0
// 2) sp <= hdr
// 3) hdr <= sp + page_size
//
// these 3 tests can be done by evaluating the following expression:
//
// (hdr -sp) & (aligned_mask - page_size)
//
// assuming both the stack pointer and page_size have their least
// significant 2 bits cleared and page_size is a power of 2
sub(hdr, hdr, sp);
mv(temp, aligned_mask - (int)os::vm_page_size());
andr(hdr, hdr, temp);
// for recursive locking, the result is zero => save it in the displaced header
// location (null in the displaced hdr location indicates recursive locking)
sd(hdr, Address(disp_hdr, 0));
// otherwise we don't care about the result and handle locking via runtime call
bnez(hdr, slow_case, /* is_far */ true);
// done
bind(done);
inc_held_monitor_count(t0);
}
lightweight_lock(disp_hdr, obj, hdr, temp, t1, slow_case);
return null_check_offset;
}
void C1_MacroAssembler::unlock_object(Register hdr, Register obj, Register disp_hdr, Register temp, Label& slow_case) {
const int aligned_mask = BytesPerWord - 1;
const int hdr_offset = oopDesc::mark_offset_in_bytes();
assert_different_registers(hdr, obj, disp_hdr, temp, t0, t1);
Label done;
if (LockingMode != LM_LIGHTWEIGHT) {
// load displaced header
ld(hdr, Address(disp_hdr, 0));
// if the loaded hdr is null we had recursive locking
// if we had recursive locking, we are done
beqz(hdr, done);
}
// load object
ld(obj, Address(disp_hdr, BasicObjectLock::obj_offset()));
verify_oop(obj);
if (LockingMode == LM_LIGHTWEIGHT) {
lightweight_unlock(obj, hdr, temp, t1, slow_case);
} else if (LockingMode == LM_LEGACY) {
// test if object header is pointing to the displaced header, and if so, restore
// the displaced header in the object - if the object header is not pointing to
// the displaced header, get the object header instead
// if the object header was not pointing to the displaced header,
// we do unlocking via runtime call
if (hdr_offset) {
la(temp, Address(obj, hdr_offset));
cmpxchgptr(disp_hdr, hdr, temp, t1, done, &slow_case);
} else {
cmpxchgptr(disp_hdr, hdr, obj, t1, done, &slow_case);
}
// done
bind(done);
dec_held_monitor_count(t0);
}
lightweight_unlock(obj, hdr, temp, t1, slow_case);
}
// Defines obj, preserves var_size_in_bytes

View File

@ -43,240 +43,11 @@
#define BIND(label) bind(label); BLOCK_COMMENT(#label ":")
void C2_MacroAssembler::fast_lock(Register objectReg, Register boxReg,
Register tmp1Reg, Register tmp2Reg, Register tmp3Reg, Register tmp4Reg) {
// Use cr register to indicate the fast_lock result: zero for success; non-zero for failure.
Register flag = t1;
Register oop = objectReg;
Register box = boxReg;
Register disp_hdr = tmp1Reg;
Register tmp = tmp2Reg;
Label object_has_monitor;
// Finish fast lock successfully. MUST branch to with flag == 0
Label locked;
// Finish fast lock unsuccessfully. slow_path MUST branch to with flag != 0
Label slow_path;
assert(LockingMode != LM_LIGHTWEIGHT, "lightweight locking should use fast_lock_lightweight");
assert_different_registers(oop, box, tmp, disp_hdr, flag, tmp3Reg, t0);
mv(flag, 1);
// Load markWord from object into displaced_header.
ld(disp_hdr, Address(oop, oopDesc::mark_offset_in_bytes()));
if (DiagnoseSyncOnValueBasedClasses != 0) {
load_klass(tmp, oop);
lbu(tmp, Address(tmp, Klass::misc_flags_offset()));
test_bit(tmp, tmp, exact_log2(KlassFlags::_misc_is_value_based_class));
bnez(tmp, slow_path);
}
// Check for existing monitor
test_bit(tmp, disp_hdr, exact_log2(markWord::monitor_value));
bnez(tmp, object_has_monitor);
if (LockingMode == LM_MONITOR) {
j(slow_path);
} else {
assert(LockingMode == LM_LEGACY, "must be");
// Set tmp to be (markWord of object | UNLOCK_VALUE).
ori(tmp, disp_hdr, markWord::unlocked_value);
// Initialize the box. (Must happen before we update the object mark!)
sd(tmp, Address(box, BasicLock::displaced_header_offset_in_bytes()));
// Compare object markWord with an unlocked value (tmp) and if
// equal exchange the stack address of our box with object markWord.
// On failure disp_hdr contains the possibly locked markWord.
cmpxchg(/*memory address*/oop, /*expected value*/tmp, /*new value*/box, Assembler::int64,
Assembler::aq, Assembler::rl, /*result*/disp_hdr);
beq(disp_hdr, tmp, locked);
assert(oopDesc::mark_offset_in_bytes() == 0, "offset of _mark is not 0");
// If the compare-and-exchange succeeded, then we found an unlocked
// object, will have now locked it will continue at label locked
// We did not see an unlocked object so try the fast recursive case.
// Check if the owner is self by comparing the value in the
// markWord of object (disp_hdr) with the stack pointer.
sub(disp_hdr, disp_hdr, sp);
mv(tmp, (intptr_t) (~(os::vm_page_size()-1) | (uintptr_t)markWord::lock_mask_in_place));
// If (mark & lock_mask) == 0 and mark - sp < page_size, we are stack-locking and goto label
// locked, hence we can store 0 as the displaced header in the box, which indicates that it
// is a recursive lock.
andr(tmp/*==0?*/, disp_hdr, tmp);
sd(tmp/*==0, perhaps*/, Address(box, BasicLock::displaced_header_offset_in_bytes()));
beqz(tmp, locked);
j(slow_path);
}
// Handle existing monitor.
bind(object_has_monitor);
// Try to CAS owner (no owner => current thread's _monitor_owner_id).
add(tmp, disp_hdr, (in_bytes(ObjectMonitor::owner_offset()) - markWord::monitor_value));
Register tid = tmp4Reg;
ld(tid, Address(xthread, JavaThread::monitor_owner_id_offset()));
cmpxchg(/*memory address*/tmp, /*expected value*/zr, /*new value*/tid, Assembler::int64,
Assembler::aq, Assembler::rl, /*result*/tmp3Reg); // cas succeeds if tmp3Reg == zr(expected)
// Store a non-null value into the box to avoid looking like a re-entrant
// lock. The fast-path monitor unlock code checks for
// markWord::monitor_value so use markWord::unused_mark which has the
// relevant bit set, and also matches ObjectSynchronizer::slow_enter.
mv(tmp, (address)markWord::unused_mark().value());
sd(tmp, Address(box, BasicLock::displaced_header_offset_in_bytes()));
beqz(tmp3Reg, locked); // CAS success means locking succeeded
bne(tmp3Reg, tid, slow_path); // Check for recursive locking
// Recursive lock case
increment(Address(disp_hdr, in_bytes(ObjectMonitor::recursions_offset()) - markWord::monitor_value), 1, tmp2Reg, tmp3Reg);
bind(locked);
mv(flag, zr);
if (LockingMode == LM_LEGACY) {
inc_held_monitor_count(t0);
}
#ifdef ASSERT
// Check that locked label is reached with flag == 0.
Label flag_correct;
beqz(flag, flag_correct);
stop("Fast Lock Flag != 0");
#endif
bind(slow_path);
#ifdef ASSERT
// Check that slow_path label is reached with flag != 0.
bnez(flag, flag_correct);
stop("Fast Lock Flag == 0");
bind(flag_correct);
#endif
// C2 uses the value of flag (0 vs !0) to determine the continuation.
}
void C2_MacroAssembler::fast_unlock(Register objectReg, Register boxReg,
Register tmp1Reg, Register tmp2Reg) {
// Use cr register to indicate the fast_unlock result: zero for success; non-zero for failure.
Register flag = t1;
Register oop = objectReg;
Register box = boxReg;
Register disp_hdr = tmp1Reg;
Register owner_addr = tmp1Reg;
Register tmp = tmp2Reg;
Label object_has_monitor;
// Finish fast lock successfully. MUST branch to with flag == 0
Label unlocked;
// Finish fast lock unsuccessfully. slow_path MUST branch to with flag != 0
Label slow_path;
assert(LockingMode != LM_LIGHTWEIGHT, "lightweight locking should use fast_unlock_lightweight");
assert_different_registers(oop, box, tmp, disp_hdr, flag, t0);
mv(flag, 1);
if (LockingMode == LM_LEGACY) {
// Find the lock address and load the displaced header from the stack.
ld(disp_hdr, Address(box, BasicLock::displaced_header_offset_in_bytes()));
// If the displaced header is 0, we have a recursive unlock.
beqz(disp_hdr, unlocked);
}
// Handle existing monitor.
ld(tmp, Address(oop, oopDesc::mark_offset_in_bytes()));
test_bit(t0, tmp, exact_log2(markWord::monitor_value));
bnez(t0, object_has_monitor);
if (LockingMode == LM_MONITOR) {
j(slow_path);
} else {
assert(LockingMode == LM_LEGACY, "must be");
// Check if it is still a light weight lock, this is true if we
// see the stack address of the basicLock in the markWord of the
// object.
cmpxchg(/*memory address*/oop, /*expected value*/box, /*new value*/disp_hdr, Assembler::int64,
Assembler::relaxed, Assembler::rl, /*result*/tmp);
beq(box, tmp, unlocked); // box == tmp if cas succeeds
j(slow_path);
}
assert(oopDesc::mark_offset_in_bytes() == 0, "offset of _mark is not 0");
// Handle existing monitor.
bind(object_has_monitor);
subi(tmp, tmp, (int)markWord::monitor_value); // monitor
ld(disp_hdr, Address(tmp, ObjectMonitor::recursions_offset()));
Label notRecursive;
beqz(disp_hdr, notRecursive); // Will be 0 if not recursive.
// Recursive lock
subi(disp_hdr, disp_hdr, 1);
sd(disp_hdr, Address(tmp, ObjectMonitor::recursions_offset()));
j(unlocked);
bind(notRecursive);
// Compute owner address.
la(owner_addr, Address(tmp, ObjectMonitor::owner_offset()));
// Set owner to null.
// Release to satisfy the JMM
membar(MacroAssembler::LoadStore | MacroAssembler::StoreStore);
sd(zr, Address(owner_addr));
// We need a full fence after clearing owner to avoid stranding.
// StoreLoad achieves this.
membar(StoreLoad);
// Check if the entry_list is empty.
ld(t0, Address(tmp, ObjectMonitor::entry_list_offset()));
beqz(t0, unlocked); // If so we are done.
// Check if there is a successor.
ld(t0, Address(tmp, ObjectMonitor::succ_offset()));
bnez(t0, unlocked); // If so we are done.
// Save the monitor pointer in the current thread, so we can try to
// reacquire the lock in SharedRuntime::monitor_exit_helper().
sd(tmp, Address(xthread, JavaThread::unlocked_inflated_monitor_offset()));
mv(flag, 1);
j(slow_path);
bind(unlocked);
mv(flag, zr);
if (LockingMode == LM_LEGACY) {
dec_held_monitor_count(t0);
}
#ifdef ASSERT
// Check that unlocked label is reached with flag == 0.
Label flag_correct;
beqz(flag, flag_correct);
stop("Fast Lock Flag != 0");
#endif
bind(slow_path);
#ifdef ASSERT
// Check that slow_path label is reached with flag != 0.
bnez(flag, flag_correct);
stop("Fast Lock Flag == 0");
bind(flag_correct);
#endif
// C2 uses the value of flag (0 vs !0) to determine the continuation.
}
void C2_MacroAssembler::fast_lock_lightweight(Register obj, Register box,
Register tmp1, Register tmp2, Register tmp3, Register tmp4) {
// Flag register, zero for success; non-zero for failure.
Register flag = t1;
assert(LockingMode == LM_LIGHTWEIGHT, "must be");
assert_different_registers(obj, box, tmp1, tmp2, tmp3, tmp4, flag, t0);
mv(flag, 1);
@ -439,7 +210,6 @@ void C2_MacroAssembler::fast_unlock_lightweight(Register obj, Register box,
// Flag register, zero for success; non-zero for failure.
Register flag = t1;
assert(LockingMode == LM_LIGHTWEIGHT, "must be");
assert_different_registers(obj, box, tmp1, tmp2, tmp3, flag, t0);
mv(flag, 1);
@ -2823,10 +2593,14 @@ void C2_MacroAssembler::char_array_compress_v(Register src, Register dst, Regist
// Intrinsic for
//
// - sun/nio/cs/ISO_8859_1$Encoder.implEncodeISOArray
// return the number of characters copied.
// - java/lang/StringUTF16.compress
// return index of non-latin1 character if copy fails, otherwise 'len'.
// - sun.nio.cs.ISO_8859_1.Encoder#encodeISOArray0(byte[] sa, int sp, byte[] da, int dp, int len)
// Encodes char[] to byte[] in ISO-8859-1
//
// - java.lang.StringCoding#encodeISOArray0(byte[] sa, int sp, byte[] da, int dp, int len)
// Encodes byte[] (containing UTF-16) to byte[] in ISO-8859-1
//
// - java.lang.StringCoding#encodeAsciiArray0(char[] sa, int sp, byte[] da, int dp, int len)
// Encodes char[] to byte[] in ASCII
//
// This version always returns the number of characters copied. A successful
// copy will complete with the post-condition: 'res' == 'len', while an

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@ -49,11 +49,6 @@
const int STUB_THRESHOLD, Label *STUB, Label *DONE);
public:
// Code used by cmpFastLock and cmpFastUnlock mach instructions in .ad file.
void fast_lock(Register object, Register box,
Register tmp1, Register tmp2, Register tmp3, Register tmp4);
void fast_unlock(Register object, Register box, Register tmp1, Register tmp2);
// Code used by cmpFastLockLightweight and cmpFastUnlockLightweight mach instructions in .ad file.
void fast_lock_lightweight(Register object, Register box,
Register tmp1, Register tmp2, Register tmp3, Register tmp4);

View File

@ -194,6 +194,9 @@ inline void FreezeBase::patch_pd(frame& hf, const frame& caller) {
}
}
inline void FreezeBase::patch_pd_unused(intptr_t* sp) {
}
//////// Thaw
// Fast path

View File

@ -733,84 +733,26 @@ void InterpreterMacroAssembler::leave_jfr_critical_section() {
void InterpreterMacroAssembler::lock_object(Register lock_reg)
{
assert(lock_reg == c_rarg1, "The argument is only for looks. It must be c_rarg1");
if (LockingMode == LM_MONITOR) {
call_VM_preemptable(noreg,
CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorenter),
lock_reg);
} else {
Label count, done;
const Register swap_reg = x10;
const Register tmp = c_rarg2;
const Register obj_reg = c_rarg3; // Will contain the oop
const Register tmp2 = c_rarg4;
const Register tmp3 = c_rarg5;
const Register tmp = c_rarg2;
const Register obj_reg = c_rarg3; // Will contain the oop
const Register tmp2 = c_rarg4;
const Register tmp3 = c_rarg5;
const int obj_offset = in_bytes(BasicObjectLock::obj_offset());
const int lock_offset = in_bytes(BasicObjectLock::lock_offset());
const int mark_offset = lock_offset +
BasicLock::displaced_header_offset_in_bytes();
// Load object pointer into obj_reg (c_rarg3)
ld(obj_reg, Address(lock_reg, BasicObjectLock::obj_offset()));
Label slow_case;
Label done, slow_case;
lightweight_lock(lock_reg, obj_reg, tmp, tmp2, tmp3, slow_case);
j(done);
// Load object pointer into obj_reg c_rarg3
ld(obj_reg, Address(lock_reg, obj_offset));
bind(slow_case);
// Call the runtime routine for slow case
call_VM_preemptable(noreg,
CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorenter),
lock_reg);
if (LockingMode == LM_LIGHTWEIGHT) {
lightweight_lock(lock_reg, obj_reg, tmp, tmp2, tmp3, slow_case);
j(done);
} else if (LockingMode == LM_LEGACY) {
if (DiagnoseSyncOnValueBasedClasses != 0) {
load_klass(tmp, obj_reg);
lbu(tmp, Address(tmp, Klass::misc_flags_offset()));
test_bit(tmp, tmp, exact_log2(KlassFlags::_misc_is_value_based_class));
bnez(tmp, slow_case);
}
// Load (object->mark() | 1) into swap_reg
ld(t0, Address(obj_reg, oopDesc::mark_offset_in_bytes()));
ori(swap_reg, t0, 1);
// Save (object->mark() | 1) into BasicLock's displaced header
sd(swap_reg, Address(lock_reg, mark_offset));
assert(lock_offset == 0,
"displached header must be first word in BasicObjectLock");
cmpxchg_obj_header(swap_reg, lock_reg, obj_reg, tmp, count, /*fallthrough*/nullptr);
// Test if the oopMark is an obvious stack pointer, i.e.,
// 1) (mark & 7) == 0, and
// 2) sp <= mark < mark + os::pagesize()
//
// These 3 tests can be done by evaluating the following
// expression: ((mark - sp) & (7 - os::vm_page_size())),
// assuming both stack pointer and pagesize have their
// least significant 3 bits clear.
// NOTE: the oopMark is in swap_reg x10 as the result of cmpxchg
sub(swap_reg, swap_reg, sp);
mv(t0, (int64_t)(7 - (int)os::vm_page_size()));
andr(swap_reg, swap_reg, t0);
// Save the test result, for recursive case, the result is zero
sd(swap_reg, Address(lock_reg, mark_offset));
bnez(swap_reg, slow_case);
bind(count);
inc_held_monitor_count(t0);
j(done);
}
bind(slow_case);
// Call the runtime routine for slow case
call_VM_preemptable(noreg,
CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorenter),
lock_reg);
bind(done);
}
bind(done);
}
@ -829,58 +771,30 @@ void InterpreterMacroAssembler::unlock_object(Register lock_reg)
{
assert(lock_reg == c_rarg1, "The argument is only for looks. It must be rarg1");
if (LockingMode == LM_MONITOR) {
call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorexit), lock_reg);
} else {
Label count, done;
const Register swap_reg = x10;
const Register header_reg = c_rarg2; // Will contain the old oopMark
const Register obj_reg = c_rarg3; // Will contain the oop
const Register tmp_reg = c_rarg4; // Temporary used by lightweight_unlock
const Register swap_reg = x10;
const Register header_reg = c_rarg2; // Will contain the old oopMark
const Register obj_reg = c_rarg3; // Will contain the oop
const Register tmp_reg = c_rarg4; // Temporary used by lightweight_unlock
save_bcp(); // Save in case of exception
save_bcp(); // Save in case of exception
// Load oop into obj_reg (c_rarg3)
ld(obj_reg, Address(lock_reg, BasicObjectLock::obj_offset()));
if (LockingMode != LM_LIGHTWEIGHT) {
// Convert from BasicObjectLock structure to object and BasicLock
// structure Store the BasicLock address into x10
la(swap_reg, Address(lock_reg, BasicObjectLock::lock_offset()));
}
// Free entry
sd(zr, Address(lock_reg, BasicObjectLock::obj_offset()));
// Load oop into obj_reg(c_rarg3)
ld(obj_reg, Address(lock_reg, BasicObjectLock::obj_offset()));
Label done, slow_case;
lightweight_unlock(obj_reg, header_reg, swap_reg, tmp_reg, slow_case);
j(done);
// Free entry
sd(zr, Address(lock_reg, BasicObjectLock::obj_offset()));
bind(slow_case);
// Call the runtime routine for slow case.
sd(obj_reg, Address(lock_reg, BasicObjectLock::obj_offset())); // restore obj
call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorexit), lock_reg);
Label slow_case;
if (LockingMode == LM_LIGHTWEIGHT) {
lightweight_unlock(obj_reg, header_reg, swap_reg, tmp_reg, slow_case);
j(done);
} else if (LockingMode == LM_LEGACY) {
// Load the old header from BasicLock structure
ld(header_reg, Address(swap_reg,
BasicLock::displaced_header_offset_in_bytes()));
// Test for recursion
beqz(header_reg, count);
// Atomic swap back the old header
cmpxchg_obj_header(swap_reg, header_reg, obj_reg, tmp_reg, count, &slow_case);
bind(count);
dec_held_monitor_count(t0);
j(done);
}
bind(slow_case);
// Call the runtime routine for slow case.
sd(obj_reg, Address(lock_reg, BasicObjectLock::obj_offset())); // restore obj
call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorexit), lock_reg);
bind(done);
restore_bcp();
}
bind(done);
restore_bcp();
}

View File

@ -6421,7 +6421,6 @@ void MacroAssembler::test_bit(Register Rd, Register Rs, uint32_t bit_pos) {
// - tmp1, tmp2, tmp3: temporary registers, will be destroyed
// - slow: branched to if locking fails
void MacroAssembler::lightweight_lock(Register basic_lock, Register obj, Register tmp1, Register tmp2, Register tmp3, Label& slow) {
assert(LockingMode == LM_LIGHTWEIGHT, "only used with new lightweight locking");
assert_different_registers(basic_lock, obj, tmp1, tmp2, tmp3, t0);
Label push;
@ -6481,7 +6480,6 @@ void MacroAssembler::lightweight_lock(Register basic_lock, Register obj, Registe
// - tmp1, tmp2, tmp3: temporary registers
// - slow: branched to if unlocking fails
void MacroAssembler::lightweight_unlock(Register obj, Register tmp1, Register tmp2, Register tmp3, Label& slow) {
assert(LockingMode == LM_LIGHTWEIGHT, "only used with new lightweight locking");
assert_different_registers(obj, tmp1, tmp2, tmp3, t0);
#ifdef ASSERT

View File

@ -1,5 +1,5 @@
//
// Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved.
// Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved.
// Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved.
// Copyright (c) 2020, 2024, Huawei Technologies Co., Ltd. All rights reserved.
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@ -11021,45 +11021,9 @@ instruct tlsLoadP(javaThread_RegP dst)
// inlined locking and unlocking
// using t1 as the 'flag' register to bridge the BoolNode producers and consumers
instruct cmpFastLock(rFlagsReg cr, iRegP object, iRegP box,
iRegPNoSp tmp1, iRegPNoSp tmp2, iRegPNoSp tmp3, iRegPNoSp tmp4)
%{
predicate(LockingMode != LM_LIGHTWEIGHT);
match(Set cr (FastLock object box));
effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4);
ins_cost(10 * DEFAULT_COST);
format %{ "fastlock $object,$box\t! kills $tmp1,$tmp2,$tmp3,$tmp4 #@cmpFastLock" %}
ins_encode %{
__ fast_lock($object$$Register, $box$$Register,
$tmp1$$Register, $tmp2$$Register, $tmp3$$Register, $tmp4$$Register);
%}
ins_pipe(pipe_serial);
%}
// using t1 as the 'flag' register to bridge the BoolNode producers and consumers
instruct cmpFastUnlock(rFlagsReg cr, iRegP object, iRegP box, iRegPNoSp tmp1, iRegPNoSp tmp2)
%{
predicate(LockingMode != LM_LIGHTWEIGHT);
match(Set cr (FastUnlock object box));
effect(TEMP tmp1, TEMP tmp2);
ins_cost(10 * DEFAULT_COST);
format %{ "fastunlock $object,$box\t! kills $tmp1, $tmp2, #@cmpFastUnlock" %}
ins_encode %{
__ fast_unlock($object$$Register, $box$$Register, $tmp1$$Register, $tmp2$$Register);
%}
ins_pipe(pipe_serial);
%}
instruct cmpFastLockLightweight(rFlagsReg cr, iRegP object, iRegP box,
iRegPNoSp tmp1, iRegPNoSp tmp2, iRegPNoSp tmp3, iRegPNoSp tmp4)
%{
predicate(LockingMode == LM_LIGHTWEIGHT);
match(Set cr (FastLock object box));
effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4);
@ -11074,10 +11038,10 @@ instruct cmpFastLockLightweight(rFlagsReg cr, iRegP object, iRegP box,
ins_pipe(pipe_serial);
%}
// using t1 as the 'flag' register to bridge the BoolNode producers and consumers
instruct cmpFastUnlockLightweight(rFlagsReg cr, iRegP object, iRegP box,
iRegPNoSp tmp1, iRegPNoSp tmp2, iRegPNoSp tmp3)
%{
predicate(LockingMode == LM_LIGHTWEIGHT);
match(Set cr (FastUnlock object box));
effect(TEMP tmp1, TEMP tmp2, TEMP tmp3);

View File

@ -1637,7 +1637,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
// We use the same pc/oopMap repeatedly when we call out.
Label native_return;
if (LockingMode != LM_LEGACY && method->is_object_wait0()) {
if (method->is_object_wait0()) {
// For convenience we use the pc we want to resume to in case of preemption on Object.wait.
__ set_last_Java_frame(sp, noreg, native_return, t0);
} else {
@ -1679,8 +1679,6 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
Label lock_done;
if (method->is_synchronized()) {
Label count;
const int mark_word_offset = BasicLock::displaced_header_offset_in_bytes();
// Get the handle (the 2nd argument)
@ -1693,42 +1691,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
// Load the oop from the handle
__ ld(obj_reg, Address(oop_handle_reg, 0));
if (LockingMode == LM_MONITOR) {
__ j(slow_path_lock);
} else if (LockingMode == LM_LEGACY) {
// Load (object->mark() | 1) into swap_reg % x10
__ ld(t0, Address(obj_reg, oopDesc::mark_offset_in_bytes()));
__ ori(swap_reg, t0, 1);
// Save (object->mark() | 1) into BasicLock's displaced header
__ sd(swap_reg, Address(lock_reg, mark_word_offset));
// src -> dest if dest == x10 else x10 <- dest
__ cmpxchg_obj_header(x10, lock_reg, obj_reg, lock_tmp, count, /*fallthrough*/nullptr);
// Test if the oopMark is an obvious stack pointer, i.e.,
// 1) (mark & 3) == 0, and
// 2) sp <= mark < mark + os::pagesize()
// These 3 tests can be done by evaluating the following
// expression: ((mark - sp) & (3 - os::vm_page_size())),
// assuming both stack pointer and pagesize have their
// least significant 2 bits clear.
// NOTE: the oopMark is in swap_reg % 10 as the result of cmpxchg
__ sub(swap_reg, swap_reg, sp);
__ mv(t0, 3 - (int)os::vm_page_size());
__ andr(swap_reg, swap_reg, t0);
// Save the test result, for recursive case, the result is zero
__ sd(swap_reg, Address(lock_reg, mark_word_offset));
__ bnez(swap_reg, slow_path_lock);
__ bind(count);
__ inc_held_monitor_count(t0);
} else {
assert(LockingMode == LM_LIGHTWEIGHT, "must be");
__ lightweight_lock(lock_reg, obj_reg, swap_reg, tmp, lock_tmp, slow_path_lock);
}
__ lightweight_lock(lock_reg, obj_reg, swap_reg, tmp, lock_tmp, slow_path_lock);
// Slow path will re-enter here
__ bind(lock_done);
@ -1789,7 +1752,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
__ membar(MacroAssembler::LoadStore | MacroAssembler::StoreStore);
__ sw(t0, Address(t1));
if (LockingMode != LM_LEGACY && method->is_object_wait0()) {
if (method->is_object_wait0()) {
// Check preemption for Object.wait()
__ ld(t1, Address(xthread, JavaThread::preempt_alternate_return_offset()));
__ beqz(t1, native_return);
@ -1818,48 +1781,18 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
// Get locked oop from the handle we passed to jni
__ ld(obj_reg, Address(oop_handle_reg, 0));
Label done, not_recursive;
if (LockingMode == LM_LEGACY) {
// Simple recursive lock?
__ ld(t0, Address(sp, lock_slot_offset * VMRegImpl::stack_slot_size));
__ bnez(t0, not_recursive);
__ dec_held_monitor_count(t0);
__ j(done);
}
__ bind(not_recursive);
// Must save x10 if if it is live now because cmpxchg must use it
if (ret_type != T_FLOAT && ret_type != T_DOUBLE && ret_type != T_VOID) {
save_native_result(masm, ret_type, stack_slots);
}
if (LockingMode == LM_MONITOR) {
__ j(slow_path_unlock);
} else if (LockingMode == LM_LEGACY) {
// get address of the stack lock
__ la(x10, Address(sp, lock_slot_offset * VMRegImpl::stack_slot_size));
// get old displaced header
__ ld(old_hdr, Address(x10, 0));
// Atomic swap old header if oop still contains the stack lock
Label count;
__ cmpxchg_obj_header(x10, old_hdr, obj_reg, lock_tmp, count, &slow_path_unlock);
__ bind(count);
__ dec_held_monitor_count(t0);
} else {
assert(LockingMode == LM_LIGHTWEIGHT, "");
__ lightweight_unlock(obj_reg, old_hdr, swap_reg, lock_tmp, slow_path_unlock);
}
__ lightweight_unlock(obj_reg, old_hdr, swap_reg, lock_tmp, slow_path_unlock);
// slow path re-enters here
__ bind(unlock_done);
if (ret_type != T_FLOAT && ret_type != T_DOUBLE && ret_type != T_VOID) {
restore_native_result(masm, ret_type, stack_slots);
}
__ bind(done);
}
Label dtrace_method_exit, dtrace_method_exit_done;

View File

@ -1253,22 +1253,17 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) {
__ mv(t0, _thread_in_Java);
__ sw(t0, Address(xthread, JavaThread::thread_state_offset()));
if (LockingMode != LM_LEGACY) {
// Check preemption for Object.wait()
Label not_preempted;
__ ld(t1, Address(xthread, JavaThread::preempt_alternate_return_offset()));
__ beqz(t1, not_preempted);
__ sd(zr, Address(xthread, JavaThread::preempt_alternate_return_offset()));
__ jr(t1);
__ bind(native_return);
__ restore_after_resume(true /* is_native */);
// reload result_handler
__ ld(result_handler, Address(fp, frame::interpreter_frame_result_handler_offset * wordSize));
__ bind(not_preempted);
} else {
// any pc will do so just use this one for LM_LEGACY to keep code together.
__ bind(native_return);
}
// Check preemption for Object.wait()
Label not_preempted;
__ ld(t1, Address(xthread, JavaThread::preempt_alternate_return_offset()));
__ beqz(t1, not_preempted);
__ sd(zr, Address(xthread, JavaThread::preempt_alternate_return_offset()));
__ jr(t1);
__ bind(native_return);
__ restore_after_resume(true /* is_native */);
// reload result_handler
__ ld(result_handler, Address(fp, frame::interpreter_frame_result_handler_offset * wordSize));
__ bind(not_preempted);
// reset_last_Java_frame
__ reset_last_Java_frame(true);

View File

@ -229,11 +229,7 @@ int LIR_Assembler::emit_unwind_handler() {
LIR_Opr lock = FrameMap::as_opr(Z_R1_scratch);
monitor_address(0, lock);
stub = new MonitorExitStub(lock, true, 0);
if (LockingMode == LM_MONITOR) {
__ branch_optimized(Assembler::bcondAlways, *stub->entry());
} else {
__ unlock_object(Rtmp1, Rtmp2, lock->as_register(), *stub->entry());
}
__ unlock_object(Rtmp1, Rtmp2, lock->as_register(), *stub->entry());
__ bind(*stub->continuation());
}
@ -2714,13 +2710,7 @@ void LIR_Assembler::emit_lock(LIR_OpLock* op) {
Register obj = op->obj_opr()->as_register(); // May not be an oop.
Register hdr = op->hdr_opr()->as_register();
Register lock = op->lock_opr()->as_register();
if (LockingMode == LM_MONITOR) {
if (op->info() != nullptr) {
add_debug_info_for_null_check_here(op->info());
__ null_check(obj);
}
__ branch_optimized(Assembler::bcondAlways, *op->stub()->entry());
} else if (op->code() == lir_lock) {
if (op->code() == lir_lock) {
assert(BasicLock::displaced_header_offset_in_bytes() == 0, "lock_reg must point to the displaced header");
// Add debug info for NullPointerException only if one is possible.
if (op->info() != nullptr) {

View File

@ -58,8 +58,6 @@ void C1_MacroAssembler::verified_entry(bool breakAtEntry) {
}
void C1_MacroAssembler::lock_object(Register Rmark, Register Roop, Register Rbox, Label& slow_case) {
const int hdr_offset = oopDesc::mark_offset_in_bytes();
const Register tmp = Z_R1_scratch;
assert_different_registers(Rmark, Roop, Rbox, tmp);
@ -69,95 +67,17 @@ void C1_MacroAssembler::lock_object(Register Rmark, Register Roop, Register Rbox
// Save object being locked into the BasicObjectLock...
z_stg(Roop, Address(Rbox, BasicObjectLock::obj_offset()));
assert(LockingMode != LM_MONITOR, "LM_MONITOR is already handled, by emit_lock()");
if (LockingMode == LM_LIGHTWEIGHT) {
lightweight_lock(Rbox, Roop, Rmark, tmp, slow_case);
} else if (LockingMode == LM_LEGACY) {
if (DiagnoseSyncOnValueBasedClasses != 0) {
load_klass(tmp, Roop);
z_tm(Address(tmp, Klass::misc_flags_offset()), KlassFlags::_misc_is_value_based_class);
branch_optimized(Assembler::bcondAllOne, slow_case);
}
NearLabel done;
// Load object header.
z_lg(Rmark, Address(Roop, hdr_offset));
// and mark it as unlocked.
z_oill(Rmark, markWord::unlocked_value);
// Save unlocked object header into the displaced header location on the stack.
z_stg(Rmark, Address(Rbox, BasicLock::displaced_header_offset_in_bytes()));
// Test if object header is still the same (i.e. unlocked), and if so, store the
// displaced header address in the object header. If it is not the same, get the
// object header instead.
z_csg(Rmark, Rbox, hdr_offset, Roop);
// If the object header was the same, we're done.
branch_optimized(Assembler::bcondEqual, done);
// If the object header was not the same, it is now in the Rmark register.
// => Test if it is a stack pointer into the same stack (recursive locking), i.e.:
//
// 1) (Rmark & markWord::lock_mask_in_place) == 0
// 2) rsp <= Rmark
// 3) Rmark <= rsp + page_size
//
// These 3 tests can be done by evaluating the following expression:
//
// (Rmark - Z_SP) & (~(page_size-1) | markWord::lock_mask_in_place)
//
// assuming both the stack pointer and page_size have their least
// significant 2 bits cleared and page_size is a power of 2
z_sgr(Rmark, Z_SP);
load_const_optimized(Z_R0_scratch, (~(os::vm_page_size() - 1) | markWord::lock_mask_in_place));
z_ngr(Rmark, Z_R0_scratch); // AND sets CC (result eq/ne 0).
// For recursive locking, the result is zero. => Save it in the displaced header
// location (null in the displaced Rmark location indicates recursive locking).
z_stg(Rmark, Address(Rbox, BasicLock::displaced_header_offset_in_bytes()));
// Otherwise we don't care about the result and handle locking via runtime call.
branch_optimized(Assembler::bcondNotZero, slow_case);
// done
bind(done);
} else {
assert(false, "Unhandled LockingMode:%d", LockingMode);
}
lightweight_lock(Rbox, Roop, Rmark, tmp, slow_case);
}
void C1_MacroAssembler::unlock_object(Register Rmark, Register Roop, Register Rbox, Label& slow_case) {
const int hdr_offset = oopDesc::mark_offset_in_bytes();
assert_different_registers(Rmark, Roop, Rbox);
NearLabel done;
if (LockingMode != LM_LIGHTWEIGHT) {
// Load displaced header.
z_ltg(Rmark, Address(Rbox, BasicLock::displaced_header_offset_in_bytes()));
// If the loaded Rmark is null we had recursive locking, and we are done.
z_bre(done);
}
// Load object.
z_lg(Roop, Address(Rbox, BasicObjectLock::obj_offset()));
verify_oop(Roop, FILE_AND_LINE);
if (LockingMode == LM_LIGHTWEIGHT) {
lightweight_unlock(Roop, Rmark, Z_R1_scratch, slow_case);
} else if (LockingMode == LM_LEGACY) {
// Test if object header is pointing to the displaced header, and if so, restore
// the displaced header in the object. If the object header is not pointing to
// the displaced header, get the object header instead.
z_csg(Rbox, Rmark, hdr_offset, Roop);
// If the object header was not pointing to the displaced header,
// we do unlocking via runtime call.
branch_optimized(Assembler::bcondNotEqual, slow_case);
} else {
assert(false, "Unhandled LockingMode:%d", LockingMode);
}
// done
bind(done);
lightweight_unlock(Roop, Rmark, Z_R1_scratch, slow_case);
}
void C1_MacroAssembler::try_allocate(

View File

@ -60,6 +60,10 @@ inline void FreezeBase::patch_pd(frame& hf, const frame& caller) {
Unimplemented();
}
inline void FreezeBase::patch_pd_unused(intptr_t* sp) {
Unimplemented();
}
inline void FreezeBase::patch_stack_pd(intptr_t* frame_sp, intptr_t* heap_sp) {
Unimplemented();
}

View File

@ -1008,109 +1008,18 @@ void InterpreterMacroAssembler::remove_activation(TosState state,
// object (Z_R11, Z_R2) - Address of the object to be locked.
// templateTable (monitorenter) is using Z_R2 for object
void InterpreterMacroAssembler::lock_object(Register monitor, Register object) {
if (LockingMode == LM_MONITOR) {
call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorenter), monitor);
return;
}
// template code: (for LM_LEGACY)
//
// markWord displaced_header = obj->mark().set_unlocked();
// monitor->lock()->set_displaced_header(displaced_header);
// if (Atomic::cmpxchg(/*addr*/obj->mark_addr(), /*cmp*/displaced_header, /*ex=*/monitor) == displaced_header) {
// // We stored the monitor address into the object's mark word.
// } else if (THREAD->is_lock_owned((address)displaced_header))
// // Simple recursive case.
// monitor->lock()->set_displaced_header(nullptr);
// } else {
// // Slow path.
// InterpreterRuntime::monitorenter(THREAD, monitor);
// }
const int hdr_offset = oopDesc::mark_offset_in_bytes();
const Register header = Z_ARG5;
const Register object_mark_addr = Z_ARG4;
const Register current_header = Z_ARG5;
const Register tmp = Z_R1_scratch;
NearLabel done, slow_case;
// markWord header = obj->mark().set_unlocked();
if (LockingMode == LM_LIGHTWEIGHT) {
lightweight_lock(monitor, object, header, tmp, slow_case);
} else if (LockingMode == LM_LEGACY) {
if (DiagnoseSyncOnValueBasedClasses != 0) {
load_klass(tmp, object);
z_tm(Address(tmp, Klass::misc_flags_offset()), KlassFlags::_misc_is_value_based_class);
z_btrue(slow_case);
}
// Load markWord from object into header.
z_lg(header, hdr_offset, object);
// Set header to be (markWord of object | UNLOCK_VALUE).
// This will not change anything if it was unlocked before.
z_oill(header, markWord::unlocked_value);
// monitor->lock()->set_displaced_header(displaced_header);
const int lock_offset = in_bytes(BasicObjectLock::lock_offset());
const int mark_offset = lock_offset + BasicLock::displaced_header_offset_in_bytes();
// Initialize the box (Must happen before we update the object mark!).
z_stg(header, mark_offset, monitor);
// if (Atomic::cmpxchg(/*addr*/obj->mark_addr(), /*cmp*/displaced_header, /*ex=*/monitor) == displaced_header) {
// not necessary, use offset in instruction directly.
// add2reg(object_mark_addr, hdr_offset, object);
// Store stack address of the BasicObjectLock (this is monitor) into object.
z_csg(header, monitor, hdr_offset, object);
assert(current_header == header,
"must be same register"); // Identified two registers from z/Architecture.
z_bre(done);
// } else if (THREAD->is_lock_owned((address)displaced_header))
// // Simple recursive case.
// monitor->lock()->set_displaced_header(nullptr);
// We did not see an unlocked object so try the fast recursive case.
// Check if owner is self by comparing the value in the markWord of object
// (current_header) with the stack pointer.
z_sgr(current_header, Z_SP);
assert(os::vm_page_size() > 0xfff, "page size too small - change the constant");
// The prior sequence "LGR, NGR, LTGR" can be done better
// (Z_R1 is temp and not used after here).
load_const_optimized(Z_R0, (~(os::vm_page_size() - 1) | markWord::lock_mask_in_place));
z_ngr(Z_R0, current_header); // AND sets CC (result eq/ne 0)
// If condition is true we are done and hence we can store 0 in the displaced
// header indicating it is a recursive lock and be done.
z_brne(slow_case);
z_release(); // Member unnecessary on zarch AND because the above csg does a sync before and after.
z_stg(Z_R0/*==0!*/, mark_offset, monitor);
}
lightweight_lock(monitor, object, header, tmp, slow_case);
z_bru(done);
// } else {
// // Slow path.
// InterpreterRuntime::monitorenter(THREAD, monitor);
// None of the above fast optimizations worked so we have to get into the
// slow case of monitor enter.
bind(slow_case);
call_VM(noreg,
CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorenter),
monitor);
// }
bind(done);
}
@ -1122,28 +1031,6 @@ void InterpreterMacroAssembler::lock_object(Register monitor, Register object) {
//
// Throw IllegalMonitorException if object is not locked by current thread.
void InterpreterMacroAssembler::unlock_object(Register monitor, Register object) {
if (LockingMode == LM_MONITOR) {
call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorexit), monitor);
return;
}
// else {
// template code: (for LM_LEGACY):
//
// if ((displaced_header = monitor->displaced_header()) == nullptr) {
// // Recursive unlock. Mark the monitor unlocked by setting the object field to null.
// monitor->set_obj(nullptr);
// } else if (Atomic::cmpxchg(obj->mark_addr(), monitor, displaced_header) == monitor) {
// // We swapped the unlocked mark in displaced_header into the object's mark word.
// monitor->set_obj(nullptr);
// } else {
// // Slow path.
// InterpreterRuntime::monitorexit(monitor);
// }
const int hdr_offset = oopDesc::mark_offset_in_bytes();
const Register header = Z_ARG4;
const Register current_header = Z_R1_scratch;
Address obj_entry(monitor, BasicObjectLock::obj_offset());
@ -1159,56 +1046,16 @@ void InterpreterMacroAssembler::unlock_object(Register monitor, Register object)
assert_different_registers(monitor, object, header, current_header);
// if ((displaced_header = monitor->displaced_header()) == nullptr) {
// // Recursive unlock. Mark the monitor unlocked by setting the object field to null.
// monitor->set_obj(nullptr);
// monitor->lock()->set_displaced_header(displaced_header);
const int lock_offset = in_bytes(BasicObjectLock::lock_offset());
const int mark_offset = lock_offset + BasicLock::displaced_header_offset_in_bytes();
clear_mem(obj_entry, sizeof(oop));
if (LockingMode != LM_LIGHTWEIGHT) {
// Test first if we are in the fast recursive case.
MacroAssembler::load_and_test_long(header, Address(monitor, mark_offset));
z_bre(done); // header == 0 -> goto done
}
// } else if (Atomic::cmpxchg(obj->mark_addr(), monitor, displaced_header) == monitor) {
// // We swapped the unlocked mark in displaced_header into the object's mark word.
// monitor->set_obj(nullptr);
// If we still have a lightweight lock, unlock the object and be done.
if (LockingMode == LM_LIGHTWEIGHT) {
lightweight_unlock(object, header, current_header, slow_case);
z_bru(done);
} else {
// The markword is expected to be at offset 0.
// This is not required on s390, at least not here.
assert(hdr_offset == 0, "unlock_object: review code below");
// We have the displaced header in header. If the lock is still
// lightweight, it will contain the monitor address and we'll store the
// displaced header back into the object's mark word.
z_lgr(current_header, monitor);
z_csg(current_header, header, hdr_offset, object);
z_bre(done);
}
// } else {
// // Slow path.
// InterpreterRuntime::monitorexit(monitor);
lightweight_unlock(object, header, current_header, slow_case);
z_bru(done);
// The lock has been converted into a heavy lock and hence
// we need to get into the slow case.
bind(slow_case);
z_stg(object, obj_entry); // Restore object entry, has been cleared above.
call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorexit), monitor);
// }
bind(done);
}

View File

@ -3766,211 +3766,6 @@ void MacroAssembler::increment_counter_eq(address counter_address, Register tmp1
bind(l);
}
// "The box" is the space on the stack where we copy the object mark.
void MacroAssembler::compiler_fast_lock_object(Register oop, Register box, Register temp1, Register temp2) {
assert(LockingMode != LM_LIGHTWEIGHT, "uses fast_lock_lightweight");
assert_different_registers(oop, box, temp1, temp2, Z_R0_scratch);
Register displacedHeader = temp1;
Register currentHeader = temp1;
Register temp = temp2;
NearLabel done, object_has_monitor;
const int hdr_offset = oopDesc::mark_offset_in_bytes();
BLOCK_COMMENT("compiler_fast_lock_object {");
// Load markWord from oop into mark.
z_lg(displacedHeader, hdr_offset, oop);
if (DiagnoseSyncOnValueBasedClasses != 0) {
load_klass(temp, oop);
z_tm(Address(temp, Klass::misc_flags_offset()), KlassFlags::_misc_is_value_based_class);
z_brne(done);
}
// Handle existing monitor.
// The object has an existing monitor iff (mark & monitor_value) != 0.
guarantee(Immediate::is_uimm16(markWord::monitor_value), "must be half-word");
z_tmll(displacedHeader, markWord::monitor_value);
z_brnaz(object_has_monitor);
if (LockingMode == LM_MONITOR) {
// Set NE to indicate 'failure' -> take slow-path
// From loading the markWord, we know that oop != nullptr
z_ltgr(oop, oop);
z_bru(done);
} else {
assert(LockingMode == LM_LEGACY, "must be");
// Set mark to markWord | markWord::unlocked_value.
z_oill(displacedHeader, markWord::unlocked_value);
// Load Compare Value application register.
// Initialize the box (must happen before we update the object mark).
z_stg(displacedHeader, BasicLock::displaced_header_offset_in_bytes(), box);
// Compare object markWord with mark and if equal, exchange box with object markWork.
// If the compare-and-swap succeeds, then we found an unlocked object and have now locked it.
z_csg(displacedHeader, box, hdr_offset, oop);
assert(currentHeader == displacedHeader, "must be same register"); // Identified two registers from z/Architecture.
z_bre(done);
// We did not see an unlocked object
// currentHeader contains what is currently stored in the oop's markWord.
// We might have a recursive case. Verify by checking if the owner is self.
// To do so, compare the value in the markWord (currentHeader) with the stack pointer.
z_sgr(currentHeader, Z_SP);
load_const_optimized(temp, (~(os::vm_page_size() - 1) | markWord::lock_mask_in_place));
z_ngr(currentHeader, temp);
// result zero: owner is self -> recursive lock. Indicate that by storing 0 in the box.
// result not-zero: attempt failed. We don't hold the lock -> go for slow case.
z_stg(currentHeader/*==0 or not 0*/, BasicLock::displaced_header_offset_in_bytes(), box);
z_bru(done);
}
bind(object_has_monitor);
Register zero = temp;
Register monitor_tagged = displacedHeader; // Tagged with markWord::monitor_value.
// Try to CAS owner (no owner => current thread's _monitor_owner_id).
// If csg succeeds then CR=EQ, otherwise, register zero is filled
// with the current owner.
z_lghi(zero, 0);
z_lg(Z_R0_scratch, Address(Z_thread, JavaThread::monitor_owner_id_offset()));
z_csg(zero, Z_R0_scratch, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner), monitor_tagged);
// Store a non-null value into the box.
z_stg(box, BasicLock::displaced_header_offset_in_bytes(), box);
z_bre(done); // acquired the lock for the first time.
BLOCK_COMMENT("fast_path_recursive_lock {");
// Check if we are already the owner (recursive lock)
z_cgr(Z_R0_scratch, zero); // owner is stored in zero by "z_csg" above
z_brne(done); // not a recursive lock
// Current thread already owns the lock. Just increment recursion count.
z_agsi(Address(monitor_tagged, OM_OFFSET_NO_MONITOR_VALUE_TAG(recursions)), 1ll);
z_cgr(zero, zero); // set the CC to EQUAL
BLOCK_COMMENT("} fast_path_recursive_lock");
bind(done);
BLOCK_COMMENT("} compiler_fast_lock_object");
// If locking was successful, CR should indicate 'EQ'.
// The compiler or the native wrapper generates a branch to the runtime call
// _complete_monitor_locking_Java.
}
void MacroAssembler::compiler_fast_unlock_object(Register oop, Register box, Register temp1, Register temp2) {
assert(LockingMode != LM_LIGHTWEIGHT, "uses fast_unlock_lightweight");
assert_different_registers(oop, box, temp1, temp2, Z_R0_scratch);
Register displacedHeader = temp1;
Register currentHeader = temp2;
Register temp = temp1;
const int hdr_offset = oopDesc::mark_offset_in_bytes();
Label done, object_has_monitor, not_recursive;
BLOCK_COMMENT("compiler_fast_unlock_object {");
if (LockingMode == LM_LEGACY) {
// Find the lock address and load the displaced header from the stack.
// if the displaced header is zero, we have a recursive unlock.
load_and_test_long(displacedHeader, Address(box, BasicLock::displaced_header_offset_in_bytes()));
z_bre(done);
}
// Handle existing monitor.
// The object has an existing monitor iff (mark & monitor_value) != 0.
z_lg(currentHeader, hdr_offset, oop);
guarantee(Immediate::is_uimm16(markWord::monitor_value), "must be half-word");
z_tmll(currentHeader, markWord::monitor_value);
z_brnaz(object_has_monitor);
if (LockingMode == LM_MONITOR) {
// Set NE to indicate 'failure' -> take slow-path
z_ltgr(oop, oop);
z_bru(done);
} else {
assert(LockingMode == LM_LEGACY, "must be");
// Check if it is still a lightweight lock, this is true if we see
// the stack address of the basicLock in the markWord of the object
// copy box to currentHeader such that csg does not kill it.
z_lgr(currentHeader, box);
z_csg(currentHeader, displacedHeader, hdr_offset, oop);
z_bru(done); // csg sets CR as desired.
}
// In case of LM_LIGHTWEIGHT, we may reach here with (temp & ObjectMonitor::ANONYMOUS_OWNER) != 0.
// This is handled like owner thread mismatches: We take the slow path.
// Handle existing monitor.
bind(object_has_monitor);
z_lg(Z_R0_scratch, Address(Z_thread, JavaThread::monitor_owner_id_offset()));
z_cg(Z_R0_scratch, Address(currentHeader, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)));
z_brne(done);
BLOCK_COMMENT("fast_path_recursive_unlock {");
load_and_test_long(temp, Address(currentHeader, OM_OFFSET_NO_MONITOR_VALUE_TAG(recursions)));
z_bre(not_recursive); // if 0 then jump, it's not recursive locking
// Recursive inflated unlock
z_agsi(Address(currentHeader, OM_OFFSET_NO_MONITOR_VALUE_TAG(recursions)), -1ll);
z_cgr(currentHeader, currentHeader); // set the CC to EQUAL
BLOCK_COMMENT("} fast_path_recursive_unlock");
z_bru(done);
bind(not_recursive);
NearLabel set_eq_unlocked;
// Set owner to null.
// Release to satisfy the JMM
z_release();
z_lghi(temp, 0);
z_stg(temp, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner), currentHeader);
// We need a full fence after clearing owner to avoid stranding.
z_fence();
// Check if the entry_list is empty.
load_and_test_long(temp, Address(currentHeader, OM_OFFSET_NO_MONITOR_VALUE_TAG(entry_list)));
z_bre(done); // If so we are done.
// Check if there is a successor.
load_and_test_long(temp, Address(currentHeader, OM_OFFSET_NO_MONITOR_VALUE_TAG(succ)));
z_brne(set_eq_unlocked); // If so we are done.
// Save the monitor pointer in the current thread, so we can try to
// reacquire the lock in SharedRuntime::monitor_exit_helper().
z_xilf(currentHeader, markWord::monitor_value);
z_stg(currentHeader, Address(Z_thread, JavaThread::unlocked_inflated_monitor_offset()));
z_ltgr(oop, oop); // Set flag = NE
z_bru(done);
bind(set_eq_unlocked);
z_cr(temp, temp); // Set flag = EQ
bind(done);
BLOCK_COMMENT("} compiler_fast_unlock_object");
// flag == EQ indicates success
// flag == NE indicates failure
}
void MacroAssembler::resolve_jobject(Register value, Register tmp1, Register tmp2) {
BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
bs->resolve_jobject(this, value, tmp1, tmp2);
@ -6349,7 +6144,6 @@ void MacroAssembler::zap_from_to(Register low, Register high, Register val, Regi
// Note: make sure Z_R1 is not manipulated here when C2 compiler is in play
void MacroAssembler::lightweight_lock(Register basic_lock, Register obj, Register temp1, Register temp2, Label& slow) {
assert(LockingMode == LM_LIGHTWEIGHT, "only used with new lightweight locking");
assert_different_registers(basic_lock, obj, temp1, temp2);
Label push;
@ -6415,7 +6209,6 @@ void MacroAssembler::lightweight_lock(Register basic_lock, Register obj, Registe
// - Z_R1_scratch: will be killed in case of Interpreter & C1 Compiler
void MacroAssembler::lightweight_unlock(Register obj, Register temp1, Register temp2, Label& slow) {
assert(LockingMode == LM_LIGHTWEIGHT, "only used with new lightweight locking");
assert_different_registers(obj, temp1, temp2);
Label unlocked, push_and_slow;

View File

@ -790,8 +790,6 @@ class MacroAssembler: public Assembler {
// Kills registers tmp1_reg and tmp2_reg and preserves the condition code.
void increment_counter_eq(address counter_address, Register tmp1_reg, Register tmp2_reg);
void compiler_fast_lock_object(Register oop, Register box, Register temp1, Register temp2);
void compiler_fast_unlock_object(Register oop, Register box, Register temp1, Register temp2);
void lightweight_lock(Register basic_lock, Register obj, Register tmp1, Register tmp2, Label& slow);
void lightweight_unlock(Register obj, Register tmp1, Register tmp2, Label& slow);
void compiler_fast_lock_lightweight_object(Register obj, Register box, Register tmp1, Register tmp2);

View File

@ -1,5 +1,5 @@
//
// Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved.
// Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
// Copyright (c) 2017, 2024 SAP SE. All rights reserved.
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
//
@ -10161,30 +10161,7 @@ instruct partialSubtypeCheckConstSuper(rarg2RegP sub, rarg1RegP super, immP supe
// ============================================================================
// inlined locking and unlocking
instruct cmpFastLock(flagsReg pcc, iRegP_N2P oop, iRegP_N2P box, iRegP tmp1, iRegP tmp2) %{
predicate(LockingMode != LM_LIGHTWEIGHT);
match(Set pcc (FastLock oop box));
effect(TEMP tmp1, TEMP tmp2);
ins_cost(100);
// TODO: s390 port size(VARIABLE_SIZE); // Uses load_const_optimized.
format %{ "FASTLOCK $oop, $box; KILL Z_ARG4, Z_ARG5" %}
ins_encode %{ __ compiler_fast_lock_object($oop$$Register, $box$$Register, $tmp1$$Register, $tmp2$$Register); %}
ins_pipe(pipe_class_dummy);
%}
instruct cmpFastUnlock(flagsReg pcc, iRegP_N2P oop, iRegP_N2P box, iRegP tmp1, iRegP tmp2) %{
predicate(LockingMode != LM_LIGHTWEIGHT);
match(Set pcc (FastUnlock oop box));
effect(TEMP tmp1, TEMP tmp2);
ins_cost(100);
// TODO: s390 port size(FIXED_SIZE);
format %{ "FASTUNLOCK $oop, $box; KILL Z_ARG4, Z_ARG5" %}
ins_encode %{ __ compiler_fast_unlock_object($oop$$Register, $box$$Register, $tmp1$$Register, $tmp2$$Register); %}
ins_pipe(pipe_class_dummy);
%}
instruct cmpFastLockLightweight(flagsReg pcc, iRegP_N2P oop, iRegP_N2P box, iRegP tmp1, iRegP tmp2) %{
predicate(LockingMode == LM_LIGHTWEIGHT);
match(Set pcc (FastLock oop box));
effect(TEMP tmp1, TEMP tmp2);
ins_cost(100);
@ -10200,7 +10177,6 @@ instruct cmpFastLockLightweight(flagsReg pcc, iRegP_N2P oop, iRegP_N2P box, iReg
%}
instruct cmpFastUnlockLightweight(flagsReg pcc, iRegP_N2P oop, iRegP_N2P box, iRegP tmp1, iRegP tmp2) %{
predicate(LockingMode == LM_LIGHTWEIGHT);
match(Set pcc (FastUnlock oop box));
effect(TEMP tmp1, TEMP tmp2);
ins_cost(100);

View File

@ -1764,13 +1764,8 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
__ add2reg(r_box, lock_offset, Z_SP);
// Try fastpath for locking.
if (LockingMode == LM_LIGHTWEIGHT) {
// Fast_lock kills r_temp_1, r_temp_2.
__ compiler_fast_lock_lightweight_object(r_oop, r_box, r_tmp1, r_tmp2);
} else {
// Fast_lock kills r_temp_1, r_temp_2.
__ compiler_fast_lock_object(r_oop, r_box, r_tmp1, r_tmp2);
}
// Fast_lock kills r_temp_1, r_temp_2.
__ compiler_fast_lock_lightweight_object(r_oop, r_box, r_tmp1, r_tmp2);
__ z_bre(done);
//-------------------------------------------------------------------------
@ -1965,13 +1960,8 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
__ add2reg(r_box, lock_offset, Z_SP);
// Try fastpath for unlocking.
if (LockingMode == LM_LIGHTWEIGHT) {
// Fast_unlock kills r_tmp1, r_tmp2.
__ compiler_fast_unlock_lightweight_object(r_oop, r_box, r_tmp1, r_tmp2);
} else {
// Fast_unlock kills r_tmp1, r_tmp2.
__ compiler_fast_unlock_object(r_oop, r_box, r_tmp1, r_tmp2);
}
// Fast_unlock kills r_tmp1, r_tmp2.
__ compiler_fast_unlock_lightweight_object(r_oop, r_box, r_tmp1, r_tmp2);
__ z_bre(done);
// Slow path for unlocking.

View File

@ -68,12 +68,13 @@ unsigned int VM_Version::_Icache_lineSize = DEFAULT
// z14: 2017-09
// z15: 2019-09
// z16: 2022-05
// z17: 2025-04
static const char* z_gen[] = {" ", "G1", "G2", "G3", "G4", "G5", "G6", "G7", "G8", "G9", "G10" };
static const char* z_machine[] = {" ", "2064", "2084", "2094", "2097", "2817", "2827", "2964", "3906", "8561", "3931" };
static const char* z_name[] = {" ", "z900", "z990", "z9 EC", "z10 EC", "z196 EC", "ec12", "z13", "z14", "z15", "z16" };
static const char* z_WDFM[] = {" ", "2006-06-30", "2008-06-30", "2010-06-30", "2012-06-30", "2014-06-30", "2016-12-31", "2019-06-30", "2021-06-30", "2024-12-31", "tbd" };
static const char* z_EOS[] = {" ", "2014-12-31", "2014-12-31", "2017-10-31", "2019-12-31", "2021-12-31", "2023-12-31", "2024-12-31", "tbd", "tbd", "tbd" };
static const char* z_gen[] = {" ", "G1", "G2", "G3", "G4", "G5", "G6", "G7", "G8", "G9", "G10", "G11" };
static const char* z_machine[] = {" ", "2064", "2084", "2094", "2097", "2817", "2827", "2964", "3906", "8561", "3931", "9175" };
static const char* z_name[] = {" ", "z900", "z990", "z9 EC", "z10 EC", "z196 EC", "ec12", "z13", "z14", "z15", "z16", "z17" };
static const char* z_WDFM[] = {" ", "2006-06-30", "2008-06-30", "2010-06-30", "2012-06-30", "2014-06-30", "2016-12-31", "2019-06-30", "2021-06-30", "2024-12-31", "tbd", "tbd" };
static const char* z_EOS[] = {" ", "2014-12-31", "2014-12-31", "2017-10-31", "2019-12-31", "2021-12-31", "2023-12-31", "2024-12-31", "tbd", "tbd", "tbd", "tbd" };
static const char* z_features[] = {" ",
"system-z, g1-z900, ldisp",
"system-z, g2-z990, ldisp_fast",
@ -85,7 +86,9 @@ static const char* z_features[] = {" ",
"system-z, g8-z14, ldisp_fast, extimm, pcrel_load/store, cmpb, cond_load/store, interlocked_update, txm, vectorinstr, instrext2, venh1",
"system-z, g9-z15, ldisp_fast, extimm, pcrel_load/store, cmpb, cond_load/store, interlocked_update, txm, vectorinstr, instrext2, venh1, instrext3, venh2",
"system-z, g10-z16, ldisp_fast, extimm, pcrel_load/store, cmpb, cond_load/store, interlocked_update, txm, vectorinstr, instrext2, venh1, instrext3, venh2,"
"bear_enh, sort_enh, nnpa_assist, storage_key_removal, vpack_decimal_enh"
"bear_enh, sort_enh, nnpa_assist, storage_key_removal, vpack_decimal_enh",
"system-z, g11-z17, ldisp_fast, extimm, pcrel_load/store, cmpb, cond_load/store, interlocked_update, txm, vectorinstr, instrext2, venh1, instrext3, venh2,"
"bear_enh, sort_enh, nnpa_assist, storage_key_removal, vpack_decimal_enh, concurrent_function"
};
void VM_Version::initialize() {
@ -339,6 +342,11 @@ int VM_Version::get_model_index() {
// is the index of the oldest detected model.
int ambiguity = 0;
int model_ix = 0;
if (is_z17()) {
model_ix = 11;
ambiguity++;
}
if (is_z16()) {
model_ix = 10;
ambiguity++;

View File

@ -100,7 +100,7 @@ class VM_Version: public Abstract_VM_Version {
#define CryptoExtension4Mask 0x0004000000000000UL // z196 (aka message-security assist extension 4, for KMF, KMCTR, KMO)
#define DFPPackedConversionMask 0x0000800000000000UL // z13
// ----------------------------------------------
// --- FeatureBitString Bits 128..192 (DW[2]) ---
// --- FeatureBitString Bits 128..191 (DW[2]) ---
// ----------------------------------------------
// 11111111111111111
// 23344455666778889
@ -118,9 +118,10 @@ class VM_Version: public Abstract_VM_Version {
#define NNPAssistFacilityMask 0x0000000004000000UL // z16, Neural-network-processing-assist facility, Bit: 165
// ----------------------------------------------
// --- FeatureBitString Bits 193..200 (DW[3]) ---
// --- FeatureBitString Bits 192..255 (DW[3]) ---
// ----------------------------------------------
#define BEAREnhFacilityMask 0x4000000000000000UL // z16, BEAR-enhancement facility, Bit: 193
#define ConcurrentFunFacilityMask 0x0040000000000000UL // z17, Concurrent-functions facility, Bit: 201
enum {
_max_cache_levels = 8, // As limited by ECAG instruction.
@ -189,7 +190,8 @@ class VM_Version: public Abstract_VM_Version {
static bool is_z13() { return has_CryptoExt5() && !has_MiscInstrExt2(); }
static bool is_z14() { return has_MiscInstrExt2() && !has_MiscInstrExt3(); }
static bool is_z15() { return has_MiscInstrExt3() && !has_BEAR_Enh_Facility(); }
static bool is_z16() { return has_BEAR_Enh_Facility(); }
static bool is_z16() { return has_BEAR_Enh_Facility() && !has_Concurrent_Fun_Facility(); }
static bool is_z17() { return has_Concurrent_Fun_Facility();}
// Need to use nested class with unscoped enum.
// C++11 declaration "enum class Cipher { ... } is not supported.
@ -497,6 +499,7 @@ class VM_Version: public Abstract_VM_Version {
static bool has_BEAR_Enh_Facility() { return (_features[3] & BEAREnhFacilityMask) == BEAREnhFacilityMask; }
static bool has_NNP_Assist_Facility() { return (_features[2] & NNPAssistFacilityMask) == NNPAssistFacilityMask; }
static bool has_Concurrent_Fun_Facility() { return (_features[3] & ConcurrentFunFacilityMask) == ConcurrentFunFacilityMask; }
// Crypto features query functions.
static bool has_Crypto_AES_GCM128() { return has_Crypto() && test_feature_bit(&_cipher_features_KMA[0], Cipher::_AES128, Cipher::_featureBits); }
@ -573,6 +576,7 @@ class VM_Version: public Abstract_VM_Version {
static void set_has_VectorPackedDecimalEnh() { _features[2] |= VectorPackedDecimalEnhMask; }
static void set_has_BEAR_Enh_Facility() { _features[3] |= BEAREnhFacilityMask;}
static void set_has_NNP_Assist_Facility() { _features[2] |= NNPAssistFacilityMask;}
static void set_has_Concurrent_Fun_Facility() { _features[3] |= ConcurrentFunFacilityMask;}
static void reset_has_VectorFacility() { _features[2] &= ~VectorFacilityMask; }

View File

@ -413,11 +413,7 @@ int LIR_Assembler::emit_unwind_handler() {
if (method()->is_synchronized()) {
monitor_address(0, FrameMap::rax_opr);
stub = new MonitorExitStub(FrameMap::rax_opr, true, 0);
if (LockingMode == LM_MONITOR) {
__ jmp(*stub->entry());
} else {
__ unlock_object(rdi, rsi, rax, *stub->entry());
}
__ unlock_object(rdi, rsi, rax, *stub->entry());
__ bind(*stub->continuation());
}
@ -2733,15 +2729,9 @@ void LIR_Assembler::emit_lock(LIR_OpLock* op) {
Register obj = op->obj_opr()->as_register(); // may not be an oop
Register hdr = op->hdr_opr()->as_register();
Register lock = op->lock_opr()->as_register();
if (LockingMode == LM_MONITOR) {
if (op->info() != nullptr) {
add_debug_info_for_null_check_here(op->info());
__ null_check(obj);
}
__ jmp(*op->stub()->entry());
} else if (op->code() == lir_lock) {
if (op->code() == lir_lock) {
assert(BasicLock::displaced_header_offset_in_bytes() == 0, "lock_reg must point to the displaced header");
Register tmp = LockingMode == LM_LIGHTWEIGHT ? op->scratch_opr()->as_register() : noreg;
Register tmp = op->scratch_opr()->as_register();
// add debug info for NullPointerException only if one is possible
int null_check_offset = __ lock_object(hdr, obj, lock, tmp, *op->stub()->entry());
if (op->info() != nullptr) {

View File

@ -289,7 +289,7 @@ void LIRGenerator::do_MonitorEnter(MonitorEnter* x) {
// this CodeEmitInfo must not have the xhandlers because here the
// object is already locked (xhandlers expect object to be unlocked)
CodeEmitInfo* info = state_for(x, x->state(), true);
LIR_Opr tmp = LockingMode == LM_LIGHTWEIGHT ? new_register(T_ADDRESS) : LIR_OprFact::illegalOpr;
LIR_Opr tmp = new_register(T_ADDRESS);
monitor_enter(obj.result(), lock, syncTempOpr(), tmp,
x->monitor_no(), info_for_exception, info);
}
@ -961,7 +961,7 @@ void LIRGenerator::do_update_CRC32(Intrinsic* x) {
CallingConvention* cc = frame_map()->c_calling_convention(&signature);
const LIR_Opr result_reg = result_register_for(x->type());
LIR_Opr addr = new_pointer_register();
LIR_Opr addr = new_register(T_ADDRESS);
__ leal(LIR_OprFact::address(a), addr);
crc.load_item_force(cc->at(0));
@ -1100,10 +1100,10 @@ void LIRGenerator::do_vectorizedMismatch(Intrinsic* x) {
CallingConvention* cc = frame_map()->c_calling_convention(&signature);
const LIR_Opr result_reg = result_register_for(x->type());
LIR_Opr ptr_addr_a = new_pointer_register();
LIR_Opr ptr_addr_a = new_register(T_ADDRESS);
__ leal(LIR_OprFact::address(addr_a), ptr_addr_a);
LIR_Opr ptr_addr_b = new_pointer_register();
LIR_Opr ptr_addr_b = new_register(T_ADDRESS);
__ leal(LIR_OprFact::address(addr_b), ptr_addr_b);
__ move(ptr_addr_a, cc->at(0));

View File

@ -42,8 +42,6 @@
#include "utilities/globalDefinitions.hpp"
int C1_MacroAssembler::lock_object(Register hdr, Register obj, Register disp_hdr, Register tmp, Label& slow_case) {
const int aligned_mask = BytesPerWord -1;
const int hdr_offset = oopDesc::mark_offset_in_bytes();
assert(hdr == rax, "hdr must be rax, for the cmpxchg instruction");
assert_different_registers(hdr, obj, disp_hdr, tmp);
int null_check_offset = -1;
@ -55,93 +53,20 @@ int C1_MacroAssembler::lock_object(Register hdr, Register obj, Register disp_hdr
null_check_offset = offset();
if (LockingMode == LM_LIGHTWEIGHT) {
lightweight_lock(disp_hdr, obj, hdr, tmp, slow_case);
} else if (LockingMode == LM_LEGACY) {
Label done;
if (DiagnoseSyncOnValueBasedClasses != 0) {
load_klass(hdr, obj, rscratch1);
testb(Address(hdr, Klass::misc_flags_offset()), KlassFlags::_misc_is_value_based_class);
jcc(Assembler::notZero, slow_case);
}
// Load object header
movptr(hdr, Address(obj, hdr_offset));
// and mark it as unlocked
orptr(hdr, markWord::unlocked_value);
// save unlocked object header into the displaced header location on the stack
movptr(Address(disp_hdr, 0), hdr);
// test if object header is still the same (i.e. unlocked), and if so, store the
// displaced header address in the object header - if it is not the same, get the
// object header instead
MacroAssembler::lock(); // must be immediately before cmpxchg!
cmpxchgptr(disp_hdr, Address(obj, hdr_offset));
// if the object header was the same, we're done
jcc(Assembler::equal, done);
// if the object header was not the same, it is now in the hdr register
// => test if it is a stack pointer into the same stack (recursive locking), i.e.:
//
// 1) (hdr & aligned_mask) == 0
// 2) rsp <= hdr
// 3) hdr <= rsp + page_size
//
// these 3 tests can be done by evaluating the following expression:
//
// (hdr - rsp) & (aligned_mask - page_size)
//
// assuming both the stack pointer and page_size have their least
// significant 2 bits cleared and page_size is a power of 2
subptr(hdr, rsp);
andptr(hdr, aligned_mask - (int)os::vm_page_size());
// for recursive locking, the result is zero => save it in the displaced header
// location (null in the displaced hdr location indicates recursive locking)
movptr(Address(disp_hdr, 0), hdr);
// otherwise we don't care about the result and handle locking via runtime call
jcc(Assembler::notZero, slow_case);
// done
bind(done);
inc_held_monitor_count();
}
lightweight_lock(disp_hdr, obj, hdr, tmp, slow_case);
return null_check_offset;
}
void C1_MacroAssembler::unlock_object(Register hdr, Register obj, Register disp_hdr, Label& slow_case) {
const int aligned_mask = BytesPerWord -1;
const int hdr_offset = oopDesc::mark_offset_in_bytes();
assert(disp_hdr == rax, "disp_hdr must be rax, for the cmpxchg instruction");
assert(hdr != obj && hdr != disp_hdr && obj != disp_hdr, "registers must be different");
Label done;
if (LockingMode != LM_LIGHTWEIGHT) {
// load displaced header
movptr(hdr, Address(disp_hdr, 0));
// if the loaded hdr is null we had recursive locking
testptr(hdr, hdr);
// if we had recursive locking, we are done
jcc(Assembler::zero, done);
}
// load object
movptr(obj, Address(disp_hdr, BasicObjectLock::obj_offset()));
verify_oop(obj);
if (LockingMode == LM_LIGHTWEIGHT) {
lightweight_unlock(obj, disp_hdr, hdr, slow_case);
} else if (LockingMode == LM_LEGACY) {
// test if object header is pointing to the displaced header, and if so, restore
// the displaced header in the object - if the object header is not pointing to
// the displaced header, get the object header instead
MacroAssembler::lock(); // must be immediately before cmpxchg!
cmpxchgptr(hdr, Address(obj, hdr_offset));
// if the object header was not pointing to the displaced header,
// we do unlocking via runtime call
jcc(Assembler::notEqual, slow_case);
// done
bind(done);
dec_held_monitor_count();
}
lightweight_unlock(obj, disp_hdr, hdr, slow_case);
}

View File

@ -219,244 +219,11 @@ inline Assembler::AvxVectorLen C2_MacroAssembler::vector_length_encoding(int vle
// obj: object to lock
// box: on-stack box address (displaced header location) - KILLED
// rax,: tmp -- KILLED
// scr: tmp -- KILLED
void C2_MacroAssembler::fast_lock(Register objReg, Register boxReg, Register tmpReg,
Register scrReg, Register cx1Reg, Register cx2Reg, Register thread,
Metadata* method_data) {
assert(LockingMode != LM_LIGHTWEIGHT, "lightweight locking should use fast_lock_lightweight");
// Ensure the register assignments are disjoint
assert(tmpReg == rax, "");
assert(cx1Reg == noreg, "");
assert(cx2Reg == noreg, "");
assert_different_registers(objReg, boxReg, tmpReg, scrReg);
// Possible cases that we'll encounter in fast_lock
// ------------------------------------------------
// * Inflated
// -- unlocked
// -- Locked
// = by self
// = by other
// * neutral
// * stack-locked
// -- by self
// = sp-proximity test hits
// = sp-proximity test generates false-negative
// -- by other
//
Label IsInflated, DONE_LABEL, NO_COUNT, COUNT;
if (DiagnoseSyncOnValueBasedClasses != 0) {
load_klass(tmpReg, objReg, scrReg);
testb(Address(tmpReg, Klass::misc_flags_offset()), KlassFlags::_misc_is_value_based_class);
jcc(Assembler::notZero, DONE_LABEL);
}
movptr(tmpReg, Address(objReg, oopDesc::mark_offset_in_bytes())); // [FETCH]
testptr(tmpReg, markWord::monitor_value); // inflated vs stack-locked|neutral
jcc(Assembler::notZero, IsInflated);
if (LockingMode == LM_MONITOR) {
// Clear ZF so that we take the slow path at the DONE label. objReg is known to be not 0.
testptr(objReg, objReg);
} else {
assert(LockingMode == LM_LEGACY, "must be");
// Attempt stack-locking ...
orptr (tmpReg, markWord::unlocked_value);
movptr(Address(boxReg, 0), tmpReg); // Anticipate successful CAS
lock();
cmpxchgptr(boxReg, Address(objReg, oopDesc::mark_offset_in_bytes())); // Updates tmpReg
jcc(Assembler::equal, COUNT); // Success
// Recursive locking.
// The object is stack-locked: markword contains stack pointer to BasicLock.
// Locked by current thread if difference with current SP is less than one page.
subptr(tmpReg, rsp);
// Next instruction set ZFlag == 1 (Success) if difference is less then one page.
andptr(tmpReg, (int32_t) (7 - (int)os::vm_page_size()) );
movptr(Address(boxReg, 0), tmpReg);
}
jmp(DONE_LABEL);
bind(IsInflated);
// The object is inflated. tmpReg contains pointer to ObjectMonitor* + markWord::monitor_value
// Unconditionally set box->_displaced_header = markWord::unused_mark().
// Without cast to int32_t this style of movptr will destroy r10 which is typically obj.
movptr(Address(boxReg, 0), checked_cast<int32_t>(markWord::unused_mark().value()));
// It's inflated and we use scrReg for ObjectMonitor* in this section.
movptr(boxReg, Address(r15_thread, JavaThread::monitor_owner_id_offset()));
movq(scrReg, tmpReg);
xorq(tmpReg, tmpReg);
lock();
cmpxchgptr(boxReg, Address(scrReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)));
// Propagate ICC.ZF from CAS above into DONE_LABEL.
jccb(Assembler::equal, COUNT); // CAS above succeeded; propagate ZF = 1 (success)
cmpptr(boxReg, rax); // Check if we are already the owner (recursive lock)
jccb(Assembler::notEqual, NO_COUNT); // If not recursive, ZF = 0 at this point (fail)
incq(Address(scrReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(recursions)));
xorq(rax, rax); // Set ZF = 1 (success) for recursive lock, denoting locking success
bind(DONE_LABEL);
// ZFlag == 1 count in fast path
// ZFlag == 0 count in slow path
jccb(Assembler::notZero, NO_COUNT); // jump if ZFlag == 0
bind(COUNT);
if (LockingMode == LM_LEGACY) {
// Count monitors in fast path
increment(Address(thread, JavaThread::held_monitor_count_offset()));
}
xorl(tmpReg, tmpReg); // Set ZF == 1
bind(NO_COUNT);
// At NO_COUNT the icc ZFlag is set as follows ...
// fast_unlock uses the same protocol.
// ZFlag == 1 -> Success
// ZFlag == 0 -> Failure - force control through the slow path
}
// obj: object to unlock
// box: box address (displaced header location), killed. Must be EAX.
// tmp: killed, cannot be obj nor box.
//
// Some commentary on balanced locking:
//
// fast_lock and fast_unlock are emitted only for provably balanced lock sites.
// Methods that don't have provably balanced locking are forced to run in the
// interpreter - such methods won't be compiled to use fast_lock and fast_unlock.
// The interpreter provides two properties:
// I1: At return-time the interpreter automatically and quietly unlocks any
// objects acquired the current activation (frame). Recall that the
// interpreter maintains an on-stack list of locks currently held by
// a frame.
// I2: If a method attempts to unlock an object that is not held by the
// the frame the interpreter throws IMSX.
//
// Lets say A(), which has provably balanced locking, acquires O and then calls B().
// B() doesn't have provably balanced locking so it runs in the interpreter.
// Control returns to A() and A() unlocks O. By I1 and I2, above, we know that O
// is still locked by A().
//
// The only other source of unbalanced locking would be JNI. The "Java Native Interface:
// Programmer's Guide and Specification" claims that an object locked by jni_monitorenter
// should not be unlocked by "normal" java-level locking and vice-versa. The specification
// doesn't specify what will occur if a program engages in such mixed-mode locking, however.
// Arguably given that the spec legislates the JNI case as undefined our implementation
// could reasonably *avoid* checking owner in fast_unlock().
// In the interest of performance we elide m->Owner==Self check in unlock.
// A perfectly viable alternative is to elide the owner check except when
// Xcheck:jni is enabled.
void C2_MacroAssembler::fast_unlock(Register objReg, Register boxReg, Register tmpReg) {
assert(LockingMode != LM_LIGHTWEIGHT, "lightweight locking should use fast_unlock_lightweight");
assert(boxReg == rax, "");
assert_different_registers(objReg, boxReg, tmpReg);
Label DONE_LABEL, Stacked, COUNT, NO_COUNT;
if (LockingMode == LM_LEGACY) {
cmpptr(Address(boxReg, 0), NULL_WORD); // Examine the displaced header
jcc (Assembler::zero, COUNT); // 0 indicates recursive stack-lock
}
movptr(tmpReg, Address(objReg, oopDesc::mark_offset_in_bytes())); // Examine the object's markword
if (LockingMode != LM_MONITOR) {
testptr(tmpReg, markWord::monitor_value); // Inflated?
jcc(Assembler::zero, Stacked);
}
// It's inflated.
// Despite our balanced locking property we still check that m->_owner == Self
// as java routines or native JNI code called by this thread might
// have released the lock.
//
// If there's no contention try a 1-0 exit. That is, exit without
// a costly MEMBAR or CAS. See synchronizer.cpp for details on how
// we detect and recover from the race that the 1-0 exit admits.
//
// Conceptually fast_unlock() must execute a STST|LDST "release" barrier
// before it STs null into _owner, releasing the lock. Updates
// to data protected by the critical section must be visible before
// we drop the lock (and thus before any other thread could acquire
// the lock and observe the fields protected by the lock).
// IA32's memory-model is SPO, so STs are ordered with respect to
// each other and there's no need for an explicit barrier (fence).
// See also http://gee.cs.oswego.edu/dl/jmm/cookbook.html.
Label LSuccess, LNotRecursive;
cmpptr(Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(recursions)), 0);
jccb(Assembler::equal, LNotRecursive);
// Recursive inflated unlock
decrement(Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(recursions)));
jmpb(LSuccess);
bind(LNotRecursive);
// Set owner to null.
// Release to satisfy the JMM
movptr(Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)), NULL_WORD);
// We need a full fence after clearing owner to avoid stranding.
// StoreLoad achieves this.
membar(StoreLoad);
// Check if the entry_list is empty.
cmpptr(Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(entry_list)), NULL_WORD);
jccb(Assembler::zero, LSuccess); // If so we are done.
// Check if there is a successor.
cmpptr(Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(succ)), NULL_WORD);
jccb(Assembler::notZero, LSuccess); // If so we are done.
// Save the monitor pointer in the current thread, so we can try to
// reacquire the lock in SharedRuntime::monitor_exit_helper().
andptr(tmpReg, ~(int32_t)markWord::monitor_value);
movptr(Address(r15_thread, JavaThread::unlocked_inflated_monitor_offset()), tmpReg);
orl (boxReg, 1); // set ICC.ZF=0 to indicate failure
jmpb (DONE_LABEL);
bind (LSuccess);
testl (boxReg, 0); // set ICC.ZF=1 to indicate success
jmpb (DONE_LABEL);
if (LockingMode == LM_LEGACY) {
bind (Stacked);
movptr(tmpReg, Address (boxReg, 0)); // re-fetch
lock();
cmpxchgptr(tmpReg, Address(objReg, oopDesc::mark_offset_in_bytes())); // Uses RAX which is box
// Intentional fall-thru into DONE_LABEL
}
bind(DONE_LABEL);
// ZFlag == 1 count in fast path
// ZFlag == 0 count in slow path
jccb(Assembler::notZero, NO_COUNT);
bind(COUNT);
if (LockingMode == LM_LEGACY) {
// Count monitors in fast path
decrementq(Address(r15_thread, JavaThread::held_monitor_count_offset()));
}
xorl(tmpReg, tmpReg); // Set ZF == 1
bind(NO_COUNT);
}
// box: on-stack box address -- KILLED
// rax: tmp -- KILLED
// t : tmp -- KILLED
void C2_MacroAssembler::fast_lock_lightweight(Register obj, Register box, Register rax_reg,
Register t, Register thread) {
assert(LockingMode == LM_LIGHTWEIGHT, "must be");
assert(rax_reg == rax, "Used for CAS");
assert_different_registers(obj, box, rax_reg, t, thread);
@ -616,8 +383,39 @@ void C2_MacroAssembler::fast_lock_lightweight(Register obj, Register box, Regist
// C2 uses the value of ZF to determine the continuation.
}
// obj: object to lock
// rax: tmp -- KILLED
// t : tmp - cannot be obj nor rax -- KILLED
//
// Some commentary on balanced locking:
//
// fast_lock and fast_unlock are emitted only for provably balanced lock sites.
// Methods that don't have provably balanced locking are forced to run in the
// interpreter - such methods won't be compiled to use fast_lock and fast_unlock.
// The interpreter provides two properties:
// I1: At return-time the interpreter automatically and quietly unlocks any
// objects acquired in the current activation (frame). Recall that the
// interpreter maintains an on-stack list of locks currently held by
// a frame.
// I2: If a method attempts to unlock an object that is not held by the
// frame the interpreter throws IMSX.
//
// Lets say A(), which has provably balanced locking, acquires O and then calls B().
// B() doesn't have provably balanced locking so it runs in the interpreter.
// Control returns to A() and A() unlocks O. By I1 and I2, above, we know that O
// is still locked by A().
//
// The only other source of unbalanced locking would be JNI. The "Java Native Interface
// Specification" states that an object locked by JNI's MonitorEnter should not be
// unlocked by "normal" java-level locking and vice-versa. The specification doesn't
// specify what will occur if a program engages in such mixed-mode locking, however.
// Arguably given that the spec legislates the JNI case as undefined our implementation
// could reasonably *avoid* checking owner in fast_unlock().
// In the interest of performance we elide m->Owner==Self check in unlock.
// A perfectly viable alternative is to elide the owner check except when
// Xcheck:jni is enabled.
void C2_MacroAssembler::fast_unlock_lightweight(Register obj, Register reg_rax, Register t, Register thread) {
assert(LockingMode == LM_LIGHTWEIGHT, "must be");
assert(reg_rax == rax, "Used for CAS");
assert_different_registers(obj, reg_rax, t);

View File

@ -34,12 +34,7 @@ public:
Assembler::AvxVectorLen vector_length_encoding(int vlen_in_bytes);
// Code used by cmpFastLock and cmpFastUnlock mach instructions in .ad file.
// See full description in macroAssembler_x86.cpp.
void fast_lock(Register obj, Register box, Register tmp,
Register scr, Register cx1, Register cx2, Register thread,
Metadata* method_data);
void fast_unlock(Register obj, Register box, Register tmp);
// See full description in c2_MacroAssembler_x86.cpp.
void fast_lock_lightweight(Register obj, Register box, Register rax_reg,
Register t, Register thread);
void fast_unlock_lightweight(Register obj, Register reg_rax, Register t, Register thread);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -98,9 +98,12 @@ frame FreezeBase::new_heap_frame(frame& f, frame& caller) {
*hf.addr_at(frame::interpreter_frame_locals_offset) = locals_offset;
return hf;
} else {
// We need to re-read fp out of the frame because it may be an oop and we might have
// had a safepoint in finalize_freeze, after constructing f.
fp = *(intptr_t**)(f.sp() - frame::sender_sp_offset);
// For a compiled frame we need to re-read fp out of the frame because it may be an
// oop and we might have had a safepoint in finalize_freeze, after constructing f.
// For stub/native frames the value is not used while frozen, and will be constructed again
// when thawing the frame (see ThawBase::new_stack_frame). We use a special bad address to
// help with debugging, particularly when inspecting frames and identifying invalid accesses.
fp = FKind::compiled ? *(intptr_t**)(f.sp() - frame::sender_sp_offset) : (intptr_t*)badAddressVal;
int fsize = FKind::size(f);
sp = caller.unextended_sp() - fsize;
@ -183,6 +186,11 @@ inline void FreezeBase::patch_pd(frame& hf, const frame& caller) {
}
}
inline void FreezeBase::patch_pd_unused(intptr_t* sp) {
intptr_t* fp_addr = sp - frame::sender_sp_offset;
*fp_addr = badAddressVal;
}
//////// Thaw
// Fast path

View File

@ -1024,100 +1024,25 @@ void InterpreterMacroAssembler::get_method_counters(Register method,
void InterpreterMacroAssembler::lock_object(Register lock_reg) {
assert(lock_reg == c_rarg1, "The argument is only for looks. It must be c_rarg1");
if (LockingMode == LM_MONITOR) {
call_VM_preemptable(noreg,
CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorenter),
lock_reg);
} else {
Label count_locking, done, slow_case;
Label done, slow_case;
const Register swap_reg = rax; // Must use rax for cmpxchg instruction
const Register tmp_reg = rbx;
const Register obj_reg = c_rarg3; // Will contain the oop
const Register rklass_decode_tmp = rscratch1;
const Register swap_reg = rax; // Must use rax for cmpxchg instruction
const Register tmp_reg = rbx;
const Register obj_reg = c_rarg3; // Will contain the oop
const int obj_offset = in_bytes(BasicObjectLock::obj_offset());
const int lock_offset = in_bytes(BasicObjectLock::lock_offset());
const int mark_offset = lock_offset +
BasicLock::displaced_header_offset_in_bytes();
// Load object pointer into obj_reg
movptr(obj_reg, Address(lock_reg, BasicObjectLock::obj_offset()));
// Load object pointer into obj_reg
movptr(obj_reg, Address(lock_reg, obj_offset));
lightweight_lock(lock_reg, obj_reg, swap_reg, tmp_reg, slow_case);
jmp(done);
if (LockingMode == LM_LIGHTWEIGHT) {
lightweight_lock(lock_reg, obj_reg, swap_reg, tmp_reg, slow_case);
} else if (LockingMode == LM_LEGACY) {
if (DiagnoseSyncOnValueBasedClasses != 0) {
load_klass(tmp_reg, obj_reg, rklass_decode_tmp);
testb(Address(tmp_reg, Klass::misc_flags_offset()), KlassFlags::_misc_is_value_based_class);
jcc(Assembler::notZero, slow_case);
}
bind(slow_case);
// Load immediate 1 into swap_reg %rax
movl(swap_reg, 1);
// Load (object->mark() | 1) into swap_reg %rax
orptr(swap_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes()));
// Save (object->mark() | 1) into BasicLock's displaced header
movptr(Address(lock_reg, mark_offset), swap_reg);
assert(lock_offset == 0,
"displaced header must be first word in BasicObjectLock");
lock();
cmpxchgptr(lock_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes()));
jcc(Assembler::zero, count_locking);
const int zero_bits = 7;
// Fast check for recursive lock.
//
// Can apply the optimization only if this is a stack lock
// allocated in this thread. For efficiency, we can focus on
// recently allocated stack locks (instead of reading the stack
// base and checking whether 'mark' points inside the current
// thread stack):
// 1) (mark & zero_bits) == 0, and
// 2) rsp <= mark < mark + os::pagesize()
//
// Warning: rsp + os::pagesize can overflow the stack base. We must
// neither apply the optimization for an inflated lock allocated
// just above the thread stack (this is why condition 1 matters)
// nor apply the optimization if the stack lock is inside the stack
// of another thread. The latter is avoided even in case of overflow
// because we have guard pages at the end of all stacks. Hence, if
// we go over the stack base and hit the stack of another thread,
// this should not be in a writeable area that could contain a
// stack lock allocated by that thread. As a consequence, a stack
// lock less than page size away from rsp is guaranteed to be
// owned by the current thread.
//
// These 3 tests can be done by evaluating the following
// expression: ((mark - rsp) & (zero_bits - os::vm_page_size())),
// assuming both stack pointer and pagesize have their
// least significant bits clear.
// NOTE: the mark is in swap_reg %rax as the result of cmpxchg
subptr(swap_reg, rsp);
andptr(swap_reg, zero_bits - (int)os::vm_page_size());
// Save the test result, for recursive case, the result is zero
movptr(Address(lock_reg, mark_offset), swap_reg);
jcc(Assembler::notZero, slow_case);
bind(count_locking);
inc_held_monitor_count();
}
jmp(done);
bind(slow_case);
// Call the runtime routine for slow case
call_VM_preemptable(noreg,
CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorenter),
lock_reg);
bind(done);
}
// Call the runtime routine for slow case
call_VM_preemptable(noreg,
CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorenter),
lock_reg);
bind(done);
}
@ -1136,63 +1061,31 @@ void InterpreterMacroAssembler::lock_object(Register lock_reg) {
void InterpreterMacroAssembler::unlock_object(Register lock_reg) {
assert(lock_reg == c_rarg1, "The argument is only for looks. It must be c_rarg1");
if (LockingMode == LM_MONITOR) {
call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorexit), lock_reg);
} else {
Label count_locking, done, slow_case;
Label done, slow_case;
const Register swap_reg = rax; // Must use rax for cmpxchg instruction
const Register header_reg = c_rarg2; // Will contain the old oopMark
const Register obj_reg = c_rarg3; // Will contain the oop
const Register swap_reg = rax; // Must use rax for cmpxchg instruction
const Register header_reg = c_rarg2; // Will contain the old oopMark
const Register obj_reg = c_rarg3; // Will contain the oop
save_bcp(); // Save in case of exception
save_bcp(); // Save in case of exception
if (LockingMode != LM_LIGHTWEIGHT) {
// Convert from BasicObjectLock structure to object and BasicLock
// structure Store the BasicLock address into %rax
lea(swap_reg, Address(lock_reg, BasicObjectLock::lock_offset()));
}
// Load oop into obj_reg(%c_rarg3)
movptr(obj_reg, Address(lock_reg, BasicObjectLock::obj_offset()));
// Load oop into obj_reg(%c_rarg3)
movptr(obj_reg, Address(lock_reg, BasicObjectLock::obj_offset()));
// Free entry
movptr(Address(lock_reg, BasicObjectLock::obj_offset()), NULL_WORD);
// Free entry
movptr(Address(lock_reg, BasicObjectLock::obj_offset()), NULL_WORD);
lightweight_unlock(obj_reg, swap_reg, header_reg, slow_case);
jmp(done);
if (LockingMode == LM_LIGHTWEIGHT) {
lightweight_unlock(obj_reg, swap_reg, header_reg, slow_case);
} else if (LockingMode == LM_LEGACY) {
// Load the old header from BasicLock structure
movptr(header_reg, Address(swap_reg,
BasicLock::displaced_header_offset_in_bytes()));
bind(slow_case);
// Call the runtime routine for slow case.
movptr(Address(lock_reg, BasicObjectLock::obj_offset()), obj_reg); // restore obj
call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorexit), lock_reg);
// Test for recursion
testptr(header_reg, header_reg);
bind(done);
// zero for recursive case
jcc(Assembler::zero, count_locking);
// Atomic swap back the old header
lock();
cmpxchgptr(header_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes()));
// zero for simple unlock of a stack-lock case
jcc(Assembler::notZero, slow_case);
bind(count_locking);
dec_held_monitor_count();
}
jmp(done);
bind(slow_case);
// Call the runtime routine for slow case.
movptr(Address(lock_reg, BasicObjectLock::obj_offset()), obj_reg); // restore obj
call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorexit), lock_reg);
bind(done);
restore_bcp();
}
restore_bcp();
}
void InterpreterMacroAssembler::test_method_data_pointer(Register mdp,

View File

@ -6027,32 +6027,46 @@ void MacroAssembler::evpbroadcast(BasicType type, XMMRegister dst, Register src,
}
}
// encode char[] to byte[] in ISO_8859_1 or ASCII
//@IntrinsicCandidate
//private static int implEncodeISOArray(byte[] sa, int sp,
//byte[] da, int dp, int len) {
// int i = 0;
// for (; i < len; i++) {
// char c = StringUTF16.getChar(sa, sp++);
// if (c > '\u00FF')
// break;
// da[dp++] = (byte)c;
// }
// return i;
//}
//
//@IntrinsicCandidate
//private static int implEncodeAsciiArray(char[] sa, int sp,
// byte[] da, int dp, int len) {
// int i = 0;
// for (; i < len; i++) {
// char c = sa[sp++];
// if (c >= '\u0080')
// break;
// da[dp++] = (byte)c;
// }
// return i;
//}
// Encode given char[]/byte[] to byte[] in ISO_8859_1 or ASCII
//
// @IntrinsicCandidate
// int sun.nio.cs.ISO_8859_1.Encoder#encodeISOArray0(
// char[] sa, int sp, byte[] da, int dp, int len) {
// int i = 0;
// for (; i < len; i++) {
// char c = sa[sp++];
// if (c > '\u00FF')
// break;
// da[dp++] = (byte) c;
// }
// return i;
// }
//
// @IntrinsicCandidate
// int java.lang.StringCoding.encodeISOArray0(
// byte[] sa, int sp, byte[] da, int dp, int len) {
// int i = 0;
// for (; i < len; i++) {
// char c = StringUTF16.getChar(sa, sp++);
// if (c > '\u00FF')
// break;
// da[dp++] = (byte) c;
// }
// return i;
// }
//
// @IntrinsicCandidate
// int java.lang.StringCoding.encodeAsciiArray0(
// char[] sa, int sp, byte[] da, int dp, int len) {
// int i = 0;
// for (; i < len; i++) {
// char c = sa[sp++];
// if (c >= '\u0080')
// break;
// da[dp++] = (byte) c;
// }
// return i;
// }
void MacroAssembler::encode_iso_array(Register src, Register dst, Register len,
XMMRegister tmp1Reg, XMMRegister tmp2Reg,
XMMRegister tmp3Reg, XMMRegister tmp4Reg,

View File

@ -137,7 +137,7 @@ void MethodHandles::verify_method(MacroAssembler* _masm, Register method, Regist
case vmIntrinsicID::_invokeBasic:
// Require compiled LambdaForm class to be fully initialized.
__ cmpb(Address(method_holder, InstanceKlass::init_state_offset()), InstanceKlass::fully_initialized);
__ jccb(Assembler::equal, L_ok);
__ jcc(Assembler::equal, L_ok);
break;
case vmIntrinsicID::_linkToStatic:
@ -154,7 +154,7 @@ void MethodHandles::verify_method(MacroAssembler* _masm, Register method, Regist
// init_state check failed, but it may be an abstract interface method
__ load_unsigned_short(temp, Address(method, Method::access_flags_offset()));
__ testl(temp, JVM_ACC_ABSTRACT);
__ jccb(Assembler::notZero, L_ok);
__ jcc(Assembler::notZero, L_ok);
break;
default:

View File

@ -59,17 +59,10 @@ void SharedRuntime::inline_check_hashcode_from_object_header(MacroAssembler* mas
__ movptr(result, Address(obj_reg, oopDesc::mark_offset_in_bytes()));
if (LockingMode == LM_LIGHTWEIGHT) {
if (!UseObjectMonitorTable) {
// check if monitor
__ testptr(result, markWord::monitor_value);
__ jcc(Assembler::notZero, slowCase);
}
} else {
// check if locked
__ testptr(result, markWord::unlocked_value);
__ jcc(Assembler::zero, slowCase);
if (!UseObjectMonitorTable) {
// check if monitor
__ testptr(result, markWord::monitor_value);
__ jcc(Assembler::notZero, slowCase);
}
// get hash

View File

@ -2133,7 +2133,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
// We use the same pc/oopMap repeatedly when we call out
Label native_return;
if (LockingMode != LM_LEGACY && method->is_object_wait0()) {
if (method->is_object_wait0()) {
// For convenience we use the pc we want to resume to in case of preemption on Object.wait.
__ set_last_Java_frame(rsp, noreg, native_return, rscratch1);
} else {
@ -2174,16 +2174,11 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
const Register swap_reg = rax; // Must use rax for cmpxchg instruction
const Register obj_reg = rbx; // Will contain the oop
const Register lock_reg = r13; // Address of compiler lock object (BasicLock)
const Register old_hdr = r13; // value of old header at unlock time
Label slow_path_lock;
Label lock_done;
if (method->is_synchronized()) {
Label count_mon;
const int mark_word_offset = BasicLock::displaced_header_offset_in_bytes();
// Get the handle (the 2nd argument)
__ mov(oop_handle_reg, c_rarg1);
@ -2194,47 +2189,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
// Load the oop from the handle
__ movptr(obj_reg, Address(oop_handle_reg, 0));
if (LockingMode == LM_MONITOR) {
__ jmp(slow_path_lock);
} else if (LockingMode == LM_LEGACY) {
// Load immediate 1 into swap_reg %rax
__ movl(swap_reg, 1);
// Load (object->mark() | 1) into swap_reg %rax
__ orptr(swap_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes()));
// Save (object->mark() | 1) into BasicLock's displaced header
__ movptr(Address(lock_reg, mark_word_offset), swap_reg);
// src -> dest iff dest == rax else rax <- dest
__ lock();
__ cmpxchgptr(lock_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes()));
__ jcc(Assembler::equal, count_mon);
// Hmm should this move to the slow path code area???
// Test if the oopMark is an obvious stack pointer, i.e.,
// 1) (mark & 3) == 0, and
// 2) rsp <= mark < mark + os::pagesize()
// These 3 tests can be done by evaluating the following
// expression: ((mark - rsp) & (3 - os::vm_page_size())),
// assuming both stack pointer and pagesize have their
// least significant 2 bits clear.
// NOTE: the oopMark is in swap_reg %rax as the result of cmpxchg
__ subptr(swap_reg, rsp);
__ andptr(swap_reg, 3 - (int)os::vm_page_size());
// Save the test result, for recursive case, the result is zero
__ movptr(Address(lock_reg, mark_word_offset), swap_reg);
__ jcc(Assembler::notEqual, slow_path_lock);
__ bind(count_mon);
__ inc_held_monitor_count();
} else {
assert(LockingMode == LM_LIGHTWEIGHT, "must be");
__ lightweight_lock(lock_reg, obj_reg, swap_reg, rscratch1, slow_path_lock);
}
__ lightweight_lock(lock_reg, obj_reg, swap_reg, rscratch1, slow_path_lock);
// Slow path will re-enter here
__ bind(lock_done);
@ -2322,7 +2277,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
// change thread state
__ movl(Address(r15_thread, JavaThread::thread_state_offset()), _thread_in_Java);
if (LockingMode != LM_LEGACY && method->is_object_wait0()) {
if (method->is_object_wait0()) {
// Check preemption for Object.wait()
__ movptr(rscratch1, Address(r15_thread, JavaThread::preempt_alternate_return_offset()));
__ cmpptr(rscratch1, NULL_WORD);
@ -2354,38 +2309,12 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
// Get locked oop from the handle we passed to jni
__ movptr(obj_reg, Address(oop_handle_reg, 0));
if (LockingMode == LM_LEGACY) {
Label not_recur;
// Simple recursive lock?
__ cmpptr(Address(rsp, lock_slot_offset * VMRegImpl::stack_slot_size), NULL_WORD);
__ jcc(Assembler::notEqual, not_recur);
__ dec_held_monitor_count();
__ jmpb(fast_done);
__ bind(not_recur);
}
// Must save rax if it is live now because cmpxchg must use it
if (ret_type != T_FLOAT && ret_type != T_DOUBLE && ret_type != T_VOID) {
save_native_result(masm, ret_type, stack_slots);
}
if (LockingMode == LM_MONITOR) {
__ jmp(slow_path_unlock);
} else if (LockingMode == LM_LEGACY) {
// get address of the stack lock
__ lea(rax, Address(rsp, lock_slot_offset * VMRegImpl::stack_slot_size));
// get old displaced header
__ movptr(old_hdr, Address(rax, 0));
// Atomic swap old header if oop still contains the stack lock
__ lock();
__ cmpxchgptr(old_hdr, Address(obj_reg, oopDesc::mark_offset_in_bytes()));
__ jcc(Assembler::notEqual, slow_path_unlock);
__ dec_held_monitor_count();
} else {
assert(LockingMode == LM_LIGHTWEIGHT, "must be");
__ lightweight_unlock(obj_reg, swap_reg, lock_reg, slow_path_unlock);
}
__ lightweight_unlock(obj_reg, swap_reg, lock_reg, slow_path_unlock);
// slow path re-enters here
__ bind(unlock_done);

View File

@ -1017,21 +1017,16 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) {
// change thread state
__ movl(Address(thread, JavaThread::thread_state_offset()), _thread_in_Java);
if (LockingMode != LM_LEGACY) {
// Check preemption for Object.wait()
Label not_preempted;
__ movptr(rscratch1, Address(r15_thread, JavaThread::preempt_alternate_return_offset()));
__ cmpptr(rscratch1, NULL_WORD);
__ jccb(Assembler::equal, not_preempted);
__ movptr(Address(r15_thread, JavaThread::preempt_alternate_return_offset()), NULL_WORD);
__ jmp(rscratch1);
__ bind(native_return);
__ restore_after_resume(true /* is_native */);
__ bind(not_preempted);
} else {
// any pc will do so just use this one for LM_LEGACY to keep code together.
__ bind(native_return);
}
// Check preemption for Object.wait()
Label not_preempted;
__ movptr(rscratch1, Address(r15_thread, JavaThread::preempt_alternate_return_offset()));
__ cmpptr(rscratch1, NULL_WORD);
__ jccb(Assembler::equal, not_preempted);
__ movptr(Address(r15_thread, JavaThread::preempt_alternate_return_offset()), NULL_WORD);
__ jmp(rscratch1);
__ bind(native_return);
__ restore_after_resume(true /* is_native */);
__ bind(not_preempted);
// reset_last_Java_frame
__ reset_last_Java_frame(true);

View File

@ -14073,33 +14073,7 @@ instruct jmpConUCF2_short(cmpOpUCF2 cop, rFlagsRegUCF cmp, label labl) %{
// ============================================================================
// inlined locking and unlocking
instruct cmpFastLock(rFlagsReg cr, rRegP object, rbx_RegP box, rax_RegI tmp, rRegP scr) %{
predicate(LockingMode != LM_LIGHTWEIGHT);
match(Set cr (FastLock object box));
effect(TEMP tmp, TEMP scr, USE_KILL box);
ins_cost(300);
format %{ "fastlock $object,$box\t! kills $box,$tmp,$scr" %}
ins_encode %{
__ fast_lock($object$$Register, $box$$Register, $tmp$$Register,
$scr$$Register, noreg, noreg, r15_thread, nullptr);
%}
ins_pipe(pipe_slow);
%}
instruct cmpFastUnlock(rFlagsReg cr, rRegP object, rax_RegP box, rRegP tmp) %{
predicate(LockingMode != LM_LIGHTWEIGHT);
match(Set cr (FastUnlock object box));
effect(TEMP tmp, USE_KILL box);
ins_cost(300);
format %{ "fastunlock $object,$box\t! kills $box,$tmp" %}
ins_encode %{
__ fast_unlock($object$$Register, $box$$Register, $tmp$$Register);
%}
ins_pipe(pipe_slow);
%}
instruct cmpFastLockLightweight(rFlagsReg cr, rRegP object, rbx_RegP box, rax_RegI rax_reg, rRegP tmp) %{
predicate(LockingMode == LM_LIGHTWEIGHT);
match(Set cr (FastLock object box));
effect(TEMP rax_reg, TEMP tmp, USE_KILL box);
ins_cost(300);
@ -14111,7 +14085,6 @@ instruct cmpFastLockLightweight(rFlagsReg cr, rRegP object, rbx_RegP box, rax_Re
%}
instruct cmpFastUnlockLightweight(rFlagsReg cr, rRegP object, rax_RegP rax_reg, rRegP tmp) %{
predicate(LockingMode == LM_LIGHTWEIGHT);
match(Set cr (FastUnlock object rax_reg));
effect(TEMP tmp, USE_KILL rax_reg);
ins_cost(300);

View File

@ -60,6 +60,10 @@ inline void FreezeBase::patch_pd(frame& hf, const frame& caller) {
Unimplemented();
}
inline void FreezeBase::patch_pd_unused(intptr_t* sp) {
Unimplemented();
}
inline void FreezeBase::patch_stack_pd(intptr_t* frame_sp, intptr_t* heap_sp) {
Unimplemented();
}

View File

@ -56,11 +56,11 @@ void SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm,
const BasicType *sig_bt,
const VMRegPair *regs,
AdapterHandlerEntry* handler) {
// foil any attempt to call the i2c, c2i or unverified c2i entries
handler->set_entry_points(CAST_FROM_FN_PTR(address,zero_null_code_stub),
CAST_FROM_FN_PTR(address,zero_null_code_stub),
CAST_FROM_FN_PTR(address,zero_null_code_stub),
nullptr);
return;
}
nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,

View File

@ -37,7 +37,7 @@
do_arch_blob, \
do_arch_entry, \
do_arch_entry_init) \
do_arch_blob(initial, 32) \
do_arch_blob(initial, 0) \
#define STUBGEN_CONTINUATION_BLOBS_ARCH_DO(do_stub, \
@ -58,7 +58,7 @@
do_arch_blob, \
do_arch_entry, \
do_arch_entry_init) \
do_arch_blob(final, 32) \
do_arch_blob(final, 0) \
#endif // CPU_ZERO_STUBDECLARATIONS_HPP

View File

@ -209,8 +209,16 @@ frame os::fetch_compiled_frame_from_context(const void* ucVoid) {
}
intptr_t* os::fetch_bcp_from_context(const void* ucVoid) {
Unimplemented();
return nullptr;
assert(ucVoid != nullptr, "invariant");
const ucontext_t* uc = (const ucontext_t*)ucVoid;
assert(os::Posix::ucontext_is_interpreter(uc), "invariant");
#if (FP_REG_NUM == 11)
assert(Rbcp == R7, "expected FP=R11, Rbcp=R7");
return (intptr_t*)uc->uc_mcontext.arm_r7;
#else
assert(Rbcp == R11, "expected FP=R7, Rbcp=R11");
return (intptr_t*)uc->uc_mcontext.arm_fp; // r11
#endif
}
frame os::get_sender_for_C_frame(frame* fr) {

View File

@ -33,7 +33,7 @@
#include "utilities/debug.hpp"
#include "utilities/growableArray.hpp"
#include "utilities/linkedlist.hpp"
#include "utilities/resizeableResourceHash.hpp"
#include "utilities/resizableHashTable.hpp"
#include "utilities/macros.hpp"
template <typename T>
@ -541,7 +541,7 @@ class CodeBuffer: public StackObj DEBUG_ONLY(COMMA private Scrubber) {
};
typedef LinkedListImpl<int> Offsets;
typedef ResizeableResourceHashtable<address, Offsets, AnyObj::C_HEAP, mtCompiler> SharedTrampolineRequests;
typedef ResizeableHashTable<address, Offsets, AnyObj::C_HEAP, mtCompiler> SharedTrampolineRequests;
private:
enum {

View File

@ -37,7 +37,7 @@
#include "oops/instanceKlass.hpp"
#include "oops/objArrayKlass.hpp"
#include "oops/trainingData.hpp"
#include "utilities/resourceHash.hpp"
#include "utilities/hashTable.hpp"
// All the classes that should be included in the AOT cache (in at least the "allocated" state)
static GrowableArrayCHeap<Klass*, mtClassShared>* _all_cached_classes = nullptr;
@ -47,7 +47,7 @@ static GrowableArrayCHeap<Klass*, mtClassShared>* _all_cached_classes = nullptr;
static GrowableArrayCHeap<InstanceKlass*, mtClassShared>* _pending_aot_inited_classes = nullptr;
static const int TABLE_SIZE = 15889; // prime number
using ClassesTable = ResourceHashtable<Klass*, bool, TABLE_SIZE, AnyObj::C_HEAP, mtClassShared>;
using ClassesTable = HashTable<Klass*, bool, TABLE_SIZE, AnyObj::C_HEAP, mtClassShared>;
static ClassesTable* _seen_classes; // all classes that have been seen by AOTArtifactFinder
static ClassesTable* _aot_inited_classes; // all classes that need to be AOT-initialized.

View File

@ -31,8 +31,8 @@
#include "oops/oopsHierarchy.hpp"
#include "utilities/exceptions.hpp"
#include "utilities/growableArray.hpp"
#include "utilities/hashTable.hpp"
#include "utilities/macros.hpp"
#include "utilities/resourceHash.hpp"
class AOTLinkedClassTable;
class InstanceKlass;
@ -69,7 +69,7 @@ enum class AOTLinkedClassCategory : int;
//
class AOTClassLinker : AllStatic {
static const int TABLE_SIZE = 15889; // prime number
using ClassesTable = ResourceHashtable<InstanceKlass*, bool, TABLE_SIZE, AnyObj::C_HEAP, mtClassShared>;
using ClassesTable = HashTable<InstanceKlass*, bool, TABLE_SIZE, AnyObj::C_HEAP, mtClassShared>;
// Classes loaded inside vmClasses::resolve_all()
static ClassesTable* _vm_classes;

View File

@ -31,8 +31,8 @@
#include "oops/oopsHierarchy.hpp"
#include "runtime/handles.hpp"
#include "utilities/exceptions.hpp"
#include "utilities/hashTable.hpp"
#include "utilities/macros.hpp"
#include "utilities/resourceHash.hpp"
class ConstantPool;
class constantPoolHandle;
@ -53,7 +53,7 @@ template <typename T> class GrowableArray;
// if all of its supertypes are loaded from the CDS archive.
class AOTConstantPoolResolver : AllStatic {
static const int TABLE_SIZE = 15889; // prime number
using ClassesTable = ResourceHashtable<InstanceKlass*, bool, TABLE_SIZE, AnyObj::C_HEAP, mtClassShared> ;
using ClassesTable = HashTable<InstanceKlass*, bool, TABLE_SIZE, AnyObj::C_HEAP, mtClassShared> ;
static ClassesTable* _processed_classes;
#ifdef ASSERT

View File

@ -35,7 +35,7 @@
#include "oops/oopHandle.inline.hpp"
#include "runtime/fieldDescriptor.inline.hpp"
#include "runtime/javaCalls.hpp"
#include "utilities/resourceHash.hpp"
#include "utilities/hashTable.hpp"
// Handling of java.lang.ref.Reference objects in the AOT cache
// ============================================================
@ -92,7 +92,7 @@
#if INCLUDE_CDS_JAVA_HEAP
class KeepAliveObjectsTable : public ResourceHashtable<oop, bool,
class KeepAliveObjectsTable : public HashTable<oop, bool,
36137, // prime number
AnyObj::C_HEAP,
mtClassShared,

View File

@ -36,8 +36,8 @@
#include "runtime/os.hpp"
#include "utilities/bitMap.hpp"
#include "utilities/growableArray.hpp"
#include "utilities/resizeableResourceHash.hpp"
#include "utilities/resourceHash.hpp"
#include "utilities/hashTable.hpp"
#include "utilities/resizableHashTable.hpp"
class ArchiveHeapInfo;
class CHeapBitMap;
@ -229,8 +229,8 @@ private:
SourceObjList _rw_src_objs; // objs to put in rw region
SourceObjList _ro_src_objs; // objs to put in ro region
ResizeableResourceHashtable<address, SourceObjInfo, AnyObj::C_HEAP, mtClassShared> _src_obj_table;
ResizeableResourceHashtable<address, address, AnyObj::C_HEAP, mtClassShared> _buffered_to_src_table;
ResizeableHashTable<address, SourceObjInfo, AnyObj::C_HEAP, mtClassShared> _src_obj_table;
ResizeableHashTable<address, address, AnyObj::C_HEAP, mtClassShared> _buffered_to_src_table;
GrowableArray<Klass*>* _klasses;
GrowableArray<Symbol*>* _symbols;
unsigned int _entropy_seed;

View File

@ -348,10 +348,10 @@ bool ArchiveHeapLoader::load_heap_region(FileMapInfo* mapinfo) {
}
class VerifyLoadedHeapEmbeddedPointers: public BasicOopIterateClosure {
ResourceHashtable<uintptr_t, bool>* _table;
HashTable<uintptr_t, bool>* _table;
public:
VerifyLoadedHeapEmbeddedPointers(ResourceHashtable<uintptr_t, bool>* table) : _table(table) {}
VerifyLoadedHeapEmbeddedPointers(HashTable<uintptr_t, bool>* table) : _table(table) {}
virtual void do_oop(narrowOop* p) {
// This should be called before the loaded region is modified, so all the embedded pointers
@ -411,7 +411,7 @@ void ArchiveHeapLoader::verify_loaded_heap() {
log_info(aot, heap)("Verify all oops and pointers in loaded heap");
ResourceMark rm;
ResourceHashtable<uintptr_t, bool> table;
HashTable<uintptr_t, bool> table;
VerifyLoadedHeapEmbeddedPointers verifier(&table);
HeapWord* bottom = (HeapWord*)_loaded_heap_bottom;
HeapWord* top = (HeapWord*)_loaded_heap_top;

View File

@ -70,7 +70,7 @@ ArchiveHeapWriter::BufferOffsetToSourceObjectTable*
ArchiveHeapWriter::_buffer_offset_to_source_obj_table = nullptr;
typedef ResourceHashtable<
typedef HashTable<
size_t, // offset of a filler from ArchiveHeapWriter::buffer_bottom()
size_t, // size of this filler (in bytes)
127, // prime number

View File

@ -32,8 +32,8 @@
#include "utilities/bitMap.hpp"
#include "utilities/exceptions.hpp"
#include "utilities/growableArray.hpp"
#include "utilities/hashTable.hpp"
#include "utilities/macros.hpp"
#include "utilities/resourceHash.hpp"
class MemRegion;
@ -152,7 +152,7 @@ private:
};
static GrowableArrayCHeap<HeapObjOrder, mtClassShared>* _source_objs_order;
typedef ResizeableResourceHashtable<size_t, oop,
typedef ResizeableHashTable<size_t, oop,
AnyObj::C_HEAP,
mtClassShared> BufferOffsetToSourceObjectTable;
static BufferOffsetToSourceObjectTable* _buffer_offset_to_source_obj_table;

View File

@ -643,8 +643,17 @@ bool CDSConfig::check_vm_args_consistency(bool patch_mod_javabase, bool mode_fla
}
if (is_dumping_static_archive()) {
if (is_dumping_preimage_static_archive() || is_dumping_final_static_archive()) {
// Don't tweak execution mode
if (is_dumping_preimage_static_archive()) {
// Don't tweak execution mode during AOT training run
} else if (is_dumping_final_static_archive()) {
if (Arguments::mode() == Arguments::_comp) {
// AOT assembly phase submits the non-blocking compilation requests
// for methods collected during training run, then waits for all compilations
// to complete. With -Xcomp, we block for each compilation request, which is
// counter-productive. Switching back to mixed mode improves testing time
// with AOT and -Xcomp.
Arguments::set_mode_flags(Arguments::_mixed);
}
} else if (!mode_flag_cmd_line) {
// By default, -Xshare:dump runs in interpreter-only mode, which is required for deterministic archive.
//

View File

@ -28,7 +28,7 @@
#include "cds/heapShared.hpp"
#include "memory/iterator.hpp"
#include "utilities/growableArray.hpp"
#include "utilities/resourceHash.hpp"
#include "utilities/hashTable.hpp"
class InstanceKlass;
class Symbol;
@ -47,7 +47,7 @@ class CDSHeapVerifier : public KlassClosure {
Symbol* _name;
};
ResourceHashtable<oop, StaticFieldInfo,
HashTable<oop, StaticFieldInfo,
15889, // prime number
AnyObj::C_HEAP,
mtClassShared,
@ -79,7 +79,7 @@ public:
// Overrides KlassClosure::do_klass()
virtual void do_klass(Klass* k);
// For ResourceHashtable::iterate()
// For HashTable::iterate()
inline bool do_entry(oop& orig_obj, HeapShared::CachedOopInfo& value);
static void verify();

View File

@ -29,7 +29,7 @@
#include "utilities/globalDefinitions.hpp"
#include "utilities/growableArray.hpp"
#include "utilities/istream.hpp"
#include "utilities/resizeableResourceHash.hpp"
#include "utilities/resizableHashTable.hpp"
class constantPoolHandle;
class Thread;
@ -77,7 +77,7 @@ public:
private:
// Must be C_HEAP allocated -- we don't want nested resource allocations.
typedef ResizeableResourceHashtable<int, InstanceKlass*,
typedef ResizeableHashTable<int, InstanceKlass*,
AnyObj::C_HEAP, mtClassShared> ID2KlassTable;
enum {

View File

@ -66,7 +66,7 @@ void ClassListWriter::write(const InstanceKlass* k, const ClassFileStream* cfs)
write_to_stream(k, w.stream(), cfs);
}
class ClassListWriter::IDTable : public ResourceHashtable<
class ClassListWriter::IDTable : public HashTable<
const InstanceKlass*, int,
15889, // prime number
AnyObj::C_HEAP> {};

View File

@ -240,7 +240,7 @@ inline unsigned DumpTimeSharedClassTable_hash(T* const& k) {
}
}
using DumpTimeSharedClassTableBaseType = ResourceHashtable<
using DumpTimeSharedClassTableBaseType = HashTable<
InstanceKlass*,
DumpTimeClassInfo,
15889, // prime number

View File

@ -367,7 +367,7 @@ bool HeapShared::archive_object(oop obj, oop referrer, KlassSubGraphInfo* subgra
}
}
class MetaspaceObjToOopHandleTable: public ResourceHashtable<MetaspaceObj*, OopHandle,
class MetaspaceObjToOopHandleTable: public HashTable<MetaspaceObj*, OopHandle,
36137, // prime number
AnyObj::C_HEAP,
mtClassShared> {

View File

@ -37,7 +37,7 @@
#include "oops/oopHandle.hpp"
#include "oops/oopsHierarchy.hpp"
#include "utilities/growableArray.hpp"
#include "utilities/resourceHash.hpp"
#include "utilities/hashTable.hpp"
#if INCLUDE_CDS_JAVA_HEAP
class DumpedInternedStrings;
@ -202,14 +202,14 @@ public:
private:
static const int INITIAL_TABLE_SIZE = 15889; // prime number
static const int MAX_TABLE_SIZE = 1000000;
typedef ResizeableResourceHashtable<oop, CachedOopInfo,
typedef ResizeableHashTable<oop, CachedOopInfo,
AnyObj::C_HEAP,
mtClassShared,
HeapShared::oop_hash> ArchivedObjectCache;
static ArchivedObjectCache* _archived_object_cache;
class DumpTimeKlassSubGraphInfoTable
: public ResourceHashtable<Klass*, KlassSubGraphInfo,
: public HashTable<Klass*, KlassSubGraphInfo,
137, // prime number
AnyObj::C_HEAP,
mtClassShared,
@ -264,7 +264,7 @@ private:
// !UseCompressedOops only: used to relocate pointers to the archived objects
static ptrdiff_t _runtime_delta;
typedef ResizeableResourceHashtable<oop, bool,
typedef ResizeableHashTable<oop, bool,
AnyObj::C_HEAP,
mtClassShared,
HeapShared::oop_hash> SeenObjectsTable;
@ -468,14 +468,14 @@ private:
#if INCLUDE_CDS_JAVA_HEAP
class DumpedInternedStrings :
public ResizeableResourceHashtable<oop, bool,
public ResizeableHashTable<oop, bool,
AnyObj::C_HEAP,
mtClassShared,
HeapShared::string_oop_hash>
{
public:
DumpedInternedStrings(unsigned size, unsigned max_size) :
ResizeableResourceHashtable<oop, bool,
ResizeableHashTable<oop, bool,
AnyObj::C_HEAP,
mtClassShared,
HeapShared::string_oop_hash>(size, max_size) {}

View File

@ -30,7 +30,7 @@
#include "classfile/javaClasses.hpp"
#include "memory/metaspaceClosure.hpp"
#include "utilities/growableArray.hpp"
#include "utilities/resourceHash.hpp"
#include "utilities/hashTable.hpp"
// This file contains *legacy* optimization for lambdas before JEP 483. May be removed in the future.
//
@ -249,7 +249,7 @@ public:
};
class DumpTimeLambdaProxyClassDictionary
: public ResourceHashtable<LambdaProxyClassKey,
: public HashTable<LambdaProxyClassKey,
DumpTimeLambdaProxyClassInfo,
137, // prime number
AnyObj::C_HEAP,

View File

@ -97,9 +97,9 @@
#include "utilities/align.hpp"
#include "utilities/bitMap.inline.hpp"
#include "utilities/defaultStream.hpp"
#include "utilities/hashTable.hpp"
#include "utilities/macros.hpp"
#include "utilities/ostream.hpp"
#include "utilities/resourceHash.hpp"
#include <sys/stat.h>
@ -178,7 +178,7 @@ class DumpClassListCLDClosure : public CLDClosure {
static const int MAX_TABLE_SIZE = 61333;
fileStream *_stream;
ResizeableResourceHashtable<InstanceKlass*, bool,
ResizeableHashTable<InstanceKlass*, bool,
AnyObj::C_HEAP, mtClassShared> _dumped_classes;
void dump(InstanceKlass* ik) {

View File

@ -32,9 +32,9 @@
#include "runtime/mutexLocker.hpp"
#include "runtime/thread.hpp"
#include "utilities/growableArray.hpp"
#include "utilities/resourceHash.hpp"
#include "utilities/hashTable.hpp"
using RegeneratedObjTable = ResourceHashtable<address, address, 15889, AnyObj::C_HEAP, mtClassShared>;
using RegeneratedObjTable = HashTable<address, address, 15889, AnyObj::C_HEAP, mtClassShared>;
static RegeneratedObjTable* _regenerated_objs = nullptr; // InstanceKlass* and Method* orig_obj -> regen_obj
static RegeneratedObjTable* _original_objs = nullptr; // InstanceKlass* and Method* regen_obj -> orig_obj
static GrowableArrayCHeap<OopHandle, mtClassShared>* _regenerated_mirrors = nullptr;

View File

@ -30,8 +30,7 @@
#include "oops/symbol.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/growableArray.hpp"
#include "utilities/resourceHash.hpp"
#include "utilities/hashTable.hpp"
/**
* Bytecode Assembler
@ -125,7 +124,7 @@ class BytecodeCPEntry {
class BytecodeConstantPool : public ResourceObj {
private:
typedef ResourceHashtable<BytecodeCPEntry, u2,
typedef HashTable<BytecodeCPEntry, u2,
256, AnyObj::RESOURCE_AREA, mtInternal,
&BytecodeCPEntry::hash, &BytecodeCPEntry::equals> IndexHash;

View File

@ -81,9 +81,9 @@
#include "utilities/formatBuffer.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/growableArray.hpp"
#include "utilities/hashTable.hpp"
#include "utilities/macros.hpp"
#include "utilities/ostream.hpp"
#include "utilities/resourceHash.hpp"
#include "utilities/utf8.hpp"
#if INCLUDE_CDS
#include "classfile/systemDictionaryShared.hpp"
@ -782,7 +782,7 @@ class NameSigHash: public ResourceObj {
}
};
using NameSigHashtable = ResourceHashtable<NameSigHash, int,
using NameSigHashtable = HashTable<NameSigHash, int,
NameSigHash::HASH_ROW_SIZE,
AnyObj::RESOURCE_AREA, mtInternal,
&NameSigHash::hash, &NameSigHash::equals>;
@ -849,7 +849,7 @@ void ClassFileParser::parse_interfaces(const ClassFileStream* const stream,
// Check if there's any duplicates in interfaces
ResourceMark rm(THREAD);
// Set containing interface names
ResourceHashtable<Symbol*, int>* interface_names = new ResourceHashtable<Symbol*, int>();
HashTable<Symbol*, int>* interface_names = new HashTable<Symbol*, int>();
for (index = 0; index < itfs_len; index++) {
const InstanceKlass* const k = _local_interfaces->at(index);
Symbol* interface_name = k->name();
@ -2022,7 +2022,7 @@ void ClassFileParser::copy_localvariable_table(const ConstMethod* cm,
ResourceMark rm(THREAD);
typedef ResourceHashtable<LocalVariableTableElement, LocalVariableTableElement*,
typedef HashTable<LocalVariableTableElement, LocalVariableTableElement*,
256, AnyObj::RESOURCE_AREA, mtInternal,
&LVT_Hash::hash, &LVT_Hash::equals> LVT_HashTable;

View File

@ -25,15 +25,13 @@
#ifndef SHARE_CLASSFILE_CLASSLOADERSTATS_HPP
#define SHARE_CLASSFILE_CLASSLOADERSTATS_HPP
#include "classfile/classLoaderData.hpp"
#include "oops/klass.hpp"
#include "oops/oop.hpp"
#include "oops/oopsHierarchy.hpp"
#include "runtime/vmOperation.hpp"
#include "services/diagnosticCommand.hpp"
#include "utilities/resourceHash.hpp"
#include "utilities/hashTable.hpp"
class ClassLoaderStatsDCmd : public DCmd {
public:
@ -105,7 +103,7 @@ protected:
return hash;
}
typedef ResourceHashtable<oop, ClassLoaderStats,
typedef HashTable<oop, ClassLoaderStats,
256, AnyObj::C_HEAP, mtStatistics,
ClassLoaderStatsClosure::oop_hash> StatsTable;

View File

@ -1886,8 +1886,9 @@ JavaThreadStatus java_lang_Thread::get_thread_status(oop java_thread) {
// Make sure the caller is operating on behalf of the VM or is
// running VM code (state == _thread_in_vm).
assert(Threads_lock->owned_by_self() || Thread::current()->is_VM_thread() ||
JavaThread::current()->thread_state() == _thread_in_vm,
"Java Thread is not running in vm");
JavaThread::current()->thread_state() == _thread_in_vm ||
JavaThread::current() == java_lang_Thread::thread(java_thread),
"unsafe call to java_lang_Thread::get_thread_status()?");
GET_FIELDHOLDER_FIELD(java_thread, get_thread_status, JavaThreadStatus::NEW /* not initialized */);
}
@ -1899,33 +1900,29 @@ oop java_lang_Thread::park_blocker(oop java_thread) {
return java_thread->obj_field_access<MO_RELAXED>(_park_blocker_offset);
}
oop java_lang_Thread::async_get_stack_trace(oop java_thread, TRAPS) {
ThreadsListHandle tlh(JavaThread::current());
JavaThread* thread;
bool is_virtual = java_lang_VirtualThread::is_instance(java_thread);
if (is_virtual) {
oop carrier_thread = java_lang_VirtualThread::carrier_thread(java_thread);
if (carrier_thread == nullptr) {
return nullptr;
}
thread = java_lang_Thread::thread(carrier_thread);
} else {
thread = java_lang_Thread::thread(java_thread);
}
if (thread == nullptr) {
// Obtain stack trace for platform or mounted virtual thread.
// If jthread is a virtual thread and it has been unmounted (or remounted to different carrier) the method returns null.
// The caller (java.lang.VirtualThread) handles returned nulls via retry.
oop java_lang_Thread::async_get_stack_trace(jobject jthread, TRAPS) {
ThreadsListHandle tlh(THREAD);
JavaThread* java_thread = nullptr;
oop thread_oop;
bool has_java_thread = tlh.cv_internal_thread_to_JavaThread(jthread, &java_thread, &thread_oop);
if (!has_java_thread) {
return nullptr;
}
class GetStackTraceHandshakeClosure : public HandshakeClosure {
public:
const Handle _java_thread;
const Handle _thread_h;
int _depth;
bool _retry_handshake;
GrowableArray<Method*>* _methods;
GrowableArray<int>* _bcis;
GetStackTraceHandshakeClosure(Handle java_thread) :
HandshakeClosure("GetStackTraceHandshakeClosure"), _java_thread(java_thread), _depth(0), _retry_handshake(false),
GetStackTraceHandshakeClosure(Handle thread_h) :
HandshakeClosure("GetStackTraceHandshakeClosure"), _thread_h(thread_h), _depth(0), _retry_handshake(false),
_methods(nullptr), _bcis(nullptr) {
}
~GetStackTraceHandshakeClosure() {
@ -1947,21 +1944,22 @@ oop java_lang_Thread::async_get_stack_trace(oop java_thread, TRAPS) {
return;
}
JavaThread* thread = JavaThread::cast(th);
JavaThread* java_thread = JavaThread::cast(th);
if (!thread->has_last_Java_frame()) {
if (!java_thread->has_last_Java_frame()) {
return;
}
bool carrier = false;
if (java_lang_VirtualThread::is_instance(_java_thread())) {
// if (thread->vthread() != _java_thread()) // We might be inside a System.executeOnCarrierThread
const ContinuationEntry* ce = thread->vthread_continuation();
if (ce == nullptr || ce->cont_oop(thread) != java_lang_VirtualThread::continuation(_java_thread())) {
return; // not mounted
if (java_lang_VirtualThread::is_instance(_thread_h())) {
// Ensure _thread_h is still mounted to java_thread.
const ContinuationEntry* ce = java_thread->vthread_continuation();
if (ce == nullptr || ce->cont_oop(java_thread) != java_lang_VirtualThread::continuation(_thread_h())) {
// Target thread has been unmounted.
return;
}
} else {
carrier = (thread->vthread_continuation() != nullptr);
carrier = (java_thread->vthread_continuation() != nullptr);
}
const int max_depth = MaxJavaStackTraceDepth;
@ -1973,7 +1971,7 @@ oop java_lang_Thread::async_get_stack_trace(oop java_thread, TRAPS) {
_bcis = new (mtInternal) GrowableArray<int>(init_length, mtInternal);
int total_count = 0;
for (vframeStream vfst(thread, false, false, carrier); // we don't process frames as we don't care about oops
for (vframeStream vfst(java_thread, false, false, carrier); // we don't process frames as we don't care about oops
!vfst.at_end() && (max_depth == 0 || max_depth != total_count);
vfst.next()) {
@ -1994,9 +1992,9 @@ oop java_lang_Thread::async_get_stack_trace(oop java_thread, TRAPS) {
// Handshake with target
ResourceMark rm(THREAD);
HandleMark hm(THREAD);
GetStackTraceHandshakeClosure gsthc(Handle(THREAD, java_thread));
GetStackTraceHandshakeClosure gsthc(Handle(THREAD, thread_oop));
do {
Handshake::execute(&gsthc, &tlh, thread);
Handshake::execute(&gsthc, &tlh, java_thread);
} while (gsthc.read_reset_retry());
// Stop if no stack trace is found.

View File

@ -463,7 +463,7 @@ class java_lang_Thread : AllStatic {
static const char* thread_status_name(oop java_thread_oop);
// Fill in current stack trace, can cause GC
static oop async_get_stack_trace(oop java_thread, TRAPS);
static oop async_get_stack_trace(jobject jthread, TRAPS);
JFR_ONLY(static u2 jfr_epoch(oop java_thread);)
JFR_ONLY(static void set_jfr_epoch(oop java_thread, u2 epoch);)

View File

@ -31,7 +31,7 @@
#include "oops/klass.inline.hpp"
#include "oops/symbolHandle.hpp"
#include "runtime/mutexLocker.hpp"
#include "utilities/resourceHash.hpp"
#include "utilities/hashTable.hpp"
// Overview
//
@ -147,7 +147,7 @@ class ConstraintSet { // copied into hashtable as
};
using InternalLoaderConstraintTable = ResourceHashtable<SymbolHandle, ConstraintSet, 107, AnyObj::C_HEAP, mtClass, SymbolHandle::compute_hash>;
using InternalLoaderConstraintTable = HashTable<SymbolHandle, ConstraintSet, 107, AnyObj::C_HEAP, mtClass, SymbolHandle::compute_hash>;
static InternalLoaderConstraintTable* _loader_constraint_table;
void LoaderConstraint::extend_loader_constraint(Symbol* class_name,

View File

@ -45,9 +45,9 @@
#include "runtime/safepoint.hpp"
#include "utilities/events.hpp"
#include "utilities/growableArray.hpp"
#include "utilities/hashTable.hpp"
#include "utilities/ostream.hpp"
#include "utilities/quickSort.hpp"
#include "utilities/resourceHash.hpp"
ModuleEntry* ModuleEntryTable::_javabase_module = nullptr;
@ -403,7 +403,7 @@ void ModuleEntry::set_loader_data(ClassLoaderData* cld) {
}
#if INCLUDE_CDS_JAVA_HEAP
typedef ResourceHashtable<
typedef HashTable<
const ModuleEntry*,
ModuleEntry*,
557, // prime number

View File

@ -31,9 +31,9 @@
#include "oops/symbolHandle.hpp"
#include "runtime/mutexLocker.hpp"
#include "utilities/growableArray.hpp"
#include "utilities/hashTable.hpp"
#include "utilities/macros.hpp"
#include "utilities/ostream.hpp"
#include "utilities/resourceHash.hpp"
#if INCLUDE_JFR
#include "jfr/support/jfrTraceIdExtension.hpp"
#endif
@ -233,7 +233,7 @@ class ModuleClosure: public StackObj {
class ModuleEntryTable : public CHeapObj<mtModule> {
private:
static ModuleEntry* _javabase_module;
ResourceHashtable<SymbolHandle, ModuleEntry*, 109, AnyObj::C_HEAP, mtModule,
HashTable<SymbolHandle, ModuleEntry*, 109, AnyObj::C_HEAP, mtModule,
SymbolHandle::compute_hash> _table;
public:

View File

@ -38,9 +38,9 @@
#include "runtime/java.hpp"
#include "utilities/events.hpp"
#include "utilities/growableArray.hpp"
#include "utilities/hashTable.hpp"
#include "utilities/ostream.hpp"
#include "utilities/quickSort.hpp"
#include "utilities/resourceHash.hpp"
PackageEntry::PackageEntry(Symbol* name, ModuleEntry* module) :
_name(name),
@ -212,7 +212,7 @@ PackageEntryTable::~PackageEntryTable() {
}
#if INCLUDE_CDS_JAVA_HEAP
typedef ResourceHashtable<
typedef HashTable<
const PackageEntry*,
PackageEntry*,
557, // prime number

View File

@ -30,9 +30,9 @@
#include "oops/symbolHandle.hpp"
#include "runtime/atomic.hpp"
#include "utilities/growableArray.hpp"
#include "utilities/hashTable.hpp"
#include "utilities/macros.hpp"
#include "utilities/ostream.hpp"
#include "utilities/resourceHash.hpp"
#if INCLUDE_JFR
#include "jfr/support/jfrTraceIdExtension.hpp"
#endif
@ -233,7 +233,7 @@ public:
// The PackageEntryTable is a Hashtable containing a list of all packages defined
// by a particular class loader. Each package is represented as a PackageEntry node.
class PackageEntryTable : public CHeapObj<mtModule> {
ResourceHashtable<SymbolHandle, PackageEntry*, 109, AnyObj::C_HEAP, mtModule,
HashTable<SymbolHandle, PackageEntry*, 109, AnyObj::C_HEAP, mtModule,
SymbolHandle::compute_hash> _table;
public:
PackageEntryTable();

View File

@ -31,7 +31,7 @@
#include "oops/symbolHandle.hpp"
#include "runtime/javaThread.hpp"
#include "runtime/mutexLocker.hpp"
#include "utilities/resourceHash.hpp"
#include "utilities/hashTable.hpp"
class PlaceholderKey {
SymbolHandle _name;
@ -49,7 +49,7 @@ class PlaceholderKey {
};
const int _placeholder_table_size = 503; // Does this really have to be prime?
using InternalPlaceholderTable = ResourceHashtable<PlaceholderKey, PlaceholderEntry, _placeholder_table_size, AnyObj::C_HEAP, mtClass,
using InternalPlaceholderTable = HashTable<PlaceholderKey, PlaceholderEntry, _placeholder_table_size, AnyObj::C_HEAP, mtClass,
PlaceholderKey::hash, PlaceholderKey::equals>;
static InternalPlaceholderTable* _placeholders;

View File

@ -30,7 +30,7 @@
#include "oops/symbol.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/mutexLocker.hpp"
#include "utilities/resourceHash.hpp"
#include "utilities/hashTable.hpp"
class ResolutionErrorKey {
ConstantPool* _cpool;
@ -53,7 +53,7 @@ class ResolutionErrorKey {
}
};
using InternalResolutionErrorTable = ResourceHashtable<ResolutionErrorKey, ResolutionErrorEntry*, 107, AnyObj::C_HEAP, mtClass,
using InternalResolutionErrorTable = HashTable<ResolutionErrorKey, ResolutionErrorEntry*, 107, AnyObj::C_HEAP, mtClass,
ResolutionErrorKey::hash,
ResolutionErrorKey::equals>;

View File

@ -59,7 +59,7 @@
#include "utilities/concurrentHashTable.inline.hpp"
#include "utilities/concurrentHashTableTasks.inline.hpp"
#include "utilities/macros.hpp"
#include "utilities/resizeableResourceHash.hpp"
#include "utilities/resizableHashTable.hpp"
#include "utilities/utf8.hpp"
#if INCLUDE_G1GC
#include "gc/g1/g1CollectedHeap.hpp"
@ -810,7 +810,7 @@ class StringTable::VerifyCompStrings : StackObj {
return java_lang_String::equals(a, b);
}
ResizeableResourceHashtable<oop, bool, AnyObj::C_HEAP, mtInternal,
ResizeableHashTable<oop, bool, AnyObj::C_HEAP, mtInternal,
string_hash, string_equals> _table;
public:
size_t _errors;

View File

@ -111,10 +111,10 @@ class InvokeMethodKey : public StackObj {
};
using InvokeMethodIntrinsicTable = ResourceHashtable<InvokeMethodKey, Method*, 139, AnyObj::C_HEAP, mtClass,
using InvokeMethodIntrinsicTable = HashTable<InvokeMethodKey, Method*, 139, AnyObj::C_HEAP, mtClass,
InvokeMethodKey::compute_hash, InvokeMethodKey::key_comparison>;
static InvokeMethodIntrinsicTable* _invoke_method_intrinsic_table;
using InvokeMethodTypeTable = ResourceHashtable<SymbolHandle, OopHandle, 139, AnyObj::C_HEAP, mtClass, SymbolHandle::compute_hash>;
using InvokeMethodTypeTable = HashTable<SymbolHandle, OopHandle, 139, AnyObj::C_HEAP, mtClass, SymbolHandle::compute_hash>;
static InvokeMethodTypeTable* _invoke_method_type_table;
OopHandle SystemDictionary::_java_system_loader;

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