Compare commits

..

39 Commits

Author SHA1 Message Date
Michael McMahon
a84946dde4 8359268: 3 JNI exception pending defect groups in 2 files
Reviewed-by: dfuchs, djelinski
Backport-of: 1fa090524a
2025-06-25 16:17:18 +00:00
Igor Veresov
fdb3e37c71 8359788: Internal Error: assert(get_instanceKlass()->is_loaded()) failed: must be at least loaded
Reviewed-by: shade
Backport-of: 5c4f92ba9a
2025-06-25 16:12:45 +00:00
Hannes Wallnöfer
80cb773b7e 8328848: Inaccuracy in the documentation of the -group option
Reviewed-by: liach
Backport-of: f8de5bc582
2025-06-25 05:40:18 +00:00
Hannes Wallnöfer
a576952039 8359024: Accessibility bugs in API documentation
Reviewed-by: liach
Backport-of: 9a726df373
2025-06-25 05:36:31 +00:00
Anthony Scarpino
b89f364842 8358099: PEM spec updates
Reviewed-by: weijun
Backport-of: 78158f30ae
2025-06-24 19:32:07 +00:00
Coleen Phillimore
0694cc1d52 8352075: Perf regression accessing fields
Reviewed-by: shade, iklam
Backport-of: e18277b470
2025-06-24 17:10:28 +00:00
Markus Grönlund
a3abaadc15 8360403: Disable constant pool ID assert during troubleshooting
Reviewed-by: egahlin
Backport-of: cbcf401170
2025-06-24 16:49:43 +00:00
Aleksey Shipilev
7cc1f82b84 8360042: GHA: Bump MSVC to 14.44
Reviewed-by: serb
Backport-of: 72679c94ee
2025-06-24 05:48:20 +00:00
William Kemper
636b56374e 8357550: GenShen crashes during freeze: assert(!chunk->requires_barriers()) failed
Reviewed-by: shade
Backport-of: 17cf49746d
2025-06-23 21:03:04 +00:00
Phil Race
fe9efb75b0 8358526: Clarify behavior of java.awt.HeadlessException constructed with no-args
Reviewed-by: honkar, tr, azvegint
Backport-of: 81985d422d
2025-06-23 17:05:48 +00:00
Erik Gahlin
ca6b165003 8359895: JFR: method-timing view doesn't work
Reviewed-by: mgronlun
Backport-of: 984d7f9cdf
2025-06-23 13:09:03 +00:00
Erik Gahlin
d5aa225451 8359242: JFR: Missing help text for method trace and timing
Reviewed-by: mgronlun
Backport-of: e57a214e2a
2025-06-23 12:22:30 +00:00
Matthias Bläsing
79a85df074 8353950: Clipboard interaction on Windows is unstable
8332271: Reading data from the clipboard from multiple threads crashes the JVM

Reviewed-by: prr
Backport-of: 92be7821f5
2025-06-20 21:49:26 +00:00
Jaikiran Pai
41928aed7d 8359709: java.net.HttpURLConnection sends unexpected "Host" request header in some cases after JDK-8344190
Reviewed-by: dfuchs
Backport-of: 57266064a7
2025-06-20 09:47:26 +00:00
Tobias Hartmann
3f6b0c69c3 8359386: Fix incorrect value for max_size of C2CodeStub when APX is used
Reviewed-by: mhaessig, epeter
Backport-of: b52af182c4
2025-06-20 08:29:10 +00:00
SendaoYan
36b185a930 8359402: Test CloseDescriptors.java should throw SkippedException when there is no lsof/sctp
Reviewed-by: jpai
Backport-of: a16d23557b
2025-06-20 06:26:52 +00:00
Erik Gahlin
c832f001e4 8359593: JFR: Instrumentation of java.lang.String corrupts recording
Reviewed-by: mgronlun
Backport-of: 2f2acb2e3f
2025-06-19 14:19:16 +00:00
Vladimir Kozlov
e5ac75a35b 8359646: C1 crash in AOTCodeAddressTable::add_C_string
Reviewed-by: shade, thartmann
Backport-of: 96070212ad
2025-06-19 13:41:06 +00:00
Erik Gahlin
b79ca5f03b 8359248: JFR: Help text for-XX:StartFlightRecording:report-on-exit should explain option can be repeated
Reviewed-by: mgronlun
Backport-of: fedd0a0ee3
2025-06-19 12:56:19 +00:00
Stuart Marks
5bcea92eaa 8338140: (str) Add notes to String.trim and String.isEmpty pointing to newer APIs
Reviewed-by: naoto, bpb, liach
Backport-of: 06d804a0f0
2025-06-17 20:45:27 +00:00
Damon Fenacci
cc4e9716ac 8358129: compiler/startup/StartupOutput.java runs into out of memory on Windows after JDK-8347406
Reviewed-by: shade
Backport-of: 534a8605e5
2025-06-17 13:10:06 +00:00
Roland Westrelin
46cfc1e194 8358334: C2/Shenandoah: incorrect execution with Unsafe
Reviewed-by: thartmann
Backport-of: 1fcede053c
2025-06-17 08:06:58 +00:00
Rajan Halade
ae71782e77 8359170: Add 2 TLS and 2 CS Sectigo roots
Reviewed-by: mullan
Backport-of: 9586817cea
2025-06-17 06:10:35 +00:00
Ioi Lam
753700182d 8355556: JVM crash because archived method handle intrinsics are not restored
Reviewed-by: shade
Backport-of: 366650a438
2025-06-17 04:36:41 +00:00
SendaoYan
eb727dcb51 8359272: Several vmTestbase/compact tests timed out on large memory machine
Reviewed-by: ayang
Backport-of: a0fb35c837
2025-06-17 00:43:52 +00:00
Johannes Bechberger
b6cacfcbc8 8359135: New test TestCPUTimeSampleThrottling fails intermittently
Reviewed-by: mdoerr
Backport-of: 3f0fef2c9c
2025-06-16 16:20:54 +00:00
Hamlin Li
d870a48880 8358892: RISC-V: jvm crash when running dacapo sunflow after JDK-8352504
8359045: RISC-V: construct test to verify invocation of C2_MacroAssembler::enc_cmove_cmp_fp => BoolTest::ge/gt

Reviewed-by: fyang
Backport-of: 9d060574e5
2025-06-16 11:18:32 +00:00
Fernando Guallini
2ea2f74f92 8358171: Additional code coverage for PEM API
Reviewed-by: rhalade, ascarpino
Backport-of: b2e7cda6a0
2025-06-16 09:54:18 +00:00
Alan Bateman
077ce2edc7 8358764: (sc) SocketChannel.close when thread blocked in read causes connection to be reset (win)
Reviewed-by: iris, jpai
Backport-of: e5196fc24d
2025-06-16 09:19:56 +00:00
Tobias Hartmann
2a3294571a 8359327: Incorrect AVX3Threshold results into code buffer overflows on APX targets
Reviewed-by: chagedorn
Backport-of: e7f63ba310
2025-06-16 08:48:49 +00:00
SendaoYan
3877746eb9 8359181: Error messages generated by configure --help after 8301197
Reviewed-by: ihse
Backport-of: 7b7136b4ec
2025-06-15 12:25:17 +00:00
Tobias Hartmann
3bd80fe3ba 8357782: JVM JIT Causes Static Initialization Order Issue
Reviewed-by: shade
Backport-of: e8ef93ae9d
2025-06-15 09:05:56 +00:00
Tobias Hartmann
03232d4a5d 8359200: Memory corruption in MStack::push
Reviewed-by: epeter, shade
Backport-of: ed39e17e34
2025-06-15 09:04:55 +00:00
Daniel Fuchs
4111730845 8359364: java/net/URL/EarlyOrDelayedParsing test fails intermittently
Reviewed-by: alanb
Backport-of: 57cabc6d74
2025-06-13 16:54:40 +00:00
Kevin Walls
74ea38e406 8358701: Remove misleading javax.management.remote API doc wording about JMX spec, and historic link to JMXMP
Reviewed-by: alanb
Backport-of: 66535fe26d
2025-06-13 14:28:14 +00:00
Tobias Hartmann
839a91e14b 8357982: Fix several failing BMI tests with -XX:+UseAPX
Reviewed-by: chagedorn
Backport-of: c98dffa186
2025-06-12 11:11:41 +00:00
Daniel Fuchs
aa4f79eaec 8358617: java/net/HttpURLConnection/HttpURLConnectionExpectContinueTest.java fails with 403 due to system proxies
Reviewed-by: jpai
Backport-of: a377773fa7
2025-06-11 16:22:34 +00:00
Stuart Marks
c7df72ff0f 8358809: Improve link to stdin.encoding from java.lang.IO
Reviewed-by: naoto
Backport-of: d024f58e61
2025-06-07 00:56:45 +00:00
Rajan Halade
80e066e733 8345414: Google CAInterop test failures
Reviewed-by: weijun
Backport-of: 8e9ba788ae
2025-06-06 21:31:33 +00:00
200 changed files with 4552 additions and 2472 deletions

View File

@@ -310,7 +310,7 @@ jobs:
uses: ./.github/workflows/build-windows.yml
with:
platform: windows-x64
msvc-toolset-version: '14.43'
msvc-toolset-version: '14.44'
msvc-toolset-architecture: 'x86.x64'
configure-arguments: ${{ github.event.inputs.configure-arguments }}
make-arguments: ${{ github.event.inputs.make-arguments }}
@@ -322,7 +322,7 @@ jobs:
uses: ./.github/workflows/build-windows.yml
with:
platform: windows-aarch64
msvc-toolset-version: '14.43'
msvc-toolset-version: '14.44'
msvc-toolset-architecture: 'arm64'
make-target: 'hotspot'
extra-conf-options: '--openjdk-target=aarch64-unknown-cygwin'

View File

@@ -1,7 +1,7 @@
[general]
project=jdk
jbs=JDK
version=26
version=25
[checks]
error=author,committer,reviewers,merge,issues,executable,symlink,message,hg-tag,whitespace,problemlists,copyright

View File

@@ -1,6 +1,6 @@
#!/bin/bash
#
# Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2012, 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
@@ -366,7 +366,7 @@ EOT
# Print additional help, e.g. a list of toolchains and JVM features.
# This must be done by the autoconf script.
( CONFIGURE_PRINT_ADDITIONAL_HELP=true . $generated_script PRINTF=printf )
( CONFIGURE_PRINT_ADDITIONAL_HELP=true . $generated_script PRINTF=printf ECHO=echo )
cat <<EOT

View File

@@ -26,17 +26,17 @@
# Default version, product, and vendor information to use,
# unless overridden by configure
DEFAULT_VERSION_FEATURE=26
DEFAULT_VERSION_FEATURE=25
DEFAULT_VERSION_INTERIM=0
DEFAULT_VERSION_UPDATE=0
DEFAULT_VERSION_PATCH=0
DEFAULT_VERSION_EXTRA1=0
DEFAULT_VERSION_EXTRA2=0
DEFAULT_VERSION_EXTRA3=0
DEFAULT_VERSION_DATE=2026-03-17
DEFAULT_VERSION_CLASSFILE_MAJOR=70 # "`$EXPR $DEFAULT_VERSION_FEATURE + 44`"
DEFAULT_VERSION_DATE=2025-09-16
DEFAULT_VERSION_CLASSFILE_MAJOR=69 # "`$EXPR $DEFAULT_VERSION_FEATURE + 44`"
DEFAULT_VERSION_CLASSFILE_MINOR=0
DEFAULT_VERSION_DOCS_API_SINCE=11
DEFAULT_ACCEPTABLE_BOOT_VERSIONS="24 25 26"
DEFAULT_JDK_SOURCE_TARGET_VERSION=26
DEFAULT_ACCEPTABLE_BOOT_VERSIONS="24 25"
DEFAULT_JDK_SOURCE_TARGET_VERSION=25
DEFAULT_PROMOTED_VERSION_PRE=ea

View File

