mirror of
https://github.com/openjdk/jdk.git
synced 2026-04-27 15:20:53 +00:00
Merge branch 'openjdk:master' into JDK-8373118
This commit is contained in:
commit
d6890230a1
@ -187,14 +187,18 @@ fi
|
||||
SOURCE_PREFIX="<sourceFolder url=\"file://"
|
||||
SOURCE_POSTFIX="\" isTestSource=\"false\" />"
|
||||
|
||||
# SOURCES is a single string containing embeded newlines.
|
||||
for root in $MODULE_ROOTS; do
|
||||
if [ "x$CYGPATH" != "x" ]; then
|
||||
root=`$CYGPATH -am $root`
|
||||
elif [ "x$WSL_DISTRO_NAME" != "x" ]; then
|
||||
root=`wslpath -am $root`
|
||||
fi
|
||||
|
||||
SOURCES=$SOURCES" $SOURCE_PREFIX""$root""$SOURCE_POSTFIX"
|
||||
# Add line termination/indentation for everything after the first entry.
|
||||
if [ "x$SOURCES" != "x" ]; then
|
||||
SOURCES="${SOURCES}\n "
|
||||
fi
|
||||
SOURCES="${SOURCES}${SOURCE_PREFIX}${root}${SOURCE_POSTFIX}"
|
||||
done
|
||||
|
||||
add_replacement "###SOURCE_ROOTS###" "$SOURCES"
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
# Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 1997, 2026, 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
|
||||
@ -93,19 +93,16 @@ JAVADOC_DISABLED_DOCLINT_WARNINGS := missing
|
||||
JAVADOC_DISABLED_DOCLINT_PACKAGES := org.w3c.* javax.smartcardio
|
||||
|
||||
# The initial set of options for javadoc
|
||||
# -XDaccessInternalAPI is a temporary workaround, see 8373909
|
||||
JAVADOC_OPTIONS := -use -keywords -notimestamp \
|
||||
-serialwarn -encoding utf-8 -docencoding utf-8 -breakiterator \
|
||||
-splitIndex --system none -javafx --expand-requires transitive \
|
||||
--override-methods=summary \
|
||||
-XDaccessInternalAPI
|
||||
--override-methods=summary
|
||||
|
||||
# The reference options must stay stable to allow for comparisons across the
|
||||
# development cycle.
|
||||
REFERENCE_OPTIONS := -XDignore.symbol.file=true -use -keywords -notimestamp \
|
||||
-serialwarn -encoding utf-8 -breakiterator -splitIndex --system none \
|
||||
-html5 -javafx --expand-requires transitive \
|
||||
-XDaccessInternalAPI
|
||||
-html5 -javafx --expand-requires transitive
|
||||
|
||||
# Should we add DRAFT stamps to the generated javadoc?
|
||||
ifeq ($(VERSION_IS_GA), true)
|
||||
|
||||
@ -1020,6 +1020,9 @@ define SetupRunJtregTestBody
|
||||
VM_OPTIONS := $$(JTREG_ALL_OPTIONS) ))
|
||||
$$(call LogWarn, AOT_JDK_CACHE=$$($1_AOT_JDK_CACHE))
|
||||
$1_JTREG_BASIC_OPTIONS += -vmoption:-XX:AOTCache="$$($1_AOT_JDK_CACHE)"
|
||||
$1_JTREG_BASIC_OPTIONS += $$(addprefix $$(JTREG_PROBLEM_LIST_PREFIX), $$(wildcard \
|
||||
$$(addprefix $$($1_TEST_ROOT)/, ProblemList-AotJdk.txt) \
|
||||
))
|
||||
endif
|
||||
|
||||
|
||||
|
||||
@ -544,12 +544,9 @@ AC_DEFUN([FLAGS_SETUP_CFLAGS_HELPER],
|
||||
TOOLCHAIN_CFLAGS_JVM="$TOOLCHAIN_CFLAGS_JVM -fstack-protector"
|
||||
TOOLCHAIN_CFLAGS_JDK="-fvisibility=hidden -pipe -fstack-protector"
|
||||
# reduce lib size on linux in link step, this needs also special compile flags
|
||||
# do this on s390x also for libjvm (where serviceability agent is not supported)
|
||||
if test "x$ENABLE_LINKTIME_GC" = xtrue; then
|
||||
TOOLCHAIN_CFLAGS_JDK="$TOOLCHAIN_CFLAGS_JDK -ffunction-sections -fdata-sections"
|
||||
if test "x$OPENJDK_TARGET_CPU" = xs390x && test "x$DEBUG_LEVEL" == xrelease; then
|
||||
TOOLCHAIN_CFLAGS_JVM="$TOOLCHAIN_CFLAGS_JVM -ffunction-sections -fdata-sections"
|
||||
fi
|
||||
TOOLCHAIN_CFLAGS_JVM="$TOOLCHAIN_CFLAGS_JVM -ffunction-sections -fdata-sections"
|
||||
fi
|
||||
# technically NOT for CXX (but since this gives *worse* performance, use
|
||||
# no-strict-aliasing everywhere!)
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2011, 2026, 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
|
||||
@ -53,16 +53,15 @@ AC_DEFUN([FLAGS_SETUP_LDFLAGS_HELPER],
|
||||
# add --icf=all (Identical Code Folding — merges identical functions)
|
||||
BASIC_LDFLAGS="-Wl,-z,defs -Wl,-z,relro -Wl,-z,now -Wl,--no-as-needed -Wl,--exclude-libs,ALL"
|
||||
|
||||
BASIC_LDFLAGS_JVM_ONLY=""
|
||||
# Linux : remove unused code+data in link step
|
||||
if test "x$ENABLE_LINKTIME_GC" = xtrue; then
|
||||
if test "x$OPENJDK_TARGET_CPU" = xs390x; then
|
||||
BASIC_LDFLAGS="$BASIC_LDFLAGS -Wl,--gc-sections"
|
||||
else
|
||||
BASIC_LDFLAGS_JDK_ONLY="$BASIC_LDFLAGS_JDK_ONLY -Wl,--gc-sections"
|
||||
fi
|
||||
# keep vtables : -Wl,--undefined-glob=_ZTV* (but this seems not to work with gold ld)
|
||||
# so keep at least the Metadata vtable that is used in the serviceability agent
|
||||
BASIC_LDFLAGS_JVM_ONLY="$BASIC_LDFLAGS_JVM_ONLY -Wl,--gc-sections -Wl,--undefined=_ZTV8Metadata"
|
||||
BASIC_LDFLAGS_JDK_ONLY="$BASIC_LDFLAGS_JDK_ONLY -Wl,--gc-sections"
|
||||
fi
|
||||
|
||||
BASIC_LDFLAGS_JVM_ONLY=""
|
||||
LDFLAGS_LTO="-flto=auto -fuse-linker-plugin -fno-strict-aliasing $DEBUG_PREFIX_CFLAGS"
|
||||
|
||||
LDFLAGS_CXX_PARTIAL_LINKING="$MACHINE_FLAG -r"
|
||||
|
||||
@ -801,10 +801,7 @@ public class CLDRConverter {
|
||||
String tzKey = Optional.ofNullable((String)handlerSupplMeta.get(tzid))
|
||||
.orElse(tzid);
|
||||
// Follow link, if needed
|
||||
String tzLink = null;
|
||||
for (var k = tzKey; tzdbLinks.containsKey(k);) {
|
||||
k = tzLink = tzdbLinks.get(k);
|
||||
}
|
||||
String tzLink = getTZDBLink(tzKey);
|
||||
if (tzLink == null && tzdbLinks.containsValue(tzKey)) {
|
||||
// reverse link search
|
||||
// this is needed as in tzdb, "America/Buenos_Aires" links to
|
||||
@ -833,7 +830,7 @@ public class CLDRConverter {
|
||||
} else {
|
||||
// TZDB short names
|
||||
tznames = Arrays.copyOf(tznames, tznames.length);
|
||||
fillTZDBShortNames(tzid, tznames);
|
||||
fillTZDBShortNames(tzKey, tznames);
|
||||
names.put(tzid, tznames);
|
||||
}
|
||||
} else {
|
||||
@ -846,11 +843,13 @@ public class CLDRConverter {
|
||||
String metaKey = METAZONE_ID_PREFIX + meta;
|
||||
data = map.get(metaKey);
|
||||
if (data instanceof String[] tznames) {
|
||||
// TZDB short names
|
||||
tznames = Arrays.copyOf((String[])names.getOrDefault(metaKey, tznames), 6);
|
||||
fillTZDBShortNames(tzid, tznames);
|
||||
// Keep the metazone prefix here.
|
||||
names.putIfAbsent(metaKey, tznames);
|
||||
if (isDefaultZone(meta, tzKey)) {
|
||||
// Record the metazone names only from the default
|
||||
// (001) zone, with short names filled from TZDB
|
||||
tznames = Arrays.copyOf(tznames, tznames.length);
|
||||
fillTZDBShortNames(tzKey, tznames);
|
||||
names.put(metaKey, tznames);
|
||||
}
|
||||
names.put(tzid, meta);
|
||||
if (tzLink != null && availableIds.contains(tzLink)) {
|
||||
names.put(tzLink, meta);
|
||||
@ -1504,12 +1503,12 @@ public class CLDRConverter {
|
||||
* Fill the TZDB short names if there is no name provided by the CLDR
|
||||
*/
|
||||
private static void fillTZDBShortNames(String tzid, String[] names) {
|
||||
var val = tzdbShortNamesMap.get(tzdbLinks.getOrDefault(tzid, tzid));
|
||||
var val = tzdbShortNamesMap.getOrDefault(tzid, tzdbShortNamesMap.get(getTZDBLink(tzid)));
|
||||
if (val != null) {
|
||||
var format = val.split(NBSP)[0];
|
||||
var rule = val.split(NBSP)[1];
|
||||
IntStream.of(1, 3, 5).forEach(i -> {
|
||||
if (names[i] == null) {
|
||||
if (names[i] == null || names[i].isEmpty()) {
|
||||
if (format.contains("%s")) {
|
||||
names[i] = switch (i) {
|
||||
case 1 -> format.formatted(tzdbSubstLetters.get(rule + NBSP + STD));
|
||||
@ -1531,6 +1530,21 @@ public class CLDRConverter {
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isDefaultZone(String meta, String tzid) {
|
||||
String zone001 = handlerMetaZones.zidMap().get(meta);
|
||||
var tzLink = getTZDBLink(tzid);
|
||||
return canonicalTZMap.getOrDefault(tzid, tzid).equals(zone001) ||
|
||||
tzLink != null && canonicalTZMap.getOrDefault(tzLink, tzLink).equals(zone001);
|
||||
}
|
||||
|
||||
private static String getTZDBLink(String tzid) {
|
||||
String tzLink = null;
|
||||
for (var k = tzid; tzdbLinks.containsKey(k);) {
|
||||
k = tzLink = tzdbLinks.get(k);
|
||||
}
|
||||
return tzLink;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert TZDB offsets to JDK's offsets, eg, "-08" to "GMT-08:00".
|
||||
* If it cannot recognize the pattern, return the argument as is.
|
||||
|
||||
@ -25,13 +25,13 @@
|
||||
|
||||
package build.tools.taglet;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import javax.lang.model.element.Element;
|
||||
|
||||
@ -141,6 +141,11 @@ public class JSpec implements Taglet {
|
||||
|
||||
@Override
|
||||
public String toString(List<? extends DocTree> tags, Element elem) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
// @Override - requires JDK-8373922 in build JDK
|
||||
public String toString(List<? extends DocTree> tags, Element elem, URI docRoot) {
|
||||
|
||||
if (tags.isEmpty())
|
||||
return "";
|
||||
@ -177,7 +182,7 @@ public class JSpec implements Taglet {
|
||||
String preview = m.group("preview"); // null if no preview feature
|
||||
String chapter = m.group("chapter");
|
||||
String section = m.group("section");
|
||||
String rootParent = currentPath().replaceAll("[^/]+", "..");
|
||||
String rootParent = docRoot.resolve("..").toString();
|
||||
|
||||
String url = preview == null ?
|
||||
String.format("%1$s/specs/%2$s/%2$s-%3$s.html#%2$s-%3$s%4$s",
|
||||
@ -230,23 +235,6 @@ public class JSpec implements Taglet {
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private static ThreadLocal<String> CURRENT_PATH = null;
|
||||
|
||||
private String currentPath() {
|
||||
if (CURRENT_PATH == null) {
|
||||
try {
|
||||
Field f = Class.forName("jdk.javadoc.internal.doclets.formats.html.HtmlDocletWriter")
|
||||
.getField("CURRENT_PATH");
|
||||
@SuppressWarnings("unchecked")
|
||||
ThreadLocal<String> tl = (ThreadLocal<String>) f.get(null);
|
||||
CURRENT_PATH = tl;
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException("Cannot determine current path", e);
|
||||
}
|
||||
}
|
||||
return CURRENT_PATH.get();
|
||||
}
|
||||
|
||||
private String expand(List<? extends DocTree> trees) {
|
||||
return (new SimpleDocTreeVisitor<StringBuilder, StringBuilder>() {
|
||||
public StringBuilder defaultAction(DocTree tree, StringBuilder sb) {
|
||||
|
||||
@ -32,7 +32,9 @@ import jdk.javadoc.doclet.Taglet;
|
||||
|
||||
import javax.lang.model.element.*;
|
||||
import javax.lang.model.type.DeclaredType;
|
||||
import javax.lang.model.util.Elements;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
@ -78,6 +80,11 @@ public final class SealedGraph implements Taglet {
|
||||
|
||||
@Override
|
||||
public String toString(List<? extends DocTree> tags, Element element) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
// @Override - requires JDK-8373922 in build JDK
|
||||
public String toString(List<? extends DocTree> tags, Element element, URI docRoot) {
|
||||
if (sealedDotOutputDir == null || sealedDotOutputDir.isEmpty()) {
|
||||
return "";
|
||||
}
|
||||
@ -85,9 +92,15 @@ public final class SealedGraph implements Taglet {
|
||||
return "";
|
||||
}
|
||||
|
||||
ModuleElement module = docletEnvironment.getElementUtils().getModuleOf(element);
|
||||
Elements util = docletEnvironment.getElementUtils();
|
||||
ModuleElement module = util.getModuleOf(element);
|
||||
|
||||
// '.' in .DOT file name is converted to '/' in .SVG path, so we use '-' as separator for nested classes.
|
||||
// module_package.subpackage.Outer-Inner.dot => module/package/subpackage/Outer-Inner-sealed-graph.svg
|
||||
Path dotFile = Path.of(sealedDotOutputDir,
|
||||
module.getQualifiedName() + "_" + typeElement.getQualifiedName() + ".dot");
|
||||
module.getQualifiedName() + "_"
|
||||
+ util.getPackageOf(element).getQualifiedName() + "."
|
||||
+ packagelessCanonicalName(typeElement).replace(".", "-") + ".dot");
|
||||
|
||||
Set<String> exports = module.getDirectives().stream()
|
||||
.filter(ModuleElement.ExportsDirective.class::isInstance)
|
||||
@ -99,7 +112,7 @@ public final class SealedGraph implements Taglet {
|
||||
.map(Objects::toString)
|
||||
.collect(Collectors.toUnmodifiableSet());
|
||||
|
||||
String dotContent = new Renderer().graph(typeElement, exports);
|
||||
String dotContent = new Renderer().graph(typeElement, exports, docRoot);
|
||||
|
||||
try {
|
||||
Files.writeString(dotFile, dotContent, WRITE, CREATE, TRUNCATE_EXISTING);
|
||||
@ -107,8 +120,8 @@ public final class SealedGraph implements Taglet {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
String simpleTypeName = packagelessCanonicalName(typeElement).replace('.', '/');
|
||||
String imageFile = simpleTypeName + "-sealed-graph.svg";
|
||||
String simpleTypeName = packagelessCanonicalName(typeElement);
|
||||
String imageFile = simpleTypeName.replace(".", "-") + "-sealed-graph.svg";
|
||||
int thumbnailHeight = 100; // also appears in the stylesheet
|
||||
String hoverImage = "<span>"
|
||||
+ getImage(simpleTypeName, imageFile, -1, true)
|
||||
@ -137,12 +150,12 @@ public final class SealedGraph implements Taglet {
|
||||
private final class Renderer {
|
||||
|
||||
// Generates a graph in DOT format
|
||||
String graph(TypeElement rootClass, Set<String> exports) {
|
||||
String graph(TypeElement rootClass, Set<String> exports, URI pathToRoot) {
|
||||
if (!isInPublicApi(rootClass, exports)) {
|
||||
// Alternatively we can return "" for the graph since there is no single root to render
|
||||
throw new IllegalArgumentException("Root not in public API: " + rootClass.getQualifiedName());
|
||||
}
|
||||
final State state = new State(rootClass);
|
||||
final State state = new State(pathToRoot);
|
||||
traverse(state, rootClass, exports);
|
||||
return state.render();
|
||||
}
|
||||
@ -168,7 +181,7 @@ public final class SealedGraph implements Taglet {
|
||||
private static final String TOOLTIP = "tooltip";
|
||||
private static final String LINK = "href";
|
||||
|
||||
private final TypeElement rootNode;
|
||||
private final URI pathToRoot;
|
||||
|
||||
private final StringBuilder builder;
|
||||
|
||||
@ -193,8 +206,8 @@ public final class SealedGraph implements Taglet {
|
||||
}
|
||||
}
|
||||
|
||||
public State(TypeElement rootNode) {
|
||||
this.rootNode = rootNode;
|
||||
public State(URI pathToRoot) {
|
||||
this.pathToRoot = pathToRoot;
|
||||
nodeStyleMap = new LinkedHashMap<>();
|
||||
builder = new StringBuilder()
|
||||
.append("digraph G {")
|
||||
@ -217,24 +230,15 @@ public final class SealedGraph implements Taglet {
|
||||
var styles = nodeStyleMap.computeIfAbsent(id(node), n -> new LinkedHashMap<>());
|
||||
styles.put(LABEL, new StyleItem.PlainString(node.getSimpleName().toString()));
|
||||
styles.put(TOOLTIP, new StyleItem.PlainString(node.getQualifiedName().toString()));
|
||||
styles.put(LINK, new StyleItem.PlainString(relativeLink(node)));
|
||||
styles.put(LINK, new StyleItem.PlainString(pathToRoot.resolve(relativeLink(node)).toString()));
|
||||
}
|
||||
|
||||
// A permitted class must be in the same package or in the same module.
|
||||
// This implies the module is always the same.
|
||||
private String relativeLink(TypeElement node) {
|
||||
var util = SealedGraph.this.docletEnvironment.getElementUtils();
|
||||
var nodePackage = util.getPackageOf(node);
|
||||
// Note: SVG files for nested types use the simple names of containing types as parent directories.
|
||||
// We therefore need to convert all dots in the qualified name to "../" below.
|
||||
var backNavigator = rootNode.getQualifiedName().toString().chars()
|
||||
.filter(c -> c == '.')
|
||||
.mapToObj(c -> "../")
|
||||
.collect(joining());
|
||||
var forwardNavigator = nodePackage.getQualifiedName().toString()
|
||||
.replace(".", "/");
|
||||
var path = util.getModuleOf(node).getQualifiedName().toString() + "/"
|
||||
+ util.getPackageOf(node).getQualifiedName().toString().replace(".", "/");
|
||||
|
||||
return backNavigator + forwardNavigator + "/" + packagelessCanonicalName(node) + ".html";
|
||||
return path + "/" + packagelessCanonicalName(node) + ".html";
|
||||
}
|
||||
|
||||
public void addEdge(TypeElement node, TypeElement subNode) {
|
||||
@ -286,14 +290,6 @@ public final class SealedGraph implements Taglet {
|
||||
private String quotedId(TypeElement node) {
|
||||
return "\"" + id(node) + "\"";
|
||||
}
|
||||
|
||||
private String simpleName(String name) {
|
||||
int lastDot = name.lastIndexOf('.');
|
||||
return lastDot < 0
|
||||
? name
|
||||
: name.substring(lastDot);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static List<TypeElement> permittedSubclasses(TypeElement node, Set<String> exports) {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2026, 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
|
||||
@ -25,13 +25,13 @@
|
||||
|
||||
package build.tools.taglet;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import javax.lang.model.element.Element;
|
||||
|
||||
@ -91,6 +91,11 @@ public class ToolGuide implements Taglet {
|
||||
|
||||
@Override
|
||||
public String toString(List<? extends DocTree> tags, Element elem) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
// @Override - requires JDK-8373922 in build JDK
|
||||
public String toString(List<? extends DocTree> tags, Element elem, URI docRoot) {
|
||||
|
||||
if (tags.isEmpty())
|
||||
return "";
|
||||
@ -118,7 +123,7 @@ public class ToolGuide implements Taglet {
|
||||
if (label.isEmpty()) {
|
||||
label = name;
|
||||
}
|
||||
String rootParent = currentPath().replaceAll("[^/]+", "..");
|
||||
String rootParent = docRoot.resolve("..").toString();
|
||||
|
||||
String url = String.format("%s/%s/%s.html",
|
||||
rootParent, BASE_URL, name);
|
||||
@ -141,22 +146,4 @@ public class ToolGuide implements Taglet {
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private static ThreadLocal<String> CURRENT_PATH = null;
|
||||
|
||||
private String currentPath() {
|
||||
if (CURRENT_PATH == null) {
|
||||
try {
|
||||
Field f = Class.forName("jdk.javadoc.internal.doclets.formats.html.HtmlDocletWriter")
|
||||
.getField("CURRENT_PATH");
|
||||
@SuppressWarnings("unchecked")
|
||||
ThreadLocal<String> tl = (ThreadLocal<String>) f.get(null);
|
||||
CURRENT_PATH = tl;
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException("Cannot determine current path", e);
|
||||
}
|
||||
}
|
||||
return CURRENT_PATH.get();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
//
|
||||
// Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
// Copyright (c) 2020, 2025, Arm Limited. All rights reserved.
|
||||
// Copyright (c) 2020, 2026, Arm Limited. All rights reserved.
|
||||
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
//
|
||||
// This code is free software; you can redistribute it and/or modify it
|
||||
@ -247,10 +247,39 @@ source %{
|
||||
case Op_MinVHF:
|
||||
case Op_MaxVHF:
|
||||
case Op_SqrtVHF:
|
||||
if (UseSVE == 0 && !is_feat_fp16_supported()) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
// At the time of writing this, the Vector API has no half-float (FP16) species.
|
||||
// Consequently, AddReductionVHF and MulReductionVHF are only produced by the
|
||||
// auto-vectorizer, which requires strictly ordered semantics for FP reductions.
|
||||
//
|
||||
// There is no direct Neon instruction that performs strictly ordered floating
|
||||
// point add reduction. Hence, on Neon only machines, the add reduction operation
|
||||
// is implemented as a scalarized sequence using half-precision scalar instruction
|
||||
// FADD which requires FEAT_FP16 and ASIMDHP to be available on the target.
|
||||
// On SVE machines (UseSVE > 0) however, there is a direct instruction (FADDA) which
|
||||
// implements strictly ordered floating point add reduction which does not require
|
||||
// the FEAT_FP16 and ASIMDHP checks as SVE supports half-precision floats by default.
|
||||
case Op_AddReductionVHF:
|
||||
// FEAT_FP16 is enabled if both "fphp" and "asimdhp" features are supported.
|
||||
// Only the Neon instructions need this check. SVE supports half-precision floats
|
||||
// by default.
|
||||
if (UseSVE == 0 && !is_feat_fp16_supported()) {
|
||||
if (length_in_bytes < 8 || (UseSVE == 0 && !is_feat_fp16_supported())) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case Op_MulReductionVHF:
|
||||
// There are no direct Neon/SVE instructions that perform strictly ordered
|
||||
// floating point multiply reduction.
|
||||
// For vector length ≤ 16 bytes, the reduction is implemented as a scalarized
|
||||
// sequence using half-precision scalar instruction FMUL. This path requires
|
||||
// FEAT_FP16 and ASIMDHP to be available on the target.
|
||||
// For vector length > 16 bytes, this operation is disabled because there is no
|
||||
// direct SVE instruction that performs a strictly ordered FP16 multiply
|
||||
// reduction.
|
||||
if (length_in_bytes < 8 || length_in_bytes > 16 || !is_feat_fp16_supported()) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
@ -300,6 +329,7 @@ source %{
|
||||
case Op_VectorRearrange:
|
||||
case Op_MulReductionVD:
|
||||
case Op_MulReductionVF:
|
||||
case Op_MulReductionVHF:
|
||||
case Op_MulReductionVI:
|
||||
case Op_MulReductionVL:
|
||||
case Op_CompressBitsV:
|
||||
@ -364,6 +394,7 @@ source %{
|
||||
case Op_VectorMaskCmp:
|
||||
case Op_LoadVectorGather:
|
||||
case Op_StoreVectorScatter:
|
||||
case Op_AddReductionVHF:
|
||||
case Op_AddReductionVF:
|
||||
case Op_AddReductionVD:
|
||||
case Op_AndReductionV:
|
||||
@ -597,13 +628,9 @@ instruct vloadcon(vReg dst, immI0 src) %{
|
||||
BasicType bt = Matcher::vector_element_basic_type(this);
|
||||
if (UseSVE == 0) {
|
||||
uint length_in_bytes = Matcher::vector_length_in_bytes(this);
|
||||
int entry_idx = __ vector_iota_entry_index(bt);
|
||||
assert(length_in_bytes <= 16, "must be");
|
||||
// The iota indices are ordered by type B/S/I/L/F/D, and the offset between two types is 16.
|
||||
int offset = exact_log2(type2aelembytes(bt)) << 4;
|
||||
if (is_floating_point_type(bt)) {
|
||||
offset += 32;
|
||||
}
|
||||
__ lea(rscratch1, ExternalAddress(StubRoutines::aarch64::vector_iota_indices() + offset));
|
||||
__ lea(rscratch1, ExternalAddress(StubRoutines::aarch64::vector_iota_indices(entry_idx)));
|
||||
if (length_in_bytes == 16) {
|
||||
__ ldrq($dst$$FloatRegister, rscratch1);
|
||||
} else {
|
||||
@ -3406,6 +3433,44 @@ instruct reduce_non_strict_order_add4F_neon(vRegF dst, vRegF fsrc, vReg vsrc, vR
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
// Add Reduction for Half floats (FP16).
|
||||
// Neon does not provide direct instructions for strictly ordered floating-point add reductions.
|
||||
// On Neon-only targets (UseSVE = 0), this operation is implemented as a sequence of scalar additions:
|
||||
// values equal to the vector width are loaded into a vector register, each lane is extracted,
|
||||
// and its value is accumulated into the running sum, producing a final scalar result.
|
||||
instruct reduce_addHF_neon(vRegF dst, vRegF fsrc, vReg vsrc, vReg tmp) %{
|
||||
predicate(UseSVE == 0);
|
||||
match(Set dst (AddReductionVHF fsrc vsrc));
|
||||
effect(TEMP_DEF dst, TEMP tmp);
|
||||
format %{ "reduce_addHF $dst, $fsrc, $vsrc\t# 4HF/8HF. KILL $tmp" %}
|
||||
ins_encode %{
|
||||
uint length_in_bytes = Matcher::vector_length_in_bytes(this, $vsrc);
|
||||
__ neon_reduce_add_fp16($dst$$FloatRegister, $fsrc$$FloatRegister,
|
||||
$vsrc$$FloatRegister, length_in_bytes, $tmp$$FloatRegister);
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
// This rule calculates the reduction result in strict order. Two cases will
|
||||
// reach here:
|
||||
// 1. Non strictly-ordered AddReductionVHF when vector size > 128-bits. For example -
|
||||
// AddReductionVHF generated by Vector API. For vector size > 128-bits, it is more
|
||||
// beneficial performance-wise to generate direct SVE instruction even if it is
|
||||
// strictly ordered.
|
||||
// 2. Strictly-ordered AddReductionVHF. For example - AddReductionVHF generated by
|
||||
// auto-vectorization on SVE machine.
|
||||
instruct reduce_addHF_sve(vRegF dst_src1, vReg src2) %{
|
||||
predicate(UseSVE > 0);
|
||||
match(Set dst_src1 (AddReductionVHF dst_src1 src2));
|
||||
format %{ "reduce_addHF_sve $dst_src1, $dst_src1, $src2" %}
|
||||
ins_encode %{
|
||||
uint length_in_bytes = Matcher::vector_length_in_bytes(this, $src2);
|
||||
assert(length_in_bytes == MaxVectorSize, "invalid vector length");
|
||||
__ sve_fadda($dst_src1$$FloatRegister, __ H, ptrue, $src2$$FloatRegister);
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
// This rule calculates the reduction result in strict order. Two cases will
|
||||
// reach here:
|
||||
// 1. Non strictly-ordered AddReductionVF when vector size > 128-bits. For example -
|
||||
@ -3496,12 +3561,14 @@ instruct reduce_addL_masked(iRegLNoSp dst, iRegL isrc, vReg vsrc, pRegGov pg, vR
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
instruct reduce_addF_masked(vRegF dst_src1, vReg src2, pRegGov pg) %{
|
||||
instruct reduce_addFHF_masked(vRegF dst_src1, vReg src2, pRegGov pg) %{
|
||||
predicate(UseSVE > 0);
|
||||
match(Set dst_src1 (AddReductionVHF (Binary dst_src1 src2) pg));
|
||||
match(Set dst_src1 (AddReductionVF (Binary dst_src1 src2) pg));
|
||||
format %{ "reduce_addF_masked $dst_src1, $pg, $dst_src1, $src2" %}
|
||||
format %{ "reduce_addFHF_masked $dst_src1, $pg, $dst_src1, $src2" %}
|
||||
ins_encode %{
|
||||
__ sve_fadda($dst_src1$$FloatRegister, __ S,
|
||||
BasicType bt = Matcher::vector_element_basic_type(this, $src2);
|
||||
__ sve_fadda($dst_src1$$FloatRegister, __ elemType_to_regVariant(bt),
|
||||
$pg$$PRegister, $src2$$FloatRegister);
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
@ -3549,14 +3616,17 @@ instruct reduce_mulL(iRegLNoSp dst, iRegL isrc, vReg vsrc) %{
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
instruct reduce_mulF(vRegF dst, vRegF fsrc, vReg vsrc, vReg tmp) %{
|
||||
|
||||
instruct reduce_mulFHF(vRegF dst, vRegF fsrc, vReg vsrc, vReg tmp) %{
|
||||
predicate(Matcher::vector_length_in_bytes(n->in(2)) <= 16);
|
||||
match(Set dst (MulReductionVHF fsrc vsrc));
|
||||
match(Set dst (MulReductionVF fsrc vsrc));
|
||||
effect(TEMP_DEF dst, TEMP tmp);
|
||||
format %{ "reduce_mulF $dst, $fsrc, $vsrc\t# 2F/4F. KILL $tmp" %}
|
||||
format %{ "reduce_mulFHF $dst, $fsrc, $vsrc\t# 2F/4F/4HF/8HF. KILL $tmp" %}
|
||||
ins_encode %{
|
||||
uint length_in_bytes = Matcher::vector_length_in_bytes(this, $vsrc);
|
||||
__ neon_reduce_mul_fp($dst$$FloatRegister, T_FLOAT, $fsrc$$FloatRegister,
|
||||
BasicType bt = Matcher::vector_element_basic_type(this, $vsrc);
|
||||
__ neon_reduce_mul_fp($dst$$FloatRegister, bt, $fsrc$$FloatRegister,
|
||||
$vsrc$$FloatRegister, length_in_bytes, $tmp$$FloatRegister);
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
//
|
||||
// Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
// Copyright (c) 2020, 2025, Arm Limited. All rights reserved.
|
||||
// Copyright (c) 2020, 2026, Arm Limited. All rights reserved.
|
||||
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
//
|
||||
// This code is free software; you can redistribute it and/or modify it
|
||||
@ -237,10 +237,39 @@ source %{
|
||||
case Op_MinVHF:
|
||||
case Op_MaxVHF:
|
||||
case Op_SqrtVHF:
|
||||
if (UseSVE == 0 && !is_feat_fp16_supported()) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
// At the time of writing this, the Vector API has no half-float (FP16) species.
|
||||
// Consequently, AddReductionVHF and MulReductionVHF are only produced by the
|
||||
// auto-vectorizer, which requires strictly ordered semantics for FP reductions.
|
||||
//
|
||||
// There is no direct Neon instruction that performs strictly ordered floating
|
||||
// point add reduction. Hence, on Neon only machines, the add reduction operation
|
||||
// is implemented as a scalarized sequence using half-precision scalar instruction
|
||||
// FADD which requires FEAT_FP16 and ASIMDHP to be available on the target.
|
||||
// On SVE machines (UseSVE > 0) however, there is a direct instruction (FADDA) which
|
||||
// implements strictly ordered floating point add reduction which does not require
|
||||
// the FEAT_FP16 and ASIMDHP checks as SVE supports half-precision floats by default.
|
||||
case Op_AddReductionVHF:
|
||||
// FEAT_FP16 is enabled if both "fphp" and "asimdhp" features are supported.
|
||||
// Only the Neon instructions need this check. SVE supports half-precision floats
|
||||
// by default.
|
||||
if (UseSVE == 0 && !is_feat_fp16_supported()) {
|
||||
if (length_in_bytes < 8 || (UseSVE == 0 && !is_feat_fp16_supported())) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case Op_MulReductionVHF:
|
||||
// There are no direct Neon/SVE instructions that perform strictly ordered
|
||||
// floating point multiply reduction.
|
||||
// For vector length ≤ 16 bytes, the reduction is implemented as a scalarized
|
||||
// sequence using half-precision scalar instruction FMUL. This path requires
|
||||
// FEAT_FP16 and ASIMDHP to be available on the target.
|
||||
// For vector length > 16 bytes, this operation is disabled because there is no
|
||||
// direct SVE instruction that performs a strictly ordered FP16 multiply
|
||||
// reduction.
|
||||
if (length_in_bytes < 8 || length_in_bytes > 16 || !is_feat_fp16_supported()) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
@ -290,6 +319,7 @@ source %{
|
||||
case Op_VectorRearrange:
|
||||
case Op_MulReductionVD:
|
||||
case Op_MulReductionVF:
|
||||
case Op_MulReductionVHF:
|
||||
case Op_MulReductionVI:
|
||||
case Op_MulReductionVL:
|
||||
case Op_CompressBitsV:
|
||||
@ -354,6 +384,7 @@ source %{
|
||||
case Op_VectorMaskCmp:
|
||||
case Op_LoadVectorGather:
|
||||
case Op_StoreVectorScatter:
|
||||
case Op_AddReductionVHF:
|
||||
case Op_AddReductionVF:
|
||||
case Op_AddReductionVD:
|
||||
case Op_AndReductionV:
|
||||
@ -2063,6 +2094,25 @@ instruct reduce_non_strict_order_add4F_neon(vRegF dst, vRegF fsrc, vReg vsrc, vR
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
dnl
|
||||
|
||||
// Add Reduction for Half floats (FP16).
|
||||
// Neon does not provide direct instructions for strictly ordered floating-point add reductions.
|
||||
// On Neon-only targets (UseSVE = 0), this operation is implemented as a sequence of scalar additions:
|
||||
// values equal to the vector width are loaded into a vector register, each lane is extracted,
|
||||
// and its value is accumulated into the running sum, producing a final scalar result.
|
||||
instruct reduce_addHF_neon(vRegF dst, vRegF fsrc, vReg vsrc, vReg tmp) %{
|
||||
predicate(UseSVE == 0);
|
||||
match(Set dst (AddReductionVHF fsrc vsrc));
|
||||
effect(TEMP_DEF dst, TEMP tmp);
|
||||
format %{ "reduce_addHF $dst, $fsrc, $vsrc\t# 4HF/8HF. KILL $tmp" %}
|
||||
ins_encode %{
|
||||
uint length_in_bytes = Matcher::vector_length_in_bytes(this, $vsrc);
|
||||
__ neon_reduce_add_fp16($dst$$FloatRegister, $fsrc$$FloatRegister,
|
||||
$vsrc$$FloatRegister, length_in_bytes, $tmp$$FloatRegister);
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
dnl
|
||||
dnl REDUCE_ADD_FP_SVE($1, $2 )
|
||||
dnl REDUCE_ADD_FP_SVE(type, size)
|
||||
define(`REDUCE_ADD_FP_SVE', `
|
||||
@ -2074,21 +2124,26 @@ define(`REDUCE_ADD_FP_SVE', `
|
||||
// strictly ordered.
|
||||
// 2. Strictly-ordered AddReductionV$1. For example - AddReductionV$1 generated by
|
||||
// auto-vectorization on SVE machine.
|
||||
instruct reduce_add$1_sve(vReg$1 dst_src1, vReg src2) %{
|
||||
predicate(!VM_Version::use_neon_for_vector(Matcher::vector_length_in_bytes(n->in(2))) ||
|
||||
n->as_Reduction()->requires_strict_order());
|
||||
instruct reduce_add$1_sve(vReg`'ifelse($1, HF, F, $1) dst_src1, vReg src2) %{
|
||||
ifelse($1, HF,
|
||||
`predicate(UseSVE > 0);',
|
||||
`predicate(!VM_Version::use_neon_for_vector(Matcher::vector_length_in_bytes(n->in(2))) ||
|
||||
n->as_Reduction()->requires_strict_order());')
|
||||
match(Set dst_src1 (AddReductionV$1 dst_src1 src2));
|
||||
format %{ "reduce_add$1_sve $dst_src1, $dst_src1, $src2" %}
|
||||
ins_encode %{
|
||||
assert(UseSVE > 0, "must be sve");
|
||||
uint length_in_bytes = Matcher::vector_length_in_bytes(this, $src2);
|
||||
ifelse($1, HF, `',
|
||||
`assert(UseSVE > 0, "must be sve");
|
||||
')dnl
|
||||
uint length_in_bytes = Matcher::vector_length_in_bytes(this, $src2);
|
||||
assert(length_in_bytes == MaxVectorSize, "invalid vector length");
|
||||
__ sve_fadda($dst_src1$$FloatRegister, __ $2, ptrue, $src2$$FloatRegister);
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}')dnl
|
||||
dnl
|
||||
REDUCE_ADD_FP_SVE(F, S)
|
||||
REDUCE_ADD_FP_SVE(HF, H)
|
||||
REDUCE_ADD_FP_SVE(F, S)
|
||||
|
||||
// reduction addD
|
||||
|
||||
@ -2129,21 +2184,30 @@ dnl
|
||||
dnl REDUCE_ADD_FP_PREDICATE($1, $2 )
|
||||
dnl REDUCE_ADD_FP_PREDICATE(insn_name, op_name)
|
||||
define(`REDUCE_ADD_FP_PREDICATE', `
|
||||
instruct reduce_add$1_masked(vReg$1 dst_src1, vReg src2, pRegGov pg) %{
|
||||
instruct reduce_add$1_masked(vReg$2 dst_src1, vReg src2, pRegGov pg) %{
|
||||
predicate(UseSVE > 0);
|
||||
match(Set dst_src1 (AddReductionV$1 (Binary dst_src1 src2) pg));
|
||||
ifelse($2, F,
|
||||
`match(Set dst_src1 (AddReductionVHF (Binary dst_src1 src2) pg));
|
||||
match(Set dst_src1 (AddReductionV$2 (Binary dst_src1 src2) pg));',
|
||||
`match(Set dst_src1 (AddReductionV$2 (Binary dst_src1 src2) pg));')
|
||||
format %{ "reduce_add$1_masked $dst_src1, $pg, $dst_src1, $src2" %}
|
||||
ins_encode %{
|
||||
__ sve_fadda($dst_src1$$FloatRegister, __ $2,
|
||||
$pg$$PRegister, $src2$$FloatRegister);
|
||||
ifelse($2, F,
|
||||
`BasicType bt = Matcher::vector_element_basic_type(this, $src2);
|
||||
',)dnl
|
||||
ifelse($2, F,
|
||||
`__ sve_fadda($dst_src1$$FloatRegister, __ elemType_to_regVariant(bt),
|
||||
$pg$$PRegister, $src2$$FloatRegister);',
|
||||
`__ sve_fadda($dst_src1$$FloatRegister, __ $2,
|
||||
$pg$$PRegister, $src2$$FloatRegister);')
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}')dnl
|
||||
dnl
|
||||
REDUCE_ADD_INT_PREDICATE(I, iRegIorL2I)
|
||||
REDUCE_ADD_INT_PREDICATE(L, iRegL)
|
||||
REDUCE_ADD_FP_PREDICATE(F, S)
|
||||
REDUCE_ADD_FP_PREDICATE(D, D)
|
||||
REDUCE_ADD_FP_PREDICATE(FHF, F)
|
||||
REDUCE_ADD_FP_PREDICATE(D, D)
|
||||
|
||||
// ------------------------------ Vector reduction mul -------------------------
|
||||
|
||||
@ -2176,30 +2240,37 @@ instruct reduce_mulL(iRegLNoSp dst, iRegL isrc, vReg vsrc) %{
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
instruct reduce_mulF(vRegF dst, vRegF fsrc, vReg vsrc, vReg tmp) %{
|
||||
predicate(Matcher::vector_length_in_bytes(n->in(2)) <= 16);
|
||||
match(Set dst (MulReductionVF fsrc vsrc));
|
||||
dnl REDUCE_MUL_FP($1, $2 )
|
||||
dnl REDUCE_MUL_FP(insn_name, op_name)
|
||||
define(`REDUCE_MUL_FP', `
|
||||
instruct reduce_mul$1(vReg$2 dst, vReg$2 ifelse($2, F, fsrc, dsrc), vReg vsrc, vReg tmp) %{
|
||||
predicate(Matcher::vector_length_in_bytes(n->in(2)) ifelse($2, F, <=, ==) 16);
|
||||
ifelse($2, F,
|
||||
`match(Set dst (MulReductionVHF fsrc vsrc));
|
||||
match(Set dst (MulReductionV$2 fsrc vsrc));',
|
||||
`match(Set dst (MulReductionV$2 dsrc vsrc));')
|
||||
effect(TEMP_DEF dst, TEMP tmp);
|
||||
format %{ "reduce_mulF $dst, $fsrc, $vsrc\t# 2F/4F. KILL $tmp" %}
|
||||
ifelse($2, F,
|
||||
`format %{ "reduce_mul$1 $dst, $fsrc, $vsrc\t# 2F/4F/4HF/8HF. KILL $tmp" %}',
|
||||
`format %{ "reduce_mul$1 $dst, $dsrc, $vsrc\t# 2D. KILL $tmp" %}')
|
||||
ins_encode %{
|
||||
uint length_in_bytes = Matcher::vector_length_in_bytes(this, $vsrc);
|
||||
__ neon_reduce_mul_fp($dst$$FloatRegister, T_FLOAT, $fsrc$$FloatRegister,
|
||||
$vsrc$$FloatRegister, length_in_bytes, $tmp$$FloatRegister);
|
||||
ifelse($2, F,
|
||||
`uint length_in_bytes = Matcher::vector_length_in_bytes(this, $vsrc);
|
||||
',)dnl
|
||||
ifelse($2, F,
|
||||
`BasicType bt = Matcher::vector_element_basic_type(this, $vsrc);
|
||||
',)dnl
|
||||
ifelse($2, F,
|
||||
`__ neon_reduce_mul_fp($dst$$FloatRegister, bt, $fsrc$$FloatRegister,
|
||||
$vsrc$$FloatRegister, length_in_bytes, $tmp$$FloatRegister);',
|
||||
`__ neon_reduce_mul_fp($dst$$FloatRegister, T_DOUBLE, $dsrc$$FloatRegister,
|
||||
$vsrc$$FloatRegister, 16, $tmp$$FloatRegister);')
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
instruct reduce_mulD(vRegD dst, vRegD dsrc, vReg vsrc, vReg tmp) %{
|
||||
predicate(Matcher::vector_length_in_bytes(n->in(2)) == 16);
|
||||
match(Set dst (MulReductionVD dsrc vsrc));
|
||||
effect(TEMP_DEF dst, TEMP tmp);
|
||||
format %{ "reduce_mulD $dst, $dsrc, $vsrc\t# 2D. KILL $tmp" %}
|
||||
ins_encode %{
|
||||
__ neon_reduce_mul_fp($dst$$FloatRegister, T_DOUBLE, $dsrc$$FloatRegister,
|
||||
$vsrc$$FloatRegister, 16, $tmp$$FloatRegister);
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
%}')dnl
|
||||
dnl
|
||||
REDUCE_MUL_FP(FHF, F)
|
||||
REDUCE_MUL_FP(D, D)
|
||||
|
||||
dnl
|
||||
dnl REDUCE_BITWISE_OP_NEON($1, $2 $3 $4 )
|
||||
|
||||
@ -1000,30 +1000,6 @@ public:
|
||||
f(0b0101010, 31, 25), f(0, 24), sf(offset, 23, 5), f(0, 4), f(cond, 3, 0);
|
||||
}
|
||||
|
||||
#define INSN(NAME, cond) \
|
||||
void NAME(address dest) { \
|
||||
br(cond, dest); \
|
||||
}
|
||||
|
||||
INSN(beq, EQ);
|
||||
INSN(bne, NE);
|
||||
INSN(bhs, HS);
|
||||
INSN(bcs, CS);
|
||||
INSN(blo, LO);
|
||||
INSN(bcc, CC);
|
||||
INSN(bmi, MI);
|
||||
INSN(bpl, PL);
|
||||
INSN(bvs, VS);
|
||||
INSN(bvc, VC);
|
||||
INSN(bhi, HI);
|
||||
INSN(bls, LS);
|
||||
INSN(bge, GE);
|
||||
INSN(blt, LT);
|
||||
INSN(bgt, GT);
|
||||
INSN(ble, LE);
|
||||
INSN(bal, AL);
|
||||
INSN(bnv, NV);
|
||||
|
||||
void br(Condition cc, Label &L);
|
||||
|
||||
#undef INSN
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright 2026 Arm Limited and/or its affiliates.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -1883,6 +1884,27 @@ void C2_MacroAssembler::neon_reduce_mul_fp(FloatRegister dst, BasicType bt,
|
||||
|
||||
BLOCK_COMMENT("neon_reduce_mul_fp {");
|
||||
switch(bt) {
|
||||
// The T_SHORT type below is for Float16 type which also uses floating-point
|
||||
// instructions.
|
||||
case T_SHORT:
|
||||
fmulh(dst, fsrc, vsrc);
|
||||
ext(vtmp, T8B, vsrc, vsrc, 2);
|
||||
fmulh(dst, dst, vtmp);
|
||||
ext(vtmp, T8B, vsrc, vsrc, 4);
|
||||
fmulh(dst, dst, vtmp);
|
||||
ext(vtmp, T8B, vsrc, vsrc, 6);
|
||||
fmulh(dst, dst, vtmp);
|
||||
if (isQ) {
|
||||
ext(vtmp, T16B, vsrc, vsrc, 8);
|
||||
fmulh(dst, dst, vtmp);
|
||||
ext(vtmp, T16B, vsrc, vsrc, 10);
|
||||
fmulh(dst, dst, vtmp);
|
||||
ext(vtmp, T16B, vsrc, vsrc, 12);
|
||||
fmulh(dst, dst, vtmp);
|
||||
ext(vtmp, T16B, vsrc, vsrc, 14);
|
||||
fmulh(dst, dst, vtmp);
|
||||
}
|
||||
break;
|
||||
case T_FLOAT:
|
||||
fmuls(dst, fsrc, vsrc);
|
||||
ins(vtmp, S, vsrc, 0, 1);
|
||||
@ -1907,6 +1929,33 @@ void C2_MacroAssembler::neon_reduce_mul_fp(FloatRegister dst, BasicType bt,
|
||||
BLOCK_COMMENT("} neon_reduce_mul_fp");
|
||||
}
|
||||
|
||||
// Vector reduction add for half float type with ASIMD instructions.
|
||||
void C2_MacroAssembler::neon_reduce_add_fp16(FloatRegister dst, FloatRegister fsrc, FloatRegister vsrc,
|
||||
unsigned vector_length_in_bytes, FloatRegister vtmp) {
|
||||
assert(vector_length_in_bytes == 8 || vector_length_in_bytes == 16, "unsupported");
|
||||
bool isQ = vector_length_in_bytes == 16;
|
||||
|
||||
BLOCK_COMMENT("neon_reduce_add_fp16 {");
|
||||
faddh(dst, fsrc, vsrc);
|
||||
ext(vtmp, T8B, vsrc, vsrc, 2);
|
||||
faddh(dst, dst, vtmp);
|
||||
ext(vtmp, T8B, vsrc, vsrc, 4);
|
||||
faddh(dst, dst, vtmp);
|
||||
ext(vtmp, T8B, vsrc, vsrc, 6);
|
||||
faddh(dst, dst, vtmp);
|
||||
if (isQ) {
|
||||
ext(vtmp, T16B, vsrc, vsrc, 8);
|
||||
faddh(dst, dst, vtmp);
|
||||
ext(vtmp, T16B, vsrc, vsrc, 10);
|
||||
faddh(dst, dst, vtmp);
|
||||
ext(vtmp, T16B, vsrc, vsrc, 12);
|
||||
faddh(dst, dst, vtmp);
|
||||
ext(vtmp, T16B, vsrc, vsrc, 14);
|
||||
faddh(dst, dst, vtmp);
|
||||
}
|
||||
BLOCK_COMMENT("} neon_reduce_add_fp16");
|
||||
}
|
||||
|
||||
// Helper to select logical instruction
|
||||
void C2_MacroAssembler::neon_reduce_logical_helper(int opc, bool is64, Register Rd,
|
||||
Register Rn, Register Rm,
|
||||
@ -2414,17 +2463,17 @@ void C2_MacroAssembler::neon_rearrange_hsd(FloatRegister dst, FloatRegister src,
|
||||
break;
|
||||
case T_LONG:
|
||||
case T_DOUBLE:
|
||||
// Load the iota indices for Long type. The indices are ordered by
|
||||
// type B/S/I/L/F/D, and the offset between two types is 16; Hence
|
||||
// the offset for L is 48.
|
||||
lea(rscratch1,
|
||||
ExternalAddress(StubRoutines::aarch64::vector_iota_indices() + 48));
|
||||
ldrq(tmp, rscratch1);
|
||||
// Check whether the input "shuffle" is the same with iota indices.
|
||||
// Return "src" if true, otherwise swap the two elements of "src".
|
||||
cm(EQ, dst, size2, shuffle, tmp);
|
||||
ext(tmp, size1, src, src, 8);
|
||||
bsl(dst, size1, src, tmp);
|
||||
{
|
||||
int idx = vector_iota_entry_index(T_LONG);
|
||||
lea(rscratch1,
|
||||
ExternalAddress(StubRoutines::aarch64::vector_iota_indices(idx)));
|
||||
ldrq(tmp, rscratch1);
|
||||
// Check whether the input "shuffle" is the same with iota indices.
|
||||
// Return "src" if true, otherwise swap the two elements of "src".
|
||||
cm(EQ, dst, size2, shuffle, tmp);
|
||||
ext(tmp, size1, src, src, 8);
|
||||
bsl(dst, size1, src, tmp);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
assert(false, "unsupported element type");
|
||||
@ -2896,3 +2945,24 @@ void C2_MacroAssembler::sve_cpy(FloatRegister dst, SIMD_RegVariant T,
|
||||
}
|
||||
Assembler::sve_cpy(dst, T, pg, imm8, isMerge);
|
||||
}
|
||||
|
||||
int C2_MacroAssembler::vector_iota_entry_index(BasicType bt) {
|
||||
// The vector iota entries array is ordered by type B/S/I/L/F/D, and
|
||||
// the offset between two types is 16.
|
||||
switch(bt) {
|
||||
case T_BYTE:
|
||||
return 0;
|
||||
case T_SHORT:
|
||||
return 1;
|
||||
case T_INT:
|
||||
return 2;
|
||||
case T_LONG:
|
||||
return 3;
|
||||
case T_FLOAT:
|
||||
return 4;
|
||||
case T_DOUBLE:
|
||||
return 5;
|
||||
default:
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
}
|
||||
|
||||
@ -177,6 +177,9 @@
|
||||
FloatRegister fsrc, FloatRegister vsrc,
|
||||
unsigned vector_length_in_bytes, FloatRegister vtmp);
|
||||
|
||||
void neon_reduce_add_fp16(FloatRegister dst, FloatRegister fsrc, FloatRegister vsrc,
|
||||
unsigned vector_length_in_bytes, FloatRegister vtmp);
|
||||
|
||||
void neon_reduce_logical(int opc, Register dst, BasicType bt, Register isrc,
|
||||
FloatRegister vsrc, unsigned vector_length_in_bytes);
|
||||
|
||||
@ -249,4 +252,5 @@
|
||||
|
||||
void sve_cpy(FloatRegister dst, SIMD_RegVariant T, PRegister pg, int imm8,
|
||||
bool isMerge);
|
||||
int vector_iota_entry_index(BasicType bt);
|
||||
#endif // CPU_AARCH64_C2_MACROASSEMBLER_AARCH64_HPP
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 2026, 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
|
||||
@ -56,7 +56,7 @@ void CardTableBarrierSetAssembler::store_at(MacroAssembler* masm, DecoratorSet d
|
||||
}
|
||||
}
|
||||
|
||||
void CardTableBarrierSetAssembler::store_check(MacroAssembler* masm, Register obj, Address dst, Register tmp1, Register tmp2) {
|
||||
void CardTableBarrierSetAssembler::store_check(MacroAssembler* masm, Register obj, Register tmp1, Register tmp2) {
|
||||
precond(tmp1 != noreg);
|
||||
precond(tmp2 != noreg);
|
||||
assert_different_registers(obj, tmp1, tmp2);
|
||||
@ -114,10 +114,10 @@ void CardTableBarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorS
|
||||
if (needs_post_barrier) {
|
||||
// flatten object address if needed
|
||||
if (!precise || (dst.index() == noreg && dst.offset() == 0)) {
|
||||
store_check(masm, dst.base(), dst, tmp1, tmp2);
|
||||
store_check(masm, dst.base(), tmp1, tmp2);
|
||||
} else {
|
||||
__ lea(tmp3, dst);
|
||||
store_check(masm, tmp3, dst, tmp1, tmp2);
|
||||
store_check(masm, tmp3, tmp1, tmp2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 2026, 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
|
||||
@ -46,7 +46,7 @@ protected:
|
||||
virtual void store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
|
||||
Address dst, Register val, Register tmp1, Register tmp2, Register tmp3);
|
||||
|
||||
void store_check(MacroAssembler* masm, Register obj, Address dst, Register tmp1, Register tmp2);
|
||||
void store_check(MacroAssembler* masm, Register obj, Register tmp1, Register tmp2);
|
||||
};
|
||||
|
||||
#endif // CPU_AARCH64_GC_SHARED_CARDTABLEBARRIERSETASSEMBLER_AARCH64_HPP
|
||||
|
||||
@ -55,6 +55,7 @@
|
||||
#include "runtime/sharedRuntime.hpp"
|
||||
#include "runtime/stubRoutines.hpp"
|
||||
#include "utilities/globalDefinitions.hpp"
|
||||
#include "utilities/integerCast.hpp"
|
||||
#include "utilities/powerOfTwo.hpp"
|
||||
#ifdef COMPILER1
|
||||
#include "c1/c1_LIRAssembler.hpp"
|
||||
@ -2916,7 +2917,11 @@ void MacroAssembler::increment(Address dst, int value)
|
||||
|
||||
// Push lots of registers in the bit set supplied. Don't push sp.
|
||||
// Return the number of words pushed
|
||||
int MacroAssembler::push(unsigned int bitset, Register stack) {
|
||||
int MacroAssembler::push(RegSet regset, Register stack) {
|
||||
if (regset.bits() == 0) {
|
||||
return 0;
|
||||
}
|
||||
auto bitset = integer_cast<unsigned int>(regset.bits());
|
||||
int words_pushed = 0;
|
||||
|
||||
// Scan bitset to accumulate register pairs
|
||||
@ -2946,7 +2951,11 @@ int MacroAssembler::push(unsigned int bitset, Register stack) {
|
||||
return count;
|
||||
}
|
||||
|
||||
int MacroAssembler::pop(unsigned int bitset, Register stack) {
|
||||
int MacroAssembler::pop(RegSet regset, Register stack) {
|
||||
if (regset.bits() == 0) {
|
||||
return 0;
|
||||
}
|
||||
auto bitset = integer_cast<unsigned int>(regset.bits());
|
||||
int words_pushed = 0;
|
||||
|
||||
// Scan bitset to accumulate register pairs
|
||||
@ -2978,7 +2987,11 @@ int MacroAssembler::pop(unsigned int bitset, Register stack) {
|
||||
|
||||
// Push lots of registers in the bit set supplied. Don't push sp.
|
||||
// Return the number of dwords pushed
|
||||
int MacroAssembler::push_fp(unsigned int bitset, Register stack, FpPushPopMode mode) {
|
||||
int MacroAssembler::push_fp(FloatRegSet regset, Register stack, FpPushPopMode mode) {
|
||||
if (regset.bits() == 0) {
|
||||
return 0;
|
||||
}
|
||||
auto bitset = integer_cast<unsigned int>(regset.bits());
|
||||
int words_pushed = 0;
|
||||
bool use_sve = false;
|
||||
int sve_vector_size_in_bytes = 0;
|
||||
@ -3091,7 +3104,11 @@ int MacroAssembler::push_fp(unsigned int bitset, Register stack, FpPushPopMode m
|
||||
}
|
||||
|
||||
// Return the number of dwords popped
|
||||
int MacroAssembler::pop_fp(unsigned int bitset, Register stack, FpPushPopMode mode) {
|
||||
int MacroAssembler::pop_fp(FloatRegSet regset, Register stack, FpPushPopMode mode) {
|
||||
if (regset.bits() == 0) {
|
||||
return 0;
|
||||
}
|
||||
auto bitset = integer_cast<unsigned int>(regset.bits());
|
||||
int words_pushed = 0;
|
||||
bool use_sve = false;
|
||||
int sve_vector_size_in_bytes = 0;
|
||||
@ -3201,7 +3218,11 @@ int MacroAssembler::pop_fp(unsigned int bitset, Register stack, FpPushPopMode mo
|
||||
}
|
||||
|
||||
// Return the number of dwords pushed
|
||||
int MacroAssembler::push_p(unsigned int bitset, Register stack) {
|
||||
int MacroAssembler::push_p(PRegSet regset, Register stack) {
|
||||
if (regset.bits() == 0) {
|
||||
return 0;
|
||||
}
|
||||
auto bitset = integer_cast<unsigned int>(regset.bits());
|
||||
bool use_sve = false;
|
||||
int sve_predicate_size_in_slots = 0;
|
||||
|
||||
@ -3238,7 +3259,11 @@ int MacroAssembler::push_p(unsigned int bitset, Register stack) {
|
||||
}
|
||||
|
||||
// Return the number of dwords popped
|
||||
int MacroAssembler::pop_p(unsigned int bitset, Register stack) {
|
||||
int MacroAssembler::pop_p(PRegSet regset, Register stack) {
|
||||
if (regset.bits() == 0) {
|
||||
return 0;
|
||||
}
|
||||
auto bitset = integer_cast<unsigned int>(regset.bits());
|
||||
bool use_sve = false;
|
||||
int sve_predicate_size_in_slots = 0;
|
||||
|
||||
|
||||
@ -499,29 +499,20 @@ private:
|
||||
void mov_immediate64(Register dst, uint64_t imm64);
|
||||
void mov_immediate32(Register dst, uint32_t imm32);
|
||||
|
||||
int push(unsigned int bitset, Register stack);
|
||||
int pop(unsigned int bitset, Register stack);
|
||||
|
||||
int push_fp(unsigned int bitset, Register stack, FpPushPopMode mode);
|
||||
int pop_fp(unsigned int bitset, Register stack, FpPushPopMode mode);
|
||||
|
||||
int push_p(unsigned int bitset, Register stack);
|
||||
int pop_p(unsigned int bitset, Register stack);
|
||||
|
||||
void mov(Register dst, Address a);
|
||||
|
||||
public:
|
||||
|
||||
void push(RegSet regs, Register stack) { if (regs.bits()) push(regs.bits(), stack); }
|
||||
void pop(RegSet regs, Register stack) { if (regs.bits()) pop(regs.bits(), stack); }
|
||||
int push(RegSet regset, Register stack);
|
||||
int pop(RegSet regset, Register stack);
|
||||
|
||||
void push_fp(FloatRegSet regs, Register stack, FpPushPopMode mode = PushPopFull) { if (regs.bits()) push_fp(regs.bits(), stack, mode); }
|
||||
void pop_fp(FloatRegSet regs, Register stack, FpPushPopMode mode = PushPopFull) { if (regs.bits()) pop_fp(regs.bits(), stack, mode); }
|
||||
int push_fp(FloatRegSet regset, Register stack, FpPushPopMode mode = PushPopFull);
|
||||
int pop_fp(FloatRegSet regset, Register stack, FpPushPopMode mode = PushPopFull);
|
||||
|
||||
static RegSet call_clobbered_gp_registers();
|
||||
|
||||
void push_p(PRegSet regs, Register stack) { if (regs.bits()) push_p(regs.bits(), stack); }
|
||||
void pop_p(PRegSet regs, Register stack) { if (regs.bits()) pop_p(regs.bits(), stack); }
|
||||
int push_p(PRegSet regset, Register stack);
|
||||
int pop_p(PRegSet regset, Register stack);
|
||||
|
||||
// Push and pop everything that might be clobbered by a native
|
||||
// runtime call except rscratch1 and rscratch2. (They are always
|
||||
@ -899,10 +890,6 @@ public:
|
||||
// thread in the default location (rthread)
|
||||
void reset_last_Java_frame(bool clear_fp);
|
||||
|
||||
// Stores
|
||||
void store_check(Register obj); // store check for obj - register is destroyed afterwards
|
||||
void store_check(Register obj, Address dst); // same as above, dst is exact store location (reg. is destroyed)
|
||||
|
||||
void resolve_jobject(Register value, Register tmp1, Register tmp2);
|
||||
void resolve_global_jobject(Register value, Register tmp1, Register tmp2);
|
||||
|
||||
|
||||
@ -97,7 +97,7 @@ protected:
|
||||
#define MACOS_WX_WRITE MACOS_AARCH64_ONLY(os::thread_wx_enable_write())
|
||||
void set_char_at(int offset, char c) { MACOS_WX_WRITE; *addr_at(offset) = (u_char)c; }
|
||||
void set_int_at(int offset, jint i) { MACOS_WX_WRITE; *(jint*)addr_at(offset) = i; }
|
||||
void set_uint_at(int offset, jint i) { MACOS_WX_WRITE; *(juint*)addr_at(offset) = i; }
|
||||
void set_uint_at(int offset, juint i) { MACOS_WX_WRITE; *(juint*)addr_at(offset) = i; }
|
||||
void set_ptr_at(int offset, address ptr) { MACOS_WX_WRITE; *(address*)addr_at(offset) = ptr; }
|
||||
void set_oop_at(int offset, oop o) { MACOS_WX_WRITE; *(oop*)addr_at(offset) = o; }
|
||||
#undef MACOS_WX_WRITE
|
||||
@ -178,13 +178,11 @@ public:
|
||||
address destination() const;
|
||||
|
||||
void set_destination(address dest) {
|
||||
int offset = dest - instruction_address();
|
||||
unsigned int insn = 0b100101 << 26;
|
||||
int64_t offset = dest - instruction_address();
|
||||
juint insn = 0b100101u << 26u;
|
||||
assert((offset & 3) == 0, "should be");
|
||||
offset >>= 2;
|
||||
offset &= (1 << 26) - 1; // mask off insn part
|
||||
insn |= offset;
|
||||
set_int_at(displacement_offset, insn);
|
||||
Instruction_aarch64::spatch(reinterpret_cast<address>(&insn), 25, 0, offset >> 2);
|
||||
set_uint_at(displacement_offset, insn);
|
||||
}
|
||||
|
||||
void verify_alignment() { ; }
|
||||
|
||||
@ -29,32 +29,39 @@
|
||||
#define STUBGEN_PREUNIVERSE_BLOBS_ARCH_DO(do_stub, \
|
||||
do_arch_blob, \
|
||||
do_arch_entry, \
|
||||
do_arch_entry_init) \
|
||||
do_arch_entry_init, \
|
||||
do_arch_entry_array) \
|
||||
do_arch_blob(preuniverse, 0) \
|
||||
|
||||
|
||||
#define STUBGEN_INITIAL_BLOBS_ARCH_DO(do_stub, \
|
||||
do_arch_blob, \
|
||||
do_arch_entry, \
|
||||
do_arch_entry_init) \
|
||||
do_arch_entry_init, \
|
||||
do_arch_entry_array) \
|
||||
do_arch_blob(initial, 10000) \
|
||||
|
||||
|
||||
#define STUBGEN_CONTINUATION_BLOBS_ARCH_DO(do_stub, \
|
||||
do_arch_blob, \
|
||||
do_arch_entry, \
|
||||
do_arch_entry_init) \
|
||||
do_arch_entry_init, \
|
||||
do_arch_entry_array) \
|
||||
do_arch_blob(continuation, 2000) \
|
||||
|
||||
// count needed for declaration of vector_iota_indices stub
|
||||
#define VECTOR_IOTA_COUNT 6
|
||||
|
||||
#define STUBGEN_COMPILER_BLOBS_ARCH_DO(do_stub, \
|
||||
do_arch_blob, \
|
||||
do_arch_entry, \
|
||||
do_arch_entry_init) \
|
||||
do_arch_entry_init, \
|
||||
do_arch_entry_array) \
|
||||
do_arch_blob(compiler, 70000) \
|
||||
do_stub(compiler, vector_iota_indices) \
|
||||
do_arch_entry(aarch64, compiler, vector_iota_indices, \
|
||||
vector_iota_indices, vector_iota_indices) \
|
||||
do_arch_entry_array(aarch64, compiler, vector_iota_indices, \
|
||||
vector_iota_indices, vector_iota_indices, \
|
||||
VECTOR_IOTA_COUNT) \
|
||||
do_stub(compiler, large_array_equals) \
|
||||
do_arch_entry(aarch64, compiler, large_array_equals, \
|
||||
large_array_equals, large_array_equals) \
|
||||
@ -115,7 +122,8 @@
|
||||
#define STUBGEN_FINAL_BLOBS_ARCH_DO(do_stub, \
|
||||
do_arch_blob, \
|
||||
do_arch_entry, \
|
||||
do_arch_entry_init) \
|
||||
do_arch_entry_init, \
|
||||
do_arch_entry_array) \
|
||||
do_arch_blob(final, 20000 ZGC_ONLY(+85000)) \
|
||||
do_stub(final, copy_byte_f) \
|
||||
do_arch_entry(aarch64, final, copy_byte_f, copy_byte_f, \
|
||||
|
||||
@ -819,12 +819,19 @@ class StubGenerator: public StubCodeGenerator {
|
||||
}
|
||||
|
||||
// Generate indices for iota vector.
|
||||
address generate_iota_indices(StubId stub_id) {
|
||||
void generate_iota_indices(StubId stub_id) {
|
||||
GrowableArray<address> entries;
|
||||
int entry_count = StubInfo::entry_count(stub_id);
|
||||
assert(entry_count == 1, "sanity check");
|
||||
address start = load_archive_data(stub_id);
|
||||
assert(entry_count == VECTOR_IOTA_COUNT, "sanity check");
|
||||
address start = load_archive_data(stub_id, &entries);
|
||||
if (start != nullptr) {
|
||||
return start;
|
||||
assert(entries.length() == entry_count - 1,
|
||||
"unexpected entries count %d", entries.length());
|
||||
StubRoutines::aarch64::_vector_iota_indices[0] = start;
|
||||
for (int i = 1; i < VECTOR_IOTA_COUNT; i++) {
|
||||
StubRoutines::aarch64::_vector_iota_indices[i] = entries.at(i - 1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
__ align(CodeEntryAlignment);
|
||||
StubCodeMark mark(this, stub_id);
|
||||
@ -832,26 +839,37 @@ class StubGenerator: public StubCodeGenerator {
|
||||
// B
|
||||
__ emit_data64(0x0706050403020100, relocInfo::none);
|
||||
__ emit_data64(0x0F0E0D0C0B0A0908, relocInfo::none);
|
||||
entries.append(__ pc());
|
||||
// H
|
||||
__ emit_data64(0x0003000200010000, relocInfo::none);
|
||||
__ emit_data64(0x0007000600050004, relocInfo::none);
|
||||
entries.append(__ pc());
|
||||
// S
|
||||
__ emit_data64(0x0000000100000000, relocInfo::none);
|
||||
__ emit_data64(0x0000000300000002, relocInfo::none);
|
||||
entries.append(__ pc());
|
||||
// D
|
||||
__ emit_data64(0x0000000000000000, relocInfo::none);
|
||||
__ emit_data64(0x0000000000000001, relocInfo::none);
|
||||
entries.append(__ pc());
|
||||
// S - FP
|
||||
__ emit_data64(0x3F80000000000000, relocInfo::none); // 0.0f, 1.0f
|
||||
__ emit_data64(0x4040000040000000, relocInfo::none); // 2.0f, 3.0f
|
||||
entries.append(__ pc());
|
||||
// D - FP
|
||||
__ emit_data64(0x0000000000000000, relocInfo::none); // 0.0d
|
||||
__ emit_data64(0x3FF0000000000000, relocInfo::none); // 1.0d
|
||||
|
||||
// record the stub entry and end
|
||||
store_archive_data(stub_id, start, __ pc());
|
||||
store_archive_data(stub_id, start, __ pc(), &entries);
|
||||
|
||||
return start;
|
||||
// install the entry addresses in the entry array
|
||||
assert(entries.length() == entry_count - 1,
|
||||
"unexpected entries count %d", entries.length());
|
||||
StubRoutines::aarch64::_vector_iota_indices[0] = start;
|
||||
for (int i = 1; i < VECTOR_IOTA_COUNT; i++) {
|
||||
StubRoutines::aarch64::_vector_iota_indices[i] = entries.at(i - 1);
|
||||
}
|
||||
}
|
||||
|
||||
// The inner part of zero_words(). This is the bulk operation,
|
||||
@ -12621,7 +12639,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
#if COMPILER2_OR_JVMCI
|
||||
|
||||
if (UseSVE == 0) {
|
||||
StubRoutines::aarch64::_vector_iota_indices = generate_iota_indices(StubId::stubgen_vector_iota_indices_id);
|
||||
generate_iota_indices(StubId::stubgen_vector_iota_indices_id);
|
||||
}
|
||||
|
||||
// array equals stub for large arrays.
|
||||
@ -12807,7 +12825,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
#if INCLUDE_CDS
|
||||
static void init_AOTAddressTable(GrowableArray<address>& external_addresses) {
|
||||
// external data defined in this file
|
||||
#define ADD(addr) external_addresses.append((address)addr);
|
||||
#define ADD(addr) external_addresses.append((address)(addr));
|
||||
ADD(_sha256_round_consts);
|
||||
ADD(_sha512_round_consts);
|
||||
ADD(_sha3_round_consts);
|
||||
|
||||
@ -41,8 +41,12 @@ static void empty_spin_wait() { }
|
||||
#define DEFINE_ARCH_ENTRY_INIT(arch, blob_name, stub_name, field_name, getter_name, init_function) \
|
||||
address StubRoutines:: arch :: STUB_FIELD_NAME(field_name) = CAST_FROM_FN_PTR(address, init_function);
|
||||
|
||||
STUBGEN_ARCH_ENTRIES_DO(DEFINE_ARCH_ENTRY, DEFINE_ARCH_ENTRY_INIT)
|
||||
#define DEFINE_ARCH_ENTRY_ARRAY(arch, blob_name, stub_name, field_name, getter_name, count) \
|
||||
address StubRoutines:: arch :: STUB_FIELD_NAME(field_name) [count];
|
||||
|
||||
STUBGEN_ARCH_ENTRIES_DO(DEFINE_ARCH_ENTRY, DEFINE_ARCH_ENTRY_INIT, DEFINE_ARCH_ENTRY_ARRAY)
|
||||
|
||||
#undef DEFINE_ARCH_ENTRY_ARARAY
|
||||
#undef DEFINE_ARCH_ENTRY_INIT
|
||||
#undef DEFINE_ARCH_ENTRY
|
||||
|
||||
@ -431,10 +435,8 @@ void StubRoutines::init_AOTAddressTable() {
|
||||
AOTCodeCache::publish_external_addresses(external_addresses);
|
||||
}
|
||||
|
||||
|
||||
#define ADD(addr) external_addresses.append((address)addr);
|
||||
|
||||
void StubRoutines::aarch64::init_AOTAddressTable(GrowableArray<address>& external_addresses) {
|
||||
#define ADD(addr) external_addresses.append((address)(addr));
|
||||
ADD(_kyberConsts);
|
||||
ADD(_dilithiumConsts);
|
||||
// this is added in generic code
|
||||
@ -445,7 +447,6 @@ void StubRoutines::aarch64::init_AOTAddressTable(GrowableArray<address>& externa
|
||||
ADD(_dcos_coef);
|
||||
ADD(_two_over_pi);
|
||||
ADD(_pio2);
|
||||
}
|
||||
|
||||
#undef ADD
|
||||
}
|
||||
#endif // INCLUDE_CDS
|
||||
|
||||
@ -60,9 +60,13 @@ class aarch64 {
|
||||
#define DECLARE_ARCH_ENTRY_INIT(arch, blob_name, stub_name, field_name, getter_name, init_function) \
|
||||
DECLARE_ARCH_ENTRY(arch, blob_name, stub_name, field_name, getter_name)
|
||||
|
||||
private:
|
||||
STUBGEN_ARCH_ENTRIES_DO(DECLARE_ARCH_ENTRY, DECLARE_ARCH_ENTRY_INIT)
|
||||
#define DECLARE_ARCH_ENTRY_ARRAY(arch, blob_name, stub_name, field_name, getter_name, count) \
|
||||
static address STUB_FIELD_NAME(field_name) [count];
|
||||
|
||||
private:
|
||||
STUBGEN_ARCH_ENTRIES_DO(DECLARE_ARCH_ENTRY, DECLARE_ARCH_ENTRY_INIT, DECLARE_ARCH_ENTRY_ARRAY)
|
||||
|
||||
#undef DECLARE_ARCH_ENTRY_ARRAY
|
||||
#undef DECLARE_ARCH_ENTRY_INIT
|
||||
#undef DECLARE_ARCH_ENTRY
|
||||
|
||||
@ -78,8 +82,15 @@ private:
|
||||
#define DEFINE_ARCH_ENTRY_GETTER_INIT(arch, blob_name, stub_name, field_name, getter_name, init_function) \
|
||||
DEFINE_ARCH_ENTRY_GETTER(arch, blob_name, stub_name, field_name, getter_name)
|
||||
|
||||
STUBGEN_ARCH_ENTRIES_DO(DEFINE_ARCH_ENTRY_GETTER, DEFINE_ARCH_ENTRY_GETTER_INIT)
|
||||
#define DEFINE_ARCH_ENTRY_GETTER_ARRAY(arch, blob_name, stub_name, field_name, getter_name, count) \
|
||||
static address getter_name(int idx) { \
|
||||
assert(0 <= idx && idx < count, "entry array index out of range"); \
|
||||
return STUB_FIELD_NAME(field_name) [idx]; \
|
||||
}
|
||||
|
||||
STUBGEN_ARCH_ENTRIES_DO(DEFINE_ARCH_ENTRY_GETTER, DEFINE_ARCH_ENTRY_GETTER_INIT, DEFINE_ARCH_ENTRY_GETTER_ARRAY)
|
||||
|
||||
#undef DEFINE_ARCH_ENTRY_GETTER_ARRAY
|
||||
#undef DEFINE_ARCH_ENTRY_GETTER_INIT
|
||||
#undef DEFINE_ARCH_ENTRY_GETTER
|
||||
|
||||
|
||||
@ -437,10 +437,6 @@ void VM_Version::initialize() {
|
||||
FLAG_SET_DEFAULT(UseSHA512Intrinsics, false);
|
||||
}
|
||||
|
||||
if (!(UseSHA1Intrinsics || UseSHA256Intrinsics || UseSHA3Intrinsics || UseSHA512Intrinsics)) {
|
||||
FLAG_SET_DEFAULT(UseSHA, false);
|
||||
}
|
||||
|
||||
if (supports_pmull()) {
|
||||
if (FLAG_IS_DEFAULT(UseGHASHIntrinsics)) {
|
||||
FLAG_SET_DEFAULT(UseGHASHIntrinsics, true);
|
||||
|
||||
@ -29,7 +29,8 @@
|
||||
#define STUBGEN_PREUNIVERSE_BLOBS_ARCH_DO(do_stub, \
|
||||
do_arch_blob, \
|
||||
do_arch_entry, \
|
||||
do_arch_entry_init) \
|
||||
do_arch_entry_init, \
|
||||
do_arch_entry_array) \
|
||||
do_arch_blob(preuniverse, 500) \
|
||||
do_stub(preuniverse, atomic_load_long) \
|
||||
do_arch_entry(Arm, preuniverse, atomic_load_long, \
|
||||
@ -42,7 +43,8 @@
|
||||
#define STUBGEN_INITIAL_BLOBS_ARCH_DO(do_stub, \
|
||||
do_arch_blob, \
|
||||
do_arch_entry, \
|
||||
do_arch_entry_init) \
|
||||
do_arch_entry_init, \
|
||||
do_arch_entry_array) \
|
||||
do_arch_blob(initial, 9000) \
|
||||
do_stub(initial, idiv_irem) \
|
||||
do_arch_entry(Arm, initial, idiv_irem, \
|
||||
@ -51,14 +53,16 @@
|
||||
#define STUBGEN_CONTINUATION_BLOBS_ARCH_DO(do_stub, \
|
||||
do_arch_blob, \
|
||||
do_arch_entry, \
|
||||
do_arch_entry_init) \
|
||||
do_arch_entry_init, \
|
||||
do_arch_entry_array) \
|
||||
do_arch_blob(continuation, 2000) \
|
||||
|
||||
|
||||
#define STUBGEN_COMPILER_BLOBS_ARCH_DO(do_stub, \
|
||||
do_arch_blob, \
|
||||
do_arch_entry, \
|
||||
do_arch_entry_init) \
|
||||
do_arch_entry_init, \
|
||||
do_arch_entry_array) \
|
||||
do_arch_blob(compiler, 22000) \
|
||||
do_stub(compiler, partial_subtype_check) \
|
||||
do_arch_entry(Arm, compiler, partial_subtype_check, \
|
||||
@ -68,7 +72,8 @@
|
||||
#define STUBGEN_FINAL_BLOBS_ARCH_DO(do_stub, \
|
||||
do_arch_blob, \
|
||||
do_arch_entry, \
|
||||
do_arch_entry_init) \
|
||||
do_arch_entry_init, \
|
||||
do_arch_entry_array) \
|
||||
do_arch_blob(final, 22000) \
|
||||
|
||||
|
||||
|
||||
@ -32,7 +32,7 @@
|
||||
#define DEFINE_ARCH_ENTRY_INIT(arch, blob_name, stub_name, field_name, getter_name, init_function) \
|
||||
address StubRoutines:: arch :: STUB_FIELD_NAME(field_name) = CAST_FROM_FN_PTR(address, init_function);
|
||||
|
||||
STUBGEN_ARCH_ENTRIES_DO(DEFINE_ARCH_ENTRY, DEFINE_ARCH_ENTRY_INIT)
|
||||
STUBGEN_ARCH_ENTRIES_DO(DEFINE_ARCH_ENTRY, DEFINE_ARCH_ENTRY_INIT, DEFINE_ARCH_ENTRY_ARRAY)
|
||||
|
||||
#undef DEFINE_ARCH_ENTRY_INIT
|
||||
#undef DEFINE_ARCH_ENTRY
|
||||
|
||||
@ -55,9 +55,13 @@ class Arm {
|
||||
#define DECLARE_ARCH_ENTRY_INIT(arch, blob_name, stub_name, field_name, getter_name, init_function) \
|
||||
DECLARE_ARCH_ENTRY(arch, blob_name, stub_name, field_name, getter_name)
|
||||
|
||||
private:
|
||||
STUBGEN_ARCH_ENTRIES_DO(DECLARE_ARCH_ENTRY, DECLARE_ARCH_ENTRY_INIT)
|
||||
#define DECLARE_ARCH_ENTRY_ARRAY(arch, blob_name, stub_name, field_name, getter_name, count) \
|
||||
static address STUB_FIELD_NAME(field_name) [count] ;
|
||||
|
||||
private:
|
||||
STUBGEN_ARCH_ENTRIES_DO(DECLARE_ARCH_ENTRY, DECLARE_ARCH_ENTRY_INIT, DECLARE_ARCH_ENTRY_ARRAY)
|
||||
|
||||
#undef DECLARE_ARCH_ENTRY_ARRAY
|
||||
#undef DECLARE_ARCH_ENTRY_INIT
|
||||
#undef DECLARE_ARCH_ENTRY
|
||||
|
||||
@ -71,8 +75,12 @@ public:
|
||||
#define DEFINE_ARCH_ENTRY_GETTER_INIT(arch, blob_name, stub_name, field_name, getter_name, init_function) \
|
||||
DEFINE_ARCH_ENTRY_GETTER(arch, blob_name, stub_name, field_name, getter_name)
|
||||
|
||||
STUBGEN_ARCH_ENTRIES_DO(DEFINE_ARCH_ENTRY_GETTER, DEFINE_ARCH_ENTRY_GETTER_INIT)
|
||||
#define DEFINE_ARCH_ENTRY_GETTER_ARRAY(arch, blob_name, stub_name, field_name, getter_name, count) \
|
||||
static address getter_name(int idx) { return STUB_FIELD_NAME(field_name) [idx] ; }
|
||||
|
||||
STUBGEN_ARCH_ENTRIES_DO(DEFINE_ARCH_ENTRY_GETTER, DEFINE_ARCH_ENTRY_GETTER_INIT, DEFINE_ARCH_ENTRY_GETTER_ARRAY)
|
||||
|
||||
#undef DEFINE_ARCH_ENTRY_GETTER_ARRAY
|
||||
#undef DEFINE_ARCH_ENTRY_GETTER_INIT
|
||||
#undef DEFINE_ARCH_ENTRY_GETTER
|
||||
|
||||
|
||||
@ -29,35 +29,40 @@
|
||||
#define STUBGEN_PREUNIVERSE_BLOBS_ARCH_DO(do_stub, \
|
||||
do_arch_blob, \
|
||||
do_arch_entry, \
|
||||
do_arch_entry_init) \
|
||||
do_arch_entry_init, \
|
||||
do_arch_entry_array) \
|
||||
do_arch_blob(preuniverse, 0) \
|
||||
|
||||
|
||||
#define STUBGEN_INITIAL_BLOBS_ARCH_DO(do_stub, \
|
||||
do_arch_blob, \
|
||||
do_arch_entry, \
|
||||
do_arch_entry_init) \
|
||||
do_arch_entry_init, \
|
||||
do_arch_entry_array) \
|
||||
do_arch_blob(initial, 20000) \
|
||||
|
||||
|
||||
#define STUBGEN_CONTINUATION_BLOBS_ARCH_DO(do_stub, \
|
||||
do_arch_blob, \
|
||||
do_arch_entry, \
|
||||
do_arch_entry_init) \
|
||||
do_arch_entry_init, \
|
||||
do_arch_entry_array) \
|
||||
do_arch_blob(continuation, 2000) \
|
||||
|
||||
|
||||
#define STUBGEN_COMPILER_BLOBS_ARCH_DO(do_stub, \
|
||||
do_arch_blob, \
|
||||
do_arch_entry, \
|
||||
do_arch_entry_init) \
|
||||
do_arch_entry_init, \
|
||||
do_arch_entry_array) \
|
||||
do_arch_blob(compiler, 24000) \
|
||||
|
||||
|
||||
#define STUBGEN_FINAL_BLOBS_ARCH_DO(do_stub, \
|
||||
do_arch_blob, \
|
||||
do_arch_entry, \
|
||||
do_arch_entry_init) \
|
||||
do_arch_entry_init, \
|
||||
do_arch_entry_array) \
|
||||
do_arch_blob(final, 24000) \
|
||||
|
||||
|
||||
|
||||
@ -311,11 +311,6 @@ void VM_Version::initialize() {
|
||||
FLAG_SET_DEFAULT(UseSHA3Intrinsics, false);
|
||||
}
|
||||
|
||||
if (!(UseSHA1Intrinsics || UseSHA256Intrinsics || UseSHA512Intrinsics)) {
|
||||
FLAG_SET_DEFAULT(UseSHA, false);
|
||||
}
|
||||
|
||||
|
||||
#ifdef COMPILER2
|
||||
if (FLAG_IS_DEFAULT(UseSquareToLenIntrinsic)) {
|
||||
UseSquareToLenIntrinsic = true;
|
||||
|
||||
@ -49,6 +49,7 @@
|
||||
#include "runtime/sharedRuntime.hpp"
|
||||
#include "runtime/stubRoutines.hpp"
|
||||
#include "utilities/globalDefinitions.hpp"
|
||||
#include "utilities/integerCast.hpp"
|
||||
#include "utilities/powerOfTwo.hpp"
|
||||
#ifdef COMPILER2
|
||||
#include "opto/compile.hpp"
|
||||
@ -1947,14 +1948,12 @@ void MacroAssembler::restore_cpu_control_state_after_jni(Register tmp) {
|
||||
}
|
||||
}
|
||||
|
||||
void MacroAssembler::push_reg(Register Rs)
|
||||
{
|
||||
void MacroAssembler::push_reg(Register Rs) {
|
||||
subi(esp, esp, wordSize);
|
||||
sd(Rs, Address(esp, 0));
|
||||
}
|
||||
|
||||
void MacroAssembler::pop_reg(Register Rd)
|
||||
{
|
||||
void MacroAssembler::pop_reg(Register Rd) {
|
||||
ld(Rd, Address(esp, 0));
|
||||
addi(esp, esp, wordSize);
|
||||
}
|
||||
@ -1973,7 +1972,11 @@ int MacroAssembler::bitset_to_regs(unsigned int bitset, unsigned char* regs) {
|
||||
|
||||
// Push integer registers in the bitset supplied. Don't push sp.
|
||||
// Return the number of words pushed
|
||||
int MacroAssembler::push_reg(unsigned int bitset, Register stack) {
|
||||
int MacroAssembler::push_reg(RegSet regset, Register stack) {
|
||||
if (regset.bits() == 0) {
|
||||
return 0;
|
||||
}
|
||||
auto bitset = integer_cast<unsigned int>(regset.bits());
|
||||
DEBUG_ONLY(int words_pushed = 0;)
|
||||
unsigned char regs[32];
|
||||
int count = bitset_to_regs(bitset, regs);
|
||||
@ -1993,7 +1996,11 @@ int MacroAssembler::push_reg(unsigned int bitset, Register stack) {
|
||||
return count;
|
||||
}
|
||||
|
||||
int MacroAssembler::pop_reg(unsigned int bitset, Register stack) {
|
||||
int MacroAssembler::pop_reg(RegSet regset, Register stack) {
|
||||
if (regset.bits() == 0) {
|
||||
return 0;
|
||||
}
|
||||
auto bitset = integer_cast<unsigned int>(regset.bits());
|
||||
DEBUG_ONLY(int words_popped = 0;)
|
||||
unsigned char regs[32];
|
||||
int count = bitset_to_regs(bitset, regs);
|
||||
@ -2015,7 +2022,11 @@ int MacroAssembler::pop_reg(unsigned int bitset, Register stack) {
|
||||
|
||||
// Push floating-point registers in the bitset supplied.
|
||||
// Return the number of words pushed
|
||||
int MacroAssembler::push_fp(unsigned int bitset, Register stack) {
|
||||
int MacroAssembler::push_fp(FloatRegSet regset, Register stack) {
|
||||
if (regset.bits() == 0) {
|
||||
return 0;
|
||||
}
|
||||
auto bitset = integer_cast<unsigned int>(regset.bits());
|
||||
DEBUG_ONLY(int words_pushed = 0;)
|
||||
unsigned char regs[32];
|
||||
int count = bitset_to_regs(bitset, regs);
|
||||
@ -2035,7 +2046,11 @@ int MacroAssembler::push_fp(unsigned int bitset, Register stack) {
|
||||
return count;
|
||||
}
|
||||
|
||||
int MacroAssembler::pop_fp(unsigned int bitset, Register stack) {
|
||||
int MacroAssembler::pop_fp(FloatRegSet regset, Register stack) {
|
||||
if (regset.bits() == 0) {
|
||||
return 0;
|
||||
}
|
||||
auto bitset = integer_cast<unsigned int>(regset.bits());
|
||||
DEBUG_ONLY(int words_popped = 0;)
|
||||
unsigned char regs[32];
|
||||
int count = bitset_to_regs(bitset, regs);
|
||||
@ -2721,7 +2736,11 @@ void MacroAssembler::kernel_crc32(Register crc, Register buf, Register len,
|
||||
#ifdef COMPILER2
|
||||
// Push vector registers in the bitset supplied.
|
||||
// Return the number of words pushed
|
||||
int MacroAssembler::push_v(unsigned int bitset, Register stack) {
|
||||
int MacroAssembler::push_v(VectorRegSet regset, Register stack) {
|
||||
if (regset.bits() == 0) {
|
||||
return 0;
|
||||
}
|
||||
auto bitset = integer_cast<unsigned int>(regset.bits());
|
||||
int vector_size_in_bytes = Matcher::scalable_vector_reg_size(T_BYTE);
|
||||
|
||||
// Scan bitset to accumulate register pairs
|
||||
@ -2736,7 +2755,11 @@ int MacroAssembler::push_v(unsigned int bitset, Register stack) {
|
||||
return count * vector_size_in_bytes / wordSize;
|
||||
}
|
||||
|
||||
int MacroAssembler::pop_v(unsigned int bitset, Register stack) {
|
||||
int MacroAssembler::pop_v(VectorRegSet regset, Register stack) {
|
||||
if (regset.bits() == 0) {
|
||||
return 0;
|
||||
}
|
||||
auto bitset = integer_cast<unsigned int>(regset.bits());
|
||||
int vector_size_in_bytes = Matcher::scalable_vector_reg_size(T_BYTE);
|
||||
|
||||
// Scan bitset to accumulate register pairs
|
||||
|
||||
@ -818,15 +818,6 @@ class MacroAssembler: public Assembler {
|
||||
void double_bgt(FloatRegister Rs1, FloatRegister Rs2, Label &l, bool is_far = false, bool is_unordered = false);
|
||||
|
||||
private:
|
||||
int push_reg(unsigned int bitset, Register stack);
|
||||
int pop_reg(unsigned int bitset, Register stack);
|
||||
int push_fp(unsigned int bitset, Register stack);
|
||||
int pop_fp(unsigned int bitset, Register stack);
|
||||
#ifdef COMPILER2
|
||||
int push_v(unsigned int bitset, Register stack);
|
||||
int pop_v(unsigned int bitset, Register stack);
|
||||
#endif // COMPILER2
|
||||
|
||||
// The signed 20-bit upper imm can materialize at most negative 0xF...F80000000, two G.
|
||||
// The following signed 12-bit imm can at max subtract 0x800, two K, from that previously loaded two G.
|
||||
bool is_valid_32bit_offset(int64_t x) {
|
||||
@ -844,15 +835,19 @@ private:
|
||||
}
|
||||
|
||||
public:
|
||||
// Stack push and pop individual 64 bit registers
|
||||
void push_reg(Register Rs);
|
||||
void pop_reg(Register Rd);
|
||||
void push_reg(RegSet regs, Register stack) { if (regs.bits()) push_reg(regs.bits(), stack); }
|
||||
void pop_reg(RegSet regs, Register stack) { if (regs.bits()) pop_reg(regs.bits(), stack); }
|
||||
void push_fp(FloatRegSet regs, Register stack) { if (regs.bits()) push_fp(regs.bits(), stack); }
|
||||
void pop_fp(FloatRegSet regs, Register stack) { if (regs.bits()) pop_fp(regs.bits(), stack); }
|
||||
|
||||
int push_reg(RegSet regset, Register stack);
|
||||
int pop_reg(RegSet regset, Register stack);
|
||||
|
||||
int push_fp(FloatRegSet regset, Register stack);
|
||||
int pop_fp(FloatRegSet regset, Register stack);
|
||||
|
||||
#ifdef COMPILER2
|
||||
void push_v(VectorRegSet regs, Register stack) { if (regs.bits()) push_v(regs.bits(), stack); }
|
||||
void pop_v(VectorRegSet regs, Register stack) { if (regs.bits()) pop_v(regs.bits(), stack); }
|
||||
int push_v(VectorRegSet regset, Register stack);
|
||||
int pop_v(VectorRegSet regset, Register stack);
|
||||
#endif // COMPILER2
|
||||
|
||||
// Push and pop everything that might be clobbered by a native
|
||||
|
||||
@ -29,28 +29,32 @@
|
||||
#define STUBGEN_PREUNIVERSE_BLOBS_ARCH_DO(do_stub, \
|
||||
do_arch_blob, \
|
||||
do_arch_entry, \
|
||||
do_arch_entry_init) \
|
||||
do_arch_entry_init, \
|
||||
do_arch_entry_array) \
|
||||
do_arch_blob(preuniverse, 0) \
|
||||
|
||||
|
||||
#define STUBGEN_INITIAL_BLOBS_ARCH_DO(do_stub, \
|
||||
do_arch_blob, \
|
||||
do_arch_entry, \
|
||||
do_arch_entry_init) \
|
||||
do_arch_entry_init, \
|
||||
do_arch_entry_array) \
|
||||
do_arch_blob(initial, 10000) \
|
||||
|
||||
|
||||
#define STUBGEN_CONTINUATION_BLOBS_ARCH_DO(do_stub, \
|
||||
do_arch_blob, \
|
||||
do_arch_entry, \
|
||||
do_arch_entry_init) \
|
||||
do_arch_entry_init, \
|
||||
do_arch_entry_array) \
|
||||
do_arch_blob(continuation, 2000) \
|
||||
|
||||
|
||||
#define STUBGEN_COMPILER_BLOBS_ARCH_DO(do_stub, \
|
||||
do_arch_blob, \
|
||||
do_arch_entry, \
|
||||
do_arch_entry_init) \
|
||||
do_arch_entry_init, \
|
||||
do_arch_entry_array) \
|
||||
do_arch_blob(compiler, 45000) \
|
||||
do_stub(compiler, compare_long_string_LL) \
|
||||
do_arch_entry(riscv, compiler, compare_long_string_LL, \
|
||||
@ -81,7 +85,8 @@
|
||||
#define STUBGEN_FINAL_BLOBS_ARCH_DO(do_stub, \
|
||||
do_arch_blob, \
|
||||
do_arch_entry, \
|
||||
do_arch_entry_init) \
|
||||
do_arch_entry_init, \
|
||||
do_arch_entry_array) \
|
||||
do_arch_blob(final, 20000 ZGC_ONLY(+10000)) \
|
||||
do_stub(final, copy_byte_f) \
|
||||
do_arch_entry(riscv, final, copy_byte_f, copy_byte_f, \
|
||||
|
||||
@ -42,8 +42,12 @@
|
||||
#define DEFINE_ARCH_ENTRY_INIT(arch, blob_name, stub_name, field_name, getter_name, init_function) \
|
||||
address StubRoutines:: arch :: STUB_FIELD_NAME(field_name) = CAST_FROM_FN_PTR(address, init_function);
|
||||
|
||||
STUBGEN_ARCH_ENTRIES_DO(DEFINE_ARCH_ENTRY, DEFINE_ARCH_ENTRY_INIT)
|
||||
#define DEFINE_ARCH_ENTRY_ARRAY(arch, blob_name, stub_name, field_name, getter_name, count) \
|
||||
address StubRoutines:: arch :: STUB_FIELD_NAME(field_name) [count] ;
|
||||
|
||||
STUBGEN_ARCH_ENTRIES_DO(DEFINE_ARCH_ENTRY, DEFINE_ARCH_ENTRY_INIT, DEFINE_ARCH_ENTRY_ARRAY)
|
||||
|
||||
#undef DEFINE_ARCH_ENTRY_ARRAY
|
||||
#undef DEFINE_ARCH_ENTRY_INIT
|
||||
#undef DEFINE_ARCH_ENTRY
|
||||
|
||||
|
||||
@ -61,9 +61,13 @@ class riscv {
|
||||
#define DECLARE_ARCH_ENTRY_INIT(arch, blob_name, stub_name, field_name, getter_name, init_function) \
|
||||
DECLARE_ARCH_ENTRY(arch, blob_name, stub_name, field_name, getter_name)
|
||||
|
||||
private:
|
||||
STUBGEN_ARCH_ENTRIES_DO(DECLARE_ARCH_ENTRY, DECLARE_ARCH_ENTRY_INIT)
|
||||
#define DECLARE_ARCH_ENTRY_ARRAY(arch, blob_name, stub_name, field_name, getter_name, count) \
|
||||
static address STUB_FIELD_NAME(field_name) [count] ;
|
||||
|
||||
private:
|
||||
STUBGEN_ARCH_ENTRIES_DO(DECLARE_ARCH_ENTRY, DECLARE_ARCH_ENTRY_INIT, DECLARE_ARCH_ENTRY_ARRAY)
|
||||
|
||||
#undef DECLARE_ARCH_ENTRY_ARRAY
|
||||
#undef DECLARE_ARCH_ENTRY_INIT
|
||||
#undef DECLARE_ARCH_ENTRY
|
||||
|
||||
@ -79,8 +83,12 @@ private:
|
||||
#define DEFINE_ARCH_ENTRY_GETTER_INIT(arch, blob_name, stub_name, field_name, getter_name, init_function) \
|
||||
DEFINE_ARCH_ENTRY_GETTER(arch, blob_name, stub_name, field_name, getter_name)
|
||||
|
||||
STUBGEN_ARCH_ENTRIES_DO(DEFINE_ARCH_ENTRY_GETTER, DEFINE_ARCH_ENTRY_GETTER_INIT)
|
||||
#define DEFINE_ARCH_ENTRY_GETTER_ARRAY(arch, blob_name, stub_name, field_name, getter_name, count) \
|
||||
static address getter_name(int idx) { return STUB_FIELD_NAME(field_name) [idx] ; }
|
||||
|
||||
STUBGEN_ARCH_ENTRIES_DO(DEFINE_ARCH_ENTRY_GETTER, DEFINE_ARCH_ENTRY_GETTER_INIT, DEFINE_ARCH_ENTRY_GETTER_ARRAY)
|
||||
|
||||
#undef DEFINE_ARCH_ENTRY_GETTER_ARRAY
|
||||
#undef DEFINE_ARCH_ENTRY_GETTER_INIT
|
||||
#undef DEFINE_ARCH_ENTRY_GETTER
|
||||
|
||||
|
||||
@ -420,11 +420,6 @@ void VM_Version::c2_initialize() {
|
||||
FLAG_SET_DEFAULT(UseSHA3Intrinsics, false);
|
||||
}
|
||||
|
||||
// UseSHA
|
||||
if (!(UseSHA1Intrinsics || UseSHA256Intrinsics || UseSHA3Intrinsics || UseSHA512Intrinsics)) {
|
||||
FLAG_SET_DEFAULT(UseSHA, false);
|
||||
}
|
||||
|
||||
// AES
|
||||
if (UseZvkn) {
|
||||
UseAES = UseAES || FLAG_IS_DEFAULT(UseAES);
|
||||
|
||||
@ -29,28 +29,32 @@
|
||||
#define STUBGEN_PREUNIVERSE_BLOBS_ARCH_DO(do_stub, \
|
||||
do_arch_blob, \
|
||||
do_arch_entry, \
|
||||
do_arch_entry_init) \
|
||||
do_arch_entry_init, \
|
||||
do_arch_entry_array) \
|
||||
do_arch_blob(preuniverse, 0) \
|
||||
|
||||
|
||||
#define STUBGEN_INITIAL_BLOBS_ARCH_DO(do_stub, \
|
||||
do_arch_blob, \
|
||||
do_arch_entry, \
|
||||
do_arch_entry_init) \
|
||||
do_arch_entry_init, \
|
||||
do_arch_entry_array) \
|
||||
do_arch_blob(initial, 20000) \
|
||||
|
||||
|
||||
#define STUBGEN_CONTINUATION_BLOBS_ARCH_DO(do_stub, \
|
||||
do_arch_blob, \
|
||||
do_arch_entry, \
|
||||
do_arch_entry_init) \
|
||||
do_arch_entry_init, \
|
||||
do_arch_entry_array) \
|
||||
do_arch_blob(continuation, 2000) \
|
||||
|
||||
|
||||
#define STUBGEN_COMPILER_BLOBS_ARCH_DO(do_stub, \
|
||||
do_arch_blob, \
|
||||
do_arch_entry, \
|
||||
do_arch_entry_init) \
|
||||
do_arch_entry_init, \
|
||||
do_arch_entry_array) \
|
||||
do_arch_blob(compiler, 20000 ) \
|
||||
do_stub(compiler, partial_subtype_check) \
|
||||
do_arch_entry(zarch, compiler, partial_subtype_check, \
|
||||
@ -60,7 +64,8 @@
|
||||
#define STUBGEN_FINAL_BLOBS_ARCH_DO(do_stub, \
|
||||
do_arch_blob, \
|
||||
do_arch_entry, \
|
||||
do_arch_entry_init) \
|
||||
do_arch_entry_init, \
|
||||
do_arch_entry_array) \
|
||||
do_arch_blob(final, 20000) \
|
||||
|
||||
|
||||
|
||||
@ -40,8 +40,12 @@
|
||||
#define DEFINE_ARCH_ENTRY_INIT(arch, blob_name, stub_name, field_name, getter_name, init_function) \
|
||||
address StubRoutines:: arch :: STUB_FIELD_NAME(field_name) = CAST_FROM_FN_PTR(address, init_function);
|
||||
|
||||
STUBGEN_ARCH_ENTRIES_DO(DEFINE_ARCH_ENTRY, DEFINE_ARCH_ENTRY_INIT)
|
||||
#define DEFINE_ARCH_ENTRY_ARRAY(arch, blob_name, stub_name, field_name, getter_name, count) \
|
||||
address StubRoutines:: arch :: STUB_FIELD_NAME(field_name) [idx] ;
|
||||
|
||||
STUBGEN_ARCH_ENTRIES_DO(DEFINE_ARCH_ENTRY, DEFINE_ARCH_ENTRY_INIT, DEFINE_ARCH_ENTRY_ARRAY)
|
||||
|
||||
#undef DEFINE_ARCH_ENTRY_ARRAY
|
||||
#undef DEFINE_ARCH_ENTRY_INIT
|
||||
#undef DEFINE_ARCH_ENTRY
|
||||
|
||||
|
||||
@ -81,9 +81,13 @@ class zarch {
|
||||
#define DECLARE_ARCH_ENTRY_INIT(arch, blob_name, stub_name, field_name, getter_name, init_function) \
|
||||
DECLARE_ARCH_ENTRY(arch, blob_name, stub_name, field_name, getter_name)
|
||||
|
||||
private:
|
||||
STUBGEN_ARCH_ENTRIES_DO(DECLARE_ARCH_ENTRY, DECLARE_ARCH_ENTRY_INIT)
|
||||
#define DECLARE_ARCH_ENTRY_ARRAY(arch, blob_name, stub_name, field_name, getter_name, count) \
|
||||
static address STUB_FIELD_NAME(field_name) [count] ;
|
||||
|
||||
private:
|
||||
STUBGEN_ARCH_ENTRIES_DO(DECLARE_ARCH_ENTRY, DECLARE_ARCH_ENTRY_INIT, DECLARE_ARCH_ENTRY_ARRAY)
|
||||
|
||||
#undef DECLARE_ARCH_ENTRY_ARRAY
|
||||
#undef DECLARE_ARCH_ENTRY_INIT
|
||||
#undef DECLARE_ARCH_ENTRY
|
||||
|
||||
@ -108,8 +112,12 @@ private:
|
||||
#define DEFINE_ARCH_ENTRY_GETTER_INIT(arch, blob_name, stub_name, field_name, getter_name, init_function) \
|
||||
DEFINE_ARCH_ENTRY_GETTER(arch, blob_name, stub_name, field_name, getter_name)
|
||||
|
||||
STUBGEN_ARCH_ENTRIES_DO(DEFINE_ARCH_ENTRY_GETTER, DEFINE_ARCH_ENTRY_GETTER_INIT)
|
||||
#define DEFINE_ARCH_ENTRY_GETTER_ARRAY(arch, blob_name, stub_name, field_name, getter_name, count) \
|
||||
static address getter_name(int idx) { return STUB_FIELD_NAME(field_name) [idx] ; }
|
||||
|
||||
STUBGEN_ARCH_ENTRIES_DO(DEFINE_ARCH_ENTRY_GETTER, DEFINE_ARCH_ENTRY_GETTER_INIT, DEFINE_ARCH_ENTRY_GETTER_ARRAY)
|
||||
|
||||
#undef DEFINE_ARCH_ENTRY_GETTER_ARRAY
|
||||
#undef DEFINE_ARCH_ENTRY_GETTER_INIT
|
||||
#undef DEFINE_ARCH_ENTRY_GETTER
|
||||
|
||||
|
||||
@ -289,10 +289,6 @@ void VM_Version::initialize() {
|
||||
FLAG_SET_DEFAULT(UseSHA3Intrinsics, false);
|
||||
}
|
||||
|
||||
if (!(UseSHA1Intrinsics || UseSHA256Intrinsics || UseSHA512Intrinsics)) {
|
||||
FLAG_SET_DEFAULT(UseSHA, false);
|
||||
}
|
||||
|
||||
if (UseSecondarySupersTable && VM_Version::get_model_index() < 5 /* z196/z11 */) {
|
||||
if (!FLAG_IS_DEFAULT(UseSecondarySupersTable)) {
|
||||
warning("UseSecondarySupersTable requires z196 or later.");
|
||||
|
||||
@ -74,7 +74,7 @@ static jlong *double_signflip_pool = double_quadword(&fp_signmask_pool[4*2], (jl
|
||||
#if INCLUDE_CDS
|
||||
// publish external addresses defined in this file
|
||||
void LIR_Assembler::init_AOTAddressTable(GrowableArray<address>& external_addresses) {
|
||||
#define ADD(addr) external_addresses.append((address)addr);
|
||||
#define ADD(addr) external_addresses.append((address)(addr));
|
||||
ADD(float_signmask_pool);
|
||||
ADD(double_signmask_pool);
|
||||
ADD(float_signflip_pool);
|
||||
|
||||
@ -1706,12 +1706,8 @@ void C2_MacroAssembler::load_constant_vector(BasicType bt, XMMRegister dst, Inte
|
||||
}
|
||||
|
||||
void C2_MacroAssembler::load_iota_indices(XMMRegister dst, int vlen_in_bytes, BasicType bt) {
|
||||
// The iota indices are ordered by type B/S/I/L/F/D, and the offset between two types is 64.
|
||||
int offset = exact_log2(type2aelembytes(bt)) << 6;
|
||||
if (is_floating_point_type(bt)) {
|
||||
offset += 128;
|
||||
}
|
||||
ExternalAddress addr(StubRoutines::x86::vector_iota_indices() + offset);
|
||||
int entry_idx = vector_iota_entry_index(bt);
|
||||
ExternalAddress addr(StubRoutines::x86::vector_iota_indices(entry_idx));
|
||||
load_vector(T_BYTE, dst, addr, vlen_in_bytes);
|
||||
}
|
||||
|
||||
@ -7164,3 +7160,24 @@ void C2_MacroAssembler::vminmax_fp16_avx10_2(int opcode, XMMRegister dst, XMMReg
|
||||
evminmaxph(dst, ktmp, src1, src2, true, AVX10_2_MINMAX_MIN_COMPARE_SIGN, vlen_enc);
|
||||
}
|
||||
}
|
||||
|
||||
int C2_MacroAssembler::vector_iota_entry_index(BasicType bt) {
|
||||
// The vector iota entries array is ordered by type B/S/I/L/F/D, and
|
||||
// the offset between two types is 16.
|
||||
switch(bt) {
|
||||
case T_BYTE:
|
||||
return 0;
|
||||
case T_SHORT:
|
||||
return 1;
|
||||
case T_INT:
|
||||
return 2;
|
||||
case T_LONG:
|
||||
return 3;
|
||||
case T_FLOAT:
|
||||
return 4;
|
||||
case T_DOUBLE:
|
||||
return 5;
|
||||
default:
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
}
|
||||
|
||||
@ -596,4 +596,5 @@ public:
|
||||
|
||||
void reconstruct_frame_pointer(Register rtmp);
|
||||
|
||||
int vector_iota_entry_index(BasicType bt);
|
||||
#endif // CPU_X86_C2_MACROASSEMBLER_X86_HPP
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 2026, 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
|
||||
@ -130,7 +130,7 @@ __ BIND(L_loop);
|
||||
__ BIND(L_done);
|
||||
}
|
||||
|
||||
void CardTableBarrierSetAssembler::store_check(MacroAssembler* masm, Register obj, Address dst, Register rscratch) {
|
||||
void CardTableBarrierSetAssembler::store_check(MacroAssembler* masm, Register obj, Register rscratch) {
|
||||
// Does a store check for the oop in register obj. The content of
|
||||
// register obj is destroyed afterwards.
|
||||
CardTableBarrierSet* ctbs = CardTableBarrierSet::barrier_set();
|
||||
@ -192,10 +192,10 @@ void CardTableBarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorS
|
||||
if (needs_post_barrier) {
|
||||
// flatten object address if needed
|
||||
if (!precise || (dst.index() == noreg && dst.disp() == 0)) {
|
||||
store_check(masm, dst.base(), dst, tmp2);
|
||||
store_check(masm, dst.base(), tmp2);
|
||||
} else {
|
||||
__ lea(tmp1, dst);
|
||||
store_check(masm, tmp1, dst, tmp2);
|
||||
store_check(masm, tmp1, tmp2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -33,7 +33,7 @@ protected:
|
||||
virtual void gen_write_ref_array_pre_barrier(MacroAssembler* masm, DecoratorSet decorators,
|
||||
Register addr, Register count) {}
|
||||
|
||||
void store_check(MacroAssembler* masm, Register obj, Address dst, Register rscratch);
|
||||
void store_check(MacroAssembler* masm, Register obj, Register rscratch);
|
||||
|
||||
virtual void gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators, Register addr, Register count, Register tmp);
|
||||
|
||||
|
||||
@ -29,14 +29,16 @@
|
||||
#define STUBGEN_PREUNIVERSE_BLOBS_ARCH_DO(do_stub, \
|
||||
do_arch_blob, \
|
||||
do_arch_entry, \
|
||||
do_arch_entry_init) \
|
||||
do_arch_entry_init, \
|
||||
do_arch_entry_array) \
|
||||
do_arch_blob(preuniverse, 500) \
|
||||
|
||||
|
||||
#define STUBGEN_INITIAL_BLOBS_ARCH_DO(do_stub, \
|
||||
do_arch_blob, \
|
||||
do_arch_entry, \
|
||||
do_arch_entry_init) \
|
||||
do_arch_entry_init, \
|
||||
do_arch_entry_array) \
|
||||
do_arch_blob(initial, PRODUCT_ONLY(20000) NOT_PRODUCT(21000) WINDOWS_ONLY(+1000)) \
|
||||
do_stub(initial, verify_mxcsr) \
|
||||
do_arch_entry(x86, initial, verify_mxcsr, verify_mxcsr_entry, \
|
||||
@ -65,14 +67,18 @@
|
||||
#define STUBGEN_CONTINUATION_BLOBS_ARCH_DO(do_stub, \
|
||||
do_arch_blob, \
|
||||
do_arch_entry, \
|
||||
do_arch_entry_init) \
|
||||
do_arch_entry_init, \
|
||||
do_arch_entry_array) \
|
||||
do_arch_blob(continuation, 3000) \
|
||||
|
||||
// count needed for declaration of vector_iota_indices stub
|
||||
#define VECTOR_IOTA_COUNT 6
|
||||
|
||||
#define STUBGEN_COMPILER_BLOBS_ARCH_DO(do_stub, \
|
||||
do_arch_blob, \
|
||||
do_arch_entry, \
|
||||
do_arch_entry_init) \
|
||||
do_arch_entry_init, \
|
||||
do_arch_entry_array) \
|
||||
do_arch_blob(compiler, 120000 WINDOWS_ONLY(+2000)) \
|
||||
do_stub(compiler, vector_float_sign_mask) \
|
||||
do_arch_entry(x86, compiler, vector_float_sign_mask, \
|
||||
@ -126,8 +132,9 @@
|
||||
do_arch_entry(x86, compiler, vector_long_sign_mask, \
|
||||
vector_long_sign_mask, vector_long_sign_mask) \
|
||||
do_stub(compiler, vector_iota_indices) \
|
||||
do_arch_entry(x86, compiler, vector_iota_indices, \
|
||||
vector_iota_indices, vector_iota_indices) \
|
||||
do_arch_entry_array(x86, compiler, vector_iota_indices, \
|
||||
vector_iota_indices, vector_iota_indices, \
|
||||
VECTOR_IOTA_COUNT) \
|
||||
do_stub(compiler, vector_count_leading_zeros_lut) \
|
||||
do_arch_entry(x86, compiler, vector_count_leading_zeros_lut, \
|
||||
vector_count_leading_zeros_lut, \
|
||||
@ -250,7 +257,8 @@
|
||||
#define STUBGEN_FINAL_BLOBS_ARCH_DO(do_stub, \
|
||||
do_arch_blob, \
|
||||
do_arch_entry, \
|
||||
do_arch_entry_init) \
|
||||
do_arch_entry_init, \
|
||||
do_arch_entry_array) \
|
||||
do_arch_blob(final, 33000 \
|
||||
WINDOWS_ONLY(+22000) ZGC_ONLY(+20000)) \
|
||||
|
||||
|
||||
@ -893,13 +893,20 @@ address StubGenerator::generate_popcount_avx_lut() {
|
||||
return start;
|
||||
}
|
||||
|
||||
address StubGenerator::generate_iota_indices() {
|
||||
void StubGenerator::generate_iota_indices() {
|
||||
StubId stub_id = StubId::stubgen_vector_iota_indices_id;
|
||||
GrowableArray<address> entries;
|
||||
int entry_count = StubInfo::entry_count(stub_id);
|
||||
assert(entry_count == 1, "sanity check");
|
||||
address start = load_archive_data(stub_id);
|
||||
assert(entry_count == VECTOR_IOTA_COUNT, "sanity check");
|
||||
address start = load_archive_data(stub_id, &entries);
|
||||
if (start != nullptr) {
|
||||
return start;
|
||||
assert(entries.length() == VECTOR_IOTA_COUNT - 1,
|
||||
"unexpected extra entry count %d", entries.length());
|
||||
StubRoutines::x86::_vector_iota_indices[0] = start;
|
||||
for (int i = 1; i < VECTOR_IOTA_COUNT; i++) {
|
||||
StubRoutines::x86::_vector_iota_indices[i] = entries.at(i - 1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
__ align(CodeEntryAlignment);
|
||||
StubCodeMark mark(this, stub_id);
|
||||
@ -913,6 +920,7 @@ address StubGenerator::generate_iota_indices() {
|
||||
__ emit_data64(0x2F2E2D2C2B2A2928, relocInfo::none);
|
||||
__ emit_data64(0x3736353433323130, relocInfo::none);
|
||||
__ emit_data64(0x3F3E3D3C3B3A3938, relocInfo::none);
|
||||
entries.append(__ pc());
|
||||
// W
|
||||
__ emit_data64(0x0003000200010000, relocInfo::none);
|
||||
__ emit_data64(0x0007000600050004, relocInfo::none);
|
||||
@ -922,6 +930,7 @@ address StubGenerator::generate_iota_indices() {
|
||||
__ emit_data64(0x0017001600150014, relocInfo::none);
|
||||
__ emit_data64(0x001B001A00190018, relocInfo::none);
|
||||
__ emit_data64(0x001F001E001D001C, relocInfo::none);
|
||||
entries.append(__ pc());
|
||||
// D
|
||||
__ emit_data64(0x0000000100000000, relocInfo::none);
|
||||
__ emit_data64(0x0000000300000002, relocInfo::none);
|
||||
@ -931,6 +940,7 @@ address StubGenerator::generate_iota_indices() {
|
||||
__ emit_data64(0x0000000B0000000A, relocInfo::none);
|
||||
__ emit_data64(0x0000000D0000000C, relocInfo::none);
|
||||
__ emit_data64(0x0000000F0000000E, relocInfo::none);
|
||||
entries.append(__ pc());
|
||||
// Q
|
||||
__ emit_data64(0x0000000000000000, relocInfo::none);
|
||||
__ emit_data64(0x0000000000000001, relocInfo::none);
|
||||
@ -940,6 +950,7 @@ address StubGenerator::generate_iota_indices() {
|
||||
__ emit_data64(0x0000000000000005, relocInfo::none);
|
||||
__ emit_data64(0x0000000000000006, relocInfo::none);
|
||||
__ emit_data64(0x0000000000000007, relocInfo::none);
|
||||
entries.append(__ pc());
|
||||
// D - FP
|
||||
__ emit_data64(0x3F80000000000000, relocInfo::none); // 0.0f, 1.0f
|
||||
__ emit_data64(0x4040000040000000, relocInfo::none); // 2.0f, 3.0f
|
||||
@ -949,6 +960,7 @@ address StubGenerator::generate_iota_indices() {
|
||||
__ emit_data64(0x4130000041200000, relocInfo::none); // 10.0f, 11.0f
|
||||
__ emit_data64(0x4150000041400000, relocInfo::none); // 12.0f, 13.0f
|
||||
__ emit_data64(0x4170000041600000, relocInfo::none); // 14.0f, 15.0f
|
||||
entries.append(__ pc());
|
||||
// Q - FP
|
||||
__ emit_data64(0x0000000000000000, relocInfo::none); // 0.0d
|
||||
__ emit_data64(0x3FF0000000000000, relocInfo::none); // 1.0d
|
||||
@ -960,9 +972,15 @@ address StubGenerator::generate_iota_indices() {
|
||||
__ emit_data64(0x401c000000000000, relocInfo::none); // 7.0d
|
||||
|
||||
// record the stub entry and end
|
||||
store_archive_data(stub_id, start, __ pc());
|
||||
store_archive_data(stub_id, start, __ pc(), &entries);
|
||||
|
||||
return start;
|
||||
// install the entry addresses in the entry array
|
||||
assert(entries.length() == entry_count - 1,
|
||||
"unexpected entries count %d", entries.length());
|
||||
StubRoutines::x86::_vector_iota_indices[0] = start;
|
||||
for (int i = 1; i < VECTOR_IOTA_COUNT; i++) {
|
||||
StubRoutines::x86::_vector_iota_indices[i] = entries.at(i - 1);
|
||||
}
|
||||
}
|
||||
|
||||
address StubGenerator::generate_vector_reverse_bit_lut() {
|
||||
@ -4837,7 +4855,7 @@ void StubGenerator::generate_compiler_stubs() {
|
||||
StubRoutines::x86::_vector_short_shuffle_mask = generate_vector_mask(StubId::stubgen_vector_short_shuffle_mask_id, 0x0100010001000100);
|
||||
StubRoutines::x86::_vector_long_shuffle_mask = generate_vector_mask(StubId::stubgen_vector_long_shuffle_mask_id, 0x0000000100000000);
|
||||
StubRoutines::x86::_vector_long_sign_mask = generate_vector_mask(StubId::stubgen_vector_long_sign_mask_id, 0x8000000000000000);
|
||||
StubRoutines::x86::_vector_iota_indices = generate_iota_indices();
|
||||
generate_iota_indices();
|
||||
StubRoutines::x86::_vector_count_leading_zeros_lut = generate_count_leading_zeros_lut();
|
||||
StubRoutines::x86::_vector_reverse_bit_lut = generate_vector_reverse_bit_lut();
|
||||
StubRoutines::x86::_vector_reverse_byte_perm_mask_long = generate_vector_reverse_byte_perm_mask_long();
|
||||
|
||||
@ -84,7 +84,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
|
||||
address generate_count_leading_zeros_lut();
|
||||
address generate_popcount_avx_lut();
|
||||
address generate_iota_indices();
|
||||
void generate_iota_indices();
|
||||
address generate_vector_reverse_bit_lut();
|
||||
|
||||
address generate_vector_reverse_byte_perm_mask_long();
|
||||
|
||||
@ -247,8 +247,9 @@ void StubGenerator::init_AOTAddressTable_constants(GrowableArray<address>& exter
|
||||
ADD(_SC_2);
|
||||
ADD(_SC_3);
|
||||
ADD(_SC_4);
|
||||
ADD(_PI_4);
|
||||
ADD(((address)_PI_4+8));
|
||||
// Use value which was already cast to (address): StubGenerator::PI_4;
|
||||
ADD(PI_4);
|
||||
ADD(PI_4 + 8);
|
||||
ADD(_PI32INV);
|
||||
ADD(_NEG_ZERO);
|
||||
ADD(_P_1);
|
||||
|
||||
@ -397,13 +397,14 @@ address StubGenerator::generate_libmExp() {
|
||||
|
||||
#if INCLUDE_CDS
|
||||
void StubGenerator::init_AOTAddressTable_exp(GrowableArray<address>& external_addresses) {
|
||||
#define ADD(addr) external_addresses.append((address)addr);
|
||||
ADD(_cv);
|
||||
ADD(((address)_cv+16));
|
||||
ADD(((address)_cv+32));
|
||||
ADD(((address)_cv+48));
|
||||
ADD(((address)_cv+64));
|
||||
ADD(((address)_cv+80));
|
||||
#define ADD(addr) external_addresses.append((address)(addr));
|
||||
address cv = (address)_cv;
|
||||
ADD(cv);
|
||||
ADD(cv + 16);
|
||||
ADD(cv + 32);
|
||||
ADD(cv + 48);
|
||||
ADD(cv + 64);
|
||||
ADD(cv + 80);
|
||||
ADD(_mmask);
|
||||
ADD(_bias);
|
||||
ADD(_Tbl_addr);
|
||||
|
||||
@ -537,7 +537,7 @@ address StubGenerator::generate_libmFmod() {
|
||||
|
||||
#if INCLUDE_CDS
|
||||
void StubGenerator::init_AOTAddressTable_fmod(GrowableArray<address>& external_addresses) {
|
||||
#define ADD(addr) external_addresses.append((address)addr);
|
||||
#define ADD(addr) external_addresses.append((address)(addr));
|
||||
ADD(CONST_NaN);
|
||||
ADD(CONST_1p260);
|
||||
ADD(CONST_MAX);
|
||||
|
||||
@ -558,7 +558,7 @@ void StubGenerator::generateHtbl_eight_blocks(Register htbl) {
|
||||
|
||||
#if INCLUDE_CDS
|
||||
void StubGenerator::init_AOTAddressTable_ghash(GrowableArray<address>& external_addresses) {
|
||||
#define ADD(addr) external_addresses.append((address)addr);
|
||||
#define ADD(addr) external_addresses.append((address)(addr));
|
||||
ADD(GHASH_SHUFFLE_MASK);
|
||||
ADD(GHASH_LONG_SWAP_MASK);
|
||||
ADD(GHASH_BYTE_SWAP_MASK);
|
||||
|
||||
@ -729,22 +729,28 @@ address StubGenerator::generate_libmLog10() {
|
||||
|
||||
#if INCLUDE_CDS
|
||||
void StubGenerator::init_AOTAddressTable_log(GrowableArray<address>& external_addresses) {
|
||||
#define ADD(addr) external_addresses.append((address)addr);
|
||||
#define ADD(addr) external_addresses.append((address)(addr));
|
||||
address log2 = (address)_log2;
|
||||
address coeff = (address)_coeff;
|
||||
address LOG10_E = (address)_LOG10_E;
|
||||
address log2_log10 = (address)_log2_log10;
|
||||
address coeff_log10 = (address)_coeff_log10;
|
||||
|
||||
ADD(_L_tbl);
|
||||
ADD(_log2);
|
||||
ADD(((address)_log2+8));
|
||||
ADD(_coeff);
|
||||
ADD(((address)_coeff+16));
|
||||
ADD(((address)_coeff+32));
|
||||
ADD(log2);
|
||||
ADD(log2 + 8);
|
||||
ADD(coeff);
|
||||
ADD(coeff + 16);
|
||||
ADD(coeff + 32);
|
||||
ADD(_HIGHSIGMASK_log10);
|
||||
ADD(_LOG10_E);
|
||||
ADD(((address)_LOG10_E+8));
|
||||
ADD(LOG10_E);
|
||||
ADD(LOG10_E + 8);
|
||||
ADD(_L_tbl_log10);
|
||||
ADD(_log2_log10);
|
||||
ADD(((address)_log2_log10+8));
|
||||
ADD(_coeff_log10);
|
||||
ADD(((address)_coeff_log10+16));
|
||||
ADD(((address)_coeff_log10+32));
|
||||
ADD(log2_log10);
|
||||
ADD(log2_log10 + 8);
|
||||
ADD(coeff_log10);
|
||||
ADD(coeff_log10 + 16);
|
||||
ADD(coeff_log10 + 32);
|
||||
#undef ADD
|
||||
}
|
||||
#endif // INCLUDE_CDS
|
||||
|
||||
@ -1709,7 +1709,7 @@ void StubGenerator::poly1305_msg_mul_reduce_vec4_avx2(
|
||||
|
||||
#if INCLUDE_CDS
|
||||
void StubGenerator::init_AOTAddressTable_poly1305(GrowableArray<address>& external_addresses) {
|
||||
#define ADD(addr) external_addresses.append((address)addr);
|
||||
#define ADD(addr) external_addresses.append((address)(addr));
|
||||
ADD(POLY1305_PAD_MSG);
|
||||
ADD(POLY1305_MASK42);
|
||||
ADD(POLY1305_MASK44);
|
||||
|
||||
@ -788,7 +788,7 @@ address StubGenerator::generate_intpoly_assign() {
|
||||
|
||||
#if INCLUDE_CDS
|
||||
void StubGenerator::init_AOTAddressTable_poly_mont(GrowableArray<address>& external_addresses) {
|
||||
#define ADD(addr) external_addresses.append((address)addr);
|
||||
#define ADD(addr) external_addresses.append((address)(addr));
|
||||
// use accessors to retrieve all correct addresses
|
||||
ADD(shift_1L());
|
||||
ADD(shift_1R());
|
||||
|
||||
@ -1875,25 +1875,30 @@ address StubGenerator::generate_libmPow() {
|
||||
|
||||
#if INCLUDE_CDS
|
||||
void StubGenerator::init_AOTAddressTable_pow(GrowableArray<address>& external_addresses) {
|
||||
#define ADD(addr) external_addresses.append((address)addr);
|
||||
#define ADD(addr) external_addresses.append((address)(addr));
|
||||
address HIGHMASK_Y = (address)_HIGHMASK_Y;
|
||||
address e_coeff = (address)_e_coeff;
|
||||
address coeff_h = (address)_coeff_h;
|
||||
address coeff_pow = (address)_coeff_pow;
|
||||
|
||||
ADD(_HIGHSIGMASK);
|
||||
ADD(_LOG2_E);
|
||||
ADD(_HIGHMASK_Y);
|
||||
ADD((address)_HIGHMASK_Y+8);
|
||||
ADD(HIGHMASK_Y);
|
||||
ADD(HIGHMASK_Y + 8);
|
||||
ADD(_T_exp);
|
||||
ADD(_e_coeff);
|
||||
ADD((address)_e_coeff+16);
|
||||
ADD((address)_e_coeff+32);
|
||||
ADD(_coeff_h);
|
||||
ADD((address)_coeff_h+8);
|
||||
ADD(e_coeff);
|
||||
ADD(e_coeff + 16);
|
||||
ADD(e_coeff + 32);
|
||||
ADD(coeff_h);
|
||||
ADD(coeff_h + 8);
|
||||
ADD(_HIGHMASK_LOG_X);
|
||||
ADD(_HALFMASK);
|
||||
ADD(_coeff_pow);
|
||||
ADD((address)_coeff_pow+16);
|
||||
ADD((address)_coeff_pow+32);
|
||||
ADD((address)_coeff_pow+48);
|
||||
ADD((address)_coeff_pow+64);
|
||||
ADD((address)_coeff_pow+80);
|
||||
ADD(coeff_pow);
|
||||
ADD(coeff_pow + 16);
|
||||
ADD(coeff_pow + 32);
|
||||
ADD(coeff_pow + 48);
|
||||
ADD(coeff_pow + 64);
|
||||
ADD(coeff_pow + 80);
|
||||
ADD(_L_tbl_pow);
|
||||
ADD(_log2_pow);
|
||||
ADD(_DOUBLE2);
|
||||
|
||||
@ -530,7 +530,7 @@ void StubGenerator::generate_sha3_stubs() {
|
||||
|
||||
#if INCLUDE_CDS
|
||||
void StubGenerator::init_AOTAddressTable_sha3(GrowableArray<address>& external_addresses) {
|
||||
#define ADD(addr) external_addresses.append((address)addr);
|
||||
#define ADD(addr) external_addresses.append((address)(addr));
|
||||
ADD(round_constsAddr());
|
||||
ADD(permsAndRotsAddr());
|
||||
#undef ADD
|
||||
|
||||
@ -661,7 +661,7 @@ address StubGenerator::generate_libmSin() {
|
||||
|
||||
#if INCLUDE_CDS
|
||||
void StubGenerator::init_AOTAddressTable_sin(GrowableArray<address>& external_addresses) {
|
||||
#define ADD(addr) external_addresses.append((address)addr);
|
||||
#define ADD(addr) external_addresses.append((address)(addr));
|
||||
ADD(_ALL_ONES);
|
||||
#undef ADD
|
||||
}
|
||||
|
||||
@ -535,21 +535,25 @@ address StubGenerator::generate_libmSinh() {
|
||||
|
||||
#if INCLUDE_CDS
|
||||
void StubGenerator::init_AOTAddressTable_sinh(GrowableArray<address>& external_addresses) {
|
||||
#define ADD(addr) external_addresses.append((address)addr);
|
||||
ADD(_L2E);
|
||||
ADD(_L2E + 8);
|
||||
#define ADD(addr) external_addresses.append((address)(addr));
|
||||
address L2E = (address)_L2E;
|
||||
address cv = (address)_cv;
|
||||
address pv = (address)_pv;
|
||||
|
||||
ADD(L2E);
|
||||
ADD(L2E + 8);
|
||||
ADD(_HALFMASK);
|
||||
ADD(_Shifter);
|
||||
ADD(_cv);
|
||||
ADD(_cv + 16);
|
||||
ADD(_cv + 32);
|
||||
ADD(_cv + 48);
|
||||
ADD(_cv + 64);
|
||||
ADD(cv);
|
||||
ADD(cv + 16);
|
||||
ADD(cv + 32);
|
||||
ADD(cv + 48);
|
||||
ADD(cv + 64);
|
||||
ADD(_T2f);
|
||||
ADD(_T2_neg_f);
|
||||
ADD(_pv);
|
||||
ADD(_pv + 16);
|
||||
ADD(_pv + 32);
|
||||
ADD(pv);
|
||||
ADD(pv + 16);
|
||||
ADD(pv + 32);
|
||||
ADD(_MASK3);
|
||||
#undef ADD
|
||||
}
|
||||
|
||||
@ -1041,7 +1041,9 @@ address StubGenerator::generate_libmTan() {
|
||||
|
||||
#if INCLUDE_CDS
|
||||
void StubGenerator::init_AOTAddressTable_tan(GrowableArray<address>& external_addresses) {
|
||||
#define ADD(addr) external_addresses.append((address)addr);
|
||||
#define ADD(addr) external_addresses.append((address)(addr));
|
||||
address PI_4_tan = (address)_PI_4_tan;
|
||||
|
||||
ADD(_MUL16);
|
||||
ADD(_sign_mask_tan);
|
||||
ADD(_PI32INV_tan);
|
||||
@ -1055,8 +1057,8 @@ void StubGenerator::init_AOTAddressTable_tan(GrowableArray<address>& external_ad
|
||||
ADD(_Q_7_tan);
|
||||
ADD(_Q_5_tan);
|
||||
ADD(_Q_3_tan);
|
||||
ADD(_PI_4_tan);
|
||||
ADD(((address)_PI_4_tan+8));
|
||||
ADD(PI_4_tan);
|
||||
ADD(PI_4_tan + 8);
|
||||
ADD(_QQ_2_tan);
|
||||
#undef ADD
|
||||
}
|
||||
|
||||
@ -511,20 +511,24 @@ address StubGenerator::generate_libmTanh() {
|
||||
|
||||
#if INCLUDE_CDS
|
||||
void StubGenerator::init_AOTAddressTable_tanh(GrowableArray<address>& external_addresses) {
|
||||
#define ADD(addr) external_addresses.append((address)addr);
|
||||
ADD(_L2E);
|
||||
ADD(_L2E + 8);
|
||||
#define ADD(addr) external_addresses.append((address)(addr));
|
||||
address L2E = (address)_L2E;
|
||||
address cv = (address)_cv;
|
||||
address pv = (address)_pv;
|
||||
|
||||
ADD(L2E);
|
||||
ADD(L2E + 8);
|
||||
ADD(_HALFMASK);
|
||||
ADD(_ONEMASK);
|
||||
ADD(_TWOMASK);
|
||||
ADD(_Shifter);
|
||||
ADD(_cv);
|
||||
ADD(_cv + 16);
|
||||
ADD(_cv + 32);
|
||||
ADD(cv);
|
||||
ADD(cv + 16);
|
||||
ADD(cv + 32);
|
||||
ADD(_T2_neg_f);
|
||||
ADD(_pv);
|
||||
ADD(_pv + 16);
|
||||
ADD(_pv + 32);
|
||||
ADD(pv);
|
||||
ADD(pv + 16);
|
||||
ADD(pv + 32);
|
||||
ADD(_MASK3);
|
||||
ADD(_RMASK);
|
||||
#undef ADD
|
||||
|
||||
@ -44,8 +44,12 @@
|
||||
#define DEFINE_ARCH_ENTRY_INIT(arch, blob_name, stub_name, field_name, getter_name, init_function) \
|
||||
address StubRoutines:: arch :: STUB_FIELD_NAME(field_name) = CAST_FROM_FN_PTR(address, init_function);
|
||||
|
||||
STUBGEN_ARCH_ENTRIES_DO(DEFINE_ARCH_ENTRY, DEFINE_ARCH_ENTRY_INIT)
|
||||
#define DEFINE_ARCH_ENTRY_ARRAY(arch, blob_name, stub_name, field_name, getter_name, count) \
|
||||
address StubRoutines:: arch :: STUB_FIELD_NAME(field_name) [count];
|
||||
|
||||
STUBGEN_ARCH_ENTRIES_DO(DEFINE_ARCH_ENTRY, DEFINE_ARCH_ENTRY_INIT, DEFINE_ARCH_ENTRY_ARRAY)
|
||||
|
||||
#undef DEFINE_ARCH_ENTRY_ARRAY
|
||||
#undef DEFINE_ARCH_ENTRY_INIT
|
||||
#undef DEFINE_ARCH_ENTRY
|
||||
|
||||
@ -435,7 +439,7 @@ void StubRoutines::init_AOTAddressTable() {
|
||||
// publish addresses of external data defined in this file which may
|
||||
// be referenced from stub or code
|
||||
void StubRoutines::x86::init_AOTAddressTable(GrowableArray<address>& external_addresses) {
|
||||
#define ADD(addr) external_addresses.append((address)addr);
|
||||
#define ADD(addr) external_addresses.append((address)(addr));
|
||||
ADD(&_mxcsr_std);
|
||||
ADD(&_mxcsr_rz);
|
||||
ADD(crc_by128_masks_addr());
|
||||
|
||||
@ -55,9 +55,13 @@ class x86 {
|
||||
#define DECLARE_ARCH_ENTRY_INIT(arch, blob_name, stub_name, field_name, getter_name, init_function) \
|
||||
DECLARE_ARCH_ENTRY(arch, blob_name, stub_name, field_name, getter_name)
|
||||
|
||||
private:
|
||||
STUBGEN_ARCH_ENTRIES_DO(DECLARE_ARCH_ENTRY, DECLARE_ARCH_ENTRY_INIT)
|
||||
#define DECLARE_ARCH_ENTRY_ARRAY(arch, blob_name, stub_name, field_name, getter_name, count) \
|
||||
static address STUB_FIELD_NAME(field_name) [count] ;
|
||||
|
||||
private:
|
||||
STUBGEN_ARCH_ENTRIES_DO(DECLARE_ARCH_ENTRY, DECLARE_ARCH_ENTRY_INIT, DECLARE_ARCH_ENTRY_ARRAY)
|
||||
|
||||
#undef DECLARE_ARCH_ENTRY_ARRAY
|
||||
#undef DECLARE_ARCH_ENTRY_INIT
|
||||
#undef DECLARE_ARCH_ENTRY
|
||||
|
||||
@ -70,9 +74,13 @@ private:
|
||||
#define DEFINE_ARCH_ENTRY_GETTER_INIT(arch, blob_name, stub_name, field_name, getter_name, init_function) \
|
||||
DEFINE_ARCH_ENTRY_GETTER(arch, blob_name, stub_name, field_name, getter_name)
|
||||
|
||||
public:
|
||||
STUBGEN_ARCH_ENTRIES_DO(DEFINE_ARCH_ENTRY_GETTER, DEFINE_ARCH_ENTRY_GETTER_INIT)
|
||||
#define DEFINE_ARCH_ENTRY_GETTER_ARRAY(arch, blob_name, stub_name, field_name, getter_name, count) \
|
||||
static address getter_name(int idx) { return STUB_FIELD_NAME(field_name) [idx]; }
|
||||
|
||||
public:
|
||||
STUBGEN_ARCH_ENTRIES_DO(DEFINE_ARCH_ENTRY_GETTER, DEFINE_ARCH_ENTRY_GETTER_INIT, DEFINE_ARCH_ENTRY_GETTER_ARRAY)
|
||||
|
||||
#undef DEFINE_ARCH_ENTRY_GETTER_ARRAY
|
||||
#undef DEFINE_ARCH_ENTRY_GETTER_INIT
|
||||
#undef DEFINE_ARCH_GETTER_ENTRY
|
||||
|
||||
|
||||
@ -1187,7 +1187,7 @@ void VM_Version::get_processor_features() {
|
||||
}
|
||||
if (!UseAESIntrinsics) {
|
||||
if (UseAESCTRIntrinsics) {
|
||||
if (FLAG_IS_DEFAULT(UseAESCTRIntrinsics)) {
|
||||
if (!FLAG_IS_DEFAULT(UseAESCTRIntrinsics)) {
|
||||
warning("AES-CTR intrinsics require UseAESIntrinsics flag to be enabled. Intrinsics will be disabled.");
|
||||
}
|
||||
FLAG_SET_DEFAULT(UseAESCTRIntrinsics, false);
|
||||
@ -1373,10 +1373,6 @@ void VM_Version::get_processor_features() {
|
||||
FLAG_SET_DEFAULT(UseSHA3Intrinsics, false);
|
||||
}
|
||||
|
||||
if (!(UseSHA1Intrinsics || UseSHA256Intrinsics || UseSHA512Intrinsics || UseSHA3Intrinsics)) {
|
||||
FLAG_SET_DEFAULT(UseSHA, false);
|
||||
}
|
||||
|
||||
#if COMPILER2_OR_JVMCI
|
||||
int max_vector_size = 0;
|
||||
if (UseAVX == 0 || !os_supports_avx_vectors()) {
|
||||
|
||||
@ -29,35 +29,40 @@
|
||||
#define STUBGEN_PREUNIVERSE_BLOBS_ARCH_DO(do_stub, \
|
||||
do_arch_blob, \
|
||||
do_arch_entry, \
|
||||
do_arch_entry_init) \
|
||||
do_arch_entry_init, \
|
||||
do_arch_entry_array) \
|
||||
do_arch_blob(preuniverse, 0) \
|
||||
|
||||
|
||||
#define STUBGEN_INITIAL_BLOBS_ARCH_DO(do_stub, \
|
||||
do_arch_blob, \
|
||||
do_arch_entry, \
|
||||
do_arch_entry_init) \
|
||||
do_arch_entry_init, \
|
||||
do_arch_entry_array) \
|
||||
do_arch_blob(initial, 0) \
|
||||
|
||||
|
||||
#define STUBGEN_CONTINUATION_BLOBS_ARCH_DO(do_stub, \
|
||||
do_arch_blob, \
|
||||
do_arch_entry, \
|
||||
do_arch_entry_init) \
|
||||
do_arch_entry_init, \
|
||||
do_arch_entry_array) \
|
||||
do_arch_blob(continuation, 0) \
|
||||
|
||||
|
||||
#define STUBGEN_COMPILER_BLOBS_ARCH_DO(do_stub, \
|
||||
do_arch_blob, \
|
||||
do_arch_entry, \
|
||||
do_arch_entry_init) \
|
||||
do_arch_entry_init, \
|
||||
do_arch_entry_array) \
|
||||
do_arch_blob(compiler, 0) \
|
||||
|
||||
|
||||
#define STUBGEN_FINAL_BLOBS_ARCH_DO(do_stub, \
|
||||
do_arch_blob, \
|
||||
do_arch_entry, \
|
||||
do_arch_entry_init) \
|
||||
do_arch_entry_init, \
|
||||
do_arch_entry_array) \
|
||||
do_arch_blob(final, 0) \
|
||||
|
||||
|
||||
|
||||
@ -40,6 +40,8 @@
|
||||
// Inlined from <linux/magic.h> for portability.
|
||||
#ifndef CGROUP2_SUPER_MAGIC
|
||||
# define CGROUP2_SUPER_MAGIC 0x63677270
|
||||
#else
|
||||
STATIC_ASSERT(CGROUP2_SUPER_MAGIC == 0x63677270);
|
||||
#endif
|
||||
|
||||
// controller names have to match the *_IDX indices
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2026, 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
|
||||
@ -4233,11 +4233,13 @@ int MatchRule::is_expensive() const {
|
||||
strcmp(opType,"PopulateIndex")==0 ||
|
||||
strcmp(opType,"AddReductionVI")==0 ||
|
||||
strcmp(opType,"AddReductionVL")==0 ||
|
||||
strcmp(opType,"AddReductionVHF")==0 ||
|
||||
strcmp(opType,"AddReductionVF")==0 ||
|
||||
strcmp(opType,"AddReductionVD")==0 ||
|
||||
strcmp(opType,"MulReductionVI")==0 ||
|
||||
strcmp(opType,"MulReductionVL")==0 ||
|
||||
strcmp(opType,"MulReductionVF")==0 ||
|
||||
strcmp(opType,"MulReductionVHF")==0 ||
|
||||
strcmp(opType,"MulReductionVD")==0 ||
|
||||
strcmp(opType,"MinReductionV")==0 ||
|
||||
strcmp(opType,"MaxReductionV")==0 ||
|
||||
@ -4348,9 +4350,9 @@ bool MatchRule::is_vector() const {
|
||||
"MaxV", "MinV", "MinVHF", "MaxVHF", "UMinV", "UMaxV",
|
||||
"CompressV", "ExpandV", "CompressM", "CompressBitsV", "ExpandBitsV",
|
||||
"AddReductionVI", "AddReductionVL",
|
||||
"AddReductionVF", "AddReductionVD",
|
||||
"AddReductionVHF", "AddReductionVF", "AddReductionVD",
|
||||
"MulReductionVI", "MulReductionVL",
|
||||
"MulReductionVF", "MulReductionVD",
|
||||
"MulReductionVHF", "MulReductionVF", "MulReductionVD",
|
||||
"MaxReductionV", "MinReductionV",
|
||||
"AndReductionV", "OrReductionV", "XorReductionV",
|
||||
"MulAddVS2VI", "MacroLogicV",
|
||||
|
||||
@ -858,6 +858,13 @@ csize_t CodeBuffer::figure_expanded_capacities(CodeSection* which_cs,
|
||||
}
|
||||
|
||||
void CodeBuffer::expand(CodeSection* which_cs, csize_t amount) {
|
||||
#ifdef ASSERT
|
||||
// The code below copies contents across temp buffers. The following
|
||||
// sizes relate to buffer contents, and should not be changed by buffer
|
||||
// expansion.
|
||||
int old_total_skipped = total_skipped_instructions_size();
|
||||
#endif
|
||||
|
||||
#ifndef PRODUCT
|
||||
if (PrintNMethods && (WizardMode || Verbose)) {
|
||||
tty->print("expanding CodeBuffer:");
|
||||
@ -916,6 +923,7 @@ void CodeBuffer::expand(CodeSection* which_cs, csize_t amount) {
|
||||
assert(cb_sect->capacity() >= new_capacity[n], "big enough");
|
||||
address cb_start = cb_sect->start();
|
||||
cb_sect->set_end(cb_start + this_sect->size());
|
||||
cb_sect->register_skipped(this_sect->_skipped_instructions_size);
|
||||
if (this_sect->mark() == nullptr) {
|
||||
cb_sect->clear_mark();
|
||||
} else {
|
||||
@ -952,6 +960,9 @@ void CodeBuffer::expand(CodeSection* which_cs, csize_t amount) {
|
||||
this->print_on(tty);
|
||||
}
|
||||
#endif //PRODUCT
|
||||
|
||||
assert(old_total_skipped == total_skipped_instructions_size(),
|
||||
"Should match: %d == %d", old_total_skipped, total_skipped_instructions_size());
|
||||
}
|
||||
|
||||
void CodeBuffer::adjust_internal_address(address from, address to) {
|
||||
|
||||
@ -1,76 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SHARE_AOT_AOTGROWABLEARRAY_HPP
|
||||
#define SHARE_AOT_AOTGROWABLEARRAY_HPP
|
||||
|
||||
#include <memory/metaspaceClosureType.hpp>
|
||||
#include <utilities/growableArray.hpp>
|
||||
|
||||
class AOTGrowableArrayHelper {
|
||||
public:
|
||||
static void deallocate(void* mem);
|
||||
};
|
||||
|
||||
// An AOTGrowableArray<T> provides the same functionality as a GrowableArray<T> that
|
||||
// uses the C heap allocator. In addition, AOTGrowableArray<T> can be iterated with
|
||||
// MetaspaceClosure. This type should be used for growable arrays that need to be
|
||||
// stored in the AOT cache. See ModuleEntry::_reads for an example.
|
||||
template <typename E>
|
||||
class AOTGrowableArray : public GrowableArrayWithAllocator<E, AOTGrowableArray<E>> {
|
||||
friend class VMStructs;
|
||||
friend class GrowableArrayWithAllocator<E, AOTGrowableArray>;
|
||||
|
||||
static E* allocate(int max, MemTag mem_tag) {
|
||||
return (E*)GrowableArrayCHeapAllocator::allocate(max, sizeof(E), mem_tag);
|
||||
}
|
||||
|
||||
E* allocate() {
|
||||
return allocate(this->_capacity, mtClass);
|
||||
}
|
||||
|
||||
void deallocate(E* mem) {
|
||||
#if INCLUDE_CDS
|
||||
AOTGrowableArrayHelper::deallocate(mem);
|
||||
#else
|
||||
GrowableArrayCHeapAllocator::deallocate(mem);
|
||||
#endif
|
||||
}
|
||||
|
||||
public:
|
||||
AOTGrowableArray(int initial_capacity, MemTag mem_tag) :
|
||||
GrowableArrayWithAllocator<E, AOTGrowableArray>(
|
||||
allocate(initial_capacity, mem_tag),
|
||||
initial_capacity) {}
|
||||
|
||||
AOTGrowableArray() : AOTGrowableArray(0, mtClassShared) {}
|
||||
|
||||
// methods required by MetaspaceClosure
|
||||
void metaspace_pointers_do(MetaspaceClosure* it);
|
||||
int size_in_heapwords() const { return (int)heap_word_size(sizeof(*this)); }
|
||||
MetaspaceClosureType type() const { return MetaspaceClosureType::GrowableArrayType; }
|
||||
static bool is_read_only_by_default() { return false; }
|
||||
};
|
||||
|
||||
#endif // SHARE_AOT_AOTGROWABLEARRAY_HPP
|
||||
@ -22,7 +22,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "cds/aotGrowableArray.hpp"
|
||||
#include "cds/aotMetaspace.hpp"
|
||||
#include "cds/archiveBuilder.hpp"
|
||||
#include "cds/archiveUtils.hpp"
|
||||
@ -41,6 +40,7 @@
|
||||
#include "oops/typeArrayKlass.hpp"
|
||||
#include "runtime/arguments.hpp"
|
||||
#include "utilities/globalDefinitions.hpp"
|
||||
#include "utilities/growableArray.hpp"
|
||||
|
||||
// Objects of the Metadata types (such as Klass and ConstantPool) have C++ vtables.
|
||||
// (In GCC this is the field <Type>::_vptr, i.e., first word in the object.)
|
||||
@ -58,10 +58,10 @@
|
||||
|
||||
#ifndef PRODUCT
|
||||
|
||||
// AOTGrowableArray has a vtable only when in non-product builds (due to
|
||||
// GrowableArray has a vtable only when in non-product builds (due to
|
||||
// the virtual printing functions in AnyObj).
|
||||
|
||||
using GrowableArray_ModuleEntry_ptr = AOTGrowableArray<ModuleEntry*>;
|
||||
using GrowableArray_ModuleEntry_ptr = GrowableArray<ModuleEntry*>;
|
||||
|
||||
#define DEBUG_CPP_VTABLE_TYPES_DO(f) \
|
||||
f(GrowableArray_ModuleEntry_ptr) \
|
||||
|
||||
@ -22,8 +22,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SHARE_CDS_LAMBDAPROXYCLASSINFO_HPP
|
||||
#define SHARE_CDS_LAMBDAPROXYCLASSINFO_HPP
|
||||
#ifndef SHARE_CDS_LAMBDAPROXYCLASSDICTIONARY_HPP
|
||||
#define SHARE_CDS_LAMBDAPROXYCLASSDICTIONARY_HPP
|
||||
|
||||
#include "cds/aotCompressedPointers.hpp"
|
||||
#include "cds/aotMetaspace.hpp"
|
||||
@ -331,4 +331,4 @@ public:
|
||||
static void print_statistics(outputStream* st, bool is_static_archive);
|
||||
};
|
||||
|
||||
#endif // SHARE_CDS_LAMBDAPROXYCLASSINFO_HPP
|
||||
#endif // SHARE_CDS_LAMBDAPROXYCLASSDICTIONARY_HPP
|
||||
|
||||
@ -537,8 +537,8 @@ void ciMethodData::clear_escape_info() {
|
||||
if (mdo != nullptr) {
|
||||
mdo->clear_escape_info();
|
||||
ArgInfoData *aid = arg_info();
|
||||
int arg_count = (aid == nullptr) ? 0 : aid->number_of_args();
|
||||
for (int i = 0; i < arg_count; i++) {
|
||||
int arg_size = (aid == nullptr) ? 0 : aid->size_of_args();
|
||||
for (int i = 0; i < arg_size; i++) {
|
||||
set_arg_modified(i, 0);
|
||||
}
|
||||
}
|
||||
@ -554,8 +554,8 @@ void ciMethodData::update_escape_info() {
|
||||
mdo->set_arg_local(_arg_local);
|
||||
mdo->set_arg_stack(_arg_stack);
|
||||
mdo->set_arg_returned(_arg_returned);
|
||||
int arg_count = mdo->method()->size_of_parameters();
|
||||
for (int i = 0; i < arg_count; i++) {
|
||||
int arg_size = mdo->method()->size_of_parameters();
|
||||
for (int i = 0; i < arg_size; i++) {
|
||||
mdo->set_arg_modified(i, arg_modified(i));
|
||||
}
|
||||
}
|
||||
@ -652,7 +652,7 @@ void ciMethodData::set_arg_modified(int arg, uint val) {
|
||||
ArgInfoData *aid = arg_info();
|
||||
if (aid == nullptr)
|
||||
return;
|
||||
assert(arg >= 0 && arg < aid->number_of_args(), "valid argument number");
|
||||
assert(arg >= 0 && arg < aid->size_of_args(), "valid argument number");
|
||||
aid->set_arg_modified(arg, val);
|
||||
}
|
||||
|
||||
@ -672,7 +672,7 @@ uint ciMethodData::arg_modified(int arg) const {
|
||||
ArgInfoData *aid = arg_info();
|
||||
if (aid == nullptr)
|
||||
return 0;
|
||||
assert(arg >= 0 && arg < aid->number_of_args(), "valid argument number");
|
||||
assert(arg >= 0 && arg < aid->size_of_args(), "valid argument number");
|
||||
return aid->arg_modified(arg);
|
||||
}
|
||||
|
||||
|
||||
@ -307,14 +307,9 @@ public:
|
||||
template <class ITER>
|
||||
inline void iterate(ITER* iter) const { iterate([&](V v) { iter->do_value(v); }); }
|
||||
|
||||
template<typename Function>
|
||||
inline void iterate(const Function& function) const { // lambda enabled API
|
||||
iterate(const_cast<Function&>(function));
|
||||
}
|
||||
|
||||
// Iterate through the values in the table, stopping when the lambda returns false.
|
||||
template<typename Function>
|
||||
inline void iterate(Function& function) const { // lambda enabled API
|
||||
inline void iterate(Function function) const { // lambda enabled API
|
||||
for (u4 i = 0; i < _bucket_count; i++) {
|
||||
u4 bucket_info = _buckets[i];
|
||||
u4 bucket_offset = BUCKET_OFFSET(bucket_info);
|
||||
|
||||
@ -23,7 +23,6 @@
|
||||
*/
|
||||
|
||||
#include "cds/aotClassLocation.hpp"
|
||||
#include "cds/aotGrowableArray.inline.hpp"
|
||||
#include "cds/archiveBuilder.hpp"
|
||||
#include "cds/archiveUtils.hpp"
|
||||
#include "cds/cdsConfig.hpp"
|
||||
@ -168,7 +167,7 @@ void ModuleEntry::add_read(ModuleEntry* m) {
|
||||
} else {
|
||||
if (reads() == nullptr) {
|
||||
// Lazily create a module's reads list
|
||||
AOTGrowableArray<ModuleEntry*>* new_reads = new (mtModule) AOTGrowableArray<ModuleEntry*>(MODULE_READS_SIZE, mtModule);
|
||||
GrowableArray<ModuleEntry*>* new_reads = new (mtModule) GrowableArray<ModuleEntry*>(MODULE_READS_SIZE, mtModule);
|
||||
set_reads(new_reads);
|
||||
}
|
||||
|
||||
|
||||
@ -25,7 +25,6 @@
|
||||
#ifndef SHARE_CLASSFILE_MODULEENTRY_HPP
|
||||
#define SHARE_CLASSFILE_MODULEENTRY_HPP
|
||||
|
||||
#include "cds/aotGrowableArray.hpp"
|
||||
#include "jni.h"
|
||||
#include "memory/metaspaceClosureType.hpp"
|
||||
#include "oops/oopHandle.hpp"
|
||||
@ -70,7 +69,7 @@ private:
|
||||
// for shared classes from this module
|
||||
Symbol* _name; // name of this module
|
||||
ClassLoaderData* _loader_data;
|
||||
AOTGrowableArray<ModuleEntry*>* _reads; // list of modules that are readable by this module
|
||||
GrowableArray<ModuleEntry*>* _reads; // list of modules that are readable by this module
|
||||
|
||||
Symbol* _version; // module version number
|
||||
Symbol* _location; // module location
|
||||
@ -118,10 +117,10 @@ public:
|
||||
|
||||
bool can_read(ModuleEntry* m) const;
|
||||
bool has_reads_list() const;
|
||||
AOTGrowableArray<ModuleEntry*>* reads() const {
|
||||
GrowableArray<ModuleEntry*>* reads() const {
|
||||
return _reads;
|
||||
}
|
||||
void set_reads(AOTGrowableArray<ModuleEntry*>* r) {
|
||||
void set_reads(GrowableArray<ModuleEntry*>* r) {
|
||||
_reads = r;
|
||||
}
|
||||
void pack_reads() {
|
||||
|
||||
@ -22,7 +22,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "cds/aotGrowableArray.inline.hpp"
|
||||
#include "cds/aotMetaspace.hpp"
|
||||
#include "cds/archiveBuilder.hpp"
|
||||
#include "cds/archiveUtils.hpp"
|
||||
@ -83,7 +82,7 @@ void PackageEntry::add_qexport(ModuleEntry* m) {
|
||||
if (!has_qual_exports_list()) {
|
||||
// Lazily create a package's qualified exports list.
|
||||
// Initial size is small, do not anticipate export lists to be large.
|
||||
_qualified_exports = new (mtModule) AOTGrowableArray<ModuleEntry*>(QUAL_EXP_SIZE, mtModule);
|
||||
_qualified_exports = new (mtModule) GrowableArray<ModuleEntry*>(QUAL_EXP_SIZE, mtModule);
|
||||
}
|
||||
|
||||
// Determine, based on this newly established export to module m,
|
||||
|
||||
@ -25,7 +25,6 @@
|
||||
#ifndef SHARE_CLASSFILE_PACKAGEENTRY_HPP
|
||||
#define SHARE_CLASSFILE_PACKAGEENTRY_HPP
|
||||
|
||||
#include "cds/aotGrowableArray.hpp"
|
||||
#include "classfile/moduleEntry.hpp"
|
||||
#include "memory/metaspaceClosureType.hpp"
|
||||
#include "oops/symbol.hpp"
|
||||
@ -116,7 +115,7 @@ private:
|
||||
bool _must_walk_exports;
|
||||
// Contains list of modules this package is qualifiedly exported to. Access
|
||||
// to this list is protected by the Module_lock.
|
||||
AOTGrowableArray<ModuleEntry*>* _qualified_exports;
|
||||
GrowableArray<ModuleEntry*>* _qualified_exports;
|
||||
JFR_ONLY(DEFINE_TRACE_ID_FIELD;)
|
||||
|
||||
// Initial size of a package entry's list of qualified exports.
|
||||
|
||||
@ -469,6 +469,9 @@ class methodHandle;
|
||||
do_intrinsic(_Reference_clear0, java_lang_ref_Reference, clear0_name, void_method_signature, F_RN) \
|
||||
do_intrinsic(_PhantomReference_clear0, java_lang_ref_PhantomReference, clear0_name, void_method_signature, F_RN) \
|
||||
\
|
||||
do_intrinsic(_Reference_reachabilityFence, java_lang_ref_Reference, reachabilityFence_name, object_void_signature, F_S) \
|
||||
do_name(reachabilityFence_name, "reachabilityFence") \
|
||||
\
|
||||
/* support for com.sun.crypto.provider.AES_Crypt and some of its callers */ \
|
||||
do_class(com_sun_crypto_provider_aescrypt, "com/sun/crypto/provider/AES_Crypt") \
|
||||
do_intrinsic(_aescrypt_encryptBlock, com_sun_crypto_provider_aescrypt, encryptBlock_name, byteArray_int_byteArray_int_signature, F_R) \
|
||||
|
||||
@ -702,6 +702,7 @@ class SerializeClosure;
|
||||
template(appendToClassPathForInstrumentation_name, "appendToClassPathForInstrumentation") \
|
||||
do_alias(appendToClassPathForInstrumentation_signature, string_void_signature) \
|
||||
template(serializePropertiesToByteArray_name, "serializePropertiesToByteArray") \
|
||||
template(serializeSecurityPropertiesToByteArray_name, "serializeSecurityPropertiesToByteArray") \
|
||||
template(serializeAgentPropertiesToByteArray_name, "serializeAgentPropertiesToByteArray") \
|
||||
template(encodeThrowable_name, "encodeThrowable") \
|
||||
template(encodeThrowable_signature, "(Ljava/lang/Throwable;JI)I") \
|
||||
|
||||
@ -1093,11 +1093,13 @@ bool AOTCodeCache::store_code_blob(CodeBlob& blob, AOTCodeEntry::Kind entry_kind
|
||||
// now we have added all the other data we can write details of any
|
||||
// extra the AOT relocations
|
||||
|
||||
bool write_ok;
|
||||
bool write_ok = true;
|
||||
if (AOTCodeEntry::is_multi_stub_blob(entry_kind)) {
|
||||
CodeSection* cs = code_buffer->code_section(CodeBuffer::SECT_INSTS);
|
||||
RelocIterator iter(cs);
|
||||
write_ok = cache->write_relocations(blob, iter);
|
||||
if (reloc_count > 0) {
|
||||
CodeSection* cs = code_buffer->code_section(CodeBuffer::SECT_INSTS);
|
||||
RelocIterator iter(cs);
|
||||
write_ok = cache->write_relocations(blob, iter);
|
||||
}
|
||||
} else {
|
||||
RelocIterator iter(&blob);
|
||||
write_ok = cache->write_relocations(blob, iter);
|
||||
@ -1403,13 +1405,15 @@ void AOTCodeReader::restore(CodeBlob* code_blob) {
|
||||
// reinstate the AOT-load time relocs we saved from the code
|
||||
// buffer that generated this blob in a new code buffer and use
|
||||
// the latter to iterate over them
|
||||
CodeBuffer code_buffer(code_blob);
|
||||
relocInfo* locs = (relocInfo*)_reloc_data;
|
||||
code_buffer.insts()->initialize_shared_locs(locs, _reloc_count);
|
||||
code_buffer.insts()->set_locs_end(locs + _reloc_count);
|
||||
CodeSection *cs = code_buffer.code_section(CodeBuffer::SECT_INSTS);
|
||||
RelocIterator reloc_iter(cs);
|
||||
fix_relocations(code_blob, reloc_iter);
|
||||
if (_reloc_count > 0) {
|
||||
CodeBuffer code_buffer(code_blob);
|
||||
relocInfo* locs = (relocInfo*)_reloc_data;
|
||||
code_buffer.insts()->initialize_shared_locs(locs, _reloc_count);
|
||||
code_buffer.insts()->set_locs_end(locs + _reloc_count);
|
||||
CodeSection *cs = code_buffer.code_section(CodeBuffer::SECT_INSTS);
|
||||
RelocIterator reloc_iter(cs);
|
||||
fix_relocations(code_blob, reloc_iter);
|
||||
}
|
||||
} else {
|
||||
// the AOT-load time relocs will be in the blob's restored relocs
|
||||
RelocIterator reloc_iter(code_blob);
|
||||
@ -1858,11 +1862,8 @@ void AOTCodeReader::read_dbg_strings(DbgStrings& dbg_strings) {
|
||||
// addresses, respectively, keyed by the relevant address
|
||||
|
||||
void AOTCodeAddressTable::hash_address(address addr, int idx) {
|
||||
// only do this if we are caching stubs and we have a non-null
|
||||
// address to record
|
||||
if (!AOTStubCaching) {
|
||||
return;
|
||||
}
|
||||
// only do this if we have a non-null address to record and the
|
||||
// cache is open for dumping
|
||||
if (addr == nullptr) {
|
||||
return;
|
||||
}
|
||||
@ -2183,7 +2184,7 @@ void AOTCodeAddressTable::set_stubgen_stubs_complete() {
|
||||
#ifdef PRODUCT
|
||||
#define MAX_STR_COUNT 200
|
||||
#else
|
||||
#define MAX_STR_COUNT 500
|
||||
#define MAX_STR_COUNT 2000
|
||||
#endif
|
||||
#define _c_str_max MAX_STR_COUNT
|
||||
static const int _c_str_base = _all_max;
|
||||
@ -2200,6 +2201,10 @@ void AOTCodeCache::load_strings() {
|
||||
if (strings_count == 0) {
|
||||
return;
|
||||
}
|
||||
if (strings_count > MAX_STR_COUNT) {
|
||||
fatal("Invalid strings_count loaded from AOT Code Cache: %d > MAX_STR_COUNT [%d]", strings_count, MAX_STR_COUNT);
|
||||
return;
|
||||
}
|
||||
uint strings_offset = _load_header->strings_offset();
|
||||
uint* string_lengths = (uint*)addr(strings_offset);
|
||||
strings_offset += (strings_count * sizeof(uint));
|
||||
@ -2210,7 +2215,6 @@ void AOTCodeCache::load_strings() {
|
||||
char* p = NEW_C_HEAP_ARRAY(char, strings_size+1, mtCode);
|
||||
memcpy(p, addr(strings_offset), strings_size);
|
||||
_C_strings_buf = p;
|
||||
assert(strings_count <= MAX_STR_COUNT, "sanity");
|
||||
for (uint i = 0; i < strings_count; i++) {
|
||||
_C_strings[i] = p;
|
||||
uint len = string_lengths[i];
|
||||
@ -2292,7 +2296,7 @@ const char* AOTCodeAddressTable::add_C_string(const char* str) {
|
||||
|
||||
int AOTCodeAddressTable::id_for_C_string(address str) {
|
||||
if (str == nullptr) {
|
||||
return -1;
|
||||
return BAD_ADDRESS_ID;
|
||||
}
|
||||
MutexLocker ml(AOTCodeCStrings_lock, Mutex::_no_safepoint_check_flag);
|
||||
for (int i = 0; i < _C_strings_count; i++) {
|
||||
@ -2310,7 +2314,7 @@ int AOTCodeAddressTable::id_for_C_string(address str) {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
return BAD_ADDRESS_ID;
|
||||
}
|
||||
|
||||
address AOTCodeAddressTable::address_for_C_string(int idx) {
|
||||
@ -2377,13 +2381,13 @@ int AOTCodeAddressTable::id_for_address(address addr, RelocIterator reloc, CodeB
|
||||
}
|
||||
// Seach for C string
|
||||
id = id_for_C_string(addr);
|
||||
if (id >= 0) {
|
||||
if (id != BAD_ADDRESS_ID) {
|
||||
return id + _c_str_base;
|
||||
}
|
||||
if (StubRoutines::contains(addr) || CodeCache::find_blob(addr) != nullptr) {
|
||||
// Search for a matching stub entry
|
||||
id = search_address(addr, _stubs_addr, _stubs_max);
|
||||
if (id < 0) {
|
||||
if (id == BAD_ADDRESS_ID) {
|
||||
StubCodeDesc* desc = StubCodeDesc::desc_for(addr);
|
||||
if (desc == nullptr) {
|
||||
desc = StubCodeDesc::desc_for(addr + frame::pc_return_offset);
|
||||
@ -2396,7 +2400,7 @@ int AOTCodeAddressTable::id_for_address(address addr, RelocIterator reloc, CodeB
|
||||
} else {
|
||||
// Search in runtime functions
|
||||
id = search_address(addr, _extrs_addr, _extrs_length);
|
||||
if (id < 0) {
|
||||
if (id == BAD_ADDRESS_ID) {
|
||||
ResourceMark rm;
|
||||
const int buflen = 1024;
|
||||
char* func_name = NEW_RESOURCE_ARRAY(char, buflen);
|
||||
@ -2511,10 +2515,11 @@ AOTStubData::AOTStubData(BlobId blob_id) :
|
||||
// cannot be accessed before initialising the universe
|
||||
if (blob_id == BlobId::stubgen_preuniverse_id) {
|
||||
// invalidate any attempt to use this
|
||||
_flags |= INVALID;
|
||||
_flags = INVALID;
|
||||
return;
|
||||
}
|
||||
if (AOTCodeCache::is_on()) {
|
||||
_flags = OPEN;
|
||||
// allow update of stub entry addresses
|
||||
if (AOTCodeCache::is_using_stub()) {
|
||||
// allow stub loading
|
||||
|
||||
@ -236,9 +236,10 @@ private:
|
||||
// whether we are loading or storing stubs or have encountered any
|
||||
// invalid stubs.
|
||||
enum Flags {
|
||||
USING = 1 << 0, // open and loading stubs
|
||||
DUMPING = 1 << 1, // open and storing stubs
|
||||
INVALID = 1 << 2, // found invalid stub when loading
|
||||
OPEN = 1 << 0, // cache is open
|
||||
USING = 1 << 1, // open and loading stubs
|
||||
DUMPING = 1 << 2, // open and storing stubs
|
||||
INVALID = 1 << 3, // found invalid stub when loading
|
||||
};
|
||||
|
||||
uint32_t _flags;
|
||||
@ -253,6 +254,7 @@ public:
|
||||
|
||||
~AOTStubData() CDS_ONLY({FREE_C_HEAP_ARRAY(StubAddrRange, _ranges);}) NOT_CDS({})
|
||||
|
||||
bool is_open() CDS_ONLY({ return (_flags & OPEN) != 0; }) NOT_CDS_RETURN_(false);
|
||||
bool is_using() CDS_ONLY({ return (_flags & USING) != 0; }) NOT_CDS_RETURN_(false);
|
||||
bool is_dumping() CDS_ONLY({ return (_flags & DUMPING) != 0; }) NOT_CDS_RETURN_(false);
|
||||
bool is_invalid() CDS_ONLY({ return (_flags & INVALID) != 0; }) NOT_CDS_RETURN_(false);
|
||||
|
||||
@ -226,7 +226,7 @@ public:
|
||||
nmethod* as_nmethod() const { assert(is_nmethod(), "must be nmethod"); return (nmethod*) this; }
|
||||
CodeBlob* as_codeblob() const { return (CodeBlob*) this; }
|
||||
// we may want to force an actual buffer blob or subtype instance
|
||||
BufferBlob* as_buffer_blob(bool strict = true) const { assert(is_buffer_blob(), "must be %sbuffer blob", (strict ? "strict " : "")); return (BufferBlob*) this; }
|
||||
BufferBlob* as_buffer_blob(bool strict = true) const { assert(is_buffer_blob(strict), "must be %sbuffer blob", (strict ? "strict " : "")); return (BufferBlob*) this; }
|
||||
AdapterBlob* as_adapter_blob() const { assert(is_adapter_blob(), "must be adapter blob"); return (AdapterBlob*) this; }
|
||||
ExceptionBlob* as_exception_blob() const { assert(is_exception_stub(), "must be exception stub"); return (ExceptionBlob*) this; }
|
||||
// this will always return a subtype instance
|
||||
@ -604,7 +604,7 @@ class DeoptimizationBlob: public SingletonBlob {
|
||||
);
|
||||
|
||||
public:
|
||||
static const int ENTRY_COUNT = 4 JVMTI_ONLY(+ 2);
|
||||
static const int ENTRY_COUNT = 4 JVMCI_ONLY(+ 2);
|
||||
// Creation
|
||||
static DeoptimizationBlob* create(
|
||||
CodeBuffer* cb,
|
||||
|
||||
@ -90,7 +90,7 @@ G1CardSetMemoryManager::~G1CardSetMemoryManager() {
|
||||
for (uint i = 0; i < num_mem_object_types(); i++) {
|
||||
_allocators[i].~G1CardSetAllocator();
|
||||
}
|
||||
FREE_C_HEAP_ARRAY(G1CardSetAllocator<G1CardSetContainer>, _allocators);
|
||||
FREE_C_HEAP_ARRAY(G1CardSetAllocator, _allocators);
|
||||
}
|
||||
|
||||
void G1CardSetMemoryManager::free(uint type, void* value) {
|
||||
|
||||
@ -3219,7 +3219,7 @@ void G1CollectedHeap::retire_gc_alloc_region(G1HeapRegion* alloc_region,
|
||||
G1HeapRegionPrinter::retire(alloc_region);
|
||||
}
|
||||
|
||||
void G1CollectedHeap::mark_evac_failure_object(uint worker_id, const oop obj, size_t obj_size) const {
|
||||
void G1CollectedHeap::mark_evac_failure_object(const oop obj) const {
|
||||
assert(!_cm->is_marked_in_bitmap(obj), "must be");
|
||||
|
||||
_cm->raw_mark_in_bitmap(obj);
|
||||
|
||||
@ -1275,7 +1275,7 @@ public:
|
||||
inline bool is_obj_dead_full(const oop obj) const;
|
||||
|
||||
// Mark the live object that failed evacuation in the bitmap.
|
||||
void mark_evac_failure_object(uint worker_id, oop obj, size_t obj_size) const;
|
||||
void mark_evac_failure_object(oop obj) const;
|
||||
|
||||
G1ConcurrentMark* concurrent_mark() const { return _cm; }
|
||||
|
||||
|
||||
@ -2173,8 +2173,7 @@ void G1CMTask::reset_for_restart() {
|
||||
void G1CMTask::register_partial_array_splitter() {
|
||||
|
||||
::new (&_partial_array_splitter) PartialArraySplitter(_cm->partial_array_state_manager(),
|
||||
_cm->max_num_tasks(),
|
||||
ObjArrayMarkingStride);
|
||||
_cm->max_num_tasks());
|
||||
}
|
||||
|
||||
void G1CMTask::unregister_partial_array_splitter() {
|
||||
@ -2359,7 +2358,7 @@ size_t G1CMTask::start_partial_array_processing(objArrayOop obj) {
|
||||
process_klass(obj->klass());
|
||||
|
||||
size_t array_length = obj->length();
|
||||
size_t initial_chunk_size = _partial_array_splitter.start(_task_queue, obj, nullptr, array_length);
|
||||
size_t initial_chunk_size = _partial_array_splitter.start(_task_queue, obj, nullptr, array_length, ObjArrayMarkingStride);
|
||||
|
||||
process_array_chunk(obj, 0, initial_chunk_size);
|
||||
|
||||
@ -2917,7 +2916,7 @@ G1CMTask::G1CMTask(uint worker_id,
|
||||
_cm(cm),
|
||||
_mark_bitmap(nullptr),
|
||||
_task_queue(task_queue),
|
||||
_partial_array_splitter(_cm->partial_array_state_manager(), _cm->max_num_tasks(), ObjArrayMarkingStride),
|
||||
_partial_array_splitter(_cm->partial_array_state_manager(), _cm->max_num_tasks()),
|
||||
_mark_stats_cache(mark_stats, G1RegionMarkStatsCache::RegionMarkStatsCacheSize),
|
||||
_calls(0),
|
||||
_time_target_ms(0.0),
|
||||
|
||||
@ -39,7 +39,7 @@ G1FullGCMarker::G1FullGCMarker(G1FullCollector* collector,
|
||||
_worker_id(worker_id),
|
||||
_bitmap(collector->mark_bitmap()),
|
||||
_task_queue(),
|
||||
_partial_array_splitter(collector->partial_array_state_manager(), collector->workers(), ObjArrayMarkingStride),
|
||||
_partial_array_splitter(collector->partial_array_state_manager(), collector->workers()),
|
||||
_mark_closure(worker_id, this, ClassLoaderData::_claim_stw_fullgc_mark, G1CollectedHeap::heap()->ref_processor_stw()),
|
||||
_stack_closure(this),
|
||||
_cld_closure(mark_closure(), ClassLoaderData::_claim_stw_fullgc_mark),
|
||||
@ -60,14 +60,26 @@ void G1FullGCMarker::process_partial_array(PartialArrayState* state, bool stolen
|
||||
process_array_chunk(obj_array, claim._start, claim._end);
|
||||
}
|
||||
|
||||
static uintx calc_array_stride(uint array_len, uint num_threads) {
|
||||
precond(num_threads > 0);
|
||||
|
||||
const size_t stride = (array_len + num_threads - 1) / num_threads;
|
||||
return clamp(stride, ArrayMarkingMinStride, ObjArrayMarkingStride);
|
||||
}
|
||||
|
||||
void G1FullGCMarker::start_partial_array_processing(objArrayOop obj) {
|
||||
mark_closure()->do_klass(obj->klass());
|
||||
// Don't push empty arrays to avoid unnecessary work.
|
||||
size_t array_length = obj->length();
|
||||
if (array_length > 0) {
|
||||
size_t initial_chunk_size = _partial_array_splitter.start(task_queue(), obj, nullptr, array_length);
|
||||
process_array_chunk(obj, 0, initial_chunk_size);
|
||||
const int array_length = obj->length();
|
||||
|
||||
if (array_length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const uintx stride = calc_array_stride(array_length, _collector->workers());
|
||||
const size_t initial_chunk_size = _partial_array_splitter.start(task_queue(), obj, nullptr, array_length, stride);
|
||||
|
||||
process_array_chunk(obj, 0, initial_chunk_size);
|
||||
}
|
||||
|
||||
void G1FullGCMarker::complete_marking(G1ScannerTasksQueueSet* task_queues,
|
||||
|
||||
@ -78,7 +78,7 @@ G1ParScanThreadState::G1ParScanThreadState(G1CollectedHeap* g1h,
|
||||
_surviving_young_words(nullptr),
|
||||
_surviving_words_length(collection_set->young_region_length() + 1),
|
||||
_old_gen_is_full(false),
|
||||
_partial_array_splitter(g1h->partial_array_state_manager(), num_workers, ParGCArrayScanChunk),
|
||||
_partial_array_splitter(g1h->partial_array_state_manager(), num_workers),
|
||||
_string_dedup_requests(),
|
||||
_max_num_optional_regions(collection_set->num_optional_regions()),
|
||||
_numa(g1h->numa()),
|
||||
@ -253,7 +253,7 @@ void G1ParScanThreadState::start_partial_objarray(oop from_obj,
|
||||
size_t array_length = to_array->length();
|
||||
size_t initial_chunk_size =
|
||||
// The source array is unused when processing states.
|
||||
_partial_array_splitter.start(_task_queue, nullptr, to_array, array_length);
|
||||
_partial_array_splitter.start(_task_queue, nullptr, to_array, array_length, ParGCArrayScanChunk);
|
||||
|
||||
assert(_scanner.skip_card_mark_set(), "must be");
|
||||
// Process the initial chunk. No need to process the type in the
|
||||
@ -650,7 +650,7 @@ oop G1ParScanThreadState::handle_evacuation_failure_par(oop old, markWord m, Kla
|
||||
|
||||
// Mark the failing object in the marking bitmap and later use the bitmap to handle
|
||||
// evacuation failure recovery.
|
||||
_g1h->mark_evac_failure_object(_worker_id, old, word_sz);
|
||||
_g1h->mark_evac_failure_object(old);
|
||||
|
||||
_evacuation_failed_info.register_copy_failure(word_sz);
|
||||
|
||||
|
||||
@ -70,7 +70,7 @@ JVMFlag::Error G1RemSetHowlMaxNumBucketsConstraintFunc(uint value, bool verbose)
|
||||
}
|
||||
if (!is_power_of_2(G1RemSetHowlMaxNumBuckets)) {
|
||||
JVMFlag::printError(verbose,
|
||||
"G1RemSetMaxHowlNumBuckets (%u) must be a power of two.\n",
|
||||
"G1RemSetHowlMaxNumBuckets (%u) must be a power of two.\n",
|
||||
value);
|
||||
return JVMFlag::VIOLATES_CONSTRAINT;
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 2026, 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
|
||||
@ -58,7 +58,7 @@ PreservedMarksSet* ParCompactionManager::_preserved_marks_set = nullptr;
|
||||
ParCompactionManager::ParCompactionManager(PreservedMarks* preserved_marks,
|
||||
ReferenceProcessor* ref_processor,
|
||||
uint parallel_gc_threads)
|
||||
:_partial_array_splitter(_partial_array_state_manager, parallel_gc_threads, ObjArrayMarkingStride),
|
||||
:_partial_array_splitter(_partial_array_state_manager, parallel_gc_threads),
|
||||
_mark_and_push_closure(this, ref_processor) {
|
||||
|
||||
ParallelScavengeHeap* heap = ParallelScavengeHeap::heap();
|
||||
@ -126,7 +126,7 @@ void ParCompactionManager::push_objArray(oop obj) {
|
||||
objArrayOop obj_array = objArrayOop(obj);
|
||||
size_t array_length = obj_array->length();
|
||||
size_t initial_chunk_size =
|
||||
_partial_array_splitter.start(&_marking_stack, obj_array, nullptr, array_length);
|
||||
_partial_array_splitter.start(&_marking_stack, obj_array, nullptr, array_length, ObjArrayMarkingStride);
|
||||
follow_array(obj_array, 0, initial_chunk_size);
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2002, 2026, 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
|
||||
@ -158,7 +158,7 @@ PartialArrayTaskStats* PSPromotionManager::partial_array_task_stats() {
|
||||
|
||||
// Most members are initialized either by initialize() or reset().
|
||||
PSPromotionManager::PSPromotionManager()
|
||||
: _partial_array_splitter(_partial_array_state_manager, ParallelGCThreads, ParGCArrayScanChunk)
|
||||
: _partial_array_splitter(_partial_array_state_manager, ParallelGCThreads)
|
||||
{
|
||||
// We set the old lab's start array.
|
||||
_old_lab.set_start_array(old_gen()->start_array());
|
||||
@ -273,7 +273,7 @@ void PSPromotionManager::push_objArray(oop old_obj, oop new_obj) {
|
||||
size_t array_length = to_array->length();
|
||||
size_t initial_chunk_size =
|
||||
// The source array is unused when processing states.
|
||||
_partial_array_splitter.start(&_claimed_stack_depth, nullptr, to_array, array_length);
|
||||
_partial_array_splitter.start(&_claimed_stack_depth, nullptr, to_array, array_length, ParGCArrayScanChunk);
|
||||
|
||||
process_array_chunk(to_array, 0, initial_chunk_size);
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2026, 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
|
||||
@ -256,6 +256,12 @@
|
||||
"before pushing a continuation entry") \
|
||||
range(1, INT_MAX/2) \
|
||||
\
|
||||
product(uintx, ArrayMarkingMinStride, 64, DIAGNOSTIC, \
|
||||
"Minimum chunk size for split array processing during marking; " \
|
||||
"the effective stride is clamped between this value " \
|
||||
"and ObjArrayMarkingStride.") \
|
||||
constraint(ArrayMarkingMinStrideConstraintFunc,AfterErgo) \
|
||||
\
|
||||
product(bool, AggressiveHeap, false, \
|
||||
"(Deprecated) Optimize heap options for long-running memory " \
|
||||
"intensive apps") \
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2026, 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
|
||||
@ -414,3 +414,15 @@ JVMFlag::Error GCCardSizeInBytesConstraintFunc(uint value, bool verbose) {
|
||||
return JVMFlag::SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
JVMFlag::Error ArrayMarkingMinStrideConstraintFunc(uintx value, bool verbose) {
|
||||
if (value > ObjArrayMarkingStride) {
|
||||
JVMFlag::printError(verbose,
|
||||
"ArrayMarkingMinStride (%zu) must be "
|
||||
"less than or equal to ObjArrayMarkingStride (%zu)\n",
|
||||
value, ObjArrayMarkingStride);
|
||||
return JVMFlag::VIOLATES_CONSTRAINT;
|
||||
} else {
|
||||
return JVMFlag::SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2026, 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
|
||||
@ -66,7 +66,8 @@
|
||||
f(uintx, SurvivorRatioConstraintFunc) \
|
||||
f(size_t, MetaspaceSizeConstraintFunc) \
|
||||
f(size_t, MaxMetaspaceSizeConstraintFunc) \
|
||||
f(uint, GCCardSizeInBytesConstraintFunc)
|
||||
f(uint, GCCardSizeInBytesConstraintFunc) \
|
||||
f(uintx, ArrayMarkingMinStrideConstraintFunc)
|
||||
|
||||
SHARED_GC_CONSTRAINTS(DECLARE_CONSTRAINT)
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2024, 2026, 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
|
||||
@ -28,10 +28,9 @@
|
||||
#include "utilities/macros.hpp"
|
||||
|
||||
PartialArraySplitter::PartialArraySplitter(PartialArrayStateManager* manager,
|
||||
uint num_workers,
|
||||
size_t chunk_size)
|
||||
uint num_workers)
|
||||
: _allocator(manager),
|
||||
_stepper(num_workers, chunk_size)
|
||||
_stepper(num_workers)
|
||||
TASKQUEUE_STATS_ONLY(COMMA _stats())
|
||||
{}
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2024, 2026, 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
|
||||
@ -44,8 +44,7 @@ class PartialArraySplitter {
|
||||
|
||||
public:
|
||||
PartialArraySplitter(PartialArrayStateManager* manager,
|
||||
uint num_workers,
|
||||
size_t chunk_size);
|
||||
uint num_workers);
|
||||
~PartialArraySplitter() = default;
|
||||
|
||||
NONCOPYABLE(PartialArraySplitter);
|
||||
@ -60,6 +59,8 @@ public:
|
||||
//
|
||||
// length is their length in elements.
|
||||
//
|
||||
// chunk_size the size of a single chunk.
|
||||
//
|
||||
// If t is a ScannerTask, queue->push(t) must be a valid expression. The
|
||||
// result of that expression is ignored.
|
||||
//
|
||||
@ -76,7 +77,8 @@ public:
|
||||
size_t start(Queue* queue,
|
||||
objArrayOop from_array,
|
||||
objArrayOop to_array,
|
||||
size_t length);
|
||||
size_t length,
|
||||
size_t chunk_size);
|
||||
|
||||
// Result type for claim(), carrying multiple values. Provides the claimed
|
||||
// chunk's start and end array indices.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2024, 2026, 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
|
||||
@ -39,14 +39,16 @@ template<typename Queue>
|
||||
size_t PartialArraySplitter::start(Queue* queue,
|
||||
objArrayOop source,
|
||||
objArrayOop destination,
|
||||
size_t length) {
|
||||
PartialArrayTaskStepper::Step step = _stepper.start(length);
|
||||
size_t length,
|
||||
size_t chunk_size) {
|
||||
precond(chunk_size > 0);
|
||||
PartialArrayTaskStepper::Step step = _stepper.start(length, chunk_size);
|
||||
// Push initial partial scan tasks.
|
||||
if (step._ncreate > 0) {
|
||||
TASKQUEUE_STATS_ONLY(_stats.inc_split(););
|
||||
TASKQUEUE_STATS_ONLY(_stats.inc_pushed(step._ncreate);)
|
||||
PartialArrayState* state =
|
||||
_allocator.allocate(source, destination, step._index, length, step._ncreate);
|
||||
_allocator.allocate(source, destination, step._index, length, chunk_size, step._ncreate);
|
||||
for (uint i = 0; i < step._ncreate; ++i) {
|
||||
queue->push(ScannerTask(state));
|
||||
}
|
||||
@ -75,9 +77,10 @@ PartialArraySplitter::claim(PartialArrayState* state, Queue* queue, bool stolen)
|
||||
queue->push(ScannerTask(state));
|
||||
}
|
||||
}
|
||||
size_t chunk_size = state->chunk_size();
|
||||
// Release state, decrementing refcount, now that we're done with it.
|
||||
_allocator.release(state);
|
||||
return Claim{step._index, step._index + _stepper.chunk_size()};
|
||||
return Claim{step._index, step._index + chunk_size};
|
||||
}
|
||||
|
||||
#endif // SHARE_GC_SHARED_PARTIALARRAYSPLITTER_INLINE_HPP
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2024, 2026, 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
|
||||
@ -35,10 +35,12 @@
|
||||
|
||||
PartialArrayState::PartialArrayState(oop src, oop dst,
|
||||
size_t index, size_t length,
|
||||
size_t chunk_size,
|
||||
size_t initial_refcount)
|
||||
: _source(src),
|
||||
_destination(dst),
|
||||
_length(length),
|
||||
_chunk_size(chunk_size),
|
||||
_index(index),
|
||||
_refcount(initial_refcount)
|
||||
{
|
||||
@ -77,6 +79,7 @@ PartialArrayStateAllocator::~PartialArrayStateAllocator() {
|
||||
PartialArrayState* PartialArrayStateAllocator::allocate(oop src, oop dst,
|
||||
size_t index,
|
||||
size_t length,
|
||||
size_t chunk_size,
|
||||
size_t initial_refcount) {
|
||||
void* p;
|
||||
FreeListEntry* head = _free_list;
|
||||
@ -87,7 +90,7 @@ PartialArrayState* PartialArrayStateAllocator::allocate(oop src, oop dst,
|
||||
head->~FreeListEntry();
|
||||
p = head;
|
||||
}
|
||||
return ::new (p) PartialArrayState(src, dst, index, length, initial_refcount);
|
||||
return ::new (p) PartialArrayState(src, dst, index, length, chunk_size, initial_refcount);
|
||||
}
|
||||
|
||||
void PartialArrayStateAllocator::release(PartialArrayState* state) {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2024, 2026, 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
|
||||
@ -61,6 +61,7 @@ class PartialArrayState {
|
||||
oop _source;
|
||||
oop _destination;
|
||||
size_t _length;
|
||||
size_t _chunk_size;
|
||||
Atomic<size_t> _index;
|
||||
Atomic<size_t> _refcount;
|
||||
|
||||
@ -68,7 +69,7 @@ class PartialArrayState {
|
||||
|
||||
PartialArrayState(oop src, oop dst,
|
||||
size_t index, size_t length,
|
||||
size_t initial_refcount);
|
||||
size_t chunk_size, size_t initial_refcount);
|
||||
|
||||
public:
|
||||
// Deleted to require management by allocator object.
|
||||
@ -89,6 +90,8 @@ public:
|
||||
// The length of the array oop.
|
||||
size_t length() const { return _length; }
|
||||
|
||||
size_t chunk_size() const { return _chunk_size; }
|
||||
|
||||
// A pointer to the start index for the next segment to process, for atomic
|
||||
// update.
|
||||
Atomic<size_t>* index_addr() { return &_index; }
|
||||
@ -130,6 +133,7 @@ public:
|
||||
// from the associated manager.
|
||||
PartialArrayState* allocate(oop src, oop dst,
|
||||
size_t index, size_t length,
|
||||
size_t chunk_size,
|
||||
size_t initial_refcount);
|
||||
|
||||
// Decrement the state's refcount. If the new refcount is zero, add the
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -48,8 +48,7 @@ static uint compute_task_fanout(uint task_limit) {
|
||||
return result;
|
||||
}
|
||||
|
||||
PartialArrayTaskStepper::PartialArrayTaskStepper(uint n_workers, size_t chunk_size) :
|
||||
_chunk_size(chunk_size),
|
||||
PartialArrayTaskStepper::PartialArrayTaskStepper(uint n_workers) :
|
||||
_task_limit(compute_task_limit(n_workers)),
|
||||
_task_fanout(compute_task_fanout(_task_limit))
|
||||
{}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2020, 2026, 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
|
||||
@ -40,19 +40,19 @@ class PartialArrayState;
|
||||
// substantially expand the task queues.
|
||||
class PartialArrayTaskStepper {
|
||||
public:
|
||||
PartialArrayTaskStepper(uint n_workers, size_t chunk_size);
|
||||
PartialArrayTaskStepper(uint n_workers);
|
||||
|
||||
struct Step {
|
||||
size_t _index; // Array index for the step.
|
||||
uint _ncreate; // Number of new tasks to create.
|
||||
};
|
||||
|
||||
// Called with the length of the array to be processed. Returns a Step with
|
||||
// _index being the end of the initial chunk, which the caller should
|
||||
// process. This is also the starting index for the next chunk to process.
|
||||
// Called with the length of the array to be processed and chunk size.
|
||||
// Returns a Step with _index being the end of the initial chunk, which the
|
||||
// caller should process. This is also the starting index for the next chunk to process.
|
||||
// The _ncreate is the number of tasks to enqueue to continue processing the
|
||||
// array. If _ncreate is zero then _index will be length.
|
||||
inline Step start(size_t length) const;
|
||||
inline Step start(size_t length, size_t chunk_size) const;
|
||||
|
||||
// Atomically increment state's index by chunk_size() to claim the next
|
||||
// chunk. Returns a Step with _index being the starting index of the
|
||||
@ -60,21 +60,16 @@ public:
|
||||
// to enqueue.
|
||||
inline Step next(PartialArrayState* state) const;
|
||||
|
||||
// The size of chunks to claim for each task.
|
||||
inline size_t chunk_size() const;
|
||||
|
||||
class TestSupport; // For unit tests
|
||||
|
||||
private:
|
||||
// Size (number of elements) of a chunk to process.
|
||||
size_t _chunk_size;
|
||||
// Limit on the number of partial array tasks to create for a given array.
|
||||
uint _task_limit;
|
||||
// Maximum number of new tasks to create when processing an existing task.
|
||||
uint _task_fanout;
|
||||
|
||||
// For unit tests.
|
||||
inline Step next_impl(size_t length, Atomic<size_t>* index_addr) const;
|
||||
inline Step next_impl(size_t length, size_t chunk_size, Atomic<size_t>* index_addr) const;
|
||||
};
|
||||
|
||||
#endif // SHARE_GC_SHARED_PARTIALARRAYTASKSTEPPER_HPP
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user