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
7c7c3d60a6
2
.gitignore
vendored
2
.gitignore
vendored
@ -24,8 +24,6 @@ NashornProfile.txt
|
||||
/.gdbinit
|
||||
/.lldbinit
|
||||
**/core.[0-9]*
|
||||
*.rej
|
||||
*.orig
|
||||
test/benchmarks/**/target
|
||||
/src/hotspot/CMakeLists.txt
|
||||
/src/hotspot/compile_commands.json
|
||||
|
||||
@ -108,3 +108,4 @@ override EXTRA_LDFLAGS :=
|
||||
# hsdis is not needed
|
||||
HSDIS_BACKEND := none
|
||||
ENABLE_HSDIS_BUNDLING := false
|
||||
DEFAULT_PRINT_ASSEMBLY_OPTIONS :=
|
||||
|
||||
@ -417,4 +417,9 @@ AC_DEFUN_ONCE([LIB_SETUP_HSDIS],
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
AC_SUBST(ENABLE_HSDIS_BUNDLING)
|
||||
|
||||
UTIL_ARG_WITH(NAME: print-assembly-options, TYPE: string,
|
||||
DEFAULT: [], RESULT: DEFAULT_PRINT_ASSEMBLY_OPTIONS,
|
||||
DESC: [default value for the PrintAssemblyOptions diagnostic flag, passed verbatim to the disassembler])
|
||||
AC_SUBST(DEFAULT_PRINT_ASSEMBLY_OPTIONS)
|
||||
])
|
||||
|
||||
@ -381,6 +381,7 @@ HSDIS_CFLAGS := @HSDIS_CFLAGS@
|
||||
HSDIS_LDFLAGS := @HSDIS_LDFLAGS@
|
||||
HSDIS_LIBS := @HSDIS_LIBS@
|
||||
CAPSTONE_ARCH_AARCH64_NAME := @CAPSTONE_ARCH_AARCH64_NAME@
|
||||
DEFAULT_PRINT_ASSEMBLY_OPTIONS := @DEFAULT_PRINT_ASSEMBLY_OPTIONS@
|
||||
|
||||
# The boot jdk to use. This is overridden in bootcycle-spec.gmk. Make sure to keep
|
||||
# it in sync.
|
||||
|
||||
@ -45,6 +45,15 @@ else
|
||||
GTEST_COPY_DEBUG_SYMBOLS := false
|
||||
endif
|
||||
|
||||
GTEST_LIBJVM_CFLAGS := $(JVM_CFLAGS)
|
||||
# Decoder does not work with debuginfo of the gtest libjvm when sections are used,
|
||||
# so we get wrong file names. That's why we filter out the section flags.
|
||||
ifeq ($(ENABLE_LINKTIME_GC), true)
|
||||
ifeq ($(TOOLCHAIN_TYPE), gcc)
|
||||
GTEST_LIBJVM_CFLAGS := $(filter-out -ffunction-sections -fdata-sections, $(JVM_CFLAGS))
|
||||
endif
|
||||
endif
|
||||
|
||||
################################################################################
|
||||
## Build libgtest
|
||||
################################################################################
|
||||
@ -99,7 +108,7 @@ $(eval $(call SetupJdkLibrary, BUILD_GTEST_LIBJVM, \
|
||||
EXCLUDE_PATTERNS := $(JVM_EXCLUDE_PATTERNS), \
|
||||
EXTRA_OBJECT_FILES := $(BUILD_LIBJVM_ALL_OBJS), \
|
||||
DEFAULT_CFLAGS := false, \
|
||||
CFLAGS := $(JVM_CFLAGS) \
|
||||
CFLAGS := $(GTEST_LIBJVM_CFLAGS) \
|
||||
-DHOTSPOT_GTEST \
|
||||
-I$(GTEST_FRAMEWORK_SRC)/googletest/include \
|
||||
-I$(GTEST_FRAMEWORK_SRC)/googlemock/include \
|
||||
|
||||
@ -209,6 +209,8 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBJVM, \
|
||||
DISABLED_WARNINGS_gcc_jvmtiTagMap.cpp := stringop-overflow, \
|
||||
DISABLED_WARNINGS_gcc_macroAssembler_ppc_sha.cpp := unused-const-variable, \
|
||||
DISABLED_WARNINGS_gcc_postaloc.cpp := address, \
|
||||
DISABLED_WARNINGS_gcc_safepointMechanism.cpp := stringop-overflow, \
|
||||
DISABLED_WARNINGS_gcc_shenandoahGenerationalHeap.cpp := stringop-overflow, \
|
||||
DISABLED_WARNINGS_gcc_shenandoahLock.cpp := stringop-overflow, \
|
||||
DISABLED_WARNINGS_gcc_stubGenerator_s390.cpp := unused-const-variable, \
|
||||
DISABLED_WARNINGS_gcc_synchronizer.cpp := stringop-overflow, \
|
||||
|
||||
@ -102,6 +102,10 @@ ifneq ($(HOTSPOT_OVERRIDE_LIBPATH), )
|
||||
JVM_CFLAGS += -DOVERRIDE_LIBPATH='"$(HOTSPOT_OVERRIDE_LIBPATH)"'
|
||||
endif
|
||||
|
||||
ifneq ($(DEFAULT_PRINT_ASSEMBLY_OPTIONS), )
|
||||
JVM_CFLAGS += -DDEFAULT_PRINT_ASSEMBLY_OPTIONS='"$(DEFAULT_PRINT_ASSEMBLY_OPTIONS)"'
|
||||
endif
|
||||
|
||||
ifeq ($(ENABLE_COMPATIBLE_CDS_ALIGNMENT), true)
|
||||
JVM_CFLAGS += -DCOMPATIBLE_CDS_ALIGNMENT
|
||||
endif
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 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
|
||||
@ -50,7 +50,7 @@ public interface BundleGenerator {
|
||||
};
|
||||
|
||||
public void generateBundle(String packageName, String baseName, String localeID,
|
||||
boolean useJava, Map<String, ?> map, BundleType type) throws IOException;
|
||||
Map<String, ?> map, BundleType type) throws IOException;
|
||||
|
||||
public void generateMetaInfo(Map<String, SortedSet<String>> metaInfo) throws IOException;
|
||||
}
|
||||
|
||||
@ -183,7 +183,6 @@ public class CLDRConverter {
|
||||
}
|
||||
}
|
||||
|
||||
static boolean USE_UTF8 = false;
|
||||
private static boolean verbose;
|
||||
|
||||
private CLDRConverter() {
|
||||
@ -232,10 +231,6 @@ public class CLDRConverter {
|
||||
DESTINATION_DIR = args[++i];
|
||||
break;
|
||||
|
||||
case "-utf8":
|
||||
USE_UTF8 = true;
|
||||
break;
|
||||
|
||||
case "-verbose":
|
||||
verbose = true;
|
||||
break;
|
||||
@ -336,7 +331,6 @@ public class CLDRConverter {
|
||||
+ "\t-year year copyright year in output%n"
|
||||
+ "\t-zntempfile template file for java.time.format.ZoneName.java%n"
|
||||
+ "\t-tzdatadir tzdata directory for java.time.format.ZoneName.java%n"
|
||||
+ "\t-utf8 use UTF-8 rather than \\uxxxx (for debug)%n"
|
||||
+ "\t-jdk-header-template <file>%n"
|
||||
+ "\t\t override default GPL header with contents of file%n");
|
||||
}
|
||||
@ -612,31 +606,31 @@ public class CLDRConverter {
|
||||
if (bundleTypes.contains(Bundle.Type.LOCALENAMES)) {
|
||||
Map<String, Object> localeNamesMap = extractLocaleNames(targetMap, id);
|
||||
if (!localeNamesMap.isEmpty() || bundle.isRoot()) {
|
||||
bundleGenerator.generateBundle("util", "LocaleNames", id, true, localeNamesMap, BundleType.OPEN);
|
||||
bundleGenerator.generateBundle("util", "LocaleNames", id, localeNamesMap, BundleType.OPEN);
|
||||
}
|
||||
}
|
||||
if (bundleTypes.contains(Bundle.Type.CURRENCYNAMES)) {
|
||||
Map<String, Object> currencyNamesMap = extractCurrencyNames(targetMap, id, bundle.getCurrencies());
|
||||
if (!currencyNamesMap.isEmpty() || bundle.isRoot()) {
|
||||
bundleGenerator.generateBundle("util", "CurrencyNames", id, true, currencyNamesMap, BundleType.OPEN);
|
||||
bundleGenerator.generateBundle("util", "CurrencyNames", id, currencyNamesMap, BundleType.OPEN);
|
||||
}
|
||||
}
|
||||
if (bundleTypes.contains(Bundle.Type.TIMEZONENAMES)) {
|
||||
Map<String, Object> zoneNamesMap = extractZoneNames(targetMap, id);
|
||||
if (!zoneNamesMap.isEmpty() || bundle.isRoot()) {
|
||||
bundleGenerator.generateBundle("util", "TimeZoneNames", id, true, zoneNamesMap, BundleType.TIMEZONE);
|
||||
bundleGenerator.generateBundle("util", "TimeZoneNames", id, zoneNamesMap, BundleType.TIMEZONE);
|
||||
}
|
||||
}
|
||||
if (bundleTypes.contains(Bundle.Type.CALENDARDATA)) {
|
||||
Map<String, Object> calendarDataMap = extractCalendarData(targetMap, id);
|
||||
if (!calendarDataMap.isEmpty() || bundle.isRoot()) {
|
||||
bundleGenerator.generateBundle("util", "CalendarData", id, true, calendarDataMap, BundleType.PLAIN);
|
||||
bundleGenerator.generateBundle("util", "CalendarData", id, calendarDataMap, BundleType.PLAIN);
|
||||
}
|
||||
}
|
||||
if (bundleTypes.contains(Bundle.Type.FORMATDATA)) {
|
||||
Map<String, Object> formatDataMap = extractFormatData(targetMap, id);
|
||||
if (!formatDataMap.isEmpty() || bundle.isRoot()) {
|
||||
bundleGenerator.generateBundle("text", "FormatData", id, true, formatDataMap, BundleType.PLAIN);
|
||||
bundleGenerator.generateBundle("text", "FormatData", id, formatDataMap, BundleType.PLAIN);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1053,28 +1047,15 @@ public class CLDRConverter {
|
||||
}
|
||||
}
|
||||
|
||||
// --- code below here is adapted from java.util.Properties ---
|
||||
private static final String specialSaveCharsJava = "\"";
|
||||
private static final String specialSaveCharsProperties = "=: \t\r\n\f#!";
|
||||
|
||||
/*
|
||||
* Converts unicodes to encoded \uxxxx
|
||||
* and writes out any of the characters in specialSaveChars
|
||||
* with a preceding slash
|
||||
* Escapes control codes to ASCII escapes or encoded \uxxxx
|
||||
* and writes out ASCII quotation marks with a preceding slash
|
||||
*/
|
||||
static String saveConvert(String theString, boolean useJava) {
|
||||
static String escape(String theString) {
|
||||
if (theString == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
String specialSaveChars;
|
||||
if (useJava) {
|
||||
specialSaveChars = specialSaveCharsJava;
|
||||
} else {
|
||||
specialSaveChars = specialSaveCharsProperties;
|
||||
}
|
||||
boolean escapeSpace = false;
|
||||
|
||||
int len = theString.length();
|
||||
StringBuilder outBuffer = new StringBuilder(len * 2);
|
||||
Formatter formatter = new Formatter(outBuffer, Locale.ROOT);
|
||||
@ -1083,14 +1064,14 @@ public class CLDRConverter {
|
||||
char aChar = theString.charAt(x);
|
||||
switch (aChar) {
|
||||
case ' ':
|
||||
if (x == 0 || escapeSpace) {
|
||||
if (x == 0) {
|
||||
outBuffer.append('\\');
|
||||
}
|
||||
outBuffer.append(' ');
|
||||
break;
|
||||
case '\\':
|
||||
outBuffer.append('\\');
|
||||
case '\\', '"':
|
||||
outBuffer.append('\\');
|
||||
outBuffer.append(aChar);
|
||||
break;
|
||||
case '\t':
|
||||
outBuffer.append('\\');
|
||||
@ -1109,12 +1090,9 @@ public class CLDRConverter {
|
||||
outBuffer.append('f');
|
||||
break;
|
||||
default:
|
||||
if (aChar < 0x0020 || (!USE_UTF8 && aChar > 0x007e)) {
|
||||
if (aChar < 0x0020) {
|
||||
formatter.format("\\u%04x", (int)aChar);
|
||||
} else {
|
||||
if (specialSaveChars.indexOf(aChar) != -1) {
|
||||
outBuffer.append('\\');
|
||||
}
|
||||
outBuffer.append(aChar);
|
||||
}
|
||||
}
|
||||
|
||||
@ -70,9 +70,8 @@ class ResourceBundleGenerator implements BundleGenerator {
|
||||
private static final String META_VALUE_PREFIX = "metaValue_";
|
||||
|
||||
@Override
|
||||
public void generateBundle(String packageName, String baseName, String localeID, boolean useJava,
|
||||
public void generateBundle(String packageName, String baseName, String localeID,
|
||||
Map<String, ?> map, BundleType type) throws IOException {
|
||||
String suffix = useJava ? ".java" : ".properties";
|
||||
String dirName = CLDRConverter.DESTINATION_DIR + File.separator + "sun" + File.separator
|
||||
+ packageName + File.separator + "resources" + File.separator + "cldr";
|
||||
packageName = packageName + ".resources.cldr";
|
||||
@ -91,23 +90,12 @@ class ResourceBundleGenerator implements BundleGenerator {
|
||||
if (!dir.exists()) {
|
||||
dir.mkdirs();
|
||||
}
|
||||
File file = new File(dir, baseName + ("root".equals(localeID) ? "" : "_" + localeID) + suffix);
|
||||
File file = new File(dir, baseName + ("root".equals(localeID) ? "" : "_" + localeID) + ".java");
|
||||
if (!file.exists()) {
|
||||
file.createNewFile();
|
||||
}
|
||||
CLDRConverter.info("\tWriting file " + file);
|
||||
|
||||
String encoding;
|
||||
if (useJava) {
|
||||
if (CLDRConverter.USE_UTF8) {
|
||||
encoding = "utf-8";
|
||||
} else {
|
||||
encoding = "us-ascii";
|
||||
}
|
||||
} else {
|
||||
encoding = "iso-8859-1";
|
||||
}
|
||||
|
||||
Formatter fmt = null;
|
||||
if (type == BundleType.TIMEZONE) {
|
||||
fmt = new Formatter();
|
||||
@ -119,7 +107,7 @@ class ResourceBundleGenerator implements BundleGenerator {
|
||||
value = (String[]) map.get(key);
|
||||
fmt.format(" final String[] %s = new String[] {\n", meta);
|
||||
for (String s : value) {
|
||||
fmt.format(" \"%s\",\n", CLDRConverter.saveConvert(s, useJava));
|
||||
fmt.format(" \"%s\",\n", CLDRConverter.escape(s));
|
||||
}
|
||||
fmt.format(" };\n");
|
||||
metaKeys.add(key);
|
||||
@ -159,11 +147,11 @@ class ResourceBundleGenerator implements BundleGenerator {
|
||||
if (val instanceof String[] values) {
|
||||
fmt.format(" final String[] %s = new String[] {\n", metaVal);
|
||||
for (String s : values) {
|
||||
fmt.format(" \"%s\",\n", CLDRConverter.saveConvert(s, useJava));
|
||||
fmt.format(" \"%s\",\n", CLDRConverter.escape(s));
|
||||
}
|
||||
fmt.format(" };\n");
|
||||
} else {
|
||||
fmt.format(" final String %s = \"%s\";\n", metaVal, CLDRConverter.saveConvert((String)val, useJava));
|
||||
fmt.format(" final String %s = \"%s\";\n", metaVal, CLDRConverter.escape((String)val));
|
||||
}
|
||||
newMap.put(oldEntry.key, oldEntry.metaKey());
|
||||
}
|
||||
@ -173,55 +161,47 @@ class ResourceBundleGenerator implements BundleGenerator {
|
||||
map = newMap;
|
||||
}
|
||||
|
||||
try (PrintWriter out = new PrintWriter(file, encoding)) {
|
||||
try (PrintWriter out = new PrintWriter(file, "utf-8")) {
|
||||
// Output copyright headers
|
||||
out.println(getOpenJDKCopyright());
|
||||
out.println(CopyrightHeaders.getUnicodeCopyright());
|
||||
|
||||
if (useJava) {
|
||||
out.println("package sun." + packageName + ";\n");
|
||||
out.printf("import %s;\n\n", type.getPathName());
|
||||
out.printf("public class %s%s extends %s {\n", baseName, "root".equals(localeID) ? "" : "_" + localeID, type.getClassName());
|
||||
out.println("package sun." + packageName + ";\n");
|
||||
out.printf("import %s;\n\n", type.getPathName());
|
||||
out.printf("public class %s%s extends %s {\n", baseName, "root".equals(localeID) ? "" : "_" + localeID, type.getClassName());
|
||||
|
||||
out.println(" @Override\n" +
|
||||
" protected final Object[][] getContents() {");
|
||||
if (fmt != null) {
|
||||
out.print(fmt.toString());
|
||||
}
|
||||
out.println(" final Object[][] data = new Object[][] {");
|
||||
out.println(" @Override\n" +
|
||||
" protected final Object[][] getContents() {");
|
||||
if (fmt != null) {
|
||||
out.print(fmt.toString());
|
||||
}
|
||||
out.println(" final Object[][] data = new Object[][] {");
|
||||
for (String key : map.keySet()) {
|
||||
if (useJava) {
|
||||
Object value = map.get(key);
|
||||
if (value == null) {
|
||||
CLDRConverter.warning("null value for " + key);
|
||||
} else if (value instanceof String) {
|
||||
String valStr = (String)value;
|
||||
if (type == BundleType.TIMEZONE &&
|
||||
!(key.startsWith(CLDRConverter.EXEMPLAR_CITY_PREFIX) ||
|
||||
key.startsWith(CLDRConverter.METAZONE_DSTOFFSET_PREFIX)) ||
|
||||
valStr.startsWith(META_VALUE_PREFIX)) {
|
||||
out.printf(" { \"%s\", %s },\n", key, CLDRConverter.saveConvert(valStr, useJava));
|
||||
} else {
|
||||
out.printf(" { \"%s\", \"%s\" },\n", key, CLDRConverter.saveConvert(valStr, useJava));
|
||||
}
|
||||
} else if (value instanceof String[]) {
|
||||
String[] values = (String[]) value;
|
||||
out.println(" { \"" + key + "\",\n new String[] {");
|
||||
for (String s : values) {
|
||||
out.println(" \"" + CLDRConverter.saveConvert(s, useJava) + "\",");
|
||||
}
|
||||
out.println(" }\n },");
|
||||
Object value = map.get(key);
|
||||
if (value == null) {
|
||||
CLDRConverter.warning("null value for " + key);
|
||||
} else if (value instanceof String) {
|
||||
String valStr = (String)value;
|
||||
if (type == BundleType.TIMEZONE &&
|
||||
!(key.startsWith(CLDRConverter.EXEMPLAR_CITY_PREFIX) ||
|
||||
key.startsWith(CLDRConverter.METAZONE_DSTOFFSET_PREFIX)) ||
|
||||
valStr.startsWith(META_VALUE_PREFIX)) {
|
||||
out.printf(" { \"%s\", %s },\n", key, CLDRConverter.escape(valStr));
|
||||
} else {
|
||||
throw new RuntimeException("unknown value type: " + value.getClass().getName());
|
||||
out.printf(" { \"%s\", \"%s\" },\n", key, CLDRConverter.escape(valStr));
|
||||
}
|
||||
} else if (value instanceof String[]) {
|
||||
String[] values = (String[]) value;
|
||||
out.println(" { \"" + key + "\",\n new String[] {");
|
||||
for (String s : values) {
|
||||
out.println(" \"" + CLDRConverter.escape(s) + "\",");
|
||||
}
|
||||
out.println(" }\n },");
|
||||
} else {
|
||||
out.println(key + "=" + CLDRConverter.saveConvert((String) map.get(key), useJava));
|
||||
throw new RuntimeException("unknown value type: " + value.getClass().getName());
|
||||
}
|
||||
}
|
||||
if (useJava) {
|
||||
out.println(" };\n return data;\n }\n}");
|
||||
}
|
||||
out.println(" };\n return data;\n }\n}");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
@ -47,8 +47,6 @@ CLDR_GEN_DONE := $(GENSRC_DIR)/_cldr-gensrc.marker
|
||||
TZ_DATA_DIR := $(MODULE_SRC)/share/data/tzdata
|
||||
ZONENAME_TEMPLATE := $(MODULE_SRC)/share/classes/java/time/format/ZoneName.java.template
|
||||
|
||||
# The `-utf8` option is used even for US English, as some names
|
||||
# may contain non-ASCII characters, such as “Türkiye”.
|
||||
$(CLDR_GEN_DONE): $(wildcard $(CLDR_DATA_DIR)/dtd/*.dtd) \
|
||||
$(wildcard $(CLDR_DATA_DIR)/main/en*.xml) \
|
||||
$(wildcard $(CLDR_DATA_DIR)/supplemental/*.xml) \
|
||||
@ -64,8 +62,7 @@ $(CLDR_GEN_DONE): $(wildcard $(CLDR_DATA_DIR)/dtd/*.dtd) \
|
||||
-basemodule \
|
||||
-year $(COPYRIGHT_YEAR) \
|
||||
-zntempfile $(ZONENAME_TEMPLATE) \
|
||||
-tzdatadir $(TZ_DATA_DIR) \
|
||||
-utf8)
|
||||
-tzdatadir $(TZ_DATA_DIR))
|
||||
$(TOUCH) $@
|
||||
|
||||
TARGETS += $(CLDR_GEN_DONE)
|
||||
|
||||
@ -395,6 +395,8 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBFONTMANAGER, \
|
||||
AccelGlyphCache.c, \
|
||||
CFLAGS := $(LIBFONTMANAGER_CFLAGS), \
|
||||
CXXFLAGS := $(LIBFONTMANAGER_CFLAGS), \
|
||||
CXXFLAGS_gcc := -fno-rtti -fno-exceptions, \
|
||||
CXXFLAGS_clang := -fno-rtti -fno-exceptions, \
|
||||
OPTIMIZATION := HIGHEST, \
|
||||
CFLAGS_windows = -DCC_NOEX, \
|
||||
EXTRA_HEADER_DIRS := $(LIBFONTMANAGER_EXTRA_HEADER_DIRS), \
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2014, 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
|
||||
@ -45,8 +45,7 @@ $(CLDR_GEN_DONE): $(wildcard $(CLDR_DATA_DIR)/dtd/*.dtd) \
|
||||
-baselocales "en-US" \
|
||||
-year $(COPYRIGHT_YEAR) \
|
||||
-o $(GENSRC_DIR) \
|
||||
-tzdatadir $(TZ_DATA_DIR) \
|
||||
-utf8)
|
||||
-tzdatadir $(TZ_DATA_DIR))
|
||||
$(TOUCH) $@
|
||||
|
||||
TARGETS += $(CLDR_GEN_DONE)
|
||||
|
||||
@ -7708,10 +7708,11 @@ instruct bytes_reverse_unsigned_short(iRegINoSp dst, iRegIorL2I src) %{
|
||||
match(Set dst (ReverseBytesUS src));
|
||||
|
||||
ins_cost(INSN_COST);
|
||||
format %{ "rev16w $dst, $src" %}
|
||||
format %{ "rev16w $dst, $src\t# $dst -> unsigned short" %}
|
||||
|
||||
ins_encode %{
|
||||
__ rev16w(as_Register($dst$$reg), as_Register($src$$reg));
|
||||
__ narrow_subword_type(as_Register($dst$$reg), T_CHAR);
|
||||
%}
|
||||
|
||||
ins_pipe(ialu_reg);
|
||||
|
||||
@ -567,13 +567,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 {
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2024, Red Hat Inc. 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
|
||||
@ -1254,6 +1255,13 @@ public:
|
||||
sz, 0b000, ordered);
|
||||
}
|
||||
|
||||
void load_store_volatile(Register data, BasicType type, Register addr,
|
||||
bool is_load) {
|
||||
load_store_exclusive(dummy_reg, data, dummy_reg, addr,
|
||||
(Assembler::operand_size)exact_log2(type2aelembytes(type)),
|
||||
is_load ? 0b110 : 0b100, /* ordered = */ true);
|
||||
}
|
||||
|
||||
#define INSN4(NAME, sz, op, o0) /* Four registers */ \
|
||||
void NAME(Register Rs, Register Rt1, Register Rt2, Register Rn) { \
|
||||
guarantee(Rs != Rn && Rs != Rt1 && Rs != Rt2, "unpredictable instruction"); \
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2020, Red Hat Inc. 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
|
||||
@ -911,8 +912,15 @@ void LIR_Assembler::stack2stack(LIR_Opr src, LIR_Opr dest, BasicType type) {
|
||||
reg2stack(temp, dest, dest->type());
|
||||
}
|
||||
|
||||
void LIR_Assembler::mem2reg(LIR_Opr src, LIR_Opr dest, BasicType type,
|
||||
LIR_PatchCode patch_code, CodeEmitInfo* info,
|
||||
bool wide) {
|
||||
mem2reg(src, dest, type, patch_code, info, wide, false);
|
||||
}
|
||||
|
||||
void LIR_Assembler::mem2reg(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_PatchCode patch_code, CodeEmitInfo* info, bool wide) {
|
||||
void LIR_Assembler::mem2reg(LIR_Opr src, LIR_Opr dest, BasicType type,
|
||||
LIR_PatchCode patch_code, CodeEmitInfo* info,
|
||||
bool wide, bool is_volatile) {
|
||||
LIR_Address* addr = src->as_address_ptr();
|
||||
LIR_Address* from_addr = src->as_address_ptr();
|
||||
|
||||
@ -925,10 +933,27 @@ void LIR_Assembler::mem2reg(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_Patch
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_volatile) {
|
||||
load_volatile(from_addr, dest, type, info);
|
||||
} else {
|
||||
load_unordered(from_addr, dest, type, wide, info);
|
||||
}
|
||||
|
||||
if (is_reference_type(type)) {
|
||||
if (UseCompressedOops && !wide) {
|
||||
__ decode_heap_oop(dest->as_register());
|
||||
}
|
||||
|
||||
__ verify_oop(dest->as_register());
|
||||
}
|
||||
}
|
||||
|
||||
void LIR_Assembler::load_unordered(LIR_Address *from_addr, LIR_Opr dest,
|
||||
BasicType type, bool wide, CodeEmitInfo* info) {
|
||||
if (info != nullptr) {
|
||||
add_debug_info_for_null_check_here(info);
|
||||
}
|
||||
int null_check_here = code_offset();
|
||||
|
||||
switch (type) {
|
||||
case T_FLOAT: {
|
||||
__ ldrs(dest->as_float_reg(), as_Address(from_addr));
|
||||
@ -986,16 +1011,44 @@ void LIR_Assembler::mem2reg(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_Patch
|
||||
default:
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
|
||||
if (is_reference_type(type)) {
|
||||
if (UseCompressedOops && !wide) {
|
||||
__ decode_heap_oop(dest->as_register());
|
||||
}
|
||||
|
||||
__ verify_oop(dest->as_register());
|
||||
}
|
||||
}
|
||||
|
||||
void LIR_Assembler::load_volatile(LIR_Address *from_addr, LIR_Opr dest,
|
||||
BasicType type, CodeEmitInfo* info) {
|
||||
__ lea(rscratch1, as_Address(from_addr));
|
||||
|
||||
Register dest_reg = rscratch2;
|
||||
if (!is_floating_point_type(type)) {
|
||||
dest_reg = (dest->is_single_cpu()
|
||||
? dest->as_register() : dest->as_register_lo());
|
||||
}
|
||||
|
||||
if (info != nullptr) {
|
||||
add_debug_info_for_null_check_here(info);
|
||||
}
|
||||
|
||||
// Uses LDAR to ensure memory ordering.
|
||||
__ load_store_volatile(dest_reg, type, rscratch1, /*is_load*/true);
|
||||
|
||||
switch (type) {
|
||||
// LDAR is unsigned so need to sign-extend for byte and short
|
||||
case T_BYTE:
|
||||
__ sxtb(dest_reg, dest_reg);
|
||||
break;
|
||||
case T_SHORT:
|
||||
__ sxth(dest_reg, dest_reg);
|
||||
break;
|
||||
// need to move from GPR to FPR after LDAR with FMOV for floating types
|
||||
case T_FLOAT:
|
||||
__ fmovs(dest->as_float_reg(), dest_reg);
|
||||
break;
|
||||
case T_DOUBLE:
|
||||
__ fmovd(dest->as_double_reg(), dest_reg);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int LIR_Assembler::array_element_size(BasicType type) const {
|
||||
int elem_size = type2aelembytes(type);
|
||||
@ -2764,7 +2817,9 @@ void LIR_Assembler::rt_call(LIR_Opr result, address dest, const LIR_OprList* arg
|
||||
}
|
||||
|
||||
void LIR_Assembler::volatile_move_op(LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmitInfo* info) {
|
||||
if (dest->is_address() || src->is_address()) {
|
||||
if (src->is_address()) {
|
||||
mem2reg(src, dest, type, lir_patch_none, info, /*wide*/false, /*is_volatile*/true);
|
||||
} else if (dest->is_address()) {
|
||||
move_op(src, dest, type, lir_patch_none, info, /*wide*/false);
|
||||
} else {
|
||||
ShouldNotReachHere();
|
||||
|
||||
@ -57,6 +57,12 @@ friend class ArrayCopyStub;
|
||||
void casw(Register addr, Register newval, Register cmpval);
|
||||
void casl(Register addr, Register newval, Register cmpval);
|
||||
|
||||
void mem2reg(LIR_Opr src, LIR_Opr dest, BasicType type,
|
||||
LIR_PatchCode patch_code,
|
||||
CodeEmitInfo* info, bool wide, bool is_volatile);
|
||||
void load_unordered(LIR_Address *from_addr, LIR_Opr dest, BasicType type, bool wide, CodeEmitInfo* info);
|
||||
void load_volatile(LIR_Address *from_addr, LIR_Opr dest, BasicType type, CodeEmitInfo* info);
|
||||
|
||||
static const int max_tableswitches = 20;
|
||||
struct tableswitch switches[max_tableswitches];
|
||||
int tableswitch_count;
|
||||
|
||||
@ -1398,14 +1398,5 @@ void LIRGenerator::volatile_field_store(LIR_Opr value, LIR_Address* address,
|
||||
|
||||
void LIRGenerator::volatile_field_load(LIR_Address* address, LIR_Opr result,
|
||||
CodeEmitInfo* info) {
|
||||
// 8179954: We need to make sure that the code generated for
|
||||
// volatile accesses forms a sequentially-consistent set of
|
||||
// operations when combined with STLR and LDAR. Without a leading
|
||||
// membar it's possible for a simple Dekker test to fail if loads
|
||||
// use LD;DMB but stores use STLR. This can happen if C2 compiles
|
||||
// the stores in one method and C1 compiles the loads in another.
|
||||
if (!CompilerConfig::is_c1_only_no_jvmci()) {
|
||||
__ membar();
|
||||
}
|
||||
__ volatile_load_mem_reg(address, result, info);
|
||||
}
|
||||
|
||||
@ -50,14 +50,10 @@ void LIR_OpShenandoahCompareAndSwap::emit_code(LIR_Assembler* masm) {
|
||||
|
||||
ShenandoahBarrierSet::assembler()->cmpxchg_oop(masm->masm(), addr, cmpval, newval, /*acquire*/ true, /*release*/ true, /*is_cae*/ false, result);
|
||||
|
||||
if (CompilerConfig::is_c1_only_no_jvmci()) {
|
||||
// The membar here is necessary to prevent reordering between the
|
||||
// release store in the CAS above and a subsequent volatile load.
|
||||
// However for tiered compilation C1 inserts a full barrier before
|
||||
// volatile loads which means we don't need an additional barrier
|
||||
// here (see LIRGenerator::volatile_field_load()).
|
||||
__ membar(__ AnyAny);
|
||||
}
|
||||
// The membar here is necessary to prevent reordering between the
|
||||
// release store in the CAS above and a subsequent volatile load.
|
||||
// See also: LIR_Assembler::casw, LIR_Assembler::casl.
|
||||
__ membar(__ AnyAny);
|
||||
}
|
||||
|
||||
#undef __
|
||||
|
||||
@ -2815,6 +2815,17 @@ void MacroAssembler::store_sized_value(Address dst, Register src, size_t size_in
|
||||
}
|
||||
}
|
||||
|
||||
void MacroAssembler::narrow_subword_type(Register reg, BasicType bt) {
|
||||
assert(is_subword_type(bt), "required");
|
||||
switch (bt) {
|
||||
case T_BOOLEAN: andw(reg, reg, 1); break;
|
||||
case T_BYTE: sxtbw(reg, reg); break;
|
||||
case T_CHAR: uxthw(reg, reg); break;
|
||||
case T_SHORT: sxthw(reg, reg); break;
|
||||
default: ShouldNotReachHere();
|
||||
}
|
||||
}
|
||||
|
||||
void MacroAssembler::decrementw(Register reg, int value)
|
||||
{
|
||||
if (value < 0) { incrementw(reg, -value); return; }
|
||||
|
||||
@ -33,6 +33,7 @@
|
||||
#include "oops/compressedOops.hpp"
|
||||
#include "oops/compressedKlass.hpp"
|
||||
#include "runtime/vm_version.hpp"
|
||||
#include "utilities/globalDefinitions.hpp"
|
||||
#include "utilities/powerOfTwo.hpp"
|
||||
|
||||
class OopMap;
|
||||
@ -719,6 +720,9 @@ public:
|
||||
// Support for sign-extension (hi:lo = extend_sign(lo))
|
||||
void extend_sign(Register hi, Register lo);
|
||||
|
||||
// Clean up a subword typed value to the representation in compliance with JVMS §2.3
|
||||
void narrow_subword_type(Register reg, BasicType bt);
|
||||
|
||||
// Load and store values by size and signed-ness
|
||||
void load_sized_value(Register dst, Address src, size_t size_in_bytes, bool is_signed);
|
||||
void store_sized_value(Address dst, Register src, size_t size_in_bytes);
|
||||
|
||||
@ -3479,7 +3479,6 @@ void TemplateTable::invokeinterface(int byte_no) {
|
||||
__ bind(notVFinal);
|
||||
|
||||
// Get receiver klass into r3
|
||||
__ restore_locals();
|
||||
__ load_klass(r3, r2);
|
||||
|
||||
Label no_such_method;
|
||||
|
||||
@ -305,9 +305,9 @@ void VM_Version::initialize() {
|
||||
FLAG_SET_DEFAULT(UseSHA, false);
|
||||
}
|
||||
|
||||
CHECK_CPU_FEATURE(supports_crc32, CRC32);
|
||||
CHECK_CPU_FEATURE(supports_lse, LSE);
|
||||
CHECK_CPU_FEATURE(supports_aes, AES);
|
||||
CHECK_CPU_FEATURE(UseCRC32, CRC32, supports_crc32(), MULTI_INST_WARNING_MSG);
|
||||
CHECK_CPU_FEATURE(UseLSE, LSE, supports_lse(), MULTI_INST_WARNING_MSG);
|
||||
CHECK_CPU_FEATURE(UseAES, AES, supports_aes(), MULTI_INST_WARNING_MSG);
|
||||
|
||||
if (_cpu == CPU_ARM &&
|
||||
model_is_in({ CPU_MODEL_ARM_NEOVERSE_V1, CPU_MODEL_ARM_NEOVERSE_V2,
|
||||
@ -789,9 +789,9 @@ void VM_Version::store_cpu_features(void* buf) {
|
||||
*(uint64_t*)buf = _features;
|
||||
}
|
||||
|
||||
bool VM_Version::supports_features(void* features_buffer) {
|
||||
bool VM_Version::verify_aot_code_cache_features(void* features_buffer) {
|
||||
uint64_t features_to_test = *(uint64_t*)features_buffer;
|
||||
return (_features & features_to_test) == features_to_test;
|
||||
return (_features == features_to_test);
|
||||
}
|
||||
|
||||
#if defined(LINUX)
|
||||
|
||||
@ -279,7 +279,7 @@ public:
|
||||
// Size of the buffer must be same as returned by cpu_features_size()
|
||||
static void store_cpu_features(void* buf);
|
||||
|
||||
static bool supports_features(void* features_to_test);
|
||||
static bool verify_aot_code_cache_features(void* features_buffer);
|
||||
};
|
||||
|
||||
#endif // CPU_AARCH64_VM_VERSION_AARCH64_HPP
|
||||
|
||||
@ -9214,10 +9214,12 @@ instruct bytes_reverse_long(iRegL dst, iRegL src) %{
|
||||
|
||||
instruct bytes_reverse_unsigned_short(iRegI dst, iRegI src) %{
|
||||
match(Set dst (ReverseBytesUS src));
|
||||
size(4);
|
||||
format %{ "REV16 $dst,$src" %}
|
||||
size(8);
|
||||
format %{ "REV32 $dst,$src\n\t"
|
||||
"LSR $dst,$dst,#16" %}
|
||||
ins_encode %{
|
||||
__ rev16($dst$$Register, $src$$Register);
|
||||
__ rev($dst$$Register, $src$$Register);
|
||||
__ mov($dst$$Register, AsmOperand($dst$$Register, lsr, 16));
|
||||
%}
|
||||
ins_pipe( iload_mem ); // FIXME
|
||||
%}
|
||||
|
||||
@ -1332,7 +1332,8 @@ void LIRGenerator::volatile_field_load(LIR_Address* address, LIR_Opr result,
|
||||
load_addr = address;
|
||||
}
|
||||
__ volatile_load_mem_reg(load_addr, result, info);
|
||||
return;
|
||||
} else {
|
||||
__ load(address, result, info, lir_patch_none);
|
||||
}
|
||||
__ load(address, result, info, lir_patch_none);
|
||||
__ membar_acquire();
|
||||
}
|
||||
|
||||
@ -1143,6 +1143,7 @@ void LIRGenerator::volatile_field_load(LIR_Address* address, LIR_Opr result,
|
||||
Unimplemented();
|
||||
// __ volatile_load_mem_reg(address, result, info);
|
||||
#endif
|
||||
__ membar_acquire();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -540,6 +540,8 @@ template<typename FKind> frame ThawBase::new_stack_frame(const frame& hf, frame&
|
||||
intptr_t* frame_sp = caller.sp() - fsize;
|
||||
|
||||
if ((bottom && argsize > 0) || caller.is_interpreted_frame()) {
|
||||
assert(!_should_patch_caller_pc, "");
|
||||
_should_patch_caller_pc = caller.is_interpreted_frame();
|
||||
frame_sp -= argsize + frame::metadata_words_at_top;
|
||||
frame_sp = align_down(frame_sp, frame::alignment_in_bytes);
|
||||
caller.set_sp(frame_sp + fsize);
|
||||
|
||||
@ -354,19 +354,9 @@ int SaveLiveRegisters::iterate_over_register_mask(IterationAction action, int of
|
||||
Register spill_addr = R0;
|
||||
int spill_offset = offset - reg_save_index * BytesPerWord;
|
||||
if (action == ACTION_SAVE) {
|
||||
if (PowerArchitecturePPC64 >= 9) {
|
||||
_masm->stxv(vs_reg, spill_offset, R1_SP);
|
||||
} else {
|
||||
_masm->addi(spill_addr, R1_SP, spill_offset);
|
||||
_masm->stxvd2x(vs_reg, spill_addr);
|
||||
}
|
||||
_masm->stxv(vs_reg, spill_offset, R1_SP);
|
||||
} else if (action == ACTION_RESTORE) {
|
||||
if (PowerArchitecturePPC64 >= 9) {
|
||||
_masm->lxv(vs_reg, spill_offset, R1_SP);
|
||||
} else {
|
||||
_masm->addi(spill_addr, R1_SP, spill_offset);
|
||||
_masm->lxvd2x(vs_reg, spill_addr);
|
||||
}
|
||||
_masm->lxv(vs_reg, spill_offset, R1_SP);
|
||||
} else {
|
||||
assert(action == ACTION_COUNT_ONLY, "Sanity");
|
||||
}
|
||||
|
||||
@ -116,7 +116,8 @@ define_pd_global(intx, InitArrayShortSize, 9*BytesPerLong);
|
||||
\
|
||||
/* special instructions */ \
|
||||
product(bool, SuperwordUseVSX, false, \
|
||||
"Use VSX instructions for superword optimization.") \
|
||||
"Use VSX instructions for superword optimization " \
|
||||
"(default for Power9 and later).") \
|
||||
\
|
||||
product(bool, UseByteReverseInstructions, false, DIAGNOSTIC, \
|
||||
"Use byte reverse instructions.") \
|
||||
|
||||
@ -799,13 +799,7 @@ void MacroAssembler::save_nonvolatile_registers(Register dst, int offset, bool i
|
||||
}
|
||||
} else {
|
||||
for (int i = 20; i < 32; i++) {
|
||||
if (PowerArchitecturePPC64 >= 9) {
|
||||
stxv(as_VectorRegister(i)->to_vsr(), offset, dst);
|
||||
} else {
|
||||
Register spill_addr = R0;
|
||||
addi(spill_addr, dst, offset);
|
||||
stxvd2x(as_VectorRegister(i)->to_vsr(), spill_addr);
|
||||
}
|
||||
stxv(as_VectorRegister(i)->to_vsr(), offset, dst);
|
||||
offset += 16;
|
||||
}
|
||||
}
|
||||
@ -838,13 +832,7 @@ void MacroAssembler::restore_nonvolatile_registers(Register src, int offset, boo
|
||||
}
|
||||
} else {
|
||||
for (int i = 20; i < 32; i++) {
|
||||
if (PowerArchitecturePPC64 >= 9) {
|
||||
lxv(as_VectorRegister(i)->to_vsr(), offset, src);
|
||||
} else {
|
||||
Register spill_addr = R0;
|
||||
addi(spill_addr, src, offset);
|
||||
lxvd2x(as_VectorRegister(i)->to_vsr(), spill_addr);
|
||||
}
|
||||
lxv(as_VectorRegister(i)->to_vsr(), offset, src);
|
||||
offset += 16;
|
||||
}
|
||||
}
|
||||
@ -3214,7 +3202,7 @@ void MacroAssembler::store_klass_gap(Register dst_oop, Register val) {
|
||||
stw(val, oopDesc::klass_gap_offset_in_bytes(), dst_oop);
|
||||
}
|
||||
|
||||
int MacroAssembler::instr_size_for_decode_klass_not_null() {
|
||||
int MacroAssembler::instr_size_for_load_klass() {
|
||||
static int computed_size = -1;
|
||||
|
||||
// Not yet computed?
|
||||
@ -3222,10 +3210,10 @@ int MacroAssembler::instr_size_for_decode_klass_not_null() {
|
||||
|
||||
// Determine by scratch emit.
|
||||
ResourceMark rm;
|
||||
int code_size = 8 * BytesPerInstWord;
|
||||
CodeBuffer cb("decode_klass_not_null scratch buffer", code_size, 0);
|
||||
int code_size = 16 * BytesPerInstWord;
|
||||
CodeBuffer cb("load_klass scratch buffer", code_size, 0);
|
||||
MacroAssembler* a = new MacroAssembler(&cb);
|
||||
a->decode_klass_not_null(R11_scratch1);
|
||||
a->load_klass(R11_scratch1, R11_scratch1);
|
||||
computed_size = a->offset();
|
||||
}
|
||||
|
||||
|
||||
@ -802,7 +802,7 @@ class MacroAssembler: public Assembler {
|
||||
MacroAssembler::PreservationLevel preservation_level);
|
||||
void load_method_holder(Register holder, Register method);
|
||||
|
||||
static int instr_size_for_decode_klass_not_null();
|
||||
static int instr_size_for_load_klass();
|
||||
void decode_klass_not_null(Register dst, Register src = noreg);
|
||||
Register encode_klass_not_null(Register dst, Register src = noreg);
|
||||
|
||||
|
||||
@ -38,10 +38,10 @@
|
||||
return false;
|
||||
}
|
||||
|
||||
// The PPC implementation uses VSX lxvd2x/stxvd2x instructions (if
|
||||
// The PPC implementation uses VSX lxv/stxv instructions (if
|
||||
// SuperwordUseVSX). They do not have alignment requirements.
|
||||
// Some VSX storage access instructions cannot encode arbitrary displacements
|
||||
// (e.g. lxv). None of them is currently used.
|
||||
// (e.g. lxv). We use memoryAlg16 for them.
|
||||
static constexpr bool misaligned_vectors_ok() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1187,7 +1187,7 @@ int MachCallDynamicJavaNode::ret_addr_offset() {
|
||||
assert(vtable_index == Method::invalid_vtable_index, "correct sentinel value");
|
||||
return 12;
|
||||
} else {
|
||||
return 24 + MacroAssembler::instr_size_for_decode_klass_not_null();
|
||||
return 20 + MacroAssembler::instr_size_for_load_klass();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1818,52 +1818,26 @@ uint MachSpillCopyNode::implementation(C2_MacroAssembler *masm, PhaseRegAlloc *r
|
||||
// VectorRegister->Memory Spill.
|
||||
else if (src_lo_rc == rc_vec && dst_lo_rc == rc_stack) {
|
||||
VectorSRegister Rsrc = as_VectorRegister(Matcher::_regEncode[src_lo]).to_vsr();
|
||||
if (PowerArchitecturePPC64 >= 9) {
|
||||
if (masm) {
|
||||
__ stxv(Rsrc, dst_offset, R1_SP); // matches storeV16_Power9
|
||||
}
|
||||
size += 4;
|
||||
} else {
|
||||
if (masm) {
|
||||
__ addi(R0, R1_SP, dst_offset);
|
||||
__ stxvd2x(Rsrc, R0); // matches storeV16_Power8
|
||||
}
|
||||
size += 8;
|
||||
if (masm) {
|
||||
__ stxv(Rsrc, dst_offset, R1_SP); // matches storeV16
|
||||
}
|
||||
size += 4;
|
||||
#ifndef PRODUCT
|
||||
if (st != nullptr) {
|
||||
if (PowerArchitecturePPC64 >= 9) {
|
||||
st->print("%-7s %s, [R1_SP + #%d] \t// vector spill copy", "STXV", Matcher::regName[src_lo], dst_offset);
|
||||
} else {
|
||||
st->print("%-7s R0, R1_SP, %d \t// vector spill copy\n\t"
|
||||
"%-7s %s, [R0] \t// vector spill copy", "ADDI", dst_offset, "STXVD2X", Matcher::regName[src_lo]);
|
||||
}
|
||||
st->print("%-7s %s, [R1_SP + #%d] \t// vector spill copy", "STXV", Matcher::regName[src_lo], dst_offset);
|
||||
}
|
||||
#endif // !PRODUCT
|
||||
}
|
||||
// Memory->VectorRegister Spill.
|
||||
else if (src_lo_rc == rc_stack && dst_lo_rc == rc_vec) {
|
||||
VectorSRegister Rdst = as_VectorRegister(Matcher::_regEncode[dst_lo]).to_vsr();
|
||||
if (PowerArchitecturePPC64 >= 9) {
|
||||
if (masm) {
|
||||
__ lxv(Rdst, src_offset, R1_SP);
|
||||
}
|
||||
size += 4;
|
||||
} else {
|
||||
if (masm) {
|
||||
__ addi(R0, R1_SP, src_offset);
|
||||
__ lxvd2x(Rdst, R0);
|
||||
}
|
||||
size += 8;
|
||||
if (masm) {
|
||||
__ lxv(Rdst, src_offset, R1_SP);
|
||||
}
|
||||
size += 4;
|
||||
#ifndef PRODUCT
|
||||
if (st != nullptr) {
|
||||
if (PowerArchitecturePPC64 >= 9) {
|
||||
st->print("%-7s %s, [R1_SP + #%d] \t// vector spill copy", "LXV", Matcher::regName[dst_lo], src_offset);
|
||||
} else {
|
||||
st->print("%-7s R0, R1_SP, %d \t// vector spill copy\n\t"
|
||||
"%-7s %s, [R0] \t// vector spill copy", "ADDI", src_offset, "LXVD2X", Matcher::regName[dst_lo]);
|
||||
}
|
||||
st->print("%-7s %s, [R1_SP + #%d] \t// vector spill copy", "LXV", Matcher::regName[dst_lo], src_offset);
|
||||
}
|
||||
#endif // !PRODUCT
|
||||
}
|
||||
@ -2284,7 +2258,7 @@ bool Matcher::match_rule_supported_vector(int opcode, int vlen, BasicType bt) {
|
||||
case Op_UMaxV:
|
||||
return bt == T_INT || bt == T_LONG;
|
||||
case Op_NegVI:
|
||||
return PowerArchitecturePPC64 >= 9 && bt == T_INT;
|
||||
return bt == T_INT;
|
||||
}
|
||||
return true; // Per default match rules are supported.
|
||||
}
|
||||
@ -2322,10 +2296,12 @@ OptoRegPair Matcher::vector_return_value(uint ideal_reg) {
|
||||
// Vector width in bytes.
|
||||
int Matcher::vector_width_in_bytes(BasicType bt) {
|
||||
if (SuperwordUseVSX) {
|
||||
assert(MaxVectorSize == 16, "");
|
||||
assert(MaxVectorSize == 16,
|
||||
"SuperwordUseVSX requires MaxVectorSize 16, got " INT64_FORMAT, (int64_t)MaxVectorSize);
|
||||
return 16;
|
||||
} else {
|
||||
assert(MaxVectorSize == 8, "");
|
||||
assert(MaxVectorSize == 8,
|
||||
"expected MaxVectorSize 8, got " INT64_FORMAT, (int64_t)MaxVectorSize);
|
||||
return 8;
|
||||
}
|
||||
}
|
||||
@ -2333,10 +2309,14 @@ int Matcher::vector_width_in_bytes(BasicType bt) {
|
||||
// Vector ideal reg.
|
||||
uint Matcher::vector_ideal_reg(int size) {
|
||||
if (SuperwordUseVSX) {
|
||||
assert(MaxVectorSize == 16 && size == 16, "");
|
||||
assert(MaxVectorSize == 16 && size == 16,
|
||||
"SuperwordUseVSX requires MaxVectorSize 16 and size 16, got MaxVectorSize=" INT64_FORMAT ", size=%d",
|
||||
(int64_t)MaxVectorSize, size);
|
||||
return Op_VecX;
|
||||
} else {
|
||||
assert(MaxVectorSize == 8 && size == 8, "");
|
||||
assert(MaxVectorSize == 8 && size == 8,
|
||||
"expected MaxVectorSize 8 and size 8, got MaxVectorSize=" INT64_FORMAT ", size=%d",
|
||||
(int64_t)MaxVectorSize, size);
|
||||
return Op_RegL;
|
||||
}
|
||||
}
|
||||
@ -5413,23 +5393,9 @@ instruct loadV8(iRegLdst dst, memoryAlg4 mem) %{
|
||||
ins_pipe(pipe_class_memory);
|
||||
%}
|
||||
|
||||
// Load Aligned Packed Byte
|
||||
// Note: The Power8 instruction loads the contents in a special order in Little Endian mode.
|
||||
instruct loadV16_Power8(vecX dst, indirect mem) %{
|
||||
predicate(n->as_LoadVector()->memory_size() == 16 && PowerArchitecturePPC64 == 8);
|
||||
match(Set dst (LoadVector mem));
|
||||
ins_cost(MEMORY_REF_COST);
|
||||
|
||||
format %{ "LXVD2X $dst, $mem \t// load 16-byte Vector" %}
|
||||
size(4);
|
||||
ins_encode %{
|
||||
__ lxvd2x($dst$$VectorRegister.to_vsr(), $mem$$Register);
|
||||
%}
|
||||
ins_pipe(pipe_class_default);
|
||||
%}
|
||||
|
||||
instruct loadV16_Power9(vecX dst, memoryAlg16 mem) %{
|
||||
predicate(n->as_LoadVector()->memory_size() == 16 && PowerArchitecturePPC64 >= 9);
|
||||
instruct loadV16(vecX dst, memoryAlg16 mem) %{
|
||||
predicate(n->as_LoadVector()->memory_size() == 16);
|
||||
match(Set dst (LoadVector mem));
|
||||
ins_cost(MEMORY_REF_COST);
|
||||
|
||||
@ -6424,23 +6390,9 @@ instruct storeA8B(memoryAlg4 mem, iRegLsrc src) %{
|
||||
ins_pipe(pipe_class_memory);
|
||||
%}
|
||||
|
||||
// Store Packed Byte long register to memory
|
||||
// Note: The Power8 instruction stores the contents in a special order in Little Endian mode.
|
||||
instruct storeV16_Power8(indirect mem, vecX src) %{
|
||||
predicate(n->as_StoreVector()->memory_size() == 16 && PowerArchitecturePPC64 == 8);
|
||||
match(Set mem (StoreVector mem src));
|
||||
ins_cost(MEMORY_REF_COST);
|
||||
|
||||
format %{ "STXVD2X $mem, $src \t// store 16-byte Vector" %}
|
||||
size(4);
|
||||
ins_encode %{
|
||||
__ stxvd2x($src$$VectorRegister.to_vsr(), $mem$$Register);
|
||||
%}
|
||||
ins_pipe(pipe_class_default);
|
||||
%}
|
||||
|
||||
instruct storeV16_Power9(memoryAlg16 mem, vecX src) %{
|
||||
predicate(n->as_StoreVector()->memory_size() == 16 && PowerArchitecturePPC64 >= 9);
|
||||
instruct storeV16(memoryAlg16 mem, vecX src) %{
|
||||
predicate(n->as_StoreVector()->memory_size() == 16);
|
||||
match(Set mem (StoreVector mem src));
|
||||
ins_cost(MEMORY_REF_COST);
|
||||
|
||||
@ -12480,6 +12432,19 @@ instruct countTrailingZerosL_cnttzd(iRegIdst dst, iRegLsrc src) %{
|
||||
ins_pipe(pipe_class_default);
|
||||
%}
|
||||
|
||||
// Expand nodes for byte_reverse_int/ushort/short.
|
||||
instruct rlwinm(iRegIdst dst, iRegIsrc src, immI16 shift, immI16 mb, immI16 me) %{
|
||||
effect(DEF dst, USE src, USE shift, USE mb, USE me);
|
||||
predicate(false);
|
||||
|
||||
format %{ "RLWINM $dst, $src, $shift, $mb, $me" %}
|
||||
size(4);
|
||||
ins_encode %{
|
||||
__ rlwinm($dst$$Register, $src$$Register, $shift$$constant, $mb$$constant, $me$$constant);
|
||||
%}
|
||||
ins_pipe(pipe_class_default);
|
||||
%}
|
||||
|
||||
// Expand nodes for byte_reverse_int.
|
||||
instruct insrwi_a(iRegIdst dst, iRegIsrc src, immI16 n, immI16 b) %{
|
||||
effect(DEF dst, USE src, USE n, USE b);
|
||||
@ -12636,34 +12601,22 @@ instruct bytes_reverse_long(iRegLdst dst, iRegLsrc src) %{
|
||||
ins_pipe(pipe_class_default);
|
||||
%}
|
||||
|
||||
// Need zero extend. Must not use brh only.
|
||||
instruct bytes_reverse_ushort_Ex(iRegIdst dst, iRegIsrc src) %{
|
||||
match(Set dst (ReverseBytesUS src));
|
||||
predicate(!UseByteReverseInstructions);
|
||||
ins_cost(2*DEFAULT_COST);
|
||||
|
||||
expand %{
|
||||
immI16 imm31 %{ (int) 31 %}
|
||||
immI16 imm24 %{ (int) 24 %}
|
||||
immI16 imm16 %{ (int) 16 %}
|
||||
immI16 imm8 %{ (int) 8 %}
|
||||
|
||||
urShiftI_reg_imm(dst, src, imm8);
|
||||
rlwinm(dst, src, imm24, imm24, imm31);
|
||||
insrwi(dst, src, imm8, imm16);
|
||||
%}
|
||||
%}
|
||||
|
||||
instruct bytes_reverse_ushort(iRegIdst dst, iRegIsrc src) %{
|
||||
match(Set dst (ReverseBytesUS src));
|
||||
predicate(UseByteReverseInstructions);
|
||||
ins_cost(DEFAULT_COST);
|
||||
size(4);
|
||||
|
||||
format %{ "BRH $dst, $src" %}
|
||||
|
||||
ins_encode %{
|
||||
__ brh($dst$$Register, $src$$Register);
|
||||
%}
|
||||
ins_pipe(pipe_class_default);
|
||||
%}
|
||||
|
||||
instruct bytes_reverse_short_Ex(iRegIdst dst, iRegIsrc src) %{
|
||||
match(Set dst (ReverseBytesS src));
|
||||
predicate(!UseByteReverseInstructions);
|
||||
@ -13656,7 +13609,7 @@ instruct vneg2D_reg(vecX dst, vecX src) %{
|
||||
|
||||
instruct vneg4I_reg(vecX dst, vecX src) %{
|
||||
match(Set dst (NegVI src));
|
||||
predicate(PowerArchitecturePPC64 >= 9 && Matcher::vector_element_basic_type(n) == T_INT);
|
||||
predicate(Matcher::vector_element_basic_type(n) == T_INT);
|
||||
format %{ "VNEGW $dst,$src\t// negate int vector" %}
|
||||
size(4);
|
||||
ins_encode %{
|
||||
|
||||
@ -360,7 +360,7 @@ OopMap* RegisterSaver::push_frame_reg_args_and_save_live_registers(MacroAssemble
|
||||
assert(RegisterSaver_LiveVecRegs[i + 1].reg_num == reg_num + 1, "or use other instructions!");
|
||||
|
||||
__ stxvp(as_VectorRegister(reg_num).to_vsr(), offset, R1_SP);
|
||||
// Note: The contents were read in the same order (see loadV16_Power9 node in ppc.ad).
|
||||
// Note: The contents were read in the same order (see loadV16 node in ppc.ad).
|
||||
// RegisterMap::pd_location only uses the first VMReg for each VectorRegister.
|
||||
if (generate_oop_map) {
|
||||
map->set_callee_saved(VMRegImpl::stack2reg(offset >> 2),
|
||||
@ -374,13 +374,8 @@ OopMap* RegisterSaver::push_frame_reg_args_and_save_live_registers(MacroAssemble
|
||||
for (int i = 0; i < vecregstosave_num; i++) {
|
||||
int reg_num = RegisterSaver_LiveVecRegs[i].reg_num;
|
||||
|
||||
if (PowerArchitecturePPC64 >= 9) {
|
||||
__ stxv(as_VectorRegister(reg_num)->to_vsr(), offset, R1_SP);
|
||||
} else {
|
||||
__ li(R31, offset);
|
||||
__ stxvd2x(as_VectorRegister(reg_num)->to_vsr(), R31, R1_SP);
|
||||
}
|
||||
// Note: The contents were read in the same order (see loadV16_Power8 / loadV16_Power9 node in ppc.ad).
|
||||
__ stxv(as_VectorRegister(reg_num)->to_vsr(), offset, R1_SP);
|
||||
// Note: The contents were read in the same order (see loadV16 node in ppc.ad).
|
||||
// RegisterMap::pd_location only uses the first VMReg for each VectorRegister.
|
||||
if (generate_oop_map) {
|
||||
VMReg vsr = RegisterSaver_LiveVecRegs[i].vmreg;
|
||||
@ -464,12 +459,7 @@ void RegisterSaver::restore_live_registers_and_pop_frame(MacroAssembler* masm,
|
||||
for (int i = 0; i < vecregstosave_num; i++) {
|
||||
int reg_num = RegisterSaver_LiveVecRegs[i].reg_num;
|
||||
|
||||
if (PowerArchitecturePPC64 >= 9) {
|
||||
__ lxv(as_VectorRegister(reg_num).to_vsr(), offset, R1_SP);
|
||||
} else {
|
||||
__ li(R31, offset);
|
||||
__ lxvd2x(as_VectorRegister(reg_num).to_vsr(), R31, R1_SP);
|
||||
}
|
||||
__ lxv(as_VectorRegister(reg_num).to_vsr(), offset, R1_SP);
|
||||
|
||||
offset += vec_reg_size;
|
||||
}
|
||||
|
||||
@ -109,6 +109,9 @@ void VM_Version::initialize() {
|
||||
if (FLAG_IS_DEFAULT(SuperwordUseVSX) && CompilerConfig::is_c2_enabled()) {
|
||||
FLAG_SET_ERGO(SuperwordUseVSX, true);
|
||||
}
|
||||
} else if (SuperwordUseVSX) {
|
||||
warning("SuperwordUseVSX specified, but needs at least Power9.");
|
||||
FLAG_SET_DEFAULT(SuperwordUseVSX, false);
|
||||
}
|
||||
|
||||
MaxVectorSize = SuperwordUseVSX ? 16 : 8;
|
||||
|
||||
@ -1169,4 +1169,5 @@ void LIRGenerator::volatile_field_store(LIR_Opr value, LIR_Address* address,
|
||||
void LIRGenerator::volatile_field_load(LIR_Address* address, LIR_Opr result,
|
||||
CodeEmitInfo* info) {
|
||||
__ volatile_load_mem_reg(address, result, info);
|
||||
__ membar_acquire();
|
||||
}
|
||||
|
||||
@ -3069,12 +3069,12 @@ void C2_MacroAssembler::reduce_mul_integral_v(Register dst, Register src1, Vecto
|
||||
// If the operation is MUL, then the identity value is one.
|
||||
vmv_v_i(vtmp1, 1);
|
||||
vmerge_vvm(vtmp2, vtmp1, src2); // vm == v0
|
||||
vslidedown_vi(vtmp1, vtmp2, vector_length);
|
||||
slidedown_v(vtmp1, vtmp2, vector_length);
|
||||
|
||||
vsetvli_helper(bt, vector_length);
|
||||
vmul_vv(vtmp1, vtmp1, vtmp2);
|
||||
} else {
|
||||
vslidedown_vi(vtmp1, src2, vector_length);
|
||||
slidedown_v(vtmp1, src2, vector_length);
|
||||
|
||||
vsetvli_helper(bt, vector_length);
|
||||
vmul_vv(vtmp1, vtmp1, src2);
|
||||
@ -3082,7 +3082,7 @@ void C2_MacroAssembler::reduce_mul_integral_v(Register dst, Register src1, Vecto
|
||||
|
||||
while (vector_length > 1) {
|
||||
vector_length /= 2;
|
||||
vslidedown_vi(vtmp2, vtmp1, vector_length);
|
||||
slidedown_v(vtmp2, vtmp1, vector_length);
|
||||
vsetvli_helper(bt, vector_length);
|
||||
vmul_vv(vtmp1, vtmp1, vtmp2);
|
||||
}
|
||||
@ -3281,40 +3281,44 @@ VFCVT_SAFE(vfcvt_rtz_x_f_v);
|
||||
|
||||
// Extract a scalar element from an vector at position 'idx'.
|
||||
// The input elements in src are expected to be of integral type.
|
||||
void C2_MacroAssembler::extract_v(Register dst, VectorRegister src, BasicType bt,
|
||||
int idx, VectorRegister tmp) {
|
||||
void C2_MacroAssembler::extract_v(Register dst, VectorRegister src,
|
||||
BasicType bt, int idx, VectorRegister vtmp) {
|
||||
assert(is_integral_type(bt), "unsupported element type");
|
||||
assert(idx >= 0, "idx cannot be negative");
|
||||
// Only need the first element after vector slidedown
|
||||
vsetvli_helper(bt, 1);
|
||||
if (idx == 0) {
|
||||
vmv_x_s(dst, src);
|
||||
} else if (idx <= 31) {
|
||||
vslidedown_vi(tmp, src, idx);
|
||||
vmv_x_s(dst, tmp);
|
||||
} else {
|
||||
mv(t0, idx);
|
||||
vslidedown_vx(tmp, src, t0);
|
||||
vmv_x_s(dst, tmp);
|
||||
slidedown_v(vtmp, src, idx);
|
||||
vmv_x_s(dst, vtmp);
|
||||
}
|
||||
}
|
||||
|
||||
// Extract a scalar element from an vector at position 'idx'.
|
||||
// The input elements in src are expected to be of floating point type.
|
||||
void C2_MacroAssembler::extract_fp_v(FloatRegister dst, VectorRegister src, BasicType bt,
|
||||
int idx, VectorRegister tmp) {
|
||||
void C2_MacroAssembler::extract_fp_v(FloatRegister dst, VectorRegister src,
|
||||
BasicType bt, int idx, VectorRegister vtmp) {
|
||||
assert(is_floating_point_type(bt), "unsupported element type");
|
||||
assert(idx >= 0, "idx cannot be negative");
|
||||
// Only need the first element after vector slidedown
|
||||
vsetvli_helper(bt, 1);
|
||||
if (idx == 0) {
|
||||
vfmv_f_s(dst, src);
|
||||
} else if (idx <= 31) {
|
||||
vslidedown_vi(tmp, src, idx);
|
||||
vfmv_f_s(dst, tmp);
|
||||
} else {
|
||||
mv(t0, idx);
|
||||
vslidedown_vx(tmp, src, t0);
|
||||
vfmv_f_s(dst, tmp);
|
||||
slidedown_v(vtmp, src, idx);
|
||||
vfmv_f_s(dst, vtmp);
|
||||
}
|
||||
}
|
||||
|
||||
// Move elements down a vector register group.
|
||||
// Offset is the start index (offset) for the source.
|
||||
void C2_MacroAssembler::slidedown_v(VectorRegister dst, VectorRegister src,
|
||||
uint32_t offset, Register tmp) {
|
||||
if (is_uimm5(offset)) {
|
||||
vslidedown_vi(dst, src, offset);
|
||||
} else {
|
||||
mv(tmp, offset);
|
||||
vslidedown_vx(dst, src, tmp);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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.
|
||||
* Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -296,7 +296,13 @@
|
||||
|
||||
void vfcvt_rtz_x_f_v_safe(VectorRegister dst, VectorRegister src);
|
||||
|
||||
void extract_v(Register dst, VectorRegister src, BasicType bt, int idx, VectorRegister tmp);
|
||||
void extract_fp_v(FloatRegister dst, VectorRegister src, BasicType bt, int idx, VectorRegister tmp);
|
||||
void extract_v(Register dst, VectorRegister src,
|
||||
BasicType bt, int idx, VectorRegister vtmp);
|
||||
|
||||
void extract_fp_v(FloatRegister dst, VectorRegister src,
|
||||
BasicType bt, int idx, VectorRegister vtmp);
|
||||
|
||||
void slidedown_v(VectorRegister dst, VectorRegister src,
|
||||
uint32_t offset, Register tmp = t0);
|
||||
|
||||
#endif // CPU_RISCV_C2_MACROASSEMBLER_RISCV_HPP
|
||||
|
||||
@ -734,6 +734,7 @@ public:
|
||||
#define __ masm->
|
||||
|
||||
void ZBarrierSetAssembler::generate_c2_load_barrier_stub(MacroAssembler* masm, ZLoadBarrierStubC2* stub) const {
|
||||
Assembler::InlineSkippedInstructionsCounter skipped_counter(masm);
|
||||
BLOCK_COMMENT("ZLoadBarrierStubC2");
|
||||
|
||||
// Stub entry
|
||||
@ -753,6 +754,7 @@ void ZBarrierSetAssembler::generate_c2_load_barrier_stub(MacroAssembler* masm, Z
|
||||
}
|
||||
|
||||
void ZBarrierSetAssembler::generate_c2_store_barrier_stub(MacroAssembler* masm, ZStoreBarrierStubC2* stub) const {
|
||||
Assembler::InlineSkippedInstructionsCounter skipped_counter(masm);
|
||||
BLOCK_COMMENT("ZStoreBarrierStubC2");
|
||||
|
||||
// Stub entry
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
// Copyright (c) 2019, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
// Copyright (c) 2020, 2023, Huawei Technologies Co., Ltd. All rights reserved.
|
||||
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
//
|
||||
@ -57,6 +57,7 @@ static void check_color(MacroAssembler* masm, Register ref, bool on_non_strong,
|
||||
}
|
||||
|
||||
static void z_load_barrier(MacroAssembler* masm, const MachNode* node, Address ref_addr, Register ref, Register tmp) {
|
||||
Assembler::InlineSkippedInstructionsCounter skipped_counter(masm);
|
||||
const bool on_non_strong =
|
||||
((node->barrier_data() & ZBarrierWeak) != 0) ||
|
||||
((node->barrier_data() & ZBarrierPhantom) != 0);
|
||||
@ -78,6 +79,7 @@ static void z_load_barrier(MacroAssembler* masm, const MachNode* node, Address r
|
||||
}
|
||||
|
||||
static void z_store_barrier(MacroAssembler* masm, const MachNode* node, Address ref_addr, Register rnew_zaddress, Register rnew_zpointer, Register tmp, bool is_atomic) {
|
||||
Assembler::InlineSkippedInstructionsCounter skipped_counter(masm);
|
||||
if (node->barrier_data() == ZBarrierElided) {
|
||||
z_color(masm, node, rnew_zpointer, rnew_zaddress, tmp);
|
||||
} else {
|
||||
|
||||
@ -3389,7 +3389,6 @@ void TemplateTable::invokeinterface(int byte_no) {
|
||||
__ bind(notVFinal);
|
||||
|
||||
// Get receiver klass into x13
|
||||
__ restore_locals();
|
||||
__ load_klass(x13, x12);
|
||||
|
||||
Label no_such_method;
|
||||
|
||||
@ -1046,6 +1046,7 @@ void LIRGenerator::volatile_field_store(LIR_Opr value, LIR_Address* address,
|
||||
void LIRGenerator::volatile_field_load(LIR_Address* address, LIR_Opr result,
|
||||
CodeEmitInfo* info) {
|
||||
__ load(address, result, info);
|
||||
__ membar_acquire();
|
||||
}
|
||||
|
||||
void LIRGenerator::do_update_CRC32(Intrinsic* x) {
|
||||
|
||||
@ -281,6 +281,7 @@ void G1BarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet decorator
|
||||
if (on_oop && on_reference && L_handle_null == nullptr) { L_handle_null = &done; }
|
||||
CardTableBarrierSetAssembler::load_at(masm, decorators, type, src, dst, tmp1, tmp2, L_handle_null);
|
||||
if (on_oop && on_reference) {
|
||||
assert(tmp1 != noreg && tmp2 != noreg, "need temp registers for G1 pre-barrier");
|
||||
// Generate the G1 pre-barrier code to log the value of
|
||||
// the referent field in an SATB buffer.
|
||||
g1_write_barrier_pre(masm, decorators | IS_NOT_NULL,
|
||||
|
||||
@ -411,7 +411,7 @@ void InterpreterMacroAssembler::load_resolved_reference_at_index(Register result
|
||||
// Load pointer for resolved_references[] objArray.
|
||||
z_lg(result, in_bytes(ConstantPool::cache_offset()), result);
|
||||
z_lg(result, in_bytes(ConstantPoolCache::resolved_references_offset()), result);
|
||||
resolve_oop_handle(result); // Load resolved references array itself.
|
||||
resolve_oop_handle(result, Z_R0_scratch, Z_R1_scratch); // Load resolved references array itself.
|
||||
#ifdef ASSERT
|
||||
NearLabel index_ok;
|
||||
z_lgf(Z_R0, Address(result, arrayOopDesc::length_offset_in_bytes()));
|
||||
|
||||
@ -4705,16 +4705,8 @@ void MacroAssembler::oop_decoder(Register Rdst, Register Rsrc, bool maybenull, R
|
||||
}
|
||||
|
||||
// ((OopHandle)result).resolve();
|
||||
void MacroAssembler::resolve_oop_handle(Register result) {
|
||||
// OopHandle::resolve is an indirection.
|
||||
z_lg(result, 0, result);
|
||||
}
|
||||
|
||||
void MacroAssembler::load_mirror_from_const_method(Register mirror, Register const_method) {
|
||||
mem2reg_opt(mirror, Address(const_method, ConstMethod::constants_offset()));
|
||||
mem2reg_opt(mirror, Address(mirror, ConstantPool::pool_holder_offset()));
|
||||
mem2reg_opt(mirror, Address(mirror, Klass::java_mirror_offset()));
|
||||
resolve_oop_handle(mirror);
|
||||
void MacroAssembler::resolve_oop_handle(Register result, Register tmp1, Register tmp2) {
|
||||
access_load_at(T_OBJECT, IN_NATIVE, Address(result, 0), result, tmp1, tmp2);
|
||||
}
|
||||
|
||||
void MacroAssembler::load_method_holder(Register holder, Register method) {
|
||||
@ -5886,6 +5878,28 @@ void MacroAssembler::asm_assert_frame_size(Register expected_size, Register tmp,
|
||||
#endif // ASSERT
|
||||
}
|
||||
|
||||
#ifdef ASSERT
|
||||
bool is_excluded(Register excluded_register[], Register reg, int n) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
if (excluded_register[i] == reg) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void MacroAssembler::clobber_volatile_registers(Register excluded_register[], int n) {
|
||||
const int magic_number = 0x82;
|
||||
|
||||
for (int i = 0; i < 6 /* R0 to R5 */; i++) {
|
||||
Register reg = as_Register(i);
|
||||
if (!is_excluded(excluded_register, reg, n)) {
|
||||
load_const_optimized(reg, magic_number);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // ASSERT
|
||||
|
||||
// Save and restore functions: Exclude Z_R0.
|
||||
void MacroAssembler::save_volatile_regs(Register dst, int offset, bool include_fp, bool include_flags) {
|
||||
z_stmg(Z_R1, Z_R5, offset, dst); offset += 5 * BytesPerWord;
|
||||
|
||||
@ -484,6 +484,10 @@ class MacroAssembler: public Assembler {
|
||||
// Pop current C frame and restore return PC register (Z_R14).
|
||||
void pop_frame_restore_retPC(int frame_size_in_bytes);
|
||||
|
||||
#ifdef ASSERT
|
||||
void clobber_volatile_registers(Register excluded_register[], int n);
|
||||
#endif // ASSERT
|
||||
|
||||
//
|
||||
// Calls
|
||||
//
|
||||
@ -885,8 +889,7 @@ class MacroAssembler: public Assembler {
|
||||
void oop_decoder(Register Rdst, Register Rsrc, bool maybenull,
|
||||
Register Rbase = Z_R1, int pow2_offset = -1);
|
||||
|
||||
void resolve_oop_handle(Register result);
|
||||
void load_mirror_from_const_method(Register mirror, Register const_method);
|
||||
void resolve_oop_handle(Register result, Register tmp1, Register tmp2);
|
||||
void load_method_holder(Register holder, Register method);
|
||||
|
||||
//--------------------------
|
||||
|
||||
@ -1113,6 +1113,7 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call) {
|
||||
{
|
||||
// locals
|
||||
const Register local_addr = Z_ARG4;
|
||||
const Register constants_addr = Z_ARG2;
|
||||
|
||||
BLOCK_COMMENT("generate_fixed_frame: initialize interpreter state {");
|
||||
|
||||
@ -1128,8 +1129,8 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call) {
|
||||
__ z_stg(Z_R10, _z_ijava_state_neg(sender_sp), fp);
|
||||
|
||||
// Load cp cache and save it at the end of this block.
|
||||
__ z_lg(Z_R1_scratch, Address(const_method, ConstMethod::constants_offset()));
|
||||
__ z_lg(Z_R1_scratch, Address(Z_R1_scratch, ConstantPool::cache_offset()));
|
||||
__ z_lg(constants_addr, Address(const_method, ConstMethod::constants_offset()));
|
||||
__ z_lg(Z_R1_scratch, Address(constants_addr, ConstantPool::cache_offset()));
|
||||
|
||||
// z_ijava_state->method = method;
|
||||
__ z_stg(Z_method, _z_ijava_state_neg(method), fp);
|
||||
@ -1192,7 +1193,9 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call) {
|
||||
__ z_stg(Z_R1_scratch, _z_ijava_state_neg(cpoolCache), fp);
|
||||
|
||||
// Get mirror and store it in the frame as GC root for this Method*.
|
||||
__ load_mirror_from_const_method(Z_R1_scratch, const_method);
|
||||
__ mem2reg_opt(Z_R1_scratch, Address(constants_addr, ConstantPool::pool_holder_offset()));
|
||||
__ mem2reg_opt(Z_R1_scratch, Address(Z_R1_scratch, Klass::java_mirror_offset()));
|
||||
__ resolve_oop_handle(Z_R1_scratch, Z_R0_scratch, Z_R1_scratch);
|
||||
__ z_stg(Z_R1_scratch, _z_ijava_state_neg(mirror), fp);
|
||||
|
||||
BLOCK_COMMENT("} generate_fixed_frame: initialize interpreter state");
|
||||
@ -2028,7 +2031,7 @@ address TemplateInterpreterGenerator::generate_currentThread() {
|
||||
uint64_t entry_off = __ offset();
|
||||
|
||||
__ z_lg(Z_RET, Address(Z_thread, JavaThread::threadObj_offset()));
|
||||
__ resolve_oop_handle(Z_RET);
|
||||
__ resolve_oop_handle(Z_RET, Z_R0_scratch, Z_R1_scratch);
|
||||
|
||||
// Restore caller sp for c2i case.
|
||||
__ resize_frame_absolute(Z_R10, Z_R0, true); // Cut the stack back to where the caller started.
|
||||
|
||||
@ -480,8 +480,9 @@ void TemplateTable::fast_aldc(LdcType type) {
|
||||
|
||||
// Convert null sentinel to null.
|
||||
__ load_const_optimized(Z_R1_scratch, (intptr_t)Universe::the_null_sentinel_addr());
|
||||
__ resolve_oop_handle(Z_R1_scratch);
|
||||
__ z_cg(Z_tos, Address(Z_R1_scratch));
|
||||
__ z_lg(Z_R1_scratch, Address(Z_R1_scratch));
|
||||
__ resolve_oop_handle(Z_R1_scratch, Z_R0_scratch, Z_R1_scratch);
|
||||
__ z_cgr(Z_tos, Z_R1_scratch);
|
||||
__ z_brne(L_resolved);
|
||||
__ clear_reg(Z_tos);
|
||||
__ z_bru(L_resolved);
|
||||
@ -2478,7 +2479,7 @@ void TemplateTable::load_resolved_field_entry(Register obj,
|
||||
if (is_static) {
|
||||
__ load_sized_value(obj, Address(cache, ResolvedFieldEntry::field_holder_offset()), sizeof(void*), false);
|
||||
__ load_sized_value(obj, Address(obj, in_bytes(Klass::java_mirror_offset())), sizeof(void*), false);
|
||||
__ resolve_oop_handle(obj);
|
||||
__ resolve_oop_handle(obj, Z_R0_scratch, Z_R1_scratch);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1664,14 +1664,14 @@ void Assembler::eandl(Register dst, Register src1, Register src2, bool no_flags)
|
||||
}
|
||||
|
||||
void Assembler::andnl(Register dst, Register src1, Register src2) {
|
||||
assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported");
|
||||
assert(VM_Version::supports_bmi1() && VM_Version::supports_avx(), "bit manipulation instructions not supported");
|
||||
InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
|
||||
int encode = vex_prefix_and_encode(dst->encoding(), src1->encoding(), src2->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_38, &attributes, true);
|
||||
emit_int16((unsigned char)0xF2, (0xC0 | encode));
|
||||
}
|
||||
|
||||
void Assembler::andnl(Register dst, Register src1, Address src2) {
|
||||
assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported");
|
||||
assert(VM_Version::supports_bmi1() && VM_Version::supports_avx(), "bit manipulation instructions not supported");
|
||||
InstructionMark im(this);
|
||||
InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
|
||||
attributes.set_address_attributes(/* tuple_type */ EVEX_NOSCALE, /* input_size_in_bits */ EVEX_32bit);
|
||||
@ -1696,14 +1696,14 @@ void Assembler::bswapl(Register reg) { // bswap
|
||||
}
|
||||
|
||||
void Assembler::blsil(Register dst, Register src) {
|
||||
assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported");
|
||||
assert(VM_Version::supports_bmi1() && VM_Version::supports_avx(), "bit manipulation instructions not supported");
|
||||
InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
|
||||
int encode = vex_prefix_and_encode(rbx->encoding(), dst->encoding(), src->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_38, &attributes, true);
|
||||
emit_int16((unsigned char)0xF3, (0xC0 | encode));
|
||||
}
|
||||
|
||||
void Assembler::blsil(Register dst, Address src) {
|
||||
assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported");
|
||||
assert(VM_Version::supports_bmi1() && VM_Version::supports_avx(), "bit manipulation instructions not supported");
|
||||
InstructionMark im(this);
|
||||
InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
|
||||
attributes.set_address_attributes(/* tuple_type */ EVEX_NOSCALE, /* input_size_in_bits */ EVEX_32bit);
|
||||
@ -1713,7 +1713,7 @@ void Assembler::blsil(Register dst, Address src) {
|
||||
}
|
||||
|
||||
void Assembler::blsmskl(Register dst, Register src) {
|
||||
assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported");
|
||||
assert(VM_Version::supports_bmi1() && VM_Version::supports_avx(), "bit manipulation instructions not supported");
|
||||
InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
|
||||
int encode = vex_prefix_and_encode(rdx->encoding(), dst->encoding(), src->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_38, &attributes, true);
|
||||
emit_int16((unsigned char)0xF3,
|
||||
@ -1721,7 +1721,7 @@ void Assembler::blsmskl(Register dst, Register src) {
|
||||
}
|
||||
|
||||
void Assembler::blsmskl(Register dst, Address src) {
|
||||
assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported");
|
||||
assert(VM_Version::supports_bmi1() && VM_Version::supports_avx(), "bit manipulation instructions not supported");
|
||||
InstructionMark im(this);
|
||||
InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
|
||||
attributes.set_address_attributes(/* tuple_type */ EVEX_NOSCALE, /* input_size_in_bits */ EVEX_32bit);
|
||||
@ -1731,14 +1731,14 @@ void Assembler::blsmskl(Register dst, Address src) {
|
||||
}
|
||||
|
||||
void Assembler::blsrl(Register dst, Register src) {
|
||||
assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported");
|
||||
assert(VM_Version::supports_bmi1() && VM_Version::supports_avx(), "bit manipulation instructions not supported");
|
||||
InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
|
||||
int encode = vex_prefix_and_encode(rcx->encoding(), dst->encoding(), src->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_38, &attributes, true);
|
||||
emit_int16((unsigned char)0xF3, (0xC0 | encode));
|
||||
}
|
||||
|
||||
void Assembler::blsrl(Register dst, Address src) {
|
||||
assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported");
|
||||
assert(VM_Version::supports_bmi1() && VM_Version::supports_avx(), "bit manipulation instructions not supported");
|
||||
InstructionMark im(this);
|
||||
InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
|
||||
attributes.set_address_attributes(/* tuple_type */ EVEX_NOSCALE, /* input_size_in_bits */ EVEX_32bit);
|
||||
@ -7275,21 +7275,21 @@ void Assembler::testl(Register dst, Address src) {
|
||||
}
|
||||
|
||||
void Assembler::tzcntl(Register dst, Register src) {
|
||||
assert(VM_Version::supports_bmi1(), "tzcnt instruction not supported");
|
||||
assert(UseCountTrailingZerosInstruction, "tzcnt instruction not supported");
|
||||
emit_int8((unsigned char)0xF3);
|
||||
int encode = prefix_and_encode(dst->encoding(), src->encoding(), true /* is_map1 */);
|
||||
emit_opcode_prefix_and_encoding((unsigned char)0xBC, 0xC0, encode);
|
||||
}
|
||||
|
||||
void Assembler::etzcntl(Register dst, Register src, bool no_flags) {
|
||||
assert(VM_Version::supports_bmi1(), "tzcnt instruction not supported");
|
||||
assert(UseCountTrailingZerosInstruction, "tzcnt instruction not supported");
|
||||
InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
|
||||
int encode = eevex_prefix_and_encode_nf(dst->encoding(), 0, src->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_3C /* MAP4 */, &attributes, no_flags);
|
||||
emit_int16((unsigned char)0xF4, (0xC0 | encode));
|
||||
}
|
||||
|
||||
void Assembler::tzcntl(Register dst, Address src) {
|
||||
assert(VM_Version::supports_bmi1(), "tzcnt instruction not supported");
|
||||
assert(UseCountTrailingZerosInstruction, "tzcnt instruction not supported");
|
||||
InstructionMark im(this);
|
||||
emit_int8((unsigned char)0xF3);
|
||||
prefix(src, dst, false, true /* is_map1 */);
|
||||
@ -7298,7 +7298,7 @@ void Assembler::tzcntl(Register dst, Address src) {
|
||||
}
|
||||
|
||||
void Assembler::etzcntl(Register dst, Address src, bool no_flags) {
|
||||
assert(VM_Version::supports_bmi1(), "tzcnt instruction not supported");
|
||||
assert(UseCountTrailingZerosInstruction, "tzcnt instruction not supported");
|
||||
InstructionMark im(this);
|
||||
InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
|
||||
attributes.set_address_attributes(/* tuple_type */ EVEX_NOSCALE, /* input_size_in_bits */ EVEX_32bit);
|
||||
@ -7308,21 +7308,21 @@ void Assembler::etzcntl(Register dst, Address src, bool no_flags) {
|
||||
}
|
||||
|
||||
void Assembler::tzcntq(Register dst, Register src) {
|
||||
assert(VM_Version::supports_bmi1(), "tzcnt instruction not supported");
|
||||
assert(UseCountTrailingZerosInstruction, "tzcnt instruction not supported");
|
||||
emit_int8((unsigned char)0xF3);
|
||||
int encode = prefixq_and_encode(dst->encoding(), src->encoding(), true /* is_map1 */);
|
||||
emit_opcode_prefix_and_encoding((unsigned char)0xBC, 0xC0, encode);
|
||||
}
|
||||
|
||||
void Assembler::etzcntq(Register dst, Register src, bool no_flags) {
|
||||
assert(VM_Version::supports_bmi1(), "tzcnt instruction not supported");
|
||||
assert(UseCountTrailingZerosInstruction, "tzcnt instruction not supported");
|
||||
InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
|
||||
int encode = eevex_prefix_and_encode_nf(dst->encoding(), 0, src->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_3C /* MAP4 */, &attributes, no_flags);
|
||||
emit_int16((unsigned char)0xF4, (0xC0 | encode));
|
||||
}
|
||||
|
||||
void Assembler::tzcntq(Register dst, Address src) {
|
||||
assert(VM_Version::supports_bmi1(), "tzcnt instruction not supported");
|
||||
assert(UseCountTrailingZerosInstruction, "tzcnt instruction not supported");
|
||||
InstructionMark im(this);
|
||||
emit_int8((unsigned char)0xF3);
|
||||
prefixq(src, dst, true /* is_map1 */);
|
||||
@ -7331,7 +7331,7 @@ void Assembler::tzcntq(Register dst, Address src) {
|
||||
}
|
||||
|
||||
void Assembler::etzcntq(Register dst, Address src, bool no_flags) {
|
||||
assert(VM_Version::supports_bmi1(), "tzcnt instruction not supported");
|
||||
assert(UseCountTrailingZerosInstruction, "tzcnt instruction not supported");
|
||||
InstructionMark im(this);
|
||||
InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
|
||||
attributes.set_address_attributes(/* tuple_type */ EVEX_NOSCALE, /* input_size_in_bits */ EVEX_64bit);
|
||||
@ -15000,14 +15000,14 @@ void Assembler::eandq(Register dst, Address src1, Register src2, bool no_flags)
|
||||
}
|
||||
|
||||
void Assembler::andnq(Register dst, Register src1, Register src2) {
|
||||
assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported");
|
||||
assert(VM_Version::supports_bmi1() && VM_Version::supports_avx(), "bit manipulation instructions not supported");
|
||||
InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
|
||||
int encode = vex_prefix_and_encode(dst->encoding(), src1->encoding(), src2->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_38, &attributes, true);
|
||||
emit_int16((unsigned char)0xF2, (0xC0 | encode));
|
||||
}
|
||||
|
||||
void Assembler::andnq(Register dst, Register src1, Address src2) {
|
||||
assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported");
|
||||
assert(VM_Version::supports_bmi1() && VM_Version::supports_avx(), "bit manipulation instructions not supported");
|
||||
InstructionMark im(this);
|
||||
InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
|
||||
attributes.set_address_attributes(/* tuple_type */ EVEX_NOSCALE, /* input_size_in_bits */ EVEX_64bit);
|
||||
@ -15032,14 +15032,14 @@ void Assembler::bswapq(Register reg) {
|
||||
}
|
||||
|
||||
void Assembler::blsiq(Register dst, Register src) {
|
||||
assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported");
|
||||
assert(VM_Version::supports_bmi1() && VM_Version::supports_avx(), "bit manipulation instructions not supported");
|
||||
InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
|
||||
int encode = vex_prefix_and_encode(rbx->encoding(), dst->encoding(), src->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_38, &attributes, true);
|
||||
emit_int16((unsigned char)0xF3, (0xC0 | encode));
|
||||
}
|
||||
|
||||
void Assembler::blsiq(Register dst, Address src) {
|
||||
assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported");
|
||||
assert(VM_Version::supports_bmi1() && VM_Version::supports_avx(), "bit manipulation instructions not supported");
|
||||
InstructionMark im(this);
|
||||
InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
|
||||
attributes.set_address_attributes(/* tuple_type */ EVEX_NOSCALE, /* input_size_in_bits */ EVEX_64bit);
|
||||
@ -15049,14 +15049,14 @@ void Assembler::blsiq(Register dst, Address src) {
|
||||
}
|
||||
|
||||
void Assembler::blsmskq(Register dst, Register src) {
|
||||
assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported");
|
||||
assert(VM_Version::supports_bmi1() && VM_Version::supports_avx(), "bit manipulation instructions not supported");
|
||||
InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
|
||||
int encode = vex_prefix_and_encode(rdx->encoding(), dst->encoding(), src->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_38, &attributes, true);
|
||||
emit_int16((unsigned char)0xF3, (0xC0 | encode));
|
||||
}
|
||||
|
||||
void Assembler::blsmskq(Register dst, Address src) {
|
||||
assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported");
|
||||
assert(VM_Version::supports_bmi1() && VM_Version::supports_avx(), "bit manipulation instructions not supported");
|
||||
InstructionMark im(this);
|
||||
InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
|
||||
attributes.set_address_attributes(/* tuple_type */ EVEX_NOSCALE, /* input_size_in_bits */ EVEX_64bit);
|
||||
@ -15066,14 +15066,14 @@ void Assembler::blsmskq(Register dst, Address src) {
|
||||
}
|
||||
|
||||
void Assembler::blsrq(Register dst, Register src) {
|
||||
assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported");
|
||||
assert(VM_Version::supports_bmi1() && VM_Version::supports_avx(), "bit manipulation instructions not supported");
|
||||
InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
|
||||
int encode = vex_prefix_and_encode(rcx->encoding(), dst->encoding(), src->encoding(), VEX_SIMD_NONE, VEX_OPCODE_0F_38, &attributes, true);
|
||||
emit_int16((unsigned char)0xF3, (0xC0 | encode));
|
||||
}
|
||||
|
||||
void Assembler::blsrq(Register dst, Address src) {
|
||||
assert(VM_Version::supports_bmi1(), "bit manipulation instructions not supported");
|
||||
assert(VM_Version::supports_bmi1() && VM_Version::supports_avx(), "bit manipulation instructions not supported");
|
||||
InstructionMark im(this);
|
||||
InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
|
||||
attributes.set_address_attributes(/* tuple_type */ EVEX_NOSCALE, /* input_size_in_bits */ EVEX_64bit);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 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
|
||||
@ -293,7 +293,7 @@ void PatchingStub::emit_code(LIR_Assembler* ce) {
|
||||
address ptr = (address)(_pc_start + i);
|
||||
int a_byte = (*ptr) & 0xFF;
|
||||
__ emit_int8(a_byte);
|
||||
*ptr = 0x90; // make the site look like a nop
|
||||
*ptr = NativeInstruction::nop_instruction_code; // make the site look like a nop
|
||||
}
|
||||
}
|
||||
|
||||
@ -342,6 +342,38 @@ void PatchingStub::emit_code(LIR_Assembler* ce) {
|
||||
assert(patch_info_pc - end_of_patch == bytes_to_skip, "incorrect patch info");
|
||||
|
||||
address entry = __ pc();
|
||||
// NativeGeneralJump::insert_unconditional will be writing a jmp rel32 at _pc_start over the existing instructions.
|
||||
// There are 2 cases:
|
||||
// - the existing instruction is a mov r64 imm64 from LIR_Assembler::klass2reg_with_patching
|
||||
// - or there are nops there (from higher in this function).
|
||||
// In the first case, since a jmp rel32 is 5-byte long, but a mov r64 imm64 is 10-byte long
|
||||
// (resp. 11 if using a REX2 prefix), so we are left with the last 5 (resp. 6) bytes of the
|
||||
// immediate operand (which are all 0x00). When debugging, this confuses the disassembler
|
||||
// because it tries to recognize an instruction starting immediately after the jmp rel32,
|
||||
// leading to wrong instructions, and possibly failure to disassemble further the whole function.
|
||||
//
|
||||
// To be disassembler-friendly, let's replace the leftover 0x00 with nops.
|
||||
// There are 2 shapes:
|
||||
// - without REX2 prefix: REX prefix | MOV r64
|
||||
// - with REX2 prefix: REX2 prefix | REX prefix | MOV r64
|
||||
// then, we know the 8 bytes after are the immediate operand.
|
||||
if (NativeInstruction* ni = nativeInstruction_at(_pc_start); ni->is_mov_literal64()) {
|
||||
int length_before_immediate = ni->has_rex2_prefix() ? 3 : 2;
|
||||
assert(*(long long int*)(_pc_start + length_before_immediate) == 0, "imm64 must be 0 in mov r64, imm64");
|
||||
// We don't need to replace the NativeGeneralJump::instruction_size first bytes, since insert_unconditional
|
||||
// will overwrite.
|
||||
for (int i = NativeGeneralJump::instruction_size; i < length_before_immediate + BytesPerLong; ++i) {
|
||||
_pc_start[i] = NativeInstruction::nop_instruction_code;
|
||||
}
|
||||
}
|
||||
#ifdef ASSERT
|
||||
else { // and we make sure otherwise, we indeed have just nops.
|
||||
for (int i = 0; i < NativeGeneralJump::instruction_size; ++i) {
|
||||
assert(_pc_start[i] == NativeInstruction::nop_instruction_code, "patching over an unexpected instruction");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
NativeGeneralJump::insert_unconditional((address)_pc_start, entry);
|
||||
address target = nullptr;
|
||||
relocInfo::relocType reloc_type = relocInfo::none;
|
||||
|
||||
@ -1432,4 +1432,5 @@ void LIRGenerator::volatile_field_load(LIR_Address* address, LIR_Opr result,
|
||||
} else {
|
||||
__ load(address, result, info);
|
||||
}
|
||||
__ membar_acquire();
|
||||
}
|
||||
|
||||
@ -5558,7 +5558,7 @@ void C2_MacroAssembler::vector_mask_operation_helper(int opc, Register dst, Regi
|
||||
}
|
||||
break;
|
||||
case Op_VectorMaskFirstTrue:
|
||||
if (VM_Version::supports_bmi1()) {
|
||||
if (UseCountTrailingZerosInstruction) {
|
||||
if (masklen < 32) {
|
||||
orl(tmp, 1 << masklen);
|
||||
tzcntl(dst, tmp);
|
||||
@ -6350,7 +6350,7 @@ void C2_MacroAssembler::udivI(Register rax, Register divisor, Register rdx) {
|
||||
// See Hacker's Delight (2nd ed), section 9.3 which is implemented in java.lang.Long.divideUnsigned()
|
||||
movl(rdx, rax);
|
||||
subl(rdx, divisor);
|
||||
if (VM_Version::supports_bmi1()) {
|
||||
if (VM_Version::supports_bmi1() && VM_Version::supports_avx()) {
|
||||
andnl(rax, rdx, rax);
|
||||
} else {
|
||||
notl(rdx);
|
||||
@ -6374,7 +6374,7 @@ void C2_MacroAssembler::umodI(Register rax, Register divisor, Register rdx) {
|
||||
// See Hacker's Delight (2nd ed), section 9.3 which is implemented in java.lang.Long.remainderUnsigned()
|
||||
movl(rdx, rax);
|
||||
subl(rax, divisor);
|
||||
if (VM_Version::supports_bmi1()) {
|
||||
if (VM_Version::supports_bmi1() && VM_Version::supports_avx()) {
|
||||
andnl(rax, rax, rdx);
|
||||
} else {
|
||||
notl(rax);
|
||||
@ -6403,7 +6403,7 @@ void C2_MacroAssembler::udivmodI(Register rax, Register divisor, Register rdx, R
|
||||
// java.lang.Long.divideUnsigned() and java.lang.Long.remainderUnsigned()
|
||||
movl(rdx, rax);
|
||||
subl(rax, divisor);
|
||||
if (VM_Version::supports_bmi1()) {
|
||||
if (VM_Version::supports_bmi1() && VM_Version::supports_avx()) {
|
||||
andnl(rax, rax, rdx);
|
||||
} else {
|
||||
notl(rax);
|
||||
@ -6515,7 +6515,7 @@ void C2_MacroAssembler::udivL(Register rax, Register divisor, Register rdx) {
|
||||
// See Hacker's Delight (2nd ed), section 9.3 which is implemented in java.lang.Long.divideUnsigned()
|
||||
movq(rdx, rax);
|
||||
subq(rdx, divisor);
|
||||
if (VM_Version::supports_bmi1()) {
|
||||
if (VM_Version::supports_bmi1() && VM_Version::supports_avx()) {
|
||||
andnq(rax, rdx, rax);
|
||||
} else {
|
||||
notq(rdx);
|
||||
@ -6539,7 +6539,7 @@ void C2_MacroAssembler::umodL(Register rax, Register divisor, Register rdx) {
|
||||
// See Hacker's Delight (2nd ed), section 9.3 which is implemented in java.lang.Long.remainderUnsigned()
|
||||
movq(rdx, rax);
|
||||
subq(rax, divisor);
|
||||
if (VM_Version::supports_bmi1()) {
|
||||
if (VM_Version::supports_bmi1() && VM_Version::supports_avx()) {
|
||||
andnq(rax, rax, rdx);
|
||||
} else {
|
||||
notq(rax);
|
||||
@ -6567,7 +6567,7 @@ void C2_MacroAssembler::udivmodL(Register rax, Register divisor, Register rdx, R
|
||||
// java.lang.Long.divideUnsigned() and java.lang.Long.remainderUnsigned()
|
||||
movq(rdx, rax);
|
||||
subq(rax, divisor);
|
||||
if (VM_Version::supports_bmi1()) {
|
||||
if (VM_Version::supports_bmi1() && VM_Version::supports_avx()) {
|
||||
andnq(rax, rax, rdx);
|
||||
} else {
|
||||
notq(rax);
|
||||
|
||||
@ -55,6 +55,7 @@
|
||||
#include "runtime/sharedRuntime.hpp"
|
||||
#include "runtime/stubRoutines.hpp"
|
||||
#include "utilities/checkedCast.hpp"
|
||||
#include "utilities/globalDefinitions.hpp"
|
||||
#include "utilities/macros.hpp"
|
||||
|
||||
#ifdef PRODUCT
|
||||
@ -2540,6 +2541,17 @@ void MacroAssembler::sign_extend_short(Register reg) {
|
||||
movswl(reg, reg); // movsxw
|
||||
}
|
||||
|
||||
void MacroAssembler::narrow_subword_type(Register reg, BasicType bt) {
|
||||
assert(is_subword_type(bt), "required");
|
||||
switch (bt) {
|
||||
case T_BOOLEAN: andl(reg, 1); break;
|
||||
case T_BYTE: movsbl(reg, reg); break;
|
||||
case T_CHAR: movzwl(reg, reg); break;
|
||||
case T_SHORT: movswl(reg, reg); break;
|
||||
default: ShouldNotReachHere();
|
||||
}
|
||||
}
|
||||
|
||||
void MacroAssembler::testl(Address dst, int32_t imm32) {
|
||||
if (imm32 >= 0 && is8bit(imm32)) {
|
||||
testb(dst, imm32);
|
||||
@ -6955,7 +6967,7 @@ void MacroAssembler::vectorized_mismatch(Register obja, Register objb, Register
|
||||
xorq(result, result);
|
||||
|
||||
if ((AVX3Threshold == 0) && (UseAVX > 2) &&
|
||||
VM_Version::supports_avx512vlbw()) {
|
||||
VM_Version::supports_avx512vlbw() && UseCountTrailingZerosInstruction) {
|
||||
Label VECTOR64_LOOP, VECTOR64_NOT_EQUAL, VECTOR32_TAIL;
|
||||
|
||||
cmpq(length, 64);
|
||||
|
||||
@ -444,6 +444,9 @@ class MacroAssembler: public Assembler {
|
||||
void sign_extend_short(Register reg);
|
||||
void sign_extend_byte(Register reg);
|
||||
|
||||
// Clean up a subword typed value to the representation in compliance with JVMS §2.3
|
||||
void narrow_subword_type(Register reg, BasicType bt);
|
||||
|
||||
// Division by power of 2, rounding towards 0
|
||||
void division_with_shift(Register reg, int shift_value);
|
||||
|
||||
|
||||
@ -97,11 +97,7 @@ class NativeInstruction {
|
||||
};
|
||||
|
||||
inline NativeInstruction* nativeInstruction_at(address address) {
|
||||
NativeInstruction* inst = (NativeInstruction*)address;
|
||||
#ifdef ASSERT
|
||||
//inst->verify();
|
||||
#endif
|
||||
return inst;
|
||||
return (NativeInstruction*)address;
|
||||
}
|
||||
|
||||
class NativeCall;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 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
|
||||
@ -4891,7 +4891,7 @@ void StubGenerator::generate_compiler_stubs() {
|
||||
StubRoutines::_data_cache_writeback_sync = generate_data_cache_writeback_sync();
|
||||
|
||||
#ifdef COMPILER2
|
||||
if ((UseAVX == 2) && EnableX86ECoreOpts) {
|
||||
if ((UseAVX == 2) && EnableX86ECoreOpts && UseCountTrailingZerosInstruction) {
|
||||
generate_string_indexof(StubRoutines::_string_indexof_array);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -942,21 +942,21 @@ void VM_Version::get_processor_features() {
|
||||
}
|
||||
|
||||
if (UseSSE < 4) {
|
||||
_features.clear_feature(CPU_SSE4_1);
|
||||
_features.clear_feature(CPU_SSE4_2);
|
||||
clear_feature(CPU_SSE4_1);
|
||||
clear_feature(CPU_SSE4_2);
|
||||
}
|
||||
|
||||
if (UseSSE < 3) {
|
||||
_features.clear_feature(CPU_SSE3);
|
||||
_features.clear_feature(CPU_SSSE3);
|
||||
_features.clear_feature(CPU_SSE4A);
|
||||
clear_feature(CPU_SSE3);
|
||||
clear_feature(CPU_SSSE3);
|
||||
clear_feature(CPU_SSE4A);
|
||||
}
|
||||
|
||||
if (UseSSE < 2)
|
||||
_features.clear_feature(CPU_SSE2);
|
||||
clear_feature(CPU_SSE2);
|
||||
|
||||
if (UseSSE < 1)
|
||||
_features.clear_feature(CPU_SSE);
|
||||
clear_feature(CPU_SSE);
|
||||
|
||||
// ZX cpus specific settings
|
||||
if (is_zx() && FLAG_IS_DEFAULT(UseAVX)) {
|
||||
@ -1030,102 +1030,119 @@ void VM_Version::get_processor_features() {
|
||||
}
|
||||
|
||||
if (UseAVX < 3) {
|
||||
_features.clear_feature(CPU_AVX512F);
|
||||
_features.clear_feature(CPU_AVX512DQ);
|
||||
_features.clear_feature(CPU_AVX512CD);
|
||||
_features.clear_feature(CPU_AVX512BW);
|
||||
_features.clear_feature(CPU_AVX512ER);
|
||||
_features.clear_feature(CPU_AVX512PF);
|
||||
_features.clear_feature(CPU_AVX512VL);
|
||||
_features.clear_feature(CPU_AVX512_VPOPCNTDQ);
|
||||
_features.clear_feature(CPU_AVX512_VPCLMULQDQ);
|
||||
_features.clear_feature(CPU_AVX512_VAES);
|
||||
_features.clear_feature(CPU_AVX512_VNNI);
|
||||
_features.clear_feature(CPU_AVX512_VBMI);
|
||||
_features.clear_feature(CPU_AVX512_VBMI2);
|
||||
_features.clear_feature(CPU_AVX512_BITALG);
|
||||
_features.clear_feature(CPU_AVX512_IFMA);
|
||||
_features.clear_feature(CPU_APX_F);
|
||||
_features.clear_feature(CPU_AVX512_FP16);
|
||||
_features.clear_feature(CPU_AVX10_1);
|
||||
_features.clear_feature(CPU_AVX10_2);
|
||||
clear_feature(CPU_AVX512F);
|
||||
clear_feature(CPU_AVX512DQ);
|
||||
clear_feature(CPU_AVX512CD);
|
||||
clear_feature(CPU_AVX512BW);
|
||||
clear_feature(CPU_AVX512ER);
|
||||
clear_feature(CPU_AVX512PF);
|
||||
clear_feature(CPU_AVX512VL);
|
||||
clear_feature(CPU_AVX512_VPOPCNTDQ);
|
||||
clear_feature(CPU_AVX512_VPCLMULQDQ);
|
||||
clear_feature(CPU_AVX512_VAES);
|
||||
clear_feature(CPU_AVX512_VNNI);
|
||||
clear_feature(CPU_AVX512_VBMI);
|
||||
clear_feature(CPU_AVX512_VBMI2);
|
||||
clear_feature(CPU_AVX512_BITALG);
|
||||
clear_feature(CPU_AVX512_IFMA);
|
||||
clear_feature(CPU_APX_F);
|
||||
clear_feature(CPU_AVX512_FP16);
|
||||
clear_feature(CPU_AVX10_1);
|
||||
clear_feature(CPU_AVX10_2);
|
||||
}
|
||||
|
||||
|
||||
if (UseAVX < 2) {
|
||||
_features.clear_feature(CPU_AVX2);
|
||||
_features.clear_feature(CPU_AVX_IFMA);
|
||||
clear_feature(CPU_AVX2);
|
||||
clear_feature(CPU_AVX_IFMA);
|
||||
}
|
||||
|
||||
if (UseAVX < 1) {
|
||||
_features.clear_feature(CPU_AVX);
|
||||
_features.clear_feature(CPU_VZEROUPPER);
|
||||
_features.clear_feature(CPU_F16C);
|
||||
_features.clear_feature(CPU_SHA512);
|
||||
clear_feature(CPU_AVX);
|
||||
clear_feature(CPU_VZEROUPPER);
|
||||
clear_feature(CPU_F16C);
|
||||
clear_feature(CPU_SHA512);
|
||||
}
|
||||
|
||||
if (logical_processors_per_package() == 1) {
|
||||
// HT processor could be installed on a system which doesn't support HT.
|
||||
_features.clear_feature(CPU_HT);
|
||||
clear_feature(CPU_HT);
|
||||
}
|
||||
|
||||
if (is_intel()) { // Intel cpus specific settings
|
||||
if (is_knights_family()) {
|
||||
_features.clear_feature(CPU_VZEROUPPER);
|
||||
_features.clear_feature(CPU_AVX512BW);
|
||||
_features.clear_feature(CPU_AVX512VL);
|
||||
_features.clear_feature(CPU_APX_F);
|
||||
_features.clear_feature(CPU_AVX512DQ);
|
||||
_features.clear_feature(CPU_AVX512_VNNI);
|
||||
_features.clear_feature(CPU_AVX512_VAES);
|
||||
_features.clear_feature(CPU_AVX512_VPOPCNTDQ);
|
||||
_features.clear_feature(CPU_AVX512_VPCLMULQDQ);
|
||||
_features.clear_feature(CPU_AVX512_VBMI);
|
||||
_features.clear_feature(CPU_AVX512_VBMI2);
|
||||
_features.clear_feature(CPU_CLWB);
|
||||
_features.clear_feature(CPU_FLUSHOPT);
|
||||
_features.clear_feature(CPU_GFNI);
|
||||
_features.clear_feature(CPU_AVX512_BITALG);
|
||||
_features.clear_feature(CPU_AVX512_IFMA);
|
||||
_features.clear_feature(CPU_AVX_IFMA);
|
||||
_features.clear_feature(CPU_AVX512_FP16);
|
||||
_features.clear_feature(CPU_AVX10_1);
|
||||
_features.clear_feature(CPU_AVX10_2);
|
||||
clear_feature(CPU_VZEROUPPER);
|
||||
clear_feature(CPU_AVX512BW);
|
||||
clear_feature(CPU_AVX512VL);
|
||||
clear_feature(CPU_APX_F);
|
||||
clear_feature(CPU_AVX512DQ);
|
||||
clear_feature(CPU_AVX512_VNNI);
|
||||
clear_feature(CPU_AVX512_VAES);
|
||||
clear_feature(CPU_AVX512_VPOPCNTDQ);
|
||||
clear_feature(CPU_AVX512_VPCLMULQDQ);
|
||||
clear_feature(CPU_AVX512_VBMI);
|
||||
clear_feature(CPU_AVX512_VBMI2);
|
||||
clear_feature(CPU_CLWB);
|
||||
clear_feature(CPU_FLUSHOPT);
|
||||
clear_feature(CPU_GFNI);
|
||||
clear_feature(CPU_AVX512_BITALG);
|
||||
clear_feature(CPU_AVX512_IFMA);
|
||||
clear_feature(CPU_AVX_IFMA);
|
||||
clear_feature(CPU_AVX512_FP16);
|
||||
clear_feature(CPU_AVX10_1);
|
||||
clear_feature(CPU_AVX10_2);
|
||||
}
|
||||
}
|
||||
|
||||
// Currently APX support is only enabled for targets supporting AVX512VL feature.
|
||||
if (supports_apx_f() && os_supports_apx_egprs() && supports_avx512vl()) {
|
||||
if (FLAG_IS_DEFAULT(UseAPX)) {
|
||||
UseAPX = false; // by default UseAPX is false
|
||||
_features.clear_feature(CPU_APX_F);
|
||||
FLAG_SET_DEFAULT(UseAPX, false); // by default UseAPX is false
|
||||
clear_feature(CPU_APX_F);
|
||||
} else if (!UseAPX) {
|
||||
_features.clear_feature(CPU_APX_F);
|
||||
clear_feature(CPU_APX_F);
|
||||
}
|
||||
} else if (UseAPX) {
|
||||
if (!FLAG_IS_DEFAULT(UseAPX)) {
|
||||
warning("APX is not supported on this CPU, setting it to false)");
|
||||
} else {
|
||||
if (!os_supports_apx_egprs() || !supports_avx512vl()) {
|
||||
clear_feature(CPU_APX_F);
|
||||
}
|
||||
if (UseAPX) {
|
||||
if (!FLAG_IS_DEFAULT(UseAPX)) {
|
||||
warning("APX is not supported on this CPU, setting it to false)");
|
||||
}
|
||||
FLAG_SET_DEFAULT(UseAPX, false);
|
||||
}
|
||||
FLAG_SET_DEFAULT(UseAPX, false);
|
||||
}
|
||||
|
||||
CHECK_CPU_FEATURE(supports_clmul, CLMUL);
|
||||
CHECK_CPU_FEATURE(supports_aes, AES);
|
||||
CHECK_CPU_FEATURE(supports_fma, FMA);
|
||||
CHECK_CPU_FEATURE(UseCLMUL, CLMUL, supports_clmul(), MULTI_INST_WARNING_MSG);
|
||||
CHECK_CPU_FEATURE(UseAES, AES, supports_aes(), MULTI_INST_WARNING_MSG);
|
||||
CHECK_CPU_FEATURE(UseFMA, FMA, supports_fma(), MULTI_INST_WARNING_MSG);
|
||||
CHECK_CPU_FEATURE(UseCountLeadingZerosInstruction, LZCNT, supports_lzcnt(), SINGLE_INST_WARNING_MSG);
|
||||
// BMI instructions (except tzcnt) use an encoding with VEX prefix.
|
||||
// VEX prefix is generated only when AVX > 0.
|
||||
CHECK_CPU_FEATURE(UseBMI1Instructions, BMI1, supports_bmi1(), MULTI_INST_WARNING_MSG);
|
||||
|
||||
if (supports_sha() || (supports_avx2() && supports_bmi2())) {
|
||||
if (FLAG_IS_DEFAULT(UseSHA)) {
|
||||
UseSHA = true;
|
||||
} else if (!UseSHA) {
|
||||
_features.clear_feature(CPU_SHA);
|
||||
if (supports_bmi2() && supports_avx()) {
|
||||
if (FLAG_IS_DEFAULT(UseBMI2Instructions)) {
|
||||
FLAG_SET_DEFAULT(UseBMI2Instructions, true);
|
||||
} else if (!UseBMI2Instructions) {
|
||||
clear_feature(CPU_BMI2);
|
||||
}
|
||||
} else if (UseSHA) {
|
||||
if (!FLAG_IS_DEFAULT(UseSHA)) {
|
||||
warning("SHA instructions are not available on this CPU");
|
||||
} else {
|
||||
if (!supports_avx()) {
|
||||
clear_feature(CPU_BMI2);
|
||||
}
|
||||
if (UseBMI2Instructions) {
|
||||
if (!FLAG_IS_DEFAULT(UseBMI2Instructions)) {
|
||||
warning("BMI2 instructions are not available on this CPU (AVX is also required)");
|
||||
}
|
||||
FLAG_SET_DEFAULT(UseBMI2Instructions, false);
|
||||
}
|
||||
FLAG_SET_DEFAULT(UseSHA, false);
|
||||
}
|
||||
|
||||
CHECK_CPU_FEATURE(UsePopCountInstruction, POPCNT, supports_popcnt(), SINGLE_INST_WARNING_MSG);
|
||||
CHECK_CPU_FEATURE(UseSHA, SHA, supports_sha() || (supports_avx2() && supports_bmi2()), MULTI_INST_WARNING_MSG);
|
||||
|
||||
if (FLAG_IS_DEFAULT(IntelJccErratumMitigation)) {
|
||||
_has_intel_jcc_erratum = compute_has_intel_jcc_erratum();
|
||||
FLAG_SET_ERGO(IntelJccErratumMitigation, _has_intel_jcc_erratum);
|
||||
@ -1716,28 +1733,11 @@ void VM_Version::get_processor_features() {
|
||||
FLAG_SET_DEFAULT(UseVectorizedHashCodeIntrinsic, false);
|
||||
}
|
||||
|
||||
// Use count leading zeros count instruction if available.
|
||||
if (supports_lzcnt()) {
|
||||
if (FLAG_IS_DEFAULT(UseCountLeadingZerosInstruction)) {
|
||||
UseCountLeadingZerosInstruction = true;
|
||||
}
|
||||
} else if (UseCountLeadingZerosInstruction) {
|
||||
if (!FLAG_IS_DEFAULT(UseCountLeadingZerosInstruction)) {
|
||||
warning("lzcnt instruction is not available on this CPU");
|
||||
}
|
||||
FLAG_SET_DEFAULT(UseCountLeadingZerosInstruction, false);
|
||||
}
|
||||
|
||||
// Use count trailing zeros instruction if available
|
||||
if (supports_bmi1()) {
|
||||
// tzcnt does not require VEX prefix
|
||||
if (FLAG_IS_DEFAULT(UseCountTrailingZerosInstruction)) {
|
||||
if (!UseBMI1Instructions && !FLAG_IS_DEFAULT(UseBMI1Instructions)) {
|
||||
// Don't use tzcnt if BMI1 is switched off on command line.
|
||||
UseCountTrailingZerosInstruction = false;
|
||||
} else {
|
||||
UseCountTrailingZerosInstruction = true;
|
||||
}
|
||||
UseCountTrailingZerosInstruction = true;
|
||||
}
|
||||
} else if (UseCountTrailingZerosInstruction) {
|
||||
if (!FLAG_IS_DEFAULT(UseCountTrailingZerosInstruction)) {
|
||||
@ -1746,42 +1746,6 @@ void VM_Version::get_processor_features() {
|
||||
FLAG_SET_DEFAULT(UseCountTrailingZerosInstruction, false);
|
||||
}
|
||||
|
||||
// BMI instructions (except tzcnt) use an encoding with VEX prefix.
|
||||
// VEX prefix is generated only when AVX > 0.
|
||||
if (supports_bmi1() && supports_avx()) {
|
||||
if (FLAG_IS_DEFAULT(UseBMI1Instructions)) {
|
||||
UseBMI1Instructions = true;
|
||||
}
|
||||
} else if (UseBMI1Instructions) {
|
||||
if (!FLAG_IS_DEFAULT(UseBMI1Instructions)) {
|
||||
warning("BMI1 instructions are not available on this CPU (AVX is also required)");
|
||||
}
|
||||
FLAG_SET_DEFAULT(UseBMI1Instructions, false);
|
||||
}
|
||||
|
||||
if (supports_bmi2() && supports_avx()) {
|
||||
if (FLAG_IS_DEFAULT(UseBMI2Instructions)) {
|
||||
UseBMI2Instructions = true;
|
||||
}
|
||||
} else if (UseBMI2Instructions) {
|
||||
if (!FLAG_IS_DEFAULT(UseBMI2Instructions)) {
|
||||
warning("BMI2 instructions are not available on this CPU (AVX is also required)");
|
||||
}
|
||||
FLAG_SET_DEFAULT(UseBMI2Instructions, false);
|
||||
}
|
||||
|
||||
// Use population count instruction if available.
|
||||
if (supports_popcnt()) {
|
||||
if (FLAG_IS_DEFAULT(UsePopCountInstruction)) {
|
||||
UsePopCountInstruction = true;
|
||||
}
|
||||
} else if (UsePopCountInstruction) {
|
||||
if (!FLAG_IS_DEFAULT(UsePopCountInstruction)) {
|
||||
warning("POPCNT instruction is not available on this CPU");
|
||||
}
|
||||
FLAG_SET_DEFAULT(UsePopCountInstruction, false);
|
||||
}
|
||||
|
||||
// Use fast-string operations if available.
|
||||
if (supports_erms()) {
|
||||
if (FLAG_IS_DEFAULT(UseFastStosb)) {
|
||||
@ -2527,7 +2491,7 @@ const char* VM_Version::cpu_brand_string(void) {
|
||||
}
|
||||
int ret_val = cpu_extended_brand_string(_cpu_brand_string, CPU_EBS_MAX_LENGTH);
|
||||
if (ret_val != OS_OK) {
|
||||
FREE_C_HEAP_ARRAY(char, _cpu_brand_string);
|
||||
FREE_C_HEAP_ARRAY(_cpu_brand_string);
|
||||
_cpu_brand_string = nullptr;
|
||||
}
|
||||
}
|
||||
@ -3366,12 +3330,12 @@ int VM_Version::cpu_features_size() {
|
||||
}
|
||||
|
||||
void VM_Version::store_cpu_features(void* buf) {
|
||||
VM_Features copy = _features;
|
||||
copy.clear_feature(CPU_HT); // HT does not result in incompatibility of aot code cache
|
||||
VM_Features copy = _features.aot_code_cache_features();
|
||||
memcpy(buf, ©, sizeof(VM_Features));
|
||||
}
|
||||
|
||||
bool VM_Version::supports_features(void* features_buffer) {
|
||||
bool VM_Version::verify_aot_code_cache_features(void* features_buffer) {
|
||||
VM_Features* features_to_test = (VM_Features*)features_buffer;
|
||||
return _features.supports_features(features_to_test);
|
||||
VM_Features rt_features = _features.aot_code_cache_features();
|
||||
return rt_features.verify_aot_code_cache_features(features_to_test);
|
||||
}
|
||||
|
||||
@ -517,14 +517,21 @@ protected:
|
||||
return (_features_bitmap[idx] & bit_mask(feature)) != 0;
|
||||
}
|
||||
|
||||
bool supports_features(VM_Features* features_to_test) {
|
||||
bool verify_aot_code_cache_features(VM_Features* features_to_test) {
|
||||
for (int i = 0; i < features_bitmap_element_count(); i++) {
|
||||
if ((_features_bitmap[i] & features_to_test->_features_bitmap[i]) != features_to_test->_features_bitmap[i]) {
|
||||
if (_features_bitmap[i] != features_to_test->_features_bitmap[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
VM_Features aot_code_cache_features() {
|
||||
VM_Features copy = *this;
|
||||
// HT does not result in incompatibility of aot code cache
|
||||
copy.clear_feature(CPU_HT);
|
||||
return copy;
|
||||
}
|
||||
};
|
||||
|
||||
// CPU feature flags vector, can be affected by VM settings.
|
||||
@ -1134,7 +1141,7 @@ public:
|
||||
// Size of the buffer must be same as returned by cpu_features_size()
|
||||
static void store_cpu_features(void* buf);
|
||||
|
||||
static bool supports_features(void* features_to_test);
|
||||
static bool verify_aot_code_cache_features(void* features_buffer);
|
||||
};
|
||||
|
||||
#endif // CPU_X86_VM_VERSION_X86_HPP
|
||||
|
||||
@ -4048,7 +4048,7 @@ class FusedPatternMatcher {
|
||||
};
|
||||
|
||||
static bool is_bmi_pattern(Node* n, Node* m) {
|
||||
assert(UseBMI1Instructions, "sanity");
|
||||
assert(VM_Version::supports_bmi1() && VM_Version::supports_avx(), "sanity");
|
||||
if (n != nullptr && m != nullptr) {
|
||||
if (m->Opcode() == Op_LoadI) {
|
||||
FusedPatternMatcher<TypeInt> bmii(n, m, Op_ConI);
|
||||
@ -4068,7 +4068,7 @@ static bool is_bmi_pattern(Node* n, Node* m) {
|
||||
// Should the matcher clone input 'm' of node 'n'?
|
||||
bool Matcher::pd_clone_node(Node* n, Node* m, Matcher::MStack& mstack) {
|
||||
// If 'n' and 'm' are part of a graph for BMI instruction, clone the input 'm'.
|
||||
if (UseBMI1Instructions && is_bmi_pattern(n, m)) {
|
||||
if (VM_Version::supports_bmi1() && VM_Version::supports_avx() && is_bmi_pattern(n, m)) {
|
||||
mstack.push(m, Visit);
|
||||
return true;
|
||||
}
|
||||
@ -4568,7 +4568,7 @@ encode %{
|
||||
} else if (_method->intrinsic_id() == vmIntrinsicID::_ensureMaterializedForStackWalk) {
|
||||
// The NOP here is purely to ensure that eliding a call to
|
||||
// JVM_EnsureMaterializedForStackWalk doesn't change the code size.
|
||||
__ addr_nop_5();
|
||||
__ nop(5);
|
||||
__ block_comment("call JVM_EnsureMaterializedForStackWalk (elided)");
|
||||
} else {
|
||||
int method_index = resolved_method_index(masm);
|
||||
@ -10899,10 +10899,11 @@ instruct xaddB(memory mem, rRegI newval, rFlagsReg cr) %{
|
||||
predicate(!n->as_LoadStore()->result_not_used());
|
||||
match(Set newval (GetAndAddB mem newval));
|
||||
effect(KILL cr);
|
||||
format %{ "xaddb_lock $mem, $newval" %}
|
||||
format %{ "xaddb_lock $mem, $newval\t# $newval -> byte" %}
|
||||
ins_encode %{
|
||||
__ lock();
|
||||
__ xaddb($mem$$Address, $newval$$Register);
|
||||
__ narrow_subword_type($newval$$Register, T_BYTE);
|
||||
%}
|
||||
ins_pipe(pipe_cmpxchg);
|
||||
%}
|
||||
@ -10935,10 +10936,11 @@ instruct xaddS(memory mem, rRegI newval, rFlagsReg cr) %{
|
||||
predicate(!n->as_LoadStore()->result_not_used());
|
||||
match(Set newval (GetAndAddS mem newval));
|
||||
effect(KILL cr);
|
||||
format %{ "xaddw_lock $mem, $newval" %}
|
||||
format %{ "xaddw_lock $mem, $newval\t# $newval -> short" %}
|
||||
ins_encode %{
|
||||
__ lock();
|
||||
__ xaddw($mem$$Address, $newval$$Register);
|
||||
__ narrow_subword_type($newval$$Register, T_SHORT);
|
||||
%}
|
||||
ins_pipe(pipe_cmpxchg);
|
||||
%}
|
||||
@ -11017,18 +11019,20 @@ instruct xaddL(memory mem, rRegL newval, rFlagsReg cr) %{
|
||||
|
||||
instruct xchgB( memory mem, rRegI newval) %{
|
||||
match(Set newval (GetAndSetB mem newval));
|
||||
format %{ "XCHGB $newval,[$mem]" %}
|
||||
format %{ "XCHGB $newval,[$mem]\t# $newval -> byte" %}
|
||||
ins_encode %{
|
||||
__ xchgb($newval$$Register, $mem$$Address);
|
||||
__ narrow_subword_type($newval$$Register, T_BYTE);
|
||||
%}
|
||||
ins_pipe( pipe_cmpxchg );
|
||||
%}
|
||||
|
||||
instruct xchgS( memory mem, rRegI newval) %{
|
||||
match(Set newval (GetAndSetS mem newval));
|
||||
format %{ "XCHGW $newval,[$mem]" %}
|
||||
format %{ "XCHGW $newval,[$mem]\t# $newval -> short" %}
|
||||
ins_encode %{
|
||||
__ xchgw($newval$$Register, $mem$$Address);
|
||||
__ narrow_subword_type($newval$$Register, T_SHORT);
|
||||
%}
|
||||
ins_pipe( pipe_cmpxchg );
|
||||
%}
|
||||
@ -13161,7 +13165,7 @@ instruct andI_mem_imm(memory dst, immI src, rFlagsReg cr)
|
||||
// BMI1 instructions
|
||||
instruct andnI_rReg_rReg_mem(rRegI dst, rRegI src1, memory src2, immI_M1 minus_1, rFlagsReg cr) %{
|
||||
match(Set dst (AndI (XorI src1 minus_1) (LoadI src2)));
|
||||
predicate(UseBMI1Instructions);
|
||||
predicate(VM_Version::supports_bmi1() && VM_Version::supports_avx());
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
|
||||
|
||||
@ -13176,7 +13180,7 @@ instruct andnI_rReg_rReg_mem(rRegI dst, rRegI src1, memory src2, immI_M1 minus_1
|
||||
|
||||
instruct andnI_rReg_rReg_rReg(rRegI dst, rRegI src1, rRegI src2, immI_M1 minus_1, rFlagsReg cr) %{
|
||||
match(Set dst (AndI (XorI src1 minus_1) src2));
|
||||
predicate(UseBMI1Instructions);
|
||||
predicate(VM_Version::supports_bmi1() && VM_Version::supports_avx());
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
|
||||
|
||||
@ -13190,7 +13194,7 @@ instruct andnI_rReg_rReg_rReg(rRegI dst, rRegI src1, rRegI src2, immI_M1 minus_1
|
||||
|
||||
instruct blsiI_rReg_rReg(rRegI dst, rRegI src, immI_0 imm_zero, rFlagsReg cr) %{
|
||||
match(Set dst (AndI (SubI imm_zero src) src));
|
||||
predicate(UseBMI1Instructions);
|
||||
predicate(VM_Version::supports_bmi1() && VM_Version::supports_avx());
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_clears_overflow_flag);
|
||||
|
||||
@ -13204,7 +13208,7 @@ instruct blsiI_rReg_rReg(rRegI dst, rRegI src, immI_0 imm_zero, rFlagsReg cr) %{
|
||||
|
||||
instruct blsiI_rReg_mem(rRegI dst, memory src, immI_0 imm_zero, rFlagsReg cr) %{
|
||||
match(Set dst (AndI (SubI imm_zero (LoadI src) ) (LoadI src) ));
|
||||
predicate(UseBMI1Instructions);
|
||||
predicate(VM_Version::supports_bmi1() && VM_Version::supports_avx());
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_clears_overflow_flag);
|
||||
|
||||
@ -13220,7 +13224,7 @@ instruct blsiI_rReg_mem(rRegI dst, memory src, immI_0 imm_zero, rFlagsReg cr) %{
|
||||
instruct blsmskI_rReg_mem(rRegI dst, memory src, immI_M1 minus_1, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (XorI (AddI (LoadI src) minus_1) (LoadI src) ) );
|
||||
predicate(UseBMI1Instructions);
|
||||
predicate(VM_Version::supports_bmi1() && VM_Version::supports_avx());
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_clears_zero_flag, PD::Flag_clears_overflow_flag);
|
||||
|
||||
@ -13236,7 +13240,7 @@ instruct blsmskI_rReg_mem(rRegI dst, memory src, immI_M1 minus_1, rFlagsReg cr)
|
||||
instruct blsmskI_rReg_rReg(rRegI dst, rRegI src, immI_M1 minus_1, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (XorI (AddI src minus_1) src));
|
||||
predicate(UseBMI1Instructions);
|
||||
predicate(VM_Version::supports_bmi1() && VM_Version::supports_avx());
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_clears_zero_flag, PD::Flag_clears_overflow_flag);
|
||||
|
||||
@ -13252,7 +13256,7 @@ instruct blsmskI_rReg_rReg(rRegI dst, rRegI src, immI_M1 minus_1, rFlagsReg cr)
|
||||
instruct blsrI_rReg_rReg(rRegI dst, rRegI src, immI_M1 minus_1, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (AndI (AddI src minus_1) src) );
|
||||
predicate(UseBMI1Instructions);
|
||||
predicate(VM_Version::supports_bmi1() && VM_Version::supports_avx());
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_clears_overflow_flag);
|
||||
|
||||
@ -13268,7 +13272,7 @@ instruct blsrI_rReg_rReg(rRegI dst, rRegI src, immI_M1 minus_1, rFlagsReg cr)
|
||||
instruct blsrI_rReg_mem(rRegI dst, memory src, immI_M1 minus_1, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (AndI (AddI (LoadI src) minus_1) (LoadI src) ) );
|
||||
predicate(UseBMI1Instructions);
|
||||
predicate(VM_Version::supports_bmi1() && VM_Version::supports_avx());
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_clears_overflow_flag);
|
||||
|
||||
@ -13809,7 +13813,7 @@ instruct btrL_mem_imm(memory dst, immL_NotPow2 con, rFlagsReg cr)
|
||||
// BMI1 instructions
|
||||
instruct andnL_rReg_rReg_mem(rRegL dst, rRegL src1, memory src2, immL_M1 minus_1, rFlagsReg cr) %{
|
||||
match(Set dst (AndL (XorL src1 minus_1) (LoadL src2)));
|
||||
predicate(UseBMI1Instructions);
|
||||
predicate(VM_Version::supports_bmi1() && VM_Version::supports_avx());
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
|
||||
|
||||
@ -13824,7 +13828,7 @@ instruct andnL_rReg_rReg_mem(rRegL dst, rRegL src1, memory src2, immL_M1 minus_1
|
||||
|
||||
instruct andnL_rReg_rReg_rReg(rRegL dst, rRegL src1, rRegL src2, immL_M1 minus_1, rFlagsReg cr) %{
|
||||
match(Set dst (AndL (XorL src1 minus_1) src2));
|
||||
predicate(UseBMI1Instructions);
|
||||
predicate(VM_Version::supports_bmi1() && VM_Version::supports_avx());
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
|
||||
|
||||
@ -13838,7 +13842,7 @@ instruct andnL_rReg_rReg_rReg(rRegL dst, rRegL src1, rRegL src2, immL_M1 minus_1
|
||||
|
||||
instruct blsiL_rReg_rReg(rRegL dst, rRegL src, immL0 imm_zero, rFlagsReg cr) %{
|
||||
match(Set dst (AndL (SubL imm_zero src) src));
|
||||
predicate(UseBMI1Instructions);
|
||||
predicate(VM_Version::supports_bmi1() && VM_Version::supports_avx());
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_clears_overflow_flag);
|
||||
|
||||
@ -13852,7 +13856,7 @@ instruct blsiL_rReg_rReg(rRegL dst, rRegL src, immL0 imm_zero, rFlagsReg cr) %{
|
||||
|
||||
instruct blsiL_rReg_mem(rRegL dst, memory src, immL0 imm_zero, rFlagsReg cr) %{
|
||||
match(Set dst (AndL (SubL imm_zero (LoadL src) ) (LoadL src) ));
|
||||
predicate(UseBMI1Instructions);
|
||||
predicate(VM_Version::supports_bmi1() && VM_Version::supports_avx());
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_clears_overflow_flag);
|
||||
|
||||
@ -13868,7 +13872,7 @@ instruct blsiL_rReg_mem(rRegL dst, memory src, immL0 imm_zero, rFlagsReg cr) %{
|
||||
instruct blsmskL_rReg_mem(rRegL dst, memory src, immL_M1 minus_1, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (XorL (AddL (LoadL src) minus_1) (LoadL src) ) );
|
||||
predicate(UseBMI1Instructions);
|
||||
predicate(VM_Version::supports_bmi1() && VM_Version::supports_avx());
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_clears_zero_flag, PD::Flag_clears_overflow_flag);
|
||||
|
||||
@ -13884,7 +13888,7 @@ instruct blsmskL_rReg_mem(rRegL dst, memory src, immL_M1 minus_1, rFlagsReg cr)
|
||||
instruct blsmskL_rReg_rReg(rRegL dst, rRegL src, immL_M1 minus_1, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (XorL (AddL src minus_1) src));
|
||||
predicate(UseBMI1Instructions);
|
||||
predicate(VM_Version::supports_bmi1() && VM_Version::supports_avx());
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_clears_zero_flag, PD::Flag_clears_overflow_flag);
|
||||
|
||||
@ -13900,7 +13904,7 @@ instruct blsmskL_rReg_rReg(rRegL dst, rRegL src, immL_M1 minus_1, rFlagsReg cr)
|
||||
instruct blsrL_rReg_rReg(rRegL dst, rRegL src, immL_M1 minus_1, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (AndL (AddL src minus_1) src) );
|
||||
predicate(UseBMI1Instructions);
|
||||
predicate(VM_Version::supports_bmi1() && VM_Version::supports_avx());
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_clears_overflow_flag);
|
||||
|
||||
@ -13916,7 +13920,7 @@ instruct blsrL_rReg_rReg(rRegL dst, rRegL src, immL_M1 minus_1, rFlagsReg cr)
|
||||
instruct blsrL_rReg_mem(rRegL dst, memory src, immL_M1 minus_1, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (AndL (AddL (LoadL src) minus_1) (LoadL src)) );
|
||||
predicate(UseBMI1Instructions);
|
||||
predicate(VM_Version::supports_bmi1() && VM_Version::supports_avx());
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_clears_overflow_flag);
|
||||
|
||||
@ -24920,11 +24924,11 @@ instruct mask_not_imm(kReg dst, kReg src, immI_M1 cnt) %{
|
||||
ins_pipe( pipe_slow );
|
||||
%}
|
||||
|
||||
instruct long_to_maskLE8_avx(vec dst, rRegL src, rRegL rtmp1, rRegL rtmp2, vec xtmp) %{
|
||||
instruct long_to_maskLE8_avx(vec dst, rRegL src, rRegL rtmp1, rRegL rtmp2) %{
|
||||
predicate(n->bottom_type()->isa_vectmask() == nullptr && Matcher::vector_length(n) <= 8);
|
||||
match(Set dst (VectorLongToMask src));
|
||||
effect(TEMP dst, TEMP rtmp1, TEMP rtmp2, TEMP xtmp);
|
||||
format %{ "long_to_mask_avx $dst, $src\t! using $rtmp1, $rtmp2, $xtmp as TEMP" %}
|
||||
effect(TEMP dst, TEMP rtmp1, TEMP rtmp2);
|
||||
format %{ "long_to_mask_avx $dst, $src\t! using $rtmp1, $rtmp2" %}
|
||||
ins_encode %{
|
||||
int mask_len = Matcher::vector_length(this);
|
||||
int vec_enc = vector_length_encoding(mask_len);
|
||||
@ -25317,6 +25321,7 @@ instruct reinterpretHF2S(rRegI dst, regF src)
|
||||
format %{ "evmovw $dst, $src" %}
|
||||
ins_encode %{
|
||||
__ evmovw($dst$$Register, $src$$XMMRegister);
|
||||
__ narrow_subword_type($dst$$Register, T_SHORT);
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
@ -578,13 +578,13 @@ void os::init_system_properties_values() {
|
||||
char *ld_library_path = NEW_C_HEAP_ARRAY(char, pathsize, mtInternal);
|
||||
os::snprintf_checked(ld_library_path, pathsize, "%s%s" DEFAULT_LIBPATH, v, v_colon);
|
||||
Arguments::set_library_path(ld_library_path);
|
||||
FREE_C_HEAP_ARRAY(char, ld_library_path);
|
||||
FREE_C_HEAP_ARRAY(ld_library_path);
|
||||
|
||||
// Extensions directories.
|
||||
os::snprintf_checked(buf, bufsize, "%s" EXTENSIONS_DIR, Arguments::get_java_home());
|
||||
Arguments::set_ext_dirs(buf);
|
||||
|
||||
FREE_C_HEAP_ARRAY(char, buf);
|
||||
FREE_C_HEAP_ARRAY(buf);
|
||||
|
||||
#undef DEFAULT_LIBPATH
|
||||
#undef EXTENSIONS_DIR
|
||||
|
||||
@ -258,10 +258,10 @@ bool CPUPerformanceInterface::CPUPerformance::initialize() {
|
||||
|
||||
CPUPerformanceInterface::CPUPerformance::~CPUPerformance() {
|
||||
if (_lcpu_names) {
|
||||
FREE_C_HEAP_ARRAY(perfstat_id_t, _lcpu_names);
|
||||
FREE_C_HEAP_ARRAY(_lcpu_names);
|
||||
}
|
||||
if (_prev_ticks) {
|
||||
FREE_C_HEAP_ARRAY(cpu_tick_store_t, _prev_ticks);
|
||||
FREE_C_HEAP_ARRAY(_prev_ticks);
|
||||
}
|
||||
}
|
||||
|
||||
@ -511,12 +511,12 @@ CPUInformationInterface::~CPUInformationInterface() {
|
||||
if (_cpu_info != nullptr) {
|
||||
if (_cpu_info->cpu_name() != nullptr) {
|
||||
const char* cpu_name = _cpu_info->cpu_name();
|
||||
FREE_C_HEAP_ARRAY(char, cpu_name);
|
||||
FREE_C_HEAP_ARRAY(cpu_name);
|
||||
_cpu_info->set_cpu_name(nullptr);
|
||||
}
|
||||
if (_cpu_info->cpu_description() != nullptr) {
|
||||
const char* cpu_desc = _cpu_info->cpu_description();
|
||||
FREE_C_HEAP_ARRAY(char, cpu_desc);
|
||||
FREE_C_HEAP_ARRAY(cpu_desc);
|
||||
_cpu_info->set_cpu_description(nullptr);
|
||||
}
|
||||
delete _cpu_info;
|
||||
@ -576,7 +576,7 @@ int NetworkPerformanceInterface::NetworkPerformance::network_utilization(Network
|
||||
|
||||
// check for error
|
||||
if (n_records < 0) {
|
||||
FREE_C_HEAP_ARRAY(perfstat_netinterface_t, net_stats);
|
||||
FREE_C_HEAP_ARRAY(net_stats);
|
||||
return OS_ERR;
|
||||
}
|
||||
|
||||
@ -593,7 +593,7 @@ int NetworkPerformanceInterface::NetworkPerformance::network_utilization(Network
|
||||
*network_interfaces = new_interface;
|
||||
}
|
||||
|
||||
FREE_C_HEAP_ARRAY(perfstat_netinterface_t, net_stats);
|
||||
FREE_C_HEAP_ARRAY(net_stats);
|
||||
return OS_OK;
|
||||
}
|
||||
|
||||
|
||||
@ -106,6 +106,14 @@
|
||||
#include <libproc.h>
|
||||
#include <mach/task_info.h>
|
||||
#include <mach-o/dyld.h>
|
||||
|
||||
// needed by current_stack_base_and_size() workaround for Mavericks
|
||||
#define DEFAULT_MAIN_THREAD_STACK_PAGES 2048
|
||||
#define OS_X_10_9_0_KERNEL_MAJOR_VERSION 13
|
||||
#endif
|
||||
|
||||
#if !defined(__APPLE__) && !defined(__NetBSD__)
|
||||
#include <pthread_np.h>
|
||||
#endif
|
||||
|
||||
#ifndef MAP_ANONYMOUS
|
||||
@ -444,14 +452,14 @@ void os::init_system_properties_values() {
|
||||
char *ld_library_path = NEW_C_HEAP_ARRAY(char, ld_library_path_size, mtInternal);
|
||||
os::snprintf_checked(ld_library_path, ld_library_path_size, "%s%s" SYS_EXT_DIR "/lib/%s:" DEFAULT_LIBPATH, v, v_colon, cpu_arch);
|
||||
Arguments::set_library_path(ld_library_path);
|
||||
FREE_C_HEAP_ARRAY(char, ld_library_path);
|
||||
FREE_C_HEAP_ARRAY(ld_library_path);
|
||||
}
|
||||
|
||||
// Extensions directories.
|
||||
os::snprintf_checked(buf, bufsize, "%s" EXTENSIONS_DIR ":" SYS_EXT_DIR EXTENSIONS_DIR, Arguments::get_java_home());
|
||||
Arguments::set_ext_dirs(buf);
|
||||
|
||||
FREE_C_HEAP_ARRAY(char, buf);
|
||||
FREE_C_HEAP_ARRAY(buf);
|
||||
|
||||
#else // __APPLE__
|
||||
|
||||
@ -538,7 +546,7 @@ void os::init_system_properties_values() {
|
||||
os::snprintf_checked(ld_library_path, ld_library_path_size, "%s%s%s%s%s" SYS_EXTENSIONS_DIR ":" SYS_EXTENSIONS_DIRS ":.",
|
||||
v, v_colon, l, l_colon, user_home_dir);
|
||||
Arguments::set_library_path(ld_library_path);
|
||||
FREE_C_HEAP_ARRAY(char, ld_library_path);
|
||||
FREE_C_HEAP_ARRAY(ld_library_path);
|
||||
}
|
||||
|
||||
// Extensions directories.
|
||||
@ -550,7 +558,7 @@ void os::init_system_properties_values() {
|
||||
user_home_dir, Arguments::get_java_home());
|
||||
Arguments::set_ext_dirs(buf);
|
||||
|
||||
FREE_C_HEAP_ARRAY(char, buf);
|
||||
FREE_C_HEAP_ARRAY(buf);
|
||||
|
||||
#undef SYS_EXTENSIONS_DIR
|
||||
#undef SYS_EXTENSIONS_DIRS
|
||||
@ -2545,6 +2553,106 @@ bool os::start_debugging(char *buf, int buflen) {
|
||||
return yes;
|
||||
}
|
||||
|
||||
// Java thread:
|
||||
//
|
||||
// Low memory addresses
|
||||
// +------------------------+
|
||||
// | |\ Java thread created by VM does not have glibc
|
||||
// | glibc guard page | - guard, attached Java thread usually has
|
||||
// | |/ 1 glibc guard page.
|
||||
// P1 +------------------------+ Thread::stack_base() - Thread::stack_size()
|
||||
// | |\
|
||||
// | HotSpot Guard Pages | - red, yellow and reserved pages
|
||||
// | |/
|
||||
// +------------------------+ StackOverflow::stack_reserved_zone_base()
|
||||
// | |\
|
||||
// | Normal Stack | -
|
||||
// | |/
|
||||
// P2 +------------------------+ Thread::stack_base()
|
||||
//
|
||||
// Non-Java thread:
|
||||
//
|
||||
// Low memory addresses
|
||||
// +------------------------+
|
||||
// | |\
|
||||
// | glibc guard page | - usually 1 page
|
||||
// | |/
|
||||
// P1 +------------------------+ Thread::stack_base() - Thread::stack_size()
|
||||
// | |\
|
||||
// | Normal Stack | -
|
||||
// | |/
|
||||
// P2 +------------------------+ Thread::stack_base()
|
||||
//
|
||||
// ** P1 (aka bottom) and size are the address and stack size
|
||||
// returned from pthread_attr_getstack().
|
||||
// ** P2 (aka stack top or base) = P1 + size
|
||||
|
||||
void os::current_stack_base_and_size(address* base, size_t* size) {
|
||||
address bottom;
|
||||
#ifdef __APPLE__
|
||||
pthread_t self = pthread_self();
|
||||
*base = (address) pthread_get_stackaddr_np(self);
|
||||
*size = pthread_get_stacksize_np(self);
|
||||
# ifdef __x86_64__
|
||||
// workaround for OS X 10.9.0 (Mavericks)
|
||||
// pthread_get_stacksize_np returns 128 pages even though the actual size is 2048 pages
|
||||
if (pthread_main_np() == 1) {
|
||||
// At least on Mac OS 10.12 we have observed stack sizes not aligned
|
||||
// to pages boundaries. This can be provoked by e.g. setrlimit() (ulimit -s xxxx in the
|
||||
// shell). Apparently Mac OS actually rounds upwards to next multiple of page size,
|
||||
// however, we round downwards here to be on the safe side.
|
||||
*size = align_down(*size, getpagesize());
|
||||
|
||||
if ((*size) < (DEFAULT_MAIN_THREAD_STACK_PAGES * (size_t)getpagesize())) {
|
||||
char kern_osrelease[256];
|
||||
size_t kern_osrelease_size = sizeof(kern_osrelease);
|
||||
int ret = sysctlbyname("kern.osrelease", kern_osrelease, &kern_osrelease_size, nullptr, 0);
|
||||
if (ret == 0) {
|
||||
// get the major number, atoi will ignore the minor amd micro portions of the version string
|
||||
if (atoi(kern_osrelease) >= OS_X_10_9_0_KERNEL_MAJOR_VERSION) {
|
||||
*size = (DEFAULT_MAIN_THREAD_STACK_PAGES*getpagesize());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
# endif
|
||||
bottom = *base - *size;
|
||||
#elif defined(__OpenBSD__)
|
||||
stack_t ss;
|
||||
int rslt = pthread_stackseg_np(pthread_self(), &ss);
|
||||
|
||||
if (rslt != 0)
|
||||
fatal("pthread_stackseg_np failed with error = %d", rslt);
|
||||
|
||||
*base = (address) ss.ss_sp;
|
||||
*size = ss.ss_size;
|
||||
bottom = *base - *size;
|
||||
#else
|
||||
pthread_attr_t attr;
|
||||
|
||||
int rslt = pthread_attr_init(&attr);
|
||||
|
||||
// JVM needs to know exact stack location, abort if it fails
|
||||
if (rslt != 0)
|
||||
fatal("pthread_attr_init failed with error = %d", rslt);
|
||||
|
||||
rslt = pthread_attr_get_np(pthread_self(), &attr);
|
||||
|
||||
if (rslt != 0)
|
||||
fatal("pthread_attr_get_np failed with error = %d", rslt);
|
||||
|
||||
if (pthread_attr_getstackaddr(&attr, (void **)&bottom) != 0 ||
|
||||
pthread_attr_getstacksize(&attr, size) != 0) {
|
||||
fatal("Can not locate current stack attributes!");
|
||||
}
|
||||
|
||||
*base = bottom + *size;
|
||||
|
||||
pthread_attr_destroy(&attr);
|
||||
#endif
|
||||
assert(os::current_stack_pointer() >= bottom &&
|
||||
os::current_stack_pointer() < *base, "just checking");
|
||||
}
|
||||
void os::print_memory_mappings(char* addr, size_t bytes, outputStream* st) {}
|
||||
|
||||
#if INCLUDE_JFR
|
||||
|
||||
@ -301,7 +301,7 @@ int SystemProcessInterface::SystemProcesses::system_processes(SystemProcess** sy
|
||||
pids_bytes = proc_listpids(PROC_ALL_PIDS, 0, pids, pids_bytes);
|
||||
if (pids_bytes <= 0) {
|
||||
// couldn't fit buffer, retry.
|
||||
FREE_RESOURCE_ARRAY(pid_t, pids, pid_count);
|
||||
FREE_RESOURCE_ARRAY(pids, pid_count);
|
||||
pids = nullptr;
|
||||
try_count++;
|
||||
if (try_count > 3) {
|
||||
@ -381,12 +381,12 @@ CPUInformationInterface::~CPUInformationInterface() {
|
||||
if (_cpu_info != nullptr) {
|
||||
if (_cpu_info->cpu_name() != nullptr) {
|
||||
const char* cpu_name = _cpu_info->cpu_name();
|
||||
FREE_C_HEAP_ARRAY(char, cpu_name);
|
||||
FREE_C_HEAP_ARRAY(cpu_name);
|
||||
_cpu_info->set_cpu_name(nullptr);
|
||||
}
|
||||
if (_cpu_info->cpu_description() != nullptr) {
|
||||
const char* cpu_desc = _cpu_info->cpu_description();
|
||||
FREE_C_HEAP_ARRAY(char, cpu_desc);
|
||||
FREE_C_HEAP_ARRAY(cpu_desc);
|
||||
_cpu_info->set_cpu_description(nullptr);
|
||||
}
|
||||
delete _cpu_info;
|
||||
|
||||
@ -649,7 +649,7 @@ bool CgroupSubsystem::active_processor_count(int (*cpu_bound_func)(), double& va
|
||||
return true;
|
||||
}
|
||||
|
||||
int cpu_count = cpu_bound_func();
|
||||
double cpu_count = static_cast<double>(cpu_bound_func());
|
||||
double result = -1;
|
||||
if (!CgroupUtil::processor_count(contrl->controller(), cpu_count, result)) {
|
||||
return false;
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
|
||||
#include "cgroupUtil_linux.hpp"
|
||||
|
||||
bool CgroupUtil::processor_count(CgroupCpuController* cpu_ctrl, int upper_bound, double& value) {
|
||||
bool CgroupUtil::processor_count(CgroupCpuController* cpu_ctrl, double upper_bound, double& value) {
|
||||
assert(upper_bound > 0, "upper bound of cpus must be positive");
|
||||
int quota = -1;
|
||||
int period = -1;
|
||||
@ -68,8 +68,8 @@ physical_memory_size_type CgroupUtil::get_updated_mem_limit(CgroupMemoryControll
|
||||
// Get an updated cpu limit. The return value is strictly less than or equal to the
|
||||
// passed in 'lowest' value.
|
||||
double CgroupUtil::get_updated_cpu_limit(CgroupCpuController* cpu,
|
||||
int lowest,
|
||||
int upper_bound) {
|
||||
double lowest,
|
||||
double upper_bound) {
|
||||
assert(lowest > 0 && lowest <= upper_bound, "invariant");
|
||||
double cpu_limit_val = -1;
|
||||
if (CgroupUtil::processor_count(cpu, upper_bound, cpu_limit_val) && cpu_limit_val != upper_bound) {
|
||||
@ -145,7 +145,7 @@ void CgroupUtil::adjust_controller(CgroupMemoryController* mem, physical_memory_
|
||||
os::free(limit_cg_path);
|
||||
}
|
||||
|
||||
void CgroupUtil::adjust_controller(CgroupCpuController* cpu, int upper_bound) {
|
||||
void CgroupUtil::adjust_controller(CgroupCpuController* cpu, double upper_bound) {
|
||||
assert(cpu->cgroup_path() != nullptr, "invariant");
|
||||
if (strstr(cpu->cgroup_path(), "../") != nullptr) {
|
||||
log_warning(os, container)("Cgroup cpu controller path at '%s' seems to have moved "
|
||||
@ -163,9 +163,9 @@ void CgroupUtil::adjust_controller(CgroupCpuController* cpu, int upper_bound) {
|
||||
char* cg_path = os::strdup(orig);
|
||||
char* last_slash;
|
||||
assert(cg_path[0] == '/', "cgroup path must start with '/'");
|
||||
int lowest_limit = upper_bound;
|
||||
double lowest_limit = upper_bound;
|
||||
double cpus = get_updated_cpu_limit(cpu, lowest_limit, upper_bound);
|
||||
int orig_limit = lowest_limit != upper_bound ? lowest_limit : upper_bound;
|
||||
double orig_limit = lowest_limit != upper_bound ? lowest_limit : upper_bound;
|
||||
char* limit_cg_path = nullptr;
|
||||
while ((last_slash = strrchr(cg_path, '/')) != cg_path) {
|
||||
*last_slash = '\0'; // strip path
|
||||
@ -193,10 +193,10 @@ void CgroupUtil::adjust_controller(CgroupCpuController* cpu, int upper_bound) {
|
||||
assert(limit_cg_path != nullptr, "limit path must be set");
|
||||
cpu->set_subsystem_path(limit_cg_path);
|
||||
log_trace(os, container)("Adjusted controller path for cpu to: %s. "
|
||||
"Lowest limit was: %d",
|
||||
"Lowest limit was: %.2f",
|
||||
cpu->subsystem_path(), lowest_limit);
|
||||
} else {
|
||||
log_trace(os, container)("Lowest limit was: %d", lowest_limit);
|
||||
log_trace(os, container)("Lowest limit was: %.2f", lowest_limit);
|
||||
log_trace(os, container)("No lower limit found for cpu in hierarchy %s, "
|
||||
"adjusting to original path %s",
|
||||
cpu->mount_point(), orig);
|
||||
|
||||
@ -32,18 +32,18 @@
|
||||
class CgroupUtil: AllStatic {
|
||||
|
||||
public:
|
||||
static bool processor_count(CgroupCpuController* cpu, int upper_bound, double& value);
|
||||
static bool processor_count(CgroupCpuController* cpu, double upper_bound, double& value);
|
||||
// Given a memory controller, adjust its path to a point in the hierarchy
|
||||
// that represents the closest memory limit.
|
||||
static void adjust_controller(CgroupMemoryController* m, physical_memory_size_type upper_bound);
|
||||
// Given a cpu controller, adjust its path to a point in the hierarchy
|
||||
// that represents the closest cpu limit.
|
||||
static void adjust_controller(CgroupCpuController* c, int upper_bound);
|
||||
static void adjust_controller(CgroupCpuController* c, double upper_bound);
|
||||
private:
|
||||
static physical_memory_size_type get_updated_mem_limit(CgroupMemoryController* m,
|
||||
physical_memory_size_type lowest,
|
||||
physical_memory_size_type upper_bound);
|
||||
static double get_updated_cpu_limit(CgroupCpuController* c, int lowest, int upper_bound);
|
||||
static double get_updated_cpu_limit(CgroupCpuController* c, double lowest, double upper_bound);
|
||||
};
|
||||
|
||||
#endif // CGROUP_UTIL_LINUX_HPP
|
||||
|
||||
@ -79,9 +79,12 @@ void OSContainer::init() {
|
||||
* that limits enforced by other means (e.g. systemd slice) are properly
|
||||
* detected.
|
||||
*/
|
||||
const char *reason;
|
||||
bool any_mem_cpu_limit_present = false;
|
||||
const char* reason;
|
||||
bool controllers_read_only = cgroup_subsystem->is_containerized();
|
||||
|
||||
bool any_mem_limit_present = false;
|
||||
bool cpu_limit_present = false;
|
||||
|
||||
if (controllers_read_only) {
|
||||
// in-container case
|
||||
reason = " because all controllers are mounted read-only (container case)";
|
||||
@ -89,19 +92,30 @@ void OSContainer::init() {
|
||||
// We can be in one of two cases:
|
||||
// 1.) On a physical Linux system without any limit
|
||||
// 2.) On a physical Linux system with a limit enforced by other means (like systemd slice)
|
||||
|
||||
physical_memory_size_type mem_limit_val = value_unlimited;
|
||||
(void)memory_limit_in_bytes(mem_limit_val); // discard error and use default
|
||||
double host_cpus = os::Linux::active_processor_count();
|
||||
any_mem_limit_present = any_mem_limit_present || (memory_limit_in_bytes(mem_limit_val) &&
|
||||
mem_limit_val != value_unlimited);
|
||||
|
||||
physical_memory_size_type throttle_limit_val = value_unlimited;
|
||||
any_mem_limit_present = any_mem_limit_present || (memory_throttle_limit_in_bytes(throttle_limit_val) &&
|
||||
throttle_limit_val != value_unlimited);
|
||||
|
||||
physical_memory_size_type soft_limit_val = value_unlimited;
|
||||
any_mem_limit_present = any_mem_limit_present || (memory_soft_limit_in_bytes(soft_limit_val) &&
|
||||
(soft_limit_val != value_unlimited && soft_limit_val != 0));
|
||||
|
||||
const double host_cpus = os::Linux::active_processor_count();
|
||||
double cpus = host_cpus;
|
||||
(void)active_processor_count(cpus); // discard error and use default
|
||||
any_mem_cpu_limit_present = mem_limit_val != value_unlimited || host_cpus != cpus;
|
||||
if (any_mem_cpu_limit_present) {
|
||||
cpu_limit_present = active_processor_count(cpus) && host_cpus != cpus;
|
||||
|
||||
if (any_mem_limit_present || cpu_limit_present) {
|
||||
reason = " because either a cpu or a memory limit is present";
|
||||
} else {
|
||||
reason = " because no cpu or memory limit is present";
|
||||
}
|
||||
}
|
||||
_is_containerized = controllers_read_only || any_mem_cpu_limit_present;
|
||||
_is_containerized = controllers_read_only || any_mem_limit_present || cpu_limit_present;
|
||||
log_debug(os, container)("OSContainer::init: is_containerized() = %s%s",
|
||||
_is_containerized ? "true" : "false",
|
||||
reason);
|
||||
|
||||
@ -710,14 +710,14 @@ void os::init_system_properties_values() {
|
||||
char *ld_library_path = NEW_C_HEAP_ARRAY(char, pathsize, mtInternal);
|
||||
os::snprintf_checked(ld_library_path, pathsize, "%s%s" SYS_EXT_DIR "/lib:" DEFAULT_LIBPATH, v, v_colon);
|
||||
Arguments::set_library_path(ld_library_path);
|
||||
FREE_C_HEAP_ARRAY(char, ld_library_path);
|
||||
FREE_C_HEAP_ARRAY(ld_library_path);
|
||||
}
|
||||
|
||||
// Extensions directories.
|
||||
os::snprintf_checked(buf, bufsize, "%s" EXTENSIONS_DIR ":" SYS_EXT_DIR EXTENSIONS_DIR, Arguments::get_java_home());
|
||||
Arguments::set_ext_dirs(buf);
|
||||
|
||||
FREE_C_HEAP_ARRAY(char, buf);
|
||||
FREE_C_HEAP_ARRAY(buf);
|
||||
|
||||
#undef DEFAULT_LIBPATH
|
||||
#undef SYS_EXT_DIR
|
||||
@ -3435,7 +3435,7 @@ void os::Linux::rebuild_cpu_to_node_map() {
|
||||
}
|
||||
}
|
||||
}
|
||||
FREE_C_HEAP_ARRAY(unsigned long, cpu_map);
|
||||
FREE_C_HEAP_ARRAY(cpu_map);
|
||||
}
|
||||
|
||||
int os::Linux::numa_node_to_cpus(int node, unsigned long *buffer, int bufferlen) {
|
||||
|
||||
@ -545,7 +545,7 @@ bool CPUPerformanceInterface::CPUPerformance::initialize() {
|
||||
|
||||
CPUPerformanceInterface::CPUPerformance::~CPUPerformance() {
|
||||
if (_counters.cpus != nullptr) {
|
||||
FREE_C_HEAP_ARRAY(char, _counters.cpus);
|
||||
FREE_C_HEAP_ARRAY(_counters.cpus);
|
||||
}
|
||||
}
|
||||
|
||||
@ -811,7 +811,7 @@ int SystemProcessInterface::SystemProcesses::ProcessIterator::current(SystemProc
|
||||
cmdline = get_cmdline();
|
||||
if (cmdline != nullptr) {
|
||||
process_info->set_command_line(allocate_string(cmdline));
|
||||
FREE_C_HEAP_ARRAY(char, cmdline);
|
||||
FREE_C_HEAP_ARRAY(cmdline);
|
||||
}
|
||||
|
||||
return OS_OK;
|
||||
@ -937,12 +937,12 @@ CPUInformationInterface::~CPUInformationInterface() {
|
||||
if (_cpu_info != nullptr) {
|
||||
if (_cpu_info->cpu_name() != nullptr) {
|
||||
const char* cpu_name = _cpu_info->cpu_name();
|
||||
FREE_C_HEAP_ARRAY(char, cpu_name);
|
||||
FREE_C_HEAP_ARRAY(cpu_name);
|
||||
_cpu_info->set_cpu_name(nullptr);
|
||||
}
|
||||
if (_cpu_info->cpu_description() != nullptr) {
|
||||
const char* cpu_desc = _cpu_info->cpu_description();
|
||||
FREE_C_HEAP_ARRAY(char, cpu_desc);
|
||||
FREE_C_HEAP_ARRAY(cpu_desc);
|
||||
_cpu_info->set_cpu_description(nullptr);
|
||||
}
|
||||
delete _cpu_info;
|
||||
|
||||
@ -45,7 +45,7 @@ ProcSmapsParser::ProcSmapsParser(FILE* f) :
|
||||
}
|
||||
|
||||
ProcSmapsParser::~ProcSmapsParser() {
|
||||
FREE_C_HEAP_ARRAY(char, _line);
|
||||
FREE_C_HEAP_ARRAY(_line);
|
||||
}
|
||||
|
||||
bool ProcSmapsParser::read_line() {
|
||||
|
||||
@ -118,7 +118,7 @@ static void save_memory_to_file(char* addr, size_t size) {
|
||||
}
|
||||
}
|
||||
}
|
||||
FREE_C_HEAP_ARRAY(char, destfile);
|
||||
FREE_C_HEAP_ARRAY(destfile);
|
||||
}
|
||||
|
||||
|
||||
@ -483,14 +483,14 @@ static char* get_user_name(uid_t uid) {
|
||||
p->pw_name == nullptr ? "pw_name = null" : "pw_name zero length");
|
||||
}
|
||||
}
|
||||
FREE_C_HEAP_ARRAY(char, pwbuf);
|
||||
FREE_C_HEAP_ARRAY(pwbuf);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
char* user_name = NEW_C_HEAP_ARRAY(char, strlen(p->pw_name) + 1, mtInternal);
|
||||
strcpy(user_name, p->pw_name);
|
||||
|
||||
FREE_C_HEAP_ARRAY(char, pwbuf);
|
||||
FREE_C_HEAP_ARRAY(pwbuf);
|
||||
return user_name;
|
||||
}
|
||||
|
||||
@ -572,7 +572,7 @@ static char* get_user_name_slow(int vmid, int nspid, TRAPS) {
|
||||
DIR* subdirp = open_directory_secure(usrdir_name);
|
||||
|
||||
if (subdirp == nullptr) {
|
||||
FREE_C_HEAP_ARRAY(char, usrdir_name);
|
||||
FREE_C_HEAP_ARRAY(usrdir_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -583,7 +583,7 @@ static char* get_user_name_slow(int vmid, int nspid, TRAPS) {
|
||||
// symlink can be exploited.
|
||||
//
|
||||
if (!is_directory_secure(usrdir_name)) {
|
||||
FREE_C_HEAP_ARRAY(char, usrdir_name);
|
||||
FREE_C_HEAP_ARRAY(usrdir_name);
|
||||
os::closedir(subdirp);
|
||||
continue;
|
||||
}
|
||||
@ -607,13 +607,13 @@ static char* get_user_name_slow(int vmid, int nspid, TRAPS) {
|
||||
// don't follow symbolic links for the file
|
||||
RESTARTABLE(::lstat(filename, &statbuf), result);
|
||||
if (result == OS_ERR) {
|
||||
FREE_C_HEAP_ARRAY(char, filename);
|
||||
FREE_C_HEAP_ARRAY(filename);
|
||||
continue;
|
||||
}
|
||||
|
||||
// skip over files that are not regular files.
|
||||
if (!S_ISREG(statbuf.st_mode)) {
|
||||
FREE_C_HEAP_ARRAY(char, filename);
|
||||
FREE_C_HEAP_ARRAY(filename);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -623,7 +623,7 @@ static char* get_user_name_slow(int vmid, int nspid, TRAPS) {
|
||||
if (statbuf.st_ctime > oldest_ctime) {
|
||||
char* user = strchr(dentry->d_name, '_') + 1;
|
||||
|
||||
FREE_C_HEAP_ARRAY(char, oldest_user);
|
||||
FREE_C_HEAP_ARRAY(oldest_user);
|
||||
oldest_user = NEW_C_HEAP_ARRAY(char, strlen(user)+1, mtInternal);
|
||||
|
||||
strcpy(oldest_user, user);
|
||||
@ -631,11 +631,11 @@ static char* get_user_name_slow(int vmid, int nspid, TRAPS) {
|
||||
}
|
||||
}
|
||||
|
||||
FREE_C_HEAP_ARRAY(char, filename);
|
||||
FREE_C_HEAP_ARRAY(filename);
|
||||
}
|
||||
}
|
||||
os::closedir(subdirp);
|
||||
FREE_C_HEAP_ARRAY(char, usrdir_name);
|
||||
FREE_C_HEAP_ARRAY(usrdir_name);
|
||||
}
|
||||
os::closedir(tmpdirp);
|
||||
|
||||
@ -1105,11 +1105,11 @@ static char* mmap_create_shared(size_t size) {
|
||||
log_info(perf, memops)("Trying to open %s/%s", dirname, short_filename);
|
||||
fd = create_sharedmem_file(dirname, short_filename, size);
|
||||
|
||||
FREE_C_HEAP_ARRAY(char, user_name);
|
||||
FREE_C_HEAP_ARRAY(char, dirname);
|
||||
FREE_C_HEAP_ARRAY(user_name);
|
||||
FREE_C_HEAP_ARRAY(dirname);
|
||||
|
||||
if (fd == -1) {
|
||||
FREE_C_HEAP_ARRAY(char, filename);
|
||||
FREE_C_HEAP_ARRAY(filename);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -1121,7 +1121,7 @@ static char* mmap_create_shared(size_t size) {
|
||||
if (mapAddress == MAP_FAILED) {
|
||||
log_debug(perf)("mmap failed - %s", os::strerror(errno));
|
||||
remove_file(filename);
|
||||
FREE_C_HEAP_ARRAY(char, filename);
|
||||
FREE_C_HEAP_ARRAY(filename);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -1171,7 +1171,7 @@ static void delete_shared_memory(char* addr, size_t size) {
|
||||
remove_file(backing_store_file_name);
|
||||
// Don't.. Free heap memory could deadlock os::abort() if it is called
|
||||
// from signal handler. OS will reclaim the heap memory.
|
||||
// FREE_C_HEAP_ARRAY(char, backing_store_file_name);
|
||||
// FREE_C_HEAP_ARRAY(backing_store_file_name);
|
||||
backing_store_file_name = nullptr;
|
||||
}
|
||||
}
|
||||
@ -1223,8 +1223,8 @@ static void mmap_attach_shared(int vmid, char** addr, size_t* sizep, TRAPS) {
|
||||
// store file, we don't follow them when attaching either.
|
||||
//
|
||||
if (!is_directory_secure(dirname)) {
|
||||
FREE_C_HEAP_ARRAY(char, dirname);
|
||||
FREE_C_HEAP_ARRAY(char, luser);
|
||||
FREE_C_HEAP_ARRAY(dirname);
|
||||
FREE_C_HEAP_ARRAY(luser);
|
||||
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
|
||||
"Process not found");
|
||||
}
|
||||
@ -1236,9 +1236,9 @@ static void mmap_attach_shared(int vmid, char** addr, size_t* sizep, TRAPS) {
|
||||
int fd = open_sharedmem_file(filename, file_flags, THREAD);
|
||||
|
||||
// free the c heap resources that are no longer needed
|
||||
FREE_C_HEAP_ARRAY(char, luser);
|
||||
FREE_C_HEAP_ARRAY(char, dirname);
|
||||
FREE_C_HEAP_ARRAY(char, filename);
|
||||
FREE_C_HEAP_ARRAY(luser);
|
||||
FREE_C_HEAP_ARRAY(dirname);
|
||||
FREE_C_HEAP_ARRAY(filename);
|
||||
|
||||
if (HAS_PENDING_EXCEPTION) {
|
||||
assert(fd == OS_ERR, "open_sharedmem_file always return OS_ERR on exceptions");
|
||||
|
||||
@ -178,9 +178,9 @@ static void destroy(MultiCounterQueryP query) {
|
||||
for (int i = 0; i < query->noOfCounters; ++i) {
|
||||
close_query(nullptr, &query->counters[i]);
|
||||
}
|
||||
FREE_C_HEAP_ARRAY(char, query->counters);
|
||||
FREE_C_HEAP_ARRAY(query->counters);
|
||||
close_query(&query->query.pdh_query_handle, nullptr);
|
||||
FREE_C_HEAP_ARRAY(MultiCounterQueryS, query);
|
||||
FREE_C_HEAP_ARRAY(query);
|
||||
}
|
||||
}
|
||||
|
||||
@ -189,15 +189,15 @@ static void destroy_query_set(MultiCounterQuerySetP query_set) {
|
||||
for (int j = 0; j < query_set->queries[i].noOfCounters; ++j) {
|
||||
close_query(nullptr, &query_set->queries[i].counters[j]);
|
||||
}
|
||||
FREE_C_HEAP_ARRAY(char, query_set->queries[i].counters);
|
||||
FREE_C_HEAP_ARRAY(query_set->queries[i].counters);
|
||||
close_query(&query_set->queries[i].query.pdh_query_handle, nullptr);
|
||||
}
|
||||
FREE_C_HEAP_ARRAY(MultiCounterQueryS, query_set->queries);
|
||||
FREE_C_HEAP_ARRAY(query_set->queries);
|
||||
}
|
||||
|
||||
static void destroy(MultiCounterQuerySetP query) {
|
||||
destroy_query_set(query);
|
||||
FREE_C_HEAP_ARRAY(MultiCounterQuerySetS, query);
|
||||
FREE_C_HEAP_ARRAY(query);
|
||||
}
|
||||
|
||||
static void destroy(ProcessQueryP query) {
|
||||
@ -229,7 +229,7 @@ static void allocate_counters(ProcessQueryP query, size_t nofCounters) {
|
||||
}
|
||||
|
||||
static void deallocate_counters(MultiCounterQueryP query) {
|
||||
FREE_C_HEAP_ARRAY(char, query->counters);
|
||||
FREE_C_HEAP_ARRAY(query->counters);
|
||||
query->counters = nullptr;
|
||||
query->noOfCounters = 0;
|
||||
}
|
||||
@ -710,11 +710,11 @@ static const char* pdh_process_image_name() {
|
||||
}
|
||||
|
||||
static void deallocate_pdh_constants() {
|
||||
FREE_C_HEAP_ARRAY(char, process_image_name);
|
||||
FREE_C_HEAP_ARRAY(process_image_name);
|
||||
process_image_name = nullptr;
|
||||
FREE_C_HEAP_ARRAY(char, pdh_process_instance_IDProcess_counter_fmt);
|
||||
FREE_C_HEAP_ARRAY(pdh_process_instance_IDProcess_counter_fmt);
|
||||
pdh_process_instance_IDProcess_counter_fmt = nullptr;
|
||||
FREE_C_HEAP_ARRAY(char, pdh_process_instance_wildcard_IDProcess_counter);
|
||||
FREE_C_HEAP_ARRAY(pdh_process_instance_wildcard_IDProcess_counter);
|
||||
pdh_process_instance_wildcard_IDProcess_counter = nullptr;
|
||||
}
|
||||
|
||||
@ -1445,9 +1445,9 @@ bool CPUInformationInterface::initialize() {
|
||||
|
||||
CPUInformationInterface::~CPUInformationInterface() {
|
||||
if (_cpu_info != nullptr) {
|
||||
FREE_C_HEAP_ARRAY(char, _cpu_info->cpu_name());
|
||||
FREE_C_HEAP_ARRAY(_cpu_info->cpu_name());
|
||||
_cpu_info->set_cpu_name(nullptr);
|
||||
FREE_C_HEAP_ARRAY(char, _cpu_info->cpu_description());
|
||||
FREE_C_HEAP_ARRAY(_cpu_info->cpu_description());
|
||||
_cpu_info->set_cpu_description(nullptr);
|
||||
delete _cpu_info;
|
||||
}
|
||||
|
||||
@ -334,14 +334,14 @@ void os::init_system_properties_values() {
|
||||
home_path = NEW_C_HEAP_ARRAY(char, strlen(home_dir) + 1, mtInternal);
|
||||
strcpy(home_path, home_dir);
|
||||
Arguments::set_java_home(home_path);
|
||||
FREE_C_HEAP_ARRAY(char, home_path);
|
||||
FREE_C_HEAP_ARRAY(home_path);
|
||||
|
||||
dll_path = NEW_C_HEAP_ARRAY(char, strlen(home_dir) + strlen(bin) + 1,
|
||||
mtInternal);
|
||||
strcpy(dll_path, home_dir);
|
||||
strcat(dll_path, bin);
|
||||
Arguments::set_dll_dir(dll_path);
|
||||
FREE_C_HEAP_ARRAY(char, dll_path);
|
||||
FREE_C_HEAP_ARRAY(dll_path);
|
||||
|
||||
if (!set_boot_path('\\', ';')) {
|
||||
vm_exit_during_initialization("Failed setting boot class path.", nullptr);
|
||||
@ -396,7 +396,7 @@ void os::init_system_properties_values() {
|
||||
strcat(library_path, ";.");
|
||||
|
||||
Arguments::set_library_path(library_path);
|
||||
FREE_C_HEAP_ARRAY(char, library_path);
|
||||
FREE_C_HEAP_ARRAY(library_path);
|
||||
}
|
||||
|
||||
// Default extensions directory
|
||||
@ -1079,7 +1079,7 @@ void os::set_native_thread_name(const char *name) {
|
||||
HRESULT hr = _SetThreadDescription(current, unicode_name);
|
||||
if (FAILED(hr)) {
|
||||
log_debug(os, thread)("set_native_thread_name: SetThreadDescription failed - falling back to debugger method");
|
||||
FREE_C_HEAP_ARRAY(WCHAR, unicode_name);
|
||||
FREE_C_HEAP_ARRAY(unicode_name);
|
||||
} else {
|
||||
log_trace(os, thread)("set_native_thread_name: SetThreadDescription succeeded - new name: %s", name);
|
||||
|
||||
@ -1102,7 +1102,7 @@ void os::set_native_thread_name(const char *name) {
|
||||
LocalFree(thread_name);
|
||||
}
|
||||
#endif
|
||||
FREE_C_HEAP_ARRAY(WCHAR, unicode_name);
|
||||
FREE_C_HEAP_ARRAY(unicode_name);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
@ -2897,7 +2897,7 @@ class NUMANodeListHolder {
|
||||
int _numa_used_node_count;
|
||||
|
||||
void free_node_list() {
|
||||
FREE_C_HEAP_ARRAY(int, _numa_used_node_list);
|
||||
FREE_C_HEAP_ARRAY(_numa_used_node_list);
|
||||
}
|
||||
|
||||
public:
|
||||
@ -4744,7 +4744,7 @@ static wchar_t* wide_abs_unc_path(char const* path, errno_t & err, int additiona
|
||||
|
||||
LPWSTR unicode_path = nullptr;
|
||||
err = convert_to_unicode(buf, &unicode_path);
|
||||
FREE_C_HEAP_ARRAY(char, buf);
|
||||
FREE_C_HEAP_ARRAY(buf);
|
||||
if (err != ERROR_SUCCESS) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -4772,9 +4772,9 @@ static wchar_t* wide_abs_unc_path(char const* path, errno_t & err, int additiona
|
||||
}
|
||||
|
||||
if (converted_path != unicode_path) {
|
||||
FREE_C_HEAP_ARRAY(WCHAR, converted_path);
|
||||
FREE_C_HEAP_ARRAY(converted_path);
|
||||
}
|
||||
FREE_C_HEAP_ARRAY(WCHAR, unicode_path);
|
||||
FREE_C_HEAP_ARRAY(unicode_path);
|
||||
|
||||
return static_cast<wchar_t*>(result); // LPWSTR and wchat_t* are the same type on Windows.
|
||||
}
|
||||
@ -5827,7 +5827,7 @@ int os::fork_and_exec(const char* cmd) {
|
||||
exit_code = -1;
|
||||
}
|
||||
|
||||
FREE_C_HEAP_ARRAY(char, cmd_string);
|
||||
FREE_C_HEAP_ARRAY(cmd_string);
|
||||
return (int)exit_code;
|
||||
}
|
||||
|
||||
|
||||
@ -113,7 +113,7 @@ static void save_memory_to_file(char* addr, size_t size) {
|
||||
}
|
||||
}
|
||||
|
||||
FREE_C_HEAP_ARRAY(char, destfile);
|
||||
FREE_C_HEAP_ARRAY(destfile);
|
||||
}
|
||||
|
||||
// Shared Memory Implementation Details
|
||||
@ -319,7 +319,7 @@ static char* get_user_name_slow(int vmid) {
|
||||
DIR* subdirp = os::opendir(usrdir_name);
|
||||
|
||||
if (subdirp == nullptr) {
|
||||
FREE_C_HEAP_ARRAY(char, usrdir_name);
|
||||
FREE_C_HEAP_ARRAY(usrdir_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -330,7 +330,7 @@ static char* get_user_name_slow(int vmid) {
|
||||
// symlink can be exploited.
|
||||
//
|
||||
if (!is_directory_secure(usrdir_name)) {
|
||||
FREE_C_HEAP_ARRAY(char, usrdir_name);
|
||||
FREE_C_HEAP_ARRAY(usrdir_name);
|
||||
os::closedir(subdirp);
|
||||
continue;
|
||||
}
|
||||
@ -350,13 +350,13 @@ static char* get_user_name_slow(int vmid) {
|
||||
strcat(filename, udentry->d_name);
|
||||
|
||||
if (::stat(filename, &statbuf) == OS_ERR) {
|
||||
FREE_C_HEAP_ARRAY(char, filename);
|
||||
FREE_C_HEAP_ARRAY(filename);
|
||||
continue;
|
||||
}
|
||||
|
||||
// skip over files that are not regular files.
|
||||
if ((statbuf.st_mode & S_IFMT) != S_IFREG) {
|
||||
FREE_C_HEAP_ARRAY(char, filename);
|
||||
FREE_C_HEAP_ARRAY(filename);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -378,18 +378,18 @@ static char* get_user_name_slow(int vmid) {
|
||||
if (statbuf.st_ctime > latest_ctime) {
|
||||
char* user = strchr(dentry->d_name, '_') + 1;
|
||||
|
||||
FREE_C_HEAP_ARRAY(char, latest_user);
|
||||
FREE_C_HEAP_ARRAY(latest_user);
|
||||
latest_user = NEW_C_HEAP_ARRAY(char, strlen(user)+1, mtInternal);
|
||||
|
||||
strcpy(latest_user, user);
|
||||
latest_ctime = statbuf.st_ctime;
|
||||
}
|
||||
|
||||
FREE_C_HEAP_ARRAY(char, filename);
|
||||
FREE_C_HEAP_ARRAY(filename);
|
||||
}
|
||||
}
|
||||
os::closedir(subdirp);
|
||||
FREE_C_HEAP_ARRAY(char, usrdir_name);
|
||||
FREE_C_HEAP_ARRAY(usrdir_name);
|
||||
}
|
||||
os::closedir(tmpdirp);
|
||||
|
||||
@ -481,7 +481,7 @@ static void remove_file(const char* dirname, const char* filename) {
|
||||
}
|
||||
}
|
||||
|
||||
FREE_C_HEAP_ARRAY(char, path);
|
||||
FREE_C_HEAP_ARRAY(path);
|
||||
}
|
||||
|
||||
// returns true if the process represented by pid is alive, otherwise
|
||||
@ -708,11 +708,11 @@ static void free_security_desc(PSECURITY_DESCRIPTOR pSD) {
|
||||
// be an ACL we enlisted. free the resources.
|
||||
//
|
||||
if (success && exists && pACL != nullptr && !isdefault) {
|
||||
FREE_C_HEAP_ARRAY(char, pACL);
|
||||
FREE_C_HEAP_ARRAY(pACL);
|
||||
}
|
||||
|
||||
// free the security descriptor
|
||||
FREE_C_HEAP_ARRAY(char, pSD);
|
||||
FREE_C_HEAP_ARRAY(pSD);
|
||||
}
|
||||
}
|
||||
|
||||
@ -768,7 +768,7 @@ static PSID get_user_sid(HANDLE hProcess) {
|
||||
if (!GetTokenInformation(hAccessToken, TokenUser, token_buf, rsize, &rsize)) {
|
||||
log_debug(perf)("GetTokenInformation failure: lasterror = %d, rsize = %d",
|
||||
GetLastError(), rsize);
|
||||
FREE_C_HEAP_ARRAY(char, token_buf);
|
||||
FREE_C_HEAP_ARRAY(token_buf);
|
||||
CloseHandle(hAccessToken);
|
||||
return nullptr;
|
||||
}
|
||||
@ -779,15 +779,15 @@ static PSID get_user_sid(HANDLE hProcess) {
|
||||
if (!CopySid(nbytes, pSID, token_buf->User.Sid)) {
|
||||
log_debug(perf)("GetTokenInformation failure: lasterror = %d, rsize = %d",
|
||||
GetLastError(), rsize);
|
||||
FREE_C_HEAP_ARRAY(char, token_buf);
|
||||
FREE_C_HEAP_ARRAY(char, pSID);
|
||||
FREE_C_HEAP_ARRAY(token_buf);
|
||||
FREE_C_HEAP_ARRAY(pSID);
|
||||
CloseHandle(hAccessToken);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// close the access token.
|
||||
CloseHandle(hAccessToken);
|
||||
FREE_C_HEAP_ARRAY(char, token_buf);
|
||||
FREE_C_HEAP_ARRAY(token_buf);
|
||||
|
||||
return pSID;
|
||||
}
|
||||
@ -865,7 +865,7 @@ static bool add_allow_aces(PSECURITY_DESCRIPTOR pSD,
|
||||
|
||||
if (!InitializeAcl(newACL, newACLsize, ACL_REVISION)) {
|
||||
log_debug(perf)("InitializeAcl failure: lasterror = %d", GetLastError());
|
||||
FREE_C_HEAP_ARRAY(char, newACL);
|
||||
FREE_C_HEAP_ARRAY(newACL);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -876,7 +876,7 @@ static bool add_allow_aces(PSECURITY_DESCRIPTOR pSD,
|
||||
LPVOID ace;
|
||||
if (!GetAce(oldACL, ace_index, &ace)) {
|
||||
log_debug(perf)("InitializeAcl failure: lasterror = %d", GetLastError());
|
||||
FREE_C_HEAP_ARRAY(char, newACL);
|
||||
FREE_C_HEAP_ARRAY(newACL);
|
||||
return false;
|
||||
}
|
||||
if (((ACCESS_ALLOWED_ACE *)ace)->Header.AceFlags && INHERITED_ACE) {
|
||||
@ -901,7 +901,7 @@ static bool add_allow_aces(PSECURITY_DESCRIPTOR pSD,
|
||||
if (!AddAce(newACL, ACL_REVISION, MAXDWORD, ace,
|
||||
((PACE_HEADER)ace)->AceSize)) {
|
||||
log_debug(perf)("AddAce failure: lasterror = %d", GetLastError());
|
||||
FREE_C_HEAP_ARRAY(char, newACL);
|
||||
FREE_C_HEAP_ARRAY(newACL);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -915,7 +915,7 @@ static bool add_allow_aces(PSECURITY_DESCRIPTOR pSD,
|
||||
aces[i].mask, aces[i].pSid)) {
|
||||
log_debug(perf)("AddAccessAllowedAce failure: lasterror = %d",
|
||||
GetLastError());
|
||||
FREE_C_HEAP_ARRAY(char, newACL);
|
||||
FREE_C_HEAP_ARRAY(newACL);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -928,13 +928,13 @@ static bool add_allow_aces(PSECURITY_DESCRIPTOR pSD,
|
||||
LPVOID ace;
|
||||
if (!GetAce(oldACL, ace_index, &ace)) {
|
||||
log_debug(perf)("InitializeAcl failure: lasterror = %d", GetLastError());
|
||||
FREE_C_HEAP_ARRAY(char, newACL);
|
||||
FREE_C_HEAP_ARRAY(newACL);
|
||||
return false;
|
||||
}
|
||||
if (!AddAce(newACL, ACL_REVISION, MAXDWORD, ace,
|
||||
((PACE_HEADER)ace)->AceSize)) {
|
||||
log_debug(perf)("AddAce failure: lasterror = %d", GetLastError());
|
||||
FREE_C_HEAP_ARRAY(char, newACL);
|
||||
FREE_C_HEAP_ARRAY(newACL);
|
||||
return false;
|
||||
}
|
||||
ace_index++;
|
||||
@ -944,7 +944,7 @@ static bool add_allow_aces(PSECURITY_DESCRIPTOR pSD,
|
||||
// add the new ACL to the security descriptor.
|
||||
if (!SetSecurityDescriptorDacl(pSD, TRUE, newACL, FALSE)) {
|
||||
log_debug(perf)("SetSecurityDescriptorDacl failure: lasterror = %d", GetLastError());
|
||||
FREE_C_HEAP_ARRAY(char, newACL);
|
||||
FREE_C_HEAP_ARRAY(newACL);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -952,7 +952,7 @@ static bool add_allow_aces(PSECURITY_DESCRIPTOR pSD,
|
||||
// protected prevents that.
|
||||
if (!SetSecurityDescriptorControl(pSD, SE_DACL_PROTECTED, SE_DACL_PROTECTED)) {
|
||||
log_debug(perf)("SetSecurityDescriptorControl failure: lasterror = %d", GetLastError());
|
||||
FREE_C_HEAP_ARRAY(char, newACL);
|
||||
FREE_C_HEAP_ARRAY(newACL);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1057,7 +1057,7 @@ static LPSECURITY_ATTRIBUTES make_user_everybody_admin_security_attr(
|
||||
// create a security attributes structure with access control
|
||||
// entries as initialized above.
|
||||
LPSECURITY_ATTRIBUTES lpSA = make_security_attr(aces, 3);
|
||||
FREE_C_HEAP_ARRAY(char, aces[0].pSid);
|
||||
FREE_C_HEAP_ARRAY(aces[0].pSid);
|
||||
FreeSid(everybodySid);
|
||||
FreeSid(administratorsSid);
|
||||
return(lpSA);
|
||||
@ -1341,8 +1341,8 @@ static char* mapping_create_shared(size_t size) {
|
||||
|
||||
// check that the file system is secure - i.e. it supports ACLs.
|
||||
if (!is_filesystem_secure(dirname)) {
|
||||
FREE_C_HEAP_ARRAY(char, dirname);
|
||||
FREE_C_HEAP_ARRAY(char, user);
|
||||
FREE_C_HEAP_ARRAY(dirname);
|
||||
FREE_C_HEAP_ARRAY(user);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -1358,15 +1358,15 @@ static char* mapping_create_shared(size_t size) {
|
||||
assert(((size != 0) && (size % os::vm_page_size() == 0)),
|
||||
"unexpected PerfMemry region size");
|
||||
|
||||
FREE_C_HEAP_ARRAY(char, user);
|
||||
FREE_C_HEAP_ARRAY(user);
|
||||
|
||||
// create the shared memory resources
|
||||
sharedmem_fileMapHandle =
|
||||
create_sharedmem_resources(dirname, filename, objectname, size);
|
||||
|
||||
FREE_C_HEAP_ARRAY(char, filename);
|
||||
FREE_C_HEAP_ARRAY(char, objectname);
|
||||
FREE_C_HEAP_ARRAY(char, dirname);
|
||||
FREE_C_HEAP_ARRAY(filename);
|
||||
FREE_C_HEAP_ARRAY(objectname);
|
||||
FREE_C_HEAP_ARRAY(dirname);
|
||||
|
||||
if (sharedmem_fileMapHandle == nullptr) {
|
||||
return nullptr;
|
||||
@ -1480,8 +1480,8 @@ static void open_file_mapping(int vmid, char** addrp, size_t* sizep, TRAPS) {
|
||||
// store file, we also don't following them when attaching
|
||||
//
|
||||
if (!is_directory_secure(dirname)) {
|
||||
FREE_C_HEAP_ARRAY(char, dirname);
|
||||
FREE_C_HEAP_ARRAY(char, luser);
|
||||
FREE_C_HEAP_ARRAY(dirname);
|
||||
FREE_C_HEAP_ARRAY(luser);
|
||||
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
|
||||
"Process not found");
|
||||
}
|
||||
@ -1498,10 +1498,10 @@ static void open_file_mapping(int vmid, char** addrp, size_t* sizep, TRAPS) {
|
||||
char* robjectname = ResourceArea::strdup(THREAD, objectname);
|
||||
|
||||
// free the c heap resources that are no longer needed
|
||||
FREE_C_HEAP_ARRAY(char, luser);
|
||||
FREE_C_HEAP_ARRAY(char, dirname);
|
||||
FREE_C_HEAP_ARRAY(char, filename);
|
||||
FREE_C_HEAP_ARRAY(char, objectname);
|
||||
FREE_C_HEAP_ARRAY(luser);
|
||||
FREE_C_HEAP_ARRAY(dirname);
|
||||
FREE_C_HEAP_ARRAY(filename);
|
||||
FREE_C_HEAP_ARRAY(objectname);
|
||||
|
||||
size_t size;
|
||||
if (*sizep == 0) {
|
||||
|
||||
@ -81,10 +81,6 @@
|
||||
# include <ucontext.h>
|
||||
#endif
|
||||
|
||||
#if !defined(__APPLE__) && !defined(__NetBSD__)
|
||||
# include <pthread_np.h>
|
||||
#endif
|
||||
|
||||
#define SPELL_REG_SP "sp"
|
||||
|
||||
#ifdef __APPLE__
|
||||
@ -415,49 +411,6 @@ size_t os::Posix::default_stack_size(os::ThreadType thr_type) {
|
||||
size_t s = (thr_type == os::compiler_thread ? 4 * M : 1 * M);
|
||||
return s;
|
||||
}
|
||||
void os::current_stack_base_and_size(address* base, size_t* size) {
|
||||
address bottom;
|
||||
#ifdef __APPLE__
|
||||
pthread_t self = pthread_self();
|
||||
*base = (address) pthread_get_stackaddr_np(self);
|
||||
*size = pthread_get_stacksize_np(self);
|
||||
bottom = *base - *size;
|
||||
#elif defined(__OpenBSD__)
|
||||
stack_t ss;
|
||||
int rslt = pthread_stackseg_np(pthread_self(), &ss);
|
||||
|
||||
if (rslt != 0)
|
||||
fatal("pthread_stackseg_np failed with error = %d", rslt);
|
||||
|
||||
*base = (address) ss.ss_sp;
|
||||
*size = ss.ss_size;
|
||||
bottom = *base - *size;
|
||||
#else
|
||||
pthread_attr_t attr;
|
||||
|
||||
int rslt = pthread_attr_init(&attr);
|
||||
|
||||
// JVM needs to know exact stack location, abort if it fails
|
||||
if (rslt != 0)
|
||||
fatal("pthread_attr_init failed with error = %d", rslt);
|
||||
|
||||
rslt = pthread_attr_get_np(pthread_self(), &attr);
|
||||
|
||||
if (rslt != 0)
|
||||
fatal("pthread_attr_get_np failed with error = %d", rslt);
|
||||
|
||||
if (pthread_attr_getstackaddr(&attr, (void **)&bottom) != 0 ||
|
||||
pthread_attr_getstacksize(&attr, size) != 0) {
|
||||
fatal("Can not locate current stack attributes!");
|
||||
}
|
||||
|
||||
*base = bottom + *size;
|
||||
|
||||
pthread_attr_destroy(&attr);
|
||||
#endif
|
||||
assert(os::current_stack_pointer() >= bottom &&
|
||||
os::current_stack_pointer() < *base, "just checking");
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// helper functions for fatal error handler
|
||||
|
||||
@ -55,6 +55,7 @@
|
||||
// put OS-includes here
|
||||
# include <sys/types.h>
|
||||
# include <sys/mman.h>
|
||||
# include <sys/sysctl.h>
|
||||
# include <pthread.h>
|
||||
# include <signal.h>
|
||||
# include <errno.h>
|
||||
@ -73,19 +74,6 @@
|
||||
# include <ucontext.h>
|
||||
#endif
|
||||
|
||||
#if !defined(__APPLE__) && !defined(__NetBSD__)
|
||||
# include <pthread_np.h>
|
||||
#endif
|
||||
|
||||
// needed by current_stack_base_and_size() workaround for Mavericks
|
||||
#if defined(__APPLE__)
|
||||
# include <errno.h>
|
||||
# include <sys/types.h>
|
||||
# include <sys/sysctl.h>
|
||||
# define DEFAULT_MAIN_THREAD_STACK_PAGES 2048
|
||||
# define OS_X_10_9_0_KERNEL_MAJOR_VERSION 13
|
||||
#endif
|
||||
|
||||
#define SPELL_REG_SP "rsp"
|
||||
#define SPELL_REG_FP "rbp"
|
||||
#define REG_BCP context_r13
|
||||
@ -499,104 +487,6 @@ size_t os::Posix::default_stack_size(os::ThreadType thr_type) {
|
||||
}
|
||||
|
||||
|
||||
// Java thread:
|
||||
//
|
||||
// Low memory addresses
|
||||
// +------------------------+
|
||||
// | |\ Java thread created by VM does not have glibc
|
||||
// | glibc guard page | - guard, attached Java thread usually has
|
||||
// | |/ 1 glibc guard page.
|
||||
// P1 +------------------------+ Thread::stack_base() - Thread::stack_size()
|
||||
// | |\
|
||||
// | HotSpot Guard Pages | - red, yellow and reserved pages
|
||||
// | |/
|
||||
// +------------------------+ StackOverflow::stack_reserved_zone_base()
|
||||
// | |\
|
||||
// | Normal Stack | -
|
||||
// | |/
|
||||
// P2 +------------------------+ Thread::stack_base()
|
||||
//
|
||||
// Non-Java thread:
|
||||
//
|
||||
// Low memory addresses
|
||||
// +------------------------+
|
||||
// | |\
|
||||
// | glibc guard page | - usually 1 page
|
||||
// | |/
|
||||
// P1 +------------------------+ Thread::stack_base() - Thread::stack_size()
|
||||
// | |\
|
||||
// | Normal Stack | -
|
||||
// | |/
|
||||
// P2 +------------------------+ Thread::stack_base()
|
||||
//
|
||||
// ** P1 (aka bottom) and size are the address and stack size
|
||||
// returned from pthread_attr_getstack().
|
||||
// ** P2 (aka stack top or base) = P1 + size
|
||||
|
||||
void os::current_stack_base_and_size(address* base, size_t* size) {
|
||||
address bottom;
|
||||
#ifdef __APPLE__
|
||||
pthread_t self = pthread_self();
|
||||
*base = (address) pthread_get_stackaddr_np(self);
|
||||
*size = pthread_get_stacksize_np(self);
|
||||
// workaround for OS X 10.9.0 (Mavericks)
|
||||
// pthread_get_stacksize_np returns 128 pages even though the actual size is 2048 pages
|
||||
if (pthread_main_np() == 1) {
|
||||
// At least on Mac OS 10.12 we have observed stack sizes not aligned
|
||||
// to pages boundaries. This can be provoked by e.g. setrlimit() (ulimit -s xxxx in the
|
||||
// shell). Apparently Mac OS actually rounds upwards to next multiple of page size,
|
||||
// however, we round downwards here to be on the safe side.
|
||||
*size = align_down(*size, getpagesize());
|
||||
|
||||
if ((*size) < (DEFAULT_MAIN_THREAD_STACK_PAGES * (size_t)getpagesize())) {
|
||||
char kern_osrelease[256];
|
||||
size_t kern_osrelease_size = sizeof(kern_osrelease);
|
||||
int ret = sysctlbyname("kern.osrelease", kern_osrelease, &kern_osrelease_size, nullptr, 0);
|
||||
if (ret == 0) {
|
||||
// get the major number, atoi will ignore the minor amd micro portions of the version string
|
||||
if (atoi(kern_osrelease) >= OS_X_10_9_0_KERNEL_MAJOR_VERSION) {
|
||||
*size = (DEFAULT_MAIN_THREAD_STACK_PAGES*getpagesize());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
bottom = *base - *size;
|
||||
#elif defined(__OpenBSD__)
|
||||
stack_t ss;
|
||||
int rslt = pthread_stackseg_np(pthread_self(), &ss);
|
||||
|
||||
if (rslt != 0)
|
||||
fatal("pthread_stackseg_np failed with error = %d", rslt);
|
||||
|
||||
*base = (address) ss.ss_sp;
|
||||
*size = ss.ss_size;
|
||||
bottom = *base - *size;
|
||||
#else
|
||||
pthread_attr_t attr;
|
||||
|
||||
int rslt = pthread_attr_init(&attr);
|
||||
|
||||
// JVM needs to know exact stack location, abort if it fails
|
||||
if (rslt != 0)
|
||||
fatal("pthread_attr_init failed with error = %d", rslt);
|
||||
|
||||
rslt = pthread_attr_get_np(pthread_self(), &attr);
|
||||
|
||||
if (rslt != 0)
|
||||
fatal("pthread_attr_get_np failed with error = %d", rslt);
|
||||
|
||||
if (pthread_attr_getstackaddr(&attr, (void **)&bottom) != 0 ||
|
||||
pthread_attr_getstacksize(&attr, size) != 0) {
|
||||
fatal("Can not locate current stack attributes!");
|
||||
}
|
||||
|
||||
*base = bottom + *size;
|
||||
|
||||
pthread_attr_destroy(&attr);
|
||||
#endif
|
||||
assert(os::current_stack_pointer() >= bottom &&
|
||||
os::current_stack_pointer() < *base, "just checking");
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// helper functions for fatal error handler
|
||||
|
||||
@ -52,7 +52,6 @@
|
||||
|
||||
#if !defined(__APPLE__) && !defined(__NetBSD__)
|
||||
#include <pthread.h>
|
||||
# include <pthread_np.h> /* For pthread_attr_get_np */
|
||||
#endif
|
||||
|
||||
address os::current_stack_pointer() {
|
||||
@ -179,52 +178,6 @@ size_t os::Posix::default_stack_size(os::ThreadType thr_type) {
|
||||
return s;
|
||||
}
|
||||
|
||||
void os::current_stack_base_and_size(address* base, size_t* size) {
|
||||
address bottom;
|
||||
|
||||
#ifdef __APPLE__
|
||||
pthread_t self = pthread_self();
|
||||
*base = (address) pthread_get_stackaddr_np(self);
|
||||
*size = pthread_get_stacksize_np(self);
|
||||
bottom = *base - *size;
|
||||
#elif defined(__OpenBSD__)
|
||||
stack_t ss;
|
||||
int rslt = pthread_stackseg_np(pthread_self(), &ss);
|
||||
|
||||
if (rslt != 0)
|
||||
fatal("pthread_stackseg_np failed with error = %d", rslt);
|
||||
|
||||
*base = (address) ss.ss_sp;
|
||||
*size = ss.ss_size;
|
||||
bottom = *base - *size;
|
||||
#else
|
||||
pthread_attr_t attr;
|
||||
|
||||
int rslt = pthread_attr_init(&attr);
|
||||
|
||||
// JVM needs to know exact stack location, abort if it fails
|
||||
if (rslt != 0)
|
||||
fatal("pthread_attr_init failed with error = %d", rslt);
|
||||
|
||||
rslt = pthread_attr_get_np(pthread_self(), &attr);
|
||||
|
||||
if (rslt != 0)
|
||||
fatal("pthread_attr_get_np failed with error = %d", rslt);
|
||||
|
||||
if (pthread_attr_getstackaddr(&attr, (void **) &bottom) != 0 ||
|
||||
pthread_attr_getstacksize(&attr, size) != 0) {
|
||||
fatal("Can not locate current stack attributes!");
|
||||
}
|
||||
|
||||
*base = bottom + *size;
|
||||
|
||||
pthread_attr_destroy(&attr);
|
||||
|
||||
#endif
|
||||
assert(os::current_stack_pointer() >= bottom &&
|
||||
os::current_stack_pointer() < *base, "just checking");
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// helper functions for fatal error handler
|
||||
|
||||
|
||||
@ -24,19 +24,26 @@
|
||||
; Support for int get_sve_vector_length();
|
||||
;
|
||||
; Returns the current SVE vector length in bytes.
|
||||
; This function uses the INCB instruction which increments a register
|
||||
; by the number of bytes in an SVE vector register.
|
||||
; This function uses the RDVL instruction which reads a multiple of the
|
||||
; vector register size into a scalar register.
|
||||
;
|
||||
; Note: This function will fault if SVE is not available or enabled.
|
||||
; The caller must ensure SVE support is detected before calling.
|
||||
; Note: This function will fault if SVE is not available or enabled. The
|
||||
; caller must ensure SVE support is detected before calling.
|
||||
|
||||
ALIGN 4
|
||||
EXPORT get_sve_vector_length
|
||||
AREA sve_text, CODE
|
||||
|
||||
get_sve_vector_length
|
||||
mov x0, #0
|
||||
incb x0
|
||||
; Older versions of Visual Studio aren't aware of SVE mnemonics, so we use
|
||||
; the raw instruction encoding to satisfy the compiler. This function call
|
||||
; is gated by `VM_Version::supports_sve()`, so this instruction will never
|
||||
; run on non-SVE hardware.
|
||||
;
|
||||
; See https://www.scs.stanford.edu/~zyedidia/arm64/rdvl_r_i.html for a quick
|
||||
; reference to the instruction encoding.
|
||||
|
||||
DCD 0x04BF5020 ; rdvl x0, #1 (i.e. x0 = 1 * vector_length_in_bytes)
|
||||
ret
|
||||
|
||||
END
|
||||
|
||||
@ -26,19 +26,52 @@
|
||||
#include "runtime/os.hpp"
|
||||
#include "runtime/vm_version.hpp"
|
||||
|
||||
// Assembly function to get SVE vector length using INCB instruction
|
||||
// Since PF_ARM_SVE_INSTRUCTIONS_AVAILABLE and related constants were added in
|
||||
// Windows 11 (version 24H2) and in Windows Server 2025, we define them here for
|
||||
// compatibility with older SDK versions.
|
||||
#ifndef PF_ARM_SVE_INSTRUCTIONS_AVAILABLE
|
||||
#define PF_ARM_SVE_INSTRUCTIONS_AVAILABLE 46
|
||||
#endif
|
||||
|
||||
#ifndef PF_ARM_SVE2_INSTRUCTIONS_AVAILABLE
|
||||
#define PF_ARM_SVE2_INSTRUCTIONS_AVAILABLE 47
|
||||
#endif
|
||||
|
||||
#ifndef PF_ARM_SVE_BITPERM_INSTRUCTIONS_AVAILABLE
|
||||
#define PF_ARM_SVE_BITPERM_INSTRUCTIONS_AVAILABLE 51
|
||||
#endif
|
||||
|
||||
#ifndef PF_ARM_SHA3_INSTRUCTIONS_AVAILABLE
|
||||
#define PF_ARM_SHA3_INSTRUCTIONS_AVAILABLE 64
|
||||
#endif
|
||||
|
||||
#ifndef PF_ARM_SHA512_INSTRUCTIONS_AVAILABLE
|
||||
#define PF_ARM_SHA512_INSTRUCTIONS_AVAILABLE 65
|
||||
#endif
|
||||
|
||||
#ifndef PF_ARM_V82_FP16_INSTRUCTIONS_AVAILABLE
|
||||
#define PF_ARM_V82_FP16_INSTRUCTIONS_AVAILABLE 67
|
||||
#endif
|
||||
|
||||
// Assembly function to get SVE vector length using RDVL instruction
|
||||
extern "C" int get_sve_vector_length();
|
||||
|
||||
int VM_Version::get_current_sve_vector_length() {
|
||||
assert(VM_Version::supports_sve(), "should not call this");
|
||||
// Use assembly instruction to get the actual SVE vector length
|
||||
return VM_Version::supports_sve() ? get_sve_vector_length() : 0; // This value is in bytes
|
||||
return VM_Version::supports_sve() ? get_sve_vector_length() : 0;
|
||||
}
|
||||
|
||||
int VM_Version::set_and_get_current_sve_vector_length(int length) {
|
||||
assert(VM_Version::supports_sve(), "should not call this");
|
||||
// Use assembly instruction to get the SVE vector length
|
||||
return VM_Version::supports_sve() ? get_sve_vector_length() : 0; // This value is in bytes
|
||||
|
||||
// Unlike Linux, Windows does not present a way to modify the VL (the
|
||||
// rationale is that the OS expects the application to use the maximum vector
|
||||
// length supported by the hardware), so we simply return the current VL. If
|
||||
// the user sets `MaxVectorSize` that is not the same as the maximum possible
|
||||
// vector length, then the caller (`VM_Version::initialize()`) will print a
|
||||
// warning, set `MaxVectorSize` to the value returned by this function, and
|
||||
// move on.
|
||||
return VM_Version::supports_sve() ? get_sve_vector_length() : 0;
|
||||
}
|
||||
|
||||
void VM_Version::get_os_cpu_info() {
|
||||
@ -67,6 +100,10 @@ void VM_Version::get_os_cpu_info() {
|
||||
if (IsProcessorFeaturePresent(PF_ARM_SVE_BITPERM_INSTRUCTIONS_AVAILABLE)) {
|
||||
set_feature(CPU_SVEBITPERM);
|
||||
}
|
||||
if (IsProcessorFeaturePresent(PF_ARM_V82_FP16_INSTRUCTIONS_AVAILABLE)) {
|
||||
set_feature(CPU_FPHP);
|
||||
set_feature(CPU_ASIMDHP);
|
||||
}
|
||||
if (IsProcessorFeaturePresent(PF_ARM_SHA3_INSTRUCTIONS_AVAILABLE)) {
|
||||
set_feature(CPU_SHA3);
|
||||
}
|
||||
|
||||
@ -417,7 +417,7 @@ void CodeSection::expand_locs(int new_capacity) {
|
||||
new_capacity = old_capacity * 2;
|
||||
relocInfo* locs_start;
|
||||
if (_locs_own) {
|
||||
locs_start = REALLOC_RESOURCE_ARRAY(relocInfo, _locs_start, old_capacity, new_capacity);
|
||||
locs_start = REALLOC_RESOURCE_ARRAY(_locs_start, old_capacity, new_capacity);
|
||||
} else {
|
||||
locs_start = NEW_RESOURCE_ARRAY(relocInfo, new_capacity);
|
||||
Copy::conjoint_jbytes(_locs_start, locs_start, old_capacity * sizeof(relocInfo));
|
||||
|
||||
@ -330,8 +330,9 @@ class LIRGenerator: public InstructionVisitor, public BlockClosure {
|
||||
|
||||
// volatile field operations are never patchable because a klass
|
||||
// must be loaded to know it's volatile which means that the offset
|
||||
// it always known as well.
|
||||
// is always known as well.
|
||||
void volatile_field_store(LIR_Opr value, LIR_Address* address, CodeEmitInfo* info);
|
||||
// volatile_field_load provides trailing membar semantics
|
||||
void volatile_field_load(LIR_Address* address, LIR_Opr result, CodeEmitInfo* info);
|
||||
|
||||
void put_Object_unsafe(LIR_Opr src, LIR_Opr offset, LIR_Opr data, BasicType type, bool is_volatile);
|
||||
|
||||
@ -105,7 +105,9 @@ public:
|
||||
// Return true if given address is in the shared metaspace regions (i.e., excluding the
|
||||
// mapped heap region.)
|
||||
static bool in_aot_cache(const void* p) {
|
||||
return MetaspaceObj::in_aot_cache((const MetaspaceObj*)p);
|
||||
// This function is called only after the AOT metaspace is initialized, so
|
||||
// we can skip init checks.
|
||||
return MetaspaceObj::is_pointer_in_aot_cache_no_init_check(p);
|
||||
}
|
||||
|
||||
static void set_aot_metaspace_range(void* base, void *static_top, void* top) NOT_CDS_RETURN;
|
||||
|
||||
@ -797,7 +797,7 @@ void AOTStreamedHeapLoader::cleanup() {
|
||||
Universe::vm_global()->release(&handles[num_null_handles], num_handles - num_null_handles);
|
||||
}
|
||||
|
||||
FREE_C_HEAP_ARRAY(void*, _object_index_to_heap_object_table);
|
||||
FREE_C_HEAP_ARRAY(_object_index_to_heap_object_table);
|
||||
|
||||
// Unmap regions
|
||||
FileMapInfo::current_info()->unmap_region(AOTMetaspace::hp);
|
||||
|
||||
@ -1171,7 +1171,7 @@ void ArchiveBuilder::write_archive(FileMapInfo* mapinfo, AOTMappedHeapInfo* mapp
|
||||
AOTMapLogger::dumptime_log(this, mapinfo, mapped_heap_info, streamed_heap_info, bitmap, bitmap_size_in_bytes);
|
||||
}
|
||||
CDS_JAVA_HEAP_ONLY(HeapShared::destroy_archived_object_cache());
|
||||
FREE_C_HEAP_ARRAY(char, bitmap);
|
||||
FREE_C_HEAP_ARRAY(bitmap);
|
||||
}
|
||||
|
||||
void ArchiveBuilder::write_region(FileMapInfo* mapinfo, int region_idx, DumpRegion* dump_region, bool read_only, bool allow_exec) {
|
||||
|
||||
@ -520,7 +520,7 @@ static void substitute_aot_filename(JVMFlagsEnum flag_enum) {
|
||||
JVMFlag::Error err = JVMFlagAccess::set_ccstr(flag, &new_filename, JVMFlagOrigin::ERGONOMIC);
|
||||
assert(err == JVMFlag::SUCCESS, "must never fail");
|
||||
}
|
||||
FREE_C_HEAP_ARRAY(char, new_filename);
|
||||
FREE_C_HEAP_ARRAY(new_filename);
|
||||
}
|
||||
|
||||
void CDSConfig::check_aotmode_record() {
|
||||
|
||||
@ -163,7 +163,7 @@
|
||||
\
|
||||
product(uint, AOTCodeMaxSize, 10*M, DIAGNOSTIC, \
|
||||
"Buffer size in bytes for AOT code caching") \
|
||||
range(1*M, max_jint) \
|
||||
range(1*M, CODE_CACHE_SIZE_LIMIT) \
|
||||
\
|
||||
product(bool, AbortVMOnAOTCodeFailure, false, DIAGNOSTIC, \
|
||||
"Abort VM on the first occurrence of AOT code load or store " \
|
||||
|
||||
@ -49,7 +49,7 @@ void ClassListWriter::init() {
|
||||
_classlist_file->print_cr("# This file is generated via the -XX:DumpLoadedClassList=<class_list_file> option");
|
||||
_classlist_file->print_cr("# and is used at CDS archive dump time (see -Xshare:dump).");
|
||||
_classlist_file->print_cr("#");
|
||||
FREE_C_HEAP_ARRAY(char, list_name);
|
||||
FREE_C_HEAP_ARRAY(list_name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -402,7 +402,7 @@ public:
|
||||
|
||||
~FileHeaderHelper() {
|
||||
if (_header != nullptr) {
|
||||
FREE_C_HEAP_ARRAY(char, _header);
|
||||
FREE_C_HEAP_ARRAY(_header);
|
||||
}
|
||||
if (_fd != -1) {
|
||||
::close(_fd);
|
||||
@ -1362,6 +1362,13 @@ bool FileMapInfo::map_aot_code_region(ReservedSpace rs) {
|
||||
return false;
|
||||
} else {
|
||||
assert(mapped_base == requested_base, "must be");
|
||||
|
||||
if (VerifySharedSpaces && !r->check_region_crc(mapped_base)) {
|
||||
aot_log_error(aot)("region %d CRC error", AOTMetaspace::ac);
|
||||
os::unmap_memory(mapped_base, r->used_aligned());
|
||||
return false;
|
||||
}
|
||||
|
||||
r->set_mapped_from_file(true);
|
||||
r->set_mapped_base(mapped_base);
|
||||
aot_log_info(aot)("Mapped static region #%d at base " INTPTR_FORMAT " top " INTPTR_FORMAT " (%s)",
|
||||
@ -1464,14 +1471,14 @@ size_t FileMapInfo::read_bytes(void* buffer, size_t count) {
|
||||
return count;
|
||||
}
|
||||
|
||||
// Get the total size in bytes of a read only region
|
||||
// Get the total size in bytes of all mapped read only region
|
||||
size_t FileMapInfo::readonly_total() {
|
||||
size_t total = 0;
|
||||
if (current_info() != nullptr) {
|
||||
if (current_info() != nullptr && current_info()->is_mapped()) {
|
||||
FileMapRegion* r = FileMapInfo::current_info()->region_at(AOTMetaspace::ro);
|
||||
if (r->read_only()) total += r->used();
|
||||
}
|
||||
if (dynamic_info() != nullptr) {
|
||||
if (dynamic_info() != nullptr && current_info()->is_mapped()) {
|
||||
FileMapRegion* r = FileMapInfo::dynamic_info()->region_at(AOTMetaspace::ro);
|
||||
if (r->read_only()) total += r->used();
|
||||
}
|
||||
|
||||
@ -600,7 +600,7 @@ class CompileReplay : public StackObj {
|
||||
_nesting.check(); // Check if a reallocation in the resource arena is safe
|
||||
int new_length = _buffer_length * 2;
|
||||
// Next call will throw error in case of OOM.
|
||||
_buffer = REALLOC_RESOURCE_ARRAY(char, _buffer, _buffer_length, new_length);
|
||||
_buffer = REALLOC_RESOURCE_ARRAY(_buffer, _buffer_length, new_length);
|
||||
_buffer_length = new_length;
|
||||
}
|
||||
if (c == '\n') {
|
||||
|
||||
@ -2363,8 +2363,8 @@ Method* ClassFileParser::parse_method(const ClassFileStream* const cfs,
|
||||
}
|
||||
if (lvt_cnt == max_lvt_cnt) {
|
||||
max_lvt_cnt <<= 1;
|
||||
localvariable_table_length = REALLOC_RESOURCE_ARRAY(u2, localvariable_table_length, lvt_cnt, max_lvt_cnt);
|
||||
localvariable_table_start = REALLOC_RESOURCE_ARRAY(const unsafe_u2*, localvariable_table_start, lvt_cnt, max_lvt_cnt);
|
||||
localvariable_table_length = REALLOC_RESOURCE_ARRAY(localvariable_table_length, lvt_cnt, max_lvt_cnt);
|
||||
localvariable_table_start = REALLOC_RESOURCE_ARRAY(localvariable_table_start, lvt_cnt, max_lvt_cnt);
|
||||
}
|
||||
localvariable_table_start[lvt_cnt] =
|
||||
parse_localvariable_table(cfs,
|
||||
@ -2393,8 +2393,8 @@ Method* ClassFileParser::parse_method(const ClassFileStream* const cfs,
|
||||
// Parse local variable type table
|
||||
if (lvtt_cnt == max_lvtt_cnt) {
|
||||
max_lvtt_cnt <<= 1;
|
||||
localvariable_type_table_length = REALLOC_RESOURCE_ARRAY(u2, localvariable_type_table_length, lvtt_cnt, max_lvtt_cnt);
|
||||
localvariable_type_table_start = REALLOC_RESOURCE_ARRAY(const unsafe_u2*, localvariable_type_table_start, lvtt_cnt, max_lvtt_cnt);
|
||||
localvariable_type_table_length = REALLOC_RESOURCE_ARRAY(localvariable_type_table_length, lvtt_cnt, max_lvtt_cnt);
|
||||
localvariable_type_table_start = REALLOC_RESOURCE_ARRAY(localvariable_type_table_start, lvtt_cnt, max_lvtt_cnt);
|
||||
}
|
||||
localvariable_type_table_start[lvtt_cnt] =
|
||||
parse_localvariable_table(cfs,
|
||||
|
||||
@ -251,7 +251,7 @@ const char* ClassPathEntry::copy_path(const char* path) {
|
||||
}
|
||||
|
||||
ClassPathDirEntry::~ClassPathDirEntry() {
|
||||
FREE_C_HEAP_ARRAY(char, _dir);
|
||||
FREE_C_HEAP_ARRAY(_dir);
|
||||
}
|
||||
|
||||
ClassFileStream* ClassPathDirEntry::open_stream(JavaThread* current, const char* name) {
|
||||
@ -280,7 +280,7 @@ ClassFileStream* ClassPathDirEntry::open_stream(JavaThread* current, const char*
|
||||
#ifdef ASSERT
|
||||
// Freeing path is a no-op here as buffer prevents it from being reclaimed. But we keep it for
|
||||
// debug builds so that we guard against use-after-free bugs.
|
||||
FREE_RESOURCE_ARRAY_IN_THREAD(current, char, path, path_len);
|
||||
FREE_RESOURCE_ARRAY_IN_THREAD(current, path, path_len);
|
||||
#endif
|
||||
// We don't verify the length of the classfile stream fits in an int, but this is the
|
||||
// bootloader so we have control of this.
|
||||
@ -291,7 +291,7 @@ ClassFileStream* ClassPathDirEntry::open_stream(JavaThread* current, const char*
|
||||
}
|
||||
}
|
||||
}
|
||||
FREE_RESOURCE_ARRAY_IN_THREAD(current, char, path, path_len);
|
||||
FREE_RESOURCE_ARRAY_IN_THREAD(current, path, path_len);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -302,7 +302,7 @@ ClassPathZipEntry::ClassPathZipEntry(jzfile* zip, const char* zip_name) : ClassP
|
||||
|
||||
ClassPathZipEntry::~ClassPathZipEntry() {
|
||||
ZipLibrary::close(_zip);
|
||||
FREE_C_HEAP_ARRAY(char, _zip_name);
|
||||
FREE_C_HEAP_ARRAY(_zip_name);
|
||||
}
|
||||
|
||||
bool ClassPathZipEntry::has_entry(JavaThread* current, const char* name) {
|
||||
@ -707,6 +707,7 @@ ClassPathEntry* ClassLoader::create_class_path_entry(JavaThread* current,
|
||||
if (zip != nullptr && error_msg == nullptr) {
|
||||
new_entry = new ClassPathZipEntry(zip, path);
|
||||
} else {
|
||||
log_info(class, path)("failed: %s, err: %s", path, error_msg);
|
||||
return nullptr;
|
||||
}
|
||||
log_info(class, path)("opened: %s", path);
|
||||
@ -1438,7 +1439,7 @@ bool ClassLoader::is_module_observable(const char* module_name) {
|
||||
struct stat st;
|
||||
const char *path = get_exploded_module_path(module_name, true);
|
||||
bool res = os::stat(path, &st) == 0;
|
||||
FREE_C_HEAP_ARRAY(char, path);
|
||||
FREE_C_HEAP_ARRAY(path);
|
||||
return res;
|
||||
}
|
||||
jlong size;
|
||||
|
||||
@ -69,7 +69,7 @@ CompactHashtableWriter::~CompactHashtableWriter() {
|
||||
delete bucket;
|
||||
}
|
||||
|
||||
FREE_C_HEAP_ARRAY(GrowableArray<Entry>*, _buckets);
|
||||
FREE_C_HEAP_ARRAY(_buckets);
|
||||
}
|
||||
|
||||
// Add an entry to the temporary hash table
|
||||
|
||||
@ -114,15 +114,15 @@ ResolutionErrorEntry::~ResolutionErrorEntry() {
|
||||
Symbol::maybe_decrement_refcount(_cause);
|
||||
|
||||
if (_message != nullptr) {
|
||||
FREE_C_HEAP_ARRAY(char, _message);
|
||||
FREE_C_HEAP_ARRAY(_message);
|
||||
}
|
||||
|
||||
if (_cause_msg != nullptr) {
|
||||
FREE_C_HEAP_ARRAY(char, _cause_msg);
|
||||
FREE_C_HEAP_ARRAY(_cause_msg);
|
||||
}
|
||||
|
||||
if (nest_host_error() != nullptr) {
|
||||
FREE_C_HEAP_ARRAY(char, nest_host_error());
|
||||
FREE_C_HEAP_ARRAY(nest_host_error());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1277,7 +1277,7 @@ unsigned int SystemDictionaryShared::hash_for_shared_dictionary(address ptr) {
|
||||
uintx offset = ArchiveBuilder::current()->any_to_offset(ptr);
|
||||
unsigned int hash = primitive_hash<uintx>(offset);
|
||||
DEBUG_ONLY({
|
||||
if (MetaspaceObj::in_aot_cache((const MetaspaceObj*)ptr)) {
|
||||
if (AOTMetaspace::in_aot_cache(ptr)) {
|
||||
assert(hash == SystemDictionaryShared::hash_for_shared_dictionary_quick(ptr), "must be");
|
||||
}
|
||||
});
|
||||
|
||||
@ -25,6 +25,7 @@
|
||||
#ifndef SHARE_CLASSFILE_SYSTEMDICTIONARYSHARED_HPP
|
||||
#define SHARE_CLASSFILE_SYSTEMDICTIONARYSHARED_HPP
|
||||
|
||||
#include "cds/aotMetaspace.hpp"
|
||||
#include "cds/cds_globals.hpp"
|
||||
#include "cds/dumpTimeClassInfo.hpp"
|
||||
#include "cds/filemap.hpp"
|
||||
@ -312,7 +313,7 @@ public:
|
||||
|
||||
template <typename T>
|
||||
static unsigned int hash_for_shared_dictionary_quick(T* ptr) {
|
||||
assert(MetaspaceObj::in_aot_cache((const MetaspaceObj*)ptr), "must be");
|
||||
assert(AOTMetaspace::in_aot_cache(ptr), "must be");
|
||||
assert(ptr > (T*)SharedBaseAddress, "must be");
|
||||
uintx offset = uintx(ptr) - uintx(SharedBaseAddress);
|
||||
return primitive_hash<uintx>(offset);
|
||||
|
||||
@ -83,15 +83,24 @@ const char* aot_code_entry_kind_name[] = {
|
||||
static LogStream& load_failure_log() {
|
||||
static LogStream err_stream(LogLevel::Error, LogTagSetMapping<LOG_TAGS(aot, codecache, init)>::tagset());
|
||||
static LogStream dbg_stream(LogLevel::Debug, LogTagSetMapping<LOG_TAGS(aot, codecache, init)>::tagset());
|
||||
if (RequireSharedSpaces) {
|
||||
if (RequireSharedSpaces || AbortVMOnAOTCodeFailure) {
|
||||
return err_stream;
|
||||
} else {
|
||||
return dbg_stream;
|
||||
}
|
||||
}
|
||||
|
||||
// Report AOT code cache failure and exit VM
|
||||
// if (AOTMode is `on` and AbortVMOnAOTCodeFailure is default)
|
||||
// or AbortVMOnAOTCodeFailure is `true`.
|
||||
//
|
||||
// Note, specifying -XX:-AbortVMOnAOTCodeFailure on command line
|
||||
// will prevent aborting VM when AOTMode is `on`. It is used for testing.
|
||||
|
||||
static void report_load_failure() {
|
||||
if (AbortVMOnAOTCodeFailure) {
|
||||
bool abort_vm = AbortVMOnAOTCodeFailure ||
|
||||
(FLAG_IS_DEFAULT(AbortVMOnAOTCodeFailure) && RequireSharedSpaces);
|
||||
if (abort_vm) {
|
||||
vm_exit_during_initialization("Unable to use AOT Code Cache.", nullptr);
|
||||
}
|
||||
load_failure_log().print_cr("Unable to use AOT Code Cache.");
|
||||
@ -482,25 +491,25 @@ bool AOTCodeCache::Config::verify_cpu_features(AOTCodeCache* cache) const {
|
||||
log.print_cr("CPU features recorded in AOTCodeCache: %s", ss.as_string());
|
||||
}
|
||||
|
||||
if (VM_Version::supports_features(cached_cpu_features_buffer)) {
|
||||
if (log.is_enabled()) {
|
||||
ResourceMark rm; // required for stringStream::as_string()
|
||||
stringStream ss;
|
||||
char* runtime_cpu_features = NEW_RESOURCE_ARRAY(char, VM_Version::cpu_features_size());
|
||||
VM_Version::store_cpu_features(runtime_cpu_features);
|
||||
VM_Version::get_missing_features_name(runtime_cpu_features, cached_cpu_features_buffer, ss);
|
||||
if (!ss.is_empty()) {
|
||||
log.print_cr("Additional runtime CPU features: %s", ss.as_string());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!VM_Version::verify_aot_code_cache_features(cached_cpu_features_buffer)) {
|
||||
if (load_failure_log().is_enabled()) {
|
||||
ResourceMark rm; // required for stringStream::as_string()
|
||||
stringStream ss;
|
||||
load_failure_log().print_cr("AOT Code Cache disabled: cpu features are incompatible");
|
||||
char* runtime_cpu_features = NEW_RESOURCE_ARRAY(char, VM_Version::cpu_features_size());
|
||||
VM_Version::store_cpu_features(runtime_cpu_features);
|
||||
VM_Version::get_missing_features_name(cached_cpu_features_buffer, runtime_cpu_features, ss);
|
||||
load_failure_log().print_cr("AOT Code Cache disabled: required cpu features are missing: %s", ss.as_string());
|
||||
|
||||
stringStream missing_features;
|
||||
VM_Version::get_missing_features_name(cached_cpu_features_buffer, runtime_cpu_features, missing_features);
|
||||
if (!missing_features.is_empty()) {
|
||||
load_failure_log().print_cr("cpu features that are required: \"%s\"", missing_features.as_string());
|
||||
}
|
||||
|
||||
stringStream additional_features;
|
||||
VM_Version::get_missing_features_name(runtime_cpu_features, cached_cpu_features_buffer, additional_features);
|
||||
if (!additional_features.is_empty()) {
|
||||
load_failure_log().print("cpu features that are additional: \"%s\"", additional_features.as_string());
|
||||
}
|
||||
load_failure_log().print_cr("");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -652,6 +661,10 @@ void AOTCodeReader::set_read_position(uint pos) {
|
||||
_read_position = pos;
|
||||
}
|
||||
|
||||
uint AOTCodeReader::align_read_int() {
|
||||
return align_up(_read_position, sizeof(int));
|
||||
}
|
||||
|
||||
bool AOTCodeCache::set_write_position(uint pos) {
|
||||
if (pos == _write_position) {
|
||||
return true;
|
||||
@ -666,21 +679,29 @@ bool AOTCodeCache::set_write_position(uint pos) {
|
||||
|
||||
static char align_buffer[256] = { 0 };
|
||||
|
||||
bool AOTCodeCache::align_write() {
|
||||
// We are not executing code from cache - we copy it by bytes first.
|
||||
// No need for big alignment (or at all).
|
||||
uint padding = DATA_ALIGNMENT - (_write_position & (DATA_ALIGNMENT - 1));
|
||||
if (padding == DATA_ALIGNMENT) {
|
||||
bool AOTCodeCache::align_write_bytes(uint alignment) {
|
||||
uint padding = alignment - (_write_position & (alignment - 1));
|
||||
if (padding == alignment) {
|
||||
return true;
|
||||
}
|
||||
uint n = write_bytes((const void*)&align_buffer, padding);
|
||||
if (n != padding) {
|
||||
return false;
|
||||
}
|
||||
log_trace(aot, codecache)("Adjust write alignment in AOT Code Cache");
|
||||
log_trace(aot, codecache)("Adjust write alignment to %d bytes in AOT Code Cache", alignment);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AOTCodeCache::align_write() {
|
||||
// We are not executing code from cache - we copy it by bytes first.
|
||||
// No need for big alignment (or at all).
|
||||
return align_write_bytes(DATA_ALIGNMENT);
|
||||
}
|
||||
|
||||
bool AOTCodeCache::align_write_int() {
|
||||
return align_write_bytes(sizeof(int));
|
||||
}
|
||||
|
||||
// Check to see if AOT code cache has required space to store "nbytes" of data
|
||||
address AOTCodeCache::reserve_bytes(uint nbytes) {
|
||||
assert(for_dump(), "Code Cache file is not created");
|
||||
@ -876,7 +897,7 @@ bool AOTCodeCache::finish_write() {
|
||||
current += size;
|
||||
uint n = write_bytes(&(entries_address[i]), sizeof(AOTCodeEntry));
|
||||
if (n != sizeof(AOTCodeEntry)) {
|
||||
FREE_C_HEAP_ARRAY(uint, search);
|
||||
FREE_C_HEAP_ARRAY(search);
|
||||
return false;
|
||||
}
|
||||
search[entries_count*2 + 0] = entries_address[i].id();
|
||||
@ -897,7 +918,7 @@ bool AOTCodeCache::finish_write() {
|
||||
}
|
||||
if (entries_count == 0) {
|
||||
log_info(aot, codecache, exit)("AOT Code Cache was not created: no entires");
|
||||
FREE_C_HEAP_ARRAY(uint, search);
|
||||
FREE_C_HEAP_ARRAY(search);
|
||||
return true; // Nothing to write
|
||||
}
|
||||
assert(entries_count <= store_count, "%d > %d", entries_count, store_count);
|
||||
@ -913,7 +934,7 @@ bool AOTCodeCache::finish_write() {
|
||||
qsort(search, entries_count, 2*sizeof(uint), uint_cmp);
|
||||
search_size = 2 * entries_count * sizeof(uint);
|
||||
copy_bytes((const char*)search, (address)current, search_size);
|
||||
FREE_C_HEAP_ARRAY(uint, search);
|
||||
FREE_C_HEAP_ARRAY(search);
|
||||
current += search_size;
|
||||
|
||||
// Write entries
|
||||
@ -1012,19 +1033,8 @@ bool AOTCodeCache::store_code_blob(CodeBlob& blob, AOTCodeEntry::Kind entry_kind
|
||||
}
|
||||
uint entry_position = cache->_write_position;
|
||||
|
||||
// Write name
|
||||
uint name_offset = cache->_write_position - entry_position;
|
||||
uint name_size = (uint)strlen(name) + 1; // Includes '/0'
|
||||
uint n = cache->write_bytes(name, name_size);
|
||||
if (n != name_size) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Write CodeBlob
|
||||
if (!cache->align_write()) {
|
||||
return false;
|
||||
}
|
||||
uint blob_offset = cache->_write_position - entry_position;
|
||||
// Code blob's size is aligned to oopSize
|
||||
address archive_buffer = cache->reserve_bytes(blob.size());
|
||||
if (archive_buffer == nullptr) {
|
||||
return false;
|
||||
@ -1056,7 +1066,7 @@ bool AOTCodeCache::store_code_blob(CodeBlob& blob, AOTCodeEntry::Kind entry_kind
|
||||
reloc_count = blob.relocation_size() / sizeof(relocInfo);
|
||||
reloc_data = (address)blob.relocation_begin();
|
||||
}
|
||||
n = cache->write_bytes(&reloc_count, sizeof(int));
|
||||
uint n = cache->write_bytes(&reloc_count, sizeof(int));
|
||||
if (n != sizeof(int)) {
|
||||
return false;
|
||||
}
|
||||
@ -1123,6 +1133,14 @@ bool AOTCodeCache::store_code_blob(CodeBlob& blob, AOTCodeEntry::Kind entry_kind
|
||||
}
|
||||
#endif /* PRODUCT */
|
||||
|
||||
// Write name after code comments
|
||||
uint name_offset = cache->_write_position - entry_position;
|
||||
uint name_size = (uint)strlen(name) + 1; // Includes '/0'
|
||||
n = cache->write_bytes(name, name_size);
|
||||
if (n != name_size) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint entry_size = cache->_write_position - entry_position;
|
||||
|
||||
AOTCodeEntry* entry = new(cache) AOTCodeEntry(entry_kind, encode_id(entry_kind, id),
|
||||
@ -1151,6 +1169,9 @@ bool AOTCodeCache::store_code_blob(CodeBlob& blob, AOTCodeEntry::Kind entry_kind
|
||||
}
|
||||
|
||||
bool AOTCodeCache::write_stub_data(CodeBlob &blob, AOTStubData *stub_data) {
|
||||
if (!align_write_int()) {
|
||||
return false;
|
||||
}
|
||||
BlobId blob_id = stub_data->blob_id();
|
||||
StubId stub_id = StubInfo::stub_base(blob_id);
|
||||
address blob_base = blob.code_begin();
|
||||
@ -1320,7 +1341,8 @@ CodeBlob* AOTCodeReader::compile_code_blob(const char* name, AOTCodeEntry::Kind
|
||||
CodeBlob* archived_blob = (CodeBlob*)addr(offset);
|
||||
offset += archived_blob->size();
|
||||
|
||||
_reloc_count = *(int*)addr(offset); offset += sizeof(int);
|
||||
_reloc_count = *(int*)addr(offset);
|
||||
offset += sizeof(int);
|
||||
if (AOTCodeEntry::is_multi_stub_blob(entry_kind)) {
|
||||
// position of relocs will have been aligned to heap word size so
|
||||
// we can install them into a code buffer
|
||||
@ -1443,7 +1465,7 @@ void AOTCodeReader::read_stub_data(CodeBlob* code_blob, AOTStubData* stub_data)
|
||||
|
||||
address blob_base = code_blob->code_begin();
|
||||
uint blob_size = (uint)(code_blob->code_end() - blob_base);
|
||||
int offset = read_position();
|
||||
uint offset = align_read_int();
|
||||
LogStreamHandle(Trace, aot, codecache, stubs) log;
|
||||
if (log.is_enabled()) {
|
||||
log.print_cr("======== Stub data starts at offset %d", offset);
|
||||
@ -1571,6 +1593,9 @@ void AOTCodeCache::publish_stub_addresses(CodeBlob &code_blob, BlobId blob_id, A
|
||||
#define BAD_ADDRESS_ID -2
|
||||
|
||||
bool AOTCodeCache::write_relocations(CodeBlob& code_blob, RelocIterator& iter) {
|
||||
if (!align_write_int()) {
|
||||
return false;
|
||||
}
|
||||
GrowableArray<uint> reloc_data;
|
||||
LogStreamHandle(Trace, aot, codecache, reloc) log;
|
||||
while (iter.next()) {
|
||||
@ -1653,7 +1678,7 @@ bool AOTCodeCache::write_relocations(CodeBlob& code_blob, RelocIterator& iter) {
|
||||
}
|
||||
|
||||
void AOTCodeReader::fix_relocations(CodeBlob *code_blob, RelocIterator& iter) {
|
||||
uint offset = read_position();
|
||||
uint offset = align_read_int();
|
||||
int reloc_count = *(int*)addr(offset);
|
||||
offset += sizeof(int);
|
||||
uint* reloc_data = (uint*)addr(offset);
|
||||
@ -1726,6 +1751,9 @@ void AOTCodeReader::fix_relocations(CodeBlob *code_blob, RelocIterator& iter) {
|
||||
}
|
||||
|
||||
bool AOTCodeCache::write_oop_map_set(CodeBlob& cb) {
|
||||
if (!align_write_int()) {
|
||||
return false;
|
||||
}
|
||||
ImmutableOopMapSet* oopmaps = cb.oop_maps();
|
||||
int oopmaps_size = oopmaps->nr_of_bytes();
|
||||
if (!write_bytes(&oopmaps_size, sizeof(int))) {
|
||||
@ -1739,7 +1767,7 @@ bool AOTCodeCache::write_oop_map_set(CodeBlob& cb) {
|
||||
}
|
||||
|
||||
ImmutableOopMapSet* AOTCodeReader::read_oop_map_set() {
|
||||
uint offset = read_position();
|
||||
uint offset = align_read_int();
|
||||
int size = *(int *)addr(offset);
|
||||
offset += sizeof(int);
|
||||
ImmutableOopMapSet* oopmaps = (ImmutableOopMapSet *)addr(offset);
|
||||
@ -1750,6 +1778,9 @@ ImmutableOopMapSet* AOTCodeReader::read_oop_map_set() {
|
||||
|
||||
#ifndef PRODUCT
|
||||
bool AOTCodeCache::write_asm_remarks(CodeBlob& cb) {
|
||||
if (!align_write_int()) {
|
||||
return false;
|
||||
}
|
||||
// Write asm remarks
|
||||
uint* count_ptr = (uint *)reserve_bytes(sizeof(uint));
|
||||
if (count_ptr == nullptr) {
|
||||
@ -1778,7 +1809,7 @@ bool AOTCodeCache::write_asm_remarks(CodeBlob& cb) {
|
||||
|
||||
void AOTCodeReader::read_asm_remarks(AsmRemarks& asm_remarks) {
|
||||
// Read asm remarks
|
||||
uint offset = read_position();
|
||||
uint offset = align_read_int();
|
||||
uint count = *(uint *)addr(offset);
|
||||
offset += sizeof(uint);
|
||||
for (uint i = 0; i < count; i++) {
|
||||
@ -1793,6 +1824,9 @@ void AOTCodeReader::read_asm_remarks(AsmRemarks& asm_remarks) {
|
||||
}
|
||||
|
||||
bool AOTCodeCache::write_dbg_strings(CodeBlob& cb) {
|
||||
if (!align_write_int()) {
|
||||
return false;
|
||||
}
|
||||
// Write dbg strings
|
||||
uint* count_ptr = (uint *)reserve_bytes(sizeof(uint));
|
||||
if (count_ptr == nullptr) {
|
||||
@ -1817,7 +1851,7 @@ bool AOTCodeCache::write_dbg_strings(CodeBlob& cb) {
|
||||
|
||||
void AOTCodeReader::read_dbg_strings(DbgStrings& dbg_strings) {
|
||||
// Read dbg strings
|
||||
uint offset = read_position();
|
||||
uint offset = align_read_int();
|
||||
uint count = *(uint *)addr(offset);
|
||||
offset += sizeof(uint);
|
||||
for (uint i = 0; i < count; i++) {
|
||||
|
||||
@ -252,7 +252,7 @@ private:
|
||||
public:
|
||||
AOTStubData(BlobId blob_id) NOT_CDS({});
|
||||
|
||||
~AOTStubData() CDS_ONLY({FREE_C_HEAP_ARRAY(StubAddrRange, _ranges);}) NOT_CDS({})
|
||||
~AOTStubData() CDS_ONLY({FREE_C_HEAP_ARRAY(_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);
|
||||
@ -478,6 +478,8 @@ private:
|
||||
|
||||
bool set_write_position(uint pos);
|
||||
bool align_write();
|
||||
bool align_write_int();
|
||||
bool align_write_bytes(uint alignment);
|
||||
address reserve_bytes(uint nbytes);
|
||||
uint write_bytes(const void* buffer, uint nbytes);
|
||||
const char* addr(uint offset) const { return _load_buffer + offset; }
|
||||
@ -643,6 +645,7 @@ private:
|
||||
uint _read_position; // Position in _load_buffer
|
||||
uint read_position() const { return _read_position; }
|
||||
void set_read_position(uint pos);
|
||||
uint align_read_int();
|
||||
const char* addr(uint offset) const { return _load_buffer + offset; }
|
||||
|
||||
bool _lookup_failed; // Failed to lookup for info (skip only this code load)
|
||||
|
||||
@ -357,9 +357,12 @@ void RuntimeBlob::trace_new_stub(RuntimeBlob* stub, const char* name1, const cha
|
||||
if (stub != nullptr && (PrintStubCode ||
|
||||
Forte::is_enabled() ||
|
||||
JvmtiExport::should_post_dynamic_code_generated())) {
|
||||
char stub_id[256];
|
||||
assert(strlen(name1) + strlen(name2) < sizeof(stub_id), "");
|
||||
jio_snprintf(stub_id, sizeof(stub_id), "%s%s", name1, name2);
|
||||
ResourceMark rm;
|
||||
const size_t name1_len = strlen(name1);
|
||||
const size_t name2_len = strlen(name2);
|
||||
const size_t stub_id_size = name1_len + name2_len + 1;
|
||||
char* stub_id = NEW_RESOURCE_ARRAY(char, stub_id_size);
|
||||
jio_snprintf(stub_id, stub_id_size, "%s%s", name1, name2);
|
||||
if (PrintStubCode) {
|
||||
ttyLocker ttyl;
|
||||
tty->print_cr("- - - [BEGIN] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
|
||||
|
||||
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