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

View File

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

View File

@@ -1,6 +1,6 @@
#!/bin/bash #!/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. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
# #
# This code is free software; you can redistribute it and/or modify it # 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. # Print additional help, e.g. a list of toolchains and JVM features.
# This must be done by the autoconf script. # 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 cat <<EOT

View File

@@ -26,17 +26,17 @@
# Default version, product, and vendor information to use, # Default version, product, and vendor information to use,
# unless overridden by configure # unless overridden by configure
DEFAULT_VERSION_FEATURE=26 DEFAULT_VERSION_FEATURE=25
DEFAULT_VERSION_INTERIM=0 DEFAULT_VERSION_INTERIM=0
DEFAULT_VERSION_UPDATE=0 DEFAULT_VERSION_UPDATE=0
DEFAULT_VERSION_PATCH=0 DEFAULT_VERSION_PATCH=0
DEFAULT_VERSION_EXTRA1=0 DEFAULT_VERSION_EXTRA1=0
DEFAULT_VERSION_EXTRA2=0 DEFAULT_VERSION_EXTRA2=0
DEFAULT_VERSION_EXTRA3=0 DEFAULT_VERSION_EXTRA3=0
DEFAULT_VERSION_DATE=2026-03-17 DEFAULT_VERSION_DATE=2025-09-16
DEFAULT_VERSION_CLASSFILE_MAJOR=70 # "`$EXPR $DEFAULT_VERSION_FEATURE + 44`" DEFAULT_VERSION_CLASSFILE_MAJOR=69 # "`$EXPR $DEFAULT_VERSION_FEATURE + 44`"
DEFAULT_VERSION_CLASSFILE_MINOR=0 DEFAULT_VERSION_CLASSFILE_MINOR=0
DEFAULT_VERSION_DOCS_API_SINCE=11 DEFAULT_VERSION_DOCS_API_SINCE=11
DEFAULT_ACCEPTABLE_BOOT_VERSIONS="24 25 26" DEFAULT_ACCEPTABLE_BOOT_VERSIONS="24 25"
DEFAULT_JDK_SOURCE_TARGET_VERSION=26 DEFAULT_JDK_SOURCE_TARGET_VERSION=25
DEFAULT_PROMOTED_VERSION_PRE=ea 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); cmov_cmp_fp_le(op1, op2, dst, src, is_single);
break; break;
case BoolTest::ge: case BoolTest::ge:
assert(false, "Should go to BoolTest::le case"); cmov_cmp_fp_ge(op1, op2, dst, src, is_single);
ShouldNotReachHere();
break; break;
case BoolTest::lt: case BoolTest::lt:
cmov_cmp_fp_lt(op1, op2, dst, src, is_single); cmov_cmp_fp_lt(op1, op2, dst, src, is_single);
break; break;
case BoolTest::gt: case BoolTest::gt:
assert(false, "Should go to BoolTest::lt case"); cmov_cmp_fp_gt(op1, op2, dst, src, is_single);
ShouldNotReachHere();
break; break;
default: default:
assert(false, "unsupported compare condition"); 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 ----------- // ----------- 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) { void MacroAssembler::cmov_cmp_fp_eq(FloatRegister cmp1, FloatRegister cmp2, Register dst, Register src, bool is_single) {
if (UseZicond) { if (UseZicond) {
if (is_single) { if (is_single) {
@@ -1289,7 +1296,7 @@ void MacroAssembler::cmov_cmp_fp_eq(FloatRegister cmp1, FloatRegister cmp2, Regi
Label no_set; Label no_set;
if (is_single) { if (is_single) {
// jump if cmp1 != cmp2, including the case of NaN // 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); float_bne(cmp1, cmp2, no_set);
} else { } else {
double_bne(cmp1, cmp2, no_set); double_bne(cmp1, cmp2, no_set);
@@ -1298,11 +1305,6 @@ void MacroAssembler::cmov_cmp_fp_eq(FloatRegister cmp1, FloatRegister cmp2, Regi
bind(no_set); 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) { void MacroAssembler::cmov_cmp_fp_ne(FloatRegister cmp1, FloatRegister cmp2, Register dst, Register src, bool is_single) {
if (UseZicond) { if (UseZicond) {
if (is_single) { if (is_single) {
@@ -1318,7 +1320,7 @@ void MacroAssembler::cmov_cmp_fp_ne(FloatRegister cmp1, FloatRegister cmp2, Regi
Label no_set; Label no_set;
if (is_single) { if (is_single) {
// jump if cmp1 == cmp2 // 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); float_beq(cmp1, cmp2, no_set);
} else { } else {
double_beq(cmp1, cmp2, no_set); double_beq(cmp1, cmp2, no_set);
@@ -1327,14 +1329,6 @@ void MacroAssembler::cmov_cmp_fp_ne(FloatRegister cmp1, FloatRegister cmp2, Regi
bind(no_set); 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) { void MacroAssembler::cmov_cmp_fp_le(FloatRegister cmp1, FloatRegister cmp2, Register dst, Register src, bool is_single) {
if (UseZicond) { if (UseZicond) {
if (is_single) { if (is_single) {
@@ -1350,7 +1344,7 @@ void MacroAssembler::cmov_cmp_fp_le(FloatRegister cmp1, FloatRegister cmp2, Regi
Label no_set; Label no_set;
if (is_single) { if (is_single) {
// jump if cmp1 > cmp2 // 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); float_bgt(cmp1, cmp2, no_set);
} else { } else {
double_bgt(cmp1, cmp2, no_set); double_bgt(cmp1, cmp2, no_set);
@@ -1359,14 +1353,30 @@ void MacroAssembler::cmov_cmp_fp_le(FloatRegister cmp1, FloatRegister cmp2, Regi
bind(no_set); bind(no_set);
} }
// When cmp1 < cmp2 or any of them is NaN then dst = src, otherwise, dst = dst void MacroAssembler::cmov_cmp_fp_ge(FloatRegister cmp1, FloatRegister cmp2, Register dst, Register src, bool is_single) {
// Clarification if (UseZicond) {
// scenario 1: if (is_single) {
// java code : cmp2 <= cmp1 ? dst : src fle_s(t0, cmp2, cmp1);
// transformed to : CMove dst, (cmp1 lt cmp2), dst, src } else {
// scenario 2: fle_d(t0, cmp2, cmp1);
// java code : cmp1 >= cmp2 ? dst : src }
// transformed to : CMove dst, (cmp1 lt cmp2), dst, src 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) { void MacroAssembler::cmov_cmp_fp_lt(FloatRegister cmp1, FloatRegister cmp2, Register dst, Register src, bool is_single) {
if (UseZicond) { if (UseZicond) {
if (is_single) { if (is_single) {
@@ -1382,7 +1392,7 @@ void MacroAssembler::cmov_cmp_fp_lt(FloatRegister cmp1, FloatRegister cmp2, Regi
Label no_set; Label no_set;
if (is_single) { if (is_single) {
// jump if cmp1 >= cmp2 // 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); float_bge(cmp1, cmp2, no_set);
} else { } else {
double_bge(cmp1, cmp2, no_set); double_bge(cmp1, cmp2, no_set);
@@ -1391,6 +1401,30 @@ void MacroAssembler::cmov_cmp_fp_lt(FloatRegister cmp1, FloatRegister cmp2, Regi
bind(no_set); 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 // Float compare branch instructions
#define INSN(NAME, FLOATCMP, BRANCH) \ #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_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_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_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_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: public:
// We try to follow risc-v asm menomics. // 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); __ subptr(rsp, 8);
__ movdbl(Address(rsp), src); __ movdbl(Address(rsp), src);
__ call(RuntimeAddress(target)); __ call(RuntimeAddress(target));
// APX REX2 encoding for pop(dst) increases the stub size by 1 byte.
__ pop(dst); __ pop(dst);
__ jmp(stub.continuation()); __ jmp(stub.continuation());
#undef __ #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()); jcc(Assembler::equal, stub->entry());
bind(stub->continuation()); bind(stub->continuation());
} }

View File

@@ -239,7 +239,7 @@
do_arch_blob, \ do_arch_blob, \
do_arch_entry, \ do_arch_entry, \
do_arch_entry_init) \ do_arch_entry_init) \
do_arch_blob(final, 31000 \ do_arch_blob(final, 33000 \
WINDOWS_ONLY(+22000) ZGC_ONLY(+20000)) \ WINDOWS_ONLY(+22000) ZGC_ONLY(+20000)) \
#endif // CPU_X86_STUBDECLARATIONS_HPP #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 // has improved implementation of 64-byte load/stores and so the default
// threshold is set to 0 for these platforms. // threshold is set to 0 for these platforms.
int VM_Version::avx3_threshold() { int VM_Version::avx3_threshold() {
return (is_intel_family_core() && return (is_intel_server_family() &&
supports_serialize() && supports_serialize() &&
FLAG_IS_DEFAULT(AVX3Threshold)) ? 0 : AVX3Threshold; 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 // Xor Register with Immediate
instruct xorI_rReg_imm(rRegI dst, immI src, rFlagsReg cr) 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)); match(Set dst (XorI dst src));
effect(KILL cr); 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); 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) 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)); match(Set dst (XorI src1 src2));
effect(KILL cr); 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); 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); predicate(UseAPX);
match(Set dst (XorI (LoadI src1) src2)); match(Set dst (XorI (LoadI src1) src2));
effect(KILL cr); 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); 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" %} 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 // Xor Register with Immediate
instruct xorL_rReg_imm(rRegL dst, immL32 src, rFlagsReg cr) 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)); match(Set dst (XorL dst src));
effect(KILL cr); 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); 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) 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)); match(Set dst (XorL src1 src2));
effect(KILL cr); 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); 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)); match(Set dst (XorL (LoadL src1) src2));
effect(KILL cr); 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); 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" %} format %{ "exorq $dst, $src1, $src2\t# long ndd" %}
ins_encode %{ 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); Deoptimization::DeoptReason reason = Deoptimization::trap_request_reason(trap_request);
if (action == Deoptimization::Action_make_not_entrant) { 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) { if (reason == Deoptimization::Reason_tenured) {
MethodData* trap_mdo = Deoptimization::get_method_data(current, method, true /*create_if_missing*/); MethodData* trap_mdo = Deoptimization::get_method_data(current, method, true /*create_if_missing*/);
if (trap_mdo != nullptr) { 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. // safepoint, but if it's still alive then make it not_entrant.
nmethod* nm = CodeCache::find_nmethod(caller_frame.pc()); nmethod* nm = CodeCache::find_nmethod(caller_frame.pc());
if (nm != nullptr) { 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()); 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. // Make sure the nmethod is invalidated, i.e. made not entrant.
nmethod* nm = CodeCache::find_nmethod(caller_frame.pc()); nmethod* nm = CodeCache::find_nmethod(caller_frame.pc());
if (nm != nullptr) { 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()); nmethod* nm = CodeCache::find_nmethod(caller_frame.pc());
assert (nm != nullptr, "no more nmethod?"); 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()); methodHandle m(current, nm->method());
MethodData* mdo = m->method_data(); 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * 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_Convert (Convert* x) { /* nothing to do */ }
void do_NullCheck (NullCheck* x) { /* nothing to do */ } void do_NullCheck (NullCheck* x) { /* nothing to do */ }
void do_TypeCast (TypeCast* 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_NewTypeArray (NewTypeArray* x) { /* nothing to do */ }
void do_NewObjectArray (NewObjectArray* x) { /* nothing to do */ } void do_NewObjectArray (NewObjectArray* x) { /* nothing to do */ }
void do_NewMultiArray (NewMultiArray* 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); 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 // ciInstanceKlass::find_method
// //

View File

@@ -231,6 +231,8 @@ public:
ciInstanceKlass* unique_concrete_subklass(); ciInstanceKlass* unique_concrete_subklass();
bool has_finalizable_subclass(); bool has_finalizable_subclass();
bool has_class_initializer();
bool contains_field_offset(int offset); bool contains_field_offset(int offset);
// Get the instance of java.lang.Class corresponding to // 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 // 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(); nmethod* nm = (entry_bci != InvocationEntryBci) ? method->lookup_osr_nmethod_for(entry_bci, comp_level, true) : method->code();
if (nm != nullptr) { if (nm != nullptr) {
nm->make_not_entrant(nmethod::ChangeReason::CI_replay); nm->make_not_entrant("CI replay");
} }
replay_state = this; replay_state = this;
CompileBroker::compile_method(methodHandle(THREAD, method), entry_bci, comp_level, CompileBroker::compile_method(methodHandle(THREAD, method), entry_bci, comp_level,

View File

@@ -154,8 +154,6 @@
#define JAVA_25_VERSION 69 #define JAVA_25_VERSION 69
#define JAVA_26_VERSION 70
void ClassFileParser::set_class_bad_constant_seen(short bad_constant) { void ClassFileParser::set_class_bad_constant_seen(short bad_constant) {
assert((bad_constant == JVM_CONSTANT_Module || assert((bad_constant == JVM_CONSTANT_Module ||
bad_constant == JVM_CONSTANT_Package) && _major_version >= JAVA_9_VERSION, 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); _cp->set_pool_holder(this_klass);
this_klass->set_constants(_cp); this_klass->set_constants(_cp);
this_klass->set_fieldinfo_stream(_fieldinfo_stream); 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_fields_status(_fields_status);
this_klass->set_methods(_methods); this_klass->set_methods(_methods);
this_klass->set_inner_classes(_inner_classes); 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_permitted_subclasses(_permitted_subclasses);
this_klass->set_record_components(_record_components); 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 // Delay the setting of _local_interfaces and _transitive_interfaces until after
// initialize_supers() in fill_instance_klass(). It is because the _local_interfaces could // 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 // 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 // note that is not safe to use the fields in the parser from this point on
assert(nullptr == _cp, "invariant"); assert(nullptr == _cp, "invariant");
assert(nullptr == _fieldinfo_stream, "invariant"); assert(nullptr == _fieldinfo_stream, "invariant");
assert(nullptr == _fieldinfo_search_table, "invariant");
assert(nullptr == _fields_status, "invariant"); assert(nullptr == _fields_status, "invariant");
assert(nullptr == _methods, "invariant"); assert(nullptr == _methods, "invariant");
assert(nullptr == _inner_classes, "invariant"); assert(nullptr == _inner_classes, "invariant");
@@ -5276,6 +5278,7 @@ ClassFileParser::ClassFileParser(ClassFileStream* stream,
_super_klass(), _super_klass(),
_cp(nullptr), _cp(nullptr),
_fieldinfo_stream(nullptr), _fieldinfo_stream(nullptr),
_fieldinfo_search_table(nullptr),
_fields_status(nullptr), _fields_status(nullptr),
_methods(nullptr), _methods(nullptr),
_inner_classes(nullptr), _inner_classes(nullptr),
@@ -5352,6 +5355,7 @@ void ClassFileParser::clear_class_metadata() {
// deallocated if classfile parsing returns an error. // deallocated if classfile parsing returns an error.
_cp = nullptr; _cp = nullptr;
_fieldinfo_stream = nullptr; _fieldinfo_stream = nullptr;
_fieldinfo_search_table = nullptr;
_fields_status = nullptr; _fields_status = nullptr;
_methods = nullptr; _methods = nullptr;
_inner_classes = nullptr; _inner_classes = nullptr;
@@ -5374,6 +5378,7 @@ ClassFileParser::~ClassFileParser() {
if (_fieldinfo_stream != nullptr) { if (_fieldinfo_stream != nullptr) {
MetadataFactory::free_array<u1>(_loader_data, _fieldinfo_stream); MetadataFactory::free_array<u1>(_loader_data, _fieldinfo_stream);
} }
MetadataFactory::free_array<u1>(_loader_data, _fieldinfo_search_table);
if (_fields_status != nullptr) { if (_fields_status != nullptr) {
MetadataFactory::free_array<FieldStatus>(_loader_data, _fields_status); MetadataFactory::free_array<FieldStatus>(_loader_data, _fields_status);
@@ -5774,6 +5779,7 @@ void ClassFileParser::post_process_parsed_stream(const ClassFileStream* const st
_fieldinfo_stream = _fieldinfo_stream =
FieldInfoStream::create_FieldInfoStream(_temp_field_info, _java_fields_count, FieldInfoStream::create_FieldInfoStream(_temp_field_info, _java_fields_count,
injected_fields_count, loader_data(), CHECK); injected_fields_count, loader_data(), CHECK);
_fieldinfo_search_table = FieldInfoStream::create_search_table(_cp, _fieldinfo_stream, _loader_data, CHECK);
_fields_status = _fields_status =
MetadataFactory::new_array<FieldStatus>(_loader_data, _temp_field_info->length(), MetadataFactory::new_array<FieldStatus>(_loader_data, _temp_field_info->length(),
FieldStatus(0), CHECK); 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@@ -123,6 +123,7 @@ class ClassFileParser {
const InstanceKlass* _super_klass; const InstanceKlass* _super_klass;
ConstantPool* _cp; ConstantPool* _cp;
Array<u1>* _fieldinfo_stream; Array<u1>* _fieldinfo_stream;
Array<u1>* _fieldinfo_search_table;
Array<FieldStatus>* _fields_status; Array<FieldStatus>* _fields_status;
Array<Method*>* _methods; Array<Method*>* _methods;
Array<u2>* _inner_classes; Array<u2>* _inner_classes;

View File

@@ -301,7 +301,7 @@ void FieldLayout::reconstruct_layout(const InstanceKlass* ik, bool& has_instance
BasicType last_type; BasicType last_type;
int last_offset = -1; int last_offset = -1;
while (ik != nullptr) { 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()); BasicType type = Signature::basic_type(fs.signature());
// distinction between static and non-static fields is missing // distinction between static and non-static fields is missing
if (fs.access_flags().is_static()) continue; if (fs.access_flags().is_static()) continue;
@@ -461,7 +461,7 @@ void FieldLayout::print(outputStream* output, bool is_static, const InstanceKlas
bool found = false; bool found = false;
const InstanceKlass* ik = super; const InstanceKlass* ik = super;
while (!found && ik != nullptr) { 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()) { if (fs.offset() == b->offset()) {
output->print_cr(" @%d \"%s\" %s %d/%d %s", output->print_cr(" @%d \"%s\" %s %d/%d %s",
b->offset(), 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); Array<u1>* new_fis = FieldInfoStream::create_FieldInfoStream(fields, java_fields, injected_fields, k->class_loader_data(), CHECK);
ik->set_fieldinfo_stream(new_fis); ik->set_fieldinfo_stream(new_fis);
MetadataFactory::free_array<u1>(k->class_loader_data(), old_stream); 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; _store_buffer = nullptr;
} }
if (_table != nullptr) { if (_table != nullptr) {
MutexLocker ml(AOTCodeCStrings_lock, Mutex::_no_safepoint_check_flag);
delete _table; delete _table;
_table = nullptr; _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 // we need to take a lock to prevent race between compiler threads generating AOT code
// and the main thread generating adapter // and the main thread generating adapter
MutexLocker ml(Compile_lock); MutexLocker ml(Compile_lock);
if (!is_on()) {
return false; // AOT code cache was already dumped and closed.
}
if (!cache->align_write()) { if (!cache->align_write()) {
return false; return false;
} }
@@ -1485,6 +1489,7 @@ void AOTCodeCache::load_strings() {
int AOTCodeCache::store_strings() { int AOTCodeCache::store_strings() {
if (_C_strings_used > 0) { if (_C_strings_used > 0) {
MutexLocker ml(AOTCodeCStrings_lock, Mutex::_no_safepoint_check_flag);
uint offset = _write_position; uint offset = _write_position;
uint length = 0; uint length = 0;
uint* lengths = (uint *)reserve_bytes(sizeof(uint) * _C_strings_used); 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) { const char* AOTCodeCache::add_C_string(const char* str) {
if (is_on_for_dump() && str != nullptr) { 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; return str;
} }
const char* AOTCodeAddressTable::add_C_string(const char* str) { const char* AOTCodeAddressTable::add_C_string(const char* str) {
if (_extrs_complete) { 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 // Check previous strings address
for (int i = 0; i < _C_strings_count; i++) { for (int i = 0; i < _C_strings_count; i++) {
if (_C_strings_in[i] == str) { 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; _C_strings_in[_C_strings_count] = str;
const char* dup = os::strdup(str); const char* dup = os::strdup(str);
_C_strings[_C_strings_count++] = dup; _C_strings[_C_strings_count++] = dup;
if (log.is_enabled()) { log_trace(aot, codecache, stringtable)("add_C_string: [%d] " INTPTR_FORMAT " '%s'", _C_strings_count, p2i(dup), dup);
log.print_cr("add_C_string: [%d] " INTPTR_FORMAT " '%s'", _C_strings_count, p2i(dup), dup);
}
return dup; return dup;
} else { } else {
assert(false, "Number of C strings >= MAX_STR_COUNT"); assert(false, "Number of C strings >= MAX_STR_COUNT");

View File

@@ -1361,7 +1361,7 @@ void CodeCache::make_marked_nmethods_deoptimized() {
while(iter.next()) { while(iter.next()) {
nmethod* nm = iter.method(); nmethod* nm = iter.method();
if (nm->is_marked_for_deoptimization() && !nm->has_been_deoptimized() && nm->can_be_deoptimized()) { 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(); 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 (LogCompilation) {
if (xtty != nullptr) { if (xtty != nullptr) {
ttyLocker ttyl; // keep the following output all in one block ttyLocker ttyl; // keep the following output all in one block
xtty->begin_elem("make_not_entrant thread='%zu' reason='%s'", 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); log_identity(xtty);
xtty->stamp(); xtty->stamp();
xtty->end_elem(); xtty->end_elem();
@@ -1989,7 +1991,7 @@ void nmethod::log_state_change(ChangeReason change_reason) const {
ResourceMark rm; ResourceMark rm;
stringStream ss(NEW_RESOURCE_ARRAY(char, 256), 256); 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()); CompileTask::print_ul(this, ss.freeze());
if (PrintCompilation) { if (PrintCompilation) {
@@ -2004,7 +2006,9 @@ void nmethod::unlink_from_method() {
} }
// Invalidate code // 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 // This can be called while the system is already at a safepoint which is ok
NoSafepointVerifier nsv; NoSafepointVerifier nsv;
@@ -2073,7 +2077,7 @@ bool nmethod::make_not_entrant(ChangeReason change_reason) {
assert(success, "Transition can't fail"); assert(success, "Transition can't fail");
// Log the transition once // Log the transition once
log_state_change(change_reason); log_state_change(reason);
// Remove nmethod from method. // Remove nmethod from method.
unlink_from_method(); unlink_from_method();

View File

@@ -471,85 +471,6 @@ class nmethod : public CodeBlob {
void oops_do_set_strong_done(nmethod* old_head); void oops_do_set_strong_done(nmethod* old_head);
public: 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 // create nmethod with entry_bci
static nmethod* new_nmethod(const methodHandle& method, static nmethod* new_nmethod(const methodHandle& method,
int compile_id, int compile_id,
@@ -712,8 +633,8 @@ public:
// alive. It is used when an uncommon trap happens. Returns true // alive. It is used when an uncommon trap happens. Returns true
// if this thread changed the state of the nmethod or false if // if this thread changed the state of the nmethod or false if
// another thread performed the transition. // another thread performed the transition.
bool make_not_entrant(ChangeReason change_reason); bool make_not_entrant(const char* reason);
bool make_not_used() { return make_not_entrant(ChangeReason::not_used); } bool make_not_used() { return make_not_entrant("not used"); }
bool is_marked_for_deoptimization() const { return deoptimization_status() != not_marked; } bool is_marked_for_deoptimization() const { return deoptimization_status() != not_marked; }
bool has_been_deoptimized() const { return deoptimization_status() == deoptimize_done; } bool has_been_deoptimized() const { return deoptimization_status() == deoptimize_done; }
@@ -1026,7 +947,7 @@ public:
// Logging // Logging
void log_identity(xmlStream* log) const; void log_identity(xmlStream* log) const;
void log_new_nmethod() 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: // Prints block-level comments, including nmethod specific block labels:
void print_nmethod_labels(outputStream* stream, address block_begin, bool print_section_labels=true) const; 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); nmethod* osr_nm = mh->lookup_osr_nmethod_for(bci, CompLevel_simple, false);
if (osr_nm != nullptr && osr_nm->comp_level() > CompLevel_simple) { if (osr_nm != nullptr && osr_nm->comp_level() > CompLevel_simple) {
// Invalidate the existing OSR nmethod so that a compile at CompLevel_simple is permitted. // 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); 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; int osr_bci = nm->is_osr_method() ? nm->osr_entry_bci() : InvocationEntryBci;
print_event(MAKE_NOT_ENTRANT, mh(), mh(), osr_bci, level); 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 // Fix up next_level if necessary to avoid deopts

View File

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

View File

@@ -62,8 +62,12 @@ private:
PhaseIdealLoop* phase, int flags); PhaseIdealLoop* phase, int flags);
static void call_lrb_stub(Node*& ctrl, Node*& val, Node* load_addr, static void call_lrb_stub(Node*& ctrl, Node*& val, Node* load_addr,
DecoratorSet decorators, PhaseIdealLoop* phase); 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 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); static Node* get_load_addr(PhaseIdealLoop* phase, VectorSet& visited, Node* lrb);
public: public:
@@ -76,6 +80,11 @@ public:
static bool expand(Compile* C, PhaseIterGVN& igvn); static bool expand(Compile* C, PhaseIterGVN& igvn);
static void pin_and_expand(PhaseIdealLoop* phase); 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 #ifdef ASSERT
static void verify(RootNode* root); static void verify(RootNode* root);
#endif #endif

View File

@@ -183,6 +183,29 @@ void ShenandoahGenerationalHeap::stop() {
regulator_thread()->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) { void ShenandoahGenerationalHeap::evacuate_collection_set(bool concurrent) {
ShenandoahRegionIterator regions; ShenandoahRegionIterator regions;
ShenandoahGenerationalEvacuationTask task(this, &regions, concurrent, false /* only promote regions */); ShenandoahGenerationalEvacuationTask task(this, &regions, concurrent, false /* only promote regions */);

View File

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

View File

@@ -27,7 +27,6 @@
#include "classfile/symbolTable.hpp" #include "classfile/symbolTable.hpp"
#include "classfile/systemDictionary.hpp" #include "classfile/systemDictionary.hpp"
#include "classfile/vmClasses.hpp" #include "classfile/vmClasses.hpp"
#include "code/nmethod.hpp"
#include "code/scopeDesc.hpp" #include "code/scopeDesc.hpp"
#include "compiler/compileBroker.hpp" #include "compiler/compileBroker.hpp"
#include "compiler/compilerEvent.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"); assert(JVMCIENV->isa_HotSpotNmethod(installed_code_handle), "wrong type");
// Clear the link to an old nmethod first // Clear the link to an old nmethod first
JVMCIObject nmethod_mirror = installed_code_handle; 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 { } else {
assert(JVMCIENV->isa_InstalledCode(installed_code_handle), "wrong type"); 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(); nmethod* code = method->code();
if (code != nullptr) { if (code != nullptr) {
code->make_not_entrant(nmethod::ChangeReason::JVMCI_reprofile); code->make_not_entrant("JVMCI reprofile");
} }
MethodData* method_data = method->method_data(); MethodData* method_data = method->method_data();
@@ -1398,7 +1397,7 @@ C2V_END
C2V_VMENTRY(void, invalidateHotSpotNmethod, (JNIEnv* env, jobject, jobject hs_nmethod, jboolean deoptimize)) C2V_VMENTRY(void, invalidateHotSpotNmethod, (JNIEnv* env, jobject, jobject hs_nmethod, jboolean deoptimize))
JVMCIObject nmethod_mirror = JVMCIENV->wrap(hs_nmethod); 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_END
C2V_VMENTRY_NULL(jlongArray, collectCounters, (JNIEnv* env, jobject)) 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()) { if (!fst.current()->is_compiled_frame()) {
JVMCI_THROW_MSG(IllegalStateException, "compiled stack frame expected"); 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); Deoptimization::deoptimize(thread, *fst.current(), Deoptimization::Reason_none);
// look for the frame again as it has been updated by deopt (pc, deopt state...) // 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()) { if (mirror.is_null()) {
JVMCI_THROW(NullPointerException); JVMCI_THROW(NullPointerException);
} }
@@ -1773,7 +1773,7 @@ void JVMCIEnv::invalidate_nmethod_mirror(JVMCIObject mirror, bool deoptimize, nm
if (!deoptimize) { if (!deoptimize) {
// Prevent future executions of the nmethod but let current executions complete. // 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 // Do not clear the address field here as the Java code may still
// want to later call this method with deoptimize == true. That requires // 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. // Deoptimize the nmethod immediately.
DeoptimizationScope deopt_scope; DeoptimizationScope deopt_scope;
deopt_scope.mark(nm); deopt_scope.mark(nm);
nm->make_not_entrant(change_reason); nm->make_not_entrant("JVMCI invalidate nmethod mirror");
nm->make_deoptimized(); nm->make_deoptimized();
deopt_scope.deoptimize_marked(); deopt_scope.deoptimize_marked();

View File

@@ -462,7 +462,7 @@ public:
// field of `mirror` to prevent it from being called. // field of `mirror` to prevent it from being called.
// If `deoptimize` is true, the nmethod is immediately deoptimized. // If `deoptimize` is true, the nmethod is immediately deoptimized.
// The HotSpotNmethod.address field is zero upon returning. // 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); 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); tty->print_cr("Replacing method %s", method_name);
} }
if (old != nullptr) { if (old != nullptr) {
old->make_not_entrant(nmethod::ChangeReason::JVMCI_register_method); old->make_not_entrant("JVMCI register method");
} }
LogTarget(Info, nmethod, install) lt; LogTarget(Info, nmethod, install) lt;

View File

@@ -47,7 +47,6 @@ void VectorSet::init(Arena* arena) {
// Expand the existing set to a bigger size // Expand the existing set to a bigger size
void VectorSet::grow(uint new_word_capacity) { 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 >= _size, "Should have been checked before, use maybe_grow?");
assert(new_word_capacity < (1U << 30), ""); assert(new_word_capacity < (1U << 30), "");
uint x = next_power_of_2(new_word_capacity); uint x = next_power_of_2(new_word_capacity);

View File

@@ -52,6 +52,7 @@ private:
// Grow vector to required word capacity // Grow vector to required word capacity
void maybe_grow(uint new_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) { if (new_word_capacity >= _size) {
grow(new_word_capacity); grow(new_word_capacity);
} }

View File

@@ -22,8 +22,11 @@
* *
*/ */
#include "memory/resourceArea.hpp"
#include "cds/cdsConfig.hpp"
#include "oops/fieldInfo.inline.hpp" #include "oops/fieldInfo.inline.hpp"
#include "runtime/atomic.hpp" #include "runtime/atomic.hpp"
#include "utilities/packedTable.hpp"
void FieldInfo::print(outputStream* os, ConstantPool* cp) { void FieldInfo::print(outputStream* os, ConstantPool* cp) {
os->print_cr("index=%d name_index=%d name=%s signature_index=%d signature=%s offset=%d " 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(), field_flags().as_uint(),
initializer_index(), initializer_index(),
generic_signature_index(), generic_signature_index(),
_field_flags.is_injected() ? lookup_symbol(generic_signature_index())->as_utf8() : cp->symbol_at(generic_signature_index())->as_utf8(), _field_flags.is_generic() ? (_field_flags.is_injected() ?
contended_group()); 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) { 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; StreamSizer s;
StreamFieldSizer sizer(&s); StreamFieldSizer sizer(&s);
assert(fields->length() == java_fields + injected_fields, "must be");
sizer.consumer()->accept_uint(java_fields); sizer.consumer()->accept_uint(java_fields);
sizer.consumer()->accept_uint(injected_fields); sizer.consumer()->accept_uint(injected_fields);
for (int i = 0; i < fields->length(); i++) { for (int i = 0; i < fields->length(); i++) {
FieldInfo* fi = fields->adr_at(i); FieldInfo* fi = fields->adr_at(i);
sizer.map_field_info(*fi); 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); 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>>; 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(java_fields);
writer.consumer()->accept_uint(injected_fields); writer.consumer()->accept_uint(injected_fields);
for (int i = 0; i < fields->length(); i++) { for (int i = 0; i < fields->length(); i++) {
FieldInfo* fi = fields->adr_at(i); writer.map_field_info(fields->at(i));
writer.map_field_info(*fi);
} }
#ifdef ASSERT #ifdef ASSERT
FieldInfoReader r(fis); FieldInfoReader r(fis);
int jfc = r.next_uint(); int jfc, ifc;
r.read_field_counts(&jfc, &ifc);
assert(jfc == java_fields, "Must be"); assert(jfc == java_fields, "Must be");
int ifc = r.next_uint();
assert(ifc == injected_fields, "Must be"); assert(ifc == injected_fields, "Must be");
for (int i = 0; i < jfc + ifc; i++) { for (int i = 0; i < jfc + ifc; i++) {
FieldInfo fi; FieldInfo fi;
@@ -113,30 +121,221 @@ Array<u1>* FieldInfoStream::create_FieldInfoStream(GrowableArray<FieldInfo>* fie
return fis; return fis;
} }
GrowableArray<FieldInfo>* FieldInfoStream::create_FieldInfoArray(const Array<u1>* fis, int* java_fields_count, int* injected_fields_count) { int FieldInfoStream::compare_name_and_sig(const Symbol* n1, const Symbol* s1, const Symbol* n2, const Symbol* s2) {
int length = FieldInfoStream::num_total_fields(fis); int cmp = n1->fast_compare(n2);
GrowableArray<FieldInfo>* array = new GrowableArray<FieldInfo>(length); 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); FieldInfoReader r(fis);
*java_fields_count = r.next_uint(); int java_fields;
*injected_fields_count = r.next_uint(); 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()) { while (r.has_next()) {
FieldInfo fi; FieldInfo fi;
r.read_field_info(fi); r.read_field_info(fi);
array->append(fi); array->append(fi);
} }
assert(array->length() == length, "Must be"); assert(array->length() == length, "Must be");
assert(array->length() == *java_fields_count + *injected_fields_count, "Must be");
return array; return array;
} }
void FieldInfoStream::print_from_fieldinfo_stream(Array<u1>* fis, outputStream* os, ConstantPool* cp) { void FieldInfoStream::print_from_fieldinfo_stream(Array<u1>* fis, outputStream* os, ConstantPool* cp) {
int length = FieldInfoStream::num_total_fields(fis);
FieldInfoReader r(fis); FieldInfoReader r(fis);
int java_field_count = r.next_uint(); int java_fields_count;
int injected_fields_count = r.next_uint(); int injected_fields_count;
r.read_field_counts(&java_fields_count, &injected_fields_count);
while (r.has_next()) { while (r.has_next()) {
FieldInfo fi; FieldInfo fi;
r.read_field_info(fi); r.read_field_info(fi);
fi.print(os, cp); 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); void map_field_info(const FieldInfo& fi);
}; };
// Gadget for decoding and reading the stream of field records. // Gadget for decoding and reading the stream of field records.
class FieldInfoReader { class FieldInfoReader {
friend class FieldInfoStream;
friend class ClassFileParser;
friend class FieldStreamBase;
friend class FieldInfo;
UNSIGNED5::Reader<const u1*, int> _r; UNSIGNED5::Reader<const u1*, int> _r;
int _next_index; int _next_index;
public: public:
FieldInfoReader(const Array<u1>* fi); FieldInfoReader(const Array<u1>* fi);
private: private:
uint32_t next_uint() { return _r.next_uint(); } inline uint32_t next_uint() { return _r.next_uint(); }
void skip(int n) { int s = _r.try_skip(n); assert(s == n,""); } void skip(int n) { int s = _r.try_skip(n); assert(s == n,""); }
public: public:
int has_next() { return _r.has_next(); } void read_field_counts(int* java_fields, int* injected_fields);
int position() { return _r.position(); } int has_next() const { return _r.position() < _r.limit(); }
int next_index() { return _next_index; } 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); 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 // skip a whole field record, both required and optional bits
FieldInfoReader& skip_field_info(); FieldInfoReader& skip_field_info();
@@ -271,6 +270,11 @@ class FieldInfoStream : AllStatic {
friend class JavaFieldStream; friend class JavaFieldStream;
friend class FieldStreamBase; friend class FieldStreamBase;
friend class ClassFileParser; 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: public:
static int num_java_fields(const Array<u1>* fis); 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 int num_total_fields(const Array<u1>* fis);
static Array<u1>* create_FieldInfoStream(GrowableArray<FieldInfo>* fields, int java_fields, int injected_fields, 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 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); 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 { 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) { inline int FieldInfoStream::num_injected_java_fields(const Array<u1>* fis) {
FieldInfoReader fir(fis); FieldInfoReader fir(fis);
fir.skip(1); int java_fields_count;
return fir.next_uint(); 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) { inline int FieldInfoStream::num_total_fields(const Array<u1>* fis) {
FieldInfoReader fir(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> template<typename CON>
inline void Mapper<CON>::map_field_info(const FieldInfo& fi) { 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) inline FieldInfoReader::FieldInfoReader(const Array<u1>* fi)
: _r(fi->data(), 0), : _r(fi->data(), fi->length()),
_next_index(0) { } _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) { inline void FieldInfoReader::read_field_info(FieldInfo& fi) {
fi._index = _next_index++; fi._index = _next_index++;
fi._name_index = checked_cast<u2>(next_uint()); read_name_and_signature(&fi._name_index, &fi._signature_index);
fi._signature_index = checked_cast<u2>(next_uint());
fi._offset = next_uint(); fi._offset = next_uint();
fi._access_flags = AccessFlags(checked_cast<u2>(next_uint())); fi._access_flags = AccessFlags(checked_cast<u2>(next_uint()));
fi._field_flags = FieldInfo::FieldFlags(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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * 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(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() { void initialize() {
int java_fields_count = _reader.next_uint(); int java_fields_count;
int injected_fields_count = _reader.next_uint(); int injected_fields_count;
assert( _limit <= java_fields_count + injected_fields_count, "Safety check"); _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) { if (_limit != 0) {
_reader.read_field_info(_fi_buf); _reader.read_field_info(_fi_buf);
} }
} }
public: public:
inline FieldStreamBase(InstanceKlass* klass); inline FieldStreamBase(InstanceKlass* klass);
@@ -138,8 +144,11 @@ class FieldStreamBase : public StackObj {
// Iterate over only the Java fields // Iterate over only the Java fields
class JavaFieldStream : public FieldStreamBase { class JavaFieldStream : public FieldStreamBase {
Array<u1>* _search_table;
public: 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 { u2 name_index() const {
assert(!field()->field_flags().is_injected(), "regular only"); assert(!field()->field_flags().is_injected(), "regular only");
@@ -149,7 +158,6 @@ class JavaFieldStream : public FieldStreamBase {
u2 signature_index() const { u2 signature_index() const {
assert(!field()->field_flags().is_injected(), "regular only"); assert(!field()->field_flags().is_injected(), "regular only");
return field()->signature_index(); return field()->signature_index();
return -1;
} }
u2 generic_signature_index() const { u2 generic_signature_index() const {
@@ -164,6 +172,10 @@ class JavaFieldStream : public FieldStreamBase {
assert(!field()->field_flags().is_injected(), "regular only"); assert(!field()->field_flags().is_injected(), "regular only");
return field()->initializer_index(); 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 { class AllFieldStream : public FieldStreamBase {
public: public:
AllFieldStream(Array<u1>* fieldinfo, ConstantPool* constants): FieldStreamBase(fieldinfo, constants) {}
AllFieldStream(const InstanceKlass* k): FieldStreamBase(k->fieldinfo_stream(), k->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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * 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) : FieldStreamBase::FieldStreamBase(const Array<u1>* fieldinfo_stream, ConstantPool* constants, int start, int limit) :
_fieldinfo_stream(fieldinfo_stream), _fieldinfo_stream(fieldinfo_stream),
_reader(FieldInfoReader(_fieldinfo_stream)), _reader(FieldInfoReader(_fieldinfo_stream)),
_constants(constantPoolHandle(Thread::current(), constants)), _index(start) { _constants(constantPoolHandle(Thread::current(), constants)),
_index = start; _index(start),
if (limit < start) { _limit(limit) {
_limit = FieldInfoStream::num_total_fields(_fieldinfo_stream);
} else {
_limit = limit;
}
initialize(); initialize();
} }
FieldStreamBase::FieldStreamBase(Array<u1>* fieldinfo_stream, ConstantPool* constants) : FieldStreamBase::FieldStreamBase(const Array<u1>* fieldinfo_stream, ConstantPool* constants) :
_fieldinfo_stream(fieldinfo_stream), _fieldinfo_stream(fieldinfo_stream),
_reader(FieldInfoReader(_fieldinfo_stream)), _reader(FieldInfoReader(_fieldinfo_stream)),
_constants(constantPoolHandle(Thread::current(), constants)), _constants(constantPoolHandle(Thread::current(), constants)),
_index(0), _index(0),
_limit(FieldInfoStream::num_total_fields(_fieldinfo_stream)) { _limit(-1) {
initialize(); initialize();
} }
@@ -57,9 +53,28 @@ FieldStreamBase::FieldStreamBase(InstanceKlass* klass) :
_reader(FieldInfoReader(_fieldinfo_stream)), _reader(FieldInfoReader(_fieldinfo_stream)),
_constants(constantPoolHandle(Thread::current(), klass->constants())), _constants(constantPoolHandle(Thread::current(), klass->constants())),
_index(0), _index(0),
_limit(FieldInfoStream::num_total_fields(_fieldinfo_stream)) { _limit(-1) {
assert(klass == field_holder(), ""); assert(klass == field_holder(), "");
initialize(); 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 #endif // SHARE_OOPS_FIELDSTREAMS_INLINE_HPP

View File

@@ -686,6 +686,11 @@ void InstanceKlass::deallocate_contents(ClassLoaderData* loader_data) {
} }
set_fieldinfo_stream(nullptr); 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()) { if (fields_status() != nullptr && !fields_status()->is_shared()) {
MetadataFactory::free_array<FieldStatus>(loader_data, fields_status()); 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 { bool InstanceKlass::find_local_field(Symbol* name, Symbol* sig, fieldDescriptor* fd) const {
for (JavaFieldStream fs(this); !fs.done(); fs.next()) { JavaFieldStream fs(this);
Symbol* f_name = fs.name(); if (fs.lookup(name, sig)) {
Symbol* f_sig = fs.signature(); assert(fs.name() == name, "name must match");
if (f_name == name && f_sig == sig) { assert(fs.signature() == sig, "signature must match");
fd->reinitialize(const_cast<InstanceKlass*>(this), fs.to_FieldInfo()); fd->reinitialize(const_cast<InstanceKlass*>(this), fs.to_FieldInfo());
return true; return true;
}
} }
return false; return false;
} }
@@ -2610,6 +2614,7 @@ void InstanceKlass::metaspace_pointers_do(MetaspaceClosure* it) {
} }
it->push(&_fieldinfo_stream); 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() // _fields_status might be written into by Rewriter::scan_method() -> fd.set_has_initialized_final_update()
it->push(&_fields_status, MetaspaceClosure::_writable); it->push(&_fields_status, MetaspaceClosure::_writable);
@@ -2710,6 +2715,8 @@ void InstanceKlass::remove_unshareable_info() {
DEBUG_ONLY(_shared_class_load_count = 0); DEBUG_ONLY(_shared_class_load_count = 0);
remove_unshareable_flags(); remove_unshareable_flags();
DEBUG_ONLY(FieldInfoStream::validate_search_table(_constants, _fieldinfo_stream, _fieldinfo_search_table));
} }
void InstanceKlass::remove_unshareable_flags() { 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()) { if (DiagnoseSyncOnValueBasedClasses && has_value_based_class_annotation() && !is_value_based()) {
set_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. // 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++) { for (int l = CompLevel_limited_profile; l < n->comp_level(); l++) {
nmethod *inv = lookup_osr_nmethod(n->method(), n->osr_entry_bci(), l, true); nmethod *inv = lookup_osr_nmethod(n->method(), n->osr_entry_bci(), l, true);
if (inv != nullptr && inv->is_in_use()) { 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++; map++;
} }
st->cr(); 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 { 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) // Fields information is stored in an UNSIGNED5 encoded stream (see fieldInfo.hpp)
Array<u1>* _fieldinfo_stream; Array<u1>* _fieldinfo_stream;
Array<u1>* _fieldinfo_search_table;
Array<FieldStatus>* _fields_status; Array<FieldStatus>* _fields_status;
// embedded Java vtable follows here // embedded Java vtable follows here
@@ -398,6 +399,9 @@ class InstanceKlass: public Klass {
Array<u1>* fieldinfo_stream() const { return _fieldinfo_stream; } Array<u1>* fieldinfo_stream() const { return _fieldinfo_stream; }
void set_fieldinfo_stream(Array<u1>* fis) { _fieldinfo_stream = fis; } 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; } Array<FieldStatus>* fields_status() const {return _fields_status; }
void set_fields_status(Array<FieldStatus>* array) { _fields_status = array; } 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. // If so, we have to make it not_entrant.
nmethod* nm = code(); // Put it into local variable to guard against concurrent updates nmethod* nm = code(); // Put it into local variable to guard against concurrent updates
if (nm != nullptr) { 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 "memory/metaspaceClosure.hpp"
#include "oops/instanceKlass.hpp" #include "oops/instanceKlass.hpp"
#include "oops/method.hpp" #include "oops/method.hpp"
#include "oops/objArrayKlass.hpp"
#include "runtime/handles.hpp" #include "runtime/handles.hpp"
#include "runtime/mutexLocker.hpp" #include "runtime/mutexLocker.hpp"
#include "utilities/resizeableResourceHash.hpp" #include "utilities/resizeableResourceHash.hpp"
@@ -286,7 +287,12 @@ private:
static bool is_klass_loaded(Klass* k) { static bool is_klass_loaded(Klass* k) {
if (have_data()) { if (have_data()) {
// If we're running in AOT mode some classes may not be loaded yet // 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; return true;
} }

View File

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

View File

@@ -53,7 +53,13 @@ class Block_Array : public ArenaObj {
ReallocMark _nesting; // Safety checks for arena reallocation ReallocMark _nesting; // Safety checks for arena reallocation
protected: protected:
Block **_blocks; 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: public:
Block_Array(Arena *a) : _size(OptoBlockListSize), _arena(a) { Block_Array(Arena *a) : _size(OptoBlockListSize), _arena(a) {
@@ -68,7 +74,7 @@ public:
Block *operator[] ( uint i ) const // Lookup, or assert for not mapped Block *operator[] ( uint i ) const // Lookup, or assert for not mapped
{ assert( i < Max(), "oob" ); return _blocks[i]; } { assert( i < Max(), "oob" ); return _blocks[i]; }
// Extend the mapping: index i maps to Block *n. // 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; } uint Max() const { DEBUG_ONLY(return _limit); return _size; }
}; };

View File

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

View File

@@ -2798,7 +2798,6 @@ const RegMask &Node::in_RegMask(uint) const {
} }
void Node_Array::grow(uint i) { 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(i >= _max, "Should have been checked before, use maybe_grow?");
assert(_max > 0, "invariant"); assert(_max > 0, "invariant");
uint old = _max; uint old = _max;
@@ -3038,10 +3037,6 @@ void Unique_Node_List::remove_useless_nodes(VectorSet &useful) {
//============================================================================= //=============================================================================
void Node_Stack::grow() { 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_top = pointer_delta(_inode_top,_inodes,sizeof(INode)); // save _top
size_t old_max = pointer_delta(_inode_max,_inodes,sizeof(INode)); size_t old_max = pointer_delta(_inode_max,_inodes,sizeof(INode));
size_t max = old_max << 1; // max * 2 size_t max = old_max << 1; // max * 2

View File

@@ -1633,6 +1633,7 @@ protected:
// Grow array to required capacity // Grow array to required capacity
void maybe_grow(uint i) { void maybe_grow(uint i) {
_nesting.check(_a); // Check if a potential reallocation in the arena is safe
if (i >= _max) { if (i >= _max) {
grow(i); grow(i);
} }
@@ -1884,7 +1885,15 @@ protected:
INode *_inodes; // Array storage for the stack INode *_inodes; // Array storage for the stack
Arena *_a; // Arena to allocate in Arena *_a; // Arena to allocate in
ReallocMark _nesting; // Safety checks for arena reallocation 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(); void grow();
public: public:
Node_Stack(int size) { Node_Stack(int size) {
size_t max = (size > OptoNodeListSize) ? size : OptoNodeListSize; size_t max = (size > OptoNodeListSize) ? size : OptoNodeListSize;
@@ -1907,7 +1916,7 @@ public:
} }
void push(Node *n, uint i) { void push(Node *n, uint i) {
++_inode_top; ++_inode_top;
grow(); maybe_grow();
INode *top = _inode_top; // optimization INode *top = _inode_top; // optimization
top->node = n; top->node = n;
top->indx = i; 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); 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); scratch_class->set_fieldinfo_stream(new_fis);
MetadataFactory::free_array<u1>(scratch_class->class_loader_data(), old_stream); 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 // 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) { if (_make_not_entrant) {
nmethod* nm = CodeCache::find_nmethod(f->pc()); nmethod* nm = CodeCache::find_nmethod(f->pc());
assert(nm != nullptr, "did not find nmethod"); assert(nm != nullptr, "did not find nmethod");
nm->make_not_entrant(nmethod::ChangeReason::whitebox_deoptimization); nm->make_not_entrant("Whitebox deoptimization");
} }
++_result; ++_result;
} }

View File

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

View File

@@ -2005,6 +2005,10 @@ const int ObjectAlignmentInBytes = 8;
product(bool, UseThreadsLockThrottleLock, true, DIAGNOSTIC, \ product(bool, UseThreadsLockThrottleLock, true, DIAGNOSTIC, \
"Use an extra lock during Thread start and exit to alleviate" \ "Use an extra lock during Thread start and exit to alleviate" \
"contention on Threads_lock.") \ "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 // end of RUNTIME_FLAGS

View File

@@ -1337,7 +1337,7 @@ void JavaThread::make_zombies() {
// it is a Java nmethod // it is a Java nmethod
nmethod* nm = CodeCache::find_nmethod(fst.current()->pc()); nmethod* nm = CodeCache::find_nmethod(fst.current()->pc());
assert(nm != nullptr, "did not find nmethod"); 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 #endif
if (CDSConfig::is_using_aot_linked_classes()) { if (CDSConfig::is_using_aot_linked_classes()) {
AOTLinkedClassBulkLoader::finish_loading_javabase_classes(CHECK_JNI_ERR);
SystemDictionary::restore_archived_method_handle_intrinsics(); SystemDictionary::restore_archived_method_handle_intrinsics();
AOTLinkedClassBulkLoader::finish_loading_javabase_classes(CHECK_JNI_ERR);
} }
// Start string deduplication thread if requested. // 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@@ -261,7 +261,7 @@ class UNSIGNED5 : AllStatic {
ARR _array; ARR _array;
OFF _limit; OFF _limit;
OFF _position; OFF _position;
int next_length() { int next_length() const {
return UNSIGNED5::check_length(_array, _position, _limit, GET()); return UNSIGNED5::check_length(_array, _position, _limit, GET());
} }
public: public:
@@ -270,7 +270,7 @@ class UNSIGNED5 : AllStatic {
uint32_t next_uint() { uint32_t next_uint() {
return UNSIGNED5::read_uint(_array, _position, _limit, GET()); return UNSIGNED5::read_uint(_array, _position, _limit, GET());
} }
bool has_next() { bool has_next() const {
return next_length() != 0; return next_length() != 0;
} }
// tries to skip count logical entries; returns actual number skipped // tries to skip count logical entries; returns actual number skipped
@@ -284,8 +284,9 @@ class UNSIGNED5 : AllStatic {
return actual; return actual;
} }
ARR array() { return _array; } ARR array() { return _array; }
OFF limit() { return _limit; } OFF limit() const { return _limit; }
OFF position() { return _position; } OFF position() const { return _position; }
void set_limit(OFF limit) { _limit = limit; }
void set_position(OFF position) { _position = position; } void set_position(OFF position) { _position = position; }
// For debugging, even in product builds (see debug.cpp). // For debugging, even in product builds (see debug.cpp).

View File

@@ -38,7 +38,7 @@ import java.nio.charset.StandardCharsets;
* <p> * <p>
* The {@link #readln()} and {@link #readln(String)} methods decode bytes read from * 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 * {@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 * 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 * always replaces malformed and unmappable byte sequences with the charset's default
* replacement string. * replacement string.

View File

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

View File

@@ -1030,14 +1030,6 @@ public sealed interface ClassFile
*/ */
int JAVA_25_VERSION = 69; 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 * A minor version number {@value} indicating a class uses preview features
* of a Java SE release since 12, for major versions {@value * 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} * {@return the latest class major version supported by the current runtime}
*/ */
static int latestMajorVersion() { 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> * <cite>The Java Virtual Machine Specification, Java SE 25 Edition</cite></a>
*/ */
RELEASE_25(69), 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 ; // Reduce code churn when appending new constants
// Note to maintainers: when adding constants for newer releases, // Note to maintainers: when adding constants for newer releases,
@@ -398,7 +386,7 @@ public enum ClassFileFormatVersion {
* {@return the latest class file format version} * {@return the latest class file format version}
*/ */
public static ClassFileFormatVersion latest() { public static ClassFileFormatVersion latest() {
return RELEASE_26; return RELEASE_25;
} }
/** /**

View File

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

View File

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

View File

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

View File

@@ -94,6 +94,15 @@ public class Net {
return EXCLUSIVE_BIND; 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 * 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 * 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 int isExclusiveBindAvailable();
private static native boolean shouldShutdownWriteBeforeClose0();
private static native boolean shouldSetBothIPv4AndIPv6Options0(); private static native boolean shouldSetBothIPv4AndIPv6Options0();
private static native boolean canIPv6SocketJoinIPv4Group0(); private static native boolean canIPv6SocketJoinIPv4Group0();

View File

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

View File

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

View File

@@ -343,7 +343,7 @@ public class Pem {
* @return PEM in a string * @return PEM in a string
*/ */
public static String pemEncoded(PEMRecord pem) { 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); 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* `report-on-exit=`*identifier*
: Specifies the name of the view to display when the Java Virtual Machine : 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 (JVM) shuts down. To specify more than one view, use the report-on-exit
to false. For a list of available views, see `jfr help view`. By default, parameter repeatedly. This option is not available if the disk option
no report is generated. is set to false. For a list of available views, see `jfr help view`.
By default, no report is generated.
`settings=`*path* `settings=`*path*
: Specifies the path and name of the event settings file (of type JFC). : 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 enhancedExceptionsInitialized = 0;
static int enhancedExceptionsAllowed = -1; static int enhancedExceptionsAllowed = 0;
#define CHECK_NULL_THROW_ERROR(X) \
if (X == NULL) { \
JNU_ThrowByName(env, "java/lang/InternalError", \
"can't initialize enhanced exceptions"); \
return -1; \
}
int getEnhancedExceptionsAllowed(JNIEnv *env) { int getEnhancedExceptionsAllowed(JNIEnv *env) {
jclass cls; jclass cls;
@@ -108,9 +101,9 @@ int getEnhancedExceptionsAllowed(JNIEnv *env) {
return enhancedExceptionsAllowed; return enhancedExceptionsAllowed;
} }
cls = (*env)->FindClass(env, "jdk/internal/util/Exceptions"); 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"); 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); enhancedExceptionsAllowed = (*env)->GetStaticBooleanField(env, cls, fid);
enhancedExceptionsInitialized = 1; enhancedExceptionsInitialized = 1;
return enhancedExceptionsAllowed; return enhancedExceptionsAllowed;

View File

@@ -183,6 +183,11 @@ int lookupCharacteristicsToAddressFamily(int characteristics);
int addressesInSystemOrder(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); int getEnhancedExceptionsAllowed(JNIEnv *env);
#endif /* NET_UTILS_H */ #endif /* NET_UTILS_H */

View File

@@ -188,8 +188,11 @@ void NET_ThrowUnknownHostExceptionWithGaiError(JNIEnv *env,
if (error_string == NULL) if (error_string == NULL)
error_string = "unknown error"; error_string = "unknown error";
int enhancedExceptions = getEnhancedExceptionsAllowed(env); int enhancedExceptions = getEnhancedExceptionsAllowed(env);
if (enhancedExceptions == ENH_INIT_ERROR && (*env)->ExceptionCheck(env)) {
return;
}
if (enhancedExceptions) { if (enhancedExceptions == ENH_ENABLED) {
size = strlen(hostname); size = strlen(hostname);
} else { } else {
size = 0; size = 0;
@@ -200,7 +203,7 @@ void NET_ThrowUnknownHostExceptionWithGaiError(JNIEnv *env,
if (buf) { if (buf) {
jstring s; jstring s;
int n; int n;
if (enhancedExceptions) { if (enhancedExceptions == ENH_ENABLED) {
n = snprintf(buf, size, "%s: %s", hostname, error_string); n = snprintf(buf, size, "%s: %s", hostname, error_string);
} else { } else {
n = snprintf(buf, size, " %s", error_string); 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; return -1;
} }
JNIEXPORT jboolean JNICALL
Java_sun_nio_ch_Net_shouldShutdownWriteBeforeClose0(JNIEnv *env, jclass clazz) {
return JNI_FALSE;
}
JNIEXPORT jboolean JNICALL JNIEXPORT jboolean JNICALL
Java_sun_nio_ch_Net_shouldSetBothIPv4AndIPv6Options0(JNIEnv* env, jclass cl) 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) { if (error) {
// report error // report error
NET_ThrowByNameWithLastError( int enh = getEnhancedExceptionsAllowed(env);
env, "java/net/UnknownHostException", if (enh == ENH_INIT_ERROR && (*env)->ExceptionCheck(env)) {
getEnhancedExceptionsAllowed(env) ? hostname : ""); goto cleanupAndReturn;
}
const char *hmsg = (enh == ENH_ENABLED) ? hostname : "";
NET_ThrowByNameWithLastError( env, "java/net/UnknownHostException", hmsg);
goto cleanupAndReturn; goto cleanupAndReturn;
} else { } else {
int i = 0; int i = 0;

View File

@@ -83,8 +83,12 @@ Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
if (error) { if (error) {
// report error // report error
NET_ThrowByNameWithLastError(env, "java/net/UnknownHostException", int enh = getEnhancedExceptionsAllowed(env);
getEnhancedExceptionsAllowed(env) ? hostname : ""); 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; goto cleanupAndReturn;
} else { } else {
int i = 0, inetCount = 0, inet6Count = 0, inetIndex = 0, 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * 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; return 1;
} }
JNIEXPORT jboolean JNICALL
Java_sun_nio_ch_Net_shouldShutdownWriteBeforeClose0(JNIEnv *env, jclass clazz) {
return JNI_TRUE;
}
JNIEXPORT jboolean JNICALL JNIEXPORT jboolean JNICALL
Java_sun_nio_ch_Net_shouldSetBothIPv4AndIPv6Options0(JNIEnv* env, jclass cl) 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> * JEP 513: Flexible Constructor Bodies</a>
*/ */
RELEASE_25, 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 ; // Reduce code churn when appending new constants
// Note that when adding constants for newer releases, the // 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} * {@return the latest source version that can be modeled}
*/ */
public static SourceVersion latest() { public static SourceVersion latest() {
return RELEASE_26; return RELEASE_25;
} }
private static final SourceVersion latestSupported = getLatestSupported(); private static final SourceVersion latestSupported = getLatestSupported();
@@ -504,7 +492,7 @@ public enum SourceVersion {
private static SourceVersion getLatestSupported() { private static SourceVersion getLatestSupported() {
int intVersion = Runtime.version().feature(); int intVersion = Runtime.version().feature();
return (intVersion >= 11) ? return (intVersion >= 11) ?
valueOf("RELEASE_" + Math.min(26, intVersion)): valueOf("RELEASE_" + Math.min(25, intVersion)):
RELEASE_10; 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@@ -44,7 +44,7 @@ import javax.annotation.processing.SupportedSourceVersion;
* @see AbstractAnnotationValueVisitor9 * @see AbstractAnnotationValueVisitor9
* @since 14 * @since 14
*/ */
@SupportedSourceVersion(RELEASE_26) @SupportedSourceVersion(RELEASE_25)
public abstract class AbstractAnnotationValueVisitor14<R, P> extends AbstractAnnotationValueVisitor9<R, P> { 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@@ -50,7 +50,7 @@ import javax.annotation.processing.ProcessingEnvironment;
* @see AbstractAnnotationValueVisitor14 * @see AbstractAnnotationValueVisitor14
* @since 23 * @since 23
*/ */
@SupportedSourceVersion(RELEASE_26) @SupportedSourceVersion(RELEASE_25)
@PreviewFeature(feature=PreviewFeature.Feature.LANGUAGE_MODEL, reflective=true) @PreviewFeature(feature=PreviewFeature.Feature.LANGUAGE_MODEL, reflective=true)
public abstract class AbstractAnnotationValueVisitorPreview<R, P> extends AbstractAnnotationValueVisitor14<R, P> { 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * 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 * @see AbstractElementVisitor9
* @since 16 * @since 16
*/ */
@SupportedSourceVersion(RELEASE_26) @SupportedSourceVersion(RELEASE_25)
public abstract class AbstractElementVisitor14<R, P> extends AbstractElementVisitor9<R, P> { public abstract class AbstractElementVisitor14<R, P> extends AbstractElementVisitor9<R, P> {
/** /**
* Constructor for concrete subclasses to call. * 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * 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 * @see AbstractElementVisitor14
* @since 23 * @since 23
*/ */
@SupportedSourceVersion(RELEASE_26) @SupportedSourceVersion(RELEASE_25)
@PreviewFeature(feature=PreviewFeature.Feature.LANGUAGE_MODEL, reflective=true) @PreviewFeature(feature=PreviewFeature.Feature.LANGUAGE_MODEL, reflective=true)
public abstract class AbstractElementVisitorPreview<R, P> extends AbstractElementVisitor14<R, P> { 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * 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 * @see AbstractTypeVisitor9
* @since 14 * @since 14
*/ */
@SupportedSourceVersion(RELEASE_26) @SupportedSourceVersion(RELEASE_25)
public abstract class AbstractTypeVisitor14<R, P> extends AbstractTypeVisitor9<R, P> { public abstract class AbstractTypeVisitor14<R, P> extends AbstractTypeVisitor9<R, P> {
/** /**
* Constructor for concrete subclasses to call. * 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * 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 * @see AbstractTypeVisitor14
* @since 23 * @since 23
*/ */
@SupportedSourceVersion(RELEASE_26) @SupportedSourceVersion(RELEASE_25)
@PreviewFeature(feature=PreviewFeature.Feature.LANGUAGE_MODEL, reflective=true) @PreviewFeature(feature=PreviewFeature.Feature.LANGUAGE_MODEL, reflective=true)
public abstract class AbstractTypeVisitorPreview<R, P> extends AbstractTypeVisitor14<R, P> { 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@@ -61,7 +61,7 @@ import javax.lang.model.SourceVersion;
* @see ElementKindVisitor9 * @see ElementKindVisitor9
* @since 16 * @since 16
*/ */
@SupportedSourceVersion(RELEASE_26) @SupportedSourceVersion(RELEASE_25)
public class ElementKindVisitor14<R, P> extends ElementKindVisitor9<R, P> { public class ElementKindVisitor14<R, P> extends ElementKindVisitor9<R, P> {
/** /**
* Constructor for concrete subclasses; uses {@code null} for the * 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * 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 * @see ElementKindVisitor14
* @since 23 * @since 23
*/ */
@SupportedSourceVersion(RELEASE_26) @SupportedSourceVersion(RELEASE_25)
@PreviewFeature(feature=PreviewFeature.Feature.LANGUAGE_MODEL, reflective=true) @PreviewFeature(feature=PreviewFeature.Feature.LANGUAGE_MODEL, reflective=true)
public class ElementKindVisitorPreview<R, P> extends ElementKindVisitor14<R, P> { 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * 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 * @see ElementScanner9
* @since 16 * @since 16
*/ */
@SupportedSourceVersion(RELEASE_26) @SupportedSourceVersion(RELEASE_25)
public class ElementScanner14<R, P> extends ElementScanner9<R, P> { public class ElementScanner14<R, P> extends ElementScanner9<R, P> {
/** /**
* Constructor for concrete subclasses; uses {@code null} for the * 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * 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 * @see ElementScanner14
* @since 23 * @since 23
*/ */
@SupportedSourceVersion(RELEASE_26) @SupportedSourceVersion(RELEASE_25)
@PreviewFeature(feature=PreviewFeature.Feature.LANGUAGE_MODEL, reflective=true) @PreviewFeature(feature=PreviewFeature.Feature.LANGUAGE_MODEL, reflective=true)
public class ElementScannerPreview<R, P> extends ElementScanner14<R, P> { 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * 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 * @see SimpleAnnotationValueVisitor9
* @since 14 * @since 14
*/ */
@SupportedSourceVersion(RELEASE_26) @SupportedSourceVersion(RELEASE_25)
public class SimpleAnnotationValueVisitor14<R, P> extends SimpleAnnotationValueVisitor9<R, P> { public class SimpleAnnotationValueVisitor14<R, P> extends SimpleAnnotationValueVisitor9<R, P> {
/** /**
* Constructor for concrete subclasses; uses {@code null} for the * 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * 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 * @see SimpleAnnotationValueVisitor14
* @since 23 * @since 23
*/ */
@SupportedSourceVersion(RELEASE_26) @SupportedSourceVersion(RELEASE_25)
@PreviewFeature(feature=PreviewFeature.Feature.LANGUAGE_MODEL, reflective=true) @PreviewFeature(feature=PreviewFeature.Feature.LANGUAGE_MODEL, reflective=true)
public class SimpleAnnotationValueVisitorPreview<R, P> extends SimpleAnnotationValueVisitor14<R, P> { 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * 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 * @see SimpleElementVisitor9
* @since 16 * @since 16
*/ */
@SupportedSourceVersion(RELEASE_26) @SupportedSourceVersion(RELEASE_25)
public class SimpleElementVisitor14<R, P> extends SimpleElementVisitor9<R, P> { public class SimpleElementVisitor14<R, P> extends SimpleElementVisitor9<R, P> {
/** /**
* Constructor for concrete subclasses; uses {@code null} for the * 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * 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 * @see SimpleElementVisitor14
* @since 23 * @since 23
*/ */
@SupportedSourceVersion(RELEASE_26) @SupportedSourceVersion(RELEASE_25)
@PreviewFeature(feature=PreviewFeature.Feature.LANGUAGE_MODEL, reflective=true) @PreviewFeature(feature=PreviewFeature.Feature.LANGUAGE_MODEL, reflective=true)
public class SimpleElementVisitorPreview<R, P> extends SimpleElementVisitor14<R, P> { 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * 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 * @see SimpleTypeVisitor9
* @since 14 * @since 14
*/ */
@SupportedSourceVersion(RELEASE_26) @SupportedSourceVersion(RELEASE_25)
public class SimpleTypeVisitor14<R, P> extends SimpleTypeVisitor9<R, P> { public class SimpleTypeVisitor14<R, P> extends SimpleTypeVisitor9<R, P> {
/** /**
* Constructor for concrete subclasses; uses {@code null} for the * 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * 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 * @see SimpleTypeVisitor14
* @since 23 * @since 23
*/ */
@SupportedSourceVersion(RELEASE_26) @SupportedSourceVersion(RELEASE_25)
@PreviewFeature(feature=PreviewFeature.Feature.LANGUAGE_MODEL, reflective=true) @PreviewFeature(feature=PreviewFeature.Feature.LANGUAGE_MODEL, reflective=true)
public class SimpleTypeVisitorPreview<R, P> extends SimpleTypeVisitor14<R, P> { 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * 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 * @see TypeKindVisitor9
* @since 14 * @since 14
*/ */
@SupportedSourceVersion(RELEASE_26) @SupportedSourceVersion(RELEASE_25)
public class TypeKindVisitor14<R, P> extends TypeKindVisitor9<R, P> { public class TypeKindVisitor14<R, P> extends TypeKindVisitor9<R, P> {
/** /**
* Constructor for concrete subclasses to call; uses {@code null} * 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