@@ -2170,15 +2170,13 @@ void C2_MacroAssembler::enc_cmove_cmp_fp(int cmpFlag, FloatRegister op1, FloatRe
cmov_cmp_fp_le(op1, op2, dst, src, is_single);
break;
case BoolTest::ge:
assert(false, "Should go to BoolTest::le case");
ShouldNotReachHere();
cmov_cmp_fp_ge(op1, op2, dst, src, is_single);
break;
case BoolTest::lt:
cmov_cmp_fp_lt(op1, op2, dst, src, is_single);
break;
case BoolTest::gt:
assert(false, "Should go to BoolTest::lt case");
ShouldNotReachHere();
cmov_cmp_fp_gt(op1, op2, dst, src, is_single);
break;
default:
assert(false, "unsupported compare condition");

View File

@@ -1268,12 +1268,19 @@ void MacroAssembler::cmov_gtu(Register cmp1, Register cmp2, Register dst, Regist
}
// ----------- cmove, compare float -----------
//
// For CmpF/D + CMoveI/L, ordered ones are quite straight and simple,
// so, just list behaviour of unordered ones as follow.
//
// Set dst (CMoveI (Binary cop (CmpF/D op1 op2)) (Binary dst src))
// (If one or both inputs to the compare are NaN, then)
// 1. (op1 lt op2) => true => CMove: dst = src
// 2. (op1 le op2) => true => CMove: dst = src
// 3. (op1 gt op2) => false => CMove: dst = dst
// 4. (op1 ge op2) => false => CMove: dst = dst
// 5. (op1 eq op2) => false => CMove: dst = dst
// 6. (op1 ne op2) => true => CMove: dst = src
// Move src to dst only if cmp1 == cmp2,
// otherwise leave dst unchanged, including the case where one of them is NaN.
// Clarification:
// java code : cmp1 != cmp2 ? dst : src
// transformed to : CMove dst, (cmp1 eq cmp2), dst, src
void MacroAssembler::cmov_cmp_fp_eq(FloatRegister cmp1, FloatRegister cmp2, Register dst, Register src, bool is_single) {
if (UseZicond) {
if (is_single) {
@@ -1289,7 +1296,7 @@ void MacroAssembler::cmov_cmp_fp_eq(FloatRegister cmp1, FloatRegister cmp2, Regi
Label no_set;
if (is_single) {
// jump if cmp1 != cmp2, including the case of NaN
// not jump (i.e. move src to dst) if cmp1 == cmp2
// fallthrough (i.e. move src to dst) if cmp1 == cmp2
float_bne(cmp1, cmp2, no_set);
} else {
double_bne(cmp1, cmp2, no_set);
@@ -1298,11 +1305,6 @@ void MacroAssembler::cmov_cmp_fp_eq(FloatRegister cmp1, FloatRegister cmp2, Regi
bind(no_set);
}
// Keep dst unchanged only if cmp1 == cmp2,
// otherwise move src to dst, including the case where one of them is NaN.
// Clarification:
// java code : cmp1 == cmp2 ? dst : src
// transformed to : CMove dst, (cmp1 ne cmp2), dst, src
void MacroAssembler::cmov_cmp_fp_ne(FloatRegister cmp1, FloatRegister cmp2, Register dst, Register src, bool is_single) {
if (UseZicond) {
if (is_single) {
@@ -1318,7 +1320,7 @@ void MacroAssembler::cmov_cmp_fp_ne(FloatRegister cmp1, FloatRegister cmp2, Regi
Label no_set;
if (is_single) {
// jump if cmp1 == cmp2
// not jump (i.e. move src to dst) if cmp1 != cmp2, including the case of NaN
// fallthrough (i.e. move src to dst) if cmp1 != cmp2, including the case of NaN
float_beq(cmp1, cmp2, no_set);
} else {
double_beq(cmp1, cmp2, no_set);
@@ -1327,14 +1329,6 @@ void MacroAssembler::cmov_cmp_fp_ne(FloatRegister cmp1, FloatRegister cmp2, Regi
bind(no_set);
}
// When cmp1 <= cmp2 or any of them is NaN then dst = src, otherwise, dst = dst
// Clarification
// scenario 1:
// java code : cmp2 < cmp1 ? dst : src
// transformed to : CMove dst, (cmp1 le cmp2), dst, src
// scenario 2:
// java code : cmp1 > cmp2 ? dst : src
// transformed to : CMove dst, (cmp1 le cmp2), dst, src
void MacroAssembler::cmov_cmp_fp_le(FloatRegister cmp1, FloatRegister cmp2, Register dst, Register src, bool is_single) {
if (UseZicond) {
if (is_single) {
@@ -1350,7 +1344,7 @@ void MacroAssembler::cmov_cmp_fp_le(FloatRegister cmp1, FloatRegister cmp2, Regi
Label no_set;
if (is_single) {
// jump if cmp1 > cmp2
// not jump (i.e. move src to dst) if cmp1 <= cmp2 or either is NaN
// fallthrough (i.e. move src to dst) if cmp1 <= cmp2 or either is NaN
float_bgt(cmp1, cmp2, no_set);
} else {
double_bgt(cmp1, cmp2, no_set);
@@ -1359,14 +1353,30 @@ void MacroAssembler::cmov_cmp_fp_le(FloatRegister cmp1, FloatRegister cmp2, Regi
bind(no_set);
}
// When cmp1 < cmp2 or any of them is NaN then dst = src, otherwise, dst = dst
// Clarification
// scenario 1:
// java code : cmp2 <= cmp1 ? dst : src
// transformed to : CMove dst, (cmp1 lt cmp2), dst, src
// scenario 2:
// java code : cmp1 >= cmp2 ? dst : src
// transformed to : CMove dst, (cmp1 lt cmp2), dst, src
void MacroAssembler::cmov_cmp_fp_ge(FloatRegister cmp1, FloatRegister cmp2, Register dst, Register src, bool is_single) {
if (UseZicond) {
if (is_single) {
fle_s(t0, cmp2, cmp1);
} else {
fle_d(t0, cmp2, cmp1);
}
czero_nez(dst, dst, t0);
czero_eqz(t0 , src, t0);
orr(dst, dst, t0);
return;
}
Label no_set;
if (is_single) {
// jump if cmp1 < cmp2 or either is NaN
// fallthrough (i.e. move src to dst) if cmp1 >= cmp2
float_blt(cmp1, cmp2, no_set, false, true);
} else {
double_blt(cmp1, cmp2, no_set, false, true);
}
mv(dst, src);
bind(no_set);
}
void MacroAssembler::cmov_cmp_fp_lt(FloatRegister cmp1, FloatRegister cmp2, Register dst, Register src, bool is_single) {
if (UseZicond) {
if (is_single) {
@@ -1382,7 +1392,7 @@ void MacroAssembler::cmov_cmp_fp_lt(FloatRegister cmp1, FloatRegister cmp2, Regi
Label no_set;
if (is_single) {
// jump if cmp1 >= cmp2
// not jump (i.e. move src to dst) if cmp1 < cmp2 or either is NaN
// fallthrough (i.e. move src to dst) if cmp1 < cmp2 or either is NaN
float_bge(cmp1, cmp2, no_set);
} else {
double_bge(cmp1, cmp2, no_set);
@@ -1391,6 +1401,30 @@ void MacroAssembler::cmov_cmp_fp_lt(FloatRegister cmp1, FloatRegister cmp2, Regi
bind(no_set);
}
void MacroAssembler::cmov_cmp_fp_gt(FloatRegister cmp1, FloatRegister cmp2, Register dst, Register src, bool is_single) {
if (UseZicond) {
if (is_single) {
flt_s(t0, cmp2, cmp1);
} else {
flt_d(t0, cmp2, cmp1);
}
czero_nez(dst, dst, t0);
czero_eqz(t0 , src, t0);
orr(dst, dst, t0);
return;
}
Label no_set;
if (is_single) {
// jump if cmp1 <= cmp2 or either is NaN
// fallthrough (i.e. move src to dst) if cmp1 > cmp2
float_ble(cmp1, cmp2, no_set, false, true);
} else {
double_ble(cmp1, cmp2, no_set, false, true);
}
mv(dst, src);
bind(no_set);
}
// Float compare branch instructions
#define INSN(NAME, FLOATCMP, BRANCH) \

View File

@@ -660,7 +660,9 @@ class MacroAssembler: public Assembler {
void cmov_cmp_fp_eq(FloatRegister cmp1, FloatRegister cmp2, Register dst, Register src, bool is_single);
void cmov_cmp_fp_ne(FloatRegister cmp1, FloatRegister cmp2, Register dst, Register src, bool is_single);
void cmov_cmp_fp_le(FloatRegister cmp1, FloatRegister cmp2, Register dst, Register src, bool is_single);
void cmov_cmp_fp_ge(FloatRegister cmp1, FloatRegister cmp2, Register dst, Register src, bool is_single);
void cmov_cmp_fp_lt(FloatRegister cmp1, FloatRegister cmp2, Register dst, Register src, bool is_single);
void cmov_cmp_fp_gt(FloatRegister cmp1, FloatRegister cmp2, Register dst, Register src, bool is_single);
public:
// We try to follow risc-v asm menomics.

View File

@@ -4655,6 +4655,7 @@ static void convertF2I_slowpath(C2_MacroAssembler& masm, C2GeneralStub<Register,
__ subptr(rsp, 8);
__ movdbl(Address(rsp), src);
__ call(RuntimeAddress(target));
// APX REX2 encoding for pop(dst) increases the stub size by 1 byte.
__ pop(dst);
__ jmp(stub.continuation());
#undef __
@@ -4687,7 +4688,9 @@ void C2_MacroAssembler::convertF2I(BasicType dst_bt, BasicType src_bt, Register
}
}
auto stub = C2CodeStub::make<Register, XMMRegister, address>(dst, src, slowpath_target, 23, convertF2I_slowpath);
// Using the APX extended general purpose registers increases the instruction encoding size by 1 byte.
int max_size = 23 + (UseAPX ? 1 : 0);
auto stub = C2CodeStub::make<Register, XMMRegister, address>(dst, src, slowpath_target, max_size, convertF2I_slowpath);
jcc(Assembler::equal, stub->entry());
bind(stub->continuation());
}

View File

@@ -239,7 +239,7 @@
do_arch_blob, \
do_arch_entry, \
do_arch_entry_init) \
do_arch_blob(final, 31000 \
do_arch_blob(final, 33000 \
WINDOWS_ONLY(+22000) ZGC_ONLY(+20000)) \
#endif // CPU_X86_STUBDECLARATIONS_HPP

View File

@@ -2111,7 +2111,7 @@ bool VM_Version::is_intel_cascade_lake() {
// has improved implementation of 64-byte load/stores and so the default
// threshold is set to 0 for these platforms.
int VM_Version::avx3_threshold() {
return (is_intel_family_core() &&
return (is_intel_server_family() &&
supports_serialize() &&
FLAG_IS_DEFAULT(AVX3Threshold)) ? 0 : AVX3Threshold;
}

View File

@@ -10527,7 +10527,8 @@ instruct xorI_rReg_im1_ndd(rRegI dst, rRegI src, immI_M1 imm)
// Xor Register with Immediate
instruct xorI_rReg_imm(rRegI dst, immI src, rFlagsReg cr)
%{
predicate(!UseAPX);
// Strict predicate check to make selection of xorI_rReg_im1 cost agnostic if immI src is -1.
predicate(!UseAPX && n->in(2)->bottom_type()->is_int()->get_con() != -1);
match(Set dst (XorI dst src));
effect(KILL cr);
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
@@ -10541,7 +10542,8 @@ instruct xorI_rReg_imm(rRegI dst, immI src, rFlagsReg cr)
instruct xorI_rReg_rReg_imm_ndd(rRegI dst, rRegI src1, immI src2, rFlagsReg cr)
%{
predicate(UseAPX);
// Strict predicate check to make selection of xorI_rReg_im1_ndd cost agnostic if immI src2 is -1.
predicate(UseAPX && n->in(2)->bottom_type()->is_int()->get_con() != -1);
match(Set dst (XorI src1 src2));
effect(KILL cr);
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
@@ -10559,6 +10561,7 @@ instruct xorI_rReg_mem_imm_ndd(rRegI dst, memory src1, immI src2, rFlagsReg cr)
predicate(UseAPX);
match(Set dst (XorI (LoadI src1) src2));
effect(KILL cr);
ins_cost(150);
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
format %{ "exorl $dst, $src1, $src2\t# int ndd" %}
@@ -11201,7 +11204,8 @@ instruct xorL_rReg_im1_ndd(rRegL dst,rRegL src, immL_M1 imm)
// Xor Register with Immediate
instruct xorL_rReg_imm(rRegL dst, immL32 src, rFlagsReg cr)
%{
predicate(!UseAPX);
// Strict predicate check to make selection of xorL_rReg_im1 cost agnostic if immL32 src is -1.
predicate(!UseAPX && n->in(2)->bottom_type()->is_long()->get_con() != -1L);
match(Set dst (XorL dst src));
effect(KILL cr);
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
@@ -11215,7 +11219,8 @@ instruct xorL_rReg_imm(rRegL dst, immL32 src, rFlagsReg cr)
instruct xorL_rReg_rReg_imm(rRegL dst, rRegL src1, immL32 src2, rFlagsReg cr)
%{
predicate(UseAPX);
// Strict predicate check to make selection of xorL_rReg_im1_ndd cost agnostic if immL32 src2 is -1.
predicate(UseAPX && n->in(2)->bottom_type()->is_long()->get_con() != -1L);
match(Set dst (XorL src1 src2));
effect(KILL cr);
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
@@ -11234,6 +11239,7 @@ instruct xorL_rReg_mem_imm(rRegL dst, memory src1, immL32 src2, rFlagsReg cr)
match(Set dst (XorL (LoadL src1) src2));
effect(KILL cr);
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
ins_cost(150);
format %{ "exorq $dst, $src1, $src2\t# long ndd" %}
ins_encode %{

View File

@@ -818,7 +818,7 @@ JRT_ENTRY(void, Runtime1::deoptimize(JavaThread* current, jint trap_request))
Deoptimization::DeoptReason reason = Deoptimization::trap_request_reason(trap_request);
if (action == Deoptimization::Action_make_not_entrant) {
if (nm->make_not_entrant(nmethod::ChangeReason::C1_deoptimize)) {
if (nm->make_not_entrant("C1 deoptimize")) {
if (reason == Deoptimization::Reason_tenured) {
MethodData* trap_mdo = Deoptimization::get_method_data(current, method, true /*create_if_missing*/);
if (trap_mdo != nullptr) {
@@ -1110,7 +1110,7 @@ JRT_ENTRY(void, Runtime1::patch_code(JavaThread* current, C1StubId stub_id ))
// safepoint, but if it's still alive then make it not_entrant.
nmethod* nm = CodeCache::find_nmethod(caller_frame.pc());
if (nm != nullptr) {
nm->make_not_entrant(nmethod::ChangeReason::C1_codepatch);
nm->make_not_entrant("C1 code patch");
}
Deoptimization::deoptimize_frame(current, caller_frame.id());
@@ -1358,7 +1358,7 @@ void Runtime1::patch_code(JavaThread* current, C1StubId stub_id) {
// Make sure the nmethod is invalidated, i.e. made not entrant.
nmethod* nm = CodeCache::find_nmethod(caller_frame.pc());
if (nm != nullptr) {
nm->make_not_entrant(nmethod::ChangeReason::C1_deoptimize_for_patching);
nm->make_not_entrant("C1 deoptimize for patching");
}
}
@@ -1486,7 +1486,7 @@ JRT_ENTRY(void, Runtime1::predicate_failed_trap(JavaThread* current))
nmethod* nm = CodeCache::find_nmethod(caller_frame.pc());
assert (nm != nullptr, "no more nmethod?");
nm->make_not_entrant(nmethod::ChangeReason::C1_predicate_failed_trap);
nm->make_not_entrant("C1 predicate failed trap");
methodHandle m(current, nm->method());
MethodData* mdo = m->method_data();

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 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
@@ -187,7 +187,13 @@ class ValueNumberingVisitor: public InstructionVisitor {
void do_Convert (Convert* x) { /* nothing to do */ }
void do_NullCheck (NullCheck* x) { /* nothing to do */ }
void do_TypeCast (TypeCast* x) { /* nothing to do */ }
void do_NewInstance (NewInstance* x) { /* nothing to do */ }
void do_NewInstance (NewInstance* x) {
ciInstanceKlass* c = x->klass();
if (c != nullptr && !c->is_initialized() &&
(!c->is_loaded() || c->has_class_initializer())) {
kill_memory();
}
}
void do_NewTypeArray (NewTypeArray* x) { /* nothing to do */ }
void do_NewObjectArray (NewObjectArray* x) { /* nothing to do */ }
void do_NewMultiArray (NewMultiArray* x) { /* nothing to do */ }

View File

@@ -549,6 +549,11 @@ bool ciInstanceKlass::compute_has_trusted_loader() {
return java_lang_ClassLoader::is_trusted_loader(loader_oop);
}
bool ciInstanceKlass::has_class_initializer() {
VM_ENTRY_MARK;
return get_instanceKlass()->class_initializer() != nullptr;
}
// ------------------------------------------------------------------
// ciInstanceKlass::find_method
//

View File

@@ -231,6 +231,8 @@ public:
ciInstanceKlass* unique_concrete_subklass();
bool has_finalizable_subclass();
bool has_class_initializer();
bool contains_field_offset(int offset);
// Get the instance of java.lang.Class corresponding to

View File

@@ -802,7 +802,7 @@ class CompileReplay : public StackObj {
// Make sure the existence of a prior compile doesn't stop this one
nmethod* nm = (entry_bci != InvocationEntryBci) ? method->lookup_osr_nmethod_for(entry_bci, comp_level, true) : method->code();
if (nm != nullptr) {
nm->make_not_entrant(nmethod::ChangeReason::CI_replay);
nm->make_not_entrant("CI replay");
}
replay_state = this;
CompileBroker::compile_method(methodHandle(THREAD, method), entry_bci, comp_level,

View File

@@ -154,8 +154,6 @@
#define JAVA_25_VERSION 69
#define JAVA_26_VERSION 70
void ClassFileParser::set_class_bad_constant_seen(short bad_constant) {
assert((bad_constant == JVM_CONSTANT_Module ||
bad_constant == JVM_CONSTANT_Package) && _major_version >= JAVA_9_VERSION,
@@ -3740,6 +3738,7 @@ void ClassFileParser::apply_parsed_class_metadata(
_cp->set_pool_holder(this_klass);
this_klass->set_constants(_cp);
this_klass->set_fieldinfo_stream(_fieldinfo_stream);
this_klass->set_fieldinfo_search_table(_fieldinfo_search_table);
this_klass->set_fields_status(_fields_status);
this_klass->set_methods(_methods);
this_klass->set_inner_classes(_inner_classes);
@@ -3749,6 +3748,8 @@ void ClassFileParser::apply_parsed_class_metadata(
this_klass->set_permitted_subclasses(_permitted_subclasses);
this_klass->set_record_components(_record_components);
DEBUG_ONLY(FieldInfoStream::validate_search_table(_cp, _fieldinfo_stream, _fieldinfo_search_table));
// Delay the setting of _local_interfaces and _transitive_interfaces until after
// initialize_supers() in fill_instance_klass(). It is because the _local_interfaces could
// be shared with _transitive_interfaces and _transitive_interfaces may be shared with
@@ -5056,6 +5057,7 @@ void ClassFileParser::fill_instance_klass(InstanceKlass* ik,
// note that is not safe to use the fields in the parser from this point on
assert(nullptr == _cp, "invariant");
assert(nullptr == _fieldinfo_stream, "invariant");
assert(nullptr == _fieldinfo_search_table, "invariant");
assert(nullptr == _fields_status, "invariant");
assert(nullptr == _methods, "invariant");
assert(nullptr == _inner_classes, "invariant");
@@ -5276,6 +5278,7 @@ ClassFileParser::ClassFileParser(ClassFileStream* stream,
_super_klass(),
_cp(nullptr),
_fieldinfo_stream(nullptr),
_fieldinfo_search_table(nullptr),
_fields_status(nullptr),
_methods(nullptr),
_inner_classes(nullptr),
@@ -5352,6 +5355,7 @@ void ClassFileParser::clear_class_metadata() {
// deallocated if classfile parsing returns an error.
_cp = nullptr;
_fieldinfo_stream = nullptr;
_fieldinfo_search_table = nullptr;
_fields_status = nullptr;
_methods = nullptr;
_inner_classes = nullptr;
@@ -5374,6 +5378,7 @@ ClassFileParser::~ClassFileParser() {
if (_fieldinfo_stream != nullptr) {
MetadataFactory::free_array<u1>(_loader_data, _fieldinfo_stream);
}
MetadataFactory::free_array<u1>(_loader_data, _fieldinfo_search_table);
if (_fields_status != nullptr) {
MetadataFactory::free_array<FieldStatus>(_loader_data, _fields_status);
@@ -5774,6 +5779,7 @@ void ClassFileParser::post_process_parsed_stream(const ClassFileStream* const st
_fieldinfo_stream =
FieldInfoStream::create_FieldInfoStream(_temp_field_info, _java_fields_count,
injected_fields_count, loader_data(), CHECK);
_fieldinfo_search_table = FieldInfoStream::create_search_table(_cp, _fieldinfo_stream, _loader_data, CHECK);
_fields_status =
MetadataFactory::new_array<FieldStatus>(_loader_data, _temp_field_info->length(),
FieldStatus(0), CHECK);

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 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
@@ -123,6 +123,7 @@ class ClassFileParser {
const InstanceKlass* _super_klass;
ConstantPool* _cp;
Array<u1>* _fieldinfo_stream;
Array<u1>* _fieldinfo_search_table;
Array<FieldStatus>* _fields_status;
Array<Method*>* _methods;
Array<u2>* _inner_classes;

View File

@@ -301,7 +301,7 @@ void FieldLayout::reconstruct_layout(const InstanceKlass* ik, bool& has_instance
BasicType last_type;
int last_offset = -1;
while (ik != nullptr) {
for (AllFieldStream fs(ik->fieldinfo_stream(), ik->constants()); !fs.done(); fs.next()) {
for (AllFieldStream fs(ik); !fs.done(); fs.next()) {
BasicType type = Signature::basic_type(fs.signature());
// distinction between static and non-static fields is missing
if (fs.access_flags().is_static()) continue;
@@ -461,7 +461,7 @@ void FieldLayout::print(outputStream* output, bool is_static, const InstanceKlas
bool found = false;
const InstanceKlass* ik = super;
while (!found && ik != nullptr) {
for (AllFieldStream fs(ik->fieldinfo_stream(), ik->constants()); !fs.done(); fs.next()) {
for (AllFieldStream fs(ik); !fs.done(); fs.next()) {
if (fs.offset() == b->offset()) {
output->print_cr(" @%d \"%s\" %s %d/%d %s",
b->offset(),

View File

@@ -967,6 +967,13 @@ void java_lang_Class::fixup_mirror(Klass* k, TRAPS) {
Array<u1>* new_fis = FieldInfoStream::create_FieldInfoStream(fields, java_fields, injected_fields, k->class_loader_data(), CHECK);
ik->set_fieldinfo_stream(new_fis);
MetadataFactory::free_array<u1>(k->class_loader_data(), old_stream);
Array<u1>* old_table = ik->fieldinfo_search_table();
Array<u1>* search_table = FieldInfoStream::create_search_table(ik->constants(), new_fis, k->class_loader_data(), CHECK);
ik->set_fieldinfo_search_table(search_table);
MetadataFactory::free_array<u1>(k->class_loader_data(), old_table);
DEBUG_ONLY(FieldInfoStream::validate_search_table(ik->constants(), new_fis, search_table));
}
}

View File

@@ -344,6 +344,7 @@ AOTCodeCache::~AOTCodeCache() {
_store_buffer = nullptr;
}
if (_table != nullptr) {
MutexLocker ml(AOTCodeCStrings_lock, Mutex::_no_safepoint_check_flag);
delete _table;
_table = nullptr;
}
@@ -774,6 +775,9 @@ bool AOTCodeCache::store_code_blob(CodeBlob& blob, AOTCodeEntry::Kind entry_kind
// we need to take a lock to prevent race between compiler threads generating AOT code
// and the main thread generating adapter
MutexLocker ml(Compile_lock);
if (!is_on()) {
return false; // AOT code cache was already dumped and closed.
}
if (!cache->align_write()) {
return false;
}
@@ -1485,6 +1489,7 @@ void AOTCodeCache::load_strings() {
int AOTCodeCache::store_strings() {
if (_C_strings_used > 0) {
MutexLocker ml(AOTCodeCStrings_lock, Mutex::_no_safepoint_check_flag);
uint offset = _write_position;
uint length = 0;
uint* lengths = (uint *)reserve_bytes(sizeof(uint) * _C_strings_used);
@@ -1510,15 +1515,17 @@ int AOTCodeCache::store_strings() {
const char* AOTCodeCache::add_C_string(const char* str) {
if (is_on_for_dump() && str != nullptr) {
return _cache->_table->add_C_string(str);
MutexLocker ml(AOTCodeCStrings_lock, Mutex::_no_safepoint_check_flag);
AOTCodeAddressTable* table = addr_table();
if (table != nullptr) {
return table->add_C_string(str);
}
}
return str;
}
const char* AOTCodeAddressTable::add_C_string(const char* str) {
if (_extrs_complete) {
LogStreamHandle(Trace, aot, codecache, stringtable) log; // ctor outside lock
MutexLocker ml(AOTCodeCStrings_lock, Mutex::_no_safepoint_check_flag);
// Check previous strings address
for (int i = 0; i < _C_strings_count; i++) {
if (_C_strings_in[i] == str) {
@@ -1535,9 +1542,7 @@ const char* AOTCodeAddressTable::add_C_string(const char* str) {
_C_strings_in[_C_strings_count] = str;
const char* dup = os::strdup(str);
_C_strings[_C_strings_count++] = dup;
if (log.is_enabled()) {
log.print_cr("add_C_string: [%d] " INTPTR_FORMAT " '%s'", _C_strings_count, p2i(dup), dup);
}
log_trace(aot, codecache, stringtable)("add_C_string: [%d] " INTPTR_FORMAT " '%s'", _C_strings_count, p2i(dup), dup);
return dup;
} else {
assert(false, "Number of C strings >= MAX_STR_COUNT");

View File

@@ -1361,7 +1361,7 @@ void CodeCache::make_marked_nmethods_deoptimized() {
while(iter.next()) {
nmethod* nm = iter.method();
if (nm->is_marked_for_deoptimization() && !nm->has_been_deoptimized() && nm->can_be_deoptimized()) {
nm->make_not_entrant(nmethod::ChangeReason::marked_for_deoptimization);
nm->make_not_entrant("marked for deoptimization");
nm->make_deoptimized();
}
}

View File

@@ -1975,12 +1975,14 @@ void nmethod::invalidate_osr_method() {
}
}
void nmethod::log_state_change(ChangeReason change_reason) const {
void nmethod::log_state_change(const char* reason) const {
assert(reason != nullptr, "Must provide a reason");
if (LogCompilation) {
if (xtty != nullptr) {
ttyLocker ttyl; // keep the following output all in one block
xtty->begin_elem("make_not_entrant thread='%zu' reason='%s'",
os::current_thread_id(), change_reason_to_string(change_reason));
os::current_thread_id(), reason);
log_identity(xtty);
xtty->stamp();
xtty->end_elem();
@@ -1989,7 +1991,7 @@ void nmethod::log_state_change(ChangeReason change_reason) const {
ResourceMark rm;
stringStream ss(NEW_RESOURCE_ARRAY(char, 256), 256);
ss.print("made not entrant: %s", change_reason_to_string(change_reason));
ss.print("made not entrant: %s", reason);
CompileTask::print_ul(this, ss.freeze());
if (PrintCompilation) {
@@ -2004,7 +2006,9 @@ void nmethod::unlink_from_method() {
}
// Invalidate code
bool nmethod::make_not_entrant(ChangeReason change_reason) {
bool nmethod::make_not_entrant(const char* reason) {
assert(reason != nullptr, "Must provide a reason");
// This can be called while the system is already at a safepoint which is ok
NoSafepointVerifier nsv;
@@ -2073,7 +2077,7 @@ bool nmethod::make_not_entrant(ChangeReason change_reason) {
assert(success, "Transition can't fail");
// Log the transition once
log_state_change(change_reason);
log_state_change(reason);
// Remove nmethod from method.
unlink_from_method();

View File

@@ -471,85 +471,6 @@ class nmethod : public CodeBlob {
void oops_do_set_strong_done(nmethod* old_head);
public:
enum class ChangeReason : u1 {
C1_codepatch,
C1_deoptimize,
C1_deoptimize_for_patching,
C1_predicate_failed_trap,
CI_replay,
JVMCI_invalidate_nmethod,
JVMCI_invalidate_nmethod_mirror,
JVMCI_materialize_virtual_object,
JVMCI_new_installation,
JVMCI_register_method,
JVMCI_replacing_with_new_code,
JVMCI_reprofile,
marked_for_deoptimization,
missing_exception_handler,
not_used,
OSR_invalidation_back_branch,
OSR_invalidation_for_compiling_with_C1,
OSR_invalidation_of_lower_level,
set_native_function,
uncommon_trap,
whitebox_deoptimization,
zombie,
};
static const char* change_reason_to_string(ChangeReason change_reason) {
switch (change_reason) {
case ChangeReason::C1_codepatch:
return "C1 code patch";
case ChangeReason::C1_deoptimize:
return "C1 deoptimized";
case ChangeReason::C1_deoptimize_for_patching:
return "C1 deoptimize for patching";
case ChangeReason::C1_predicate_failed_trap:
return "C1 predicate failed trap";
case ChangeReason::CI_replay:
return "CI replay";
case ChangeReason::JVMCI_invalidate_nmethod:
return "JVMCI invalidate nmethod";
case ChangeReason::JVMCI_invalidate_nmethod_mirror:
return "JVMCI invalidate nmethod mirror";
case ChangeReason::JVMCI_materialize_virtual_object:
return "JVMCI materialize virtual object";
case ChangeReason::JVMCI_new_installation:
return "JVMCI new installation";
case ChangeReason::JVMCI_register_method:
return "JVMCI register method";
case ChangeReason::JVMCI_replacing_with_new_code:
return "JVMCI replacing with new code";
case ChangeReason::JVMCI_reprofile:
return "JVMCI reprofile";
case ChangeReason::marked_for_deoptimization:
return "marked for deoptimization";
case ChangeReason::missing_exception_handler:
return "missing exception handler";
case ChangeReason::not_used:
return "not used";
case ChangeReason::OSR_invalidation_back_branch:
return "OSR invalidation back branch";
case ChangeReason::OSR_invalidation_for_compiling_with_C1:
return "OSR invalidation for compiling with C1";
case ChangeReason::OSR_invalidation_of_lower_level:
return "OSR invalidation of lower level";
case ChangeReason::set_native_function:
return "set native function";
case ChangeReason::uncommon_trap:
return "uncommon trap";
case ChangeReason::whitebox_deoptimization:
return "whitebox deoptimization";
case ChangeReason::zombie:
return "zombie";
default: {
assert(false, "Unhandled reason");
return "Unknown";
}
}
}
// create nmethod with entry_bci
static nmethod* new_nmethod(const methodHandle& method,
int compile_id,
@@ -712,8 +633,8 @@ public:
// alive. It is used when an uncommon trap happens. Returns true
// if this thread changed the state of the nmethod or false if
// another thread performed the transition.
bool make_not_entrant(ChangeReason change_reason);
bool make_not_used() { return make_not_entrant(ChangeReason::not_used); }
bool make_not_entrant(const char* reason);
bool make_not_used() { return make_not_entrant("not used"); }
bool is_marked_for_deoptimization() const { return deoptimization_status() != not_marked; }
bool has_been_deoptimized() const { return deoptimization_status() == deoptimize_done; }
@@ -1026,7 +947,7 @@ public:
// Logging
void log_identity(xmlStream* log) const;
void log_new_nmethod() const;
void log_state_change(ChangeReason change_reason) const;
void log_state_change(const char* reason) const;
// Prints block-level comments, including nmethod specific block labels:
void print_nmethod_labels(outputStream* stream, address block_begin, bool print_section_labels=true) const;

View File

@@ -924,7 +924,7 @@ void CompilationPolicy::compile(const methodHandle& mh, int bci, CompLevel level
nmethod* osr_nm = mh->lookup_osr_nmethod_for(bci, CompLevel_simple, false);
if (osr_nm != nullptr && osr_nm->comp_level() > CompLevel_simple) {
// Invalidate the existing OSR nmethod so that a compile at CompLevel_simple is permitted.
osr_nm->make_not_entrant(nmethod::ChangeReason::OSR_invalidation_for_compiling_with_C1);
osr_nm->make_not_entrant("OSR invalidation for compiling with C1");
}
compile(mh, bci, CompLevel_simple, THREAD);
}
@@ -1516,7 +1516,7 @@ void CompilationPolicy::method_back_branch_event(const methodHandle& mh, const m
int osr_bci = nm->is_osr_method() ? nm->osr_entry_bci() : InvocationEntryBci;
print_event(MAKE_NOT_ENTRANT, mh(), mh(), osr_bci, level);
}
nm->make_not_entrant(nmethod::ChangeReason::OSR_invalidation_back_branch);
nm->make_not_entrant("OSR invalidation, back branch");
}
}
// Fix up next_level if necessary to avoid deopts

View File

@@ -625,6 +625,34 @@ void ShenandoahBarrierC2Support::verify(RootNode* root) {
}
#endif
bool ShenandoahBarrierC2Support::is_anti_dependent_load_at_control(PhaseIdealLoop* phase, Node* maybe_load, Node* store,
Node* control) {
return maybe_load->is_Load() && phase->C->can_alias(store->adr_type(), phase->C->get_alias_index(maybe_load->adr_type())) &&
phase->ctrl_or_self(maybe_load) == control;
}
void ShenandoahBarrierC2Support::maybe_push_anti_dependent_loads(PhaseIdealLoop* phase, Node* maybe_store, Node* control, Unique_Node_List &wq) {
if (!maybe_store->is_Store() && !maybe_store->is_LoadStore()) {
return;
}
Node* mem = maybe_store->in(MemNode::Memory);
for (DUIterator_Fast imax, i = mem->fast_outs(imax); i < imax; i++) {
Node* u = mem->fast_out(i);
if (is_anti_dependent_load_at_control(phase, u, maybe_store, control)) {
wq.push(u);
}
}
}
void ShenandoahBarrierC2Support::push_data_inputs_at_control(PhaseIdealLoop* phase, Node* n, Node* ctrl, Unique_Node_List &wq) {
for (uint i = 0; i < n->req(); i++) {
Node* in = n->in(i);
if (in != nullptr && phase->has_ctrl(in) && phase->get_ctrl(in) == ctrl) {
wq.push(in);
}
}
}
bool ShenandoahBarrierC2Support::is_dominator_same_ctrl(Node* c, Node* d, Node* n, PhaseIdealLoop* phase) {
// That both nodes have the same control is not sufficient to prove
// domination, verify that there's no path from d to n
@@ -639,22 +667,9 @@ bool ShenandoahBarrierC2Support::is_dominator_same_ctrl(Node* c, Node* d, Node*
if (m->is_Phi() && m->in(0)->is_Loop()) {
assert(phase->ctrl_or_self(m->in(LoopNode::EntryControl)) != c, "following loop entry should lead to new control");
} else {
if (m->is_Store() || m->is_LoadStore()) {
// Take anti-dependencies into account
Node* mem = m->in(MemNode::Memory);
for (DUIterator_Fast imax, i = mem->fast_outs(imax); i < imax; i++) {
Node* u = mem->fast_out(i);
if (u->is_Load() && phase->C->can_alias(m->adr_type(), phase->C->get_alias_index(u->adr_type())) &&
phase->ctrl_or_self(u) == c) {
wq.push(u);
}
}
}
for (uint i = 0; i < m->req(); i++) {
if (m->in(i) != nullptr && phase->ctrl_or_self(m->in(i)) == c) {
wq.push(m->in(i));
}
}
// Take anti-dependencies into account
maybe_push_anti_dependent_loads(phase, m, c, wq);
push_data_inputs_at_control(phase, m, c, wq);
}
}
return true;
@@ -1006,7 +1021,20 @@ void ShenandoahBarrierC2Support::call_lrb_stub(Node*& ctrl, Node*& val, Node* lo
phase->register_new_node(val, ctrl);
}
void ShenandoahBarrierC2Support::fix_ctrl(Node* barrier, Node* region, const MemoryGraphFixer& fixer, Unique_Node_List& uses, Unique_Node_List& uses_to_ignore, uint last, PhaseIdealLoop* phase) {
void ShenandoahBarrierC2Support::collect_nodes_above_barrier(Unique_Node_List &nodes_above_barrier, PhaseIdealLoop* phase, Node* ctrl, Node* init_raw_mem) {
nodes_above_barrier.clear();
if (phase->has_ctrl(init_raw_mem) && phase->get_ctrl(init_raw_mem) == ctrl && !init_raw_mem->is_Phi()) {
nodes_above_barrier.push(init_raw_mem);
}
for (uint next = 0; next < nodes_above_barrier.size(); next++) {
Node* n = nodes_above_barrier.at(next);
// Take anti-dependencies into account
maybe_push_anti_dependent_loads(phase, n, ctrl, nodes_above_barrier);
push_data_inputs_at_control(phase, n, ctrl, nodes_above_barrier);
}
}
void ShenandoahBarrierC2Support::fix_ctrl(Node* barrier, Node* region, const MemoryGraphFixer& fixer, Unique_Node_List& uses, Unique_Node_List& nodes_above_barrier, uint last, PhaseIdealLoop* phase) {
Node* ctrl = phase->get_ctrl(barrier);
Node* init_raw_mem = fixer.find_mem(ctrl, barrier);
@@ -1017,30 +1045,17 @@ void ShenandoahBarrierC2Support::fix_ctrl(Node* barrier, Node* region, const Mem
// control will be after the expanded barrier. The raw memory (if
// its memory is control dependent on the barrier's input control)
// must stay above the barrier.
uses_to_ignore.clear();
if (phase->has_ctrl(init_raw_mem) && phase->get_ctrl(init_raw_mem) == ctrl && !init_raw_mem->is_Phi()) {
uses_to_ignore.push(init_raw_mem);
}
for (uint next = 0; next < uses_to_ignore.size(); next++) {
Node *n = uses_to_ignore.at(next);
for (uint i = 0; i < n->req(); i++) {
Node* in = n->in(i);
if (in != nullptr && phase->has_ctrl(in) && phase->get_ctrl(in) == ctrl) {
uses_to_ignore.push(in);
}
}
}
collect_nodes_above_barrier(nodes_above_barrier, phase, ctrl, init_raw_mem);
for (DUIterator_Fast imax, i = ctrl->fast_outs(imax); i < imax; i++) {
Node* u = ctrl->fast_out(i);
if (u->_idx < last &&
u != barrier &&
!u->depends_only_on_test() && // preserve dependency on test
!uses_to_ignore.member(u) &&
!nodes_above_barrier.member(u) &&
(u->in(0) != ctrl || (!u->is_Region() && !u->is_Phi())) &&
(ctrl->Opcode() != Op_CatchProj || u->Opcode() != Op_CreateEx)) {
Node* old_c = phase->ctrl_or_self(u);
Node* c = old_c;
if (c != ctrl ||
if (old_c != ctrl ||
is_dominator_same_ctrl(old_c, barrier, u, phase) ||
ShenandoahBarrierSetC2::is_shenandoah_state_load(u)) {
phase->igvn().rehash_node_delayed(u);
@@ -1315,7 +1330,7 @@ void ShenandoahBarrierC2Support::pin_and_expand(PhaseIdealLoop* phase) {
// Expand load-reference-barriers
MemoryGraphFixer fixer(Compile::AliasIdxRaw, true, phase);
Unique_Node_List uses_to_ignore;
Unique_Node_List nodes_above_barriers;
for (int i = state->load_reference_barriers_count() - 1; i >= 0; i--) {
ShenandoahLoadReferenceBarrierNode* lrb = state->load_reference_barrier(i);
uint last = phase->C->unique();
@@ -1410,7 +1425,7 @@ void ShenandoahBarrierC2Support::pin_and_expand(PhaseIdealLoop* phase) {
Node* out_val = val_phi;
phase->register_new_node(val_phi, region);
fix_ctrl(lrb, region, fixer, uses, uses_to_ignore, last, phase);
fix_ctrl(lrb, region, fixer, uses, nodes_above_barriers, last, phase);
ctrl = orig_ctrl;

View File

@@ -62,8 +62,12 @@ private:
PhaseIdealLoop* phase, int flags);
static void call_lrb_stub(Node*& ctrl, Node*& val, Node* load_addr,
DecoratorSet decorators, PhaseIdealLoop* phase);
static void collect_nodes_above_barrier(Unique_Node_List &nodes_above_barrier, PhaseIdealLoop* phase, Node* ctrl,
Node* init_raw_mem);
static void test_in_cset(Node*& ctrl, Node*& not_cset_ctrl, Node* val, Node* raw_mem, PhaseIdealLoop* phase);
static void fix_ctrl(Node* barrier, Node* region, const MemoryGraphFixer& fixer, Unique_Node_List& uses, Unique_Node_List& uses_to_ignore, uint last, PhaseIdealLoop* phase);
static void fix_ctrl(Node* barrier, Node* region, const MemoryGraphFixer& fixer, Unique_Node_List& uses, Unique_Node_List& nodes_above_barrier, uint last, PhaseIdealLoop* phase);
static Node* get_load_addr(PhaseIdealLoop* phase, VectorSet& visited, Node* lrb);
public:
@@ -76,6 +80,11 @@ public:
static bool expand(Compile* C, PhaseIterGVN& igvn);
static void pin_and_expand(PhaseIdealLoop* phase);
static void push_data_inputs_at_control(PhaseIdealLoop* phase, Node* n, Node* ctrl,
Unique_Node_List &wq);
static bool is_anti_dependent_load_at_control(PhaseIdealLoop* phase, Node* maybe_load, Node* store, Node* control);
static void maybe_push_anti_dependent_loads(PhaseIdealLoop* phase, Node* maybe_store, Node* control, Unique_Node_List &wq);
#ifdef ASSERT
static void verify(RootNode* root);
#endif

View File

@@ -183,6 +183,29 @@ void ShenandoahGenerationalHeap::stop() {
regulator_thread()->stop();
}
bool ShenandoahGenerationalHeap::requires_barriers(stackChunkOop obj) const {
if (is_idle()) {
return false;
}
if (is_concurrent_young_mark_in_progress() && is_in_young(obj) && !marking_context()->allocated_after_mark_start(obj)) {
// We are marking young, this object is in young, and it is below the TAMS
return true;
}
if (is_in_old(obj)) {
// Card marking barriers are required for objects in the old generation
return true;
}
if (has_forwarded_objects()) {
// Object may have pointers that need to be updated
return true;
}
return false;
}
void ShenandoahGenerationalHeap::evacuate_collection_set(bool concurrent) {
ShenandoahRegionIterator regions;
ShenandoahGenerationalEvacuationTask task(this, &regions, concurrent, false /* only promote regions */);

View File

@@ -128,6 +128,8 @@ public:
void stop() override;
bool requires_barriers(stackChunkOop obj) const override;
// Used for logging the result of a region transfer outside the heap lock
struct TransferResult {
bool success;

View File

@@ -27,7 +27,6 @@
#include "classfile/symbolTable.hpp"
#include "classfile/systemDictionary.hpp"
#include "classfile/vmClasses.hpp"
#include "code/nmethod.hpp"
#include "code/scopeDesc.hpp"
#include "compiler/compileBroker.hpp"
#include "compiler/compilerEvent.hpp"
@@ -1207,7 +1206,7 @@ C2V_VMENTRY_0(jint, installCode0, (JNIEnv *env, jobject,
assert(JVMCIENV->isa_HotSpotNmethod(installed_code_handle), "wrong type");
// Clear the link to an old nmethod first
JVMCIObject nmethod_mirror = installed_code_handle;
JVMCIENV->invalidate_nmethod_mirror(nmethod_mirror, true, nmethod::ChangeReason::JVMCI_replacing_with_new_code, JVMCI_CHECK_0);
JVMCIENV->invalidate_nmethod_mirror(nmethod_mirror, true, JVMCI_CHECK_0);
} else {
assert(JVMCIENV->isa_InstalledCode(installed_code_handle), "wrong type");
}
@@ -1383,7 +1382,7 @@ C2V_VMENTRY(void, reprofile, (JNIEnv* env, jobject, ARGUMENT_PAIR(method)))
nmethod* code = method->code();
if (code != nullptr) {
code->make_not_entrant(nmethod::ChangeReason::JVMCI_reprofile);
code->make_not_entrant("JVMCI reprofile");
}
MethodData* method_data = method->method_data();
@@ -1398,7 +1397,7 @@ C2V_END
C2V_VMENTRY(void, invalidateHotSpotNmethod, (JNIEnv* env, jobject, jobject hs_nmethod, jboolean deoptimize))
JVMCIObject nmethod_mirror = JVMCIENV->wrap(hs_nmethod);
JVMCIENV->invalidate_nmethod_mirror(nmethod_mirror, deoptimize, nmethod::ChangeReason::JVMCI_invalidate_nmethod, JVMCI_CHECK);
JVMCIENV->invalidate_nmethod_mirror(nmethod_mirror, deoptimize, JVMCI_CHECK);
C2V_END
C2V_VMENTRY_NULL(jlongArray, collectCounters, (JNIEnv* env, jobject))
@@ -1823,7 +1822,7 @@ C2V_VMENTRY(void, materializeVirtualObjects, (JNIEnv* env, jobject, jobject _hs_
if (!fst.current()->is_compiled_frame()) {
JVMCI_THROW_MSG(IllegalStateException, "compiled stack frame expected");
}
fst.current()->cb()->as_nmethod()->make_not_entrant(nmethod::ChangeReason::JVMCI_materialize_virtual_object);
fst.current()->cb()->as_nmethod()->make_not_entrant("JVMCI materialize virtual objects");
}
Deoptimization::deoptimize(thread, *fst.current(), Deoptimization::Reason_none);
// look for the frame again as it has been updated by deopt (pc, deopt state...)

View File

@@ -1750,7 +1750,7 @@ void JVMCIEnv::initialize_installed_code(JVMCIObject installed_code, CodeBlob* c
}
void JVMCIEnv::invalidate_nmethod_mirror(JVMCIObject mirror, bool deoptimize, nmethod::ChangeReason change_reason, JVMCI_TRAPS) {
void JVMCIEnv::invalidate_nmethod_mirror(JVMCIObject mirror, bool deoptimize, JVMCI_TRAPS) {
if (mirror.is_null()) {
JVMCI_THROW(NullPointerException);
}
@@ -1773,7 +1773,7 @@ void JVMCIEnv::invalidate_nmethod_mirror(JVMCIObject mirror, bool deoptimize, nm
if (!deoptimize) {
// Prevent future executions of the nmethod but let current executions complete.
nm->make_not_entrant(change_reason);
nm->make_not_entrant("JVMCI invalidate nmethod mirror");
// Do not clear the address field here as the Java code may still
// want to later call this method with deoptimize == true. That requires
@@ -1782,7 +1782,7 @@ void JVMCIEnv::invalidate_nmethod_mirror(JVMCIObject mirror, bool deoptimize, nm
// Deoptimize the nmethod immediately.
DeoptimizationScope deopt_scope;
deopt_scope.mark(nm);
nm->make_not_entrant(change_reason);
nm->make_not_entrant("JVMCI invalidate nmethod mirror");
nm->make_deoptimized();
deopt_scope.deoptimize_marked();

View File

@@ -462,7 +462,7 @@ public:
// field of `mirror` to prevent it from being called.
// If `deoptimize` is true, the nmethod is immediately deoptimized.
// The HotSpotNmethod.address field is zero upon returning.
void invalidate_nmethod_mirror(JVMCIObject mirror, bool deoptimze, nmethod::ChangeReason change_reason, JVMCI_TRAPS);
void invalidate_nmethod_mirror(JVMCIObject mirror, bool deoptimze, JVMCI_TRAPS);
void initialize_installed_code(JVMCIObject installed_code, CodeBlob* cb, JVMCI_TRAPS);

View File

@@ -2184,7 +2184,7 @@ JVMCI::CodeInstallResult JVMCIRuntime::register_method(JVMCIEnv* JVMCIENV,
tty->print_cr("Replacing method %s", method_name);
}
if (old != nullptr) {
old->make_not_entrant(nmethod::ChangeReason::JVMCI_register_method);
old->make_not_entrant("JVMCI register method");
}
LogTarget(Info, nmethod, install) lt;

View File

@@ -47,7 +47,6 @@ void VectorSet::init(Arena* arena) {
// Expand the existing set to a bigger size
void VectorSet::grow(uint new_word_capacity) {
_nesting.check(_set_arena); // Check if a potential reallocation in the arena is safe
assert(new_word_capacity >= _size, "Should have been checked before, use maybe_grow?");
assert(new_word_capacity < (1U << 30), "");
uint x = next_power_of_2(new_word_capacity);

View File

@@ -52,6 +52,7 @@ private:
// Grow vector to required word capacity
void maybe_grow(uint new_word_capacity) {
_nesting.check(_set_arena); // Check if a potential reallocation in the arena is safe
if (new_word_capacity >= _size) {
grow(new_word_capacity);
}

View File

@@ -22,8 +22,11 @@
*
*/
#include "memory/resourceArea.hpp"
#include "cds/cdsConfig.hpp"
#include "oops/fieldInfo.inline.hpp"
#include "runtime/atomic.hpp"
#include "utilities/packedTable.hpp"
void FieldInfo::print(outputStream* os, ConstantPool* cp) {
os->print_cr("index=%d name_index=%d name=%s signature_index=%d signature=%s offset=%d "
@@ -37,8 +40,10 @@ void FieldInfo::print(outputStream* os, ConstantPool* cp) {
field_flags().as_uint(),
initializer_index(),
generic_signature_index(),
_field_flags.is_injected() ? lookup_symbol(generic_signature_index())->as_utf8() : cp->symbol_at(generic_signature_index())->as_utf8(),
contended_group());
_field_flags.is_generic() ? (_field_flags.is_injected() ?
lookup_symbol(generic_signature_index())->as_utf8() : cp->symbol_at(generic_signature_index())->as_utf8()
) : "",
is_contended() ? contended_group() : 0);
}
void FieldInfo::print_from_growable_array(outputStream* os, GrowableArray<FieldInfo>* array, ConstantPool* cp) {
@@ -62,13 +67,17 @@ Array<u1>* FieldInfoStream::create_FieldInfoStream(GrowableArray<FieldInfo>* fie
StreamSizer s;
StreamFieldSizer sizer(&s);
assert(fields->length() == java_fields + injected_fields, "must be");
sizer.consumer()->accept_uint(java_fields);
sizer.consumer()->accept_uint(injected_fields);
for (int i = 0; i < fields->length(); i++) {
FieldInfo* fi = fields->adr_at(i);
sizer.map_field_info(*fi);
}
int storage_size = sizer.consumer()->position() + 1;
// Originally there was an extra byte with 0 terminating the reading;
// now we check limits instead.
int storage_size = sizer.consumer()->position();
Array<u1>* const fis = MetadataFactory::new_array<u1>(loader_data, storage_size, CHECK_NULL);
using StreamWriter = UNSIGNED5::Writer<Array<u1>*, int, ArrayHelper<Array<u1>*, int>>;
@@ -79,15 +88,14 @@ Array<u1>* FieldInfoStream::create_FieldInfoStream(GrowableArray<FieldInfo>* fie
writer.consumer()->accept_uint(java_fields);
writer.consumer()->accept_uint(injected_fields);
for (int i = 0; i < fields->length(); i++) {
FieldInfo* fi = fields->adr_at(i);
writer.map_field_info(*fi);
writer.map_field_info(fields->at(i));
}
#ifdef ASSERT
FieldInfoReader r(fis);
int jfc = r.next_uint();
int jfc, ifc;
r.read_field_counts(&jfc, &ifc);
assert(jfc == java_fields, "Must be");
int ifc = r.next_uint();
assert(ifc == injected_fields, "Must be");
for (int i = 0; i < jfc + ifc; i++) {
FieldInfo fi;
@@ -113,30 +121,221 @@ Array<u1>* FieldInfoStream::create_FieldInfoStream(GrowableArray<FieldInfo>* fie
return fis;
}
GrowableArray<FieldInfo>* FieldInfoStream::create_FieldInfoArray(const Array<u1>* fis, int* java_fields_count, int* injected_fields_count) {
int length = FieldInfoStream::num_total_fields(fis);
GrowableArray<FieldInfo>* array = new GrowableArray<FieldInfo>(length);
int FieldInfoStream::compare_name_and_sig(const Symbol* n1, const Symbol* s1, const Symbol* n2, const Symbol* s2) {
int cmp = n1->fast_compare(n2);
return cmp != 0 ? cmp : s1->fast_compare(s2);
}
// We use both name and signature during the comparison; while JLS require unique
// names for fields, JVMS requires only unique name + signature combination.
struct field_pos {
Symbol* _name;
Symbol* _signature;
int _index;
int _position;
};
class FieldInfoSupplier: public PackedTableBuilder::Supplier {
const field_pos* _positions;
size_t _elements;
public:
FieldInfoSupplier(const field_pos* positions, size_t elements): _positions(positions), _elements(elements) {}
bool next(uint32_t* key, uint32_t* value) override {
if (_elements == 0) {
return false;
}
*key = _positions->_position;
*value = _positions->_index;
++_positions;
--_elements;
return true;
}
};
Array<u1>* FieldInfoStream::create_search_table(ConstantPool* cp, const Array<u1>* fis, ClassLoaderData* loader_data, TRAPS) {
if (CDSConfig::is_dumping_dynamic_archive()) {
// We cannot use search table; in case of dynamic archives it should be sorted by "requested" addresses,
// but Symbol* addresses are coming from _constants, which has "buffered" addresses.
// For background, see new comments inside allocate_node_impl in symbolTable.cpp
return nullptr;
}
FieldInfoReader r(fis);
*java_fields_count = r.next_uint();
*injected_fields_count = r.next_uint();
int java_fields;
int injected_fields;
r.read_field_counts(&java_fields, &injected_fields);
assert(java_fields >= 0, "must be");
if (java_fields == 0 || fis->length() == 0 || static_cast<uint>(java_fields) < BinarySearchThreshold) {
return nullptr;
}
ResourceMark rm;
field_pos* positions = NEW_RESOURCE_ARRAY(field_pos, java_fields);
for (int i = 0; i < java_fields; ++i) {
assert(r.has_next(), "number of fields must match");
positions[i]._position = r.position();
FieldInfo fi;
r.read_field_info(fi);
positions[i]._name = fi.name(cp);
positions[i]._signature = fi.signature(cp);
positions[i]._index = i;
}
auto compare_pair = [](const void* v1, const void* v2) {
const field_pos* p1 = reinterpret_cast<const field_pos*>(v1);
const field_pos* p2 = reinterpret_cast<const field_pos*>(v2);
return compare_name_and_sig(p1->_name, p1->_signature, p2->_name, p2->_signature);
};
qsort(positions, java_fields, sizeof(field_pos), compare_pair);
PackedTableBuilder builder(fis->length() - 1, java_fields - 1);
Array<u1>* table = MetadataFactory::new_array<u1>(loader_data, java_fields * builder.element_bytes(), CHECK_NULL);
FieldInfoSupplier supplier(positions, java_fields);
builder.fill(table->data(), static_cast<size_t>(table->length()), supplier);
return table;
}
GrowableArray<FieldInfo>* FieldInfoStream::create_FieldInfoArray(const Array<u1>* fis, int* java_fields_count, int* injected_fields_count) {
FieldInfoReader r(fis);
r.read_field_counts(java_fields_count, injected_fields_count);
int length = *java_fields_count + *injected_fields_count;
GrowableArray<FieldInfo>* array = new GrowableArray<FieldInfo>(length);
while (r.has_next()) {
FieldInfo fi;
r.read_field_info(fi);
array->append(fi);
}
assert(array->length() == length, "Must be");
assert(array->length() == *java_fields_count + *injected_fields_count, "Must be");
return array;
}
void FieldInfoStream::print_from_fieldinfo_stream(Array<u1>* fis, outputStream* os, ConstantPool* cp) {
int length = FieldInfoStream::num_total_fields(fis);
FieldInfoReader r(fis);
int java_field_count = r.next_uint();
int injected_fields_count = r.next_uint();
int java_fields_count;
int injected_fields_count;
r.read_field_counts(&java_fields_count, &injected_fields_count);
while (r.has_next()) {
FieldInfo fi;
r.read_field_info(fi);
fi.print(os, cp);
}
}
class FieldInfoComparator: public PackedTableLookup::Comparator {
const FieldInfoReader* _reader;
ConstantPool* _cp;
const Symbol* _name;
const Symbol* _signature;
public:
FieldInfoComparator(const FieldInfoReader* reader, ConstantPool* cp, const Symbol* name, const Symbol* signature):
_reader(reader), _cp(cp), _name(name), _signature(signature) {}
int compare_to(uint32_t position) override {
FieldInfoReader r2(*_reader);
r2.set_position_and_next_index(position, -1);
u2 name_index, sig_index;
r2.read_name_and_signature(&name_index, &sig_index);
Symbol* mid_name = _cp->symbol_at(name_index);
Symbol* mid_sig = _cp->symbol_at(sig_index);
return FieldInfoStream::compare_name_and_sig(_name, _signature, mid_name, mid_sig);
}
#ifdef ASSERT
void reset(uint32_t position) override {
FieldInfoReader r2(*_reader);
r2.set_position_and_next_index(position, -1);
u2 name_index, signature_index;
r2.read_name_and_signature(&name_index, &signature_index);
_name = _cp->symbol_at(name_index);
_signature = _cp->symbol_at(signature_index);
}
#endif // ASSERT
};
#ifdef ASSERT
void FieldInfoStream::validate_search_table(ConstantPool* cp, const Array<u1>* fis, const Array<u1>* search_table) {
if (search_table == nullptr) {
return;
}
FieldInfoReader reader(fis);
int java_fields, injected_fields;
reader.read_field_counts(&java_fields, &injected_fields);
assert(java_fields > 0, "must be");
PackedTableLookup lookup(fis->length() - 1, java_fields - 1, search_table);
assert(lookup.element_bytes() * java_fields == static_cast<unsigned int>(search_table->length()), "size does not match");
FieldInfoComparator comparator(&reader, cp, nullptr, nullptr);
// Check 1: assert that elements have the correct order based on the comparison function
lookup.validate_order(comparator);
// Check 2: Iterate through the original stream (not just search_table) and try if lookup works as expected
reader.set_position_and_next_index(0, 0);
reader.read_field_counts(&java_fields, &injected_fields);
while (reader.has_next()) {
int field_start = reader.position();
FieldInfo fi;
reader.read_field_info(fi);
if (fi.field_flags().is_injected()) {
// checking only java fields that precede injected ones
break;
}
FieldInfoReader r2(fis);
int index = r2.search_table_lookup(search_table, fi.name(cp), fi.signature(cp), cp, java_fields);
assert(index == static_cast<int>(fi.index()), "wrong index: %d != %u", index, fi.index());
assert(index == r2.next_index(), "index should match");
assert(field_start == r2.position(), "must find the same position");
}
}
#endif // ASSERT
void FieldInfoStream::print_search_table(outputStream* st, ConstantPool* cp, const Array<u1>* fis, const Array<u1>* search_table) {
if (search_table == nullptr) {
return;
}
FieldInfoReader reader(fis);
int java_fields, injected_fields;
reader.read_field_counts(&java_fields, &injected_fields);
assert(java_fields > 0, "must be");
PackedTableLookup lookup(fis->length() - 1, java_fields - 1, search_table);
auto printer = [&] (size_t offset, uint32_t position, uint32_t index) {
reader.set_position_and_next_index(position, -1);
u2 name_index, sig_index;
reader.read_name_and_signature(&name_index, &sig_index);
Symbol* name = cp->symbol_at(name_index);
Symbol* sig = cp->symbol_at(sig_index);
st->print(" [%zu] #%d,#%d = ", offset, name_index, sig_index);
name->print_symbol_on(st);
st->print(":");
sig->print_symbol_on(st);
st->print(" @ %p,%p", name, sig);
st->cr();
};
lookup.iterate(printer);
}
int FieldInfoReader::search_table_lookup(const Array<u1>* search_table, const Symbol* name, const Symbol* signature, ConstantPool* cp, int java_fields) {
assert(java_fields >= 0, "must be");
if (java_fields == 0) {
return -1;
}
FieldInfoComparator comp(this, cp, name, signature);
PackedTableLookup lookup(_r.limit() - 1, java_fields - 1, search_table);
uint32_t position;
static_assert(sizeof(uint32_t) == sizeof(_next_index), "field size assert");
if (lookup.search(comp, &position, reinterpret_cast<uint32_t*>(&_next_index))) {
_r.set_position(static_cast<int>(position));
return _next_index;
} else {
return -1;
}
}

View File

@@ -222,29 +222,28 @@ public:
void map_field_info(const FieldInfo& fi);
};
// Gadget for decoding and reading the stream of field records.
class FieldInfoReader {
friend class FieldInfoStream;
friend class ClassFileParser;
friend class FieldStreamBase;
friend class FieldInfo;
UNSIGNED5::Reader<const u1*, int> _r;
int _next_index;
public:
public:
FieldInfoReader(const Array<u1>* fi);
private:
uint32_t next_uint() { return _r.next_uint(); }
private:
inline uint32_t next_uint() { return _r.next_uint(); }
void skip(int n) { int s = _r.try_skip(n); assert(s == n,""); }
public:
int has_next() { return _r.has_next(); }
int position() { return _r.position(); }
int next_index() { return _next_index; }
void read_field_counts(int* java_fields, int* injected_fields);
int has_next() const { return _r.position() < _r.limit(); }
int position() const { return _r.position(); }
int next_index() const { return _next_index; }
void read_name_and_signature(u2* name_index, u2* signature_index);
void read_field_info(FieldInfo& fi);
int search_table_lookup(const Array<u1>* search_table, const Symbol* name, const Symbol* signature, ConstantPool* cp, int java_fields);
// skip a whole field record, both required and optional bits
FieldInfoReader& skip_field_info();
@@ -271,6 +270,11 @@ class FieldInfoStream : AllStatic {
friend class JavaFieldStream;
friend class FieldStreamBase;
friend class ClassFileParser;
friend class FieldInfoReader;
friend class FieldInfoComparator;
private:
static int compare_name_and_sig(const Symbol* n1, const Symbol* s1, const Symbol* n2, const Symbol* s2);
public:
static int num_java_fields(const Array<u1>* fis);
@@ -278,9 +282,14 @@ class FieldInfoStream : AllStatic {
static int num_total_fields(const Array<u1>* fis);
static Array<u1>* create_FieldInfoStream(GrowableArray<FieldInfo>* fields, int java_fields, int injected_fields,
ClassLoaderData* loader_data, TRAPS);
ClassLoaderData* loader_data, TRAPS);
static Array<u1>* create_search_table(ConstantPool* cp, const Array<u1>* fis, ClassLoaderData* loader_data, TRAPS);
static GrowableArray<FieldInfo>* create_FieldInfoArray(const Array<u1>* fis, int* java_fields_count, int* injected_fields_count);
static void print_from_fieldinfo_stream(Array<u1>* fis, outputStream* os, ConstantPool* cp);
DEBUG_ONLY(static void validate_search_table(ConstantPool* cp, const Array<u1>* fis, const Array<u1>* search_table);)
static void print_search_table(outputStream* st, ConstantPool* cp, const Array<u1>* fis, const Array<u1>* search_table);
};
class FieldStatus {

View File

@@ -56,16 +56,27 @@ inline Symbol* FieldInfo::lookup_symbol(int symbol_index) const {
inline int FieldInfoStream::num_injected_java_fields(const Array<u1>* fis) {
FieldInfoReader fir(fis);
fir.skip(1);
return fir.next_uint();
int java_fields_count;
int injected_fields_count;
fir.read_field_counts(&java_fields_count, &injected_fields_count);
return injected_fields_count;
}
inline int FieldInfoStream::num_total_fields(const Array<u1>* fis) {
FieldInfoReader fir(fis);
return fir.next_uint() + fir.next_uint();
int java_fields_count;
int injected_fields_count;
fir.read_field_counts(&java_fields_count, &injected_fields_count);
return java_fields_count + injected_fields_count;
}
inline int FieldInfoStream::num_java_fields(const Array<u1>* fis) { return FieldInfoReader(fis).next_uint(); }
inline int FieldInfoStream::num_java_fields(const Array<u1>* fis) {
FieldInfoReader fir(fis);
int java_fields_count;
int injected_fields_count;
fir.read_field_counts(&java_fields_count, &injected_fields_count);
return java_fields_count;
}
template<typename CON>
inline void Mapper<CON>::map_field_info(const FieldInfo& fi) {
@@ -94,13 +105,22 @@ inline void Mapper<CON>::map_field_info(const FieldInfo& fi) {
inline FieldInfoReader::FieldInfoReader(const Array<u1>* fi)
: _r(fi->data(), 0),
: _r(fi->data(), fi->length()),
_next_index(0) { }
inline void FieldInfoReader::read_field_counts(int* java_fields, int* injected_fields) {
*java_fields = next_uint();
*injected_fields = next_uint();
}
inline void FieldInfoReader::read_name_and_signature(u2* name_index, u2* signature_index) {
*name_index = checked_cast<u2>(next_uint());
*signature_index = checked_cast<u2>(next_uint());
}
inline void FieldInfoReader::read_field_info(FieldInfo& fi) {
fi._index = _next_index++;
fi._name_index = checked_cast<u2>(next_uint());
fi._signature_index = checked_cast<u2>(next_uint());
read_name_and_signature(&fi._name_index, &fi._signature_index);
fi._offset = next_uint();
fi._access_flags = AccessFlags(checked_cast<u2>(next_uint()));
fi._field_flags = FieldInfo::FieldFlags(next_uint());

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 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
@@ -56,17 +56,23 @@ class FieldStreamBase : public StackObj {
inline FieldStreamBase(const Array<u1>* fieldinfo_stream, ConstantPool* constants, int start, int limit);
inline FieldStreamBase(Array<u1>* fieldinfo_stream, ConstantPool* constants);
inline FieldStreamBase(const Array<u1>* fieldinfo_stream, ConstantPool* constants);
private:
private:
void initialize() {
int java_fields_count = _reader.next_uint();
int injected_fields_count = _reader.next_uint();
assert( _limit <= java_fields_count + injected_fields_count, "Safety check");
int java_fields_count;
int injected_fields_count;
_reader.read_field_counts(&java_fields_count, &injected_fields_count);
if (_limit < _index) {
_limit = java_fields_count + injected_fields_count;
} else {
assert( _limit <= java_fields_count + injected_fields_count, "Safety check");
}
if (_limit != 0) {
_reader.read_field_info(_fi_buf);
}
}
public:
inline FieldStreamBase(InstanceKlass* klass);
@@ -138,8 +144,11 @@ class FieldStreamBase : public StackObj {
// Iterate over only the Java fields
class JavaFieldStream : public FieldStreamBase {
Array<u1>* _search_table;
public:
JavaFieldStream(const InstanceKlass* k): FieldStreamBase(k->fieldinfo_stream(), k->constants(), 0, k->java_fields_count()) {}
JavaFieldStream(const InstanceKlass* k): FieldStreamBase(k->fieldinfo_stream(), k->constants(), 0, k->java_fields_count()),
_search_table(k->fieldinfo_search_table()) {}
u2 name_index() const {
assert(!field()->field_flags().is_injected(), "regular only");
@@ -149,7 +158,6 @@ class JavaFieldStream : public FieldStreamBase {
u2 signature_index() const {
assert(!field()->field_flags().is_injected(), "regular only");
return field()->signature_index();
return -1;
}
u2 generic_signature_index() const {
@@ -164,6 +172,10 @@ class JavaFieldStream : public FieldStreamBase {
assert(!field()->field_flags().is_injected(), "regular only");
return field()->initializer_index();
}
// Performs either a linear search or binary search through the stream
// looking for a matching name/signature combo
bool lookup(const Symbol* name, const Symbol* signature);
};
@@ -176,7 +188,6 @@ class InternalFieldStream : public FieldStreamBase {
class AllFieldStream : public FieldStreamBase {
public:
AllFieldStream(Array<u1>* fieldinfo, ConstantPool* constants): FieldStreamBase(fieldinfo, constants) {}
AllFieldStream(const InstanceKlass* k): FieldStreamBase(k->fieldinfo_stream(), k->constants()) {}
};

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -33,22 +33,18 @@
FieldStreamBase::FieldStreamBase(const Array<u1>* fieldinfo_stream, ConstantPool* constants, int start, int limit) :
_fieldinfo_stream(fieldinfo_stream),
_reader(FieldInfoReader(_fieldinfo_stream)),
_constants(constantPoolHandle(Thread::current(), constants)), _index(start) {
_index = start;
if (limit < start) {
_limit = FieldInfoStream::num_total_fields(_fieldinfo_stream);
} else {
_limit = limit;
}
_constants(constantPoolHandle(Thread::current(), constants)),
_index(start),
_limit(limit) {
initialize();
}
FieldStreamBase::FieldStreamBase(Array<u1>* fieldinfo_stream, ConstantPool* constants) :
FieldStreamBase::FieldStreamBase(const Array<u1>* fieldinfo_stream, ConstantPool* constants) :
_fieldinfo_stream(fieldinfo_stream),
_reader(FieldInfoReader(_fieldinfo_stream)),
_constants(constantPoolHandle(Thread::current(), constants)),
_index(0),
_limit(FieldInfoStream::num_total_fields(_fieldinfo_stream)) {
_limit(-1) {
initialize();
}
@@ -57,9 +53,28 @@ FieldStreamBase::FieldStreamBase(InstanceKlass* klass) :
_reader(FieldInfoReader(_fieldinfo_stream)),
_constants(constantPoolHandle(Thread::current(), klass->constants())),
_index(0),
_limit(FieldInfoStream::num_total_fields(_fieldinfo_stream)) {
_limit(-1) {
assert(klass == field_holder(), "");
initialize();
}
inline bool JavaFieldStream::lookup(const Symbol* name, const Symbol* signature) {
if (_search_table != nullptr) {
int index = _reader.search_table_lookup(_search_table, name, signature, _constants(), _limit);
if (index >= 0) {
assert(index < _limit, "must be");
_index = index;
_reader.read_field_info(_fi_buf);
return true;
}
} else {
for (; !done(); next()) {
if (this->name() == name && this->signature() == signature) {
return true;
}
}
}
return false;
}
#endif // SHARE_OOPS_FIELDSTREAMS_INLINE_HPP

View File

@@ -686,6 +686,11 @@ void InstanceKlass::deallocate_contents(ClassLoaderData* loader_data) {
}
set_fieldinfo_stream(nullptr);
if (fieldinfo_search_table() != nullptr && !fieldinfo_search_table()->is_shared()) {
MetadataFactory::free_array<u1>(loader_data, fieldinfo_search_table());
}
set_fieldinfo_search_table(nullptr);
if (fields_status() != nullptr && !fields_status()->is_shared()) {
MetadataFactory::free_array<FieldStatus>(loader_data, fields_status());
}
@@ -1786,13 +1791,12 @@ FieldInfo InstanceKlass::field(int index) const {
}
bool InstanceKlass::find_local_field(Symbol* name, Symbol* sig, fieldDescriptor* fd) const {
for (JavaFieldStream fs(this); !fs.done(); fs.next()) {
Symbol* f_name = fs.name();
Symbol* f_sig = fs.signature();
if (f_name == name && f_sig == sig) {
fd->reinitialize(const_cast<InstanceKlass*>(this), fs.to_FieldInfo());
return true;
}
JavaFieldStream fs(this);
if (fs.lookup(name, sig)) {
assert(fs.name() == name, "name must match");
assert(fs.signature() == sig, "signature must match");
fd->reinitialize(const_cast<InstanceKlass*>(this), fs.to_FieldInfo());
return true;
}
return false;
}
@@ -2610,6 +2614,7 @@ void InstanceKlass::metaspace_pointers_do(MetaspaceClosure* it) {
}
it->push(&_fieldinfo_stream);
it->push(&_fieldinfo_search_table);
// _fields_status might be written into by Rewriter::scan_method() -> fd.set_has_initialized_final_update()
it->push(&_fields_status, MetaspaceClosure::_writable);
@@ -2710,6 +2715,8 @@ void InstanceKlass::remove_unshareable_info() {
DEBUG_ONLY(_shared_class_load_count = 0);
remove_unshareable_flags();
DEBUG_ONLY(FieldInfoStream::validate_search_table(_constants, _fieldinfo_stream, _fieldinfo_search_table));
}
void InstanceKlass::remove_unshareable_flags() {
@@ -2816,6 +2823,8 @@ void InstanceKlass::restore_unshareable_info(ClassLoaderData* loader_data, Handl
if (DiagnoseSyncOnValueBasedClasses && has_value_based_class_annotation() && !is_value_based()) {
set_is_value_based();
}
DEBUG_ONLY(FieldInfoStream::validate_search_table(_constants, _fieldinfo_stream, _fieldinfo_search_table));
}
// Check if a class or any of its supertypes has a version older than 50.
@@ -3492,7 +3501,7 @@ void InstanceKlass::add_osr_nmethod(nmethod* n) {
for (int l = CompLevel_limited_profile; l < n->comp_level(); l++) {
nmethod *inv = lookup_osr_nmethod(n->method(), n->osr_entry_bci(), l, true);
if (inv != nullptr && inv->is_in_use()) {
inv->make_not_entrant(nmethod::ChangeReason::OSR_invalidation_of_lower_level);
inv->make_not_entrant("OSR invalidation of lower levels");
}
}
}
@@ -3760,6 +3769,11 @@ void InstanceKlass::print_on(outputStream* st) const {
map++;
}
st->cr();
if (fieldinfo_search_table() != nullptr) {
st->print_cr(BULLET"---- field info search table:");
FieldInfoStream::print_search_table(st, _constants, _fieldinfo_stream, _fieldinfo_search_table);
}
}
void InstanceKlass::print_value_on(outputStream* st) const {

View File

@@ -276,6 +276,7 @@ class InstanceKlass: public Klass {
// Fields information is stored in an UNSIGNED5 encoded stream (see fieldInfo.hpp)
Array<u1>* _fieldinfo_stream;
Array<u1>* _fieldinfo_search_table;
Array<FieldStatus>* _fields_status;
// embedded Java vtable follows here
@@ -398,6 +399,9 @@ class InstanceKlass: public Klass {
Array<u1>* fieldinfo_stream() const { return _fieldinfo_stream; }
void set_fieldinfo_stream(Array<u1>* fis) { _fieldinfo_stream = fis; }
Array<u1>* fieldinfo_search_table() const { return _fieldinfo_search_table; }
void set_fieldinfo_search_table(Array<u1>* table) { _fieldinfo_search_table = table; }
Array<FieldStatus>* fields_status() const {return _fields_status; }
void set_fields_status(Array<FieldStatus>* array) { _fields_status = array; }

View File

@@ -1028,7 +1028,7 @@ void Method::set_native_function(address function, bool post_event_flag) {
// If so, we have to make it not_entrant.
nmethod* nm = code(); // Put it into local variable to guard against concurrent updates
if (nm != nullptr) {
nm->make_not_entrant(nmethod::ChangeReason::set_native_function);
nm->make_not_entrant("set native function");
}
}

View File

@@ -34,6 +34,7 @@
#include "memory/metaspaceClosure.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/method.hpp"
#include "oops/objArrayKlass.hpp"
#include "runtime/handles.hpp"
#include "runtime/mutexLocker.hpp"
#include "utilities/resizeableResourceHash.hpp"
@@ -286,7 +287,12 @@ private:
static bool is_klass_loaded(Klass* k) {
if (have_data()) {
// If we're running in AOT mode some classes may not be loaded yet
return !k->is_instance_klass() || InstanceKlass::cast(k)->is_loaded();
if (k->is_objArray_klass()) {
k = ObjArrayKlass::cast(k)->bottom_klass();
}
if (k->is_instance_klass()) {
return InstanceKlass::cast(k)->is_loaded();
}
}
return true;
}

View File

@@ -37,11 +37,8 @@
#include "utilities/copy.hpp"
#include "utilities/powerOfTwo.hpp"
void Block_Array::grow( uint i ) {
_nesting.check(_arena); // Check if a potential reallocation in the arena is safe
if (i < Max()) {
return; // No need to grow
}
void Block_Array::grow(uint i) {
assert(i >= Max(), "Should have been checked before, use maybe_grow?");
DEBUG_ONLY(_limit = i+1);
if( i < _size ) return;
if( !_size ) {

View File

@@ -53,7 +53,13 @@ class Block_Array : public ArenaObj {
ReallocMark _nesting; // Safety checks for arena reallocation
protected:
Block **_blocks;
void grow( uint i ); // Grow array node to fit
void maybe_grow(uint i) {
_nesting.check(_arena); // Check if a potential reallocation in the arena is safe
if (i >= Max()) {
grow(i);
}
}
void grow(uint i); // Grow array node to fit
public:
Block_Array(Arena *a) : _size(OptoBlockListSize), _arena(a) {
@@ -68,7 +74,7 @@ public:
Block *operator[] ( uint i ) const // Lookup, or assert for not mapped
{ assert( i < Max(), "oob" ); return _blocks[i]; }
// Extend the mapping: index i maps to Block *n.
void map( uint i, Block *n ) { grow(i); _blocks[i] = n; }
void map( uint i, Block *n ) { maybe_grow(i); _blocks[i] = n; }
uint Max() const { DEBUG_ONLY(return _limit); return _size; }
};

View File

@@ -65,13 +65,8 @@ public:
Node_Stack::push(n, (uint)ns);
}
void push(Node *n, Node_State ns, Node *parent, int indx) {
++_inode_top;
if ((_inode_top + 1) >= _inode_max) grow();
_inode_top->node = parent;
_inode_top->indx = (uint)indx;
++_inode_top;
_inode_top->node = n;
_inode_top->indx = (uint)ns;
Node_Stack::push(parent, (uint)indx);
Node_Stack::push(n, (uint)ns);
}
Node *parent() {
pop();

View File

@@ -2798,7 +2798,6 @@ const RegMask &Node::in_RegMask(uint) const {
}
void Node_Array::grow(uint i) {
_nesting.check(_a); // Check if a potential reallocation in the arena is safe
assert(i >= _max, "Should have been checked before, use maybe_grow?");
assert(_max > 0, "invariant");
uint old = _max;
@@ -3038,10 +3037,6 @@ void Unique_Node_List::remove_useless_nodes(VectorSet &useful) {
//=============================================================================
void Node_Stack::grow() {
_nesting.check(_a); // Check if a potential reallocation in the arena is safe
if (_inode_top < _inode_max) {
return; // No need to grow
}
size_t old_top = pointer_delta(_inode_top,_inodes,sizeof(INode)); // save _top
size_t old_max = pointer_delta(_inode_max,_inodes,sizeof(INode));
size_t max = old_max << 1; // max * 2

View File

@@ -1633,6 +1633,7 @@ protected:
// Grow array to required capacity
void maybe_grow(uint i) {
_nesting.check(_a); // Check if a potential reallocation in the arena is safe
if (i >= _max) {
grow(i);
}
@@ -1884,7 +1885,15 @@ protected:
INode *_inodes; // Array storage for the stack
Arena *_a; // Arena to allocate in
ReallocMark _nesting; // Safety checks for arena reallocation
void maybe_grow() {
_nesting.check(_a); // Check if a potential reallocation in the arena is safe
if (_inode_top >= _inode_max) {
grow();
}
}
void grow();
public:
Node_Stack(int size) {
size_t max = (size > OptoNodeListSize) ? size : OptoNodeListSize;
@@ -1907,7 +1916,7 @@ public:
}
void push(Node *n, uint i) {
++_inode_top;
grow();
maybe_grow();
INode *top = _inode_top; // optimization
top->node = n;
top->indx = i;

View File

@@ -3550,6 +3550,13 @@ void VM_RedefineClasses::set_new_constant_pool(
Array<u1>* new_fis = FieldInfoStream::create_FieldInfoStream(fields, java_fields, injected_fields, scratch_class->class_loader_data(), CHECK);
scratch_class->set_fieldinfo_stream(new_fis);
MetadataFactory::free_array<u1>(scratch_class->class_loader_data(), old_stream);
Array<u1>* old_table = scratch_class->fieldinfo_search_table();
Array<u1>* search_table = FieldInfoStream::create_search_table(scratch_class->constants(), new_fis, scratch_class->class_loader_data(), CHECK);
scratch_class->set_fieldinfo_search_table(search_table);
MetadataFactory::free_array<u1>(scratch_class->class_loader_data(), old_table);
DEBUG_ONLY(FieldInfoStream::validate_search_table(scratch_class->constants(), new_fis, search_table));
}
// Update constant pool indices in the inner classes info to use

View File

@@ -794,7 +794,7 @@ class VM_WhiteBoxDeoptimizeFrames : public VM_WhiteBoxOperation {
if (_make_not_entrant) {
nmethod* nm = CodeCache::find_nmethod(f->pc());
assert(nm != nullptr, "did not find nmethod");
nm->make_not_entrant(nmethod::ChangeReason::whitebox_deoptimization);
nm->make_not_entrant("Whitebox deoptimization");
}
++_result;
}

View File

@@ -1826,7 +1826,7 @@ void Deoptimization::deoptimize(JavaThread* thread, frame fr, DeoptReason reason
#if INCLUDE_JVMCI
address Deoptimization::deoptimize_for_missing_exception_handler(nmethod* nm) {
// there is no exception handler for this pc => deoptimize
nm->make_not_entrant(nmethod::ChangeReason::missing_exception_handler);
nm->make_not_entrant("missing exception handler");
// Use Deoptimization::deoptimize for all of its side-effects:
// gathering traps statistics, logging...
@@ -2455,7 +2455,7 @@ JRT_ENTRY(void, Deoptimization::uncommon_trap_inner(JavaThread* current, jint tr
// Recompile
if (make_not_entrant) {
if (!nm->make_not_entrant(nmethod::ChangeReason::uncommon_trap)) {
if (!nm->make_not_entrant("uncommon trap")) {
return; // the call did not change nmethod's state
}

View File

@@ -2005,6 +2005,10 @@ const int ObjectAlignmentInBytes = 8;
product(bool, UseThreadsLockThrottleLock, true, DIAGNOSTIC, \
"Use an extra lock during Thread start and exit to alleviate" \
"contention on Threads_lock.") \
\
develop(uint, BinarySearchThreshold, 16, \
"Minimal number of elements in a sorted collection to prefer" \
"binary search over simple linear search." ) \
// end of RUNTIME_FLAGS

View File

@@ -1337,7 +1337,7 @@ void JavaThread::make_zombies() {
// it is a Java nmethod
nmethod* nm = CodeCache::find_nmethod(fst.current()->pc());
assert(nm != nullptr, "did not find nmethod");
nm->make_not_entrant(nmethod::ChangeReason::zombie);
nm->make_not_entrant("zombie");
}
}
}

View File

@@ -771,8 +771,8 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) {
#endif
if (CDSConfig::is_using_aot_linked_classes()) {
AOTLinkedClassBulkLoader::finish_loading_javabase_classes(CHECK_JNI_ERR);
SystemDictionary::restore_archived_method_handle_intrinsics();
AOTLinkedClassBulkLoader::finish_loading_javabase_classes(CHECK_JNI_ERR);
}
// Start string deduplication thread if requested.

View File

@@ -0,0 +1,113 @@
/*
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* 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.
*
*/
#include <cstring>
#include "utilities/align.hpp"
#include "utilities/count_leading_zeros.hpp"
#include "utilities/packedTable.hpp"
// The thresholds are inclusive, and in practice the limits are rounded
// to the nearest power-of-two - 1.
// Based on the max_key and max_value we figure out the number of bits required to store
// key and value; imagine that only as bits (not aligned to byte boundary... yet).
// Then we concatenate the bits for key and value, and 'add' 1-7 padding zeroes
// (high-order bits) to align on bytes.
// In the end we have each element in the table consuming 1-8 bytes (case with 0 bits for key
// is ruled out).
PackedTableBase::PackedTableBase(uint32_t max_key, uint32_t max_value) {
unsigned int key_bits = max_key == 0 ? 0 : 32 - count_leading_zeros(max_key);
unsigned int value_bits = max_value == 0 ? 0 : 32 - count_leading_zeros(max_value);
_element_bytes = align_up(key_bits + value_bits, 8) / 8;
// shifting left by 32 is undefined behaviour, and in practice returns 1
_key_mask = key_bits >= 32 ? -1 : (1U << key_bits) - 1;
_value_shift = key_bits;
_value_mask = value_bits >= 32 ? -1 : (1U << value_bits) - 1;
guarantee(_element_bytes > 0, "wouldn't work");
assert(_element_bytes <= sizeof(uint64_t), "shouldn't happen");
}
// Note: we require the supplier to provide the elements in the final order as we can't easily sort
// within this method - qsort() accepts only pure function as comparator.
void PackedTableBuilder::fill(u1* table, size_t table_length, Supplier &supplier) const {
uint32_t key, value;
size_t offset = 0;
for (; offset <= table_length && supplier.next(&key, &value); offset += _element_bytes) {
assert((key & ~_key_mask) == 0, "key out of bounds");
assert((value & ~_value_mask) == 0, "value out of bounds: %x vs. %x (%x)", value, _value_mask, ~_value_mask);
uint64_t element = static_cast<uint64_t>(key) | (static_cast<uint64_t>(value) << _value_shift);
for (unsigned int i = 0; i < _element_bytes; ++i) {
table[offset + i] = static_cast<u1>(0xFF & element);
element >>= 8;
}
}
assert(offset == table_length, "Did not fill whole array");
assert(!supplier.next(&key, &value), "Supplier has more elements");
}
uint64_t PackedTableLookup::read_element(size_t offset) const {
uint64_t element = 0;
for (unsigned int i = 0; i < _element_bytes; ++i) {
element |= static_cast<uint64_t>(_table[offset + i]) << (8 * i);
}
assert((element & ~((uint64_t) _key_mask | ((uint64_t) _value_mask << _value_shift))) == 0, "read too much");
return element;
}
bool PackedTableLookup::search(Comparator& comparator, uint32_t* found_key, uint32_t* found_value) const {
unsigned int low = 0, high = checked_cast<unsigned int>(_table_length / _element_bytes);
assert(low < high, "must be");
while (low < high) {
unsigned int mid = low + (high - low) / 2;
assert(mid >= low && mid < high, "integer overflow?");
uint64_t element = read_element(_element_bytes * mid);
// Ignoring high 32 bits in element on purpose
uint32_t key = static_cast<uint32_t>(element) & _key_mask;
int cmp = comparator.compare_to(key);
if (cmp == 0) {
*found_key = key;
// Since __builtin_memcpy in read_element does not copy bits outside the element
// anything above _value_mask << _value_shift should be zero.
*found_value = checked_cast<uint32_t>(element >> _value_shift) & _value_mask;
return true;
} else if (cmp < 0) {
high = mid;
} else {
low = mid + 1;
}
}
return false;
}
#ifdef ASSERT
void PackedTableLookup::validate_order(Comparator &comparator) const {
auto validator = [&] (size_t offset, uint32_t key, uint32_t value) {
if (offset != 0) {
assert(comparator.compare_to(key) < 0, "not sorted");
}
comparator.reset(key);
};
iterate(validator);
}
#endif

View File

@@ -0,0 +1,123 @@
/*
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* 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.
*
*/
#include "oops/array.hpp"
#include "utilities/globalDefinitions.hpp"
// Base for space-optimized structure supporting binary search. Each element
// consists of up to 32-bit key, and up to 32-bit value; these are packed
// into a bit-record with 1-byte alignment.
// The keys are ordered according to a custom comparator.
class PackedTableBase {
protected:
unsigned int _element_bytes;
uint32_t _key_mask;
unsigned int _value_shift;
uint32_t _value_mask;
public:
PackedTableBase(uint32_t max_key, uint32_t max_value);
// Returns number of bytes each element will occupy.
inline unsigned int element_bytes(void) const { return _element_bytes; }
};
// Helper class for constructing a packed table in the provided array.
class PackedTableBuilder: public PackedTableBase {
public:
class Supplier {
public:
// Returns elements with already ordered keys.
// This function should return true when the key and value was set,
// and false when there's no more elements.
// Packed table does NOT support duplicate keys.
virtual bool next(uint32_t* key, uint32_t* value) = 0;
};
// The thresholds are inclusive, and in practice the limits are rounded
// to the nearest power-of-two - 1.
// See PackedTableBase constructor for details.
PackedTableBuilder(uint32_t max_key, uint32_t max_value): PackedTableBase(max_key, max_value) {}
// Constructs a packed table in the provided array, filling it with elements
// from the supplier. Note that no comparator is requied by this method -
// the supplier must return elements with already ordered keys.
// The table_length (in bytes) should match number of elements provided
// by the supplier (when Supplier::next() returns false the whole array should
// be filled).
void fill(u1* table, size_t table_length, Supplier &supplier) const;
};
// Helper class for lookup in a packed table.
class PackedTableLookup: public PackedTableBase {
const u1* const _table;
const size_t _table_length;
uint64_t read_element(size_t offset) const;
public:
// The comparator implementation does not have to store a key (uint32_t);
// the idea is that key can point into a different structure that hosts data
// suitable for the actual comparison. That's why PackedTableLookup::search(...)
// returns the key it found as well as the value.
class Comparator {
public:
// Returns negative/0/positive if the target referred to by this comparator
// is lower/equal/higher than the target referred to by the key.
virtual int compare_to(uint32_t key) = 0;
// Changes the target this comparator refers to.
DEBUG_ONLY(virtual void reset(uint32_t key) = 0);
};
// The thresholds are inclusive, and in practice the limits are rounded
// to the nearest power-of-two - 1.
// See PackedTableBase constructor for details.
PackedTableLookup(uint32_t max_key, uint32_t max_value, const u1 *table, size_t table_length):
PackedTableBase(max_key, max_value), _table(table), _table_length(table_length) {}
PackedTableLookup(uint32_t max_key, uint32_t max_value, const Array<u1> *table):
PackedTableLookup(max_key, max_value, table->data(), static_cast<size_t>(table->length())) {}
// Performs a binary search in the packed table, looking for an element with key
// referring to a target equal according to the comparator.
// When the element is found, found_key and found_value are updated from the element
// and the function returns true.
// When the element is not found, found_key and found_value are not changed and
// the function returns false.
bool search(Comparator& comparator, uint32_t* found_key, uint32_t* found_value) const;
// Asserts that elements in the packed table follow the order defined by the comparator.
DEBUG_ONLY(void validate_order(Comparator &comparator) const);
template<typename Function>
void iterate(Function func) const {
for (size_t offset = 0; offset < _table_length; offset += _element_bytes) {
uint64_t element = read_element(offset);
uint32_t key = static_cast<uint32_t>(element) & _key_mask;
uint32_t value = checked_cast<uint32_t>(element >> _value_shift) & _value_mask;
func(offset, key, value);
}
}
};

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 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
@@ -261,7 +261,7 @@ class UNSIGNED5 : AllStatic {
ARR _array;
OFF _limit;
OFF _position;
int next_length() {
int next_length() const {
return UNSIGNED5::check_length(_array, _position, _limit, GET());
}
public:
@@ -270,7 +270,7 @@ class UNSIGNED5 : AllStatic {
uint32_t next_uint() {
return UNSIGNED5::read_uint(_array, _position, _limit, GET());
}
bool has_next() {
bool has_next() const {
return next_length() != 0;
}
// tries to skip count logical entries; returns actual number skipped
@@ -284,8 +284,9 @@ class UNSIGNED5 : AllStatic {
return actual;
}
ARR array() { return _array; }
OFF limit() { return _limit; }
OFF position() { return _position; }
OFF limit() const { return _limit; }
OFF position() const { return _position; }
void set_limit(OFF limit) { _limit = limit; }
void set_position(OFF position) { _position = position; }
// For debugging, even in product builds (see debug.cpp).

View File

@@ -38,7 +38,7 @@ import java.nio.charset.StandardCharsets;
* <p>
* The {@link #readln()} and {@link #readln(String)} methods decode bytes read from
* {@code System.in} into characters. The charset used for decoding is specified by the
* {@link System#getProperties stdin.encoding} property. If this property is not present,
* {@link System##stdin.encoding stdin.encoding} property. If this property is not present,
* or if the charset it names cannot be loaded, then UTF-8 is used instead. Decoding
* always replaces malformed and unmappable byte sequences with the charset's default
* replacement string.

View File

@@ -1589,6 +1589,11 @@ public final class String
* @return {@code true} if {@link #length()} is {@code 0}, otherwise
* {@code false}
*
* @apiNote
* To determine whether a string contains only
* {@linkplain Character#isWhitespace(int) white space}, use
* {@link #isBlank() isBlank}.
*
* @since 1.6
*/
@Override
@@ -3827,9 +3832,13 @@ public final class String
* begins with the character at index <i>k</i> and ends with the
* character at index <i>m</i>-that is, the result of
* {@code this.substring(k, m + 1)}.
* <p>
* This method may be used to trim space (as defined above) from
* the beginning and end of a string.
*
* @apiNote
* This method removes leading and trailing space characters and ASCII control
* characters from the string. To remove characters using a Unicode-based definition of
* {@linkplain Character#isWhitespace(int) white space}, use {@link #strip() strip},
* {@link #stripIndent() stripIndent}, {@link #stripLeading() stripLeading}, or
* {@link #stripTrailing() stripTrailing}.
*
* @return a string whose value is this string, with all leading
* and trailing space removed, or this string if it
@@ -3934,13 +3943,9 @@ public final class String
}
/**
* Returns {@code true} if the string is empty or contains only
* {@linkplain Character#isWhitespace(int) white space} codepoints,
* otherwise {@code false}.
*
* @return {@code true} if the string is empty or contains only
* {@linkplain Character#isWhitespace(int) white space} codepoints,
* otherwise {@code false}
* {@return {@code true} if the string is {@linkplain #isEmpty empty} or contains
* only {@linkplain Character#isWhitespace(int) white space} codepoints,
* otherwise {@code false}}
*
* @see Character#isWhitespace(int)
*

View File

@@ -1030,14 +1030,6 @@ public sealed interface ClassFile
*/
int JAVA_25_VERSION = 69;
/**
* The class major version introduced by Java SE 26, {@value}.
*
* @see ClassFileFormatVersion#RELEASE_26
* @since 26
*/
int JAVA_26_VERSION = 70;
/**
* A minor version number {@value} indicating a class uses preview features
* of a Java SE release since 12, for major versions {@value
@@ -1049,7 +1041,7 @@ public sealed interface ClassFile
* {@return the latest class major version supported by the current runtime}
*/
static int latestMajorVersion() {
return JAVA_26_VERSION;
return JAVA_25_VERSION;
}
/**

View File

@@ -371,18 +371,6 @@ public enum ClassFileFormatVersion {
* <cite>The Java Virtual Machine Specification, Java SE 25 Edition</cite></a>
*/
RELEASE_25(69),
/**
* The version introduced by the Java Platform, Standard Edition
* 26.
*
* @since 26
*
* @see <a
* href="https://docs.oracle.com/javase/specs/jvms/se26/html/index.html">
* <cite>The Java Virtual Machine Specification, Java SE 26 Edition</cite></a>
*/
RELEASE_26(70),
; // Reduce code churn when appending new constants
// Note to maintainers: when adding constants for newer releases,
@@ -398,7 +386,7 @@ public enum ClassFileFormatVersion {
* {@return the latest class file format version}
*/
public static ClassFileFormatVersion latest() {
return RELEASE_26;
return RELEASE_25;
}
/**

View File

@@ -81,24 +81,24 @@ import java.util.Objects;
* {@link PEMRecord}.
*
* <p> The {@linkplain #decode(String, Class)} and
* {@linkplain #decode(InputStream, Class)} methods take a Class parameter
* {@linkplain #decode(InputStream, Class)} methods take a class parameter
* which determines the type of {@code DEREncodable} that is returned. These
* methods are useful when extracting or changing the return class.
* For example, if the PEM contains both public and private keys, the
* Class parameter can specify which to return. Use
* class parameter can specify which to return. Use
* {@code PrivateKey.class} to return only the private key.
* If the Class parameter is set to {@code X509EncodedKeySpec.class}, the
* If the class parameter is set to {@code X509EncodedKeySpec.class}, the
* public key will be returned in that format. Any type of PEM data can be
* decoded into a {@code PEMRecord} by specifying {@code PEMRecord.class}.
* If the Class parameter doesn't match the PEM content, an
* {@code IllegalArgumentException} will be thrown.
* If the class parameter doesn't match the PEM content, a
* {@linkplain ClassCastException} will be thrown.
*
* <p> A new {@code PEMDecoder} instance is created when configured
* with {@linkplain #withFactory(Provider)} and/or
* {@linkplain #withDecryption(char[])}. {@linkplain #withFactory(Provider)}
* configures the decoder to use only {@linkplain KeyFactory} and
* {@linkplain CertificateFactory} instances from the given {@code Provider}.
* {@link#withDecryption(char[])} configures the decoder to decrypt all
* {@linkplain #withDecryption(char[])} configures the decoder to decrypt all
* encrypted private key PEM data using the given password.
* Configuring an instance for decryption does not prevent decoding with
* unencrypted PEM. Any encrypted PEM that fails decryption
@@ -117,15 +117,15 @@ import java.util.Objects;
* <p> Here is an example of a {@code PEMDecoder} configured with decryption
* and a factory provider:
* {@snippet lang = java:
* PEMDecoder pe = PEMDecoder.of().withDecryption(password).
* PEMDecoder pd = PEMDecoder.of().withDecryption(password).
* withFactory(provider);
* byte[] pemData = pe.decode(privKey);
* byte[] pemData = pd.decode(privKey);
* }
*
* @implNote An implementation may support other PEM types and
* {@code DEREncodables}. This implementation additionally supports PEM types:
* {@code X509 CERTIFICATE}, {@code X.509 CERTIFICATE}, {@code CRL},
* and {@code RSA PRIVATE KEY}.
* {@code DEREncodable} objects. This implementation additionally supports
* the following PEM types: {@code X509 CERTIFICATE},
* {@code X.509 CERTIFICATE}, {@code CRL}, and {@code RSA PRIVATE KEY}.
*
* @see PEMEncoder
* @see PEMRecord
@@ -179,13 +179,13 @@ public final class PEMDecoder {
return switch (pem.type()) {
case Pem.PUBLIC_KEY -> {
X509EncodedKeySpec spec =
new X509EncodedKeySpec(decoder.decode(pem.pem()));
new X509EncodedKeySpec(decoder.decode(pem.content()));
yield getKeyFactory(
KeyUtil.getAlgorithm(spec.getEncoded())).
generatePublic(spec);
}
case Pem.PRIVATE_KEY -> {
PKCS8Key p8key = new PKCS8Key(decoder.decode(pem.pem()));
PKCS8Key p8key = new PKCS8Key(decoder.decode(pem.content()));
String algo = p8key.getAlgorithm();
KeyFactory kf = getKeyFactory(algo);
DEREncodable d = kf.generatePrivate(
@@ -216,27 +216,27 @@ public final class PEMDecoder {
case Pem.ENCRYPTED_PRIVATE_KEY -> {
if (password == null) {
yield new EncryptedPrivateKeyInfo(decoder.decode(
pem.pem()));
pem.content()));
}
yield new EncryptedPrivateKeyInfo(decoder.decode(pem.pem())).
yield new EncryptedPrivateKeyInfo(decoder.decode(pem.content())).
getKey(password.getPassword());
}
case Pem.CERTIFICATE, Pem.X509_CERTIFICATE,
Pem.X_509_CERTIFICATE -> {
CertificateFactory cf = getCertFactory("X509");
yield (X509Certificate) cf.generateCertificate(
new ByteArrayInputStream(decoder.decode(pem.pem())));
new ByteArrayInputStream(decoder.decode(pem.content())));
}
case Pem.X509_CRL, Pem.CRL -> {
CertificateFactory cf = getCertFactory("X509");
yield (X509CRL) cf.generateCRL(
new ByteArrayInputStream(decoder.decode(pem.pem())));
new ByteArrayInputStream(decoder.decode(pem.content())));
}
case Pem.RSA_PRIVATE_KEY -> {
KeyFactory kf = getKeyFactory("RSA");
yield kf.generatePrivate(
RSAPrivateCrtKeyImpl.getKeySpec(decoder.decode(
pem.pem())));
pem.content())));
}
default -> pem;
};
@@ -271,7 +271,6 @@ public final class PEMDecoder {
*/
public DEREncodable decode(String str) {
Objects.requireNonNull(str);
DEREncodable de;
try {
return decode(new ByteArrayInputStream(
str.getBytes(StandardCharsets.UTF_8)));
@@ -483,9 +482,6 @@ public final class PEMDecoder {
* from the specified {@link Provider} to produce cryptographic objects.
* Any errors using the {@code Provider} will occur during decoding.
*
* <p>If {@code provider} is {@code null}, a new instance is returned with
* the default provider configuration.
*
* @param provider the factory provider
* @return a new PEMEncoder instance configured to the {@code Provider}.
* @throws NullPointerException if {@code provider} is null

View File

@@ -71,7 +71,7 @@ import java.util.concurrent.locks.ReentrantLock;
* OneAsymmetricKey structure using the "PRIVATE KEY" type.
*
* <p> When encoding a {@link PEMRecord}, the API surrounds the
* {@linkplain PEMRecord#pem()} with the PEM header and footer
* {@linkplain PEMRecord#content()} with the PEM header and footer
* from {@linkplain PEMRecord#type()}. {@linkplain PEMRecord#leadingData()} is
* not included in the encoding. {@code PEMRecord} will not perform
* validity checks on the data.
@@ -108,7 +108,8 @@ import java.util.concurrent.locks.ReentrantLock;
* byte[] pemData = pe.encode(privKey);
* }
*
* @implNote An implementation may support other PEM types and DEREncodables.
* @implNote An implementation may support other PEM types and
* {@code DEREncodable} objects.
*
*
* @see PEMDecoder
@@ -287,7 +288,7 @@ public final class PEMEncoder {
}
// If `keySpec` is non-null, then `key` hasn't been established.
// Setting a `key' prevents repeated key generations operations.
// Setting a `key` prevents repeated key generation operations.
// withEncryption() is a configuration method and cannot throw an
// exception; therefore generation is delayed.
if (keySpec != null) {

View File

@@ -29,7 +29,6 @@ import jdk.internal.javac.PreviewFeature;
import sun.security.util.Pem;
import java.util.Base64;
import java.util.Objects;
/**
@@ -39,20 +38,20 @@ import java.util.Objects;
* cryptographic object is not desired or the type has no
* {@code DEREncodable}.
*
* <p> {@code type} and {@code pem} may not be {@code null}.
* <p> {@code type} and {@code content} may not be {@code null}.
* {@code leadingData} may be null if no non-PEM data preceded PEM header
* during decoding. {@code leadingData} may be useful for reading metadata
* that accompanies PEM data.
*
* <p> No validation is performed during instantiation to ensure that
* {@code type} conforms to {@code RFC 7468}, that {@code pem} is valid Base64,
* or that {@code pem} matches the {@code type}. {@code leadingData} is not
* defensively copied and does not return a clone when
* {@linkplain #leadingData()} is called.
* {@code type} conforms to {@code RFC 7468}, that {@code content} is valid
* Base64, or that {@code content} matches the {@code type}.
* {@code leadingData} is not defensively copied and does not return a
* clone when {@linkplain #leadingData()} is called.
*
* @param type the type identifier in the PEM header without PEM syntax labels.
* For a public key, {@code type} would be "PUBLIC KEY".
* @param pem any data between the PEM header and footer.
* @param content the Base64-encoded data, excluding the PEM header and footer
* @param leadingData any non-PEM data preceding the PEM header when decoding.
*
* @spec https://www.rfc-editor.org/info/rfc7468
@@ -64,25 +63,25 @@ import java.util.Objects;
* @since 25
*/
@PreviewFeature(feature = PreviewFeature.Feature.PEM_API)
public record PEMRecord(String type, String pem, byte[] leadingData)
public record PEMRecord(String type, String content, byte[] leadingData)
implements DEREncodable {
/**
* Creates a {@code PEMRecord} instance with the given parameters.
*
* @param type the type identifier
* @param pem the Base64-encoded data encapsulated by the PEM header and
* footer.
* @param content the Base64-encoded data, excluding the PEM header and
* footer
* @param leadingData any non-PEM data read during the decoding process
* before the PEM header. This value maybe {@code null}.
* @throws IllegalArgumentException if the {@code type} is incorrectly
* @throws IllegalArgumentException if {@code type} is incorrectly
* formatted.
* @throws NullPointerException if {@code type} and/or {@code pem} are
* @throws NullPointerException if {@code type} and/or {@code content} are
* {@code null}.
*/
public PEMRecord(String type, String pem, byte[] leadingData) {
public PEMRecord {
Objects.requireNonNull(type, "\"type\" cannot be null.");
Objects.requireNonNull(pem, "\"pem\" cannot be null.");
Objects.requireNonNull(content, "\"content\" cannot be null.");
// With no validity checking on `type`, the constructor accept anything
// including lowercase. The onus is on the caller.
@@ -92,37 +91,22 @@ public record PEMRecord(String type, String pem, byte[] leadingData)
"Only the PEM type identifier is allowed");
}
this.type = type;
this.pem = pem;
this.leadingData = leadingData;
}
/**
* Creates a {@code PEMRecord} instance with a given {@code type} and
* {@code pem} data in String form. {@code leadingData} is set to null.
* {@code content} data in String form. {@code leadingData} is set to null.
*
* @param type the PEM type identifier
* @param pem the Base64-encoded data encapsulated by the PEM header and
* footer.
* @throws IllegalArgumentException if the {@code type} is incorrectly
* @param content the Base64-encoded data, excluding the PEM header and
* footer
* @throws IllegalArgumentException if {@code type} is incorrectly
* formatted.
* @throws NullPointerException if {@code type} and/or {@code pem} are
* @throws NullPointerException if {@code type} and/or {@code content} are
* {@code null}.
*/
public PEMRecord(String type, String pem) {
this(type, pem, null);
}
/**
* Returns the binary encoding from the Base64 data contained in
* {@code pem}.
*
* @throws IllegalArgumentException if {@code pem} cannot be decoded.
* @return a new array of the binary encoding each time this
* method is called.
*/
public byte[] getEncoded() {
return Base64.getMimeDecoder().decode(pem);
public PEMRecord(String type, String content) {
this(type, content, null);
}
/**

View File

@@ -621,10 +621,10 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
if (port != -1 && port != url.getDefaultPort()) {
host += ":" + String.valueOf(port);
}
String reqHost = requests.findValue("Host");
if (reqHost == null || !reqHost.equalsIgnoreCase(host)) {
requests.set("Host", host);
}
// if the "Host" header hasn't been explicitly set, then set its
// value to the one determined through the request URL
requests.setIfNotSet("Host", host);
requests.setIfNotSet("Accept", acceptString);
/*

View File

@@ -94,6 +94,15 @@ public class Net {
return EXCLUSIVE_BIND;
}
private static final StableValue<Boolean> SHUTDOWN_WRITE_BEFORE_CLOSE = StableValue.of();
/**
* Tells whether a TCP connection should be shutdown for writing before closing.
*/
static boolean shouldShutdownWriteBeforeClose() {
return SHUTDOWN_WRITE_BEFORE_CLOSE.orElseSet(Net::shouldShutdownWriteBeforeClose0);
}
/**
* Tells whether both IPV6_XXX and IP_XXX socket options should be set on
* IPv6 sockets. On some kernels, both IPV6_XXX and IP_XXX socket options
@@ -462,6 +471,8 @@ public class Net {
*/
private static native int isExclusiveBindAvailable();
private static native boolean shouldShutdownWriteBeforeClose0();
private static native boolean shouldSetBothIPv4AndIPv6Options0();
private static native boolean canIPv6SocketJoinIPv4Group0();

View File

@@ -846,7 +846,7 @@ class SocketChannelImpl
/**
* Marks the beginning of a connect operation that might block.
* @param blocking true if configured blocking
* @param isa the remote address
* @param sa the remote socket address
* @throws ClosedChannelException if the channel is closed
* @throws AlreadyConnectedException if already connected
* @throws ConnectionPendingException is a connection is pending
@@ -1070,8 +1070,8 @@ class SocketChannelImpl
}
/**
* Closes the socket if there are no I/O operations in progress and the
* channel is not registered with a Selector.
* Closes the socket if there are no I/O operations in progress (or no I/O
* operations tracked), and the channel is not registered with a Selector.
*/
private boolean tryClose() throws IOException {
assert Thread.holdsLock(stateLock) && state == ST_CLOSING;
@@ -1096,11 +1096,21 @@ class SocketChannelImpl
}
/**
* Closes this channel when configured in blocking mode.
* Closes this channel when configured in blocking mode. If there are no I/O
* operations in progress (or tracked), then the channel's socket is closed. If
* there are I/O operations in progress then the behavior is platform specific.
*
* If there is an I/O operation in progress then the socket is pre-closed
* and the I/O threads signalled, in which case the final close is deferred
* until all I/O operations complete.
* On Unix systems, the channel's socket is pre-closed. This unparks any virtual
* threads that are blocked in I/O operations on this channel. If there are
* platform threads blocked on the channel's socket then the socket is dup'ed
* and the platform threads signalled. The final close is deferred until all I/O
* operations complete.
*
* On Windows, the channel's socket is pre-closed. This unparks any virtual
* threads that are blocked in I/O operations on this channel. If there are no
* virtual threads blocked in I/O operations on this channel then the channel's
* socket is closed. If there are virtual threads in I/O then the final close is
* deferred until all I/O operations on virtual threads complete.
*
* Note that a channel configured blocking may be registered with a Selector
* This arises when a key is canceled and the channel configured to blocking
@@ -1112,17 +1122,17 @@ class SocketChannelImpl
boolean connected = (state == ST_CONNECTED);
state = ST_CLOSING;
if (!tryClose()) {
if (connected && Net.shouldShutdownWriteBeforeClose()) {
// shutdown output when linger interval not set to 0
if (connected) {
try {
var SO_LINGER = StandardSocketOptions.SO_LINGER;
if ((int) Net.getSocketOption(fd, SO_LINGER) != 0) {
Net.shutdown(fd, Net.SHUT_WR);
}
} catch (IOException ignore) { }
}
try {
var SO_LINGER = StandardSocketOptions.SO_LINGER;
if ((int) Net.getSocketOption(fd, SO_LINGER) != 0) {
Net.shutdown(fd, Net.SHUT_WR);
}
} catch (IOException ignore) { }
}
if (!tryClose()) {
// prepare file descriptor for closing
nd.preClose(fd, readerThread, writerThread);
}

View File

@@ -565,7 +565,7 @@ public class X509Factory extends CertificateFactorySpi {
} catch (EOFException e) {
return null;
}
return Base64.getDecoder().decode(rec.pem());
return Base64.getDecoder().decode(rec.content());
} catch (IllegalArgumentException e) {
throw new IOException(e);
}

View File

@@ -343,7 +343,7 @@ public class Pem {
* @return PEM in a string
*/
public static String pemEncoded(PEMRecord pem) {
String p = pem.pem().replaceAll("(.{64})", "$1\r\n");
String p = pem.content().replaceAll("(.{64})", "$1\r\n");
return pemEncoded(pem.type(), p);
}
}

View File

@@ -0,0 +1,21 @@
Owner: CN=Sectigo Public Code Signing Root E46, O=Sectigo Limited, C=GB
Issuer: CN=Sectigo Public Code Signing Root E46, O=Sectigo Limited, C=GB
Serial number: 50249ba2ef8ea6bf6c2c1f1a6385d4c3
Valid from: Mon Mar 22 00:00:00 GMT 2021 until: Wed Mar 21 23:59:59 GMT 2046
Signature algorithm name: SHA384withECDSA
Subject Public Key Algorithm: 384-bit EC (secp384r1) key
Version: 3
-----BEGIN CERTIFICATE-----
MIICKDCCAa+gAwIBAgIQUCSbou+Opr9sLB8aY4XUwzAKBggqhkjOPQQDAzBWMQsw
CQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMS0wKwYDVQQDEyRT
ZWN0aWdvIFB1YmxpYyBDb2RlIFNpZ25pbmcgUm9vdCBFNDYwHhcNMjEwMzIyMDAw
MDAwWhcNNDYwMzIxMjM1OTU5WjBWMQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2Vj
dGlnbyBMaW1pdGVkMS0wKwYDVQQDEyRTZWN0aWdvIFB1YmxpYyBDb2RlIFNpZ25p
bmcgUm9vdCBFNDYwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQIMoEDH487om+BR4zl
e7m6wWmyW0nAKLkUWG8kM85Qm3PZO8FoOZx6Yc5c0iJHRKuAhanllayqrmZYhlan
uIODzLTRDqlR+EtnOX+MubY5aDSPGUq6jiHrQrisVp0J3AejQjBAMB0GA1UdDgQW
BBTPfSygkHqYHd22XoXC4NoVcdLlXjAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/
BAUwAwEB/zAKBggqhkjOPQQDAwNnADBkAjACd++zAerlV83j8HflRwwwlLmgchbs
aGX/4g44dv/oG8KfzCVTRg6sZHMobtK0IqYCMGk5W6+oBFyZMtOebrSwXs8lGjll
/zHz43Zy8DMXO+iiqzSEwWGneZ6KupkGGqfVKw==
-----END CERTIFICATE-----

View File

@@ -0,0 +1,39 @@
Owner: CN=Sectigo Public Code Signing Root R46, O=Sectigo Limited, C=GB
Issuer: CN=Sectigo Public Code Signing Root R46, O=Sectigo Limited, C=GB
Serial number: 4b2c3b01018bad2abc8c7b5b3eed9057
Valid from: Mon Mar 22 00:00:00 GMT 2021 until: Wed Mar 21 23:59:59 GMT 2046
Signature algorithm name: SHA384withRSA
Subject Public Key Algorithm: 4096-bit RSA key
Version: 3
-----BEGIN CERTIFICATE-----
MIIFeDCCA2CgAwIBAgIQSyw7AQGLrSq8jHtbPu2QVzANBgkqhkiG9w0BAQwFADBW
MQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMS0wKwYDVQQD
EyRTZWN0aWdvIFB1YmxpYyBDb2RlIFNpZ25pbmcgUm9vdCBSNDYwHhcNMjEwMzIy
MDAwMDAwWhcNNDYwMzIxMjM1OTU5WjBWMQswCQYDVQQGEwJHQjEYMBYGA1UEChMP
U2VjdGlnbyBMaW1pdGVkMS0wKwYDVQQDEyRTZWN0aWdvIFB1YmxpYyBDb2RlIFNp
Z25pbmcgUm9vdCBSNDYwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCN
55QSIgQkdC7/FiMCkoq2rjaFrEfUI5ErPtx94jGgUW+shJHjUoq14pbe0IdjJImK
/+8Skzt9u7aKvb0Ffyeba2XTpQxpsbxJOZrxbW6q5KCDJ9qaDStQ6Utbs7hkNqR+
Sj2pcaths3OzPAsM79szV+W+NDfjlxtd/R8SPYIDdub7P2bSlDFp+m2zNKzBenjc
klDyZMeqLQSrw2rq4C+np9xu1+j/2iGrQL+57g2extmeme/G3h+pDHazJyCh1rr9
gOcB0u/rgimVcI3/uxXP/tEPNqIuTzKQdEZrRzUTdwUzT2MuuC3hv2WnBGsY2HH6
zAjybYmZELGt2z4s5KoYsMYHAXVn3m3pY2MeNn9pib6qRT5uWl+PoVvLnTCGMOgD
s0DGDQ84zWeoU4j6uDBl+m/H5x2xg3RpPqzEaDux5mczmrYI4IAFSEDu9oJkRqj1
c7AGlfJsZZ+/VVscnFcax3hGfHCqlBuCF6yH6bbJDoEcQNYWFyn8XJwYK+pF9e+9
1WdPKF4F7pBMeufG9ND8+s0+MkYTIDaKBOq3qgdGnA2TOglmmVhcKaO5DKYwODzQ
RjY1fJy67sPV+Qp2+n4FG0DKkjXp1XrRtX8ArqmQqsV/AZwQsRb8zG4Y3G9i/qZQ
p7h7uJ0VP/4gDHXIIloTlRmQAOka1cKG8eOO7F/05QIDAQABo0IwQDAdBgNVHQ4E
FgQUMuuSmv81lkgvKEBCcCA2kVwXheYwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB
/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAHZlwuPXIkrXHYle/2lexhQCTXOm
zc0oyrA36r+nySGqql/av/aDbNCA0QpcAKTL88w5D55BcYjVPOiKe4wXI/fKNHSR
bAauUD8AWbImPDwXg1cDPi3RGj3UzwdUskMLUnKoiPXEF/Jv0Vil0WjkPZgIGO42
9EhImvpUcPCI1HAWMEJJ0Nk/dUtFcdiuorthDoiFUFe5uhErNikfjyBynlyeidGC
2kWNapnahHFrM6UQu3nwl/Z0gaA/V8eGjDCMDjiVrgHGHqvcqB9vL9f/dh6uF3Nt
5bl1s2EGqJUzwk5vsjfylb6FVBK5yL1iQnb3Kvz1NzEDJlf+0ebb8BYCcoOMCLOE
rKnkB/ihiMQTWlBHVEKm7dBBNCyYsT6iNKEMXb2s9395p79tDFYyhRtLl7jhrOSk
PHHxo+FOY9b0Rrr1CwjhYzztolkvCtQsayOinqFN7tESzRgzUO1Bbst/PUFgC2ML
ePV170MVtzYLEK/cXBipmNk22R3YhLMGioLjexskp0LO7g8+VlwyfexL3lYrOzu6
+XpY0FG2bNb2WKJSJHpEhqEcYD9J0/z6+YQcBcI0v+Lm8RkqmS9WVzWctfUHw0Yv
3jg9GQ37o/HfE57nqXJYMa+96trX1m13MzOO9Kz9wb9Jh9JwBWd0Bqb2eEAtFgSR
Dx/TFsS4ehcNJMmy
-----END CERTIFICATE-----

View File

@@ -0,0 +1,21 @@
Owner: CN=Sectigo Public Server Authentication Root E46, O=Sectigo Limited, C=GB
Issuer: CN=Sectigo Public Server Authentication Root E46, O=Sectigo Limited, C=GB
Serial number: 42f2ccda1b6937445f15fe752810b8f4
Valid from: Mon Mar 22 00:00:00 GMT 2021 until: Wed Mar 21 23:59:59 GMT 2046
Signature algorithm name: SHA384withECDSA
Subject Public Key Algorithm: 384-bit EC (secp384r1) key
Version: 3
-----BEGIN CERTIFICATE-----
MIICOjCCAcGgAwIBAgIQQvLM2htpN0RfFf51KBC49DAKBggqhkjOPQQDAzBfMQsw
CQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1T
ZWN0aWdvIFB1YmxpYyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBFNDYwHhcN
MjEwMzIyMDAwMDAwWhcNNDYwMzIxMjM1OTU5WjBfMQswCQYDVQQGEwJHQjEYMBYG
A1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1TZWN0aWdvIFB1YmxpYyBT
ZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBFNDYwdjAQBgcqhkjOPQIBBgUrgQQA
IgNiAAR2+pmpbiDt+dd34wc7qNs9Xzjoq1WmVk/WSOrsfy2qw7LFeeyZYX8QeccC
WvkEN/U0NSt3zn8gj1KjAIns1aeibVvjS5KToID1AZTc8GgHHs3u/iVStSBDHBv+
6xnOQ6OjQjBAMB0GA1UdDgQWBBTRItpMWfFLXyY4qp3W7usNw/upYTAOBgNVHQ8B
Af8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNnADBkAjAn7qRa
qCG76UeXlImldCBteU/IvZNeWBj7LRoAasm4PdCkT0RHlAFWovgzJQxC36oCMB3q
4S6ILuH5px0CMk7yn2xVdOOurvulGu7t0vzCAxHrRVxgED1cf5kDW21USAGKcw==
-----END CERTIFICATE-----

View File

@@ -0,0 +1,39 @@
Owner: CN=Sectigo Public Server Authentication Root R46, O=Sectigo Limited, C=GB
Issuer: CN=Sectigo Public Server Authentication Root R46, O=Sectigo Limited, C=GB
Serial number: 758dfd8bae7c0700faa925a7e1c7ad14
Valid from: Mon Mar 22 00:00:00 GMT 2021 until: Wed Mar 21 23:59:59 GMT 2046
Signature algorithm name: SHA384withRSA
Subject Public Key Algorithm: 4096-bit RSA key
Version: 3
-----BEGIN CERTIFICATE-----
MIIFijCCA3KgAwIBAgIQdY39i658BwD6qSWn4cetFDANBgkqhkiG9w0BAQwFADBf
MQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQD
Ey1TZWN0aWdvIFB1YmxpYyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBSNDYw
HhcNMjEwMzIyMDAwMDAwWhcNNDYwMzIxMjM1OTU5WjBfMQswCQYDVQQGEwJHQjEY
MBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1TZWN0aWdvIFB1Ymxp
YyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBSNDYwggIiMA0GCSqGSIb3DQEB
AQUAA4ICDwAwggIKAoICAQCTvtU2UnXYASOgHEdCSe5jtrch/cSV1UgrJnwUUxDa
ef0rty2k1Cz66jLdScK5vQ9IPXtamFSvnl0xdE8H/FAh3aTPaE8bEmNtJZlMKpnz
SDBh+oF8HqcIStw+KxwfGExxqjWMrfhu6DtK2eWUAtaJhBOqbchPM8xQljeSM9xf
iOefVNlI8JhD1mb9nxc4Q8UBUQvX4yMPFF1bFOdLvt30yNoDN9HWOaEhUTCDsG3X
ME6WW5HwcCSrv0WBZEMNvSE6Lzzpng3LILVCJ8zab5vuZDCQOc2TZYEhMbUjUDM3
IuM47fgxMMxF/mL50V0yeUKH32rMVhlATc6qu/m1dkmU8Sf4kaWD5QazYw6A3OAS
VYCmO2a0OYctyPDQ0RTp5A1NDvZdV3LFOxxHVp3i1fuBYYzMTYCQNFu31xR13NgE
SJ/AwSiItOkcyqex8Va3e0lMWeUgFaiEAin6OJRpmkkGj80feRQXEgyDet4fsZfu
+Zd4KKTIRJLpfSYFplhym3kT2BFfrsU4YjRosoYwjviQYZ4ybPUHNs2iTG7sijbt
8uaZFURww3y8nDnAtOFr94MlI1fZEoDlSfB1D++N6xybVCi0ITz8fAr/73trdf+L
HaAZBav6+CuBQug4urv7qv094PPK306Xlynt8xhW6aWWrL3DkJiy4Pmi1KZHQ3xt
zwIDAQABo0IwQDAdBgNVHQ4EFgQUVnNYZJX5khqwEioEYnmhQBWIIUkwDgYDVR0P
AQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAC9c
mTz8Bl6MlC5w6tIyMY208FHVvArzZJ8HXtXBc2hkeqK5Duj5XYUtqDdFqij0lgVQ
YKlJfp/imTYpE0RHap1VIDzYm/EDMrraQKFz6oOht0SmDpkBm+S8f74TlH7Kph52
gDY9hAaLMyZlbcp+nv4fjFg4exqDsQ+8FxG75gbMY/qB8oFM2gsQa6H61SilzwZA
Fv97fRheORKkU55+MkIQpiGRqRxOF3yEvJ+M0ejf5lG5Nkc/kLnHvALcWxxPDkjB
JYOcCj+esQMzEhonrPcibCTRAUH4WAP+JWgiH5paPHxsnnVI84HxZmduTILA7rpX
DhjvLpr3Etiga+kFpaHpaPi8TD8SHkXoUsCjvxInebnMMTzD9joiFgOgyY9mpFui
TdaBJQbpdqQACj7LzTWb4OE4y2BThihCQRxEV+ioratF4yUQvNs+ZUH7G6aXD+u5
dHn5HrwdVw1Hr8Mvn4dGp+smWg9WY7ViYG4A++MnESLn/pmPNPW56MORcr3Ywx65
LvKRRFHQV80MNNVIIb/bE/FmJUNS0nAiNs2fxBx1IK1jcmMGDw4nztJqDby1ORrp
0XZ60Vzk50lJLVU3aPAaOpg+VBeHVOmmJ1CJeyAvP/+/oYtKR5j/K3tJPsMpRmAY
QqszKbrAKbkTidOIijlBO8n9pu0f9GBj39ItVQGL
-----END CERTIFICATE-----

View File

@@ -1449,9 +1449,10 @@ These `java` options control the runtime behavior of the Java HotSpot VM.
`report-on-exit=`*identifier*
: Specifies the name of the view to display when the Java Virtual Machine
(JVM) shuts down. This option is not available if the disk option is set
to false. For a list of available views, see `jfr help view`. By default,
no report is generated.
(JVM) shuts down. To specify more than one view, use the report-on-exit
parameter repeatedly. This option is not available if the disk option
is set to false. For a list of available views, see `jfr help view`.
By default, no report is generated.
`settings=`*path*
: Specifies the path and name of the event settings file (of type JFC).

View File

@@ -91,14 +91,7 @@ DEF_JNI_OnLoad(JavaVM *vm, void *reserved)
}
static int enhancedExceptionsInitialized = 0;
static int enhancedExceptionsAllowed = -1;
#define CHECK_NULL_THROW_ERROR(X) \
if (X == NULL) { \
JNU_ThrowByName(env, "java/lang/InternalError", \
"can't initialize enhanced exceptions"); \
return -1; \
}
static int enhancedExceptionsAllowed = 0;
int getEnhancedExceptionsAllowed(JNIEnv *env) {
jclass cls;
@@ -108,9 +101,9 @@ int getEnhancedExceptionsAllowed(JNIEnv *env) {
return enhancedExceptionsAllowed;
}
cls = (*env)->FindClass(env, "jdk/internal/util/Exceptions");
CHECK_NULL_THROW_ERROR(cls);
CHECK_NULL_RETURN(cls, ENH_INIT_ERROR);
fid = (*env)->GetStaticFieldID(env, cls, "enhancedNonSocketExceptionText", "Z");
CHECK_NULL_THROW_ERROR(fid);
CHECK_NULL_RETURN(fid, ENH_INIT_ERROR);
enhancedExceptionsAllowed = (*env)->GetStaticBooleanField(env, cls, fid);
enhancedExceptionsInitialized = 1;
return enhancedExceptionsAllowed;

View File

@@ -183,6 +183,11 @@ int lookupCharacteristicsToAddressFamily(int characteristics);
int addressesInSystemOrder(int characteristics);
/* return codes */
#define ENH_INIT_ERROR -1 /* initialization error: check exceptions */
#define ENH_DISABLED 0 /* enhanced exceptions disabled */
#define ENH_ENABLED 1 /* enhanced exceptions enabled */
int getEnhancedExceptionsAllowed(JNIEnv *env);
#endif /* NET_UTILS_H */

View File

@@ -188,8 +188,11 @@ void NET_ThrowUnknownHostExceptionWithGaiError(JNIEnv *env,
if (error_string == NULL)
error_string = "unknown error";
int enhancedExceptions = getEnhancedExceptionsAllowed(env);
if (enhancedExceptions == ENH_INIT_ERROR && (*env)->ExceptionCheck(env)) {
return;
}
if (enhancedExceptions) {
if (enhancedExceptions == ENH_ENABLED) {
size = strlen(hostname);
} else {
size = 0;
@@ -200,7 +203,7 @@ void NET_ThrowUnknownHostExceptionWithGaiError(JNIEnv *env,
if (buf) {
jstring s;
int n;
if (enhancedExceptions) {
if (enhancedExceptions == ENH_ENABLED) {
n = snprintf(buf, size, "%s: %s", hostname, error_string);
} else {
n = snprintf(buf, size, " %s", error_string);

View File

@@ -205,6 +205,11 @@ Java_sun_nio_ch_Net_isExclusiveBindAvailable(JNIEnv *env, jclass clazz) {
return -1;
}
JNIEXPORT jboolean JNICALL
Java_sun_nio_ch_Net_shouldShutdownWriteBeforeClose0(JNIEnv *env, jclass clazz) {
return JNI_FALSE;
}
JNIEXPORT jboolean JNICALL
Java_sun_nio_ch_Net_shouldSetBothIPv4AndIPv6Options0(JNIEnv* env, jclass cl)
{

View File

@@ -88,9 +88,12 @@ Java_java_net_Inet4AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
if (error) {
// report error
NET_ThrowByNameWithLastError(
env, "java/net/UnknownHostException",
getEnhancedExceptionsAllowed(env) ? hostname : "");
int enh = getEnhancedExceptionsAllowed(env);
if (enh == ENH_INIT_ERROR && (*env)->ExceptionCheck(env)) {
goto cleanupAndReturn;
}
const char *hmsg = (enh == ENH_ENABLED) ? hostname : "";
NET_ThrowByNameWithLastError( env, "java/net/UnknownHostException", hmsg);
goto cleanupAndReturn;
} else {
int i = 0;

View File

@@ -83,8 +83,12 @@ Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
if (error) {
// report error
NET_ThrowByNameWithLastError(env, "java/net/UnknownHostException",
getEnhancedExceptionsAllowed(env) ? hostname : "");
int enh = getEnhancedExceptionsAllowed(env);
if (enh == ENH_INIT_ERROR && (*env)->ExceptionCheck(env)) {
goto cleanupAndReturn;
}
const char *hmsg = (enh == ENH_ENABLED) ? hostname : "";
NET_ThrowByNameWithLastError(env, "java/net/UnknownHostException", hmsg);
goto cleanupAndReturn;
} else {
int i = 0, inetCount = 0, inet6Count = 0, inetIndex = 0,

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 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
@@ -117,6 +117,11 @@ Java_sun_nio_ch_Net_isExclusiveBindAvailable(JNIEnv *env, jclass clazz) {
return 1;
}
JNIEXPORT jboolean JNICALL
Java_sun_nio_ch_Net_shouldShutdownWriteBeforeClose0(JNIEnv *env, jclass clazz) {
return JNI_TRUE;
}
JNIEXPORT jboolean JNICALL
Java_sun_nio_ch_Net_shouldSetBothIPv4AndIPv6Options0(JNIEnv* env, jclass cl)
{

View File

@@ -468,18 +468,6 @@ public enum SourceVersion {
* JEP 513: Flexible Constructor Bodies</a>
*/
RELEASE_25,
/**
* The version introduced by the Java Platform, Standard Edition
* 26.
*
* @since 26
*
* @see <a
* href="https://docs.oracle.com/javase/specs/jls/se26/html/index.html">
* <cite>The Java Language Specification, Java SE 26 Edition</cite></a>
*/
RELEASE_26,
; // Reduce code churn when appending new constants
// Note that when adding constants for newer releases, the
@@ -489,7 +477,7 @@ public enum SourceVersion {
* {@return the latest source version that can be modeled}
*/
public static SourceVersion latest() {
return RELEASE_26;
return RELEASE_25;
}
private static final SourceVersion latestSupported = getLatestSupported();
@@ -504,7 +492,7 @@ public enum SourceVersion {
private static SourceVersion getLatestSupported() {
int intVersion = Runtime.version().feature();
return (intVersion >= 11) ?
valueOf("RELEASE_" + Math.min(26, intVersion)):
valueOf("RELEASE_" + Math.min(25, intVersion)):
RELEASE_10;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2024, 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,7 +44,7 @@ import javax.annotation.processing.SupportedSourceVersion;
* @see AbstractAnnotationValueVisitor9
* @since 14
*/
@SupportedSourceVersion(RELEASE_26)
@SupportedSourceVersion(RELEASE_25)
public abstract class AbstractAnnotationValueVisitor14<R, P> extends AbstractAnnotationValueVisitor9<R, P> {
/**

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -50,7 +50,7 @@ import javax.annotation.processing.ProcessingEnvironment;
* @see AbstractAnnotationValueVisitor14
* @since 23
*/
@SupportedSourceVersion(RELEASE_26)
@SupportedSourceVersion(RELEASE_25)
@PreviewFeature(feature=PreviewFeature.Feature.LANGUAGE_MODEL, reflective=true)
public abstract class AbstractAnnotationValueVisitorPreview<R, P> extends AbstractAnnotationValueVisitor14<R, P> {

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -50,7 +50,7 @@ import static javax.lang.model.SourceVersion.*;
* @see AbstractElementVisitor9
* @since 16
*/
@SupportedSourceVersion(RELEASE_26)
@SupportedSourceVersion(RELEASE_25)
public abstract class AbstractElementVisitor14<R, P> extends AbstractElementVisitor9<R, P> {
/**
* Constructor for concrete subclasses to call.

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -53,7 +53,7 @@ import static javax.lang.model.SourceVersion.*;
* @see AbstractElementVisitor14
* @since 23
*/
@SupportedSourceVersion(RELEASE_26)
@SupportedSourceVersion(RELEASE_25)
@PreviewFeature(feature=PreviewFeature.Feature.LANGUAGE_MODEL, reflective=true)
public abstract class AbstractElementVisitorPreview<R, P> extends AbstractElementVisitor14<R, P> {
/**

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -47,7 +47,7 @@ import static javax.lang.model.SourceVersion.*;
* @see AbstractTypeVisitor9
* @since 14
*/
@SupportedSourceVersion(RELEASE_26)
@SupportedSourceVersion(RELEASE_25)
public abstract class AbstractTypeVisitor14<R, P> extends AbstractTypeVisitor9<R, P> {
/**
* Constructor for concrete subclasses to call.

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -53,7 +53,7 @@ import static javax.lang.model.SourceVersion.*;
* @see AbstractTypeVisitor14
* @since 23
*/
@SupportedSourceVersion(RELEASE_26)
@SupportedSourceVersion(RELEASE_25)
@PreviewFeature(feature=PreviewFeature.Feature.LANGUAGE_MODEL, reflective=true)
public abstract class AbstractTypeVisitorPreview<R, P> extends AbstractTypeVisitor14<R, P> {
/**

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -61,7 +61,7 @@ import javax.lang.model.SourceVersion;
* @see ElementKindVisitor9
* @since 16
*/
@SupportedSourceVersion(RELEASE_26)
@SupportedSourceVersion(RELEASE_25)
public class ElementKindVisitor14<R, P> extends ElementKindVisitor9<R, P> {
/**
* Constructor for concrete subclasses; uses {@code null} for the

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2024, 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
@@ -67,7 +67,7 @@ import static javax.lang.model.SourceVersion.*;
* @see ElementKindVisitor14
* @since 23
*/
@SupportedSourceVersion(RELEASE_26)
@SupportedSourceVersion(RELEASE_25)
@PreviewFeature(feature=PreviewFeature.Feature.LANGUAGE_MODEL, reflective=true)
public class ElementKindVisitorPreview<R, P> extends ElementKindVisitor14<R, P> {
/**

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2024, 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
@@ -77,7 +77,7 @@ import static javax.lang.model.SourceVersion.*;
* @see ElementScanner9
* @since 16
*/
@SupportedSourceVersion(RELEASE_26)
@SupportedSourceVersion(RELEASE_25)
public class ElementScanner14<R, P> extends ElementScanner9<R, P> {
/**
* Constructor for concrete subclasses; uses {@code null} for the

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2024, 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
@@ -81,7 +81,7 @@ import static javax.lang.model.SourceVersion.*;
* @see ElementScanner14
* @since 23
*/
@SupportedSourceVersion(RELEASE_26)
@SupportedSourceVersion(RELEASE_25)
@PreviewFeature(feature=PreviewFeature.Feature.LANGUAGE_MODEL, reflective=true)
public class ElementScannerPreview<R, P> extends ElementScanner14<R, P> {
/**

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2024, 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
@@ -52,7 +52,7 @@ import static javax.lang.model.SourceVersion.*;
* @see SimpleAnnotationValueVisitor9
* @since 14
*/
@SupportedSourceVersion(RELEASE_26)
@SupportedSourceVersion(RELEASE_25)
public class SimpleAnnotationValueVisitor14<R, P> extends SimpleAnnotationValueVisitor9<R, P> {
/**
* Constructor for concrete subclasses; uses {@code null} for the

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -58,7 +58,7 @@ import static javax.lang.model.SourceVersion.*;
* @see SimpleAnnotationValueVisitor14
* @since 23
*/
@SupportedSourceVersion(RELEASE_26)
@SupportedSourceVersion(RELEASE_25)
@PreviewFeature(feature=PreviewFeature.Feature.LANGUAGE_MODEL, reflective=true)
public class SimpleAnnotationValueVisitorPreview<R, P> extends SimpleAnnotationValueVisitor14<R, P> {
/**

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -58,7 +58,7 @@ import static javax.lang.model.SourceVersion.*;
* @see SimpleElementVisitor9
* @since 16
*/
@SupportedSourceVersion(RELEASE_26)
@SupportedSourceVersion(RELEASE_25)
public class SimpleElementVisitor14<R, P> extends SimpleElementVisitor9<R, P> {
/**
* Constructor for concrete subclasses; uses {@code null} for the

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -61,7 +61,7 @@ import static javax.lang.model.SourceVersion.*;
* @see SimpleElementVisitor14
* @since 23
*/
@SupportedSourceVersion(RELEASE_26)
@SupportedSourceVersion(RELEASE_25)
@PreviewFeature(feature=PreviewFeature.Feature.LANGUAGE_MODEL, reflective=true)
public class SimpleElementVisitorPreview<R, P> extends SimpleElementVisitor14<R, P> {
/**

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -56,7 +56,7 @@ import static javax.lang.model.SourceVersion.*;
* @see SimpleTypeVisitor9
* @since 14
*/
@SupportedSourceVersion(RELEASE_26)
@SupportedSourceVersion(RELEASE_25)
public class SimpleTypeVisitor14<R, P> extends SimpleTypeVisitor9<R, P> {
/**
* Constructor for concrete subclasses; uses {@code null} for the

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2024, 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
@@ -62,7 +62,7 @@ import static javax.lang.model.SourceVersion.*;
* @see SimpleTypeVisitor14
* @since 23
*/
@SupportedSourceVersion(RELEASE_26)
@SupportedSourceVersion(RELEASE_25)
@PreviewFeature(feature=PreviewFeature.Feature.LANGUAGE_MODEL, reflective=true)
public class SimpleTypeVisitorPreview<R, P> extends SimpleTypeVisitor14<R, P> {
/**

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -61,7 +61,7 @@ import static javax.lang.model.SourceVersion.*;
* @see TypeKindVisitor9
* @since 14
*/
@SupportedSourceVersion(RELEASE_26)
@SupportedSourceVersion(RELEASE_25)
public class TypeKindVisitor14<R, P> extends TypeKindVisitor9<R, P> {
/**
* Constructor for concrete subclasses to call; uses {@code null}

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