Merge branch 'openjdk:master' into JDK-8373118

This commit is contained in:
Doug Lea 2026-04-27 08:08:31 -04:00 committed by GitHub
commit 7c7c3d60a6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
597 changed files with 8884 additions and 4155 deletions

2
.gitignore vendored
View File

@ -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

View File

@ -108,3 +108,4 @@ override EXTRA_LDFLAGS :=
# hsdis is not needed
HSDIS_BACKEND := none
ENABLE_HSDIS_BUNDLING := false
DEFAULT_PRINT_ASSEMBLY_OPTIONS :=

View File

@ -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)
])

View File

@ -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.

View File

@ -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 \

View File

@ -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, \

View File

@ -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

View File

@ -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;
}

View File

@ -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 &#92;uxxxx
* and writes out any of the characters in specialSaveChars
* with a preceding slash
* Escapes control codes to ASCII escapes or encoded &#92;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);
}
}

View File

@ -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}");
}
}

View File

@ -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)

View File

@ -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), \

View File

@ -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)

View File

@ -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);

View File

@ -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 {

View File

@ -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"); \

View File

@ -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();

View File

@ -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;

View File

@ -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);
}

View File

@ -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 __

View File

@ -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; }

View File

@ -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);

View File

@ -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;

View File

@ -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)

View File

@ -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

View File

@ -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
%}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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);

View File

@ -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");
}

View File

@ -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.") \

View File

@ -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();
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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 %{

View File

@ -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;
}

View File

@ -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;

View File

@ -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();
}

View File

@ -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);
}
}

View File

@ -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

View File

@ -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

View File

@ -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 {

View File

@ -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;

View File

@ -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) {

View File

@ -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,

View File

@ -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()));

View File

@ -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;

View File

@ -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);
//--------------------------

View File

@ -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.

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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;

View File

@ -1432,4 +1432,5 @@ void LIRGenerator::volatile_field_load(LIR_Address* address, LIR_Opr result,
} else {
__ load(address, result, info);
}
__ membar_acquire();
}

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -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, &copy, 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);
}

View File

@ -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

View File

@ -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);
%}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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) {

View File

@ -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;

View File

@ -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() {

View File

@ -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");

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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) {

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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));

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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) {

View File

@ -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() {

View File

@ -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 " \

View File

@ -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);
}
}

View File

@ -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();
}

View File

@ -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') {

View File

@ -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,

View File

@ -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;

View File

@ -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

View File

@ -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());
}
}

View File

@ -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");
}
});

View File

@ -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);

View File

@ -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++) {

View File

@ -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)

View File

@ -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