Merge branch 'master' into opt-simploop-8346177

This commit is contained in:
katkerem 2026-04-10 12:06:34 +01:00
commit 22a3526dad
416 changed files with 3520 additions and 1252 deletions

5
.github/pull_request_template.md vendored Normal file
View File

@ -0,0 +1,5 @@
---------
- [ ] I confirm that I make this contribution in accordance with the [OpenJDK Interim AI Policy](https://openjdk.org/legal/ai).

View File

@ -44,6 +44,9 @@ ifeq ($(HSDIS_BACKEND), capstone)
else ifeq ($(call isTargetCpuArch, aarch64), true)
CAPSTONE_ARCH := CS_ARCH_$(CAPSTONE_ARCH_AARCH64_NAME)
CAPSTONE_MODE := CS_MODE_ARM
else ifeq ($(call isTargetCpuArch, arm), true)
CAPSTONE_ARCH := CS_ARCH_ARM
CAPSTONE_MODE := CS_MODE_ARM
else
$(error No support for Capstone on this platform)
endif

View File

@ -87,6 +87,7 @@ public class CLDRConverter {
static final String EXEMPLAR_CITY_PREFIX = "timezone.excity.";
static final String ZONE_NAME_PREFIX = "timezone.displayname.";
static final String METAZONE_ID_PREFIX = "metazone.id.";
static final String METAZONE_DSTOFFSET_PREFIX = "metazone.dstoffset.";
static final String PARENT_LOCALE_PREFIX = "parentLocale.";
static final String LIKELY_SCRIPT_PREFIX = "likelyScript.";
static final String META_EMPTY_ZONE_NAME = "EMPTY_ZONE";
@ -139,6 +140,11 @@ public class CLDRConverter {
private static final Map<String, String> tzdbSubstLetters = HashMap.newHashMap(512);
private static final Map<String, String> tzdbLinks = HashMap.newHashMap(512);
// Map of explicit dst offsets for metazones
// key: time zone ID
// value: explicit dstOffset for the corresponding metazone name
static final Map<String, String> explicitDstOffsets = HashMap.newHashMap(32);
static enum DraftType {
UNCONFIRMED,
PROVISIONAL,
@ -867,6 +873,12 @@ public class CLDRConverter {
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
names.putAll(exCities);
// Explicit metazone offsets
if (id.equals("root")) {
explicitDstOffsets.forEach((k, v) ->
names.put(METAZONE_DSTOFFSET_PREFIX + k, v));
}
// If there's no UTC entry at this point, add an empty one
if (!names.isEmpty() && !names.containsKey("UTC")) {
names.putIfAbsent(METAZONE_ID_PREFIX + META_EMPTY_ZONE_NAME, EMPTY_ZONE);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2020, 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
@ -84,7 +84,15 @@ class MetaZonesParseHandler extends AbstractLDMLHandler<String> {
if (fromLDT.isBefore(now) && toLDT.isAfter(now)) {
metazone = attributes.getValue("mzone");
// Explicit metazone DST offsets. Only the "dst" offset is needed,
// as "std" is used by default when it doesn't match.
String dstOffset = attributes.getValue("dstOffset");
if (dstOffset != null) {
CLDRConverter.explicitDstOffsets.put(tzid, dstOffset);
}
}
pushIgnoredContainer(qName);
break;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2024, 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
@ -198,7 +198,8 @@ class ResourceBundleGenerator implements BundleGenerator {
} else if (value instanceof String) {
String valStr = (String)value;
if (type == BundleType.TIMEZONE &&
!key.startsWith(CLDRConverter.EXEMPLAR_CITY_PREFIX) ||
!(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 {

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@ -55,6 +55,12 @@ else
LIBSAPROC_LINK_TYPE := C
endif
# DWARF related sources would be included on supported platforms only.
LIBSAPROC_EXCLUDE_FILES :=
ifneq ($(call And, $(call isTargetOs, linux) $(call isTargetCpu, x86_64 aarch64)), true)
LIBSAPROC_EXCLUDE_FILES := DwarfParser.cpp dwarf.cpp
endif
$(eval $(call SetupJdkLibrary, BUILD_LIBSAPROC, \
NAME := saproc, \
LINK_TYPE := $(LIBSAPROC_LINK_TYPE), \
@ -70,6 +76,7 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBSAPROC, \
CFLAGS := $(LIBSAPROC_CFLAGS), \
CXXFLAGS := $(LIBSAPROC_CFLAGS) $(LIBSAPROC_CXXFLAGS), \
EXTRA_SRC := $(LIBSAPROC_EXTRA_SRC), \
EXCLUDE_FILES := $(LIBSAPROC_EXCLUDE_FILES), \
JDK_LIBS := java.base:libjava, \
LIBS_linux := $(LIBDL), \
LIBS_macosx := \

View File

@ -1098,6 +1098,7 @@ void VM_Version::get_processor_features() {
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);
} else if (!UseAPX) {
_features.clear_feature(CPU_APX_F);
}
@ -1206,16 +1207,7 @@ void VM_Version::get_processor_features() {
}
}
} else {
if (!UseAES) {
if (UseAESIntrinsics && !FLAG_IS_DEFAULT(UseAESIntrinsics)) {
warning("AES intrinsics require UseAES flag to be enabled. Intrinsics will be disabled.");
}
FLAG_SET_DEFAULT(UseAESIntrinsics, false);
if (UseAESCTRIntrinsics && !FLAG_IS_DEFAULT(UseAESCTRIntrinsics)) {
warning("AES_CTR intrinsics require UseAES flag to be enabled. AES_CTR intrinsics will be disabled.");
}
FLAG_SET_DEFAULT(UseAESCTRIntrinsics, false);
} else if (!cpu_supports_aes()) {
if (!cpu_supports_aes()) {
if (UseAESIntrinsics && !FLAG_IS_DEFAULT(UseAESIntrinsics)) {
warning("AES intrinsics are not available on this CPU");
}
@ -1224,6 +1216,15 @@ void VM_Version::get_processor_features() {
warning("AES-CTR intrinsics are not available on this CPU");
}
FLAG_SET_DEFAULT(UseAESCTRIntrinsics, false);
} else if (!UseAES) {
if (UseAESIntrinsics && !FLAG_IS_DEFAULT(UseAESIntrinsics)) {
warning("AES intrinsics require UseAES flag to be enabled. Intrinsics will be disabled.");
}
FLAG_SET_DEFAULT(UseAESIntrinsics, false);
if (UseAESCTRIntrinsics && !FLAG_IS_DEFAULT(UseAESCTRIntrinsics)) {
warning("AES_CTR intrinsics require UseAES flag to be enabled. AES_CTR intrinsics will be disabled.");
}
FLAG_SET_DEFAULT(UseAESCTRIntrinsics, false);
}
}

View File

@ -2163,8 +2163,6 @@ void os::print_os_info(outputStream* st) {
os::Posix::print_rlimit_info(st);
os::print_open_file_descriptors(st);
os::Posix::print_load_average(st);
st->cr();

View File

@ -1905,9 +1905,6 @@ void AOTCodeAddressTable::init_extrs() {
ADD_EXTERNAL_ADDRESS(SharedRuntime::handle_wrong_method_ic_miss);
#if defined(AARCH64) && !defined(ZERO)
ADD_EXTERNAL_ADDRESS(JavaThread::aarch64_get_thread_helper);
#endif
#if defined(AARCH64)
ADD_EXTERNAL_ADDRESS(BarrierSetAssembler::patching_epoch_addr());
#endif

View File

@ -45,9 +45,10 @@ class OopMapSet;
enum class CodeBlobType {
MethodNonProfiled = 0, // Execution level 1 and 4 (non-profiled) nmethods (including native nmethods)
MethodProfiled = 1, // Execution level 2 and 3 (profiled) nmethods
NonNMethod = 2, // Non-nmethods like Buffers, Adapters and Runtime Stubs
All = 3, // All types (No code cache segmentation)
NumTypes = 4 // Number of CodeBlobTypes
MethodHot = 2, // Nmethods predicted to be always hot
NonNMethod = 3, // Non-nmethods like Buffers, Adapters and Runtime Stubs
All = 4, // All types (No code cache segmentation)
NumTypes = 5 // Number of CodeBlobTypes
};
// CodeBlob - superclass for all entries in the CodeCache.

View File

@ -201,6 +201,7 @@ void CodeCache::initialize_heaps() {
CodeHeapInfo non_nmethod = {NonNMethodCodeHeapSize, FLAG_IS_CMDLINE(NonNMethodCodeHeapSize), true};
CodeHeapInfo profiled = {ProfiledCodeHeapSize, FLAG_IS_CMDLINE(ProfiledCodeHeapSize), true};
CodeHeapInfo non_profiled = {NonProfiledCodeHeapSize, FLAG_IS_CMDLINE(NonProfiledCodeHeapSize), true};
CodeHeapInfo hot = {HotCodeHeapSize, FLAG_IS_CMDLINE(HotCodeHeapSize), true};
const bool cache_size_set = FLAG_IS_CMDLINE(ReservedCodeCacheSize);
const size_t ps = page_size(false, 8);
@ -219,6 +220,12 @@ void CodeCache::initialize_heaps() {
profiled.enabled = false;
}
if (!heap_available(CodeBlobType::MethodHot)) {
hot.size = 0;
hot.set = true;
hot.enabled = false;
}
assert(heap_available(CodeBlobType::MethodNonProfiled), "MethodNonProfiled heap is always available for segmented code heap");
size_t compiler_buffer_size = 0;
@ -238,14 +245,36 @@ void CodeCache::initialize_heaps() {
set_size_of_unset_code_heap(&non_profiled, cache_size, non_nmethod.size + profiled.size, min_size);
}
if (!profiled.set && non_profiled.set) {
set_size_of_unset_code_heap(&profiled, cache_size, non_nmethod.size + non_profiled.size, min_size);
if (!profiled.set && non_profiled.set && hot.set) {
set_size_of_unset_code_heap(&profiled, cache_size, non_nmethod.size + non_profiled.size + hot.size, min_size);
}
if (hot.enabled) {
if (!hot.set) {
assert(hot.size == 0, "must be calculated during heaps initialization");
// An application usually has ~20% hot code which is mostly non-profiled code.
// We set the hot code heap size to 20% of the non-profiled code heap.
hot.size = MAX2(non_profiled.size / 5, min_size);
if (non_profiled.set) {
err_msg msg("Must manually set HotCodeHeapSize when NonProfiledCodeHeapSize is set");
vm_exit_during_initialization("Invalid code heap sizes", msg);
}
non_profiled.size -= hot.size;
}
if (hot.size > non_profiled.size) {
err_msg msg("Hot (%zuK) exceeds NonProfiled (%zuK).",
hot.size / K, non_profiled.size / K);
vm_exit_during_initialization("Invalid code heap sizes", msg);
}
}
// Compatibility.
size_t non_nmethod_min_size = min_cache_size + compiler_buffer_size;
if (!non_nmethod.set && profiled.set && non_profiled.set) {
set_size_of_unset_code_heap(&non_nmethod, cache_size, profiled.size + non_profiled.size, non_nmethod_min_size);
if (!non_nmethod.set && profiled.set && non_profiled.set && hot.set) {
set_size_of_unset_code_heap(&non_nmethod, cache_size, profiled.size + non_profiled.size + hot.size, non_nmethod_min_size);
}
// Note: if large page support is enabled, min_size is at least the large
@ -253,8 +282,9 @@ void CodeCache::initialize_heaps() {
non_nmethod.size = align_up(non_nmethod.size, min_size);
profiled.size = align_up(profiled.size, min_size);
non_profiled.size = align_up(non_profiled.size, min_size);
hot.size = align_up(hot.size, min_size);
size_t aligned_total = non_nmethod.size + profiled.size + non_profiled.size;
size_t aligned_total = non_nmethod.size + profiled.size + non_profiled.size + hot.size;
if (!cache_size_set) {
// If ReservedCodeCacheSize is explicitly set and exceeds CODE_CACHE_SIZE_LIMIT,
// it is rejected by flag validation elsewhere. Here we only handle the case
@ -262,15 +292,15 @@ void CodeCache::initialize_heaps() {
// sizes (after alignment) exceed the platform limit.
if (aligned_total > CODE_CACHE_SIZE_LIMIT) {
err_msg message("ReservedCodeCacheSize (%zuK), Max (%zuK)."
"Segments: NonNMethod (%zuK), NonProfiled (%zuK), Profiled (%zuK).",
"Segments: NonNMethod (%zuK), NonProfiled (%zuK), Profiled (%zuK), Hot (%zuK).",
aligned_total/K, CODE_CACHE_SIZE_LIMIT/K,
non_nmethod.size/K, non_profiled.size/K, profiled.size/K);
non_nmethod.size/K, non_profiled.size/K, profiled.size/K, hot.size/K);
vm_exit_during_initialization("Code cache size exceeds platform limit", message);
}
if (aligned_total != cache_size) {
log_info(codecache)("ReservedCodeCache size %zuK changed to total segments size NonNMethod "
"%zuK NonProfiled %zuK Profiled %zuK = %zuK",
cache_size/K, non_nmethod.size/K, non_profiled.size/K, profiled.size/K, aligned_total/K);
"%zuK NonProfiled %zuK Profiled %zuK Hot %zuK = %zuK",
cache_size/K, non_nmethod.size/K, non_profiled.size/K, profiled.size/K, hot.size/K, aligned_total/K);
// Adjust ReservedCodeCacheSize as necessary because it was not set explicitly
cache_size = aligned_total;
}
@ -295,19 +325,23 @@ void CodeCache::initialize_heaps() {
}
if (profiled.enabled && !profiled.set && profiled.size > min_size) {
profiled.size -= min_size;
if (--delta == 0) break;
}
if (hot.enabled && !hot.set && hot.size > min_size) {
hot.size -= min_size;
delta--;
}
if (delta == start_delta) {
break;
}
}
aligned_total = non_nmethod.size + profiled.size + non_profiled.size;
aligned_total = non_nmethod.size + profiled.size + non_profiled.size + hot.size;
}
}
log_debug(codecache)("Initializing code heaps ReservedCodeCache %zuK NonNMethod %zuK"
" NonProfiled %zuK Profiled %zuK",
cache_size/K, non_nmethod.size/K, non_profiled.size/K, profiled.size/K);
" NonProfiled %zuK Profiled %zuK Hot %zuK",
cache_size/K, non_nmethod.size/K, non_profiled.size/K, profiled.size/K, hot.size/K);
// Validation
// Check minimal required sizes
@ -318,6 +352,9 @@ void CodeCache::initialize_heaps() {
if (non_profiled.enabled) { // non_profiled.enabled is always ON for segmented code heap, leave it checked for clarity
check_min_size("non-profiled code heap", non_profiled.size, min_size);
}
if (hot.enabled) {
check_min_size("hot code heap", hot.size, min_size);
}
// ReservedCodeCacheSize was set explicitly, so report an error and abort if it doesn't match the segment sizes
if (aligned_total != cache_size && cache_size_set) {
@ -328,6 +365,9 @@ void CodeCache::initialize_heaps() {
if (non_profiled.enabled) {
message.append(" + NonProfiledCodeHeapSize (%zuK)", non_profiled.size/K);
}
if (hot.enabled) {
message.append(" + HotCodeHeapSize (%zuK)", hot.size/K);
}
message.append(" = %zuK", aligned_total/K);
message.append((aligned_total > cache_size) ? " is greater than " : " is less than ");
message.append("ReservedCodeCacheSize (%zuK).", cache_size/K);
@ -348,6 +388,7 @@ void CodeCache::initialize_heaps() {
FLAG_SET_ERGO(NonNMethodCodeHeapSize, non_nmethod.size);
FLAG_SET_ERGO(ProfiledCodeHeapSize, profiled.size);
FLAG_SET_ERGO(NonProfiledCodeHeapSize, non_profiled.size);
FLAG_SET_ERGO(HotCodeHeapSize, hot.size);
FLAG_SET_ERGO(ReservedCodeCacheSize, cache_size);
ReservedSpace rs = reserve_heap_memory(cache_size, ps);
@ -368,6 +409,13 @@ void CodeCache::initialize_heaps() {
// Non-nmethods (stubs, adapters, ...)
add_heap(non_method_space, "CodeHeap 'non-nmethods'", CodeBlobType::NonNMethod);
if (hot.enabled) {
ReservedSpace hot_space = rs.partition(offset, hot.size);
offset += hot.size;
// Nmethods known to be always hot.
add_heap(hot_space, "CodeHeap 'hot nmethods'", CodeBlobType::MethodHot);
}
if (non_profiled.enabled) {
ReservedSpace non_profiled_space = rs.partition(offset, non_profiled.size);
// Tier 1 and tier 4 (non-profiled) methods and native methods
@ -406,16 +454,25 @@ bool CodeCache::heap_available(CodeBlobType code_blob_type) {
// Interpreter only: we don't need any method code heaps
return (code_blob_type == CodeBlobType::NonNMethod);
} else if (CompilerConfig::is_c1_profiling()) {
// Tiered compilation: use all code heaps
// Tiered compilation: use all code heaps including
// the hot code heap when it is present.
if (COMPILER2_PRESENT(!HotCodeHeap &&) (code_blob_type == CodeBlobType::MethodHot)) {
return false;
}
return (code_blob_type < CodeBlobType::All);
} else {
// No TieredCompilation: we only need the non-nmethod and non-profiled code heap
// and the hot code heap if it is requested.
return (code_blob_type == CodeBlobType::NonNMethod) ||
(code_blob_type == CodeBlobType::MethodNonProfiled);
(code_blob_type == CodeBlobType::MethodNonProfiled)
COMPILER2_PRESENT(|| ((code_blob_type == CodeBlobType::MethodHot) && HotCodeHeap));
}
}
const char* CodeCache::get_code_heap_flag_name(CodeBlobType code_blob_type) {
// Returns the name of the VM option to set the size of the corresponding CodeHeap
static const char* get_code_heap_flag_name(CodeBlobType code_blob_type) {
switch(code_blob_type) {
case CodeBlobType::NonNMethod:
return "NonNMethodCodeHeapSize";
@ -426,6 +483,9 @@ const char* CodeCache::get_code_heap_flag_name(CodeBlobType code_blob_type) {
case CodeBlobType::MethodProfiled:
return "ProfiledCodeHeapSize";
break;
case CodeBlobType::MethodHot:
return "HotCodeHeapSize";
break;
default:
ShouldNotReachHere();
return nullptr;
@ -542,7 +602,7 @@ CodeBlob* CodeCache::allocate(uint size, CodeBlobType code_blob_type, bool handl
// Get CodeHeap for the given CodeBlobType
CodeHeap* heap = get_code_heap(code_blob_type);
assert(heap != nullptr, "heap is null");
assert(heap != nullptr, "No heap for given code_blob_type (%d), heap is null", (int)code_blob_type);
while (true) {
cb = (CodeBlob*)heap->allocate(size);
@ -570,6 +630,9 @@ CodeBlob* CodeCache::allocate(uint size, CodeBlobType code_blob_type, bool handl
type = CodeBlobType::MethodNonProfiled;
}
break;
case CodeBlobType::MethodHot:
type = CodeBlobType::MethodNonProfiled;
break;
default:
break;
}

View File

@ -118,10 +118,6 @@ class CodeCache : AllStatic {
// Creates a new heap with the given name and size, containing CodeBlobs of the given type
static void add_heap(ReservedSpace rs, const char* name, CodeBlobType code_blob_type);
static CodeHeap* get_code_heap_containing(void* p); // Returns the CodeHeap containing the given pointer, or nullptr
static CodeHeap* get_code_heap(const void* cb); // Returns the CodeHeap for the given CodeBlob
static CodeHeap* get_code_heap(CodeBlobType code_blob_type); // Returns the CodeHeap for the given CodeBlobType
// Returns the name of the VM option to set the size of the corresponding CodeHeap
static const char* get_code_heap_flag_name(CodeBlobType code_blob_type);
static ReservedSpace reserve_heap_memory(size_t size, size_t rs_ps); // Reserves one continuous chunk of memory for the CodeHeaps
// Iteration
@ -145,6 +141,8 @@ class CodeCache : AllStatic {
static int code_heap_compare(CodeHeap* const &lhs, CodeHeap* const &rhs);
static void add_heap(CodeHeap* heap);
static CodeHeap* get_code_heap(const void* cb); // Returns the CodeHeap for the given CodeBlob
static CodeHeap* get_code_heap(CodeBlobType code_blob_type); // Returns the CodeHeap for the given CodeBlobType
static const GrowableArray<CodeHeap*>* heaps() { return _heaps; }
static const GrowableArray<CodeHeap*>* nmethod_heaps() { return _nmethod_heaps; }
@ -264,7 +262,7 @@ class CodeCache : AllStatic {
}
static bool code_blob_type_accepts_nmethod(CodeBlobType type) {
return type == CodeBlobType::All || type <= CodeBlobType::MethodProfiled;
return type == CodeBlobType::All || type <= CodeBlobType::MethodHot;
}
static bool code_blob_type_accepts_allocable(CodeBlobType type) {

View File

@ -66,6 +66,9 @@
#include "runtime/flags/flagSetting.hpp"
#include "runtime/frame.inline.hpp"
#include "runtime/handles.inline.hpp"
#ifdef COMPILER2
#include "runtime/hotCodeCollector.hpp"
#endif // COMPILER2
#include "runtime/icache.hpp"
#include "runtime/jniHandles.inline.hpp"
#include "runtime/orderAccess.hpp"
@ -1258,6 +1261,11 @@ void nmethod::post_init() {
ICache::invalidate_range(code_begin(), code_size());
Universe::heap()->register_nmethod(this);
#ifdef COMPILER2
HotCodeCollector::register_nmethod(this);
#endif // COMPILER2
DEBUG_ONLY(Universe::heap()->verify_nmethod(this));
CodeCache::commit(this);
@ -2476,6 +2484,11 @@ void nmethod::purge(bool unregister_nmethod) {
if (unregister_nmethod) {
Universe::heap()->unregister_nmethod(this);
}
#ifdef COMPILER2
HotCodeCollector::unregister_nmethod(this);
#endif // COMPILER2
CodeCache::unregister_old_nmethod(this);
JVMCI_ONLY( _metadata_size = 0; )

View File

@ -286,8 +286,38 @@ void CompilerConfig::set_compilation_policy_flags() {
}
}
#ifdef COMPILER2
if (HotCodeHeap) {
if (FLAG_IS_DEFAULT(SegmentedCodeCache)) {
FLAG_SET_ERGO(SegmentedCodeCache, true);
} else if (!SegmentedCodeCache) {
vm_exit_during_initialization("HotCodeHeap requires SegmentedCodeCache enabled");
}
if (FLAG_IS_DEFAULT(NMethodRelocation)) {
FLAG_SET_ERGO(NMethodRelocation, true);
} else if (!NMethodRelocation) {
vm_exit_during_initialization("HotCodeHeap requires NMethodRelocation enabled");
}
if (!is_c2_enabled()) {
vm_exit_during_initialization("HotCodeHeap requires C2 enabled");
}
if (HotCodeMinSamplingMs > HotCodeMaxSamplingMs) {
vm_exit_during_initialization("HotCodeMinSamplingMs cannot be larger than HotCodeMaxSamplingMs");
}
} else if (HotCodeHeapSize > 0) {
vm_exit_during_initialization("HotCodeHeapSize requires HotCodeHeap enabled");
}
#else
if (HotCodeHeapSize > 0) {
vm_exit_during_initialization("HotCodeHeapSize requires C2 present");
}
#endif // COMPILER2
if (CompileThresholdScaling < 0) {
vm_exit_during_initialization("Negative value specified for CompileThresholdScaling", nullptr);
vm_exit_during_initialization("Negative value specified for CompileThresholdScaling");
}
if (CompilationModeFlag::disable_intermediate()) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 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
@ -326,11 +326,14 @@ bool G1ConcurrentRefineSweepState::complete_work(bool concurrent, bool print_log
if (print_log) {
G1ConcurrentRefineStats* s = &_stats;
log_debug(gc, refine)("Refinement took %.2fms (pre-sweep %.2fms card refine %.2f) "
State state_bounded_by_sweeprt = (_state == State::SweepRT || _state == State::CompleteRefineWork)
? State::SweepRT : _state;
log_debug(gc, refine)("Refinement took %.2fms (pre-sweep %.2fms card refine %.2fms) "
"(scanned %zu clean %zu (%.2f%%) not_clean %zu (%.2f%%) not_parsable %zu "
"refers_to_cset %zu (%.2f%%) still_refers_to_cset %zu (%.2f%%) no_cross_region %zu pending %zu)",
get_duration(State::Idle, _state).seconds() * 1000.0,
get_duration(State::Idle, State::SweepRT).seconds() * 1000.0,
get_duration(State::Idle, state_bounded_by_sweeprt).seconds() * 1000.0,
TimeHelper::counter_to_millis(s->refine_duration()),
s->cards_scanned(),
s->cards_clean(),

View File

@ -962,12 +962,12 @@ void G1Policy::record_young_collection_end(bool concurrent_operation_is_full_mar
_free_regions_at_end_of_collection = _g1h->num_free_regions();
_old_gen_alloc_tracker.reset_after_gc(_g1h->humongous_regions_count() * G1HeapRegion::GrainBytes);
// Do not update dynamic IHOP due to G1 periodic collection as it is highly likely
// that in this case we are not running in a "normal" operating mode.
if (_g1h->gc_cause() != GCCause::_g1_periodic_collection) {
update_young_length_bounds();
_old_gen_alloc_tracker.reset_after_gc(_g1h->humongous_regions_count() * G1HeapRegion::GrainBytes);
if (update_ihop_prediction(app_time_ms / 1000.0, is_young_only_pause)) {
_ihop_control->report_statistics(_g1h->gc_tracer_stw(), _g1h->non_young_occupancy_after_allocation(allocation_word_size));
}

View File

@ -96,6 +96,7 @@ class outputStream;
LOG_TAG(heap) \
LOG_TAG(heapdump) \
NOT_PRODUCT(LOG_TAG(heapsampling)) \
COMPILER2_PRESENT(LOG_TAG(hotcode)) \
LOG_TAG(humongous) \
LOG_TAG(ihop) \
LOG_TAG(iklass) \

View File

@ -258,6 +258,19 @@ Node* ArrayCopyNode::try_clone_instance(PhaseGVN *phase, bool can_reshape, int c
return mem;
}
// We may have narrowed the type of base because this runs with PhaseIterGVN::_delay_transform true, explicitly
// update the type of the AddP so it's consistent with its base and load() picks the right memory slice.
Node* ArrayCopyNode::make_and_transform_addp(PhaseGVN* phase, Node* base, Node* offset) {
return make_and_transform_addp(phase, base, base, offset);
}
Node* ArrayCopyNode::make_and_transform_addp(PhaseGVN* phase, Node* base, Node* ptr, Node* offset) {
assert(phase->is_IterGVN() == nullptr || phase->is_IterGVN()->delay_transform(), "helper method when delay transform is set");
Node* addp = phase->transform(AddPNode::make_with_base(base, ptr, offset));
phase->set_type(addp, addp->Value(phase));
return addp;
}
bool ArrayCopyNode::prepare_array_copy(PhaseGVN *phase, bool can_reshape,
Node*& adr_src,
Node*& base_src,
@ -332,12 +345,11 @@ bool ArrayCopyNode::prepare_array_copy(PhaseGVN *phase, bool can_reshape,
Node* dest_scale = phase->transform(new LShiftXNode(dest_offset, phase->intcon(shift)));
adr_src = phase->transform(AddPNode::make_with_base(base_src, src_scale));
adr_dest = phase->transform(AddPNode::make_with_base(base_dest, dest_scale));
adr_src = phase->transform(AddPNode::make_with_base(base_src, adr_src, phase->MakeConX(header)));
adr_dest = phase->transform(AddPNode::make_with_base(base_dest, adr_dest, phase->MakeConX(header)));
adr_src = make_and_transform_addp(phase, base_src, src_scale);
adr_dest = make_and_transform_addp(phase, base_dest, dest_scale);
adr_src = make_and_transform_addp(phase, base_src, adr_src, phase->MakeConX(header));
adr_dest = make_and_transform_addp(phase, base_dest, adr_dest, phase->MakeConX(header));
copy_type = dest_elem;
} else {
assert(ary_src != nullptr, "should be a clone");
@ -355,8 +367,8 @@ bool ArrayCopyNode::prepare_array_copy(PhaseGVN *phase, bool can_reshape,
return false;
}
adr_src = phase->transform(AddPNode::make_with_base(base_src, src_offset));
adr_dest = phase->transform(AddPNode::make_with_base(base_dest, dest_offset));
adr_src = make_and_transform_addp(phase, base_src, src_offset);
adr_dest = make_and_transform_addp(phase, base_dest, dest_offset);
// The address is offsetted to an aligned address where a raw copy would start.
// If the clone copy is decomposed into load-stores - the address is adjusted to
@ -366,8 +378,8 @@ bool ArrayCopyNode::prepare_array_copy(PhaseGVN *phase, bool can_reshape,
int diff = arrayOopDesc::base_offset_in_bytes(elem) - offset;
assert(diff >= 0, "clone should not start after 1st array element");
if (diff > 0) {
adr_src = phase->transform(AddPNode::make_with_base(base_src, adr_src, phase->MakeConX(diff)));
adr_dest = phase->transform(AddPNode::make_with_base(base_dest, adr_dest, phase->MakeConX(diff)));
adr_src = make_and_transform_addp(phase, base_src, adr_src, phase->MakeConX(diff));
adr_dest = make_and_transform_addp(phase, base_dest, adr_dest, phase->MakeConX(diff));
}
copy_type = elem;
value_type = ary_src->elem();
@ -429,12 +441,8 @@ Node* ArrayCopyNode::array_copy_forward(PhaseGVN *phase,
store(bs, phase, forward_ctl, mm, adr_dest, atp_dest, v, value_type, copy_type);
for (int i = 1; i < count; i++) {
Node* off = phase->MakeConX(type2aelembytes(copy_type) * i);
Node* next_src = phase->transform(AddPNode::make_with_base(base_src,adr_src,off));
// We may have narrowed the type of next_src right before calling this method but because this runs with
// PhaseIterGVN::_delay_transform true, explicitly update the type of the AddP so it's consistent with its
// base and load() picks the right memory slice.
phase->set_type(next_src, next_src->Value(phase));
Node* next_dest = phase->transform(AddPNode::make_with_base(base_dest,adr_dest,off));
Node* next_src = make_and_transform_addp(phase, base_src,adr_src,off);
Node* next_dest = make_and_transform_addp(phase, base_dest,adr_dest,off);
// Same as above
phase->set_type(next_dest, next_dest->Value(phase));
v = load(bs, phase, forward_ctl, mm, next_src, atp_src, value_type, copy_type);
@ -473,13 +481,8 @@ Node* ArrayCopyNode::array_copy_backward(PhaseGVN *phase,
if (count > 0) {
for (int i = count-1; i >= 1; i--) {
Node* off = phase->MakeConX(type2aelembytes(copy_type) * i);
Node* next_src = phase->transform(AddPNode::make_with_base(base_src,adr_src,off));
// We may have narrowed the type of next_src right before calling this method but because this runs with
// PhaseIterGVN::_delay_transform true, explicitly update the type of the AddP so it's consistent with its
// base and store() picks the right memory slice.
phase->set_type(next_src, next_src->Value(phase));
Node* next_dest = phase->transform(AddPNode::make_with_base(base_dest,adr_dest,off));
phase->set_type(next_dest, next_dest->Value(phase));
Node* next_src = make_and_transform_addp(phase, base_src,adr_src,off);
Node* next_dest = make_and_transform_addp(phase, base_dest,adr_dest,off);
Node* v = load(bs, phase, backward_ctl, mm, next_src, atp_src, value_type, copy_type);
store(bs, phase, backward_ctl, mm, next_dest, atp_dest, v, value_type, copy_type);
}
@ -618,21 +621,31 @@ Node *ArrayCopyNode::Ideal(PhaseGVN *phase, bool can_reshape) {
phase->set_type(src, phase->type(src)->join_speculative(atp_src));
phase->set_type(dest, phase->type(dest)->join_speculative(atp_dest));
// Control flow is going to be created, it's easier to do with _delay_transform set to true.
// prepare_array_copy() doesn't build control flow, but it creates AddP nodes. The src/dest type possibly gets
// narrowed above. If a newly created AddP node is commoned with a pre-existing one, then the type narrowing is lost.
// Setting _delay_transform before prepare_array_copy() guarantees this doesn't happen.
if (can_reshape) {
assert(!phase->is_IterGVN()->delay_transform(), "cannot delay transforms");
phase->is_IterGVN()->set_delay_transform(true);
}
if (!prepare_array_copy(phase, can_reshape,
adr_src, base_src, adr_dest, base_dest,
copy_type, value_type, disjoint_bases)) {
assert(adr_src == nullptr, "no node can be left behind");
assert(adr_dest == nullptr, "no node can be left behind");
if (can_reshape) {
assert(phase->is_IterGVN()->delay_transform(), "cannot delay transforms");
phase->is_IterGVN()->set_delay_transform(false);
}
return nullptr;
}
Node* in_mem = in(TypeFunc::Memory);
if (can_reshape) {
assert(!phase->is_IterGVN()->delay_transform(), "cannot delay transforms");
phase->is_IterGVN()->set_delay_transform(true);
}
Node* backward_ctl = phase->C->top();
Node* forward_ctl = phase->C->top();
array_copy_test_overlap(phase, can_reshape, disjoint_bases, count, forward_ctl, backward_ctl);

View File

@ -104,6 +104,10 @@ private:
static const TypePtr* get_address_type(PhaseGVN* phase, const TypePtr* atp, Node* n);
Node* try_clone_instance(PhaseGVN *phase, bool can_reshape, int count);
Node* make_and_transform_addp(PhaseGVN* phase, Node* base, Node* offset);
Node* make_and_transform_addp(PhaseGVN* phase, Node* base, Node* ptr, Node* offset);
bool prepare_array_copy(PhaseGVN *phase, bool can_reshape,
Node*& adr_src, Node*& base_src, Node*& adr_dest, Node*& base_dest,
BasicType& copy_type, const Type*& value_type, bool& disjoint_bases);

View File

@ -914,6 +914,44 @@
\
develop(bool, StressCountedLoop, false, \
"Randomly delay conversion to counted loops") \
\
product(bool, HotCodeHeap, false, EXPERIMENTAL, \
"Enable the code heap for hot C2 nmethods") \
\
product(double, HotCodeSamplePercent, 80, EXPERIMENTAL, \
"Minimum percentage of profiling samples that must be in " \
"the MethodHot heap before stopping hot code collection") \
range(0, 100) \
\
product(double, HotCodeStablePercent, 5, EXPERIMENTAL, \
"Maximum percentage of newly compiled to total C2 nmethods " \
"to treat nmethod count as stable. " \
"Values less than zero disable the stable check") \
range(-1, DBL_MAX) \
\
product(uint, HotCodeIntervalSeconds, 300, EXPERIMENTAL, \
"Seconds between hot code grouping attempts") \
range(0, max_juint) \
\
product(uint, HotCodeSampleSeconds, 120, EXPERIMENTAL, \
"Seconds to sample application threads per grouping attempt") \
range(0, max_juint) \
\
product(uint, HotCodeStartupDelaySeconds, 120, EXPERIMENTAL, \
"Seconds to delay before starting hot code grouping thread") \
range(0, max_juint) \
\
product(uint, HotCodeMinSamplingMs, 5, EXPERIMENTAL, \
"Minimum sampling interval in milliseconds") \
range(0, max_juint) \
\
product(uint, HotCodeMaxSamplingMs, 15, EXPERIMENTAL, \
"Maximum sampling interval in milliseconds") \
range(0, max_juint) \
\
product(uint, HotCodeCallLevel, 1, EXPERIMENTAL, \
"Number of levels of callees to relocate per candidate") \
range(0, max_juint) \
// end of C2_FLAGS

View File

@ -55,7 +55,7 @@ enum class vmIntrinsicID;
} \
} else if (Use##feature) { \
if (!FLAG_IS_DEFAULT(Use##feature)) { \
warning(#feature " instructions not available on this CPU"); \
warning(#feature " instructions are not available on this CPU"); \
} \
FLAG_SET_DEFAULT(Use##feature, false); \
}

View File

@ -1514,6 +1514,10 @@ const int ObjectAlignmentInBytes = 8;
"Size of code heap with non-nmethods (in bytes)") \
constraint(VMPageSizeConstraintFunc, AtParse) \
\
product(size_t, HotCodeHeapSize, 0, EXPERIMENTAL, \
"Size of code heap with predicted hot methods (in bytes)") \
range(0, SIZE_MAX) \
\
product_pd(size_t, CodeCacheExpansionSize, \
"Code cache expansion size (in bytes)") \
range(32*K, SIZE_MAX) \

View File

@ -0,0 +1,258 @@
/*
* Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifdef COMPILER2
#include "code/codeCache.hpp"
#include "code/compiledIC.hpp"
#include "compiler/compilerDefinitions.inline.hpp"
#include "logging/log.hpp"
#include "memory/resourceArea.hpp"
#include "runtime/hotCodeCollector.hpp"
#include "runtime/hotCodeSampler.hpp"
#include "runtime/java.hpp"
#include "runtime/javaThread.inline.hpp"
// Initialize static variables
bool HotCodeCollector::_is_initialized = false;
int HotCodeCollector::_new_c2_nmethods_count = 0;
int HotCodeCollector::_total_c2_nmethods_count = 0;
HotCodeCollector::HotCodeCollector() : JavaThread(thread_entry) {}
void HotCodeCollector::initialize() {
EXCEPTION_MARK;
assert(HotCodeHeap, "HotCodeCollector requires HotCodeHeap enabled");
assert(CompilerConfig::is_c2_enabled(), "HotCodeCollector requires C2 enabled");
assert(NMethodRelocation, "HotCodeCollector requires NMethodRelocation enabled");
assert(HotCodeHeapSize > 0, "HotCodeHeapSize must be non-zero to use HotCodeCollector");
assert(CodeCache::get_code_heap(CodeBlobType::MethodHot) != nullptr, "MethodHot code heap not found");
Handle thread_oop = JavaThread::create_system_thread_object("HotCodeCollectorThread", CHECK);
HotCodeCollector* thread = new HotCodeCollector();
JavaThread::vm_exit_on_osthread_failure(thread);
JavaThread::start_internal_daemon(THREAD, thread, thread_oop, NormPriority);
_is_initialized = true;
}
bool HotCodeCollector::is_nmethod_count_stable() {
if (HotCodeStablePercent < 0) {
log_info(hotcode)("HotCodeStablePercent is less than zero, stable check disabled");
return true;
}
MutexLocker ml_CodeCache_lock(CodeCache_lock, Mutex::_no_safepoint_check_flag);
if (_total_c2_nmethods_count <= 0) {
log_info(hotcode)("No registered C2 nmethods");
return false;
}
const double percent_new = 100.0 * _new_c2_nmethods_count / _total_c2_nmethods_count;
bool is_stable_nmethod_count = percent_new <= HotCodeStablePercent;
log_info(hotcode)("C2 nmethod count %s", is_stable_nmethod_count ? "stable" : "not stable");
log_debug(hotcode)("C2 nmethod stats: New: %d, Total: %d, Percent new: %f", _new_c2_nmethods_count, _total_c2_nmethods_count, percent_new);
_new_c2_nmethods_count = 0;
return is_stable_nmethod_count;
}
void HotCodeCollector::thread_entry(JavaThread* thread, TRAPS) {
// Initial sleep to allow JVM to warm up
thread->sleep(HotCodeStartupDelaySeconds * 1000);
while (true) {
ResourceMark rm;
// Sample application and group hot nmethods if nmethod count is stable
if (is_nmethod_count_stable()) {
log_info(hotcode)("Sampling...");
ThreadSampler sampler;
uint64_t start_time = os::javaTimeMillis();
while (os::javaTimeMillis() - start_time <= HotCodeSampleSeconds * 1000) {
sampler.sample_all_java_threads();
thread->sleep(rand_sampling_period_ms());
}
Candidates candidates(sampler);
do_grouping(candidates);
}
thread->sleep(HotCodeIntervalSeconds * 1000);
}
}
void HotCodeCollector::do_grouping(Candidates& candidates) {
int num_relocated = 0;
// Sort nmethods by increasing sample count so pop() returns the hottest
candidates.sort();
while (candidates.has_candidates()) {
double percent_from_hot = candidates.get_hot_sample_percent();
log_debug(hotcode)("Percentage of samples from hot code heap: %f", percent_from_hot);
if (percent_from_hot >= HotCodeSamplePercent) {
log_info(hotcode)("Percentage of samples from hot nmethods over threshold. Done collecting hot code");
break;
}
nmethod* candidate = candidates.get_candidate();
MutexLocker ml_Compile_lock(Compile_lock);
MutexLocker ml_CompiledIC_lock(CompiledIC_lock, Mutex::_no_safepoint_check_flag);
MutexLocker ml_CodeCache_lock(CodeCache_lock, Mutex::_no_safepoint_check_flag);
num_relocated += do_relocation(candidate, 0);
}
log_info(hotcode)("Collection done. Relocated %d nmethods to the MethodHot heap", num_relocated);
}
int HotCodeCollector::do_relocation(void* candidate, uint call_level) {
if (candidate == nullptr) {
return 0;
}
// Verify that address still points to CodeBlob
CodeBlob* blob = CodeCache::find_blob(candidate);
if (blob == nullptr) {
return 0;
}
// Verify that blob is nmethod
nmethod* nm = blob->as_nmethod_or_null();
if (nm == nullptr || nm->method() == nullptr) {
return 0;
}
// The candidate may have been recompiled or already relocated.
// Retrieve the latest nmethod from the Method
nm = nm->method()->code();
// Verify the nmethod is still valid for relocation
if (nm == nullptr || !nm->is_in_use() || !nm->is_compiled_by_c2()) {
return 0;
}
// Verify code heap has space
if (CodeCache::get_code_heap(CodeBlobType::MethodHot)->unallocated_capacity() < (size_t)nm->size()) {
log_info(hotcode)("Not enough free space in MethodHot heap (%zd bytes) to relocate nm (%d bytes). Bailing out",
CodeCache::get_code_heap(CodeBlobType::MethodHot)->unallocated_capacity(), nm->size());
return 0;
}
// Number of nmethods relocated (candidate + callees)
int num_relocated = 0;
// Pointer to nmethod in hot heap
nmethod* hot_nm = nullptr;
if (CodeCache::get_code_blob_type(nm) != CodeBlobType::MethodHot) {
CompiledICLocker ic_locker(nm);
hot_nm = nm->relocate(CodeBlobType::MethodHot);
if (hot_nm != nullptr) {
// Successfully relocated nmethod. Update counts and proceed to callee relocation.
log_debug(hotcode)("Successful relocation: nmethod (%p), method (%s), call level (%d)", nm, hot_nm->method()->name_and_sig_as_C_string(), call_level);
num_relocated++;
} else {
// Relocation failed so return and do not attempt to relocate callees
log_debug(hotcode)("Failed relocation: nmethod (%p), call level (%d)", nm, call_level);
return 0;
}
} else {
// Skip relocation since already in hot heap, but still relocate callees
// since they may not have been compiled when this method was first relocated
log_debug(hotcode)("Already relocated: nmethod (%p), method (%s), call level (%d)", nm, nm->method()->name_and_sig_as_C_string(), call_level);
hot_nm = nm;
}
assert(hot_nm != nullptr, "unable to relocate callees");
if (call_level < HotCodeCallLevel) {
// Loop over relocations to relocate callees
RelocIterator relocIter(hot_nm);
while (relocIter.next()) {
// Check if this is a call
Relocation* reloc = relocIter.reloc();
if (!reloc->is_call()) {
continue;
}
// Find the call destination address
address dest = ((CallRelocation*) reloc)->destination();
// Recursively relocate callees
num_relocated += do_relocation(dest, call_level + 1);
}
}
return num_relocated;
}
void HotCodeCollector::unregister_nmethod(nmethod* nm) {
assert_lock_strong(CodeCache_lock);
if (!_is_initialized) {
return;
}
if (!nm->is_compiled_by_c2()) {
return;
}
if (CodeCache::get_code_blob_type(nm) == CodeBlobType::MethodHot) {
// Nmethods in the hot code heap do not count towards total C2 nmethods.
return;
}
// CodeCache_lock is held, so we can safely decrement the count.
_total_c2_nmethods_count--;
}
void HotCodeCollector::register_nmethod(nmethod* nm) {
assert_lock_strong(CodeCache_lock);
if (!_is_initialized) {
return;
}
if (!nm->is_compiled_by_c2()) {
return; // Only C2 nmethods are relocated to HotCodeHeap.
}
if (CodeCache::get_code_blob_type(nm) == CodeBlobType::MethodHot) {
// Nmethods in the hot code heap do not count towards total C2 nmethods.
return;
}
// CodeCache_lock is held, so we can safely increment the count.
_new_c2_nmethods_count++;
_total_c2_nmethods_count++;
}
#endif // COMPILER2

View File

@ -0,0 +1,56 @@
/*
* Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifdef COMPILER2
#ifndef SHARE_RUNTIME_HOTCODECOLLECTOR_HPP
#define SHARE_RUNTIME_HOTCODECOLLECTOR_HPP
#include "runtime/javaThread.hpp"
class Candidates;
class HotCodeCollector : public JavaThread {
private:
static bool _is_initialized;
static int _new_c2_nmethods_count;
static int _total_c2_nmethods_count;
HotCodeCollector();
static void do_grouping(Candidates& candidates);
static int do_relocation(void* candidate, uint call_level);
public:
static void initialize();
static void thread_entry(JavaThread* thread, TRAPS);
static void unregister_nmethod(nmethod* nm);
static void register_nmethod(nmethod* nm);
static bool is_nmethod_count_stable();
};
#endif // SHARE_RUNTIME_HOTCODECOLLECTOR_HPP
#endif // COMPILER2

View File

@ -0,0 +1,121 @@
/*
* Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifdef COMPILER2
#include "code/codeCache.hpp"
#include "logging/log.hpp"
#include "runtime/hotCodeSampler.hpp"
#include "runtime/javaThread.inline.hpp"
void ThreadSampler::sample_all_java_threads() {
// Collect samples for each JavaThread
for (JavaThreadIteratorWithHandle jtiwh; JavaThread *jt = jtiwh.next(); ) {
if (jt->is_hidden_from_external_view() ||
jt->in_deopt_handler() ||
(jt->thread_state() != _thread_in_native && jt->thread_state() != _thread_in_Java)) {
continue;
}
GetPCTask task(jt);
task.run();
address pc = task.pc();
if (pc == nullptr) {
continue;
}
if (CodeCache::contains(pc)) {
nmethod* nm = CodeCache::find_blob(pc)->as_nmethod_or_null();
if (nm != nullptr) {
bool created = false;
int *count = _samples.put_if_absent(nm, 0, &created);
(*count)++;
if (created) {
_samples.maybe_grow();
}
}
}
}
}
Candidates::Candidates(ThreadSampler& sampler)
: _hot_sample_count(0), _non_profiled_sample_count(0) {
auto func = [&](nmethod* nm, int count) {
if (CodeCache::get_code_blob_type(nm) == CodeBlobType::MethodNonProfiled) {
_candidates.append(Pair<nmethod*, int>(nm, count));
add_non_profiled_sample_count(count);
} else if (CodeCache::get_code_blob_type(nm) == CodeBlobType::MethodHot) {
add_hot_sample_count(count);
}
};
sampler.iterate_samples(func);
log_info(hotcode)("Generated candidate list from %d samples corresponding to %d nmethods", _non_profiled_sample_count + _hot_sample_count, _candidates.length());
}
void Candidates::add_candidate(nmethod* nm, int count) {
_candidates.append(Pair<nmethod*, int>(nm, count));
}
void Candidates::add_hot_sample_count(int count) {
_hot_sample_count += count;
}
void Candidates::add_non_profiled_sample_count(int count) {
_non_profiled_sample_count += count;
}
void Candidates::sort() {
_candidates.sort(
[](Pair<nmethod*, int>* a, Pair<nmethod*, int>* b) {
if (a->second > b->second) return 1;
if (a->second < b->second) return -1;
return 0;
}
);
}
bool Candidates::has_candidates() {
return !_candidates.is_empty();
}
nmethod* Candidates::get_candidate() {
assert(has_candidates(), "must not be empty");
Pair<nmethod*, int> candidate = _candidates.pop();
_hot_sample_count += candidate.second;
_non_profiled_sample_count -= candidate.second;
return candidate.first;
}
double Candidates::get_hot_sample_percent() {
if (_hot_sample_count + _non_profiled_sample_count == 0) {
return 0;
}
return 100.0 * _hot_sample_count / (_hot_sample_count + _non_profiled_sample_count);
}
#endif // COMPILER2

View File

@ -0,0 +1,104 @@
/*
* Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifdef COMPILER2
#ifndef SHARE_RUNTIME_HOTCODESAMPLER_HPP
#define SHARE_RUNTIME_HOTCODESAMPLER_HPP
#include "runtime/javaThread.hpp"
#include "runtime/suspendedThreadTask.hpp"
#include "runtime/threadSMR.hpp"
#include "utilities/pair.hpp"
#include "utilities/resizableHashTable.hpp"
// Generate a random sampling period between min and max
static inline uint rand_sampling_period_ms() {
assert(HotCodeMaxSamplingMs >= HotCodeMinSamplingMs, "max cannot be smaller than min");
julong range = (julong)HotCodeMaxSamplingMs - (julong)HotCodeMinSamplingMs + 1;
return (uint)(os::random() % range) + HotCodeMinSamplingMs;
}
class ThreadSampler;
class Candidates : public StackObj {
private:
GrowableArray<Pair<nmethod*, int>> _candidates;
int _hot_sample_count;
int _non_profiled_sample_count;
public:
Candidates(ThreadSampler& sampler);
void add_candidate(nmethod* nm, int count);
void add_hot_sample_count(int count);
void add_non_profiled_sample_count(int count);
void sort();
bool has_candidates();
nmethod* get_candidate();
double get_hot_sample_percent();
};
class GetPCTask : public SuspendedThreadTask {
private:
address _pc;
void do_task(const SuspendedThreadTaskContext& context) override {
JavaThread* jt = JavaThread::cast(context.thread());
if (jt->thread_state() != _thread_in_native && jt->thread_state() != _thread_in_Java) {
return;
}
_pc = os::fetch_frame_from_context(context.ucontext(), nullptr, nullptr);
}
public:
GetPCTask(JavaThread* thread) : SuspendedThreadTask(thread), _pc(nullptr) {}
address pc() const {
return _pc;
}
};
class ThreadSampler : public StackObj {
private:
static const int INITIAL_TABLE_SIZE = 109;
// Table of nmethods found during profiling with sample count
ResizeableHashTable<nmethod*, int, AnyObj::C_HEAP, mtInternal> _samples;
public:
ThreadSampler() : _samples(INITIAL_TABLE_SIZE, HotCodeSampleSeconds * 1000 / HotCodeMaxSamplingMs) {}
// Iterate over and sample all Java threads
void sample_all_java_threads();
// Iterate over all samples with a callback function
template<typename Function>
void iterate_samples(Function func) {
_samples.iterate_all(func);
}
};
#endif // SHARE_RUNTIME_HOTCODESAMPLER_HPP
#endif // COMPILER2

View File

@ -113,6 +113,7 @@
#endif
#ifdef COMPILER2
#include "opto/idealGraphPrinter.hpp"
#include "runtime/hotCodeCollector.hpp"
#endif
#if INCLUDE_JFR
#include "jfr/jfr.hpp"
@ -798,6 +799,12 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) {
StringDedup::start();
}
#ifdef COMPILER2
if (HotCodeHeap) {
HotCodeCollector::initialize();
}
#endif // COMPILER2
// Pre-initialize some JSR292 core classes to avoid deadlock during class loading.
// It is done after compilers are initialized, because otherwise compilations of
// signature polymorphic MH intrinsics can be missed

View File

@ -1327,13 +1327,13 @@ void VMError::report(outputStream* st, bool _verbose) {
STEP_IF("printing OS information", _verbose)
os::print_os_info(st);
st->cr();
#ifdef __APPLE__
// Avoid large stack allocation on Mac for FD count during signal-handling.
os::Bsd::print_open_file_descriptors(st, buf, sizeof(buf));
st->cr();
#else
os::print_open_file_descriptors(st);
st->cr();
#endif
STEP_IF("printing CPU info", _verbose)
@ -1553,7 +1553,6 @@ void VMError::print_vm_info(outputStream* st) {
// STEP("printing OS information")
os::print_os_info(st);
st->cr();
os::print_open_file_descriptors(st);
st->cr();

View File

@ -70,9 +70,9 @@ import sun.nio.cs.UTF_8;
* string literals in Java programs, such as {@code "abc"}, are
* implemented as instances of this class.
* <p>
* Strings are constant; their values cannot be changed after they
* are created. String buffers support mutable strings.
* Because String objects are immutable they can be shared. For example:
* Strings are immutable; their values cannot be changed after they
* are created. Because String objects are immutable they can be shared.
* For example:
* <blockquote><pre>
* String str = "abc";
* </pre></blockquote><p>

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 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
@ -41,7 +41,7 @@ package java.text;
import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import static java.text.DateFormatSymbols.*;
import java.time.ZoneOffset;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
@ -57,6 +57,8 @@ import sun.util.calendar.ZoneInfoFile;
import sun.util.locale.provider.LocaleProviderAdapter;
import sun.util.locale.provider.TimeZoneNameUtility;
import static java.text.DateFormatSymbols.*;
/**
* {@code SimpleDateFormat} is a concrete class for formatting and
* parsing dates in a locale-sensitive manner. It allows for formatting
@ -1293,15 +1295,22 @@ public class SimpleDateFormat extends DateFormat {
case PATTERN_ZONE_NAME: // 'z'
if (current == null) {
TimeZone tz = calendar.getTimeZone();
String tzid = tz.getID();
int zoneOffset = calendar.get(Calendar.ZONE_OFFSET);
int dstOffset = calendar.get(Calendar.DST_OFFSET) + zoneOffset;
// Check if an explicit metazone DST offset exists
String explicitDstOffset = TimeZoneNameUtility.explicitDstOffset(tzid);
boolean daylight = explicitDstOffset != null ?
dstOffset == ZoneOffset.of(explicitDstOffset).getTotalSeconds() * 1_000 :
dstOffset != zoneOffset;
if (formatData.locale == null || formatData.isZoneStringsSet) {
int zoneIndex =
formatData.getZoneIndex(calendar.getTimeZone().getID());
int zoneIndex = formatData.getZoneIndex(tzid);
if (zoneIndex == -1) {
value = calendar.get(Calendar.ZONE_OFFSET) +
calendar.get(Calendar.DST_OFFSET);
buffer.append(ZoneInfoFile.toCustomID(value));
buffer.append(ZoneInfoFile.toCustomID(dstOffset));
} else {
int index = (calendar.get(Calendar.DST_OFFSET) == 0) ? 1: 3;
int index = daylight ? 3 : 1;
if (count < 4) {
// Use the short name
index++;
@ -1310,8 +1319,6 @@ public class SimpleDateFormat extends DateFormat {
buffer.append(zoneStrings[zoneIndex][index]);
}
} else {
TimeZone tz = calendar.getTimeZone();
boolean daylight = (calendar.get(Calendar.DST_OFFSET) != 0);
int tzstyle = (count < 4 ? TimeZone.SHORT : TimeZone.LONG);
buffer.append(tz.getDisplayName(daylight, tzstyle, formatData.locale));
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2026, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2025, Alibaba Group Holding Limited. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@ -4513,7 +4513,11 @@ public final class DateTimeFormatterBuilder {
TemporalAccessor dt = context.getTemporal();
int type = GENERIC;
if (!isGeneric) {
if (dt.isSupported(ChronoField.INSTANT_SECONDS)) {
// Check if an explicit metazone DST offset exists
String dstOffset = TimeZoneNameUtility.explicitDstOffset(zname);
if (dt.isSupported(OFFSET_SECONDS) && dstOffset != null) {
type = ZoneOffset.from(dt).equals(ZoneOffset.of(dstOffset)) ? DST : STD;
} else if (dt.isSupported(ChronoField.INSTANT_SECONDS)) {
type = zone.getRules().isDaylightSavings(Instant.from(dt)) ? DST : STD;
} else if (dt.isSupported(ChronoField.EPOCH_DAY) &&
dt.isSupported(ChronoField.NANO_OF_DAY)) {

View File

@ -1932,7 +1932,7 @@ public final class Locale implements Cloneable, Serializable {
}
/**
* Returns a name for the locale's language that is appropriate for display to the
* Returns a name for {@code this} locale's language that is appropriate for display to the
* user.
* If possible, the name returned will be localized for the default
* {@link Locale.Category#DISPLAY DISPLAY} locale.
@ -1946,14 +1946,15 @@ public final class Locale implements Cloneable, Serializable {
* this function falls back on the English name, and uses the ISO code as a last-resort
* value. If the locale doesn't specify a language, this function returns the empty string.
*
* @return The name of the display language.
* @return The name of the display language appropriate to the default
* {@link Locale.Category#DISPLAY DISPLAY} locale.
*/
public final String getDisplayLanguage() {
public String getDisplayLanguage() {
return getDisplayLanguage(getDefault(Category.DISPLAY));
}
/**
* Returns a name for the locale's language that is appropriate for display to the
* Returns a name for {@code this} locale's language that is appropriate for display to the
* user.
* If possible, the name returned will be localized according to inLocale.
* For example, if the locale is fr_FR and inLocale
@ -1964,7 +1965,7 @@ public final class Locale implements Cloneable, Serializable {
* on the ISO code as a last-resort value. If the locale doesn't specify a language,
* this function returns the empty string.
*
* @param inLocale The locale for which to retrieve the display language.
* @param inLocale The locale in which to localize the display language.
* @return The name of the display language appropriate to the given locale.
* @throws NullPointerException if {@code inLocale} is {@code null}
*/
@ -1973,13 +1974,13 @@ public final class Locale implements Cloneable, Serializable {
}
/**
* Returns a name for the locale's script that is appropriate for display to
* Returns a name for {@code this} locale's script that is appropriate for display to
* the user. If possible, the name will be localized for the default
* {@link Locale.Category#DISPLAY DISPLAY} locale. Returns
* the empty string if this locale doesn't specify a script code.
*
* @return the display name of the script code for the current default
* {@link Locale.Category#DISPLAY DISPLAY} locale
* @return The display name of the script code appropriate to the default
* {@link Locale.Category#DISPLAY DISPLAY} locale.
* @since 1.7
*/
public String getDisplayScript() {
@ -1987,14 +1988,13 @@ public final class Locale implements Cloneable, Serializable {
}
/**
* Returns a name for the locale's script that is appropriate
* Returns a name for {@code this} locale's script that is appropriate
* for display to the user. If possible, the name will be
* localized for the given locale. Returns the empty string if
* this locale doesn't specify a script code.
*
* @param inLocale The locale for which to retrieve the display script.
* @return the display name of the script code for the current default
* {@link Locale.Category#DISPLAY DISPLAY} locale
* @param inLocale The locale in which to localize the display script.
* @return The display name of the script code appropriate to the given locale.
* @throws NullPointerException if {@code inLocale} is {@code null}
* @since 1.7
*/
@ -2003,7 +2003,7 @@ public final class Locale implements Cloneable, Serializable {
}
/**
* Returns a name for the locale's country that is appropriate for display to the
* Returns a name for {@code this} locale's country that is appropriate for display to the
* user.
* If possible, the name returned will be localized for the default
* {@link Locale.Category#DISPLAY DISPLAY} locale.
@ -2017,14 +2017,15 @@ public final class Locale implements Cloneable, Serializable {
* this function falls back on the English name, and uses the ISO code as a last-resort
* value. If the locale doesn't specify a country, this function returns the empty string.
*
* @return The name of the country appropriate to the locale.
* @return The name of the country appropriate to the default
* {@link Locale.Category#DISPLAY DISPLAY} locale.
*/
public final String getDisplayCountry() {
public String getDisplayCountry() {
return getDisplayCountry(getDefault(Category.DISPLAY));
}
/**
* Returns a name for the locale's country that is appropriate for display to the
* Returns a name for {@code this} locale's country that is appropriate for display to the
* user.
* If possible, the name returned will be localized according to inLocale.
* For example, if the locale is fr_FR and inLocale
@ -2035,7 +2036,7 @@ public final class Locale implements Cloneable, Serializable {
* on the ISO code as a last-resort value. If the locale doesn't specify a country,
* this function returns the empty string.
*
* @param inLocale The locale for which to retrieve the display country.
* @param inLocale The locale in which to localize the display country.
* @return The name of the country appropriate to the given locale.
* @throws NullPointerException if {@code inLocale} is {@code null}
*/
@ -2061,23 +2062,24 @@ public final class Locale implements Cloneable, Serializable {
}
/**
* Returns a name for the locale's variant code that is appropriate for display to the
* Returns a name for {@code this} locale's variant code that is appropriate for display to the
* user. If possible, the name will be localized for the default
* {@link Locale.Category#DISPLAY DISPLAY} locale. If the locale
* doesn't specify a variant code, this function returns the empty string.
*
* @return The name of the display variant code appropriate to the locale.
* @return The name of the display variant code appropriate to the default
* {@link Locale.Category#DISPLAY DISPLAY} locale.
*/
public final String getDisplayVariant() {
public String getDisplayVariant() {
return getDisplayVariant(getDefault(Category.DISPLAY));
}
/**
* Returns a name for the locale's variant code that is appropriate for display to the
* Returns a name for {@code this} locale's variant code that is appropriate for display to the
* user. If possible, the name will be localized for inLocale. If the locale
* doesn't specify a variant code, this function returns the empty string.
*
* @param inLocale The locale for which to retrieve the display variant code.
* @param inLocale The locale in which to localize the display variant code.
* @return The name of the display variant code appropriate to the given locale.
* @throws NullPointerException if {@code inLocale} is {@code null}
*/
@ -2098,7 +2100,7 @@ public final class Locale implements Cloneable, Serializable {
}
/**
* Returns a name for the locale that is appropriate for display to the
* Returns a name for {@code this} locale that is appropriate for display to the
* user. This will be the values returned by getDisplayLanguage(),
* getDisplayScript(), getDisplayCountry(), getDisplayVariant() and
* optional {@linkplain ##def_locale_extension Unicode extensions}
@ -2116,14 +2118,15 @@ public final class Locale implements Cloneable, Serializable {
* be localized depending on the locale. If the language, script, country,
* and variant fields are all empty, this function returns the empty string.
*
* @return The name of the locale appropriate to display.
* @return The display name appropriate to the default
* {@link Locale.Category#DISPLAY DISPLAY} locale.
*/
public final String getDisplayName() {
public String getDisplayName() {
return getDisplayName(getDefault(Category.DISPLAY));
}
/**
* Returns a name for the locale that is appropriate for display
* Returns a name for {@code this} locale that is appropriate for display
* to the user. This will be the values returned by
* getDisplayLanguage(), getDisplayScript(), getDisplayCountry(),
* getDisplayVariant(), and optional {@linkplain ##def_locale_extension
@ -2142,8 +2145,8 @@ public final class Locale implements Cloneable, Serializable {
* be localized depending on the locale. If the language, script, country,
* and variant fields are all empty, this function returns the empty string.
*
* @param inLocale The locale for which to retrieve the display name.
* @return The name of the locale appropriate to display.
* @param inLocale The locale in which to localize the display name.
* @return The display name appropriate to the given locale.
* @throws NullPointerException if {@code inLocale} is {@code null}
*/
public String getDisplayName(Locale inLocale) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1995, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1995, 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
@ -651,8 +651,9 @@ public class ZipEntry implements ZipConstants, Cloneable {
}
/**
* Sets the optional comment string for the entry.
* @param comment the comment string
* Sets the optional comment string for the entry. If {@code comment} is an
* empty string or {@code null} then the entry will have no comment.
* @param comment the comment string, or an empty string or null for no comment
* @throws IllegalArgumentException if the combined length
* of the specified entry comment, the {@linkplain #getName() entry name},
* the {@linkplain #getExtra() extra field data}, and the

View File

@ -43,6 +43,10 @@ import sun.nio.cs.UTF_8;
* <p> Unless otherwise noted, passing a {@code null} argument to a constructor
* or method in this class will cause a {@link NullPointerException} to be
* thrown.
* <p> By default, the UTF-8 charset is used to encode entry names and comments.
* {@link #ZipOutputStream(OutputStream, Charset)} may be be used to specify
* an alternative charset.
*
* @author David Connelly
* @since 1.1
*/
@ -110,10 +114,8 @@ public class ZipOutputStream extends DeflaterOutputStream implements ZipConstant
public static final int DEFLATED = ZipEntry.DEFLATED;
/**
* Creates a new ZIP output stream.
*
* <p>The UTF-8 {@link java.nio.charset.Charset charset} is used
* to encode the entry names and comments.
* Creates a new ZIP output stream using the UTF-8
* {@link Charset charset} to encode entry names and comments.
*
* @param out the actual output stream
*/
@ -122,12 +124,13 @@ public class ZipOutputStream extends DeflaterOutputStream implements ZipConstant
}
/**
* Creates a new ZIP output stream.
* Creates a new ZIP output stream using the specified
* {@link Charset charset} to encode entry names and comments.
*
* @param out the actual output stream
*
* @param charset the {@linkplain java.nio.charset.Charset charset}
* to be used to encode the entry names and comments
* to be used to encode entry names and comments
*
* @since 1.7
*/
@ -140,10 +143,15 @@ public class ZipOutputStream extends DeflaterOutputStream implements ZipConstant
}
/**
* Sets the ZIP file comment.
* @param comment the comment string
* @throws IllegalArgumentException if the length of the specified
* ZIP file comment is greater than 0xFFFF bytes
* Sets the ZIP file comment. If {@code comment} is an empty string or
* {@code null} then the output will have no ZIP file comment.
*
* @param comment the comment string, or an empty string or null for no comment
*
* @throws IllegalArgumentException if the length of the specified ZIP file
* comment is greater than 0xFFFF bytes or if the {@code comment}
* contains characters that cannot be mapped by the {@code Charset}
* used to encode entry names and comments
*/
public void setComment(String comment) {
byte[] bytes = null;

View File

@ -105,6 +105,9 @@ public class LocaleResources {
// TimeZoneNamesBundle exemplar city prefix
private static final String TZNB_EXCITY_PREFIX = "timezone.excity.";
// TimeZoneNamesBundle explicit metazone dst offset prefix
private static final String TZNB_METAZONE_DSTOFFSET_PREFIX = "metazone.dstoffset.";
// null singleton cache value
private static final Object NULLOBJECT = new Object();
@ -321,7 +324,8 @@ public class LocaleResources {
if (Objects.isNull(data) || Objects.isNull(val = data.get())) {
TimeZoneNamesBundle tznb = localeData.getTimeZoneNames(locale);
if (key.startsWith(TZNB_EXCITY_PREFIX)) {
if (key.startsWith(TZNB_EXCITY_PREFIX) ||
key.startsWith(TZNB_METAZONE_DSTOFFSET_PREFIX)) {
if (tznb.containsKey(key)) {
val = tznb.getString(key);
assert val instanceof String;
@ -378,7 +382,8 @@ public class LocaleResources {
Set<String[]> value = new LinkedHashSet<>();
Set<String> tzIds = new HashSet<>(Arrays.asList(TimeZone.getAvailableIDs()));
for (String key : keyset) {
if (!key.startsWith(TZNB_EXCITY_PREFIX)) {
if (!key.startsWith(TZNB_EXCITY_PREFIX) &&
!key.startsWith(TZNB_METAZONE_DSTOFFSET_PREFIX)) {
value.add(rb.getStringArray(key));
tzIds.remove(key);
}

View File

@ -37,7 +37,7 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.spi.TimeZoneNameProvider;
import sun.util.calendar.ZoneInfo;
import sun.util.cldr.CLDRLocaleProviderAdapter;
import static sun.util.locale.provider.LocaleProviderAdapter.Type;
import static sun.util.locale.provider.LocaleProviderAdapter.Type.CLDR;
/**
* Utility class that deals with the localized time zone names
@ -169,10 +169,22 @@ public final class TimeZoneNameUtility {
* Returns the canonical ID for the given ID
*/
public static Optional<String> canonicalTZID(String id) {
return ((CLDRLocaleProviderAdapter)LocaleProviderAdapter.forType(Type.CLDR))
return ((CLDRLocaleProviderAdapter)LocaleProviderAdapter.forType(CLDR))
.canonicalTZID(id);
}
/**
* {@return the explicit metazone DST offset for the specified time zone ID, if exists}
* @param tzid the time zone ID
*/
public static String explicitDstOffset(String tzid) {
return (String) (LocaleProviderAdapter.forType(CLDR) instanceof CLDRLocaleProviderAdapter ca ?
ca.getLocaleResources(Locale.ROOT)
.getTimeZoneNames("metazone.dstoffset." +
ca.canonicalTZID(tzid).orElse(tzid)) :
null);
}
private static String[] retrieveDisplayNamesImpl(String id, Locale locale) {
LocaleServiceProviderPool pool =
LocaleServiceProviderPool.getPool(TimeZoneNameProvider.class);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -43,8 +43,6 @@ package sun.util.resources;
import java.util.Map;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.MissingResourceException;
import java.util.Objects;
import java.util.Set;
/**

View File

@ -31,73 +31,54 @@
#define CHECK_EXCEPTION if (env->ExceptionCheck()) { return; }
static jfieldID p_dwarf_context_ID = 0;
static jint sa_RAX = -1;
static jint sa_RDX = -1;
static jint sa_RCX = -1;
static jint sa_RBX = -1;
static jint sa_RSI = -1;
static jint sa_RDI = -1;
static jint sa_RBP = -1;
static jint sa_RSP = -1;
static jint sa_R8 = -1;
static jint sa_R9 = -1;
static jint sa_R10 = -1;
static jint sa_R11 = -1;
static jint sa_R12 = -1;
static jint sa_R13 = -1;
static jint sa_R14 = -1;
static jint sa_R15 = -1;
// DWARF_REG macro is used by DWARF_REGLIST.
#define DWARF_REG(reg, _) \
static jint sa_##reg = -1;
DWARF_REGLIST
#undef DWARF_REG
static jlong get_dwarf_context(JNIEnv *env, jobject obj) {
return env->GetLongField(obj, p_dwarf_context_ID);
}
#define SET_REG(env, reg, reg_cls) \
/*
* Class: sun_jvm_hotspot_debugger_linux_DwarfParser
* Method: init0
* Signature: ()V
*/
extern "C"
JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_linux_DwarfParser_init0
(JNIEnv *env, jclass this_cls) {
jclass cls = env->FindClass("sun/jvm/hotspot/debugger/linux/DwarfParser");
CHECK_EXCEPTION
p_dwarf_context_ID = env->GetFieldID(cls, "p_dwarf_context", "J");
CHECK_EXCEPTION
jclass reg_cls = env->FindClass(THREAD_CONTEXT_CLASS);
CHECK_EXCEPTION
// DWARF_REG macro is used by DWARF_REGLIST.
#define DWARF_REG(reg, _) \
jfieldID reg##_ID = env->GetStaticFieldID(reg_cls, #reg, "I"); \
CHECK_EXCEPTION \
sa_##reg = env->GetStaticIntField(reg_cls, reg##_ID); \
CHECK_EXCEPTION
/*
* Class: sun_jvm_hotspot_debugger_linux_amd64_DwarfParser
* Method: init0
* Signature: ()V
*/
extern "C"
JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_linux_amd64_DwarfParser_init0
(JNIEnv *env, jclass this_cls) {
jclass cls = env->FindClass("sun/jvm/hotspot/debugger/linux/amd64/DwarfParser");
CHECK_EXCEPTION
p_dwarf_context_ID = env->GetFieldID(cls, "p_dwarf_context", "J");
CHECK_EXCEPTION
DWARF_REGLIST
jclass reg_cls = env->FindClass("sun/jvm/hotspot/debugger/amd64/AMD64ThreadContext");
CHECK_EXCEPTION
SET_REG(env, RAX, reg_cls);
SET_REG(env, RDX, reg_cls);
SET_REG(env, RCX, reg_cls);
SET_REG(env, RBX, reg_cls);
SET_REG(env, RSI, reg_cls);
SET_REG(env, RDI, reg_cls);
SET_REG(env, RBP, reg_cls);
SET_REG(env, RSP, reg_cls);
SET_REG(env, R8, reg_cls);
SET_REG(env, R9, reg_cls);
SET_REG(env, R10, reg_cls);
SET_REG(env, R11, reg_cls);
SET_REG(env, R12, reg_cls);
SET_REG(env, R13, reg_cls);
SET_REG(env, R14, reg_cls);
SET_REG(env, R15, reg_cls);
#undef DWARF_REG
}
/*
* Class: sun_jvm_hotspot_debugger_linux_amd64_DwarfParser
* Class: sun_jvm_hotspot_debugger_linux_DwarfParser
* Method: createDwarfContext
* Signature: (J)J
*/
extern "C"
JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_debugger_linux_amd64_DwarfParser_createDwarfContext
JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_debugger_linux_DwarfParser_createDwarfContext
(JNIEnv *env, jclass this_cls, jlong lib) {
DwarfParser *parser = new DwarfParser(reinterpret_cast<lib_info *>(lib));
if (!parser->is_parseable()) {
@ -113,36 +94,36 @@ JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_debugger_linux_amd64_DwarfParser_cr
}
/*
* Class: sun_jvm_hotspot_debugger_linux_amd64_DwarfParser
* Class: sun_jvm_hotspot_debugger_linux_DwarfParser
* Method: destroyDwarfContext
* Signature: (J)V
*/
extern "C"
JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_linux_amd64_DwarfParser_destroyDwarfContext
JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_linux_DwarfParser_destroyDwarfContext
(JNIEnv *env, jclass this_cls, jlong context) {
DwarfParser *parser = reinterpret_cast<DwarfParser *>(context);
delete parser;
}
/*
* Class: sun_jvm_hotspot_debugger_linux_amd64_DwarfParser
* Class: sun_jvm_hotspot_debugger_linux_DwarfParser
* Method: isIn0
* Signature: (J)Z
*/
extern "C"
JNIEXPORT jboolean JNICALL Java_sun_jvm_hotspot_debugger_linux_amd64_DwarfParser_isIn0
JNIEXPORT jboolean JNICALL Java_sun_jvm_hotspot_debugger_linux_DwarfParser_isIn0
(JNIEnv *env, jobject this_obj, jlong pc) {
DwarfParser *parser = reinterpret_cast<DwarfParser *>(get_dwarf_context(env, this_obj));
return static_cast<jboolean>(parser->is_in(pc));
}
/*
* Class: sun_jvm_hotspot_debugger_linux_amd64_DwarfParser
* Class: sun_jvm_hotspot_debugger_linux_DwarfParser
* Method: processDwarf0
* Signature: (J)V
*/
extern "C"
JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_linux_amd64_DwarfParser_processDwarf0
JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_linux_DwarfParser_processDwarf0
(JNIEnv *env, jobject this_obj, jlong pc) {
DwarfParser *parser = reinterpret_cast<DwarfParser *>(get_dwarf_context(env, this_obj));
if (!parser->process_dwarf(pc)) {
@ -155,67 +136,106 @@ JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_linux_amd64_DwarfParser_pro
}
/*
* Class: sun_jvm_hotspot_debugger_linux_amd64_DwarfParser
* Class: sun_jvm_hotspot_debugger_linux_DwarfParser
* Method: getCFARegister
* Signature: ()I
*/
extern "C"
JNIEXPORT jint JNICALL Java_sun_jvm_hotspot_debugger_linux_amd64_DwarfParser_getCFARegister
JNIEXPORT jint JNICALL Java_sun_jvm_hotspot_debugger_linux_DwarfParser_getCFARegister
(JNIEnv *env, jobject this_obj) {
DwarfParser *parser = reinterpret_cast<DwarfParser *>(get_dwarf_context(env, this_obj));
switch (parser->get_cfa_register()) {
case RAX: return sa_RAX;
case RDX: return sa_RDX;
case RCX: return sa_RCX;
case RBX: return sa_RBX;
case RSI: return sa_RSI;
case RDI: return sa_RDI;
case RBP: return sa_RBP;
case RSP: return sa_RSP;
case R8: return sa_R8;
case R9: return sa_R9;
case R10: return sa_R10;
case R11: return sa_R11;
case R12: return sa_R12;
case R13: return sa_R13;
case R14: return sa_R14;
case R15: return sa_R15;
// DWARF_REG macro is used by DWARF_REGLIST.
#define DWARF_REG(reg, _) \
case reg: return sa_##reg;
DWARF_REGLIST
#undef DWARF_REG
default: return -1;
}
}
/*
* Class: sun_jvm_hotspot_debugger_linux_amd64_DwarfParser
* Class: sun_jvm_hotspot_debugger_linux_DwarfParser
* Method: getCFAOffset
* Signature: ()I
*/
extern "C"
JNIEXPORT jint JNICALL Java_sun_jvm_hotspot_debugger_linux_amd64_DwarfParser_getCFAOffset
JNIEXPORT jint JNICALL Java_sun_jvm_hotspot_debugger_linux_DwarfParser_getCFAOffset
(JNIEnv *env, jobject this_obj) {
DwarfParser *parser = reinterpret_cast<DwarfParser *>(get_dwarf_context(env, this_obj));
return parser->get_cfa_offset();
}
/*
* Class: sun_jvm_hotspot_debugger_linux_amd64_DwarfParser
* Class: sun_jvm_hotspot_debugger_linux_DwarfParser
* Method: getOffsetFromCFA
* Signature: (I)I
*/
extern "C"
JNIEXPORT jint JNICALL Java_sun_jvm_hotspot_debugger_linux_DwarfParser_getOffsetFromCFA
(JNIEnv *env, jobject this_obj, jint sareg) {
DwarfParser *parser = reinterpret_cast<DwarfParser *>(get_dwarf_context(env, this_obj));
// DWARF_REG macro is used by DWARF_REGLIST.
#define DWARF_REG(reg, dwreg) \
if (sareg == sa_##reg) { \
return parser->get_offset_from_cfa(static_cast<enum DWARF_Register>(dwreg)); \
} else
DWARF_REGLIST
#undef DWARF_REG
return INT_MAX;
}
/*
* Class: sun_jvm_hotspot_debugger_linux_DwarfParser
* Method: getRARegister
* Signature: ()I
*/
extern "C"
JNIEXPORT jint JNICALL Java_sun_jvm_hotspot_debugger_linux_DwarfParser_getRARegister
(JNIEnv *env, jobject this_obj) {
DwarfParser *parser = reinterpret_cast<DwarfParser *>(get_dwarf_context(env, this_obj));
switch (parser->get_ra_register()) {
// DWARF_REG macro is used by DWARF_REGLIST.
#define DWARF_REG(reg, _) \
case reg: return sa_##reg;
DWARF_REGLIST
#undef DWARF_REG
default: return -1;
}
}
/*
* Class: sun_jvm_hotspot_debugger_linux_DwarfParser
* Method: getReturnAddressOffsetFromCFA
* Signature: ()I
*/
extern "C"
JNIEXPORT jint JNICALL Java_sun_jvm_hotspot_debugger_linux_amd64_DwarfParser_getReturnAddressOffsetFromCFA
JNIEXPORT jint JNICALL Java_sun_jvm_hotspot_debugger_linux_DwarfParser_getReturnAddressOffsetFromCFA
(JNIEnv *env, jobject this_obj) {
DwarfParser *parser = reinterpret_cast<DwarfParser *>(get_dwarf_context(env, this_obj));
return parser->get_offset_from_cfa(RA);
}
/*
* Class: sun_jvm_hotspot_debugger_linux_amd64_DwarfParser
* Class: sun_jvm_hotspot_debugger_linux_DwarfParser
* Method: getBasePointerOffsetFromCFA
* Signature: ()I
*/
extern "C"
JNIEXPORT jint JNICALL Java_sun_jvm_hotspot_debugger_linux_amd64_DwarfParser_getBasePointerOffsetFromCFA
JNIEXPORT jint JNICALL Java_sun_jvm_hotspot_debugger_linux_DwarfParser_getBasePointerOffsetFromCFA
(JNIEnv *env, jobject this_obj) {
DwarfParser *parser = reinterpret_cast<DwarfParser *>(get_dwarf_context(env, this_obj));
return parser->get_offset_from_cfa(RBP);
return parser->get_offset_from_cfa(BP);
}

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2021, NTT DATA.
* Copyright (c) 2002, 2026, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2026, NTT DATA.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -289,6 +289,13 @@ JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_at
snprintf(msg, sizeof(msg), "Can't attach to the process: %s", err_buf);
THROW_NEW_DEBUGGER_EXCEPTION(msg);
}
#ifdef __aarch64__
if (pac_enabled(ph)) {
printf("WARNING: PAC is enabled. Stack traces might be incomplete.\n");
}
#endif
env->SetLongField(this_obj, p_ps_prochandle_ID, (jlong)(intptr_t)ph);
fillThreadsAndLoadObjects(env, this_obj, ph);
}
@ -313,6 +320,13 @@ JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_at
if ( (ph = Pgrab_core(execName_cstr, coreName_cstr)) == NULL) {
THROW_NEW_DEBUGGER_EXCEPTION("Can't attach to the core file. For more information, export LIBSAPROC_DEBUG=1 and try again.");
}
#ifdef __aarch64__
if (pac_enabled(ph)) {
printf("WARNING: PAC is enabled. Stack traces might be incomplete.\n");
}
#endif
env->SetLongField(this_obj, p_ps_prochandle_ID, (jlong)(intptr_t)ph);
fillThreadsAndLoadObjects(env, this_obj, ph);
}

View File

@ -217,6 +217,20 @@ void DwarfParser::parse_dwarf_instructions(uintptr_t begin, uintptr_t pc, const
_state.offset_from_cfa[reg] = _initial_state.offset_from_cfa[reg];
break;
}
#ifdef __aarch64__
// SA hasn't yet supported Pointer Authetication Code (PAC), so following
// instructions would be ignored with warning message.
// https://github.com/ARM-software/abi-aa/blob/2025Q4/aadwarf64/aadwarf64.rst
case 0x2d: // DW_CFA_AARCH64_negate_ra_state
print_debug("DWARF: DW_CFA_AARCH64_negate_ra_state is unimplemented.\n", op);
break;
case 0x2c: // DW_CFA_AARCH64_negate_ra_state_with_pc
print_debug("DWARF: DW_CFA_AARCH64_negate_ra_state_with_pc is unimplemented.\n", op);
break;
case 0x2b: // DW_CFA_AARCH64_set_ra_state
print_debug("DWARF: DW_CFA_AARCH64_set_ra_state is unimplemented.\n", op);
break;
#endif
default:
print_debug("DWARF: Unknown opcode: 0x%x\n", op);
return;

View File

@ -30,30 +30,21 @@
#include "libproc_impl.h"
/*
* from System V Application Binary Interface
* AMD64 Architecture Processor Supplement
* Figure 3.38: DWARF Register Number Mapping
* https://software.intel.com/sites/default/files/article/402129/mpx-linux64-abi.pdf
*/
#ifdef __x86_64__
#include "dwarf_regs_amd64.h"
#elif defined(__aarch64__)
#include "dwarf_regs_aarch64.h"
#endif
enum DWARF_Register {
RAX,
RDX,
RCX,
RBX,
RSI,
RDI,
RBP,
RSP,
R8,
R9,
R10,
R11,
R12,
R13,
R14,
R15,
RA,
// DWARF_REG macro is used by DWARF_REGLIST and DWARF_PSEUDO_REGLIST.
#define DWARF_REG(reg, no) \
reg = no,
DWARF_REGLIST
DWARF_PSEUDO_REGLIST
#undef DWARF_REG
MAX_VALUE
};
@ -94,6 +85,7 @@ class DwarfParser {
bool process_dwarf(const uintptr_t pc);
enum DWARF_Register get_cfa_register() { return _state.cfa_reg; }
int get_cfa_offset() { return _state.cfa_offset; }
enum DWARF_Register get_ra_register() { return _state.return_address_reg; }
int get_offset_from_cfa(enum DWARF_Register reg) { return _state.offset_from_cfa[reg]; }
bool is_in(long pc) {

View File

@ -0,0 +1,78 @@
/*
* Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2026, NTT DATA.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef DWARF_REGS_AARCH64_H
#define DWARF_REGS_AARCH64_H
#define THREAD_CONTEXT_CLASS "sun/jvm/hotspot/debugger/aarch64/AARCH64ThreadContext"
/*
* from DWARF for the Arm (R) 64-bit Architecture (AArch64)
* https://github.com/ARM-software/abi-aa/blob/2025Q4/aadwarf64/aadwarf64.rst
* 4.1 DWARF register names
*/
#define DWARF_REGLIST \
DWARF_REG(R0, 0) \
DWARF_REG(R1, 1) \
DWARF_REG(R2, 2) \
DWARF_REG(R3, 3) \
DWARF_REG(R4, 4) \
DWARF_REG(R5, 5) \
DWARF_REG(R6, 6) \
DWARF_REG(R7, 7) \
DWARF_REG(R8, 8) \
DWARF_REG(R9, 9) \
DWARF_REG(R10, 10) \
DWARF_REG(R11, 11) \
DWARF_REG(R12, 12) \
DWARF_REG(R13, 13) \
DWARF_REG(R14, 14) \
DWARF_REG(R15, 15) \
DWARF_REG(R16, 16) \
DWARF_REG(R17, 17) \
DWARF_REG(R18, 18) \
DWARF_REG(R19, 19) \
DWARF_REG(R20, 20) \
DWARF_REG(R21, 21) \
DWARF_REG(R22, 22) \
DWARF_REG(R23, 23) \
DWARF_REG(R24, 24) \
DWARF_REG(R25, 25) \
DWARF_REG(R26, 26) \
DWARF_REG(R27, 27) \
DWARF_REG(R28, 28) \
DWARF_REG(FP, 29) \
DWARF_REG(LR, 30) \
DWARF_REG(SP, 31) \
DWARF_REG(PC, 32)
// RA_SIGN_STATE might be needed in future to handle PAC.
#define DWARF_PSEUDO_REGLIST
/* Aliases */
#define BP FP
#define RA LR
#endif

View File

@ -0,0 +1,61 @@
/*
* Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2026, NTT DATA.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef DWARF_REGS_AMD64_H
#define DWARF_REGS_AMD64_H
#define THREAD_CONTEXT_CLASS "sun/jvm/hotspot/debugger/amd64/AMD64ThreadContext"
/*
* from System V Application Binary Interface
* AMD64 Architecture Processor Supplement
* https://refspecs.linuxbase.org/elf/x86_64-abi-0.99.pdf
* Figure 3.36: DWARF Register Number Mapping
*/
#define DWARF_REGLIST \
DWARF_REG(RAX, 0) \
DWARF_REG(RDX, 1) \
DWARF_REG(RCX, 2) \
DWARF_REG(RBX, 3) \
DWARF_REG(RSI, 4) \
DWARF_REG(RDI, 5) \
DWARF_REG(RBP, 6) \
DWARF_REG(RSP, 7) \
DWARF_REG(R8, 8) \
DWARF_REG(R9, 9) \
DWARF_REG(R10, 10) \
DWARF_REG(R11, 11) \
DWARF_REG(R12, 12) \
DWARF_REG(R13, 13) \
DWARF_REG(R14, 14) \
DWARF_REG(R15, 15)
#define DWARF_PSEUDO_REGLIST \
DWARF_REG(RA, 16)
/* Aliases */
#define BP RBP
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2022, 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
@ -119,6 +119,10 @@ struct ps_prochandle* get_proc_handle(JNIEnv* env, jobject this_obj);
void throw_new_debugger_exception(JNIEnv* env, const char* errMsg);
#ifdef __aarch64__
bool pac_enabled(struct ps_prochandle* ph);
#endif
#ifdef __cplusplus
}
#endif

View File

@ -478,6 +478,12 @@ struct lib_info *find_lib_by_address(struct ps_prochandle* ph, uintptr_t pc) {
return NULL;
}
#ifdef __aarch64__
bool pac_enabled(struct ps_prochandle* ph) {
return ph->pac_enabled;
}
#endif
//--------------------------------------------------------------------------
// proc service functions

View File

@ -115,6 +115,10 @@ struct ps_prochandle {
int num_threads;
thread_info* threads; // head of thread list
struct core_data* core; // data only used for core dumps, NULL for process
#ifdef __aarch64__
// true if the HWCAP_PACA variant of Pointer Authentication Code (PAC) is enabled.
bool pac_enabled;
#endif
};
#ifdef __cplusplus

View File

@ -39,6 +39,12 @@
#include "proc_service.h"
#include "salibelf.h"
// HWCAP_PACA was introduced in glibc 2.30
// https://sourceware.org/git/?p=glibc.git;a=commit;h=a2e57f89a35e6056c9488428e68c4889e114ef71
#if defined(__aarch64__) && !defined(HWCAP_PACA)
#define HWCAP_PACA (1 << 30)
#endif
// This file has the libproc implementation to read core files.
// For live processes, refer to ps_proc.c. Portions of this is adapted
// /modelled after Solaris libproc.so (in particular Pcore.c)
@ -290,6 +296,10 @@ static bool core_handle_note(struct ps_prochandle* ph, ELF_PHDR* note_phdr) {
break;
} else if (auxv->a_type == AT_SYSINFO_EHDR) {
ph->core->vdso_addr = auxv->a_un.a_val;
#ifdef __aarch64__
} else if (auxv->a_type == AT_HWCAP) {
ph->pac_enabled = auxv->a_un.a_val & HWCAP_PACA;
#endif
}
auxv++;
}
@ -610,23 +620,38 @@ static uintptr_t calc_prelinked_load_address(struct ps_prochandle* ph, int lib_f
return load_addr;
}
static int handle_vdso_internal(struct ps_prochandle* ph, char* vdso_name, char* lib_name, size_t lib_name_len) {
int lib_fd;
struct utsname uts;
uname(&uts);
char *vdso_path = (char*)malloc(lib_name_len);
snprintf(vdso_path, lib_name_len, "/lib/modules/%s/vdso/%s", uts.release, vdso_name);
print_debug("Try to open vDSO: %s\n", vdso_path);
lib_fd = pathmap_open(vdso_path);
if (lib_fd != -1) {
print_debug("replace vDSO: %s -> %s\n", lib_name, vdso_path);
strncpy(lib_name, vdso_path, lib_name_len);
}
free(vdso_path);
return lib_fd;
}
// Check for vDSO binary in kernel directory (/lib/modules/<version>/vdso),
// rewrite the given lib_name string if found.
// Otherwise copy vDSO memory in coredump to temporal file generated by tmpfile().
// Returns FD for vDSO (should be closed by caller), or -1 on error.
static int handle_vdso(struct ps_prochandle* ph, char* lib_name, size_t lib_name_len) {
int lib_fd;
struct utsname uts;
uname(&uts);
// Check vDSO binary first (for referring debuginfo if possible).
char *vdso_path = (char*)malloc(lib_name_len);
snprintf(vdso_path, lib_name_len, "/lib/modules/%s/vdso/vdso64.so", uts.release);
lib_fd = pathmap_open(vdso_path);
if (lib_fd != -1) {
print_debug("replace vDSO: %s -> %s\n", lib_name, vdso_path);
strncpy(lib_name, vdso_path, lib_name_len);
} else {
lib_fd = handle_vdso_internal(ph, "vdso64.so", lib_name, lib_name_len);
if (lib_fd == -1) {
// Try again with vdso.so
lib_fd = handle_vdso_internal(ph, "vdso.so", lib_name, lib_name_len);
}
if (lib_fd == -1) {
// Copy vDSO memory segment from core to temporal memory
// if vDSO binary is not available.
FILE* tmpf = tmpfile();
@ -644,7 +669,6 @@ static int handle_vdso(struct ps_prochandle* ph, char* lib_name, size_t lib_name
}
}
free(vdso_path);
return lib_fd;
}

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
@ -36,6 +36,17 @@
#include <sys/uio.h>
#include "libproc_impl.h"
#ifdef __aarch64__
#include <sys/auxv.h>
// HWCAP_PACA was introduced in glibc 2.30
// https://sourceware.org/git/?p=glibc.git;a=commit;h=a2e57f89a35e6056c9488428e68c4889e114ef71
#ifndef HWCAP_PACA
#define HWCAP_PACA (1 << 30)
#endif
#endif
#if defined(x86_64) && !defined(amd64)
#define amd64 1
#endif
@ -460,6 +471,10 @@ Pgrab(pid_t pid, char* err_buf, size_t err_buf_len) {
return NULL;
}
#ifdef __aarch64__
ph->pac_enabled = HWCAP_PACA & getauxval(AT_HWCAP);
#endif
// initialize ps_prochandle
ph->pid = pid;
if (add_thread_info(ph, ph->pid) == NULL) {

View File

@ -417,10 +417,14 @@ static struct symtab* build_symtab_internal(int fd, const char *filename, bool t
uintptr_t sym_value;
char *sym_name = symtab->strs + syms->st_name;
// skip non-object and non-function symbols
// skip non-object and non-function symbols, but STT_NOTYPE is allowed for
// signal trampoline.
int st_type = ELF_ST_TYPE(syms->st_info);
if ( st_type != STT_FUNC && st_type != STT_OBJECT)
if (st_type != STT_FUNC &&
st_type != STT_OBJECT &&
st_type != STT_NOTYPE) {
continue;
}
// skip empty strings and undefined symbols
if (*sym_name == '\0' || syms->st_shndx == SHN_UNDEF) continue;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -39,7 +39,7 @@ public interface CFrame {
public CFrame sender(ThreadProxy th);
/** Find sender frame with given FP and PC */
public default CFrame sender(ThreadProxy th, Address sp, Address fp, Address pc) {
public default CFrame sender(ThreadProxy th, Address senderSP, Address senderFP, Address senderPC) {
return sender(th);
}

View File

@ -0,0 +1,187 @@
/*
* Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2026, NTT DATA.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
package sun.jvm.hotspot.debugger.linux;
import sun.jvm.hotspot.debugger.Address;
import sun.jvm.hotspot.debugger.ThreadProxy;
import sun.jvm.hotspot.debugger.UnalignedAddressException;
import sun.jvm.hotspot.debugger.UnmappedAddressException;
import sun.jvm.hotspot.debugger.cdbg.CFrame;
import sun.jvm.hotspot.debugger.cdbg.ClosestSymbol;
import sun.jvm.hotspot.debugger.cdbg.basic.BasicCFrame;
import sun.jvm.hotspot.runtime.VM;
public class DwarfCFrame extends BasicCFrame {
private Address sp;
private Address fp;
private Address pc;
private Address cfa;
private LinuxDebugger linuxDbg;
private DwarfParser dwarf;
private boolean use1ByteBeforeToLookup;
/**
* @return DwarfParser instance for the PC, null if native library relates to the pc not found.
* @throws DebuggerException if DWARF processing is failed.
* For example: pc is not covered in this DWARF, Common Information Entry (CIE) has
* language personality routine and/or Language Data Area (LSDA).
*/
protected static DwarfParser createDwarfParser(LinuxDebugger linuxDbg, Address pc) {
Address libptr = linuxDbg.findLibPtrByAddress(pc);
if (libptr != null) {
DwarfParser dwarf = new DwarfParser(libptr);
dwarf.processDwarf(pc);
return dwarf;
}
return null;
}
protected DwarfCFrame(LinuxDebugger linuxDbg, Address sp, Address fp, Address cfa, Address pc, DwarfParser dwarf) {
this(linuxDbg, sp, fp, cfa, pc, dwarf, false);
}
protected DwarfCFrame(LinuxDebugger linuxDbg, Address sp, Address fp, Address cfa, Address pc, DwarfParser dwarf, boolean use1ByteBeforeToLookup) {
super(linuxDbg.getCDebugger());
this.sp = sp;
this.fp = fp;
this.cfa = cfa;
this.pc = pc;
this.linuxDbg = linuxDbg;
this.dwarf = dwarf;
this.use1ByteBeforeToLookup = use1ByteBeforeToLookup;
}
public Address sp() {
return sp;
}
public Address fp() {
return fp;
}
public Address pc() {
return pc;
}
public LinuxDebugger linuxDbg() {
return linuxDbg;
}
public DwarfParser dwarf() {
return dwarf;
}
// override base class impl to avoid ELF parsing
@Override
public ClosestSymbol closestSymbolToPC() {
Address symAddr = use1ByteBeforeToLookup ? pc.addOffsetTo(-1) : pc;
var sym = linuxDbg.lookup(linuxDbg.getAddressValue(symAddr));
// Returns a special symbol if the address is signal trampoline,
// otherwise returns closest symbol generated by LinuxDebugger.
return linuxDbg.isSignalTrampoline(symAddr)
? new ClosestSymbol(sym.getName() + " <signal trampoline>", 0)
: sym;
}
@Override
public Address localVariableBase() {
return (dwarf != null && dwarf.isBPOffsetAvailable())
? cfa.addOffsetTo(dwarf.getBasePointerOffsetFromCFA())
: fp;
}
protected boolean isValidFrame(Address senderCFA, Address senderFP) {
// Both CFA and FP must not be null.
if (senderCFA == null && senderFP == null) {
return false;
}
// FP must not be null if CFA is null - it happens between Java frame and Native frame.
// We cannot validate FP value because it might be used as GPR. Thus returns true
// if FP is not null.
if (senderCFA == null && senderFP != null) {
return true;
}
// senderCFA must be greater than current CFA.
if (senderCFA != null && senderCFA.greaterThanOrEqual(cfa)) {
return true;
}
// Otherwise, the frame is not valid.
return false;
}
protected Address getSenderPC(Address senderPC) {
if (senderPC != null) {
return senderPC;
}
try {
return dwarf == null
? fp.getAddressAt(VM.getVM().getAddressSize()) // Current frame is Java
: cfa.getAddressAt(dwarf.getReturnAddressOffsetFromCFA()); // current frame is Native
} catch (UnmappedAddressException | UnalignedAddressException _) {
// Sender PC is invalid - maybe bottom of stack
return null;
}
}
protected Address getSenderSP(Address senderSP) {
if (senderSP != null) {
return senderSP;
} else if (dwarf == null) {
// Current frame is Java - skip saved BP and RA
return fp.addOffsetTo(2 * VM.getVM().getAddressSize());
} else {
// Current frame is Native
// CFA points SP at the call site in the previous frame.
// See 6.4 Call Frame Information in DWARF Debugging Information Format
// https://dwarfstd.org/dwarf4std.html
return cfa;
}
}
protected Address getSenderFP(Address senderFP) {
if (senderFP != null) {
return senderFP;
} else if (dwarf == null) { // Current frame is Java
return fp.getAddressAt(0);
} else { // Current frame is Native
return dwarf.isBPOffsetAvailable()
? cfa.getAddressAt(dwarf.getBasePointerOffsetFromCFA())
: fp;
}
}
@Override
public CFrame sender(ThreadProxy th) {
return sender(th, null, null, null);
}
}

View File

@ -23,7 +23,7 @@
*
*/
package sun.jvm.hotspot.debugger.linux.amd64;
package sun.jvm.hotspot.debugger.linux;
import java.lang.ref.Cleaner;
import sun.jvm.hotspot.debugger.Address;
@ -75,6 +75,8 @@ public class DwarfParser {
public native int getCFARegister();
public native int getCFAOffset();
public native int getOffsetFromCFA(int sareg);
public native int getRARegister();
public native int getReturnAddressOffsetFromCFA();
public native int getBasePointerOffsetFromCFA();
}

View File

@ -91,13 +91,7 @@ class LinuxCDebugger implements CDebugger {
return new LinuxPPC64CFrame(dbg, sp, pc, LinuxDebuggerLocal.getAddressSize());
} else if (cpu.equals("aarch64")) {
AARCH64ThreadContext context = (AARCH64ThreadContext) thread.getContext();
Address sp = context.getRegisterAsAddress(AARCH64ThreadContext.SP);
if (sp == null) return null;
Address fp = context.getRegisterAsAddress(AARCH64ThreadContext.FP);
if (fp == null) return null;
Address pc = context.getRegisterAsAddress(AARCH64ThreadContext.PC);
if (pc == null) return null;
return new LinuxAARCH64CFrame(dbg, sp, fp, pc);
return LinuxAARCH64CFrame.getTopFrame(dbg, context);
} else if (cpu.equals("riscv64")) {
RISCV64ThreadContext context = (RISCV64ThreadContext) thread.getContext();
Address sp = context.getRegisterAsAddress(RISCV64ThreadContext.SP);

View File

@ -33,12 +33,17 @@ import sun.jvm.hotspot.debugger.cdbg.*;
by the architecture-specific subpackages. */
public interface LinuxDebugger extends JVMDebugger {
// SIGHANDLER_NAMES holds the name of signal handler.
public static final List<String> SIGHANDLER_NAMES = List.of(
// SIGTRAMP_NAMES holds the name of signal trampoline.
public static final List<String> SIGTRAMP_NAMES = List.of(
// For AMD64
// - sysdeps/unix/sysv/linux/x86_64/libc_sigaction.c in glibc
// - gdb/amd64-linux-tdep.c in GDB
"__restore_rt"
"__restore_rt",
// For AArch64
// - arch/arm64/kernel/vdso/vdso.lds.S in Linux kernel
"__kernel_rt_sigreturn",
"VDSO_sigtramp"
);
public String addressValueToString(long address) throws DebuggerException;

View File

@ -133,7 +133,7 @@ public class LinuxDebuggerLocal extends DebuggerBase implements LinuxDebugger {
@Override
public boolean isSignalTrampoline(Address pc) {
var sym = lookup(getAddressValue(pc));
return sym == null ? false : SIGHANDLER_NAMES.contains(sym.getName());
return sym == null ? false : SIGTRAMP_NAMES.contains(sym.getName());
}
// Note on Linux threads are really processes. When target process is

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.
* Copyright (c) 2015, Red Hat Inc.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@ -25,73 +25,109 @@
package sun.jvm.hotspot.debugger.linux.aarch64;
import java.util.function.Function;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.debugger.aarch64.*;
import sun.jvm.hotspot.debugger.linux.*;
import sun.jvm.hotspot.debugger.cdbg.*;
import sun.jvm.hotspot.debugger.cdbg.basic.*;
import sun.jvm.hotspot.code.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.runtime.aarch64.*;
public final class LinuxAARCH64CFrame extends BasicCFrame {
public LinuxAARCH64CFrame(LinuxDebugger dbg, Address sp, Address fp, Address pc) {
super(dbg.getCDebugger());
this.sp = sp;
this.fp = fp;
this.pc = pc;
this.dbg = dbg;
public final class LinuxAARCH64CFrame extends DwarfCFrame {
private Address lr;
private static LinuxAARCH64CFrame getFrameFromReg(LinuxDebugger linuxDbg, Function<Integer, Address> getreg) {
Address pc = getreg.apply(AARCH64ThreadContext.PC);
Address sp = getreg.apply(AARCH64ThreadContext.SP);
Address fp = getreg.apply(AARCH64ThreadContext.FP);
Address lr = getreg.apply(AARCH64ThreadContext.LR);
Address cfa = null;
DwarfParser dwarf = createDwarfParser(linuxDbg, pc);
if (dwarf != null) { // Native frame
cfa = getreg.apply(dwarf.getCFARegister())
.addOffsetTo(dwarf.getCFAOffset());
}
return (fp == null && cfa == null)
? null
: new LinuxAARCH64CFrame(linuxDbg, sp, fp, cfa, pc, lr, dwarf);
}
// override base class impl to avoid ELF parsing
public ClosestSymbol closestSymbolToPC() {
// try native lookup in debugger.
return dbg.lookup(dbg.getAddressValue(pc()));
public static LinuxAARCH64CFrame getTopFrame(LinuxDebugger linuxDbg, ThreadContext context) {
return getFrameFromReg(linuxDbg, context::getRegisterAsAddress);
}
public Address pc() {
return pc;
private LinuxAARCH64CFrame(LinuxDebugger linuxDbg, Address sp, Address fp, Address cfa, Address pc, Address lr, DwarfParser dwarf) {
this(linuxDbg, sp, fp, cfa, pc, lr, dwarf, false);
}
public Address localVariableBase() {
return fp;
private LinuxAARCH64CFrame(LinuxDebugger linuxDbg, Address sp, Address fp, Address cfa, Address pc, DwarfParser dwarf) {
this(linuxDbg, sp, fp, cfa, pc, null, dwarf, false);
}
@Override
public CFrame sender(ThreadProxy thread) {
return sender(thread, null, null, null);
private LinuxAARCH64CFrame(LinuxDebugger linuxDbg, Address sp, Address fp, Address cfa, Address pc, DwarfParser dwarf, boolean use1ByteBeforeToLookup) {
this(linuxDbg, sp, fp, cfa, pc, null, dwarf, use1ByteBeforeToLookup);
}
@Override
public CFrame sender(ThreadProxy thread, Address nextSP, Address nextFP, Address nextPC) {
// Check fp
// Skip if both nextFP and nextPC are given - do not need to load from fp.
if (nextFP == null && nextPC == null) {
if (fp == null) {
return null;
private LinuxAARCH64CFrame(LinuxDebugger linuxDbg, Address sp, Address fp, Address cfa, Address pc, Address lr, DwarfParser dwarf, boolean use1ByteBeforeToLookup) {
super(linuxDbg, sp, fp, cfa, pc, dwarf, use1ByteBeforeToLookup);
if (dwarf != null) {
// Prioritize to use RA from DWARF instead of LR
var senderPCFromDwarf = getSenderPC(null);
if (senderPCFromDwarf != null) {
lr = senderPCFromDwarf;
} else if (lr != null) {
// We should set passed lr to LR of this frame,
// but throws DebuggerException if lr is not used for RA.
var raReg = dwarf.getRARegister();
if (raReg != AARCH64ThreadContext.LR) {
throw new DebuggerException("Unexpected RA register: " + raReg);
}
}
}
// Check alignment of fp
if (dbg.getAddressValue(fp) % (2 * ADDRESS_SIZE) != 0) {
this.lr = lr;
}
private Address getSenderCFA(DwarfParser senderDwarf, Address senderSP, Address senderFP) {
if (senderDwarf == null) { // Sender frame is Java
// CFA is not available on Java frame
return null;
}
// Sender frame is Native
int senderCFAReg = senderDwarf.getCFARegister();
return switch(senderCFAReg){
case AARCH64ThreadContext.FP -> senderFP.addOffsetTo(senderDwarf.getCFAOffset());
case AARCH64ThreadContext.SP -> senderSP.addOffsetTo(senderDwarf.getCFAOffset());
default -> throw new DebuggerException("Unsupported CFA register: " + senderCFAReg);
};
}
@Override
public CFrame sender(ThreadProxy thread, Address senderSP, Address senderFP, Address senderPC) {
if (linuxDbg().isSignalTrampoline(pc())) {
// SP points signal context
// https://github.com/torvalds/linux/blob/v6.17/arch/arm64/kernel/signal.c#L1357
return getFrameFromReg(linuxDbg(), r -> LinuxAARCH64ThreadContext.getRegFromSignalTrampoline(sp(), r.intValue()));
}
if (senderPC == null) {
// Use getSenderPC() if current frame is Java because we cannot rely on lr in this case.
senderPC = dwarf() == null ? getSenderPC(null) : lr;
if (senderPC == null) {
return null;
}
}
if (nextFP == null) {
nextFP = fp.getAddressAt(0 * ADDRESS_SIZE);
}
if (nextFP == null) {
return null;
}
senderFP = getSenderFP(senderFP);
if (nextPC == null) {
nextPC = fp.getAddressAt(1 * ADDRESS_SIZE);
}
if (nextPC == null) {
return null;
}
if (nextSP == null) {
if (senderSP == null) {
CodeCache cc = VM.getVM().getCodeCache();
CodeBlob currentBlob = cc.findBlobUnsafe(pc());
@ -99,29 +135,62 @@ public final class LinuxAARCH64CFrame extends BasicCFrame {
if (currentBlob != null && (currentBlob.isContinuationStub() || currentBlob.isNativeMethod())) {
// Use FP since it should always be valid for these cases.
// TODO: These should be walked as Frames not CFrames.
nextSP = fp.addOffsetTo(2 * ADDRESS_SIZE);
senderSP = fp().addOffsetTo(2 * VM.getVM().getAddressSize());
} else {
CodeBlob codeBlob = cc.findBlobUnsafe(nextPC);
CodeBlob codeBlob = cc.findBlobUnsafe(senderPC);
boolean useCodeBlob = codeBlob != null && codeBlob.getFrameSize() > 0;
nextSP = useCodeBlob ? nextFP.addOffsetTo((2 * ADDRESS_SIZE) - codeBlob.getFrameSize()) : nextFP;
senderSP = useCodeBlob ? senderFP.addOffsetTo((2 * VM.getVM().getAddressSize()) - codeBlob.getFrameSize()) : getSenderSP(null);
}
}
if (nextSP == null) {
if (senderSP == null) {
return null;
}
return new LinuxAARCH64CFrame(dbg, nextSP, nextFP, nextPC);
DwarfParser senderDwarf = null;
boolean fallback = false;
try {
senderDwarf = createDwarfParser(linuxDbg(), senderPC);
} catch (DebuggerException _) {
// Try again with PC-1 in case PC is just outside function bounds,
// due to function ending with a `call` instruction.
try {
senderDwarf = createDwarfParser(linuxDbg(), senderPC.addOffsetTo(-1));
fallback = true;
} catch (DebuggerException _) {
if (linuxDbg().isSignalTrampoline(senderPC)) {
// We can use the caller frame if it is a signal trampoline.
// DWARF processing might fail because vdso.so .eh_frame is not required on aarch64.
return new LinuxAARCH64CFrame(linuxDbg(), senderSP, senderFP, null, senderPC, senderDwarf);
}
// DWARF processing should succeed when the frame is native
// but it might fail if Common Information Entry (CIE) has language
// personality routine and/or Language Specific Data Area (LSDA).
return null;
}
}
try {
Address senderCFA = getSenderCFA(senderDwarf, senderSP, senderFP);
return isValidFrame(senderCFA, senderFP)
? new LinuxAARCH64CFrame(linuxDbg(), senderSP, senderFP, senderCFA, senderPC, senderDwarf, fallback)
: null;
} catch (DebuggerException e) {
if (linuxDbg().isSignalTrampoline(senderPC)) {
// We can use the caller frame if it is a signal trampoline.
// getSenderCFA() might fail because DwarfParser cannot find out CFA register.
return new LinuxAARCH64CFrame(linuxDbg(), senderSP, senderFP, null, senderPC, senderDwarf, fallback);
}
// Rethrow the original exception if getSenderCFA() failed
// and the caller is not signal trampoline.
throw e;
}
}
@Override
public Frame toFrame() {
return new AARCH64Frame(sp, fp, pc);
return new AARCH64Frame(sp(), fp(), pc());
}
// package/class internals only
private static final int ADDRESS_SIZE = 8;
private Address pc;
private Address sp;
private Address fp;
private LinuxDebugger dbg;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2026, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, Red Hat Inc.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@ -28,6 +28,7 @@ package sun.jvm.hotspot.debugger.linux.aarch64;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.debugger.aarch64.*;
import sun.jvm.hotspot.debugger.linux.*;
import sun.jvm.hotspot.runtime.*;
public class LinuxAARCH64ThreadContext extends AARCH64ThreadContext {
private LinuxDebugger debugger;
@ -44,4 +45,24 @@ public class LinuxAARCH64ThreadContext extends AARCH64ThreadContext {
public Address getRegisterAsAddress(int index) {
return debugger.newAddress(getRegister(index));
}
public static Address getRegFromSignalTrampoline(Address sp, int index) {
// ucontext_t locates at 2nd element of rt_sigframe.
// See definition of rt_sigframe in arch/arm/kernel/signal.h
// in Linux Kernel.
Address addrUContext = sp.addOffsetTo(128); // sizeof(siginfo_t) = 128
Address addrUCMContext = addrUContext.addOffsetTo(176); // offsetof(ucontext_t, uc_mcontext) = 176
Address ptrCallerSP = addrUCMContext.addOffsetTo(256); // offsetof(uc_mcontext, sp) = 256
Address ptrCallerPC = addrUCMContext.addOffsetTo(264); // offsetof(uc_mcontext, pc) = 264
Address ptrCallerRegs = addrUCMContext.addOffsetTo(8); // offsetof(uc_mcontext, regs) = 8
return switch(index) {
case AARCH64ThreadContext.FP -> ptrCallerRegs.getAddressAt(AARCH64ThreadContext.FP * VM.getVM().getAddressSize());
case AARCH64ThreadContext.LR -> ptrCallerRegs.getAddressAt(AARCH64ThreadContext.LR * VM.getVM().getAddressSize());
case AARCH64ThreadContext.SP -> ptrCallerSP.getAddressAt(0);
case AARCH64ThreadContext.PC -> ptrCallerPC.getAddressAt(0);
default -> throw new IllegalArgumentException("Unsupported register index: " + index);
};
}
}

View File

@ -29,181 +29,82 @@ import java.util.function.Function;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.debugger.amd64.*;
import sun.jvm.hotspot.debugger.linux.*;
import sun.jvm.hotspot.debugger.linux.amd64.*;
import sun.jvm.hotspot.debugger.cdbg.*;
import sun.jvm.hotspot.debugger.cdbg.basic.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.runtime.amd64.*;
public final class LinuxAMD64CFrame extends BasicCFrame {
public final class LinuxAMD64CFrame extends DwarfCFrame {
private static LinuxAMD64CFrame getFrameFromReg(LinuxDebugger dbg, Function<Integer, Address> getreg) {
private static LinuxAMD64CFrame getFrameFromReg(LinuxDebugger linuxDbg, Function<Integer, Address> getreg) {
Address rip = getreg.apply(AMD64ThreadContext.RIP);
Address rsp = getreg.apply(AMD64ThreadContext.RSP);
Address rbp = getreg.apply(AMD64ThreadContext.RBP);
Address libptr = dbg.findLibPtrByAddress(rip);
Address cfa = null;
DwarfParser dwarf = null;
if (libptr != null) { // Native frame
dwarf = new DwarfParser(libptr);
try {
dwarf.processDwarf(rip);
} catch (DebuggerException e) {
// DWARF processing should succeed when the frame is native
// but it might fail if Common Information Entry (CIE) has language
// personality routine and/or Language Specific Data Area (LSDA).
return new LinuxAMD64CFrame(dbg, rsp, rbp, cfa, rip, dwarf, true);
}
DwarfParser dwarf = createDwarfParser(linuxDbg, rip);
if (dwarf != null) { // Native frame
cfa = getreg.apply(dwarf.getCFARegister())
.addOffsetTo(dwarf.getCFAOffset());
}
return (rbp == null && cfa == null)
? null
: new LinuxAMD64CFrame(dbg, rsp, rbp, cfa, rip, dwarf);
: new LinuxAMD64CFrame(linuxDbg, rsp, rbp, cfa, rip, dwarf);
}
public static LinuxAMD64CFrame getTopFrame(LinuxDebugger dbg, ThreadContext context) {
return getFrameFromReg(dbg, context::getRegisterAsAddress);
public static LinuxAMD64CFrame getTopFrame(LinuxDebugger linuxDbg, ThreadContext context) {
return getFrameFromReg(linuxDbg, context::getRegisterAsAddress);
}
private LinuxAMD64CFrame(LinuxDebugger dbg, Address rsp, Address rbp, Address cfa, Address rip, DwarfParser dwarf) {
this(dbg, rsp, rbp, cfa, rip, dwarf, false);
private LinuxAMD64CFrame(LinuxDebugger linuxDbg, Address rsp, Address rbp, Address cfa, Address rip, DwarfParser dwarf) {
this(linuxDbg, rsp, rbp, cfa, rip, dwarf, false);
}
private LinuxAMD64CFrame(LinuxDebugger dbg, Address rsp, Address rbp, Address cfa, Address rip, DwarfParser dwarf, boolean use1ByteBeforeToLookup) {
super(dbg.getCDebugger());
this.rsp = rsp;
this.rbp = rbp;
this.cfa = cfa;
this.rip = rip;
this.dbg = dbg;
this.dwarf = dwarf;
this.use1ByteBeforeToLookup = use1ByteBeforeToLookup;
private LinuxAMD64CFrame(LinuxDebugger linuxDbg, Address rsp, Address rbp, Address cfa, Address rip, DwarfParser dwarf, boolean use1ByteBeforeToLookup) {
super(linuxDbg, rsp, rbp, cfa, rip, dwarf, use1ByteBeforeToLookup);
}
// override base class impl to avoid ELF parsing
public ClosestSymbol closestSymbolToPC() {
Address symAddr = use1ByteBeforeToLookup ? pc().addOffsetTo(-1) : pc();
var sym = dbg.lookup(dbg.getAddressValue(symAddr));
// Returns a special symbol if the address is signal handler,
// otherwise returns closest symbol generated by LinuxDebugger.
return dbg.isSignalTrampoline(symAddr)
? new ClosestSymbol(sym.getName() + " <signal trampoline>", 0)
: sym;
}
public Address pc() {
return rip;
}
public Address localVariableBase() {
return (dwarf != null && dwarf.isBPOffsetAvailable())
? cfa.addOffsetTo(dwarf.getBasePointerOffsetFromCFA())
: rbp;
}
private Address getNextPC() {
try {
return dwarf == null
? rbp.getAddressAt(ADDRESS_SIZE) // Java frame
: cfa.getAddressAt(dwarf.getReturnAddressOffsetFromCFA()); // Native frame
} catch (UnmappedAddressException | UnalignedAddressException e) {
return null;
}
}
private boolean isValidFrame(Address nextCFA, Address nextRBP) {
// Both CFA and RBP must not be null.
if (nextCFA == null && nextRBP == null) {
return false;
}
// RBP must not be null if CFA is null - it happens between Java frame and Native frame.
// We cannot validate RBP value because it might be used as GPR. Thus returns true
// if RBP is not null.
if (nextCFA == null && nextRBP != null) {
return true;
}
// nextCFA must be greater than current CFA.
if (nextCFA != null && nextCFA.greaterThanOrEqual(cfa)) {
return true;
}
// Otherwise, the frame is not valid.
return false;
}
private Address getNextRSP() {
return dwarf == null ? rbp.addOffsetTo(2 * ADDRESS_SIZE) // Java frame - skip saved BP and RA
: cfa.addOffsetTo(dwarf.getReturnAddressOffsetFromCFA())
.addOffsetTo(ADDRESS_SIZE); // Native frame
}
private Address getNextRBP(Address senderFP) {
if (senderFP != null) {
return senderFP;
} else if (dwarf == null) { // Current frame is Java
return rbp.getAddressAt(0);
} else { // Current frame is Native
return dwarf.isBPOffsetAvailable()
? cfa.getAddressAt(dwarf.getBasePointerOffsetFromCFA())
: rbp;
}
}
private Address getNextCFA(DwarfParser nextDwarf, Address senderFP, Address senderPC) {
if (nextDwarf == null) { // Next frame is Java
private Address getSenderCFA(DwarfParser senderDwarf, Address senderSP, Address senderFP) {
if (senderDwarf == null) { // Sender frame is Java
// CFA is not available on Java frame
return null;
}
// Next frame is Native
int nextCFAReg = nextDwarf.getCFARegister();
return switch(nextCFAReg){
case AMD64ThreadContext.RBP -> getNextRBP(senderFP).addOffsetTo(nextDwarf.getCFAOffset());
case AMD64ThreadContext.RSP -> getNextRSP().addOffsetTo(nextDwarf.getCFAOffset());
default -> throw new DebuggerException("Unsupported CFA register: " + nextCFAReg);
// Sender frame is Native
int senderCFAReg = senderDwarf.getCFARegister();
return switch(senderCFAReg){
case AMD64ThreadContext.RBP -> senderFP.addOffsetTo(senderDwarf.getCFAOffset());
case AMD64ThreadContext.RSP -> senderSP.addOffsetTo(senderDwarf.getCFAOffset());
default -> throw new DebuggerException("Unsupported CFA register: " + senderCFAReg);
};
}
@Override
public CFrame sender(ThreadProxy th) {
return sender(th, null, null, null);
}
@Override
public CFrame sender(ThreadProxy th, Address sp, Address fp, Address pc) {
if (dbg.isSignalTrampoline(pc())) {
public CFrame sender(ThreadProxy th, Address senderSP, Address senderFP, Address senderPC) {
if (linuxDbg().isSignalTrampoline(pc())) {
// RSP points signal context
// https://github.com/torvalds/linux/blob/v6.17/arch/x86/kernel/signal.c#L94
return getFrameFromReg(dbg, r -> LinuxAMD64ThreadContext.getRegFromSignalTrampoline(this.rsp, r.intValue()));
return getFrameFromReg(linuxDbg(), r -> LinuxAMD64ThreadContext.getRegFromSignalTrampoline(sp(), r.intValue()));
}
ThreadContext context = th.getContext();
Address nextRSP = sp != null ? sp : getNextRSP();
if (nextRSP == null) {
senderSP = getSenderSP(senderSP);
if (senderSP == null) {
return null;
}
Address nextPC = pc != null ? pc : getNextPC();
if (nextPC == null) {
senderPC = getSenderPC(senderPC);
if (senderPC == null) {
return null;
}
DwarfParser nextDwarf = null;
DwarfParser senderDwarf = null;
boolean fallback = false;
try {
nextDwarf = createDwarfParser(nextPC);
senderDwarf = createDwarfParser(linuxDbg(), senderPC);
} catch (DebuggerException _) {
// Try again with RIP-1 in case RIP is just outside function bounds,
// Try again with PC-1 in case PC is just outside function bounds,
// due to function ending with a `call` instruction.
try {
nextDwarf = createDwarfParser(nextPC.addOffsetTo(-1));
senderDwarf = createDwarfParser(linuxDbg(), senderPC.addOffsetTo(-1));
fallback = true;
} catch (DebuggerException _) {
// DWARF processing should succeed when the frame is native
@ -213,56 +114,29 @@ public final class LinuxAMD64CFrame extends BasicCFrame {
}
}
Address nextRBP = getNextRBP(fp);
senderFP = getSenderFP(senderFP);
try {
Address nextCFA = getNextCFA(nextDwarf, fp, nextPC);
return isValidFrame(nextCFA, nextRBP)
? new LinuxAMD64CFrame(dbg, nextRSP, nextRBP, nextCFA, nextPC, nextDwarf, fallback)
Address senderCFA = getSenderCFA(senderDwarf, senderSP, senderFP);
return isValidFrame(senderCFA, senderFP)
? new LinuxAMD64CFrame(linuxDbg(), senderSP, senderFP, senderCFA, senderPC, senderDwarf, fallback)
: null;
} catch (DebuggerException e) {
if (dbg.isSignalTrampoline(nextPC)) {
// We can through the caller frame if it is signal trampoline.
// getNextCFA() might fail because DwarfParser cannot find out CFA register.
return new LinuxAMD64CFrame(dbg, nextRSP, nextRBP, null, nextPC, nextDwarf, fallback);
if (linuxDbg().isSignalTrampoline(senderPC)) {
// We can use the caller frame if it is a signal trampoline.
// getSenderCFA() might fail because DwarfParser cannot find out CFA register.
return new LinuxAMD64CFrame(linuxDbg(), senderSP, senderFP, null, senderPC, senderDwarf, fallback);
}
// Rethrow the original exception if getNextCFA() failed
// Rethrow the original exception if getSenderCFA() failed
// and the caller is not signal trampoline.
throw e;
}
}
private DwarfParser createDwarfParser(Address pc) throws DebuggerException {
DwarfParser nextDwarf = null;
Address libptr = dbg.findLibPtrByAddress(pc);
if (libptr != null) {
try {
nextDwarf = new DwarfParser(libptr);
} catch (DebuggerException _) {
// Bail out to Java frame
}
}
if (nextDwarf != null) {
nextDwarf.processDwarf(pc);
}
return nextDwarf;
}
@Override
public Frame toFrame() {
return new AMD64Frame(rsp, localVariableBase(), rip);
return new AMD64Frame(sp(), localVariableBase(), pc());
}
// package/class internals only
private static final int ADDRESS_SIZE = 8;
private Address rsp;
private Address rbp;
private Address rip;
private Address cfa;
private LinuxDebugger dbg;
private DwarfParser dwarf;
private boolean use1ByteBeforeToLookup;
}

View File

@ -1246,7 +1246,11 @@ class ZipFileSystem extends FileSystem {
private LinkedHashMap<IndexNode, IndexNode> inodes;
final byte[] getBytes(String name) {
return zc.getBytes(name);
try {
return zc.getBytes(name);
} catch (IllegalArgumentException e) {
throw new InvalidPathException(name, "unmappable character in path name");
}
}
final String getString(byte[] name) {

View File

@ -58,6 +58,7 @@
and that causes invalid macro expansion.
*/
#undef aarch64
#undef arm
#include <capstone.h>
#include "hsdis.h"
@ -163,9 +164,9 @@ void* decode_instructions_virtual(uintptr_t start_va, uintptr_t end_va,
size_t count = cs_disasm(cs_handle, buffer, length, (uintptr_t) buffer, 0 , &insn);
if (count) {
for (unsigned int j = 0; j < count; j++) {
(*event_callback)(event_stream, "insn", (void*) insn[j].address);
(*event_callback)(event_stream, "insn", (void*)(uintptr_t) insn[j].address);
print("%s\t\t%s", insn[j].mnemonic, insn[j].op_str);
(*event_callback)(event_stream, "/insn", (void*) (insn[j].address + insn[j].size));
(*event_callback)(event_stream, "/insn", (void*)(uintptr_t) (insn[j].address + insn[j].size));
if (newline) {
/* follow each complete insn by a nice newline */
print("\n");

View File

@ -56,7 +56,6 @@ compiler/c2/irTests/TestDuplicateBackedge.java 8318904 generic-all
compiler/codecache/jmx/PoolsIndependenceTest.java 8264632 macosx-all
compiler/vectorapi/reshape/TestVectorReinterpret.java 8348519 linux-s390x
compiler/vectorapi/VectorRebracket128Test.java 8330538 generic-all
compiler/vectorization/TestVectorAlgorithms.java#noSuperWord 8376803 aix-ppc64,linux-s390x

View File

@ -0,0 +1,65 @@
/*
* Copyright (c) 2026 IBM Corporation. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* @test
* @bug 8380158
* @summary C2: compiler/c2/TestGVNCrash.java asserts with adr and adr_type must agree
* @run main/othervm -XX:-TieredCompilation -XX:-UseOnStackReplacement -XX:-BackgroundCompilation
* -XX:CompileOnly=compiler.arraycopy.TestACNonEscapingSrcBadAddPBaseType::test1
* -XX:+UnlockDiagnosticVMOptions -XX:+StressIGVN -XX:StressSeed=946074051 ${test.main.class}
* @run main/othervm -XX:-TieredCompilation -XX:-UseOnStackReplacement -XX:-BackgroundCompilation
* -XX:CompileOnly=compiler.arraycopy.TestACNonEscapingSrcBadAddPBaseType::test1
* -XX:+UnlockDiagnosticVMOptions -XX:+StressIGVN ${test.main.class}
* @run main ${test.main.class}
*/
package compiler.arraycopy;
public class TestACNonEscapingSrcBadAddPBaseType {
private static volatile int volatileField;
public static void main(String[] args) {
int[] dst = new int[2];
for (int i = 0; i < 20_000; i++) {
test1(dst);
}
}
private static void test1(int[] dst) {
int[] array = new int[2];
A a = new A(array);
volatileField = 42;
int[] src = a.src;
System.arraycopy(src, 0, dst, 0, src.length);
System.arraycopy(src, 0, dst, 0, src.length);
}
private static class A {
private final int[] src;
public A(int[] src) {
this.src = src;
}
}
}

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022 SAP SE. All rights reserved.ights reserved.
* Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2025 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -28,6 +28,7 @@
* @requires vm.compMode == "Xmixed"
* @requires vm.opt.TieredCompilation == null | vm.opt.TieredCompilation == true
* @requires vm.opt.TieredStopAtLevel == null | vm.opt.TieredStopAtLevel == 4
* @requires vm.compiler2.enabled
* @summary test allocation failure of method handle intrinsic in profiled/non-profiled space
* @library /test/lib
* @modules java.base/jdk.internal.misc
@ -39,6 +40,11 @@
* -XX:+WhiteBoxAPI -XX:CompileCommand=compileonly,null::*
* -XX:ReservedCodeCacheSize=16m -XX:+SegmentedCodeCache
* compiler.codecache.MHIntrinsicAllocFailureTest
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI -XX:CompileCommand=compileonly,null::*
* -XX:ReservedCodeCacheSize=20m -XX:+SegmentedCodeCache
* -XX:+TieredCompilation -XX:+UnlockExperimentalVMOptions -XX:+HotCodeHeap -XX:HotCodeHeapSize=4M
* compiler.codecache.MHIntrinsicAllocFailureTest
*/
package compiler.codecache;
@ -73,7 +79,7 @@ public class MHIntrinsicAllocFailureTest {
// JIT compilers should be off, now.
Asserts.assertNotEquals(WHITE_BOX.getCompilationActivityMode(), 1);
System.out.println("Code cache segments for non-profiled and profiled nmethods are full.");
// Generate and use a MH itrinsic. Should not trigger one of the following:
// Generate and use a MH intrinsic. Should not trigger one of the following:
// - VirtualMachineError: Out of space in CodeCache for method handle intrinsic
// - InternalError: java.lang.NoSuchMethodException: no such method:
// java.lang.invoke.MethodHandle.linkToStatic(int,int,Object,MemberName)int/invokeStatic

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -44,6 +44,27 @@
* compiler.codecache.OverflowCodeCacheTest
*/
/*
* @test OverflowCodeCacheTest
* @bug 8059550 8279356 8326205
* @requires vm.compiler2.enabled
* @summary testing of code cache segments overflow
* @library /test/lib
* @modules java.base/jdk.internal.misc
* java.management
*
* @build jdk.test.whitebox.WhiteBox
* @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI -XX:+TieredCompilation -XX:+UnlockExperimentalVMOptions -XX:+HotCodeHeap -XX:HotCodeHeapSize=8M
* -Xmixed -XX:TieredStopAtLevel=4
* compiler.codecache.OverflowCodeCacheTest
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI -XX:-TieredCompilation -XX:+UnlockExperimentalVMOptions -XX:+HotCodeHeap -XX:HotCodeHeapSize=8M
* -Xmixed -XX:TieredStopAtLevel=4
* compiler.codecache.OverflowCodeCacheTest
*/
package compiler.codecache;
import jdk.test.lib.Asserts;
@ -85,6 +106,7 @@ public class OverflowCodeCacheTest {
System.out.println("allocating till possible...");
ArrayList<Long> blobs = new ArrayList<>();
int compilationActivityMode = -1;
CodeCacheConstraints constraints = getCodeCacheConstraints(type);
// Lock compilation to be able to better control code cache space
WHITE_BOX.lockCompilation();
try {
@ -115,6 +137,7 @@ public class OverflowCodeCacheTest {
} catch (VirtualMachineError e) {
// Expected
}
constraints.check();
// Free code cache space
for (Long blob : blobs) {
WHITE_BOX.freeCodeBlob(blob);
@ -143,4 +166,31 @@ public class OverflowCodeCacheTest {
return bean.getUsage().getMax();
}
class CodeCacheConstraints {
void check() {}
}
CodeCacheConstraints getCodeCacheConstraints(final BlobType type) {
if (Long.valueOf(0).equals(WHITE_BOX.getVMFlag("HotCodeHeapSize"))) {
return new CodeCacheConstraints();
} else if (BlobType.MethodHot == type) {
// NonProfiledHeap is used when HotCodeHeap runs out of space.
return new CodeCacheConstraints() {
final int nonProfiledCount = WHITE_BOX.getCodeHeapEntries(BlobType.MethodNonProfiled.id).length;
@Override
void check() {
Asserts.assertLT(nonProfiledCount, WHITE_BOX.getCodeHeapEntries(BlobType.MethodNonProfiled.id).length);
}
};
} else {
// HotCodeHeap should not be used when other heap runs out of space.
return new CodeCacheConstraints() {
final int hotCount = WHITE_BOX.getCodeHeapEntries(BlobType.MethodHot.id).length;
@Override
void check() {
Asserts.assertEQ(hotCount, WHITE_BOX.getCodeHeapEntries(BlobType.MethodHot.id).length);
}
};
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -50,10 +50,16 @@ public class TestSegmentedCodeCacheOption {
private static final String USE_SEGMENTED_CODE_CACHE
= CommandLineOptionTest.prepareBooleanFlag(SEGMENTED_CODE_CACHE,
true);
private static final String UNLOCK_EXPERIMENTAL_VM_OPTIONS
= CommandLineOptionTest.prepareBooleanFlag("UnlockExperimentalVMOptions", true);
private static final String HOT_CODE_HEAP
= CommandLineOptionTest.prepareBooleanFlag("HotCodeHeap", true);
private static final long THRESHOLD_CC_SIZE_VALUE
= CodeCacheOptions.mB(240);
private static final long BELOW_THRESHOLD_CC_SIZE
= THRESHOLD_CC_SIZE_VALUE - CodeCacheOptions.mB(1);
private static final long HOT_CODE_HEAP_SIZE
= CodeCacheOptions.mB(8);
private static final String[] UNEXPECTED_MESSAGES = new String[] {
".*" + SEGMENTED_CODE_CACHE + ".*"
};
@ -104,7 +110,7 @@ public class TestSegmentedCodeCacheOption {
public void run() throws Throwable {
// SCC is disabled w/o TieredCompilation by default
String errorMessage = SEGMENTED_CODE_CACHE
+ " should be disabled by default when tiered "
+ " should be disabled by default when tiered "
+ "compilation is disabled";
CommandLineOptionTest.verifyOptionValueForSameVM(
@ -162,6 +168,52 @@ public class TestSegmentedCodeCacheOption {
CommandLineOptionTest.prepareBooleanFlag(
TIERED_COMPILATION, true));
}
},
OPTION_VALUES_HOT {
@Override
public boolean isApplicable() {
return Platform.isServer();
}
@Override
public void run() throws Throwable {
// SCC is enabled w hot code heap w/o TieredCompilation
String errorMessage = SEGMENTED_CODE_CACHE
+ " should be enabled when the hot code heap "
+ "is enabled";
CommandLineOptionTest.verifyOptionValueForSameVM(
SEGMENTED_CODE_CACHE, "true", errorMessage,
UNLOCK_EXPERIMENTAL_VM_OPTIONS,
HOT_CODE_HEAP,
CommandLineOptionTest.prepareNumericFlag(
BlobType.MethodHot.sizeOptionName,
HOT_CODE_HEAP_SIZE),
CommandLineOptionTest.prepareBooleanFlag(
TIERED_COMPILATION, false));
// Hot code heap could be explicitly enabled w/ SegmentedCodeCache
// and w/ ReservedCodeCacheSize value below the threshold
errorMessage = String.format("It should be possible to explicitly "
+ "enable %s and %s with %s below threshold %d.",
BlobType.MethodHot.sizeOptionName,
SEGMENTED_CODE_CACHE,
BlobType.All.sizeOptionName,
THRESHOLD_CC_SIZE_VALUE);
CommandLineOptionTest.verifyOptionValueForSameVM(
BlobType.MethodHot.sizeOptionName, String.valueOf(HOT_CODE_HEAP_SIZE),
errorMessage,
UNLOCK_EXPERIMENTAL_VM_OPTIONS,
HOT_CODE_HEAP,
CommandLineOptionTest.prepareNumericFlag(
BlobType.All.sizeOptionName,
BELOW_THRESHOLD_CC_SIZE),
CommandLineOptionTest.prepareNumericFlag(
BlobType.MethodHot.sizeOptionName,
HOT_CODE_HEAP_SIZE),
USE_SEGMENTED_CODE_CACHE);
}
};
TestCase() {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -69,5 +69,13 @@ public class GenericCodeHeapSizeRunner implements CodeCacheCLITestCase.Runner {
BlobType.MethodProfiled.sizeOptionName,
expectedValues.profiled),
testCaseDescription.getTestOptions(options));
CommandLineOptionTest.verifyOptionValueForSameVM(
BlobType.MethodHot.sizeOptionName,
Long.toString(expectedValues.hot),
String.format("%s should have value %d.",
BlobType.MethodHot.sizeOptionName,
expectedValues.hot),
testCaseDescription.getTestOptions(options));
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -48,13 +48,15 @@ import java.util.EnumSet;
public class TestCodeHeapSizeOptions extends CodeCacheCLITestBase {
private static final CodeCacheCLITestCase JVM_STARTUP
= new CodeCacheCLITestCase(new CodeCacheCLITestCase.Description(
options -> options.segmented,
options -> options.segmented
&& options.hot == 0,
EnumSet.noneOf(BlobType.class)),
new JVMStartupRunner());
private static final CodeCacheCLITestCase CODE_CACHE_FREE_SPACE
= new CodeCacheCLITestCase(new CodeCacheCLITestCase.Description(
options -> options.segmented
&& options.hot == 0
&& Platform.isDebugBuild(),
EnumSet.noneOf(BlobType.class)),
new CodeCacheFreeSpaceRunner());
@ -65,13 +67,19 @@ public class TestCodeHeapSizeOptions extends CodeCacheCLITestBase {
private TestCodeHeapSizeOptions() {
super(CodeCacheCLITestBase.OPTIONS_SET,
new CodeCacheCLITestCase(CodeCacheCLITestCase
.CommonDescriptions.NON_TIERED.description,
.CommonDescriptions.NON_TIERED_WO_HOT.description,
GENERIC_RUNNER),
new CodeCacheCLITestCase(CodeCacheCLITestCase
.CommonDescriptions.TIERED_LEVEL_1.description,
GENERIC_RUNNER),
new CodeCacheCLITestCase(CodeCacheCLITestCase
.CommonDescriptions.TIERED_LEVEL_4.description,
.CommonDescriptions.TIERED_LEVEL_4_WO_HOT.description,
GENERIC_RUNNER),
new CodeCacheCLITestCase(CodeCacheCLITestCase
.CommonDescriptions.NON_TIERED_W_HOT.description,
GENERIC_RUNNER),
new CodeCacheCLITestCase(CodeCacheCLITestCase
.CommonDescriptions.TIERED_LEVEL_4_W_HOT.description,
GENERIC_RUNNER),
JVM_STARTUP,
CODE_CACHE_FREE_SPACE);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -40,7 +40,13 @@ public class CodeCacheCLITestBase {
CodeCacheOptions.mB(100)),
new CodeCacheOptions(CodeCacheOptions.mB(60)),
new CodeCacheOptions(CodeCacheOptions.mB(200)),
new CodeCacheOptions(CodeCacheOptions.mB(300))
new CodeCacheOptions(CodeCacheOptions.mB(300)),
new CodeCacheOptions(CodeCacheOptions.mB(250),
CodeCacheOptions.mB(50), CodeCacheOptions.mB(75),
CodeCacheOptions.mB(75), CodeCacheOptions.mB(50)),
new CodeCacheOptions(CodeCacheOptions.mB(200),
CodeCacheOptions.mB(50), CodeCacheOptions.mB(100),
CodeCacheOptions.mB(0), CodeCacheOptions.mB(50))
};
private final CodeCacheCLITestCase[] testCases;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -39,15 +39,24 @@ import java.util.function.Function;
* description.
*/
public class CodeCacheCLITestCase {
private static final Function<CodeCacheOptions, Boolean> ONLY_SEGMENTED
= options -> options.segmented;
private static final Function<CodeCacheOptions, Boolean> SEGMENTED_SERVER
= ONLY_SEGMENTED.andThen(isSegmented -> isSegmented
private static final Function<CodeCacheOptions, Boolean> SEGMENTED_WO_HOT
= options -> options.segmented && options.hot == 0;
private static final Function<CodeCacheOptions, Boolean> SEGMENTED_SERVER_WO_HOT
= SEGMENTED_WO_HOT.andThen(isSegmented -> isSegmented
&& Platform.isServer() && Platform.isTieredSupported());
private static final Function<CodeCacheOptions, Boolean> SEGMENTED_W_HOT
= options -> options.segmented && options.hot > 0
&& options.profiled > 0 && Platform.isTieredSupported();
private static final Function<CodeCacheOptions, Boolean> SEGMENTED_W_HOT_WO_PROFILED
= options -> options.segmented && options.hot > 0
&& options.profiled == 0 && Platform.isTieredSupported();
private static final String USE_INT_MODE = "-Xint";
private static final String SEGMENTED_CODE_CACHE = "SegmentedCodeCache";
private static final String TIERED_COMPILATION = "TieredCompilation";
private static final String TIERED_STOP_AT = "TieredStopAtLevel";
private static final String UNLOCK_EXPERIMENTAL_VM_OPTIONS = "UnlockExperimentalVMOptions";
private static final String HOT_CODE_HEAP = "HotCodeHeap";
private final Description description;
private final Runner runner;
@ -68,7 +77,7 @@ public class CodeCacheCLITestCase {
* Verifies that in interpreted mode PrintCodeCache output contains
* the whole code cache. Int mode disables SegmentedCodeCache with a warning.
*/
INT_MODE(ONLY_SEGMENTED, EnumSet.of(BlobType.All), USE_INT_MODE),
INT_MODE(options -> options.hot == 0, EnumSet.of(BlobType.All), USE_INT_MODE),
/**
* Verifies that with disabled SegmentedCodeCache PrintCodeCache output
* contains only CodeCache's entry.
@ -81,7 +90,7 @@ public class CodeCacheCLITestCase {
* code cache PrintCodeCache output does not contain information about
* profiled-nmethods heap and non-segmented CodeCache.
*/
NON_TIERED(ONLY_SEGMENTED,
NON_TIERED_WO_HOT(SEGMENTED_WO_HOT,
EnumSet.of(BlobType.NonNMethod, BlobType.MethodNonProfiled),
CommandLineOptionTest.prepareBooleanFlag(TIERED_COMPILATION,
false)),
@ -90,7 +99,7 @@ public class CodeCacheCLITestCase {
* warn about SegmentedCodeCache and contain information about all
* heaps only.
*/
TIERED_LEVEL_0(SEGMENTED_SERVER,
TIERED_LEVEL_0(SEGMENTED_SERVER_WO_HOT,
EnumSet.of(BlobType.All),
CommandLineOptionTest.prepareBooleanFlag(TIERED_COMPILATION,
true),
@ -100,19 +109,44 @@ public class CodeCacheCLITestCase {
* contain information about non-nmethods and non-profiled nmethods
* heaps only.
*/
TIERED_LEVEL_1(SEGMENTED_SERVER,
TIERED_LEVEL_1(SEGMENTED_SERVER_WO_HOT,
EnumSet.of(BlobType.NonNMethod, BlobType.MethodNonProfiled),
CommandLineOptionTest.prepareBooleanFlag(TIERED_COMPILATION,
true),
CommandLineOptionTest.prepareNumericFlag(TIERED_STOP_AT, 1)),
/**
* Verifies that with TieredStopAtLevel=4 PrintCodeCache output will
* contain information about all three code heaps.
* contain information about non-nmethods, non-profiled nmethods
* and profiled nmethods heaps only.
*/
TIERED_LEVEL_4(SEGMENTED_SERVER,
EnumSet.complementOf(EnumSet.of(BlobType.All)),
TIERED_LEVEL_4_WO_HOT(SEGMENTED_SERVER_WO_HOT,
EnumSet.complementOf(EnumSet.of(BlobType.MethodHot, BlobType.All)),
CommandLineOptionTest.prepareBooleanFlag(TIERED_COMPILATION,
true),
CommandLineOptionTest.prepareNumericFlag(TIERED_STOP_AT, 4)),
/**
* Verifies that with disabled tiered compilation and enabled hot code
* cache PrintCodeCache output does not contain information about
* profiled-nmethods heap and non-segmented CodeCache.
*/
NON_TIERED_W_HOT(SEGMENTED_W_HOT_WO_PROFILED,
EnumSet.of(BlobType.NonNMethod, BlobType.MethodNonProfiled, BlobType.MethodHot),
CommandLineOptionTest.prepareBooleanFlag(UNLOCK_EXPERIMENTAL_VM_OPTIONS, true),
CommandLineOptionTest.prepareBooleanFlag(HOT_CODE_HEAP, true),
CommandLineOptionTest.prepareBooleanFlag(TIERED_COMPILATION,
false)),
/**
* Verifies that with TieredStopAtLevel=4 and hot code heap
* PrintCodeCache output will contain information about non-nmethods,
* non-profiled nmethods, profiled nmethods, and hot code heaps only.
*/
TIERED_LEVEL_4_W_HOT(SEGMENTED_W_HOT,
EnumSet.complementOf(EnumSet.of(BlobType.All)),
CommandLineOptionTest.prepareBooleanFlag(UNLOCK_EXPERIMENTAL_VM_OPTIONS, true),
CommandLineOptionTest.prepareBooleanFlag(HOT_CODE_HEAP, true),
CommandLineOptionTest.prepareBooleanFlag(TIERED_COMPILATION, true),
CommandLineOptionTest.prepareNumericFlag(TIERED_STOP_AT, 4));
CommonDescriptions(Function<CodeCacheOptions, Boolean> predicate,

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -37,15 +37,20 @@ public class CodeCacheOptions {
= EnumSet.of(BlobType.All);
private static final EnumSet<BlobType> ALL_SEGMENTED_HEAPS
= EnumSet.complementOf(NON_SEGMENTED_HEAPS);
private static final EnumSet<BlobType> SEGMENTED_HEAPS_WO_PROFILED
private static final EnumSet<BlobType> NON_NMETHOD_AND_NON_PROFILED_HEAPS
= EnumSet.of(BlobType.NonNMethod, BlobType.MethodNonProfiled);
private static final EnumSet<BlobType> SEGMENTED_HEAPS_WO_HOT
= EnumSet.of(BlobType.NonNMethod, BlobType.MethodProfiled, BlobType.MethodNonProfiled);
private static final EnumSet<BlobType> ONLY_NON_METHODS_HEAP
= EnumSet.of(BlobType.NonNMethod);
private static final EnumSet<BlobType> NON_NMETHOD_AND_NON_PROFILED_AND_HOT_HEAPS
= EnumSet.of(BlobType.NonNMethod, BlobType.MethodNonProfiled, BlobType.MethodHot);
public final long reserved;
public final long nonNmethods;
public final long nonProfiled;
public final long profiled;
public final long hot;
public final boolean segmented;
public static long mB(long val) {
@ -61,6 +66,7 @@ public class CodeCacheOptions {
this.nonNmethods = 0;
this.nonProfiled = 0;
this.profiled = 0;
this.hot = 0;
this.segmented = false;
}
@ -70,6 +76,17 @@ public class CodeCacheOptions {
this.nonNmethods = nonNmethods;
this.nonProfiled = nonProfiled;
this.profiled = profiled;
this.hot = 0;
this.segmented = true;
}
public CodeCacheOptions(long reserved, long nonNmethods, long nonProfiled,
long profiled, long hot) {
this.reserved = reserved;
this.nonNmethods = nonNmethods;
this.nonProfiled = nonProfiled;
this.profiled = profiled;
this.hot = hot;
this.segmented = true;
}
@ -83,6 +100,8 @@ public class CodeCacheOptions {
return this.nonProfiled;
case MethodProfiled:
return this.profiled;
case MethodHot:
return this.hot;
default:
throw new Error("Unknown heap: " + heap.name());
}
@ -106,6 +125,11 @@ public class CodeCacheOptions {
nonProfiled),
CommandLineOptionTest.prepareNumericFlag(
BlobType.MethodProfiled.sizeOptionName, profiled));
if (hot > 0) {
Collections.addAll(options,
CommandLineOptionTest.prepareNumericFlag(
BlobType.MethodHot.sizeOptionName, hot));
}
}
return options.toArray(new String[options.size()]);
}
@ -113,9 +137,11 @@ public class CodeCacheOptions {
public CodeCacheOptions mapOptions(EnumSet<BlobType> involvedCodeHeaps) {
if (involvedCodeHeaps.isEmpty()
|| involvedCodeHeaps.equals(NON_SEGMENTED_HEAPS)
|| involvedCodeHeaps.equals(ALL_SEGMENTED_HEAPS)) {
|| involvedCodeHeaps.equals(SEGMENTED_HEAPS_WO_HOT)
|| involvedCodeHeaps.equals(ALL_SEGMENTED_HEAPS)
|| involvedCodeHeaps.equals(NON_NMETHOD_AND_NON_PROFILED_AND_HOT_HEAPS)) {
return this;
} else if (involvedCodeHeaps.equals(SEGMENTED_HEAPS_WO_PROFILED)) {
} else if (involvedCodeHeaps.equals(NON_NMETHOD_AND_NON_PROFILED_HEAPS)) {
return new CodeCacheOptions(reserved, nonNmethods,
profiled + nonProfiled, 0L);
} else if (involvedCodeHeaps.equals(ONLY_NON_METHODS_HEAP)) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -46,7 +46,7 @@ import java.util.EnumSet;
public class TestPrintCodeCacheOption extends CodeCacheCLITestBase {
private static final CodeCacheCLITestCase DISABLED_PRINT_CODE_CACHE
= new CodeCacheCLITestCase(new CodeCacheCLITestCase.Description(
options -> true, EnumSet.noneOf(BlobType.class)),
options -> options.hot == 0, EnumSet.noneOf(BlobType.class)),
new PrintCodeCacheRunner(false));
private static final CodeCacheCLITestCase.Runner DEFAULT_RUNNER
@ -61,7 +61,7 @@ public class TestPrintCodeCacheOption extends CodeCacheCLITestBase {
.CommonDescriptions.NON_SEGMENTED.description,
DEFAULT_RUNNER),
new CodeCacheCLITestCase(CodeCacheCLITestCase
.CommonDescriptions.NON_TIERED.description,
.CommonDescriptions.NON_TIERED_WO_HOT.description,
DEFAULT_RUNNER),
new CodeCacheCLITestCase(CodeCacheCLITestCase
.CommonDescriptions.TIERED_LEVEL_0.description,
@ -70,7 +70,13 @@ public class TestPrintCodeCacheOption extends CodeCacheCLITestBase {
.CommonDescriptions.TIERED_LEVEL_1.description,
DEFAULT_RUNNER),
new CodeCacheCLITestCase(CodeCacheCLITestCase
.CommonDescriptions.TIERED_LEVEL_4.description,
.CommonDescriptions.TIERED_LEVEL_4_WO_HOT.description,
DEFAULT_RUNNER),
new CodeCacheCLITestCase(CodeCacheCLITestCase
.CommonDescriptions.NON_TIERED_W_HOT.description,
DEFAULT_RUNNER),
new CodeCacheCLITestCase(CodeCacheCLITestCase
.CommonDescriptions.TIERED_LEVEL_4_W_HOT.description,
DEFAULT_RUNNER),
DISABLED_PRINT_CODE_CACHE);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -40,6 +40,26 @@
* compiler.codecache.jmx.BeanTypeTest
*/
/**
* @test BeanTypeTest
* @requires vm.compiler2.enabled
* @summary verify types of code cache memory pool bean
* @modules java.base/jdk.internal.misc
* java.management
* @library /test/lib
*
* @build jdk.test.whitebox.WhiteBox
* @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI
* -XX:+UnlockExperimentalVMOptions -XX:+HotCodeHeap -XX:HotCodeHeapSize=8M -XX:+TieredCompilation -XX:TieredStopAtLevel=4
* compiler.codecache.jmx.BeanTypeTest
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI
* -XX:+UnlockExperimentalVMOptions -XX:+HotCodeHeap -XX:HotCodeHeapSize=8M -XX:-TieredCompilation -XX:TieredStopAtLevel=4
* compiler.codecache.jmx.BeanTypeTest
*/
package compiler.codecache.jmx;
import jdk.test.lib.Asserts;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -40,6 +40,26 @@
* compiler.codecache.jmx.CodeHeapBeanPresenceTest
*/
/**
* @test CodeHeapBeanPresenceTest
* @requires vm.compiler2.enabled
* @summary verify CodeHeap bean presence
* @modules java.base/jdk.internal.misc
* java.management
* @library /test/lib
*
* @build jdk.test.whitebox.WhiteBox
* @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI
* -XX:+UnlockExperimentalVMOptions -XX:+HotCodeHeap -XX:HotCodeHeapSize=8M -XX:+TieredCompilation -XX:TieredStopAtLevel=4
* compiler.codecache.jmx.CodeHeapBeanPresenceTest
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI
* -XX:+UnlockExperimentalVMOptions -XX:+HotCodeHeap -XX:HotCodeHeapSize=8M -XX:-TieredCompilation -XX:TieredStopAtLevel=4
* compiler.codecache.jmx.CodeHeapBeanPresenceTest
*/
package compiler.codecache.jmx;
import jdk.test.lib.Asserts;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -42,6 +42,28 @@
* compiler.codecache.jmx.GetUsageTest
*/
/*
* @test GetUsageTest
* @requires vm.compiler2.enabled
* @summary testing of getUsage() for segmented code cache
* @modules java.base/jdk.internal.misc
* java.management
* @library /test/lib /
*
* @build jdk.test.whitebox.WhiteBox
* @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI -XX:CompileCommand=compileonly,null::*
* -XX:-UseCodeCacheFlushing -XX:-MethodFlushing
* -XX:+UnlockExperimentalVMOptions -XX:+HotCodeHeap -XX:HotCodeHeapSize=8M -XX:+TieredCompilation -XX:TieredStopAtLevel=4
* compiler.codecache.jmx.GetUsageTest
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI -XX:CompileCommand=compileonly,null::*
* -XX:-UseCodeCacheFlushing -XX:-MethodFlushing
* -XX:+UnlockExperimentalVMOptions -XX:+HotCodeHeap -XX:HotCodeHeapSize=8M -XX:-TieredCompilation -XX:TieredStopAtLevel=4
* compiler.codecache.jmx.GetUsageTest
*/
package compiler.codecache.jmx;
import jdk.test.lib.Asserts;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -42,6 +42,28 @@
* compiler.codecache.jmx.InitialAndMaxUsageTest
*/
/*
* @test InitialAndMaxUsageTest
* @requires vm.compiler2.enabled
* @summary testing of initial and max usage
* @modules java.base/jdk.internal.misc
* java.management
* @library /test/lib /
*
* @build jdk.test.whitebox.WhiteBox
* @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
* @run main/othervm -Xbootclasspath/a:. -XX:-UseCodeCacheFlushing
* -XX:-MethodFlushing -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
* -XX:CompileCommand=compileonly,null::* -XX:-UseLargePages
* -XX:+UnlockExperimentalVMOptions -XX:+HotCodeHeap -XX:HotCodeHeapSize=8M -XX:+TieredCompilation -XX:TieredStopAtLevel=4
* compiler.codecache.jmx.InitialAndMaxUsageTest
* @run main/othervm -Xbootclasspath/a:. -XX:-UseCodeCacheFlushing
* -XX:-MethodFlushing -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
* -XX:CompileCommand=compileonly,null::* -XX:-UseLargePages
* -XX:+UnlockExperimentalVMOptions -XX:+HotCodeHeap -XX:HotCodeHeapSize=8M -XX:-TieredCompilation -XX:TieredStopAtLevel=4
* compiler.codecache.jmx.InitialAndMaxUsageTest
*/
package compiler.codecache.jmx;
import jdk.test.lib.Asserts;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -40,6 +40,26 @@
* compiler.codecache.jmx.ManagerNamesTest
*/
/**
* @test ManagerNamesTest
* @requires vm.compiler2.enabled
* @summary verify getMemoryManageNames calls in case of segmented code cache
* @modules java.base/jdk.internal.misc
* java.management
* @library /test/lib
*
* @build jdk.test.whitebox.WhiteBox
* @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI
* -XX:+UnlockExperimentalVMOptions -XX:+HotCodeHeap -XX:HotCodeHeapSize=8M -XX:+TieredCompilation -XX:TieredStopAtLevel=4
* compiler.codecache.jmx.ManagerNamesTest
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI
* -XX:+UnlockExperimentalVMOptions -XX:+HotCodeHeap -XX:HotCodeHeapSize=8M -XX:-TieredCompilation -XX:TieredStopAtLevel=4
* compiler.codecache.jmx.ManagerNamesTest
*/
package compiler.codecache.jmx;
import jdk.test.lib.Asserts;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -40,6 +40,26 @@
* compiler.codecache.jmx.MemoryPoolsPresenceTest
*/
/**
* @test MemoryPoolsPresenceTest
* @requires vm.compiler2.enabled
* @summary verify that MemoryManagerMXBean exists for every code cache segment
* @modules java.base/jdk.internal.misc
* java.management
* @library /test/lib
*
* @build jdk.test.whitebox.WhiteBox
* @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI
* -XX:+UnlockExperimentalVMOptions -XX:+HotCodeHeap -XX:HotCodeHeapSize=8M -XX:+TieredCompilation -XX:TieredStopAtLevel=4
* compiler.codecache.jmx.MemoryPoolsPresenceTest
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI
* -XX:+UnlockExperimentalVMOptions -XX:+HotCodeHeap -XX:HotCodeHeapSize=8M -XX:-TieredCompilation -XX:TieredStopAtLevel=4
* compiler.codecache.jmx.MemoryPoolsPresenceTest
*/
package compiler.codecache.jmx;
import jdk.test.lib.Asserts;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -23,6 +23,8 @@
/*
* @test PeakUsageTest
* @summary testing of getPeakUsage() and resetPeakUsage for
* segmented code cache
* @library /test/lib /
* @modules java.base/jdk.internal.misc
* java.management
@ -37,8 +39,27 @@
* -XX:+WhiteBoxAPI -XX:CompileCommand=compileonly,null::*
* -XX:-SegmentedCodeCache
* compiler.codecache.jmx.PeakUsageTest
*/
/*
* @test PeakUsageTest
* @requires vm.compiler2.enabled
* @summary testing of getPeakUsage() and resetPeakUsage for
* segmented code cache
* @library /test/lib /
* @modules java.base/jdk.internal.misc
* java.management
*
* @build jdk.test.whitebox.WhiteBox
* @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI -XX:CompileCommand=compileonly,null::*
* -XX:+UnlockExperimentalVMOptions -XX:+HotCodeHeap -XX:HotCodeHeapSize=8M -XX:+TieredCompilation -XX:TieredStopAtLevel=4
* compiler.codecache.jmx.PeakUsageTest
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI -XX:CompileCommand=compileonly,null::*
* -XX:+UnlockExperimentalVMOptions -XX:+HotCodeHeap -XX:HotCodeHeapSize=8M -XX:-TieredCompilation -XX:TieredStopAtLevel=4
* compiler.codecache.jmx.PeakUsageTest
*/
package compiler.codecache.jmx;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -40,6 +40,26 @@
* compiler.codecache.jmx.PoolsIndependenceTest
*/
/*
* @test PoolsIndependenceTest
* @requires vm.compiler2.enabled
* @summary testing of getUsageThreshold()
* @modules java.base/jdk.internal.misc
* java.management
* @library /test/lib /
*
* @build jdk.test.whitebox.WhiteBox
* @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI -XX:-UseCodeCacheFlushing -XX:-MethodFlushing
* -XX:+UnlockExperimentalVMOptions -XX:+HotCodeHeap -XX:HotCodeHeapSize=8M -XX:+TieredCompilation -XX:TieredStopAtLevel=4
* compiler.codecache.jmx.PoolsIndependenceTest
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI -XX:-UseCodeCacheFlushing -XX:-MethodFlushing
* -XX:+UnlockExperimentalVMOptions -XX:+HotCodeHeap -XX:HotCodeHeapSize=8M -XX:-TieredCompilation -XX:TieredStopAtLevel=4
* compiler.codecache.jmx.PoolsIndependenceTest
*/
package compiler.codecache.jmx;
import jdk.test.lib.Asserts;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -40,6 +40,26 @@
* compiler.codecache.jmx.ThresholdNotificationsTest
*/
/*
* @test ThresholdNotificationsTest
* @requires vm.compiler2.enabled
* @summary testing of getUsageThreshold()
* @library /test/lib /
* @modules java.base/jdk.internal.misc
* java.management
*
* @build jdk.test.whitebox.WhiteBox
* @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -Xbootclasspath/a:. -XX:-UseCodeCacheFlushing
* -XX:+WhiteBoxAPI -XX:-MethodFlushing -XX:CompileCommand=compileonly,null::*
* -XX:+UnlockExperimentalVMOptions -XX:+HotCodeHeap -XX:HotCodeHeapSize=8M -XX:+TieredCompilation -XX:TieredStopAtLevel=4
* compiler.codecache.jmx.ThresholdNotificationsTest
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -Xbootclasspath/a:. -XX:-UseCodeCacheFlushing
* -XX:+WhiteBoxAPI -XX:-MethodFlushing -XX:CompileCommand=compileonly,null::*
* -XX:+UnlockExperimentalVMOptions -XX:+HotCodeHeap -XX:HotCodeHeapSize=8M -XX:-TieredCompilation -XX:TieredStopAtLevel=4
* compiler.codecache.jmx.ThresholdNotificationsTest
*/
package compiler.codecache.jmx;
import jdk.test.lib.Asserts;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -42,3 +42,26 @@
* -XX:-SegmentedCodeCache
* compiler.codecache.jmx.UsageThresholdExceededTest
*/
/*
* @test UsageThresholdExceededSeveralTimesTest
* @requires vm.compiler2.enabled
* @summary verifying that getUsageThresholdCount() returns correct value
* after threshold has been hit several times
* @library /test/lib /
* @modules java.base/jdk.internal.misc
* java.management
*
* @build jdk.test.whitebox.WhiteBox
* @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI -XX:-UseCodeCacheFlushing -XX:-MethodFlushing
* -XX:CompileCommand=compileonly,null::* -Djdk.test.lib.iterations=10
* -XX:+UnlockExperimentalVMOptions -XX:+HotCodeHeap -XX:HotCodeHeapSize=8M -XX:+TieredCompilation -XX:TieredStopAtLevel=4
* compiler.codecache.jmx.UsageThresholdExceededTest
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI -XX:-UseCodeCacheFlushing -XX:-MethodFlushing
* -XX:CompileCommand=compileonly,null::* -Djdk.test.lib.iterations=10
* -XX:+UnlockExperimentalVMOptions -XX:+HotCodeHeap -XX:HotCodeHeapSize=8M -XX:-TieredCompilation -XX:TieredStopAtLevel=4
* compiler.codecache.jmx.UsageThresholdExceededTest
*/

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -32,17 +32,40 @@
* @build jdk.test.whitebox.WhiteBox
* @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI -XX:-UseCodeCacheFlushing -XX:-MethodFlushing
* -XX:+WhiteBoxAPI -XX:-UseCodeCacheFlushing -XX:-MethodFlushing
* -XX:CompileCommand=compileonly,null::*
* -XX:+SegmentedCodeCache
* compiler.codecache.jmx.UsageThresholdExceededTest
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI -XX:-UseCodeCacheFlushing -XX:-MethodFlushing
* -XX:+WhiteBoxAPI -XX:-UseCodeCacheFlushing -XX:-MethodFlushing
* -XX:CompileCommand=compileonly,null::*
* -XX:-SegmentedCodeCache
* compiler.codecache.jmx.UsageThresholdExceededTest
*/
/*
* @test UsageThresholdExceededTest
* @requires vm.compiler2.enabled
* @summary verifying that getUsageThresholdCount() returns correct value
* after threshold has been hit
* @library /test/lib /
* @modules java.base/jdk.internal.misc
* java.management
*
* @build jdk.test.whitebox.WhiteBox
* @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI -XX:-UseCodeCacheFlushing -XX:-MethodFlushing
* -XX:CompileCommand=compileonly,null::*
* -XX:+UnlockExperimentalVMOptions -XX:+HotCodeHeap -XX:HotCodeHeapSize=8M -XX:+TieredCompilation -XX:TieredStopAtLevel=4
* compiler.codecache.jmx.UsageThresholdExceededTest
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI -XX:-UseCodeCacheFlushing -XX:-MethodFlushing
* -XX:CompileCommand=compileonly,null::*
* -XX:+UnlockExperimentalVMOptions -XX:+HotCodeHeap -XX:HotCodeHeapSize=8M -XX:-TieredCompilation -XX:TieredStopAtLevel=4
* compiler.codecache.jmx.UsageThresholdExceededTest
*/
package compiler.codecache.jmx;
import jdk.test.whitebox.code.BlobType;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -42,6 +42,28 @@
* compiler.codecache.jmx.UsageThresholdIncreasedTest
*/
/*
* @test UsageThresholdIncreasedTest
* @requires vm.compiler2.enabled
* @summary verifying that threshold hasn't been hit after allocation smaller
* than threshold value and that threshold value can be changed
* @library /test/lib /
* @modules java.base/jdk.internal.misc
* java.management
* @build jdk.test.whitebox.WhiteBox
* @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI -XX:-UseCodeCacheFlushing -XX:-MethodFlushing
* -XX:CompileCommand=compileonly,null::*
* -XX:+UnlockExperimentalVMOptions -XX:+HotCodeHeap -XX:HotCodeHeapSize=8M -XX:+TieredCompilation -XX:TieredStopAtLevel=4
* compiler.codecache.jmx.UsageThresholdIncreasedTest
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI -XX:-UseCodeCacheFlushing -XX:-MethodFlushing
* -XX:CompileCommand=compileonly,null::*
* -XX:+UnlockExperimentalVMOptions -XX:+HotCodeHeap -XX:HotCodeHeapSize=8M -XX:-TieredCompilation -XX:TieredStopAtLevel=4
* compiler.codecache.jmx.UsageThresholdIncreasedTest
*/
package compiler.codecache.jmx;
import jdk.test.whitebox.code.BlobType;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -43,6 +43,29 @@
* compiler.codecache.jmx.UsageThresholdNotExceededTest
*/
/*
* @test UsageThresholdNotExceededTest
* @requires vm.compiler2.enabled
* @summary verifying that usage threshold not exceeded while allocating less
* than usage threshold
* @library /test/lib /
* @modules java.base/jdk.internal.misc
* java.management
*
* @build jdk.test.whitebox.WhiteBox
* @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
* * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI -XX:-UseCodeCacheFlushing -XX:-MethodFlushing
* -XX:CompileCommand=compileonly,null::*
* -XX:+UnlockExperimentalVMOptions -XX:+HotCodeHeap -XX:HotCodeHeapSize=8M -XX:+TieredCompilation -XX:TieredStopAtLevel=4
* compiler.codecache.jmx.UsageThresholdNotExceededTest
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI -XX:-UseCodeCacheFlushing -XX:-MethodFlushing
* -XX:CompileCommand=compileonly,null::*
* -XX:+UnlockExperimentalVMOptions -XX:+HotCodeHeap -XX:HotCodeHeapSize=8M -XX:-TieredCompilation -XX:TieredStopAtLevel=4
* compiler.codecache.jmx.UsageThresholdNotExceededTest
*/
package compiler.codecache.jmx;
import jdk.test.whitebox.code.BlobType;

View File

@ -43,6 +43,29 @@
* compiler.codecache.stress.RandomAllocationTest
*/
/*
* @test RandomAllocationTest
* @key stress randomness
* @requires vm.compiler2.enabled
* @summary stressing code cache by allocating randomly sized "dummy" code blobs
* @library /test/lib /
* @modules java.base/jdk.internal.misc
* java.management
*
* @build jdk.test.whitebox.WhiteBox compiler.codecache.stress.Helper compiler.codecache.stress.TestCaseImpl
* @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI
* -XX:CompileCommand=dontinline,compiler.codecache.stress.Helper$TestCase::method
* -XX:+UnlockExperimentalVMOptions -XX:+HotCodeHeap -XX:HotCodeHeapSize=8M -XX:+TieredCompilation -XX:TieredStopAtLevel=4
* compiler.codecache.stress.RandomAllocationTest
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI
* -XX:CompileCommand=dontinline,compiler.codecache.stress.Helper$TestCase::method
* -XX:+UnlockExperimentalVMOptions -XX:+HotCodeHeap -XX:HotCodeHeapSize=8M -XX:-TieredCompilation -XX:TieredStopAtLevel=4
* compiler.codecache.stress.RandomAllocationTest
*/
package compiler.codecache.stress;
import jdk.test.whitebox.code.BlobType;

View File

@ -123,12 +123,10 @@ public class CPUFeaturesClearTest {
if (isCpuFeatureSupported("sve2")) {
outputAnalyzer = ProcessTools.executeTestJava(generateArgs(prepareNumericFlag("UseSVE", 1)));
outputAnalyzer.shouldNotMatch("[os,cpu] CPU: .* sve2.*");
verifyOutput(null, new String[]{"sve2"}, null, outputAnalyzer);
}
if (isCpuFeatureSupported("sve")) {
outputAnalyzer = ProcessTools.executeTestJava(generateArgs(prepareNumericFlag("UseSVE", 0)));
outputAnalyzer.shouldNotMatch("[os,cpu] CPU: .* sve.*");
verifyOutput(null, new String[]{"sve"}, null, outputAnalyzer);
}
}

View File

@ -26,7 +26,6 @@
* @library /test/lib /
* @modules java.base/jdk.internal.misc
* java.management
* @requires (vm.cpu.features ~= ".*aes.*" | vm.cpu.features ~= ".*zvkn.*") & !vm.graal.enabled
* @build jdk.test.whitebox.WhiteBox
* @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
* @run main/othervm/timeout=600 -Xbootclasspath/a:.

View File

@ -81,7 +81,7 @@ public class TestAESIntrinsicsOnUnsupportedConfig extends AESIntrinsicsBase {
/**
* Test checks following situation: <br/>
* UseAESIntrinsics flag is set to true, TestAESMain is executed <br/>
* UseAES flag is set to true, TestAESMain is executed <br/>
* Expected result: UseAES flag is set to false <br/>
* UseAES flag is set to false <br/>
* Output shouldn't contain intrinsics usage <br/>

View File

@ -22,6 +22,7 @@
*/
package compiler.exceptions;
import compiler.lib.ir_framework.CompLevel;
import compiler.lib.ir_framework.Run;
import compiler.lib.ir_framework.Test;
import compiler.lib.ir_framework.TestFramework;
@ -38,7 +39,7 @@ import test.java.lang.invoke.lib.InstructionHelper;
/**
* @test
* @bug 8350208
* @summary Safepoints added during the processing of exception handlers should never reexecute
* @summary Safepoints added during the processing of exception handlers need correct stack state
* @library /test/lib /test/jdk/java/lang/invoke/common /
* @build test.java.lang.invoke.lib.InstructionHelper
*
@ -110,7 +111,7 @@ public class TestDebugDuringExceptionCatching {
});
}
@Test
@Test(compLevel = CompLevel.C2) // see JDK-8381786
private static int testBackwardHandler(V v) throws Throwable {
return (int) SNIPPET_HANDLE.invokeExact(v);
}

View File

@ -0,0 +1,88 @@
/*
* Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
/*
* @test
* @library /test/lib /
* @build jdk.test.whitebox.WhiteBox
* @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
* @run main/othervm -Xbootclasspath/a:. -Xbatch -XX:-TieredCompilation -XX:+SegmentedCodeCache -XX:+UnlockExperimentalVMOptions -XX:+HotCodeHeap
* -XX:+NMethodRelocation -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:HotCodeIntervalSeconds=0 -XX:HotCodeCallLevel=0
* -XX:HotCodeSampleSeconds=5 -XX:HotCodeStablePercent=-1 -XX:HotCodeSamplePercent=100 -XX:HotCodeStartupDelaySeconds=0
* -XX:CompileCommand=compileonly,compiler.hotcode.HotCodeCollectorMoveFunction::func
* compiler.hotcode.HotCodeCollectorMoveFunction
*/
package compiler.hotcode;
import java.lang.reflect.Method;
import jdk.test.lib.Asserts;
import jdk.test.whitebox.WhiteBox;
import jdk.test.whitebox.code.BlobType;
import jdk.test.whitebox.code.NMethod;
public class HotCodeCollectorMoveFunction {
private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
private static final Method method;
private static final int C2_LEVEL = 4;
private static final int FUNC_RUN_MILLIS = 60_000;
static {
try {
method = HotCodeCollectorMoveFunction.class.getMethod("func");
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
}
public static void main(String[] args) throws Exception {
WHITE_BOX.testSetDontInlineMethod(method, true);
compileFunc();
// Call function so collector samples and relocates
func();
// Function should now be in the Hot code heap after collector has had time to relocate
NMethod reloc_nm = NMethod.get(method, false);
Asserts.assertNotEquals(reloc_nm, null);
Asserts.assertEQ(reloc_nm.code_blob_type, BlobType.MethodHot);
}
public static void compileFunc() {
WHITE_BOX.enqueueMethodForCompilation(method, C2_LEVEL);
if (WHITE_BOX.getMethodCompilationLevel(method) != C2_LEVEL) {
throw new IllegalStateException("Method " + method + " is not compiled by C2.");
}
}
public static void func() {
long start = System.currentTimeMillis();
while (System.currentTimeMillis() - start < FUNC_RUN_MILLIS) {}
}
}

View File

@ -0,0 +1,167 @@
/*
* Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
/*
* @test
* @library /test/lib /
* @build jdk.test.whitebox.WhiteBox
* @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
* @run main/othervm -Xbootclasspath/a:. -Xcomp -XX:-TieredCompilation -XX:+UnlockExperimentalVMOptions -XX:+HotCodeHeap -XX:+NMethodRelocation
* -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:HotCodeIntervalSeconds=0 -XX:HotCodeSampleSeconds=10
* -XX:HotCodeStablePercent=-1 -XX:HotCodeSamplePercent=100 -XX:HotCodeStartupDelaySeconds=0
* compiler.hotcode.StressHotCodeCollector
*/
package compiler.hotcode;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Random;
import jdk.test.lib.compiler.InMemoryJavaCompiler;
import jdk.test.whitebox.WhiteBox;
public class StressHotCodeCollector {
private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
private static final double RUN_MILLIS = 60_000;
private static TestMethod[] methods = new TestMethod[100];
private static byte[] num1;
private static byte[] num2;
private static byte[] genNum(Random random, int digitCount) {
byte[] num = new byte[digitCount];
int d;
do {
d = random.nextInt(10);
} while (d == 0);
num[0] = (byte)d;
for (int i = 1; i < digitCount; ++i) {
num[i] = (byte)random.nextInt(10);
}
return num;
}
private static void initNums() {
final long seed = 8374592837465123L;
Random random = new Random(seed);
final int digitCount = 40;
num1 = genNum(random, digitCount);
num2 = genNum(random, digitCount);
}
private static void generateCode() throws Exception {
byte[] result = new byte[num1.length + 1];
for (int i = 0; i < methods.length; i++) {
methods[i] = new TestMethod();
}
}
public static void main(String[] args) throws Exception {
initNums();
generateCode();
long start = System.currentTimeMillis();
Random random = new Random();
while (System.currentTimeMillis() - start < RUN_MILLIS) {
for (TestMethod m : methods) {
if (random.nextInt(100) < 10) {
m.deoptimize();
}
byte[] result = new byte[num1.length + 1];
m.invoke(num1, num2, result);
}
}
}
private static final class TestMethod {
private static final String CLASS_NAME = "A";
private static final String METHOD_TO_COMPILE = "sum";
private static final String JAVA_CODE = """
public class A {
public static void sum(byte[] n1, byte[] n2, byte[] out) {
long start = System.currentTimeMillis();
while (System.currentTimeMillis() - start < 100) {}
final int digitCount = n1.length;
int carry = 0;
for (int i = digitCount - 1; i >= 0; --i) {
int sum = n1[i] + n2[i] + carry;
out[i] = (byte)(sum % 10);
carry = sum / 10;
}
if (carry != 0) {
for (int i = digitCount; i > 0; --i) {
out[i] = out[i - 1];
}
out[0] = (byte)carry;
}
}
}""";
private static final byte[] BYTE_CODE;
static {
BYTE_CODE = InMemoryJavaCompiler.compile(CLASS_NAME, JAVA_CODE);
}
private final Method method;
private static ClassLoader createClassLoaderFor() {
return new ClassLoader() {
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
if (!name.equals(CLASS_NAME)) {
return super.loadClass(name);
}
return defineClass(name, BYTE_CODE, 0, BYTE_CODE.length);
}
};
}
public TestMethod() throws Exception {
var cl = createClassLoaderFor().loadClass(CLASS_NAME);
method = cl.getMethod(METHOD_TO_COMPILE, byte[].class, byte[].class, byte[].class);
WHITE_BOX.testSetDontInlineMethod(method, true);
}
public void invoke(byte[] num1, byte[] num2, byte[] result) throws Exception {
method.invoke(null, num1, num2, result);
}
public void deoptimize() {
WHITE_BOX.deoptimizeMethod(method);
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2021, 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
@ -71,7 +71,7 @@ public class TestVectorDoubleExpandShrink {
}
@Test
@IR(counts = {REINTERPRET_NODE, "2"})
@IR(applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"}, counts = {REINTERPRET_NODE, "2"})
public static void testB128toB64(MemorySegment input, MemorySegment output) {
vectorDoubleExpandShrink(BSPEC128, BSPEC64, input, output);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2021, 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
@ -38,7 +38,7 @@ import static compiler.vectorapi.reshape.utils.VectorReshapeHelper.*;
*/
public class TestVectorExpandShrink {
@Test
@IR(counts = {REINTERPRET_NODE, "1"})
@IR(applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"}, counts = {REINTERPRET_NODE, "1"})
public static void testB64toB128(MemorySegment input, MemorySegment output) {
vectorExpandShrink(BSPEC64, BSPEC128, input, output);
}
@ -71,7 +71,7 @@ public class TestVectorExpandShrink {
}
@Test
@IR(counts = {REINTERPRET_NODE, "1"})
@IR(applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"}, counts = {REINTERPRET_NODE, "1"})
public static void testB128toB64(MemorySegment input, MemorySegment output) {
vectorExpandShrink(BSPEC128, BSPEC64, input, output);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2021, 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
@ -41,7 +41,7 @@ import static compiler.vectorapi.reshape.utils.VectorReshapeHelper.*;
*/
public class TestVectorRebracket {
@Test
@IR(counts = {REINTERPRET_NODE, "1"})
@IR(applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"}, counts = {REINTERPRET_NODE, "1"})
public static void testB64toS64(byte[] input, short[] output) {
vectorRebracket(BSPEC64, SSPEC64, input, output);
}
@ -52,7 +52,7 @@ public class TestVectorRebracket {
}
@Test
@IR(counts = {REINTERPRET_NODE, "1"})
@IR(applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"}, counts = {REINTERPRET_NODE, "1"})
public static void testB64toI64(byte[] input, int[] output) {
vectorRebracket(BSPEC64, ISPEC64, input, output);
}
@ -63,7 +63,7 @@ public class TestVectorRebracket {
}
@Test
@IR(counts = {REINTERPRET_NODE, "1"})
@IR(applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"}, counts = {REINTERPRET_NODE, "1"})
public static void testB64toL64(byte[] input, long[] output) {
vectorRebracket(BSPEC64, LSPEC64, input, output);
}
@ -74,7 +74,7 @@ public class TestVectorRebracket {
}
@Test
@IR(counts = {REINTERPRET_NODE, "1"})
@IR(applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"}, counts = {REINTERPRET_NODE, "1"})
public static void testB64toF64(byte[] input, float[] output) {
vectorRebracket(BSPEC64, FSPEC64, input, output);
}
@ -85,7 +85,7 @@ public class TestVectorRebracket {
}
@Test
@IR(counts = {REINTERPRET_NODE, "1"})
@IR(applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"}, counts = {REINTERPRET_NODE, "1"})
public static void testB64toD64(byte[] input, double[] output) {
vectorRebracket(BSPEC64, DSPEC64, input, output);
}
@ -96,7 +96,7 @@ public class TestVectorRebracket {
}
@Test
@IR(counts = {REINTERPRET_NODE, "1"})
@IR(applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"}, counts = {REINTERPRET_NODE, "1"})
public static void testS64toB64(short[] input, byte[] output) {
vectorRebracket(SSPEC64, BSPEC64, input, output);
}
@ -107,7 +107,7 @@ public class TestVectorRebracket {
}
@Test
@IR(counts = {REINTERPRET_NODE, "1"})
@IR(applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"}, counts = {REINTERPRET_NODE, "1"})
public static void testS64toI64(short[] input, int[] output) {
vectorRebracket(SSPEC64, ISPEC64, input, output);
}
@ -118,7 +118,7 @@ public class TestVectorRebracket {
}
@Test
@IR(counts = {REINTERPRET_NODE, "1"})
@IR(applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"}, counts = {REINTERPRET_NODE, "1"})
public static void testS64toL64(short[] input, long[] output) {
vectorRebracket(SSPEC64, LSPEC64, input, output);
}
@ -129,7 +129,7 @@ public class TestVectorRebracket {
}
@Test
@IR(counts = {REINTERPRET_NODE, "1"})
@IR(applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"}, counts = {REINTERPRET_NODE, "1"})
public static void testS64toF64(short[] input, float[] output) {
vectorRebracket(SSPEC64, FSPEC64, input, output);
}
@ -140,7 +140,7 @@ public class TestVectorRebracket {
}
@Test
@IR(counts = {REINTERPRET_NODE, "1"})
@IR(applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"}, counts = {REINTERPRET_NODE, "1"})
public static void testS64toD64(short[] input, double[] output) {
vectorRebracket(SSPEC64, DSPEC64, input, output);
}
@ -151,7 +151,7 @@ public class TestVectorRebracket {
}
@Test
@IR(counts = {REINTERPRET_NODE, "1"})
@IR(applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"}, counts = {REINTERPRET_NODE, "1"})
public static void testI64toB64(int[] input, byte[] output) {
vectorRebracket(ISPEC64, BSPEC64, input, output);
}
@ -162,7 +162,7 @@ public class TestVectorRebracket {
}
@Test
@IR(counts = {REINTERPRET_NODE, "1"})
@IR(applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"}, counts = {REINTERPRET_NODE, "1"})
public static void testI64toS64(int[] input, short[] output) {
vectorRebracket(ISPEC64, SSPEC64, input, output);
}
@ -173,7 +173,7 @@ public class TestVectorRebracket {
}
@Test
@IR(counts = {REINTERPRET_NODE, "1"})
@IR(applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"}, counts = {REINTERPRET_NODE, "1"})
public static void testI64toL64(int[] input, long[] output) {
vectorRebracket(ISPEC64, LSPEC64, input, output);
}
@ -184,7 +184,7 @@ public class TestVectorRebracket {
}
@Test
@IR(counts = {REINTERPRET_NODE, "1"})
@IR(applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"}, counts = {REINTERPRET_NODE, "1"})
public static void testI64toF64(int[] input, float[] output) {
vectorRebracket(ISPEC64, FSPEC64, input, output);
}
@ -195,7 +195,7 @@ public class TestVectorRebracket {
}
@Test
@IR(counts = {REINTERPRET_NODE, "1"})
@IR(applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"}, counts = {REINTERPRET_NODE, "1"})
public static void testI64toD64(int[] input, double[] output) {
vectorRebracket(ISPEC64, DSPEC64, input, output);
}
@ -206,7 +206,7 @@ public class TestVectorRebracket {
}
@Test
@IR(counts = {REINTERPRET_NODE, "1"})
@IR(applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"}, counts = {REINTERPRET_NODE, "1"})
public static void testL64toB64(long[] input, byte[] output) {
vectorRebracket(LSPEC64, BSPEC64, input, output);
}
@ -217,7 +217,7 @@ public class TestVectorRebracket {
}
@Test
@IR(counts = {REINTERPRET_NODE, "1"})
@IR(applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"}, counts = {REINTERPRET_NODE, "1"})
public static void testL64toS64(long[] input, short[] output) {
vectorRebracket(LSPEC64, SSPEC64, input, output);
}
@ -228,7 +228,7 @@ public class TestVectorRebracket {
}
@Test
@IR(counts = {REINTERPRET_NODE, "1"})
@IR(applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"}, counts = {REINTERPRET_NODE, "1"})
public static void testL64toI64(long[] input, int[] output) {
vectorRebracket(LSPEC64, ISPEC64, input, output);
}
@ -239,7 +239,7 @@ public class TestVectorRebracket {
}
@Test
@IR(counts = {REINTERPRET_NODE, "1"})
@IR(applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"}, counts = {REINTERPRET_NODE, "1"})
public static void testL64toF64(long[] input, float[] output) {
vectorRebracket(LSPEC64, FSPEC64, input, output);
}
@ -250,7 +250,7 @@ public class TestVectorRebracket {
}
@Test
@IR(counts = {REINTERPRET_NODE, "1"})
@IR(applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"}, counts = {REINTERPRET_NODE, "1"})
public static void testL64toD64(long[] input, double[] output) {
vectorRebracket(LSPEC64, DSPEC64, input, output);
}
@ -261,7 +261,7 @@ public class TestVectorRebracket {
}
@Test
@IR(counts = {REINTERPRET_NODE, "1"})
@IR(applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"}, counts = {REINTERPRET_NODE, "1"})
public static void testF64toB64(float[] input, byte[] output) {
vectorRebracket(FSPEC64, BSPEC64, input, output);
}
@ -272,7 +272,7 @@ public class TestVectorRebracket {
}
@Test
@IR(counts = {REINTERPRET_NODE, "1"})
@IR(applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"}, counts = {REINTERPRET_NODE, "1"})
public static void testF64toS64(float[] input, short[] output) {
vectorRebracket(FSPEC64, SSPEC64, input, output);
}
@ -283,7 +283,7 @@ public class TestVectorRebracket {
}
@Test
@IR(counts = {REINTERPRET_NODE, "1"})
@IR(applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"}, counts = {REINTERPRET_NODE, "1"})
public static void testF64toI64(float[] input, int[] output) {
vectorRebracket(FSPEC64, ISPEC64, input, output);
}
@ -294,7 +294,7 @@ public class TestVectorRebracket {
}
@Test
@IR(counts = {REINTERPRET_NODE, "1"})
@IR(applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"}, counts = {REINTERPRET_NODE, "1"})
public static void testF64toL64(float[] input, long[] output) {
vectorRebracket(FSPEC64, LSPEC64, input, output);
}
@ -305,7 +305,7 @@ public class TestVectorRebracket {
}
@Test
@IR(counts = {REINTERPRET_NODE, "1"})
@IR(applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"}, counts = {REINTERPRET_NODE, "1"})
public static void testF64toD64(float[] input, double[] output) {
vectorRebracket(FSPEC64, DSPEC64, input, output);
}
@ -316,7 +316,7 @@ public class TestVectorRebracket {
}
@Test
@IR(counts = {REINTERPRET_NODE, "1"})
@IR(applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"}, counts = {REINTERPRET_NODE, "1"})
public static void testD64toB64(double[] input, byte[] output) {
vectorRebracket(DSPEC64, BSPEC64, input, output);
}
@ -327,7 +327,7 @@ public class TestVectorRebracket {
}
@Test
@IR(counts = {REINTERPRET_NODE, "1"})
@IR(applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"}, counts = {REINTERPRET_NODE, "1"})
public static void testD64toS64(double[] input, short[] output) {
vectorRebracket(DSPEC64, SSPEC64, input, output);
}
@ -338,7 +338,7 @@ public class TestVectorRebracket {
}
@Test
@IR(counts = {REINTERPRET_NODE, "1"})
@IR(applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"}, counts = {REINTERPRET_NODE, "1"})
public static void testD64toI64(double[] input, int[] output) {
vectorRebracket(DSPEC64, ISPEC64, input, output);
}
@ -349,7 +349,7 @@ public class TestVectorRebracket {
}
@Test
@IR(counts = {REINTERPRET_NODE, "1"})
@IR(applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"}, counts = {REINTERPRET_NODE, "1"})
public static void testD64toL64(double[] input, long[] output) {
vectorRebracket(DSPEC64, LSPEC64, input, output);
}
@ -360,7 +360,7 @@ public class TestVectorRebracket {
}
@Test
@IR(counts = {REINTERPRET_NODE, "1"})
@IR(applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"}, counts = {REINTERPRET_NODE, "1"})
public static void testD64toF64(double[] input, float[] output) {
vectorRebracket(DSPEC64, FSPEC64, input, output);
}

View File

@ -38,7 +38,7 @@ import jdk.test.lib.process.OutputAnalyzer;
* @requires vm.hasSA
* @requires vm.gc != "Z"
* @requires os.family == "linux"
* @requires os.arch == "amd64"
* @requires (os.arch == "amd64") | (os.arch == "aarch64")
* @library /test/lib
* @run driver TestJhsdbJstackMixedWithXComp
*/
@ -49,7 +49,7 @@ import jdk.test.lib.process.OutputAnalyzer;
* @requires vm.hasSA
* @requires vm.gc != "Z"
* @requires os.family == "linux"
* @requires os.arch == "amd64"
* @requires (os.arch == "amd64") | (os.arch == "aarch64")
* @library /test/lib
* @run driver TestJhsdbJstackMixedWithXComp -XX:+PreserveFramePointer
*/
@ -60,7 +60,7 @@ import jdk.test.lib.process.OutputAnalyzer;
* @requires vm.hasSA
* @requires vm.gc != "Z"
* @requires os.family == "linux"
* @requires os.arch == "amd64"
* @requires (os.arch == "amd64") | (os.arch == "aarch64")
* @library /test/lib
* @run driver TestJhsdbJstackMixedWithXComp -XX:-TieredCompilation
*/

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 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
@ -30,8 +30,8 @@
* @modules java.net.http
* java.logging
* @build ALPNFailureTest
* @run main/othervm -Djdk.internal.httpclient.debug=true ALPNFailureTest HTTP_1_1
* @run main/othervm ALPNFailureTest HTTP_2
* @run main/othervm -Djdk.internal.httpclient.debug=true ${test.main.class} HTTP_1_1
* @run main/othervm ${test.main.class} HTTP_2
*/
import javax.net.ServerSocketFactory;
import javax.net.ssl.SSLContext;

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.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -31,8 +31,8 @@
* @build jdk.test.lib.net.SimpleSSLContext DigestEchoServer
* jdk.httpclient.test.lib.common.HttpServerAdapters
* ALPNFailureTest ALPNProxyFailureTest
* @run main/othervm -Djdk.internal.httpclient.debug=true -Dtest.nolinger=true ALPNProxyFailureTest HTTP_1_1
* @run main/othervm -Dtest.nolinger=true ALPNProxyFailureTest HTTP_2
* @run main/othervm -Djdk.internal.httpclient.debug=true -Dtest.nolinger=true ${test.main.class} HTTP_1_1
* @run main/othervm -Dtest.nolinger=true ${test.main.class} HTTP_2
*/
import javax.net.ServerSocketFactory;
import javax.net.ssl.SSLContext;

View File

@ -29,7 +29,7 @@
* ReferenceTracker AggregateRequestBodyTest
* @run junit/othervm -Djdk.internal.httpclient.debug=true
* -Djdk.httpclient.HttpClient.log=requests,responses,errors,headers,frames
* AggregateRequestBodyTest
* ${test.main.class}
* @summary Tests HttpRequest.BodyPublishers::concat
*/

View File

@ -56,7 +56,7 @@ import org.junit.jupiter.api.Test;
*
* @run junit/othervm -Djdk.internal.httpclient.debug=true
* -Djdk.httpclient.HttpClient.log=requests,responses,errors
* AltServiceUsageTest
* ${test.main.class}
*/
public class AltServiceUsageTest implements HttpServerAdapters {

View File

@ -87,7 +87,7 @@ import org.junit.jupiter.params.provider.MethodSource;
* jdk.test.lib.Platform jdk.test.lib.util.FileUtils
* jdk.httpclient.test.lib.common.HttpServerAdapters
* jdk.httpclient.test.lib.common.TestServerConfigurator
* @run junit/othervm/timeout=480 AsFileDownloadTest
* @run junit/othervm/timeout=480 ${test.main.class}
*/
public class AsFileDownloadTest {

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