From 286a26c36600ed82726f1678194363b2828851dd Mon Sep 17 00:00:00 2001 From: Hamlin Li Date: Mon, 6 Dec 2021 11:50:11 +0000 Subject: [PATCH 001/671] 8278277: G1: Simplify implementation of G1GCPhaseTimes::record_or_add_time_secs Reviewed-by: iwalulya, sjohanss, tschatzl --- src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp b/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp index 7c3eba2be94..cc4a90a36f1 100644 --- a/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp +++ b/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp @@ -266,11 +266,7 @@ void G1GCPhaseTimes::add_time_secs(GCParPhases phase, uint worker_id, double sec } void G1GCPhaseTimes::record_or_add_time_secs(GCParPhases phase, uint worker_id, double secs) { - if (_gc_par_phases[phase]->get(worker_id) == _gc_par_phases[phase]->uninitialized()) { - record_time_secs(phase, worker_id, secs); - } else { - add_time_secs(phase, worker_id, secs); - } + _gc_par_phases[phase]->set_or_add(worker_id, secs); } double G1GCPhaseTimes::get_time_secs(GCParPhases phase, uint worker_id) { -- GitLab From 6994d809371e80c1e24cd296c48c7f75886577b7 Mon Sep 17 00:00:00 2001 From: Jie Fu Date: Mon, 6 Dec 2021 13:44:22 +0000 Subject: [PATCH 002/671] 8278291: compiler/uncommontrap/TraceDeoptimizationNoRealloc.java fails with release VMs after JDK-8154011 Reviewed-by: shade, thartmann --- .../compiler/uncommontrap/TraceDeoptimizationNoRealloc.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/hotspot/jtreg/compiler/uncommontrap/TraceDeoptimizationNoRealloc.java b/test/hotspot/jtreg/compiler/uncommontrap/TraceDeoptimizationNoRealloc.java index 4a371a525b3..4cd10a1a63e 100644 --- a/test/hotspot/jtreg/compiler/uncommontrap/TraceDeoptimizationNoRealloc.java +++ b/test/hotspot/jtreg/compiler/uncommontrap/TraceDeoptimizationNoRealloc.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2021, 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 @@ -27,7 +27,7 @@ * @summary -XX:+TraceDeoptimization tries to print realloc'ed objects even when there are none * * @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement - * -XX:+IgnoreUnrecognizedVMOptions -XX:+TraceDeoptimization + * -XX:+UnlockDiagnosticVMOptions -XX:+TraceDeoptimization * compiler.uncommontrap.TraceDeoptimizationNoRealloc */ -- GitLab From a885aab696777c99c8c4c5d9a46afc5fe0a4fe47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Gr=C3=B6nlund?= Date: Mon, 6 Dec 2021 14:36:51 +0000 Subject: [PATCH 003/671] 8276125: RunThese24H.java SIGSEGV in JfrThreadGroup::thread_group_id Reviewed-by: egahlin, shade --- .../jfr/recorder/checkpoint/types/jfrThreadGroup.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrThreadGroup.cpp b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrThreadGroup.cpp index 107e7fa15d9..6d362305400 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrThreadGroup.cpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrThreadGroup.cpp @@ -151,8 +151,12 @@ int JfrThreadGroupsHelper::populate_thread_group_hierarchy(const JavaThread* jt, assert(current != NULL, "invariant"); assert(_thread_group_hierarchy != NULL, "invariant"); + oop thread_oop = jt->threadObj(); + if (thread_oop == nullptr) { + return 0; + } // immediate thread group - Handle thread_group_handle(current, java_lang_Thread::threadGroup(jt->threadObj())); + Handle thread_group_handle(current, java_lang_Thread::threadGroup(thread_oop)); if (thread_group_handle == NULL) { return 0; } @@ -167,7 +171,7 @@ int JfrThreadGroupsHelper::populate_thread_group_hierarchy(const JavaThread* jt, Handle parent_thread_group_handle(current, parent_thread_group_obj); // and check parents parents... - while (!(parent_thread_group_handle == NULL)) { + while (parent_thread_group_handle != nullptr) { const jweak parent_group_weak_ref = use_weak_handles ? JNIHandles::make_weak_global(parent_thread_group_handle) : NULL; thread_group_pointers = new JfrThreadGroupPointers(parent_thread_group_handle, parent_group_weak_ref); _thread_group_hierarchy->append(thread_group_pointers); -- GitLab From 7c6f57fcb1f1fcecf26f7b8046a5a41ca6d9c315 Mon Sep 17 00:00:00 2001 From: Christian Hagedorn Date: Mon, 6 Dec 2021 14:48:03 +0000 Subject: [PATCH 004/671] 8275610: C2: Object field load floats above its null check resulting in a segfault Reviewed-by: kvn, roland --- src/hotspot/share/opto/loopopts.cpp | 10 ++ .../TestEliminateNullCheckWithSplitIf.java | 102 ++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 test/hotspot/jtreg/compiler/loopopts/TestEliminateNullCheckWithSplitIf.java diff --git a/src/hotspot/share/opto/loopopts.cpp b/src/hotspot/share/opto/loopopts.cpp index 8dff310c569..f1cb053d87e 100644 --- a/src/hotspot/share/opto/loopopts.cpp +++ b/src/hotspot/share/opto/loopopts.cpp @@ -1174,6 +1174,16 @@ bool PhaseIdealLoop::identical_backtoback_ifs(Node *n) { if (!n->in(0)->is_Region()) { return false; } + + IfNode* n_if = n->as_If(); + if (n_if->proj_out(0)->outcnt() > 1 || n_if->proj_out(1)->outcnt() > 1) { + // Removing the dominated If node by using the split-if optimization does not work if there are data dependencies. + // Some data dependencies depend on its immediate dominator If node and should not be separated from it (e.g. null + // checks, division by zero checks etc.). Bail out for now until data dependencies are correctly handled when + // optimizing back-to-back ifs. + return false; + } + Node* region = n->in(0); Node* dom = idom(region); if (!dom->is_If() || dom->in(1) != n->in(1)) { diff --git a/test/hotspot/jtreg/compiler/loopopts/TestEliminateNullCheckWithSplitIf.java b/test/hotspot/jtreg/compiler/loopopts/TestEliminateNullCheckWithSplitIf.java new file mode 100644 index 00000000000..e83b23255b3 --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopopts/TestEliminateNullCheckWithSplitIf.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2021, 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. + * + */ + +/* + * @test + * @key stress randomness + * @bug 8275610 + * @summary Null check for field access of object floats above null check resulting in a segfault. + * @requires vm.compiler2.enabled + * @run main/othervm -Xbatch -XX:CompileCommand=compileonly,compiler.loopopts.TestEliminateNullCheckWithSplitIf::test + * -XX:+UnlockDiagnosticVMOptions -XX:+StressGCM -XX:StressSeed=42 compiler.loopopts.TestEliminateNullCheckWithSplitIf + * @run main/othervm -Xbatch -XX:CompileCommand=compileonly,compiler.loopopts.TestEliminateNullCheckWithSplitIf::test + * -XX:+UnlockDiagnosticVMOptions -XX:+StressGCM -XX:+StressIGVN compiler.loopopts.TestEliminateNullCheckWithSplitIf + */ + +package compiler.loopopts; + +public class TestEliminateNullCheckWithSplitIf { + public static int[] iArrFld = new int[20]; + public static int[] iArrFld2 = new int[20]; + public static int iFld = 10; + public static MyClass obj; + + public static void main(String[] strArr) { + for (int i = 0; i < 10000; i++) { + obj = (i % 100 == 0 ? null : new MyClass()); + test(); + } + } + + // The field access obj.iFld requires a null check NC3 and adds a not-null CastPP node on the succeeded projection. + // In the first IGVN after parsing, the null check NC3 can be subsumed by the explicit null check NC2. + // (done in IfNode::simple_subsuming()). The Bool node of NC2 is also shared with the same null check NC1 earlier. + // However, C2 cannot remove the null check NC2, yet, because the IR in between the two checks are too complex + // (IfNode::search_identical() fails). + // Now, loopopts are applied: + // (1) First, the split if optimization is done. It recognizes that NC1 and NC2 are back to back null checks and removes + // the null check NC2 by splitting it through the region R which is removed afterwards. In this process, control dependent + // data nodes on the out projections of NC2 end up at the new regions R1/R2 created for each projection for R. They get + // the last nodes of the if and else block as input. For this example, R1 is a control input to the CastPP node which + // will merge both true projections. + // (2) Later in loop opts, the loop L is transformed into normal code and y will become a constant 1. + // After loopopts, another round of IGVN is done: + // (These steps also depend on the order in which they are applied in order to trigger the bug) + // (1) The region R is removed because one path is dead (a result of the split if optimization). + // (2) The new If node added by the above split if optimization is also folded. This rewires the CastPP node to + // the last control node in the If block which is the true projection of range check RC2. Up until now, the CastPP + // is still after the null check NC1. + // (3) The range check RC2 is removed because the range check RC1 already covers this range (see RangeCheck::Ideal()). + // All data nodes which are control dependent on RC2 will be rewired to the dominating range check RC1, including + // the non-null CastPP node - which now has a control input above the null check NC1. This also means that the field + // load obj.iFld now has the same early control as the CastPP (CastPP -> AddP -> LoadI). Using StressGCM can + // now schedule the obj.iFld load before the null check NC1 because the early control allows it which leads to a + // segmentation fault if obj is null. + public static void test() { + int x = iArrFld[17]; // Emits range check RC1 + if (obj != null) { // Null check NC1 + int y = 0; + for (int i = 0; i < 1; i++) { // Loop L + y++; + } + // Use additional loop to keep the rangecheck for iArrFld[y] in before loopopts. + // y will become constant 1 but only once the loop above is removed in loopopts. + x = iArrFld[y]; // Emits range check RC2 + } else { + x = iArrFld2[18]; + } + // Region R merging the if and else paths above. + if (obj != null) { // Null check NC2 + x = iArrFld2[obj.iFld]; // Emits Null check NC3 for obj.iFld + } + } +} + +class MyClass { + int iFld; +} + + + + -- GitLab From adf39522c178b82dc73e341751b2d9aba984469d Mon Sep 17 00:00:00 2001 From: Vishal Chand Date: Mon, 6 Dec 2021 15:28:20 +0000 Subject: [PATCH 005/671] 8277372: Add getters for BOT and card table members Reviewed-by: tschatzl, sjohanss, ayang --- .../gc/g1/g1BarrierSetAssembler_aarch64.cpp | 4 +- .../cardTableBarrierSetAssembler_aarch64.cpp | 6 +- src/hotspot/cpu/arm/c1_LIRGenerator_arm.cpp | 2 +- .../arm/gc/g1/g1BarrierSetAssembler_arm.cpp | 4 +- .../cardTableBarrierSetAssembler_arm.cpp | 6 +- .../ppc/gc/g1/g1BarrierSetAssembler_ppc.cpp | 4 +- .../cardTableBarrierSetAssembler_ppc.cpp | 6 +- .../s390/gc/g1/g1BarrierSetAssembler_s390.cpp | 4 +- .../cardTableBarrierSetAssembler_s390.cpp | 6 +- .../x86/gc/g1/g1BarrierSetAssembler_x86.cpp | 4 +- .../cardTableBarrierSetAssembler_x86.cpp | 10 +-- src/hotspot/share/gc/g1/c2/g1BarrierSetC2.cpp | 2 +- src/hotspot/share/gc/g1/g1AllocRegion.cpp | 2 +- src/hotspot/share/gc/g1/g1Arguments.cpp | 2 +- .../share/gc/g1/g1BlockOffsetTable.cpp | 40 ++++++------ .../share/gc/g1/g1BlockOffsetTable.hpp | 10 +-- .../share/gc/g1/g1BlockOffsetTable.inline.hpp | 8 +-- src/hotspot/share/gc/g1/g1CardCounts.cpp | 2 +- src/hotspot/share/gc/g1/g1CardTable.cpp | 2 +- src/hotspot/share/gc/g1/g1CardTable.hpp | 4 +- .../share/gc/g1/g1CardTable.inline.hpp | 2 +- src/hotspot/share/gc/g1/g1CollectedHeap.cpp | 2 +- src/hotspot/share/gc/g1/g1RemSet.cpp | 4 +- src/hotspot/share/gc/g1/heapRegion.cpp | 2 +- src/hotspot/share/gc/g1/heapRegionRemSet.cpp | 2 +- .../share/gc/g1/heapRegionRemSet.inline.hpp | 4 +- .../share/gc/parallel/objectStartArray.cpp | 26 ++++---- .../share/gc/parallel/objectStartArray.hpp | 25 ++++++-- src/hotspot/share/gc/parallel/psOldGen.cpp | 2 +- .../share/gc/shared/blockOffsetTable.cpp | 64 +++++++++---------- .../share/gc/shared/blockOffsetTable.hpp | 39 +++++++---- .../gc/shared/blockOffsetTable.inline.hpp | 4 +- .../gc/shared/c1/cardTableBarrierSetC1.cpp | 4 +- .../gc/shared/c2/cardTableBarrierSetC2.cpp | 2 +- src/hotspot/share/gc/shared/cardTable.cpp | 30 ++++----- src/hotspot/share/gc/shared/cardTable.hpp | 28 +++++--- src/hotspot/share/gc/shared/vmStructs_gc.hpp | 7 -- .../share/jvmci/jvmciCompilerToVMInit.cpp | 2 +- .../gtest/gc/g1/test_freeRegionList.cpp | 2 +- .../gtest/gc/g1/test_g1CardSetContainers.cpp | 2 +- 40 files changed, 205 insertions(+), 176 deletions(-) diff --git a/src/hotspot/cpu/aarch64/gc/g1/g1BarrierSetAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/gc/g1/g1BarrierSetAssembler_aarch64.cpp index 77a6dc8b739..cd689b008e0 100644 --- a/src/hotspot/cpu/aarch64/gc/g1/g1BarrierSetAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/gc/g1/g1BarrierSetAssembler_aarch64.cpp @@ -222,7 +222,7 @@ void G1BarrierSetAssembler::g1_write_barrier_post(MacroAssembler* masm, const Register card_addr = tmp; - __ lsr(card_addr, store_addr, CardTable::card_shift); + __ lsr(card_addr, store_addr, CardTable::card_shift()); // get the address of the card __ load_byte_map_base(tmp2); @@ -444,7 +444,7 @@ void G1BarrierSetAssembler::generate_c1_post_barrier_runtime_stub(StubAssembler* assert_different_registers(card_offset, byte_map_base, rscratch1); __ load_parameter(0, card_offset); - __ lsr(card_offset, card_offset, CardTable::card_shift); + __ lsr(card_offset, card_offset, CardTable::card_shift()); __ load_byte_map_base(byte_map_base); __ ldrb(rscratch1, Address(byte_map_base, card_offset)); __ cmpw(rscratch1, (int)G1CardTable::g1_young_card_val()); diff --git a/src/hotspot/cpu/aarch64/gc/shared/cardTableBarrierSetAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/gc/shared/cardTableBarrierSetAssembler_aarch64.cpp index fb677828e20..f94f2b9c902 100644 --- a/src/hotspot/cpu/aarch64/gc/shared/cardTableBarrierSetAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/gc/shared/cardTableBarrierSetAssembler_aarch64.cpp @@ -38,7 +38,7 @@ void CardTableBarrierSetAssembler::store_check(MacroAssembler* masm, Register ob BarrierSet* bs = BarrierSet::barrier_set(); assert(bs->kind() == BarrierSet::CardTableBarrierSet, "Wrong barrier set kind"); - __ lsr(obj, obj, CardTable::card_shift); + __ lsr(obj, obj, CardTable::card_shift()); assert(CardTable::dirty_card_val() == 0, "must be"); @@ -64,8 +64,8 @@ void CardTableBarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembl __ lea(end, Address(start, count, Address::lsl(LogBytesPerHeapOop))); // end = start + count << LogBytesPerHeapOop __ sub(end, end, BytesPerHeapOop); // last element address to make inclusive - __ lsr(start, start, CardTable::card_shift); - __ lsr(end, end, CardTable::card_shift); + __ lsr(start, start, CardTable::card_shift()); + __ lsr(end, end, CardTable::card_shift()); __ sub(count, end, start); // number of bytes to copy __ load_byte_map_base(scratch); diff --git a/src/hotspot/cpu/arm/c1_LIRGenerator_arm.cpp b/src/hotspot/cpu/arm/c1_LIRGenerator_arm.cpp index 0a5b80b23b7..69a76f4beb0 100644 --- a/src/hotspot/cpu/arm/c1_LIRGenerator_arm.cpp +++ b/src/hotspot/cpu/arm/c1_LIRGenerator_arm.cpp @@ -377,7 +377,7 @@ void LIRGenerator::CardTableBarrierSet_post_barrier_helper(LIR_Opr addr, LIR_Con // Use unsigned type T_BOOLEAN here rather than (signed) T_BYTE since signed load // byte instruction does not support the addressing mode we need. - LIR_Address* card_addr = new LIR_Address(tmp, addr, (LIR_Address::Scale) -CardTable::card_shift, 0, T_BOOLEAN); + LIR_Address* card_addr = new LIR_Address(tmp, addr, (LIR_Address::Scale) -CardTable::card_shift(), 0, T_BOOLEAN); if (UseCondCardMark) { LIR_Opr cur_value = new_register(T_INT); __ move(card_addr, cur_value); diff --git a/src/hotspot/cpu/arm/gc/g1/g1BarrierSetAssembler_arm.cpp b/src/hotspot/cpu/arm/gc/g1/g1BarrierSetAssembler_arm.cpp index 63bf45b8db5..765b05e779b 100644 --- a/src/hotspot/cpu/arm/gc/g1/g1BarrierSetAssembler_arm.cpp +++ b/src/hotspot/cpu/arm/gc/g1/g1BarrierSetAssembler_arm.cpp @@ -218,7 +218,7 @@ void G1BarrierSetAssembler::g1_write_barrier_post(MacroAssembler* masm, const Register card_addr = tmp1; __ mov_address(tmp2, (address)ct->byte_map_base()); - __ add(card_addr, tmp2, AsmOperand(store_addr, lsr, CardTable::card_shift)); + __ add(card_addr, tmp2, AsmOperand(store_addr, lsr, CardTable::card_shift())); __ ldrb(tmp2, Address(card_addr)); __ cmp(tmp2, (int)G1CardTable::g1_young_card_val()); @@ -452,7 +452,7 @@ void G1BarrierSetAssembler::generate_c1_post_barrier_runtime_stub(StubAssembler* // explicitly specify that 'cardtable' has a relocInfo::none // type. __ lea(r_card_base_1, cardtable); - __ add(r_card_addr_0, r_card_base_1, AsmOperand(r_obj_0, lsr, CardTable::card_shift)); + __ add(r_card_addr_0, r_card_base_1, AsmOperand(r_obj_0, lsr, CardTable::card_shift())); // first quick check without barrier __ ldrb(r_tmp2, Address(r_card_addr_0)); diff --git a/src/hotspot/cpu/arm/gc/shared/cardTableBarrierSetAssembler_arm.cpp b/src/hotspot/cpu/arm/gc/shared/cardTableBarrierSetAssembler_arm.cpp index 86f43597e22..11b2ca2ef1d 100644 --- a/src/hotspot/cpu/arm/gc/shared/cardTableBarrierSetAssembler_arm.cpp +++ b/src/hotspot/cpu/arm/gc/shared/cardTableBarrierSetAssembler_arm.cpp @@ -55,8 +55,8 @@ void CardTableBarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembl __ add_ptr_scaled_int32(count, addr, count, LogBytesPerHeapOop); __ sub(count, count, BytesPerHeapOop); // last addr - __ logical_shift_right(addr, addr, CardTable::card_shift); - __ logical_shift_right(count, count, CardTable::card_shift); + __ logical_shift_right(addr, addr, CardTable::card_shift()); + __ logical_shift_right(count, count, CardTable::card_shift()); __ sub(count, count, addr); // nb of cards // warning: Rthread has not been preserved @@ -129,7 +129,7 @@ void CardTableBarrierSetAssembler::store_check_part2(MacroAssembler* masm, Regis "Wrong barrier set kind"); assert(CardTable::dirty_card_val() == 0, "Dirty card value must be 0 due to optimizations."); - Address card_table_addr(card_table_base, obj, lsr, CardTable::card_shift); + Address card_table_addr(card_table_base, obj, lsr, CardTable::card_shift()); if (UseCondCardMark) { Label already_dirty; diff --git a/src/hotspot/cpu/ppc/gc/g1/g1BarrierSetAssembler_ppc.cpp b/src/hotspot/cpu/ppc/gc/g1/g1BarrierSetAssembler_ppc.cpp index a9328e8d616..05c8374cfa4 100644 --- a/src/hotspot/cpu/ppc/gc/g1/g1BarrierSetAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/gc/g1/g1BarrierSetAssembler_ppc.cpp @@ -245,7 +245,7 @@ void G1BarrierSetAssembler::g1_write_barrier_post(MacroAssembler* masm, Decorato Register Rbase = tmp2; __ load_const_optimized(Rbase, (address)(ct->card_table()->byte_map_base()), /*temp*/ tmp3); - __ srdi(Rcard_addr, store_addr, CardTable::card_shift); + __ srdi(Rcard_addr, store_addr, CardTable::card_shift()); // Get the address of the card. __ lbzx(/*card value*/ tmp3, Rbase, Rcard_addr); @@ -516,7 +516,7 @@ void G1BarrierSetAssembler::generate_c1_post_barrier_runtime_stub(StubAssembler* __ std(addr, -8, R1_SP); __ std(tmp2, -16, R1_SP); - __ srdi(addr, R0, CardTable::card_shift); // Addr is passed in R0. + __ srdi(addr, R0, CardTable::card_shift()); // Addr is passed in R0. __ load_const_optimized(/*cardtable*/ tmp2, byte_map_base, tmp); __ add(addr, tmp2, addr); __ lbz(tmp, 0, addr); // tmp := [addr + cardtable] diff --git a/src/hotspot/cpu/ppc/gc/shared/cardTableBarrierSetAssembler_ppc.cpp b/src/hotspot/cpu/ppc/gc/shared/cardTableBarrierSetAssembler_ppc.cpp index 8337317e3f2..0d80f2fd954 100644 --- a/src/hotspot/cpu/ppc/gc/shared/cardTableBarrierSetAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/gc/shared/cardTableBarrierSetAssembler_ppc.cpp @@ -54,8 +54,8 @@ void CardTableBarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembl __ addi(count, count, -BytesPerHeapOop); __ add(count, addr, count); // Use two shifts to clear out those low order two bits! (Cannot opt. into 1.) - __ srdi(addr, addr, CardTable::card_shift); - __ srdi(count, count, CardTable::card_shift); + __ srdi(addr, addr, CardTable::card_shift()); + __ srdi(count, count, CardTable::card_shift()); __ subf(count, addr, count); __ add_const_optimized(addr, addr, (address)ct->byte_map_base(), R0); __ addi(count, count, 1); @@ -74,7 +74,7 @@ void CardTableBarrierSetAssembler::card_table_write(MacroAssembler* masm, Register tmp, Register obj) { assert_different_registers(obj, tmp, R0); __ load_const_optimized(tmp, (address)byte_map_base, R0); - __ srdi(obj, obj, CardTable::card_shift); + __ srdi(obj, obj, CardTable::card_shift()); __ li(R0, CardTable::dirty_card_val()); __ stbx(R0, tmp, obj); } diff --git a/src/hotspot/cpu/s390/gc/g1/g1BarrierSetAssembler_s390.cpp b/src/hotspot/cpu/s390/gc/g1/g1BarrierSetAssembler_s390.cpp index 7258630bb0b..b6e3d9eb2c7 100644 --- a/src/hotspot/cpu/s390/gc/g1/g1BarrierSetAssembler_s390.cpp +++ b/src/hotspot/cpu/s390/gc/g1/g1BarrierSetAssembler_s390.cpp @@ -305,7 +305,7 @@ void G1BarrierSetAssembler::g1_write_barrier_post(MacroAssembler* masm, Decorato // calculate address of card __ load_const_optimized(Rbase, (address)ct->card_table()->byte_map_base()); // Card table base. - __ z_srlg(Rcard_addr, Rstore_addr, CardTable::card_shift); // Index into card table. + __ z_srlg(Rcard_addr, Rstore_addr, CardTable::card_shift()); // Index into card table. __ z_algr(Rcard_addr, Rbase); // Explicit calculation needed for cli. Rbase = noreg; // end of lifetime @@ -548,7 +548,7 @@ void G1BarrierSetAssembler::generate_c1_post_barrier_runtime_stub(StubAssembler* // Calculate address of card corresponding to the updated oop slot. AddressLiteral rs(byte_map_base); - __ z_srlg(addr_card, addr_oop, CardTable::card_shift); + __ z_srlg(addr_card, addr_oop, CardTable::card_shift()); addr_oop = noreg; // dead now __ load_const_optimized(cardtable, rs); // cardtable := __ z_agr(addr_card, cardtable); // addr_card := addr_oop>>card_shift + cardtable diff --git a/src/hotspot/cpu/s390/gc/shared/cardTableBarrierSetAssembler_s390.cpp b/src/hotspot/cpu/s390/gc/shared/cardTableBarrierSetAssembler_s390.cpp index d3f7bafd33e..0124868e46a 100644 --- a/src/hotspot/cpu/s390/gc/shared/cardTableBarrierSetAssembler_s390.cpp +++ b/src/hotspot/cpu/s390/gc/shared/cardTableBarrierSetAssembler_s390.cpp @@ -70,8 +70,8 @@ void CardTableBarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembl __ load_const_optimized(Z_R1, (address)ct->byte_map_base()); // count = (count>>shift) - (addr>>shift) - __ z_srlg(addr, addr, CardTable::card_shift); - __ z_srlg(count, count, CardTable::card_shift); + __ z_srlg(addr, addr, CardTable::card_shift()); + __ z_srlg(count, count, CardTable::card_shift()); // Prefetch first elements of card table for update. if (VM_Version::has_Prefetch()) { @@ -146,7 +146,7 @@ void CardTableBarrierSetAssembler::store_check(MacroAssembler* masm, Register st assert_different_registers(store_addr, tmp); - __ z_srlg(store_addr, store_addr, CardTable::card_shift); + __ z_srlg(store_addr, store_addr, CardTable::card_shift()); __ load_absolute_address(tmp, (address)ct->byte_map_base()); __ z_agr(store_addr, tmp); __ z_mvi(0, store_addr, CardTable::dirty_card_val()); diff --git a/src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.cpp b/src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.cpp index 645c2fec8bd..6525b13c5c2 100644 --- a/src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.cpp @@ -298,7 +298,7 @@ void G1BarrierSetAssembler::g1_write_barrier_post(MacroAssembler* masm, const Register cardtable = tmp2; __ movptr(card_addr, store_addr); - __ shrptr(card_addr, CardTable::card_shift); + __ shrptr(card_addr, CardTable::card_shift()); // Do not use ExternalAddress to load 'byte_map_base', since 'byte_map_base' is NOT // a valid address and therefore is not properly handled by the relocation code. __ movptr(cardtable, (intptr_t)ct->card_table()->byte_map_base()); @@ -540,7 +540,7 @@ void G1BarrierSetAssembler::generate_c1_post_barrier_runtime_stub(StubAssembler* const Register card_addr = rcx; __ load_parameter(0, card_addr); - __ shrptr(card_addr, CardTable::card_shift); + __ shrptr(card_addr, CardTable::card_shift()); // Do not use ExternalAddress to load 'byte_map_base', since 'byte_map_base' is NOT // a valid address and therefore is not properly handled by the relocation code. __ movptr(cardtable, (intptr_t)ct->card_table()->byte_map_base()); diff --git a/src/hotspot/cpu/x86/gc/shared/cardTableBarrierSetAssembler_x86.cpp b/src/hotspot/cpu/x86/gc/shared/cardTableBarrierSetAssembler_x86.cpp index 9b2d2c5efed..7fc36ffae8f 100644 --- a/src/hotspot/cpu/x86/gc/shared/cardTableBarrierSetAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/gc/shared/cardTableBarrierSetAssembler_x86.cpp @@ -60,8 +60,8 @@ void CardTableBarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembl #ifdef _LP64 __ leaq(end, Address(addr, count, TIMES_OOP, 0)); // end == addr+count*oop_size __ subptr(end, BytesPerHeapOop); // end - 1 to make inclusive - __ shrptr(addr, CardTable::card_shift); - __ shrptr(end, CardTable::card_shift); + __ shrptr(addr, CardTable::card_shift()); + __ shrptr(end, CardTable::card_shift()); __ subptr(end, addr); // end --> cards count __ mov64(tmp, disp); @@ -72,8 +72,8 @@ __ BIND(L_loop); __ jcc(Assembler::greaterEqual, L_loop); #else __ lea(end, Address(addr, count, Address::times_ptr, -wordSize)); - __ shrptr(addr, CardTable::card_shift); - __ shrptr(end, CardTable::card_shift); + __ shrptr(addr, CardTable::card_shift()); + __ shrptr(end, CardTable::card_shift()); __ subptr(end, addr); // end --> count __ BIND(L_loop); Address cardtable(addr, count, Address::times_1, disp); @@ -93,7 +93,7 @@ void CardTableBarrierSetAssembler::store_check(MacroAssembler* masm, Register ob CardTableBarrierSet* ctbs = barrier_set_cast(bs); CardTable* ct = ctbs->card_table(); - __ shrptr(obj, CardTable::card_shift); + __ shrptr(obj, CardTable::card_shift()); Address card_addr; diff --git a/src/hotspot/share/gc/g1/c2/g1BarrierSetC2.cpp b/src/hotspot/share/gc/g1/c2/g1BarrierSetC2.cpp index d5c4c14f92e..7d28f26e68e 100644 --- a/src/hotspot/share/gc/g1/c2/g1BarrierSetC2.cpp +++ b/src/hotspot/share/gc/g1/c2/g1BarrierSetC2.cpp @@ -442,7 +442,7 @@ void G1BarrierSetC2::post_barrier(GraphKit* kit, Node* cast = __ CastPX(__ ctrl(), adr); // Divide pointer by card size - Node* card_offset = __ URShiftX( cast, __ ConI(CardTable::card_shift) ); + Node* card_offset = __ URShiftX( cast, __ ConI(CardTable::card_shift()) ); // Combine card table base and card offset Node* card_adr = __ AddP(no_base, byte_map_base_node(kit), card_offset ); diff --git a/src/hotspot/share/gc/g1/g1AllocRegion.cpp b/src/hotspot/share/gc/g1/g1AllocRegion.cpp index 239822d6d1d..915110e3ebb 100644 --- a/src/hotspot/share/gc/g1/g1AllocRegion.cpp +++ b/src/hotspot/share/gc/g1/g1AllocRegion.cpp @@ -371,7 +371,7 @@ HeapRegion* OldGCAllocRegion::release() { // Determine how far we are from the next card boundary. If it is smaller than // the minimum object size we can allocate into, expand into the next card. HeapWord* top = cur->top(); - HeapWord* aligned_top = align_up(top, BOTConstants::N_bytes); + HeapWord* aligned_top = align_up(top, BOTConstants::card_size()); size_t to_allocate_words = pointer_delta(aligned_top, top, HeapWordSize); diff --git a/src/hotspot/share/gc/g1/g1Arguments.cpp b/src/hotspot/share/gc/g1/g1Arguments.cpp index 400f6b50024..348402cf957 100644 --- a/src/hotspot/share/gc/g1/g1Arguments.cpp +++ b/src/hotspot/share/gc/g1/g1Arguments.cpp @@ -135,7 +135,7 @@ void G1Arguments::initialize_card_set_configuration() { uint region_size_log_mb = (uint)MAX2(HeapRegion::LogOfHRGrainBytes - LOG_M, 0); if (FLAG_IS_DEFAULT(G1RemSetArrayOfCardsEntries)) { - uint max_cards_in_inline_ptr = G1CardSetConfiguration::max_cards_in_inline_ptr(HeapRegion::LogOfHRGrainBytes - CardTable::card_shift); + uint max_cards_in_inline_ptr = G1CardSetConfiguration::max_cards_in_inline_ptr(HeapRegion::LogOfHRGrainBytes - CardTable::card_shift()); FLAG_SET_ERGO(G1RemSetArrayOfCardsEntries, MAX2(max_cards_in_inline_ptr * 2, G1RemSetArrayOfCardsEntriesBase * (1u << (region_size_log_mb + 1)))); } diff --git a/src/hotspot/share/gc/g1/g1BlockOffsetTable.cpp b/src/hotspot/share/gc/g1/g1BlockOffsetTable.cpp index c98aa2c79a2..08e7dd5f1d4 100644 --- a/src/hotspot/share/gc/g1/g1BlockOffsetTable.cpp +++ b/src/hotspot/share/gc/g1/g1BlockOffsetTable.cpp @@ -52,14 +52,14 @@ G1BlockOffsetTable::G1BlockOffsetTable(MemRegion heap, G1RegionToSpaceMapper* st bool G1BlockOffsetTable::is_card_boundary(HeapWord* p) const { assert(p >= _reserved.start(), "just checking"); size_t delta = pointer_delta(p, _reserved.start()); - return (delta & right_n_bits((int)BOTConstants::LogN_words)) == (size_t)NoBits; + return (delta & right_n_bits((int)BOTConstants::log_card_size_in_words())) == (size_t)NoBits; } #ifdef ASSERT void G1BlockOffsetTable::check_index(size_t index, const char* msg) const { - assert((index) < (_reserved.word_size() >> BOTConstants::LogN_words), + assert((index) < (_reserved.word_size() >> BOTConstants::log_card_size_in_words()), "%s - index: " SIZE_FORMAT ", _vs.committed_size: " SIZE_FORMAT, - msg, (index), (_reserved.word_size() >> BOTConstants::LogN_words)); + msg, (index), (_reserved.word_size() >> BOTConstants::log_card_size_in_words())); assert(G1CollectedHeap::heap()->is_in(address_for_index_raw(index)), "Index " SIZE_FORMAT " corresponding to " PTR_FORMAT " (%u) is not in committed area.", @@ -134,7 +134,7 @@ void G1BlockOffsetTablePart:: set_remainder_to_point_to_start(HeapWord* start, H size_t start_card = _bot->index_for(start); size_t end_card = _bot->index_for(end-1); assert(start ==_bot->address_for_index(start_card), "Precondition"); - assert(end ==_bot->address_for_index(end_card)+BOTConstants::N_words, "Precondition"); + assert(end ==_bot->address_for_index(end_card)+BOTConstants::card_size_in_words(), "Precondition"); set_remainder_to_point_to_start_incl(start_card, end_card); // closed interval } @@ -144,7 +144,7 @@ void G1BlockOffsetTablePart:: set_remainder_to_point_to_start(HeapWord* start, H void G1BlockOffsetTablePart::set_remainder_to_point_to_start_incl(size_t start_card, size_t end_card) { assert(start_card <= end_card, "precondition"); assert(start_card > _bot->index_for(_hr->bottom()), "Cannot be first card"); - assert(_bot->offset_array(start_card-1) <= BOTConstants::N_words, + assert(_bot->offset_array(start_card-1) <= BOTConstants::card_size_in_words(), "Offset card has an unexpected value"); size_t start_card_for_region = start_card; u_char offset = max_jubyte; @@ -153,7 +153,7 @@ void G1BlockOffsetTablePart::set_remainder_to_point_to_start_incl(size_t start_c // so that the reach ends in this region and not at the start // of the next. size_t reach = start_card - 1 + (BOTConstants::power_to_cards_back(i+1) - 1); - offset = BOTConstants::N_words + i; + offset = BOTConstants::card_size_in_words() + i; if (reach >= end_card) { _bot->set_offset_array(start_card_for_region, end_card, offset); start_card_for_region = reach + 1; @@ -174,16 +174,16 @@ void G1BlockOffsetTablePart::check_all_cards(size_t start_card, size_t end_card) if (end_card < start_card) { return; } - guarantee(_bot->offset_array(start_card) == BOTConstants::N_words, "Wrong value in second card"); + guarantee(_bot->offset_array(start_card) == BOTConstants::card_size_in_words(), "Wrong value in second card"); for (size_t c = start_card + 1; c <= end_card; c++ /* yeah! */) { u_char entry = _bot->offset_array(c); if (c - start_card > BOTConstants::power_to_cards_back(1)) { - guarantee(entry > BOTConstants::N_words, + guarantee(entry > BOTConstants::card_size_in_words(), "Should be in logarithmic region - " "entry: %u, " "_array->offset_array(c): %u, " "N_words: %u", - (uint)entry, (uint)_bot->offset_array(c), BOTConstants::N_words); + (uint)entry, (uint)_bot->offset_array(c), BOTConstants::card_size_in_words()); } size_t backskip = BOTConstants::entry_to_cards_back(entry); size_t landing_card = c - backskip; @@ -196,10 +196,10 @@ void G1BlockOffsetTablePart::check_all_cards(size_t start_card, size_t end_card) } else { guarantee(landing_card == start_card - 1, "Tautology"); // Note that N_words is the maximum offset value - guarantee(_bot->offset_array(landing_card) <= BOTConstants::N_words, + guarantee(_bot->offset_array(landing_card) <= BOTConstants::card_size_in_words(), "landing card offset: %u, " "N_words: %u", - (uint)_bot->offset_array(landing_card), (uint)BOTConstants::N_words); + (uint)_bot->offset_array(landing_card), (uint)BOTConstants::card_size_in_words()); } } } @@ -224,13 +224,13 @@ void G1BlockOffsetTablePart::alloc_block_work(HeapWord** threshold_, HeapWord* b "phantom block"); assert(blk_end > threshold, "should be past threshold"); assert(blk_start <= threshold, "blk_start should be at or before threshold"); - assert(pointer_delta(threshold, blk_start) <= BOTConstants::N_words, + assert(pointer_delta(threshold, blk_start) <= BOTConstants::card_size_in_words(), "offset should be <= BlockOffsetSharedArray::N"); assert(G1CollectedHeap::heap()->is_in_reserved(blk_start), "reference must be into the heap"); assert(G1CollectedHeap::heap()->is_in_reserved(blk_end-1), "limit must be within the heap"); - assert(threshold == _bot->_reserved.start() + index*BOTConstants::N_words, + assert(threshold == _bot->_reserved.start() + index*BOTConstants::card_size_in_words(), "index must agree with threshold"); DEBUG_ONLY(size_t orig_index = index;) @@ -250,14 +250,14 @@ void G1BlockOffsetTablePart::alloc_block_work(HeapWord** threshold_, HeapWord* b HeapWord* rem_st = _bot->address_for_index(index + 1); // Calculate rem_end this way because end_index // may be the last valid index in the covered region. - HeapWord* rem_end = _bot->address_for_index(end_index) + BOTConstants::N_words; + HeapWord* rem_end = _bot->address_for_index(end_index) + BOTConstants::card_size_in_words(); set_remainder_to_point_to_start(rem_st, rem_end); } index = end_index + 1; // Calculate threshold_ this way because end_index // may be the last valid index in the covered region. - threshold = _bot->address_for_index(end_index) + BOTConstants::N_words; + threshold = _bot->address_for_index(end_index) + BOTConstants::card_size_in_words(); assert(threshold >= blk_end, "Incorrect offset threshold"); *threshold_ = threshold; @@ -268,7 +268,7 @@ void G1BlockOffsetTablePart::alloc_block_work(HeapWord** threshold_, HeapWord* b size_t start_index = _bot->index_for(blk_start); HeapWord* boundary = _bot->address_for_index(start_index); assert((_bot->offset_array(orig_index) == 0 && blk_start == boundary) || - (_bot->offset_array(orig_index) > 0 && _bot->offset_array(orig_index) <= BOTConstants::N_words), + (_bot->offset_array(orig_index) > 0 && _bot->offset_array(orig_index) <= BOTConstants::card_size_in_words()), "offset array should have been set - " "orig_index offset: %u, " "blk_start: " PTR_FORMAT ", " @@ -278,12 +278,12 @@ void G1BlockOffsetTablePart::alloc_block_work(HeapWord** threshold_, HeapWord* b for (size_t j = orig_index + 1; j <= end_index; j++) { assert(_bot->offset_array(j) > 0 && _bot->offset_array(j) <= - (u_char) (BOTConstants::N_words+BOTConstants::N_powers-1), + (u_char) (BOTConstants::card_size_in_words()+BOTConstants::N_powers-1), "offset array should have been set - " "%u not > 0 OR %u not <= %u", (uint) _bot->offset_array(j), (uint) _bot->offset_array(j), - (uint) (BOTConstants::N_words+BOTConstants::N_powers-1)); + (uint) (BOTConstants::card_size_in_words() + BOTConstants::N_powers - 1)); } #endif } @@ -297,7 +297,7 @@ void G1BlockOffsetTablePart::verify() const { for (size_t current_card = start_card; current_card < end_card; current_card++) { u_char entry = _bot->offset_array(current_card); - if (entry < BOTConstants::N_words) { + if (entry < BOTConstants::card_size_in_words()) { // The entry should point to an object before the current card. Verify that // it is possible to walk from that object in to the current card by just // iterating over the objects following it. @@ -361,7 +361,7 @@ void G1BlockOffsetTablePart::zero_bottom_entry_raw() { } void G1BlockOffsetTablePart::initialize_threshold() { - _next_offset_threshold = _hr->bottom() + BOTConstants::N_words; + _next_offset_threshold = _hr->bottom() + BOTConstants::card_size_in_words(); } void G1BlockOffsetTablePart::set_for_starts_humongous(HeapWord* obj_top, size_t fill_size) { diff --git a/src/hotspot/share/gc/g1/g1BlockOffsetTable.hpp b/src/hotspot/share/gc/g1/g1BlockOffsetTable.hpp index 128e9d105a2..fa7658e185e 100644 --- a/src/hotspot/share/gc/g1/g1BlockOffsetTable.hpp +++ b/src/hotspot/share/gc/g1/g1BlockOffsetTable.hpp @@ -55,9 +55,9 @@ private: volatile u_char* _offset_array; // byte array keeping backwards offsets void check_offset(size_t offset, const char* msg) const { - assert(offset <= BOTConstants::N_words, + assert(offset <= BOTConstants::card_size_in_words(), "%s - offset: " SIZE_FORMAT ", N_words: %u", - msg, offset, BOTConstants::N_words); + msg, offset, BOTConstants::card_size_in_words()); } // Bounds checking accessors: @@ -80,13 +80,13 @@ public: // Return the number of slots needed for an offset array // that covers mem_region_words words. static size_t compute_size(size_t mem_region_words) { - size_t number_of_slots = (mem_region_words / BOTConstants::N_words); + size_t number_of_slots = (mem_region_words / BOTConstants::card_size_in_words()); return ReservedSpace::allocation_align_size_up(number_of_slots); } // Returns how many bytes of the heap a single byte of the BOT corresponds to. static size_t heap_map_factor() { - return BOTConstants::N_bytes; + return BOTConstants::card_size(); } // Initialize the Block Offset Table to cover the memory region passed @@ -102,7 +102,7 @@ public: inline HeapWord* address_for_index(size_t index) const; // Variant of address_for_index that does not check the index for validity. inline HeapWord* address_for_index_raw(size_t index) const { - return _reserved.start() + (index << BOTConstants::LogN_words); + return _reserved.start() + (index << BOTConstants::log_card_size_in_words()); } }; diff --git a/src/hotspot/share/gc/g1/g1BlockOffsetTable.inline.hpp b/src/hotspot/share/gc/g1/g1BlockOffsetTable.inline.hpp index 7471a4ca078..aa0c004a302 100644 --- a/src/hotspot/share/gc/g1/g1BlockOffsetTable.inline.hpp +++ b/src/hotspot/share/gc/g1/g1BlockOffsetTable.inline.hpp @@ -41,7 +41,7 @@ inline HeapWord* G1BlockOffsetTablePart::threshold_for_addr(const void* addr) { } // Calculate next threshold. - HeapWord* threshold = card_boundary + BOTConstants::N_words; + HeapWord* threshold = card_boundary + BOTConstants::card_size_in_words(); return threshold; } @@ -84,7 +84,7 @@ void G1BlockOffsetTable::set_offset_array(size_t left, size_t right, u_char offs // Variant of index_for that does not check the index for validity. inline size_t G1BlockOffsetTable::index_for_raw(const void* p) const { - return pointer_delta((char*)p, _reserved.start(), sizeof(char)) >> BOTConstants::LogN; + return pointer_delta((char*)p, _reserved.start(), sizeof(char)) >> BOTConstants::log_card_size(); } inline size_t G1BlockOffsetTable::index_for(const void* p) const { @@ -120,14 +120,14 @@ inline HeapWord* G1BlockOffsetTablePart::block_at_or_preceding(const void* addr) size_t index = _bot->index_for(addr); uint offset = _bot->offset_array(index); // Extend u_char to uint. - while (offset >= BOTConstants::N_words) { + while (offset >= BOTConstants::card_size_in_words()) { // The excess of the offset from N_words indicates a power of Base // to go back by. size_t n_cards_back = BOTConstants::entry_to_cards_back(offset); index -= n_cards_back; offset = _bot->offset_array(index); } - assert(offset < BOTConstants::N_words, "offset too large"); + assert(offset < BOTConstants::card_size_in_words(), "offset too large"); HeapWord* q = _bot->address_for_index(index); return q - offset; diff --git a/src/hotspot/share/gc/g1/g1CardCounts.cpp b/src/hotspot/share/gc/g1/g1CardCounts.cpp index 1607ec40b95..6e56eecafb9 100644 --- a/src/hotspot/share/gc/g1/g1CardCounts.cpp +++ b/src/hotspot/share/gc/g1/g1CardCounts.cpp @@ -126,7 +126,7 @@ void G1CardCounts::clear_range(MemRegion mr) { HeapWord* start_addr = _ct->addr_for(from_card_ptr); assert(start_addr == mr.start(), "MemRegion start must be aligned to a card."); HeapWord* last_addr = _ct->addr_for(last_card_ptr); - assert((last_addr + G1CardTable::card_size_in_words) == mr.end(), "MemRegion end must be aligned to a card."); + assert((last_addr + G1CardTable::card_size_in_words()) == mr.end(), "MemRegion end must be aligned to a card."); #endif // ASSERT // Clear the counts for the (exclusive) card range. diff --git a/src/hotspot/share/gc/g1/g1CardTable.cpp b/src/hotspot/share/gc/g1/g1CardTable.cpp index 9e565c1ba64..4fc6db5bac1 100644 --- a/src/hotspot/share/gc/g1/g1CardTable.cpp +++ b/src/hotspot/share/gc/g1/g1CardTable.cpp @@ -62,7 +62,7 @@ void G1CardTable::initialize(G1RegionToSpaceMapper* mapper) { _covered[0] = _whole_heap; _byte_map = (CardValue*) mapper->reserved().start(); - _byte_map_base = _byte_map - (uintptr_t(low_bound) >> card_shift); + _byte_map_base = _byte_map - (uintptr_t(low_bound) >> _card_shift); assert(byte_for(low_bound) == &_byte_map[0], "Checking start of map"); assert(byte_for(high_bound-1) <= &_byte_map[_last_valid_index], "Checking end of map"); diff --git a/src/hotspot/share/gc/g1/g1CardTable.hpp b/src/hotspot/share/gc/g1/g1CardTable.hpp index fd150db39f8..e73cbfaf86d 100644 --- a/src/hotspot/share/gc/g1/g1CardTable.hpp +++ b/src/hotspot/share/gc/g1/g1CardTable.hpp @@ -110,12 +110,12 @@ public: inline uint region_idx_for(CardValue* p); static size_t compute_size(size_t mem_region_size_in_words) { - size_t number_of_slots = (mem_region_size_in_words / card_size_in_words); + size_t number_of_slots = (mem_region_size_in_words / _card_size_in_words); return ReservedSpace::allocation_align_size_up(number_of_slots); } // Returns how many bytes of the heap a single byte of the Card Table corresponds to. - static size_t heap_map_factor() { return card_size; } + static size_t heap_map_factor() { return _card_size; } void initialize() {} void initialize(G1RegionToSpaceMapper* mapper); diff --git a/src/hotspot/share/gc/g1/g1CardTable.inline.hpp b/src/hotspot/share/gc/g1/g1CardTable.inline.hpp index 41ffdf5318e..d2962cbad84 100644 --- a/src/hotspot/share/gc/g1/g1CardTable.inline.hpp +++ b/src/hotspot/share/gc/g1/g1CardTable.inline.hpp @@ -31,7 +31,7 @@ inline uint G1CardTable::region_idx_for(CardValue* p) { size_t const card_idx = pointer_delta(p, _byte_map, sizeof(CardValue)); - return (uint)(card_idx >> (HeapRegion::LogOfHRGrainBytes - card_shift)); + return (uint)(card_idx >> (HeapRegion::LogOfHRGrainBytes - _card_shift)); } inline bool G1CardTable::mark_clean_as_dirty(CardValue* card) { diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp index b35f48eaa7b..58f4a34d344 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp @@ -1660,7 +1660,7 @@ jint G1CollectedHeap::initialize() { // The G1FromCardCache reserves card with value 0 as "invalid", so the heap must not // start within the first card. - guarantee((uintptr_t)(heap_rs.base()) >= G1CardTable::card_size, "Java heap must not start within the first card."); + guarantee((uintptr_t)(heap_rs.base()) >= G1CardTable::card_size(), "Java heap must not start within the first card."); G1FromCardCache::initialize(max_reserved_regions()); // Also create a G1 rem set. _rem_set = new G1RemSet(this, _card_table, _hot_card_cache); diff --git a/src/hotspot/share/gc/g1/g1RemSet.cpp b/src/hotspot/share/gc/g1/g1RemSet.cpp index dcde1bd8fa5..f4893300a07 100644 --- a/src/hotspot/share/gc/g1/g1RemSet.cpp +++ b/src/hotspot/share/gc/g1/g1RemSet.cpp @@ -808,7 +808,7 @@ class G1ScanHRForRegionClosure : public HeapRegionClosure { return; } - HeapWord* scan_end = MIN2(card_start + (num_cards << BOTConstants::LogN_words), top); + HeapWord* scan_end = MIN2(card_start + (num_cards << BOTConstants::log_card_size_in_words()), top); if (_scanned_to >= scan_end) { return; } @@ -1674,7 +1674,7 @@ void G1RemSet::refine_card_concurrently(CardValue* const card_ptr, // Don't use addr_for(card_ptr + 1) which can ask for // a card beyond the heap. - HeapWord* end = start + G1CardTable::card_size_in_words; + HeapWord* end = start + G1CardTable::card_size_in_words(); MemRegion dirty_region(start, MIN2(scan_limit, end)); assert(!dirty_region.is_empty(), "sanity"); diff --git a/src/hotspot/share/gc/g1/heapRegion.cpp b/src/hotspot/share/gc/g1/heapRegion.cpp index 78ca4ad8bf9..ca85f50ae25 100644 --- a/src/hotspot/share/gc/g1/heapRegion.cpp +++ b/src/hotspot/share/gc/g1/heapRegion.cpp @@ -91,7 +91,7 @@ void HeapRegion::setup_heap_region_size(size_t max_heap_size) { GrainWords = GrainBytes >> LogHeapWordSize; guarantee(CardsPerRegion == 0, "we should only set it once"); - CardsPerRegion = GrainBytes >> G1CardTable::card_shift; + CardsPerRegion = GrainBytes >> G1CardTable::card_shift(); LogCardsPerRegion = log2i(CardsPerRegion); diff --git a/src/hotspot/share/gc/g1/heapRegionRemSet.cpp b/src/hotspot/share/gc/g1/heapRegionRemSet.cpp index 694496975f5..d4570173f0e 100644 --- a/src/hotspot/share/gc/g1/heapRegionRemSet.cpp +++ b/src/hotspot/share/gc/g1/heapRegionRemSet.cpp @@ -60,7 +60,7 @@ void HeapRegionRemSet::initialize(MemRegion reserved) { vm_exit_during_initialization("Can not represent all cards in a card region within uint."); } - _split_card_shift = CardBitsWithinCardRegion + CardTable::card_shift; + _split_card_shift = CardBitsWithinCardRegion + CardTable::card_shift(); _split_card_mask = ((size_t)1 << _split_card_shift) - 1; // Check if the card region/region within cards combination can cover the heap. diff --git a/src/hotspot/share/gc/g1/heapRegionRemSet.inline.hpp b/src/hotspot/share/gc/g1/heapRegionRemSet.inline.hpp index eaa2d7f1e56..cd48da2a5bf 100644 --- a/src/hotspot/share/gc/g1/heapRegionRemSet.inline.hpp +++ b/src/hotspot/share/gc/g1/heapRegionRemSet.inline.hpp @@ -118,7 +118,7 @@ inline void HeapRegionRemSet::iterate_for_merge(CardOrRangeVisitor& cl) { void HeapRegionRemSet::split_card(OopOrNarrowOopStar from, uint& card_region, uint& card_within_region) const { size_t offset = pointer_delta(from, _heap_base_address, 1); card_region = (uint)(offset >> _split_card_shift); - card_within_region = (uint)((offset & _split_card_mask) >> CardTable::card_shift); + card_within_region = (uint)((offset & _split_card_mask) >> CardTable::card_shift()); assert(card_within_region < ((uint)1 << G1CardSetContainer::LogCardsPerRegionLimit), "must be"); } @@ -129,7 +129,7 @@ void HeapRegionRemSet::add_reference(OopOrNarrowOopStar from, uint tid) { } uint cur_idx = _hr->hrm_index(); - uintptr_t from_card = uintptr_t(from) >> CardTable::card_shift; + uintptr_t from_card = uintptr_t(from) >> CardTable::card_shift(); if (G1FromCardCache::contains_or_replace(tid, cur_idx, from_card)) { // We can't check whether the card is in the remembered set - the card container diff --git a/src/hotspot/share/gc/parallel/objectStartArray.cpp b/src/hotspot/share/gc/parallel/objectStartArray.cpp index c9c7ac6b796..7768ca5ee00 100644 --- a/src/hotspot/share/gc/parallel/objectStartArray.cpp +++ b/src/hotspot/share/gc/parallel/objectStartArray.cpp @@ -31,26 +31,26 @@ #include "services/memTracker.hpp" #include "utilities/align.hpp" -uint ObjectStartArray::block_shift = 0; -uint ObjectStartArray::block_size = 0; -uint ObjectStartArray::block_size_in_words = 0; +uint ObjectStartArray::_card_shift = 0; +uint ObjectStartArray::_card_size = 0; +uint ObjectStartArray::_card_size_in_words = 0; void ObjectStartArray::initialize_block_size(uint card_shift) { - block_shift = card_shift; - block_size = 1 << block_shift; - block_size_in_words = block_size / sizeof(HeapWord); + _card_shift = card_shift; + _card_size = 1 << _card_shift; + _card_size_in_words = _card_size / sizeof(HeapWord); } void ObjectStartArray::initialize(MemRegion reserved_region) { // We're based on the assumption that we use the same // size blocks as the card table. - assert((int)block_size == (int)CardTable::card_size, "Sanity"); - assert(block_size <= MaxBlockSize, "block_size must be less than or equal to " UINT32_FORMAT, MaxBlockSize); + assert(_card_size == CardTable::card_size(), "Sanity"); + assert(_card_size <= MaxBlockSize, "block_size must be less than or equal to " UINT32_FORMAT, MaxBlockSize); // Calculate how much space must be reserved _reserved_region = reserved_region; - size_t bytes_to_reserve = reserved_region.word_size() / block_size_in_words; + size_t bytes_to_reserve = reserved_region.word_size() / _card_size_in_words; assert(bytes_to_reserve > 0, "Sanity"); bytes_to_reserve = @@ -76,7 +76,7 @@ void ObjectStartArray::initialize(MemRegion reserved_region) { MemTracker::record_virtual_memory_type((address)_raw_base, mtGC); - _offset_base = _raw_base - (size_t(reserved_region.start()) >> block_shift); + _offset_base = _raw_base - (size_t(reserved_region.start()) >> _card_shift); _covered_region.set_start(reserved_region.start()); _covered_region.set_word_size(0); @@ -91,10 +91,10 @@ void ObjectStartArray::set_covered_region(MemRegion mr) { HeapWord* low_bound = mr.start(); HeapWord* high_bound = mr.end(); - assert((uintptr_t(low_bound) & (block_size - 1)) == 0, "heap must start at block boundary"); - assert((uintptr_t(high_bound) & (block_size - 1)) == 0, "heap must end at block boundary"); + assert((uintptr_t(low_bound) & (_card_size - 1)) == 0, "heap must start at block boundary"); + assert((uintptr_t(high_bound) & (_card_size - 1)) == 0, "heap must end at block boundary"); - size_t requested_blocks_size_in_bytes = mr.word_size() / block_size_in_words; + size_t requested_blocks_size_in_bytes = mr.word_size() / _card_size_in_words; // Only commit memory in page sized chunks requested_blocks_size_in_bytes = diff --git a/src/hotspot/share/gc/parallel/objectStartArray.hpp b/src/hotspot/share/gc/parallel/objectStartArray.hpp index 02c91d20ded..857b01daa3a 100644 --- a/src/hotspot/share/gc/parallel/objectStartArray.hpp +++ b/src/hotspot/share/gc/parallel/objectStartArray.hpp @@ -46,16 +46,16 @@ class ObjectStartArray : public CHeapObj { jbyte* _raw_base; jbyte* _offset_base; + static uint _card_shift; + static uint _card_size; + static uint _card_size_in_words; + public: enum BlockValueConstants { clean_block = -1 }; - static uint block_shift; - static uint block_size; - static uint block_size_in_words; - // Maximum size an offset table entry can cover. This maximum is derived from that // we need an extra bit for possible offsets in the byte for backskip values, leaving 2^7 possible offsets. // Minimum object alignment is 8 bytes (2^3), so we can at most represent 2^10 offsets within a BOT value. @@ -64,13 +64,24 @@ class ObjectStartArray : public CHeapObj { // Initialize block size based on card size static void initialize_block_size(uint card_shift); + static uint card_shift() { + return _card_shift; + } + + static uint card_size() { + return _card_size; + } + static uint card_size_in_words() { + return _card_size_in_words; + } + protected: // Mapping from address to object start array entry jbyte* block_for_addr(void* p) const { assert(_covered_region.contains(p), "out of bounds access to object start array"); - jbyte* result = &_offset_base[uintptr_t(p) >> block_shift]; + jbyte* result = &_offset_base[uintptr_t(p) >> _card_shift]; assert(_blocks_region.contains(result), "out of bounds result in byte_for"); return result; @@ -81,7 +92,7 @@ class ObjectStartArray : public CHeapObj { assert(_blocks_region.contains(p), "out of bounds access to object start array"); size_t delta = pointer_delta(p, _offset_base, sizeof(jbyte)); - HeapWord* result = (HeapWord*) (delta << block_shift); + HeapWord* result = (HeapWord*) (delta << _card_shift); assert(_covered_region.contains(result), "out of bounds accessor from card marking array"); return result; @@ -104,7 +115,7 @@ class ObjectStartArray : public CHeapObj { } size_t delta = pointer_delta(p, _offset_base, sizeof(jbyte)); - HeapWord* result = (HeapWord*) (delta << block_shift); + HeapWord* result = (HeapWord*) (delta << _card_shift); result += *p; assert(_covered_region.contains(result), diff --git a/src/hotspot/share/gc/parallel/psOldGen.cpp b/src/hotspot/share/gc/parallel/psOldGen.cpp index 4f689ec7251..efbaac25d07 100644 --- a/src/hotspot/share/gc/parallel/psOldGen.cpp +++ b/src/hotspot/share/gc/parallel/psOldGen.cpp @@ -152,7 +152,7 @@ size_t PSOldGen::num_iterable_blocks() const { void PSOldGen::object_iterate_block(ObjectClosure* cl, size_t block_index) { size_t block_word_size = IterateBlockSize / HeapWordSize; - assert((block_word_size % (ObjectStartArray::block_size)) == 0, + assert((block_word_size % (ObjectStartArray::card_size())) == 0, "Block size not a multiple of start_array block"); MutableSpace *space = object_space(); diff --git a/src/hotspot/share/gc/shared/blockOffsetTable.cpp b/src/hotspot/share/gc/shared/blockOffsetTable.cpp index b7d58649208..e350e70ad5f 100644 --- a/src/hotspot/share/gc/shared/blockOffsetTable.cpp +++ b/src/hotspot/share/gc/shared/blockOffsetTable.cpp @@ -33,16 +33,16 @@ #include "runtime/java.hpp" #include "services/memTracker.hpp" -uint BOTConstants::LogN = 0; -uint BOTConstants::LogN_words = 0; -uint BOTConstants::N_bytes = 0; -uint BOTConstants::N_words = 0; +uint BOTConstants::_log_card_size = 0; +uint BOTConstants::_log_card_size_in_words = 0; +uint BOTConstants::_card_size = 0; +uint BOTConstants::_card_size_in_words = 0; void BOTConstants::initialize_bot_size(uint card_shift) { - LogN = card_shift; - LogN_words = LogN - LogHeapWordSize; - N_bytes = 1 << LogN; - N_words = 1 << LogN_words; + _log_card_size = card_shift; + _log_card_size_in_words = _log_card_size - LogHeapWordSize; + _card_size = 1 << _log_card_size; + _card_size_in_words = 1 << _log_card_size_in_words; } ////////////////////////////////////////////////////////////////////// @@ -99,7 +99,7 @@ void BlockOffsetSharedArray::resize(size_t new_word_size) { bool BlockOffsetSharedArray::is_card_boundary(HeapWord* p) const { assert(p >= _reserved.start(), "just checking"); size_t delta = pointer_delta(p, _reserved.start()); - return (delta & right_n_bits((int)BOTConstants::LogN_words)) == (size_t)NoBits; + return (delta & right_n_bits((int)BOTConstants::log_card_size_in_words())) == (size_t)NoBits; } @@ -116,7 +116,7 @@ BlockOffsetArray::BlockOffsetArray(BlockOffsetSharedArray* array, set_init_to_zero(init_to_zero_); if (!init_to_zero_) { // initialize cards to point back to mr.start() - set_remainder_to_point_to_start(mr.start() + BOTConstants::N_words, mr.end()); + set_remainder_to_point_to_start(mr.start() + BOTConstants::card_size_in_words(), mr.end()); _array->set_offset_array(0, 0); // set first card to 0 } } @@ -172,7 +172,7 @@ set_remainder_to_point_to_start(HeapWord* start, HeapWord* end, bool reducing) { size_t start_card = _array->index_for(start); size_t end_card = _array->index_for(end-1); assert(start ==_array->address_for_index(start_card), "Precondition"); - assert(end ==_array->address_for_index(end_card)+BOTConstants::N_words, "Precondition"); + assert(end ==_array->address_for_index(end_card)+BOTConstants::card_size_in_words(), "Precondition"); set_remainder_to_point_to_start_incl(start_card, end_card, reducing); // closed interval } @@ -188,7 +188,7 @@ BlockOffsetArray::set_remainder_to_point_to_start_incl(size_t start_card, size_t return; } assert(start_card > _array->index_for(_bottom), "Cannot be first card"); - assert(_array->offset_array(start_card-1) <= BOTConstants::N_words, + assert(_array->offset_array(start_card-1) <= BOTConstants::card_size_in_words(), "Offset card has an unexpected value"); size_t start_card_for_region = start_card; u_char offset = max_jubyte; @@ -197,7 +197,7 @@ BlockOffsetArray::set_remainder_to_point_to_start_incl(size_t start_card, size_t // so that the reach ends in this region and not at the start // of the next. size_t reach = start_card - 1 + (BOTConstants::power_to_cards_back(i+1) - 1); - offset = BOTConstants::N_words + i; + offset = BOTConstants::card_size_in_words() + i; if (reach >= end_card) { _array->set_offset_array(start_card_for_region, end_card, offset, reducing); start_card_for_region = reach + 1; @@ -218,13 +218,13 @@ void BlockOffsetArray::check_all_cards(size_t start_card, size_t end_card) const if (end_card < start_card) { return; } - guarantee(_array->offset_array(start_card) == BOTConstants::N_words, "Wrong value in second card"); - u_char last_entry = BOTConstants::N_words; + guarantee(_array->offset_array(start_card) == BOTConstants::card_size_in_words(), "Wrong value in second card"); + u_char last_entry = BOTConstants::card_size_in_words(); for (size_t c = start_card + 1; c <= end_card; c++ /* yeah! */) { u_char entry = _array->offset_array(c); guarantee(entry >= last_entry, "Monotonicity"); if (c - start_card > BOTConstants::power_to_cards_back(1)) { - guarantee(entry > BOTConstants::N_words, "Should be in logarithmic region"); + guarantee(entry > BOTConstants::card_size_in_words(), "Should be in logarithmic region"); } size_t backskip = BOTConstants::entry_to_cards_back(entry); size_t landing_card = c - backskip; @@ -234,7 +234,7 @@ void BlockOffsetArray::check_all_cards(size_t start_card, size_t end_card) const } else { guarantee(landing_card == (start_card - 1), "Tautology"); // Note that N_words is the maximum offset value - guarantee(_array->offset_array(landing_card) <= BOTConstants::N_words, "Offset value"); + guarantee(_array->offset_array(landing_card) <= BOTConstants::card_size_in_words(), "Offset value"); } last_entry = entry; // remember for monotonicity test } @@ -266,7 +266,7 @@ BlockOffsetArray::do_block_internal(HeapWord* blk_start, uintptr_t start_ui = (uintptr_t)blk_start; // Calculate the last card boundary preceding end of blk intptr_t boundary_before_end = (intptr_t)end_ui; - clear_bits(boundary_before_end, right_n_bits((int)BOTConstants::LogN)); + clear_bits(boundary_before_end, right_n_bits((int)BOTConstants::log_card_size())); if (start_ui <= (uintptr_t)boundary_before_end) { // blk starts at or crosses a boundary // Calculate index of card on which blk begins @@ -279,7 +279,7 @@ BlockOffsetArray::do_block_internal(HeapWord* blk_start, if (blk_start != boundary) { // blk starts strictly after boundary // adjust card boundary and start_index forward to next card - boundary += BOTConstants::N_words; + boundary += BOTConstants::card_size_in_words(); start_index++; } assert(start_index <= end_index, "monotonicity of index_for()"); @@ -296,8 +296,8 @@ BlockOffsetArray::do_block_internal(HeapWord* blk_start, // We have finished marking the "offset card". We need to now // mark the subsequent cards that this blk spans. if (start_index < end_index) { - HeapWord* rem_st = _array->address_for_index(start_index) + BOTConstants::N_words; - HeapWord* rem_end = _array->address_for_index(end_index) + BOTConstants::N_words; + HeapWord* rem_st = _array->address_for_index(start_index) + BOTConstants::card_size_in_words(); + HeapWord* rem_end = _array->address_for_index(end_index) + BOTConstants::card_size_in_words(); set_remainder_to_point_to_start(rem_st, rem_end, reducing); } break; @@ -380,22 +380,22 @@ HeapWord* BlockOffsetArrayContigSpace::block_start_unsafe(const void* addr) cons HeapWord* q = _array->address_for_index(index); uint offset = _array->offset_array(index); // Extend u_char to uint. - while (offset > BOTConstants::N_words) { + while (offset > BOTConstants::card_size_in_words()) { // The excess of the offset from N_words indicates a power of Base // to go back by. size_t n_cards_back = BOTConstants::entry_to_cards_back(offset); - q -= (BOTConstants::N_words * n_cards_back); + q -= (BOTConstants::card_size_in_words() * n_cards_back); assert(q >= _sp->bottom(), "Went below bottom!"); index -= n_cards_back; offset = _array->offset_array(index); } - while (offset == BOTConstants::N_words) { + while (offset == BOTConstants::card_size_in_words()) { assert(q >= _sp->bottom(), "Went below bottom!"); - q -= BOTConstants::N_words; + q -= BOTConstants::card_size_in_words(); index--; offset = _array->offset_array(index); } - assert(offset < BOTConstants::N_words, "offset too large"); + assert(offset < BOTConstants::card_size_in_words(), "offset too large"); q -= offset; HeapWord* n = q; @@ -428,14 +428,14 @@ void BlockOffsetArrayContigSpace::alloc_block_work(HeapWord* blk_start, "should be past threshold"); assert(blk_start <= _next_offset_threshold, "blk_start should be at or before threshold"); - assert(pointer_delta(_next_offset_threshold, blk_start) <= BOTConstants::N_words, + assert(pointer_delta(_next_offset_threshold, blk_start) <= BOTConstants::card_size_in_words(), "offset should be <= BlockOffsetSharedArray::N"); assert(_sp->is_in_reserved(blk_start), "reference must be into the space"); assert(_sp->is_in_reserved(blk_end-1), "limit must be within the space"); assert(_next_offset_threshold == - _array->_reserved.start() + _next_offset_index*BOTConstants::N_words, + _array->_reserved.start() + _next_offset_index*BOTConstants::card_size_in_words(), "index must agree with threshold"); debug_only(size_t orig_next_offset_index = _next_offset_index;) @@ -457,7 +457,7 @@ void BlockOffsetArrayContigSpace::alloc_block_work(HeapWord* blk_start, HeapWord* rem_st = _array->address_for_index(_next_offset_index + 1); // Calculate rem_end this way because end_index // may be the last valid index in the covered region. - HeapWord* rem_end = _array->address_for_index(end_index) + BOTConstants::N_words; + HeapWord* rem_end = _array->address_for_index(end_index) + BOTConstants::card_size_in_words(); set_remainder_to_point_to_start(rem_st, rem_end); } @@ -465,7 +465,7 @@ void BlockOffsetArrayContigSpace::alloc_block_work(HeapWord* blk_start, _next_offset_index = end_index + 1; // Calculate _next_offset_threshold this way because end_index // may be the last valid index in the covered region. - _next_offset_threshold = _array->address_for_index(end_index) + BOTConstants::N_words; + _next_offset_threshold = _array->address_for_index(end_index) + BOTConstants::card_size_in_words(); assert(_next_offset_threshold >= blk_end, "Incorrect offset threshold"); #ifdef ASSERT @@ -476,11 +476,11 @@ void BlockOffsetArrayContigSpace::alloc_block_work(HeapWord* blk_start, assert((_array->offset_array(orig_next_offset_index) == 0 && blk_start == boundary) || (_array->offset_array(orig_next_offset_index) > 0 && - _array->offset_array(orig_next_offset_index) <= BOTConstants::N_words), + _array->offset_array(orig_next_offset_index) <= BOTConstants::card_size_in_words()), "offset array should have been set"); for (size_t j = orig_next_offset_index + 1; j <= end_index; j++) { assert(_array->offset_array(j) > 0 && - _array->offset_array(j) <= (u_char) (BOTConstants::N_words+BOTConstants::N_powers-1), + _array->offset_array(j) <= (u_char) (BOTConstants::card_size_in_words()+BOTConstants::N_powers-1), "offset array should have been set"); } #endif diff --git a/src/hotspot/share/gc/shared/blockOffsetTable.hpp b/src/hotspot/share/gc/shared/blockOffsetTable.hpp index fef56d31205..7d6ddfdf799 100644 --- a/src/hotspot/share/gc/shared/blockOffsetTable.hpp +++ b/src/hotspot/share/gc/shared/blockOffsetTable.hpp @@ -49,12 +49,12 @@ class ContiguousSpace; class BOTConstants : public AllStatic { -public: - static uint LogN; - static uint LogN_words; - static uint N_bytes; - static uint N_words; + static uint _log_card_size; + static uint _log_card_size_in_words; + static uint _card_size; + static uint _card_size_in_words; +public: // entries "e" of at least N_words mean "go back by Base^(e-N_words)." // All entries are less than "N_words + N_powers". static const uint LogBase = 4; @@ -67,9 +67,22 @@ public: static size_t power_to_cards_back(uint i) { return (size_t)1 << (LogBase * i); } + static size_t entry_to_cards_back(u_char entry) { - assert(entry >= N_words, "Precondition"); - return power_to_cards_back(entry - N_words); + assert(entry >= _card_size_in_words, "Precondition"); + return power_to_cards_back(entry - _card_size_in_words); + } + static uint log_card_size() { + return _log_card_size; + } + static uint log_card_size_in_words() { + return _log_card_size_in_words; + } + static uint card_size() { + return _card_size; + } + static uint card_size_in_words() { + return _card_size_in_words; } }; @@ -91,7 +104,7 @@ public: BlockOffsetTable(HeapWord* bottom, HeapWord* end): _bottom(bottom), _end(end) { assert(_bottom <= _end, "arguments out of order"); - assert(BOTConstants::N_bytes == CardTable::card_size, "sanity"); + assert(BOTConstants::card_size() == CardTable::card_size(), "sanity"); } // Note that the committed size of the covered space may have changed, @@ -178,7 +191,7 @@ class BlockOffsetSharedArray: public CHeapObj { check_reducing_assertion(reducing); assert(index < _vs.committed_size(), "index out of range"); assert(high >= low, "addresses out of order"); - assert(pointer_delta(high, low) <= BOTConstants::N_words, "offset too large"); + assert(pointer_delta(high, low) <= BOTConstants::card_size_in_words(), "offset too large"); assert(!reducing || _offset_array[index] >= (u_char)pointer_delta(high, low), "Not reducing"); _offset_array[index] = (u_char)pointer_delta(high, low); @@ -189,7 +202,7 @@ class BlockOffsetSharedArray: public CHeapObj { assert(index_for(right - 1) < _vs.committed_size(), "right address out of range"); assert(left < right, "Heap addresses out of order"); - size_t num_cards = pointer_delta(right, left) >> BOTConstants::LogN_words; + size_t num_cards = pointer_delta(right, left) >> BOTConstants::log_card_size_in_words(); fill_range(index_for(left), num_cards, offset); } @@ -206,7 +219,7 @@ class BlockOffsetSharedArray: public CHeapObj { void check_offset_array(size_t index, HeapWord* high, HeapWord* low) const { assert(index < _vs.committed_size(), "index out of range"); assert(high >= low, "addresses out of order"); - assert(pointer_delta(high, low) <= BOTConstants::N_words, "offset too large"); + assert(pointer_delta(high, low) <= BOTConstants::card_size_in_words(), "offset too large"); assert(_offset_array[index] == pointer_delta(high, low), "Wrong offset"); } @@ -221,7 +234,7 @@ class BlockOffsetSharedArray: public CHeapObj { // to be reserved. size_t compute_size(size_t mem_region_words) { - size_t number_of_slots = (mem_region_words / BOTConstants::N_words) + 1; + size_t number_of_slots = (mem_region_words / BOTConstants::card_size_in_words()) + 1; return ReservedSpace::allocation_align_size_up(number_of_slots); } @@ -335,7 +348,7 @@ class BlockOffsetArray: public BlockOffsetTable { assert(_array->is_card_boundary(new_end), "new _end would not be a card boundary"); // set all the newly added cards - _array->set_offset_array(_end, new_end, BOTConstants::N_words); + _array->set_offset_array(_end, new_end, BOTConstants::card_size_in_words()); } _end = new_end; // update _end } diff --git a/src/hotspot/share/gc/shared/blockOffsetTable.inline.hpp b/src/hotspot/share/gc/shared/blockOffsetTable.inline.hpp index ceb852b4ffc..abaa0dade46 100644 --- a/src/hotspot/share/gc/shared/blockOffsetTable.inline.hpp +++ b/src/hotspot/share/gc/shared/blockOffsetTable.inline.hpp @@ -50,14 +50,14 @@ inline size_t BlockOffsetSharedArray::index_for(const void* p) const { pc < (char*)_reserved.end(), "p not in range."); size_t delta = pointer_delta(pc, _reserved.start(), sizeof(char)); - size_t result = delta >> BOTConstants::LogN; + size_t result = delta >> BOTConstants::log_card_size(); assert(result < _vs.committed_size(), "bad index from address"); return result; } inline HeapWord* BlockOffsetSharedArray::address_for_index(size_t index) const { assert(index < _vs.committed_size(), "bad index"); - HeapWord* result = _reserved.start() + (index << BOTConstants::LogN_words); + HeapWord* result = _reserved.start() + (index << BOTConstants::log_card_size_in_words()); assert(result >= _reserved.start() && result < _reserved.end(), "bad address from index"); return result; diff --git a/src/hotspot/share/gc/shared/c1/cardTableBarrierSetC1.cpp b/src/hotspot/share/gc/shared/c1/cardTableBarrierSetC1.cpp index b66e94836ed..660c324aa99 100644 --- a/src/hotspot/share/gc/shared/c1/cardTableBarrierSetC1.cpp +++ b/src/hotspot/share/gc/shared/c1/cardTableBarrierSetC1.cpp @@ -69,9 +69,9 @@ void CardTableBarrierSetC1::post_barrier(LIRAccess& access, LIR_Opr addr, LIR_Op if (TwoOperandLIRForm) { LIR_Opr addr_opr = LIR_OprFact::address(new LIR_Address(addr, addr->type())); __ leal(addr_opr, tmp); - __ unsigned_shift_right(tmp, CardTable::card_shift, tmp); + __ unsigned_shift_right(tmp, CardTable::card_shift(), tmp); } else { - __ unsigned_shift_right(addr, CardTable::card_shift, tmp); + __ unsigned_shift_right(addr, CardTable::card_shift(), tmp); } LIR_Address* card_addr; diff --git a/src/hotspot/share/gc/shared/c2/cardTableBarrierSetC2.cpp b/src/hotspot/share/gc/shared/c2/cardTableBarrierSetC2.cpp index 73ea620041b..0a7a032c117 100644 --- a/src/hotspot/share/gc/shared/c2/cardTableBarrierSetC2.cpp +++ b/src/hotspot/share/gc/shared/c2/cardTableBarrierSetC2.cpp @@ -91,7 +91,7 @@ void CardTableBarrierSetC2::post_barrier(GraphKit* kit, Node* cast = __ CastPX(__ ctrl(), adr); // Divide by card size - Node* card_offset = __ URShiftX(cast, __ ConI(CardTable::card_shift)); + Node* card_offset = __ URShiftX(cast, __ ConI(CardTable::card_shift())); // Combine card table base and card offset Node* card_adr = __ AddP(__ top(), byte_map_base_node(kit), card_offset); diff --git a/src/hotspot/share/gc/shared/cardTable.cpp b/src/hotspot/share/gc/shared/cardTable.cpp index 10e4723934d..2ff5f8d31c3 100644 --- a/src/hotspot/share/gc/shared/cardTable.cpp +++ b/src/hotspot/share/gc/shared/cardTable.cpp @@ -38,27 +38,27 @@ #include "gc/parallel/objectStartArray.hpp" #endif -uint CardTable::card_shift = 0; -uint CardTable::card_size = 0; -uint CardTable::card_size_in_words = 0; +uint CardTable::_card_shift = 0; +uint CardTable::_card_size = 0; +uint CardTable::_card_size_in_words = 0; void CardTable::initialize_card_size() { assert(UseG1GC || UseParallelGC || UseSerialGC, "Initialize card size should only be called by card based collectors."); - card_size = GCCardSizeInBytes; - card_shift = log2i_exact(card_size); - card_size_in_words = card_size / sizeof(HeapWord); + _card_size = GCCardSizeInBytes; + _card_shift = log2i_exact(_card_size); + _card_size_in_words = _card_size / sizeof(HeapWord); // Set blockOffsetTable size based on card table entry size - BOTConstants::initialize_bot_size(card_shift); + BOTConstants::initialize_bot_size(_card_shift); #if INCLUDE_PARALLELGC // Set ObjectStartArray block size based on card table entry size - ObjectStartArray::initialize_block_size(card_shift); + ObjectStartArray::initialize_block_size(_card_shift); #endif - log_info_p(gc, init)("CardTable entry size: " UINT32_FORMAT, card_size); + log_info_p(gc, init)("CardTable entry size: " UINT32_FORMAT, _card_size); } size_t CardTable::compute_byte_map_size() { @@ -82,8 +82,8 @@ CardTable::CardTable(MemRegion whole_heap) : _committed(MemRegion::create_array(_max_covered_regions, mtGC)), _guard_region() { - assert((uintptr_t(_whole_heap.start()) & (card_size - 1)) == 0, "heap must start at card boundary"); - assert((uintptr_t(_whole_heap.end()) & (card_size - 1)) == 0, "heap must end at card boundary"); + assert((uintptr_t(_whole_heap.start()) & (_card_size - 1)) == 0, "heap must start at card boundary"); + assert((uintptr_t(_whole_heap.end()) & (_card_size - 1)) == 0, "heap must end at card boundary"); } CardTable::~CardTable() { @@ -120,7 +120,7 @@ void CardTable::initialize() { // // _byte_map = _byte_map_base + (uintptr_t(low_bound) >> card_shift) _byte_map = (CardValue*) heap_rs.base(); - _byte_map_base = _byte_map - (uintptr_t(low_bound) >> card_shift); + _byte_map_base = _byte_map - (uintptr_t(low_bound) >> _card_shift); assert(byte_for(low_bound) == &_byte_map[0], "Checking start of map"); assert(byte_for(high_bound-1) <= &_byte_map[_last_valid_index], "Checking end of map"); @@ -413,7 +413,7 @@ void CardTable::dirty_card_iterate(MemRegion mr, MemRegionClosure* cl) { next_entry <= limit && *next_entry == dirty_card; dirty_cards++, next_entry++); MemRegion cur_cards(addr_for(cur_entry), - dirty_cards*card_size_in_words); + dirty_cards*_card_size_in_words); cl->do_MemRegion(cur_cards); } } @@ -439,7 +439,7 @@ MemRegion CardTable::dirty_card_range_after_reset(MemRegion mr, next_entry <= limit && *next_entry == dirty_card; dirty_cards++, next_entry++); MemRegion cur_cards(addr_for(cur_entry), - dirty_cards*card_size_in_words); + dirty_cards * _card_size_in_words); if (reset) { for (size_t i = 0; i < dirty_cards; i++) { cur_entry[i] = reset_val; @@ -493,7 +493,7 @@ void CardTable::verify_region(MemRegion mr, CardValue val, bool val_equals) { } log_error(gc, verify)("== card " PTR_FORMAT " [" PTR_FORMAT "," PTR_FORMAT "], val: %d", p2i(curr), p2i(addr_for(curr)), - p2i((HeapWord*) (((size_t) addr_for(curr)) + card_size)), + p2i((HeapWord*) (((size_t) addr_for(curr)) + _card_size)), (int) curr_val); } } diff --git a/src/hotspot/share/gc/shared/cardTable.hpp b/src/hotspot/share/gc/shared/cardTable.hpp index bf116a1f1e7..075b961b3cd 100644 --- a/src/hotspot/share/gc/shared/cardTable.hpp +++ b/src/hotspot/share/gc/shared/cardTable.hpp @@ -111,6 +111,11 @@ protected: // a word's worth (row) of clean card values static const intptr_t clean_card_row = (intptr_t)(-1); + // CardTable entry size + static uint _card_shift; + static uint _card_size; + static uint _card_size_in_words; + public: CardTable(MemRegion whole_heap); virtual ~CardTable(); @@ -133,8 +138,8 @@ public: // in, um, words. inline size_t cards_required(size_t covered_words) { // Add one for a guard card, used to detect errors. - const size_t words = align_up(covered_words, card_size_in_words); - return words / card_size_in_words + 1; + const size_t words = align_up(covered_words, _card_size_in_words); + return words / _card_size_in_words + 1; } // Dirty the bytes corresponding to "mr" (not all of which must be @@ -157,7 +162,7 @@ public: "Attempt to access p = " PTR_FORMAT " out of bounds of " " card marking array's _whole_heap = [" PTR_FORMAT "," PTR_FORMAT ")", p2i(p), p2i(_whole_heap.start()), p2i(_whole_heap.end())); - CardValue* result = &_byte_map_base[uintptr_t(p) >> card_shift]; + CardValue* result = &_byte_map_base[uintptr_t(p) >> _card_shift]; assert(result >= _byte_map && result < _byte_map + _byte_map_size, "out of bounds accessor for card marking array"); return result; @@ -189,7 +194,7 @@ public: " _byte_map: " PTR_FORMAT " _byte_map + _byte_map_size: " PTR_FORMAT, p2i(p), p2i(_byte_map), p2i(_byte_map + _byte_map_size)); size_t delta = pointer_delta(p, _byte_map_base, sizeof(CardValue)); - HeapWord* result = (HeapWord*) (delta << card_shift); + HeapWord* result = (HeapWord*) (delta << _card_shift); assert(_whole_heap.contains(result), "Returning result = " PTR_FORMAT " out of bounds of " " card marking array's _whole_heap = [" PTR_FORMAT "," PTR_FORMAT ")", @@ -228,10 +233,17 @@ public: MemRegion dirty_card_range_after_reset(MemRegion mr, bool reset, int reset_val); - // CardTable entry size - static uint card_shift; - static uint card_size; - static uint card_size_in_words; + static uint card_shift() { + return _card_shift; + } + + static uint card_size() { + return _card_size; + } + + static uint card_size_in_words() { + return _card_size_in_words; + } static constexpr CardValue clean_card_val() { return clean_card; } static constexpr CardValue dirty_card_val() { return dirty_card; } diff --git a/src/hotspot/share/gc/shared/vmStructs_gc.hpp b/src/hotspot/share/gc/shared/vmStructs_gc.hpp index 2de1cc8c57c..f9b1c631123 100644 --- a/src/hotspot/share/gc/shared/vmStructs_gc.hpp +++ b/src/hotspot/share/gc/shared/vmStructs_gc.hpp @@ -261,10 +261,6 @@ declare_constant(BarrierSet::ModRef) \ declare_constant(BarrierSet::CardTableBarrierSet) \ \ - declare_constant(BOTConstants::LogN) \ - declare_constant(BOTConstants::LogN_words) \ - declare_constant(BOTConstants::N_bytes) \ - declare_constant(BOTConstants::N_words) \ declare_constant(BOTConstants::LogBase) \ declare_constant(BOTConstants::Base) \ declare_constant(BOTConstants::N_powers) \ @@ -274,9 +270,6 @@ declare_constant(CardTable::dirty_card) \ declare_constant(CardTable::Precise) \ declare_constant(CardTable::ObjHeadPreciseArray) \ - declare_constant(CardTable::card_shift) \ - declare_constant(CardTable::card_size) \ - declare_constant(CardTable::card_size_in_words) \ \ declare_constant(CollectedHeap::Serial) \ declare_constant(CollectedHeap::Parallel) \ diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp index bde6be763ca..63e41d3574c 100644 --- a/src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp +++ b/src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp @@ -138,7 +138,7 @@ void CompilerToVM::Data::initialize(JVMCI_TRAPS) { CardTable::CardValue* base = ci_card_table_address(); assert(base != NULL, "unexpected byte_map_base"); cardtable_start_address = base; - cardtable_shift = CardTable::card_shift; + cardtable_shift = CardTable::card_shift(); } else { // No card mark barriers cardtable_start_address = 0; diff --git a/test/hotspot/gtest/gc/g1/test_freeRegionList.cpp b/test/hotspot/gtest/gc/g1/test_freeRegionList.cpp index 9a69816558b..2cf82eb4037 100644 --- a/test/hotspot/gtest/gc/g1/test_freeRegionList.cpp +++ b/test/hotspot/gtest/gc/g1/test_freeRegionList.cpp @@ -57,7 +57,7 @@ TEST_VM(FreeRegionList, length) { bot_rs.size(), os::vm_page_size(), HeapRegion::GrainBytes, - BOTConstants::N_bytes, + BOTConstants::card_size(), mtGC); G1BlockOffsetTable bot(heap, bot_storage); bot_storage->commit_regions(0, num_regions_in_test); diff --git a/test/hotspot/gtest/gc/g1/test_g1CardSetContainers.cpp b/test/hotspot/gtest/gc/g1/test_g1CardSetContainers.cpp index c2ebeadd481..9283fc3303f 100644 --- a/test/hotspot/gtest/gc/g1/test_g1CardSetContainers.cpp +++ b/test/hotspot/gtest/gc/g1/test_g1CardSetContainers.cpp @@ -240,7 +240,7 @@ TEST_VM_F(G1CardSetContainersTest, basic_cardset_inptr_test) { uint const max = (uint)log2i(HeapRegionBounds::max_size()); for (uint i = min; i <= max; i++) { - G1CardSetContainersTest::cardset_inlineptr_test(i - CardTable::card_shift); + G1CardSetContainersTest::cardset_inlineptr_test(i - CardTable::card_shift()); } } -- GitLab From ab781874b27ee4fe1bc6b5fa2cd7997e451e2026 Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Mon, 6 Dec 2021 15:43:42 +0000 Subject: [PATCH 006/671] 8277105: Inconsistent handling of missing permitted subclasses Reviewed-by: vromero --- .../com/sun/tools/javac/comp/Flow.java | 33 ++- .../tools/javac/patterns/Exhaustiveness.java | 96 --------- .../sealed/MissingPermittedSubtypes.java | 199 ++++++++++++++++++ 3 files changed, 214 insertions(+), 114 deletions(-) create mode 100644 test/langtools/tools/javac/sealed/MissingPermittedSubtypes.java diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java index eaff2f1106d..1346d141bb7 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java @@ -207,7 +207,6 @@ public class Flow { private final JCDiagnostic.Factory diags; private Env attrEnv; private Lint lint; - private final DeferredCompletionFailureHandler dcfh; private final boolean allowEffectivelyFinalInInnerClasses; public static Flow instance(Context context) { @@ -332,7 +331,6 @@ public class Flow { lint = Lint.instance(context); rs = Resolve.instance(context); diags = JCDiagnostic.Factory.instance(context); - dcfh = DeferredCompletionFailureHandler.instance(context); Source source = Source.instance(context); allowEffectivelyFinalInInnerClasses = Feature.EFFECTIVELY_FINAL_IN_INNER_CLASSES.allowedInSource(source); } @@ -693,7 +691,7 @@ public class Flow { } if (!tree.hasTotalPattern && exhaustiveSwitch && !TreeInfo.isErrorEnumSwitch(tree.selector, tree.cases) && - (constants == null || !isExhaustive(tree.selector.type, constants))) { + (constants == null || !isExhaustive(tree.selector.pos(), tree.selector.type, constants))) { log.error(tree, Errors.NotExhaustiveStatement); } if (!tree.hasTotalPattern) { @@ -728,7 +726,7 @@ public class Flow { } } if (!tree.hasTotalPattern && !TreeInfo.isErrorEnumSwitch(tree.selector, tree.cases) && - !isExhaustive(tree.selector.type, constants)) { + !isExhaustive(tree.selector.pos(), tree.selector.type, constants)) { log.error(tree, Errors.NotExhaustive); } alive = prevAlive; @@ -751,7 +749,7 @@ public class Flow { } } - private void transitiveCovers(Type seltype, Set covered) { + private void transitiveCovers(DiagnosticPosition pos, Type seltype, Set covered) { List todo = List.from(covered); while (todo.nonEmpty()) { Symbol sym = todo.head; @@ -773,7 +771,7 @@ public class Flow { case TYP -> { for (Type sup : types.directSupertypes(sym.type)) { if (sup.tsym.kind == TYP) { - if (isTransitivelyCovered(seltype, sup.tsym, covered) && + if (isTransitivelyCovered(pos, seltype, sup.tsym, covered) && covered.add(sup.tsym)) { todo = todo.prepend(sup.tsym); } @@ -784,9 +782,8 @@ public class Flow { } } - private boolean isTransitivelyCovered(Type seltype, Symbol sealed, Set covered) { - DeferredCompletionFailureHandler.Handler prevHandler = - dcfh.setHandler(dcfh.speculativeCodeHandler); + private boolean isTransitivelyCovered(DiagnosticPosition pos, Type seltype, + Symbol sealed, Set covered) { try { if (covered.stream().anyMatch(c -> sealed.isSubClass(c, types))) return true; @@ -796,30 +793,30 @@ public class Flow { .filter(s -> { return types.isCastable(seltype, s.type/*, types.noWarnings*/); }) - .allMatch(s -> isTransitivelyCovered(seltype, s, covered)); + .allMatch(s -> isTransitivelyCovered(pos, seltype, s, covered)); } return false; } catch (CompletionFailure cf) { - //safe to ignore, the symbol will be un-completed when the speculative handler is removed. - return false; - } finally { - dcfh.setHandler(prevHandler); + chk.completionError(pos, cf); + return true; } } - private boolean isExhaustive(Type seltype, Set covered) { - transitiveCovers(seltype, covered); + private boolean isExhaustive(DiagnosticPosition pos, Type seltype, Set covered) { + transitiveCovers(pos, seltype, covered); return switch (seltype.getTag()) { case CLASS -> { if (seltype.isCompound()) { if (seltype.isIntersection()) { - yield ((Type.IntersectionClassType) seltype).getComponents().stream().anyMatch(t -> isExhaustive(t, covered)); + yield ((Type.IntersectionClassType) seltype).getComponents() + .stream() + .anyMatch(t -> isExhaustive(pos, t, covered)); } yield false; } yield covered.contains(seltype.tsym); } - case TYPEVAR -> isExhaustive(((TypeVar) seltype).getUpperBound(), covered); + case TYPEVAR -> isExhaustive(pos, ((TypeVar) seltype).getUpperBound(), covered); default -> false; }; } diff --git a/test/langtools/tools/javac/patterns/Exhaustiveness.java b/test/langtools/tools/javac/patterns/Exhaustiveness.java index 36c824deeee..b7db66c3231 100644 --- a/test/langtools/tools/javac/patterns/Exhaustiveness.java +++ b/test/langtools/tools/javac/patterns/Exhaustiveness.java @@ -369,102 +369,6 @@ public class Exhaustiveness extends TestRunner { """); } - @Test - public void testInaccessiblePermitted(Path base) throws IOException { - Path current = base.resolve("."); - Path libSrc = current.resolve("lib-src"); - - tb.writeJavaFiles(libSrc, - """ - package lib; - public sealed interface S permits A, B {} - """, - """ - package lib; - public final class A implements S {} - """, - """ - package lib; - final class B implements S {} - """); - - Path libClasses = current.resolve("libClasses"); - - Files.createDirectories(libClasses); - - new JavacTask(tb) - .options("--enable-preview", - "-source", JAVA_VERSION) - .outdir(libClasses) - .files(tb.findJavaFiles(libSrc)) - .run(); - - Path src = current.resolve("src"); - tb.writeJavaFiles(src, - """ - package test; - import lib.*; - public class Test { - private int test(S obj) { - return switch (obj) { - case A a -> 0; - }; - } - } - """); - - Path classes = current.resolve("libClasses"); - - Files.createDirectories(libClasses); - - var log = - new JavacTask(tb) - .options("--enable-preview", - "-source", JAVA_VERSION, - "-XDrawDiagnostics", - "-Xlint:-preview", - "--class-path", libClasses.toString()) - .outdir(classes) - .files(tb.findJavaFiles(src)) - .run(Task.Expect.FAIL) - .writeAll() - .getOutputLines(Task.OutputKind.DIRECT); - - List expectedErrors = List.of( - "Test.java:5:16: compiler.err.not.exhaustive", - "- compiler.note.preview.filename: Test.java, DEFAULT", - "- compiler.note.preview.recompile", - "1 error"); - - if (!expectedErrors.equals(log)) { - throw new AssertionError("Incorrect errors, expected: " + expectedErrors + - ", actual: " + log); - } - - Path bClass = libClasses.resolve("lib").resolve("B.class"); - - Files.delete(bClass); - - var log2 = - new JavacTask(tb) - .options("--enable-preview", - "-source", JAVA_VERSION, - "-XDrawDiagnostics", - "-Xlint:-preview", - "--class-path", libClasses.toString()) - .outdir(classes) - .files(tb.findJavaFiles(src)) - .run(Task.Expect.FAIL) - .writeAll() - .getOutputLines(Task.OutputKind.DIRECT); - - if (!expectedErrors.equals(log2)) { - throw new AssertionError("Incorrect errors, expected: " + expectedErrors + - ", actual: " + log2); - } - - } - @Test public void testExhaustiveStatement1(Path base) throws Exception { doTest(base, diff --git a/test/langtools/tools/javac/sealed/MissingPermittedSubtypes.java b/test/langtools/tools/javac/sealed/MissingPermittedSubtypes.java new file mode 100644 index 00000000000..ba75407099a --- /dev/null +++ b/test/langtools/tools/javac/sealed/MissingPermittedSubtypes.java @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2021, 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. + */ + +/** + * @test + * @bug 8277105 + * @summary Verify missing permitted subtype is handled properly for both casts and pattern switches. + * @library /tools/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.main + * jdk.compiler/com.sun.tools.javac.util + * @build toolbox.ToolBox toolbox.JavacTask + * @run main MissingPermittedSubtypes +*/ + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; + +import toolbox.TestRunner; +import toolbox.JavacTask; +import toolbox.Task; +import toolbox.ToolBox; + +public class MissingPermittedSubtypes extends TestRunner { + + private static final String JAVA_VERSION = System.getProperty("java.specification.version"); + + ToolBox tb; + + public static void main(String... args) throws Exception { + new MissingPermittedSubtypes().runTests(); + } + + MissingPermittedSubtypes() { + super(System.err); + tb = new ToolBox(); + } + + public void runTests() throws Exception { + runTests(m -> new Object[] { Paths.get(m.getName()) }); + } + + @Test + public void testInaccessiblePermitted(Path base) throws IOException { + Path current = base.resolve("."); + Path libSrc = current.resolve("lib-src"); + + tb.writeJavaFiles(libSrc, + """ + package lib; + public sealed interface S permits A, B1, B2 {} + """, + """ + package lib; + public final class A implements S {} + """, + """ + package lib; + final class B1 implements S {} + """, + """ + package lib; + final class B2 implements S, Runnable { + public void run() {} + } + """); + + Path libClasses = current.resolve("libClasses"); + + Files.createDirectories(libClasses); + + new JavacTask(tb) + .options("--enable-preview", + "-source", JAVA_VERSION) + .outdir(libClasses) + .files(tb.findJavaFiles(libSrc)) + .run(); + + Path b1Class = libClasses.resolve("lib").resolve("B1.class"); + + Files.delete(b1Class); + + Path b2Class = libClasses.resolve("lib").resolve("B2.class"); + + Files.delete(b2Class); + + { + Path src1 = current.resolve("src1"); + tb.writeJavaFiles(src1, + """ + package test; + import lib.*; + public class Test1 { + private void test(S obj) { + int i = switch (obj) { + case A a -> 0; + }; + Runnable r = () -> {obj = null;}; + } + } + """); + + Path classes1 = current.resolve("classes1"); + + Files.createDirectories(classes1); + + var log = + new JavacTask(tb) + .options("--enable-preview", + "-source", JAVA_VERSION, + "-XDrawDiagnostics", + "-Xlint:-preview", + "--class-path", libClasses.toString()) + .outdir(classes1) + .files(tb.findJavaFiles(src1)) + .run(Task.Expect.FAIL) + .writeAll() + .getOutputLines(Task.OutputKind.DIRECT); + + List expectedErrors = List.of( + "Test1.java:5:24: compiler.err.cant.access: lib.B1, (compiler.misc.class.file.not.found: lib.B1)", + "Test1.java:8:29: compiler.err.cant.ref.non.effectively.final.var: obj, (compiler.misc.lambda)", + "- compiler.note.preview.filename: Test1.java, DEFAULT", + "- compiler.note.preview.recompile", + "2 errors"); + + if (!expectedErrors.equals(log)) { + throw new AssertionError("Incorrect errors, expected: " + expectedErrors + + ", actual: " + log); + } + } + + { + Path src2 = current.resolve("src2"); + tb.writeJavaFiles(src2, + """ + package test; + import lib.*; + public class Test1 { + private void test(S obj) { + Runnable r = (Runnable) obj; + String s = (String) obj; + } + } + """); + + Path classes2 = current.resolve("classes2"); + + Files.createDirectories(classes2); + + var log = + new JavacTask(tb) + .options("--enable-preview", + "-source", JAVA_VERSION, + "-XDrawDiagnostics", + "-Xlint:-preview", + "--class-path", libClasses.toString()) + .outdir(classes2) + .files(tb.findJavaFiles(src2)) + .run(Task.Expect.FAIL) + .writeAll() + .getOutputLines(Task.OutputKind.DIRECT); + + List expectedErrors = List.of( + "Test1.java:5:19: compiler.err.cant.access: lib.B1, (compiler.misc.class.file.not.found: lib.B1)", + "Test1.java:6:26: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: lib.S, java.lang.String)", + "2 errors"); + + if (!expectedErrors.equals(log)) { + throw new AssertionError("Incorrect errors, expected: " + expectedErrors + + ", actual: " + log); + } + } + } + +} -- GitLab From 082fdf479367612a7bd795d3becfe9830db4b2d6 Mon Sep 17 00:00:00 2001 From: Prasanta Sadhukhan Date: Mon, 6 Dec 2021 16:08:28 +0000 Subject: [PATCH 007/671] 8172065: javax/swing/JTree/4908142/bug4908142.java The selected index should be "aad" Reviewed-by: aivanov --- test/jdk/javax/swing/JTree/4908142/bug4908142.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/test/jdk/javax/swing/JTree/4908142/bug4908142.java b/test/jdk/javax/swing/JTree/4908142/bug4908142.java index 671af8abd2d..784feda153d 100644 --- a/test/jdk/javax/swing/JTree/4908142/bug4908142.java +++ b/test/jdk/javax/swing/JTree/4908142/bug4908142.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2021, 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 @@ -60,6 +60,7 @@ public class bug4908142 { }); robot.waitForIdle(); + robot.delay(1000); SwingUtilities.invokeAndWait(new Runnable() { @@ -70,12 +71,14 @@ public class bug4908142 { }); robot.waitForIdle(); - + robot.delay(500); robot.keyPress(KeyEvent.VK_A); robot.keyRelease(KeyEvent.VK_A); + robot.waitForIdle(); robot.keyPress(KeyEvent.VK_A); robot.keyRelease(KeyEvent.VK_A); + robot.waitForIdle(); robot.keyPress(KeyEvent.VK_D); robot.keyRelease(KeyEvent.VK_D); robot.waitForIdle(); @@ -114,6 +117,7 @@ public class bug4908142 { JScrollPane sp = new JScrollPane(tree); fr.getContentPane().add(sp); + fr.setLocationRelativeTo(null); fr.setSize(200, 200); fr.setVisible(true); } -- GitLab From 587e5409c2488cf8c3579a4932c588efc5a02749 Mon Sep 17 00:00:00 2001 From: Chris Plummer Date: Mon, 6 Dec 2021 16:09:45 +0000 Subject: [PATCH 008/671] 8210558: serviceability/sa/TestJhsdbJstackLock.java fails to find '^\s+- waiting to lock <0x[0-9a-f]+> \(a java\.lang\.Class ...' Reviewed-by: kevinw, sspitsyn --- .../serviceability/sa/LingeredAppWithLock.java | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/test/hotspot/jtreg/serviceability/sa/LingeredAppWithLock.java b/test/hotspot/jtreg/serviceability/sa/LingeredAppWithLock.java index 9acf9d3bbb9..4140a3e3381 100644 --- a/test/hotspot/jtreg/serviceability/sa/LingeredAppWithLock.java +++ b/test/hotspot/jtreg/serviceability/sa/LingeredAppWithLock.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -47,6 +47,19 @@ public class LingeredAppWithLock extends LingeredApp { objectLock.start(); primitiveLock.start(); + // Wait until all threads have reached their blocked or timed wait state + while ((classLock1.getState() != Thread.State.BLOCKED && + classLock1.getState() != Thread.State.TIMED_WAITING) || + (classLock2.getState() != Thread.State.BLOCKED && + classLock2.getState() != Thread.State.TIMED_WAITING) || + (objectLock.getState() != Thread.State.TIMED_WAITING) || + (primitiveLock.getState() != Thread.State.TIMED_WAITING)) { + try { + Thread.sleep(100); + } catch (InterruptedException ex) { + } + } + LingeredApp.main(args); } } -- GitLab From 5045eb538b3afc6cf646642f1109473597b3004a Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Mon, 6 Dec 2021 16:56:27 +0000 Subject: [PATCH 009/671] 8278273: Remove unnecessary exclusion of doclint accessibility checks Reviewed-by: iris, alanb, ihse --- make/modules/java.base/Java.gmk | 4 ++-- make/modules/java.instrument/Java.gmk | 4 ++-- make/modules/java.logging/Java.gmk | 4 ++-- make/modules/java.management/Java.gmk | 4 ++-- make/modules/java.smartcardio/Java.gmk | 4 ++-- make/modules/java.sql.rowset/Java.gmk | 4 ++-- make/modules/java.xml/Java.gmk | 4 ++-- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/make/modules/java.base/Java.gmk b/make/modules/java.base/Java.gmk index 58d707e6148..b5bd86ada54 100644 --- a/make/modules/java.base/Java.gmk +++ b/make/modules/java.base/Java.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ # questions. # -DOCLINT += -Xdoclint:all/protected,-reference,-accessibility \ +DOCLINT += -Xdoclint:all/protected,-reference \ '-Xdoclint/package:java.*,javax.*' JAVAC_FLAGS += -XDstringConcat=inline COPY += .icu .dat .spp .nrm content-types.properties \ diff --git a/make/modules/java.instrument/Java.gmk b/make/modules/java.instrument/Java.gmk index 5f46b155e0c..f49e425718e 100644 --- a/make/modules/java.instrument/Java.gmk +++ b/make/modules/java.instrument/Java.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -23,5 +23,5 @@ # questions. # -DOCLINT += -Xdoclint:all/protected,-accessibility \ +DOCLINT += -Xdoclint:all/protected \ '-Xdoclint/package:java.*,javax.*' diff --git a/make/modules/java.logging/Java.gmk b/make/modules/java.logging/Java.gmk index 40da53d432b..a6641fc1485 100644 --- a/make/modules/java.logging/Java.gmk +++ b/make/modules/java.logging/Java.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -23,5 +23,5 @@ # questions. # -DOCLINT += -Xdoclint:all/protected,-reference,-accessibility \ +DOCLINT += -Xdoclint:all/protected,-reference \ '-Xdoclint/package:java.*,javax.*' diff --git a/make/modules/java.management/Java.gmk b/make/modules/java.management/Java.gmk index 40da53d432b..a6641fc1485 100644 --- a/make/modules/java.management/Java.gmk +++ b/make/modules/java.management/Java.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -23,5 +23,5 @@ # questions. # -DOCLINT += -Xdoclint:all/protected,-reference,-accessibility \ +DOCLINT += -Xdoclint:all/protected,-reference \ '-Xdoclint/package:java.*,javax.*' diff --git a/make/modules/java.smartcardio/Java.gmk b/make/modules/java.smartcardio/Java.gmk index 5f46b155e0c..f49e425718e 100644 --- a/make/modules/java.smartcardio/Java.gmk +++ b/make/modules/java.smartcardio/Java.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -23,5 +23,5 @@ # questions. # -DOCLINT += -Xdoclint:all/protected,-accessibility \ +DOCLINT += -Xdoclint:all/protected \ '-Xdoclint/package:java.*,javax.*' diff --git a/make/modules/java.sql.rowset/Java.gmk b/make/modules/java.sql.rowset/Java.gmk index 2ea5be28ed1..63437c6113f 100644 --- a/make/modules/java.sql.rowset/Java.gmk +++ b/make/modules/java.sql.rowset/Java.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ # questions. # -DOCLINT += -Xdoclint:all/protected,-accessibility \ +DOCLINT += -Xdoclint:all/protected \ '-Xdoclint/package:java.*,javax.*' CLEAN_FILES += $(wildcard \ $(TOPDIR)/src/java.sql.rowset/share/classes/com/sun/rowset/*.properties \ diff --git a/make/modules/java.xml/Java.gmk b/make/modules/java.xml/Java.gmk index b7bf8b70165..aa4b786020f 100644 --- a/make/modules/java.xml/Java.gmk +++ b/make/modules/java.xml/Java.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ # questions. # -DOCLINT += -Xdoclint:all/protected,-accessibility \ +DOCLINT += -Xdoclint:all/protected \ '-Xdoclint/package:$(call CommaList, javax.xml.catalog javax.xml.datatype \ javax.xml.transform javax.xml.validation javax.xml.xpath)' CLEAN += .properties -- GitLab From 70bad89b012eb200ca1e76f384a6e5fb307cf26d Mon Sep 17 00:00:00 2001 From: Artem Semenov Date: Mon, 6 Dec 2021 17:39:43 +0000 Subject: [PATCH 010/671] 8277497: Last column cell in the JTAble row is read as empty cell Reviewed-by: ant, kizune, pbansal --- .../share/classes/javax/swing/JLabel.java | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/java.desktop/share/classes/javax/swing/JLabel.java b/src/java.desktop/share/classes/javax/swing/JLabel.java index bb1db1fdfb8..8dff4a8fd25 100644 --- a/src/java.desktop/share/classes/javax/swing/JLabel.java +++ b/src/java.desktop/share/classes/javax/swing/JLabel.java @@ -1075,6 +1075,10 @@ public class JLabel extends JComponent implements SwingConstants, Accessible * @see AccessibleContext#setAccessibleName */ public String getAccessibleName() { + return getAccessibleNameCheckIcon(getAccessibleNameImpl()); + } + + private String getAccessibleNameImpl() { String name = accessibleName; if (name == null) { @@ -1089,6 +1093,19 @@ public class JLabel extends JComponent implements SwingConstants, Accessible return name; } + private String getAccessibleNameCheckIcon(String name) { + if (((name == null) || name.isEmpty()) && + (JLabel.this.getIcon() != null)) { + if (JLabel.this.getIcon() instanceof Accessible) { + AccessibleContext ac = ((Accessible) JLabel.this.getIcon()).getAccessibleContext(); + if (ac != null) { + name = ac.getAccessibleName(); + } + } + } + return name; + } + /** * Get the role of this object. * @@ -1097,6 +1114,11 @@ public class JLabel extends JComponent implements SwingConstants, Accessible * @see AccessibleRole */ public AccessibleRole getAccessibleRole() { + String name = getAccessibleNameImpl(); + if (((name == null) || name.isEmpty()) && + (JLabel.this.getIcon() != null)) { + return AccessibleRole.ICON; + } return AccessibleRole.LABEL; } -- GitLab From 2c31a1735d5b8646ed8984a5475d5c8c9c91c19d Mon Sep 17 00:00:00 2001 From: Weijun Wang Date: Mon, 6 Dec 2021 18:00:54 +0000 Subject: [PATCH 011/671] 8275082: Update XML Security for Java to 2.3.0 Reviewed-by: mullan --- .../apache/xml/internal/security/Init.java | 10 +- .../implementations/IntegrityHmac.java | 2 +- .../Canonicalizer20010315.java | 2 +- .../implementations/CanonicalizerBase.java | 6 +- .../CanonicalizerPhysical.java | 2 +- .../implementations/NameSpaceSymbTable.java | 2 +- .../XMLSecurityRuntimeException.java | 181 ------------------ .../keys/keyresolver/KeyResolver.java | 12 +- .../KeyInfoReferenceResolver.java | 3 +- .../xml/internal/security/resource/config.xml | 2 - .../resource/xmlsecurity_en.properties | 3 +- .../security/signature/XMLSignatureInput.java | 15 +- .../implementations/TransformC14N.java | 2 +- .../TransformC14NExclusive.java | 2 +- .../TransformEnvelopedSignature.java | 8 +- .../implementations/TransformXPath.java | 15 +- .../xml/internal/security/utils/Base64.java | 1 + .../security/utils/DOMNamespaceContext.java | 6 +- .../security/utils/RFC2253Parser.java | 114 +++++------ .../xml/internal/security/utils/XMLUtils.java | 2 +- .../utils/resolver/ResourceResolver.java | 13 +- .../resolver/ResourceResolverContext.java | 1 - .../implementations/ResolverDirectHTTP.java | 5 +- .../ResolverLocalFilesystem.java | 45 +---- .../internal/dom/ApacheCanonicalizer.java | 3 - .../xml/dsig/internal/dom/DOMReference.java | 2 +- .../xml/dsig/internal/dom/DOMTransform.java | 2 +- .../dsig/internal/dom/DOMURIDereferencer.java | 2 +- .../org/jcp/xml/dsig/internal/dom/Policy.java | 25 ++- .../org/jcp/xml/dsig/internal/dom/Utils.java | 2 +- .../jcp/xml/dsig/internal/dom/XMLDSigRI.java | 2 +- src/java.xml.crypto/share/legal/santuario.md | 2 +- 32 files changed, 141 insertions(+), 353 deletions(-) delete mode 100644 src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/exceptions/XMLSecurityRuntimeException.java diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/Init.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/Init.java index 4c51e7b5e83..a35a4699d82 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/Init.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/Init.java @@ -84,7 +84,7 @@ public class Init { } @SuppressWarnings("removal") - InputStream is = + InputStream is = //NOPMD AccessController.doPrivileged( (PrivilegedAction) () -> { @@ -351,6 +351,9 @@ public class Init { * @param callingClass The Class object of the calling object */ public static URL getResource(String resourceName, Class callingClass) { + if (resourceName == null) { + throw new NullPointerException(); + } URL url = Thread.currentThread().getContextClassLoader().getResource(resourceName); if (url == null && resourceName.charAt(0) == '/') { //certain classloaders need it without the leading / @@ -404,6 +407,9 @@ public class Init { * @param callingClass The Class object of the calling object */ private static List getResources(String resourceName, Class callingClass) { + if (resourceName == null) { + throw new NullPointerException(); + } List ret = new ArrayList<>(); Enumeration urls = new Enumeration() { public boolean hasMoreElements() { @@ -479,7 +485,7 @@ public class Init { } - if (ret.isEmpty() && resourceName != null && resourceName.charAt(0) != '/') { + if (ret.isEmpty() && resourceName.charAt(0) != '/') { return getResources('/' + resourceName, callingClass); } return ret; diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/IntegrityHmac.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/IntegrityHmac.java index 90302d47844..fdaf8643279 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/IntegrityHmac.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/IntegrityHmac.java @@ -309,7 +309,7 @@ public abstract class IntegrityHmac extends SignatureAlgorithmSpi { Node n = XMLUtils.selectDsNode(element.getFirstChild(), Constants._TAG_HMACOUTPUTLENGTH, 0); if (n != null) { String hmacLength = XMLUtils.getFullTextChildrenFromNode(n); - if (hmacLength != null && !"".equals(hmacLength)) { + if (hmacLength != null && hmacLength.length() != 0) { this.hmacOutputLength = new HMACOutputLength(Integer.parseInt(hmacLength)); } } diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/Canonicalizer20010315.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/Canonicalizer20010315.java index 1ed26fea60b..f0cd610b320 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/Canonicalizer20010315.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/Canonicalizer20010315.java @@ -125,7 +125,7 @@ public abstract class Canonicalizer20010315 extends CanonicalizerBase { * Output the Attr[]s for the given element. *
* The code of this method is a copy of - * {@link #outputAttributes(Element, NameSpaceSymbTable, Map)}, + * {@link #outputAttributes(Element, NameSpaceSymbTable, Map, OutputStream)}, * whereas it takes into account that subtree-c14n is -- well -- subtree-based. * So if the element in question isRoot of c14n, it's parent is not in the * node set, as well as all other ancestors. diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/CanonicalizerBase.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/CanonicalizerBase.java index d3b972c95f8..ce971a45a98 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/CanonicalizerBase.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/CanonicalizerBase.java @@ -211,7 +211,7 @@ public abstract class CanonicalizerBase extends CanonicalizerSpi { Node sibling = null; Node parentNode = null; Map cache = new HashMap<>(); - do { + do { //NOPMD switch (currentNode.getNodeType()) { case Node.ENTITY_NODE : @@ -338,7 +338,7 @@ public abstract class CanonicalizerBase extends CanonicalizerSpi { Node parentNode = null; int documentLevel = NODE_BEFORE_DOCUMENT_ELEMENT; Map cache = new HashMap<>(); - do { + do { //NOPMD switch (currentNode.getNodeType()) { case Node.ENTITY_NODE : @@ -560,7 +560,7 @@ public abstract class CanonicalizerBase extends CanonicalizerSpi { } parents.clear(); Attr nsprefix = ns.getMappingWithoutRendered(XMLNS); - if (nsprefix != null && "".equals(nsprefix.getValue())) { + if (nsprefix != null && nsprefix.getValue().length() == 0) { ns.addMappingAndRender( XMLNS, "", getNullNode(nsprefix.getOwnerDocument())); } diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/CanonicalizerPhysical.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/CanonicalizerPhysical.java index 4b2333938f5..66ad12029fc 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/CanonicalizerPhysical.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/CanonicalizerPhysical.java @@ -110,7 +110,7 @@ public class CanonicalizerPhysical extends CanonicalizerBase { * Output the Attr[]s for the given element. *
* The code of this method is a copy of - * {@link #outputAttributes(Element, NameSpaceSymbTable, Map)}, + * {@link #outputAttributes(Element, NameSpaceSymbTable, Map, OutputStream)}, * whereas it takes into account that subtree-c14n is -- well -- subtree-based. * So if the element in question isRoot of c14n, it's parent is not in the * node set, as well as all other ancestors. diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/NameSpaceSymbTable.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/NameSpaceSymbTable.java index 2fc853fe690..f0b1903accd 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/NameSpaceSymbTable.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/NameSpaceSymbTable.java @@ -348,7 +348,7 @@ class SymbMap implements Cloneable { List entrySet() { List a = new ArrayList<>(); for (int i = 0;i < entries.length;i++) { - if (entries[i] != null && !"".equals(entries[i].uri)) { + if (entries[i] != null && entries[i].uri.length() != 0) { a.add(entries[i]); } } diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/exceptions/XMLSecurityRuntimeException.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/exceptions/XMLSecurityRuntimeException.java deleted file mode 100644 index 7d17fe867e1..00000000000 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/exceptions/XMLSecurityRuntimeException.java +++ /dev/null @@ -1,181 +0,0 @@ -/* - * reserved comment block - * DO NOT REMOVE OR ALTER! - */ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package com.sun.org.apache.xml.internal.security.exceptions; - -import java.text.MessageFormat; - -import com.sun.org.apache.xml.internal.security.utils.Constants; -import com.sun.org.apache.xml.internal.security.utils.I18n; - -/** - * The mother of all runtime Exceptions in this bundle. It allows exceptions to have - * their messages translated to the different locales. - * - * The {@code xmlsecurity_en.properties} file contains this line: - *
- * xml.WrongElement = Can't create a {0} from a {1} element
- * 
- * - * Usage in the Java source is: - *
- * {
- *    Object[] exArgs = { Constants._TAG_TRANSFORMS, "BadElement" };
- *
- *    throw new XMLSecurityException("xml.WrongElement", exArgs);
- * }
- * 
- * - * Additionally, if another Exception has been caught, we can supply it, too - *
- * try {
- *    ...
- * } catch (Exception oldEx) {
- *    Object[] exArgs = { Constants._TAG_TRANSFORMS, "BadElement" };
- *
- *    throw new XMLSecurityException("xml.WrongElement", exArgs, oldEx);
- * }
- * 
- * - * - */ -public class XMLSecurityRuntimeException extends RuntimeException { - - private static final long serialVersionUID = 1L; - - /** Field msgID */ - protected String msgID; - - /** - * Constructor XMLSecurityRuntimeException - * - */ - public XMLSecurityRuntimeException() { - super("Missing message string"); - - this.msgID = null; - } - - /** - * Constructor XMLSecurityRuntimeException - * - * @param msgID - */ - public XMLSecurityRuntimeException(String msgID) { - super(I18n.getExceptionMessage(msgID)); - - this.msgID = msgID; - } - - /** - * Constructor XMLSecurityRuntimeException - * - * @param msgID - * @param exArgs - */ - public XMLSecurityRuntimeException(String msgID, Object[] exArgs) { - super(MessageFormat.format(I18n.getExceptionMessage(msgID), exArgs)); - - this.msgID = msgID; - } - - /** - * Constructor XMLSecurityRuntimeException - * - * @param originalException - */ - public XMLSecurityRuntimeException(Exception originalException) { - super("Missing message ID to locate message string in resource bundle \"" - + Constants.exceptionMessagesResourceBundleBase - + "\". Original Exception was a " - + originalException.getClass().getName() + " and message " - + originalException.getMessage(), originalException); - } - - /** - * Constructor XMLSecurityRuntimeException - * - * @param msgID - * @param originalException - */ - public XMLSecurityRuntimeException(String msgID, Exception originalException) { - super(I18n.getExceptionMessage(msgID, originalException), originalException); - - this.msgID = msgID; - } - - /** - * Constructor XMLSecurityRuntimeException - * - * @param msgID - * @param exArgs - * @param originalException - */ - public XMLSecurityRuntimeException(String msgID, Object[] exArgs, Exception originalException) { - super(MessageFormat.format(I18n.getExceptionMessage(msgID), exArgs), originalException); - - this.msgID = msgID; - } - - /** - * Method getMsgID - * - * @return the messageId - */ - public String getMsgID() { - if (msgID == null) { - return "Missing message ID"; - } - return msgID; - } - - /** {@inheritDoc} */ - public String toString() { - String s = this.getClass().getName(); - String message = super.getLocalizedMessage(); - - if (message != null) { - message = s + ": " + message; - } else { - message = s; - } - - if (this.getCause() != null) { - message = message + "\nOriginal Exception was " + this.getCause().toString(); - } - - return message; - } - - /** - * Method getOriginalException - * - * @return the original exception - */ - public Exception getOriginalException() { - if (this.getCause() instanceof Exception) { - return (Exception)this.getCause(); - } - return null; - } - -} diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/KeyResolver.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/KeyResolver.java index 7aa9a30128a..7445013e9cb 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/KeyResolver.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/KeyResolver.java @@ -170,8 +170,8 @@ public class KeyResolver { ClassNotFoundException, IllegalAccessException, InstantiationException, InvocationTargetException { JavaUtils.checkRegisterPermission(); - KeyResolverSpi keyResolverSpi = - (KeyResolverSpi) JavaUtils.newInstanceWithEmptyConstructor(ClassLoaderUtils.loadClass(className, KeyResolver.class)); + KeyResolverSpi keyResolverSpi = (KeyResolverSpi) + JavaUtils.newInstanceWithEmptyConstructor(ClassLoaderUtils.loadClass(className, KeyResolver.class)); register(keyResolverSpi, false); } @@ -193,8 +193,8 @@ public class KeyResolver { KeyResolverSpi keyResolverSpi = null; Exception ex = null; try { - keyResolverSpi = (KeyResolverSpi) JavaUtils.newInstanceWithEmptyConstructor( - ClassLoaderUtils.loadClass(className, KeyResolver.class)); + keyResolverSpi = (KeyResolverSpi) + JavaUtils.newInstanceWithEmptyConstructor(ClassLoaderUtils.loadClass(className, KeyResolver.class)); register(keyResolverSpi, true); } catch (ClassNotFoundException | IllegalAccessException | InstantiationException | InvocationTargetException e) { ex = e; @@ -253,8 +253,8 @@ public class KeyResolver { JavaUtils.checkRegisterPermission(); List keyResolverList = new ArrayList<>(classNames.size()); for (String className : classNames) { - KeyResolverSpi keyResolverSpi = (KeyResolverSpi)JavaUtils - .newInstanceWithEmptyConstructor(ClassLoaderUtils.loadClass(className, KeyResolver.class)); + KeyResolverSpi keyResolverSpi = (KeyResolverSpi) + JavaUtils.newInstanceWithEmptyConstructor(ClassLoaderUtils.loadClass(className, KeyResolver.class)); keyResolverList.add(keyResolverSpi); } resolverList.addAll(keyResolverList); diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/implementations/KeyInfoReferenceResolver.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/implementations/KeyInfoReferenceResolver.java index fb32875c1b1..101fd2d12a5 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/implementations/KeyInfoReferenceResolver.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/implementations/KeyInfoReferenceResolver.java @@ -162,6 +162,7 @@ public class KeyInfoReferenceResolver extends KeyResolverSpi { validateReference(referentElement, secureValidation); KeyInfo referent = new KeyInfo(referentElement, baseURI); + referent.setSecureValidation(secureValidation); referent.addStorageResolver(storage); return referent; } @@ -181,7 +182,7 @@ public class KeyInfoReferenceResolver extends KeyResolverSpi { } KeyInfo referent = new KeyInfo(referentElement, ""); - if (referent.containsKeyInfoReference()) { + if (referent.containsKeyInfoReference() || referent.containsRetrievalMethod()) { if (secureValidation) { throw new XMLSecurityException("KeyInfoReferenceResolver.InvalidReferentElement.ReferenceWithSecure"); } else { diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/resource/config.xml b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/resource/config.xml index 603d49e0ad5..bbd26a399ca 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/resource/config.xml +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/resource/config.xml @@ -96,8 +96,6 @@ - all his descendants in the output. + * method included the node and all its descendants in the output. * * @param rootNode */ @@ -528,7 +527,7 @@ public class XMLSignatureInput { if (inputOctetStreamProxy == null) { return null; } - try { + try { //NOPMD bytes = JavaUtils.getBytesFromStream(inputOctetStreamProxy); } finally { inputOctetStreamProxy.close(); @@ -539,15 +538,9 @@ public class XMLSignatureInput { /** * @param filter */ - public void addNodeFilter(NodeFilter filter) { + public void addNodeFilter(NodeFilter filter) throws XMLParserException, IOException { if (isOctetStream()) { - try { - convertToNodes(); - } catch (Exception e) { - throw new XMLSecurityRuntimeException( - "signature.XMLSignatureInput.nodesetReference", e - ); - } + convertToNodes(); } nodeFilters.add(filter); } diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/TransformC14N.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/TransformC14N.java index e0f9b4faa1e..6337bc2c201 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/TransformC14N.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/TransformC14N.java @@ -60,7 +60,7 @@ public class TransformC14N extends TransformSpi { Canonicalizer20010315 c14n = getCanonicalizer(); - if (os == null) { + if (os == null && (input.isOctetStream() || input.isElement() || input.isNodeSet())) { try (ByteArrayOutputStream writer = new ByteArrayOutputStream()) { c14n.engineCanonicalize(input, writer, secureValidation); writer.flush(); diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/TransformC14NExclusive.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/TransformC14NExclusive.java index 5393fa99ac3..eca648267e1 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/TransformC14NExclusive.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/TransformC14NExclusive.java @@ -82,7 +82,7 @@ public class TransformC14NExclusive extends TransformSpi { Canonicalizer20010315Excl c14n = getCanonicalizer(); - if (os == null) { + if (os == null && (input.isOctetStream() || input.isElement() || input.isNodeSet())) { try (ByteArrayOutputStream writer = new ByteArrayOutputStream()) { c14n.engineCanonicalize(input, inclusiveNamespaces, writer, secureValidation); writer.flush(); diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/TransformEnvelopedSignature.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/TransformEnvelopedSignature.java index 539590cc84c..030d7063cc3 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/TransformEnvelopedSignature.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/TransformEnvelopedSignature.java @@ -22,8 +22,10 @@ */ package com.sun.org.apache.xml.internal.security.transforms.implementations; +import java.io.IOException; import java.io.OutputStream; +import com.sun.org.apache.xml.internal.security.parser.XMLParserException; import com.sun.org.apache.xml.internal.security.signature.NodeFilter; import com.sun.org.apache.xml.internal.security.signature.XMLSignatureInput; import com.sun.org.apache.xml.internal.security.transforms.TransformSpi; @@ -71,7 +73,11 @@ public class TransformEnvelopedSignature extends TransformSpi { Node signatureElement = searchSignatureElement(transformElement); input.setExcludeNode(signatureElement); - input.addNodeFilter(new EnvelopedNodeFilter(signatureElement)); + try { + input.addNodeFilter(new EnvelopedNodeFilter(signatureElement)); + } catch (XMLParserException | IOException ex) { + throw new TransformationException(ex); + } return input; } diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/TransformXPath.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/TransformXPath.java index cdde27c6834..ca844c00682 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/TransformXPath.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/TransformXPath.java @@ -22,11 +22,12 @@ */ package com.sun.org.apache.xml.internal.security.transforms.implementations; +import java.io.IOException; import java.io.OutputStream; import javax.xml.transform.TransformerException; -import com.sun.org.apache.xml.internal.security.exceptions.XMLSecurityRuntimeException; +import com.sun.org.apache.xml.internal.security.parser.XMLParserException; import com.sun.org.apache.xml.internal.security.signature.NodeFilter; import com.sun.org.apache.xml.internal.security.signature.XMLSignatureInput; import com.sun.org.apache.xml.internal.security.transforms.TransformSpi; @@ -51,6 +52,9 @@ import org.w3c.dom.Node; */ public class TransformXPath extends TransformSpi { + private static final com.sun.org.slf4j.internal.Logger LOG = + com.sun.org.slf4j.internal.LoggerFactory.getLogger(TransformXPath.class); + /** * {@inheritDoc} */ @@ -102,7 +106,7 @@ public class TransformXPath extends TransformSpi { input.addNodeFilter(new XPathNodeFilter(xpathElement, xpathnode, str, xpathAPIInstance)); input.setNodeSet(true); return input; - } catch (DOMException ex) { + } catch (XMLParserException | IOException | DOMException ex) { throw new TransformationException(ex); } } @@ -144,11 +148,8 @@ public class TransformXPath extends TransformSpi { } return 0; } catch (TransformerException e) { - Object[] eArgs = {currentNode}; - throw new XMLSecurityRuntimeException("signature.Transform.node", eArgs, e); - } catch (Exception e) { - Object[] eArgs = {currentNode, currentNode.getNodeType()}; - throw new XMLSecurityRuntimeException("signature.Transform.nodeAndType",eArgs, e); + LOG.debug("Error evaluating XPath expression", e); + return 0; } } diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/Base64.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/Base64.java index d9d0e761468..0534fff3844 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/Base64.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/Base64.java @@ -43,6 +43,7 @@ import org.w3c.dom.Text; * @see com.sun.org.apache.xml.internal.security.transforms.implementations.TransformBase64Decode */ @Deprecated +@SuppressWarnings("PMD") public final class Base64 { /** Field BASE64DEFAULTLENGTH */ diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/DOMNamespaceContext.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/DOMNamespaceContext.java index 116e8688342..6a2f5d5af26 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/DOMNamespaceContext.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/DOMNamespaceContext.java @@ -127,11 +127,11 @@ public class DOMNamespaceContext implements NamespaceContext { return DEFAULT_NS_PREFIX; } } - if (namespaceURI == null) { + if (namespaceURI == null && context != null) { return context.lookupNamespaceURI(null) != null ? null : DEFAULT_NS_PREFIX; - } else if (namespaceURI.equals(XML_NS_URI)) { + } else if (XML_NS_URI.equals(namespaceURI)) { return XML_NS_PREFIX; - } else if (namespaceURI.equals(XMLNS_ATTRIBUTE_NS_URI)) { + } else if (XMLNS_ATTRIBUTE_NS_URI.equals(namespaceURI)) { return XMLNS_ATTRIBUTE; } return null; diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/RFC2253Parser.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/RFC2253Parser.java index 4574e35f76a..552d1330a3f 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/RFC2253Parser.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/RFC2253Parser.java @@ -190,20 +190,21 @@ public class RFC2253Parser { if (value.startsWith("\"")) { StringBuilder sb = new StringBuilder(); - StringReader sr = new StringReader(value.substring(1, value.length() - 1)); - int i = 0; - char c; + try (StringReader sr = new StringReader(value.substring(1, value.length() - 1))) { + int i = 0; + char c; - while ((i = sr.read()) > -1) { - c = (char) i; + while ((i = sr.read()) > -1) { + c = (char) i; - //the following char is defined at 4.Relationship with RFC1779 and LDAPv2 inrfc2253 - if (c == ',' || c == '=' || c == '+' || c == '<' - || c == '>' || c == '#' || c == ';') { - sb.append('\\'); - } + //the following char is defined at 4.Relationship with RFC1779 and LDAPv2 inrfc2253 + if (c == ',' || c == '=' || c == '+' || c == '<' + || c == '>' || c == '#' || c == ';') { + sb.append('\\'); + } - sb.append(c); + sb.append(c); + } } value = trim(sb.toString()); @@ -263,37 +264,38 @@ public class RFC2253Parser { */ static String changeLess32toRFC(String string) throws IOException { StringBuilder sb = new StringBuilder(); - StringReader sr = new StringReader(string); int i = 0; char c; - while ((i = sr.read()) > -1) { - c = (char) i; - - if (c == '\\') { - sb.append(c); - - char c1 = (char) sr.read(); - char c2 = (char) sr.read(); - - //65 (A) 97 (a) - if ((c1 >= 48 && c1 <= 57 || c1 >= 65 && c1 <= 70 || c1 >= 97 && c1 <= 102) - && (c2 >= 48 && c2 <= 57 - || c2 >= 65 && c2 <= 70 - || c2 >= 97 && c2 <= 102)) { - try { - char ch = (char) Byte.parseByte("" + c1 + c2, 16); + try (StringReader sr = new StringReader(string)) { + while ((i = sr.read()) > -1) { + c = (char) i; - sb.append(ch); - } catch (NumberFormatException ex) { - throw new IOException(ex); + if (c == '\\') { + sb.append(c); + + char c1 = (char) sr.read(); + char c2 = (char) sr.read(); + + //65 (A) 97 (a) + if ((c1 >= 48 && c1 <= 57 || c1 >= 65 && c1 <= 70 || c1 >= 97 && c1 <= 102) + && (c2 >= 48 && c2 <= 57 + || c2 >= 65 && c2 <= 70 + || c2 >= 97 && c2 <= 102)) { + try { + char ch = (char) Byte.parseByte("" + c1 + c2, 16); + + sb.append(ch); + } catch (NumberFormatException ex) { + throw new IOException(ex); + } + } else { + sb.append(c1); + sb.append(c2); } } else { - sb.append(c1); - sb.append(c2); + sb.append(c); } - } else { - sb.append(c); } } @@ -309,15 +311,16 @@ public class RFC2253Parser { */ static String changeLess32toXML(String string) throws IOException { StringBuilder sb = new StringBuilder(); - StringReader sr = new StringReader(string); int i = 0; - while ((i = sr.read()) > -1) { - if (i < 32) { - sb.append('\\'); - sb.append(Integer.toHexString(i)); - } else { - sb.append((char) i); + try (StringReader sr = new StringReader(string)) { + while ((i = sr.read()) > -1) { + if (i < 32) { + sb.append('\\'); + sb.append(Integer.toHexString(i)); + } else { + sb.append((char) i); + } } } @@ -333,28 +336,29 @@ public class RFC2253Parser { */ static String changeWStoXML(String string) throws IOException { StringBuilder sb = new StringBuilder(); - StringReader sr = new StringReader(string); int i = 0; char c; - while ((i = sr.read()) > -1) { - c = (char) i; + try (StringReader sr = new StringReader(string)) { + while ((i = sr.read()) > -1) { + c = (char) i; - if (c == '\\') { - char c1 = (char) sr.read(); + if (c == '\\') { + char c1 = (char) sr.read(); - if (c1 == ' ') { - sb.append('\\'); + if (c1 == ' ') { + sb.append('\\'); - String s = "20"; + String s = "20"; - sb.append(s); + sb.append(s); + } else { + sb.append('\\'); + sb.append(c1); + } } else { - sb.append('\\'); - sb.append(c1); + sb.append(c); } - } else { - sb.append(c); } } diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/XMLUtils.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/XMLUtils.java index 5eaeda3b5f0..446d640194e 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/XMLUtils.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/XMLUtils.java @@ -583,7 +583,7 @@ public final class XMLUtils { Node parent = null; Node sibling = null; final String namespaceNs = Constants.NamespaceSpecNS; - do { + do { //NOPMD switch (node.getNodeType()) { case Node.ELEMENT_NODE : Element element = (Element) node; diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/ResourceResolver.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/ResourceResolver.java index 1b3f2be87cb..42271aa0128 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/ResourceResolver.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/ResourceResolver.java @@ -122,8 +122,8 @@ public class ResourceResolver { List resourceResolversToAdd = new ArrayList<>(classNames.size()); for (String className : classNames) { - ResourceResolverSpi resourceResolverSpi = (ResourceResolverSpi)JavaUtils - .newInstanceWithEmptyConstructor(ClassLoaderUtils.loadClass(className, ResourceResolver.class)); + ResourceResolverSpi resourceResolverSpi = (ResourceResolverSpi) + JavaUtils.newInstanceWithEmptyConstructor(ClassLoaderUtils.loadClass(className, ResourceResolver.class)); resourceResolversToAdd.add(resourceResolverSpi); } resolverList.addAll(resourceResolversToAdd); @@ -159,15 +159,6 @@ public class ResourceResolver { LOG.debug("check resolvability by class {}", resolver.getClass().getName()); if (resolver.engineCanResolveURI(context)) { - // Check to see whether the Resolver is allowed - if (context.secureValidation - && (resolver instanceof ResolverLocalFilesystem - || resolver instanceof ResolverDirectHTTP)) { - Object[] exArgs = { resolver.getClass().getName() }; - throw new ResourceResolverException( - "signature.Reference.ForbiddenResolver", exArgs, context.uriToResolve, context.baseUri - ); - } return resolver.engineResolveURI(context); } } diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/ResourceResolverContext.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/ResourceResolverContext.java index 47d0dbb87a8..ef56d435dde 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/ResourceResolverContext.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/ResourceResolverContext.java @@ -54,5 +54,4 @@ public class ResourceResolverContext { public Map getProperties() { return properties; } - } diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/implementations/ResolverDirectHTTP.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/implementations/ResolverDirectHTTP.java index 955a42a01cf..c1f9e199fb2 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/implementations/ResolverDirectHTTP.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/implementations/ResolverDirectHTTP.java @@ -219,7 +219,8 @@ public class ResolverDirectHTTP extends ResourceResolverSpi { LOG.debug("I was asked whether I can resolve {}", context.uriToResolve); if (context.uriToResolve.startsWith("http:") || - context.baseUri != null && context.baseUri.startsWith("http:")) { + context.uriToResolve.startsWith("https:") || + context.baseUri != null && (context.baseUri.startsWith("http:") || context.baseUri.startsWith("https:"))) { LOG.debug("I state that I can resolve {}", context.uriToResolve); return true; } @@ -231,7 +232,7 @@ public class ResolverDirectHTTP extends ResourceResolverSpi { private static URI getNewURI(String uri, String baseURI) throws URISyntaxException { URI newUri = null; - if (baseURI == null || "".equals(baseURI)) { + if (baseURI == null || baseURI.length() == 0) { newUri = new URI(uri); } else { newUri = new URI(baseURI).resolve(uri); diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/implementations/ResolverLocalFilesystem.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/implementations/ResolverLocalFilesystem.java index 7e73ace1b2a..9d7e00bdbd6 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/implementations/ResolverLocalFilesystem.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/implementations/ResolverLocalFilesystem.java @@ -38,8 +38,6 @@ import com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverS */ public class ResolverLocalFilesystem extends ResourceResolverSpi { - private static final int FILE_URI_LENGTH = "file:/".length(); - private static final com.sun.org.slf4j.internal.Logger LOG = com.sun.org.slf4j.internal.LoggerFactory.getLogger(ResolverLocalFilesystem.class); @@ -53,9 +51,7 @@ public class ResolverLocalFilesystem extends ResourceResolverSpi { // calculate new URI URI uriNew = getNewURI(context.uriToResolve, context.baseUri); - String fileName = - ResolverLocalFilesystem.translateUriToFilename(uriNew.toString()); - InputStream inputStream = Files.newInputStream(Paths.get(fileName)); + InputStream inputStream = Files.newInputStream(Paths.get(uriNew)); //NOPMD XMLSignatureInput result = new XMLSignatureInput(inputStream); result.setSecureValidation(context.secureValidation); @@ -67,41 +63,6 @@ public class ResolverLocalFilesystem extends ResourceResolverSpi { } } - /** - * Method translateUriToFilename - * - * @param uri - * @return the string of the filename - */ - private static String translateUriToFilename(String uri) { - - String subStr = uri.substring(FILE_URI_LENGTH); - - if (subStr.indexOf("%20") > -1) { - int offset = 0; - int index = 0; - StringBuilder temp = new StringBuilder(subStr.length()); - do { - index = subStr.indexOf("%20",offset); - if (index == -1) { - temp.append(subStr.substring(offset)); - } else { - temp.append(subStr.substring(offset, index)); - temp.append(' '); - offset = index + 3; - } - } while(index != -1); - subStr = temp.toString(); - } - - if (subStr.charAt(1) == ':') { - // we're running M$ Windows, so this works fine - return subStr; - } - // we're running some UNIX, so we have to prepend a slash - return "/" + subStr; - } - /** * {@inheritDoc} */ @@ -111,7 +72,7 @@ public class ResolverLocalFilesystem extends ResourceResolverSpi { } if (context.uriToResolve.isEmpty() || context.uriToResolve.charAt(0) == '#' || - context.uriToResolve.startsWith("http:")) { + context.uriToResolve.startsWith("http:") || context.uriToResolve.startsWith("https:")) { return false; } @@ -133,7 +94,7 @@ public class ResolverLocalFilesystem extends ResourceResolverSpi { private static URI getNewURI(String uri, String baseURI) throws URISyntaxException { URI newUri = null; - if (baseURI == null || "".equals(baseURI)) { + if (baseURI == null || baseURI.length() == 0) { newUri = new URI(uri); } else { newUri = new URI(baseURI).resolve(uri); diff --git a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/ApacheCanonicalizer.java b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/ApacheCanonicalizer.java index bb279ecc728..7655866ad74 100644 --- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/ApacheCanonicalizer.java +++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/ApacheCanonicalizer.java @@ -239,9 +239,6 @@ public abstract class ApacheCanonicalizer extends TransformService { try { in = apacheTransform.performTransform(in, os, secVal); - if (!in.isNodeSet() && !in.isElement()) { - return null; - } if (in.isOctetStream()) { return new ApacheOctetStreamData(in); } else { diff --git a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMReference.java b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMReference.java index 0b63c5eba16..d278808ea05 100644 --- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMReference.java +++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMReference.java @@ -447,7 +447,7 @@ public final class DOMReference extends DOMStructure } Data data = dereferencedData; XMLSignatureInput xi = null; - try (OutputStream os = new UnsyncBufferedOutputStream(dos)) { + try (OutputStream os = new UnsyncBufferedOutputStream(dos)) { //NOPMD for (int i = 0, size = transforms.size(); i < size; i++) { DOMTransform transform = (DOMTransform)transforms.get(i); if (i < size - 1) { diff --git a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMTransform.java b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMTransform.java index a18b76e81f6..fd6a89229c4 100644 --- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMTransform.java +++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMTransform.java @@ -116,7 +116,7 @@ public class DOMTransform extends DOMStructure implements Transform { Document ownerDoc = DOMUtils.getOwnerDocument(parent); Element transformElem = null; - if (parent.getLocalName().equals("Transforms")) { + if ("Transforms".equals(parent.getLocalName())) { transformElem = DOMUtils.createElement(ownerDoc, "Transform", XMLSignature.XMLNS, dsPrefix); diff --git a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMURIDereferencer.java b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMURIDereferencer.java index 6b728e236cb..b7412738725 100644 --- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMURIDereferencer.java +++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMURIDereferencer.java @@ -138,7 +138,7 @@ public final class DOMURIDereferencer implements URIDereferencer { } try { - ResourceResolverContext resContext = new ResourceResolverContext(uriAttr, baseURI, false); + ResourceResolverContext resContext = new ResourceResolverContext(uriAttr, baseURI, secVal); XMLSignatureInput in = ResourceResolver.resolve(resContext); if (in.isOctetStream()) { return new ApacheOctetStreamData(in); diff --git a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/Policy.java b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/Policy.java index f32cf39fd62..fffca6b38f5 100644 --- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/Policy.java +++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/Policy.java @@ -43,14 +43,13 @@ import java.util.Set; */ public final class Policy { - // all restrictions are initialized to be unconstrained - private static Set disallowedAlgs = new HashSet<>(); - private static int maxTrans = Integer.MAX_VALUE; - private static int maxRefs = Integer.MAX_VALUE; - private static Set disallowedRefUriSchemes = new HashSet<>(); - private static Map minKeyMap = new HashMap<>(); - private static boolean noDuplicateIds = false; - private static boolean noRMLoops = false; + private static Set disallowedAlgs; + private static int maxTrans; + private static int maxRefs; + private static Set disallowedRefUriSchemes; + private static Map minKeyMap; + private static boolean noDuplicateIds; + private static boolean noRMLoops; static { try { @@ -64,6 +63,16 @@ public final class Policy { private Policy() {} private static void initialize() { + // First initialized to be unconstrained and then parse the + // security property "jdk.xml.dsig.secureValidationPolicy" + disallowedAlgs = new HashSet<>(); + maxTrans = Integer.MAX_VALUE; + maxRefs = Integer.MAX_VALUE; + disallowedRefUriSchemes = new HashSet<>(); + minKeyMap = new HashMap<>(); + noDuplicateIds = false; + noRMLoops = false; + @SuppressWarnings("removal") String prop = AccessController.doPrivileged((PrivilegedAction) () -> diff --git a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/Utils.java b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/Utils.java index 0edb5dd5aff..72c34c647ba 100644 --- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/Utils.java +++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/Utils.java @@ -114,7 +114,7 @@ public final class Utils { } private static boolean getBoolean(XMLCryptoContext xc, String name) { - Boolean value = (Boolean)xc.getProperty(name); + Boolean value = (Boolean) xc.getProperty(name); return value != null && value; } } diff --git a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/XMLDSigRI.java b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/XMLDSigRI.java index f26b6d9940b..65bb25f058f 100644 --- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/XMLDSigRI.java +++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/XMLDSigRI.java @@ -134,7 +134,7 @@ public final class XMLDSigRI extends Provider { @SuppressWarnings("removal") public XMLDSigRI() { // This is the JDK XMLDSig provider, synced from - // Apache Santuario XML Security for Java, version 2.2.1 + // Apache Santuario XML Security for Java, version 2.3.0 super("XMLDSig", VER, INFO); final Provider p = this; diff --git a/src/java.xml.crypto/share/legal/santuario.md b/src/java.xml.crypto/share/legal/santuario.md index eba3a79e3e9..fa87128126d 100644 --- a/src/java.xml.crypto/share/legal/santuario.md +++ b/src/java.xml.crypto/share/legal/santuario.md @@ -1,4 +1,4 @@ -## Apache Santuario v2.2.1 +## Apache Santuario v2.3.0 ### Apache Santuario Notice
-- 
GitLab


From 239362da51e70b9e968cb488b7c2ec9d91c32837 Mon Sep 17 00:00:00 2001
From: ANUPAM DEV 
Date: Mon, 6 Dec 2021 18:46:29 +0000
Subject: [PATCH 012/671] 8247973: Javadoc incorrect for IdentityArrayList,
 IdentityLinkedList

Reviewed-by: aivanov, prr
---
 .../sun/awt/util/IdentityArrayList.java       | 20 +++++++++++++------
 .../sun/awt/util/IdentityLinkedList.java      | 10 +++++-----
 2 files changed, 19 insertions(+), 11 deletions(-)

diff --git a/src/java.desktop/share/classes/sun/awt/util/IdentityArrayList.java b/src/java.desktop/share/classes/sun/awt/util/IdentityArrayList.java
index 8f1bbdc4714..98f93cc3ec7 100644
--- a/src/java.desktop/share/classes/sun/awt/util/IdentityArrayList.java
+++ b/src/java.desktop/share/classes/sun/awt/util/IdentityArrayList.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2021, 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
@@ -203,7 +203,7 @@ public class IdentityArrayList extends AbstractList
      * Returns {@code true} if this list contains the specified element.
      * More formally, returns {@code true} if and only if this list contains
      * at least one element {@code e} such that
-     * {@code Objects.equals(o, e)}.
+     * {@code o == e}.
      *
      * @param o element whose presence in this list is to be tested
      * @return {@code true} if this list contains the specified element
@@ -216,8 +216,12 @@ public class IdentityArrayList extends AbstractList
      * Returns the index of the first occurrence of the specified element
      * in this list, or -1 if this list does not contain the element.
      * More formally, returns the lowest index {@code i} such that
-     * {@code Objects.equals(o, get(i))},
+     * {@code get(i) == o},
      * or -1 if there is no such index.
+     *
+     * @param o element to search for
+     * @return the index of the first occurrence of the specified element in
+     *         this list, or -1 if this list does not contain the element
      */
     public int indexOf(Object o) {
         for (int i = 0; i < size; i++) {
@@ -232,8 +236,12 @@ public class IdentityArrayList extends AbstractList
      * Returns the index of the last occurrence of the specified element
      * in this list, or -1 if this list does not contain the element.
      * More formally, returns the highest index {@code i} such that
-     * {@code Objects.equals(o, get(i))},
+     * {@code get(i) == o},
      * or -1 if there is no such index.
+     *
+     * @param o element to search for
+     * @return the index of the last occurrence of the specified element in
+     *         this list, or -1 if this list does not contain the element
      */
     public int lastIndexOf(Object o) {
         for (int i = size-1; i >= 0; i--) {
@@ -390,9 +398,9 @@ public class IdentityArrayList extends AbstractList
 
     /**
      * Removes the first occurrence of the specified element from this list,
-     * if it is present.  If the list does not contain the element, it is
+     * if it is present.  If this list does not contain the element, the list is
      * unchanged.  More formally, removes the element with the lowest index
-     * {@code i} such that {@code Objects.equals(o, get(i))}
+     * {@code i} such that {@code get(i) == o}
      * (if such an element exists).  Returns {@code true} if this list
      * contained the specified element (or equivalently, if this list
      * changed as a result of the call).
diff --git a/src/java.desktop/share/classes/sun/awt/util/IdentityLinkedList.java b/src/java.desktop/share/classes/sun/awt/util/IdentityLinkedList.java
index 21474bafcfd..fef09665bc0 100644
--- a/src/java.desktop/share/classes/sun/awt/util/IdentityLinkedList.java
+++ b/src/java.desktop/share/classes/sun/awt/util/IdentityLinkedList.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2021, 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
@@ -183,7 +183,7 @@ public class IdentityLinkedList
      * Returns {@code true} if this list contains the specified element.
      * More formally, returns {@code true} if and only if this list contains
      * at least one element {@code e} such that
-     * {@code Objects.equals(o, e)}.
+     * {@code o == e}.
      *
      * @param o element whose presence in this list is to be tested
      * @return {@code true} if this list contains the specified element
@@ -218,7 +218,7 @@ public class IdentityLinkedList
      * Removes the first occurrence of the specified element from this list,
      * if it is present.  If this list does not contain the element, it is
      * unchanged.  More formally, removes the element with the lowest index
-     * {@code i} such that {@code get(i)==o}
+     * {@code i} such that {@code get(i) == o}
      * (if such an element exists).  Returns {@code true} if this list
      * contained the specified element (or equivalently, if this list
      * changed as a result of the call).
@@ -389,7 +389,7 @@ public class IdentityLinkedList
      * Returns the index of the first occurrence of the specified element
      * in this list, or -1 if this list does not contain the element.
      * More formally, returns the lowest index {@code i} such that
-     * {@code get(i)==o},
+     * {@code get(i) == o},
      * or -1 if there is no such index.
      *
      * @param o element to search for
@@ -411,7 +411,7 @@ public class IdentityLinkedList
      * Returns the index of the last occurrence of the specified element
      * in this list, or -1 if this list does not contain the element.
      * More formally, returns the highest index {@code i} such that
-     * {@code get(i)==o},
+     * {@code get(i) == o},
      * or -1 if there is no such index.
      *
      * @param o element to search for
-- 
GitLab


From ea8d3c92c69c393cdbc6c62398f1e9c6adc708d3 Mon Sep 17 00:00:00 2001
From: Martin Balao 
Date: Mon, 6 Dec 2021 20:31:55 +0000
Subject: [PATCH 013/671] 8271566: DSA signature length value is not accurate
 in P11Signature

Reviewed-by: valeriep
---
 .../classes/sun/security/pkcs11/P11Key.java   | 742 +++++++++++-------
 .../sun/security/pkcs11/P11Signature.java     |  35 +-
 .../pkcs11/Signature/LargeDSAKey.java         |  98 +++
 3 files changed, 568 insertions(+), 307 deletions(-)
 create mode 100644 test/jdk/sun/security/pkcs11/Signature/LargeDSAKey.java

diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Key.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Key.java
index 638bd208aa6..bf0c5f2ba84 100644
--- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Key.java
+++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Key.java
@@ -115,7 +115,7 @@ abstract class P11Key implements Key, Length {
     }
 
     P11Key(String type, Session session, long keyID, String algorithm,
-            int keyLength, CK_ATTRIBUTE[] attributes) {
+            int keyLength, CK_ATTRIBUTE[] attrs) {
         this.type = type;
         this.token = session.token;
         this.algorithm = algorithm;
@@ -123,15 +123,15 @@ abstract class P11Key implements Key, Length {
         boolean tokenObject = false;
         boolean sensitive = false;
         boolean extractable = true;
-        int n = (attributes == null) ? 0 : attributes.length;
-        for (int i = 0; i < n; i++) {
-            CK_ATTRIBUTE attr = attributes[i];
-            if (attr.type == CKA_TOKEN) {
-                tokenObject = attr.getBoolean();
-            } else if (attr.type == CKA_SENSITIVE) {
-                sensitive = attr.getBoolean();
-            } else if (attr.type == CKA_EXTRACTABLE) {
-                extractable = attr.getBoolean();
+        if (attrs != null) {
+            for (CK_ATTRIBUTE attr : attrs) {
+                if (attr.type == CKA_TOKEN) {
+                    tokenObject = attr.getBoolean();
+                } else if (attr.type == CKA_SENSITIVE) {
+                    sensitive = attr.getBoolean();
+                } else if (attr.type == CKA_EXTRACTABLE) {
+                    extractable = attr.getBoolean();
+                }
             }
         }
         this.tokenObject = tokenObject;
@@ -247,7 +247,7 @@ abstract class P11Key implements Key, Length {
     public String toString() {
         token.ensureValid();
         String s1 = token.provider.getName() + " " + algorithm + " " + type
-                + " key, " + keyLength + " bits";
+                + " key, " + keyLength + " bits ";
         s1 += (tokenObject ? "token" : "session") + " object";
         if (isPublic()) {
             s1 += ")";
@@ -278,19 +278,31 @@ abstract class P11Key implements Key, Length {
         return type == SECRET;
     }
 
-    void fetchAttributes(CK_ATTRIBUTE[] attributes) {
+    CK_ATTRIBUTE[] fetchAttributes(CK_ATTRIBUTE[] attrs) {
+        Objects.requireNonNull(attrs, "attrs must be non-null");
         Session tempSession = null;
         long keyID = this.getKeyID();
         try {
             tempSession = token.getOpSession();
             token.p11.C_GetAttributeValue(tempSession.id(), keyID,
-                        attributes);
+                    attrs);
         } catch (PKCS11Exception e) {
             throw new ProviderException(e);
         } finally {
             this.releaseKeyID();
             token.releaseSession(tempSession);
         }
+        return attrs;
+    }
+
+    // convenience method which returns the attribute values as BigInteger[]
+    BigInteger[] fetchAttributesAsInts(CK_ATTRIBUTE[] attrs) {
+        attrs = fetchAttributes(attrs);
+        BigInteger[] res = new BigInteger[attrs.length];
+        for (int i = 0; i < attrs.length; i++) {
+            res[i] = attrs[i].getBigInteger();
+        }
+        return res;
     }
 
     private static final CK_ATTRIBUTE[] A0 = new CK_ATTRIBUTE[0];
@@ -329,44 +341,43 @@ abstract class P11Key implements Key, Length {
     }
 
     static SecretKey secretKey(Session session, long keyID, String algorithm,
-            int keyLength, CK_ATTRIBUTE[] attributes) {
-        attributes = getAttributes(session, keyID, attributes, new CK_ATTRIBUTE[] {
-            new CK_ATTRIBUTE(CKA_TOKEN),
-            new CK_ATTRIBUTE(CKA_SENSITIVE),
-            new CK_ATTRIBUTE(CKA_EXTRACTABLE),
+            int keyLength, CK_ATTRIBUTE[] attrs) {
+        attrs = getAttributes(session, keyID, attrs, new CK_ATTRIBUTE[] {
+                    new CK_ATTRIBUTE(CKA_TOKEN),
+                    new CK_ATTRIBUTE(CKA_SENSITIVE),
+                    new CK_ATTRIBUTE(CKA_EXTRACTABLE),
         });
-        return new P11SecretKey(session, keyID, algorithm, keyLength,
-                attributes);
+        return new P11SecretKey(session, keyID, algorithm, keyLength, attrs);
     }
 
-    static SecretKey masterSecretKey(Session session, long keyID, String algorithm,
-            int keyLength, CK_ATTRIBUTE[] attributes, int major, int minor) {
-        attributes = getAttributes(session, keyID, attributes, new CK_ATTRIBUTE[] {
-            new CK_ATTRIBUTE(CKA_TOKEN),
-            new CK_ATTRIBUTE(CKA_SENSITIVE),
-            new CK_ATTRIBUTE(CKA_EXTRACTABLE),
+    static SecretKey masterSecretKey(Session session, long keyID,
+            String algorithm, int keyLength, CK_ATTRIBUTE[] attrs,
+            int major, int minor) {
+        attrs = getAttributes(session, keyID, attrs, new CK_ATTRIBUTE[] {
+                    new CK_ATTRIBUTE(CKA_TOKEN),
+                    new CK_ATTRIBUTE(CKA_SENSITIVE),
+                    new CK_ATTRIBUTE(CKA_EXTRACTABLE),
         });
-        return new P11TlsMasterSecretKey(
-                session, keyID, algorithm, keyLength, attributes, major,
-                minor);
+        return new P11TlsMasterSecretKey(session, keyID, algorithm, keyLength,
+                attrs, major, minor);
     }
 
     // we assume that all components of public keys are always accessible
     static PublicKey publicKey(Session session, long keyID, String algorithm,
-            int keyLength, CK_ATTRIBUTE[] attributes) {
+            int keyLength, CK_ATTRIBUTE[] attrs) {
         switch (algorithm) {
             case "RSA":
                 return new P11RSAPublicKey(session, keyID, algorithm,
-                        keyLength, attributes);
+                        keyLength, attrs);
             case "DSA":
                 return new P11DSAPublicKey(session, keyID, algorithm,
-                        keyLength, attributes);
+                        keyLength, attrs);
             case "DH":
                 return new P11DHPublicKey(session, keyID, algorithm,
-                        keyLength, attributes);
+                        keyLength, attrs);
             case "EC":
                 return new P11ECPublicKey(session, keyID, algorithm,
-                        keyLength, attributes);
+                        keyLength, attrs);
             default:
                 throw new ProviderException
                     ("Unknown public key algorithm " + algorithm);
@@ -374,73 +385,45 @@ abstract class P11Key implements Key, Length {
     }
 
     static PrivateKey privateKey(Session session, long keyID, String algorithm,
-            int keyLength, CK_ATTRIBUTE[] attributes) {
-        attributes = getAttributes(session, keyID, attributes, new CK_ATTRIBUTE[] {
-            new CK_ATTRIBUTE(CKA_TOKEN),
-            new CK_ATTRIBUTE(CKA_SENSITIVE),
-            new CK_ATTRIBUTE(CKA_EXTRACTABLE),
+            int keyLength, CK_ATTRIBUTE[] attrs) {
+        attrs = getAttributes(session, keyID, attrs, new CK_ATTRIBUTE[] {
+                    new CK_ATTRIBUTE(CKA_TOKEN),
+                    new CK_ATTRIBUTE(CKA_SENSITIVE),
+                    new CK_ATTRIBUTE(CKA_EXTRACTABLE),
         });
-        if (attributes[1].getBoolean() || (attributes[2].getBoolean() == false)) {
-            return new P11PrivateKey
-                (session, keyID, algorithm, keyLength, attributes);
-        } else {
-            switch (algorithm) {
-                case "RSA":
-                    // In order to decide if this is RSA CRT key, we first query
-                    // and see if all extra CRT attributes are available.
-                    CK_ATTRIBUTE[] attrs2 = new CK_ATTRIBUTE[] {
-                        new CK_ATTRIBUTE(CKA_PUBLIC_EXPONENT),
-                        new CK_ATTRIBUTE(CKA_PRIME_1),
-                        new CK_ATTRIBUTE(CKA_PRIME_2),
-                        new CK_ATTRIBUTE(CKA_EXPONENT_1),
-                        new CK_ATTRIBUTE(CKA_EXPONENT_2),
-                        new CK_ATTRIBUTE(CKA_COEFFICIENT),
-                    };
-                    boolean crtKey;
-                    try {
-                        session.token.p11.C_GetAttributeValue
-                            (session.id(), keyID, attrs2);
-                        crtKey = ((attrs2[0].pValue instanceof byte[]) &&
-                                  (attrs2[1].pValue instanceof byte[]) &&
-                                  (attrs2[2].pValue instanceof byte[]) &&
-                                  (attrs2[3].pValue instanceof byte[]) &&
-                                  (attrs2[4].pValue instanceof byte[]) &&
-                                  (attrs2[5].pValue instanceof byte[])) ;
-                    } catch (PKCS11Exception e) {
-                        // ignore, assume not available
-                        crtKey = false;
-                    }
-                    if (crtKey) {
-                        return new P11RSAPrivateKey(session, keyID, algorithm,
-                                keyLength, attributes, attrs2);
-                    } else {
-                        return new P11RSAPrivateNonCRTKey(session, keyID,
-                                algorithm, keyLength, attributes);
-                    }
-                case "DSA":
-                    return new P11DSAPrivateKey(session, keyID, algorithm,
-                            keyLength, attributes);
-                case "DH":
-                    return new P11DHPrivateKey(session, keyID, algorithm,
-                            keyLength, attributes);
-                case "EC":
-                    return new P11ECPrivateKey(session, keyID, algorithm,
-                            keyLength, attributes);
-                default:
-                    throw new ProviderException
-                            ("Unknown private key algorithm " + algorithm);
-            }
+
+        boolean keySensitive = (attrs[0].getBoolean() ||
+                attrs[1].getBoolean() || !attrs[2].getBoolean());
+
+        switch (algorithm) {
+        case "RSA":
+            return P11RSAPrivateKeyInternal.of(session, keyID, algorithm,
+                    keyLength, attrs, keySensitive);
+        case "DSA":
+            return P11DSAPrivateKeyInternal.of(session, keyID, algorithm,
+                    keyLength, attrs, keySensitive);
+        case "DH":
+            return P11DHPrivateKeyInternal.of(session, keyID, algorithm,
+                    keyLength, attrs, keySensitive);
+        case "EC":
+            return P11ECPrivateKeyInternal.of(session, keyID, algorithm,
+                    keyLength, attrs, keySensitive);
+        default:
+            throw new ProviderException
+                    ("Unknown private key algorithm " + algorithm);
         }
     }
 
-    // class for sensitive and unextractable private keys
-    private static final class P11PrivateKey extends P11Key
-                                                implements PrivateKey {
+    // base class for all PKCS11 private keys
+    private static abstract class P11PrivateKey extends P11Key implements
+            PrivateKey {
         private static final long serialVersionUID = -2138581185214187615L;
 
+        protected byte[] encoded; // guard by synchronized
+
         P11PrivateKey(Session session, long keyID, String algorithm,
-                int keyLength, CK_ATTRIBUTE[] attributes) {
-            super(PRIVATE, session, keyID, algorithm, keyLength, attributes);
+                int keyLength, CK_ATTRIBUTE[] attrs) {
+            super(PRIVATE, session, keyID, algorithm, keyLength, attrs);
         }
         // XXX temporary encoding for serialization purposes
         public String getFormat() {
@@ -455,11 +438,14 @@ abstract class P11Key implements Key, Length {
 
     private static class P11SecretKey extends P11Key implements SecretKey {
         private static final long serialVersionUID = -7828241727014329084L;
-        private volatile byte[] encoded;
+
+        private volatile byte[] encoded; // guard by double-checked locking
+
         P11SecretKey(Session session, long keyID, String algorithm,
-                int keyLength, CK_ATTRIBUTE[] attributes) {
-            super(SECRET, session, keyID, algorithm, keyLength, attributes);
+                int keyLength, CK_ATTRIBUTE[] attrs) {
+            super(SECRET, session, keyID, algorithm, keyLength, attrs);
         }
+
         public String getFormat() {
             token.ensureValid();
             if (sensitive || (extractable == false)) {
@@ -468,32 +454,21 @@ abstract class P11Key implements Key, Length {
                 return "RAW";
             }
         }
+
         byte[] getEncodedInternal() {
             token.ensureValid();
             if (getFormat() == null) {
                 return null;
             }
+
             byte[] b = encoded;
             if (b == null) {
                 synchronized (this) {
                     b = encoded;
                     if (b == null) {
-                        Session tempSession = null;
-                        long keyID = this.getKeyID();
-                        try {
-                            tempSession = token.getOpSession();
-                            CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
+                        b = fetchAttributes(new CK_ATTRIBUTE[] {
                                 new CK_ATTRIBUTE(CKA_VALUE),
-                            };
-                            token.p11.C_GetAttributeValue
-                                    (tempSession.id(), keyID, attributes);
-                            b = attributes[0].getByteArray();
-                        } catch (PKCS11Exception e) {
-                            throw new ProviderException(e);
-                        } finally {
-                            this.releaseKeyID();
-                            token.releaseSession(tempSession);
-                        }
+                        })[0].getByteArray();
                         encoded = b;
                     }
                 }
@@ -502,6 +477,19 @@ abstract class P11Key implements Key, Length {
         }
     }
 
+    // base class for all PKCS11 public keys
+    private static abstract class P11PublicKey extends P11Key implements
+            PublicKey {
+        private static final long serialVersionUID = 1L;
+
+        protected byte[] encoded; // guard by synchronized
+
+        P11PublicKey(Session session, long keyID, String algorithm,
+                int keyLength, CK_ATTRIBUTE[] attrs) {
+            super(PUBLIC, session, keyID, algorithm, keyLength, attrs);
+        }
+    }
+
     @SuppressWarnings("deprecation")
     private static class P11TlsMasterSecretKey extends P11SecretKey
             implements TlsMasterSecret {
@@ -509,8 +497,8 @@ abstract class P11Key implements Key, Length {
 
         private final int majorVersion, minorVersion;
         P11TlsMasterSecretKey(Session session, long keyID, String algorithm,
-                int keyLength, CK_ATTRIBUTE[] attributes, int major, int minor) {
-            super(session, keyID, algorithm, keyLength, attributes);
+                int keyLength, CK_ATTRIBUTE[] attrs, int major, int minor) {
+            super(session, keyID, algorithm, keyLength, attrs);
             this.majorVersion = major;
             this.minorVersion = minor;
         }
@@ -523,17 +511,92 @@ abstract class P11Key implements Key, Length {
         }
     }
 
+    // impl class for sensitive/unextractable RSA private keys
+    static class P11RSAPrivateKeyInternal extends P11PrivateKey {
+        private static final long serialVersionUID = -2138581185214187615L;
+
+        static P11RSAPrivateKeyInternal of(Session session, long keyID,
+                String algorithm, int keyLength, CK_ATTRIBUTE[] attrs,
+                boolean keySensitive) {
+            if (keySensitive) {
+                return new P11RSAPrivateKeyInternal(session, keyID, algorithm,
+                        keyLength, attrs);
+            } else {
+                CK_ATTRIBUTE[] rsaAttrs = new CK_ATTRIBUTE[] {
+                        new CK_ATTRIBUTE(CKA_MODULUS),
+                        new CK_ATTRIBUTE(CKA_PRIVATE_EXPONENT),
+                        new CK_ATTRIBUTE(CKA_PUBLIC_EXPONENT),
+                        new CK_ATTRIBUTE(CKA_PRIME_1),
+                        new CK_ATTRIBUTE(CKA_PRIME_2),
+                        new CK_ATTRIBUTE(CKA_EXPONENT_1),
+                        new CK_ATTRIBUTE(CKA_EXPONENT_2),
+                        new CK_ATTRIBUTE(CKA_COEFFICIENT),
+                };
+                boolean isCRT = true;
+                Session tempSession = null;
+                try {
+                    tempSession = session.token.getOpSession();
+                    session.token.p11.C_GetAttributeValue(tempSession.id(),
+                            keyID, rsaAttrs);
+                    for (CK_ATTRIBUTE attr : rsaAttrs) {
+                        isCRT &= (attr.pValue instanceof byte[]);
+                        if (!isCRT) break;
+                    }
+                } catch (PKCS11Exception e) {
+                    // ignore, assume not available
+                    isCRT = false;
+                } finally {
+                    session.token.releaseSession(tempSession);
+                }
+                BigInteger n = rsaAttrs[0].getBigInteger();
+                BigInteger d = rsaAttrs[1].getBigInteger();
+                if (isCRT) {
+                    return new P11RSAPrivateKey(session, keyID, algorithm,
+                           keyLength, attrs, n, d,
+                           Arrays.copyOfRange(rsaAttrs, 2, rsaAttrs.length));
+                } else {
+                    return new P11RSAPrivateNonCRTKey(session, keyID,
+                           algorithm, keyLength, attrs, n, d);
+                }
+            }
+        }
+
+        protected transient BigInteger n;
+
+        private P11RSAPrivateKeyInternal(Session session, long keyID,
+                String algorithm, int keyLength, CK_ATTRIBUTE[] attrs) {
+            super(session, keyID, algorithm, keyLength, attrs);
+        }
+
+        private synchronized void fetchValues() {
+            token.ensureValid();
+            if (n != null) return;
+
+            n = fetchAttributesAsInts(new CK_ATTRIBUTE[] {
+                    new CK_ATTRIBUTE(CKA_MODULUS)
+            })[0];
+        }
+
+        public BigInteger getModulus() {
+            fetchValues();
+            return n;
+        }
+    }
+
     // RSA CRT private key
-    private static final class P11RSAPrivateKey extends P11Key
-                implements RSAPrivateCrtKey {
+    private static final class P11RSAPrivateKey extends P11RSAPrivateKeyInternal
+            implements RSAPrivateCrtKey {
         private static final long serialVersionUID = 9215872438913515220L;
 
-        private BigInteger n, e, d, p, q, pe, qe, coeff;
-        private byte[] encoded;
-        P11RSAPrivateKey(Session session, long keyID, String algorithm,
-                int keyLength, CK_ATTRIBUTE[] attrs, CK_ATTRIBUTE[] crtAttrs) {
-            super(PRIVATE, session, keyID, algorithm, keyLength, attrs);
+        private transient BigInteger e, d, p, q, pe, qe, coeff;
+
+        private P11RSAPrivateKey(Session session, long keyID, String algorithm,
+                int keyLength, CK_ATTRIBUTE[] attrs, BigInteger n, BigInteger d,
+                CK_ATTRIBUTE[] crtAttrs) {
+            super(session, keyID, algorithm, keyLength, attrs);
 
+            this.n = n;
+            this.d = d;
             for (CK_ATTRIBUTE a : crtAttrs) {
                 if (a.type == CKA_PUBLIC_EXPONENT) {
                     e = a.getBigInteger();
@@ -550,28 +613,15 @@ abstract class P11Key implements Key, Length {
                 }
             }
         }
-        private synchronized void fetchValues() {
-            token.ensureValid();
-            if (n != null) {
-                return;
-            }
-            CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
-                new CK_ATTRIBUTE(CKA_MODULUS),
-                new CK_ATTRIBUTE(CKA_PRIVATE_EXPONENT),
-            };
-            fetchAttributes(attributes);
-            n = attributes[0].getBigInteger();
-            d = attributes[1].getBigInteger();
-        }
 
         public String getFormat() {
             token.ensureValid();
             return "PKCS#8";
         }
+
         synchronized byte[] getEncodedInternal() {
             token.ensureValid();
             if (encoded == null) {
-                fetchValues();
                 try {
                     Key newKey = RSAPrivateCrtKeyImpl.newKey
                         (KeyType.RSA, null, n, e, d, p, q, pe, qe, coeff);
@@ -582,15 +632,15 @@ abstract class P11Key implements Key, Length {
             }
             return encoded;
         }
+
+        @Override
         public BigInteger getModulus() {
-            fetchValues();
             return n;
         }
         public BigInteger getPublicExponent() {
             return e;
         }
         public BigInteger getPrivateExponent() {
-            fetchValues();
             return d;
         }
         public BigInteger getPrimeP() {
@@ -611,37 +661,28 @@ abstract class P11Key implements Key, Length {
     }
 
     // RSA non-CRT private key
-    private static final class P11RSAPrivateNonCRTKey extends P11Key
-                implements RSAPrivateKey {
+    private static final class P11RSAPrivateNonCRTKey extends
+            P11RSAPrivateKeyInternal implements RSAPrivateKey {
         private static final long serialVersionUID = 1137764983777411481L;
 
-        private BigInteger n, d;
-        private byte[] encoded;
+        private transient BigInteger d;
+
         P11RSAPrivateNonCRTKey(Session session, long keyID, String algorithm,
-                int keyLength, CK_ATTRIBUTE[] attributes) {
-            super(PRIVATE, session, keyID, algorithm, keyLength, attributes);
-        }
-        private synchronized void fetchValues() {
-            token.ensureValid();
-            if (n != null) {
-                return;
-            }
-            CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
-                new CK_ATTRIBUTE(CKA_MODULUS),
-                new CK_ATTRIBUTE(CKA_PRIVATE_EXPONENT),
-            };
-            fetchAttributes(attributes);
-            n = attributes[0].getBigInteger();
-            d = attributes[1].getBigInteger();
+                int keyLength, CK_ATTRIBUTE[] attrs, BigInteger n,
+                BigInteger d) {
+            super(session, keyID, algorithm, keyLength, attrs);
+            this.n = n;
+            this.d = d;
         }
+
         public String getFormat() {
             token.ensureValid();
             return "PKCS#8";
         }
+
         synchronized byte[] getEncodedInternal() {
             token.ensureValid();
             if (encoded == null) {
-                fetchValues();
                 try {
                     // XXX make constructor in SunRsaSign provider public
                     // and call it directly
@@ -655,42 +696,43 @@ abstract class P11Key implements Key, Length {
             }
             return encoded;
         }
+
+        @Override
         public BigInteger getModulus() {
-            fetchValues();
             return n;
         }
         public BigInteger getPrivateExponent() {
-            fetchValues();
             return d;
         }
     }
 
-    private static final class P11RSAPublicKey extends P11Key
+    private static final class P11RSAPublicKey extends P11PublicKey
                                                 implements RSAPublicKey {
         private static final long serialVersionUID = -826726289023854455L;
-        private BigInteger n, e;
-        private byte[] encoded;
+        private transient BigInteger n, e;
+
         P11RSAPublicKey(Session session, long keyID, String algorithm,
-                int keyLength, CK_ATTRIBUTE[] attributes) {
-            super(PUBLIC, session, keyID, algorithm, keyLength, attributes);
+                int keyLength, CK_ATTRIBUTE[] attrs) {
+            super(session, keyID, algorithm, keyLength, attrs);
         }
+
         private synchronized void fetchValues() {
             token.ensureValid();
-            if (n != null) {
-                return;
-            }
-            CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
+            if (n != null) return;
+
+            BigInteger[] res = fetchAttributesAsInts(new CK_ATTRIBUTE[] {
                 new CK_ATTRIBUTE(CKA_MODULUS),
-                new CK_ATTRIBUTE(CKA_PUBLIC_EXPONENT),
-            };
-            fetchAttributes(attributes);
-            n = attributes[0].getBigInteger();
-            e = attributes[1].getBigInteger();
+                new CK_ATTRIBUTE(CKA_PUBLIC_EXPONENT)
+            });
+            n = res[0];
+            e = res[1];
         }
+
         public String getFormat() {
             token.ensureValid();
             return "X.509";
         }
+
         synchronized byte[] getEncodedInternal() {
             token.ensureValid();
             if (encoded == null) {
@@ -704,6 +746,7 @@ abstract class P11Key implements Key, Length {
             }
             return encoded;
         }
+
         public BigInteger getModulus() {
             fetchValues();
             return n;
@@ -719,41 +762,37 @@ abstract class P11Key implements Key, Length {
         }
     }
 
-    private static final class P11DSAPublicKey extends P11Key
+    private static final class P11DSAPublicKey extends P11PublicKey
                                                 implements DSAPublicKey {
         private static final long serialVersionUID = 5989753793316396637L;
 
-        private BigInteger y;
-        @SuppressWarnings("serial") // Type of field is not Serializable
-        private DSAParams params;
-        private byte[] encoded;
+        private transient BigInteger y;
+        private transient DSAParams params;
+
         P11DSAPublicKey(Session session, long keyID, String algorithm,
-                int keyLength, CK_ATTRIBUTE[] attributes) {
-            super(PUBLIC, session, keyID, algorithm, keyLength, attributes);
+                int keyLength, CK_ATTRIBUTE[] attrs) {
+            super(session, keyID, algorithm, keyLength, attrs);
         }
+
         private synchronized void fetchValues() {
             token.ensureValid();
-            if (y != null) {
-                return;
-            }
-            CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
+            if (y != null) return;
+
+            BigInteger[] res = fetchAttributesAsInts(new CK_ATTRIBUTE[] {
                 new CK_ATTRIBUTE(CKA_VALUE),
                 new CK_ATTRIBUTE(CKA_PRIME),
                 new CK_ATTRIBUTE(CKA_SUBPRIME),
-                new CK_ATTRIBUTE(CKA_BASE),
-            };
-            fetchAttributes(attributes);
-            y = attributes[0].getBigInteger();
-            params = new DSAParameterSpec(
-                attributes[1].getBigInteger(),
-                attributes[2].getBigInteger(),
-                attributes[3].getBigInteger()
-            );
+                new CK_ATTRIBUTE(CKA_BASE)
+            });
+            y = res[0];
+            params = new DSAParameterSpec(res[1], res[2], res[3]);
         }
+
         public String getFormat() {
             token.ensureValid();
             return "X.509";
         }
+
         synchronized byte[] getEncodedInternal() {
             token.ensureValid();
             if (encoded == null) {
@@ -783,41 +822,76 @@ abstract class P11Key implements Key, Length {
         }
     }
 
-    private static final class P11DSAPrivateKey extends P11Key
-                                                implements DSAPrivateKey {
+    static class P11DSAPrivateKeyInternal extends P11PrivateKey {
         private static final long serialVersionUID = 3119629997181999389L;
 
-        private BigInteger x;
-        @SuppressWarnings("serial") // Type of field is not Serializable
-        private DSAParams params;
-        private byte[] encoded;
+        protected transient DSAParams params;
+
+        static P11DSAPrivateKeyInternal of(Session session, long keyID,
+                String algorithm, int keyLength, CK_ATTRIBUTE[] attrs,
+                boolean keySensitive) {
+            if (keySensitive) {
+                return new P11DSAPrivateKeyInternal(session, keyID, algorithm,
+                        keyLength, attrs);
+            } else {
+                return new P11DSAPrivateKey(session, keyID, algorithm,
+                        keyLength, attrs);
+            }
+        }
+
+        private P11DSAPrivateKeyInternal(Session session, long keyID,
+                String algorithm, int keyLength, CK_ATTRIBUTE[] attrs) {
+            super(session, keyID, algorithm, keyLength, attrs);
+        }
+
+        private synchronized void fetchValues() {
+            token.ensureValid();
+            if (params != null) return;
+
+            BigInteger[] res = fetchAttributesAsInts(new CK_ATTRIBUTE[] {
+                    new CK_ATTRIBUTE(CKA_PRIME),
+                    new CK_ATTRIBUTE(CKA_SUBPRIME),
+                    new CK_ATTRIBUTE(CKA_BASE),
+            });
+            params = new DSAParameterSpec(res[0], res[1], res[2]);
+        }
+
+        protected DSAParams getParams() {
+            fetchValues();
+            return params;
+        }
+    }
+
+    private static final class P11DSAPrivateKey extends P11DSAPrivateKeyInternal
+                                        implements DSAPrivateKey {
+        private static final long serialVersionUID = 3119629997181999389L;
+
+        private transient BigInteger x; // params inside P11DSAPrivateKeyInternal
+
         P11DSAPrivateKey(Session session, long keyID, String algorithm,
-                int keyLength, CK_ATTRIBUTE[] attributes) {
-            super(PRIVATE, session, keyID, algorithm, keyLength, attributes);
+                int keyLength, CK_ATTRIBUTE[] attrs) {
+            super(session, keyID, algorithm, keyLength, attrs);
         }
+
         private synchronized void fetchValues() {
             token.ensureValid();
-            if (x != null) {
-                return;
-            }
-            CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
-                new CK_ATTRIBUTE(CKA_VALUE),
-                new CK_ATTRIBUTE(CKA_PRIME),
-                new CK_ATTRIBUTE(CKA_SUBPRIME),
-                new CK_ATTRIBUTE(CKA_BASE),
-            };
-            fetchAttributes(attributes);
-            x = attributes[0].getBigInteger();
-            params = new DSAParameterSpec(
-                attributes[1].getBigInteger(),
-                attributes[2].getBigInteger(),
-                attributes[3].getBigInteger()
-            );
+            if (x != null) return;
+
+            BigInteger[] res = fetchAttributesAsInts(new CK_ATTRIBUTE[] {
+                    new CK_ATTRIBUTE(CKA_VALUE),
+                    new CK_ATTRIBUTE(CKA_PRIME),
+                    new CK_ATTRIBUTE(CKA_SUBPRIME),
+                    new CK_ATTRIBUTE(CKA_BASE),
+            });
+            x = res[0];
+            params = new DSAParameterSpec(res[1], res[2], res[3]);
         }
+
         public String getFormat() {
             token.ensureValid();
             return "PKCS#8";
         }
+
         synchronized byte[] getEncodedInternal() {
             token.ensureValid();
             if (encoded == null) {
@@ -828,49 +902,87 @@ abstract class P11Key implements Key, Length {
             }
             return encoded;
         }
+
         public BigInteger getX() {
             fetchValues();
             return x;
         }
+
+        @Override
         public DSAParams getParams() {
             fetchValues();
             return params;
         }
     }
 
-    private static final class P11DHPrivateKey extends P11Key
+    static class P11DHPrivateKeyInternal extends P11PrivateKey {
+        private static final long serialVersionUID = 1L;
+
+        protected transient DHParameterSpec params;
+
+        static P11DHPrivateKeyInternal of(Session session, long keyID,
+                String algorithm, int keyLength, CK_ATTRIBUTE[] attrs,
+                boolean keySensitive) {
+            if (keySensitive) {
+                return new P11DHPrivateKeyInternal(session, keyID, algorithm,
+                        keyLength, attrs);
+            } else {
+                return new P11DHPrivateKey(session, keyID, algorithm,
+                        keyLength, attrs);
+            }
+        }
+
+        private P11DHPrivateKeyInternal(Session session, long keyID,
+                String algorithm, int keyLength, CK_ATTRIBUTE[] attrs) {
+            super(session, keyID, algorithm, keyLength, attrs);
+        }
+
+        private synchronized void fetchValues() {
+            token.ensureValid();
+            if (params != null) return;
+
+            BigInteger[] res = fetchAttributesAsInts(new CK_ATTRIBUTE[] {
+                    new CK_ATTRIBUTE(CKA_PRIME),
+                    new CK_ATTRIBUTE(CKA_BASE),
+            });
+            params = new DHParameterSpec(res[0], res[1]);
+        }
+
+        public DHParameterSpec getParams() {
+            fetchValues();
+            return params;
+        }
+    }
+
+    private static final class P11DHPrivateKey extends P11DHPrivateKeyInternal
                                                 implements DHPrivateKey {
         private static final long serialVersionUID = -1698576167364928838L;
 
-        private BigInteger x;
-        @SuppressWarnings("serial") // Type of field is not Serializable
-        private DHParameterSpec params;
-        private byte[] encoded;
+        private transient BigInteger x; // params in P11DHPrivateKeyInternal
+
         P11DHPrivateKey(Session session, long keyID, String algorithm,
-                int keyLength, CK_ATTRIBUTE[] attributes) {
-            super(PRIVATE, session, keyID, algorithm, keyLength, attributes);
+                int keyLength, CK_ATTRIBUTE[] attrs) {
+            super(session, keyID, algorithm, keyLength, attrs);
         }
+
         private synchronized void fetchValues() {
             token.ensureValid();
-            if (x != null) {
-                return;
-            }
-            CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
-                new CK_ATTRIBUTE(CKA_VALUE),
-                new CK_ATTRIBUTE(CKA_PRIME),
-                new CK_ATTRIBUTE(CKA_BASE),
-            };
-            fetchAttributes(attributes);
-            x = attributes[0].getBigInteger();
-            params = new DHParameterSpec(
-                attributes[1].getBigInteger(),
-                attributes[2].getBigInteger()
-            );
+            if (x != null) return;
+
+            BigInteger[] res = fetchAttributesAsInts(new CK_ATTRIBUTE[] {
+                    new CK_ATTRIBUTE(CKA_VALUE),
+                    new CK_ATTRIBUTE(CKA_PRIME),
+                    new CK_ATTRIBUTE(CKA_BASE),
+            });
+            x = res[0];
+            params = new DHParameterSpec(res[1], res[2]);
         }
+
         public String getFormat() {
             token.ensureValid();
             return "PKCS#8";
         }
+
         synchronized byte[] getEncodedInternal() {
             token.ensureValid();
             if (encoded == null) {
@@ -897,10 +1009,10 @@ abstract class P11Key implements Key, Length {
             return params;
         }
         public int hashCode() {
+            fetchValues();
             if (!token.isValid()) {
                 return 0;
             }
-            fetchValues();
             return Objects.hash(x, params.getP(), params.getG());
         }
         public boolean equals(Object obj) {
@@ -921,39 +1033,36 @@ abstract class P11Key implements Key, Length {
         }
     }
 
-    private static final class P11DHPublicKey extends P11Key
+    private static final class P11DHPublicKey extends P11PublicKey
                                                 implements DHPublicKey {
         static final long serialVersionUID = -598383872153843657L;
 
-        private BigInteger y;
-        @SuppressWarnings("serial") // Type of field is not Serializable
-        private DHParameterSpec params;
-        private byte[] encoded;
+        private transient BigInteger y;
+        private transient DHParameterSpec params;
+
         P11DHPublicKey(Session session, long keyID, String algorithm,
-                int keyLength, CK_ATTRIBUTE[] attributes) {
-            super(PUBLIC, session, keyID, algorithm, keyLength, attributes);
+                int keyLength, CK_ATTRIBUTE[] attrs) {
+            super(session, keyID, algorithm, keyLength, attrs);
         }
+
         private synchronized void fetchValues() {
             token.ensureValid();
-            if (y != null) {
-                return;
-            }
-            CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
-                new CK_ATTRIBUTE(CKA_VALUE),
-                new CK_ATTRIBUTE(CKA_PRIME),
-                new CK_ATTRIBUTE(CKA_BASE),
-            };
-            fetchAttributes(attributes);
-            y = attributes[0].getBigInteger();
-            params = new DHParameterSpec(
-                attributes[1].getBigInteger(),
-                attributes[2].getBigInteger()
-            );
+            if (y != null) return;
+
+            BigInteger[] res = fetchAttributesAsInts(new CK_ATTRIBUTE[] {
+                    new CK_ATTRIBUTE(CKA_VALUE),
+                    new CK_ATTRIBUTE(CKA_PRIME),
+                    new CK_ATTRIBUTE(CKA_BASE),
+            });
+            y = res[0];
+            params = new DHParameterSpec(res[1], res[2]);
         }
+
         public String getFormat() {
             token.ensureValid();
             return "X.509";
         }
+
         synchronized byte[] getEncodedInternal() {
             token.ensureValid();
             if (encoded == null) {
@@ -1009,45 +1118,88 @@ abstract class P11Key implements Key, Length {
         }
     }
 
-    private static final class P11ECPrivateKey extends P11Key
+    static class P11ECPrivateKeyInternal extends P11PrivateKey {
+
+        private static final long serialVersionUID = 1L;
+
+        protected transient ECParameterSpec params;
+
+        static P11ECPrivateKeyInternal of(Session session, long keyID,
+                String algorithm, int keyLength, CK_ATTRIBUTE[] attrs,
+                boolean keySensitive) {
+            if (keySensitive) {
+                return new P11ECPrivateKeyInternal(session, keyID, algorithm,
+                        keyLength, attrs);
+            } else {
+                return new P11ECPrivateKey(session, keyID, algorithm,
+                        keyLength, attrs);
+            }
+        }
+
+        private P11ECPrivateKeyInternal(Session session, long keyID,
+                String algorithm, int keyLength, CK_ATTRIBUTE[] attrs) {
+            super(session, keyID, algorithm, keyLength, attrs);
+        }
+
+        private synchronized void fetchValues() {
+            token.ensureValid();
+            if (params != null) return;
+
+            try {
+                byte[] paramBytes = fetchAttributes(new CK_ATTRIBUTE[] {
+                        new CK_ATTRIBUTE(CKA_EC_PARAMS)
+                })[0].getByteArray();
+
+                params = P11ECKeyFactory.decodeParameters(paramBytes);
+            } catch (Exception e) {
+                throw new RuntimeException("Could not parse key values", e);
+            }
+        }
+
+        protected ECParameterSpec getParams() {
+            fetchValues();
+            return params;
+        }
+    }
+
+    private static final class P11ECPrivateKey extends P11ECPrivateKeyInternal
                                                 implements ECPrivateKey {
         private static final long serialVersionUID = -7786054399510515515L;
 
-        private BigInteger s;
-        @SuppressWarnings("serial") // Type of field is not Serializable
-        private ECParameterSpec params;
-        private byte[] encoded;
+        private transient BigInteger s; // params in P11ECPrivateKeyInternal
+
         P11ECPrivateKey(Session session, long keyID, String algorithm,
-                int keyLength, CK_ATTRIBUTE[] attributes) {
-            super(PRIVATE, session, keyID, algorithm, keyLength, attributes);
+                int keyLength, CK_ATTRIBUTE[] attrs) {
+            super(session, keyID, algorithm, keyLength, attrs);
         }
+
         private synchronized void fetchValues() {
             token.ensureValid();
-            if (s != null) {
-                return;
-            }
-            CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
+            if (s != null) return;
+
+            CK_ATTRIBUTE[] attrs = fetchAttributes(new CK_ATTRIBUTE[] {
                 new CK_ATTRIBUTE(CKA_VALUE),
-                new CK_ATTRIBUTE(CKA_EC_PARAMS, params),
-            };
-            fetchAttributes(attributes);
-            s = attributes[0].getBigInteger();
+                new CK_ATTRIBUTE(CKA_EC_PARAMS),
+            });
+
+            s = attrs[0].getBigInteger();
             try {
                 params = P11ECKeyFactory.decodeParameters
-                            (attributes[1].getByteArray());
+                            (attrs[1].getByteArray());
             } catch (Exception e) {
                 throw new RuntimeException("Could not parse key values", e);
             }
         }
+
         public String getFormat() {
             token.ensureValid();
             return "PKCS#8";
         }
+
         synchronized byte[] getEncodedInternal() {
-            token.ensureValid();
             if (encoded == null) {
-                fetchValues();
                 try {
+                    fetchValues();
                     Key key = ECUtil.generateECPrivateKey(s, params);
                     encoded = key.getEncoded();
                 } catch (InvalidKeySpecException e) {
@@ -1056,44 +1208,43 @@ abstract class P11Key implements Key, Length {
             }
             return encoded;
         }
+
         public BigInteger getS() {
             fetchValues();
             return s;
         }
+
         public ECParameterSpec getParams() {
             fetchValues();
             return params;
         }
     }
 
-    private static final class P11ECPublicKey extends P11Key
+    private static final class P11ECPublicKey extends P11PublicKey
                                                 implements ECPublicKey {
         private static final long serialVersionUID = -6371481375154806089L;
 
-        @SuppressWarnings("serial") // Type of field is not Serializable
-        private ECPoint w;
-        @SuppressWarnings("serial") // Type of field is not Serializable
-        private ECParameterSpec params;
-        private byte[] encoded;
+        private transient ECPoint w;
+        private transient ECParameterSpec params;
+
         P11ECPublicKey(Session session, long keyID, String algorithm,
-                int keyLength, CK_ATTRIBUTE[] attributes) {
-            super(PUBLIC, session, keyID, algorithm, keyLength, attributes);
+                int keyLength, CK_ATTRIBUTE[] attrs) {
+            super(session, keyID, algorithm, keyLength, attrs);
         }
+
         private synchronized void fetchValues() {
             token.ensureValid();
-            if (w != null) {
-                return;
-            }
-            CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
+            if (w != null) return;
+
+            CK_ATTRIBUTE[] attrs = fetchAttributes(new CK_ATTRIBUTE[] {
                 new CK_ATTRIBUTE(CKA_EC_POINT),
                 new CK_ATTRIBUTE(CKA_EC_PARAMS),
-            };
-            fetchAttributes(attributes);
+            });
 
             try {
                 params = P11ECKeyFactory.decodeParameters
-                            (attributes[1].getByteArray());
-                byte[] ecKey = attributes[0].getByteArray();
+                            (attrs[1].getByteArray());
+                byte[] ecKey = attrs[0].getByteArray();
 
                 // Check whether the X9.63 encoding of an EC point is wrapped
                 // in an ASN.1 OCTET STRING
@@ -1115,10 +1266,12 @@ abstract class P11Key implements Key, Length {
                 throw new RuntimeException("Could not parse key values", e);
             }
         }
+
         public String getFormat() {
             token.ensureValid();
             return "X.509";
         }
+
         synchronized byte[] getEncodedInternal() {
             token.ensureValid();
             if (encoded == null) {
@@ -1417,3 +1570,4 @@ final class SessionKeyRef extends PhantomReference {
         this.clear();
     }
 }
+
diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Signature.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Signature.java
index 7c171435640..f18fc621d2e 100644
--- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Signature.java
+++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Signature.java
@@ -119,6 +119,9 @@ final class P11Signature extends SignatureSpi {
     // key instance used, if init*() was called
     private P11Key p11Key;
 
+    // signature length expected or 0 for unknown
+    private int sigLen;
+
     // message digest, if we do the digesting ourselves
     private final MessageDigest md;
 
@@ -285,7 +288,7 @@ final class P11Signature extends SignatureSpi {
         try {
             if (mode == M_SIGN) {
                 if (type == T_UPDATE) {
-                    token.p11.C_SignFinal(session.id(), 0);
+                    token.p11.C_SignFinal(session.id(), sigLen);
                 } else {
                     byte[] digest;
                     if (type == T_DIGEST) {
@@ -296,12 +299,7 @@ final class P11Signature extends SignatureSpi {
                     token.p11.C_Sign(session.id(), digest);
                 }
             } else { // M_VERIFY
-                byte[] signature;
-                if (mechanism == CKM_DSA) {
-                    signature = new byte[64]; // assume N = 256
-                } else {
-                    signature = new byte[(p11Key.length() + 7) >> 3];
-                }
+                byte[] signature = new byte[sigLen];
                 if (type == T_UPDATE) {
                     token.p11.C_VerifyFinal(session.id(), signature);
                 } else {
@@ -372,6 +370,15 @@ final class P11Signature extends SignatureSpi {
                 md.reset();
             }
         }
+        sigLen = 0;
+        if ("DSA".equals(p11Key.getAlgorithm())) {
+            if (p11Key instanceof P11Key.P11DSAPrivateKeyInternal) {
+                sigLen = ((P11Key.P11DSAPrivateKeyInternal)p11Key).getParams()
+                        .getQ().bitLength() >> 2;
+            } else if (p11Key instanceof DSAKey) {
+                sigLen = ((DSAKey)p11Key).getParams().getQ().bitLength() >> 2;
+            }
+        }
         initialized = true;
     }
 
@@ -617,7 +624,7 @@ final class P11Signature extends SignatureSpi {
         try {
             byte[] signature;
             if (type == T_UPDATE) {
-                signature = token.p11.C_SignFinal(session.id(), 0);
+                signature = token.p11.C_SignFinal(session.id(), sigLen);
             } else {
                 byte[] digest;
                 if (type == T_DIGEST) {
@@ -684,7 +691,7 @@ final class P11Signature extends SignatureSpi {
         try {
             if (!p1363Format) {
                 if (keyAlgorithm.equals("DSA")) {
-                    signature = asn1ToDSA(signature);
+                    signature = asn1ToDSA(signature, sigLen);
                 } else if (keyAlgorithm.equals("EC")) {
                     signature = asn1ToECDSA(signature);
                 }
@@ -801,7 +808,8 @@ final class P11Signature extends SignatureSpi {
         }
     }
 
-    private static byte[] asn1ToDSA(byte[] sig) throws SignatureException {
+    private static byte[] asn1ToDSA(byte[] sig, int sigLen)
+            throws SignatureException {
         try {
             // Enforce strict DER checking for signatures
             DerInputStream in = new DerInputStream(sig, 0, sig.length, false);
@@ -816,8 +824,8 @@ final class P11Signature extends SignatureSpi {
             BigInteger r = values[0].getPositiveBigInteger();
             BigInteger s = values[1].getPositiveBigInteger();
 
-            byte[] br = toByteArray(r, 20);
-            byte[] bs = toByteArray(s, 20);
+            byte[] br = toByteArray(r, sigLen/2);
+            byte[] bs = toByteArray(s, sigLen/2);
             if ((br == null) || (bs == null)) {
                 throw new SignatureException("Out of range value for R or S");
             }
@@ -829,7 +837,7 @@ final class P11Signature extends SignatureSpi {
         }
     }
 
-    private byte[] asn1ToECDSA(byte[] sig) throws SignatureException {
+    private static byte[] asn1ToECDSA(byte[] sig) throws SignatureException {
         try {
             // Enforce strict DER checking for signatures
             DerInputStream in = new DerInputStream(sig, 0, sig.length, false);
@@ -909,3 +917,4 @@ final class P11Signature extends SignatureSpi {
         return null;
     }
 }
+
diff --git a/test/jdk/sun/security/pkcs11/Signature/LargeDSAKey.java b/test/jdk/sun/security/pkcs11/Signature/LargeDSAKey.java
new file mode 100644
index 00000000000..a45a5ca47f5
--- /dev/null
+++ b/test/jdk/sun/security/pkcs11/Signature/LargeDSAKey.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2021, Red Hat, Inc.
+ *
+ * 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.
+ */
+
+import java.security.AlgorithmParameterGenerator;
+import java.security.AlgorithmParameters;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.PrivateKey;
+import java.security.Provider;
+import java.security.PublicKey;
+import java.security.SecureRandom;
+import java.security.Signature;
+import java.security.spec.DSAGenParameterSpec;
+import java.security.spec.DSAParameterSpec;
+
+/*
+ * @test
+ * @bug 8271566
+ * @library /test/lib ..
+ * @modules jdk.crypto.cryptoki
+ * @run main/othervm/timeout=30 LargeDSAKey
+ */
+
+public final class LargeDSAKey extends PKCS11Test {
+
+    private static final boolean enableDebug = false;
+
+    private static final String knownText =
+            "Known text known text known text";
+
+    @Override
+    public void main(Provider p) throws Exception {
+        KeyPairGenerator kpg = KeyPairGenerator.getInstance("DSA", p);
+        AlgorithmParameterGenerator dsaParGen =
+                AlgorithmParameterGenerator.getInstance("DSA");
+        DSAGenParameterSpec dsaParGenSpec =
+                new DSAGenParameterSpec(2048, 256);
+        dsaParGen.init(dsaParGenSpec, new SecureRandom());
+        AlgorithmParameters params = dsaParGen.generateParameters();
+        DSAParameterSpec dsaParams =
+                params.getParameterSpec(DSAParameterSpec.class);
+        kpg.initialize(dsaParams);
+        KeyPair kp = kpg.generateKeyPair();
+        doTestSignature(kp, p);
+    }
+
+    private static void doTestSignature(KeyPair kp, Provider p)
+            throws Exception {
+        byte[] knownTextSig = null;
+        Signature s = Signature.getInstance("SHA1withDSA", p);
+        PrivateKey privKey = kp.getPrivate();
+        PublicKey pubKey = kp.getPublic();
+        if (enableDebug) {
+            System.out.println("Signature algorithm: " + s.getAlgorithm());
+            System.out.println("Signature Provider: " + s.getProvider());
+            System.out.println("Private key for signature: " + privKey);
+            System.out.println("Public key for signature: " + pubKey);
+        }
+        s.initSign(privKey);
+        s.update(knownText.getBytes());
+        knownTextSig = s.sign();
+        s.initVerify(pubKey);
+        s.update(knownText.getBytes());
+        if (s.verify(knownTextSig) == false) {
+            throw new Exception("Could not verify signature");
+        }
+        if (enableDebug) {
+            System.out.println("Signature verified");
+        }
+    }
+
+    public static void main(String[] args) throws Throwable {
+        main(new LargeDSAKey());
+        System.out.println("TEST PASS - OK");
+    }
+
+}
-- 
GitLab


From 2ff12966a345eaa1c16ed73165b3eb273e56f8dd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ivan=20=C5=A0ipka?= 
Date: Mon, 6 Dec 2021 23:34:32 +0000
Subject: [PATCH 014/671] 8277957: Add test group for IPv6 exclusive testing

Reviewed-by: alanb, msheppar
---
 test/jdk/TEST.groups | 18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)

diff --git a/test/jdk/TEST.groups b/test/jdk/TEST.groups
index 37dafa2e73a..9cdec38ea9a 100644
--- a/test/jdk/TEST.groups
+++ b/test/jdk/TEST.groups
@@ -518,7 +518,23 @@ needs_g1gc = \
   jdk/jfr/event/gc/objectcount/TestObjectCountAfterGCEventWithG1FullCollection.java \
   jdk/jfr/event/gc/objectcount/TestObjectCountAfterGCEventWithG1ConcurrentMark.java \
   jdk/jfr/event/gc/heapsummary/TestHeapSummaryEventG1.java
-  
+
+#  This set of tests will be executed in an ipv6 only environment
+
+jdk_ipv6_only = \
+    :jdk_net \
+    :jdk_nio_networkchannel
+
+jdk_nio_networkchannel = \
+    java/nio/channels/AsyncCloseAndInterrupt.java \
+    java/nio/channels/AsynchronousServerSocketChannel \
+    java/nio/channels/AsynchronousSocketChannel \
+    java/nio/channels/DatagramChannel \
+    java/nio/channels/ServerSocketChannel \
+    java/nio/channels/SocketChannel \
+    java/nio/channels/Selector \
+    java/nio/channels/etc
+
 jdk_core_manual = \
     :jdk_core_manual_no_input \
     :jdk_core_manual_no_input_security \
-- 
GitLab


From f148e3e4623c6d0270a10ba73140e0c37ca5398a Mon Sep 17 00:00:00 2001
From: Jonathan Gibbons 
Date: Tue, 7 Dec 2021 00:41:11 +0000
Subject: [PATCH 015/671] 8278318: Create {@index} entries for key LangTools
 terms

Reviewed-by: darcy
---
 src/java.compiler/share/classes/module-info.java | 6 ++++--
 src/jdk.compiler/share/classes/module-info.java  | 6 +++++-
 2 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/src/java.compiler/share/classes/module-info.java b/src/java.compiler/share/classes/module-info.java
index 3d937e09f0c..0793855d1dc 100644
--- a/src/java.compiler/share/classes/module-info.java
+++ b/src/java.compiler/share/classes/module-info.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2021, 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
@@ -24,7 +24,9 @@
  */
 
 /**
- * Defines the Language Model, Annotation Processing, and Java Compiler APIs.
+ * Defines the {@index "Language Model"}, {@index "Annotation Processing"}, and
+ * {@index "Java Compiler"} APIs.
+ *
  * 

* These APIs model declarations and types of the Java programming language, * and define interfaces for tools such as compilers which can be invoked diff --git a/src/jdk.compiler/share/classes/module-info.java b/src/jdk.compiler/share/classes/module-info.java index 88066d3c363..a417a2998dc 100644 --- a/src/jdk.compiler/share/classes/module-info.java +++ b/src/jdk.compiler/share/classes/module-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2021, 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 @@ -28,6 +28,10 @@ * {@linkplain javax.tools.ToolProvider#getSystemJavaCompiler system Java compiler} * and its command line equivalent, {@index javac javac tool}. * + *

The {@code com.sun.source.*} packages provide the {@index "Compiler Tree API"}: + * an API for accessing the abstract trees (ASTs) representing Java source code + * and documentation comments, used by javac, javadoc and related tools. + * *

javac

* *

-- GitLab From 10db0e41634b62be5c1a931bd54ac4260108670d Mon Sep 17 00:00:00 2001 From: Weijun Wang Date: Tue, 7 Dec 2021 01:37:55 +0000 Subject: [PATCH 016/671] 8277932: Subject:callAs() not throwing NPE when action is null Reviewed-by: rriggs --- src/java.base/share/classes/javax/security/auth/Subject.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/java.base/share/classes/javax/security/auth/Subject.java b/src/java.base/share/classes/javax/security/auth/Subject.java index 8e30f84ff44..c1235bffd53 100644 --- a/src/java.base/share/classes/javax/security/auth/Subject.java +++ b/src/java.base/share/classes/javax/security/auth/Subject.java @@ -402,6 +402,7 @@ public final class Subject implements java.io.Serializable { */ public static T callAs(final Subject subject, final Callable action) throws CompletionException { + Objects.requireNonNull(action); if (USE_TL) { Subject oldSubject = SUBJECT_THREAD_LOCAL.get(); SUBJECT_THREAD_LOCAL.set(subject); -- GitLab From f22d157e551fb28991e7713a45e63a0a8d9d2c4c Mon Sep 17 00:00:00 2001 From: Sibabrata Sahoo Date: Tue, 7 Dec 2021 05:10:30 +0000 Subject: [PATCH 017/671] 8277353: java/security/MessageDigest/ThreadSafetyTest.java test times out Reviewed-by: weijun --- .../jdk/java/security/MessageDigest/ThreadSafetyTest.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/jdk/java/security/MessageDigest/ThreadSafetyTest.java b/test/jdk/java/security/MessageDigest/ThreadSafetyTest.java index 41ecbca2677..594e9926eab 100644 --- a/test/jdk/java/security/MessageDigest/ThreadSafetyTest.java +++ b/test/jdk/java/security/MessageDigest/ThreadSafetyTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Azul Systems, Inc. All rights reserved. + * Copyright (c) 2020, 2021, Azul Systems, Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,9 +23,9 @@ /* * @test - * @bug 8241960 + * @bug 8241960 8277353 * @summary Confirm that java.security.MessageDigest is thread-safe after clone. - * @run main/othervm ThreadSafetyTest 5 4 + * @run main ThreadSafetyTest 4 2 */ import java.security.MessageDigest; @@ -56,7 +56,7 @@ public class ThreadSafetyTest { duration = Integer.parseInt(args[1]); } int nProcessors = Runtime.getRuntime().availableProcessors(); - int nTasks = nProcessors * threadsFactor; + int nTasks = Math.min(nProcessors, 4) * threadsFactor; System.out.println("Testing with " + nTasks + " threads on " + nProcessors + " processors for " + duration + -- GitLab From e535cb3fbac11785cfdb43c9b6f73b2a38a621d6 Mon Sep 17 00:00:00 2001 From: Serguei Spitsyn Date: Tue, 7 Dec 2021 08:16:49 +0000 Subject: [PATCH 018/671] 8272395: Bad HTML in JVMTI man page Reviewed-by: dholmes, iris --- src/hotspot/share/prims/jvmti.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/hotspot/share/prims/jvmti.xml b/src/hotspot/share/prims/jvmti.xml index af48e72a1cf..b05d34cdec2 100644 --- a/src/hotspot/share/prims/jvmti.xml +++ b/src/hotspot/share/prims/jvmti.xml @@ -6861,7 +6861,7 @@ class C2 extends C1 implements I2 {

  • By loading and deriving a class from a class file representation using a class loader (see ).
  • -
  • By invoking Lookup::defineHiddenClass +
  • By invoking Lookup::defineHiddenClass that creates a hidden class or interface from a class file representation.
  • By invoking methods in certain Java SE Platform APIs such as reflection.
@@ -6923,7 +6923,7 @@ class C2 extends C1 implements I2 { class_count_ptr, and the array itself via classes_ptr.

- See Lookup::defineHiddenClass. + See Lookup::defineHiddenClass. jvmdi @@ -6973,7 +6973,7 @@ class C2 extends C1 implements I2 { "L" + N + "." + S + ";" where N is the binary name encoded in internal form (JVMS 4.2.1) indicated by the class file passed to - Lookup::defineHiddenClass, + Lookup::defineHiddenClass, and S is an unqualified name. The returned name is not a type descriptor and does not conform to JVMS 4.3.2. For example, com.foo.Foo/AnySuffix is "Lcom/foo/Foo.AnySuffix;" -- GitLab From 24877ac0788d3db9f2e9c7492a0d3e42244e7e06 Mon Sep 17 00:00:00 2001 From: Alan Bateman Date: Tue, 7 Dec 2021 08:49:18 +0000 Subject: [PATCH 019/671] 8278270: ServerSocket is not thread safe Reviewed-by: dfuchs --- .../share/classes/java/net/ServerSocket.java | 131 +++++++++--------- 1 file changed, 66 insertions(+), 65 deletions(-) diff --git a/src/java.base/share/classes/java/net/ServerSocket.java b/src/java.base/share/classes/java/net/ServerSocket.java index 3d985f84df3..7c567d3e8c7 100644 --- a/src/java.base/share/classes/java/net/ServerSocket.java +++ b/src/java.base/share/classes/java/net/ServerSocket.java @@ -78,17 +78,17 @@ import sun.net.PlatformSocketImpl; */ public class ServerSocket implements java.io.Closeable { /** - * Various states of this socket. + * The underlying SocketImpl */ - private boolean created = false; - private boolean bound = false; - private boolean closed = false; - private Object closeLock = new Object(); + private final SocketImpl impl; /** - * The implementation of this Socket. + * Various states of this socket, need stateLock to change. */ - private SocketImpl impl; + private volatile boolean created; // impl.create(boolean) called + private volatile boolean bound; + private volatile boolean closed; + private final Object stateLock = new Object(); /** * Creates a server socket with a user-specified {@code SocketImpl}. @@ -124,7 +124,7 @@ public class ServerSocket implements java.io.Closeable { * @revised 1.4 */ public ServerSocket() throws IOException { - setImpl(); + this.impl = createImpl(); } /** @@ -264,18 +264,15 @@ public class ServerSocket implements java.io.Closeable { * @since 1.1 */ public ServerSocket(int port, int backlog, InetAddress bindAddr) throws IOException { - setImpl(); if (port < 0 || port > 0xFFFF) - throw new IllegalArgumentException( - "Port value out of range: " + port); + throw new IllegalArgumentException("Port value out of range: " + port); if (backlog < 1) - backlog = 50; + backlog = 50; + + this.impl = createImpl(); try { bind(new InetSocketAddress(bindAddr, port), backlog); - } catch(SecurityException e) { - close(); - throw e; - } catch(IOException e) { + } catch (IOException | SecurityException e) { close(); throw e; } @@ -289,35 +286,36 @@ public class ServerSocket implements java.io.Closeable { * @throws SocketException if creation fails. * @since 1.4 */ - SocketImpl getImpl() throws SocketException { - if (!created) - createImpl(); + private SocketImpl getImpl() throws SocketException { + if (!created) { + synchronized (stateLock) { + if (!created) { + if (closed) { + throw new SocketException("Socket is closed"); + } + try { + impl.create(true); + } catch (SocketException e) { + throw e; + } catch (IOException e) { + throw new SocketException(e.getMessage()); + } + created = true; + } + } + } return impl; } - private void setImpl() { + /** + * Create a SocketImpl for a server socket. + */ + private static SocketImpl createImpl() { SocketImplFactory factory = ServerSocket.factory; if (factory != null) { - impl = factory.createSocketImpl(); + return factory.createSocketImpl(); } else { - impl = SocketImpl.createPlatformSocketImpl(true); - } - } - - /** - * Creates the socket implementation. - * - * @throws SocketException if creation fails - * @since 1.4 - */ - void createImpl() throws SocketException { - if (impl == null) - setImpl(); - try { - impl.create(true); - created = true; - } catch (IOException e) { - throw new SocketException(e.getMessage()); + return SocketImpl.createPlatformSocketImpl(true); } } @@ -379,21 +377,21 @@ public class ServerSocket implements java.io.Closeable { if (epoint.isUnresolved()) throw new SocketException("Unresolved address"); if (backlog < 1) - backlog = 50; - try { - @SuppressWarnings("removal") - SecurityManager security = System.getSecurityManager(); - if (security != null) - security.checkListen(epoint.getPort()); + backlog = 50; + + @SuppressWarnings("removal") + SecurityManager security = System.getSecurityManager(); + if (security != null) + security.checkListen(epoint.getPort()); + + synchronized (stateLock) { + if (closed) + throw new SocketException("Socket is closed"); + if (bound) + throw new SocketException("Already bound"); getImpl().bind(epoint.getAddress(), epoint.getPort()); getImpl().listen(backlog); bound = true; - } catch(SecurityException e) { - bound = false; - throw e; - } catch(IOException e) { - bound = false; - throw e; } } @@ -711,12 +709,18 @@ public class ServerSocket implements java.io.Closeable { * @revised 1.4 */ public void close() throws IOException { - synchronized(closeLock) { - if (isClosed()) - return; - if (created) - impl.close(); - closed = true; + synchronized (stateLock) { + if (!closed) { + try { + // close underlying socket if created + if (created) { + impl.close(); + } + } finally { + closed = true; + } + + } } } @@ -760,9 +764,7 @@ public class ServerSocket implements java.io.Closeable { * @since 1.4 */ public boolean isClosed() { - synchronized(closeLock) { - return closed; - } + return closed; } /** @@ -783,7 +785,7 @@ public class ServerSocket implements java.io.Closeable { * @since 1.1 * @see #getSoTimeout() */ - public synchronized void setSoTimeout(int timeout) throws SocketException { + public void setSoTimeout(int timeout) throws SocketException { if (isClosed()) throw new SocketException("Socket is closed"); if (timeout < 0) @@ -799,7 +801,7 @@ public class ServerSocket implements java.io.Closeable { * @since 1.1 * @see #setSoTimeout(int) */ - public synchronized int getSoTimeout() throws IOException { + public int getSoTimeout() throws IOException { if (isClosed()) throw new SocketException("Socket is closed"); Object o = getImpl().getOption(SocketOptions.SO_TIMEOUT); @@ -984,7 +986,7 @@ public class ServerSocket implements java.io.Closeable { * @since 1.4 * @see #getReceiveBufferSize */ - public synchronized void setReceiveBufferSize (int size) throws SocketException { + public void setReceiveBufferSize (int size) throws SocketException { if (!(size > 0)) { throw new IllegalArgumentException("negative receive size"); } @@ -1007,8 +1009,7 @@ public class ServerSocket implements java.io.Closeable { * @see #setReceiveBufferSize(int) * @since 1.4 */ - public synchronized int getReceiveBufferSize() - throws SocketException{ + public int getReceiveBufferSize() throws SocketException { if (isClosed()) throw new SocketException("Socket is closed"); int result = 0; -- GitLab From 07669e3bc65b1728d784e21ec83b437374f9fa19 Mon Sep 17 00:00:00 2001 From: Yasumasa Suenaga Date: Tue, 7 Dec 2021 09:26:13 +0000 Subject: [PATCH 020/671] 8275375: [REDO] JDK-8271949 dumppath in -XX:FlightRecorderOptions does not affect Reviewed-by: egahlin, mgronlun --- src/hotspot/share/jfr/jni/jfrJniMethod.cpp | 17 ++++++- src/hotspot/share/jfr/jni/jfrJniMethod.hpp | 6 ++- .../jfr/jni/jfrJniMethodRegistration.cpp | 2 + .../recorder/repository/jfrEmergencyDump.cpp | 47 ++++++++++++++--- .../recorder/repository/jfrEmergencyDump.hpp | 9 +++- .../jfr/recorder/service/jfrOptionSet.cpp | 22 ++++++++ .../share/classes/jdk/jfr/internal/JVM.java | 17 ++++++- .../classes/jdk/jfr/internal/Options.java | 31 +++++++++--- .../jdk/jfr/internal/SecuritySupport.java | 6 +-- .../jdk/jfr/internal/dcmd/DCmdConfigure.java | 11 ++-- test/jdk/jdk/jfr/jvm/TestDumpOnCrash.java | 50 ++++++++++++++----- 11 files changed, 179 insertions(+), 39 deletions(-) diff --git a/src/hotspot/share/jfr/jni/jfrJniMethod.cpp b/src/hotspot/share/jfr/jni/jfrJniMethod.cpp index 54a4680ced8..690b02ef36d 100644 --- a/src/hotspot/share/jfr/jni/jfrJniMethod.cpp +++ b/src/hotspot/share/jfr/jni/jfrJniMethod.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2021, 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 @@ -35,6 +35,7 @@ #include "jfr/recorder/repository/jfrRepository.hpp" #include "jfr/recorder/repository/jfrChunkRotation.hpp" #include "jfr/recorder/repository/jfrChunkWriter.hpp" +#include "jfr/recorder/repository/jfrEmergencyDump.hpp" #include "jfr/recorder/service/jfrEventThrottler.hpp" #include "jfr/recorder/service/jfrOptionSet.hpp" #include "jfr/recorder/stacktrace/jfrStackTraceRepository.hpp" @@ -315,6 +316,20 @@ JVM_ENTRY_NO_ENV(void, jfr_set_repository_location(JNIEnv* env, jobject repo, js return JfrRepository::set_path(location, thread); JVM_END +NO_TRANSITION(void, jfr_set_dump_path(JNIEnv* env, jobject jvm, jstring dumppath)) + if (dumppath == NULL) { + JfrEmergencyDump::set_dump_path(NULL); + } else { + const char* dump_path = env->GetStringUTFChars(dumppath, NULL); + JfrEmergencyDump::set_dump_path(dump_path); + env->ReleaseStringUTFChars(dumppath, dump_path); + } +NO_TRANSITION_END + +NO_TRANSITION(jstring, jfr_get_dump_path(JNIEnv* env, jobject jvm)) + return env->NewStringUTF(JfrEmergencyDump::get_dump_path()); +NO_TRANSITION_END + JVM_ENTRY_NO_ENV(void, jfr_uncaught_exception(JNIEnv* env, jobject jvm, jobject t, jthrowable throwable)) JfrJavaSupport::uncaught_exception(throwable, thread); JVM_END diff --git a/src/hotspot/share/jfr/jni/jfrJniMethod.hpp b/src/hotspot/share/jfr/jni/jfrJniMethod.hpp index 19a676c4a22..946ef04470d 100644 --- a/src/hotspot/share/jfr/jni/jfrJniMethod.hpp +++ b/src/hotspot/share/jfr/jni/jfrJniMethod.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2021, 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 @@ -113,6 +113,10 @@ jlong JNICALL jfr_type_id(JNIEnv* env, jobject jvm, jclass jc); void JNICALL jfr_set_repository_location(JNIEnv* env, jobject repo, jstring location); +void JNICALL jfr_set_dump_path(JNIEnv* env, jobject jvm, jstring dumppath); + +jstring JNICALL jfr_get_dump_path(JNIEnv* env, jobject jvm); + jobject JNICALL jfr_get_event_writer(JNIEnv* env, jclass cls); jobject JNICALL jfr_new_event_writer(JNIEnv* env, jclass cls); diff --git a/src/hotspot/share/jfr/jni/jfrJniMethodRegistration.cpp b/src/hotspot/share/jfr/jni/jfrJniMethodRegistration.cpp index db137776f65..5bc8a95a826 100644 --- a/src/hotspot/share/jfr/jni/jfrJniMethodRegistration.cpp +++ b/src/hotspot/share/jfr/jni/jfrJniMethodRegistration.cpp @@ -75,6 +75,8 @@ JfrJniMethodRegistration::JfrJniMethodRegistration(JNIEnv* env) { (char*)"flush", (char*)"(Ljdk/jfr/internal/EventWriter;II)Z", (void*)jfr_event_writer_flush, (char*)"flush", (char*)"()V", (void*)jfr_flush, (char*)"setRepositoryLocation", (char*)"(Ljava/lang/String;)V", (void*)jfr_set_repository_location, + (char*)"setDumpPath", (char*)"(Ljava/lang/String;)V", (void*)jfr_set_dump_path, + (char*)"getDumpPath", (char*)"()Ljava/lang/String;", (void*)jfr_get_dump_path, (char*)"abort", (char*)"(Ljava/lang/String;)V", (void*)jfr_abort, (char*)"addStringConstant", (char*)"(JLjava/lang/String;)Z", (void*)jfr_add_string_constant, (char*)"uncaughtException", (char*)"(Ljava/lang/Thread;Ljava/lang/Throwable;)V", (void*)jfr_uncaught_exception, diff --git a/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp b/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp index 0bcfc8568f5..1dac9703459 100644 --- a/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp +++ b/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp @@ -41,6 +41,8 @@ #include "utilities/growableArray.hpp" #include "utilities/ostream.hpp" +char JfrEmergencyDump::_dump_path[JVM_MAXPATHLEN] = { 0 }; + static const char vm_error_filename_fmt[] = "hs_err_pid%p.jfr"; static const char vm_oom_filename_fmt[] = "hs_oom_pid%p.jfr"; static const char vm_soe_filename_fmt[] = "hs_soe_pid%p.jfr"; @@ -66,12 +68,17 @@ static bool is_path_empty() { } // returns with an appended file separator (if successful) -static size_t get_current_directory() { - if (os::get_current_directory(_path_buffer, sizeof(_path_buffer)) == NULL) { - return 0; +static size_t get_dump_directory() { + const char* dump_path = JfrEmergencyDump::get_dump_path(); + if (*dump_path == '\0') { + if (os::get_current_directory(_path_buffer, sizeof(_path_buffer)) == NULL) { + return 0; + } + } else { + strcpy(_path_buffer, dump_path); } - const size_t cwd_len = strlen(_path_buffer); - const int result = jio_snprintf(_path_buffer + cwd_len, + const size_t path_len = strlen(_path_buffer); + const int result = jio_snprintf(_path_buffer + path_len, sizeof(_path_buffer), "%s", os::file_separator()); @@ -105,7 +112,7 @@ static void close_emergency_dump_file() { static const char* create_emergency_dump_path() { assert(is_path_empty(), "invariant"); - const size_t path_len = get_current_directory(); + const size_t path_len = get_dump_directory(); if (path_len == 0) { return NULL; } @@ -125,12 +132,21 @@ static const char* create_emergency_dump_path() { return result ? _path_buffer : NULL; } -static bool open_emergency_dump_file() { +bool JfrEmergencyDump::open_emergency_dump_file() { if (is_emergency_dump_file_open()) { // opened already return true; } - return open_emergency_dump_fd(create_emergency_dump_path()); + + bool result = open_emergency_dump_fd(create_emergency_dump_path()); + if (!result && *_dump_path != '\0') { + log_warning(jfr)("Unable to create an emergency dump file at the location set by dumppath=%s", _dump_path); + // Fallback. Try to create it in the current directory. + *_dump_path = '\0'; + *_path_buffer = '\0'; + result = open_emergency_dump_fd(create_emergency_dump_path()); + } + return result; } static void report(outputStream* st, bool emergency_file_opened, const char* repository_path) { @@ -150,6 +166,21 @@ static void report(outputStream* st, bool emergency_file_opened, const char* rep } } +void JfrEmergencyDump::set_dump_path(const char* dump_path) { + if (dump_path == NULL || *dump_path == '\0') { + os::get_current_directory(_dump_path, sizeof(_dump_path)); + } else { + if (strlen(dump_path) < JVM_MAXPATHLEN) { + strncpy(_dump_path, dump_path, JVM_MAXPATHLEN); + _dump_path[JVM_MAXPATHLEN - 1] = '\0'; + } + } +} + +const char* JfrEmergencyDump::get_dump_path() { + return _dump_path; +} + void JfrEmergencyDump::on_vm_error_report(outputStream* st, const char* repository_path) { assert(st != NULL, "invariant"); Thread* thread = Thread::current_or_null_safe(); diff --git a/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.hpp b/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.hpp index 909f73bf892..c96a7d802dc 100644 --- a/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.hpp +++ b/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,7 +32,14 @@ // Responsible for creating an hs_err.jfr file in exceptional shutdown situations (crash, OOM) // class JfrEmergencyDump : AllStatic { + private: + static char _dump_path[JVM_MAXPATHLEN]; + + static bool open_emergency_dump_file(); + public: + static void set_dump_path(const char* dump_path); + static const char* get_dump_path(); static const char* chunk_path(const char* repository_path); static void on_vm_error(const char* repository_path); static void on_vm_error_report(outputStream* st, const char* repository_path); diff --git a/src/hotspot/share/jfr/recorder/service/jfrOptionSet.cpp b/src/hotspot/share/jfr/recorder/service/jfrOptionSet.cpp index 166603d4397..7f9dfcee4ff 100644 --- a/src/hotspot/share/jfr/recorder/service/jfrOptionSet.cpp +++ b/src/hotspot/share/jfr/recorder/service/jfrOptionSet.cpp @@ -163,6 +163,7 @@ bool JfrOptionSet::allow_event_retransforms() { // default options for the dcmd parser const char* const default_repository = NULL; +const char* const default_dumppath = NULL; const char* const default_global_buffer_size = "512k"; const char* const default_num_global_buffers = "20"; const char* const default_memory_size = "10m"; @@ -182,6 +183,13 @@ static DCmdArgument _dcmd_repository( false, default_repository); +static DCmdArgument _dcmd_dumppath( + "dumppath", + "Path to emergency dump", + "STRING", + false, + default_dumppath); + static DCmdArgument _dcmd_threadbuffersize( "threadbuffersize", "Thread buffer size", @@ -258,6 +266,7 @@ static DCmdParser _parser; static void register_parser_options() { _parser.add_dcmd_option(&_dcmd_repository); + _parser.add_dcmd_option(&_dcmd_dumppath); _parser.add_dcmd_option(&_dcmd_threadbuffersize); _parser.add_dcmd_option(&_dcmd_memorysize); _parser.add_dcmd_option(&_dcmd_globalbuffersize); @@ -346,6 +355,18 @@ bool JfrOptionSet::configure(TRAPS) { configure._repository_path.set_value(repo_copy); } + configure._dump_path.set_is_set(_dcmd_dumppath.is_set()); + char* dumppath = _dcmd_dumppath.value(); + if (dumppath != NULL) { + const size_t len = strlen(dumppath); + char* dumppath_copy = JfrCHeapObj::new_array(len + 1); + if (NULL == dumppath_copy) { + return false; + } + strncpy(dumppath_copy, dumppath, len + 1); + configure._dump_path.set_value(dumppath_copy); + } + configure._stack_depth.set_is_set(_dcmd_stackdepth.is_set()); configure._stack_depth.set_value(_dcmd_stackdepth.value()); @@ -373,6 +394,7 @@ bool JfrOptionSet::configure(TRAPS) { if (HAS_PENDING_EXCEPTION) { java_lang_Throwable::print(PENDING_EXCEPTION, tty); CLEAR_PENDING_EXCEPTION; + tty->cr(); // java_lang_Throwable::print will not print '\n' return false; } return true; diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/JVM.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/JVM.java index b5aff49cbe0..ff84b31b0cd 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/JVM.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/JVM.java @@ -473,13 +473,26 @@ public final class JVM { public native void flush(); /** - * Sets the location of the disk repository, to be used at an emergency - * dump. + * Sets the location of the disk repository. * * @param dirText */ public native void setRepositoryLocation(String dirText); + /** + * Sets the path to emergency dump. + * + * @param dumpPathText + */ + public native void setDumpPath(String dumpPathText); + + /** + * Gets the path to emergency dump. + * + * @return The path to emergency dump. + */ + public native String getDumpPath(); + /** * Access to VM termination support. * diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/Options.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/Options.java index 4d430bebba2..204badc4242 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/Options.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/Options.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2021, 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 @@ -25,9 +25,16 @@ package jdk.jfr.internal; +import java.io.IOException; + +import jdk.jfr.internal.LogLevel; +import jdk.jfr.internal.LogTag; +import jdk.jfr.internal.Logger; import jdk.jfr.internal.SecuritySupport.SafePath; import jdk.internal.misc.Unsafe; +import static java.nio.file.LinkOption.*; + /** * Options that control Flight Recorder. * @@ -48,7 +55,7 @@ public final class Options { private static final int DEFAULT_STACK_DEPTH = 64; private static final boolean DEFAULT_SAMPLE_THREADS = true; private static final long DEFAULT_MAX_CHUNK_SIZE = 12 * 1024 * 1024; - private static final SafePath DEFAULT_DUMP_PATH = SecuritySupport.USER_HOME; + private static final SafePath DEFAULT_DUMP_PATH = null; private static long memorySize; private static long globalBufferSize; @@ -57,7 +64,6 @@ public final class Options { private static int stackDepth; private static boolean sampleThreads; private static long maxChunkSize; - private static SafePath dumpPath; static { final long pageSize = Unsafe.getUnsafe().pageSize(); @@ -113,12 +119,19 @@ public final class Options { globalBufferSize = globalBufsize; } - public static synchronized void setDumpPath(SafePath path) { - dumpPath = path; + public static synchronized void setDumpPath(SafePath path) throws IOException { + if (path != null) { + if (SecuritySupport.isWritable(path)) { + path = SecuritySupport.toRealPath(path, NOFOLLOW_LINKS); + } else { + throw new IOException("Cannot write JFR emergency dump to " + path.toString()); + } + } + jvm.setDumpPath(path == null ? null : path.toString()); } public static synchronized SafePath getDumpPath() { - return dumpPath; + return new SafePath(jvm.getDumpPath()); } public static synchronized void setStackDepth(Integer stackTraceDepth) { @@ -144,7 +157,11 @@ public final class Options { setMemorySize(DEFAULT_MEMORY_SIZE); setGlobalBufferSize(DEFAULT_GLOBAL_BUFFER_SIZE); setGlobalBufferCount(DEFAULT_GLOBAL_BUFFER_COUNT); - setDumpPath(DEFAULT_DUMP_PATH); + try { + setDumpPath(DEFAULT_DUMP_PATH); + } catch (IOException e) { + // Ignore (depends on default value in JVM: it would be NULL) + } setSampleThreads(DEFAULT_SAMPLE_THREADS); setStackDepth(DEFAULT_STACK_DEPTH); setThreadBufferSize(DEFAULT_THREAD_BUFFER_SIZE); diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/SecuritySupport.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/SecuritySupport.java index d761eb98c58..ae03bce313d 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/SecuritySupport.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/SecuritySupport.java @@ -41,6 +41,7 @@ import java.nio.channels.ReadableByteChannel; import java.nio.file.DirectoryStream; import java.nio.file.FileVisitResult; import java.nio.file.Files; +import java.nio.file.LinkOption; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.SimpleFileVisitor; @@ -77,7 +78,6 @@ public final class SecuritySupport { private static final Module JFR_MODULE = Event.class.getModule(); public static final SafePath JFC_DIRECTORY = getPathInProperty("java.home", "lib/jfr"); public static final FileAccess PRIVILEGED = new Privileged(); - static final SafePath USER_HOME = getPathInProperty("user.home", null); static final SafePath JAVA_IO_TMPDIR = getPathInProperty("java.io.tmpdir", null); static { @@ -365,8 +365,8 @@ public final class SecuritySupport { doPriviligedIO(() -> Files.walkFileTree(safePath.toPath(), new DirectoryCleaner())); } - static SafePath toRealPath(SafePath safePath) throws IOException { - return new SafePath(doPrivilegedIOWithReturn(() -> safePath.toPath().toRealPath())); + static SafePath toRealPath(SafePath safePath, LinkOption... options) throws IOException { + return new SafePath(doPrivilegedIOWithReturn(() -> safePath.toPath().toRealPath(options))); } static boolean existDirectory(SafePath directory) throws IOException { diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdConfigure.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdConfigure.java index 4cfc9ae4800..edcb1530474 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdConfigure.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdConfigure.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2021, 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 @@ -25,7 +25,7 @@ package jdk.jfr.internal.dcmd; - +import java.io.IOException; import jdk.jfr.FlightRecorder; import jdk.jfr.internal.LogLevel; @@ -106,7 +106,11 @@ final class DCmdConfigure extends AbstractDCmd { } if (dumpPath != null) { - Options.setDumpPath(new SafePath(dumpPath)); + try { + Options.setDumpPath(new SafePath(dumpPath)); + } catch (IOException e) { + throw new DCmdException("Could not set " + dumpPath + " to emergency dump path. " + e.getMessage(), e); + } Logger.log(LogTag.JFR, LogLevel.INFO, "Emergency dump path set to " + dumpPath); if (verbose) { printDumpPath(); @@ -183,6 +187,7 @@ final class DCmdConfigure extends AbstractDCmd { println("Current configuration:"); println(); printRepositoryPath(); + printDumpPath(); printStackDepth(); printGlobalBufferCount(); printGlobalBufferSize(); diff --git a/test/jdk/jdk/jfr/jvm/TestDumpOnCrash.java b/test/jdk/jdk/jfr/jvm/TestDumpOnCrash.java index 3869509b242..5cd1f435bfd 100644 --- a/test/jdk/jdk/jfr/jvm/TestDumpOnCrash.java +++ b/test/jdk/jdk/jfr/jvm/TestDumpOnCrash.java @@ -26,6 +26,7 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.ArrayList; import java.util.List; import jdk.internal.misc.Unsafe; @@ -74,22 +75,42 @@ public class TestDumpOnCrash { } public static void main(String[] args) throws Exception { + // Test without dumppath test(CrasherIllegalAccess.class, "", true); test(CrasherIllegalAccess.class, "", false); test(CrasherHalt.class, "", true); test(CrasherHalt.class, "", false); + // Test with dumppath + Path dumppath = Files.createTempDirectory(null); + try { + test(CrasherIllegalAccess.class, "", true, dumppath.toString()); + test(CrasherIllegalAccess.class, "", false, dumppath.toString()); + test(CrasherHalt.class, "", true, dumppath.toString()); + test(CrasherHalt.class, "", false, dumppath.toString()); + } finally { + dumppath.toFile().delete(); + } + // Test is excluded until 8219680 is fixed // @ignore 8219680 // test(CrasherSig.class, "FPE", true); } private static void test(Class crasher, String signal, boolean disk) throws Exception { + test(crasher, signal, disk, null); + } + + private static void test(Class crasher, String signal, boolean disk, String dumppath) throws Exception { + test(crasher, signal, disk, dumppath, dumppath); + } + + private static void test(Class crasher, String signal, boolean disk, String dumppath, String expectedPath) throws Exception { // The JVM may be in a state it can't recover from, so try three times // before concluding functionality is not working. for (int attempt = 0; attempt < ATTEMPTS; attempt++) { try { - verify(runProcess(crasher, signal, disk)); + verify(runProcess(crasher, signal, disk, dumppath), expectedPath); return; } catch (Exception e) { System.out.println("Attempt " + attempt + ". Verification failed:"); @@ -105,17 +126,19 @@ public class TestDumpOnCrash { throw new Exception(ATTEMPTS + " attempts with failure!"); } - private static long runProcess(Class crasher, String signal, boolean disk) throws Exception { + private static long runProcess(Class crasher, String signal, boolean disk, String dumppath) throws Exception { System.out.println("Test case for crasher " + crasher.getName()); - final String flightRecordingOptions = "dumponexit=true,disk=" + Boolean.toString(disk); - Process p = ProcessTools.createTestJvm( - "-Xmx64m", - "-XX:-CreateCoredumpOnCrash", - "--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED", - "-XX:StartFlightRecording:" + flightRecordingOptions, - crasher.getName(), - signal) - .start(); + List options = new ArrayList<>(); + options.add("-Xmx64m"); + options.add("-XX:-CreateCoredumpOnCrash"); + options.add("--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED"); + options.add("-XX:StartFlightRecording:dumponexit=true,disk=" + Boolean.toString(disk)); + if (dumppath != null) { + options.add("-XX:FlightRecorderOptions=dumppath=" + dumppath); + } + options.add(crasher.getName()); + options.add(signal); + Process p = ProcessTools.createTestJvm(options).start(); OutputAnalyzer output = new OutputAnalyzer(p); System.out.println("========== Crasher process output:"); @@ -125,9 +148,10 @@ public class TestDumpOnCrash { return p.pid(); } - private static void verify(long pid) throws IOException { + private static void verify(long pid, String dumppath) throws IOException { String fileName = "hs_err_pid" + pid + ".jfr"; - Path file = Paths.get(fileName).toAbsolutePath().normalize(); + Path file = (dumppath == null) ? Paths.get(fileName) : Paths.get(dumppath, fileName); + file = file.toAbsolutePath().normalize(); Asserts.assertTrue(Files.exists(file), "No emergency jfr recording file " + file + " exists"); Asserts.assertNotEquals(Files.size(file), 0L, "File length 0. Should at least be some bytes"); -- GitLab From b2638e5efd3c2b1abe790ab59baf28afa308614f Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Tue, 7 Dec 2021 11:32:17 +0000 Subject: [PATCH 021/671] 8244602: Add JTREG_REPEAT_COUNT to repeat execution of a test Reviewed-by: ihse, erikj --- doc/testing.html | 2 ++ doc/testing.md | 4 ++++ make/RunTests.gmk | 23 ++++++++++++++++++++++- 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/doc/testing.html b/doc/testing.html index 1146400df80..f647af91934 100644 --- a/doc/testing.html +++ b/doc/testing.html @@ -194,6 +194,8 @@ TEST FAILURE

Generate AOT modules before testing for the specified module, or set of modules. If multiple modules are specified, they should be separated by space (or, to help avoid quoting issues, the special value %20).

RETRY_COUNT

Retry failed tests up to a set number of times. Defaults to 0.

+

REPEAT_COUNT

+

Repeat the tests for a set number of times. Defaults to 0.

Gtest keywords

REPEAT

The number of times to repeat the tests (--gtest_repeat).

diff --git a/doc/testing.md b/doc/testing.md index 5dde4d11804..bba5ae0941c 100644 --- a/doc/testing.md +++ b/doc/testing.md @@ -421,6 +421,10 @@ modules. If multiple modules are specified, they should be separated by space Retry failed tests up to a set number of times. Defaults to 0. +#### REPEAT_COUNT + +Repeat the tests for a set number of times. Defaults to 0. + ### Gtest keywords #### REPEAT diff --git a/make/RunTests.gmk b/make/RunTests.gmk index a2c8ea8101e..81540266ec0 100644 --- a/make/RunTests.gmk +++ b/make/RunTests.gmk @@ -200,7 +200,7 @@ $(eval $(call SetTestOpt,FAILURE_HANDLER_TIMEOUT,JTREG)) $(eval $(call ParseKeywordVariable, JTREG, \ SINGLE_KEYWORDS := JOBS TIMEOUT_FACTOR FAILURE_HANDLER_TIMEOUT \ TEST_MODE ASSERT VERBOSE RETAIN MAX_MEM RUN_PROBLEM_LISTS \ - RETRY_COUNT MAX_OUTPUT $(CUSTOM_JTREG_SINGLE_KEYWORDS), \ + RETRY_COUNT REPEAT_COUNT MAX_OUTPUT $(CUSTOM_JTREG_SINGLE_KEYWORDS), \ STRING_KEYWORDS := OPTIONS JAVA_OPTIONS VM_OPTIONS KEYWORDS \ EXTRA_PROBLEM_LISTS LAUNCHER_OPTIONS \ $(CUSTOM_JTREG_STRING_KEYWORDS), \ @@ -745,6 +745,15 @@ define SetupRunJtregTestBody JTREG_RETAIN ?= fail,error JTREG_RUN_PROBLEM_LISTS ?= false JTREG_RETRY_COUNT ?= 0 + JTREG_REPEAT_COUNT ?= 0 + + ifneq ($$(JTREG_RETRY_COUNT), 0) + ifneq ($$(JTREG_REPEAT_COUNT), 0) + $$(info Error: Cannot use both JTREG_RETRY_COUNT and JTREG_REPEAT_COUNT together.) + $$(info Please choose one or the other.) + $$(error Cannot continue) + endif + endif ifneq ($$(JTREG_LAUNCHER_OPTIONS), ) $1_JTREG_LAUNCHER_OPTIONS += $$(JTREG_LAUNCHER_OPTIONS) @@ -869,6 +878,18 @@ define SetupRunJtregTestBody done endif + ifneq ($$(JTREG_REPEAT_COUNT), 0) + $1_COMMAND_LINE := \ + for i in {1..$$(JTREG_REPEAT_COUNT)}; do \ + $$(PRINTF) "\nRepeating Jtreg run: $$$$i out of $$(JTREG_REPEAT_COUNT)\n"; \ + $$($1_COMMAND_LINE); \ + if [ "`$$(CAT) $$($1_EXITCODE)`" != "0" ]; then \ + $$(PRINTF) "\nFailures detected, no more repeats.\n"; \ + break; \ + fi; \ + done + endif + run-test-$1: pre-run-test clean-workdir-$1 $$(call LogWarn) $$(call LogWarn, Running test '$$($1_TEST)') -- GitLab From 44fcee3830466e34656ea553d10a60fc382c85a6 Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Tue, 7 Dec 2021 13:34:35 +0000 Subject: [PATCH 022/671] 8278289: Drop G1BlockOffsetTablePart::_object_can_span Reviewed-by: tschatzl, sjohanss, mli --- src/hotspot/share/gc/g1/g1BlockOffsetTable.cpp | 7 ------- src/hotspot/share/gc/g1/g1BlockOffsetTable.hpp | 4 ---- src/hotspot/share/gc/g1/g1BlockOffsetTable.inline.hpp | 11 ++++++++--- src/hotspot/share/gc/g1/heapRegion.cpp | 4 ---- 4 files changed, 8 insertions(+), 18 deletions(-) diff --git a/src/hotspot/share/gc/g1/g1BlockOffsetTable.cpp b/src/hotspot/share/gc/g1/g1BlockOffsetTable.cpp index 08e7dd5f1d4..1c4bc3d3332 100644 --- a/src/hotspot/share/gc/g1/g1BlockOffsetTable.cpp +++ b/src/hotspot/share/gc/g1/g1BlockOffsetTable.cpp @@ -75,7 +75,6 @@ void G1BlockOffsetTable::check_index(size_t index, const char* msg) const { G1BlockOffsetTablePart::G1BlockOffsetTablePart(G1BlockOffsetTable* array, HeapRegion* hr) : _next_offset_threshold(NULL), - DEBUG_ONLY(_object_can_span(false) COMMA) _bot(array), _hr(hr) { @@ -331,12 +330,6 @@ void G1BlockOffsetTablePart::verify() const { } } -#ifdef ASSERT -void G1BlockOffsetTablePart::set_object_can_span(bool can_span) { - _object_can_span = can_span; -} -#endif - #ifndef PRODUCT void G1BlockOffsetTablePart::print_on(outputStream* out) { size_t from_index = _bot->index_for(_hr->bottom()); diff --git a/src/hotspot/share/gc/g1/g1BlockOffsetTable.hpp b/src/hotspot/share/gc/g1/g1BlockOffsetTable.hpp index fa7658e185e..1a13ad68c07 100644 --- a/src/hotspot/share/gc/g1/g1BlockOffsetTable.hpp +++ b/src/hotspot/share/gc/g1/g1BlockOffsetTable.hpp @@ -114,9 +114,6 @@ private: // allocation boundary at which offset array must be updated HeapWord* _next_offset_threshold; - // Indicates if an object can span into this G1BlockOffsetTablePart. - debug_only(bool _object_can_span;) - // This is the global BlockOffsetTable. G1BlockOffsetTable* _bot; @@ -212,7 +209,6 @@ public: } void set_for_starts_humongous(HeapWord* obj_top, size_t fill_size); - void set_object_can_span(bool can_span) NOT_DEBUG_RETURN; void print_on(outputStream* out) PRODUCT_RETURN; }; diff --git a/src/hotspot/share/gc/g1/g1BlockOffsetTable.inline.hpp b/src/hotspot/share/gc/g1/g1BlockOffsetTable.inline.hpp index aa0c004a302..c606d9393f5 100644 --- a/src/hotspot/share/gc/g1/g1BlockOffsetTable.inline.hpp +++ b/src/hotspot/share/gc/g1/g1BlockOffsetTable.inline.hpp @@ -113,9 +113,14 @@ inline size_t G1BlockOffsetTablePart::block_size(const HeapWord* p) const { } inline HeapWord* G1BlockOffsetTablePart::block_at_or_preceding(const void* addr) const { - assert(_object_can_span || _bot->offset_array(_bot->index_for(_hr->bottom())) == 0, - "Object crossed region boundary, found offset %u instead of 0", - (uint) _bot->offset_array(_bot->index_for(_hr->bottom()))); +#ifdef ASSERT + if (!_hr->is_continues_humongous()) { + // For non-ContinuesHumongous regions, the first obj always starts from bottom. + u_char offset = _bot->offset_array(_bot->index_for(_hr->bottom())); + assert(offset == 0, "Found offset %u instead of 0 for region %u %s", + offset, _hr->hrm_index(), _hr->get_short_type_str()); + } +#endif size_t index = _bot->index_for(addr); diff --git a/src/hotspot/share/gc/g1/heapRegion.cpp b/src/hotspot/share/gc/g1/heapRegion.cpp index ca85f50ae25..bcf240336ce 100644 --- a/src/hotspot/share/gc/g1/heapRegion.cpp +++ b/src/hotspot/share/gc/g1/heapRegion.cpp @@ -214,8 +214,6 @@ void HeapRegion::set_continues_humongous(HeapRegion* first_hr) { report_region_type_change(G1HeapRegionTraceType::ContinuesHumongous); _type.set_continues_humongous(); _humongous_start_region = first_hr; - - _bot_part.set_object_can_span(true); } void HeapRegion::clear_humongous() { @@ -223,8 +221,6 @@ void HeapRegion::clear_humongous() { assert(capacity() == HeapRegion::GrainBytes, "pre-condition"); _humongous_start_region = NULL; - - _bot_part.set_object_can_span(false); } HeapRegion::HeapRegion(uint hrm_index, -- GitLab From 35361270cb3aae9fa560736f8d05f1b258704c87 Mon Sep 17 00:00:00 2001 From: Thomas Stuefe Date: Tue, 7 Dec 2021 14:15:04 +0000 Subject: [PATCH 023/671] 8277383: VM.metaspace optionally show chunk freelist details Reviewed-by: coleenp, shade --- .../share/memory/metaspace/metaspaceDCmd.cpp | 3 +++ .../share/memory/metaspace/metaspaceDCmd.hpp | 1 + .../memory/metaspace/metaspaceReporter.cpp | 18 +++++++++++++++ .../memory/metaspace/metaspaceReporter.hpp | 4 +++- .../runtime/Metaspace/PrintMetaspaceDcmd.java | 23 +++++++++++++++++++ 5 files changed, 48 insertions(+), 1 deletion(-) diff --git a/src/hotspot/share/memory/metaspace/metaspaceDCmd.cpp b/src/hotspot/share/memory/metaspace/metaspaceDCmd.cpp index 22e623b2356..96814781377 100644 --- a/src/hotspot/share/memory/metaspace/metaspaceDCmd.cpp +++ b/src/hotspot/share/memory/metaspace/metaspaceDCmd.cpp @@ -42,6 +42,7 @@ MetaspaceDCmd::MetaspaceDCmd(outputStream* output, bool heap) : _by_spacetype("by-spacetype", "Break down numbers by loader type.", "BOOLEAN", false, "false"), _by_chunktype("by-chunktype", "Break down numbers by chunk type.", "BOOLEAN", false, "false"), _show_vslist("vslist", "Shows details about the underlying virtual space.", "BOOLEAN", false, "false"), + _show_chunkfreelist("chunkfreelist", "Shows details about global chunk free lists (ChunkManager).", "BOOLEAN", false, "false"), _scale("scale", "Memory usage in which to scale. Valid values are: 1, KB, MB or GB (fixed scale) " "or \"dynamic\" for a dynamically chosen scale.", "STRING", false, "dynamic"), @@ -53,6 +54,7 @@ MetaspaceDCmd::MetaspaceDCmd(outputStream* output, bool heap) : _dcmdparser.add_dcmd_option(&_by_chunktype); _dcmdparser.add_dcmd_option(&_by_spacetype); _dcmdparser.add_dcmd_option(&_show_vslist); + _dcmdparser.add_dcmd_option(&_show_chunkfreelist); _dcmdparser.add_dcmd_option(&_scale); } @@ -96,6 +98,7 @@ void MetaspaceDCmd::execute(DCmdSource source, TRAPS) { if (_by_chunktype.value()) flags |= (int)MetaspaceReporter::Option::BreakDownByChunkType; if (_by_spacetype.value()) flags |= (int)MetaspaceReporter::Option::BreakDownBySpaceType; if (_show_vslist.value()) flags |= (int)MetaspaceReporter::Option::ShowVSList; + if (_show_chunkfreelist.value()) flags |= (int)MetaspaceReporter::Option::ShowChunkFreeList; VM_PrintMetadata op(output(), scale, flags); VMThread::execute(&op); } diff --git a/src/hotspot/share/memory/metaspace/metaspaceDCmd.hpp b/src/hotspot/share/memory/metaspace/metaspaceDCmd.hpp index 0c0f49795d5..329dd6025d7 100644 --- a/src/hotspot/share/memory/metaspace/metaspaceDCmd.hpp +++ b/src/hotspot/share/memory/metaspace/metaspaceDCmd.hpp @@ -38,6 +38,7 @@ class MetaspaceDCmd : public DCmdWithParser { DCmdArgument _by_spacetype; DCmdArgument _by_chunktype; DCmdArgument _show_vslist; + DCmdArgument _show_chunkfreelist; DCmdArgument _scale; DCmdArgument _show_classes; public: diff --git a/src/hotspot/share/memory/metaspace/metaspaceReporter.cpp b/src/hotspot/share/memory/metaspace/metaspaceReporter.cpp index d856883aaec..2bdc9019acf 100644 --- a/src/hotspot/share/memory/metaspace/metaspaceReporter.cpp +++ b/src/hotspot/share/memory/metaspace/metaspaceReporter.cpp @@ -300,6 +300,24 @@ void MetaspaceReporter::print_report(outputStream* out, size_t scale, int flags) out->cr(); } + // -- Print Chunkmanager details. + if ((flags & (int)Option::ShowChunkFreeList) > 0) { + out->cr(); + out->print_cr("Chunk freelist details:"); + if (Metaspace::using_class_space()) { + out->print_cr(" Non-Class:"); + } + ChunkManager::chunkmanager_nonclass()->print_on(out); + out->cr(); + if (Metaspace::using_class_space()) { + out->print_cr(" Class:"); + ChunkManager::chunkmanager_class()->print_on(out); + out->cr(); + } + } + out->cr(); + + //////////// Waste section /////////////////////////// // As a convenience, print a summary of common waste. out->cr(); diff --git a/src/hotspot/share/memory/metaspace/metaspaceReporter.hpp b/src/hotspot/share/memory/metaspace/metaspaceReporter.hpp index 45c76b69e9d..2aab2063379 100644 --- a/src/hotspot/share/memory/metaspace/metaspaceReporter.hpp +++ b/src/hotspot/share/memory/metaspace/metaspaceReporter.hpp @@ -44,7 +44,9 @@ public: // Print details about the underlying virtual spaces. ShowVSList = (1 << 3), // If show_loaders: show loaded classes for each loader. - ShowClasses = (1 << 4) + ShowClasses = (1 << 4), + // Print details about the underlying virtual spaces. + ShowChunkFreeList = (1 << 5) }; // This will print out a basic metaspace usage report but diff --git a/test/hotspot/jtreg/runtime/Metaspace/PrintMetaspaceDcmd.java b/test/hotspot/jtreg/runtime/Metaspace/PrintMetaspaceDcmd.java index 413a911e700..d90a49a0adb 100644 --- a/test/hotspot/jtreg/runtime/Metaspace/PrintMetaspaceDcmd.java +++ b/test/hotspot/jtreg/runtime/Metaspace/PrintMetaspaceDcmd.java @@ -168,6 +168,29 @@ public class PrintMetaspaceDcmd { output.shouldContain("Virtual space list"); output.shouldMatch("node.*reserved.*committed.*used.*"); + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.metaspace", "chunkfreelist"}); + // Output should look somewhat like this... + // vvvvvvvvvvvvvvvv + // Chunk freelist details: + // Non-Class: + // cm non-class-space: 5 chunks, total word size: 402944. + // -- List[lv00]: empty + // -- List[lv01]: - - total : 1 chunks. + // -- List[lv02]: - - total : 1 chunks. + // -- List[lv03]: empty + // ..... + // + // total chunks: 5, total word size: 402944. + // ^^^^^^^^^^^^^^^^^ + // .... but the actual number of chunks in the freelist is difficult to predict and may be low or zero since + // no class unloading happened yet. + output = new OutputAnalyzer(pb.start()); + output.shouldHaveExitValue(0); + output.shouldContain("Chunk freelist details:"); + // ... but we should see at least one one chunk somewhere, the list should never be empty. + output.shouldMatch(".*-- List\\[lv00\\].*"); + output.shouldMatch(".*total chunks.*total word size.*"); + // Test with different scales pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.metaspace", "scale=G"}); output = new OutputAnalyzer(pb.start()); -- GitLab From 56ca66e86f848d3790115aa2faec632c226d8cd2 Mon Sep 17 00:00:00 2001 From: Alan Bateman Date: Tue, 7 Dec 2021 14:21:47 +0000 Subject: [PATCH 024/671] 8277863: Deprecate sun.misc.Unsafe methods that return offsets Reviewed-by: psandoz, mchung --- .../share/classes/sun/misc/Unsafe.java | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/jdk.unsupported/share/classes/sun/misc/Unsafe.java b/src/jdk.unsupported/share/classes/sun/misc/Unsafe.java index e0ab5f3dffa..2f8d397c6c9 100644 --- a/src/jdk.unsupported/share/classes/sun/misc/Unsafe.java +++ b/src/jdk.unsupported/share/classes/sun/misc/Unsafe.java @@ -633,8 +633,15 @@ public final class Unsafe { * the field locations in a form usable by {@link #getInt(Object,long)}. * Therefore, code which will be ported to such JVMs on 64-bit platforms * must preserve all bits of static field offsets. + * + * @deprecated The guarantee that a field will always have the same offset + * and base may not be true in a future release. The ability to provide an + * offset and object reference to a heap memory accessor will be removed + * in a future release. Use {@link java.lang.invoke.VarHandle} instead. + * * @see #getInt(Object, long) */ + @Deprecated(since="18") @ForceInline public long objectFieldOffset(Field f) { if (f == null) { @@ -665,8 +672,15 @@ public final class Unsafe { * a few bits to encode an offset within a non-array object, * However, for consistency with other methods in this class, * this method reports its result as a long value. + * + * @deprecated The guarantee that a field will always have the same offset + * and base may not be true in a future release. The ability to provide an + * offset and object reference to a heap memory accessor will be removed + * in a future release. Use {@link java.lang.invoke.VarHandle} instead. + * * @see #getInt(Object, long) */ + @Deprecated(since="18") @ForceInline public long staticFieldOffset(Field f) { if (f == null) { @@ -691,7 +705,13 @@ public final class Unsafe { * which is a "cookie", not guaranteed to be a real Object, and it should * not be used in any way except as argument to the get and put routines in * this class. + * + * @deprecated The guarantee that a field will always have the same offset + * and base may not be true in a future release. The ability to provide an + * offset and object reference to a heap memory accessor will be removed + * in a future release. Use {@link java.lang.invoke.VarHandle} instead. */ + @Deprecated(since="18") @ForceInline public Object staticFieldBase(Field f) { if (f == null) { -- GitLab From 69d8669fb3f1e4db2fbb3366a1349dd0285f5b0f Mon Sep 17 00:00:00 2001 From: Alan Bateman Date: Tue, 7 Dec 2021 14:22:35 +0000 Subject: [PATCH 025/671] 8278339: ServerSocket::isClosed may return false after accept throws Reviewed-by: dfuchs --- .../share/classes/java/net/ServerSocket.java | 13 ++- .../ServerSocket/IsClosedAfterAsyncClose.java | 81 +++++++++++++++++++ 2 files changed, 86 insertions(+), 8 deletions(-) create mode 100644 test/jdk/java/net/ServerSocket/IsClosedAfterAsyncClose.java diff --git a/src/java.base/share/classes/java/net/ServerSocket.java b/src/java.base/share/classes/java/net/ServerSocket.java index 7c567d3e8c7..9441e6476e3 100644 --- a/src/java.base/share/classes/java/net/ServerSocket.java +++ b/src/java.base/share/classes/java/net/ServerSocket.java @@ -711,15 +711,12 @@ public class ServerSocket implements java.io.Closeable { public void close() throws IOException { synchronized (stateLock) { if (!closed) { - try { - // close underlying socket if created - if (created) { - impl.close(); - } - } finally { - closed = true; - } + closed = true; + // close underlying socket if created + if (created) { + impl.close(); + } } } } diff --git a/test/jdk/java/net/ServerSocket/IsClosedAfterAsyncClose.java b/test/jdk/java/net/ServerSocket/IsClosedAfterAsyncClose.java new file mode 100644 index 00000000000..1b777932900 --- /dev/null +++ b/test/jdk/java/net/ServerSocket/IsClosedAfterAsyncClose.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2021, 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. + */ + +/** + * @test + * @bug 8278339 + * @summary Test that ServerSocket::isClosed returns true after async close + */ + +import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.ServerSocket; +import java.net.Socket; + +public class IsClosedAfterAsyncClose { + + private static final int ITERATIONS = 100; + + public static void main(String[] args) throws Exception { + for (int i = 0; i < ITERATIONS; i++) { + System.out.printf("Test %d...%n", i); + + // create listener bound to the loopback address + ServerSocket listener = new ServerSocket(); + InetAddress loopback = InetAddress.getLoopbackAddress(); + listener.bind(new InetSocketAddress(loopback, 0)); + + // task to close listener after a delay + Runnable closeListener = () -> { + try { + Thread.sleep(100); + listener.close(); + } catch (Exception e) { + e.printStackTrace(); + } + }; + + // main thread blocks in accept. When listener is closed then accept + // should wakeup with an IOException and isClosed should be true. + try (listener) { + Thread closer = new Thread(closeListener); + closer.start(); + try { + while (true) { + Socket s = listener.accept(); + // close spurious connection + s.close(); + } + } catch (IOException ioe) { + if (!listener.isClosed()) { + throw new RuntimeException("isClosed returned false!!"); + } + } finally { + closer.join(); + } + } + } + } +} + -- GitLab From 5b81d5eeb4124ff04dc3b9a96d0b53edcfa07c5f Mon Sep 17 00:00:00 2001 From: Roman Kennke Date: Tue, 7 Dec 2021 14:41:42 +0000 Subject: [PATCH 026/671] 8276901: Implement UseHeavyMonitors consistently Reviewed-by: coleenp, mdoerr, dcubed --- src/hotspot/cpu/aarch64/aarch64.ad | 91 +++++++------ .../cpu/aarch64/c1_LIRAssembler_aarch64.cpp | 8 +- .../cpu/aarch64/sharedRuntime_aarch64.cpp | 87 ++++++------ src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp | 2 +- src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp | 4 +- src/hotspot/cpu/ppc/macroAssembler_ppc.cpp | 91 +++++++------ src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp | 2 +- src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp | 8 +- src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp | 58 ++++---- src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp | 103 ++++++++------- src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp | 100 +++++++------- src/hotspot/share/c1/c1_LIRGenerator.cpp | 2 +- src/hotspot/share/c1/c1_Runtime1.cpp | 2 +- src/hotspot/share/c1/c1_globals.hpp | 3 - src/hotspot/share/runtime/arguments.cpp | 17 +++ src/hotspot/share/runtime/globals.hpp | 7 +- src/hotspot/share/runtime/synchronizer.cpp | 124 ++++++++++-------- .../CommandLine/VMDeprecatedOptions.java | 43 +++--- .../ConcurrentHashMap/MapLoops.java | 8 ++ 19 files changed, 442 insertions(+), 318 deletions(-) diff --git a/src/hotspot/cpu/aarch64/aarch64.ad b/src/hotspot/cpu/aarch64/aarch64.ad index 1f1a2172934..4e6ed4832bf 100644 --- a/src/hotspot/cpu/aarch64/aarch64.ad +++ b/src/hotspot/cpu/aarch64/aarch64.ad @@ -3906,37 +3906,40 @@ encode %{ // Check for existing monitor __ tbnz(disp_hdr, exact_log2(markWord::monitor_value), object_has_monitor); - // Set tmp to be (markWord of object | UNLOCK_VALUE). - __ orr(tmp, disp_hdr, markWord::unlocked_value); - - // Initialize the box. (Must happen before we update the object mark!) - __ str(tmp, Address(box, BasicLock::displaced_header_offset_in_bytes())); - - // Compare object markWord with an unlocked value (tmp) and if - // equal exchange the stack address of our box with object markWord. - // On failure disp_hdr contains the possibly locked markWord. - __ cmpxchg(oop, tmp, box, Assembler::xword, /*acquire*/ true, - /*release*/ true, /*weak*/ false, disp_hdr); - __ br(Assembler::EQ, cont); - - assert(oopDesc::mark_offset_in_bytes() == 0, "offset of _mark is not 0"); - - // If the compare-and-exchange succeeded, then we found an unlocked - // object, will have now locked it will continue at label cont - - __ bind(cas_failed); - // We did not see an unlocked object so try the fast recursive case. - - // Check if the owner is self by comparing the value in the - // markWord of object (disp_hdr) with the stack pointer. - __ mov(rscratch1, sp); - __ sub(disp_hdr, disp_hdr, rscratch1); - __ mov(tmp, (address) (~(os::vm_page_size()-1) | markWord::lock_mask_in_place)); - // If condition is true we are cont and hence we can store 0 as the - // displaced header in the box, which indicates that it is a recursive lock. - __ ands(tmp/*==0?*/, disp_hdr, tmp); // Sets flags for result - __ str(tmp/*==0, perhaps*/, Address(box, BasicLock::displaced_header_offset_in_bytes())); - + if (!UseHeavyMonitors) { + // Set tmp to be (markWord of object | UNLOCK_VALUE). + __ orr(tmp, disp_hdr, markWord::unlocked_value); + + // Initialize the box. (Must happen before we update the object mark!) + __ str(tmp, Address(box, BasicLock::displaced_header_offset_in_bytes())); + + // Compare object markWord with an unlocked value (tmp) and if + // equal exchange the stack address of our box with object markWord. + // On failure disp_hdr contains the possibly locked markWord. + __ cmpxchg(oop, tmp, box, Assembler::xword, /*acquire*/ true, + /*release*/ true, /*weak*/ false, disp_hdr); + __ br(Assembler::EQ, cont); + + assert(oopDesc::mark_offset_in_bytes() == 0, "offset of _mark is not 0"); + + // If the compare-and-exchange succeeded, then we found an unlocked + // object, will have now locked it will continue at label cont + + __ bind(cas_failed); + // We did not see an unlocked object so try the fast recursive case. + + // Check if the owner is self by comparing the value in the + // markWord of object (disp_hdr) with the stack pointer. + __ mov(rscratch1, sp); + __ sub(disp_hdr, disp_hdr, rscratch1); + __ mov(tmp, (address) (~(os::vm_page_size()-1) | markWord::lock_mask_in_place)); + // If condition is true we are cont and hence we can store 0 as the + // displaced header in the box, which indicates that it is a recursive lock. + __ ands(tmp/*==0?*/, disp_hdr, tmp); // Sets flags for result + __ str(tmp/*==0, perhaps*/, Address(box, BasicLock::displaced_header_offset_in_bytes())); + } else { + __ tst(oop, oop); // Set NE to indicate 'failure' -> take slow-path. We know that oop != 0. + } __ b(cont); // Handle existing monitor. @@ -3982,23 +3985,29 @@ encode %{ assert_different_registers(oop, box, tmp, disp_hdr); - // Find the lock address and load the displaced header from the stack. - __ ldr(disp_hdr, Address(box, BasicLock::displaced_header_offset_in_bytes())); + if (!UseHeavyMonitors) { + // Find the lock address and load the displaced header from the stack. + __ ldr(disp_hdr, Address(box, BasicLock::displaced_header_offset_in_bytes())); - // If the displaced header is 0, we have a recursive unlock. - __ cmp(disp_hdr, zr); - __ br(Assembler::EQ, cont); + // If the displaced header is 0, we have a recursive unlock. + __ cmp(disp_hdr, zr); + __ br(Assembler::EQ, cont); + } // Handle existing monitor. __ ldr(tmp, Address(oop, oopDesc::mark_offset_in_bytes())); __ tbnz(disp_hdr, exact_log2(markWord::monitor_value), object_has_monitor); - // Check if it is still a light weight lock, this is is true if we - // see the stack address of the basicLock in the markWord of the - // object. + if (!UseHeavyMonitors) { + // Check if it is still a light weight lock, this is is true if we + // see the stack address of the basicLock in the markWord of the + // object. - __ cmpxchg(oop, box, disp_hdr, Assembler::xword, /*acquire*/ false, - /*release*/ true, /*weak*/ false, tmp); + __ cmpxchg(oop, box, disp_hdr, Assembler::xword, /*acquire*/ false, + /*release*/ true, /*weak*/ false, tmp); + } else { + __ tst(oop, oop); // Set NE to indicate 'failure' -> take slow-path. We know that oop != 0. + } __ b(cont); assert(oopDesc::mark_offset_in_bytes() == 0, "offset of _mark is not 0"); diff --git a/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp index fead8af7d1b..6f91b1539a6 100644 --- a/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp @@ -438,7 +438,11 @@ int LIR_Assembler::emit_unwind_handler() { if (method()->is_synchronized()) { monitor_address(0, FrameMap::r0_opr); stub = new MonitorExitStub(FrameMap::r0_opr, true, 0); - __ unlock_object(r5, r4, r0, *stub->entry()); + if (UseHeavyMonitors) { + __ b(*stub->entry()); + } else { + __ unlock_object(r5, r4, r0, *stub->entry()); + } __ bind(*stub->continuation()); } @@ -2562,7 +2566,7 @@ void LIR_Assembler::emit_lock(LIR_OpLock* op) { Register obj = op->obj_opr()->as_register(); // may not be an oop Register hdr = op->hdr_opr()->as_register(); Register lock = op->lock_opr()->as_register(); - if (!UseFastLocking) { + if (UseHeavyMonitors) { __ b(*op->stub()->entry()); } else if (op->code() == lir_lock) { assert(BasicLock::displaced_header_offset_in_bytes() == 0, "lock_reg must point to the displaced header"); diff --git a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp index 5c80566aead..254cde16e09 100644 --- a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp @@ -1642,39 +1642,42 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, // Load the oop from the handle __ ldr(obj_reg, Address(oop_handle_reg, 0)); - // Load (object->mark() | 1) into swap_reg %r0 - __ ldr(rscratch1, Address(obj_reg, oopDesc::mark_offset_in_bytes())); - __ orr(swap_reg, rscratch1, 1); + if (!UseHeavyMonitors) { + // Load (object->mark() | 1) into swap_reg %r0 + __ ldr(rscratch1, Address(obj_reg, oopDesc::mark_offset_in_bytes())); + __ orr(swap_reg, rscratch1, 1); - // Save (object->mark() | 1) into BasicLock's displaced header - __ str(swap_reg, Address(lock_reg, mark_word_offset)); + // Save (object->mark() | 1) into BasicLock's displaced header + __ str(swap_reg, Address(lock_reg, mark_word_offset)); - // src -> dest iff dest == r0 else r0 <- dest - { Label here; - __ cmpxchg_obj_header(r0, lock_reg, obj_reg, rscratch1, lock_done, /*fallthrough*/NULL); - } + // src -> dest iff dest == r0 else r0 <- dest + { Label here; + __ cmpxchg_obj_header(r0, lock_reg, obj_reg, rscratch1, lock_done, /*fallthrough*/NULL); + } - // Hmm should this move to the slow path code area??? + // Hmm should this move to the slow path code area??? - // Test if the oopMark is an obvious stack pointer, i.e., - // 1) (mark & 3) == 0, and - // 2) sp <= mark < mark + os::pagesize() - // These 3 tests can be done by evaluating the following - // expression: ((mark - sp) & (3 - os::vm_page_size())), - // assuming both stack pointer and pagesize have their - // least significant 2 bits clear. - // NOTE: the oopMark is in swap_reg %r0 as the result of cmpxchg + // Test if the oopMark is an obvious stack pointer, i.e., + // 1) (mark & 3) == 0, and + // 2) sp <= mark < mark + os::pagesize() + // These 3 tests can be done by evaluating the following + // expression: ((mark - sp) & (3 - os::vm_page_size())), + // assuming both stack pointer and pagesize have their + // least significant 2 bits clear. + // NOTE: the oopMark is in swap_reg %r0 as the result of cmpxchg - __ sub(swap_reg, sp, swap_reg); - __ neg(swap_reg, swap_reg); - __ ands(swap_reg, swap_reg, 3 - os::vm_page_size()); + __ sub(swap_reg, sp, swap_reg); + __ neg(swap_reg, swap_reg); + __ ands(swap_reg, swap_reg, 3 - os::vm_page_size()); - // Save the test result, for recursive case, the result is zero - __ str(swap_reg, Address(lock_reg, mark_word_offset)); - __ br(Assembler::NE, slow_path_lock); + // Save the test result, for recursive case, the result is zero + __ str(swap_reg, Address(lock_reg, mark_word_offset)); + __ br(Assembler::NE, slow_path_lock); + } else { + __ b(slow_path_lock); + } // Slow path will re-enter here - __ bind(lock_done); } @@ -1775,26 +1778,30 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, __ ldr(obj_reg, Address(oop_handle_reg, 0)); Label done; - // Simple recursive lock? - __ ldr(rscratch1, Address(sp, lock_slot_offset * VMRegImpl::stack_slot_size)); - __ cbz(rscratch1, done); + if (!UseHeavyMonitors) { + // Simple recursive lock? + __ ldr(rscratch1, Address(sp, lock_slot_offset * VMRegImpl::stack_slot_size)); + __ cbz(rscratch1, done); - // Must save r0 if if it is live now because cmpxchg must use it - if (ret_type != T_FLOAT && ret_type != T_DOUBLE && ret_type != T_VOID) { - save_native_result(masm, ret_type, stack_slots); - } + // Must save r0 if if it is live now because cmpxchg must use it + if (ret_type != T_FLOAT && ret_type != T_DOUBLE && ret_type != T_VOID) { + save_native_result(masm, ret_type, stack_slots); + } - // get address of the stack lock - __ lea(r0, Address(sp, lock_slot_offset * VMRegImpl::stack_slot_size)); - // get old displaced header - __ ldr(old_hdr, Address(r0, 0)); + // get address of the stack lock + __ lea(r0, Address(sp, lock_slot_offset * VMRegImpl::stack_slot_size)); + // get old displaced header + __ ldr(old_hdr, Address(r0, 0)); - // Atomic swap old header if oop still contains the stack lock - Label succeed; - __ cmpxchg_obj_header(r0, old_hdr, obj_reg, rscratch1, succeed, &slow_path_unlock); - __ bind(succeed); + // Atomic swap old header if oop still contains the stack lock + Label succeed; + __ cmpxchg_obj_header(r0, old_hdr, obj_reg, rscratch1, succeed, &slow_path_unlock); + __ bind(succeed); + } else { + __ b(slow_path_unlock); + } // slow path re-enters here __ bind(unlock_done); diff --git a/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp b/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp index 3ec2db3b313..95fab38a584 100644 --- a/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp +++ b/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp @@ -2425,7 +2425,7 @@ void LIR_Assembler::emit_lock(LIR_OpLock* op) { Register hdr = op->hdr_opr()->as_pointer_register(); Register lock = op->lock_opr()->as_pointer_register(); - if (!UseFastLocking) { + if (UseHeavyMonitors) { __ b(*op->stub()->entry()); } else if (op->code() == lir_lock) { assert(BasicLock::displaced_header_offset_in_bytes() == 0, "lock_reg must point to the displaced header"); diff --git a/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp b/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp index 23e03cb36e3..2d5ac43f442 100644 --- a/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp @@ -2689,7 +2689,7 @@ void LIR_Assembler::emit_lock(LIR_OpLock* op) { // Obj may not be an oop. if (op->code() == lir_lock) { MonitorEnterStub* stub = (MonitorEnterStub*)op->stub(); - if (UseFastLocking) { + if (!UseHeavyMonitors) { assert(BasicLock::displaced_header_offset_in_bytes() == 0, "lock_reg must point to the displaced header"); // Add debug info for NullPointerException only if one is possible. if (op->info() != NULL) { @@ -2711,7 +2711,7 @@ void LIR_Assembler::emit_lock(LIR_OpLock* op) { } } else { assert (op->code() == lir_unlock, "Invalid code, expected lir_unlock"); - if (UseFastLocking) { + if (!UseHeavyMonitors) { assert(BasicLock::displaced_header_offset_in_bytes() == 0, "lock_reg must point to the displaced header"); __ unlock_object(hdr, obj, lock, *op->stub()->entry()); } else { diff --git a/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp b/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp index 98565003691..cb58e775422 100644 --- a/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp @@ -2660,27 +2660,32 @@ void MacroAssembler::compiler_fast_lock_object(ConditionRegister flag, Register andi_(temp, displaced_header, markWord::monitor_value); bne(CCR0, object_has_monitor); - // Set displaced_header to be (markWord of object | UNLOCK_VALUE). - ori(displaced_header, displaced_header, markWord::unlocked_value); - - // Load Compare Value application register. - - // Initialize the box. (Must happen before we update the object mark!) - std(displaced_header, BasicLock::displaced_header_offset_in_bytes(), box); - - // Must fence, otherwise, preceding store(s) may float below cmpxchg. - // Compare object markWord with mark and if equal exchange scratch1 with object markWord. - cmpxchgd(/*flag=*/flag, - /*current_value=*/current_header, - /*compare_value=*/displaced_header, - /*exchange_value=*/box, - /*where=*/oop, - MacroAssembler::MemBarRel | MacroAssembler::MemBarAcq, - MacroAssembler::cmpxchgx_hint_acquire_lock(), - noreg, - &cas_failed, - /*check without membar and ldarx first*/true); - assert(oopDesc::mark_offset_in_bytes() == 0, "offset of _mark is not 0"); + if (!UseHeavyMonitors) { + // Set displaced_header to be (markWord of object | UNLOCK_VALUE). + ori(displaced_header, displaced_header, markWord::unlocked_value); + + // Load Compare Value application register. + + // Initialize the box. (Must happen before we update the object mark!) + std(displaced_header, BasicLock::displaced_header_offset_in_bytes(), box); + + // Must fence, otherwise, preceding store(s) may float below cmpxchg. + // Compare object markWord with mark and if equal exchange scratch1 with object markWord. + cmpxchgd(/*flag=*/flag, + /*current_value=*/current_header, + /*compare_value=*/displaced_header, + /*exchange_value=*/box, + /*where=*/oop, + MacroAssembler::MemBarRel | MacroAssembler::MemBarAcq, + MacroAssembler::cmpxchgx_hint_acquire_lock(), + noreg, + &cas_failed, + /*check without membar and ldarx first*/true); + assert(oopDesc::mark_offset_in_bytes() == 0, "offset of _mark is not 0"); + } else { + // Set NE to indicate 'failure' -> take slow-path. + crandc(flag, Assembler::equal, flag, Assembler::equal); + } // If the compare-and-exchange succeeded, then we found an unlocked // object and we have now locked it. @@ -2768,12 +2773,14 @@ void MacroAssembler::compiler_fast_unlock_object(ConditionRegister flag, Registe } #endif - // Find the lock address and load the displaced header from the stack. - ld(displaced_header, BasicLock::displaced_header_offset_in_bytes(), box); + if (!UseHeavyMonitors) { + // Find the lock address and load the displaced header from the stack. + ld(displaced_header, BasicLock::displaced_header_offset_in_bytes(), box); - // If the displaced header is 0, we have a recursive unlock. - cmpdi(flag, displaced_header, 0); - beq(flag, cont); + // If the displaced header is 0, we have a recursive unlock. + cmpdi(flag, displaced_header, 0); + beq(flag, cont); + } // Handle existing monitor. // The object has an existing monitor iff (mark & monitor_value) != 0. @@ -2782,20 +2789,24 @@ void MacroAssembler::compiler_fast_unlock_object(ConditionRegister flag, Registe andi_(R0, current_header, markWord::monitor_value); bne(CCR0, object_has_monitor); - // Check if it is still a light weight lock, this is is true if we see - // the stack address of the basicLock in the markWord of the object. - // Cmpxchg sets flag to cmpd(current_header, box). - cmpxchgd(/*flag=*/flag, - /*current_value=*/current_header, - /*compare_value=*/box, - /*exchange_value=*/displaced_header, - /*where=*/oop, - MacroAssembler::MemBarRel, - MacroAssembler::cmpxchgx_hint_release_lock(), - noreg, - &cont); - - assert(oopDesc::mark_offset_in_bytes() == 0, "offset of _mark is not 0"); + if (!UseHeavyMonitors) { + // Check if it is still a light weight lock, this is is true if we see + // the stack address of the basicLock in the markWord of the object. + // Cmpxchg sets flag to cmpd(current_header, box). + cmpxchgd(/*flag=*/flag, + /*current_value=*/current_header, + /*compare_value=*/box, + /*exchange_value=*/displaced_header, + /*where=*/oop, + MacroAssembler::MemBarRel, + MacroAssembler::cmpxchgx_hint_release_lock(), + noreg, + &cont); + assert(oopDesc::mark_offset_in_bytes() == 0, "offset of _mark is not 0"); + } else { + // Set NE to indicate 'failure' -> take slow-path. + crandc(flag, Assembler::equal, flag, Assembler::equal); + } // Handle existing monitor. b(cont); diff --git a/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp b/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp index cb5903886ca..1d1f163826e 100644 --- a/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp +++ b/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp @@ -2730,7 +2730,7 @@ void LIR_Assembler::emit_lock(LIR_OpLock* op) { Register obj = op->obj_opr()->as_register(); // May not be an oop. Register hdr = op->hdr_opr()->as_register(); Register lock = op->lock_opr()->as_register(); - if (!UseFastLocking) { + if (UseHeavyMonitors) { __ branch_optimized(Assembler::bcondAlways, *op->stub()->entry()); } else if (op->code() == lir_lock) { assert(BasicLock::displaced_header_offset_in_bytes() == 0, "lock_reg must point to the displaced header"); diff --git a/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp b/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp index 07f2762fa16..eaeeae235f0 100644 --- a/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp @@ -461,7 +461,11 @@ int LIR_Assembler::emit_unwind_handler() { if (method()->is_synchronized()) { monitor_address(0, FrameMap::rax_opr); stub = new MonitorExitStub(FrameMap::rax_opr, true, 0); - __ unlock_object(rdi, rsi, rax, *stub->entry()); + if (UseHeavyMonitors) { + __ jmp(*stub->entry()); + } else { + __ unlock_object(rdi, rsi, rax, *stub->entry()); + } __ bind(*stub->continuation()); } @@ -3498,7 +3502,7 @@ void LIR_Assembler::emit_lock(LIR_OpLock* op) { Register obj = op->obj_opr()->as_register(); // may not be an oop Register hdr = op->hdr_opr()->as_register(); Register lock = op->lock_opr()->as_register(); - if (!UseFastLocking) { + if (UseHeavyMonitors) { __ jmp(*op->stub()->entry()); } else if (op->code() == lir_lock) { assert(BasicLock::displaced_header_offset_in_bytes() == 0, "lock_reg must point to the displaced header"); diff --git a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp index 4aec9668a14..cc0ad344c96 100644 --- a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp @@ -485,6 +485,7 @@ void C2_MacroAssembler::fast_lock(Register objReg, Register boxReg, Register tmp #if INCLUDE_RTM_OPT if (UseRTMForStackLocks && use_rtm) { + assert(!UseHeavyMonitors, "+UseHeavyMonitors and +UseRTMForStackLocks are mutually exclusive"); rtm_stack_locking(objReg, tmpReg, scrReg, cx2Reg, stack_rtm_counters, method_data, profile_rtm, DONE_LABEL, IsInflated); @@ -495,20 +496,25 @@ void C2_MacroAssembler::fast_lock(Register objReg, Register boxReg, Register tmp testptr(tmpReg, markWord::monitor_value); // inflated vs stack-locked|neutral jccb(Assembler::notZero, IsInflated); - // Attempt stack-locking ... - orptr (tmpReg, markWord::unlocked_value); - movptr(Address(boxReg, 0), tmpReg); // Anticipate successful CAS - lock(); - cmpxchgptr(boxReg, Address(objReg, oopDesc::mark_offset_in_bytes())); // Updates tmpReg - jcc(Assembler::equal, DONE_LABEL); // Success - - // Recursive locking. - // The object is stack-locked: markword contains stack pointer to BasicLock. - // Locked by current thread if difference with current SP is less than one page. - subptr(tmpReg, rsp); - // Next instruction set ZFlag == 1 (Success) if difference is less then one page. - andptr(tmpReg, (int32_t) (NOT_LP64(0xFFFFF003) LP64_ONLY(7 - os::vm_page_size())) ); - movptr(Address(boxReg, 0), tmpReg); + if (!UseHeavyMonitors) { + // Attempt stack-locking ... + orptr (tmpReg, markWord::unlocked_value); + movptr(Address(boxReg, 0), tmpReg); // Anticipate successful CAS + lock(); + cmpxchgptr(boxReg, Address(objReg, oopDesc::mark_offset_in_bytes())); // Updates tmpReg + jcc(Assembler::equal, DONE_LABEL); // Success + + // Recursive locking. + // The object is stack-locked: markword contains stack pointer to BasicLock. + // Locked by current thread if difference with current SP is less than one page. + subptr(tmpReg, rsp); + // Next instruction set ZFlag == 1 (Success) if difference is less then one page. + andptr(tmpReg, (int32_t) (NOT_LP64(0xFFFFF003) LP64_ONLY(7 - os::vm_page_size())) ); + movptr(Address(boxReg, 0), tmpReg); + } else { + // Clear ZF so that we take the slow path at the DONE label. objReg is known to be not 0. + testptr(objReg, objReg); + } jmp(DONE_LABEL); bind(IsInflated); @@ -638,6 +644,7 @@ void C2_MacroAssembler::fast_unlock(Register objReg, Register boxReg, Register t #if INCLUDE_RTM_OPT if (UseRTMForStackLocks && use_rtm) { + assert(!UseHeavyMonitors, "+UseHeavyMonitors and +UseRTMForStackLocks are mutually exclusive"); Label L_regular_unlock; movptr(tmpReg, Address(objReg, oopDesc::mark_offset_in_bytes())); // fetch markword andptr(tmpReg, markWord::lock_mask_in_place); // look at 2 lock bits @@ -649,11 +656,15 @@ void C2_MacroAssembler::fast_unlock(Register objReg, Register boxReg, Register t } #endif - cmpptr(Address(boxReg, 0), (int32_t)NULL_WORD); // Examine the displaced header - jcc (Assembler::zero, DONE_LABEL); // 0 indicates recursive stack-lock + if (!UseHeavyMonitors) { + cmpptr(Address(boxReg, 0), (int32_t)NULL_WORD); // Examine the displaced header + jcc (Assembler::zero, DONE_LABEL); // 0 indicates recursive stack-lock + } movptr(tmpReg, Address(objReg, oopDesc::mark_offset_in_bytes())); // Examine the object's markword - testptr(tmpReg, markWord::monitor_value); // Inflated? - jccb (Assembler::zero, Stacked); + if (!UseHeavyMonitors) { + testptr(tmpReg, markWord::monitor_value); // Inflated? + jccb (Assembler::zero, Stacked); + } // It's inflated. #if INCLUDE_RTM_OPT @@ -795,11 +806,12 @@ void C2_MacroAssembler::fast_unlock(Register objReg, Register boxReg, Register t testl (boxReg, 0); // set ICC.ZF=1 to indicate success jmpb (DONE_LABEL); - bind (Stacked); - movptr(tmpReg, Address (boxReg, 0)); // re-fetch - lock(); - cmpxchgptr(tmpReg, Address(objReg, oopDesc::mark_offset_in_bytes())); // Uses RAX which is box - + if (!UseHeavyMonitors) { + bind (Stacked); + movptr(tmpReg, Address (boxReg, 0)); // re-fetch + lock(); + cmpxchgptr(tmpReg, Address(objReg, oopDesc::mark_offset_in_bytes())); // Uses RAX which is box + } #endif bind(DONE_LABEL); } diff --git a/src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp b/src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp index a00af0e4af0..e139b3cf6eb 100644 --- a/src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp +++ b/src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp @@ -1705,36 +1705,41 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, // Load the oop from the handle __ movptr(obj_reg, Address(oop_handle_reg, 0)); - // Load immediate 1 into swap_reg %rax, - __ movptr(swap_reg, 1); - - // Load (object->mark() | 1) into swap_reg %rax, - __ orptr(swap_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes())); - - // Save (object->mark() | 1) into BasicLock's displaced header - __ movptr(Address(lock_reg, mark_word_offset), swap_reg); - - // src -> dest iff dest == rax, else rax, <- dest - // *obj_reg = lock_reg iff *obj_reg == rax, else rax, = *(obj_reg) - __ lock(); - __ cmpxchgptr(lock_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes())); - __ jcc(Assembler::equal, lock_done); - - // Test if the oopMark is an obvious stack pointer, i.e., - // 1) (mark & 3) == 0, and - // 2) rsp <= mark < mark + os::pagesize() - // These 3 tests can be done by evaluating the following - // expression: ((mark - rsp) & (3 - os::vm_page_size())), - // assuming both stack pointer and pagesize have their - // least significant 2 bits clear. - // NOTE: the oopMark is in swap_reg %rax, as the result of cmpxchg - - __ subptr(swap_reg, rsp); - __ andptr(swap_reg, 3 - os::vm_page_size()); - - // Save the test result, for recursive case, the result is zero - __ movptr(Address(lock_reg, mark_word_offset), swap_reg); - __ jcc(Assembler::notEqual, slow_path_lock); + if (!UseHeavyMonitors) { + // Load immediate 1 into swap_reg %rax, + __ movptr(swap_reg, 1); + + // Load (object->mark() | 1) into swap_reg %rax, + __ orptr(swap_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes())); + + // Save (object->mark() | 1) into BasicLock's displaced header + __ movptr(Address(lock_reg, mark_word_offset), swap_reg); + + // src -> dest iff dest == rax, else rax, <- dest + // *obj_reg = lock_reg iff *obj_reg == rax, else rax, = *(obj_reg) + __ lock(); + __ cmpxchgptr(lock_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes())); + __ jcc(Assembler::equal, lock_done); + + // Test if the oopMark is an obvious stack pointer, i.e., + // 1) (mark & 3) == 0, and + // 2) rsp <= mark < mark + os::pagesize() + // These 3 tests can be done by evaluating the following + // expression: ((mark - rsp) & (3 - os::vm_page_size())), + // assuming both stack pointer and pagesize have their + // least significant 2 bits clear. + // NOTE: the oopMark is in swap_reg %rax, as the result of cmpxchg + + __ subptr(swap_reg, rsp); + __ andptr(swap_reg, 3 - os::vm_page_size()); + + // Save the test result, for recursive case, the result is zero + __ movptr(Address(lock_reg, mark_word_offset), swap_reg); + __ jcc(Assembler::notEqual, slow_path_lock); + } else { + __ jmp(slow_path_lock); + } + // Slow path will re-enter here __ bind(lock_done); } @@ -1852,28 +1857,32 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, // Get locked oop from the handle we passed to jni __ movptr(obj_reg, Address(oop_handle_reg, 0)); - // Simple recursive lock? + if (!UseHeavyMonitors) { + // Simple recursive lock? - __ cmpptr(Address(rbp, lock_slot_rbp_offset), (int32_t)NULL_WORD); - __ jcc(Assembler::equal, done); + __ cmpptr(Address(rbp, lock_slot_rbp_offset), (int32_t)NULL_WORD); + __ jcc(Assembler::equal, done); - // Must save rax, if if it is live now because cmpxchg must use it - if (ret_type != T_FLOAT && ret_type != T_DOUBLE && ret_type != T_VOID) { - save_native_result(masm, ret_type, stack_slots); - } + // Must save rax, if if it is live now because cmpxchg must use it + if (ret_type != T_FLOAT && ret_type != T_DOUBLE && ret_type != T_VOID) { + save_native_result(masm, ret_type, stack_slots); + } - // get old displaced header - __ movptr(rbx, Address(rbp, lock_slot_rbp_offset)); + // get old displaced header + __ movptr(rbx, Address(rbp, lock_slot_rbp_offset)); - // get address of the stack lock - __ lea(rax, Address(rbp, lock_slot_rbp_offset)); + // get address of the stack lock + __ lea(rax, Address(rbp, lock_slot_rbp_offset)); - // Atomic swap old header if oop still contains the stack lock - // src -> dest iff dest == rax, else rax, <- dest - // *obj_reg = rbx, iff *obj_reg == rax, else rax, = *(obj_reg) - __ lock(); - __ cmpxchgptr(rbx, Address(obj_reg, oopDesc::mark_offset_in_bytes())); - __ jcc(Assembler::notEqual, slow_path_unlock); + // Atomic swap old header if oop still contains the stack lock + // src -> dest iff dest == rax, else rax, <- dest + // *obj_reg = rbx, iff *obj_reg == rax, else rax, = *(obj_reg) + __ lock(); + __ cmpxchgptr(rbx, Address(obj_reg, oopDesc::mark_offset_in_bytes())); + __ jcc(Assembler::notEqual, slow_path_unlock); + } else { + __ jmp(slow_path_unlock); + } // slow path re-enters here __ bind(unlock_done); diff --git a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp index f78ec39c25e..9ff40e943ba 100644 --- a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp +++ b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp @@ -1918,37 +1918,41 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, // Load the oop from the handle __ movptr(obj_reg, Address(oop_handle_reg, 0)); - // Load immediate 1 into swap_reg %rax - __ movl(swap_reg, 1); - - // Load (object->mark() | 1) into swap_reg %rax - __ orptr(swap_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes())); - - // Save (object->mark() | 1) into BasicLock's displaced header - __ movptr(Address(lock_reg, mark_word_offset), swap_reg); - - // src -> dest iff dest == rax else rax <- dest - __ lock(); - __ cmpxchgptr(lock_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes())); - __ jcc(Assembler::equal, lock_done); - - // Hmm should this move to the slow path code area??? - - // Test if the oopMark is an obvious stack pointer, i.e., - // 1) (mark & 3) == 0, and - // 2) rsp <= mark < mark + os::pagesize() - // These 3 tests can be done by evaluating the following - // expression: ((mark - rsp) & (3 - os::vm_page_size())), - // assuming both stack pointer and pagesize have their - // least significant 2 bits clear. - // NOTE: the oopMark is in swap_reg %rax as the result of cmpxchg - - __ subptr(swap_reg, rsp); - __ andptr(swap_reg, 3 - os::vm_page_size()); - - // Save the test result, for recursive case, the result is zero - __ movptr(Address(lock_reg, mark_word_offset), swap_reg); - __ jcc(Assembler::notEqual, slow_path_lock); + if (!UseHeavyMonitors) { + // Load immediate 1 into swap_reg %rax + __ movl(swap_reg, 1); + + // Load (object->mark() | 1) into swap_reg %rax + __ orptr(swap_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes())); + + // Save (object->mark() | 1) into BasicLock's displaced header + __ movptr(Address(lock_reg, mark_word_offset), swap_reg); + + // src -> dest iff dest == rax else rax <- dest + __ lock(); + __ cmpxchgptr(lock_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes())); + __ jcc(Assembler::equal, lock_done); + + // Hmm should this move to the slow path code area??? + + // Test if the oopMark is an obvious stack pointer, i.e., + // 1) (mark & 3) == 0, and + // 2) rsp <= mark < mark + os::pagesize() + // These 3 tests can be done by evaluating the following + // expression: ((mark - rsp) & (3 - os::vm_page_size())), + // assuming both stack pointer and pagesize have their + // least significant 2 bits clear. + // NOTE: the oopMark is in swap_reg %rax as the result of cmpxchg + + __ subptr(swap_reg, rsp); + __ andptr(swap_reg, 3 - os::vm_page_size()); + + // Save the test result, for recursive case, the result is zero + __ movptr(Address(lock_reg, mark_word_offset), swap_reg); + __ jcc(Assembler::notEqual, slow_path_lock); + } else { + __ jmp(slow_path_lock); + } // Slow path will re-enter here @@ -2055,26 +2059,30 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, __ movptr(obj_reg, Address(oop_handle_reg, 0)); Label done; - // Simple recursive lock? - __ cmpptr(Address(rsp, lock_slot_offset * VMRegImpl::stack_slot_size), (int32_t)NULL_WORD); - __ jcc(Assembler::equal, done); + if (!UseHeavyMonitors) { + // Simple recursive lock? + __ cmpptr(Address(rsp, lock_slot_offset * VMRegImpl::stack_slot_size), (int32_t)NULL_WORD); + __ jcc(Assembler::equal, done); - // Must save rax if if it is live now because cmpxchg must use it - if (ret_type != T_FLOAT && ret_type != T_DOUBLE && ret_type != T_VOID) { - save_native_result(masm, ret_type, stack_slots); - } + // Must save rax if if it is live now because cmpxchg must use it + if (ret_type != T_FLOAT && ret_type != T_DOUBLE && ret_type != T_VOID) { + save_native_result(masm, ret_type, stack_slots); + } - // get address of the stack lock - __ lea(rax, Address(rsp, lock_slot_offset * VMRegImpl::stack_slot_size)); - // get old displaced header - __ movptr(old_hdr, Address(rax, 0)); + // get address of the stack lock + __ lea(rax, Address(rsp, lock_slot_offset * VMRegImpl::stack_slot_size)); + // get old displaced header + __ movptr(old_hdr, Address(rax, 0)); - // Atomic swap old header if oop still contains the stack lock - __ lock(); - __ cmpxchgptr(old_hdr, Address(obj_reg, oopDesc::mark_offset_in_bytes())); - __ jcc(Assembler::notEqual, slow_path_unlock); + // Atomic swap old header if oop still contains the stack lock + __ lock(); + __ cmpxchgptr(old_hdr, Address(obj_reg, oopDesc::mark_offset_in_bytes())); + __ jcc(Assembler::notEqual, slow_path_unlock); + } else { + __ jmp(slow_path_unlock); + } // slow path re-enters here __ bind(unlock_done); diff --git a/src/hotspot/share/c1/c1_LIRGenerator.cpp b/src/hotspot/share/c1/c1_LIRGenerator.cpp index 05aa3587ee2..c064558b458 100644 --- a/src/hotspot/share/c1/c1_LIRGenerator.cpp +++ b/src/hotspot/share/c1/c1_LIRGenerator.cpp @@ -620,7 +620,7 @@ void LIRGenerator::monitor_exit(LIR_Opr object, LIR_Opr lock, LIR_Opr new_hdr, L // setup registers LIR_Opr hdr = lock; lock = new_hdr; - CodeStub* slow_path = new MonitorExitStub(lock, UseFastLocking, monitor_no); + CodeStub* slow_path = new MonitorExitStub(lock, !UseHeavyMonitors, monitor_no); __ load_stack_address_monitor(monitor_no, lock); __ unlock_object(hdr, object, lock, scratch, slow_path); } diff --git a/src/hotspot/share/c1/c1_Runtime1.cpp b/src/hotspot/share/c1/c1_Runtime1.cpp index d7e0df012e5..68e77c823c8 100644 --- a/src/hotspot/share/c1/c1_Runtime1.cpp +++ b/src/hotspot/share/c1/c1_Runtime1.cpp @@ -736,7 +736,7 @@ JRT_BLOCK_ENTRY(void, Runtime1::monitorenter(JavaThread* current, oopDesc* obj, _monitorenter_slowcase_cnt++; } #endif - if (!UseFastLocking) { + if (UseHeavyMonitors) { lock->set_obj(obj); } assert(obj == lock->obj(), "must match"); diff --git a/src/hotspot/share/c1/c1_globals.hpp b/src/hotspot/share/c1/c1_globals.hpp index 2b5de079a0c..e90aaf6536d 100644 --- a/src/hotspot/share/c1/c1_globals.hpp +++ b/src/hotspot/share/c1/c1_globals.hpp @@ -242,9 +242,6 @@ develop(bool, UseFastNewObjectArray, true, \ "Use fast inlined object array allocation") \ \ - develop(bool, UseFastLocking, true, \ - "Use fast inlined locking code") \ - \ develop(bool, UseSlowPath, false, \ "For debugging: test slow cases by always using them") \ \ diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp index 89352c1f95e..969c8e82b91 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -532,6 +532,9 @@ static SpecialFlag const special_jvm_flags[] = { { "DynamicDumpSharedSpaces", JDK_Version::jdk(18), JDK_Version::jdk(19), JDK_Version::undefined() }, { "RequireSharedSpaces", JDK_Version::jdk(18), JDK_Version::jdk(19), JDK_Version::undefined() }, { "UseSharedSpaces", JDK_Version::jdk(18), JDK_Version::jdk(19), JDK_Version::undefined() }, +#ifdef PRODUCT + { "UseHeavyMonitors", JDK_Version::jdk(18), JDK_Version::jdk(19), JDK_Version::jdk(20) }, +#endif // --- Deprecated alias flags (see also aliased_jvm_flags) - sorted by obsolete_in then expired_in: { "DefaultMaxRAMFraction", JDK_Version::jdk(8), JDK_Version::undefined(), JDK_Version::undefined() }, @@ -2018,6 +2021,20 @@ bool Arguments::check_vm_args_consistency() { } #endif +#if !defined(X86) && !defined(AARCH64) && !defined(PPC64) + if (UseHeavyMonitors) { + warning("UseHeavyMonitors is not fully implemented on this architecture"); + } +#endif +#if defined(X86) || defined(PPC64) + if (UseHeavyMonitors && UseRTMForStackLocks) { + fatal("-XX:+UseHeavyMonitors and -XX:+UseRTMForStackLocks are mutually exclusive"); + } +#endif + if (VerifyHeavyMonitors && !UseHeavyMonitors) { + fatal("-XX:+VerifyHeavyMonitors requires -XX:+UseHeavyMonitors"); + } + return status; } diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp index ded9a1fe93a..beb719ff0b9 100644 --- a/src/hotspot/share/runtime/globals.hpp +++ b/src/hotspot/share/runtime/globals.hpp @@ -1066,7 +1066,12 @@ const intx ObjectAlignmentInBytes = 8; "If true, error data is printed to stdout instead of a file") \ \ product(bool, UseHeavyMonitors, false, \ - "use heavyweight instead of lightweight Java monitors") \ + "(Deprecated) Use heavyweight instead of lightweight Java " \ + "monitors") \ + \ + develop(bool, VerifyHeavyMonitors, false, \ + "Checks that no stack locking happens when using " \ + "+UseHeavyMonitors") \ \ product(bool, PrintStringTableStatistics, false, \ "print statistics about the StringTable and SymbolTable") \ diff --git a/src/hotspot/share/runtime/synchronizer.cpp b/src/hotspot/share/runtime/synchronizer.cpp index 87f28806508..4f9c7c21a9b 100644 --- a/src/hotspot/share/runtime/synchronizer.cpp +++ b/src/hotspot/share/runtime/synchronizer.cpp @@ -417,6 +417,14 @@ void ObjectSynchronizer::handle_sync_on_value_based_class(Handle obj, JavaThread } } +static bool useHeavyMonitors() { +#if defined(X86) || defined(AARCH64) || defined(PPC64) + return UseHeavyMonitors; +#else + return false; +#endif +} + // ----------------------------------------------------------------------------- // Monitor Enter/Exit // The interpreter and compiler assembly code tries to lock using the fast path @@ -428,28 +436,33 @@ void ObjectSynchronizer::enter(Handle obj, BasicLock* lock, JavaThread* current) handle_sync_on_value_based_class(obj, current); } - markWord mark = obj->mark(); - if (mark.is_neutral()) { - // Anticipate successful CAS -- the ST of the displaced mark must - // be visible <= the ST performed by the CAS. - lock->set_displaced_header(mark); - if (mark == obj()->cas_set_mark(markWord::from_pointer(lock), mark)) { + if (!useHeavyMonitors()) { + markWord mark = obj->mark(); + if (mark.is_neutral()) { + // Anticipate successful CAS -- the ST of the displaced mark must + // be visible <= the ST performed by the CAS. + lock->set_displaced_header(mark); + if (mark == obj()->cas_set_mark(markWord::from_pointer(lock), mark)) { + return; + } + // Fall through to inflate() ... + } else if (mark.has_locker() && + current->is_lock_owned((address)mark.locker())) { + assert(lock != mark.locker(), "must not re-lock the same lock"); + assert(lock != (BasicLock*)obj->mark().value(), "don't relock with same BasicLock"); + lock->set_displaced_header(markWord::from_pointer(NULL)); return; } - // Fall through to inflate() ... - } else if (mark.has_locker() && - current->is_lock_owned((address)mark.locker())) { - assert(lock != mark.locker(), "must not re-lock the same lock"); - assert(lock != (BasicLock*)obj->mark().value(), "don't relock with same BasicLock"); - lock->set_displaced_header(markWord::from_pointer(NULL)); - return; + + // The object header will never be displaced to this lock, + // so it does not matter what the value is, except that it + // must be non-zero to avoid looking like a re-entrant lock, + // and must not look locked either. + lock->set_displaced_header(markWord::unused_mark()); + } else if (VerifyHeavyMonitors) { + guarantee(!obj->mark().has_locker(), "must not be stack-locked"); } - // The object header will never be displaced to this lock, - // so it does not matter what the value is, except that it - // must be non-zero to avoid looking like a re-entrant lock, - // and must not look locked either. - lock->set_displaced_header(markWord::unused_mark()); // An async deflation can race after the inflate() call and before // enter() can make the ObjectMonitor busy. enter() returns false if // we have lost the race to async deflation and we simply try again. @@ -462,45 +475,49 @@ void ObjectSynchronizer::enter(Handle obj, BasicLock* lock, JavaThread* current) } void ObjectSynchronizer::exit(oop object, BasicLock* lock, JavaThread* current) { - markWord mark = object->mark(); + if (!useHeavyMonitors()) { + markWord mark = object->mark(); - markWord dhw = lock->displaced_header(); - if (dhw.value() == 0) { - // If the displaced header is NULL, then this exit matches up with - // a recursive enter. No real work to do here except for diagnostics. + markWord dhw = lock->displaced_header(); + if (dhw.value() == 0) { + // If the displaced header is NULL, then this exit matches up with + // a recursive enter. No real work to do here except for diagnostics. #ifndef PRODUCT - if (mark != markWord::INFLATING()) { - // Only do diagnostics if we are not racing an inflation. Simply - // exiting a recursive enter of a Java Monitor that is being - // inflated is safe; see the has_monitor() comment below. - assert(!mark.is_neutral(), "invariant"); - assert(!mark.has_locker() || - current->is_lock_owned((address)mark.locker()), "invariant"); - if (mark.has_monitor()) { - // The BasicLock's displaced_header is marked as a recursive - // enter and we have an inflated Java Monitor (ObjectMonitor). - // This is a special case where the Java Monitor was inflated - // after this thread entered the stack-lock recursively. When a - // Java Monitor is inflated, we cannot safely walk the Java - // Monitor owner's stack and update the BasicLocks because a - // Java Monitor can be asynchronously inflated by a thread that - // does not own the Java Monitor. - ObjectMonitor* m = mark.monitor(); - assert(m->object()->mark() == mark, "invariant"); - assert(m->is_entered(current), "invariant"); + if (mark != markWord::INFLATING()) { + // Only do diagnostics if we are not racing an inflation. Simply + // exiting a recursive enter of a Java Monitor that is being + // inflated is safe; see the has_monitor() comment below. + assert(!mark.is_neutral(), "invariant"); + assert(!mark.has_locker() || + current->is_lock_owned((address)mark.locker()), "invariant"); + if (mark.has_monitor()) { + // The BasicLock's displaced_header is marked as a recursive + // enter and we have an inflated Java Monitor (ObjectMonitor). + // This is a special case where the Java Monitor was inflated + // after this thread entered the stack-lock recursively. When a + // Java Monitor is inflated, we cannot safely walk the Java + // Monitor owner's stack and update the BasicLocks because a + // Java Monitor can be asynchronously inflated by a thread that + // does not own the Java Monitor. + ObjectMonitor* m = mark.monitor(); + assert(m->object()->mark() == mark, "invariant"); + assert(m->is_entered(current), "invariant"); + } } - } #endif - return; - } - - if (mark == markWord::from_pointer(lock)) { - // If the object is stack-locked by the current thread, try to - // swing the displaced header from the BasicLock back to the mark. - assert(dhw.is_neutral(), "invariant"); - if (object->cas_set_mark(dhw, mark) == mark) { return; } + + if (mark == markWord::from_pointer(lock)) { + // If the object is stack-locked by the current thread, try to + // swing the displaced header from the BasicLock back to the mark. + assert(dhw.is_neutral(), "invariant"); + if (object->cas_set_mark(dhw, mark) == mark) { + return; + } + } + } else if (VerifyHeavyMonitors) { + guarantee(!object->mark().has_locker(), "must not be stack-locked"); } // We have to take the slow-path of possible inflation and then exit. @@ -804,7 +821,10 @@ intptr_t ObjectSynchronizer::FastHashCode(Thread* current, oop obj) { markWord temp, test; intptr_t hash; markWord mark = read_stable_mark(obj); - + if (VerifyHeavyMonitors) { + assert(UseHeavyMonitors, "+VerifyHeavyMonitors requires +UseHeavyMonitors"); + guarantee(!mark.has_locker(), "must not be stack locked"); + } if (mark.is_neutral()) { // if this is a normal header hash = mark.hash(); if (hash != 0) { // if it has a hash, just return it diff --git a/test/hotspot/jtreg/runtime/CommandLine/VMDeprecatedOptions.java b/test/hotspot/jtreg/runtime/CommandLine/VMDeprecatedOptions.java index b8e6c41c1ba..4f4d7470630 100644 --- a/test/hotspot/jtreg/runtime/CommandLine/VMDeprecatedOptions.java +++ b/test/hotspot/jtreg/runtime/CommandLine/VMDeprecatedOptions.java @@ -21,6 +21,10 @@ * questions. */ +import java.util.Arrays; +import java.util.ArrayList; + +import jdk.test.lib.Platform; import jdk.test.lib.process.ProcessTools; import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.cli.*; @@ -39,22 +43,31 @@ public class VMDeprecatedOptions { * each entry is {[0]: option name, [1]: value to set * (true/false/n/string)}. */ - public static final String[][] DEPRECATED_OPTIONS = { - // deprecated non-alias flags: - {"MaxGCMinorPauseMillis", "1032"}, - {"MaxRAMFraction", "8"}, - {"MinRAMFraction", "2"}, - {"InitialRAMFraction", "64"}, - {"TLABStats", "false"}, - {"AllowRedefinitionToAddDeleteMethods", "true"}, - {"UseSharedSpaces", "false"}, - {"RequireSharedSpaces", "false"}, - {"DumpSharedSpaces", "false"}, - {"DynamicDumpSharedSpaces", "false"}, + public static final String[][] DEPRECATED_OPTIONS; + static { + ArrayList deprecated = new ArrayList( + Arrays.asList(new String[][] { + // deprecated non-alias flags: + {"MaxGCMinorPauseMillis", "1032"}, + {"MaxRAMFraction", "8"}, + {"MinRAMFraction", "2"}, + {"InitialRAMFraction", "64"}, + {"TLABStats", "false"}, + {"AllowRedefinitionToAddDeleteMethods", "true"}, + {"UseSharedSpaces", "false"}, + {"RequireSharedSpaces", "false"}, + {"DumpSharedSpaces", "false"}, + {"DynamicDumpSharedSpaces", "false"}, - // deprecated alias flags (see also aliased_jvm_flags): - {"DefaultMaxRAMFraction", "4"}, - {"CreateMinidumpOnCrash", "false"} + // deprecated alias flags (see also aliased_jvm_flags): + {"DefaultMaxRAMFraction", "4"}, + {"CreateMinidumpOnCrash", "false"} + } + )); + if (!Platform.isDebugBuild()) { + deprecated.add(new String[]{"UseHeavyMonitors", "false"}); + } + DEPRECATED_OPTIONS = deprecated.toArray(new String[][]{}); }; static String getDeprecationString(String optionName) { diff --git a/test/jdk/java/util/concurrent/ConcurrentHashMap/MapLoops.java b/test/jdk/java/util/concurrent/ConcurrentHashMap/MapLoops.java index 0f52bc67f08..922b18836dd 100644 --- a/test/jdk/java/util/concurrent/ConcurrentHashMap/MapLoops.java +++ b/test/jdk/java/util/concurrent/ConcurrentHashMap/MapLoops.java @@ -45,6 +45,14 @@ * @run main/timeout=1600 MapLoops */ +/* + * @test + * @summary Exercise multithreaded maps, using only heavy monitors. + * @requires os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64" | os.arch=="aarch64" | os.arch == "ppc64" | os.arch == "ppc64le" + * @library /test/lib + * @run main/othervm/timeout=1600 -XX:+IgnoreUnrecognizedVMOptions -XX:+UseHeavyMonitors -XX:+VerifyHeavyMonitors MapLoops + */ + import static java.util.concurrent.TimeUnit.MILLISECONDS; import java.util.List; -- GitLab From bb50b92b804839577cee5092a8a62a98b760f0dc Mon Sep 17 00:00:00 2001 From: Andrey Turbanov Date: Tue, 7 Dec 2021 14:54:32 +0000 Subject: [PATCH 027/671] 8277536: Use String.blank in jdk.javadoc where applicable Reviewed-by: jjg --- .../doclets/formats/html/HtmlDocletWriter.java | 18 +++++------------- .../jdk/javadoc/internal/doclint/Checker.java | 8 +------- 2 files changed, 6 insertions(+), 20 deletions(-) diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java index 76709124ff2..cf9c43264c1 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java @@ -896,7 +896,7 @@ public class HtmlDocletWriter { * Return the link for the given member. * * @param context the id of the context where the link will be printed. - * @param typeElement the typeElement that we should link to. This is not + * @param typeElement the typeElement that we should link to. This is * not necessarily the type containing element since we may be * inheriting comments. * @param element the member being linked to. @@ -912,7 +912,7 @@ public class HtmlDocletWriter { * Return the link for the given member. * * @param context the id of the context where the link will be printed. - * @param typeElement the typeElement that we should link to. This is not + * @param typeElement the typeElement that we should link to. This is * not necessarily the type containing element since we may be * inheriting comments. * @param element the member being linked to. @@ -929,7 +929,7 @@ public class HtmlDocletWriter { * Return the link for the given member. * * @param context the id of the context where the link will be printed. - * @param typeElement the typeElement that we should link to. This is not + * @param typeElement the typeElement that we should link to. This is * not necessarily the type containing element since we may be * inheriting comments. * @param element the member being linked to. @@ -945,7 +945,7 @@ public class HtmlDocletWriter { * Return the link for the given member. * * @param context the id of the context where the link will be printed. - * @param typeElement the typeElement that we should link to. This is not + * @param typeElement the typeElement that we should link to. This is * not necessarily the type containing element since we may be * inheriting comments. * @param element the member being linked to. @@ -1407,14 +1407,6 @@ public class HtmlDocletWriter { return false; } - boolean isAllWhiteSpace(String body) { - for (int i = 0 ; i < body.length(); i++) { - if (!Character.isWhitespace(body.charAt(i))) - return false; - } - return true; - } - // Notify the next DocTree handler to take necessary action private boolean commentRemoved = false; @@ -1505,7 +1497,7 @@ public class HtmlDocletWriter { // Ignore any trailing whitespace OR whitespace after removed html comment if ((isLastNode || commentRemoved) && tag.getKind() == TEXT - && isAllWhiteSpace(ch.getText(tag))) + && ch.getText(tag).isBlank()) continue; // Ignore any leading html comments diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/Checker.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/Checker.java index 0d73d233cc1..abf8c698bba 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/Checker.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/Checker.java @@ -1236,13 +1236,7 @@ public class Checker extends DocTreePathScanner { } boolean hasNonWhitespace(TextTree tree) { - String s = tree.getBody(); - for (int i = 0; i < s.length(); i++) { - Character c = s.charAt(i); - if (!Character.isWhitespace(s.charAt(i))) - return true; - } - return false; + return !tree.getBody().isBlank(); } // -- GitLab From c609b5d3d7a3d08e489c2c9ed40c42bcb5bd2147 Mon Sep 17 00:00:00 2001 From: Aleksei Efimov Date: Tue, 7 Dec 2021 15:42:02 +0000 Subject: [PATCH 028/671] 8277628: Spec for InetAddressResolverProvider::get() throwing error or exception could be clearer Reviewed-by: alanb, dfuchs --- .../classes/java/net/spi/InetAddressResolverProvider.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/java.base/share/classes/java/net/spi/InetAddressResolverProvider.java b/src/java.base/share/classes/java/net/spi/InetAddressResolverProvider.java index 30f1c4f5b3e..6dff033ffc8 100644 --- a/src/java.base/share/classes/java/net/spi/InetAddressResolverProvider.java +++ b/src/java.base/share/classes/java/net/spi/InetAddressResolverProvider.java @@ -66,7 +66,8 @@ import java.util.ServiceLoader; * *

If instantiating a custom resolver from a provider discovered in * step 1 throws an error or exception, the system-wide resolver will not be - * set and the error or exception will be propagated to the calling thread. + * set and the error or exception will be propagated to the caller of the method + * that triggered the lookup operation. * Otherwise, any lookup operation will be performed using the * system-wide resolver. * @@ -85,7 +86,7 @@ public abstract class InetAddressResolverProvider { * *

Any error or exception thrown by this method is considered as * a failure of {@code InetAddressResolver} instantiation and will be propagated to - * the calling thread. + * the caller of the method that triggered the lookup operation. * @param configuration a {@link Configuration} instance containing platform built-in address * resolution configuration. * @return the resolver provided by this provider -- GitLab From bd7c54aee8d9795676087d6b34d4744031de1ef1 Mon Sep 17 00:00:00 2001 From: Maurizio Cimadamore Date: Tue, 7 Dec 2021 16:13:54 +0000 Subject: [PATCH 029/671] 8278341: Liveness check for global scope is not as fast as it could be Reviewed-by: shade, jvernee --- .../classes/jdk/internal/foreign/ResourceScopeImpl.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/ResourceScopeImpl.java b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/ResourceScopeImpl.java index dbb830a1b53..ab47db827e7 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/ResourceScopeImpl.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/ResourceScopeImpl.java @@ -217,6 +217,11 @@ public abstract non-sealed class ResourceScopeImpl implements ResourceScope, Seg void addInternal(ResourceList.ResourceCleanup resource) { // do nothing } + + @Override + public boolean isAlive() { + return true; + } } public static final ResourceScopeImpl GLOBAL = new GlobalScopeImpl(null); -- GitLab From 543d1a8cf41d32dca161c9d8041f133a71bf0ecb Mon Sep 17 00:00:00 2001 From: Naoto Sato Date: Tue, 7 Dec 2021 16:44:52 +0000 Subject: [PATCH 030/671] 8275721: Name of UTC timezone in a locale changes depending on previous code Reviewed-by: joehw --- .../cldr/CLDRTimeZoneNameProviderImpl.java | 42 +++++------ .../TimeZone/ChineseTimeZoneNameTest.java | 72 +++++++++++++++++++ 2 files changed, 91 insertions(+), 23 deletions(-) create mode 100644 test/jdk/sun/util/resources/TimeZone/ChineseTimeZoneNameTest.java diff --git a/src/java.base/share/classes/sun/util/cldr/CLDRTimeZoneNameProviderImpl.java b/src/java.base/share/classes/sun/util/cldr/CLDRTimeZoneNameProviderImpl.java index 6d78d77f64d..d03e753a0a4 100644 --- a/src/java.base/share/classes/sun/util/cldr/CLDRTimeZoneNameProviderImpl.java +++ b/src/java.base/share/classes/sun/util/cldr/CLDRTimeZoneNameProviderImpl.java @@ -82,7 +82,7 @@ public class CLDRTimeZoneNameProviderImpl extends TimeZoneNameProviderImpl { } if (namesSuper != null) { - // CLDR's resource bundle has an translated entry for this id. + // CLDR's resource bundle has a translated entry for this id. // Fix up names if needed, either missing or no-inheritance namesSuper[INDEX_TZID] = id; @@ -91,7 +91,7 @@ public class CLDRTimeZoneNameProviderImpl extends TimeZoneNameProviderImpl { case "": // Fill in empty elements deriveFallbackName(namesSuper, i, locale, - !TimeZone.getTimeZone(id).useDaylightTime()); + TimeZone.getTimeZone(id).toZoneId().getRules().isFixedOffset()); break; case NO_INHERITANCE_MARKER: // CLDR's "no inheritance marker" @@ -129,7 +129,7 @@ public class CLDRTimeZoneNameProviderImpl extends TimeZoneNameProviderImpl { // Derive fallback time zone name according to LDML's logic private void deriveFallbackNames(String[] names, Locale locale) { - boolean noDST = !TimeZone.getTimeZone(names[0]).useDaylightTime(); + boolean noDST = TimeZone.getTimeZone(names[0]).toZoneId().getRules().isFixedOffset(); for (int i = INDEX_STD_LONG; i <= INDEX_GEN_SHORT; i++) { deriveFallbackName(names, i, locale, noDST); @@ -149,13 +149,12 @@ public class CLDRTimeZoneNameProviderImpl extends TimeZoneNameProviderImpl { return; } - // Check parent locale first + // Check parent locales first if (!exists(names, index)) { CLDRLocaleProviderAdapter clpa = (CLDRLocaleProviderAdapter)LocaleProviderAdapter.forType(Type.CLDR); var cands = clpa.getCandidateLocales("", locale); - if (cands.size() > 1) { - var parentLoc = cands.get(1); // immediate parent locale - String[] parentNames = super.getDisplayNameArray(id, parentLoc); + for (int i = 1; i < cands.size() ; i++) { + String[] parentNames = super.getDisplayNameArray(id, cands.get(i)); if (parentNames != null && !parentNames[index].isEmpty()) { names[index] = parentNames[index]; return; @@ -163,22 +162,6 @@ public class CLDRTimeZoneNameProviderImpl extends TimeZoneNameProviderImpl { } } - // Check if COMPAT can substitute the name - if (LocaleProviderAdapter.getAdapterPreference().contains(Type.JRE)) { - String[] compatNames = (String[])LocaleProviderAdapter.forJRE() - .getLocaleResources(mapChineseLocale(locale)) - .getTimeZoneNames(id); - if (compatNames != null) { - for (int i = INDEX_STD_LONG; i <= INDEX_GEN_SHORT; i++) { - // Assumes COMPAT has no empty slots - if (i == index || !exists(names, i)) { - names[i] = compatNames[i]; - } - } - return; - } - } - // Region Fallback if (regionFormatFallback(names, index, locale)) { return; @@ -189,6 +172,19 @@ public class CLDRTimeZoneNameProviderImpl extends TimeZoneNameProviderImpl { return; } + // Check if COMPAT can substitute the name + if (!exists(names, index) && + LocaleProviderAdapter.getAdapterPreference().contains(Type.JRE)) { + String[] compatNames = (String[])LocaleProviderAdapter.forJRE() + .getLocaleResources(mapChineseLocale(locale)) + .getTimeZoneNames(id); + if (compatNames != null) { + // Assumes COMPAT has no empty slots + names[index] = compatNames[index]; + return; + } + } + // last resort names[index] = toGMTFormat(id, index == INDEX_DST_LONG || index == INDEX_DST_SHORT, diff --git a/test/jdk/sun/util/resources/TimeZone/ChineseTimeZoneNameTest.java b/test/jdk/sun/util/resources/TimeZone/ChineseTimeZoneNameTest.java new file mode 100644 index 00000000000..c752ec4d63c --- /dev/null +++ b/test/jdk/sun/util/resources/TimeZone/ChineseTimeZoneNameTest.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2021, 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. + */ + + /* + * @test + * @bug 8275721 + * @modules jdk.localedata + * @summary Checks Chinese time zone names for `UTC` using CLDR are consistent + * @run testng/othervm -Djava.locale.providers=CLDR,COMPAT ChineseTimeZoneNameTest + * @run testng/othervm -Djava.locale.providers=CLDR ChineseTimeZoneNameTest + */ + +import java.time.Instant; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Locale; + +import static org.testng.Assert.assertEquals; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +@Test +public class ChineseTimeZoneNameTest { + + private static final Locale SIMPLIFIED_CHINESE = Locale.forLanguageTag("zh-Hans"); + private static final Locale TRADITIONAL_CHINESE = Locale.forLanguageTag("zh-Hant"); + private static final ZonedDateTime EPOCH_UTC = + ZonedDateTime.ofInstant(Instant.ofEpochSecond (0), ZoneId.of ("UTC")); + + @DataProvider(name="locales") + Object[][] data() { + return new Object[][] { + {Locale.CHINESE, SIMPLIFIED_CHINESE}, + {Locale.SIMPLIFIED_CHINESE, SIMPLIFIED_CHINESE}, + {Locale.forLanguageTag("zh-SG"), SIMPLIFIED_CHINESE}, + {Locale.forLanguageTag("zh-Hans-TW"), SIMPLIFIED_CHINESE}, + {Locale.forLanguageTag("zh-HK"), TRADITIONAL_CHINESE}, + {Locale.forLanguageTag("zh-MO"), TRADITIONAL_CHINESE}, + {Locale.TRADITIONAL_CHINESE, TRADITIONAL_CHINESE}, + {Locale.forLanguageTag("zh-Hant-CN"), TRADITIONAL_CHINESE}, + }; + } + + @Test(dataProvider="locales") + public void test_ChineseTimeZoneNames(Locale testLoc, Locale resourceLoc) { + assertEquals(DateTimeFormatter.ofPattern("z", testLoc).format(EPOCH_UTC), + DateTimeFormatter.ofPattern("z", resourceLoc).format(EPOCH_UTC)); + assertEquals(DateTimeFormatter.ofPattern("zzzz", testLoc).format(EPOCH_UTC), + DateTimeFormatter.ofPattern("zzzz", resourceLoc).format(EPOCH_UTC)); + } +} -- GitLab From 7ea4b19f544cabb70590793ef59d5a8be05deeb1 Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Tue, 7 Dec 2021 16:47:24 +0000 Subject: [PATCH 031/671] 8278166: java/nio/channels/Channels/TransferTo.java timed out Reviewed-by: lancea, alanb --- .../nio/channels/Channels/TransferTo.java | 148 +++++++++++------- 1 file changed, 95 insertions(+), 53 deletions(-) diff --git a/test/jdk/java/nio/channels/Channels/TransferTo.java b/test/jdk/java/nio/channels/Channels/TransferTo.java index c75b9913e87..e7fa169788c 100644 --- a/test/jdk/java/nio/channels/Channels/TransferTo.java +++ b/test/jdk/java/nio/channels/Channels/TransferTo.java @@ -23,9 +23,10 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; -import java.io.IOException; import java.io.InputStream; +import java.io.IOException; import java.io.OutputStream; +import java.nio.ByteBuffer; import java.nio.channels.Channels; import java.nio.channels.FileChannel; import java.nio.channels.IllegalBlockingModeException; @@ -51,6 +52,7 @@ import org.testng.annotations.Test; import jdk.test.lib.RandomFactory; import static java.lang.String.format; +import static java.nio.file.StandardOpenOption.*; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertThrows; @@ -62,8 +64,8 @@ import static org.testng.Assert.assertTrue; * @build jdk.test.lib.RandomFactory * @run testng/othervm/timeout=180 TransferTo * @bug 8265891 - * @summary tests whether sun.nio.ChannelInputStream.transferTo conforms to the - * InputStream.transferTo contract defined in the javadoc + * @summary Tests whether sun.nio.ChannelInputStream.transferTo conforms to the + * InputStream.transferTo specification * @key randomness */ public class TransferTo { @@ -72,16 +74,17 @@ public class TransferTo { private static final int ITERATIONS = 10; - private static final int NUM_WRITES = 3 * 1024; - private static final int BYTES_PER_WRITE = 1024 * 1024; - private static final long BYTES_WRITTEN = (long) NUM_WRITES * BYTES_PER_WRITE; + private static final int NUM_WRITES = 3*1024; + private static final int BYTES_PER_WRITE = 1024*1024; + private static final long BYTES_WRITTEN = (long) NUM_WRITES*BYTES_PER_WRITE; private static final Random RND = RandomFactory.getRandom(); private static final Path CWD = Path.of("."); /* - * Provides test scenarios, i. e. combinations of input and output streams to be tested. + * Provides test scenarios, i.e., combinations of input and output streams + * to be tested. */ @DataProvider public static Object[][] streamCombinations() throws Exception { @@ -89,10 +92,12 @@ public class TransferTo { // tests FileChannel.transferTo(FileChannel) optimized case { fileChannelInput(), fileChannelOutput() }, - // tests FileChannel.transferTo(SelectableChannelOutput) optimized case + // tests FileChannel.transferTo(SelectableChannelOutput) + // optimized case { fileChannelInput(), selectableChannelOutput() }, - // tests FileChannel.transferTo(WritableChannelOutput) optimized case + // tests FileChannel.transferTo(WritableChannelOutput) + // optimized case { fileChannelInput(), writableByteChannelOutput() }, // tests InputStream.transferTo(OutputStream) default case @@ -101,7 +106,8 @@ public class TransferTo { } /* - * Testing API compliance: Input stream must throw NullPointerException when parameter "out" is null. + * Testing API compliance: input stream must throw NullPointerException + * when parameter "out" is null. */ @Test(dataProvider = "streamCombinations") public void testNullPointerException(InputStreamProvider inputStreamProvider, @@ -117,7 +123,8 @@ public class TransferTo { } /* - * Testing API compliance: Complete content of input stream must be transferred to output stream. + * Testing API compliance: complete content of input stream must be + * transferred to output stream. */ @Test(dataProvider = "streamCombinations") public void testStreamContents(InputStreamProvider inputStreamProvider, @@ -128,10 +135,12 @@ public class TransferTo { // tests input stream with a length between 1k and 4k checkTransferredContents(inputStreamProvider, outputStreamProvider, createRandomBytes(1024, 4096)); - // tests input stream with several data chunks, as 16k is more than a single chunk can hold + // tests input stream with several data chunks, as 16k is more than a + // single chunk can hold checkTransferredContents(inputStreamProvider, outputStreamProvider, createRandomBytes(16384, 16384)); - // tests randomly chosen starting positions within source and target stream + // tests randomly chosen starting positions within source and + // target stream for (int i = 0; i < ITERATIONS; i++) { byte[] inBytes = createRandomBytes(MIN_SIZE, MAX_SIZE_INCR); int posIn = RND.nextInt(inBytes.length); @@ -147,34 +156,60 @@ public class TransferTo { } /* - * Special test for file-to-file transfer of more than two GB. - * This test covers multiple iterations of FileChannel.transerTo(FileChannel), - * which ChannelInputStream.transferTo() only applies in this particular case, - * and cannot get tested using a single byte[] due to size limitation of arrays. + * Special test for file-to-file transfer of more than 2 GB. This test + * covers multiple iterations of FileChannel.transerTo(FileChannel), + * which ChannelInputStream.transferTo() only applies in this particular + * case, and cannot get tested using a single byte[] due to size limitation + * of arrays. */ @Test public void testMoreThanTwoGB() throws IOException { - Path sourceFile = Files.createTempFile(CWD, "test2GBSource", null); + // prepare two temporary files to be compared at the end of the test + // set the source file name + String sourceName = String.format("test3GBSource%s.tmp", + String.valueOf(RND.nextInt(Integer.MAX_VALUE))); + Path sourceFile = CWD.resolve(sourceName); + try { - // preparing two temporary files which will be compared at the end of the test - Path targetFile = Files.createTempFile(CWD, "test2GBtarget", null); + // set the target file name + String targetName = String.format("test3GBTarget%s.tmp", + String.valueOf(RND.nextInt(Integer.MAX_VALUE))); + Path targetFile = CWD.resolve(targetName); + try { - // writing 3 GB of random bytes into source file - for (int i = 0; i < NUM_WRITES; i++) - Files.write(sourceFile, createRandomBytes(BYTES_PER_WRITE, 0), StandardOpenOption.APPEND); + // calculate initial position to be just short of 2GB + final long initPos = 2047*BYTES_PER_WRITE; + + // create the source file with a hint to be sparse + try (FileChannel fc = FileChannel.open(sourceFile, CREATE_NEW, SPARSE, WRITE, APPEND);) { + // set initial position to avoid writing nearly 2GB + fc.position(initPos); + + // fill the remainder of the file with random bytes + int nw = (int)(NUM_WRITES - initPos/BYTES_PER_WRITE); + for (int i = 0; i < nw; i++) { + byte[] rndBytes = createRandomBytes(BYTES_PER_WRITE, 0); + ByteBuffer src = ByteBuffer.wrap(rndBytes); + fc.write(src); + } + } - // performing actual transfer, effectively by multiple invocations of Filechannel.transferTo(FileChannel) - long count; - try (InputStream inputStream = Channels.newInputStream(FileChannel.open(sourceFile)); - OutputStream outputStream = Channels - .newOutputStream(FileChannel.open(targetFile, StandardOpenOption.WRITE))) { - count = inputStream.transferTo(outputStream); + // create the target file with a hint to be sparse + try (FileChannel fc = FileChannel.open(targetFile, CREATE_NEW, WRITE, SPARSE);) { } - // comparing reported transferred bytes, must be 3 GB - assertEquals(count, BYTES_WRITTEN); + // perform actual transfer, effectively by multiple invocations + // of Filechannel.transferTo(FileChannel) + try (InputStream inputStream = Channels.newInputStream(FileChannel.open(sourceFile)); + OutputStream outputStream = Channels.newOutputStream(FileChannel.open(targetFile, WRITE))) { + long count = inputStream.transferTo(outputStream); + + // compare reported transferred bytes, must be 3 GB + // less the value of the initial position + assertEquals(count, BYTES_WRITTEN - initPos); + } - // comparing content of both files, failing in case of any difference + // compare content of both files, failing if different assertEquals(Files.mismatch(sourceFile, targetFile), -1); } finally { @@ -186,28 +221,33 @@ public class TransferTo { } /* - * Special test whether selectable channel based transfer throws blocking mode exception. + * Special test of whether selectable channel based transfer throws blocking + * mode exception. */ @Test public void testIllegalBlockingMode() throws IOException { Pipe pipe = Pipe.open(); try { - // testing arbitrary input (here: empty file) to non-blocking selectable output + // testing arbitrary input (here: empty file) to non-blocking + // selectable output try (FileChannel fc = FileChannel.open(Files.createTempFile(CWD, "testIllegalBlockingMode", null)); - InputStream is = Channels.newInputStream(fc); - SelectableChannel sc = pipe.sink().configureBlocking(false); - OutputStream os = Channels.newOutputStream((WritableByteChannel) sc)) { + InputStream is = Channels.newInputStream(fc); + SelectableChannel sc = pipe.sink().configureBlocking(false); + OutputStream os = Channels.newOutputStream((WritableByteChannel) sc)) { - // IllegalBlockingMode must be thrown when trying to perform a transfer + // IllegalBlockingMode must be thrown when trying to perform + // a transfer assertThrows(IllegalBlockingModeException.class, () -> is.transferTo(os)); } - // testing non-blocking selectable input to arbitrary output (here: byte array) + // testing non-blocking selectable input to arbitrary output + // (here: byte array) try (SelectableChannel sc = pipe.source().configureBlocking(false); - InputStream is = Channels.newInputStream((ReadableByteChannel) sc); - OutputStream os = new ByteArrayOutputStream()) { + InputStream is = Channels.newInputStream((ReadableByteChannel) sc); + OutputStream os = new ByteArrayOutputStream()) { - // IllegalBlockingMode must be thrown when trying to perform a transfer + // IllegalBlockingMode must be thrown when trying to perform + // a transfer assertThrows(IllegalBlockingModeException.class, () -> is.transferTo(os)); } } finally { @@ -217,9 +257,9 @@ public class TransferTo { } /* - * Asserts that the transferred content is correct, i. e. compares the actually transferred bytes - * to the expected assumption. The position of the input and output stream before the transfer is - * the start of stream (BOF). + * Asserts that the transferred content is correct, i.e., compares the bytes + * actually transferred to those expected. The position of the input and + * output streams before the transfer are zero (BOF). */ private static void checkTransferredContents(InputStreamProvider inputStreamProvider, OutputStreamProvider outputStreamProvider, byte[] inBytes) throws Exception { @@ -227,16 +267,16 @@ public class TransferTo { } /* - * Asserts that the transferred content is correct, i. e. compares the actually transferred bytes - * to the expected assumption. The position of the input and output stream before the transfer is - * provided by the caller. + * Asserts that the transferred content is correct, i. e. compares the bytes + * actually transferred to those expected. The positions of the input and + * output streams before the transfer are provided by the caller. */ private static void checkTransferredContents(InputStreamProvider inputStreamProvider, OutputStreamProvider outputStreamProvider, byte[] inBytes, int posIn, int posOut) throws Exception { AtomicReference> recorder = new AtomicReference<>(); try (InputStream in = inputStreamProvider.input(inBytes); - OutputStream out = outputStreamProvider.output(recorder::set)) { - // skip bytes till starting position + OutputStream out = outputStreamProvider.output(recorder::set)) { + // skip bytes until starting position in.skipNBytes(posIn); out.write(new byte[posOut]); @@ -252,7 +292,8 @@ public class TransferTo { } /* - * Creates an array of random size (between min and min + maxRandomAdditive) filled with random bytes + * Creates an array of random size (between min and min + maxRandomAdditive) + * filled with random bytes */ private static byte[] createRandomBytes(int min, int maxRandomAdditive) { byte[] bytes = new byte[min + (maxRandomAdditive == 0 ? 0 : RND.nextInt(maxRandomAdditive))]; @@ -298,7 +339,8 @@ public class TransferTo { } /* - * Creates a provider for an input stream which wraps a readable byte channel but is not a file channel + * Creates a provider for an input stream which wraps a readable byte + * channel but is not a file channel */ private static InputStreamProvider readableByteChannelInput() { return new InputStreamProvider() { @@ -316,7 +358,7 @@ public class TransferTo { return new OutputStreamProvider() { public OutputStream output(Consumer> spy) throws Exception { Path path = Files.createTempFile(CWD, "fileChannelOutput", null); - FileChannel fileChannel = FileChannel.open(path, StandardOpenOption.WRITE); + FileChannel fileChannel = FileChannel.open(path, WRITE); spy.accept(() -> { try { return Files.readAllBytes(path); -- GitLab From 7217cb78789046cfc823b63cacc36f6cf2b825f5 Mon Sep 17 00:00:00 2001 From: Maxim Kartashev Date: Tue, 7 Dec 2021 16:59:34 +0000 Subject: [PATCH 032/671] 8274883: (se) Selector.open throws IAE when the default file system provider is changed to a custom provider Reviewed-by: alanb, michaelm --- .../classes/sun/nio/ch/SocketChannelImpl.java | 4 +- .../classes/sun/nio/ch/UnixDomainSockets.java | 16 +- .../channels/Selector/CustomFileSystem.java | 37 ++++ .../Selector/CustomFileSystemProvider.java | 204 ++++++++++++++++++ 4 files changed, 256 insertions(+), 5 deletions(-) create mode 100644 test/jdk/java/nio/channels/Selector/CustomFileSystem.java create mode 100644 test/jdk/java/nio/channels/Selector/CustomFileSystemProvider.java diff --git a/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java b/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java index 477fa1afca2..117c14d5711 100644 --- a/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java +++ b/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java @@ -700,11 +700,11 @@ class SocketChannelImpl private SocketAddress unixBind(SocketAddress local) throws IOException { UnixDomainSockets.checkPermission(); if (local == null) { - return UnixDomainSockets.UNNAMED; + return UnixDomainSockets.unnamed(); } else { Path path = UnixDomainSockets.checkAddress(local).getPath(); if (path.toString().isEmpty()) { - return UnixDomainSockets.UNNAMED; + return UnixDomainSockets.unnamed(); } else { // bind to non-empty path UnixDomainSockets.bind(fd, path); diff --git a/src/java.base/share/classes/sun/nio/ch/UnixDomainSockets.java b/src/java.base/share/classes/sun/nio/ch/UnixDomainSockets.java index ee7e1d9d51a..251e79c6ecc 100644 --- a/src/java.base/share/classes/sun/nio/ch/UnixDomainSockets.java +++ b/src/java.base/share/classes/sun/nio/ch/UnixDomainSockets.java @@ -44,7 +44,9 @@ import sun.nio.fs.AbstractFileSystemProvider; class UnixDomainSockets { private UnixDomainSockets() { } - static final UnixDomainSocketAddress UNNAMED = UnixDomainSocketAddress.of(""); + private static class UnnamedHolder { + static final UnixDomainSocketAddress UNNAMED = UnixDomainSocketAddress.of(""); + } private static final boolean supported; @@ -71,7 +73,7 @@ class UnixDomainSockets { // Security check passed } catch (SecurityException e) { // Return unnamed address only if security check fails - addr = UNNAMED; + addr = unnamed(); } return addr; } @@ -133,7 +135,11 @@ class UnixDomainSockets { throw new BindException("Could not locate temporary directory for sockets"); int rnd = random.nextInt(Integer.MAX_VALUE); try { - Path path = Path.of(dir, "socket_" + rnd); + final Path path = Path.of(dir, "socket_" + rnd); + if (path.getFileSystem().provider() != sun.nio.fs.DefaultFileSystemProvider.instance()) { + throw new UnsupportedOperationException( + "Unix Domain Sockets not supported on non-default file system"); + } return UnixDomainSocketAddress.of(path); } catch (InvalidPathException e) { throw new BindException("Invalid temporary directory"); @@ -160,6 +166,10 @@ class UnixDomainSockets { return n; } + static UnixDomainSocketAddress unnamed() { + return UnnamedHolder.UNNAMED; + } + private static native boolean init(); private static native int socket0() throws IOException; diff --git a/test/jdk/java/nio/channels/Selector/CustomFileSystem.java b/test/jdk/java/nio/channels/Selector/CustomFileSystem.java new file mode 100644 index 00000000000..8113a716910 --- /dev/null +++ b/test/jdk/java/nio/channels/Selector/CustomFileSystem.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, JetBrains s.r.o.. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @summary Verifies that an attempt to call Selector.open() on a non-default + * file system succeeds. + * @build CustomFileSystem CustomFileSystemProvider + * @run main/othervm -Djava.nio.file.spi.DefaultFileSystemProvider=CustomFileSystemProvider CustomFileSystem + */ + +public class CustomFileSystem { + public static void main(String args[]) throws java.io.IOException { + java.nio.channels.Selector.open(); + } +} diff --git a/test/jdk/java/nio/channels/Selector/CustomFileSystemProvider.java b/test/jdk/java/nio/channels/Selector/CustomFileSystemProvider.java new file mode 100644 index 00000000000..f3e876e08a7 --- /dev/null +++ b/test/jdk/java/nio/channels/Selector/CustomFileSystemProvider.java @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, JetBrains s.r.o.. 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. + */ + +import java.io.File; +import java.io.IOException; +import java.net.URI; +import java.nio.channels.FileChannel; +import java.nio.channels.SeekableByteChannel; +import java.nio.file.AccessMode; +import java.nio.file.CopyOption; +import java.nio.file.DirectoryStream; +import java.nio.file.FileStore; +import java.nio.file.FileSystem; +import java.nio.file.LinkOption; +import java.nio.file.OpenOption; +import java.nio.file.Path; +import java.nio.file.ReadOnlyFileSystemException; +import java.nio.file.attribute.BasicFileAttributes; +import java.nio.file.attribute.FileAttribute; +import java.nio.file.attribute.FileAttributeView; +import java.nio.file.attribute.UserPrincipalLookupService; +import java.nio.file.spi.FileSystemProvider; +import java.util.Collections; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +public class CustomFileSystemProvider extends FileSystemProvider { + + private final FileSystemProvider defaultProvider; + + public CustomFileSystemProvider(FileSystemProvider defaultProvider) { + this.defaultProvider = defaultProvider; + } + + FileSystemProvider defaultProvider() { + return defaultProvider; + } + + @Override + public String getScheme() { + return "file"; + } + + @Override + public FileSystem newFileSystem(URI uri, Map env) throws IOException { + return defaultProvider.newFileSystem(uri, env); + } + + @Override + public FileSystem getFileSystem(URI uri) { + return defaultProvider.getFileSystem(uri); + } + + @Override + public Path getPath(URI uri) { + return defaultProvider.getPath(uri); + } + + @Override + public void setAttribute(Path file, String attribute, Object value, + LinkOption... options) + throws IOException + { + throw new RuntimeException("not implemented"); + } + + @Override + public Map readAttributes(Path file, String attributes, + LinkOption... options) + throws IOException + { + throw new RuntimeException("not implemented"); + } + + @Override + public A readAttributes(Path file, + Class type, + LinkOption... options) + throws IOException + { + throw new RuntimeException("not implemented"); + } + + @Override + public V getFileAttributeView(Path file, + Class type, + LinkOption... options) + { + throw new RuntimeException("not implemented"); + } + + @Override + public boolean isHidden(Path file) throws IOException { + throw new ReadOnlyFileSystemException(); + } + + @Override + public boolean isSameFile(Path file, Path other) throws IOException { + throw new RuntimeException("not implemented"); + } + + @Override + public void checkAccess(Path file, AccessMode... modes) + throws IOException + { + throw new RuntimeException("not implemented"); + } + + @Override + public void copy(Path source, Path target, CopyOption... options) + throws IOException + { + throw new RuntimeException("not implemented"); + } + + @Override + public void move(Path source, Path target, CopyOption... options) + throws IOException + { + throw new RuntimeException("not implemented"); + } + + @Override + public void delete(Path file) throws IOException { + throw new RuntimeException("not implemented"); + } + + @Override + public void createSymbolicLink(Path link, Path target, FileAttribute... attrs) + throws IOException + { + throw new RuntimeException("not implemented"); + } + + @Override + public void createLink(Path link, Path existing) throws IOException { + throw new RuntimeException("not implemented"); + } + + @Override + public Path readSymbolicLink(Path link) throws IOException { + throw new RuntimeException("not implemented"); + } + + @Override + public void createDirectory(Path dir, FileAttribute... attrs) + throws IOException + { + throw new RuntimeException("not implemented"); + } + + @Override + public DirectoryStream newDirectoryStream(Path dir, + DirectoryStream.Filter filter) + throws IOException + { + throw new RuntimeException("not implemented"); + } + + @Override + public SeekableByteChannel newByteChannel(Path file, + Set options, + FileAttribute... attrs) + throws IOException + { + throw new RuntimeException("not implemented"); + } + + @Override + public FileChannel newFileChannel(Path file, + Set options, + FileAttribute... attrs) + throws IOException + { + throw new RuntimeException("not implemented"); + } + + @Override + public FileStore getFileStore(Path file) throws IOException { + throw new RuntimeException("not implemented"); + } +} -- GitLab From 5a036ace01ebedd88fb3d9100e3a0c19871677ac Mon Sep 17 00:00:00 2001 From: Zhengyu Gu Date: Tue, 7 Dec 2021 17:42:08 +0000 Subject: [PATCH 033/671] 8277990: NMT: Remove NMT shutdown capability Reviewed-by: stuefe, shade --- src/hotspot/os/posix/perfMemory_posix.cpp | 2 +- src/hotspot/os/windows/perfMemory_windows.cpp | 2 +- src/hotspot/share/gc/z/zPhysicalMemory.cpp | 4 +- src/hotspot/share/prims/whitebox.cpp | 32 ---- src/hotspot/share/runtime/os.cpp | 8 +- .../share/services/mallocSiteTable.cpp | 175 +++++++----------- .../share/services/mallocSiteTable.hpp | 89 ++------- src/hotspot/share/services/mallocTracker.cpp | 27 +-- src/hotspot/share/services/mallocTracker.hpp | 7 - src/hotspot/share/services/memTracker.cpp | 42 +---- src/hotspot/share/services/memTracker.hpp | 40 ++-- src/hotspot/share/services/nmtCommon.cpp | 8 +- src/hotspot/share/services/nmtCommon.hpp | 25 +-- .../share/services/threadStackTracker.cpp | 15 +- .../share/services/threadStackTracker.hpp | 3 +- .../share/services/virtualMemoryTracker.cpp | 17 -- .../share/services/virtualMemoryTracker.hpp | 4 +- .../runtime/NMT/ChangeTrackingLevel.java | 49 ----- test/lib/jdk/test/whitebox/WhiteBox.java | 1 - test/lib/sun/hotspot/WhiteBox.java | 1 - 20 files changed, 118 insertions(+), 433 deletions(-) delete mode 100644 test/hotspot/jtreg/runtime/NMT/ChangeTrackingLevel.java diff --git a/src/hotspot/os/posix/perfMemory_posix.cpp b/src/hotspot/os/posix/perfMemory_posix.cpp index a89947f32ed..5d0448246bf 100644 --- a/src/hotspot/os/posix/perfMemory_posix.cpp +++ b/src/hotspot/os/posix/perfMemory_posix.cpp @@ -1028,7 +1028,7 @@ static char* mmap_create_shared(size_t size) { // static void unmap_shared(char* addr, size_t bytes) { int res; - if (MemTracker::tracking_level() > NMT_minimal) { + if (MemTracker::enabled()) { // Note: Tracker contains a ThreadCritical. Tracker tkr(Tracker::release); res = ::munmap(addr, bytes); diff --git a/src/hotspot/os/windows/perfMemory_windows.cpp b/src/hotspot/os/windows/perfMemory_windows.cpp index 600eb8882f9..0a53a94957c 100644 --- a/src/hotspot/os/windows/perfMemory_windows.cpp +++ b/src/hotspot/os/windows/perfMemory_windows.cpp @@ -1834,7 +1834,7 @@ void PerfMemory::detach(char* addr, size_t bytes) { return; } - if (MemTracker::tracking_level() > NMT_minimal) { + if (MemTracker::enabled()) { // it does not go through os api, the operation has to record from here Tracker tkr(Tracker::release); remove_file_mapping(addr); diff --git a/src/hotspot/share/gc/z/zPhysicalMemory.cpp b/src/hotspot/share/gc/z/zPhysicalMemory.cpp index abdf7df69b0..eb889f4e4f2 100644 --- a/src/hotspot/share/gc/z/zPhysicalMemory.cpp +++ b/src/hotspot/share/gc/z/zPhysicalMemory.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2021, 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 @@ -282,7 +282,7 @@ void ZPhysicalMemoryManager::nmt_commit(uintptr_t offset, size_t size) const { } void ZPhysicalMemoryManager::nmt_uncommit(uintptr_t offset, size_t size) const { - if (MemTracker::tracking_level() > NMT_minimal) { + if (MemTracker::enabled()) { const uintptr_t addr = ZAddress::marked0(offset); Tracker tracker(Tracker::uncommit); tracker.record((address)addr, size); diff --git a/src/hotspot/share/prims/whitebox.cpp b/src/hotspot/share/prims/whitebox.cpp index 4411ddc802d..03bda0315a1 100644 --- a/src/hotspot/share/prims/whitebox.cpp +++ b/src/hotspot/share/prims/whitebox.cpp @@ -703,37 +703,6 @@ WB_ENTRY(void, WB_NMTReleaseMemory(JNIEnv* env, jobject o, jlong addr, jlong siz os::release_memory((char *)(uintptr_t)addr, size); WB_END -WB_ENTRY(jboolean, WB_NMTChangeTrackingLevel(JNIEnv* env)) - // Test that we can downgrade NMT levels but not upgrade them. - if (MemTracker::tracking_level() == NMT_off) { - MemTracker::transition_to(NMT_off); - return MemTracker::tracking_level() == NMT_off; - } else { - assert(MemTracker::tracking_level() == NMT_detail, "Should start out as detail tracking"); - MemTracker::transition_to(NMT_summary); - assert(MemTracker::tracking_level() == NMT_summary, "Should be summary now"); - - // Can't go to detail once NMT is set to summary. - MemTracker::transition_to(NMT_detail); - assert(MemTracker::tracking_level() == NMT_summary, "Should still be summary now"); - - // Shutdown sets tracking level to minimal. - MemTracker::shutdown(); - assert(MemTracker::tracking_level() == NMT_minimal, "Should be minimal now"); - - // Once the tracking level is minimal, we cannot increase to summary. - // The code ignores this request instead of asserting because if the malloc site - // table overflows in another thread, it tries to change the code to summary. - MemTracker::transition_to(NMT_summary); - assert(MemTracker::tracking_level() == NMT_minimal, "Should still be minimal now"); - - // Really can never go up to detail, verify that the code would never do this. - MemTracker::transition_to(NMT_detail); - assert(MemTracker::tracking_level() == NMT_minimal, "Should still be minimal now"); - return MemTracker::tracking_level() == NMT_minimal; - } -WB_END - WB_ENTRY(jint, WB_NMTGetHashSize(JNIEnv* env, jobject o)) int hash_size = MallocSiteTable::hash_buckets(); assert(hash_size > 0, "NMT hash_size should be > 0"); @@ -2567,7 +2536,6 @@ static JNINativeMethod methods[] = { {CC"NMTCommitMemory", CC"(JJ)V", (void*)&WB_NMTCommitMemory }, {CC"NMTUncommitMemory", CC"(JJ)V", (void*)&WB_NMTUncommitMemory }, {CC"NMTReleaseMemory", CC"(JJ)V", (void*)&WB_NMTReleaseMemory }, - {CC"NMTChangeTrackingLevel", CC"()Z", (void*)&WB_NMTChangeTrackingLevel}, {CC"NMTGetHashSize", CC"()I", (void*)&WB_NMTGetHashSize }, {CC"NMTNewArena", CC"(J)J", (void*)&WB_NMTNewArena }, {CC"NMTFreeArena", CC"(J)V", (void*)&WB_NMTFreeArena }, diff --git a/src/hotspot/share/runtime/os.cpp b/src/hotspot/share/runtime/os.cpp index 65695f7d1ce..8263480c11d 100644 --- a/src/hotspot/share/runtime/os.cpp +++ b/src/hotspot/share/runtime/os.cpp @@ -1786,7 +1786,7 @@ void os::commit_memory_or_exit(char* addr, size_t size, size_t alignment_hint, bool os::uncommit_memory(char* addr, size_t bytes, bool executable) { bool res; - if (MemTracker::tracking_level() > NMT_minimal) { + if (MemTracker::enabled()) { Tracker tkr(Tracker::uncommit); res = pd_uncommit_memory(addr, bytes, executable); if (res) { @@ -1800,7 +1800,7 @@ bool os::uncommit_memory(char* addr, size_t bytes, bool executable) { bool os::release_memory(char* addr, size_t bytes) { bool res; - if (MemTracker::tracking_level() > NMT_minimal) { + if (MemTracker::enabled()) { // Note: Tracker contains a ThreadCritical. Tracker tkr(Tracker::release); res = pd_release_memory(addr, bytes); @@ -1869,7 +1869,7 @@ char* os::remap_memory(int fd, const char* file_name, size_t file_offset, bool os::unmap_memory(char *addr, size_t bytes) { bool result; - if (MemTracker::tracking_level() > NMT_minimal) { + if (MemTracker::enabled()) { Tracker tkr(Tracker::release); result = pd_unmap_memory(addr, bytes); if (result) { @@ -1905,7 +1905,7 @@ char* os::reserve_memory_special(size_t size, size_t alignment, size_t page_size bool os::release_memory_special(char* addr, size_t bytes) { bool res; - if (MemTracker::tracking_level() > NMT_minimal) { + if (MemTracker::enabled()) { // Note: Tracker contains a ThreadCritical. Tracker tkr(Tracker::release); res = pd_release_memory_special(addr, bytes); diff --git a/src/hotspot/share/services/mallocSiteTable.cpp b/src/hotspot/share/services/mallocSiteTable.cpp index dae1357cef1..2670c138daa 100644 --- a/src/hotspot/share/services/mallocSiteTable.cpp +++ b/src/hotspot/share/services/mallocSiteTable.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,12 +33,6 @@ MallocSiteHashtableEntry* MallocSiteTable::_table[MallocSiteTable::table_size]; const NativeCallStack* MallocSiteTable::_hash_entry_allocation_stack = NULL; const MallocSiteHashtableEntry* MallocSiteTable::_hash_entry_allocation_site = NULL; -// concurrent access counter -volatile int MallocSiteTable::_access_count = 0; - -// Tracking hashtable contention -NOT_PRODUCT(int MallocSiteTable::_peak_count = 0;) - /* * Initialize malloc site table. * Hashtable entry is malloc'd, so it can cause infinite recursion. @@ -202,122 +196,81 @@ void MallocSiteTable::delete_linked_list(MallocSiteHashtableEntry* head) { } } -void MallocSiteTable::shutdown() { - AccessLock locker(&_access_count); - locker.exclusiveLock(); - reset(); -} - bool MallocSiteTable::walk_malloc_site(MallocSiteWalker* walker) { assert(walker != NULL, "NuLL walker"); - AccessLock locker(&_access_count); - if (locker.sharedLock()) { - NOT_PRODUCT(_peak_count = MAX2(_peak_count, _access_count);) - return walk(walker); - } - return false; -} - - -void MallocSiteTable::AccessLock::exclusiveLock() { - int target; - int val; - - assert(_lock_state != ExclusiveLock, "Can only call once"); - assert(*_lock >= 0, "Can not content exclusive lock"); - - // make counter negative to block out shared locks - do { - val = *_lock; - target = _MAGIC_ + *_lock; - } while (Atomic::cmpxchg(_lock, val, target) != val); - - // wait for all readers to exit - while (*_lock != _MAGIC_) { -#ifdef _WINDOWS - os::naked_short_sleep(1); -#else - os::naked_yield(); -#endif - } - _lock_state = ExclusiveLock; + return walk(walker); } void MallocSiteTable::print_tuning_statistics(outputStream* st) { - - AccessLock locker(&_access_count); - if (locker.sharedLock()) { - // Total number of allocation sites, include empty sites - int total_entries = 0; - // Number of allocation sites that have all memory freed - int empty_entries = 0; - // Number of captured call stack distribution - int stack_depth_distribution[NMT_TrackingStackDepth + 1] = { 0 }; - // Chain lengths - int lengths[table_size] = { 0 }; - - for (int i = 0; i < table_size; i ++) { - int this_chain_length = 0; - const MallocSiteHashtableEntry* head = _table[i]; - while (head != NULL) { - total_entries ++; - this_chain_length ++; - if (head->size() == 0) { - empty_entries ++; - } - const int callstack_depth = head->peek()->call_stack()->frames(); - assert(callstack_depth >= 0 && callstack_depth <= NMT_TrackingStackDepth, - "Sanity (%d)", callstack_depth); - stack_depth_distribution[callstack_depth] ++; - head = head->next(); - } - lengths[i] = this_chain_length; - } - - st->print_cr("Malloc allocation site table:"); - st->print_cr("\tTotal entries: %d", total_entries); - st->print_cr("\tEmpty entries: %d (%2.2f%%)", empty_entries, ((float)empty_entries * 100) / total_entries); - st->cr(); - - // We report the hash distribution (chain length distribution) of the n shortest chains - // - under the assumption that this usually contains all lengths. Reporting threshold - // is 20, and the expected avg chain length is 5..6 (see table size). - static const int chain_length_threshold = 20; - int chain_length_distribution[chain_length_threshold] = { 0 }; - int over_threshold = 0; - int longest_chain_length = 0; - for (int i = 0; i < table_size; i ++) { - if (lengths[i] >= chain_length_threshold) { - over_threshold ++; - } else { - chain_length_distribution[lengths[i]] ++; + // Total number of allocation sites, include empty sites + int total_entries = 0; + // Number of allocation sites that have all memory freed + int empty_entries = 0; + // Number of captured call stack distribution + int stack_depth_distribution[NMT_TrackingStackDepth + 1] = { 0 }; + // Chain lengths + int lengths[table_size] = { 0 }; + + for (int i = 0; i < table_size; i ++) { + int this_chain_length = 0; + const MallocSiteHashtableEntry* head = _table[i]; + while (head != NULL) { + total_entries ++; + this_chain_length ++; + if (head->size() == 0) { + empty_entries ++; } - longest_chain_length = MAX2(longest_chain_length, lengths[i]); + const int callstack_depth = head->peek()->call_stack()->frames(); + assert(callstack_depth >= 0 && callstack_depth <= NMT_TrackingStackDepth, + "Sanity (%d)", callstack_depth); + stack_depth_distribution[callstack_depth] ++; + head = head->next(); } + lengths[i] = this_chain_length; + } - st->print_cr("Hash distribution:"); - if (chain_length_distribution[0] == 0) { - st->print_cr("no empty buckets."); + st->print_cr("Malloc allocation site table:"); + st->print_cr("\tTotal entries: %d", total_entries); + st->print_cr("\tEmpty entries: %d (%2.2f%%)", empty_entries, ((float)empty_entries * 100) / total_entries); + st->cr(); + + // We report the hash distribution (chain length distribution) of the n shortest chains + // - under the assumption that this usually contains all lengths. Reporting threshold + // is 20, and the expected avg chain length is 5..6 (see table size). + static const int chain_length_threshold = 20; + int chain_length_distribution[chain_length_threshold] = { 0 }; + int over_threshold = 0; + int longest_chain_length = 0; + for (int i = 0; i < table_size; i ++) { + if (lengths[i] >= chain_length_threshold) { + over_threshold ++; } else { - st->print_cr("%d buckets are empty.", chain_length_distribution[0]); - } - for (int len = 1; len < MIN2(longest_chain_length + 1, chain_length_threshold); len ++) { - st->print_cr("%2d %s: %d.", len, (len == 1 ? " entry" : "entries"), chain_length_distribution[len]); + chain_length_distribution[lengths[i]] ++; } - if (longest_chain_length >= chain_length_threshold) { - st->print_cr(">=%2d entries: %d.", chain_length_threshold, over_threshold); - } - st->print_cr("most entries: %d.", longest_chain_length); - st->cr(); + longest_chain_length = MAX2(longest_chain_length, lengths[i]); + } - st->print_cr("Call stack depth distribution:"); - for (int i = 0; i <= NMT_TrackingStackDepth; i ++) { - st->print_cr("\t%d: %d", i, stack_depth_distribution[i]); - } - st->cr(); - } // lock -} + st->print_cr("Hash distribution:"); + if (chain_length_distribution[0] == 0) { + st->print_cr("no empty buckets."); + } else { + st->print_cr("%d buckets are empty.", chain_length_distribution[0]); + } + for (int len = 1; len < MIN2(longest_chain_length + 1, chain_length_threshold); len ++) { + st->print_cr("%2d %s: %d.", len, (len == 1 ? " entry" : "entries"), chain_length_distribution[len]); + } + if (longest_chain_length >= chain_length_threshold) { + st->print_cr(">=%2d entries: %d.", chain_length_threshold, over_threshold); + } + st->print_cr("most entries: %d.", longest_chain_length); + st->cr(); + st->print_cr("Call stack depth distribution:"); + for (int i = 0; i <= NMT_TrackingStackDepth; i ++) { + st->print_cr("\t%d: %d", i, stack_depth_distribution[i]); + } + st->cr(); +} bool MallocSiteHashtableEntry::atomic_insert(MallocSiteHashtableEntry* entry) { return Atomic::replace_if_null(&_next, entry); diff --git a/src/hotspot/share/services/mallocSiteTable.hpp b/src/hotspot/share/services/mallocSiteTable.hpp index 8aa25310326..6e026f9704c 100644 --- a/src/hotspot/share/services/mallocSiteTable.hpp +++ b/src/hotspot/share/services/mallocSiteTable.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2021, 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 @@ -118,54 +118,8 @@ class MallocSiteTable : AllStatic { // in the malloc header can hold. STATIC_ASSERT(table_size <= MAX_MALLOCSITE_TABLE_SIZE); - // This is a very special lock, that allows multiple shared accesses (sharedLock), but - // once exclusive access (exclusiveLock) is requested, all shared accesses are - // rejected forever. - class AccessLock : public StackObj { - enum LockState { - NoLock, - SharedLock, - ExclusiveLock - }; - - private: - // A very large negative number. The only possibility to "overflow" - // this number is when there are more than -min_jint threads in - // this process, which is not going to happen in foreseeable future. - const static int _MAGIC_ = min_jint; - - LockState _lock_state; - volatile int* _lock; - public: - AccessLock(volatile int* lock) : - _lock_state(NoLock), _lock(lock) { - } - - ~AccessLock() { - if (_lock_state == SharedLock) { - Atomic::dec(_lock); - } - } - // Acquire shared lock. - // Return true if shared access is granted. - inline bool sharedLock() { - jint res = Atomic::add(_lock, 1); - if (res < 0) { - Atomic::dec(_lock); - return false; - } - _lock_state = SharedLock; - return true; - } - // Acquire exclusive lock - void exclusiveLock(); - }; - public: static bool initialize(); - static void shutdown(); - - NOT_PRODUCT(static int access_peak_count() { return _peak_count; }) // Number of hash buckets static inline int hash_buckets() { return (int)table_size; } @@ -174,14 +128,10 @@ class MallocSiteTable : AllStatic { // acquired before access the entry. static inline bool access_stack(NativeCallStack& stack, size_t bucket_idx, size_t pos_idx) { - AccessLock locker(&_access_count); - if (locker.sharedLock()) { - NOT_PRODUCT(_peak_count = MAX2(_peak_count, _access_count);) - MallocSite* site = malloc_site(bucket_idx, pos_idx); - if (site != NULL) { - stack = *site->call_stack(); - return true; - } + MallocSite* site = malloc_site(bucket_idx, pos_idx); + if (site != NULL) { + stack = *site->call_stack(); + return true; } return false; } @@ -195,27 +145,18 @@ class MallocSiteTable : AllStatic { // 2. overflow hash bucket static inline bool allocation_at(const NativeCallStack& stack, size_t size, size_t* bucket_idx, size_t* pos_idx, MEMFLAGS flags) { - AccessLock locker(&_access_count); - if (locker.sharedLock()) { - NOT_PRODUCT(_peak_count = MAX2(_peak_count, _access_count);) - MallocSite* site = lookup_or_add(stack, bucket_idx, pos_idx, flags); - if (site != NULL) site->allocate(size); - return site != NULL; - } - return false; + MallocSite* site = lookup_or_add(stack, bucket_idx, pos_idx, flags); + if (site != NULL) site->allocate(size); + return site != NULL; } // Record memory deallocation. bucket_idx and pos_idx indicate where the allocation // information was recorded. static inline bool deallocation_at(size_t size, size_t bucket_idx, size_t pos_idx) { - AccessLock locker(&_access_count); - if (locker.sharedLock()) { - NOT_PRODUCT(_peak_count = MAX2(_peak_count, _access_count);) - MallocSite* site = malloc_site(bucket_idx, pos_idx); - if (site != NULL) { - site->deallocate(size); - return true; - } + MallocSite* site = malloc_site(bucket_idx, pos_idx); + if (site != NULL) { + site->deallocate(size); + return true; } return false; } @@ -251,17 +192,11 @@ class MallocSiteTable : AllStatic { } private: - // Counter for counting concurrent access - static volatile int _access_count; - // The callsite hashtable. It has to be a static table, // since malloc call can come from C runtime linker. static MallocSiteHashtableEntry* _table[table_size]; static const NativeCallStack* _hash_entry_allocation_stack; static const MallocSiteHashtableEntry* _hash_entry_allocation_site; - - - NOT_PRODUCT(static int _peak_count;) }; #endif // INCLUDE_NMT diff --git a/src/hotspot/share/services/mallocTracker.cpp b/src/hotspot/share/services/mallocTracker.cpp index be1d6eea330..285a60d853f 100644 --- a/src/hotspot/share/services/mallocTracker.cpp +++ b/src/hotspot/share/services/mallocTracker.cpp @@ -113,8 +113,7 @@ void MallocHeader::mark_block_as_dead() { } void MallocHeader::release() { - // Tracking already shutdown, no housekeeping is needed anymore - if (MemTracker::tracking_level() <= NMT_minimal) return; + assert(MemTracker::enabled(), "Sanity"); check_block_integrity(); @@ -222,15 +221,7 @@ void MallocHeader::check_block_integrity() const { bool MallocHeader::record_malloc_site(const NativeCallStack& stack, size_t size, size_t* bucket_idx, size_t* pos_idx, MEMFLAGS flags) const { - bool ret = MallocSiteTable::allocation_at(stack, size, bucket_idx, pos_idx, flags); - - // Something went wrong, could be OOM or overflow malloc site table. - // We want to keep tracking data under OOM circumstance, so transition to - // summary tracking. - if (!ret) { - MemTracker::transition_to(NMT_summary); - } - return ret; + return MallocSiteTable::allocation_at(stack, size, bucket_idx, pos_idx, flags); } bool MallocHeader::get_stack(NativeCallStack& stack) const { @@ -248,18 +239,6 @@ bool MallocTracker::initialize(NMT_TrackingLevel level) { return true; } -bool MallocTracker::transition(NMT_TrackingLevel from, NMT_TrackingLevel to) { - assert(from != NMT_off, "Can not transition from off state"); - assert(to != NMT_off, "Can not transition to off state"); - assert (from != NMT_minimal, "cannot transition from minimal state"); - - if (from == NMT_detail) { - assert(to == NMT_minimal || to == NMT_summary, "Just check"); - MallocSiteTable::shutdown(); - } - return true; -} - // Record a malloc memory allocation void* MallocTracker::record_malloc(void* malloc_base, size_t size, MEMFLAGS flags, const NativeCallStack& stack, NMT_TrackingLevel level) { @@ -281,7 +260,7 @@ void* MallocTracker::record_malloc(void* malloc_base, size_t size, MEMFLAGS flag assert(((size_t)memblock & (sizeof(size_t) * 2 - 1)) == 0, "Alignment check"); #ifdef ASSERT - if (level > NMT_minimal) { + if (level > NMT_off) { // Read back assert(get_size(memblock) == size, "Wrong size"); assert(get_flags(memblock) == flags, "Wrong flags"); diff --git a/src/hotspot/share/services/mallocTracker.hpp b/src/hotspot/share/services/mallocTracker.hpp index 9fd3968831b..6490b3d53ff 100644 --- a/src/hotspot/share/services/mallocTracker.hpp +++ b/src/hotspot/share/services/mallocTracker.hpp @@ -330,13 +330,8 @@ class MallocHeader { public: MallocHeader(size_t size, MEMFLAGS flags, const NativeCallStack& stack, NMT_TrackingLevel level) { - assert(size < max_reasonable_malloc_size, "Too large allocation size?"); - if (level == NMT_minimal) { - return; - } - _flags = NMTUtil::flag_to_index(flags); set_size(size); if (level == NMT_detail) { @@ -386,8 +381,6 @@ class MallocTracker : AllStatic { // Initialize malloc tracker for specific tracking level static bool initialize(NMT_TrackingLevel level); - static bool transition(NMT_TrackingLevel from, NMT_TrackingLevel to); - // malloc tracking header size for specific tracking level static inline size_t malloc_header_size(NMT_TrackingLevel level) { return (level == NMT_off) ? 0 : sizeof(MallocHeader); diff --git a/src/hotspot/share/services/memTracker.cpp b/src/hotspot/share/services/memTracker.cpp index a28d3badbcf..1037ec27418 100644 --- a/src/hotspot/share/services/memTracker.cpp +++ b/src/hotspot/share/services/memTracker.cpp @@ -108,41 +108,9 @@ void Tracker::record(address addr, size_t size) { } } - -// Shutdown can only be issued via JCmd, and NMT JCmd is serialized by lock -void MemTracker::shutdown() { - // We can only shutdown NMT to minimal tracking level if it is ever on. - if (tracking_level() > NMT_minimal) { - transition_to(NMT_minimal); - } -} - -bool MemTracker::transition_to(NMT_TrackingLevel level) { - NMT_TrackingLevel current_level = tracking_level(); - - assert(level != NMT_off || current_level == NMT_off, "Cannot transition NMT to off"); - - if (current_level == level) { - return true; - } else if (current_level > level) { - // Downgrade tracking level, we want to lower the tracking level first - _tracking_level = level; - // Make _tracking_level visible immediately. - OrderAccess::fence(); - VirtualMemoryTracker::transition(current_level, level); - MallocTracker::transition(current_level, level); - ThreadStackTracker::transition(current_level, level); - } else { - // Upgrading tracking level is not supported and has never been supported. - // Allocating and deallocating malloc tracking structures is not thread safe and - // leads to inconsistencies unless a lot coarser locks are added. - } - return true; -} - // Report during error reporting. void MemTracker::error_report(outputStream* output) { - if (tracking_level() >= NMT_summary) { + if (enabled()) { report(true, output, MemReporterBase::default_scale); // just print summary for error case. output->print("Preinit state:"); NMTPreInit::print_state(output); @@ -157,11 +125,8 @@ void MemTracker::final_report(outputStream* output) { // printing the final report during normal VM exit, it should not print // the final report again. In addition, it should be guarded from // recursive calls in case NMT reporting itself crashes. - if (Atomic::cmpxchg(&g_final_report_did_run, false, true) == false) { - NMT_TrackingLevel level = tracking_level(); - if (level >= NMT_summary) { - report(level == NMT_summary, output, 1); - } + if (enabled() && Atomic::cmpxchg(&g_final_report_did_run, false, true) == false) { + report(tracking_level() == NMT_summary, output, 1); } } @@ -189,7 +154,6 @@ void MemTracker::tuning_statistics(outputStream* out) { out->print_cr("State: %s", NMTUtil::tracking_level_to_string(_tracking_level)); out->print_cr("Malloc allocation site table size: %d", MallocSiteTable::hash_buckets()); out->print_cr(" Tracking stack depth: %d", NMT_TrackingStackDepth); - NOT_PRODUCT(out->print_cr("Peak concurrent access: %d", MallocSiteTable::access_peak_count());) out->cr(); MallocSiteTable::print_tuning_statistics(out); out->cr(); diff --git a/src/hotspot/share/services/memTracker.hpp b/src/hotspot/share/services/memTracker.hpp index 21d1aa82630..1c81c3f7928 100644 --- a/src/hotspot/share/services/memTracker.hpp +++ b/src/hotspot/share/services/memTracker.hpp @@ -49,7 +49,7 @@ class Tracker : public StackObj { class MemTracker : AllStatic { public: static inline NMT_TrackingLevel tracking_level() { return NMT_off; } - static inline void shutdown() { } + static inline bool enabled() { return false; } static inline void init() { } static bool check_launcher_nmt_support(const char* value) { return true; } static bool verify_nmt_option() { return true; } @@ -137,14 +137,9 @@ class MemTracker : AllStatic { return _tracking_level; } - // Shutdown native memory tracking. - // This transitions the tracking level: - // summary -> minimal - // detail -> minimal - static void shutdown(); - - // Transition the tracking level to specified level - static bool transition_to(NMT_TrackingLevel level); + static inline bool enabled() { + return _tracking_level > NMT_off; + } static inline void* record_malloc(void* mem_base, size_t size, MEMFLAGS flag, const NativeCallStack& stack, NMT_TrackingLevel level) { @@ -180,20 +175,20 @@ class MemTracker : AllStatic { // Record creation of an arena static inline void record_new_arena(MEMFLAGS flag) { - if (tracking_level() < NMT_summary) return; + if (!enabled()) return; MallocTracker::record_new_arena(flag); } // Record destruction of an arena static inline void record_arena_free(MEMFLAGS flag) { - if (tracking_level() < NMT_summary) return; + if (!enabled()) return; MallocTracker::record_arena_free(flag); } // Record arena size change. Arena size is the size of all arena // chuncks that backing up the arena. static inline void record_arena_size_change(ssize_t diff, MEMFLAGS flag) { - if (tracking_level() < NMT_summary) return; + if (!enabled()) return; MallocTracker::record_arena_size_change(diff, flag); } @@ -203,11 +198,9 @@ class MemTracker : AllStatic { static inline void record_virtual_memory_reserve(void* addr, size_t size, const NativeCallStack& stack, MEMFLAGS flag = mtNone) { assert_post_init(); - if (tracking_level() < NMT_summary) return; + if (!enabled()) return; if (addr != NULL) { ThreadCritical tc; - // Recheck to avoid potential racing during NMT shutdown - if (tracking_level() < NMT_summary) return; VirtualMemoryTracker::add_reserved_region((address)addr, size, stack, flag); } } @@ -215,10 +208,9 @@ class MemTracker : AllStatic { static inline void record_virtual_memory_reserve_and_commit(void* addr, size_t size, const NativeCallStack& stack, MEMFLAGS flag = mtNone) { assert_post_init(); - if (tracking_level() < NMT_summary) return; + if (!enabled()) return; if (addr != NULL) { ThreadCritical tc; - if (tracking_level() < NMT_summary) return; VirtualMemoryTracker::add_reserved_region((address)addr, size, stack, flag); VirtualMemoryTracker::add_committed_region((address)addr, size, stack); } @@ -227,10 +219,9 @@ class MemTracker : AllStatic { static inline void record_virtual_memory_commit(void* addr, size_t size, const NativeCallStack& stack) { assert_post_init(); - if (tracking_level() < NMT_summary) return; + if (!enabled()) return; if (addr != NULL) { ThreadCritical tc; - if (tracking_level() < NMT_summary) return; VirtualMemoryTracker::add_committed_region((address)addr, size, stack); } } @@ -243,28 +234,25 @@ class MemTracker : AllStatic { // memory flags of the original region. static inline void record_virtual_memory_split_reserved(void* addr, size_t size, size_t split) { assert_post_init(); - if (tracking_level() < NMT_summary) return; + if (!enabled()) return; if (addr != NULL) { ThreadCritical tc; - // Recheck to avoid potential racing during NMT shutdown - if (tracking_level() < NMT_summary) return; VirtualMemoryTracker::split_reserved_region((address)addr, size, split); } } static inline void record_virtual_memory_type(void* addr, MEMFLAGS flag) { assert_post_init(); - if (tracking_level() < NMT_summary) return; + if (!enabled()) return; if (addr != NULL) { ThreadCritical tc; - if (tracking_level() < NMT_summary) return; VirtualMemoryTracker::set_reserved_region_type((address)addr, flag); } } static void record_thread_stack(void* addr, size_t size) { assert_post_init(); - if (tracking_level() < NMT_summary) return; + if (!enabled()) return; if (addr != NULL) { ThreadStackTracker::new_thread_stack((address)addr, size, CALLER_PC); } @@ -272,7 +260,7 @@ class MemTracker : AllStatic { static inline void release_thread_stack(void* addr, size_t size) { assert_post_init(); - if (tracking_level() < NMT_summary) return; + if (!enabled()) return; if (addr != NULL) { ThreadStackTracker::delete_thread_stack((address)addr, size); } diff --git a/src/hotspot/share/services/nmtCommon.cpp b/src/hotspot/share/services/nmtCommon.cpp index 0137a880d8c..2494336595b 100644 --- a/src/hotspot/share/services/nmtCommon.cpp +++ b/src/hotspot/share/services/nmtCommon.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2021, 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 @@ -28,11 +28,14 @@ #define MEMORY_TYPE_DECLARE_NAME(type, human_readable) \ human_readable, +STATIC_ASSERT(NMT_off > NMT_unknown); +STATIC_ASSERT(NMT_summary > NMT_off); +STATIC_ASSERT(NMT_detail > NMT_summary); + const char* NMTUtil::_memory_type_names[] = { MEMORY_TYPES_DO(MEMORY_TYPE_DECLARE_NAME) }; - const char* NMTUtil::scale_name(size_t scale) { switch(scale) { case 1: return ""; @@ -64,7 +67,6 @@ const char* NMTUtil::tracking_level_to_string(NMT_TrackingLevel lvl) { switch(lvl) { case NMT_unknown: return "unknown"; break; case NMT_off: return "off"; break; - case NMT_minimal: return "minimal"; break; case NMT_summary: return "summary"; break; case NMT_detail: return "detail"; break; default: return "invalid"; break; diff --git a/src/hotspot/share/services/nmtCommon.hpp b/src/hotspot/share/services/nmtCommon.hpp index 10876976091..b573fb6b7df 100644 --- a/src/hotspot/share/services/nmtCommon.hpp +++ b/src/hotspot/share/services/nmtCommon.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,10 +41,6 @@ // - nothing is tracked // - no malloc headers are used // -// "minimal": after shutdown - NMT had been on at some point but has been switched off -// - nothing is tracked -// - malloc headers are allocated but not initialized not used -// // "summary": after initialization with NativeMemoryTracking=summary - NMT in summary mode // - category summaries per tag are tracked // - thread stacks are tracked @@ -59,25 +55,16 @@ // - malloc headers are used // - malloc call site table is allocated and used // -// Valid state transitions: -// -// unknown ----> off -// | -// |--> summary -- -// | | -// |--> detail --+--> minimal -// // Please keep relation of numerical values! -// unknown < off < minimal < summary < detail +// unknown < off < summary < detail // enum NMT_TrackingLevel { - NMT_unknown = 0, - NMT_off = 1, - NMT_minimal = 2, - NMT_summary = 3, - NMT_detail = 4 + NMT_unknown, + NMT_off, + NMT_summary, + NMT_detail }; // Number of stack frames to capture. This is a diff --git a/src/hotspot/share/services/threadStackTracker.cpp b/src/hotspot/share/services/threadStackTracker.cpp index b426e81613b..5caad66bb89 100644 --- a/src/hotspot/share/services/threadStackTracker.cpp +++ b/src/hotspot/share/services/threadStackTracker.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Red Hat, Inc. All rights reserved. + * Copyright (c) 2019, 2021, Red Hat, Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,19 +42,6 @@ bool ThreadStackTracker::initialize(NMT_TrackingLevel level) { return true; } -bool ThreadStackTracker::transition(NMT_TrackingLevel from, NMT_TrackingLevel to) { - assert (from != NMT_minimal, "cannot convert from the lowest tracking level to anything"); - if (to == NMT_minimal) { - assert(from == NMT_summary || from == NMT_detail, "Just check"); - ThreadCritical tc; - if (_simple_thread_stacks != NULL) { - delete _simple_thread_stacks; - _simple_thread_stacks = NULL; - } - } - return true; -} - int ThreadStackTracker::compare_thread_stack_base(const SimpleThreadStackSite& s1, const SimpleThreadStackSite& s2) { return s1.base() - s2.base(); } diff --git a/src/hotspot/share/services/threadStackTracker.hpp b/src/hotspot/share/services/threadStackTracker.hpp index 3eee93cd71c..74e2311b763 100644 --- a/src/hotspot/share/services/threadStackTracker.hpp +++ b/src/hotspot/share/services/threadStackTracker.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Red Hat, Inc. All rights reserved. + * Copyright (c) 2019, 2021, Red Hat, Inc. 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 @@ -72,7 +72,6 @@ private: static SortedLinkedList* _simple_thread_stacks; public: static bool initialize(NMT_TrackingLevel level); - static bool transition(NMT_TrackingLevel from, NMT_TrackingLevel to); static void new_thread_stack(void* base, size_t size, const NativeCallStack& stack); static void delete_thread_stack(void* base, size_t size); diff --git a/src/hotspot/share/services/virtualMemoryTracker.cpp b/src/hotspot/share/services/virtualMemoryTracker.cpp index f9909f9e569..77fb24927f5 100644 --- a/src/hotspot/share/services/virtualMemoryTracker.cpp +++ b/src/hotspot/share/services/virtualMemoryTracker.cpp @@ -671,20 +671,3 @@ bool VirtualMemoryTracker::walk_virtual_memory(VirtualMemoryWalker* walker) { } return true; } - -// Transition virtual memory tracking level. -bool VirtualMemoryTracker::transition(NMT_TrackingLevel from, NMT_TrackingLevel to) { - assert (from != NMT_minimal, "cannot convert from the lowest tracking level to anything"); - if (to == NMT_minimal) { - assert(from == NMT_summary || from == NMT_detail, "Just check"); - // Clean up virtual memory tracking data structures. - ThreadCritical tc; - // Check for potential race with other thread calling transition - if (_reserved_regions != NULL) { - delete _reserved_regions; - _reserved_regions = NULL; - } - } - - return true; -} diff --git a/src/hotspot/share/services/virtualMemoryTracker.hpp b/src/hotspot/share/services/virtualMemoryTracker.hpp index a7948f67447..c96af6b8387 100644 --- a/src/hotspot/share/services/virtualMemoryTracker.hpp +++ b/src/hotspot/share/services/virtualMemoryTracker.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2021, 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 @@ -387,8 +387,6 @@ class VirtualMemoryTracker : AllStatic { // Walk virtual memory data structure for creating baseline, etc. static bool walk_virtual_memory(VirtualMemoryWalker* walker); - static bool transition(NMT_TrackingLevel from, NMT_TrackingLevel to); - // Snapshot current thread stacks static void snapshot_thread_stacks(); diff --git a/test/hotspot/jtreg/runtime/NMT/ChangeTrackingLevel.java b/test/hotspot/jtreg/runtime/NMT/ChangeTrackingLevel.java deleted file mode 100644 index 0cc059c13b9..00000000000 --- a/test/hotspot/jtreg/runtime/NMT/ChangeTrackingLevel.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2013, 2021, 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. - */ - -/* - * @test - * @bug 8059100 - * @summary Test that you can decrease NMT tracking level but not increase it. - * @modules java.base/jdk.internal.misc - * @library /test/lib - * @build sun.hotspot.WhiteBox - * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail ChangeTrackingLevel - */ - -import sun.hotspot.WhiteBox; - -public class ChangeTrackingLevel { - - public static WhiteBox wb = WhiteBox.getWhiteBox(); - public static void main(String args[]) throws Exception { - boolean testChangeLevel = wb.NMTChangeTrackingLevel(); - if (testChangeLevel) { - System.out.println("NMT level change test passed."); - } else { - // it also fails if the VM asserts. - throw new RuntimeException("NMT level change test failed"); - } - } -}; diff --git a/test/lib/jdk/test/whitebox/WhiteBox.java b/test/lib/jdk/test/whitebox/WhiteBox.java index c4f90b975a4..e1e137f3b89 100644 --- a/test/lib/jdk/test/whitebox/WhiteBox.java +++ b/test/lib/jdk/test/whitebox/WhiteBox.java @@ -225,7 +225,6 @@ public class WhiteBox { public native void NMTReleaseMemory(long addr, long size); public native long NMTMallocWithPseudoStack(long size, int index); public native long NMTMallocWithPseudoStackAndType(long size, int index, int type); - public native boolean NMTChangeTrackingLevel(); public native int NMTGetHashSize(); public native long NMTNewArena(long initSize); public native void NMTFreeArena(long arena); diff --git a/test/lib/sun/hotspot/WhiteBox.java b/test/lib/sun/hotspot/WhiteBox.java index 4536e608093..1729545b0bb 100644 --- a/test/lib/sun/hotspot/WhiteBox.java +++ b/test/lib/sun/hotspot/WhiteBox.java @@ -226,7 +226,6 @@ public class WhiteBox { public native void NMTReleaseMemory(long addr, long size); public native long NMTMallocWithPseudoStack(long size, int index); public native long NMTMallocWithPseudoStackAndType(long size, int index, int type); - public native boolean NMTChangeTrackingLevel(); public native int NMTGetHashSize(); public native long NMTNewArena(long initSize); public native void NMTFreeArena(long arena); -- GitLab From 3955b037da8a0981d8efc67f28caaacdef7dfb31 Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Tue, 7 Dec 2021 18:15:25 +0000 Subject: [PATCH 034/671] 8277328: jdk/jshell/CommandCompletionTest.java failures on Windows Reviewed-by: vromero --- .../jdk/internal/jshell/tool/JShellTool.java | 8 +++--- .../jdk/jshell/CommandCompletionTest.java | 25 ++++++++++++++++--- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java index b257b132363..ac78e23eff6 100644 --- a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java +++ b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java @@ -254,7 +254,7 @@ public class JShellTool implements MessageHandler { Pattern.compile(OPTION_PRE_PATTERN.pattern() + "(?

-??)(?-([a-z][a-z\\-]*)?)"); // match an option flag and a (possibly missing or incomplete) value private static final Pattern OPTION_VALUE_PATTERN = - Pattern.compile(OPTION_PATTERN.pattern() + "\\s+(?\\S*)"); + Pattern.compile(OPTION_PATTERN.pattern() + "\\s+(?(\\S|\\\\ )*)"); // Tool id (tid) mapping: the three name spaces NameSpace mainNamespace; @@ -1561,13 +1561,13 @@ public class JShellTool implements MessageHandler { private static CompletionProvider fileCompletions(Predicate accept) { return (code, cursor, anchor) -> { int lastSlash = code.lastIndexOf('/'); - String path = code.substring(0, lastSlash + 1); - String prefix = lastSlash != (-1) ? code.substring(lastSlash + 1) : code; + String path = code.substring(0, lastSlash + 1).replace("\\ ", " "); + String prefix = (lastSlash != (-1) ? code.substring(lastSlash + 1) : code).replace("\\ ", " "); Path current = toPathResolvingUserHome(path); List result = new ArrayList<>(); try (Stream dir = Files.list(current)) { dir.filter(f -> accept.test(f) && f.getFileName().toString().startsWith(prefix)) - .map(f -> new ArgSuggestion(f.getFileName() + (Files.isDirectory(f) ? "/" : ""))) + .map(f -> new ArgSuggestion(f.getFileName().toString().replace(" ", "\\ ") + (Files.isDirectory(f) ? "/" : ""))) .forEach(result::add); } catch (IOException ex) { //ignore... diff --git a/test/langtools/jdk/jshell/CommandCompletionTest.java b/test/langtools/jdk/jshell/CommandCompletionTest.java index 27746a748b9..3a5eb1a46a7 100644 --- a/test/langtools/jdk/jshell/CommandCompletionTest.java +++ b/test/langtools/jdk/jshell/CommandCompletionTest.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8144095 8164825 8169818 8153402 8165405 8177079 8178013 8167554 8166232 + * @bug 8144095 8164825 8169818 8153402 8165405 8177079 8178013 8167554 8166232 8277328 * @summary Test Command Completion * @modules jdk.compiler/com.sun.tools.javac.api * jdk.compiler/com.sun.tools.javac.main @@ -331,6 +331,22 @@ public class CommandCompletionTest extends ReplToolTesting { ); } + @Test + public void testClassPathWithSpace() throws IOException { + Compiler compiler = new Compiler(); + Path outDir = compiler.getPath("testClassPathWithSpace"); + Path dirWithSpace = Files.createDirectories(outDir.resolve("dir with space")); + Files.createDirectories(dirWithSpace.resolve("nested with space")); + String[] pathArray = new String[] {"dir\\ with\\ space/"}; + String[] pathArray2 = new String[] {"nested\\ with\\ space/"}; + testNoStartUp( + a -> assertCompletion(a, "/env -class-path " + outDir + "/|", false, pathArray), + a -> assertCompletion(a, "/env -class-path " + outDir + "/dir|", false, pathArray), + a -> assertCompletion(a, "/env -class-path " + outDir + "/dir\\ with|", false, pathArray), + a -> assertCompletion(a, "/env -class-path " + outDir + "/dir\\ with\\ space/|", false, pathArray2) + ); + } + @Test public void testUserHome() throws IOException { List completions; @@ -338,8 +354,9 @@ public class CommandCompletionTest extends ReplToolTesting { String selectedFile; try (Stream content = Files.list(home)) { selectedFile = content.filter(CLASSPATH_FILTER) + .filter(file -> file.getFileName().toString().contains(" ")) .findAny() - .map(file -> file.getFileName().toString()) + .map(file -> file.getFileName().toString().replace(" ", "\\ ")) .orElse(null); } if (selectedFile == null) { @@ -347,8 +364,8 @@ public class CommandCompletionTest extends ReplToolTesting { } try (Stream content = Files.list(home)) { completions = content.filter(CLASSPATH_FILTER) - .filter(file -> file.getFileName().toString().startsWith(selectedFile)) - .map(file -> file.getFileName().toString() + (Files.isDirectory(file) ? "/" : "")) + .filter(file -> file.getFileName().toString().startsWith(selectedFile.replace("\\ ", " "))) + .map(file -> file.getFileName().toString().replace(" ", "\\ ") + (Files.isDirectory(file) ? "/" : "")) .sorted() .collect(Collectors.toList()); } -- GitLab From d7c283a081c37bfb8bc5934e4b2af16cad512fd2 Mon Sep 17 00:00:00 2001 From: Liam Miller-Cushon Date: Tue, 7 Dec 2021 18:44:39 +0000 Subject: [PATCH 035/671] 8275233: Incorrect line number reported in exception stack trace thrown from a lambda expression Reviewed-by: jlahoda --- .../sun/tools/javac/comp/LambdaToMethod.java | 11 +++-- .../diags/examples/LambdaDeduplicate.java | 2 +- .../deduplication/DeduplicationDebugInfo.java | 41 +++++++++++++++++++ .../deduplication/DeduplicationDebugInfo.out | 1 + .../DeduplicationDebugInfo_none.out | 0 .../deduplication/DeduplicationTest.java | 1 + 6 files changed, 52 insertions(+), 4 deletions(-) create mode 100644 test/langtools/tools/javac/lambda/deduplication/DeduplicationDebugInfo.java create mode 100644 test/langtools/tools/javac/lambda/deduplication/DeduplicationDebugInfo.out create mode 100644 test/langtools/tools/javac/lambda/deduplication/DeduplicationDebugInfo_none.out diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java index 55f79c5bc1c..0638da66a89 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java @@ -165,9 +165,14 @@ public class LambdaToMethod extends TreeTranslator { dumpLambdaToMethodStats = options.isSet("debug.dumpLambdaToMethodStats"); attr = Attr.instance(context); forceSerializable = options.isSet("forceSerializable"); - debugLinesOrVars = options.isSet(Option.G) - || options.isSet(Option.G_CUSTOM, "lines") - || options.isSet(Option.G_CUSTOM, "vars"); + boolean lineDebugInfo = + options.isUnset(Option.G_CUSTOM) || + options.isSet(Option.G_CUSTOM, "lines"); + boolean varDebugInfo = + options.isUnset(Option.G_CUSTOM) + ? options.isSet(Option.G) + : options.isSet(Option.G_CUSTOM, "vars"); + debugLinesOrVars = lineDebugInfo || varDebugInfo; verboseDeduplication = options.isSet("debug.dumpLambdaToMethodDeduplication"); deduplicateLambdas = options.getBoolean("deduplicateLambdas", true); nestmateLambdas = Target.instance(context).runtimeUseNestAccess(); diff --git a/test/langtools/tools/javac/diags/examples/LambdaDeduplicate.java b/test/langtools/tools/javac/diags/examples/LambdaDeduplicate.java index 8dda7bb2dd9..cf39f9ffb75 100644 --- a/test/langtools/tools/javac/diags/examples/LambdaDeduplicate.java +++ b/test/langtools/tools/javac/diags/examples/LambdaDeduplicate.java @@ -23,7 +23,7 @@ // key: compiler.note.verbose.l2m.deduplicate -// options: --debug=dumpLambdaToMethodDeduplication +// options: -g:none --debug=dumpLambdaToMethodDeduplication import java.util.function.Function; diff --git a/test/langtools/tools/javac/lambda/deduplication/DeduplicationDebugInfo.java b/test/langtools/tools/javac/lambda/deduplication/DeduplicationDebugInfo.java new file mode 100644 index 00000000000..2302b8f431d --- /dev/null +++ b/test/langtools/tools/javac/lambda/deduplication/DeduplicationDebugInfo.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2021, Google LLC. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test 8275233 + * @summary Incorrect line number reported in exception stack trace thrown from a lambda expression + * @compile/ref=DeduplicationDebugInfo.out -XDrawDiagnostics -XDdebug.dumpLambdaToMethodDeduplication -g:none DeduplicationDebugInfo.java + * @compile/ref=DeduplicationDebugInfo_none.out -XDrawDiagnostics -XDdebug.dumpLambdaToMethodDeduplication DeduplicationDebugInfo.java + * @compile/ref=DeduplicationDebugInfo_none.out -XDrawDiagnostics -XDdebug.dumpLambdaToMethodDeduplication -g:lines DeduplicationDebugInfo.java + * @compile/ref=DeduplicationDebugInfo_none.out -XDrawDiagnostics -XDdebug.dumpLambdaToMethodDeduplication -g:vars DeduplicationDebugInfo.java + * @compile/ref=DeduplicationDebugInfo_none.out -XDrawDiagnostics -XDdebug.dumpLambdaToMethodDeduplication -g:lines,vars DeduplicationDebugInfo.java + */ + +import java.util.function.Function; + +class DeduplicationDebugInfoTest { + void f() { + Function f = x -> x.hashCode(); + Function g = x -> x.hashCode(); + } +} diff --git a/test/langtools/tools/javac/lambda/deduplication/DeduplicationDebugInfo.out b/test/langtools/tools/javac/lambda/deduplication/DeduplicationDebugInfo.out new file mode 100644 index 00000000000..f428fe28846 --- /dev/null +++ b/test/langtools/tools/javac/lambda/deduplication/DeduplicationDebugInfo.out @@ -0,0 +1 @@ +DeduplicationDebugInfo.java:39:39: compiler.note.verbose.l2m.deduplicate: lambda$f$0(java.lang.Object) diff --git a/test/langtools/tools/javac/lambda/deduplication/DeduplicationDebugInfo_none.out b/test/langtools/tools/javac/lambda/deduplication/DeduplicationDebugInfo_none.out new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/langtools/tools/javac/lambda/deduplication/DeduplicationTest.java b/test/langtools/tools/javac/lambda/deduplication/DeduplicationTest.java index 14d0b88f09e..44c200e6226 100644 --- a/test/langtools/tools/javac/lambda/deduplication/DeduplicationTest.java +++ b/test/langtools/tools/javac/lambda/deduplication/DeduplicationTest.java @@ -93,6 +93,7 @@ public class DeduplicationTest { Arrays.asList( "-d", ".", + "-g:none", "-XDdebug.dumpLambdaToMethodDeduplication", "-XDdebug.dumpLambdaToMethodStats"), null, -- GitLab From 061017a9f4280657987524092b60611bfae8b95f Mon Sep 17 00:00:00 2001 From: Pavel Rappo Date: Tue, 7 Dec 2021 18:56:58 +0000 Subject: [PATCH 036/671] 8273175: Add @since tags to the DocTree.Kind enum constants Reviewed-by: darcy --- .../classes/com/sun/source/doctree/DocTree.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/jdk.compiler/share/classes/com/sun/source/doctree/DocTree.java b/src/jdk.compiler/share/classes/com/sun/source/doctree/DocTree.java index b0375d200c3..4dea3d09bf4 100644 --- a/src/jdk.compiler/share/classes/com/sun/source/doctree/DocTree.java +++ b/src/jdk.compiler/share/classes/com/sun/source/doctree/DocTree.java @@ -80,6 +80,8 @@ public interface DocTree { /** * Used for instances of {@link DocTypeTree} * representing an HTML DocType declaration. + * + * @since 10 */ DOC_TYPE, @@ -122,6 +124,8 @@ public interface DocTree { /** * Used for instances of {@link IndexTree} * representing an {@code @index} tag. + * + * @since 9 */ INDEX("index"), @@ -158,6 +162,8 @@ public interface DocTree { /** * Used for instances of {@link ProvidesTree} * representing an {@code @provides} tag. + * + * @since 9 */ PROVIDES("provides"), @@ -207,6 +213,8 @@ public interface DocTree { /** * Used for instances of {@link SnippetTree} * representing an {@code @snippet} tag. + * + * @since 18 */ SNIPPET("snippet"), @@ -219,12 +227,16 @@ public interface DocTree { /** * Used for instances of {@link SystemPropertyTree} * representing an {@code @systemProperty} tag. + * + * @since 12 */ SYSTEM_PROPERTY("systemProperty"), /** * Used for instances of {@link SummaryTree} * representing an {@code @summary} tag. + * + * @since 10 */ SUMMARY("summary"), @@ -255,6 +267,8 @@ public interface DocTree { /** * Used for instances of {@link UsesTree} * representing an {@code @uses} tag. + * + * @since 9 */ USES("uses"), -- GitLab From a8a1fbce5b8efe014b2dac16b83e60de4cf65a3e Mon Sep 17 00:00:00 2001 From: Pavel Rappo Date: Tue, 7 Dec 2021 18:58:08 +0000 Subject: [PATCH 037/671] 8278068: Fix next-line modifier (snippet markup) 8277027: Treat unrecognized markup as snippet text, but warn about it Reviewed-by: jjg --- .../toolkit/resources/doclets.properties | 2 + .../toolkit/taglets/SnippetTaglet.java | 20 +++- .../toolkit/taglets/snippet/MarkupParser.java | 47 ++++---- .../toolkit/taglets/snippet/Parser.java | 10 +- .../doclet/testSnippetTag/SnippetTester.java | 44 +++++++ .../testSnippetTag/TestSnippetMarkup.java | 109 ++++++++++++++++++ .../doclet/testSnippetTag/TestSnippetTag.java | 5 +- 7 files changed, 201 insertions(+), 36 deletions(-) diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets.properties b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets.properties index 8825d98f96d..78fc21db8a2 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets.properties +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets.properties @@ -373,6 +373,8 @@ doclet.snippet.contents.mismatch=\ doclet.snippet.markup=\ snippet markup: {0} +doclet.snippet.markup.spurious=\ + spurious markup doclet.snippet.markup.attribute.absent=\ missing attribute "{0}" doclet.snippet.markup.attribute.simultaneous.use=\ diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/SnippetTaglet.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/SnippetTaglet.java index 925359bf4ae..0f40ab1e297 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/SnippetTaglet.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/SnippetTaglet.java @@ -269,8 +269,14 @@ public class SnippetTaglet extends BaseTaglet { StyledText externalSnippet = null; try { + Diags d = (text, pos) -> { + var path = writer.configuration().utils.getCommentHelper(holder) + .getDocTreePath(snippetTag.getBody()); + writer.configuration().getReporter().print(Diagnostic.Kind.WARNING, + path, pos, pos, pos, text); + }; if (inlineContent != null) { - inlineSnippet = parse(writer.configuration().getDocResources(), language, inlineContent); + inlineSnippet = parse(writer.configuration().getDocResources(), d, language, inlineContent); } } catch (ParseException e) { var path = writer.configuration().utils.getCommentHelper(holder) @@ -284,8 +290,10 @@ public class SnippetTaglet extends BaseTaglet { } try { + var finalFileObject = fileObject; + Diags d = (text, pos) -> writer.configuration().getMessages().warning(finalFileObject, pos, pos, pos, text); if (externalContent != null) { - externalSnippet = parse(writer.configuration().getDocResources(), language, externalContent); + externalSnippet = parse(writer.configuration().getDocResources(), d, language, externalContent); } } catch (ParseException e) { assert fileObject != null; @@ -363,12 +371,16 @@ public class SnippetTaglet extends BaseTaglet { """.formatted(inline, external); } - private StyledText parse(Resources resources, Optional language, String content) throws ParseException { - Parser.Result result = new Parser(resources).parse(language, content); + private StyledText parse(Resources resources, Diags diags, Optional language, String content) throws ParseException { + Parser.Result result = new Parser(resources).parse(diags, language, content); result.actions().forEach(Action::perform); return result.text(); } + public interface Diags { + void warn(String text, int pos); + } + private static String stringValueOf(AttributeTree at) throws BadSnippetException { if (at.getValueKind() == AttributeTree.ValueKind.EMPTY) { throw new BadSnippetException(at, "doclet.tag.attribute.value.missing", diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/snippet/MarkupParser.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/snippet/MarkupParser.java index 879ba7bf2e4..59d6b3f9fdb 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/snippet/MarkupParser.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/snippet/MarkupParser.java @@ -31,11 +31,8 @@ import java.util.List; import jdk.javadoc.internal.doclets.toolkit.Resources; // -// markup-comment = { markup-tag } ; -// markup-tag = "@" , tag-name , {attribute} [":"] ; -// -// If optional trailing ":" is present, the tag refers to the next line -// rather than to this line. +// markup-comment = { markup-tag } [":"] ; +// markup-tag = "@" , tag-name , {attribute} ; // /** @@ -76,15 +73,28 @@ public final class MarkupParser { } protected List parse() throws ParseException { + List tags = readTags(); + if (ch == ':') { + tags.forEach(t -> t.appliesToNextLine = true); + nextChar(); + } + skipWhitespace(); + if (ch != EOI) { + return List.of(); + } + return tags; + } + + protected List readTags() throws ParseException { List tags = new ArrayList<>(); - // TODO: what to do with leading and trailing unrecognized markup? + skipWhitespace(); while (bp < buflen) { - switch (ch) { - case '@' -> tags.add(readTag()); - default -> nextChar(); + if (ch == '@') { + tags.add(readTag()); + } else { + break; } } - return tags; } @@ -94,26 +104,13 @@ public final class MarkupParser { String name = readIdentifier(); skipWhitespace(); - boolean appliesToNextLine = false; - List attributes = List.of(); - - if (ch == ':') { - appliesToNextLine = true; - nextChar(); - } else { - attributes = attrs(); - skipWhitespace(); - if (ch == ':') { - appliesToNextLine = true; - nextChar(); - } - } + List attributes = attrs(); + skipWhitespace(); Parser.Tag i = new Parser.Tag(); i.nameLineOffset = nameBp; i.name = name; i.attributes = attributes; - i.appliesToNextLine = appliesToNextLine; return i; } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/snippet/Parser.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/snippet/Parser.java index ccc6ce87799..3ed4ac03166 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/snippet/Parser.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/snippet/Parser.java @@ -94,19 +94,19 @@ public final class Parser { this.markupParser = new MarkupParser(resources); } - public Result parse(Optional language, String source) throws ParseException { + public Result parse(SnippetTaglet.Diags diags, Optional language, String source) throws ParseException { SnippetTaglet.Language lang = language.orElse(SnippetTaglet.Language.JAVA); var p = switch (lang) { case JAVA -> JAVA_COMMENT; case PROPERTIES -> PROPERTIES_COMMENT; }; - return parse(p, source); + return parse(diags, p, source); } /* * Newline characters in the returned text are of the \n form. */ - private Result parse(Pattern commentPattern, String source) throws ParseException { + private Result parse(SnippetTaglet.Diags diags, Pattern commentPattern, String source) throws ParseException { Objects.requireNonNull(commentPattern); Objects.requireNonNull(source); @@ -150,7 +150,7 @@ public final class Parser { parsedTags = markupParser.parse(maybeMarkup); } catch (ParseException e) { // translate error position from markup to file line - throw new ParseException(e::getMessage, markedUpLine.start("markup") + e.getPosition()); + throw new ParseException(e::getMessage, next.offset() + markedUpLine.start("markup") + e.getPosition()); } for (Tag t : parsedTags) { t.lineSourceOffset = next.offset(); @@ -166,7 +166,7 @@ public final class Parser { } } if (parsedTags.isEmpty()) { // (2) - // TODO: log this with NOTICE; + diags.warn(resources.getText("doclet.snippet.markup.spurious"), next.offset() + markedUpLine.start("markup")); line = rawLine + (addLineTerminator ? "\n" : ""); } else { // (3) hasMarkup = true; diff --git a/test/langtools/jdk/javadoc/doclet/testSnippetTag/SnippetTester.java b/test/langtools/jdk/javadoc/doclet/testSnippetTag/SnippetTester.java index ebe13149bb2..23d653be00f 100644 --- a/test/langtools/jdk/javadoc/doclet/testSnippetTag/SnippetTester.java +++ b/test/langtools/jdk/javadoc/doclet/testSnippetTag/SnippetTester.java @@ -26,9 +26,11 @@ import java.io.UncheckedIOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardOpenOption; +import java.nio.file.attribute.BasicFileAttributes; import java.util.Arrays; import java.util.List; import java.util.Optional; +import java.util.function.BiPredicate; import java.util.function.ObjIntConsumer; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -122,4 +124,46 @@ public class SnippetTester extends JavadocTester {
%s
""".formatted(svgString, idString, langString, content); } + + // There's JavadocTester.diff(), but its semantics is different; hence we + // use this method. + protected void match(Path path1, Path path2, BiPredicate filter) throws IOException { + checking("diff " + path1 + ", " + path2); + try (var paths1 = Files.find(path1, Integer.MAX_VALUE, filter).sorted(); + var paths2 = Files.find(path2, Integer.MAX_VALUE, filter).sorted()) { + var it1 = paths1.iterator(); + var it2 = paths2.iterator(); + while (true) { + if (it1.hasNext() != it2.hasNext()) { + failed(it1.hasNext() ? it1.next() : it2.next(), "missing"); + return; + } + if (!it1.hasNext()) { + passed("match"); + return; + } + Path next1 = it1.next(); + Path next2 = it2.next(); + if (!path1.relativize(next1).equals(path2.relativize(next2))) { + // compare directory tree to see the difference + failed("mismatching names %s %s".formatted(next1, next2)); + return; + } + if (Files.isDirectory(next1) != Files.isDirectory(next2)) { + // it'd be surprising to ever see this + failed("mismatching types %s %s".formatted(next1, next2)); + return; + } + if (Files.isDirectory(next1)) { + continue; + } + if (Files.size(next1) != Files.size(next2) + || Files.mismatch(next1, next2) != -1L) { + failed("mismatching contents: diff %s %s".formatted(next1.toAbsolutePath(), + next2.toAbsolutePath())); + return; + } + } + } + } } diff --git a/test/langtools/jdk/javadoc/doclet/testSnippetTag/TestSnippetMarkup.java b/test/langtools/jdk/javadoc/doclet/testSnippetTag/TestSnippetMarkup.java index 66d08933bc2..8b5e6b4438d 100644 --- a/test/langtools/jdk/javadoc/doclet/testSnippetTag/TestSnippetMarkup.java +++ b/test/langtools/jdk/javadoc/doclet/testSnippetTag/TestSnippetMarkup.java @@ -603,6 +603,115 @@ First line // @highlight : testPositive(base, testCases); } + @Test + public void testPositiveInlineTagMarkup_FalseMarkup(Path base) throws Exception { + var testCases = List.of( + new TestCase( + """ + First line + // @formatter:off + Second Line + Third line + // @formatter:on + Fourth line + """, + """ + First line + // @formatter:off + Second Line + Third line + // @formatter:on + Fourth line + """), + new TestCase("showThis", + """ + First line + // @formatter:off + // @start region=showThis + Second Line + Third line + // @end region + // @formatter:on + Fourth line + """, + """ + Second Line + Third line + """) + ); + testPositive(base, testCases); + } + + @Test + public void testPositiveInlineTagMarkup_NextLineTwoTags(Path base) throws Exception { + var firstTag = new String[]{ + "@highlight string=firstWord", + "@replace string=secondWord replacement=replacedSecondWord", + "@link substring=firstWord target=java.lang.Object"}; + var secondTag = new String[]{ + "@highlight string=secondWord", + "@replace string=firstWord replacement=replacedFirstWord", + "@link substring=secondWord target=java.lang.Thread"}; + List testCases = new ArrayList<>(); + for (var f : firstTag) { + for (var s : secondTag) + for (var separator : List.of("", " ")) { + var t = new TestCase( + """ + first-line // %s %s%s: + firstWord secondWord thirdWord + """.formatted(f, s, separator), + """ + first-line + firstWord secondWord thirdWord // %s %s + """.formatted(f, s)); + testCases.add(t); + } + } + testEquivalence(base, testCases); + } + + record Snippet(String region, String snippet) { } + + private void testEquivalence(Path base, List testCases) throws IOException { + // group all the testcases in just two runs + Path out1 = base.resolve("out1"); + Path out2 = base.resolve("out2"); + run(base.resolve("src1"), out1, testCases.stream().map(t -> new Snippet(t.region(), t.input())).toList()); + run(base.resolve("src2"), out2, testCases.stream().map(t -> new Snippet(t.region(), t.expectedOutput())).toList()); + match(out1, out2, (p, a) -> /* p.toString().endsWith(".html") */ true); + } + + private void run(Path source, Path target, List snippets) throws IOException { + StringBuilder methods = new StringBuilder(); + forEachNumbered(snippets, (i, n) -> { + String r = i.region.isBlank() ? "" : "region=" + i.region; + var methodDef = """ + + /** + {@snippet %s: + %s}*/ + public void case%s() {} + """.formatted(r, i.snippet(), n); + methods.append(methodDef); + }); + var classDef = """ + public class A { + %s + } + """.formatted(methods.toString()); + Path src = Files.createDirectories(source); + tb.writeJavaFiles(src, classDef); + javadoc("-d", target.toString(), + "--limit-modules", "java.base", + "-quiet", "-nohelp", "-noindex", "-nonavbar", "-nosince", + "-notimestamp", "-notree", "-Xdoclint:none", + "-sourcepath", src.toString(), + src.resolve("A.java").toString()); + checkExit(Exit.OK); + checkNoCrashes(); + } + private static String link(boolean linkPlain, String targetReference, String content) diff --git a/test/langtools/jdk/javadoc/doclet/testSnippetTag/TestSnippetTag.java b/test/langtools/jdk/javadoc/doclet/testSnippetTag/TestSnippetTag.java index 07efd52829b..fac9dfef6e1 100644 --- a/test/langtools/jdk/javadoc/doclet/testSnippetTag/TestSnippetTag.java +++ b/test/langtools/jdk/javadoc/doclet/testSnippetTag/TestSnippetTag.java @@ -2418,11 +2418,12 @@ error: snippet markup: invalid attribute value /* ---------------------- */ new TestCase(""" {@snippet : - hello // @highlight substring=" + hello + there // @highlight substring=" }""", """ error: snippet markup: unterminated attribute value - hello // @highlight substring=" + there // @highlight substring=" ^ """), new TestCase(""" -- GitLab From 716c2e1e85c244b31cf73e5ac1a2d765e3514c4d Mon Sep 17 00:00:00 2001 From: "Daniel D. Daugherty" Date: Tue, 7 Dec 2021 19:28:04 +0000 Subject: [PATCH 038/671] 8278368: ProblemList tools/jpackage/share/MultiNameTwoPhaseTest.java on macosx-x64 Reviewed-by: mikael --- test/jdk/ProblemList.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 24519795f9a..5a03523f327 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -833,6 +833,8 @@ jdk/jfr/api/consumer/streaming/TestLatestEvent.java 8268297 windows- # jdk_jpackage +tools/jpackage/share/MultiNameTwoPhaseTest.java 8278233 macosx-x64 + ############################################################################ # Client manual tests -- GitLab From 3d61372ba589fbd76fee62ea607997f0fb0bc433 Mon Sep 17 00:00:00 2001 From: Mikhailo Seledtsov Date: Tue, 7 Dec 2021 21:58:19 +0000 Subject: [PATCH 039/671] 8278363: Create extented container test groups Reviewed-by: lmesnik --- test/hotspot/jtreg/TEST.groups | 7 +++++++ test/jdk/TEST.groups | 5 +++++ 2 files changed, 12 insertions(+) diff --git a/test/hotspot/jtreg/TEST.groups b/test/hotspot/jtreg/TEST.groups index 9ca2a042577..c66e80a10c1 100644 --- a/test/hotspot/jtreg/TEST.groups +++ b/test/hotspot/jtreg/TEST.groups @@ -71,6 +71,13 @@ hotspot_native_sanity = \ hotspot_containers = \ containers +# Test sets for running inside container environment +hotspot_containers_extended = \ + runtime \ + serviceability \ + vmTestbase/nsk/jvmti \ + vmTestbase/nsk/monitoring + hotspot_vector_1 = \ compiler/c2/cr6340864 \ compiler/codegen \ diff --git a/test/jdk/TEST.groups b/test/jdk/TEST.groups index 9cdec38ea9a..3f8f683af09 100644 --- a/test/jdk/TEST.groups +++ b/test/jdk/TEST.groups @@ -583,3 +583,8 @@ jdk_core_manual_requires_human_input = \ java/util/TimeZone/DefaultTimeZoneTest.java +# Test sets for running inside container environment +jdk_containers_extended = \ + :jdk_io \ + :jdk_nio \ + :jdk_svc -- GitLab From 3c2951f738c5041761b551674822a32b418094c2 Mon Sep 17 00:00:00 2001 From: Vicente Romero Date: Tue, 7 Dec 2021 23:31:09 +0000 Subject: [PATCH 040/671] 8275771: JDK source code contains redundant boolean operations in jdk.compiler and langtools Reviewed-by: jlahoda --- .../tools/compileproperties/CompileProperties.java | 3 ++- .../classes/com/sun/tools/javac/comp/Resolve.java | 10 +++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/make/langtools/tools/compileproperties/CompileProperties.java b/make/langtools/tools/compileproperties/CompileProperties.java index 49cfc8a4a4b..7d69f9b47b2 100644 --- a/make/langtools/tools/compileproperties/CompileProperties.java +++ b/make/langtools/tools/compileproperties/CompileProperties.java @@ -183,7 +183,8 @@ public class CompileProperties { log.error("cannot close " + filename, e); } } - if ( ok = true && contents != null ) { + ok = true; + if ( contents != null ) { String tokens[] = (new String(contents)).split("\\s+"); if ( tokens.length > 0 ) { ok = parseOptions(tokens); diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java index 1ba0ace43b4..aa8ce943d04 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java @@ -1301,7 +1301,7 @@ public class Resolve { @Override void skip(JCTree tree) { - result &= false; + result = false; } @Override @@ -1313,9 +1313,9 @@ public class Resolve { @Override public void visitReference(JCMemberReference tree) { if (sRet.hasTag(VOID)) { - result &= true; + // do nothing } else if (tRet.hasTag(VOID)) { - result &= false; + result = false; } else if (tRet.isPrimitive() != sRet.isPrimitive()) { boolean retValIsPrimitive = tree.refPolyKind == PolyKind.STANDALONE && @@ -1335,9 +1335,9 @@ public class Resolve { @Override public void visitLambda(JCLambda tree) { if (sRet.hasTag(VOID)) { - result &= true; + // do nothing } else if (tRet.hasTag(VOID)) { - result &= false; + result = false; } else { List lambdaResults = lambdaResults(tree); if (!lambdaResults.isEmpty() && unrelatedFunctionalInterfaces(tRet, sRet)) { -- GitLab From ec7cb6d5d305003429b51384ed72973767c70124 Mon Sep 17 00:00:00 2001 From: Brent Christian Date: Wed, 8 Dec 2021 00:23:15 +0000 Subject: [PATCH 041/671] 8276447: Deprecate finalization-related methods for removal Reviewed-by: rriggs, alanb, lancea, darcy, mchung, serb, smarks, prr --- .../share/classes/java/lang/Enum.java | 7 +++- .../share/classes/java/lang/Object.java | 40 +++++++++++-------- .../share/classes/java/lang/Runtime.java | 9 +++++ .../share/classes/java/lang/System.java | 12 +++++- .../java/util/concurrent/Executors.java | 2 +- .../util/concurrent/ThreadPoolExecutor.java | 7 +++- .../classes/sun/net/www/MeteredStream.java | 2 +- .../sun/security/ssl/BaseSSLSocketImpl.java | 2 +- .../classes/apple/laf/JRSUIControl.java | 2 +- .../classes/sun/awt/CGraphicsEnvironment.java | 2 +- .../macosx/classes/sun/font/CFont.java | 2 +- .../macosx/classes/sun/font/CStrike.java | 2 +- .../sun/lwawt/macosx/CFRetainedResource.java | 2 +- .../classes/sun/lwawt/macosx/CPrinterJob.java | 2 +- .../plugins/common/SubImageInputStream.java | 2 +- .../imageio/plugins/png/PNGImageWriter.java | 4 +- .../plugins/tiff/TIFFBaseJPEGCompressor.java | 2 +- .../plugins/tiff/TIFFJPEGDecompressor.java | 2 +- .../plugins/tiff/TIFFOldJPEGDecompressor.java | 2 +- .../sun/imageio/stream/StreamFinalizer.java | 2 +- .../sun/media/sound/AbstractMidiDevice.java | 2 +- .../sun/media/sound/JavaSoundAudioClip.java | 1 + .../share/classes/java/awt/Graphics.java | 15 +++---- .../share/classes/java/awt/PrintJob.java | 15 +++---- .../javax/imageio/spi/ServiceRegistry.java | 16 +++----- .../stream/FileCacheImageInputStream.java | 14 +++---- .../imageio/stream/FileImageInputStream.java | 14 +++---- .../imageio/stream/FileImageOutputStream.java | 14 +++---- .../imageio/stream/ImageInputStreamImpl.java | 14 +++---- .../stream/MemoryCacheImageInputStream.java | 14 +++---- .../javax/swing/text/StringContent.java | 2 +- .../classes/sun/java2d/SunGraphics2D.java | 2 +- .../share/classes/sun/print/PeekGraphics.java | 2 +- .../share/classes/sun/print/PrintJob2D.java | 2 +- .../classes/sun/print/ProxyGraphics.java | 2 +- .../classes/sun/print/ProxyGraphics2D.java | 2 +- .../classes/sun/awt/X11InputMethodBase.java | 2 +- .../classes/sun/awt/windows/WInputMethod.java | 2 +- .../java/lang/management/MemoryMXBean.java | 8 +++- .../classes/sun/management/MemoryImpl.java | 1 + .../ldap/AbstractLdapNamingEnumeration.java | 2 +- .../classes/com/sun/jndi/ldap/LdapClient.java | 2 +- .../classes/com/sun/jndi/ldap/LdapCtx.java | 2 +- .../ldap/sasl/DefaultCallbackHandler.java | 2 +- .../classes/sun/rmi/log/LogInputStream.java | 2 +- .../security/jgss/wrapper/GSSCredElement.java | 2 +- .../security/jgss/wrapper/GSSNameElement.java | 2 +- .../jgss/wrapper/NativeGSSContext.java | 2 +- .../com/sun/security/sasl/CramMD5Base.java | 2 +- .../com/sun/security/sasl/PlainClient.java | 2 +- .../sun/security/smartcardio/CardImpl.java | 2 +- .../sun/security/pkcs11/P11KeyStore.java | 2 +- .../sun/security/pkcs11/wrapper/PKCS11.java | 2 +- .../classes/sun/security/mscapi/CKey.java | 2 +- .../sun/tools/jconsole/SummaryTab.java | 1 + .../jdk/jfr/internal/ChunkInputStream.java | 2 +- .../jdk/jfr/internal/ChunksChannel.java | 2 +- .../jdk/jfr/internal/RepositoryChunk.java | 2 +- .../classes/com/sun/jndi/dns/DnsClient.java | 2 +- .../jndi/rmi/registry/RegistryContext.java | 4 +- .../security/sasl/gsskerb/GssKrb5Base.java | 2 +- .../classes/jdk/nio/zipfs/ZipFileSystem.java | 2 +- 62 files changed, 156 insertions(+), 140 deletions(-) diff --git a/src/java.base/share/classes/java/lang/Enum.java b/src/java.base/share/classes/java/lang/Enum.java index 636ad7c757e..886461c3a91 100644 --- a/src/java.base/share/classes/java/lang/Enum.java +++ b/src/java.base/share/classes/java/lang/Enum.java @@ -275,8 +275,13 @@ public abstract class Enum> /** * enum classes cannot have finalize methods. + * + * @deprecated Finalization has been deprecated for removal. See + * {@link java.lang.Object#finalize} for background information and details + * about migration options. */ - @SuppressWarnings("deprecation") + @Deprecated(since="18", forRemoval=true) + @SuppressWarnings("removal") protected final void finalize() { } /** diff --git a/src/java.base/share/classes/java/lang/Object.java b/src/java.base/share/classes/java/lang/Object.java index b8085b230af..52028ba99a7 100644 --- a/src/java.base/share/classes/java/lang/Object.java +++ b/src/java.base/share/classes/java/lang/Object.java @@ -478,6 +478,12 @@ public class Object { * A subclass overrides the {@code finalize} method to dispose of * system resources or to perform other cleanup. *

+ * When running in a Java virtual machine in which finalization has been + * disabled or removed, the garbage collector will never call + * {@code finalize()}. In a Java virtual machine in which finalization is + * enabled, the garbage collector might call {@code finalize} only after an + * indefinite delay. + *

* The general contract of {@code finalize} is that it is invoked * if and when the Java virtual * machine has determined that there is no longer any @@ -543,27 +549,29 @@ public class Object { * } * } * - * @deprecated The finalization mechanism is inherently problematic. - * Finalization can lead to performance issues, deadlocks, and hangs. - * Errors in finalizers can lead to resource leaks; there is no way to cancel - * finalization if it is no longer necessary; and no ordering is specified - * among calls to {@code finalize} methods of different objects. - * Furthermore, there are no guarantees regarding the timing of finalization. - * The {@code finalize} method might be called on a finalizable object - * only after an indefinite delay, if at all. - * - * Classes whose instances hold non-heap resources should provide a method - * to enable explicit release of those resources, and they should also - * implement {@link AutoCloseable} if appropriate. - * The {@link java.lang.ref.Cleaner} and {@link java.lang.ref.PhantomReference} - * provide more flexible and efficient ways to release resources when an object - * becomes unreachable. + * @deprecated Finalization is deprecated and subject to removal in a future + * release. The use of finalization can lead to problems with security, + * performance, and reliability. + * See JEP 421 for + * discussion and alternatives. + *

+ * Subclasses that override {@code finalize} to perform cleanup should use + * alternative cleanup mechanisms and remove the {@code finalize} method. + * Use {@link java.lang.ref.Cleaner} and + * {@link java.lang.ref.PhantomReference} as safer ways to release resources + * when an object becomes unreachable. Alternatively, add a {@code close} + * method to explicitly release resources, and implement + * {@code AutoCloseable} to enable use of the {@code try}-with-resources + * statement. + *

+ * This method will remain in place until finalizers have been removed from + * most existing code. * * @throws Throwable the {@code Exception} raised by this method * @see java.lang.ref.WeakReference * @see java.lang.ref.PhantomReference * @jls 12.6 Finalization of Class Instances */ - @Deprecated(since="9") + @Deprecated(since="9", forRemoval=true) protected void finalize() throws Throwable { } } diff --git a/src/java.base/share/classes/java/lang/Runtime.java b/src/java.base/share/classes/java/lang/Runtime.java index 2288aca4d11..c674880c636 100644 --- a/src/java.base/share/classes/java/lang/Runtime.java +++ b/src/java.base/share/classes/java/lang/Runtime.java @@ -707,8 +707,17 @@ public class Runtime { * The method {@link System#runFinalization()} is the conventional * and convenient means of invoking this method. * + * @deprecated Finalization has been deprecated for removal. See + * {@link java.lang.Object#finalize} for background information and details + * about migration options. + *

+ * When running in a JVM in which finalization has been disabled or removed, + * no objects will be pending finalization, so this method does nothing. + * * @see java.lang.Object#finalize() + * @jls 12.6 Finalization of Class Instances */ + @Deprecated(since="18", forRemoval=true) public void runFinalization() { SharedSecrets.getJavaLangRefAccess().runFinalization(); } diff --git a/src/java.base/share/classes/java/lang/System.java b/src/java.base/share/classes/java/lang/System.java index 12a82813433..47b436847cb 100644 --- a/src/java.base/share/classes/java/lang/System.java +++ b/src/java.base/share/classes/java/lang/System.java @@ -1922,8 +1922,18 @@ public final class System { * Runtime.getRuntime().runFinalization() * * + * @deprecated Finalization has been deprecated for removal. See + * {@link java.lang.Object#finalize} for background information and details + * about migration options. + *

+ * When running in a JVM in which finalization has been disabled or removed, + * no objects will be pending finalization, so this method does nothing. + * * @see java.lang.Runtime#runFinalization() + * @jls 12.6 Finalization of Class Instances */ + @Deprecated(since="18", forRemoval=true) + @SuppressWarnings("removal") public static void runFinalization() { Runtime.getRuntime().runFinalization(); } @@ -2321,7 +2331,7 @@ public final class System { public Thread newThreadWithAcc(Runnable target, @SuppressWarnings("removal") AccessControlContext acc) { return new Thread(target, acc); } - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") public void invokeFinalize(Object o) throws Throwable { o.finalize(); } diff --git a/src/java.base/share/classes/java/util/concurrent/Executors.java b/src/java.base/share/classes/java/util/concurrent/Executors.java index a9e7de32a00..3345153bd97 100644 --- a/src/java.base/share/classes/java/util/concurrent/Executors.java +++ b/src/java.base/share/classes/java/util/concurrent/Executors.java @@ -791,7 +791,7 @@ public class Executors { FinalizableDelegatedExecutorService(ExecutorService executor) { super(executor); } - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() { super.shutdown(); } diff --git a/src/java.base/share/classes/java/util/concurrent/ThreadPoolExecutor.java b/src/java.base/share/classes/java/util/concurrent/ThreadPoolExecutor.java index 49d2a29b262..f23e72a8f70 100644 --- a/src/java.base/share/classes/java/util/concurrent/ThreadPoolExecutor.java +++ b/src/java.base/share/classes/java/util/concurrent/ThreadPoolExecutor.java @@ -1477,8 +1477,13 @@ public class ThreadPoolExecutor extends AbstractExecutorService { * @implNote Previous versions of this class had a finalize method * that shut down this executor, but in this version, finalize * does nothing. + * + * @deprecated Finalization has been deprecated for removal. See + * {@link java.lang.Object#finalize} for background information and details + * about migration options. */ - @Deprecated(since="9") + @Deprecated(since="9", forRemoval=true) + @SuppressWarnings("removal") protected void finalize() {} /** diff --git a/src/java.base/share/classes/sun/net/www/MeteredStream.java b/src/java.base/share/classes/sun/net/www/MeteredStream.java index 049b16c03c6..fc0579a679e 100644 --- a/src/java.base/share/classes/sun/net/www/MeteredStream.java +++ b/src/java.base/share/classes/sun/net/www/MeteredStream.java @@ -242,7 +242,7 @@ public class MeteredStream extends FilterInputStream { return readLock.isHeldByCurrentThread(); } - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() throws Throwable { try { close(); diff --git a/src/java.base/share/classes/sun/security/ssl/BaseSSLSocketImpl.java b/src/java.base/share/classes/sun/security/ssl/BaseSSLSocketImpl.java index ba58741d759..8923dee25c9 100644 --- a/src/java.base/share/classes/sun/security/ssl/BaseSSLSocketImpl.java +++ b/src/java.base/share/classes/sun/security/ssl/BaseSSLSocketImpl.java @@ -270,7 +270,7 @@ abstract class BaseSSLSocketImpl extends SSLSocket { * the penalty of prematurly killing SSL sessions. */ @Override - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected final void finalize() throws Throwable { try { close(); diff --git a/src/java.desktop/macosx/classes/apple/laf/JRSUIControl.java b/src/java.desktop/macosx/classes/apple/laf/JRSUIControl.java index e3579449b75..6e6c86ccf7a 100644 --- a/src/java.desktop/macosx/classes/apple/laf/JRSUIControl.java +++ b/src/java.desktop/macosx/classes/apple/laf/JRSUIControl.java @@ -114,7 +114,7 @@ public final class JRSUIControl { changes.putAll(other.changes); } - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected synchronized void finalize() throws Throwable { if (cfDictionaryPtr == 0) return; disposeCFDictionary(cfDictionaryPtr); diff --git a/src/java.desktop/macosx/classes/sun/awt/CGraphicsEnvironment.java b/src/java.desktop/macosx/classes/sun/awt/CGraphicsEnvironment.java index e96ce7e18d7..fe4431e3091 100644 --- a/src/java.desktop/macosx/classes/sun/awt/CGraphicsEnvironment.java +++ b/src/java.desktop/macosx/classes/sun/awt/CGraphicsEnvironment.java @@ -144,7 +144,7 @@ public final class CGraphicsEnvironment extends SunGraphicsEnvironment { } @Override - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() throws Throwable { try { super.finalize(); diff --git a/src/java.desktop/macosx/classes/sun/font/CFont.java b/src/java.desktop/macosx/classes/sun/font/CFont.java index 885fc7fc471..85b38beb86c 100644 --- a/src/java.desktop/macosx/classes/sun/font/CFont.java +++ b/src/java.desktop/macosx/classes/sun/font/CFont.java @@ -247,7 +247,7 @@ public final class CFont extends PhysicalFont implements FontSubstitution { return compFont; } - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected synchronized void finalize() { if (nativeFontPtr != 0) { disposeNativeFont(nativeFontPtr); diff --git a/src/java.desktop/macosx/classes/sun/font/CStrike.java b/src/java.desktop/macosx/classes/sun/font/CStrike.java index 088fb01591e..eb049c3d449 100644 --- a/src/java.desktop/macosx/classes/sun/font/CStrike.java +++ b/src/java.desktop/macosx/classes/sun/font/CStrike.java @@ -125,7 +125,7 @@ public final class CStrike extends PhysicalStrike { return nativeStrikePtr; } - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected synchronized void finalize() throws Throwable { if (nativeStrikePtr != 0) { disposeNativeStrikePtr(nativeStrikePtr); diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CFRetainedResource.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CFRetainedResource.java index de0553501e6..43d6c218b29 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CFRetainedResource.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CFRetainedResource.java @@ -163,7 +163,7 @@ public class CFRetainedResource { } @Override - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected final void finalize() throws Throwable { dispose(); } diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterJob.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterJob.java index de96e59d92e..8dd02462284 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterJob.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterJob.java @@ -598,7 +598,7 @@ public final class CPrinterJob extends RasterPrinterJob { // The following methods are CPrinterJob specific. @Override - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() { synchronized (fNSPrintInfoLock) { if (fNSPrintInfo != -1) { diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/common/SubImageInputStream.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/common/SubImageInputStream.java index 8ddffc522f1..10211c6636c 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/common/SubImageInputStream.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/common/SubImageInputStream.java @@ -72,7 +72,7 @@ public final class SubImageInputStream extends ImageInputStreamImpl { streamPos = pos; } - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() throws Throwable { // Empty finalizer (for improved performance; no need to call // super.finalize() in this case) diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGImageWriter.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGImageWriter.java index 449661b8c91..ce6f771ecdc 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGImageWriter.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGImageWriter.java @@ -147,7 +147,7 @@ final class ChunkStream extends ImageOutputStreamImpl { } @Override - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() throws Throwable { // Empty finalizer (for improved performance; no need to call // super.finalize() in this case) @@ -284,7 +284,7 @@ final class IDATOutputStream extends ImageOutputStreamImpl { } @Override - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() throws Throwable { // Empty finalizer (for improved performance; no need to call // super.finalize() in this case) diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFBaseJPEGCompressor.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFBaseJPEGCompressor.java index 74695ae46ce..dba8d878169 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFBaseJPEGCompressor.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFBaseJPEGCompressor.java @@ -435,7 +435,7 @@ public abstract class TIFFBaseJPEGCompressor extends TIFFCompressor { return compDataLength; } - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() throws Throwable { super.finalize(); if(JPEGWriter != null) { diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFJPEGDecompressor.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFJPEGDecompressor.java index 384687f8344..0b21835901b 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFJPEGDecompressor.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFJPEGDecompressor.java @@ -139,7 +139,7 @@ public class TIFFJPEGDecompressor extends TIFFDecompressor { JPEGReader.read(0, JPEGParam); } - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() throws Throwable { super.finalize(); JPEGReader.dispose(); diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFOldJPEGDecompressor.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFOldJPEGDecompressor.java index 67dd60f8a79..3cd89b396cc 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFOldJPEGDecompressor.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFOldJPEGDecompressor.java @@ -610,7 +610,7 @@ public class TIFFOldJPEGDecompressor extends TIFFJPEGDecompressor { JPEGReader.read(0, JPEGParam); } - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() throws Throwable { super.finalize(); JPEGReader.dispose(); diff --git a/src/java.desktop/share/classes/com/sun/imageio/stream/StreamFinalizer.java b/src/java.desktop/share/classes/com/sun/imageio/stream/StreamFinalizer.java index be1e659ee6e..012d7e10645 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/stream/StreamFinalizer.java +++ b/src/java.desktop/share/classes/com/sun/imageio/stream/StreamFinalizer.java @@ -60,7 +60,7 @@ public class StreamFinalizer { this.stream = stream; } - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() throws Throwable { try { stream.close(); diff --git a/src/java.desktop/share/classes/com/sun/media/sound/AbstractMidiDevice.java b/src/java.desktop/share/classes/com/sun/media/sound/AbstractMidiDevice.java index 1b50f31eb9e..3ba4ce2ed36 100644 --- a/src/java.desktop/share/classes/com/sun/media/sound/AbstractMidiDevice.java +++ b/src/java.desktop/share/classes/com/sun/media/sound/AbstractMidiDevice.java @@ -425,7 +425,7 @@ abstract class AbstractMidiDevice implements MidiDevice, ReferenceCountingDevice * close this device if discarded by the garbage collector. */ @Override - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected final void finalize() { close(); } diff --git a/src/java.desktop/share/classes/com/sun/media/sound/JavaSoundAudioClip.java b/src/java.desktop/share/classes/com/sun/media/sound/JavaSoundAudioClip.java index bc2f87fe33f..c804a0e49c2 100644 --- a/src/java.desktop/share/classes/com/sun/media/sound/JavaSoundAudioClip.java +++ b/src/java.desktop/share/classes/com/sun/media/sound/JavaSoundAudioClip.java @@ -283,6 +283,7 @@ public final class JavaSoundAudioClip implements AudioClip, MetaEventListener, L } @Override + @SuppressWarnings("removal") protected void finalize() { if (clip != null) { diff --git a/src/java.desktop/share/classes/java/awt/Graphics.java b/src/java.desktop/share/classes/java/awt/Graphics.java index 51cdd6a88da..5ed31aeadb0 100644 --- a/src/java.desktop/share/classes/java/awt/Graphics.java +++ b/src/java.desktop/share/classes/java/awt/Graphics.java @@ -1162,17 +1162,14 @@ public abstract class Graphics { /** * Disposes of this graphics context once it is no longer referenced. * - * @deprecated The {@code finalize} method has been deprecated. - * Subclasses that override {@code finalize} in order to perform cleanup - * should be modified to use alternative cleanup mechanisms and - * to remove the overriding {@code finalize} method. - * When overriding the {@code finalize} method, its implementation must explicitly - * ensure that {@code super.finalize()} is invoked as described in {@link Object#finalize}. - * See the specification for {@link Object#finalize()} for further - * information about migration options. + * @deprecated Finalization has been deprecated for removal. See + * {@link java.lang.Object#finalize} for background information and details + * about migration options. + * * @see #dispose */ - @Deprecated(since="9") + @Deprecated(since="9", forRemoval=true) + @SuppressWarnings("removal") public void finalize() { dispose(); } diff --git a/src/java.desktop/share/classes/java/awt/PrintJob.java b/src/java.desktop/share/classes/java/awt/PrintJob.java index a9e2bd8bea2..f4ea24efd97 100644 --- a/src/java.desktop/share/classes/java/awt/PrintJob.java +++ b/src/java.desktop/share/classes/java/awt/PrintJob.java @@ -85,17 +85,14 @@ public abstract class PrintJob { /** * Ends this print job once it is no longer referenced. * - * @deprecated The {@code finalize} method has been deprecated. - * Subclasses that override {@code finalize} in order to perform cleanup - * should be modified to use alternative cleanup mechanisms and - * to remove the overriding {@code finalize} method. - * When overriding the {@code finalize} method, its implementation must explicitly - * ensure that {@code super.finalize()} is invoked as described in {@link Object#finalize}. - * See the specification for {@link Object#finalize()} for further - * information about migration options. + * @deprecated Finalization has been deprecated for removal. See + * {@link java.lang.Object#finalize} for background information and details + * about migration options. + * * @see #end */ - @Deprecated(since="9") + @Deprecated(since="9", forRemoval=true) + @SuppressWarnings("removal") public void finalize() { end(); } diff --git a/src/java.desktop/share/classes/javax/imageio/spi/ServiceRegistry.java b/src/java.desktop/share/classes/javax/imageio/spi/ServiceRegistry.java index 741ca55c501..4a43ca8133a 100644 --- a/src/java.desktop/share/classes/javax/imageio/spi/ServiceRegistry.java +++ b/src/java.desktop/share/classes/javax/imageio/spi/ServiceRegistry.java @@ -680,16 +680,12 @@ public class ServiceRegistry { * @exception Throwable if an error occurs during superclass * finalization. * - * @deprecated The {@code finalize} method has been deprecated. - * Subclasses that override {@code finalize} in order to perform cleanup - * should be modified to use alternative cleanup mechanisms and - * to remove the overriding {@code finalize} method. - * When overriding the {@code finalize} method, its implementation must explicitly - * ensure that {@code super.finalize()} is invoked as described in {@link Object#finalize}. - * See the specification for {@link Object#finalize()} for further - * information about migration options. + * @deprecated Finalization has been deprecated for removal. See + * {@link java.lang.Object#finalize} for background information and details + * about migration options. */ - @Deprecated(since="9") + @Deprecated(since="9", forRemoval=true) + @SuppressWarnings("removal") public void finalize() throws Throwable { deregisterAll(); super.finalize(); @@ -842,7 +838,7 @@ class SubRegistry { accMap.clear(); } - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") public synchronized void finalize() { clear(); } diff --git a/src/java.desktop/share/classes/javax/imageio/stream/FileCacheImageInputStream.java b/src/java.desktop/share/classes/javax/imageio/stream/FileCacheImageInputStream.java index e5974900161..6bf14838b7f 100644 --- a/src/java.desktop/share/classes/javax/imageio/stream/FileCacheImageInputStream.java +++ b/src/java.desktop/share/classes/javax/imageio/stream/FileCacheImageInputStream.java @@ -261,16 +261,12 @@ public class FileCacheImageInputStream extends ImageInputStreamImpl { /** * {@inheritDoc} * - * @deprecated The {@code finalize} method has been deprecated. - * Subclasses that override {@code finalize} in order to perform cleanup - * should be modified to use alternative cleanup mechanisms and - * to remove the overriding {@code finalize} method. - * When overriding the {@code finalize} method, its implementation must explicitly - * ensure that {@code super.finalize()} is invoked as described in {@link Object#finalize}. - * See the specification for {@link Object#finalize()} for further - * information about migration options. + * @deprecated Finalization has been deprecated for removal. See + * {@link java.lang.Object#finalize} for background information and details + * about migration options. */ - @Deprecated(since="9") + @Deprecated(since="9", forRemoval=true) + @SuppressWarnings("removal") protected void finalize() throws Throwable { // Empty finalizer: for performance reasons we instead use the // Disposer mechanism for ensuring that the underlying diff --git a/src/java.desktop/share/classes/javax/imageio/stream/FileImageInputStream.java b/src/java.desktop/share/classes/javax/imageio/stream/FileImageInputStream.java index 7ecc28767a0..b1cce6fae4c 100644 --- a/src/java.desktop/share/classes/javax/imageio/stream/FileImageInputStream.java +++ b/src/java.desktop/share/classes/javax/imageio/stream/FileImageInputStream.java @@ -156,16 +156,12 @@ public class FileImageInputStream extends ImageInputStreamImpl { /** * {@inheritDoc} * - * @deprecated The {@code finalize} method has been deprecated. - * Subclasses that override {@code finalize} in order to perform cleanup - * should be modified to use alternative cleanup mechanisms and - * to remove the overriding {@code finalize} method. - * When overriding the {@code finalize} method, its implementation must explicitly - * ensure that {@code super.finalize()} is invoked as described in {@link Object#finalize}. - * See the specification for {@link Object#finalize()} for further - * information about migration options. + * @deprecated Finalization has been deprecated for removal. See + * {@link java.lang.Object#finalize} for background information and details + * about migration options. */ - @Deprecated(since="9") + @Deprecated(since="9", forRemoval=true) + @SuppressWarnings("removal") protected void finalize() throws Throwable { // Empty finalizer: for performance reasons we instead use the // Disposer mechanism for ensuring that the underlying diff --git a/src/java.desktop/share/classes/javax/imageio/stream/FileImageOutputStream.java b/src/java.desktop/share/classes/javax/imageio/stream/FileImageOutputStream.java index e75c40396d8..715b43f40fb 100644 --- a/src/java.desktop/share/classes/javax/imageio/stream/FileImageOutputStream.java +++ b/src/java.desktop/share/classes/javax/imageio/stream/FileImageOutputStream.java @@ -164,16 +164,12 @@ public class FileImageOutputStream extends ImageOutputStreamImpl { /** * {@inheritDoc} * - * @deprecated The {@code finalize} method has been deprecated. - * Subclasses that override {@code finalize} in order to perform cleanup - * should be modified to use alternative cleanup mechanisms and - * to remove the overriding {@code finalize} method. - * When overriding the {@code finalize} method, its implementation must explicitly - * ensure that {@code super.finalize()} is invoked as described in {@link Object#finalize}. - * See the specification for {@link Object#finalize()} for further - * information about migration options. + * @deprecated Finalization has been deprecated for removal. See + * {@link java.lang.Object#finalize} for background information and details + * about migration options. */ - @Deprecated(since="9") + @Deprecated(since="9", forRemoval=true) + @SuppressWarnings("removal") protected void finalize() throws Throwable { // Empty finalizer: for performance reasons we instead use the // Disposer mechanism for ensuring that the underlying diff --git a/src/java.desktop/share/classes/javax/imageio/stream/ImageInputStreamImpl.java b/src/java.desktop/share/classes/javax/imageio/stream/ImageInputStreamImpl.java index c7cdc47cdaf..053bbf74918 100644 --- a/src/java.desktop/share/classes/javax/imageio/stream/ImageInputStreamImpl.java +++ b/src/java.desktop/share/classes/javax/imageio/stream/ImageInputStreamImpl.java @@ -868,16 +868,12 @@ public abstract class ImageInputStreamImpl implements ImageInputStream { * @exception Throwable if an error occurs during superclass * finalization. * - * @deprecated The {@code finalize} method has been deprecated. - * Subclasses that override {@code finalize} in order to perform cleanup - * should be modified to use alternative cleanup mechanisms and - * to remove the overriding {@code finalize} method. - * When overriding the {@code finalize} method, its implementation must explicitly - * ensure that {@code super.finalize()} is invoked as described in {@link Object#finalize}. - * See the specification for {@link Object#finalize()} for further - * information about migration options. + * @deprecated Finalization has been deprecated for removal. See + * {@link java.lang.Object#finalize} for background information and details + * about migration options. */ - @Deprecated(since="9") + @Deprecated(since="9", forRemoval=true) + @SuppressWarnings("removal") protected void finalize() throws Throwable { if (!isClosed) { try { diff --git a/src/java.desktop/share/classes/javax/imageio/stream/MemoryCacheImageInputStream.java b/src/java.desktop/share/classes/javax/imageio/stream/MemoryCacheImageInputStream.java index 4fcb0f40b81..44b9d8cd5fb 100644 --- a/src/java.desktop/share/classes/javax/imageio/stream/MemoryCacheImageInputStream.java +++ b/src/java.desktop/share/classes/javax/imageio/stream/MemoryCacheImageInputStream.java @@ -179,16 +179,12 @@ public class MemoryCacheImageInputStream extends ImageInputStreamImpl { /** * {@inheritDoc} * - * @deprecated The {@code finalize} method has been deprecated. - * Subclasses that override {@code finalize} in order to perform cleanup - * should be modified to use alternative cleanup mechanisms and - * to remove the overriding {@code finalize} method. - * When overriding the {@code finalize} method, its implementation must explicitly - * ensure that {@code super.finalize()} is invoked as described in {@link Object#finalize}. - * See the specification for {@link Object#finalize()} for further - * information about migration options. + * @deprecated Finalization has been deprecated for removal. See + * {@link java.lang.Object#finalize} for background information and details + * about migration options. */ - @Deprecated(since="9") + @Deprecated(since="9", forRemoval=true) + @SuppressWarnings("removal") protected void finalize() throws Throwable { // Empty finalizer: for performance reasons we instead use the // Disposer mechanism for ensuring that the underlying diff --git a/src/java.desktop/share/classes/javax/swing/text/StringContent.java b/src/java.desktop/share/classes/javax/swing/text/StringContent.java index c66156a39f2..7f154df38ed 100644 --- a/src/java.desktop/share/classes/javax/swing/text/StringContent.java +++ b/src/java.desktop/share/classes/javax/swing/text/StringContent.java @@ -350,7 +350,7 @@ public final class StringContent implements AbstractDocument.Content, Serializab return rec.offset; } - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() throws Throwable { // schedule the record to be removed later // on another thread. diff --git a/src/java.desktop/share/classes/sun/java2d/SunGraphics2D.java b/src/java.desktop/share/classes/sun/java2d/SunGraphics2D.java index 15db79d69d2..b5b5225938b 100644 --- a/src/java.desktop/share/classes/sun/java2d/SunGraphics2D.java +++ b/src/java.desktop/share/classes/sun/java2d/SunGraphics2D.java @@ -3656,7 +3656,7 @@ public final class SunGraphics2D * enough to know that if our override is empty then it should not * mark us as finalizeable. */ - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") public void finalize() { // DO NOT REMOVE THIS METHOD } diff --git a/src/java.desktop/share/classes/sun/print/PeekGraphics.java b/src/java.desktop/share/classes/sun/print/PeekGraphics.java index c400ad59ca2..b5eabc84773 100644 --- a/src/java.desktop/share/classes/sun/print/PeekGraphics.java +++ b/src/java.desktop/share/classes/sun/print/PeekGraphics.java @@ -1336,7 +1336,7 @@ public class PeekGraphics extends Graphics2D /** * Empty finalizer as no clean up needed here. */ - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") public void finalize() { } diff --git a/src/java.desktop/share/classes/sun/print/PrintJob2D.java b/src/java.desktop/share/classes/sun/print/PrintJob2D.java index 323cb0cc84e..9083bd3e269 100644 --- a/src/java.desktop/share/classes/sun/print/PrintJob2D.java +++ b/src/java.desktop/share/classes/sun/print/PrintJob2D.java @@ -940,7 +940,7 @@ public class PrintJob2D extends PrintJob implements Printable, Runnable { * Ends this print job once it is no longer referenced. * @see #end */ - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") public void finalize() { end(); } diff --git a/src/java.desktop/share/classes/sun/print/ProxyGraphics.java b/src/java.desktop/share/classes/sun/print/ProxyGraphics.java index 124a7a487f6..c6c0615c343 100644 --- a/src/java.desktop/share/classes/sun/print/ProxyGraphics.java +++ b/src/java.desktop/share/classes/sun/print/ProxyGraphics.java @@ -1099,7 +1099,7 @@ public class ProxyGraphics extends Graphics { /** * Empty finalizer as no clean up needed here. */ - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") public void finalize() { } diff --git a/src/java.desktop/share/classes/sun/print/ProxyGraphics2D.java b/src/java.desktop/share/classes/sun/print/ProxyGraphics2D.java index fc1c0e76810..c05ba9a6188 100644 --- a/src/java.desktop/share/classes/sun/print/ProxyGraphics2D.java +++ b/src/java.desktop/share/classes/sun/print/ProxyGraphics2D.java @@ -1264,7 +1264,7 @@ public class ProxyGraphics2D extends Graphics2D implements PrinterGraphics { /** * Empty finalizer as no clean up needed here. */ - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") public void finalize() { } diff --git a/src/java.desktop/unix/classes/sun/awt/X11InputMethodBase.java b/src/java.desktop/unix/classes/sun/awt/X11InputMethodBase.java index 671df20d1db..eb71b7a5972 100644 --- a/src/java.desktop/unix/classes/sun/awt/X11InputMethodBase.java +++ b/src/java.desktop/unix/classes/sun/awt/X11InputMethodBase.java @@ -172,7 +172,7 @@ public abstract class X11InputMethodBase extends InputMethodAdapter { } } - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() throws Throwable { dispose(); super.finalize(); diff --git a/src/java.desktop/windows/classes/sun/awt/windows/WInputMethod.java b/src/java.desktop/windows/classes/sun/awt/windows/WInputMethod.java index 9ad52ba7111..681662032e1 100644 --- a/src/java.desktop/windows/classes/sun/awt/windows/WInputMethod.java +++ b/src/java.desktop/windows/classes/sun/awt/windows/WInputMethod.java @@ -133,7 +133,7 @@ final class WInputMethod extends InputMethodAdapter } @Override - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() throws Throwable { // Release the resources used by the native input context. diff --git a/src/java.management/share/classes/java/lang/management/MemoryMXBean.java b/src/java.management/share/classes/java/lang/management/MemoryMXBean.java index 716d2bcefca..f17e5e8077a 100644 --- a/src/java.management/share/classes/java/lang/management/MemoryMXBean.java +++ b/src/java.management/share/classes/java/lang/management/MemoryMXBean.java @@ -207,9 +207,15 @@ public interface MemoryMXBean extends PlatformManagedObject { * Returns the approximate number of objects for which * finalization is pending. * + * @deprecated Finalization has been deprecated for removal. See + * {@link java.lang.Object#finalize} for details. + * * @return the approximate number objects for which finalization - * is pending. + * is pending. If this MemoryMXBean contains information about a JVM in + * which finalization has been disabled or removed, this method always + * returns zero. */ + @Deprecated(since="18") public int getObjectPendingFinalizationCount(); /** diff --git a/src/java.management/share/classes/sun/management/MemoryImpl.java b/src/java.management/share/classes/sun/management/MemoryImpl.java index 7850b90e783..5bdbe7b6349 100644 --- a/src/java.management/share/classes/sun/management/MemoryImpl.java +++ b/src/java.management/share/classes/sun/management/MemoryImpl.java @@ -58,6 +58,7 @@ class MemoryImpl extends NotificationEmitterSupport this.jvm = vm; } + @SuppressWarnings("deprecation") public int getObjectPendingFinalizationCount() { return jdk.internal.misc.VM.getFinalRefCount(); } diff --git a/src/java.naming/share/classes/com/sun/jndi/ldap/AbstractLdapNamingEnumeration.java b/src/java.naming/share/classes/com/sun/jndi/ldap/AbstractLdapNamingEnumeration.java index 94c15c09d11..5c7644212f9 100644 --- a/src/java.naming/share/classes/com/sun/jndi/ldap/AbstractLdapNamingEnumeration.java +++ b/src/java.naming/share/classes/com/sun/jndi/ldap/AbstractLdapNamingEnumeration.java @@ -383,7 +383,7 @@ abstract class AbstractLdapNamingEnumeration listArg = ne.listArg; } - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected final void finalize() { cleanup(); } diff --git a/src/java.naming/share/classes/com/sun/jndi/ldap/LdapClient.java b/src/java.naming/share/classes/com/sun/jndi/ldap/LdapClient.java index d972766dc11..4834b6e530a 100644 --- a/src/java.naming/share/classes/com/sun/jndi/ldap/LdapClient.java +++ b/src/java.naming/share/classes/com/sun/jndi/ldap/LdapClient.java @@ -477,7 +477,7 @@ public final class LdapClient implements PooledConnection { } } - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() { if (debug > 0) System.err.println("LdapClient: finalize " + this); forceClose(pooled); diff --git a/src/java.naming/share/classes/com/sun/jndi/ldap/LdapCtx.java b/src/java.naming/share/classes/com/sun/jndi/ldap/LdapCtx.java index 059b654f581..9a918edf0c3 100644 --- a/src/java.naming/share/classes/com/sun/jndi/ldap/LdapCtx.java +++ b/src/java.naming/share/classes/com/sun/jndi/ldap/LdapCtx.java @@ -2639,7 +2639,7 @@ public final class LdapCtx extends ComponentDirContext // ----------------- Connection --------------------- - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() { try { close(); diff --git a/src/java.naming/share/classes/com/sun/jndi/ldap/sasl/DefaultCallbackHandler.java b/src/java.naming/share/classes/com/sun/jndi/ldap/sasl/DefaultCallbackHandler.java index 2a782c0e9cc..b6388915840 100644 --- a/src/java.naming/share/classes/com/sun/jndi/ldap/sasl/DefaultCallbackHandler.java +++ b/src/java.naming/share/classes/com/sun/jndi/ldap/sasl/DefaultCallbackHandler.java @@ -131,7 +131,7 @@ final class DefaultCallbackHandler implements CallbackHandler { } } - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() throws Throwable { clearPassword(); } diff --git a/src/java.rmi/share/classes/sun/rmi/log/LogInputStream.java b/src/java.rmi/share/classes/sun/rmi/log/LogInputStream.java index 649fa22516d..1dbdd3064bc 100644 --- a/src/java.rmi/share/classes/sun/rmi/log/LogInputStream.java +++ b/src/java.rmi/share/classes/sun/rmi/log/LogInputStream.java @@ -128,7 +128,7 @@ class LogInputStream extends InputStream { /** * Closes the stream when garbage is collected. */ - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() throws IOException { close(); } diff --git a/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/GSSCredElement.java b/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/GSSCredElement.java index bfe1807935a..447b6c947e9 100644 --- a/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/GSSCredElement.java +++ b/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/GSSCredElement.java @@ -132,7 +132,7 @@ public class GSSCredElement implements GSSCredentialSpi { return "N/A"; } - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() throws Throwable { dispose(); } diff --git a/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/GSSNameElement.java b/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/GSSNameElement.java index 54641f2f6e6..b449169c441 100644 --- a/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/GSSNameElement.java +++ b/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/GSSNameElement.java @@ -290,7 +290,7 @@ public class GSSNameElement implements GSSNameSpi { } } - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() throws Throwable { dispose(); } diff --git a/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/NativeGSSContext.java b/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/NativeGSSContext.java index e89b109250e..61640be3507 100644 --- a/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/NativeGSSContext.java +++ b/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/NativeGSSContext.java @@ -639,7 +639,7 @@ class NativeGSSContext implements GSSContextSpi { return isInitiator; } - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() throws Throwable { dispose(); } diff --git a/src/java.security.sasl/share/classes/com/sun/security/sasl/CramMD5Base.java b/src/java.security.sasl/share/classes/com/sun/security/sasl/CramMD5Base.java index bbbe88a71e4..b59b449e3c5 100644 --- a/src/java.security.sasl/share/classes/com/sun/security/sasl/CramMD5Base.java +++ b/src/java.security.sasl/share/classes/com/sun/security/sasl/CramMD5Base.java @@ -136,7 +136,7 @@ abstract class CramMD5Base { } } - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() { clearPassword(); } diff --git a/src/java.security.sasl/share/classes/com/sun/security/sasl/PlainClient.java b/src/java.security.sasl/share/classes/com/sun/security/sasl/PlainClient.java index e365e772e6e..04a8d9856c2 100644 --- a/src/java.security.sasl/share/classes/com/sun/security/sasl/PlainClient.java +++ b/src/java.security.sasl/share/classes/com/sun/security/sasl/PlainClient.java @@ -195,7 +195,7 @@ final class PlainClient implements SaslClient { } } - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() { clearPassword(); } diff --git a/src/java.smartcardio/share/classes/sun/security/smartcardio/CardImpl.java b/src/java.smartcardio/share/classes/sun/security/smartcardio/CardImpl.java index 576333a1421..b982df5dd07 100644 --- a/src/java.smartcardio/share/classes/sun/security/smartcardio/CardImpl.java +++ b/src/java.smartcardio/share/classes/sun/security/smartcardio/CardImpl.java @@ -276,7 +276,7 @@ final class CardImpl extends Card { + ", protocol " + getProtocol() + ", state " + state; } - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() throws Throwable { try { if (state == State.OK) { diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11KeyStore.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11KeyStore.java index 0f7b97ebc87..585fb47ec54 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11KeyStore.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11KeyStore.java @@ -243,7 +243,7 @@ final class P11KeyStore extends KeyStoreSpi { pc.setPassword(password); // this clones the password if not null } - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() throws Throwable { if (password != null) { Arrays.fill(password, ' '); diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/PKCS11.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/PKCS11.java index 2b2f3d0ebd4..a4c852f7abf 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/PKCS11.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/PKCS11.java @@ -1615,7 +1615,7 @@ public class PKCS11 { * * @exception Throwable If finalization fails. */ - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() throws Throwable { disconnect(); } diff --git a/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/CKey.java b/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/CKey.java index 019f0ccac56..e010e971787 100644 --- a/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/CKey.java +++ b/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/CKey.java @@ -55,7 +55,7 @@ abstract class CKey implements Key, Length { this.hCryptKey = hCryptKey; } - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() throws Throwable { try { synchronized(this) { diff --git a/src/jdk.jconsole/share/classes/sun/tools/jconsole/SummaryTab.java b/src/jdk.jconsole/share/classes/sun/tools/jconsole/SummaryTab.java index f70f1b1f358..3168665cfc0 100644 --- a/src/jdk.jconsole/share/classes/sun/tools/jconsole/SummaryTab.java +++ b/src/jdk.jconsole/share/classes/sun/tools/jconsole/SummaryTab.java @@ -113,6 +113,7 @@ class SummaryTab extends Tab { StringBuilder buf; + @SuppressWarnings("deprecation") synchronized Result formatSummary() { Result result = new Result(); ProxyClient proxyClient = vmPanel.getProxyClient(); diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/ChunkInputStream.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/ChunkInputStream.java index a5e1d01783f..5b192443980 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/ChunkInputStream.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/ChunkInputStream.java @@ -112,7 +112,7 @@ final class ChunkInputStream extends InputStream { } @Override - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() throws Throwable { super.finalize(); close(); diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/ChunksChannel.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/ChunksChannel.java index 1139536c938..b606105d29e 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/ChunksChannel.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/ChunksChannel.java @@ -137,7 +137,7 @@ final class ChunksChannel implements ReadableByteChannel { } @Override - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() throws Throwable { super.finalize(); close(); diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/RepositoryChunk.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/RepositoryChunk.java index af5ff3e08e4..8cb8bd85c37 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/RepositoryChunk.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/RepositoryChunk.java @@ -134,7 +134,7 @@ final class RepositoryChunk { } @Override - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() { boolean destroy = false; synchronized (this) { diff --git a/src/jdk.naming.dns/share/classes/com/sun/jndi/dns/DnsClient.java b/src/jdk.naming.dns/share/classes/com/sun/jndi/dns/DnsClient.java index ed4f2d8a105..a5508ec45db 100644 --- a/src/jdk.naming.dns/share/classes/com/sun/jndi/dns/DnsClient.java +++ b/src/jdk.naming.dns/share/classes/com/sun/jndi/dns/DnsClient.java @@ -148,7 +148,7 @@ public class DnsClient { } } - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() { close(); } diff --git a/src/jdk.naming.rmi/share/classes/com/sun/jndi/rmi/registry/RegistryContext.java b/src/jdk.naming.rmi/share/classes/com/sun/jndi/rmi/registry/RegistryContext.java index bea428a6068..d77055d2808 100644 --- a/src/jdk.naming.rmi/share/classes/com/sun/jndi/rmi/registry/RegistryContext.java +++ b/src/jdk.naming.rmi/share/classes/com/sun/jndi/rmi/registry/RegistryContext.java @@ -120,7 +120,7 @@ public class RegistryContext implements Context, Referenceable { reference = ctx.reference; } - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() { close(); } @@ -596,7 +596,7 @@ class BindingEnumeration implements NamingEnumeration { nextName = 0; } - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() { ctx.close(); } diff --git a/src/jdk.security.jgss/share/classes/com/sun/security/sasl/gsskerb/GssKrb5Base.java b/src/jdk.security.jgss/share/classes/com/sun/security/sasl/gsskerb/GssKrb5Base.java index 04cc61a5d2e..afdb7279c17 100644 --- a/src/jdk.security.jgss/share/classes/com/sun/security/sasl/gsskerb/GssKrb5Base.java +++ b/src/jdk.security.jgss/share/classes/com/sun/security/sasl/gsskerb/GssKrb5Base.java @@ -162,7 +162,7 @@ abstract class GssKrb5Base extends AbstractSaslImpl { } } - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() throws Throwable { dispose(); } diff --git a/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java b/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java index 4f9b4e427bc..d63ca41424a 100644 --- a/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java +++ b/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java @@ -1219,7 +1219,7 @@ class ZipFileSystem extends FileSystem { return zc.toString(name); } - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") protected void finalize() throws IOException { close(); } -- GitLab From d7ad546758091ea16f836c9771ff5c03a32fb712 Mon Sep 17 00:00:00 2001 From: Stuart Marks Date: Wed, 8 Dec 2021 00:27:53 +0000 Subject: [PATCH 042/671] 8276422: Add command-line option to disable finalization Co-authored-by: David Holmes Co-authored-by: Brent Christian Reviewed-by: dholmes, kbarrett, bchristi --- make/data/hotspot-symbols/symbols-unix | 1 + .../share/classfile/classFileParser.cpp | 6 +- src/hotspot/share/include/jvm.h | 3 + src/hotspot/share/oops/instanceKlass.cpp | 1 + src/hotspot/share/oops/instanceKlass.hpp | 10 ++ src/hotspot/share/prims/jvm.cpp | 4 + src/hotspot/share/runtime/arguments.cpp | 12 ++ .../classes/java/lang/ref/Finalizer.java | 30 +++-- .../launcher/resources/launcher.properties | 5 +- .../share/native/libjava/Finalizer.c | 5 +- .../java/lang/Object/FinalizationOption.java | 122 ++++++++++++++++++ .../Object/InvalidFinalizationOption.java | 52 ++++++++ .../runtime/TestFinalizerStatisticsEvent.java | 31 ++++- 13 files changed, 265 insertions(+), 17 deletions(-) create mode 100644 test/jdk/java/lang/Object/FinalizationOption.java create mode 100644 test/jdk/java/lang/Object/InvalidFinalizationOption.java diff --git a/make/data/hotspot-symbols/symbols-unix b/make/data/hotspot-symbols/symbols-unix index d735f61b3a4..9ec0c1ec7c7 100644 --- a/make/data/hotspot-symbols/symbols-unix +++ b/make/data/hotspot-symbols/symbols-unix @@ -147,6 +147,7 @@ JVM_IsArrayClass JVM_IsCDSDumpingEnabled JVM_IsConstructorIx JVM_IsDumpingClassList +JVM_IsFinalizationEnabled JVM_IsHiddenClass JVM_IsInterface JVM_IsPrimitiveClass diff --git a/src/hotspot/share/classfile/classFileParser.cpp b/src/hotspot/share/classfile/classFileParser.cpp index a7ae7bef5c3..368e3534184 100644 --- a/src/hotspot/share/classfile/classFileParser.cpp +++ b/src/hotspot/share/classfile/classFileParser.cpp @@ -2835,7 +2835,8 @@ Method* ClassFileParser::parse_method(const ClassFileStream* const cfs, annotation_default_length, CHECK_NULL); - if (name == vmSymbols::finalize_method_name() && + if (InstanceKlass::is_finalization_enabled() && + name == vmSymbols::finalize_method_name() && signature == vmSymbols::void_method_signature()) { if (m->is_empty_method()) { _has_empty_finalizer = true; @@ -4171,7 +4172,8 @@ void ClassFileParser::set_precomputed_flags(InstanceKlass* ik) { bool f = false; const Method* const m = ik->lookup_method(vmSymbols::finalize_method_name(), vmSymbols::void_method_signature()); - if (m != NULL && !m->is_empty_method()) { + if (InstanceKlass::is_finalization_enabled() && + (m != NULL) && !m->is_empty_method()) { f = true; } diff --git a/src/hotspot/share/include/jvm.h b/src/hotspot/share/include/jvm.h index 7783b00841d..e4f56c552b7 100644 --- a/src/hotspot/share/include/jvm.h +++ b/src/hotspot/share/include/jvm.h @@ -759,6 +759,9 @@ JVM_SupportsCX8(void); JNIEXPORT void JNICALL JVM_ReportFinalizationComplete(JNIEnv *env, jobject finalizee); +JNIEXPORT jboolean JNICALL +JVM_IsFinalizationEnabled(JNIEnv *env); + /************************************************************************* PART 2: Support for the Verifier and Class File Format Checker ************************************************************************/ diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp index b4ee9c5dc0b..fafc58fa9fd 100644 --- a/src/hotspot/share/oops/instanceKlass.cpp +++ b/src/hotspot/share/oops/instanceKlass.cpp @@ -141,6 +141,7 @@ #endif // ndef DTRACE_ENABLED +bool InstanceKlass::_finalization_enabled = true; static inline bool is_class_loader(const Symbol* class_name, const ClassFileParser& parser) { diff --git a/src/hotspot/share/oops/instanceKlass.hpp b/src/hotspot/share/oops/instanceKlass.hpp index c2ad122e92b..82e918d1444 100644 --- a/src/hotspot/share/oops/instanceKlass.hpp +++ b/src/hotspot/share/oops/instanceKlass.hpp @@ -329,7 +329,17 @@ class InstanceKlass: public Klass { static bool _disable_method_binary_search; + // Controls finalizer registration + static bool _finalization_enabled; + public: + + // Queries finalization state + static bool is_finalization_enabled() { return _finalization_enabled; } + + // Sets finalization state + static void set_finalization_enabled(bool val) { _finalization_enabled = val; } + // The three BUILTIN class loader types bool is_shared_boot_class() const { return (_misc_flags & _misc_is_shared_boot_class) != 0; diff --git a/src/hotspot/share/prims/jvm.cpp b/src/hotspot/share/prims/jvm.cpp index de4e35492c8..f1d00c5da97 100644 --- a/src/hotspot/share/prims/jvm.cpp +++ b/src/hotspot/share/prims/jvm.cpp @@ -690,6 +690,10 @@ JVM_ENTRY(void, JVM_ReportFinalizationComplete(JNIEnv * env, jobject finalizee)) MANAGEMENT_ONLY(FinalizerService::on_complete(JNIHandles::resolve_non_null(finalizee), THREAD);) JVM_END +JVM_ENTRY(jboolean, JVM_IsFinalizationEnabled(JNIEnv * env)) + return InstanceKlass::is_finalization_enabled(); +JVM_END + // java.io.File /////////////////////////////////////////////////////////////// JVM_LEAF(char*, JVM_NativePath(char* path)) diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp index 969c8e82b91..8b32e89e834 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -40,6 +40,7 @@ #include "logging/logStream.hpp" #include "logging/logTag.hpp" #include "memory/allocation.inline.hpp" +#include "oops/instanceKlass.hpp" #include "oops/oop.inline.hpp" #include "prims/jvmtiExport.hpp" #include "runtime/arguments.hpp" @@ -2887,6 +2888,17 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, bool* patch_m if (FLAG_SET_CMDLINE(ErrorFileToStdout, true) != JVMFlag::SUCCESS) { return JNI_EINVAL; } + } else if (match_option(option, "--finalization=", &tail)) { + if (strcmp(tail, "enabled") == 0) { + InstanceKlass::set_finalization_enabled(true); + } else if (strcmp(tail, "disabled") == 0) { + InstanceKlass::set_finalization_enabled(false); + } else { + jio_fprintf(defaultStream::error_stream(), + "Invalid finalization value '%s', must be 'disabled' or 'enabled'.\n", + tail); + return JNI_EINVAL; + } } else if (match_option(option, "-XX:+ExtendedDTraceProbes")) { #if defined(DTRACE_ENABLED) if (FLAG_SET_CMDLINE(ExtendedDTraceProbes, true) != JVMFlag::SUCCESS) { diff --git a/src/java.base/share/classes/java/lang/ref/Finalizer.java b/src/java.base/share/classes/java/lang/ref/Finalizer.java index d5838b7a6b1..18aedf11bb3 100644 --- a/src/java.base/share/classes/java/lang/ref/Finalizer.java +++ b/src/java.base/share/classes/java/lang/ref/Finalizer.java @@ -61,9 +61,17 @@ final class Finalizer extends FinalReference { /* Package-private; must return queue; } + static final boolean ENABLED = isFinalizationEnabled(); + + private static native boolean isFinalizationEnabled(); + /* Invoked by VM */ static void register(Object finalizee) { - new Finalizer(finalizee); + if (ENABLED) { + new Finalizer(finalizee); + } else { + throw new InternalError("unexpected call to Finalizer::register when finalization is disabled"); + } } private void runFinalizer(JavaLangAccess jla) { @@ -130,7 +138,7 @@ final class Finalizer extends FinalReference { /* Package-private; must /* Called by Runtime.runFinalization() */ static void runFinalization() { - if (VM.initLevel() == 0) { + if (VM.initLevel() == 0 || ! ENABLED) { return; } @@ -182,14 +190,16 @@ final class Finalizer extends FinalReference { /* Package-private; must } static { - ThreadGroup tg = Thread.currentThread().getThreadGroup(); - for (ThreadGroup tgn = tg; - tgn != null; - tg = tgn, tgn = tg.getParent()); - Thread finalizer = new FinalizerThread(tg); - finalizer.setPriority(Thread.MAX_PRIORITY - 2); - finalizer.setDaemon(true); - finalizer.start(); + if (ENABLED) { + ThreadGroup tg = Thread.currentThread().getThreadGroup(); + for (ThreadGroup tgn = tg; + tgn != null; + tg = tgn, tgn = tg.getParent()); + Thread finalizer = new FinalizerThread(tg); + finalizer.setPriority(Thread.MAX_PRIORITY - 2); + finalizer.setDaemon(true); + finalizer.start(); + } } } diff --git a/src/java.base/share/classes/sun/launcher/resources/launcher.properties b/src/java.base/share/classes/sun/launcher/resources/launcher.properties index efcc4d69969..22fe4a35a5e 100644 --- a/src/java.base/share/classes/sun/launcher/resources/launcher.properties +++ b/src/java.base/share/classes/sun/launcher/resources/launcher.properties @@ -194,7 +194,10 @@ java.launcher.X.usage=\n\ \ override or augment a module with classes and resources\n\ \ in JAR files or directories.\n\ \ --source \n\ -\ set the version of the source in source-file mode.\n\n\ +\ set the version of the source in source-file mode.\n\ +\ --finalization=\n\ +\ controls finalization\n\ +\ is one of "enabled" or "disabled"\n\n\ These extra options are subject to change without notice.\n # Translators please note do not translate the options themselves diff --git a/src/java.base/share/native/libjava/Finalizer.c b/src/java.base/share/native/libjava/Finalizer.c index d0b81f63d6e..063e330ac9b 100644 --- a/src/java.base/share/native/libjava/Finalizer.c +++ b/src/java.base/share/native/libjava/Finalizer.c @@ -32,4 +32,7 @@ Java_java_lang_ref_Finalizer_reportComplete(JNIEnv* env, jclass cls, jobject fin JVM_ReportFinalizationComplete(env, finalizee); } - +JNIEXPORT jboolean JNICALL +Java_java_lang_ref_Finalizer_isFinalizationEnabled(JNIEnv* env, jclass cls) { + return JVM_IsFinalizationEnabled(env); +} diff --git a/test/jdk/java/lang/Object/FinalizationOption.java b/test/jdk/java/lang/Object/FinalizationOption.java new file mode 100644 index 00000000000..7d50412e26f --- /dev/null +++ b/test/jdk/java/lang/Object/FinalizationOption.java @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2021, 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. + */ + +/* + * @test + * @bug 8276422 + * @summary add command-line option to disable finalization + * @run main/othervm FinalizationOption yes + * @run main/othervm --finalization=enabled FinalizationOption yes + * @run main/othervm --finalization=disabled FinalizationOption no + */ +public class FinalizationOption { + static volatile boolean finalizerWasCalled = false; + + @SuppressWarnings("deprecation") + protected void finalize() { + finalizerWasCalled = true; + } + + static void create() { + new FinalizationOption(); + } + + /** + * Checks whether the finalizer thread is or is not running. The finalizer thread + * is a thread in the root thread group whose named is "Finalizer". + * @param expected boolean indicating whether a finalizer thread should exist + * @return boolean indicating whether the expectation was met + */ + static boolean checkFinalizerThread(boolean expected) { + ThreadGroup root = Thread.currentThread().getThreadGroup(); + for (ThreadGroup parent = root; + parent != null; + root = parent, parent = root.getParent()) + ; + + int nt = 100; + Thread[] threads; + while (true) { + threads = new Thread[nt]; + nt = root.enumerate(threads); + if (nt < threads.length) + break; + threads = new Thread[nt + 100]; + } + + Thread ft = null; + for (int i = 0; i < nt; i++) { + if ("Finalizer".equals(threads[i].getName())) { + ft = threads[i]; + break; + } + } + + String msg = (ft == null) ? "(none)" : ft.toString(); + boolean passed = (ft != null) == expected; + System.out.printf("Finalizer thread. Expected: %s Actual: %s %s%n", + expected, msg, passed ? "Passed." : "FAILED!"); + return passed; + } + + /** + * Checks whether there was a call to the finalize() method. + * @param expected boolean whether finalize() should be called + * @return boolean indicating whether the expecation was met + */ + static boolean checkFinalizerCalled(boolean expected) { + create(); + for (int i = 0; i < 100; i++) { + System.gc(); + try { + Thread.sleep(10L); + } catch (InterruptedException ie) { + Thread.currentThread().interrupt(); + } + if (finalizerWasCalled) { + break; + } + } + boolean passed = (expected == finalizerWasCalled); + System.out.printf("Call to finalize(). Expected: %s Actual: %s %s%n", + expected, finalizerWasCalled, + passed ? "Passed." : "FAILED!"); + return passed; + } + + public static void main(String[] args) { + boolean finalizationEnabled = switch (args[0]) { + case "yes" -> true; + case "no" -> false; + default -> { + throw new AssertionError("usage: FinalizationOption yes|no"); + } + }; + + boolean threadPass = checkFinalizerThread(finalizationEnabled); + boolean calledPass = checkFinalizerCalled(finalizationEnabled); + + if (!threadPass || !calledPass) + throw new AssertionError("Test failed."); + } +} diff --git a/test/jdk/java/lang/Object/InvalidFinalizationOption.java b/test/jdk/java/lang/Object/InvalidFinalizationOption.java new file mode 100644 index 00000000000..c5cca549ead --- /dev/null +++ b/test/jdk/java/lang/Object/InvalidFinalizationOption.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2021, 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. + */ + +/* + * @test + * @bug 8276422 + * @summary Invalid/missing values for the finalization option should be rejected + * @library /test/lib + * @run driver InvalidFinalizationOption + */ + +import jdk.test.lib.process.ProcessTools; +import jdk.test.lib.process.OutputAnalyzer; + +public class InvalidFinalizationOption { + public static void main(String[] args) throws Exception { + record TestData(String arg, String expected) { } + + TestData[] testData = { + new TestData("--finalization", "Unrecognized option"), + new TestData("--finalization=", "Invalid finalization value"), + new TestData("--finalization=azerty", "Invalid finalization value") + }; + + for (var data : testData) { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(data.arg); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldContain(data.expected); + output.shouldHaveExitValue(1); + } + } +} diff --git a/test/jdk/jdk/jfr/event/runtime/TestFinalizerStatisticsEvent.java b/test/jdk/jdk/jfr/event/runtime/TestFinalizerStatisticsEvent.java index ecec7c383fb..8256a62b571 100644 --- a/test/jdk/jdk/jfr/event/runtime/TestFinalizerStatisticsEvent.java +++ b/test/jdk/jdk/jfr/event/runtime/TestFinalizerStatisticsEvent.java @@ -34,17 +34,20 @@ import jdk.test.lib.jfr.TestClassLoader; /** * @test + * @bug 8266936 8276422 * @summary The test verifies that classes overriding finalize() are represented as events. * @key jfr * @requires vm.hasJFR * @library /test/lib /test/jdk * @run main/othervm -Xlog:class+unload,finalizer -Xmx16m jdk.jfr.event.runtime.TestFinalizerStatisticsEvent + * @run main/othervm -Xlog:class+unload,finalizer -Xmx16m --finalization=disabled jdk.jfr.event.runtime.TestFinalizerStatisticsEvent disabled */ public final class TestFinalizerStatisticsEvent { private final static String TEST_CLASS_NAME = "jdk.jfr.event.runtime.TestFinalizerStatisticsEvent$TestClassOverridingFinalize"; private final static String TEST_CLASS_UNLOAD_NAME = "jdk.jfr.event.runtime.TestFinalizerStatisticsEvent$TestClassUnloadOverridingFinalize"; private final static String EVENT_PATH = EventNames.FinalizerStatistics; + private static boolean disabled = false; // Declare as public static to prevent the compiler from optimizing away all unread writes public static TestClassLoader unloadableClassLoader; @@ -52,6 +55,10 @@ public final class TestFinalizerStatisticsEvent { public static Object overridingInstance; public static void main(String[] args) throws Throwable { + if (args.length > 0 && "disabled".equals(args[0])) { + disabled = true; + System.out.println("Testing with finalization disabled"); + } Recording recording1 = new Recording(); recording1.enable(EVENT_PATH); Recording recording2 = new Recording(); @@ -69,8 +76,12 @@ public final class TestFinalizerStatisticsEvent { recording1.stop(); // rotation writes an event for TEST_CLASS_NAME into recording1 which now has 4 events reflecting this test case (3 chunks + 1 unload) try { - verify(recording2); - verify(recording1); + if (disabled) { + verifyDisabled(recording1); + } else { + verifyEnabled(recording2); + verifyEnabled(recording1); + } } finally { recording2.close(); @@ -84,7 +95,8 @@ public final class TestFinalizerStatisticsEvent { System.gc(); } - private static void verify(Recording recording) throws Throwable { + /* Verify correct operation with finalization enabled */ + private static void verifyEnabled(Recording recording) throws Throwable { boolean foundTestClassName = false; boolean foundTestClassUnloadName = false; List events = Events.fromRecording(recording); @@ -108,6 +120,19 @@ public final class TestFinalizerStatisticsEvent { Asserts.assertTrue(foundTestClassUnloadName, "The class: " + TEST_CLASS_UNLOAD_NAME + " overriding finalize() is not found"); } + /* Verify no jdk.FinalizerStatistics events with finalization disabled */ + private static void verifyDisabled(Recording recording) throws Throwable { + int f10nEvents = 0; + List events = Events.fromRecording(recording); + for (RecordedEvent event : events) { + System.out.println("Event:" + event); + if ("jdk.FinalizerStatistics".equals(event.getEventType().getName())) { + f10nEvents++; + } + } + Asserts.assertEquals(f10nEvents, 0, "Finalization disabled, but recorded " + f10nEvents + " jdk.FinalizerStatistics events"); + } + static public class TestClassOverridingFinalize { public boolean finalized = false; -- GitLab From fb6d6113112d8a15864195ccd59b583fc12087fd Mon Sep 17 00:00:00 2001 From: Hamlin Li Date: Wed, 8 Dec 2021 01:26:35 +0000 Subject: [PATCH 043/671] 8278276: G1: Refine naming of G1GCParPhaseTimesTracker::_must_record Reviewed-by: sjohanss, tschatzl --- src/hotspot/share/gc/g1/g1GCParPhaseTimesTracker.hpp | 6 +++--- src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp | 10 +++++----- src/hotspot/share/gc/g1/g1RemSet.cpp | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/hotspot/share/gc/g1/g1GCParPhaseTimesTracker.hpp b/src/hotspot/share/gc/g1/g1GCParPhaseTimesTracker.hpp index 11a62b03825..af626e99fd4 100644 --- a/src/hotspot/share/gc/g1/g1GCParPhaseTimesTracker.hpp +++ b/src/hotspot/share/gc/g1/g1GCParPhaseTimesTracker.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,10 +36,10 @@ protected: G1GCPhaseTimes* _phase_times; uint _worker_id; EventGCPhaseParallel _event; - bool _must_record; + bool _allow_multiple_record; public: - G1GCParPhaseTimesTracker(G1GCPhaseTimes* phase_times, G1GCPhaseTimes::GCParPhases phase, uint worker_id, bool must_record = true); + G1GCParPhaseTimesTracker(G1GCPhaseTimes* phase_times, G1GCPhaseTimes::GCParPhases phase, uint worker_id, bool allow_multiple_record = false); virtual ~G1GCParPhaseTimesTracker(); }; diff --git a/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp b/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp index cc4a90a36f1..3495c22f841 100644 --- a/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp +++ b/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp @@ -574,8 +574,8 @@ void G1EvacPhaseWithTrimTimeTracker::stop() { _stopped = true; } -G1GCParPhaseTimesTracker::G1GCParPhaseTimesTracker(G1GCPhaseTimes* phase_times, G1GCPhaseTimes::GCParPhases phase, uint worker_id, bool must_record) : - _start_time(), _phase(phase), _phase_times(phase_times), _worker_id(worker_id), _event(), _must_record(must_record) { +G1GCParPhaseTimesTracker::G1GCParPhaseTimesTracker(G1GCPhaseTimes* phase_times, G1GCPhaseTimes::GCParPhases phase, uint worker_id, bool allow_multiple_record) : + _start_time(), _phase(phase), _phase_times(phase_times), _worker_id(worker_id), _event(), _allow_multiple_record(allow_multiple_record) { if (_phase_times != NULL) { _start_time = Ticks::now(); } @@ -583,10 +583,10 @@ G1GCParPhaseTimesTracker::G1GCParPhaseTimesTracker(G1GCPhaseTimes* phase_times, G1GCParPhaseTimesTracker::~G1GCParPhaseTimesTracker() { if (_phase_times != NULL) { - if (_must_record) { - _phase_times->record_time_secs(_phase, _worker_id, (Ticks::now() - _start_time).seconds()); - } else { + if (_allow_multiple_record) { _phase_times->record_or_add_time_secs(_phase, _worker_id, (Ticks::now() - _start_time).seconds()); + } else { + _phase_times->record_time_secs(_phase, _worker_id, (Ticks::now() - _start_time).seconds()); } _event.commit(GCId::current(), _worker_id, G1GCPhaseTimes::phase_name(_phase)); } diff --git a/src/hotspot/share/gc/g1/g1RemSet.cpp b/src/hotspot/share/gc/g1/g1RemSet.cpp index f4893300a07..26bb89f2dbb 100644 --- a/src/hotspot/share/gc/g1/g1RemSet.cpp +++ b/src/hotspot/share/gc/g1/g1RemSet.cpp @@ -1423,7 +1423,7 @@ public: // Merge remembered sets of current candidates. { - G1GCParPhaseTimesTracker x(p, merge_remset_phase, worker_id, _initial_evacuation /* must_record */); + G1GCParPhaseTimesTracker x(p, merge_remset_phase, worker_id, !_initial_evacuation /* allow_multiple_record */); G1MergeCardSetStats stats; { G1MergeCardSetClosure cl(_scan_state); -- GitLab From e7db581e9196b64ef65849e4600f17b23ca9138a Mon Sep 17 00:00:00 2001 From: Pengfei Li Date: Wed, 8 Dec 2021 04:29:23 +0000 Subject: [PATCH 044/671] 8277168: AArch64: Enable arraycopy partial inlining with SVE Reviewed-by: jbhateja, roland, aph --- src/hotspot/cpu/aarch64/aarch64.ad | 2 +- src/hotspot/cpu/aarch64/aarch64_sve.ad | 17 +++++++++++++- src/hotspot/cpu/aarch64/aarch64_sve_ad.m4 | 17 +++++++++++++- .../cpu/aarch64/vm_version_aarch64.cpp | 8 +++++++ src/hotspot/cpu/arm/arm.ad | 2 +- src/hotspot/cpu/ppc/ppc.ad | 2 +- src/hotspot/cpu/s390/s390.ad | 2 +- src/hotspot/cpu/x86/x86.ad | 2 +- src/hotspot/share/opto/c2_globals.hpp | 2 +- src/hotspot/share/opto/library_call.cpp | 2 +- src/hotspot/share/opto/macroArrayCopy.cpp | 2 +- src/hotspot/share/opto/matcher.hpp | 2 +- src/hotspot/share/opto/type.cpp | 12 ++++++++-- src/hotspot/share/opto/type.hpp | 2 ++ src/hotspot/share/opto/vectornode.cpp | 22 ++++++++++++------- src/hotspot/share/opto/vectornode.hpp | 14 +++++------- 16 files changed, 80 insertions(+), 30 deletions(-) diff --git a/src/hotspot/cpu/aarch64/aarch64.ad b/src/hotspot/cpu/aarch64/aarch64.ad index 4e6ed4832bf..970ddecf3bd 100644 --- a/src/hotspot/cpu/aarch64/aarch64.ad +++ b/src/hotspot/cpu/aarch64/aarch64.ad @@ -2481,7 +2481,7 @@ const RegMask* Matcher::predicate_reg_mask(void) { return &_PR_REG_mask; } -const TypeVect* Matcher::predicate_reg_type(const Type* elemTy, int length) { +const TypeVectMask* Matcher::predicate_reg_type(const Type* elemTy, int length) { return new TypeVectMask(elemTy, length); } diff --git a/src/hotspot/cpu/aarch64/aarch64_sve.ad b/src/hotspot/cpu/aarch64/aarch64_sve.ad index 6ad2d68526c..0d922d4c77a 100644 --- a/src/hotspot/cpu/aarch64/aarch64_sve.ad +++ b/src/hotspot/cpu/aarch64/aarch64_sve.ad @@ -5744,4 +5744,19 @@ instruct vmask_lasttrue_partial(iRegINoSp dst, pReg src, pReg ptmp, rFlagsReg cr __ sve_vmask_lasttrue($dst$$Register, bt, as_PRegister($ptmp$$reg), as_PRegister($ptmp$$reg)); %} ins_pipe(pipe_slow); -%} \ No newline at end of file +%} + +// ---------------------------- Vector mask generation --------------------------- +instruct vmask_gen(pRegGov pg, iRegL len, rFlagsReg cr) %{ + predicate(UseSVE > 0); + match(Set pg (VectorMaskGen len)); + effect(KILL cr); + ins_cost(SVE_COST); + format %{ "sve_whilelo $pg, zr, $len\t # sve" %} + ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this); + Assembler::SIMD_RegVariant size = __ elemType_to_regVariant(bt); + __ sve_whilelo(as_PRegister($pg$$reg), size, zr, as_Register($len$$reg)); + %} + ins_pipe(pipe_slow); +%} diff --git a/src/hotspot/cpu/aarch64/aarch64_sve_ad.m4 b/src/hotspot/cpu/aarch64/aarch64_sve_ad.m4 index 65de321a6e1..10f9096b54b 100644 --- a/src/hotspot/cpu/aarch64/aarch64_sve_ad.m4 +++ b/src/hotspot/cpu/aarch64/aarch64_sve_ad.m4 @@ -3174,4 +3174,19 @@ instruct vmask_lasttrue_partial(iRegINoSp dst, pReg src, pReg ptmp, rFlagsReg cr __ sve_vmask_lasttrue($dst$$Register, bt, as_PRegister($ptmp$$reg), as_PRegister($ptmp$$reg)); %} ins_pipe(pipe_slow); -%}dnl +%} + +// ---------------------------- Vector mask generation --------------------------- +instruct vmask_gen(pRegGov pg, iRegL len, rFlagsReg cr) %{ + predicate(UseSVE > 0); + match(Set pg (VectorMaskGen len)); + effect(KILL cr); + ins_cost(SVE_COST); + format %{ "sve_whilelo $pg, zr, $len\t # sve" %} + ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this); + Assembler::SIMD_RegVariant size = __ elemType_to_regVariant(bt); + __ sve_whilelo(as_PRegister($pg$$reg), size, zr, as_Register($len$$reg)); + %} + ins_pipe(pipe_slow); +%} diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp index e08d0b6f134..4ec813df164 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp @@ -469,6 +469,14 @@ void VM_Version::initialize() { } } + int inline_size = (UseSVE > 0 && MaxVectorSize >= 16) ? MaxVectorSize : 0; + if (FLAG_IS_DEFAULT(ArrayOperationPartialInlineSize)) { + FLAG_SET_DEFAULT(ArrayOperationPartialInlineSize, inline_size); + } else if (ArrayOperationPartialInlineSize != 0 && ArrayOperationPartialInlineSize != inline_size) { + warning("Setting ArrayOperationPartialInlineSize to %d", inline_size); + ArrayOperationPartialInlineSize = inline_size; + } + if (FLAG_IS_DEFAULT(OptoScheduling)) { OptoScheduling = true; } diff --git a/src/hotspot/cpu/arm/arm.ad b/src/hotspot/cpu/arm/arm.ad index 9e76f430054..16217afd105 100644 --- a/src/hotspot/cpu/arm/arm.ad +++ b/src/hotspot/cpu/arm/arm.ad @@ -991,7 +991,7 @@ const RegMask* Matcher::predicate_reg_mask(void) { return NULL; } -const TypeVect* Matcher::predicate_reg_type(const Type* elemTy, int length) { +const TypeVectMask* Matcher::predicate_reg_type(const Type* elemTy, int length) { return NULL; } diff --git a/src/hotspot/cpu/ppc/ppc.ad b/src/hotspot/cpu/ppc/ppc.ad index 2ced017e2f4..5a712117e82 100644 --- a/src/hotspot/cpu/ppc/ppc.ad +++ b/src/hotspot/cpu/ppc/ppc.ad @@ -2185,7 +2185,7 @@ const RegMask* Matcher::predicate_reg_mask(void) { return NULL; } -const TypeVect* Matcher::predicate_reg_type(const Type* elemTy, int length) { +const TypeVectMask* Matcher::predicate_reg_type(const Type* elemTy, int length) { return NULL; } diff --git a/src/hotspot/cpu/s390/s390.ad b/src/hotspot/cpu/s390/s390.ad index 60c27c61a51..8a6e62a809b 100644 --- a/src/hotspot/cpu/s390/s390.ad +++ b/src/hotspot/cpu/s390/s390.ad @@ -1544,7 +1544,7 @@ const RegMask* Matcher::predicate_reg_mask(void) { return NULL; } -const TypeVect* Matcher::predicate_reg_type(const Type* elemTy, int length) { +const TypeVectMask* Matcher::predicate_reg_type(const Type* elemTy, int length) { return NULL; } diff --git a/src/hotspot/cpu/x86/x86.ad b/src/hotspot/cpu/x86/x86.ad index c7e396e2637..47e898ea46b 100644 --- a/src/hotspot/cpu/x86/x86.ad +++ b/src/hotspot/cpu/x86/x86.ad @@ -2051,7 +2051,7 @@ const RegMask* Matcher::predicate_reg_mask(void) { return &_VECTMASK_REG_mask; } -const TypeVect* Matcher::predicate_reg_type(const Type* elemTy, int length) { +const TypeVectMask* Matcher::predicate_reg_type(const Type* elemTy, int length) { return new TypeVectMask(elemTy, length); } diff --git a/src/hotspot/share/opto/c2_globals.hpp b/src/hotspot/share/opto/c2_globals.hpp index b30bb4b70a4..cc6d1d762da 100644 --- a/src/hotspot/share/opto/c2_globals.hpp +++ b/src/hotspot/share/opto/c2_globals.hpp @@ -85,7 +85,7 @@ product(intx, ArrayOperationPartialInlineSize, 0, DIAGNOSTIC, \ "Partial inline size used for small array operations" \ "(e.g. copy,cmp) acceleration.") \ - range(0, 64) \ + range(0, 256) \ \ product(bool, AlignVector, true, \ "Perform vector store/load alignment in loop") \ diff --git a/src/hotspot/share/opto/library_call.cpp b/src/hotspot/share/opto/library_call.cpp index 0270b1ac01a..ea56b6e01de 100644 --- a/src/hotspot/share/opto/library_call.cpp +++ b/src/hotspot/share/opto/library_call.cpp @@ -5427,7 +5427,7 @@ bool LibraryCallKit::inline_vectorizedMismatch() { Node* obja_adr_mem = memory(C->get_alias_index(obja_adr_t)); Node* objb_adr_mem = memory(C->get_alias_index(objb_adr_t)); - Node* vmask = _gvn.transform(new VectorMaskGenNode(ConvI2X(casted_length), TypeVect::VECTMASK, elem_bt)); + Node* vmask = _gvn.transform(VectorMaskGenNode::make(ConvI2X(casted_length), elem_bt)); Node* vload_obja = _gvn.transform(new LoadVectorMaskedNode(control(), obja_adr_mem, obja_adr, obja_adr_t, vt, vmask)); Node* vload_objb = _gvn.transform(new LoadVectorMaskedNode(control(), objb_adr_mem, objb_adr, objb_adr_t, vt, vmask)); Node* result = _gvn.transform(new VectorCmpMaskedNode(vload_obja, vload_objb, vmask, TypeInt::INT)); diff --git a/src/hotspot/share/opto/macroArrayCopy.cpp b/src/hotspot/share/opto/macroArrayCopy.cpp index 68f98070e76..37f2db44269 100644 --- a/src/hotspot/share/opto/macroArrayCopy.cpp +++ b/src/hotspot/share/opto/macroArrayCopy.cpp @@ -237,7 +237,7 @@ void PhaseMacroExpand::generate_partial_inlining_block(Node** ctrl, MergeMemNode inline_block = generate_guard(ctrl, bol_le, NULL, PROB_FAIR); stub_block = *ctrl; - Node* mask_gen = new VectorMaskGenNode(casted_length, TypeVect::VECTMASK, type); + Node* mask_gen = VectorMaskGenNode::make(casted_length, type); transform_later(mask_gen); unsigned vec_size = lane_count * type2aelembytes(type); diff --git a/src/hotspot/share/opto/matcher.hpp b/src/hotspot/share/opto/matcher.hpp index 446fb259ee5..c428193ff72 100644 --- a/src/hotspot/share/opto/matcher.hpp +++ b/src/hotspot/share/opto/matcher.hpp @@ -332,7 +332,7 @@ public: static const bool match_rule_supported_vector_masked(int opcode, int vlen, BasicType bt); static const RegMask* predicate_reg_mask(void); - static const TypeVect* predicate_reg_type(const Type* elemTy, int length); + static const TypeVectMask* predicate_reg_type(const Type* elemTy, int length); // Vector width in bytes static const int vector_width_in_bytes(BasicType bt); diff --git a/src/hotspot/share/opto/type.cpp b/src/hotspot/share/opto/type.cpp index 2cd8925002a..56e5c54ef18 100644 --- a/src/hotspot/share/opto/type.cpp +++ b/src/hotspot/share/opto/type.cpp @@ -2390,8 +2390,7 @@ const TypeVect *TypeVect::makemask(const Type* elem, uint length) { BasicType elem_bt = elem->array_element_basic_type(); if (Matcher::has_predicated_vectors() && Matcher::match_rule_supported_vector_masked(Op_VectorLoadMask, length, elem_bt)) { - const TypeVect* mtype = Matcher::predicate_reg_type(elem, length); - return (TypeVect*)(const_cast(mtype))->hashcons(); + return TypeVectMask::make(elem, length); } else { return make(elem, length); } @@ -2505,6 +2504,15 @@ const Type *TypeVectMask::xdual() const { return new TypeVectMask(element_type()->dual(), length()); } +const TypeVectMask *TypeVectMask::make(const BasicType elem_bt, uint length) { + return make(get_const_basic_type(elem_bt), length); +} + +const TypeVectMask *TypeVectMask::make(const Type* elem, uint length) { + const TypeVectMask* mtype = Matcher::predicate_reg_type(elem, length); + return (TypeVectMask*) const_cast(mtype)->hashcons(); +} + //============================================================================= // Convenience common pre-built types. const TypePtr *TypePtr::NULL_PTR; diff --git a/src/hotspot/share/opto/type.hpp b/src/hotspot/share/opto/type.hpp index 6a927ee49a7..754e0c0adc6 100644 --- a/src/hotspot/share/opto/type.hpp +++ b/src/hotspot/share/opto/type.hpp @@ -870,6 +870,8 @@ public: TypeVectMask(const Type* elem, uint length) : TypeVect(VectorMask, elem, length) {} virtual bool eq(const Type *t) const; virtual const Type *xdual() const; + static const TypeVectMask* make(const BasicType elem_bt, uint length); + static const TypeVectMask* make(const Type* elem, uint length); }; //------------------------------TypePtr---------------------------------------- diff --git a/src/hotspot/share/opto/vectornode.cpp b/src/hotspot/share/opto/vectornode.cpp index 3a88fb37ab0..49be2d3e7ae 100644 --- a/src/hotspot/share/opto/vectornode.cpp +++ b/src/hotspot/share/opto/vectornode.cpp @@ -801,10 +801,10 @@ Node* LoadVectorMaskedNode::Ideal(PhaseGVN* phase, bool can_reshape) { Node* mask_len = in(3)->in(1); const TypeLong* ty = phase->type(mask_len)->isa_long(); if (ty && ty->is_con()) { - BasicType mask_bt = ((VectorMaskGenNode*)in(3))->get_elem_type(); - uint load_sz = type2aelembytes(mask_bt) * ty->get_con(); - if ( load_sz == 32 || load_sz == 64) { - assert(load_sz == 32 || MaxVectorSize > 32, "Unexpected load size"); + BasicType mask_bt = Matcher::vector_element_basic_type(in(3)); + int load_sz = type2aelembytes(mask_bt) * ty->get_con(); + assert(load_sz <= MaxVectorSize, "Unexpected load size"); + if (load_sz == MaxVectorSize) { Node* ctr = in(MemNode::Control); Node* mem = in(MemNode::Memory); Node* adr = in(MemNode::Address); @@ -820,10 +820,10 @@ Node* StoreVectorMaskedNode::Ideal(PhaseGVN* phase, bool can_reshape) { Node* mask_len = in(4)->in(1); const TypeLong* ty = phase->type(mask_len)->isa_long(); if (ty && ty->is_con()) { - BasicType mask_bt = ((VectorMaskGenNode*)in(4))->get_elem_type(); - uint load_sz = type2aelembytes(mask_bt) * ty->get_con(); - if ( load_sz == 32 || load_sz == 64) { - assert(load_sz == 32 || MaxVectorSize > 32, "Unexpected store size"); + BasicType mask_bt = Matcher::vector_element_basic_type(in(4)); + int load_sz = type2aelembytes(mask_bt) * ty->get_con(); + assert(load_sz <= MaxVectorSize, "Unexpected store size"); + if (load_sz == MaxVectorSize) { Node* ctr = in(MemNode::Control); Node* mem = in(MemNode::Memory); Node* adr = in(MemNode::Address); @@ -1425,6 +1425,12 @@ Node* ShiftVNode::Identity(PhaseGVN* phase) { return this; } +Node* VectorMaskGenNode::make(Node* length, BasicType mask_bt) { + int max_vector = Matcher::max_vector_size(mask_bt); + const TypeVectMask* t_vmask = TypeVectMask::make(mask_bt, max_vector); + return new VectorMaskGenNode(length, t_vmask); +} + Node* VectorMaskOpNode::make(Node* mask, const Type* ty, int mopc) { switch(mopc) { case Op_VectorMaskTrueCount: diff --git a/src/hotspot/share/opto/vectornode.hpp b/src/hotspot/share/opto/vectornode.hpp index 95079919f78..fc424f59a3e 100644 --- a/src/hotspot/share/opto/vectornode.hpp +++ b/src/hotspot/share/opto/vectornode.hpp @@ -919,23 +919,19 @@ class VectorCmpMaskedNode : public TypeNode { virtual int Opcode() const; }; +//------------------------------VectorMaskGenNode---------------------------------- class VectorMaskGenNode : public TypeNode { public: - VectorMaskGenNode(Node* length, const Type* ty, BasicType ety): TypeNode(ty, 2), _elemType(ety) { + VectorMaskGenNode(Node* length, const Type* ty): TypeNode(ty, 2) { init_req(1, length); } virtual int Opcode() const; - BasicType get_elem_type() { return _elemType;} - virtual uint size_of() const { return sizeof(VectorMaskGenNode); } - virtual uint ideal_reg() const { - return Op_RegVectMask; - } - - private: - BasicType _elemType; + virtual uint ideal_reg() const { return Op_RegVectMask; } + static Node* make(Node* length, BasicType vmask_bt); }; +//------------------------------VectorMaskOpNode----------------------------------- class VectorMaskOpNode : public TypeNode { public: VectorMaskOpNode(Node* mask, const Type* ty, int mopc): -- GitLab From 5266e7d780efee11309260ce96ae0c5b4836effb Mon Sep 17 00:00:00 2001 From: Jie Fu Date: Wed, 8 Dec 2021 06:45:01 +0000 Subject: [PATCH 045/671] 8278379: Zero VM is broken due to UseRTMForStackLocks was not declared after JDK-8276901 Reviewed-by: dholmes, shade --- src/hotspot/share/runtime/arguments.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp index 8b32e89e834..adfe1a1fb6a 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -2027,7 +2027,7 @@ bool Arguments::check_vm_args_consistency() { warning("UseHeavyMonitors is not fully implemented on this architecture"); } #endif -#if defined(X86) || defined(PPC64) +#if (defined(X86) || defined(PPC64)) && !defined(ZERO) if (UseHeavyMonitors && UseRTMForStackLocks) { fatal("-XX:+UseHeavyMonitors and -XX:+UseRTMForStackLocks are mutually exclusive"); } -- GitLab From 30f0c6475359516ce454722f06ac0c997e09868b Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Wed, 8 Dec 2021 06:52:16 +0000 Subject: [PATCH 046/671] 8277992: Add fast jdk_svc subtests to jdk:tier3 Reviewed-by: mseledtsov, alanb --- test/jdk/TEST.groups | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/test/jdk/TEST.groups b/test/jdk/TEST.groups index 3f8f683af09..00b06cae87b 100644 --- a/test/jdk/TEST.groups +++ b/test/jdk/TEST.groups @@ -74,7 +74,9 @@ tier3 = \ :build \ :jdk_vector \ :jdk_rmi \ - :jdk_jfr_tier3 + :jdk_svc \ + -:jdk_svc_sanity \ + -:svc_tools # Everything not in other tiers tier4 = \ @@ -283,9 +285,6 @@ jdk_tools = \ jdk_jfr = \ jdk/jfr -jdk_jfr_tier3 = \ - jdk/jfr/event/metadata/TestLookForUntestedEvents.java - # # Catch-all for other areas with a small number of tests # -- GitLab From b334d9680b2ee796d5058d68881215bb11499aad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20Walln=C3=B6fer?= Date: Wed, 8 Dec 2021 07:07:57 +0000 Subject: [PATCH 047/671] 8276964: Better indicate a snippet that could not be processed Reviewed-by: jjg --- .../formats/html/HtmlDocletWriter.java | 35 +- .../formats/html/TagletWriterImpl.java | 9 + .../formats/html/markup/HtmlStyle.java | 5 + .../doclets/formats/html/markup/TagName.java | 2 + .../html/resources/standard.properties | 1 + .../doclets/toolkit/resources/stylesheet.css | 14 +- .../toolkit/taglets/SnippetTaglet.java | 12 +- .../doclets/toolkit/taglets/TagletWriter.java | 12 + .../TestGenericTypeLink.java | 42 ++- .../doclet/testInherited/TestInherited.java | 36 ++- .../TestNonInlineHtmlTagRemoval.java | 2 +- .../javadoc/doclet/testSeeTag/TestSeeTag.java | 7 +- .../doclet/testSnippetTag/TestSnippetTag.java | 303 +++++++++++------- 13 files changed, 329 insertions(+), 151 deletions(-) diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java index cf9c43264c1..1a735412886 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java @@ -36,6 +36,7 @@ import java.util.ListIterator; import java.util.Locale; import java.util.Map; import java.util.Objects; +import java.util.Optional; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -1063,7 +1064,8 @@ public class HtmlDocletWriter { "doclet.see.class_or_package_not_found", "@" + tagName, seeText); - return (labelContent.isEmpty() ? text: labelContent); + return invalidTagOutput(resources.getText("doclet.tag.invalid", tagName), + Optional.of(labelContent.isEmpty() ? text: labelContent)); } } } else if (refMemName == null) { @@ -1614,13 +1616,18 @@ public class HtmlDocletWriter { DocTreePath dtp = ch.getDocTreePath(node); if (dtp != null) { String body = node.getBody(); - if (body.matches("(?i)\\{@[a-z]+.*")) { - messages.warning(dtp,"doclet.tag.invalid_usage", body); - } else { + Matcher m = Pattern.compile("(?i)\\{@([a-z]+).*").matcher(body); + String tagName = m.matches() ? m.group(1) : null; + if (tagName == null) { messages.warning(dtp, "doclet.tag.invalid_input", body); + result.add(invalidTagOutput(resources.getText("doclet.tag.invalid_input", body), + Optional.empty())); + } else { + messages.warning(dtp, "doclet.tag.invalid_usage", body); + result.add(invalidTagOutput(resources.getText("doclet.tag.invalid", tagName), + Optional.of(Text.of(body)))); } } - result.add(Text.of(node.toString())); return false; } @@ -1774,6 +1781,24 @@ public class HtmlDocletWriter { && currentPageElement != utils.getEnclosingTypeElement(element)); } + /** + * Returns the output for an invalid tag. The returned content uses special styling to + * highlight the problem. Depending on the presence of the {@code detail} string the method + * returns a plain text span or an expandable component. + * + * @param summary the single-line summary message + * @param detail the optional detail message which may contain preformatted text + * @return the output + */ + protected Content invalidTagOutput(String summary, Optional detail) { + if (detail.isEmpty() || detail.get().isEmpty()) { + return HtmlTree.SPAN(HtmlStyle.invalidTag, Text.of(summary)); + } + return new HtmlTree(TagName.DETAILS).addStyle(HtmlStyle.invalidTag) + .add(new HtmlTree(TagName.SUMMARY).add(Text.of(summary))) + .add(new HtmlTree(TagName.PRE).add(detail.get())); + } + /** * Returns true if element lives in the same package as the type or package * element of this writer. diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TagletWriterImpl.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TagletWriterImpl.java index 640786dd4eb..576597ae86e 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TagletWriterImpl.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TagletWriterImpl.java @@ -29,6 +29,7 @@ import java.util.ArrayList; import java.util.EnumSet; import java.util.HashSet; import java.util.List; +import java.util.Optional; import java.util.Set; import javax.lang.model.element.Element; @@ -536,6 +537,14 @@ public class TagletWriterImpl extends TagletWriter { : Text.of(constantVal); } + @Override + protected Content invalidTagOutput(String summary, Optional detail) { + return htmlWriter.invalidTagOutput(summary, + detail.isEmpty() || detail.get().isEmpty() + ? Optional.empty() + : Optional.of(Text.of(utils.normalizeNewlines(detail.get())))); + } + @Override public Content commentTagsToOutput(DocTree holder, List tags) { return commentTagsToOutput(null, holder, tags, false); diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlStyle.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlStyle.java index 1d22926b816..ad74b81eee5 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlStyle.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlStyle.java @@ -907,6 +907,11 @@ public enum HtmlStyle { */ inheritedList, + /** + * The class of an element that acts as a notification for an invalid tag. + */ + invalidTag, + /** * The class of a {@code p} element containing legal copy in the page footer. */ diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/TagName.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/TagName.java index 34655300b30..59aad16bf2d 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/TagName.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/TagName.java @@ -47,6 +47,7 @@ public enum TagName { CAPTION, CODE, DD, + DETAILS, DIV, DL, DT, @@ -83,6 +84,7 @@ public enum TagName { SPAN, STRONG, SUB, + SUMMARY, SUP, TABLE, TBODY, diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties index f491b97adfe..8a511b8ca4f 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties @@ -106,6 +106,7 @@ doclet.see.class_or_package_not_accessible=Tag {0}: reference not accessible: {1 doclet.see.nested_link=Tag {0}: nested link doclet.tag.invalid_usage=invalid usage of tag {0} doclet.tag.invalid_input=invalid input: ''{0}'' +doclet.tag.invalid=invalid @{0} doclet.Deprecated_API=Deprecated API doclet.Deprecated_Elements=Deprecated {0} doclet.Deprecated_In_Release=Deprecated in {0} diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/stylesheet.css b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/stylesheet.css index d61caef2a0e..69252eab283 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/stylesheet.css +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/stylesheet.css @@ -555,6 +555,18 @@ div.block { div.block div.deprecation-comment { font-style:normal; } +details.invalid-tag, span.invalid-tag { + font-size:14px; + font-family:'DejaVu Serif', Georgia, "Times New Roman", Times, serif; + background: #ffe6e6; + border: thin solid #000000; + border-radius:2px; + padding: 2px 4px; + display:inline-block; +} +details.invalid-tag summary { + cursor: pointer; +} /* * Styles specific to HTML5 elements. */ @@ -991,11 +1003,9 @@ button.snippet-copy:active { pre.snippet .italic { font-style: italic; } - pre.snippet .bold { font-weight: bold; } - pre.snippet .highlighted { background-color: #f7c590; border-radius: 10%; diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/SnippetTaglet.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/SnippetTaglet.java index 0f40ab1e297..3c13b194c22 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/SnippetTaglet.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/SnippetTaglet.java @@ -120,7 +120,8 @@ public class SnippetTaglet extends BaseTaglet { return generateContent(holder, tag, writer); } catch (BadSnippetException e) { error(writer, holder, e.tag(), e.key(), e.args()); - return badSnippet(writer); + String details = writer.configuration().getDocResources().getText(e.key(), e.args()); + return badSnippet(writer, Optional.of(details)); } } @@ -286,7 +287,7 @@ public class SnippetTaglet extends BaseTaglet { .getText("doclet.snippet.markup", e.getMessage()); writer.configuration().getReporter().print(Diagnostic.Kind.ERROR, path, e.getPosition(), e.getPosition(), e.getPosition(), msg); - return badSnippet(writer); + return badSnippet(writer, Optional.of(e.getMessage())); } try { @@ -299,7 +300,7 @@ public class SnippetTaglet extends BaseTaglet { assert fileObject != null; writer.configuration().getMessages().error(fileObject, e.getPosition(), e.getPosition(), e.getPosition(), "doclet.snippet.markup", e.getMessage()); - return badSnippet(writer); + return badSnippet(writer, Optional.of(e.getMessage())); } // the region must be matched at least in one content: it can be matched @@ -408,8 +409,9 @@ public class SnippetTaglet extends BaseTaglet { writer.configuration().utils.getCommentHelper(holder).getDocTreePath(tag), key, args); } - private Content badSnippet(TagletWriter writer) { - return writer.getOutputInstance().add("bad snippet"); + private Content badSnippet(TagletWriter writer, Optional details) { + Resources resources = writer.configuration().getDocResources(); + return writer.invalidTagOutput(resources.getText("doclet.tag.invalid", "snippet"), details); } private String packageName(PackageElement pkg, Utils utils) { diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/TagletWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/TagletWriter.java index a12c7b42ffd..b9142d6721a 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/TagletWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/TagletWriter.java @@ -27,6 +27,7 @@ package jdk.javadoc.internal.doclets.toolkit.taglets; import java.util.List; import java.util.Map; +import java.util.Optional; import javax.lang.model.element.Element; import javax.lang.model.element.ElementKind; import javax.lang.model.element.TypeElement; @@ -239,6 +240,17 @@ public abstract class TagletWriter { protected abstract Content valueTagOutput(VariableElement field, String constantVal, boolean includeLink); + /** + * Returns the output for an invalid tag. The returned content uses special styling to + * highlight the problem. Depending on the presence of the {@code detail} string the method + * returns a plain text span or an expandable component. + * + * @param summary the single-line summary message + * @param detail the optional detail message which may contain preformatted text + * @return the output + */ + protected abstract Content invalidTagOutput(String summary, Optional detail); + /** * Returns the main type element of the current page or null for pages that don't have one. * diff --git a/test/langtools/jdk/javadoc/doclet/testGenericTypeLink/TestGenericTypeLink.java b/test/langtools/jdk/javadoc/doclet/testGenericTypeLink/TestGenericTypeLink.java index fbfbb5f3978..1f0ea233288 100644 --- a/test/langtools/jdk/javadoc/doclet/testGenericTypeLink/TestGenericTypeLink.java +++ b/test/langtools/jdk/javadoc/doclet/testGenericTypeLink/TestGenericTypeLink.java @@ -166,18 +166,48 @@ public class TestGenericTypeLink extends JavadocTester { checkExit(Exit.ERROR); checkOutput("pkg2/B.html", true, """ -
java.util.Foo<String> - Baz<Object> - #b(List<Integer>)
""", +
+
+ invalid @link +
java.util.Foo<String>
+
+ + \s +
+ invalid @linkplain +
Baz<Object>
+
+ + \s +
+ invalid @link +
#b(List<Integer>)
+
+
""", """
See Also:
    -
  • java.util.List<Bar>
  • -
  • Baz<Object, String>
  • -
  • B#b(List<Baz>)
  • +
  • +
    + invalid @see +
    java.util.List<Bar>
    +
    +
  • +
  • +
    + invalid @see +
    Baz<Object, String>
    +
    +
  • +
  • +
    + invalid @see +
    B#b(List<Baz>)
    +
    +
"""); diff --git a/test/langtools/jdk/javadoc/doclet/testInherited/TestInherited.java b/test/langtools/jdk/javadoc/doclet/testInherited/TestInherited.java index 21391201a03..0806278b43d 100644 --- a/test/langtools/jdk/javadoc/doclet/testInherited/TestInherited.java +++ b/test/langtools/jdk/javadoc/doclet/testInherited/TestInherited.java @@ -69,11 +69,11 @@ public class TestInherited extends JavadocTester { checkExit(Exit.OK); checkOutput("BadParam.Base.html", true, """
Parameters:
-
i - a < b
+
i - a invalid input: '<' b
"""); checkOutput("BadParam.Sub.html", true, """
Parameters:
-
i - a < b
+
i - a invalid input: '<' b
"""); } @@ -101,11 +101,11 @@ public class TestInherited extends JavadocTester { checkExit(Exit.OK); checkOutput("BadReturn.Base.html", true, """
Returns:
-
a < b
+
a invalid input: '<' b
"""); checkOutput("BadReturn.Sub.html", true, """
Returns:
-
a < b
+
a invalid input: '<' b
"""); } @@ -147,16 +147,36 @@ public class TestInherited extends JavadocTester { src.resolve("BadReference.java").toString()); checkExit(Exit.OK); checkOutput("BadReference.Intf.html", true, """ -
NonExistingClass
+
+
+ invalid @link +
NonExistingClass
+
+
"""); checkOutput("BadReference.Impl1.html", true, """ -
NonExistingClass
+
+
+ invalid @link +
NonExistingClass
+
+
"""); checkOutput("BadReference.Impl2.html", true, """ -
NonExistingClass
+
+
+ invalid @link +
NonExistingClass
+
+
"""); checkOutput("BadReference.Impl3.html", true, """ -
NonExistingClass
+
+
+ invalid @link +
NonExistingClass
+
+
"""); } } diff --git a/test/langtools/jdk/javadoc/doclet/testNonInlineHtmlTagRemoval/TestNonInlineHtmlTagRemoval.java b/test/langtools/jdk/javadoc/doclet/testNonInlineHtmlTagRemoval/TestNonInlineHtmlTagRemoval.java index 35a25e29bf2..b0b54bbdd6c 100644 --- a/test/langtools/jdk/javadoc/doclet/testNonInlineHtmlTagRemoval/TestNonInlineHtmlTagRemoval.java +++ b/test/langtools/jdk/javadoc/doclet/testNonInlineHtmlTagRemoval/TestNonInlineHtmlTagRemoval.java @@ -85,6 +85,6 @@ public class TestNonInlineHtmlTagRemoval extends JavadocTester { checkOutput("Negative.html", true, """ -
case1: A hanging < : xx<
"""); +
case1: A hanging < : xxinvalid input: '<'
"""); } } diff --git a/test/langtools/jdk/javadoc/doclet/testSeeTag/TestSeeTag.java b/test/langtools/jdk/javadoc/doclet/testSeeTag/TestSeeTag.java index f364cd47ef7..b6661acae52 100644 --- a/test/langtools/jdk/javadoc/doclet/testSeeTag/TestSeeTag.java +++ b/test/langtools/jdk/javadoc/doclet/testSeeTag/TestSeeTag.java @@ -100,7 +100,12 @@ public class TestSeeTag extends JavadocTester {
  • Object
  • -
  • Foo<String>
  • +
  • +
    + invalid @see +
    Foo<String>
    +
    +
"""); diff --git a/test/langtools/jdk/javadoc/doclet/testSnippetTag/TestSnippetTag.java b/test/langtools/jdk/javadoc/doclet/testSnippetTag/TestSnippetTag.java index fac9dfef6e1..4b0dd06a2a2 100644 --- a/test/langtools/jdk/javadoc/doclet/testSnippetTag/TestSnippetTag.java +++ b/test/langtools/jdk/javadoc/doclet/testSnippetTag/TestSnippetTag.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8266666 8275788 + * @bug 8266666 8275788 8276964 * @summary Implementation for snippets * @library /tools/lib ../../lib * @modules jdk.compiler/com.sun.tools.javac.api @@ -1080,6 +1080,12 @@ public class TestSnippetTag extends SnippetTester { checkOutput(Output.OUT, true, """ A.java:4: error: File not found: %s""".formatted(fileName)); + checkOutput("pkg/A.html", true, """ +
+ invalid @snippet +
File not found: text.txt
+
+ """); checkNoCrashes(); } @@ -1155,6 +1161,12 @@ public class TestSnippetTag extends SnippetTester { checkOutput(Output.OUT, true, """ A.java:3: error: @snippet does not specify contents"""); + checkOutput("pkg/A.html", true, """ +
+ invalid @snippet +
@snippet does not specify contents
+
+ """); checkNoCrashes(); } @@ -1211,6 +1223,12 @@ public class TestSnippetTag extends SnippetTester { checkOutput(Output.OUT, true, """ A.java:3: error: @snippet specifies multiple external contents, which is ambiguous"""); + checkOutput("pkg/A.html", true, """ +
+ invalid @snippet +
@snippet specifies multiple external contents, which is ambiguous
+
+ """); checkNoCrashes(); } @@ -1863,15 +1881,15 @@ public class TestSnippetTag extends SnippetTester { for (String attrName : List.of("class", "file", "id", "lang", "region")) { // special case: valueless region attribute TestCase t = new TestCase(""" -{@snippet %s: - First line - Second line -} -""".formatted(attrName), -""" -: error: missing value for attribute "%s" -{@snippet %s: - ^""".formatted(attrName, attrName)); + {@snippet %s: + First line + Second line + } + """.formatted(attrName), + """ + : error: missing value for attribute "%s" + {@snippet %s: + ^""".formatted(attrName, attrName)); testCases.add(t); } @@ -1915,15 +1933,18 @@ public class TestSnippetTag extends SnippetTester { for (String quote : List.of("", "'", "\"")) for (String value : List.of("", " ")) { var t = new TestCase(""" -{@snippet region=%s%s%s: - First line - Second line -} -""".formatted(quote, value, quote), - """ -: error: illegal value for attribute "region": "%s" -{@snippet region=%s%s%s: - ^""".formatted(quote.isEmpty() ? "" : value, quote, value, quote)); // unquoted whitespace translates to empty string + {@snippet region=%s%s%s: + First line + Second line + } + """.formatted(quote, value, quote), + """ + : error: illegal value for attribute "region": "%s" + {@snippet region=%s%s%s: + ^ + """.formatted( + quote.isEmpty() ? "" : value, // unquoted whitespace translates to empty string + quote, value, quote)); testCases.add(t); } @@ -2015,6 +2036,17 @@ public class TestSnippetTag extends SnippetTester { checkOutput(Output.OUT, true, """ A.java:4: error: contents mismatch"""); + checkOutput("pkg/A.html", true, """ +
+ invalid @snippet +
contents mismatch:
+                        ----------------- inline -------------------
+                        Hello, Snippet!
+                        ----------------- external -----------------
+                        Hello, Snippet!...more
+                        
+
+ """); checkNoCrashes(); } @@ -2055,6 +2087,19 @@ public class TestSnippetTag extends SnippetTester { checkOutput(Output.OUT, true, """ A.java:4: error: contents mismatch"""); + checkOutput("pkg/A.html", true, """ +
+ invalid @snippet +
contents mismatch:
+                        ----------------- inline -------------------
+                        Hello, Snippet! ...more
+
+                        ----------------- external -----------------
+                        Hello, Snippet!
+
+                        
+
+ """); checkNoCrashes(); } @@ -2278,41 +2323,41 @@ public class TestSnippetTag extends SnippetTester { final var testCases = List.of( new TestCase(""" -{@snippet : -hello there // @highlight regex ="\t**" -}""", + {@snippet : + hello there // @highlight regex ="\t**" + }""", """ -error: snippet markup: invalid regex -hello there // @highlight regex ="\t**" - \t ^ -"""), + error: snippet markup: invalid regex + hello there // @highlight regex ="\t**" + \t ^ + """), new TestCase(""" -{@snippet : -hello there // @highlight regex ="\\t**" -}""", + {@snippet : + hello there // @highlight regex ="\\t**" + }""", """ -error: snippet markup: invalid regex -hello there // @highlight regex ="\\t**" - ^ -"""), + error: snippet markup: invalid regex + hello there // @highlight regex ="\\t**" + ^ + """), new TestCase(""" -{@snippet : -hello there // @highlight regex="\\.\\*\\+\\E" -}""", + {@snippet : + hello there // @highlight regex="\\.\\*\\+\\E" + }""", """ -error: snippet markup: invalid regex -hello there // @highlight regex="\\.\\*\\+\\E" - \s\s\s\s ^ -"""), // use \s to counteract shift introduced by \\ so as to visually align ^ right below E + error: snippet markup: invalid regex + hello there // @highlight regex="\\.\\*\\+\\E" + \s\s\s\s ^ + """), // use \s to counteract shift introduced by \\ so as to visually align ^ right below E new TestCase(""" -{@snippet : -hello there // @highlight type="italics" regex =" [" -}""", + {@snippet : + hello there // @highlight type="italics" regex =" [" + }""", """ -error: snippet markup: invalid regex -hello there // @highlight type="italics" regex =" [" - ^ -""") + error: snippet markup: invalid regex + hello there // @highlight type="italics" regex =" [" + ^ + """) ); List inputs = testCases.stream().map(s -> s.input).toList(); @@ -2342,6 +2387,12 @@ hello there // @highlight type="italics" regex =" [" src.resolve("A.java").toString()); checkExit(Exit.ERROR); checkOrder(Output.OUT, testCases.stream().map(TestCase::expectedError).toArray(String[]::new)); + checkOutput("A.html", true, """ +
+ invalid @snippet +
invalid regex
+
+ """); checkNoCrashes(); } @@ -2352,118 +2403,118 @@ hello there // @highlight type="italics" regex =" [" final var testCases = List.of( new TestCase(""" -{@snippet : - hello // @link -}""", + {@snippet : + hello // @link + }""", """ -error: snippet markup: missing attribute "target" - hello // @link - ^ + error: snippet markup: missing attribute "target" + hello // @link + ^ """), new TestCase(""" -{@snippet : - hello // @start -}""", + {@snippet : + hello // @start + }""", """ -error: snippet markup: missing attribute "region" - hello // @start - ^ + error: snippet markup: missing attribute "region" + hello // @start + ^ """), new TestCase(""" -{@snippet : - hello // @replace -}""", + {@snippet : + hello // @replace + }""", """ -error: snippet markup: missing attribute "replacement" - hello // @replace - ^ + error: snippet markup: missing attribute "replacement" + hello // @replace + ^ """), /* ---------------------- */ new TestCase(""" -{@snippet : - hello // @highlight regex=\\w+ substring=hello -}""", + {@snippet : + hello // @highlight regex=\\w+ substring=hello + }""", """ -error: snippet markup: attributes "substring" and "regex" used simultaneously - hello // @highlight regex=\\w+ substring=hello - ^ + error: snippet markup: attributes "substring" and "regex" used simultaneously + hello // @highlight regex=\\w+ substring=hello + ^ """), new TestCase(""" -{@snippet : - hello // @start region="x" name="here" -}""", + {@snippet : + hello // @start region="x" name="here" + }""", """ -error: snippet markup: unexpected attribute - hello // @start region="x" name="here" - ^ + error: snippet markup: unexpected attribute + hello // @start region="x" name="here" + ^ """), new TestCase(""" -{@snippet : - hello // @start region="" -}""", + {@snippet : + hello // @start region="" + }""", """ -error: snippet markup: invalid attribute value - hello // @start region="" - ^ + error: snippet markup: invalid attribute value + hello // @start region="" + ^ """), new TestCase(""" -{@snippet : - hello // @link target="Object#equals()" type=fluffy -}""", + {@snippet : + hello // @link target="Object#equals()" type=fluffy + }""", """ -error: snippet markup: invalid attribute value - hello // @link target="Object#equals()" type=fluffy - ^ + error: snippet markup: invalid attribute value + hello // @link target="Object#equals()" type=fluffy + ^ """), /* ---------------------- */ new TestCase(""" -{@snippet : - hello - there // @highlight substring=" -}""", + {@snippet : + hello + there // @highlight substring=" + }""", """ -error: snippet markup: unterminated attribute value - there // @highlight substring=" - ^ + error: snippet markup: unterminated attribute value + there // @highlight substring=" + ^ """), new TestCase(""" -{@snippet : - hello // @start region="this" - world // @start region="this" - ! // @end -}""", + {@snippet : + hello // @start region="this" + world // @start region="this" + ! // @end + }""", """ -error: snippet markup: duplicated region - world // @start region="this" - ^ + error: snippet markup: duplicated region + world // @start region="this" + ^ """), new TestCase(""" -{@snippet : - hello // @end -}""", + {@snippet : + hello // @end + }""", """ -error: snippet markup: no region to end - hello // @end - ^ + error: snippet markup: no region to end + hello // @end + ^ """), new TestCase(""" -{@snippet : - hello // @start region=this -}""", + {@snippet : + hello // @start region=this + }""", """ -error: snippet markup: unpaired region - hello // @start region=this - ^ + error: snippet markup: unpaired region + hello // @start region=this + ^ """), new TestCase(""" -{@snippet : - hello // @highlight substring="hello" : -}""", + {@snippet : + hello // @highlight substring="hello" : + }""", """ -error: snippet markup: tag refers to non-existent lines - hello // @highlight substring="hello" : - ^ - """) + error: snippet markup: tag refers to non-existent lines + hello // @highlight substring="hello" : + ^ + """) ); List inputs = testCases.stream().map(s -> s.input).toList(); StringBuilder methods = new StringBuilder(); @@ -2493,6 +2544,12 @@ error: snippet markup: tag refers to non-existent lines checkExit(Exit.ERROR); // use the facility from JDK-8273154 when it becomes available checkOutput(Output.OUT, true, testCases.stream().map(TestCase::expectedError).toArray(String[]::new)); + checkOutput("A.html", true, """ +
+ invalid @snippet +
missing attribute "target"
+
+ """); checkNoCrashes(); } } -- GitLab From 5dcdee4bcd337591c79aad8620a7f38345e6e3d9 Mon Sep 17 00:00:00 2001 From: Roland Westrelin Date: Wed, 8 Dec 2021 07:55:12 +0000 Subject: [PATCH 048/671] 8262341: Refine identical code in AddI/LNode. Reviewed-by: thartmann, eliu --- src/hotspot/share/opto/addnode.cpp | 261 +++++++---------------- src/hotspot/share/opto/addnode.hpp | 21 +- src/hotspot/share/opto/castnode.hpp | 13 +- src/hotspot/share/opto/cfgnode.cpp | 2 +- src/hotspot/share/opto/loopPredicate.cpp | 2 +- src/hotspot/share/opto/loopTransform.cpp | 9 +- src/hotspot/share/opto/loopnode.cpp | 12 +- src/hotspot/share/opto/loopnode.hpp | 30 +-- src/hotspot/share/opto/mulnode.cpp | 13 ++ src/hotspot/share/opto/mulnode.hpp | 27 +-- src/hotspot/share/opto/node.hpp | 41 +++- src/hotspot/share/opto/subnode.hpp | 32 --- src/hotspot/share/opto/type.cpp | 24 +++ src/hotspot/share/opto/type.hpp | 12 +- 14 files changed, 185 insertions(+), 314 deletions(-) diff --git a/src/hotspot/share/opto/addnode.cpp b/src/hotspot/share/opto/addnode.cpp index 598deb08ffa..7c27e5c4724 100644 --- a/src/hotspot/share/opto/addnode.cpp +++ b/src/hotspot/share/opto/addnode.cpp @@ -263,66 +263,69 @@ AddNode* AddNode::make(Node* in1, Node* in2, BasicType bt) { //============================================================================= //------------------------------Idealize--------------------------------------- -Node *AddINode::Ideal(PhaseGVN *phase, bool can_reshape) { +Node* AddNode::IdealIL(PhaseGVN* phase, bool can_reshape, BasicType bt) { Node* in1 = in(1); Node* in2 = in(2); int op1 = in1->Opcode(); int op2 = in2->Opcode(); // Fold (con1-x)+con2 into (con1+con2)-x - if ( op1 == Op_AddI && op2 == Op_SubI ) { + if (op1 == Op_Add(bt) && op2 == Op_Sub(bt)) { // Swap edges to try optimizations below in1 = in2; in2 = in(1); op1 = op2; op2 = in2->Opcode(); } - if( op1 == Op_SubI ) { - const Type *t_sub1 = phase->type( in1->in(1) ); - const Type *t_2 = phase->type( in2 ); - if( t_sub1->singleton() && t_2->singleton() && t_sub1 != Type::TOP && t_2 != Type::TOP ) - return new SubINode(phase->makecon( add_ring( t_sub1, t_2 ) ), in1->in(2) ); + if (op1 == Op_Sub(bt)) { + const Type* t_sub1 = phase->type(in1->in(1)); + const Type* t_2 = phase->type(in2 ); + if (t_sub1->singleton() && t_2->singleton() && t_sub1 != Type::TOP && t_2 != Type::TOP) { + return SubNode::make(phase->makecon(add_ring(t_sub1, t_2)), in1->in(2), bt); + } // Convert "(a-b)+(c-d)" into "(a+c)-(b+d)" - if( op2 == Op_SubI ) { + if (op2 == Op_Sub(bt)) { // Check for dead cycle: d = (a-b)+(c-d) assert( in1->in(2) != this && in2->in(2) != this, "dead loop in AddINode::Ideal" ); - Node *sub = new SubINode(NULL, NULL); - sub->init_req(1, phase->transform(new AddINode(in1->in(1), in2->in(1) ) )); - sub->init_req(2, phase->transform(new AddINode(in1->in(2), in2->in(2) ) )); + Node* sub = SubNode::make(NULL, NULL, bt); + sub->init_req(1, phase->transform(AddNode::make(in1->in(1), in2->in(1), bt))); + sub->init_req(2, phase->transform(AddNode::make(in1->in(2), in2->in(2), bt))); return sub; } // Convert "(a-b)+(b+c)" into "(a+c)" - if( op2 == Op_AddI && in1->in(2) == in2->in(1) ) { - assert(in1->in(1) != this && in2->in(2) != this,"dead loop in AddINode::Ideal"); - return new AddINode(in1->in(1), in2->in(2)); + if (op2 == Op_Add(bt) && in1->in(2) == in2->in(1)) { + assert(in1->in(1) != this && in2->in(2) != this,"dead loop in AddINode::Ideal/AddLNode::Ideal"); + return AddNode::make(in1->in(1), in2->in(2), bt); } // Convert "(a-b)+(c+b)" into "(a+c)" - if( op2 == Op_AddI && in1->in(2) == in2->in(2) ) { - assert(in1->in(1) != this && in2->in(1) != this,"dead loop in AddINode::Ideal"); - return new AddINode(in1->in(1), in2->in(1)); + if (op2 == Op_Add(bt) && in1->in(2) == in2->in(2)) { + assert(in1->in(1) != this && in2->in(1) != this,"dead loop in AddINode::Ideal/AddLNode::Ideal"); + return AddNode::make(in1->in(1), in2->in(1), bt); } // Convert "(a-b)+(b-c)" into "(a-c)" - if( op2 == Op_SubI && in1->in(2) == in2->in(1) ) { - assert(in1->in(1) != this && in2->in(2) != this,"dead loop in AddINode::Ideal"); - return new SubINode(in1->in(1), in2->in(2)); + if (op2 == Op_Sub(bt) && in1->in(2) == in2->in(1)) { + assert(in1->in(1) != this && in2->in(2) != this,"dead loop in AddINode::Ideal/AddLNode::Ideal"); + return SubNode::make(in1->in(1), in2->in(2), bt); } // Convert "(a-b)+(c-a)" into "(c-b)" - if( op2 == Op_SubI && in1->in(1) == in2->in(2) ) { - assert(in1->in(2) != this && in2->in(1) != this,"dead loop in AddINode::Ideal"); - return new SubINode(in2->in(1), in1->in(2)); + if (op2 == Op_Sub(bt) && in1->in(1) == in2->in(2)) { + assert(in1->in(2) != this && in2->in(1) != this,"dead loop in AddINode::Ideal/AddLNode::Ideal"); + return SubNode::make(in2->in(1), in1->in(2), bt); } } // Convert "x+(0-y)" into "(x-y)" - if( op2 == Op_SubI && phase->type(in2->in(1)) == TypeInt::ZERO ) - return new SubINode(in1, in2->in(2) ); + if (op2 == Op_Sub(bt) && phase->type(in2->in(1)) == TypeInteger::zero(bt)) { + return SubNode::make(in1, in2->in(2), bt); + } // Convert "(0-y)+x" into "(x-y)" - if( op1 == Op_SubI && phase->type(in1->in(1)) == TypeInt::ZERO ) - return new SubINode( in2, in1->in(2) ); + if (op1 == Op_Sub(bt) && phase->type(in1->in(1)) == TypeInteger::zero(bt)) { + return SubNode::make(in2, in1->in(2), bt); + } // Associative - if (op1 == Op_MulI && op2 == Op_MulI) { + if (op1 == Op_Mul(bt) && op2 == Op_Mul(bt)) { Node* add_in1 = NULL; Node* add_in2 = NULL; Node* mul_in = NULL; @@ -350,49 +353,26 @@ Node *AddINode::Ideal(PhaseGVN *phase, bool can_reshape) { } if (mul_in != NULL) { - Node* add = phase->transform(new AddINode(add_in1, add_in2)); - return new MulINode(mul_in, add); - } - } - - // Convert (x>>>z)+y into (x+(y<>>z for small constant z and y. - // Helps with array allocation math constant folding - // See 4790063: - // Unrestricted transformation is unsafe for some runtime values of 'x' - // ( x == 0, z == 1, y == -1 ) fails - // ( x == -5, z == 1, y == 1 ) fails - // Transform works for small z and small negative y when the addition - // (x + (y << z)) does not cross zero. - // Implement support for negative y and (x >= -(y << z)) - // Have not observed cases where type information exists to support - // positive y and (x <= -(y << z)) - if( op1 == Op_URShiftI && op2 == Op_ConI && - in1->in(2)->Opcode() == Op_ConI ) { - jint z = phase->type( in1->in(2) )->is_int()->get_con() & 0x1f; // only least significant 5 bits matter - jint y = phase->type( in2 )->is_int()->get_con(); - - if( z < 5 && -5 < y && y < 0 ) { - const Type *t_in11 = phase->type(in1->in(1)); - if( t_in11 != Type::TOP && (t_in11->is_int()->_lo >= -(y << z)) ) { - Node *a = phase->transform( new AddINode( in1->in(1), phase->intcon(y<in(2) ); - } + Node* add = phase->transform(AddNode::make(add_in1, add_in2, bt)); + return MulNode::make(mul_in, add, bt); } } // Convert (x >>> rshift) + (x << lshift) into RotateRight(x, rshift) if (Matcher::match_rule_supported(Op_RotateRight) && - ((op1 == Op_URShiftI && op2 == Op_LShiftI) || (op1 == Op_LShiftI && op2 == Op_URShiftI)) && + ((op1 == Op_URShift(bt) && op2 == Op_LShift(bt)) || (op1 == Op_LShift(bt) && op2 == Op_URShift(bt))) && in1->in(1) != NULL && in1->in(1) == in2->in(1)) { - Node* rshift = op1 == Op_URShiftI ? in1->in(2) : in2->in(2); - Node* lshift = op1 == Op_URShiftI ? in2->in(2) : in1->in(2); + Node* rshift = op1 == Op_URShift(bt) ? in1->in(2) : in2->in(2); + Node* lshift = op1 == Op_URShift(bt) ? in2->in(2) : in1->in(2); if (rshift != NULL && lshift != NULL) { const TypeInt* rshift_t = phase->type(rshift)->isa_int(); const TypeInt* lshift_t = phase->type(lshift)->isa_int(); + int bits = bt == T_INT ? 32 : 64; + int mask = bt == T_INT ? 0x1F : 0x3F; if (lshift_t != NULL && lshift_t->is_con() && rshift_t != NULL && rshift_t->is_con() && - ((lshift_t->get_con() & 0x1F) == (32 - (rshift_t->get_con() & 0x1F)))) { - return new RotateRightNode(in1->in(1), phase->intcon(rshift_t->get_con() & 0x1F), TypeInt::INT); + ((lshift_t->get_con() & mask) == (bits - (rshift_t->get_con() & mask)))) { + return new RotateRightNode(in1->in(1), phase->intcon(rshift_t->get_con() & mask), TypeInteger::bottom(bt)); } } } @@ -400,14 +380,49 @@ Node *AddINode::Ideal(PhaseGVN *phase, bool can_reshape) { // Convert (~x+1) into -x. Note there isn't a bitwise not bytecode, // "~x" would typically represented as "x^(-1)", so (~x+1) will // be (x^(-1))+1. - if (op1 == Op_XorI && phase->type(in2) == TypeInt::ONE && - phase->type(in1->in(2)) == TypeInt::MINUS_1) { - return new SubINode(phase->makecon(TypeInt::ZERO), in1->in(1)); + if (op1 == Op_Xor(bt) && phase->type(in2) == TypeInteger::one(bt) && + phase->type(in1->in(2)) == TypeInteger::minus_1(bt)) { + return SubNode::make(phase->makecon(TypeInteger::zero(bt)), in1->in(1), bt); } return AddNode::Ideal(phase, can_reshape); } +Node* AddINode::Ideal(PhaseGVN* phase, bool can_reshape) { + Node* in1 = in(1); + Node* in2 = in(2); + int op1 = in1->Opcode(); + int op2 = in2->Opcode(); + + // Convert (x>>>z)+y into (x+(y<>>z for small constant z and y. + // Helps with array allocation math constant folding + // See 4790063: + // Unrestricted transformation is unsafe for some runtime values of 'x' + // ( x == 0, z == 1, y == -1 ) fails + // ( x == -5, z == 1, y == 1 ) fails + // Transform works for small z and small negative y when the addition + // (x + (y << z)) does not cross zero. + // Implement support for negative y and (x >= -(y << z)) + // Have not observed cases where type information exists to support + // positive y and (x <= -(y << z)) + if (op1 == Op_URShiftI && op2 == Op_ConI && + in1->in(2)->Opcode() == Op_ConI) { + jint z = phase->type(in1->in(2))->is_int()->get_con() & 0x1f; // only least significant 5 bits matter + jint y = phase->type(in2)->is_int()->get_con(); + + if (z < 5 && -5 < y && y < 0) { + const Type* t_in11 = phase->type(in1->in(1)); + if( t_in11 != Type::TOP && (t_in11->is_int()->_lo >= -(y << z))) { + Node* a = phase->transform(new AddINode( in1->in(1), phase->intcon(y<in(2)); + } + } + } + + return AddNode::IdealIL(phase, can_reshape, T_INT); +} + + //------------------------------Identity--------------------------------------- // Fold (x-y)+y OR y+(x-y) into x Node* AddINode::Identity(PhaseGVN* phase) { @@ -451,124 +466,8 @@ const Type *AddINode::add_ring( const Type *t0, const Type *t1 ) const { //============================================================================= //------------------------------Idealize--------------------------------------- -Node *AddLNode::Ideal(PhaseGVN *phase, bool can_reshape) { - Node* in1 = in(1); - Node* in2 = in(2); - int op1 = in1->Opcode(); - int op2 = in2->Opcode(); - // Fold (con1-x)+con2 into (con1+con2)-x - if ( op1 == Op_AddL && op2 == Op_SubL ) { - // Swap edges to try optimizations below - in1 = in2; - in2 = in(1); - op1 = op2; - op2 = in2->Opcode(); - } - // Fold (con1-x)+con2 into (con1+con2)-x - if( op1 == Op_SubL ) { - const Type *t_sub1 = phase->type( in1->in(1) ); - const Type *t_2 = phase->type( in2 ); - if( t_sub1->singleton() && t_2->singleton() && t_sub1 != Type::TOP && t_2 != Type::TOP ) - return new SubLNode(phase->makecon( add_ring( t_sub1, t_2 ) ), in1->in(2) ); - // Convert "(a-b)+(c-d)" into "(a+c)-(b+d)" - if( op2 == Op_SubL ) { - // Check for dead cycle: d = (a-b)+(c-d) - assert( in1->in(2) != this && in2->in(2) != this, - "dead loop in AddLNode::Ideal" ); - Node *sub = new SubLNode(NULL, NULL); - sub->init_req(1, phase->transform(new AddLNode(in1->in(1), in2->in(1) ) )); - sub->init_req(2, phase->transform(new AddLNode(in1->in(2), in2->in(2) ) )); - return sub; - } - // Convert "(a-b)+(b+c)" into "(a+c)" - if( op2 == Op_AddL && in1->in(2) == in2->in(1) ) { - assert(in1->in(1) != this && in2->in(2) != this,"dead loop in AddLNode::Ideal"); - return new AddLNode(in1->in(1), in2->in(2)); - } - // Convert "(a-b)+(c+b)" into "(a+c)" - if( op2 == Op_AddL && in1->in(2) == in2->in(2) ) { - assert(in1->in(1) != this && in2->in(1) != this,"dead loop in AddLNode::Ideal"); - return new AddLNode(in1->in(1), in2->in(1)); - } - // Convert "(a-b)+(b-c)" into "(a-c)" - if( op2 == Op_SubL && in1->in(2) == in2->in(1) ) { - assert(in1->in(1) != this && in2->in(2) != this,"dead loop in AddLNode::Ideal"); - return new SubLNode(in1->in(1), in2->in(2)); - } - // Convert "(a-b)+(c-a)" into "(c-b)" - if( op2 == Op_SubL && in1->in(1) == in2->in(2) ) { - assert(in1->in(2) != this && in2->in(1) != this,"dead loop in AddLNode::Ideal"); - return new SubLNode(in2->in(1), in1->in(2)); - } - } - - // Convert "x+(0-y)" into "(x-y)" - if( op2 == Op_SubL && phase->type(in2->in(1)) == TypeLong::ZERO ) - return new SubLNode( in1, in2->in(2) ); - - // Convert "(0-y)+x" into "(x-y)" - if( op1 == Op_SubL && phase->type(in1->in(1)) == TypeLong::ZERO ) - return new SubLNode( in2, in1->in(2) ); - - // Associative - if (op1 == Op_MulL && op2 == Op_MulL) { - Node* add_in1 = NULL; - Node* add_in2 = NULL; - Node* mul_in = NULL; - - if (in1->in(1) == in2->in(1)) { - // Convert "a*b+a*c into a*(b+c) - add_in1 = in1->in(2); - add_in2 = in2->in(2); - mul_in = in1->in(1); - } else if (in1->in(2) == in2->in(1)) { - // Convert a*b+b*c into b*(a+c) - add_in1 = in1->in(1); - add_in2 = in2->in(2); - mul_in = in1->in(2); - } else if (in1->in(2) == in2->in(2)) { - // Convert a*c+b*c into (a+b)*c - add_in1 = in1->in(1); - add_in2 = in2->in(1); - mul_in = in1->in(2); - } else if (in1->in(1) == in2->in(2)) { - // Convert a*b+c*a into a*(b+c) - add_in1 = in1->in(2); - add_in2 = in2->in(1); - mul_in = in1->in(1); - } - - if (mul_in != NULL) { - Node* add = phase->transform(new AddLNode(add_in1, add_in2)); - return new MulLNode(mul_in, add); - } - } - - // Convert (x >>> rshift) + (x << lshift) into RotateRight(x, rshift) - if (Matcher::match_rule_supported(Op_RotateRight) && - ((op1 == Op_URShiftL && op2 == Op_LShiftL) || (op1 == Op_LShiftL && op2 == Op_URShiftL)) && - in1->in(1) != NULL && in1->in(1) == in2->in(1)) { - Node* rshift = op1 == Op_URShiftL ? in1->in(2) : in2->in(2); - Node* lshift = op1 == Op_URShiftL ? in2->in(2) : in1->in(2); - if (rshift != NULL && lshift != NULL) { - const TypeInt* rshift_t = phase->type(rshift)->isa_int(); - const TypeInt* lshift_t = phase->type(lshift)->isa_int(); - if (lshift_t != NULL && lshift_t->is_con() && - rshift_t != NULL && rshift_t->is_con() && - ((lshift_t->get_con() & 0x3F) == (64 - (rshift_t->get_con() & 0x3F)))) { - return new RotateRightNode(in1->in(1), phase->intcon(rshift_t->get_con() & 0x3F), TypeLong::LONG); - } - } - } - - // Convert (~x+1) into -x. Note there isn't a bitwise not bytecode, - // "~x" would typically represented as "x^(-1)", so (~x+1) will - // be (x^(-1))+1 - if (op1 == Op_XorL && phase->type(in2) == TypeLong::ONE && - phase->type(in1->in(2)) == TypeLong::MINUS_1) { - return new SubLNode(phase->makecon(TypeLong::ZERO), in1->in(1)); - } - return AddNode::Ideal(phase, can_reshape); +Node* AddLNode::Ideal(PhaseGVN* phase, bool can_reshape) { + return AddNode::IdealIL(phase, can_reshape, T_LONG); } diff --git a/src/hotspot/share/opto/addnode.hpp b/src/hotspot/share/opto/addnode.hpp index 132d796aea4..1e9c3a8b1df 100644 --- a/src/hotspot/share/opto/addnode.hpp +++ b/src/hotspot/share/opto/addnode.hpp @@ -51,7 +51,8 @@ public: // We also canonicalize the Node, moving constants to the right input, // and flatten expressions (so that 1+x+2 becomes x+3). - virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); + virtual Node* Ideal(PhaseGVN* phase, bool can_reshape); + Node* IdealIL(PhaseGVN* phase, bool can_reshape, BasicType bt); // Compute a new Type for this node. Basically we just do the pre-check, // then call the virtual add() to set the type. @@ -74,10 +75,6 @@ public: // Supplied function to return the multiplicative opcode virtual int min_opcode() const = 0; - virtual bool operates_on(BasicType bt, bool signed_int) const { - assert(bt == T_INT || bt == T_LONG, "unsupported"); - return false; - } static AddNode* make(Node* in1, Node* in2, BasicType bt); }; @@ -92,12 +89,9 @@ public: virtual const Type *bottom_type() const { return TypeInt::INT; } int max_opcode() const { return Op_MaxI; } int min_opcode() const { return Op_MinI; } - virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); + virtual Node* Ideal(PhaseGVN* phase, bool can_reshape); virtual Node* Identity(PhaseGVN* phase); - virtual bool operates_on(BasicType bt, bool signed_int) const { - assert(bt == T_INT || bt == T_LONG, "unsupported"); - return bt == T_INT; - } + virtual uint ideal_reg() const { return Op_RegI; } }; @@ -112,12 +106,9 @@ public: virtual const Type *bottom_type() const { return TypeLong::LONG; } int max_opcode() const { return Op_MaxL; } int min_opcode() const { return Op_MinL; } - virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); + virtual Node* Ideal(PhaseGVN* phase, bool can_reshape); virtual Node* Identity(PhaseGVN* phase); - virtual bool operates_on(BasicType bt, bool signed_int) const { - assert(bt == T_INT || bt == T_LONG, "unsupported"); - return bt == T_LONG; - } + virtual uint ideal_reg() const { return Op_RegL; } }; diff --git a/src/hotspot/share/opto/castnode.hpp b/src/hotspot/share/opto/castnode.hpp index 2aa318c0e24..ae4cf418945 100644 --- a/src/hotspot/share/opto/castnode.hpp +++ b/src/hotspot/share/opto/castnode.hpp @@ -60,10 +60,6 @@ public: TypeNode* dominating_cast(PhaseGVN* gvn, PhaseTransform* pt) const; static Node* make_cast(int opcode, Node* c, Node *n, const Type *t, DependencyType dependency); static Node* make(Node* c, Node *n, const Type *t, BasicType bt); - virtual bool operates_on(BasicType bt, bool signed_int) const { - assert(bt == T_INT || bt == T_LONG, "unsupported"); - return false; - } #ifndef PRODUCT virtual void dump_spec(outputStream *st) const; @@ -104,10 +100,6 @@ class CastIINode: public ConstraintCastNode { return false; #endif } - virtual bool operates_on(BasicType bt, bool signed_int) const { - assert(bt == T_INT || bt == T_LONG, "unsupported"); - return bt == T_INT; - } #ifndef PRODUCT virtual void dump_spec(outputStream* st) const; @@ -125,10 +117,7 @@ public: : ConstraintCastNode(n, t, dependency){ init_class_id(Class_CastLL); } - virtual bool operates_on(BasicType bt, bool signed_int) const { - assert(bt == T_INT || bt == T_LONG, "unsupported"); - return bt == T_LONG; - } + virtual int Opcode() const; virtual uint ideal_reg() const { return Op_RegL; } }; diff --git a/src/hotspot/share/opto/cfgnode.cpp b/src/hotspot/share/opto/cfgnode.cpp index 64bf4b7f582..e583dd9deec 100644 --- a/src/hotspot/share/opto/cfgnode.cpp +++ b/src/hotspot/share/opto/cfgnode.cpp @@ -2521,7 +2521,7 @@ bool PhiNode::is_data_loop(RegionNode* r, Node* uin, const PhaseGVN* phase) { //------------------------------is_tripcount----------------------------------- bool PhiNode::is_tripcount(BasicType bt) const { return (in(0) != NULL && in(0)->is_BaseCountedLoop() && - in(0)->as_BaseCountedLoop()->operates_on(bt, true) && + in(0)->as_BaseCountedLoop()->bt() == bt && in(0)->as_BaseCountedLoop()->phi() == this); } diff --git a/src/hotspot/share/opto/loopPredicate.cpp b/src/hotspot/share/opto/loopPredicate.cpp index 279edf25046..c0396bbe95d 100644 --- a/src/hotspot/share/opto/loopPredicate.cpp +++ b/src/hotspot/share/opto/loopPredicate.cpp @@ -741,7 +741,7 @@ bool IdealLoopTree::is_range_check_if(IfNode *iff, PhaseIdealLoop *phase, BasicT return false; } const CmpNode *cmp = bol->in(1)->as_Cmp(); - if (!(cmp->is_Cmp() && cmp->operates_on(bt, false))) { + if (cmp->Opcode() != Op_Cmp_unsigned(bt)) { return false; } range = cmp->in(2); diff --git a/src/hotspot/share/opto/loopTransform.cpp b/src/hotspot/share/opto/loopTransform.cpp index 00147d54ec7..0b2b58c50b8 100644 --- a/src/hotspot/share/opto/loopTransform.cpp +++ b/src/hotspot/share/opto/loopTransform.cpp @@ -2521,7 +2521,7 @@ bool PhaseIdealLoop::is_scaled_iv(Node* exp, Node* iv, jlong* p_scale, BasicType } int opc = exp->Opcode(); // Can't use is_Mul() here as it's true for AndI and AndL - if ((opc == Op_MulI || opc == Op_MulL) && exp->operates_on(bt, true)) { + if (opc == Op_Mul(bt)) { if (exp->in(1)->uncast() == iv && exp->in(2)->is_Con()) { if (p_scale != NULL) { *p_scale = exp->in(2)->get_integer_as_long(bt); @@ -2534,7 +2534,7 @@ bool PhaseIdealLoop::is_scaled_iv(Node* exp, Node* iv, jlong* p_scale, BasicType } return true; } - } else if (exp->is_LShift() && exp->operates_on(bt, true)) { + } else if (opc == Op_LShift(bt)) { if (exp->in(1)->uncast() == iv && exp->in(2)->is_Con()) { if (p_scale != NULL) { jint shift_amount = exp->in(2)->get_int(); @@ -2563,7 +2563,8 @@ bool PhaseIdealLoop::is_scaled_iv_plus_offset(Node* exp, Node* iv, jlong* p_scal return true; } exp = exp->uncast(); - if (exp->is_Add() && exp->operates_on(bt, true)) { + int opc = exp->Opcode(); + if (opc == Op_Add(bt)) { if (is_scaled_iv(exp->in(1), iv, p_scale, bt)) { if (p_offset != NULL) { *p_offset = exp->in(2); @@ -2590,7 +2591,7 @@ bool PhaseIdealLoop::is_scaled_iv_plus_offset(Node* exp, Node* iv, jlong* p_scal return true; } } - } else if (exp->is_Sub() && exp->operates_on(bt, true)) { + } else if (opc == Op_Sub(bt)) { if (is_scaled_iv(exp->in(1), iv, p_scale, bt)) { if (p_offset != NULL) { Node *zero = _igvn.integercon(0, bt); diff --git a/src/hotspot/share/opto/loopnode.cpp b/src/hotspot/share/opto/loopnode.cpp index 3e150b9cb94..46e675ae239 100644 --- a/src/hotspot/share/opto/loopnode.cpp +++ b/src/hotspot/share/opto/loopnode.cpp @@ -71,7 +71,7 @@ void LoopNode::dump_spec(outputStream *st) const { //------------------------------is_valid_counted_loop------------------------- bool LoopNode::is_valid_counted_loop(BasicType bt) const { - if (is_BaseCountedLoop() && operates_on(bt, false)) { + if (is_BaseCountedLoop() && as_BaseCountedLoop()->bt() == bt) { BaseCountedLoopNode* l = as_BaseCountedLoop(); BaseCountedLoopEndNode* le = l->loopexit_or_null(); if (le != NULL && @@ -1433,12 +1433,12 @@ bool PhaseIdealLoop::is_counted_loop(Node* x, IdealLoopTree*&loop, BasicType iv_ Node* incr = NULL; Node* limit = NULL; Node* cmp = loop_exit_test(back_control, loop, incr, limit, bt, cl_prob); - if (cmp == NULL || !(cmp->is_Cmp() && cmp->operates_on(iv_bt, true))) { + if (cmp == NULL || cmp->Opcode() != Op_Cmp(iv_bt)) { return false; // Avoid pointer & float & 64-bit compares } // Trip-counter increment must be commutative & associative. - if (incr->is_ConstraintCast() && incr->operates_on(iv_bt, false)) { + if (incr->Opcode() == Op_Cast(iv_bt)) { incr = incr->in(1); } @@ -1455,7 +1455,7 @@ bool PhaseIdealLoop::is_counted_loop(Node* x, IdealLoopTree*&loop, BasicType iv_ if (!(incr = CountedLoopNode::match_incr_with_optional_truncation(incr, &trunc1, &trunc2, &iv_trunc_t, iv_bt))) { return false; // Funny increment opcode } - assert(incr->is_Add() && incr->operates_on(iv_bt, false), "wrong increment code"); + assert(incr->Opcode() == Op_Add(iv_bt), "wrong increment code"); Node* xphi = NULL; Node* stride = loop_iv_stride(incr, loop, xphi); @@ -1464,7 +1464,7 @@ bool PhaseIdealLoop::is_counted_loop(Node* x, IdealLoopTree*&loop, BasicType iv_ return false; } - if (xphi->is_ConstraintCast() && xphi->operates_on(iv_bt, false)) { + if (xphi->Opcode() == Op_Cast(iv_bt)) { xphi = xphi->in(1); } @@ -2272,7 +2272,7 @@ Node* CountedLoopNode::match_incr_with_optional_truncation(Node* expr, Node** tr } // If (maybe after stripping) it is an AddI, we won: - if (n1->is_Add() && n1->operates_on(bt, true)) { + if (n1op == Op_Add(bt)) { *trunc1 = t1; *trunc2 = t2; *trunc_type = trunc_t; diff --git a/src/hotspot/share/opto/loopnode.hpp b/src/hotspot/share/opto/loopnode.hpp index 1fee41ba62a..4cca7ab45da 100644 --- a/src/hotspot/share/opto/loopnode.hpp +++ b/src/hotspot/share/opto/loopnode.hpp @@ -215,10 +215,6 @@ public: BaseCountedLoopEndNode* loopexit() const; virtual BasicType bt() const = 0; - virtual bool operates_on(BasicType bt, bool signed_int) const { - assert(bt == T_INT || bt == T_LONG, "unsupported"); - return false; - } static BaseCountedLoopNode* make(Node* entry, Node* backedge, BasicType bt); }; @@ -342,10 +338,6 @@ public: static Node* skip_predicates_from_entry(Node* ctrl); Node* skip_predicates(); - virtual bool operates_on(BasicType bt, bool signed_int) const { - assert(bt == T_INT || bt == T_LONG, "unsupported"); - return bt == T_INT; - } virtual BasicType bt() const { return T_INT; } @@ -366,11 +358,6 @@ public: virtual int Opcode() const; - virtual bool operates_on(BasicType bt, bool signed_int) const { - assert(bt == T_INT || bt == T_LONG, "unsupported"); - return bt == T_LONG; - } - virtual BasicType bt() const { return T_LONG; } @@ -423,17 +410,13 @@ public: if (!ln->is_BaseCountedLoop() || ln->as_BaseCountedLoop()->loopexit_or_null() != this) { return NULL; } - if (!ln->operates_on(bt(), true)) { + if (ln->as_BaseCountedLoop()->bt() != bt()) { return NULL; } return ln->as_BaseCountedLoop(); } BoolTest::mask test_trip() const { return in(TestValue)->as_Bool()->_test._test; } - virtual bool operates_on(BasicType bt, bool signed_int) const { - assert(bt == T_INT || bt == T_LONG, "unsupported"); - return false; - } jlong stride_con() const; virtual BasicType bt() const = 0; @@ -453,10 +436,6 @@ public: CountedLoopNode* loopnode() const { return (CountedLoopNode*) BaseCountedLoopEndNode::loopnode(); } - virtual bool operates_on(BasicType bt, bool signed_int) const { - assert(bt == T_INT || bt == T_LONG, "unsupported"); - return bt == T_INT; - } virtual BasicType bt() const { return T_INT; @@ -477,10 +456,7 @@ public: LongCountedLoopNode* loopnode() const { return (LongCountedLoopNode*) BaseCountedLoopEndNode::loopnode(); } - virtual bool operates_on(BasicType bt, bool signed_int) const { - assert(bt == T_INT || bt == T_LONG, "unsupported"); - return bt == T_LONG; - } + virtual int Opcode() const; virtual BasicType bt() const { @@ -498,7 +474,7 @@ inline BaseCountedLoopEndNode* BaseCountedLoopNode::loopexit_or_null() const { return NULL; } BaseCountedLoopEndNode* result = lexit->as_BaseCountedLoopEnd(); - if (!result->operates_on(bt(), true)) { + if (result->bt() != bt()) { return NULL; } return result; diff --git a/src/hotspot/share/opto/mulnode.cpp b/src/hotspot/share/opto/mulnode.cpp index 4c999ea5524..a45ad23f6c1 100644 --- a/src/hotspot/share/opto/mulnode.cpp +++ b/src/hotspot/share/opto/mulnode.cpp @@ -222,6 +222,19 @@ const Type* MulNode::Value(PhaseGVN* phase) const { return mul_ring(t1,t2); // Local flavor of type multiplication } +MulNode* MulNode::make(Node* in1, Node* in2, BasicType bt) { + switch (bt) { + case T_INT: + return new MulINode(in1, in2); + case T_LONG: + return new MulLNode(in1, in2); + default: + fatal("Not implemented for %s", type2name(bt)); + } + return NULL; +} + + //============================================================================= //------------------------------Ideal------------------------------------------ // Check for power-of-2 multiply, then try the regular MulNode::Ideal diff --git a/src/hotspot/share/opto/mulnode.hpp b/src/hotspot/share/opto/mulnode.hpp index 25bd6ebf150..3c7f27910a7 100644 --- a/src/hotspot/share/opto/mulnode.hpp +++ b/src/hotspot/share/opto/mulnode.hpp @@ -75,16 +75,13 @@ public: // Supplied function to return the multiplicative opcode virtual int mul_opcode() const = 0; - virtual bool operates_on(BasicType bt, bool signed_int) const { - assert(bt == T_INT || bt == T_LONG, "unsupported"); - return false; - } - // Supplied function to return the additive opcode virtual int max_opcode() const = 0; // Supplied function to return the multiplicative opcode virtual int min_opcode() const = 0; + + static MulNode* make(Node* in1, Node* in2, BasicType bt); }; //------------------------------MulINode--------------------------------------- @@ -103,10 +100,6 @@ public: int min_opcode() const { return Op_MinI; } const Type *bottom_type() const { return TypeInt::INT; } virtual uint ideal_reg() const { return Op_RegI; } - virtual bool operates_on(BasicType bt, bool signed_int) const { - assert(bt == T_INT || bt == T_LONG, "unsupported"); - return bt == T_INT; - } }; //------------------------------MulLNode--------------------------------------- @@ -125,10 +118,6 @@ public: int min_opcode() const { return Op_MinL; } const Type *bottom_type() const { return TypeLong::LONG; } virtual uint ideal_reg() const { return Op_RegL; } - virtual bool operates_on(BasicType bt, bool signed_int) const { - assert(bt == T_INT || bt == T_LONG, "unsupported"); - return bt == T_LONG; - } }; @@ -234,10 +223,6 @@ public: LShiftNode(Node *in1, Node *in2) : Node(NULL,in1,in2) { init_class_id(Class_LShift); } - virtual bool operates_on(BasicType bt, bool signed_int) const { - assert(bt == T_INT || bt == T_LONG, "unsupported"); - return false; - } }; //------------------------------LShiftINode------------------------------------ @@ -251,10 +236,6 @@ public: virtual const Type* Value(PhaseGVN* phase) const; const Type *bottom_type() const { return TypeInt::INT; } virtual uint ideal_reg() const { return Op_RegI; } - virtual bool operates_on(BasicType bt, bool signed_int) const { - assert(bt == T_INT || bt == T_LONG, "unsupported"); - return bt == T_INT; - } }; //------------------------------LShiftLNode------------------------------------ @@ -268,10 +249,6 @@ public: virtual const Type* Value(PhaseGVN* phase) const; const Type *bottom_type() const { return TypeLong::LONG; } virtual uint ideal_reg() const { return Op_RegL; } - virtual bool operates_on(BasicType bt, bool signed_int) const { - assert(bt == T_INT || bt == T_LONG, "unsupported"); - return bt == T_LONG; - } }; diff --git a/src/hotspot/share/opto/node.hpp b/src/hotspot/share/opto/node.hpp index 94fd6ac3385..79fbf805fda 100644 --- a/src/hotspot/share/opto/node.hpp +++ b/src/hotspot/share/opto/node.hpp @@ -1265,12 +1265,6 @@ public: uint _del_tick; // Bumped when a deletion happens.. #endif #endif -public: - virtual bool operates_on(BasicType bt, bool signed_int) const { - assert(bt == T_INT || bt == T_LONG, "unsupported"); - Unimplemented(); - return false; - } }; inline bool not_a_node(const Node* n) { @@ -1835,4 +1829,39 @@ public: #endif }; +#include "opto/opcodes.hpp" + +#define Op_IL(op) \ + inline int Op_ ## op(BasicType bt) { \ + assert(bt == T_INT || bt == T_LONG, "only for int or longs"); \ + if (bt == T_INT) { \ + return Op_## op ## I; \ + } \ + return Op_## op ## L; \ +} + +Op_IL(Add) +Op_IL(Sub) +Op_IL(Mul) +Op_IL(URShift) +Op_IL(LShift) +Op_IL(Xor) +Op_IL(Cmp) + +inline int Op_Cmp_unsigned(BasicType bt) { + assert(bt == T_INT || bt == T_LONG, "only for int or longs"); + if (bt == T_INT) { + return Op_CmpU; + } + return Op_CmpUL; +} + +inline int Op_Cast(BasicType bt) { + assert(bt == T_INT || bt == T_LONG, "only for int or longs"); + if (bt == T_INT) { + return Op_CastII; + } + return Op_CastLL; +} + #endif // SHARE_OPTO_NODE_HPP diff --git a/src/hotspot/share/opto/subnode.hpp b/src/hotspot/share/opto/subnode.hpp index 281b28237c8..398b219e646 100644 --- a/src/hotspot/share/opto/subnode.hpp +++ b/src/hotspot/share/opto/subnode.hpp @@ -62,10 +62,6 @@ public: virtual const Type *add_id() const = 0; static SubNode* make(Node* in1, Node* in2, BasicType bt); - virtual bool operates_on(BasicType bt, bool signed_int) const { - assert(bt == T_INT || bt == T_LONG, "unsupported"); - return false; - } }; @@ -81,10 +77,6 @@ public: const Type *add_id() const { return TypeInt::ZERO; } const Type *bottom_type() const { return TypeInt::INT; } virtual uint ideal_reg() const { return Op_RegI; } - virtual bool operates_on(BasicType bt, bool signed_int) const { - assert(bt == T_INT || bt == T_LONG, "unsupported"); - return bt == T_INT; - } }; //------------------------------SubLNode--------------------------------------- @@ -98,10 +90,6 @@ public: const Type *add_id() const { return TypeLong::ZERO; } const Type *bottom_type() const { return TypeLong::LONG; } virtual uint ideal_reg() const { return Op_RegL; } - virtual bool operates_on(BasicType bt, bool signed_int) const { - assert(bt == T_INT || bt == T_LONG, "unsupported"); - return bt == T_LONG; - } }; // NOTE: SubFPNode should be taken away and replaced by add and negate @@ -162,10 +150,6 @@ public: // including eventual control nodes and their projections. virtual void related(GrowableArray *in_rel, GrowableArray *out_rel, bool compact) const; #endif - virtual bool operates_on(BasicType bt, bool signed_int) const { - assert(bt == T_INT || bt == T_LONG, "unsupported"); - return false; - } }; //------------------------------CmpINode--------------------------------------- @@ -176,10 +160,6 @@ public: virtual int Opcode() const; virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); virtual const Type *sub( const Type *, const Type * ) const; - virtual bool operates_on(BasicType bt, bool signed_int) const { - assert(bt == T_INT || bt == T_LONG, "unsupported"); - return bt == T_INT && signed_int; - } }; //------------------------------CmpUNode--------------------------------------- @@ -191,10 +171,6 @@ public: virtual const Type *sub( const Type *, const Type * ) const; const Type* Value(PhaseGVN* phase) const; bool is_index_range_check() const; - virtual bool operates_on(BasicType bt, bool signed_int) const { - assert(bt == T_INT || bt == T_LONG, "unsupported"); - return bt == T_INT && !signed_int; - } }; //------------------------------CmpPNode--------------------------------------- @@ -225,10 +201,6 @@ public: virtual int Opcode() const; virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); virtual const Type *sub( const Type *, const Type * ) const; - virtual bool operates_on(BasicType bt, bool signed_int) const { - assert(bt == T_INT || bt == T_LONG, "unsupported"); - return bt == T_LONG && signed_int; - } }; //------------------------------CmpULNode--------------------------------------- @@ -238,10 +210,6 @@ public: CmpULNode(Node* in1, Node* in2) : CmpNode(in1, in2) { } virtual int Opcode() const; virtual const Type* sub(const Type*, const Type*) const; - virtual bool operates_on(BasicType bt, bool signed_int) const { - assert(bt == T_INT || bt == T_LONG, "unsupported"); - return bt == T_LONG && !signed_int; - } }; //------------------------------CmpL3Node-------------------------------------- diff --git a/src/hotspot/share/opto/type.cpp b/src/hotspot/share/opto/type.cpp index 56e5c54ef18..5484406beb0 100644 --- a/src/hotspot/share/opto/type.cpp +++ b/src/hotspot/share/opto/type.cpp @@ -1413,6 +1413,30 @@ const TypeInteger* TypeInteger::bottom(BasicType bt) { return TypeLong::LONG; } +const TypeInteger* TypeInteger::zero(BasicType bt) { + if (bt == T_INT) { + return TypeInt::ZERO; + } + assert(bt == T_LONG, "basic type not an int or long"); + return TypeLong::ZERO; +} + +const TypeInteger* TypeInteger::one(BasicType bt) { + if (bt == T_INT) { + return TypeInt::ONE; + } + assert(bt == T_LONG, "basic type not an int or long"); + return TypeLong::ONE; +} + +const TypeInteger* TypeInteger::minus_1(BasicType bt) { + if (bt == T_INT) { + return TypeInt::MINUS_1; + } + assert(bt == T_LONG, "basic type not an int or long"); + return TypeLong::MINUS_1; +} + //============================================================================= // Convience common pre-built types. const TypeInt *TypeInt::MAX; // INT_MAX diff --git a/src/hotspot/share/opto/type.hpp b/src/hotspot/share/opto/type.hpp index 754e0c0adc6..f525a75b14e 100644 --- a/src/hotspot/share/opto/type.hpp +++ b/src/hotspot/share/opto/type.hpp @@ -558,10 +558,14 @@ public: virtual jlong hi_as_long() const = 0; virtual jlong lo_as_long() const = 0; jlong get_con_as_long(BasicType bt) const; + bool is_con() const { return lo_as_long() == hi_as_long(); } static const TypeInteger* make(jlong lo, jlong hi, int w, BasicType bt); static const TypeInteger* bottom(BasicType type); + static const TypeInteger* zero(BasicType type); + static const TypeInteger* one(BasicType type); + static const TypeInteger* minus_1(BasicType type); }; @@ -588,9 +592,9 @@ public: static const TypeInt *make(jint lo, jint hi, int w); // Check for single integer - int is_con() const { return _lo==_hi; } + bool is_con() const { return _lo==_hi; } bool is_con(int i) const { return is_con() && _lo == i; } - jint get_con() const { assert( is_con(), "" ); return _lo; } + jint get_con() const { assert(is_con(), "" ); return _lo; } virtual bool is_finite() const; // Has a finite value @@ -656,9 +660,9 @@ public: static const TypeLong *make(jlong lo, jlong hi, int w); // Check for single integer - int is_con() const { return _lo==_hi; } + bool is_con() const { return _lo==_hi; } bool is_con(int i) const { return is_con() && _lo == i; } - jlong get_con() const { assert( is_con(), "" ); return _lo; } + jlong get_con() const { assert(is_con(), "" ); return _lo; } // Check for positive 32-bit value. int is_positive_int() const { return _lo >= 0 && _hi <= (jlong)max_jint; } -- GitLab From 10e0318ff7289b248289a70a56adeff3c257de04 Mon Sep 17 00:00:00 2001 From: Julia Boes Date: Wed, 8 Dec 2021 09:16:44 +0000 Subject: [PATCH 049/671] 8278158: jwebserver should set request timeout Reviewed-by: dfuchs, michaelm --- .../httpserver/simpleserver/JWebServer.java | 21 ++++++++++++++----- .../sun/net/httpserver/simpleserver/Main.java | 21 ++++++++++++++----- 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/JWebServer.java b/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/JWebServer.java index c338e4844e6..59f77abbae8 100644 --- a/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/JWebServer.java +++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/JWebServer.java @@ -28,11 +28,6 @@ import static java.nio.charset.StandardCharsets.UTF_8; /** * Programmatic entry point to start the jwebserver tool. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interface are subject to change or deletion - * without notice. */ public class JWebServer { @@ -51,11 +46,18 @@ public class JWebServer { * or an I/O error occurs, the server is not started and this method invokes * System::exit with an appropriate exit code. * + *

If the system property "sun.net.httpserver.maxReqTime" has not been + * set by the user, it is set to a value of 5 seconds. This is to prevent + * the server from hanging indefinitely, for example in the case of an HTTPS + * request. + * * @param args the command-line options * @throws NullPointerException if {@code args} is {@code null}, or if there * are any {@code null} values in the {@code args} array */ public static void main(String... args) { + setMaxReqTime(); + int ec = SimpleFileServerImpl.start(new PrintWriter(System.out, true, UTF_8), "jwebserver", args); if (ec != 0) { System.exit(ec); @@ -63,4 +65,13 @@ public class JWebServer { // runs in another non-daemon thread, or -h or -version have been // passed and the main thread has exited normally. } + + public static final String MAXREQTIME_KEY = "sun.net.httpserver.maxReqTime"; + public static final String MAXREQTIME_VAL = "5"; + + private static void setMaxReqTime() { + if (System.getProperty(MAXREQTIME_KEY) == null) { + System.setProperty(MAXREQTIME_KEY, MAXREQTIME_VAL); + } + } } diff --git a/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/Main.java b/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/Main.java index 9f76be48abd..83441cdbc7f 100644 --- a/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/Main.java +++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/Main.java @@ -28,11 +28,6 @@ import static java.nio.charset.StandardCharsets.UTF_8; /** * Programmatic entry point to start "java -m jdk.httpserver". - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interface are subject to change or deletion - * without notice. */ public class Main { @@ -51,11 +46,18 @@ public class Main { * or an I/O error occurs, the server is not started and this method invokes * System::exit with an appropriate exit code. * + *

If the system property "sun.net.httpserver.maxReqTime" has not been + * set by the user, it is set to a value of 5 seconds. This is to prevent + * the server from hanging indefinitely, for example in the case of an HTTPS + * request. + * * @param args the command-line options * @throws NullPointerException if {@code args} is {@code null}, or if there * are any {@code null} values in the {@code args} array */ public static void main(String... args) { + setMaxReqTime(); + int ec = SimpleFileServerImpl.start(new PrintWriter(System.out, true, UTF_8), "java", args); if (ec != 0) { System.exit(ec); @@ -63,4 +65,13 @@ public class Main { // runs in another non-daemon thread, or -h or -version have been // passed and the main thread has exited normally. } + + public static final String MAXREQTIME_KEY = "sun.net.httpserver.maxReqTime"; + public static final String MAXREQTIME_VAL = "5"; + + private static void setMaxReqTime() { + if (System.getProperty(MAXREQTIME_KEY) == null) { + System.setProperty(MAXREQTIME_KEY, MAXREQTIME_VAL); + } + } } -- GitLab From 54993b13078ceb05736bb0e1d7ed7415c390442e Mon Sep 17 00:00:00 2001 From: Thomas Stuefe Date: Wed, 8 Dec 2021 09:18:58 +0000 Subject: [PATCH 050/671] 8278309: [windows] use of uninitialized OSThread::_state Reviewed-by: dholmes, shade --- src/hotspot/os/windows/os_windows.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index 6f8c88d764d..7273e9ec539 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -676,6 +676,9 @@ bool os::create_thread(Thread* thread, ThreadType thr_type, return false; } + // Initial state is ALLOCATED but not INITIALIZED + osthread->set_state(ALLOCATED); + // Initialize the JDK library's interrupt event. // This should really be done when OSThread is constructed, // but there is no way for a constructor to report failure to @@ -777,7 +780,7 @@ bool os::create_thread(Thread* thread, ThreadType thr_type, osthread->set_thread_handle(thread_handle); osthread->set_thread_id(thread_id); - // Initial thread state is INITIALIZED, not SUSPENDED + // Thread state now is INITIALIZED, not SUSPENDED osthread->set_state(INITIALIZED); // The thread is returned suspended (in state INITIALIZED), and is started higher up in the call chain -- GitLab From e5cb84e9a1bca321f22d6e3ce13a6026342b4b85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Gr=C3=B6nlund?= Date: Wed, 8 Dec 2021 11:18:24 +0000 Subject: [PATCH 051/671] 8278336: Use int64_t to represent byte quantities consistently in JfrObjectAllocationSample Reviewed-by: egahlin --- .../jfr/support/jfrObjectAllocationSample.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/hotspot/share/jfr/support/jfrObjectAllocationSample.cpp b/src/hotspot/share/jfr/support/jfrObjectAllocationSample.cpp index 412c35229b4..fb71d7a3362 100644 --- a/src/hotspot/share/jfr/support/jfrObjectAllocationSample.cpp +++ b/src/hotspot/share/jfr/support/jfrObjectAllocationSample.cpp @@ -35,7 +35,7 @@ inline void send_allocation_sample(const Klass* klass, int64_t allocated_bytes) assert(allocated_bytes > 0, "invariant"); EventObjectAllocationSample event; if (event.should_commit()) { - const size_t weight = allocated_bytes - _last_allocated_bytes; + const int64_t weight = allocated_bytes - _last_allocated_bytes; assert(weight > 0, "invariant"); event.set_objectClass(klass); event.set_weight(weight); @@ -48,7 +48,7 @@ inline bool send_allocation_sample_with_result(const Klass* klass, int64_t alloc assert(allocated_bytes > 0, "invariant"); EventObjectAllocationSample event; if (event.should_commit()) { - const size_t weight = allocated_bytes - _last_allocated_bytes; + const int64_t weight = allocated_bytes - _last_allocated_bytes; assert(weight > 0, "invariant"); event.set_objectClass(klass); event.set_weight(weight); @@ -59,11 +59,11 @@ inline bool send_allocation_sample_with_result(const Klass* klass, int64_t alloc return false; } -inline intptr_t estimate_tlab_size_bytes(Thread* thread) { +inline int64_t estimate_tlab_size_bytes(Thread* thread) { const size_t desired_tlab_size_bytes = thread->tlab().desired_size() * HeapWordSize; const size_t alignment_reserve_bytes = thread->tlab().alignment_reserve_in_bytes(); assert(desired_tlab_size_bytes > alignment_reserve_bytes, "invariant"); - return static_cast(desired_tlab_size_bytes - alignment_reserve_bytes); + return static_cast(desired_tlab_size_bytes - alignment_reserve_bytes); } inline int64_t load_allocated_bytes(Thread* thread) { @@ -81,14 +81,14 @@ inline int64_t load_allocated_bytes(Thread* thread) { // To avoid large objects from being undersampled compared to the regular TLAB samples, // the data amount is normalized as if it was a TLAB, giving a number of TLAB sampling attempts to the large object. -static void normalize_as_tlab_and_send_allocation_samples(const Klass* klass, intptr_t obj_alloc_size_bytes, Thread* thread) { +static void normalize_as_tlab_and_send_allocation_samples(const Klass* klass, int64_t obj_alloc_size_bytes, Thread* thread) { const int64_t allocated_bytes = load_allocated_bytes(thread); assert(allocated_bytes > 0, "invariant"); // obj_alloc_size_bytes is already attributed to allocated_bytes at this point. if (!UseTLAB) { send_allocation_sample(klass, allocated_bytes); return; } - const intptr_t tlab_size_bytes = estimate_tlab_size_bytes(thread); + const int64_t tlab_size_bytes = estimate_tlab_size_bytes(thread); if (allocated_bytes - _last_allocated_bytes < tlab_size_bytes) { return; } @@ -103,7 +103,7 @@ static void normalize_as_tlab_and_send_allocation_samples(const Klass* klass, in void JfrObjectAllocationSample::send_event(const Klass* klass, size_t alloc_size, bool outside_tlab, Thread* thread) { if (outside_tlab) { - normalize_as_tlab_and_send_allocation_samples(klass, static_cast(alloc_size), thread); + normalize_as_tlab_and_send_allocation_samples(klass, static_cast(alloc_size), thread); return; } const int64_t allocated_bytes = load_allocated_bytes(thread); -- GitLab From fd8cb2dae87e5726e89a1789e5a1ddd461c4400d Mon Sep 17 00:00:00 2001 From: Matthias Baesken Date: Wed, 8 Dec 2021 14:03:56 +0000 Subject: [PATCH 052/671] 8278346: java/nio/file/Files/probeContentType/Basic.java fails on Linux SLES15 machine Reviewed-by: shade --- .../java/nio/file/Files/probeContentType/Basic.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/jdk/java/nio/file/Files/probeContentType/Basic.java b/test/jdk/java/nio/file/Files/probeContentType/Basic.java index 0812f886c30..b404673b2f4 100644 --- a/test/jdk/java/nio/file/Files/probeContentType/Basic.java +++ b/test/jdk/java/nio/file/Files/probeContentType/Basic.java @@ -110,8 +110,8 @@ public class Basic { + " cannot be determined"); failures++; } else if (!expectedTypes.contains(type)) { - System.err.printf("Content type: %s; expected: %s%n", - type, expectedTypes); + System.err.printf("For extension %s we got content type: %s; expected: %s%n", + extension, type, expectedTypes); failures++; } } finally { @@ -155,7 +155,7 @@ public class Basic { // Verify that certain extensions are mapped to the correct type. var exTypes = new ExType[] { new ExType("adoc", List.of("text/plain")), - new ExType("bz2", List.of("application/bz2", "application/x-bzip2")), + new ExType("bz2", List.of("application/bz2", "application/x-bzip2", "application/x-bzip")), new ExType("css", List.of("text/css")), new ExType("csv", List.of("text/csv")), new ExType("doc", List.of("application/msword")), @@ -166,19 +166,19 @@ public class Basic { new ExType("js", List.of("text/javascript", "application/javascript")), new ExType("json", List.of("application/json")), new ExType("markdown", List.of("text/markdown")), - new ExType("md", List.of("text/markdown")), + new ExType("md", List.of("text/markdown", "application/x-genesis-rom")), new ExType("mp3", List.of("audio/mpeg")), new ExType("mp4", List.of("video/mp4")), new ExType("odp", List.of("application/vnd.oasis.opendocument.presentation")), new ExType("ods", List.of("application/vnd.oasis.opendocument.spreadsheet")), new ExType("odt", List.of("application/vnd.oasis.opendocument.text")), new ExType("pdf", List.of("application/pdf")), - new ExType("php", List.of("text/plain", "text/php")), + new ExType("php", List.of("text/plain", "text/php", "application/x-php")), new ExType("png", List.of("image/png")), new ExType("ppt", List.of("application/vnd.ms-powerpoint")), new ExType("pptx",List.of("application/vnd.openxmlformats-officedocument.presentationml.presentation")), new ExType("py", List.of("text/plain", "text/x-python", "text/x-python-script")), - new ExType("rar", List.of("application/rar", "application/vnd.rar")), + new ExType("rar", List.of("application/rar", "application/vnd.rar", "application/x-rar")), new ExType("rtf", List.of("application/rtf", "text/rtf")), new ExType("webm", List.of("video/webm")), new ExType("webp", List.of("image/webp")), -- GitLab From 37921e30803449c06b4d542fdfeed9928cce8a7d Mon Sep 17 00:00:00 2001 From: Daniel Fuchs Date: Wed, 8 Dec 2021 15:31:49 +0000 Subject: [PATCH 053/671] 8269258: java/net/httpclient/ManyRequestsLegacy.java failed with connection timeout Reviewed-by: michaelm --- .../jdk/java/net/httpclient/ManyRequests.java | 204 ++++++++++++------ .../java/net/httpclient/ManyRequests2.java | 12 +- .../net/httpclient/ManyRequestsLegacy.java | 184 +++++++++++----- 3 files changed, 274 insertions(+), 126 deletions(-) diff --git a/test/jdk/java/net/httpclient/ManyRequests.java b/test/jdk/java/net/httpclient/ManyRequests.java index f79d565162a..296377441a7 100644 --- a/test/jdk/java/net/httpclient/ManyRequests.java +++ b/test/jdk/java/net/httpclient/ManyRequests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,13 +32,13 @@ * @compile ../../../com/sun/net/httpserver/LogFilter.java * @compile ../../../com/sun/net/httpserver/EchoHandler.java * @compile ../../../com/sun/net/httpserver/FileServerHandler.java - * @run main/othervm/timeout=40 -Djdk.httpclient.HttpClient.log=ssl ManyRequests - * @run main/othervm/timeout=40 -Dtest.insertDelay=true ManyRequests - * @run main/othervm/timeout=40 -Dtest.chunkSize=64 ManyRequests - * @run main/othervm/timeout=40 -Dtest.insertDelay=true -Dtest.chunkSize=64 ManyRequests + * @run main/othervm/timeout=40 -Djdk.httpclient.HttpClient.log=ssl,channel ManyRequests + * @run main/othervm/timeout=40 -Djdk.httpclient.HttpClient.log=channel -Dtest.insertDelay=true ManyRequests + * @run main/othervm/timeout=40 -Djdk.httpclient.HttpClient.log=channel -Dtest.chunkSize=64 ManyRequests + * @run main/othervm/timeout=40 -Djdk.httpclient.HttpClient.log=channel -Dtest.insertDelay=true -Dtest.chunkSize=64 ManyRequests * @summary Send a large number of requests asynchronously */ - // * @run main/othervm/timeout=40 -Djdk.httpclient.HttpClient.log=ssl ManyRequests + // * @run main/othervm/timeout=40 -Djdk.httpclient.HttpClient.log=ssl,channel ManyRequests import com.sun.net.httpserver.HttpsConfigurator; import com.sun.net.httpserver.HttpsParameters; @@ -47,6 +47,7 @@ import com.sun.net.httpserver.HttpExchange; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.net.ConnectException; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.URI; @@ -54,13 +55,18 @@ import java.net.http.HttpClient; import java.net.http.HttpClient.Builder; import java.net.http.HttpRequest; import java.net.http.HttpRequest.BodyPublishers; +import java.net.http.HttpResponse; import java.net.http.HttpResponse.BodyHandlers; import java.time.Duration; import java.util.Arrays; import java.util.Formatter; import java.util.HashMap; import java.util.LinkedList; +import java.util.Map; import java.util.Random; +import java.util.concurrent.CompletionException; +import java.util.concurrent.CompletionStage; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ThreadFactory; @@ -68,17 +74,27 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.logging.Logger; import java.util.logging.Level; import java.util.concurrent.CompletableFuture; +import java.util.stream.Stream; import javax.net.ssl.SSLContext; + +import jdk.test.lib.Platform; +import jdk.test.lib.RandomFactory; import jdk.test.lib.net.SimpleSSLContext; +import jdk.test.lib.net.URIBuilder; public class ManyRequests { - volatile static int counter = 0; + static final int MAX_COUNT = 20; + static final int MAX_LIMIT = 40; + static final AtomicInteger COUNT = new AtomicInteger(); + static final AtomicInteger LIMIT = new AtomicInteger(MAX_LIMIT); + static final Random RANDOM = RandomFactory.getRandom(); public static void main(String[] args) throws Exception { Logger logger = Logger.getLogger("com.sun.net.httpserver"); logger.setLevel(Level.ALL); logger.info("TEST"); + Stream.of(Logger.getLogger("").getHandlers()).forEach((h) -> h.setLevel(Level.ALL)); System.out.println("Sending " + REQUESTS + " requests; delay=" + INSERT_DELAY + ", chunks=" + CHUNK_SIZE @@ -106,14 +122,14 @@ public class ManyRequests { } //static final int REQUESTS = 1000; - static final int REQUESTS = 20; + static final int REQUESTS = MAX_COUNT; static final boolean INSERT_DELAY = Boolean.getBoolean("test.insertDelay"); static final int CHUNK_SIZE = Math.max(0, Integer.parseInt(System.getProperty("test.chunkSize", "0"))); static final boolean XFIXED = Boolean.getBoolean("test.XFixed"); static class TestEchoHandler extends EchoHandler { - final Random rand = jdk.test.lib.RandomFactory.getRandom(); + final Random rand = RANDOM; @Override public void handle(HttpExchange e) throws IOException { System.out.println("Server: received " + e.getRequestURI()); @@ -139,60 +155,126 @@ public class ManyRequests { } } + static String now(long start) { + long elapsed = System.nanoTime() - start; + long ms = elapsed / 1000_000L; + long s = ms / 1000L; + if (s == 0) return ms + "ms: "; + return s + "s, " + (ms - s * 1000L) + "ms: "; + } + + static String failure(Throwable t) { + String s = "\n\t failed: " + t; + for (t = t.getCause(); t != null ; t = t.getCause()) { + s = s + "\n\t\t Caused by: " + t; + } + return s; + } + static void test(HttpsServer server, HttpClient client) throws Exception { int port = server.getAddress().getPort(); - URI baseURI = new URI("https://localhost:" + port + "/foo/x"); + + URI baseURI = URIBuilder.newBuilder() + .scheme("https") + .host(InetAddress.getLoopbackAddress().getHostName()) + .port(port) + .path("/foo/x").build(); server.createContext("/foo", new TestEchoHandler()); server.start(); - RequestLimiter limiter = new RequestLimiter(40); - Random rand = new Random(); - CompletableFuture[] results = new CompletableFuture[REQUESTS]; - HashMap bodies = new HashMap<>(); - - for (int i=0; i { - System.out.println("Client: sendAsync: " + r.uri()); - return client.sendAsync(r, BodyHandlers.ofByteArray()); - }) - .thenCompose((resp) -> { - limiter.requestComplete(); - if (resp.statusCode() != 200) { - String s = "Expected 200, got: " + resp.statusCode(); - System.out.println(s + " from " - + resp.request().uri().getPath()); - return completedWithIOException(s); - } else { - counter++; - System.out.println("Result (" + counter + ") from " - + resp.request().uri().getPath()); - } - return CompletableFuture.completedStage(resp.body()) - .thenApply((b) -> new Pair<>(resp, b)); - }) - .thenAccept((pair) -> { - HttpRequest request = pair.t.request(); - byte[] requestBody = bodies.get(request); - check(Arrays.equals(requestBody, pair.u), - "bodies not equal:[" + bytesToHexString(requestBody) - + "] [" + bytesToHexString(pair.u) + "]"); - - }); - } + // This loop implements a retry mechanism to work around an issue + // on some systems (observed on Windows 10) that seem to be trying to + // throttle the number of connections that can be made concurrently by + // rejecting connection attempts. + // On the first iteration of this loop, we will attempt 20 concurrent + // requests. If this fails with ConnectException, we will retry the + // 20 requests, but limiting the concurrency to 10 (LIMIT <- 10). + // If this fails again, the test will fail. + boolean done = false; + LOOP: do { + RequestLimiter limiter = new RequestLimiter(LIMIT.get()); + Random rand = RANDOM; + CompletableFuture[] results = new CompletableFuture[REQUESTS]; + Map bodies = new ConcurrentHashMap<>(); + + long start = System.nanoTime(); + + for (int i = 0; i < REQUESTS; i++) { + byte[] buf = new byte[(i + 1) * CHUNK_SIZE + i + 1]; // different size bodies + rand.nextBytes(buf); + URI uri = new URI(baseURI.toString() + String.valueOf(i + 1)); + HttpRequest r = HttpRequest.newBuilder(uri) + .header("XFixed", "true") + .POST(BodyPublishers.ofByteArray(buf)) + .build(); + bodies.put(r, buf); + + results[i] = + limiter.whenOkToSend() + .thenCompose((v) -> { + System.out.println("Client: sendAsync: " + r.uri()); + return client.sendAsync(r, BodyHandlers.ofByteArray()); + }) + .handle((resp, t) -> { + limiter.requestComplete(); + CompletionStage, byte[]>> res; + String now = now(start); + if (t == null) { + if (resp.statusCode() != 200) { + String s = "Expected 200, got: " + resp.statusCode(); + System.out.println(now + s + " from " + + resp.request().uri().getPath()); + res = completedWithIOException(s); + return res; + } else { + int counter = COUNT.incrementAndGet(); + System.out.println(now + "Result (" + counter + ") from " + + resp.request().uri().getPath()); + } + res = CompletableFuture.completedStage(resp.body()) + .thenApply((b) -> new Pair<>(resp, b)); + return res; + } else { + int counter = COUNT.incrementAndGet(); + System.out.println(now + "Result (" + counter + ") from " + + r.uri().getPath() + + failure(t)); + res = CompletableFuture.failedFuture(t); + return res; + } + }) + .thenCompose(c -> c) + .thenAccept((pair) -> { + HttpRequest request = pair.t.request(); + byte[] requestBody = bodies.get(request); + check(Arrays.equals(requestBody, pair.u), + "bodies not equal:[" + bytesToHexString(requestBody) + + "] [" + bytesToHexString(pair.u) + "]"); + + }); + } + + // wait for them all to complete and throw exception in case of err + try { + CompletableFuture.allOf(results).join(); + done = true; + } catch (CompletionException e) { + if (!Platform.isWindows()) throw e; + if (LIMIT.get() < REQUESTS) throw e; + Throwable cause = e; + while ((cause = cause.getCause()) != null) { + if (cause instanceof ConnectException) { + // try again, limit concurrency by half + COUNT.set(0); + LIMIT.set(REQUESTS/2); + System.out.println("*** Retrying due to " + cause); + continue LOOP; + } + } + throw e; + } + } while (!done); - // wait for them all to complete and throw exception in case of error - CompletableFuture.allOf(results).join(); } static CompletableFuture completedWithIOException(String message) { @@ -213,13 +295,7 @@ public class ManyRequests { return sb.toString(); } - static final class Pair { - Pair(T t, U u) { - this.t = t; this.u = u; - } - T t; - U u; - } + record Pair(T t, U u) { } /** * A simple limiter for controlling the number of requests to be run in diff --git a/test/jdk/java/net/httpclient/ManyRequests2.java b/test/jdk/java/net/httpclient/ManyRequests2.java index b0eee6e3be4..49e7f758f7c 100644 --- a/test/jdk/java/net/httpclient/ManyRequests2.java +++ b/test/jdk/java/net/httpclient/ManyRequests2.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,10 +33,14 @@ * @compile ../../../com/sun/net/httpserver/EchoHandler.java * @compile ../../../com/sun/net/httpserver/FileServerHandler.java * @build ManyRequests ManyRequests2 - * @run main/othervm/timeout=40 -Dtest.XFixed=true ManyRequests2 - * @run main/othervm/timeout=40 -Dtest.XFixed=true -Dtest.insertDelay=true ManyRequests2 - * @run main/othervm/timeout=40 -Dtest.XFixed=true -Dtest.chunkSize=64 ManyRequests2 + * @run main/othervm/timeout=40 -Dtest.XFixed=true + * -Djdk.httpclient.HttpClient.log=channel ManyRequests2 + * @run main/othervm/timeout=40 -Dtest.XFixed=true -Dtest.insertDelay=true + * -Djdk.httpclient.HttpClient.log=channel ManyRequests2 + * @run main/othervm/timeout=40 -Dtest.XFixed=true -Dtest.chunkSize=64 + * -Djdk.httpclient.HttpClient.log=channel ManyRequests2 * @run main/othervm/timeout=40 -Djdk.internal.httpclient.debug=true + * -Djdk.httpclient.HttpClient.log=channel * -Dtest.XFixed=true -Dtest.insertDelay=true * -Dtest.chunkSize=64 ManyRequests2 * @summary Send a large number of requests asynchronously. diff --git a/test/jdk/java/net/httpclient/ManyRequestsLegacy.java b/test/jdk/java/net/httpclient/ManyRequestsLegacy.java index b8d296087b9..0e9aba5deaf 100644 --- a/test/jdk/java/net/httpclient/ManyRequestsLegacy.java +++ b/test/jdk/java/net/httpclient/ManyRequestsLegacy.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,6 +43,7 @@ import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.HostnameVerifier; + import com.sun.net.httpserver.HttpsConfigurator; import com.sun.net.httpserver.HttpsParameters; import com.sun.net.httpserver.HttpsServer; @@ -50,12 +51,18 @@ import com.sun.net.httpserver.HttpExchange; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.net.ConnectException; import java.net.HttpURLConnection; import java.net.InetAddress; import java.net.URI; import java.net.URLConnection; +import java.util.Map; import java.util.Optional; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; +import java.util.concurrent.CompletionStage; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSession; @@ -73,12 +80,20 @@ import java.util.LinkedList; import java.util.Random; import java.util.logging.Logger; import java.util.logging.Level; + +import jdk.test.lib.Platform; +import jdk.test.lib.RandomFactory; import jdk.test.lib.net.SimpleSSLContext; import static java.net.Proxy.NO_PROXY; public class ManyRequestsLegacy { - volatile static int counter = 0; + static final int MAX_COUNT = 20; + static final int MAX_LIMIT = 40; + static final AtomicInteger COUNT = new AtomicInteger(); + static final AtomicInteger LIMIT = new AtomicInteger(MAX_LIMIT); + static final Random RANDOM = RandomFactory.getRandom(); + public static void main(String[] args) throws Exception { Logger logger = Logger.getLogger("com.sun.net.httpserver"); @@ -110,7 +125,7 @@ public class ManyRequestsLegacy { } //static final int REQUESTS = 1000; - static final int REQUESTS = 20; + static final int REQUESTS = MAX_COUNT; static final boolean INSERT_DELAY = Boolean.getBoolean("test.insertDelay"); static final int CHUNK_SIZE = Math.max(0, Integer.parseInt(System.getProperty("test.chunkSize", "0"))); @@ -194,7 +209,7 @@ public class ManyRequestsLegacy { } static class TestEchoHandler extends EchoHandler { - final Random rand = new Random(); + final Random rand = RANDOM; @Override public void handle(HttpExchange e) throws IOException { System.out.println("Server: received " + e.getRequestURI()); @@ -220,60 +235,119 @@ public class ManyRequestsLegacy { } } + static String now(long start) { + long elapsed = System.nanoTime() - start; + long ms = elapsed / 1000_000L; + long s = ms / 1000L; + if (s == 0) return ms + "ms: "; + return s + "s, " + (ms - s * 1000L) + "ms: "; + } + + static String failure(Throwable t) { + String s = "\n\t failed: " + t; + for (t = t.getCause(); t != null ; t = t.getCause()) { + s = s + "\n\t\t Caused by: " + t; + } + return s; + } + static void test(HttpsServer server, LegacyHttpClient client) throws Exception { int port = server.getAddress().getPort(); URI baseURI = new URI("https://localhost:" + port + "/foo/x"); server.createContext("/foo", new TestEchoHandler()); server.start(); - RequestLimiter limiter = new RequestLimiter(40); - Random rand = new Random(); - CompletableFuture[] results = new CompletableFuture[REQUESTS]; - HashMap bodies = new HashMap<>(); - - for (int i=0; i { - System.out.println("Client: sendAsync: " + r.uri()); - return client.sendAsync(r, buf); - }) - .thenCompose((resp) -> { - limiter.requestComplete(); - if (resp.statusCode() != 200) { - String s = "Expected 200, got: " + resp.statusCode(); - System.out.println(s + " from " - + resp.request().uri().getPath()); - return completedWithIOException(s); - } else { - counter++; - System.out.println("Result (" + counter + ") from " - + resp.request().uri().getPath()); - } - return CompletableFuture.completedStage(resp.body()) - .thenApply((b) -> new Pair<>(resp, b)); - }) - .thenAccept((pair) -> { - HttpRequest request = pair.t.request(); - byte[] requestBody = bodies.get(request); - check(Arrays.equals(requestBody, pair.u), - "bodies not equal:[" + bytesToHexString(requestBody) - + "] [" + bytesToHexString(pair.u) + "]"); - - }); - } + // This loop implements a retry mechanism to work around an issue + // on some systems (observed on Windows 10) that seem to be trying to + // throttle the number of connections that can be made concurrently by + // rejecting connection attempts. + // On the first iteration of this loop, we will attempt 20 concurrent + // requests. If this fails with ConnectException, we will retry the + // 20 requests, but limiting the concurrency to 10 (LIMIT <- 10). + // If this fails again, the test will fail. + boolean done = false; + LOOP: do { + RequestLimiter limiter = new RequestLimiter(LIMIT.get()); + Random rand = RANDOM; + CompletableFuture[] results = new CompletableFuture[REQUESTS]; + Map bodies = new ConcurrentHashMap<>(); + long start = System.nanoTime(); + + for (int i = 0; i < REQUESTS; i++) { + byte[] buf = new byte[(i + 1) * CHUNK_SIZE + i + 1]; // different size bodies + rand.nextBytes(buf); + URI uri = new URI(baseURI.toString() + String.valueOf(i + 1)); + HttpRequest r = HttpRequest.newBuilder(uri) + .header("XFixed", "true") + .POST(BodyPublishers.ofByteArray(buf)) + .build(); + bodies.put(r, buf); + + results[i] = + limiter.whenOkToSend() + .thenCompose((v) -> { + System.out.println("Client: sendAsync: " + r.uri()); + return client.sendAsync(r, buf); + }) + .handle((resp, t) -> { + limiter.requestComplete(); + CompletionStage, byte[]>> res; + String now = now(start); + if (t == null) { + if (resp.statusCode() != 200) { + String s = "Expected 200, got: " + resp.statusCode(); + System.out.println(now + s + " from " + + resp.request().uri().getPath()); + res = completedWithIOException(s); + return res; + } else { + int counter = COUNT.incrementAndGet(); + System.out.println(now + "Result (" + counter + ") from " + + resp.request().uri().getPath()); + } + res = CompletableFuture.completedStage(resp.body()) + .thenApply((b) -> new Pair<>(resp, b)); + return res; + } else { + int counter = COUNT.incrementAndGet(); + System.out.println(now + "Result (" + counter + ") from " + + r.uri().getPath() + + failure(t)); + res = CompletableFuture.failedFuture(t); + return res; + } + }) + .thenCompose(c -> c) + .thenAccept((pair) -> { + HttpRequest request = pair.t.request(); + byte[] requestBody = bodies.get(request); + check(Arrays.equals(requestBody, pair.u), + "bodies not equal:[" + bytesToHexString(requestBody) + + "] [" + bytesToHexString(pair.u) + "]"); + + }); + } - // wait for them all to complete and throw exception in case of error - CompletableFuture.allOf(results).join(); + try { + // wait for them all to complete and throw exception in case of error + CompletableFuture.allOf(results).join(); + done = true; + } catch (CompletionException e) { + if (!Platform.isWindows()) throw e; + if (LIMIT.get() < REQUESTS) throw e; + Throwable cause = e; + while ((cause = cause.getCause()) != null) { + if (cause instanceof ConnectException) { + // try again, limit concurrency by half + COUNT.set(0); + LIMIT.set(REQUESTS/2); + System.out.println("*** Retrying due to " + cause); + continue LOOP; + } + } + throw e; + } + } while (!done); } static CompletableFuture completedWithIOException(String message) { @@ -294,13 +368,7 @@ public class ManyRequestsLegacy { return sb.toString(); } - static final class Pair { - Pair(T t, U u) { - this.t = t; this.u = u; - } - T t; - U u; - } + record Pair(T t, U u) { } /** * A simple limiter for controlling the number of requests to be run in -- GitLab From e4852c6f0aa25e7d40c577d507aedc7916ee8d50 Mon Sep 17 00:00:00 2001 From: Calvin Cheung Date: Wed, 8 Dec 2021 15:59:37 +0000 Subject: [PATCH 054/671] 8277998: runtime/cds/appcds/loaderConstraints/DynamicLoaderConstraintsTest.java#custom-cl-zgc failed "assert(ZAddress::is_marked(addr)) failed: Should be marked" Reviewed-by: iklam, minqi --- src/hotspot/share/cds/dynamicArchive.cpp | 3 ++ src/hotspot/share/cds/lambdaFormInvokers.cpp | 33 ++++++++++++++++--- src/hotspot/share/cds/lambdaFormInvokers.hpp | 6 +++- .../cds/appcds/DumpClassListWithLF.java | 4 +-- 4 files changed, 38 insertions(+), 8 deletions(-) diff --git a/src/hotspot/share/cds/dynamicArchive.cpp b/src/hotspot/share/cds/dynamicArchive.cpp index c821d46d4d0..64c95e08933 100644 --- a/src/hotspot/share/cds/dynamicArchive.cpp +++ b/src/hotspot/share/cds/dynamicArchive.cpp @@ -354,6 +354,9 @@ public: _builder.doit(); } + ~VM_PopulateDynamicDumpSharedSpace() { + LambdaFormInvokers::cleanup_regenerated_classes(); + } }; void DynamicArchive::check_for_dynamic_dump() { diff --git a/src/hotspot/share/cds/lambdaFormInvokers.cpp b/src/hotspot/share/cds/lambdaFormInvokers.cpp index 5c058dc43ac..59666085d04 100644 --- a/src/hotspot/share/cds/lambdaFormInvokers.cpp +++ b/src/hotspot/share/cds/lambdaFormInvokers.cpp @@ -39,10 +39,11 @@ #include "memory/oopFactory.hpp" #include "memory/resourceArea.hpp" #include "oops/instanceKlass.hpp" -#include "oops/klass.hpp" +#include "oops/klass.inline.hpp" #include "oops/objArrayKlass.hpp" #include "oops/objArrayOop.hpp" #include "oops/oop.inline.hpp" +#include "oops/oopHandle.inline.hpp" #include "oops/typeArrayOop.inline.hpp" #include "runtime/handles.inline.hpp" #include "runtime/javaCalls.hpp" @@ -50,6 +51,7 @@ GrowableArrayCHeap* LambdaFormInvokers::_lambdaform_lines = nullptr; Array*>* LambdaFormInvokers::_static_archive_invokers = nullptr; +GrowableArrayCHeap* LambdaFormInvokers::_regenerated_mirrors = nullptr; #define NUM_FILTER 4 static const char* filter[NUM_FILTER] = {"java.lang.invoke.Invokers$Holder", @@ -81,6 +83,25 @@ void LambdaFormInvokers::append(char* line) { _lambdaform_lines->append(line); } +// The regenerated Klass is not added to any class loader, so we need +// to keep its java_mirror alive to avoid class unloading. +void LambdaFormInvokers::add_regenerated_class(oop regenerated_class) { + if (_regenerated_mirrors == nullptr) { + _regenerated_mirrors = new GrowableArrayCHeap(150); + } + _regenerated_mirrors->append(OopHandle(Universe::vm_global(), regenerated_class)); +} + +void LambdaFormInvokers::cleanup_regenerated_classes() { + if (_regenerated_mirrors == nullptr) return; + + for (int i = 0; i < _regenerated_mirrors->length(); i++) { + _regenerated_mirrors->at(i).release(Universe::vm_global()); + } + delete _regenerated_mirrors; + _regenerated_mirrors = nullptr; +} + // convenient output class PrintLambdaFormMessage { public: @@ -155,12 +176,11 @@ void LambdaFormInvokers::regenerate_holder_classes(TRAPS) { char *buf = NEW_RESOURCE_ARRAY(char, len); memcpy(buf, (char*)h_bytes->byte_at_addr(0), len); ClassFileStream st((u1*)buf, len, NULL, ClassFileStream::verify); - reload_class(class_name, st, CHECK); + regenerate_class(class_name, st, CHECK); } } -// class_handle - the class name, bytes_handle - the class bytes -void LambdaFormInvokers::reload_class(char* name, ClassFileStream& st, TRAPS) { +void LambdaFormInvokers::regenerate_class(char* name, ClassFileStream& st, TRAPS) { Symbol* class_name = SymbolTable::new_symbol((const char*)name); // the class must exist Klass* klass = SystemDictionary::resolve_or_null(class_name, THREAD); @@ -180,6 +200,9 @@ void LambdaFormInvokers::reload_class(char* name, ClassFileStream& st, TRAPS) { cl_info, CHECK); + assert(result->java_mirror() != nullptr, "must be"); + add_regenerated_class(result->java_mirror()); + { MutexLocker mu_r(THREAD, Compile_lock); // add_to_hierarchy asserts this. SystemDictionary::add_to_hierarchy(result); @@ -191,7 +214,7 @@ void LambdaFormInvokers::reload_class(char* name, ClassFileStream& st, TRAPS) { // exclude the existing class from dump SystemDictionaryShared::set_excluded(InstanceKlass::cast(klass)); SystemDictionaryShared::init_dumptime_info(result); - log_info(cds, lambda)("Replaced class %s, old: " INTPTR_FORMAT " new: " INTPTR_FORMAT, + log_info(cds, lambda)("Regenerated class %s, old: " INTPTR_FORMAT " new: " INTPTR_FORMAT, name, p2i(klass), p2i(result)); } diff --git a/src/hotspot/share/cds/lambdaFormInvokers.hpp b/src/hotspot/share/cds/lambdaFormInvokers.hpp index acb5eab4d8a..c3b151790f1 100644 --- a/src/hotspot/share/cds/lambdaFormInvokers.hpp +++ b/src/hotspot/share/cds/lambdaFormInvokers.hpp @@ -25,6 +25,7 @@ #ifndef SHARE_CDS_LAMBDAFORMINVOKERS_HPP #define SHARE_CDS_LAMBDAFORMINVOKERS_HPP #include "memory/allStatic.hpp" +#include "oops/oopHandle.hpp" #include "runtime/handles.hpp" #include "utilities/growableArray.hpp" @@ -37,7 +38,9 @@ class LambdaFormInvokers : public AllStatic { static GrowableArrayCHeap* _lambdaform_lines; // For storing LF form lines (LF_RESOLVE only) in read only table. static Array*>* _static_archive_invokers; - static void reload_class(char* name, ClassFileStream& st, TRAPS); + static GrowableArrayCHeap* _regenerated_mirrors; + static void regenerate_class(char* name, ClassFileStream& st, TRAPS); + static void add_regenerated_class(oop regenerated_class); public: static void append(char* line); static void append_filtered(char* line); @@ -45,5 +48,6 @@ class LambdaFormInvokers : public AllStatic { static void read_static_archive_invokers(); static void regenerate_holder_classes(TRAPS); static void serialize(SerializeClosure* soc); + static void cleanup_regenerated_classes(); }; #endif // SHARE_CDS_LAMBDAFORMINVOKERS_HPP diff --git a/test/hotspot/jtreg/runtime/cds/appcds/DumpClassListWithLF.java b/test/hotspot/jtreg/runtime/cds/appcds/DumpClassListWithLF.java index a0a898989e1..b0851f46e9c 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/DumpClassListWithLF.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/DumpClassListWithLF.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,7 +33,7 @@ */ public class DumpClassListWithLF extends ClassListFormatBase { - static final String REPLACE_OK = "Replaced class java/lang/invoke/DirectMethodHandle$Holder"; + static final String REPLACE_OK = "Regenerated class java/lang/invoke/DirectMethodHandle$Holder"; public static void main(String[] args) throws Throwable { String appJar = JarBuilder.getOrCreateHelloJar(); -- GitLab From 40d726b8aae7dff4316115b3a25001d502321efe Mon Sep 17 00:00:00 2001 From: Calvin Cheung Date: Wed, 8 Dec 2021 16:07:49 +0000 Subject: [PATCH 055/671] 8278310: Improve logging in CDS DynamicLoaderConstraintsTest.java Reviewed-by: iklam --- src/hotspot/share/cds/archiveBuilder.hpp | 4 ++-- .../loaderConstraints/DynamicLoaderConstraintsTest.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/hotspot/share/cds/archiveBuilder.hpp b/src/hotspot/share/cds/archiveBuilder.hpp index 1057d05b083..484f7271a7c 100644 --- a/src/hotspot/share/cds/archiveBuilder.hpp +++ b/src/hotspot/share/cds/archiveBuilder.hpp @@ -312,14 +312,14 @@ public: template u4 buffer_to_offset_u4(T p) const { uintx offset = buffer_to_offset((address)p); - guarantee(offset <= MAX_SHARED_DELTA, "must be 32-bit offset"); + guarantee(offset <= MAX_SHARED_DELTA, "must be 32-bit offset " INTPTR_FORMAT, offset); return (u4)offset; } template u4 any_to_offset_u4(T p) const { uintx offset = any_to_offset((address)p); - guarantee(offset <= MAX_SHARED_DELTA, "must be 32-bit offset"); + guarantee(offset <= MAX_SHARED_DELTA, "must be 32-bit offset " INTPTR_FORMAT, offset); return (u4)offset; } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/loaderConstraints/DynamicLoaderConstraintsTest.java b/test/hotspot/jtreg/runtime/cds/appcds/loaderConstraints/DynamicLoaderConstraintsTest.java index 9d194c288a3..e983b5a7aec 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/loaderConstraints/DynamicLoaderConstraintsTest.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/loaderConstraints/DynamicLoaderConstraintsTest.java @@ -139,7 +139,7 @@ public class DynamicLoaderConstraintsTest extends DynamicArchiveTestBase { "java.base,jdk.httpserver", "--add-exports", "java.base/jdk.internal.misc=ALL-UNNAMED", - "-Xlog:class+load,class+loader+constraints", + "-Xlog:cds=debug,class+load,class+loader+constraints", }; if (useCustomLoader) { -- GitLab From 79165b738d6d1336740631c855960a235b9ecfe4 Mon Sep 17 00:00:00 2001 From: Calvin Cheung Date: Wed, 8 Dec 2021 16:10:06 +0000 Subject: [PATCH 056/671] 8278324: Update the --generate-cds-archive jlink plugin usage message Reviewed-by: alanb --- .../share/classes/jdk/tools/jlink/resources/plugins.properties | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins.properties b/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins.properties index 958c43c2ca4..017c46baab0 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins.properties +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins.properties @@ -142,7 +142,8 @@ generate-cds-archive.description=\ CDS plugin: generate cds archives if the runtime image supports CDS feature.\n\ generate-cds-archive.usage=\ -\ --generate-cds-archive Generate CDS archives if the runtime image supports CDS feature. +\ --generate-cds-archive Generate CDS archive if the runtime image supports\n\ +\ the CDS feature. generate-jli-classes.argument=@filename -- GitLab From 3e93e0b809f2c6cb4a466af92ec678cbc82863e4 Mon Sep 17 00:00:00 2001 From: Yumin Qi Date: Wed, 8 Dec 2021 16:20:39 +0000 Subject: [PATCH 057/671] 8276769: -Xshare:auto should tolerate problems in the CDS archive Reviewed-by: iklam, ccheung --- src/hotspot/share/cds/filemap.cpp | 228 +++++++++++------- src/hotspot/share/include/cds.h | 4 +- src/hotspot/share/runtime/arguments.cpp | 37 ++- src/hotspot/share/runtime/arguments.hpp | 2 +- .../cds/appcds/SharedArchiveConsistency.java | 16 +- .../dynamicArchive/ArchiveConsistency.java | 101 +++++--- .../DynamicArchiveTestBase.java | 6 +- 7 files changed, 259 insertions(+), 135 deletions(-) diff --git a/src/hotspot/share/cds/filemap.cpp b/src/hotspot/share/cds/filemap.cpp index 72a0d35bca7..89a4d90d257 100644 --- a/src/hotspot/share/cds/filemap.cpp +++ b/src/hotspot/share/cds/filemap.cpp @@ -121,7 +121,6 @@ void FileMapInfo::fail_continue(const char *msg, ...) { fail_exit(msg, ap); } else { if (log_is_enabled(Info, cds)) { - ResourceMark rm; LogStream ls(Log(cds)::info()); ls.print("UseSharedSpaces: "); ls.vprint_cr(msg, ap); @@ -1042,15 +1041,20 @@ void FileMapInfo::validate_non_existent_class_paths() { } } -// a utility class for checking file header +// A utility class for reading/validating the GenericCDSFileMapHeader portion of +// a CDS archive's header. The file header of all CDS archives with versions from +// CDS_GENERIC_HEADER_SUPPORTED_MIN_VERSION (12) are guaranteed to always start +// with GenericCDSFileMapHeader. This makes it possible to read important information +// from a CDS archive created by a different version of HotSpot, so that we can +// automatically regenerate the archive as necessary (JDK-8261455). class FileHeaderHelper { int _fd; - GenericCDSFileMapHeader _header; + bool _is_valid; + GenericCDSFileMapHeader* _header; + const char* _base_archive_name; public: - FileHeaderHelper() { - _fd = -1; - } + FileHeaderHelper() : _fd(-1), _is_valid(false), _header(nullptr), _base_archive_name(nullptr) {} ~FileHeaderHelper() { if (_fd != -1) { @@ -1059,8 +1063,10 @@ public: } bool initialize(const char* archive_name) { + log_info(cds)("Opening shared archive: %s", archive_name); _fd = os::open(archive_name, O_RDONLY | O_BINARY, 0); if (_fd < 0) { + FileMapInfo::fail_continue("Specified shared archive not found (%s)", archive_name); return false; } return initialize(_fd); @@ -1069,117 +1075,185 @@ public: // for an already opened file, do not set _fd bool initialize(int fd) { assert(fd != -1, "Archive should be opened"); + + + // First read the generic header so we know the exact size of the actual header. + GenericCDSFileMapHeader gen_header; size_t size = sizeof(GenericCDSFileMapHeader); lseek(fd, 0, SEEK_SET); - size_t n = os::read(fd, (void*)&_header, (unsigned int)size); + size_t n = os::read(fd, (void*)&gen_header, (unsigned int)size); if (n != size) { - vm_exit_during_initialization("Unable to read generic CDS file map header from shared archive"); + FileMapInfo::fail_continue("Unable to read generic CDS file map header from shared archive"); return false; } + + if (gen_header._magic != CDS_ARCHIVE_MAGIC && + gen_header._magic != CDS_DYNAMIC_ARCHIVE_MAGIC) { + FileMapInfo::fail_continue("The shared archive file has a bad magic number: %#x", gen_header._magic); + return false; + } + + if (gen_header._version < CDS_GENERIC_HEADER_SUPPORTED_MIN_VERSION) { + FileMapInfo::fail_continue("Cannot handle shared archive file version %d. Must be at least %d", + gen_header._version, CDS_GENERIC_HEADER_SUPPORTED_MIN_VERSION); + return false; + } + + size_t filelen = os::lseek(fd, 0, SEEK_END); + if (gen_header._header_size >= filelen) { + FileMapInfo::fail_continue("Archive file header larger than archive file"); + return false; + } + + // Read the actual header and perform more checks + size = gen_header._header_size; + _header = (GenericCDSFileMapHeader*)NEW_C_HEAP_ARRAY(char, size, mtInternal); + lseek(fd, 0, SEEK_SET); + n = os::read(fd, (void*)_header, (unsigned int)size); + if (n != size) { + FileMapInfo::fail_continue("Unable to read actual CDS file map header from shared archive"); + return false; + } + + if (!check_crc()) { + return false; + } + + if (!check_and_init_base_archive_name()) { + return false; + } + + // All fields in the GenericCDSFileMapHeader has been validated. + _is_valid = true; return true; } GenericCDSFileMapHeader* get_generic_file_header() { - return &_header; - } - - char* read_base_archive_name() { - assert(_fd != -1, "Archive should be open"); - size_t name_size = _header._base_archive_name_size; - assert(name_size != 0, "For non-default base archive, name size should be non-zero!"); - char* base_name = NEW_C_HEAP_ARRAY(char, name_size, mtInternal); - lseek(_fd, _header._base_archive_name_offset, SEEK_SET); // position to correct offset. - size_t n = os::read(_fd, base_name, (unsigned int)name_size); - if (n != name_size) { - log_info(cds)("Unable to read base archive name from archive"); - FREE_C_HEAP_ARRAY(char, base_name); - return nullptr; + assert(_header != nullptr && _is_valid, "must be a valid archive file"); + return _header; + } + + const char* base_archive_name() { + assert(_header != nullptr && _is_valid, "must be a valid archive file"); + return _base_archive_name; + } + + private: + bool check_crc() { + if (VerifySharedSpaces) { + FileMapHeader* header = (FileMapHeader*)_header; + int actual_crc = header->compute_crc(); + if (actual_crc != header->crc()) { + log_info(cds)("_crc expected: %d", header->crc()); + log_info(cds)(" actual: %d", actual_crc); + FileMapInfo::fail_continue("Header checksum verification failed."); + return false; + } } - if (base_name[name_size - 1] != '\0' || strlen(base_name) != name_size - 1) { - log_info(cds)("Base archive name is damaged"); - FREE_C_HEAP_ARRAY(char, base_name); - return nullptr; + return true; + } + + bool check_and_init_base_archive_name() { + unsigned int name_offset = _header->_base_archive_name_offset; + unsigned int name_size = _header->_base_archive_name_size; + unsigned int header_size = _header->_header_size; + + if (name_offset + name_size < name_offset) { + FileMapInfo::fail_continue("base_archive_name offset/size overflow: " UINT32_FORMAT "/" UINT32_FORMAT, + name_offset, name_size); + return false; } - if (!os::file_exists(base_name)) { - log_info(cds)("Base archive %s does not exist", base_name); - FREE_C_HEAP_ARRAY(char, base_name); - return nullptr; + if (_header->_magic == CDS_ARCHIVE_MAGIC) { + if (name_offset != 0) { + FileMapInfo::fail_continue("static shared archive must have zero _base_archive_name_offset"); + return false; + } + if (name_size != 0) { + FileMapInfo::fail_continue("static shared archive must have zero _base_archive_name_size"); + return false; + } + } else { + assert(_header->_magic == CDS_DYNAMIC_ARCHIVE_MAGIC, "must be"); + if ((name_size == 0 && name_offset != 0) || + (name_size != 0 && name_offset == 0)) { + // If either is zero, both must be zero. This indicates that we are using the default base archive. + FileMapInfo::fail_continue("Invalid base_archive_name offset/size: " UINT32_FORMAT "/" UINT32_FORMAT, + name_offset, name_size); + return false; + } + if (name_size > 0) { + if (name_offset + name_size > header_size) { + FileMapInfo::fail_continue("Invalid base_archive_name offset/size (out of range): " + UINT32_FORMAT " + " UINT32_FORMAT " > " UINT32_FORMAT , + name_offset, name_size, header_size); + return false; + } + const char* name = ((const char*)_header) + _header->_base_archive_name_offset; + if (name[name_size - 1] != '\0' || strlen(name) != name_size - 1) { + FileMapInfo::fail_continue("Base archive name is damaged"); + return false; + } + if (!os::file_exists(name)) { + FileMapInfo::fail_continue("Base archive %s does not exist", name); + return false; + } + _base_archive_name = name; + } } - return base_name; + return true; } }; bool FileMapInfo::check_archive(const char* archive_name, bool is_static) { FileHeaderHelper file_helper; if (!file_helper.initialize(archive_name)) { - // do not vm_exit_during_initialization here because Arguments::init_shared_archive_paths() - // requires a shared archive name. The open_for_read() function will log a message regarding - // failure in opening a shared archive. + // Any errors are reported by fail_continue(). return false; } GenericCDSFileMapHeader* header = file_helper.get_generic_file_header(); if (is_static) { if (header->_magic != CDS_ARCHIVE_MAGIC) { - vm_exit_during_initialization("Not a base shared archive", archive_name); - return false; - } - if (header->_base_archive_name_offset != 0) { - log_info(cds)("_base_archive_name_offset should be 0"); - log_info(cds)("_base_archive_name_offset = " UINT32_FORMAT, header->_base_archive_name_offset); + fail_continue("Not a base shared archive: %s", archive_name); return false; } } else { if (header->_magic != CDS_DYNAMIC_ARCHIVE_MAGIC) { - vm_exit_during_initialization("Not a top shared archive", archive_name); + fail_continue("Not a top shared archive: %s", archive_name); return false; } - unsigned int name_size = header->_base_archive_name_size; - unsigned int name_offset = header->_base_archive_name_offset; - unsigned int header_size = header->_header_size; - if (name_offset + name_size != header_size) { - log_info(cds)("_header_size should be equal to _base_archive_name_offset plus _base_archive_name_size"); - log_info(cds)(" _base_archive_name_size = " UINT32_FORMAT, name_size); - log_info(cds)(" _base_archive_name_offset = " UINT32_FORMAT, name_offset); - log_info(cds)(" _header_size = " UINT32_FORMAT, header_size); - return false; - } - char* base_name = file_helper.read_base_archive_name(); - if (base_name == nullptr) { - return false; - } - FREE_C_HEAP_ARRAY(char, base_name); } return true; } +// Return value: +// false: +// is not a valid archive. *base_archive_name is set to null. +// true && (*base_archive_name) == NULL: +// is a valid static archive. +// true && (*base_archive_name) != NULL: +// is a valid dynamic archive. bool FileMapInfo::get_base_archive_name_from_header(const char* archive_name, char** base_archive_name) { FileHeaderHelper file_helper; + *base_archive_name = NULL; + if (!file_helper.initialize(archive_name)) { return false; } GenericCDSFileMapHeader* header = file_helper.get_generic_file_header(); if (header->_magic != CDS_DYNAMIC_ARCHIVE_MAGIC) { - // Not a dynamic header, no need to proceed further. - return false; + assert(header->_magic == CDS_ARCHIVE_MAGIC, "must be"); + return true; } - if ((header->_base_archive_name_size == 0 && header->_base_archive_name_offset != 0) || - (header->_base_archive_name_size != 0 && header->_base_archive_name_offset == 0)) { - fail_continue("Default base archive not set correct"); - return false; - } - if (header->_base_archive_name_size == 0 && - header->_base_archive_name_offset == 0) { + const char* base = file_helper.base_archive_name(); + if (base == nullptr) { *base_archive_name = Arguments::get_default_shared_archive_path(); } else { - // read the base archive name - *base_archive_name = file_helper.read_base_archive_name(); - if (*base_archive_name == nullptr) { - return false; - } + *base_archive_name = os::strdup_check_oom(base); } + return true; } @@ -1247,16 +1321,6 @@ bool FileMapInfo::init_from_file(int fd) { return false; } - if (VerifySharedSpaces) { - int expected_crc = header()->compute_crc(); - if (expected_crc != header()->crc()) { - log_info(cds)("_crc expected: %d", expected_crc); - log_info(cds)(" actual: %d", header()->crc()); - FileMapInfo::fail_continue("Header checksum verification failed."); - return false; - } - } - _file_offset = header()->header_size(); // accounts for the size of _base_archive_name if (is_static()) { @@ -1294,9 +1358,9 @@ bool FileMapInfo::open_for_read() { int fd = os::open(_full_path, O_RDONLY | O_BINARY, 0); if (fd < 0) { if (errno == ENOENT) { - fail_continue("Specified shared archive not found (%s).", _full_path); + fail_continue("Specified shared archive not found (%s)", _full_path); } else { - fail_continue("Failed to open shared archive file (%s).", + fail_continue("Failed to open shared archive file (%s)", os::strerror(errno)); } return false; diff --git a/src/hotspot/share/include/cds.h b/src/hotspot/share/include/cds.h index eeb45ba34c4..476f84c34df 100644 --- a/src/hotspot/share/include/cds.h +++ b/src/hotspot/share/include/cds.h @@ -38,6 +38,7 @@ #define NUM_CDS_REGIONS 7 // this must be the same as MetaspaceShared::n_regions #define CDS_ARCHIVE_MAGIC 0xf00baba2 #define CDS_DYNAMIC_ARCHIVE_MAGIC 0xf00baba8 +#define CDS_GENERIC_HEADER_SUPPORTED_MIN_VERSION 12 #define CURRENT_CDS_ARCHIVE_VERSION 12 typedef struct CDSFileMapRegion { @@ -59,7 +60,8 @@ typedef struct CDSFileMapRegion { char* _mapped_base; // Actually mapped address (NULL if this region is not mapped). } CDSFileMapRegion; -// This portion of the archive file header must remain unchanged for _version >= 12. +// This portion of the archive file header must remain unchanged for +// _version >= CDS_GENERIC_HEADER_SUPPORTED_MIN_VERSION (12). // This makes it possible to read important information from a CDS archive created by // a different version of HotSpot, so that we can automatically regenerate the archive as necessary. typedef struct GenericCDSFileMapHeader { diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp index adfe1a1fb6a..fe54fd3cb29 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -3449,7 +3449,7 @@ jint Arguments::parse_options_buffer(const char* name, char* buffer, const size_ return vm_args->set_args(&options); } -jint Arguments::set_shared_spaces_flags_and_archive_paths() { +void Arguments::set_shared_spaces_flags_and_archive_paths() { if (DumpSharedSpaces) { if (RequireSharedSpaces) { warning("Cannot dump shared archive while using shared archive"); @@ -3459,9 +3459,12 @@ jint Arguments::set_shared_spaces_flags_and_archive_paths() { #if INCLUDE_CDS // Initialize shared archive paths which could include both base and dynamic archive paths // This must be after set_ergonomics_flags() called so flag UseCompressedOops is set properly. - init_shared_archive_paths(); + // + // UseSharedSpaces may be disabled if -XX:SharedArchiveFile is invalid. + if (DumpSharedSpaces || UseSharedSpaces) { + init_shared_archive_paths(); + } #endif // INCLUDE_CDS - return JNI_OK; } #if INCLUDE_CDS @@ -3510,7 +3513,9 @@ void Arguments::extract_shared_archive_paths(const char* archive_path, char* cur_path = NEW_C_HEAP_ARRAY(char, len + 1, mtInternal); strncpy(cur_path, begin_ptr, len); cur_path[len] = '\0'; - FileMapInfo::check_archive((const char*)cur_path, true /*is_static*/); + if (!FileMapInfo::check_archive((const char*)cur_path, true /*is_static*/)) { + return; + } *base_archive_path = cur_path; begin_ptr = ++end_ptr; @@ -3522,7 +3527,9 @@ void Arguments::extract_shared_archive_paths(const char* archive_path, len = end_ptr - begin_ptr; cur_path = NEW_C_HEAP_ARRAY(char, len + 1, mtInternal); strncpy(cur_path, begin_ptr, len + 1); - FileMapInfo::check_archive((const char*)cur_path, false /*is_static*/); + if (!FileMapInfo::check_archive((const char*)cur_path, false /*is_static*/)) { + return; + } *top_archive_path = cur_path; } @@ -3566,17 +3573,26 @@ void Arguments::init_shared_archive_paths() { "Cannot have more than 2 archive files specified in the -XX:SharedArchiveFile option"); } if (archives == 1) { - char* temp_archive_path = os::strdup_check_oom(SharedArchiveFile, mtArguments); + char* base_archive_path = NULL; bool success = - FileMapInfo::get_base_archive_name_from_header(temp_archive_path, &SharedArchivePath); + FileMapInfo::get_base_archive_name_from_header(SharedArchiveFile, &base_archive_path); if (!success) { - SharedArchivePath = temp_archive_path; + no_shared_spaces("invalid archive"); + } else if (base_archive_path == NULL) { + // User has specified a single archive, which is a static archive. + SharedArchivePath = const_cast(SharedArchiveFile); } else { - SharedDynamicArchivePath = temp_archive_path; + // User has specified a single archive, which is a dynamic archive. + SharedDynamicArchivePath = const_cast(SharedArchiveFile); + SharedArchivePath = base_archive_path; // has been c-heap allocated. } } else { extract_shared_archive_paths((const char*)SharedArchiveFile, &SharedArchivePath, &SharedDynamicArchivePath); + if (SharedArchivePath == NULL) { + assert(SharedDynamicArchivePath == NULL, "must be"); + no_shared_spaces("invalid archive"); + } } if (SharedDynamicArchivePath != nullptr) { @@ -4049,8 +4065,7 @@ jint Arguments::apply_ergo() { GCConfig::arguments()->initialize(); - result = set_shared_spaces_flags_and_archive_paths(); - if (result != JNI_OK) return result; + set_shared_spaces_flags_and_archive_paths(); // Initialize Metaspace flags and alignments Metaspace::ergo_initialize(); diff --git a/src/hotspot/share/runtime/arguments.hpp b/src/hotspot/share/runtime/arguments.hpp index 0867f5c5c4d..40b9308c82b 100644 --- a/src/hotspot/share/runtime/arguments.hpp +++ b/src/hotspot/share/runtime/arguments.hpp @@ -366,7 +366,7 @@ class Arguments : AllStatic { static void set_use_compressed_oops(); static void set_use_compressed_klass_ptrs(); static jint set_ergonomics_flags(); - static jint set_shared_spaces_flags_and_archive_paths(); + static void set_shared_spaces_flags_and_archive_paths(); // Limits the given heap size by the maximum amount of virtual // memory this process is currently allowed to use. It also takes // the virtual-to-physical ratio of the current GC into account. diff --git a/test/hotspot/jtreg/runtime/cds/appcds/SharedArchiveConsistency.java b/test/hotspot/jtreg/runtime/cds/appcds/SharedArchiveConsistency.java index 57086f343b3..aee023198f5 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/SharedArchiveConsistency.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/SharedArchiveConsistency.java @@ -112,7 +112,8 @@ public class SharedArchiveConsistency { // test, should pass System.out.println("1. Normal, should pass but may fail\n"); - String[] execArgs = {"-Xlog:cds=debug", "-cp", jarFile, "Hello"}; + // disable VerifySharedSpaces, it may be turned on by jtreg args + String[] execArgs = {"-Xlog:cds=debug", "-XX:-VerifySharedSpaces", "-cp", jarFile, "Hello"}; // tests that corrupt contents of the archive need to run with // VerifySharedSpaces enabled to detect inconsistencies String[] verifyExecArgs = {"-Xlog:cds", "-XX:+VerifySharedSpaces", "-cp", jarFile, "Hello"}; @@ -172,7 +173,7 @@ public class SharedArchiveConsistency { System.out.println("\n2d. Corrupt _version, should fail\n"); String modVersion = startNewArchive("modify-version"); copiedJsa = CDSArchiveUtils.copyArchiveFile(orgJsaFile, modVersion); - CDSArchiveUtils.modifyHeaderIntField(copiedJsa, CDSArchiveUtils.offsetVersion(), 0x00000000); + CDSArchiveUtils.modifyHeaderIntField(copiedJsa, CDSArchiveUtils.offsetVersion(), 0x3FFFFFFF); output = shareAuto ? TestCommon.execAuto(execArgs) : TestCommon.execCommon(execArgs); output.shouldContain("The shared archive file has the wrong version"); output.shouldNotContain("Checksum verification failed"); @@ -180,6 +181,17 @@ public class SharedArchiveConsistency { output.shouldContain(HELLO_WORLD); } + System.out.println("\n2e. Corrupt _version, should fail\n"); + String modVersion2 = startNewArchive("modify-version2"); + copiedJsa = CDSArchiveUtils.copyArchiveFile(orgJsaFile, modVersion2); + CDSArchiveUtils.modifyHeaderIntField(copiedJsa, CDSArchiveUtils.offsetVersion(), 0x00000000); + output = shareAuto ? TestCommon.execAuto(execArgs) : TestCommon.execCommon(execArgs); + output.shouldContain("Cannot handle shared archive file version 0. Must be at least 12"); + output.shouldNotContain("Checksum verification failed"); + if (shareAuto) { + output.shouldContain(HELLO_WORLD); + } + // modify content inside regions System.out.println("\n3. Corrupt Content, should fail\n"); for (int i=0; i { for (String s : checkMessages) { output.shouldContain(s); } + output.shouldContain(HELLO_WORLD); }); } else { result.assertAbnormalExit( output -> { for (String s : checkMessages) { output.shouldContain(s); } + output.shouldContain("Unable to use shared archive"); }); } } + private static void startTest(String str) { + System.out.println("\n" + str); + } + private static void doTest(String baseArchiveName, String topArchiveName) throws Exception { String appJar = ClassFileInstaller.getJarPath("hello.jar"); String mainClass = "Hello"; @@ -94,42 +110,36 @@ public class ArchiveConsistency extends DynamicArchiveTestBase { throw new IOException(jsa + " does not exist!"); } - // 1. Modify the CRC values in the header of the top archive. - System.out.println("\n1. Modify the CRC values in the header of the top archive"); + startTest("1. Modify the CRC values in the header of the top archive"); String modTop = getNewArchiveName("modTopRegionsCrc"); File copiedJsa = CDSArchiveUtils.copyArchiveFile(jsa, modTop); CDSArchiveUtils.modifyAllRegionsCrc(copiedJsa); + VERIFY_CRC = true; runTwo(baseArchiveName, modTop, - appJar, mainClass, 1, - new String[] {"Header checksum verification failed", - "Unable to use shared archive"}); + appJar, mainClass, isAuto ? 0 : 1, + "Header checksum verification failed"); + VERIFY_CRC = false; - // 2. Make header size larger than the archive size - System.out.println("\n2. Make header size larger than the archive size"); + startTest("2. Make header size larger than the archive size"); String largerHeaderSize = getNewArchiveName("largerHeaderSize"); copiedJsa = CDSArchiveUtils.copyArchiveFile(jsa, largerHeaderSize); CDSArchiveUtils.modifyHeaderIntField(copiedJsa, CDSArchiveUtils.offsetHeaderSize(), (int)copiedJsa.length() + 1024); runTwo(baseArchiveName, largerHeaderSize, - appJar, mainClass, 1, - new String[] {"_header_size should be equal to _base_archive_name_offset plus _base_archive_name_size", - "Unable to use shared archive"}); + appJar, mainClass, isAuto ? 0 : 1, + "Archive file header larger than archive file"); - // 3. Make base archive path offset beyond of header size - System.out.println("\n3. Make base archive path offset beyond of header size."); + startTest("3. Make base archive name offset beyond of header size."); String wrongBaseArchiveNameOffset = getNewArchiveName("wrongBaseArchiveNameOffset"); copiedJsa = CDSArchiveUtils.copyArchiveFile(jsa, wrongBaseArchiveNameOffset); int fileHeaderSize = (int)CDSArchiveUtils.fileHeaderSize(copiedJsa); int baseArchiveNameOffset = CDSArchiveUtils.baseArchiveNameOffset(copiedJsa); CDSArchiveUtils.modifyHeaderIntField(copiedJsa, CDSArchiveUtils.offsetBaseArchiveNameOffset(), baseArchiveNameOffset + 1024); runTwo(baseArchiveName, wrongBaseArchiveNameOffset, - appJar, mainClass, 1, - new String[] {"_header_size should be equal to _base_archive_name_offset plus _base_archive_name_size", - "The shared archive file has an incorrect header size", - "Unable to use shared archive"}); + appJar, mainClass, isAuto ? 0 : 1, + "Invalid base_archive_name offset/size (out of range)"); - // 4. Make base archive path offset points to middle of name size - System.out.println("\n4. Make base archive path offset points to middle of name size"); + startTest("4. Make base archive name offset points to middle of the base archive name"); String wrongBaseNameOffset = getNewArchiveName("wrongBaseNameOffset"); copiedJsa = CDSArchiveUtils.copyArchiveFile(jsa, wrongBaseNameOffset); int baseArchiveNameSize = CDSArchiveUtils.baseArchiveNameSize(copiedJsa); @@ -137,13 +147,10 @@ public class ArchiveConsistency extends DynamicArchiveTestBase { CDSArchiveUtils.modifyHeaderIntField(copiedJsa, baseArchiveNameOffset, baseArchiveNameOffset + baseArchiveNameSize/2); runTwo(baseArchiveName, wrongBaseNameOffset, - appJar, mainClass, 1, - new String[] {"An error has occurred while processing the shared archive file.", - "Header checksum verification failed", - "Unable to use shared archive"}); + appJar, mainClass, isAuto ? 0 : 1, + "Base archive name is damaged"); - // 5. Make base archive name not terminated with '\0' - System.out.println("\n5. Make base archive name not terminated with '\0'"); + startTest("5. Make base archive name not terminated with '\0'"); String wrongBaseName = getNewArchiveName("wrongBaseName"); copiedJsa = CDSArchiveUtils.copyArchiveFile(jsa, wrongBaseName); baseArchiveNameOffset = CDSArchiveUtils.baseArchiveNameOffset(copiedJsa); @@ -152,12 +159,10 @@ public class ArchiveConsistency extends DynamicArchiveTestBase { CDSArchiveUtils.writeData(copiedJsa, offset, new byte[] {(byte)'X'}); runTwo(baseArchiveName, wrongBaseName, - appJar, mainClass, 1, - new String[] {"Base archive name is damaged", - "Header checksum verification failed"}); + appJar, mainClass, isAuto ? 0 : 1, + "Base archive name is damaged"); - // 6. Modify base archive name to a file that doesn't exist. - System.out.println("\n6. Modify base archive name to a file that doesn't exist"); + startTest("6. Modify base archive name to a file that doesn't exist"); String wrongBaseName2 = getNewArchiveName("wrongBaseName2"); copiedJsa = CDSArchiveUtils.copyArchiveFile(jsa, wrongBaseName2); baseArchiveNameOffset = CDSArchiveUtils.baseArchiveNameOffset(copiedJsa); @@ -170,8 +175,32 @@ public class ArchiveConsistency extends DynamicArchiveTestBase { (new File(badName)).delete(); runTwo(baseArchiveName, wrongBaseName2, - appJar, mainClass, 1, - new String[] {"Base archive " + badName + " does not exist", - "Header checksum verification failed"}); + appJar, mainClass, isAuto ? 0 : 1, + "Base archive " + badName + " does not exist"); + + // Following three tests: + // -XX:SharedArchiveFile=non-exist-base.jsa:top.jsa + // -XX:SharedArchiveFile=base.jsa:non-exist-top.jsa + // -XX:SharedArchiveFile=non-exist-base.jsa:non-exist-top.jsa + startTest("7. Non-exist base archive"); + String nonExistBase = "non-exist-base.jsa"; + File nonExistBaseFile = new File(nonExistBase); + nonExistBaseFile.delete(); + runTwo(nonExistBase, topArchiveName, + appJar, mainClass, isAuto ? 0 : 1, + "Specified shared archive not found (" + nonExistBase + ")"); + + startTest("8. Non-exist top archive"); + String nonExistTop = "non-exist-top.jsa"; + File nonExistTopFile = new File(nonExistTop); + nonExistTopFile.delete(); + runTwo(baseArchiveName, nonExistTop, + appJar, mainClass, isAuto ? 0 : 1, + "Specified shared archive not found (" + nonExistTop + ")"); + + startTest("9. nost-exist-base and non-exist-top"); + runTwo(nonExistBase, nonExistTop, + appJar, mainClass, isAuto ? 0 : 1, + "Specified shared archive not found (" + nonExistBase + ")"); } } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/DynamicArchiveTestBase.java b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/DynamicArchiveTestBase.java index b61894c1b4b..b46eb7ea35a 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/DynamicArchiveTestBase.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/DynamicArchiveTestBase.java @@ -36,6 +36,7 @@ import sun.hotspot.WhiteBox; */ class DynamicArchiveTestBase { private static boolean executedIn_run = false; + private static boolean autoMode = false; // -Xshare:auto private static final WhiteBox WB = WhiteBox.getWhiteBox(); @@ -47,6 +48,7 @@ class DynamicArchiveTestBase { public void run(String args[]) throws Exception; } + public static void setAutoMode(boolean val) { autoMode = val; } /* * Tests for dynamic archives should be written using this pattern: @@ -183,7 +185,7 @@ class DynamicArchiveTestBase { (topArchiveName == null) ? baseArchiveName : baseArchiveName + File.pathSeparator + topArchiveName; String[] cmdLine = TestCommon.concat( - "-Xshare:on", + autoMode ? "-Xshare:auto" : "-Xshare:on", "-XX:SharedArchiveFile=" + archiveFiles); cmdLine = TestCommon.concat(cmdLine, cmdLineSuffix); return execProcess("exec", null, cmdLine); @@ -202,7 +204,7 @@ class DynamicArchiveTestBase { (topArchiveName == null) ? baseArchiveName : baseArchiveName + File.pathSeparator + topArchiveName; String[] cmdLine = TestCommon.concat( - "-Xshare:on", + autoMode ? "-Xshare:auto" : "-Xshare:on", "-XX:SharedArchiveFile=" + archiveFiles); cmdLine = TestCommon.concat(cmdLine, cmdLineSuffix); return execProcess("exec", jarDir, cmdLine); -- GitLab From 8af3b27ce98bcb9cf0c155c98d6b9a9bc159aafe Mon Sep 17 00:00:00 2001 From: Roland Westrelin Date: Wed, 8 Dec 2021 16:39:24 +0000 Subject: [PATCH 058/671] 8277850: C2: optimize mask checks in counted loops Reviewed-by: kvn, thartmann --- src/hotspot/share/opto/mulnode.cpp | 93 ++++++++++++++- src/hotspot/share/opto/mulnode.hpp | 5 + .../compiler/c2/irTests/TestShiftAndMask.java | 108 ++++++++++++++++++ .../compiler/lib/ir_framework/IRNode.java | 8 ++ 4 files changed, 213 insertions(+), 1 deletion(-) create mode 100644 test/hotspot/jtreg/compiler/c2/irTests/TestShiftAndMask.java diff --git a/src/hotspot/share/opto/mulnode.cpp b/src/hotspot/share/opto/mulnode.cpp index a45ad23f6c1..e28ccb6e94a 100644 --- a/src/hotspot/share/opto/mulnode.cpp +++ b/src/hotspot/share/opto/mulnode.cpp @@ -505,6 +505,15 @@ const Type *AndINode::mul_ring( const Type *t0, const Type *t1 ) const { return TypeInt::INT; // No constants to be had } +const Type* AndINode::Value(PhaseGVN* phase) const { + // patterns similar to (v << 2) & 3 + if (AndIL_shift_and_mask(phase, in(2), in(1), T_INT)) { + return TypeInt::ZERO; + } + + return MulNode::Value(phase); +} + //------------------------------Identity--------------------------------------- // Masking off the high bits of an unsigned load is not required Node* AndINode::Identity(PhaseGVN* phase) { @@ -598,6 +607,12 @@ Node *AndINode::Ideal(PhaseGVN *phase, bool can_reshape) { phase->type(load->in(1)) == TypeInt::ZERO ) return new AndINode( load->in(2), in(2) ); + // pattern similar to (v1 + (v2 << 2)) & 3 transformed to v1 & 3 + Node* progress = AndIL_add_shift_and_mask(phase, T_INT); + if (progress != NULL) { + return progress; + } + return MulNode::Ideal(phase, can_reshape); } @@ -629,6 +644,15 @@ const Type *AndLNode::mul_ring( const Type *t0, const Type *t1 ) const { return TypeLong::LONG; // No constants to be had } +const Type* AndLNode::Value(PhaseGVN* phase) const { + // patterns similar to (v << 2) & 3 + if (AndIL_shift_and_mask(phase, in(2), in(1), T_LONG)) { + return TypeLong::ZERO; + } + + return MulNode::Value(phase); +} + //------------------------------Identity--------------------------------------- // Masking off the high bits of an unsigned load is not required Node* AndLNode::Identity(PhaseGVN* phase) { @@ -675,7 +699,7 @@ Node *AndLNode::Ideal(PhaseGVN *phase, bool can_reshape) { const jlong mask = t2->get_con(); Node* in1 = in(1); - uint op = in1->Opcode(); + int op = in1->Opcode(); // Are we masking a long that was converted from an int with a mask // that fits in 32-bits? Commute them and use an AndINode. Don't @@ -705,6 +729,12 @@ Node *AndLNode::Ideal(PhaseGVN *phase, bool can_reshape) { } } + // pattern similar to (v1 + (v2 << 2)) & 3 transformed to v1 & 3 + Node* progress = AndIL_add_shift_and_mask(phase, T_LONG); + if (progress != NULL) { + return progress; + } + return MulNode::Ideal(phase, can_reshape); } @@ -1683,3 +1713,64 @@ const Type* RotateRightNode::Value(PhaseGVN* phase) const { return TypeLong::LONG; } } + +// Helper method to transform: +// patterns similar to (v << 2) & 3 to 0 +// and +// patterns similar to (v1 + (v2 << 2)) & 3 transformed to v1 & 3 +bool MulNode::AndIL_shift_and_mask(PhaseGVN* phase, Node* mask, Node* shift, BasicType bt) { + if (mask == NULL || shift == NULL) { + return false; + } + const TypeInteger* mask_t = phase->type(mask)->isa_integer(bt); + const TypeInteger* shift_t = phase->type(shift)->isa_integer(bt); + if (mask_t == NULL || shift_t == NULL) { + return false; + } + if (bt == T_LONG && shift != NULL && shift->Opcode() == Op_ConvI2L) { + bt = T_INT; + shift = shift->in(1); + if (shift == NULL) { + return false; + } + } + if (shift->Opcode() != Op_LShift(bt)) { + return false; + } + Node* shift2 = shift->in(2); + if (shift2 == NULL) { + return false; + } + const Type* shift2_t = phase->type(shift2); + if (!shift2_t->isa_int() || !shift2_t->is_int()->is_con()) { + return false; + } + + jint shift_con = shift2_t->is_int()->get_con() & ((bt == T_INT ? BitsPerJavaInteger : BitsPerJavaLong) - 1); + if ((((jlong)1) << shift_con) > mask_t->hi_as_long() && mask_t->lo_as_long() >= 0) { + return true; + } + + return false; +} + +// Helper method to transform: +// patterns similar to (v1 + (v2 << 2)) & 3 to v1 & 3 +Node* MulNode::AndIL_add_shift_and_mask(PhaseGVN* phase, BasicType bt) { + Node* in1 = in(1); + Node* in2 = in(2); + if (in1 != NULL && in2 != NULL && in1->Opcode() == Op_Add(bt)) { + Node* add1 = in1->in(1); + Node* add2 = in1->in(2); + if (add1 != NULL && add2 != NULL) { + if (AndIL_shift_and_mask(phase, in2, add1, bt)) { + set_req_X(1, add2, phase); + return this; + } else if (AndIL_shift_and_mask(phase, in2, add2, bt)) { + set_req_X(1, add1, phase); + return this; + } + } + } + return NULL; +} diff --git a/src/hotspot/share/opto/mulnode.hpp b/src/hotspot/share/opto/mulnode.hpp index 3c7f27910a7..ec751aec799 100644 --- a/src/hotspot/share/opto/mulnode.hpp +++ b/src/hotspot/share/opto/mulnode.hpp @@ -82,6 +82,9 @@ public: virtual int min_opcode() const = 0; static MulNode* make(Node* in1, Node* in2, BasicType bt); + + static bool AndIL_shift_and_mask(PhaseGVN* phase, Node* mask, Node* shift, BasicType bt); + Node* AndIL_add_shift_and_mask(PhaseGVN* phase, BasicType bt); }; //------------------------------MulINode--------------------------------------- @@ -189,6 +192,7 @@ public: virtual int Opcode() const; virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); virtual Node* Identity(PhaseGVN* phase); + virtual const Type* Value(PhaseGVN* phase) const; virtual const Type *mul_ring( const Type *, const Type * ) const; const Type *mul_id() const { return TypeInt::MINUS_1; } const Type *add_id() const { return TypeInt::ZERO; } @@ -208,6 +212,7 @@ public: virtual int Opcode() const; virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); virtual Node* Identity(PhaseGVN* phase); + virtual const Type* Value(PhaseGVN* phase) const; virtual const Type *mul_ring( const Type *, const Type * ) const; const Type *mul_id() const { return TypeLong::MINUS_1; } const Type *add_id() const { return TypeLong::ZERO; } diff --git a/test/hotspot/jtreg/compiler/c2/irTests/TestShiftAndMask.java b/test/hotspot/jtreg/compiler/c2/irTests/TestShiftAndMask.java new file mode 100644 index 00000000000..ca6d59428a8 --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/irTests/TestShiftAndMask.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2021, Red Hat, Inc. 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. + */ + +package compiler.c2.irTests; + +import compiler.lib.ir_framework.*; + +/* + * @test + * @bug 8277850 + * @summary C2: optimize mask checks in counted loops + * @library /test/lib / + * @run driver compiler.c2.irTests.TestShiftAndMask + */ + +public class TestShiftAndMask { + public static void main(String[] args) { + TestFramework.run(); + } + + @Test + @Arguments(Argument.RANDOM_EACH) + @IR(failOn = { IRNode.AND_I, IRNode.LSHIFT_I }) + public static int shiftMaskInt(int i) { + return (i << 2) & 3; // transformed to: return 0; + } + + @Test + @Arguments(Argument.RANDOM_EACH) + @IR(failOn = { IRNode.AND_L, IRNode.LSHIFT_L }) + public static long shiftMaskLong(long i) { + return (i << 2) & 3; // transformed to: return 0; + } + + @Test + @Arguments({Argument.RANDOM_EACH, Argument.RANDOM_EACH}) + @IR(counts = { IRNode.AND_I, "1" }) + @IR(failOn = { IRNode.ADD_I, IRNode.LSHIFT_I }) + public static int addShiftMaskInt(int i, int j) { + return (j + (i << 2)) & 3; // transformed to: return j & 3; + } + + @Test + @Arguments({Argument.RANDOM_EACH, Argument.RANDOM_EACH}) + @IR(counts = { IRNode.AND_L, "1" }) + @IR(failOn = { IRNode.ADD_L, IRNode.LSHIFT_L }) + public static long addShiftMaskLong(long i, long j) { + return (j + (i << 2)) & 3; // transformed to: return j & 3; + } + + @Test + @Arguments({Argument.RANDOM_EACH, Argument.RANDOM_EACH}) + @IR(failOn = { IRNode.AND_I, IRNode.ADD_I, IRNode.LSHIFT_I }) + public static int addShiftMaskInt2(int i, int j) { + return ((j << 2) + (i << 2)) & 3; // transformed to: return 0; + } + + @Test + @Arguments({Argument.RANDOM_EACH, Argument.RANDOM_EACH}) + @IR(failOn = { IRNode.AND_L, IRNode.ADD_L, IRNode.LSHIFT_L }) + public static long addShiftMaskLong2(long i, long j) { + return ((j << 2) + (i << 2)) & 3; // transformed to: return 0; + } + + @Test + @Arguments(Argument.RANDOM_EACH) + @IR(failOn = { IRNode.AND_L, IRNode.LSHIFT_I }) + public static long shiftConvMask(int i) { + return ((long)(i << 2)) & 3; // transformed to: return 0; + } + + @Test + @Arguments({Argument.RANDOM_EACH, Argument.RANDOM_EACH}) + @IR(counts = { IRNode.AND_L, "1" }) + @IR(failOn = { IRNode.ADD_L, IRNode.LSHIFT_I, IRNode.CONV_I2L }) + public static long addShiftConvMask(int i, long j) { + return (j + (i << 2)) & 3; // transformed to: return j & 3; + } + + @Test + @Arguments({Argument.RANDOM_EACH, Argument.RANDOM_EACH}) + @IR(failOn = { IRNode.AND_L, IRNode.ADD_L, IRNode.LSHIFT_L }) + public static long addShiftConvMask2(int i, int j) { + return (((long)(j << 2)) + ((long)(i << 2))) & 3; // transformed to: return 0; + } + +} + diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java index a995cad3f2d..18875cd9377 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java @@ -133,6 +133,14 @@ public class IRNode { public static final String SCOPE_OBJECT = "(.*# ScObj.*" + END; public static final String MEMBAR = START + "MemBar" + MID + END; + public static final String AND_I = START + "AndI" + MID + END; + public static final String AND_L = START + "AndL" + MID + END; + public static final String LSHIFT_I = START + "LShiftI" + MID + END; + public static final String LSHIFT_L = START + "LShiftL" + MID + END; + public static final String ADD_I = START + "AddI" + MID + END; + public static final String ADD_L = START + "AddL" + MID + END; + public static final String CONV_I2L = START + "ConvI2L" + MID + END; + /** * Called by {@link IRMatcher} to merge special composite nodes together with additional user-defined input. */ -- GitLab From 2478158815a9ae0466542e27562bff046d760d3e Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Wed, 8 Dec 2021 17:11:14 +0000 Subject: [PATCH 059/671] 8277361: java/nio/channels/Channels/ReadXBytes.java fails with OOM error Reviewed-by: alanb, lancea --- .../nio/channels/Channels/ReadXBytes.java | 54 +++++++++++++------ 1 file changed, 38 insertions(+), 16 deletions(-) diff --git a/test/jdk/java/nio/channels/Channels/ReadXBytes.java b/test/jdk/java/nio/channels/Channels/ReadXBytes.java index 1f36d4031fd..f146d629da1 100644 --- a/test/jdk/java/nio/channels/Channels/ReadXBytes.java +++ b/test/jdk/java/nio/channels/Channels/ReadXBytes.java @@ -25,12 +25,12 @@ * @test * @bug 8268435 8274780 * @summary Verify ChannelInputStream methods readAllBytes and readNBytes - * @requires vm.bits == 64 + * @requires (sun.arch.data.model == "64" & os.maxMemory >= 16g) * @library .. * @library /test/lib * @build jdk.test.lib.RandomFactory * @modules java.base/jdk.internal.util - * @run testng/othervm/timeout=900 -Xmx8G ReadXBytes + * @run testng/othervm/timeout=900 -Xmx12G ReadXBytes * @key randomness */ import java.io.File; @@ -38,7 +38,7 @@ import java.io.FileInputStream; import java.io.FilterInputStream; import java.io.InputStream; import java.io.IOException; -import java.io.RandomAccessFile; +import java.nio.ByteBuffer; import java.nio.channels.Channel; import java.nio.channels.Channels; import java.nio.channels.FileChannel; @@ -46,11 +46,12 @@ import java.nio.channels.ReadableByteChannel; import java.nio.channels.SeekableByteChannel; import java.nio.file.Files; import java.nio.file.Path; -import static java.nio.file.StandardOpenOption.READ; import java.util.List; import java.util.Random; import jdk.internal.util.ArraysSupport; +import static java.nio.file.StandardOpenOption.*; + import jdk.test.lib.RandomFactory; import org.testng.Assert; @@ -72,30 +73,51 @@ public class ReadXBytes { // A length greater than a 32-bit integer can accommodate private static final long HUGE_LENGTH = Integer.MAX_VALUE + 27L; + // Current directory + private static final Path DIR = Path.of(System.getProperty("test.dir", ".")); + // --- Framework --- + // Create a temporary file path + static Path createFilePath() { + String name = String.format("ReadXBytes%d.tmp", System.nanoTime()); + return DIR.resolve(name); + } + // Creates a temporary file of a specified length with undefined content static Path createFile(long length) throws IOException { - File file = File.createTempFile("foo", ".bar"); - file.deleteOnExit(); - try (RandomAccessFile raf = new RandomAccessFile(file, "rw")) { - raf.setLength(length); + Path path = createFilePath(); + path.toFile().deleteOnExit(); + try (FileChannel fc = FileChannel.open(path, CREATE_NEW, SPARSE, WRITE)) { + if (length > 0) { + fc.position(length - 1); + fc.write(ByteBuffer.wrap(new byte[] {27})); + } } - return file.toPath(); + return path; } // Creates a temporary file of a specified length with random content static Path createFileWithRandomContent(long length) throws IOException { Path file = createFile(length); - try (RandomAccessFile raf = new RandomAccessFile(file.toFile(), "rw")) { - long written = 0L; - int bufLength = Math.min(32768, (int)Math.min(length, BIG_LENGTH)); + try (FileChannel fc = FileChannel.open(file, WRITE);) { + long pos = 0L; + // if the length exceeds 2 GB, skip the first 2 GB - 1 MB bytes + if (length >= 2L*1024*1024*1024) { + // write the last (length - 2GB - 1MB) bytes + pos = 2047L*1024*1024; + } else if (length > 0) { + // write either the first or last bytes only + long p = Math.min(Math.abs(RAND.nextLong()), length - 1); + pos = RAND.nextBoolean() ? p : length - 1 - p; + } + fc.position(pos); + int bufLength = Math.min(32768, (int)Math.min(length - pos, BIG_LENGTH)); byte[] buf = new byte[bufLength]; - while (written < length) { + while (pos < length) { RAND.nextBytes(buf); - int len = (int)Math.min(bufLength, length - written); - raf.write(buf, 0, len); - written += len; + int len = (int)Math.min(bufLength, length - pos); + pos += fc.write(ByteBuffer.wrap(buf, 0, len)); } } return file; -- GitLab From 9b747491de01fd011b09668a67113e80c2b7c708 Mon Sep 17 00:00:00 2001 From: Valerie Peng Date: Wed, 8 Dec 2021 17:44:10 +0000 Subject: [PATCH 060/671] 8276660: Scalability bottleneck in java.security.Provider.getService() Reviewed-by: weijun --- .../share/classes/java/security/Provider.java | 501 ++++++++++-------- 1 file changed, 275 insertions(+), 226 deletions(-) diff --git a/src/java.base/share/classes/java/security/Provider.java b/src/java.base/share/classes/java/security/Provider.java index 11c8eb29ca7..c6c3d63c61f 100644 --- a/src/java.base/share/classes/java/security/Provider.java +++ b/src/java.base/share/classes/java/security/Provider.java @@ -191,6 +191,8 @@ public abstract class Provider extends Properties { this.versionStr = Double.toString(version); this.info = info; this.serviceMap = new ConcurrentHashMap<>(); + this.legacyMap = new ConcurrentHashMap<>(); + this.prngAlgos = new LinkedHashSet(6); putId(); initialized = true; } @@ -229,6 +231,8 @@ public abstract class Provider extends Properties { this.version = parseVersionStr(versionStr); this.info = info; this.serviceMap = new ConcurrentHashMap<>(); + this.legacyMap = new ConcurrentHashMap<>(); + this.prngAlgos = new LinkedHashSet(6); putId(); initialized = true; } @@ -572,7 +576,6 @@ public abstract class Provider extends Properties { public synchronized boolean replace(Object key, Object oldValue, Object newValue) { check("putProviderProperty." + name); - if (debug != null) { debug.println("Replace " + name + " provider property " + key); } @@ -598,7 +601,6 @@ public abstract class Provider extends Properties { @Override public synchronized Object replace(Object key, Object value) { check("putProviderProperty." + name); - if (debug != null) { debug.println("Replace " + name + " provider property " + key); } @@ -627,7 +629,6 @@ public abstract class Provider extends Properties { public synchronized void replaceAll(BiFunction function) { check("putProviderProperty." + name); - if (debug != null) { debug.println("ReplaceAll " + name + " provider property "); } @@ -657,7 +658,6 @@ public abstract class Provider extends Properties { ? super Object, ? extends Object> remappingFunction) { check("putProviderProperty." + name); check("removeProviderProperty." + name); - if (debug != null) { debug.println("Compute " + name + " provider property " + key); } @@ -684,11 +684,10 @@ public abstract class Provider extends Properties { * @since 1.8 */ @Override - public synchronized Object computeIfAbsent(Object key, Function mappingFunction) { + public synchronized Object computeIfAbsent(Object key, + Function mappingFunction) { check("putProviderProperty." + name); check("removeProviderProperty." + name); - if (debug != null) { debug.println("ComputeIfAbsent " + name + " provider property " + key); @@ -714,11 +713,11 @@ public abstract class Provider extends Properties { * @since 1.8 */ @Override - public synchronized Object computeIfPresent(Object key, BiFunction remappingFunction) { + public synchronized Object computeIfPresent(Object key, + BiFunction + remappingFunction) { check("putProviderProperty." + name); check("removeProviderProperty." + name); - if (debug != null) { debug.println("ComputeIfPresent " + name + " provider property " + key); @@ -747,11 +746,11 @@ public abstract class Provider extends Properties { * @since 1.8 */ @Override - public synchronized Object merge(Object key, Object value, BiFunction remappingFunction) { + public synchronized Object merge(Object key, Object value, + BiFunction + remappingFunction) { check("putProviderProperty." + name); check("removeProviderProperty." + name); - if (debug != null) { debug.println("Merge " + name + " provider property " + key); } @@ -777,7 +776,8 @@ public abstract class Provider extends Properties { * @since 1.8 */ @Override - public synchronized void forEach(BiConsumer action) { + public synchronized void forEach(BiConsumer + action) { checkInitialized(); super.forEach(action); } @@ -817,14 +817,11 @@ public abstract class Provider extends Properties { } } - // legacy properties changed since last call to any services method? - private transient boolean legacyChanged; + // legacyMap changed since last call to getServices() + private transient volatile boolean legacyChanged; // serviceMap changed since last call to getServices() private transient volatile boolean servicesChanged; - // Map used to keep track of legacy registration - private transient Map legacyStrings; - // Map // used for services added via putService(), initialized on demand private transient Map serviceMap; @@ -832,6 +829,9 @@ public abstract class Provider extends Properties { // For backward compatibility, the registration ordering of // SecureRandom (RNG) algorithms needs to be preserved for // "new SecureRandom()" calls when this provider is used + // NOTE: may need extra mechanism for providers to indicate their + // preferred ordering of SecureRandom algorithms since registration + // ordering info is lost once serialized private transient Set prngAlgos; // Map @@ -840,7 +840,7 @@ public abstract class Provider extends Properties { // Set // Unmodifiable set of all services. Initialized on demand. - private transient Set serviceSet; + private transient volatile Set serviceSet; // register the id attributes for this provider // this is to ensure that equals() and hashCode() do not incorrectly @@ -872,6 +872,7 @@ public abstract class Provider extends Properties { for (Map.Entry entry : super.entrySet()) { copy.put(entry.getKey(), entry.getValue()); } + defaults = null; in.defaultReadObject(); if (this.versionStr == null) { @@ -882,23 +883,22 @@ public abstract class Provider extends Properties { this.version = parseVersionStr(this.versionStr); } this.serviceMap = new ConcurrentHashMap<>(); + this.legacyMap = new ConcurrentHashMap<>(); + this.prngAlgos = new LinkedHashSet(6); implClear(); initialized = true; putAll(copy); } - // check whether to update 'legacyString' with the specified key - private boolean checkLegacy(Object key) { - String keyString = (String)key; - if (keyString.startsWith("Provider.")) { + // returns false if no update necessary, i.e. key isn't String or + // is String but it's provider-related (name/version/info/className) + private static boolean checkLegacy(Object key) { + if (key instanceof String && ((String)key).startsWith("Provider.")) { + // ignore provider related updates return false; + } else { + return true; } - - legacyChanged = true; - if (legacyStrings == null) { - legacyStrings = new LinkedHashMap<>(); - } - return true; } /** @@ -913,149 +913,161 @@ public abstract class Provider extends Properties { } private Object implRemove(Object key) { - if (key instanceof String) { - if (!checkLegacy(key)) { - return null; - } - legacyStrings.remove((String)key); + if (!checkLegacy(key)) return null; + + Object o = super.remove(key); + if (o instanceof String so && key instanceof String sk) { + parseLegacy(sk, so, OPType.REMOVE); } - return super.remove(key); + return o; } private boolean implRemove(Object key, Object value) { - if (key instanceof String && value instanceof String) { - if (!checkLegacy(key)) { - return false; - } - legacyStrings.remove((String)key, (String)value); + if (!checkLegacy(key)) return false; + + boolean result = super.remove(key, value); + if (result && key instanceof String sk && value instanceof String sv) { + parseLegacy(sk, sv, OPType.REMOVE); } - return super.remove(key, value); + return result; } private boolean implReplace(Object key, Object oldValue, Object newValue) { - if ((key instanceof String) && (oldValue instanceof String) && - (newValue instanceof String)) { - if (!checkLegacy(key)) { - return false; + if (!checkLegacy(key)) return false; + + boolean result = super.replace(key, oldValue, newValue); + if (result && key instanceof String sk) { + if (newValue instanceof String sv) { + parseLegacy(sk, sv, OPType.ADD); + } else if (oldValue instanceof String sv) { + parseLegacy(sk, sv, OPType.REMOVE); } - legacyStrings.replace((String)key, (String)oldValue, - (String)newValue); } - return super.replace(key, oldValue, newValue); + return result; } private Object implReplace(Object key, Object value) { - if ((key instanceof String) && (value instanceof String)) { - if (!checkLegacy(key)) { - return null; + if (!checkLegacy(key)) return null; + + Object o = super.replace(key, value); + if (key instanceof String sk) { + if (o instanceof String so) { + if (value instanceof String sv) { + parseLegacy(sk, sv, OPType.ADD); + } else { + parseLegacy(sk, so, OPType.REMOVE); + } } - legacyStrings.replace((String)key, (String)value); } - return super.replace(key, value); + return o; } @SuppressWarnings("unchecked") // Function must actually operate over strings private void implReplaceAll(BiFunction function) { + + super.replaceAll(function); + // clear out all existing mappings and start fresh + legacyMap.clear(); legacyChanged = true; - if (legacyStrings == null) { - legacyStrings = new LinkedHashMap<>(); - } else { - legacyStrings.replaceAll((BiFunction) function); + for (Map.Entry entry : super.entrySet()) { + Object key = entry.getKey(); + Object value = entry.getValue(); + if ((key instanceof String sk) && (value instanceof String sv)) { + if (!checkLegacy(sk)) { + continue; + } + parseLegacy(sk, sv, OPType.ADD); + } } - super.replaceAll(function); } @SuppressWarnings("unchecked") // Function must actually operate over strings private Object implMerge(Object key, Object value, BiFunction remappingFunction) { - if ((key instanceof String) && (value instanceof String)) { - if (!checkLegacy(key)) { - return null; + if (!checkLegacy(key)) return null; + + Object o = super.merge(key, value, remappingFunction); + if (key instanceof String sk) { + if (o == null) { + parseLegacy(sk, null, OPType.REMOVE); + } else if (o instanceof String so) { + parseLegacy(sk, so, OPType.ADD); } - legacyStrings.merge((String)key, (String)value, - (BiFunction) remappingFunction); } - return super.merge(key, value, remappingFunction); + return o; } @SuppressWarnings("unchecked") // Function must actually operate over strings private Object implCompute(Object key, BiFunction remappingFunction) { - if (key instanceof String) { - if (!checkLegacy(key)) { - return null; + + if (!checkLegacy(key)) return null; + + Object o = super.compute(key, remappingFunction); + if (key instanceof String sk) { + if (o == null) { + parseLegacy(sk, null, OPType.REMOVE); + } else if (o instanceof String so) { + parseLegacy(sk, so, OPType.ADD); } - legacyStrings.compute((String) key, - (BiFunction) remappingFunction); } - return super.compute(key, remappingFunction); + return o; } @SuppressWarnings("unchecked") // Function must actually operate over strings private Object implComputeIfAbsent(Object key, Function mappingFunction) { - if (key instanceof String) { - if (!checkLegacy(key)) { - return null; - } - legacyStrings.computeIfAbsent((String) key, - (Function) - mappingFunction); + if (!checkLegacy(key)) return null; + + Object o = super.computeIfAbsent(key, mappingFunction); + if (o instanceof String so && key instanceof String sk) { + parseLegacy(sk, so, OPType.ADD); } - return super.computeIfAbsent(key, mappingFunction); + return o; } @SuppressWarnings("unchecked") // Function must actually operate over strings private Object implComputeIfPresent(Object key, BiFunction remappingFunction) { - if (key instanceof String) { - if (!checkLegacy(key)) { - return null; - } - legacyStrings.computeIfPresent((String) key, - (BiFunction) remappingFunction); + if (!checkLegacy(key)) return null; + + Object o = super.computeIfPresent(key, remappingFunction); + if (o instanceof String so && key instanceof String sk) { + parseLegacy(sk, so, OPType.ADD); } - return super.computeIfPresent(key, remappingFunction); + return o; } private Object implPut(Object key, Object value) { - if ((key instanceof String) && (value instanceof String)) { - if (!checkLegacy(key)) { - return null; - } - legacyStrings.put((String)key, (String)value); + if (!checkLegacy(key)) return null; + + Object o = super.put(key, value); + if (key instanceof String sk && value instanceof String sv) { + parseLegacy(sk, sv, OPType.ADD); } - return super.put(key, value); + return o; } private Object implPutIfAbsent(Object key, Object value) { - if ((key instanceof String) && (value instanceof String)) { - if (!checkLegacy(key)) { - return null; - } - legacyStrings.putIfAbsent((String)key, (String)value); + if (!checkLegacy(key)) return null; + + Object o = super.putIfAbsent(key, value); + if (o == null && key instanceof String sk && + value instanceof String sv) { + parseLegacy(sk, sv, OPType.ADD); } - return super.putIfAbsent(key, value); + return o; } private void implClear() { - if (legacyStrings != null) { - legacyStrings.clear(); - } - if (legacyMap != null) { - legacyMap.clear(); - } + legacyMap.clear(); serviceMap.clear(); legacyChanged = false; servicesChanged = false; serviceSet = null; - prngAlgos = null; + prngAlgos.clear(); super.clear(); putId(); } @@ -1085,40 +1097,8 @@ public abstract class Provider extends Properties { boolean matches(String type, String algorithm) { return (this.type == type) && (this.originalAlgorithm == algorithm); } - } - - /** - * Ensure all the legacy String properties are fully parsed into - * service objects. - */ - private void ensureLegacyParsed() { - if (legacyChanged == false || (legacyStrings == null)) { - return; - } - serviceSet = null; - if (legacyMap == null) { - legacyMap = new ConcurrentHashMap<>(); - } else { - legacyMap.clear(); - } - for (Map.Entry entry : legacyStrings.entrySet()) { - parseLegacyPut(entry.getKey(), entry.getValue()); - } - removeInvalidServices(legacyMap); - legacyChanged = false; - } - - /** - * Remove all invalid services from the Map. Invalid services can only - * occur if the legacy properties are inconsistent or incomplete. - */ - private void removeInvalidServices(Map map) { - for (Iterator> t = - map.entrySet().iterator(); t.hasNext(); ) { - Service s = t.next().getValue(); - if (s.isValid() == false) { - t.remove(); - } + public String toString() { + return type + "." + algorithm; } } @@ -1136,71 +1116,136 @@ public abstract class Provider extends Properties { return new String[] {type, alg}; } + // utility method for getting a String with service type and algorithm + private static String getKey(Service s) { + return s.getType() + "." + s.getAlgorithm(); + } + private static final String ALIAS_PREFIX = "Alg.Alias."; private static final String ALIAS_PREFIX_LOWER = "alg.alias."; private static final int ALIAS_LENGTH = ALIAS_PREFIX.length(); - private void parseLegacyPut(String name, String value) { + private static enum OPType { + ADD, REMOVE; + } + + private void parseLegacy(String name, String value, OPType opType) { + // alias if (name.toLowerCase(ENGLISH).startsWith(ALIAS_PREFIX_LOWER)) { // e.g. put("Alg.Alias.MessageDigest.SHA", "SHA-1"); // aliasKey ~ MessageDigest.SHA - String stdAlg = value; - String aliasKey = name.substring(ALIAS_LENGTH); - String[] typeAndAlg = getTypeAndAlgorithm(aliasKey); + String aliasKeyStr = name.substring(ALIAS_LENGTH); + String[] typeAndAlg = getTypeAndAlgorithm(aliasKeyStr); if (typeAndAlg == null) { return; } + legacyChanged = true; + Objects.requireNonNull(value, "alias value should map to an alg"); String type = getEngineName(typeAndAlg[0]); String aliasAlg = typeAndAlg[1].intern(); - ServiceKey key = new ServiceKey(type, stdAlg, true); - Service s = legacyMap.get(key); - if (s == null) { - s = new Service(this, type, stdAlg); - legacyMap.put(key, s); + ServiceKey stdKey = new ServiceKey(type, value, true); + Service stdService = legacyMap.get(stdKey); + ServiceKey aliasKey = new ServiceKey(type, aliasAlg, true); + switch (opType) { + case ADD: + // clean up old alias if present + Service prevAliasService = legacyMap.get(aliasAlg); + if (prevAliasService != null) { + prevAliasService.removeAlias(aliasAlg); + } + if (stdService == null) { + // add standard mapping in order to add alias + stdService = new Service(this, type, value); + legacyMap.put(stdKey, stdService); + } + stdService.addAlias(aliasAlg); + legacyMap.put(aliasKey, stdService); + break; + case REMOVE: + if (stdService != null) { + stdService.removeAlias(aliasAlg); + } + legacyMap.remove(aliasKey); + break; + default: + throw new AssertionError(); } - legacyMap.put(new ServiceKey(type, aliasAlg, true), s); - s.addAlias(aliasAlg); } else { String[] typeAndAlg = getTypeAndAlgorithm(name); if (typeAndAlg == null) { return; } + legacyChanged = true; int i = typeAndAlg[1].indexOf(' '); + // regular registration if (i == -1) { // e.g. put("MessageDigest.SHA-1", "sun.security.provider.SHA"); String type = getEngineName(typeAndAlg[0]); String stdAlg = typeAndAlg[1].intern(); - String className = value; - ServiceKey key = new ServiceKey(type, stdAlg, true); - Service s = legacyMap.get(key); - if (s == null) { - s = new Service(this, type, stdAlg); - legacyMap.put(key, s); - } - s.className = className; - - if (type.equals("SecureRandom")) { - updateSecureRandomEntries(true, s.algorithm); + ServiceKey stdKey = new ServiceKey(type, stdAlg, true); + Service stdService = legacyMap.get(stdKey); + switch (opType) { + case ADD: + Objects.requireNonNull(value, + "className can't be null"); + if (stdService == null) { + stdService = new Service(this, type, stdAlg); + legacyMap.put(stdKey, stdService); + } + stdService.className = value; + break; + case REMOVE: + // only remove if value also matches when non-null + if (stdService != null) { + if (value == null) { + legacyMap.remove(stdKey); + } else if (stdService.className.equals(value)) { + legacyMap.remove(stdKey, stdService); + } + // remove all corresponding alias mappings + for (String alias : stdService.getAliases()) { + legacyMap.remove(new ServiceKey(type, alias, + true), stdService); + } + } + break; + default: + throw new AssertionError(); } + checkAndUpdateSecureRandom(type, stdAlg, + (opType != OPType.REMOVE)); } else { // attribute // e.g. put("MessageDigest.SHA-1 ImplementedIn", "Software"); - String attributeValue = value; String type = getEngineName(typeAndAlg[0]); - String attributeString = typeAndAlg[1]; - String stdAlg = attributeString.substring(0, i).intern(); - String attributeName = attributeString.substring(i + 1); + String attrString = typeAndAlg[1]; + String stdAlg = attrString.substring(0, i).intern(); + String attrName = attrString.substring(i + 1); // kill additional spaces - while (attributeName.startsWith(" ")) { - attributeName = attributeName.substring(1); + while (attrName.startsWith(" ")) { + attrName = attrName.substring(1); } - attributeName = attributeName.intern(); - ServiceKey key = new ServiceKey(type, stdAlg, true); - Service s = legacyMap.get(key); - if (s == null) { - s = new Service(this, type, stdAlg); - legacyMap.put(key, s); + attrName = attrName.intern(); + ServiceKey stdKey = new ServiceKey(type, stdAlg, true); + Service stdService = legacyMap.get(stdKey); + switch (opType) { + case ADD: + Objects.requireNonNull(value, + "attribute value should not be null"); + + if (stdService == null) { + stdService = new Service(this, type, stdAlg); + legacyMap.put(stdKey, stdService); + } + stdService.addAttribute(attrName, value); + break; + case REMOVE: + if (stdService != null) { + stdService.removeAttribute(attrName, value); + } + break; + default: + throw new AssertionError(); } - s.addAttribute(attributeName, attributeValue); } } } @@ -1227,25 +1272,25 @@ public abstract class Provider extends Properties { */ public Service getService(String type, String algorithm) { checkInitialized(); - // avoid allocating a new ServiceKey object if possible ServiceKey key = previousKey; if (key.matches(type, algorithm) == false) { key = new ServiceKey(type, algorithm, false); previousKey = key; } - if (!serviceMap.isEmpty()) { - Service s = serviceMap.get(key); - if (s != null) { - return s; - } + + Service s = serviceMap.get(key); + if (s != null) { + return s; } - synchronized (this) { - ensureLegacyParsed(); - if (legacyMap != null && !legacyMap.isEmpty()) { - return legacyMap.get(key); - } + + s = legacyMap.get(key); + if (s != null && !s.isValid()) { + legacyMap.remove(key, s); + } else { + return s; } + return null; } @@ -1267,22 +1312,19 @@ public abstract class Provider extends Properties { * * @since 1.5 */ - public synchronized Set getServices() { + public Set getServices() { checkInitialized(); - if (legacyChanged || servicesChanged) { - serviceSet = null; - } - if (serviceSet == null) { - ensureLegacyParsed(); + if (serviceSet == null || legacyChanged || servicesChanged) { Set set = new LinkedHashSet<>(); if (!serviceMap.isEmpty()) { set.addAll(serviceMap.values()); } - if (legacyMap != null && !legacyMap.isEmpty()) { + if (!legacyMap.isEmpty()) { set.addAll(legacyMap.values()); } serviceSet = Collections.unmodifiableSet(set); servicesChanged = false; + legacyChanged = false; } return serviceSet; } @@ -1339,44 +1381,36 @@ public abstract class Provider extends Properties { servicesChanged = true; synchronized (this) { putPropertyStrings(s); - if (type.equals("SecureRandom")) { - updateSecureRandomEntries(true, s.algorithm); - } + checkAndUpdateSecureRandom(type, algorithm, true); } } - // keep tracks of the registered secure random algos and store them in order - private void updateSecureRandomEntries(boolean doAdd, String s) { - Objects.requireNonNull(s); - if (doAdd) { - if (prngAlgos == null) { - prngAlgos = new LinkedHashSet(); + private void checkAndUpdateSecureRandom(String type, String algo, + boolean doAdd) { + if (type.equalsIgnoreCase("SecureRandom")) { + if (doAdd) { + prngAlgos.add(algo); + } else { + prngAlgos.remove(algo); + } + if (debug != null) { + debug.println((doAdd? "Add":"Remove") + + " SecureRandom algo " + algo); } - prngAlgos.add(s); - } else { - prngAlgos.remove(s); - } - - if (debug != null) { - debug.println((doAdd? "Add":"Remove") + " SecureRandom algo " + s); } } // used by new SecureRandom() to find out the default SecureRandom // service for this provider - synchronized Service getDefaultSecureRandomService() { + Service getDefaultSecureRandomService() { checkInitialized(); - if (legacyChanged) { - prngAlgos = null; - ensureLegacyParsed(); - } - - if (prngAlgos != null && !prngAlgos.isEmpty()) { + if (!prngAlgos.isEmpty()) { + String algo = prngAlgos.iterator().next(); // IMPORTANT: use the Service obj returned by getService(...) call // as providers may override putService(...)/getService(...) and // return their own Service objects - return getService("SecureRandom", prngAlgos.iterator().next()); + return getService("SecureRandom", algo); } return null; @@ -1473,12 +1507,9 @@ public abstract class Provider extends Properties { for (String alias : s.getAliases()) { serviceMap.remove(new ServiceKey(type, alias, false)); } - synchronized (this) { - removePropertyStrings(s); - if (type.equals("SecureRandom")) { - updateSecureRandomEntries(false, s.algorithm); - } - } + + removePropertyStrings(s); + checkAndUpdateSecureRandom(type, algorithm, false); } // Wrapped String that behaves in a case insensitive way for equals/hashCode @@ -1686,6 +1717,13 @@ public abstract class Provider extends Properties { aliases.add(alias); } + private void removeAlias(String alias) { + if (aliases.isEmpty()) { + return; + } + aliases.remove(alias); + } + void addAttribute(String type, String value) { if (attributes.isEmpty()) { attributes = new HashMap<>(8); @@ -1693,6 +1731,17 @@ public abstract class Provider extends Properties { attributes.put(new UString(type), value); } + void removeAttribute(String type, String value) { + if (attributes.isEmpty()) { + return; + } + if (value == null) { + attributes.remove(new UString(type)); + } else { + attributes.remove(new UString(type), value); + } + } + /** * Construct a new service. * -- GitLab From 83454530ea538c80e2f1205cd8d2f9732503b592 Mon Sep 17 00:00:00 2001 From: Alexey Ushakov Date: Wed, 8 Dec 2021 17:48:53 +0000 Subject: [PATCH 061/671] 8272392: Lanai: SwingSet2. Black background on expanding tree node Reviewed-by: aghaisas, jdv --- .../java2d/metal/EncoderManager.m | 40 ++++++-------- .../libawt_lwawt/java2d/metal/MTLBlitLoops.m | 5 +- .../libawt_lwawt/java2d/metal/MTLClip.m | 3 - .../libawt_lwawt/java2d/metal/MTLPaints.m | 25 ++++----- .../java2d/metal/MTLPipelineStatesStorage.m | 55 +++++++++---------- .../libawt_lwawt/java2d/metal/RenderOptions.h | 1 - .../native/libawt_lwawt/java2d/metal/common.h | 1 - 7 files changed, 57 insertions(+), 73 deletions(-) diff --git a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/EncoderManager.m b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/EncoderManager.m index 0fb18c3f4c3..95374d2c93e 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/EncoderManager.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/EncoderManager.m @@ -41,11 +41,9 @@ const SurfaceRasterFlags defaultRasterFlags = { JNI_FALSE, JNI_TRUE }; - (void)dealloc; - (void)reset:(id)destination - isDstOpaque:(jboolean)isDstOpaque - isDstPremultiplied:(jboolean)isDstPremultiplied - isAA:(jboolean)isAA - isText:(jboolean)isText - isLCD:(jboolean)isLCD; + isAA:(jboolean)isAA + isText:(jboolean)isText + isLCD:(jboolean)isLCD; - (void)updateEncoder:(id)encoder context:(MTLContext *)mtlc @@ -64,7 +62,6 @@ const SurfaceRasterFlags defaultRasterFlags = { JNI_FALSE, JNI_TRUE }; // Persistent encoder properties id _destination; - SurfaceRasterFlags _dstFlags; jboolean _isAA; jboolean _isText; @@ -123,14 +120,10 @@ const SurfaceRasterFlags defaultRasterFlags = { JNI_FALSE, JNI_TRUE }; } - (void)reset:(id)destination - isDstOpaque:(jboolean)isDstOpaque - isDstPremultiplied:(jboolean)isDstPremultiplied - isAA:(jboolean)isAA - isText:(jboolean)isText - isLCD:(jboolean)isLCD { + isAA:(jboolean)isAA + isText:(jboolean)isText + isLCD:(jboolean)isLCD { _destination = destination; - _dstFlags.isOpaque = isDstOpaque; - _dstFlags.isPremultiplied = isDstPremultiplied; _isAA = isAA; _isText = isText; _isLCD = isLCD; @@ -288,20 +281,20 @@ const SurfaceRasterFlags defaultRasterFlags = { JNI_FALSE, JNI_TRUE }; - (id _Nonnull)getAARenderEncoder:(const BMTLSDOps * _Nonnull)dstOps { id dstTxt = dstOps->pTexture; - RenderOptions roptions = {JNI_FALSE, JNI_TRUE, INTERPOLATION_NEAREST_NEIGHBOR, defaultRasterFlags, {dstOps->isOpaque, JNI_TRUE}, JNI_FALSE, JNI_FALSE, JNI_FALSE}; + RenderOptions roptions = {JNI_FALSE, JNI_TRUE, INTERPOLATION_NEAREST_NEIGHBOR, defaultRasterFlags, JNI_FALSE, JNI_FALSE, JNI_FALSE}; return [self getEncoder:dstTxt renderOptions:&roptions]; } - (id _Nonnull)getAAShaderRenderEncoder:(const BMTLSDOps * _Nonnull)dstOps { - RenderOptions roptions = {JNI_FALSE, JNI_FALSE, INTERPOLATION_NEAREST_NEIGHBOR, defaultRasterFlags, {dstOps->isOpaque, JNI_TRUE}, JNI_FALSE, JNI_FALSE, JNI_TRUE}; + RenderOptions roptions = {JNI_FALSE, JNI_FALSE, INTERPOLATION_NEAREST_NEIGHBOR, defaultRasterFlags, JNI_FALSE, JNI_FALSE, JNI_TRUE}; return [self getEncoder:dstOps->pTexture renderOptions:&roptions]; } - (id _Nonnull)getRenderEncoder:(id _Nonnull)dest isDstOpaque:(bool)isOpaque { - RenderOptions roptions = {JNI_FALSE, JNI_FALSE, INTERPOLATION_NEAREST_NEIGHBOR, defaultRasterFlags, {isOpaque, JNI_TRUE}, JNI_FALSE, JNI_FALSE, JNI_FALSE}; + RenderOptions roptions = {JNI_FALSE, JNI_FALSE, INTERPOLATION_NEAREST_NEIGHBOR, defaultRasterFlags, JNI_FALSE, JNI_FALSE, JNI_FALSE}; return [self getEncoder:dest renderOptions:&roptions]; } @@ -329,7 +322,7 @@ const SurfaceRasterFlags defaultRasterFlags = { JNI_FALSE, JNI_TRUE }; isSrcOpaque:(bool)isSrcOpaque isDstOpaque:(bool)isDstOpaque { - RenderOptions roptions = {JNI_TRUE, JNI_FALSE, INTERPOLATION_NEAREST_NEIGHBOR, {isSrcOpaque, JNI_TRUE }, {isDstOpaque, JNI_TRUE}, JNI_FALSE, JNI_TRUE, JNI_FALSE}; + RenderOptions roptions = {JNI_TRUE, JNI_FALSE, INTERPOLATION_NEAREST_NEIGHBOR, {isSrcOpaque, JNI_TRUE }, JNI_FALSE, JNI_TRUE, JNI_FALSE}; return [self getEncoder:dest renderOptions:&roptions]; } @@ -339,7 +332,7 @@ const SurfaceRasterFlags defaultRasterFlags = { JNI_FALSE, JNI_TRUE }; interpolation:(int)interpolation isAA:(jboolean)isAA { - RenderOptions roptions = {JNI_TRUE, isAA, interpolation, { isSrcOpaque, JNI_TRUE }, {isDstOpaque, JNI_TRUE}, JNI_FALSE, JNI_FALSE, JNI_FALSE}; + RenderOptions roptions = {JNI_TRUE, isAA, interpolation, { isSrcOpaque, JNI_TRUE }, JNI_FALSE, JNI_FALSE, JNI_FALSE}; return [self getEncoder:dest renderOptions:&roptions]; } @@ -354,7 +347,8 @@ const SurfaceRasterFlags defaultRasterFlags = { JNI_FALSE, JNI_TRUE }; - (id _Nonnull) getTextEncoder:(const BMTLSDOps * _Nonnull)dstOps isSrcOpaque:(bool)isSrcOpaque { - RenderOptions roptions = {JNI_TRUE, JNI_FALSE, INTERPOLATION_NEAREST_NEIGHBOR, { isSrcOpaque, JNI_TRUE }, {dstOps->isOpaque, JNI_TRUE}, JNI_TRUE, JNI_FALSE, JNI_FALSE}; + RenderOptions roptions = {JNI_TRUE, JNI_FALSE, INTERPOLATION_NEAREST_NEIGHBOR, { isSrcOpaque, JNI_TRUE }, + JNI_TRUE, JNI_FALSE, JNI_FALSE}; return [self getEncoder:dstOps->pTexture renderOptions:&roptions]; } @@ -437,11 +431,9 @@ const SurfaceRasterFlags defaultRasterFlags = { JNI_FALSE, JNI_TRUE }; _encoder = [[cbw getCommandBuffer] renderCommandEncoderWithDescriptor:rpd]; [_encoderStates reset:dest - isDstOpaque:renderOptions->dstFlags.isOpaque - isDstPremultiplied:YES - isAA:renderOptions->isAA - isText:renderOptions->isText - isLCD:renderOptions->isLCD]; + isAA:renderOptions->isAA + isText:renderOptions->isText + isLCD:renderOptions->isLCD]; } // diff --git a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLBlitLoops.m b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLBlitLoops.m index bf55d8c8976..47571a5e7ae 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLBlitLoops.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLBlitLoops.m @@ -595,8 +595,9 @@ MTLBlitLoops_Blit(JNIEnv *env, } #ifdef TRACE_BLIT - J2dTraceImpl(J2D_TRACE_VERBOSE, JNI_FALSE, - "MTLBlitLoops_Blit [tx=%d, xf=%d, AC=%s]: bdst=%s, src=%p (%dx%d) O=%d premul=%d | (%d, %d, %d, %d)->(%1.2f, %1.2f, %1.2f, %1.2f)", + J2dTraceImpl(J2D_TRACE_VERBOSE, JNI_TRUE, + "MTLBlitLoops_Blit srctype=%d [tx=%d, xf=%d, AC=%s]: bdst=%s, src=%p (%dx%d) O=%d premul=%d | (%d, " + "%d, %d, %d)->(%1.2f, %1.2f, %1.2f, %1.2f)", srctype, texture, xform, [mtlc getCompositeDescription].cString, getSurfaceDescription(dstOps).cString, srcOps, sx2 - sx1, sy2 - sy1, diff --git a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLClip.m b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLClip.m index 35d8ba624c9..effe7aebae6 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLClip.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLClip.m @@ -58,7 +58,6 @@ static void initTemplatePipelineDescriptors() { BMTLSDOps* _dstOps; BOOL _stencilMaskGenerationInProgress; BOOL _stencilMaskGenerationStarted; - BOOL _clipReady; MTLOrigin _clipShapeOrigin; MTLSize _clipShapeSize; } @@ -73,7 +72,6 @@ static void initTemplatePipelineDescriptors() { _dstOps = NULL; _stencilMaskGenerationInProgress = NO; _stencilMaskGenerationStarted = NO; - _clipReady = NO; } return self; } @@ -189,7 +187,6 @@ static void initTemplatePipelineDescriptors() { _stencilMaskGenerationStarted = NO; _dstOps = dstOps; _clipType = SHAPE_CLIP; - _clipReady = NO; } - (void)setMaskGenerationPipelineState:(id)encoder diff --git a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLPaints.m b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLPaints.m index a3b1254bf13..5686449a295 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLPaints.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLPaints.m @@ -56,7 +56,7 @@ static MTLRenderPipelineDescriptor * templateLCDPipelineDesc = nil; static MTLRenderPipelineDescriptor * templateAAPipelineDesc = nil; static void setTxtUniforms(MTLContext *mtlc, int color, id encoder, int interpolation, bool repeat, - jfloat extraAlpha, const SurfaceRasterFlags *srcFlags, const SurfaceRasterFlags *dstFlags, int mode); + jfloat extraAlpha, const SurfaceRasterFlags *srcFlags, int mode); static void initTemplatePipelineDescriptors() { if (templateRenderPipelineDesc != nil && templateTexturePipelineDesc != nil && @@ -228,8 +228,8 @@ jint _color; rpDesc = [[templateLCDPipelineDesc copy] autorelease]; } setTxtUniforms(mtlc, _color, encoder, - renderOptions->interpolation, NO, [mtlc.composite getExtraAlpha], &renderOptions->srcFlags, - &renderOptions->dstFlags, 1); + renderOptions->interpolation, NO, [mtlc.composite getExtraAlpha], + &renderOptions->srcFlags, 1); } else if (renderOptions->isAAShader) { vertShader = @"vert_col_aa"; fragShader = @"frag_col_aa"; @@ -270,7 +270,7 @@ jint _color; setTxtUniforms(mtlc, col, encoder, renderOptions->interpolation, NO, [mtlc.composite getExtraAlpha], - &renderOptions->srcFlags, &renderOptions->dstFlags, 1); + &renderOptions->srcFlags, 1); [encoder setFragmentBytes:&xorColor length:sizeof(xorColor) atIndex:0]; [encoder setFragmentTexture:dstOps->pTexture atIndex:1]; @@ -809,9 +809,8 @@ jint _color; [encoder setFragmentTexture:_paintTexture atIndex:0]; } const SurfaceRasterFlags srcFlags = {_isOpaque, renderOptions->srcFlags.isPremultiplied}; - setTxtUniforms(mtlc, 0, encoder, - renderOptions->interpolation, YES, [mtlc.composite getExtraAlpha], - &srcFlags, &renderOptions->dstFlags, 0); + setTxtUniforms(mtlc, 0, encoder, renderOptions->interpolation, YES, [mtlc.composite getExtraAlpha], + &srcFlags, 0); id pipelineState = [pipelineStateStorage getPipelineState:rpDesc vertexShaderId:vertShader @@ -893,8 +892,8 @@ jint _color; static void setTxtUniforms(MTLContext *mtlc, int color, id encoder, int interpolation, bool repeat, - jfloat extraAlpha, const SurfaceRasterFlags *srcFlags, const SurfaceRasterFlags *dstFlags, int mode) { - struct TxtFrameUniforms uf = {RGBA_TO_V4(color), mode, srcFlags->isOpaque, dstFlags->isOpaque, extraAlpha}; + jfloat extraAlpha, const SurfaceRasterFlags *srcFlags, int mode) { + struct TxtFrameUniforms uf = {RGBA_TO_V4(color), mode, srcFlags->isOpaque, extraAlpha}; [encoder setFragmentBytes:&uf length:sizeof(uf) atIndex:FrameUniformBuffer]; [mtlc.samplerManager setSamplerWithEncoder:encoder interpolation:interpolation repeat:repeat]; } @@ -956,8 +955,7 @@ setTxtUniforms(MTLContext *mtlc, int color, id encoder } else { setTxtUniforms(mtlc, 0, encoder, renderOptions->interpolation, NO, [mtlc.composite getExtraAlpha], - &renderOptions->srcFlags, - &renderOptions->dstFlags, 0); + &renderOptions->srcFlags, 0); } id pipelineState = [pipelineStateStorage getPipelineState:rpDesc @@ -998,7 +996,7 @@ setTxtUniforms(MTLContext *mtlc, int color, id encoder const int col = 0 ^ xorColor; setTxtUniforms(mtlc, col, encoder, renderOptions->interpolation, NO, [mtlc.composite getExtraAlpha], - &renderOptions->srcFlags, &renderOptions->dstFlags, 0); + &renderOptions->srcFlags, 0); [encoder setFragmentBytes:&xorColor length:sizeof(xorColor) atIndex: 0]; BMTLSDOps *dstOps = MTLRenderQueue_GetCurrentDestination(); @@ -1006,8 +1004,7 @@ setTxtUniforms(MTLContext *mtlc, int color, id encoder setTxtUniforms(mtlc, 0, encoder, renderOptions->interpolation, NO, [mtlc.composite getExtraAlpha], - &renderOptions->srcFlags, - &renderOptions->dstFlags, 0); + &renderOptions->srcFlags, 0); id pipelineState = [pipelineStateStorage getPipelineState:rpDesc vertexShaderId:vertShader diff --git a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLPipelineStatesStorage.m b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLPipelineStatesStorage.m index 0928f12d426..9a7862e8c26 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLPipelineStatesStorage.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLPipelineStatesStorage.m @@ -84,7 +84,7 @@ static void setBlendingFactors( vertexShaderId:(NSString *)vertexShaderId fragmentShaderId:(NSString *)fragmentShaderId { - RenderOptions defaultOptions = {JNI_FALSE, JNI_FALSE, 0/*unused*/, {JNI_FALSE, JNI_TRUE}, {JNI_FALSE, JNI_TRUE}, JNI_FALSE, JNI_FALSE, JNI_FALSE}; + RenderOptions defaultOptions = {JNI_FALSE, JNI_FALSE, 0/*unused*/, {JNI_FALSE, JNI_TRUE}, JNI_FALSE, JNI_FALSE, JNI_FALSE}; return [self getPipelineState:pipelineDescriptor vertexShaderId:vertexShaderId fragmentShaderId:fragmentShaderId @@ -98,7 +98,7 @@ static void setBlendingFactors( fragmentShaderId:(NSString *)fragmentShaderId stencilNeeded:(bool)stencilNeeded { - RenderOptions defaultOptions = {JNI_FALSE, JNI_FALSE, 0/*unused*/, {JNI_FALSE, JNI_TRUE}, {JNI_FALSE, JNI_TRUE}, JNI_FALSE, JNI_FALSE, JNI_FALSE}; + RenderOptions defaultOptions = {JNI_FALSE, JNI_FALSE, 0/*unused*/, {JNI_FALSE, JNI_TRUE}, JNI_FALSE, JNI_FALSE, JNI_FALSE}; return [self getPipelineState:pipelineDescriptor vertexShaderId:vertexShaderId fragmentShaderId:fragmentShaderId @@ -107,6 +107,19 @@ static void setBlendingFactors( stencilNeeded:stencilNeeded]; } +// Pipeline state index +union StateIndex { + uint32_t value; + struct { + uint32_t srcPremultiplied : 1, + srcOpaque : 1, + stencil : 1, + aa : 1, + extAlpha : 1, + compositeRule : 27; + } bits; +}; + // Base method to obtain MTLRenderPipelineState. // NOTE: parameters compositeRule, srcFlags, dstFlags are used to set MTLRenderPipelineColorAttachmentDescriptor multipliers - (id) getPipelineState:(MTLRenderPipelineDescriptor *) pipelineDescriptor @@ -123,45 +136,31 @@ static void setBlendingFactors( // Calculate index by flags and compositeRule // TODO: reimplement, use map with convenient key (calculated by all arguments) - int subIndex = 0; + union StateIndex index; + index.value = 0; if (useXorComposite) { // compositeRule value is already XOR_COMPOSITE_RULE } else { if (useComposite) { - if (!renderOptions->srcFlags.isPremultiplied) - subIndex |= 1; - if (renderOptions->srcFlags.isOpaque) - subIndex |= 1 << 1; - if (!renderOptions->dstFlags.isPremultiplied) - subIndex |= 1 << 2; - if (renderOptions->dstFlags.isOpaque) - subIndex |= 1 << 3; + index.bits.srcPremultiplied = renderOptions->srcFlags.isPremultiplied; + index.bits.srcOpaque = renderOptions->srcFlags.isOpaque; } else compositeRule = RULE_Src; } - if (stencilNeeded) { - subIndex |= 1 << 4; - } - - if (renderOptions->isAA) { - subIndex |= 1 << 5; - } - - if ((composite != nil && FLT_LT([composite getExtraAlpha], 1.0f))) { - subIndex |= 1 << 6; - } - - int index = compositeRule*128 + subIndex; + index.bits.stencil = stencilNeeded; + index.bits.aa = renderOptions->isAA; + index.bits.extAlpha = composite != nil && FLT_LT([composite getExtraAlpha], 1.0f); + index.bits.compositeRule = compositeRule; NSPointerArray * subStates = [self getSubStates:vertexShaderId fragmentShader:fragmentShaderId]; - if (index >= subStates.count) { - subStates.count = (NSUInteger) (index + 1); + if (index.value >= subStates.count) { + subStates.count = index.value + 1; } - id result = [subStates pointerAtIndex:index]; + id result = [subStates pointerAtIndex:index.value]; if (result == nil) { @autoreleasepool { id vertexShader = [self getShader:vertexShaderId]; @@ -222,7 +221,7 @@ static void setBlendingFactors( exit(0); } - [subStates insertPointer:result atIndex:index]; + [subStates replacePointerAtIndex:index.value withPointer:result]; } } diff --git a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/RenderOptions.h b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/RenderOptions.h index 46521ca5b09..f24f131631a 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/RenderOptions.h +++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/RenderOptions.h @@ -35,7 +35,6 @@ typedef struct { jboolean isAA; int interpolation; SurfaceRasterFlags srcFlags; - SurfaceRasterFlags dstFlags; jboolean isText; jboolean isLCD; jboolean isAAShader; diff --git a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/common.h b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/common.h index 556bbf5d88e..70218f7e849 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/common.h +++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/common.h @@ -114,7 +114,6 @@ struct TxtFrameUniforms { vector_float4 color; int mode; // NOTE: consider to use bit fields int isSrcOpaque; - int isDstOpaque; float extraAlpha; }; -- GitLab From 92aa75b72185c681757e6520d6fdc1ae4161d0c5 Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Wed, 8 Dec 2021 17:52:03 +0000 Subject: [PATCH 062/671] 8274903: Zero: Support AsyncGetCallTrace Reviewed-by: sspitsyn, aph --- src/hotspot/cpu/zero/frame_zero.cpp | 64 +++++++++++++++++-- .../os_cpu/linux_zero/thread_linux_zero.cpp | 41 +++++++++++- .../os_cpu/linux_zero/thread_linux_zero.hpp | 14 ++-- src/hotspot/share/prims/forte.cpp | 42 +++++++++++- 4 files changed, 143 insertions(+), 18 deletions(-) diff --git a/src/hotspot/cpu/zero/frame_zero.cpp b/src/hotspot/cpu/zero/frame_zero.cpp index 19970cfb82b..2e00d703377 100644 --- a/src/hotspot/cpu/zero/frame_zero.cpp +++ b/src/hotspot/cpu/zero/frame_zero.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. - * Copyright 2007, 2008, 2009, 2010, 2011 Red Hat, Inc. + * Copyright (c) 2007, 2021, Red Hat, Inc. 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 @@ -116,13 +116,67 @@ void frame::patch_pc(Thread* thread, address pc) { } bool frame::safe_for_sender(JavaThread *thread) { - ShouldNotCallThis(); - return false; + address sp = (address)_sp; + + // consider stack guards when trying to determine "safe" stack pointers + // sp must be within the usable part of the stack (not in guards) + if (!thread->is_in_usable_stack(sp)) { + return false; + } + + // an fp must be within the stack and above (but not equal) sp + if (!thread->is_in_stack_range_excl((address)fp(), sp)) { + return false; + } + + // All good. + return true; } bool frame::is_interpreted_frame_valid(JavaThread *thread) const { - ShouldNotCallThis(); - return false; + assert(is_interpreted_frame(), "Not an interpreted frame"); + // These are reasonable sanity checks + if (fp() == 0 || (intptr_t(fp()) & (wordSize-1)) != 0) { + return false; + } + if (sp() == 0 || (intptr_t(sp()) & (wordSize-1)) != 0) { + return false; + } + // These are hacks to keep us out of trouble. + // The problem with these is that they mask other problems + if (fp() <= sp()) { // this attempts to deal with unsigned comparison above + return false; + } + + // do some validation of frame elements + // first the method + + Method* m = *interpreter_frame_method_addr(); + + // validate the method we'd find in this potential sender + if (!Method::is_valid_method(m)) { + return false; + } + + // validate bci/bcp + address bcp = interpreter_frame_bcp(); + if (m->validate_bci_from_bcp(bcp) < 0) { + return false; + } + + // validate ConstantPoolCache* + ConstantPoolCache* cp = *interpreter_frame_cache_addr(); + if (MetaspaceObj::is_valid(cp) == false) { + return false; + } + + // validate locals + address locals = (address) *interpreter_frame_locals_addr(); + if (!thread->is_in_stack_range_incl(locals, (address)fp())) { + return false; + } + + return true; } BasicType frame::interpreter_frame_result(oop* oop_result, diff --git a/src/hotspot/os_cpu/linux_zero/thread_linux_zero.cpp b/src/hotspot/os_cpu/linux_zero/thread_linux_zero.cpp index 816ca411430..e4313782613 100644 --- a/src/hotspot/os_cpu/linux_zero/thread_linux_zero.cpp +++ b/src/hotspot/os_cpu/linux_zero/thread_linux_zero.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. - * Copyright 2009, 2010 Red Hat, Inc. + * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2021, Red Hat, Inc. 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 @@ -35,3 +35,40 @@ frame JavaThread::pd_last_frame() { void JavaThread::cache_global_variables() { // nothing to do } + +bool JavaThread::pd_get_top_frame_for_signal_handler(frame* fr_addr, + void* ucontext, + bool isInJava) { + if (has_last_Java_frame()) { + *fr_addr = pd_last_frame(); + return true; + } + + if (isInJava) { + // We know we are in Java, but there is no frame? + // Try to find the top-most Java frame on Zero stack then. + intptr_t* sp = zero_stack()->sp(); + ZeroFrame* zf = top_zero_frame(); + while (zf != NULL) { + if (zf->is_interpreter_frame()) { + interpreterState istate = zf->as_interpreter_frame()->interpreter_state(); + if (istate->self_link() == istate) { + // Valid interpreter state found, this is our frame. + *fr_addr = frame(zf, sp); + return true; + } + } + sp = ((intptr_t *) zf) + 1; + zf = zf->next(); + } + } + + // No dice. + return false; +} + +bool JavaThread::pd_get_top_frame_for_profiling(frame* fr_addr, + void* ucontext, + bool isInJava) { + return pd_get_top_frame_for_signal_handler(fr_addr, ucontext, isInJava); +} diff --git a/src/hotspot/os_cpu/linux_zero/thread_linux_zero.hpp b/src/hotspot/os_cpu/linux_zero/thread_linux_zero.hpp index b180611b2f9..b915c40c049 100644 --- a/src/hotspot/os_cpu/linux_zero/thread_linux_zero.hpp +++ b/src/hotspot/os_cpu/linux_zero/thread_linux_zero.hpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. - * Copyright 2007, 2008, 2009, 2010 Red Hat, Inc. + * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2021, Red Hat, Inc. 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 @@ -96,16 +96,10 @@ public: bool pd_get_top_frame_for_signal_handler(frame* fr_addr, void* ucontext, - bool isInJava) { - ShouldNotCallThis(); - return false; // silence compile warning - } + bool isInJava); bool pd_get_top_frame_for_profiling(frame* fr_addr, void* ucontext, - bool isInJava) { - ShouldNotCallThis(); - return false; // silence compile warning - } + bool isInJava); #endif // OS_CPU_LINUX_ZERO_THREAD_LINUX_ZERO_HPP diff --git a/src/hotspot/share/prims/forte.cpp b/src/hotspot/share/prims/forte.cpp index e2310ede951..c68c371ce47 100644 --- a/src/hotspot/share/prims/forte.cpp +++ b/src/hotspot/share/prims/forte.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2021, 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 @@ -314,6 +314,46 @@ static bool find_initial_Java_frame(JavaThread* thread, frame candidate = *fr; +#ifdef ZERO + // Zero has no frames with code blobs, so the generic code fails. + // Instead, try to do Zero-specific search for Java frame. + + { + RegisterMap map(thread, false, false); + + while (true) { + // Cannot walk this frame? Cannot do anything anymore. + if (!candidate.safe_for_sender(thread)) { + return false; + } + + if (candidate.is_entry_frame()) { + // jcw is NULL if the java call wrapper could not be found + JavaCallWrapper* jcw = candidate.entry_frame_call_wrapper_if_safe(thread); + // If initial frame is frame from StubGenerator and there is no + // previous anchor, there are no java frames associated with a method + if (jcw == NULL || jcw->is_first_frame()) { + return false; + } + } + + // If we find a decipherable interpreted frame, this is our initial frame. + if (candidate.is_interpreted_frame()) { + if (is_decipherable_interpreted_frame(thread, &candidate, method_p, bci_p)) { + *initial_frame_p = candidate; + return true; + } + } + + // Walk some more. + candidate = candidate.sender(&map); + } + + // No dice, report no initial frames. + return false; + } +#endif + // If the starting frame we were given has no codeBlob associated with // it see if we can find such a frame because only frames with codeBlobs // are possible Java frames. -- GitLab From ba86dd4aaf597a0f0832085b50fa00498f053a6a Mon Sep 17 00:00:00 2001 From: "Daniel D. Daugherty" Date: Wed, 8 Dec 2021 18:02:34 +0000 Subject: [PATCH 063/671] 8278445: ProblemList tools/jpackage/share/IconTest.java on macosx-x64 Reviewed-by: bpb --- test/jdk/ProblemList.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 5a03523f327..a48fe6af429 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -833,6 +833,7 @@ jdk/jfr/api/consumer/streaming/TestLatestEvent.java 8268297 windows- # jdk_jpackage +tools/jpackage/share/IconTest.java 8278233 macosx-x64 tools/jpackage/share/MultiNameTwoPhaseTest.java 8278233 macosx-x64 ############################################################################ -- GitLab From 42d9b1baac25df649a8d575f5ffa3a0d5b8e7ed0 Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Wed, 8 Dec 2021 18:50:38 +0000 Subject: [PATCH 064/671] 8277106: Cannot compile certain sources with --release Reviewed-by: darcy, mcimadamore --- make/data/symbols/java.base-C.sym.txt | 14 +- make/data/symbols/java.base-E.sym.txt | 16 +- make/data/symbols/java.base-G.sym.txt | 117 +++++- make/data/symbols/java.base-H.sym.txt | 37 +- make/data/symbols/java.xml-B.sym.txt | 4 +- make/data/symbols/java.xml-C.sym.txt | 4 +- make/data/symbols/java.xml-D.sym.txt | 4 +- make/data/symbols/java.xml-E.sym.txt | 4 +- .../symbols/jdk.incubator.foreign-F.sym.txt | 14 +- .../symbols/jdk.incubator.foreign-G.sym.txt | 4 +- .../symbols/jdk.incubator.foreign-H.sym.txt | 2 +- .../symbols/jdk.incubator.vector-G.sym.txt | 9 + .../symbols/jdk.incubator.vector-H.sym.txt | 92 +++++ make/data/symbols/jdk.javadoc-H.sym.txt | 2 +- make/data/symbols/jdk.jfr-B.sym.txt | 13 +- make/data/symbols/jdk.jfr-G.sym.txt | 7 +- .../tools/symbolgenerator/CreateSymbols.java | 272 ++++++++++++-- .../javac/platform/NonExportedSuperTypes.java | 41 +++ .../createsymbols/CreateSymbolsTest.java | 2 +- .../createsymbols/CreateSymbolsTestImpl.java | 346 +++++++++++++++++- 20 files changed, 927 insertions(+), 77 deletions(-) create mode 100644 test/langtools/tools/javac/platform/NonExportedSuperTypes.java diff --git a/make/data/symbols/java.base-C.sym.txt b/make/data/symbols/java.base-C.sym.txt index 27896d9902f..7a45fc1b49e 100644 --- a/make/data/symbols/java.base-C.sym.txt +++ b/make/data/symbols/java.base-C.sym.txt @@ -1,5 +1,5 @@ # -# Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2019, 2021, 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 @@ -27,7 +27,7 @@ # ########################################################## # module name java.base -header exports java/io,java/lang,java/lang/annotation,java/lang/constant,java/lang/invoke,java/lang/module,java/lang/ref,java/lang/reflect,java/math,java/net,java/net/spi,java/nio,java/nio/channels,java/nio/channels/spi,java/nio/charset,java/nio/charset/spi,java/nio/file,java/nio/file/attribute,java/nio/file/spi,java/security,java/security/acl,java/security/cert,java/security/interfaces,java/security/spec,java/text,java/text/spi,java/time,java/time/chrono,java/time/format,java/time/temporal,java/time/zone,java/util,java/util/concurrent,java/util/concurrent/atomic,java/util/concurrent/locks,java/util/function,java/util/jar,java/util/regex,java/util/spi,java/util/stream,java/util/zip,javax/crypto,javax/crypto/interfaces,javax/crypto/spec,javax/net,javax/net/ssl,javax/security/auth,javax/security/auth/callback,javax/security/auth/login,javax/security/auth/spi,javax/security/auth/x500,javax/security/cert uses java/lang/System$LoggerFinder,java/net/ContentHandlerFactory,java/net/spi/URLStreamHandlerProvider,java/nio/channels/spi/AsynchronousChannelProvider,java/nio/channels/spi/SelectorProvider,java/nio/charset/spi/CharsetProvider,java/nio/file/spi/FileSystemProvider,java/nio/file/spi/FileTypeDetector,java/security/Provider,java/text/spi/BreakIteratorProvider,java/text/spi/CollatorProvider,java/text/spi/DateFormatProvider,java/text/spi/DateFormatSymbolsProvider,java/text/spi/DecimalFormatSymbolsProvider,java/text/spi/NumberFormatProvider,java/time/chrono/AbstractChronology,java/time/chrono/Chronology,java/time/zone/ZoneRulesProvider,java/util/spi/CalendarDataProvider,java/util/spi/CalendarNameProvider,java/util/spi/CurrencyNameProvider,java/util/spi/LocaleNameProvider,java/util/spi/ResourceBundleControlProvider,java/util/spi/ResourceBundleProvider,java/util/spi/TimeZoneNameProvider,java/util/spi/ToolProvider,javax/security/auth/spi/LoginModule,jdk/internal/logger/DefaultLoggerFinder,sun/text/spi/JavaTimeDateTimePatternProvider,sun/util/locale/provider/LocaleDataMetaInfo,sun/util/resources/LocaleData$CommonResourceBundleProvider,sun/util/resources/LocaleData$SupplementaryResourceBundleProvider,sun/util/spi/CalendarProvider provides interface\u0020;java/nio/file/spi/FileSystemProvider\u0020;impls\u0020;jdk/internal/jrtfs/JrtFileSystemProvider target linux-amd64 flags 8000 +header exports java/io,java/lang,java/lang/annotation,java/lang/constant,java/lang/invoke,java/lang/module,java/lang/ref,java/lang/reflect,java/math,java/net,java/net/spi,java/nio,java/nio/channels,java/nio/channels/spi,java/nio/charset,java/nio/charset/spi,java/nio/file,java/nio/file/attribute,java/nio/file/spi,java/security,java/security/acl,java/security/cert,java/security/interfaces,java/security/spec,java/text,java/text/spi,java/time,java/time/chrono,java/time/format,java/time/temporal,java/time/zone,java/util,java/util/concurrent,java/util/concurrent/atomic,java/util/concurrent/locks,java/util/function,java/util/jar,java/util/regex,java/util/spi,java/util/stream,java/util/zip,javax/crypto,javax/crypto/interfaces,javax/crypto/spec,javax/net,javax/net/ssl,javax/security/auth,javax/security/auth/callback,javax/security/auth/login,javax/security/auth/spi,javax/security/auth/x500,javax/security/cert,jdk/internal/event[jdk.jfr] uses java/lang/System$LoggerFinder,java/net/ContentHandlerFactory,java/net/spi/URLStreamHandlerProvider,java/nio/channels/spi/AsynchronousChannelProvider,java/nio/channels/spi/SelectorProvider,java/nio/charset/spi/CharsetProvider,java/nio/file/spi/FileSystemProvider,java/nio/file/spi/FileTypeDetector,java/security/Provider,java/text/spi/BreakIteratorProvider,java/text/spi/CollatorProvider,java/text/spi/DateFormatProvider,java/text/spi/DateFormatSymbolsProvider,java/text/spi/DecimalFormatSymbolsProvider,java/text/spi/NumberFormatProvider,java/time/chrono/AbstractChronology,java/time/chrono/Chronology,java/time/zone/ZoneRulesProvider,java/util/spi/CalendarDataProvider,java/util/spi/CalendarNameProvider,java/util/spi/CurrencyNameProvider,java/util/spi/LocaleNameProvider,java/util/spi/ResourceBundleControlProvider,java/util/spi/ResourceBundleProvider,java/util/spi/TimeZoneNameProvider,java/util/spi/ToolProvider,javax/security/auth/spi/LoginModule,jdk/internal/logger/DefaultLoggerFinder,sun/text/spi/JavaTimeDateTimePatternProvider,sun/util/locale/provider/LocaleDataMetaInfo,sun/util/resources/LocaleData$CommonResourceBundleProvider,sun/util/resources/LocaleData$SupplementaryResourceBundleProvider,sun/util/spi/CalendarProvider provides interface\u0020;java/nio/file/spi/FileSystemProvider\u0020;impls\u0020;jdk/internal/jrtfs/JrtFileSystemProvider target linux-amd64 flags 8000 class name java/io/FileInputStream -method name finalize descriptor ()V @@ -634,3 +634,13 @@ field name serialVersionUID descriptor J constantValue -1430015993304333921 flag class name javax/net/ssl/HttpsURLConnection method name getSSLSession descriptor ()Ljava/util/Optional; flags 1 signature ()Ljava/util/Optional; +class name jdk/internal/event/Event +header extends java/lang/Object flags 421 +method name descriptor ()V flags 4 +method name begin descriptor ()V flags 1 +method name end descriptor ()V flags 1 +method name commit descriptor ()V flags 1 +method name isEnabled descriptor ()Z flags 1 +method name shouldCommit descriptor ()Z flags 1 +method name set descriptor (ILjava/lang/Object;)V flags 1 + diff --git a/make/data/symbols/java.base-E.sym.txt b/make/data/symbols/java.base-E.sym.txt index 0aebcdd54d9..eaebf4b68f5 100644 --- a/make/data/symbols/java.base-E.sym.txt +++ b/make/data/symbols/java.base-E.sym.txt @@ -1,5 +1,5 @@ # -# Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2020, 2021, 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 @@ -27,7 +27,7 @@ # ########################################################## # module name java.base -header exports java/io,java/lang,java/lang/annotation,java/lang/constant,java/lang/invoke,java/lang/module,java/lang/ref,java/lang/reflect,java/lang/runtime,java/math,java/net,java/net/spi,java/nio,java/nio/channels,java/nio/channels/spi,java/nio/charset,java/nio/charset/spi,java/nio/file,java/nio/file/attribute,java/nio/file/spi,java/security,java/security/cert,java/security/interfaces,java/security/spec,java/text,java/text/spi,java/time,java/time/chrono,java/time/format,java/time/temporal,java/time/zone,java/util,java/util/concurrent,java/util/concurrent/atomic,java/util/concurrent/locks,java/util/function,java/util/jar,java/util/regex,java/util/spi,java/util/stream,java/util/zip,javax/crypto,javax/crypto/interfaces,javax/crypto/spec,javax/net,javax/net/ssl,javax/security/auth,javax/security/auth/callback,javax/security/auth/login,javax/security/auth/spi,javax/security/auth/x500,javax/security/cert uses java/lang/System$LoggerFinder,java/net/ContentHandlerFactory,java/net/spi/URLStreamHandlerProvider,java/nio/channels/spi/AsynchronousChannelProvider,java/nio/channels/spi/SelectorProvider,java/nio/charset/spi/CharsetProvider,java/nio/file/spi/FileSystemProvider,java/nio/file/spi/FileTypeDetector,java/security/Provider,java/text/spi/BreakIteratorProvider,java/text/spi/CollatorProvider,java/text/spi/DateFormatProvider,java/text/spi/DateFormatSymbolsProvider,java/text/spi/DecimalFormatSymbolsProvider,java/text/spi/NumberFormatProvider,java/time/chrono/AbstractChronology,java/time/chrono/Chronology,java/time/zone/ZoneRulesProvider,java/util/spi/CalendarDataProvider,java/util/spi/CalendarNameProvider,java/util/spi/CurrencyNameProvider,java/util/spi/LocaleNameProvider,java/util/spi/ResourceBundleControlProvider,java/util/spi/ResourceBundleProvider,java/util/spi/TimeZoneNameProvider,java/util/spi/ToolProvider,javax/security/auth/spi/LoginModule,jdk/internal/logger/DefaultLoggerFinder,sun/text/spi/JavaTimeDateTimePatternProvider,sun/util/locale/provider/LocaleDataMetaInfo,sun/util/resources/LocaleData$CommonResourceBundleProvider,sun/util/resources/LocaleData$SupplementaryResourceBundleProvider,sun/util/spi/CalendarProvider provides interface\u0020;java/nio/file/spi/FileSystemProvider\u0020;impls\u0020;jdk/internal/jrtfs/JrtFileSystemProvider target linux-amd64 flags 8000 +header exports java/io,java/lang,java/lang/annotation,java/lang/constant,java/lang/invoke,java/lang/module,java/lang/ref,java/lang/reflect,java/lang/runtime,java/math,java/net,java/net/spi,java/nio,java/nio/channels,java/nio/channels/spi,java/nio/charset,java/nio/charset/spi,java/nio/file,java/nio/file/attribute,java/nio/file/spi,java/security,java/security/cert,java/security/interfaces,java/security/spec,java/text,java/text/spi,java/time,java/time/chrono,java/time/format,java/time/temporal,java/time/zone,java/util,java/util/concurrent,java/util/concurrent/atomic,java/util/concurrent/locks,java/util/function,java/util/jar,java/util/regex,java/util/spi,java/util/stream,java/util/zip,javax/crypto,javax/crypto/interfaces,javax/crypto/spec,javax/net,javax/net/ssl,javax/security/auth,javax/security/auth/callback,javax/security/auth/login,javax/security/auth/spi,javax/security/auth/x500,javax/security/cert,jdk/internal/event[jdk.jfr] uses java/lang/System$LoggerFinder,java/net/ContentHandlerFactory,java/net/spi/URLStreamHandlerProvider,java/nio/channels/spi/AsynchronousChannelProvider,java/nio/channels/spi/SelectorProvider,java/nio/charset/spi/CharsetProvider,java/nio/file/spi/FileSystemProvider,java/nio/file/spi/FileTypeDetector,java/security/Provider,java/text/spi/BreakIteratorProvider,java/text/spi/CollatorProvider,java/text/spi/DateFormatProvider,java/text/spi/DateFormatSymbolsProvider,java/text/spi/DecimalFormatSymbolsProvider,java/text/spi/NumberFormatProvider,java/time/chrono/AbstractChronology,java/time/chrono/Chronology,java/time/zone/ZoneRulesProvider,java/util/spi/CalendarDataProvider,java/util/spi/CalendarNameProvider,java/util/spi/CurrencyNameProvider,java/util/spi/LocaleNameProvider,java/util/spi/ResourceBundleControlProvider,java/util/spi/ResourceBundleProvider,java/util/spi/TimeZoneNameProvider,java/util/spi/ToolProvider,javax/security/auth/spi/LoginModule,jdk/internal/logger/DefaultLoggerFinder,sun/text/spi/JavaTimeDateTimePatternProvider,sun/util/locale/provider/LocaleDataMetaInfo,sun/util/resources/LocaleData$CommonResourceBundleProvider,sun/util/resources/LocaleData$SupplementaryResourceBundleProvider,sun/util/spi/CalendarProvider provides interface\u0020;java/nio/file/spi/FileSystemProvider\u0020;impls\u0020;jdk/internal/jrtfs/JrtFileSystemProvider target linux-amd64 flags 8000 class name java/io/PrintStream method name write descriptor ([B)V thrownTypes java/io/IOException flags 1 @@ -209,18 +209,18 @@ method name setCurrentBlocker descriptor (Ljava/lang/Object;)V flags 9 class name java/util/concurrent/locks/StampedLock header extends java/lang/Object implements java/io/Serializable flags 21 classAnnotations @Ljdk/Profile+Annotation;(value=I1) -method name tryWriteLock descriptor ()J flags 1 -method name writeLockInterruptibly descriptor ()J thrownTypes java/lang/InterruptedException flags 1 -method name tryReadLock descriptor ()J flags 1 -method name tryReadLock descriptor (JLjava/util/concurrent/TimeUnit;)J thrownTypes java/lang/InterruptedException flags 1 -method name readLockInterruptibly descriptor ()J thrownTypes java/lang/InterruptedException flags 1 -method name unlock descriptor (J)V flags 1 -method name tryWriteLock descriptor ()J -method name writeLockInterruptibly descriptor ()J -method name tryReadLock descriptor ()J -method name tryReadLock descriptor (JLjava/util/concurrent/TimeUnit;)J -method name readLockInterruptibly descriptor ()J -method name unlock descriptor (J)V +method name tryWriteLock descriptor ()J flags 1 +method name writeLockInterruptibly descriptor ()J thrownTypes java/lang/InterruptedException flags 1 +method name tryReadLock descriptor ()J flags 1 +method name tryReadLock descriptor (JLjava/util/concurrent/TimeUnit;)J thrownTypes java/lang/InterruptedException flags 1 +method name readLockInterruptibly descriptor ()J thrownTypes java/lang/InterruptedException flags 1 +method name unlock descriptor (J)V flags 1 -class name java/util/jar/Pack200 diff --git a/make/data/symbols/java.base-G.sym.txt b/make/data/symbols/java.base-G.sym.txt index 774c74459b4..8196ef6be11 100644 --- a/make/data/symbols/java.base-G.sym.txt +++ b/make/data/symbols/java.base-G.sym.txt @@ -1,5 +1,5 @@ # -# Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2020, 2021, 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 @@ -26,6 +26,9 @@ # ### THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### # ########################################################## # +module name java.base +header exports java/io,java/lang,java/lang/annotation,java/lang/constant,java/lang/invoke,java/lang/module,java/lang/ref,java/lang/reflect,java/lang/runtime,java/math,java/net,java/net/spi,java/nio,java/nio/channels,java/nio/channels/spi,java/nio/charset,java/nio/charset/spi,java/nio/file,java/nio/file/attribute,java/nio/file/spi,java/security,java/security/cert,java/security/interfaces,java/security/spec,java/text,java/text/spi,java/time,java/time/chrono,java/time/format,java/time/temporal,java/time/zone,java/util,java/util/concurrent,java/util/concurrent/atomic,java/util/concurrent/locks,java/util/function,java/util/jar,java/util/regex,java/util/spi,java/util/stream,java/util/zip,javax/crypto,javax/crypto/interfaces,javax/crypto/spec,javax/net,javax/net/ssl,javax/security/auth,javax/security/auth/callback,javax/security/auth/login,javax/security/auth/spi,javax/security/auth/x500,javax/security/cert,jdk/internal/event[jdk.jfr],jdk/internal/vm/vector[jdk.incubator.vector] uses java/lang/System$LoggerFinder,java/net/ContentHandlerFactory,java/net/spi/URLStreamHandlerProvider,java/nio/channels/spi/AsynchronousChannelProvider,java/nio/channels/spi/SelectorProvider,java/nio/charset/spi/CharsetProvider,java/nio/file/spi/FileSystemProvider,java/nio/file/spi/FileTypeDetector,java/security/Provider,java/text/spi/BreakIteratorProvider,java/text/spi/CollatorProvider,java/text/spi/DateFormatProvider,java/text/spi/DateFormatSymbolsProvider,java/text/spi/DecimalFormatSymbolsProvider,java/text/spi/NumberFormatProvider,java/time/chrono/AbstractChronology,java/time/chrono/Chronology,java/time/zone/ZoneRulesProvider,java/util/spi/CalendarDataProvider,java/util/spi/CalendarNameProvider,java/util/spi/CurrencyNameProvider,java/util/spi/LocaleNameProvider,java/util/spi/ResourceBundleControlProvider,java/util/spi/ResourceBundleProvider,java/util/spi/TimeZoneNameProvider,java/util/spi/ToolProvider,javax/security/auth/spi/LoginModule,jdk/internal/logger/DefaultLoggerFinder,sun/text/spi/JavaTimeDateTimePatternProvider,sun/util/locale/provider/LocaleDataMetaInfo,sun/util/resources/LocaleData$CommonResourceBundleProvider,sun/util/resources/LocaleData$SupplementaryResourceBundleProvider,sun/util/spi/CalendarProvider provides interface\u0020;java/nio/file/spi/FileSystemProvider\u0020;impls\u0020;jdk/internal/jrtfs/JrtFileSystemProvider target linux-amd64 flags 8000 + class name java/io/PrintStream header extends java/io/FilterOutputStream implements java/lang/Appendable,java/io/Closeable flags 21 innerclass innerClass java/util/Locale$Category outerClass java/util/Locale innerClassName Category flags 4019 @@ -677,8 +680,8 @@ method name toString descriptor ()Ljava/lang/String; flags 1 class name java/security/spec/PSSParameterSpec -field name TRAILER_FIELD_BC descriptor I -field name TRAILER_FIELD_BC descriptor I constantValue 1 flags 19 -method name toString descriptor ()Ljava/lang/String; +field name TRAILER_FIELD_BC descriptor I constantValue 1 flags 19 method name toString descriptor ()Ljava/lang/String; flags 1 class name java/security/spec/RSAKeyGenParameterSpec @@ -1169,3 +1172,113 @@ header extends java/lang/Object implements java/security/spec/AlgorithmParameter class name javax/crypto/spec/SecretKeySpec header extends java/lang/Object implements java/security/spec/KeySpec,javax/crypto/SecretKey flags 21 +class name jdk/internal/event/Event +header extends java/lang/Object flags 421 +-method name descriptor ()V +-method name begin descriptor ()V +-method name end descriptor ()V +-method name commit descriptor ()V +-method name isEnabled descriptor ()Z +-method name shouldCommit descriptor ()Z +-method name set descriptor (ILjava/lang/Object;)V +method name descriptor ()V flags 4 +method name begin descriptor ()V flags 1 +method name end descriptor ()V flags 1 +method name commit descriptor ()V flags 1 +method name isEnabled descriptor ()Z flags 1 +method name shouldCommit descriptor ()Z flags 1 +method name set descriptor (ILjava/lang/Object;)V flags 1 + +class name jdk/internal/vm/vector/VectorSupport +header extends java/lang/Object nestMembers jdk/internal/vm/vector/VectorSupport$VectorMask,jdk/internal/vm/vector/VectorSupport$VectorShuffle,jdk/internal/vm/vector/VectorSupport$Vector,jdk/internal/vm/vector/VectorSupport$VectorPayload,jdk/internal/vm/vector/VectorSupport$VectorSpecies flags 21 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorSpecies outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorSpecies flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorShuffle outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorShuffle flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$Vector outerClass jdk/internal/vm/vector/VectorSupport innerClassName Vector flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorMask outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorMask flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorPayload outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorPayload flags 9 +field name VECTOR_OP_ABS descriptor I constantValue 0 flags 19 +field name VECTOR_OP_NEG descriptor I constantValue 1 flags 19 +field name VECTOR_OP_SQRT descriptor I constantValue 2 flags 19 +field name VECTOR_OP_ADD descriptor I constantValue 4 flags 19 +field name VECTOR_OP_SUB descriptor I constantValue 5 flags 19 +field name VECTOR_OP_MUL descriptor I constantValue 6 flags 19 +field name VECTOR_OP_DIV descriptor I constantValue 7 flags 19 +field name VECTOR_OP_MIN descriptor I constantValue 8 flags 19 +field name VECTOR_OP_MAX descriptor I constantValue 9 flags 19 +field name VECTOR_OP_AND descriptor I constantValue 10 flags 19 +field name VECTOR_OP_OR descriptor I constantValue 11 flags 19 +field name VECTOR_OP_XOR descriptor I constantValue 12 flags 19 +field name VECTOR_OP_FMA descriptor I constantValue 13 flags 19 +field name VECTOR_OP_LSHIFT descriptor I constantValue 14 flags 19 +field name VECTOR_OP_RSHIFT descriptor I constantValue 15 flags 19 +field name VECTOR_OP_URSHIFT descriptor I constantValue 16 flags 19 +field name VECTOR_OP_CAST descriptor I constantValue 17 flags 19 +field name VECTOR_OP_REINTERPRET descriptor I constantValue 18 flags 19 +field name BT_eq descriptor I constantValue 0 flags 19 +field name BT_ne descriptor I constantValue 4 flags 19 +field name BT_le descriptor I constantValue 5 flags 19 +field name BT_ge descriptor I constantValue 7 flags 19 +field name BT_lt descriptor I constantValue 3 flags 19 +field name BT_gt descriptor I constantValue 1 flags 19 +field name BT_overflow descriptor I constantValue 2 flags 19 +field name BT_no_overflow descriptor I constantValue 6 flags 19 +field name T_FLOAT descriptor I constantValue 6 flags 19 +field name T_DOUBLE descriptor I constantValue 7 flags 19 +field name T_BYTE descriptor I constantValue 8 flags 19 +field name T_SHORT descriptor I constantValue 9 flags 19 +field name T_INT descriptor I constantValue 10 flags 19 +field name T_LONG descriptor I constantValue 11 flags 19 +method name descriptor ()V flags 1 +method name broadcastCoerced descriptor (Ljava/lang/Class;Ljava/lang/Class;IJLjdk/internal/vm/vector/VectorSupport$VectorSpecies;Ljdk/internal/vm/vector/VectorSupport$BroadcastOperation;)Ljava/lang/Object; flags 9 signature ;>(Ljava/lang/Class<+TVM;>;Ljava/lang/Class;IJTS;Ljdk/internal/vm/vector/VectorSupport$BroadcastOperation;)TVM; runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +method name shuffleIota descriptor (Ljava/lang/Class;Ljava/lang/Class;Ljdk/internal/vm/vector/VectorSupport$VectorSpecies;IIIILjdk/internal/vm/vector/VectorSupport$ShuffleIotaOperation;)Ljdk/internal/vm/vector/VectorSupport$VectorShuffle; flags 9 signature ;>(Ljava/lang/Class<*>;Ljava/lang/Class<*>;TS;IIIILjdk/internal/vm/vector/VectorSupport$ShuffleIotaOperation;)Ljdk/internal/vm/vector/VectorSupport$VectorShuffle; runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +method name shuffleToVector descriptor (Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Class;Ljdk/internal/vm/vector/VectorSupport$VectorShuffle;ILjdk/internal/vm/vector/VectorSupport$ShuffleToVectorOperation;)Ljava/lang/Object; flags 9 signature ;E:Ljava/lang/Object;>(Ljava/lang/Class<*>;Ljava/lang/Class<*>;Ljava/lang/Class<*>;TSh;ILjdk/internal/vm/vector/VectorSupport$ShuffleToVectorOperation;)TVM; runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +method name indexVector descriptor (Ljava/lang/Class;Ljava/lang/Class;ILjdk/internal/vm/vector/VectorSupport$Vector;ILjdk/internal/vm/vector/VectorSupport$VectorSpecies;Ljdk/internal/vm/vector/VectorSupport$IndexOperation;)Ljdk/internal/vm/vector/VectorSupport$Vector; flags 9 signature ;E:Ljava/lang/Object;S:Ljdk/internal/vm/vector/VectorSupport$VectorSpecies;>(Ljava/lang/Class<+TV;>;Ljava/lang/Class;ITV;ITS;Ljdk/internal/vm/vector/VectorSupport$IndexOperation;)TV; +method name reductionCoerced descriptor (ILjava/lang/Class;Ljava/lang/Class;ILjdk/internal/vm/vector/VectorSupport$Vector;Ljava/util/function/Function;)J flags 9 signature ;>(ILjava/lang/Class<*>;Ljava/lang/Class<*>;ITV;Ljava/util/function/Function;)J runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +method name extract descriptor (Ljava/lang/Class;Ljava/lang/Class;ILjdk/internal/vm/vector/VectorSupport$Vector;ILjdk/internal/vm/vector/VectorSupport$VecExtractOp;)J flags 9 signature ;>(Ljava/lang/Class<*>;Ljava/lang/Class<*>;ITV;ILjdk/internal/vm/vector/VectorSupport$VecExtractOp;)J runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +method name insert descriptor (Ljava/lang/Class;Ljava/lang/Class;ILjdk/internal/vm/vector/VectorSupport$Vector;IJLjdk/internal/vm/vector/VectorSupport$VecInsertOp;)Ljdk/internal/vm/vector/VectorSupport$Vector; flags 9 signature ;>(Ljava/lang/Class<+TV;>;Ljava/lang/Class<*>;ITV;IJLjdk/internal/vm/vector/VectorSupport$VecInsertOp;)TV; runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +method name unaryOp descriptor (ILjava/lang/Class;Ljava/lang/Class;ILjava/lang/Object;Ljava/util/function/Function;)Ljava/lang/Object; flags 9 signature (ILjava/lang/Class<+TVM;>;Ljava/lang/Class<*>;ITVM;Ljava/util/function/Function;)TVM; runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +method name binaryOp descriptor (ILjava/lang/Class;Ljava/lang/Class;ILjava/lang/Object;Ljava/lang/Object;Ljava/util/function/BiFunction;)Ljava/lang/Object; flags 9 signature (ILjava/lang/Class<+TVM;>;Ljava/lang/Class<*>;ITVM;TVM;Ljava/util/function/BiFunction;)TVM; runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +method name ternaryOp descriptor (ILjava/lang/Class;Ljava/lang/Class;ILjava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljdk/internal/vm/vector/VectorSupport$TernaryOperation;)Ljava/lang/Object; flags 9 signature (ILjava/lang/Class<+TVM;>;Ljava/lang/Class<*>;ITVM;TVM;TVM;Ljdk/internal/vm/vector/VectorSupport$TernaryOperation;)TVM; runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +method name load descriptor (Ljava/lang/Class;Ljava/lang/Class;ILjava/lang/Object;JLjava/lang/Object;ILjdk/internal/vm/vector/VectorSupport$VectorSpecies;Ljdk/internal/vm/vector/VectorSupport$LoadOperation;)Ljava/lang/Object; flags 9 signature ;>(Ljava/lang/Class<+TVM;>;Ljava/lang/Class;ILjava/lang/Object;JTC;ITS;Ljdk/internal/vm/vector/VectorSupport$LoadOperation;)TVM; runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +method name loadWithMap descriptor (Ljava/lang/Class;Ljava/lang/Class;ILjava/lang/Class;Ljava/lang/Object;JLjdk/internal/vm/vector/VectorSupport$Vector;Ljava/lang/Object;I[IILjdk/internal/vm/vector/VectorSupport$VectorSpecies;Ljdk/internal/vm/vector/VectorSupport$LoadVectorOperationWithMap;)Ljdk/internal/vm/vector/VectorSupport$Vector; flags 9 signature ;W:Ljdk/internal/vm/vector/VectorSupport$Vector;E:Ljava/lang/Object;S:Ljdk/internal/vm/vector/VectorSupport$VectorSpecies;>(Ljava/lang/Class<*>;Ljava/lang/Class;ILjava/lang/Class<*>;Ljava/lang/Object;JTW;TC;I[IITS;Ljdk/internal/vm/vector/VectorSupport$LoadVectorOperationWithMap;)TV; runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +method name store descriptor (Ljava/lang/Class;Ljava/lang/Class;ILjava/lang/Object;JLjdk/internal/vm/vector/VectorSupport$Vector;Ljava/lang/Object;ILjdk/internal/vm/vector/VectorSupport$StoreVectorOperation;)V flags 9 signature ;>(Ljava/lang/Class<*>;Ljava/lang/Class<*>;ILjava/lang/Object;JTV;TC;ILjdk/internal/vm/vector/VectorSupport$StoreVectorOperation;)V runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +method name storeWithMap descriptor (Ljava/lang/Class;Ljava/lang/Class;ILjava/lang/Class;Ljava/lang/Object;JLjdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$Vector;Ljava/lang/Object;I[IILjdk/internal/vm/vector/VectorSupport$StoreVectorOperationWithMap;)V flags 9 signature ;W:Ljdk/internal/vm/vector/VectorSupport$Vector;>(Ljava/lang/Class<*>;Ljava/lang/Class<*>;ILjava/lang/Class<*>;Ljava/lang/Object;JTW;TV;TC;I[IILjdk/internal/vm/vector/VectorSupport$StoreVectorOperationWithMap;)V runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +method name test descriptor (ILjava/lang/Class;Ljava/lang/Class;ILjava/lang/Object;Ljava/lang/Object;Ljava/util/function/BiFunction;)Z flags 9 signature (ILjava/lang/Class<*>;Ljava/lang/Class<*>;ITVM;TVM;Ljava/util/function/BiFunction;)Z runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +method name compare descriptor (ILjava/lang/Class;Ljava/lang/Class;Ljava/lang/Class;ILjdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$VectorCompareOp;)Ljdk/internal/vm/vector/VectorSupport$VectorMask; flags 9 signature ;M:Ljdk/internal/vm/vector/VectorSupport$VectorMask;E:Ljava/lang/Object;>(ILjava/lang/Class<+TV;>;Ljava/lang/Class;Ljava/lang/Class<*>;ITV;TV;Ljdk/internal/vm/vector/VectorSupport$VectorCompareOp;)TM; runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +method name rearrangeOp descriptor (Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Class;ILjdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$VectorShuffle;Ljdk/internal/vm/vector/VectorSupport$VectorRearrangeOp;)Ljdk/internal/vm/vector/VectorSupport$Vector; flags 9 signature ;Sh:Ljdk/internal/vm/vector/VectorSupport$VectorShuffle;E:Ljava/lang/Object;>(Ljava/lang/Class<+TV;>;Ljava/lang/Class;Ljava/lang/Class<*>;ITV;TSh;Ljdk/internal/vm/vector/VectorSupport$VectorRearrangeOp;)TV; runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +method name blend descriptor (Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Class;ILjdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$VectorMask;Ljdk/internal/vm/vector/VectorSupport$VectorBlendOp;)Ljdk/internal/vm/vector/VectorSupport$Vector; flags 9 signature ;M:Ljdk/internal/vm/vector/VectorSupport$VectorMask;E:Ljava/lang/Object;>(Ljava/lang/Class<+TV;>;Ljava/lang/Class;Ljava/lang/Class<*>;ITV;TV;TM;Ljdk/internal/vm/vector/VectorSupport$VectorBlendOp;)TV; runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +method name broadcastInt descriptor (ILjava/lang/Class;Ljava/lang/Class;ILjdk/internal/vm/vector/VectorSupport$Vector;ILjdk/internal/vm/vector/VectorSupport$VectorBroadcastIntOp;)Ljdk/internal/vm/vector/VectorSupport$Vector; flags 9 signature ;>(ILjava/lang/Class<+TV;>;Ljava/lang/Class<*>;ITV;ILjdk/internal/vm/vector/VectorSupport$VectorBroadcastIntOp;)TV; runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +method name convert descriptor (ILjava/lang/Class;Ljava/lang/Class;ILjava/lang/Class;Ljava/lang/Class;ILjdk/internal/vm/vector/VectorSupport$VectorPayload;Ljdk/internal/vm/vector/VectorSupport$VectorSpecies;Ljdk/internal/vm/vector/VectorSupport$VectorConvertOp;)Ljdk/internal/vm/vector/VectorSupport$VectorPayload; flags 9 signature ;>(ILjava/lang/Class<*>;Ljava/lang/Class<*>;ILjava/lang/Class<*>;Ljava/lang/Class<*>;ITVIN;TS;Ljdk/internal/vm/vector/VectorSupport$VectorConvertOp;)TVOUT; runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +method name maybeRebox descriptor (Ljava/lang/Object;)Ljava/lang/Object; flags 9 signature (TV;)TV; runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +method name getMaxLaneCount descriptor (Ljava/lang/Class;)I flags 109 signature (Ljava/lang/Class<*>;)I +method name isNonCapturingLambda descriptor (Ljava/lang/Object;)Z flags 9 + +class name jdk/internal/vm/vector/VectorSupport$Vector +header extends jdk/internal/vm/vector/VectorSupport$VectorPayload nestHost jdk/internal/vm/vector/VectorSupport flags 21 signature Ljdk/internal/vm/vector/VectorSupport$VectorPayload; +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorPayload outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorPayload flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$Vector outerClass jdk/internal/vm/vector/VectorSupport innerClassName Vector flags 9 +method name descriptor (Ljava/lang/Object;)V flags 1 + +class name jdk/internal/vm/vector/VectorSupport$VectorMask +header extends jdk/internal/vm/vector/VectorSupport$VectorPayload nestHost jdk/internal/vm/vector/VectorSupport flags 21 signature Ljdk/internal/vm/vector/VectorSupport$VectorPayload; +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorPayload outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorPayload flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorMask outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorMask flags 9 +method name descriptor (Ljava/lang/Object;)V flags 1 + +class name jdk/internal/vm/vector/VectorSupport$VectorPayload +header extends java/lang/Object nestHost jdk/internal/vm/vector/VectorSupport flags 21 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorPayload outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorPayload flags 9 +method name descriptor (Ljava/lang/Object;)V flags 1 +method name getPayload descriptor ()Ljava/lang/Object; flags 14 + +class name jdk/internal/vm/vector/VectorSupport$VectorShuffle +header extends jdk/internal/vm/vector/VectorSupport$VectorPayload nestHost jdk/internal/vm/vector/VectorSupport flags 21 signature Ljdk/internal/vm/vector/VectorSupport$VectorPayload; +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorPayload outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorPayload flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorShuffle outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorShuffle flags 9 +method name descriptor (Ljava/lang/Object;)V flags 1 + +class name jdk/internal/vm/vector/VectorSupport$VectorSpecies +header extends java/lang/Object nestHost jdk/internal/vm/vector/VectorSupport flags 21 signature Ljava/lang/Object; +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorSpecies outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorSpecies flags 9 +method name descriptor ()V flags 1 + diff --git a/make/data/symbols/java.base-H.sym.txt b/make/data/symbols/java.base-H.sym.txt index 585d05063b3..c6ef0d70aeb 100644 --- a/make/data/symbols/java.base-H.sym.txt +++ b/make/data/symbols/java.base-H.sym.txt @@ -27,7 +27,7 @@ # ########################################################## # module name java.base -header exports java/io,java/lang,java/lang/annotation,java/lang/constant,java/lang/invoke,java/lang/module,java/lang/ref,java/lang/reflect,java/lang/runtime,java/math,java/net,java/net/spi,java/nio,java/nio/channels,java/nio/channels/spi,java/nio/charset,java/nio/charset/spi,java/nio/file,java/nio/file/attribute,java/nio/file/spi,java/security,java/security/cert,java/security/interfaces,java/security/spec,java/text,java/text/spi,java/time,java/time/chrono,java/time/format,java/time/temporal,java/time/zone,java/util,java/util/concurrent,java/util/concurrent/atomic,java/util/concurrent/locks,java/util/function,java/util/jar,java/util/random,java/util/regex,java/util/spi,java/util/stream,java/util/zip,javax/crypto,javax/crypto/interfaces,javax/crypto/spec,javax/net,javax/net/ssl,javax/security/auth,javax/security/auth/callback,javax/security/auth/login,javax/security/auth/spi,javax/security/auth/x500,javax/security/cert uses java/lang/System$LoggerFinder,java/net/ContentHandlerFactory,java/net/spi/URLStreamHandlerProvider,java/nio/channels/spi/AsynchronousChannelProvider,java/nio/channels/spi/SelectorProvider,java/nio/charset/spi/CharsetProvider,java/nio/file/spi/FileSystemProvider,java/nio/file/spi/FileTypeDetector,java/security/Provider,java/text/spi/BreakIteratorProvider,java/text/spi/CollatorProvider,java/text/spi/DateFormatProvider,java/text/spi/DateFormatSymbolsProvider,java/text/spi/DecimalFormatSymbolsProvider,java/text/spi/NumberFormatProvider,java/time/chrono/AbstractChronology,java/time/chrono/Chronology,java/time/zone/ZoneRulesProvider,java/util/random/RandomGenerator,java/util/spi/CalendarDataProvider,java/util/spi/CalendarNameProvider,java/util/spi/CurrencyNameProvider,java/util/spi/LocaleNameProvider,java/util/spi/ResourceBundleControlProvider,java/util/spi/ResourceBundleProvider,java/util/spi/TimeZoneNameProvider,java/util/spi/ToolProvider,javax/security/auth/spi/LoginModule,jdk/internal/logger/DefaultLoggerFinder,sun/text/spi/JavaTimeDateTimePatternProvider,sun/util/locale/provider/LocaleDataMetaInfo,sun/util/resources/LocaleData$CommonResourceBundleProvider,sun/util/resources/LocaleData$SupplementaryResourceBundleProvider,sun/util/spi/CalendarProvider provides interface\u0020;java/nio/file/spi/FileSystemProvider\u0020;impls\u0020;jdk/internal/jrtfs/JrtFileSystemProvider,interface\u0020;java/util/random/RandomGenerator\u0020;impls\u0020;java/security/SecureRandom\u005C;u002C;java/util/Random\u005C;u002C;java/util/SplittableRandom target linux-amd64 flags 8000 +header exports java/io,java/lang,java/lang/annotation,java/lang/constant,java/lang/invoke,java/lang/module,java/lang/ref,java/lang/reflect,java/lang/runtime,java/math,java/net,java/net/spi,java/nio,java/nio/channels,java/nio/channels/spi,java/nio/charset,java/nio/charset/spi,java/nio/file,java/nio/file/attribute,java/nio/file/spi,java/security,java/security/cert,java/security/interfaces,java/security/spec,java/text,java/text/spi,java/time,java/time/chrono,java/time/format,java/time/temporal,java/time/zone,java/util,java/util/concurrent,java/util/concurrent/atomic,java/util/concurrent/locks,java/util/function,java/util/jar,java/util/random,java/util/regex,java/util/spi,java/util/stream,java/util/zip,javax/crypto,javax/crypto/interfaces,javax/crypto/spec,javax/net,javax/net/ssl,javax/security/auth,javax/security/auth/callback,javax/security/auth/login,javax/security/auth/spi,javax/security/auth/x500,javax/security/cert,jdk/internal/event[jdk.jfr],jdk/internal/vm/vector[jdk.incubator.vector] uses java/lang/System$LoggerFinder,java/net/ContentHandlerFactory,java/net/spi/URLStreamHandlerProvider,java/nio/channels/spi/AsynchronousChannelProvider,java/nio/channels/spi/SelectorProvider,java/nio/charset/spi/CharsetProvider,java/nio/file/spi/FileSystemProvider,java/nio/file/spi/FileTypeDetector,java/security/Provider,java/text/spi/BreakIteratorProvider,java/text/spi/CollatorProvider,java/text/spi/DateFormatProvider,java/text/spi/DateFormatSymbolsProvider,java/text/spi/DecimalFormatSymbolsProvider,java/text/spi/NumberFormatProvider,java/time/chrono/AbstractChronology,java/time/chrono/Chronology,java/time/zone/ZoneRulesProvider,java/util/random/RandomGenerator,java/util/spi/CalendarDataProvider,java/util/spi/CalendarNameProvider,java/util/spi/CurrencyNameProvider,java/util/spi/LocaleNameProvider,java/util/spi/ResourceBundleControlProvider,java/util/spi/ResourceBundleProvider,java/util/spi/TimeZoneNameProvider,java/util/spi/ToolProvider,javax/security/auth/spi/LoginModule,jdk/internal/logger/DefaultLoggerFinder,sun/text/spi/JavaTimeDateTimePatternProvider,sun/util/locale/provider/LocaleDataMetaInfo,sun/util/resources/LocaleData$CommonResourceBundleProvider,sun/util/resources/LocaleData$SupplementaryResourceBundleProvider,sun/util/spi/CalendarProvider provides interface\u0020;java/nio/file/spi/FileSystemProvider\u0020;impls\u0020;jdk/internal/jrtfs/JrtFileSystemProvider,interface\u0020;java/util/random/RandomGenerator\u0020;impls\u0020;java/security/SecureRandom\u005C;u002C;java/util/Random\u005C;u002C;java/util/SplittableRandom target linux-amd64 flags 8000 class name java/io/CharArrayReader method name read descriptor (Ljava/nio/CharBuffer;)I thrownTypes java/io/IOException flags 1 @@ -114,8 +114,8 @@ header extends java/lang/Object implements java/lang/annotation/Annotation flags class name java/lang/System -method name setSecurityManager descriptor (Ljava/lang/SecurityManager;)V -method name getSecurityManager descriptor ()Ljava/lang/SecurityManager; -method name getSecurityManager descriptor ()Ljava/lang/SecurityManager; flags 9 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="17") method name setSecurityManager descriptor (Ljava/lang/SecurityManager;)V flags 9 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="17")@Ljdk/internal/reflect/CallerSensitive; +method name getSecurityManager descriptor ()Ljava/lang/SecurityManager; flags 9 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="17") class name java/lang/Thread -method name checkAccess descriptor ()V @@ -313,8 +313,8 @@ field name SHA512_256 descriptor Ljava/security/spec/MGF1ParameterSpec; flags 19 class name java/security/spec/PSSParameterSpec -field name TRAILER_FIELD_BC descriptor I -field name TRAILER_FIELD_BC descriptor I constantValue 1 flags 19 -method name toString descriptor ()Ljava/lang/String; +field name TRAILER_FIELD_BC descriptor I constantValue 1 flags 19 method name toString descriptor ()Ljava/lang/String; flags 1 class name java/security/spec/RSAKeyGenParameterSpec @@ -470,8 +470,8 @@ method name splits descriptor ()Ljava/util/stream/Stream; flags 1 signature ()Lj method name splits descriptor (J)Ljava/util/stream/Stream; flags 1 signature (J)Ljava/util/stream/Stream; method name splits descriptor (Ljava/util/random/RandomGenerator$SplittableGenerator;)Ljava/util/stream/Stream; flags 1 signature (Ljava/util/random/RandomGenerator$SplittableGenerator;)Ljava/util/stream/Stream; method name splits descriptor (JLjava/util/random/RandomGenerator$SplittableGenerator;)Ljava/util/stream/Stream; flags 1 signature (JLjava/util/random/RandomGenerator$SplittableGenerator;)Ljava/util/stream/Stream; -method name split descriptor ()Ljava/util/random/RandomGenerator$SplittableGenerator; flags 1041 method name split descriptor (Ljava/util/random/RandomGenerator$SplittableGenerator;)Ljava/util/random/RandomGenerator$SplittableGenerator; flags 1041 +method name split descriptor ()Ljava/util/random/RandomGenerator$SplittableGenerator; flags 1041 class name java/util/TimeZone header extends java/lang/Object implements java/io/Serializable,java/lang/Cloneable flags 421 @@ -928,3 +928,32 @@ method name doAsPrivileged descriptor (Ljavax/security/auth/Subject;Ljava/securi class name javax/security/auth/SubjectDomainCombiner header extends java/lang/Object implements java/security/DomainCombiner flags 21 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="17") +class name jdk/internal/vm/vector/VectorSupport +field name VECTOR_OP_MASK_TRUECOUNT descriptor I constantValue 19 flags 19 +field name VECTOR_OP_MASK_FIRSTTRUE descriptor I constantValue 20 flags 19 +field name VECTOR_OP_MASK_LASTTRUE descriptor I constantValue 21 flags 19 +field name VECTOR_OP_TAN descriptor I constantValue 101 flags 19 +field name VECTOR_OP_TANH descriptor I constantValue 102 flags 19 +field name VECTOR_OP_SIN descriptor I constantValue 103 flags 19 +field name VECTOR_OP_SINH descriptor I constantValue 104 flags 19 +field name VECTOR_OP_COS descriptor I constantValue 105 flags 19 +field name VECTOR_OP_COSH descriptor I constantValue 106 flags 19 +field name VECTOR_OP_ASIN descriptor I constantValue 107 flags 19 +field name VECTOR_OP_ACOS descriptor I constantValue 108 flags 19 +field name VECTOR_OP_ATAN descriptor I constantValue 109 flags 19 +field name VECTOR_OP_ATAN2 descriptor I constantValue 110 flags 19 +field name VECTOR_OP_CBRT descriptor I constantValue 111 flags 19 +field name VECTOR_OP_LOG descriptor I constantValue 112 flags 19 +field name VECTOR_OP_LOG10 descriptor I constantValue 113 flags 19 +field name VECTOR_OP_LOG1P descriptor I constantValue 114 flags 19 +field name VECTOR_OP_POW descriptor I constantValue 115 flags 19 +field name VECTOR_OP_EXP descriptor I constantValue 116 flags 19 +field name VECTOR_OP_EXPM1 descriptor I constantValue 117 flags 19 +field name VECTOR_OP_HYPOT descriptor I constantValue 118 flags 19 +field name BT_unsigned_compare descriptor I constantValue 16 flags 19 +field name BT_ule descriptor I constantValue 21 flags 19 +field name BT_uge descriptor I constantValue 23 flags 19 +field name BT_ult descriptor I constantValue 19 flags 19 +field name BT_ugt descriptor I constantValue 17 flags 19 +method name maskReductionCoerced descriptor (ILjava/lang/Class;Ljava/lang/Class;ILjava/lang/Object;Ljdk/internal/vm/vector/VectorSupport$VectorMaskOp;)I flags 9 signature (ILjava/lang/Class<+TM;>;Ljava/lang/Class<*>;ITM;Ljdk/internal/vm/vector/VectorSupport$VectorMaskOp;)I runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; + diff --git a/make/data/symbols/java.xml-B.sym.txt b/make/data/symbols/java.xml-B.sym.txt index 08675c9bf03..3f256899258 100644 --- a/make/data/symbols/java.xml-B.sym.txt +++ b/make/data/symbols/java.xml-B.sym.txt @@ -1,5 +1,5 @@ # -# Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2018, 2021, 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 @@ -136,8 +136,8 @@ header extends java/lang/Object implements javax/xml/stream/util/XMLEventConsume class name javax/xml/stream/XMLInputFactory header extends java/lang/Object flags 421 -method name newFactory descriptor ()Ljavax/xml/stream/XMLInputFactory; thrownTypes javax/xml/stream/FactoryConfigurationError flags 9 -method name newFactory descriptor ()Ljavax/xml/stream/XMLInputFactory; +method name newFactory descriptor ()Ljavax/xml/stream/XMLInputFactory; thrownTypes javax/xml/stream/FactoryConfigurationError flags 9 class name javax/xml/stream/XMLOutputFactory header extends java/lang/Object flags 421 diff --git a/make/data/symbols/java.xml-C.sym.txt b/make/data/symbols/java.xml-C.sym.txt index 6023e7f147c..56f91aac3dc 100644 --- a/make/data/symbols/java.xml-C.sym.txt +++ b/make/data/symbols/java.xml-C.sym.txt @@ -1,5 +1,5 @@ # -# Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2019, 2021, 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 @@ -27,6 +27,6 @@ # ########################################################## # class name javax/xml/stream/XMLInputFactory -method name newFactory descriptor ()Ljavax/xml/stream/XMLInputFactory; thrownTypes javax/xml/stream/FactoryConfigurationError flags 9 -method name newFactory descriptor ()Ljavax/xml/stream/XMLInputFactory; +method name newFactory descriptor ()Ljavax/xml/stream/XMLInputFactory; thrownTypes javax/xml/stream/FactoryConfigurationError flags 9 diff --git a/make/data/symbols/java.xml-D.sym.txt b/make/data/symbols/java.xml-D.sym.txt index 29a4adb0d58..a91b0cd8dd1 100644 --- a/make/data/symbols/java.xml-D.sym.txt +++ b/make/data/symbols/java.xml-D.sym.txt @@ -1,5 +1,5 @@ # -# Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -42,6 +42,6 @@ method name newNSInstance descriptor ()Ljavax/xml/parsers/SAXParserFactory; flag method name newNSInstance descriptor (Ljava/lang/String;Ljava/lang/ClassLoader;)Ljavax/xml/parsers/SAXParserFactory; flags 9 class name javax/xml/stream/XMLInputFactory -method name newFactory descriptor ()Ljavax/xml/stream/XMLInputFactory; thrownTypes javax/xml/stream/FactoryConfigurationError flags 9 -method name newFactory descriptor ()Ljavax/xml/stream/XMLInputFactory; +method name newFactory descriptor ()Ljavax/xml/stream/XMLInputFactory; thrownTypes javax/xml/stream/FactoryConfigurationError flags 9 diff --git a/make/data/symbols/java.xml-E.sym.txt b/make/data/symbols/java.xml-E.sym.txt index 3c5d6da6fc3..9c4ac9945e8 100644 --- a/make/data/symbols/java.xml-E.sym.txt +++ b/make/data/symbols/java.xml-E.sym.txt @@ -1,5 +1,5 @@ # -# Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2019, 2021, 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 @@ -27,8 +27,8 @@ # ########################################################## # class name javax/xml/stream/XMLInputFactory -method name newFactory descriptor ()Ljavax/xml/stream/XMLInputFactory; thrownTypes javax/xml/stream/FactoryConfigurationError flags 9 -method name newFactory descriptor ()Ljavax/xml/stream/XMLInputFactory; +method name newFactory descriptor ()Ljavax/xml/stream/XMLInputFactory; thrownTypes javax/xml/stream/FactoryConfigurationError flags 9 class name org/xml/sax/ContentHandler method name declaration descriptor (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V thrownTypes org/xml/sax/SAXException flags 1 diff --git a/make/data/symbols/jdk.incubator.foreign-F.sym.txt b/make/data/symbols/jdk.incubator.foreign-F.sym.txt index 4a37cfad9b5..efb2d71b334 100644 --- a/make/data/symbols/jdk.incubator.foreign-F.sym.txt +++ b/make/data/symbols/jdk.incubator.foreign-F.sym.txt @@ -1,5 +1,5 @@ # -# Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2020, 2021, 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 @@ -59,9 +59,9 @@ method name asSlice descriptor (JJ)Ljdk/incubator/foreign/MemorySegment; flags 1 method name withAccessModes descriptor (I)Ljdk/incubator/foreign/MemorySegment; flags 1041 class name jdk/incubator/foreign/MemoryAddress -field name NULL descriptor Ljdk/incubator/foreign/MemoryAddress; flags 19 -method name offset descriptor ()J -method name copy descriptor (Ljdk/incubator/foreign/MemoryAddress;Ljdk/incubator/foreign/MemoryAddress;J)V +field name NULL descriptor Ljdk/incubator/foreign/MemoryAddress; flags 19 method name segmentOffset descriptor ()J flags 401 method name toRawLongValue descriptor ()J flags 401 method name rebase descriptor (Ljdk/incubator/foreign/MemorySegment;)Ljdk/incubator/foreign/MemoryAddress; flags 401 @@ -78,8 +78,8 @@ method name collectCoordinates descriptor (Ljava/lang/invoke/VarHandle;ILjava/la method name dropCoordinates descriptor (Ljava/lang/invoke/VarHandle;I[Ljava/lang/Class;)Ljava/lang/invoke/VarHandle; flags 89 signature (Ljava/lang/invoke/VarHandle;I[Ljava/lang/Class<*>;)Ljava/lang/invoke/VarHandle; class name jdk/incubator/foreign/MemoryLayout -field name LAYOUT_NAME descriptor Ljava/lang/String; constantValue layout/name flags 19 -method name offset descriptor ([Ljdk/incubator/foreign/MemoryLayout$PathElement;)J +field name LAYOUT_NAME descriptor Ljava/lang/String; constantValue layout/name flags 19 method name attribute descriptor (Ljava/lang/String;)Ljava/util/Optional; flags 401 signature (Ljava/lang/String;)Ljava/util/Optional; method name withAttribute descriptor (Ljava/lang/String;Ljava/lang/constant/Constable;)Ljdk/incubator/foreign/MemoryLayout; flags 401 method name attributes descriptor ()Ljava/util/stream/Stream; flags 401 signature ()Ljava/util/stream/Stream; @@ -88,16 +88,16 @@ method name byteOffset descriptor ([Ljdk/incubator/foreign/MemoryLayout$PathElem method name isPadding descriptor ()Z flags 401 class name jdk/incubator/foreign/MemorySegment +-method name acquire descriptor ()Ljdk/incubator/foreign/MemorySegment; +-method name asReadOnly descriptor ()Ljdk/incubator/foreign/MemorySegment; +-method name isReadOnly descriptor ()Z +-method name mapFromPath descriptor (Ljava/nio/file/Path;JLjava/nio/channels/FileChannel$MapMode;)Ljdk/incubator/foreign/MemorySegment; field name READ descriptor I constantValue 1 flags 19 field name WRITE descriptor I constantValue 2 flags 19 field name CLOSE descriptor I constantValue 4 flags 19 field name ACQUIRE descriptor I constantValue 8 flags 19 field name HANDOFF descriptor I constantValue 16 flags 19 field name ALL_ACCESS descriptor I constantValue 31 flags 19 --method name acquire descriptor ()Ljdk/incubator/foreign/MemorySegment; --method name asReadOnly descriptor ()Ljdk/incubator/foreign/MemorySegment; --method name isReadOnly descriptor ()Z --method name mapFromPath descriptor (Ljava/nio/file/Path;JLjava/nio/channels/FileChannel$MapMode;)Ljdk/incubator/foreign/MemorySegment; method name spliterator descriptor (Ljdk/incubator/foreign/MemorySegment;Ljdk/incubator/foreign/SequenceLayout;)Ljava/util/Spliterator; flags 9 signature (TS;Ljdk/incubator/foreign/SequenceLayout;)Ljava/util/Spliterator; method name withOwnerThread descriptor (Ljava/lang/Thread;)Ljdk/incubator/foreign/MemorySegment; flags 401 method name withAccessModes descriptor (I)Ljdk/incubator/foreign/MemorySegment; flags 401 diff --git a/make/data/symbols/jdk.incubator.foreign-G.sym.txt b/make/data/symbols/jdk.incubator.foreign-G.sym.txt index 5bb38702f4f..3ea0960ea1e 100644 --- a/make/data/symbols/jdk.incubator.foreign-G.sym.txt +++ b/make/data/symbols/jdk.incubator.foreign-G.sym.txt @@ -1,5 +1,5 @@ # -# Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2020, 2021, 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 @@ -264,12 +264,12 @@ header extends java/lang/Object implements jdk/incubator/foreign/Addressable,jav innerclass innerClass java/nio/channels/FileChannel$MapMode outerClass java/nio/channels/FileChannel innerClassName MapMode flags 9 innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 -field name ACQUIRE descriptor I -field name SHARE descriptor I constantValue 8 flags 19 -method name baseAddress descriptor ()Ljdk/incubator/foreign/MemoryAddress; -method name spliterator descriptor (Ljdk/incubator/foreign/MemorySegment;Ljdk/incubator/foreign/SequenceLayout;)Ljava/util/Spliterator; -method name withOwnerThread descriptor (Ljava/lang/Thread;)Ljdk/incubator/foreign/MemorySegment; -method name mapFromPath descriptor (Ljava/nio/file/Path;JJLjava/nio/channels/FileChannel$MapMode;)Ljdk/incubator/foreign/MappedMemorySegment; -method name ofNativeRestricted descriptor (Ljdk/incubator/foreign/MemoryAddress;JLjava/lang/Thread;Ljava/lang/Runnable;Ljava/lang/Object;)Ljdk/incubator/foreign/MemorySegment; +field name SHARE descriptor I constantValue 8 flags 19 method name address descriptor ()Ljdk/incubator/foreign/MemoryAddress; flags 401 method name spliterator descriptor (Ljdk/incubator/foreign/SequenceLayout;)Ljava/util/Spliterator; flags 401 signature (Ljdk/incubator/foreign/SequenceLayout;)Ljava/util/Spliterator; method name asSlice descriptor (Ljdk/incubator/foreign/MemoryAddress;J)Ljdk/incubator/foreign/MemorySegment; flags 1 diff --git a/make/data/symbols/jdk.incubator.foreign-H.sym.txt b/make/data/symbols/jdk.incubator.foreign-H.sym.txt index 376ba519f57..d5349d378bf 100644 --- a/make/data/symbols/jdk.incubator.foreign-H.sym.txt +++ b/make/data/symbols/jdk.incubator.foreign-H.sym.txt @@ -43,6 +43,7 @@ innerclass innerClass jdk/incubator/foreign/CLinker$VaList$Builder outerClass jd -method name allocateMemoryRestricted descriptor (J)Ljdk/incubator/foreign/MemoryAddress; -method name freeMemoryRestricted descriptor (Ljdk/incubator/foreign/MemoryAddress;)V method name getInstance descriptor ()Ljdk/incubator/foreign/CLinker; flags 9 runtimeAnnotations @Ljdk/internal/reflect/CallerSensitive; +method name systemLookup descriptor ()Ljdk/incubator/foreign/SymbolLookup; flags 9 runtimeAnnotations @Ljdk/internal/reflect/CallerSensitive; method name downcallHandle descriptor (Ljdk/incubator/foreign/Addressable;Ljdk/incubator/foreign/SegmentAllocator;Ljava/lang/invoke/MethodType;Ljdk/incubator/foreign/FunctionDescriptor;)Ljava/lang/invoke/MethodHandle; flags 401 method name downcallHandle descriptor (Ljava/lang/invoke/MethodType;Ljdk/incubator/foreign/FunctionDescriptor;)Ljava/lang/invoke/MethodHandle; flags 401 method name upcallStub descriptor (Ljava/lang/invoke/MethodHandle;Ljdk/incubator/foreign/FunctionDescriptor;Ljdk/incubator/foreign/ResourceScope;)Ljdk/incubator/foreign/MemoryAddress; flags 401 @@ -51,7 +52,6 @@ method name toCString descriptor (Ljava/lang/String;Ljdk/incubator/foreign/Resou method name toJavaString descriptor (Ljdk/incubator/foreign/MemoryAddress;)Ljava/lang/String; flags 9 runtimeAnnotations @Ljdk/internal/reflect/CallerSensitive; method name allocateMemory descriptor (J)Ljdk/incubator/foreign/MemoryAddress; flags 9 runtimeAnnotations @Ljdk/internal/reflect/CallerSensitive; method name freeMemory descriptor (Ljdk/incubator/foreign/MemoryAddress;)V flags 9 runtimeAnnotations @Ljdk/internal/reflect/CallerSensitive; -method name systemLookup descriptor ()Ljdk/incubator/foreign/SymbolLookup; flags 9 runtimeAnnotations @Ljdk/internal/reflect/CallerSensitive; class name jdk/incubator/foreign/CLinker$VaList header extends java/lang/Object implements jdk/incubator/foreign/Addressable nestHost jdk/incubator/foreign/CLinker sealed true flags 601 diff --git a/make/data/symbols/jdk.incubator.vector-G.sym.txt b/make/data/symbols/jdk.incubator.vector-G.sym.txt index dec09658dc0..35c8da2c622 100644 --- a/make/data/symbols/jdk.incubator.vector-G.sym.txt +++ b/make/data/symbols/jdk.incubator.vector-G.sym.txt @@ -32,6 +32,8 @@ header exports jdk/incubator/vector requires name\u0020;java.base\u0020;flags\u0 class name jdk/incubator/vector/AbstractVector header extends jdk/incubator/vector/Vector flags 420 signature Ljdk/incubator/vector/Vector; innerclass innerClass jdk/incubator/vector/VectorOperators$Conversion outerClass jdk/incubator/vector/VectorOperators innerClassName Conversion flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorPayload outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorPayload flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorSpecies outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorSpecies flags 9 innerclass innerClass jdk/incubator/vector/VectorOperators$Associative outerClass jdk/incubator/vector/VectorOperators innerClassName Associative flags 609 innerclass innerClass jdk/incubator/vector/VectorOperators$Binary outerClass jdk/incubator/vector/VectorOperators innerClassName Binary flags 609 innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 @@ -55,6 +57,7 @@ method name slice descriptor (I)Ljdk/incubator/vector/Vector; flags 1041 class name jdk/incubator/vector/ByteVector header extends jdk/incubator/vector/AbstractVector flags 421 signature Ljdk/incubator/vector/AbstractVector; innerclass innerClass jdk/incubator/vector/VectorOperators$Operator outerClass jdk/incubator/vector/VectorOperators innerClassName Operator flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorSpecies outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorSpecies flags 9 innerclass innerClass jdk/incubator/vector/VectorOperators$Unary outerClass jdk/incubator/vector/VectorOperators innerClassName Unary flags 609 innerclass innerClass jdk/incubator/vector/VectorOperators$Comparison outerClass jdk/incubator/vector/VectorOperators innerClassName Comparison flags 609 innerclass innerClass jdk/incubator/vector/VectorOperators$Associative outerClass jdk/incubator/vector/VectorOperators innerClassName Associative flags 609 @@ -230,6 +233,7 @@ method name slice descriptor (I)Ljdk/incubator/vector/AbstractVector; flags 1041 class name jdk/incubator/vector/DoubleVector header extends jdk/incubator/vector/AbstractVector flags 421 signature Ljdk/incubator/vector/AbstractVector; innerclass innerClass jdk/incubator/vector/VectorOperators$Operator outerClass jdk/incubator/vector/VectorOperators innerClassName Operator flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorSpecies outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorSpecies flags 9 innerclass innerClass jdk/incubator/vector/VectorOperators$Unary outerClass jdk/incubator/vector/VectorOperators innerClassName Unary flags 609 innerclass innerClass jdk/incubator/vector/VectorOperators$Comparison outerClass jdk/incubator/vector/VectorOperators innerClassName Comparison flags 609 innerclass innerClass jdk/incubator/vector/VectorOperators$Associative outerClass jdk/incubator/vector/VectorOperators innerClassName Associative flags 609 @@ -402,6 +406,7 @@ method name slice descriptor (I)Ljdk/incubator/vector/AbstractVector; flags 1041 class name jdk/incubator/vector/FloatVector header extends jdk/incubator/vector/AbstractVector flags 421 signature Ljdk/incubator/vector/AbstractVector; innerclass innerClass jdk/incubator/vector/VectorOperators$Operator outerClass jdk/incubator/vector/VectorOperators innerClassName Operator flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorSpecies outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorSpecies flags 9 innerclass innerClass jdk/incubator/vector/VectorOperators$Unary outerClass jdk/incubator/vector/VectorOperators innerClassName Unary flags 609 innerclass innerClass jdk/incubator/vector/VectorOperators$Comparison outerClass jdk/incubator/vector/VectorOperators innerClassName Comparison flags 609 innerclass innerClass jdk/incubator/vector/VectorOperators$Associative outerClass jdk/incubator/vector/VectorOperators innerClassName Associative flags 609 @@ -574,6 +579,7 @@ method name slice descriptor (I)Ljdk/incubator/vector/AbstractVector; flags 1041 class name jdk/incubator/vector/IntVector header extends jdk/incubator/vector/AbstractVector flags 421 signature Ljdk/incubator/vector/AbstractVector; innerclass innerClass jdk/incubator/vector/VectorOperators$Operator outerClass jdk/incubator/vector/VectorOperators innerClassName Operator flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorSpecies outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorSpecies flags 9 innerclass innerClass jdk/incubator/vector/VectorOperators$Unary outerClass jdk/incubator/vector/VectorOperators innerClassName Unary flags 609 innerclass innerClass jdk/incubator/vector/VectorOperators$Comparison outerClass jdk/incubator/vector/VectorOperators innerClassName Comparison flags 609 innerclass innerClass jdk/incubator/vector/VectorOperators$Associative outerClass jdk/incubator/vector/VectorOperators innerClassName Associative flags 609 @@ -750,6 +756,7 @@ method name slice descriptor (I)Ljdk/incubator/vector/AbstractVector; flags 1041 class name jdk/incubator/vector/LongVector header extends jdk/incubator/vector/AbstractVector flags 421 signature Ljdk/incubator/vector/AbstractVector; innerclass innerClass jdk/incubator/vector/VectorOperators$Operator outerClass jdk/incubator/vector/VectorOperators innerClassName Operator flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorSpecies outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorSpecies flags 9 innerclass innerClass jdk/incubator/vector/VectorOperators$Unary outerClass jdk/incubator/vector/VectorOperators innerClassName Unary flags 609 innerclass innerClass jdk/incubator/vector/VectorOperators$Comparison outerClass jdk/incubator/vector/VectorOperators innerClassName Comparison flags 609 innerclass innerClass jdk/incubator/vector/VectorOperators$Associative outerClass jdk/incubator/vector/VectorOperators innerClassName Associative flags 609 @@ -919,6 +926,7 @@ method name slice descriptor (I)Ljdk/incubator/vector/AbstractVector; flags 1041 class name jdk/incubator/vector/ShortVector header extends jdk/incubator/vector/AbstractVector flags 421 signature Ljdk/incubator/vector/AbstractVector; innerclass innerClass jdk/incubator/vector/VectorOperators$Operator outerClass jdk/incubator/vector/VectorOperators innerClassName Operator flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorSpecies outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorSpecies flags 9 innerclass innerClass jdk/incubator/vector/VectorOperators$Unary outerClass jdk/incubator/vector/VectorOperators innerClassName Unary flags 609 innerclass innerClass jdk/incubator/vector/VectorOperators$Comparison outerClass jdk/incubator/vector/VectorOperators innerClassName Comparison flags 609 innerclass innerClass jdk/incubator/vector/VectorOperators$Associative outerClass jdk/incubator/vector/VectorOperators innerClassName Associative flags 609 @@ -1184,6 +1192,7 @@ method name hashCode descriptor ()I flags 401 class name jdk/incubator/vector/VectorMask header extends jdk/internal/vm/vector/VectorSupport$VectorMask flags 421 signature Ljdk/internal/vm/vector/VectorSupport$VectorMask; innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorMask outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorMask flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorSpecies outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorSpecies flags 9 innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 method name vectorSpecies descriptor ()Ljdk/incubator/vector/VectorSpecies; flags 401 signature ()Ljdk/incubator/vector/VectorSpecies; method name length descriptor ()I flags 11 runtimeAnnotations @Ljdk/internal/vm/annotation/ForceInline; diff --git a/make/data/symbols/jdk.incubator.vector-H.sym.txt b/make/data/symbols/jdk.incubator.vector-H.sym.txt index a815726e54b..b83ff570747 100644 --- a/make/data/symbols/jdk.incubator.vector-H.sym.txt +++ b/make/data/symbols/jdk.incubator.vector-H.sym.txt @@ -27,6 +27,20 @@ # ########################################################## # class name jdk/incubator/vector/ByteVector +header extends jdk/incubator/vector/AbstractVector flags 421 signature Ljdk/incubator/vector/AbstractVector; +innerclass innerClass jdk/incubator/vector/VectorOperators$Operator outerClass jdk/incubator/vector/VectorOperators innerClassName Operator flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorSpecies outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorSpecies flags 9 +innerclass innerClass jdk/incubator/vector/VectorOperators$Unary outerClass jdk/incubator/vector/VectorOperators innerClassName Unary flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Comparison outerClass jdk/incubator/vector/VectorOperators innerClassName Comparison flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Associative outerClass jdk/incubator/vector/VectorOperators innerClassName Associative flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Binary outerClass jdk/incubator/vector/VectorOperators innerClassName Binary flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$Vector outerClass jdk/internal/vm/vector/VectorSupport innerClassName Vector flags 9 +innerclass innerClass jdk/incubator/vector/VectorOperators$Ternary outerClass jdk/incubator/vector/VectorOperators innerClassName Ternary flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Test outerClass jdk/incubator/vector/VectorOperators innerClassName Test flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorMask outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorMask flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorShuffle outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorShuffle flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorPayload outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorPayload flags 9 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 method name fromBooleanArray descriptor (Ljdk/incubator/vector/VectorSpecies;[ZI)Ljdk/incubator/vector/ByteVector; flags 9 signature (Ljdk/incubator/vector/VectorSpecies;[ZI)Ljdk/incubator/vector/ByteVector; runtimeAnnotations @Ljdk/internal/vm/annotation/ForceInline; method name fromBooleanArray descriptor (Ljdk/incubator/vector/VectorSpecies;[ZILjdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/ByteVector; flags 9 signature (Ljdk/incubator/vector/VectorSpecies;[ZILjdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/ByteVector; runtimeAnnotations @Ljdk/internal/vm/annotation/ForceInline; method name fromBooleanArray descriptor (Ljdk/incubator/vector/VectorSpecies;[ZI[II)Ljdk/incubator/vector/ByteVector; flags 9 signature (Ljdk/incubator/vector/VectorSpecies;[ZI[II)Ljdk/incubator/vector/ByteVector; runtimeAnnotations @Ljdk/internal/vm/annotation/ForceInline; @@ -36,7 +50,85 @@ method name intoBooleanArray descriptor ([ZILjdk/incubator/vector/VectorMask;)V method name intoBooleanArray descriptor ([ZI[II)V flags 11 runtimeAnnotations @Ljdk/internal/vm/annotation/ForceInline; method name intoBooleanArray descriptor ([ZI[IILjdk/incubator/vector/VectorMask;)V flags 11 signature ([ZI[IILjdk/incubator/vector/VectorMask;)V runtimeAnnotations @Ljdk/internal/vm/annotation/ForceInline; +class name jdk/incubator/vector/DoubleVector +header extends jdk/incubator/vector/AbstractVector flags 421 signature Ljdk/incubator/vector/AbstractVector; +innerclass innerClass jdk/incubator/vector/VectorOperators$Operator outerClass jdk/incubator/vector/VectorOperators innerClassName Operator flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorSpecies outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorSpecies flags 9 +innerclass innerClass jdk/incubator/vector/VectorOperators$Unary outerClass jdk/incubator/vector/VectorOperators innerClassName Unary flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Comparison outerClass jdk/incubator/vector/VectorOperators innerClassName Comparison flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Associative outerClass jdk/incubator/vector/VectorOperators innerClassName Associative flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Binary outerClass jdk/incubator/vector/VectorOperators innerClassName Binary flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Ternary outerClass jdk/incubator/vector/VectorOperators innerClassName Ternary flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Test outerClass jdk/incubator/vector/VectorOperators innerClassName Test flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$Vector outerClass jdk/internal/vm/vector/VectorSupport innerClassName Vector flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorMask outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorMask flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorShuffle outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorShuffle flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorPayload outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorPayload flags 9 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name jdk/incubator/vector/FloatVector +header extends jdk/incubator/vector/AbstractVector flags 421 signature Ljdk/incubator/vector/AbstractVector; +innerclass innerClass jdk/incubator/vector/VectorOperators$Operator outerClass jdk/incubator/vector/VectorOperators innerClassName Operator flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorSpecies outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorSpecies flags 9 +innerclass innerClass jdk/incubator/vector/VectorOperators$Unary outerClass jdk/incubator/vector/VectorOperators innerClassName Unary flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Comparison outerClass jdk/incubator/vector/VectorOperators innerClassName Comparison flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Associative outerClass jdk/incubator/vector/VectorOperators innerClassName Associative flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Binary outerClass jdk/incubator/vector/VectorOperators innerClassName Binary flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Ternary outerClass jdk/incubator/vector/VectorOperators innerClassName Ternary flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Test outerClass jdk/incubator/vector/VectorOperators innerClassName Test flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$Vector outerClass jdk/internal/vm/vector/VectorSupport innerClassName Vector flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorMask outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorMask flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorShuffle outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorShuffle flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorPayload outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorPayload flags 9 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name jdk/incubator/vector/IntVector +header extends jdk/incubator/vector/AbstractVector flags 421 signature Ljdk/incubator/vector/AbstractVector; +innerclass innerClass jdk/incubator/vector/VectorOperators$Operator outerClass jdk/incubator/vector/VectorOperators innerClassName Operator flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorSpecies outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorSpecies flags 9 +innerclass innerClass jdk/incubator/vector/VectorOperators$Unary outerClass jdk/incubator/vector/VectorOperators innerClassName Unary flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Comparison outerClass jdk/incubator/vector/VectorOperators innerClassName Comparison flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Associative outerClass jdk/incubator/vector/VectorOperators innerClassName Associative flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Binary outerClass jdk/incubator/vector/VectorOperators innerClassName Binary flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$Vector outerClass jdk/internal/vm/vector/VectorSupport innerClassName Vector flags 9 +innerclass innerClass jdk/incubator/vector/VectorOperators$Ternary outerClass jdk/incubator/vector/VectorOperators innerClassName Ternary flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Test outerClass jdk/incubator/vector/VectorOperators innerClassName Test flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorMask outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorMask flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorShuffle outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorShuffle flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorPayload outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorPayload flags 9 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name jdk/incubator/vector/LongVector +header extends jdk/incubator/vector/AbstractVector flags 421 signature Ljdk/incubator/vector/AbstractVector; +innerclass innerClass jdk/incubator/vector/VectorOperators$Operator outerClass jdk/incubator/vector/VectorOperators innerClassName Operator flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorSpecies outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorSpecies flags 9 +innerclass innerClass jdk/incubator/vector/VectorOperators$Unary outerClass jdk/incubator/vector/VectorOperators innerClassName Unary flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Comparison outerClass jdk/incubator/vector/VectorOperators innerClassName Comparison flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Associative outerClass jdk/incubator/vector/VectorOperators innerClassName Associative flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Binary outerClass jdk/incubator/vector/VectorOperators innerClassName Binary flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$Vector outerClass jdk/internal/vm/vector/VectorSupport innerClassName Vector flags 9 +innerclass innerClass jdk/incubator/vector/VectorOperators$Ternary outerClass jdk/incubator/vector/VectorOperators innerClassName Ternary flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Test outerClass jdk/incubator/vector/VectorOperators innerClassName Test flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorMask outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorMask flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorShuffle outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorShuffle flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorPayload outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorPayload flags 9 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + class name jdk/incubator/vector/ShortVector +header extends jdk/incubator/vector/AbstractVector flags 421 signature Ljdk/incubator/vector/AbstractVector; +innerclass innerClass jdk/incubator/vector/VectorOperators$Operator outerClass jdk/incubator/vector/VectorOperators innerClassName Operator flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorSpecies outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorSpecies flags 9 +innerclass innerClass jdk/incubator/vector/VectorOperators$Unary outerClass jdk/incubator/vector/VectorOperators innerClassName Unary flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Comparison outerClass jdk/incubator/vector/VectorOperators innerClassName Comparison flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Associative outerClass jdk/incubator/vector/VectorOperators innerClassName Associative flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Binary outerClass jdk/incubator/vector/VectorOperators innerClassName Binary flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$Vector outerClass jdk/internal/vm/vector/VectorSupport innerClassName Vector flags 9 +innerclass innerClass jdk/incubator/vector/VectorOperators$Ternary outerClass jdk/incubator/vector/VectorOperators innerClassName Ternary flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Test outerClass jdk/incubator/vector/VectorOperators innerClassName Test flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorMask outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorMask flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorShuffle outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorShuffle flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorPayload outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorPayload flags 9 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 method name fromCharArray descriptor (Ljdk/incubator/vector/VectorSpecies;[CI)Ljdk/incubator/vector/ShortVector; flags 9 signature (Ljdk/incubator/vector/VectorSpecies;[CI)Ljdk/incubator/vector/ShortVector; runtimeAnnotations @Ljdk/internal/vm/annotation/ForceInline; method name fromCharArray descriptor (Ljdk/incubator/vector/VectorSpecies;[CILjdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/ShortVector; flags 9 signature (Ljdk/incubator/vector/VectorSpecies;[CILjdk/incubator/vector/VectorMask;)Ljdk/incubator/vector/ShortVector; runtimeAnnotations @Ljdk/internal/vm/annotation/ForceInline; method name fromCharArray descriptor (Ljdk/incubator/vector/VectorSpecies;[CI[II)Ljdk/incubator/vector/ShortVector; flags 9 signature (Ljdk/incubator/vector/VectorSpecies;[CI[II)Ljdk/incubator/vector/ShortVector; runtimeAnnotations @Ljdk/internal/vm/annotation/ForceInline; diff --git a/make/data/symbols/jdk.javadoc-H.sym.txt b/make/data/symbols/jdk.javadoc-H.sym.txt index b2ab2561f5c..d7d4a4c3779 100644 --- a/make/data/symbols/jdk.javadoc-H.sym.txt +++ b/make/data/symbols/jdk.javadoc-H.sym.txt @@ -29,9 +29,9 @@ class name jdk/javadoc/doclet/Reporter header extends java/lang/Object flags 601 innerclass innerClass javax/tools/Diagnostic$Kind outerClass javax/tools/Diagnostic innerClassName Kind flags 4019 +method name print descriptor (Ljavax/tools/Diagnostic$Kind;Ljavax/tools/FileObject;IIILjava/lang/String;)V flags 1 method name getStandardWriter descriptor ()Ljava/io/PrintWriter; flags 1 method name getDiagnosticWriter descriptor ()Ljava/io/PrintWriter; flags 1 -method name print descriptor (Ljavax/tools/Diagnostic$Kind;Ljavax/tools/FileObject;IIILjava/lang/String;)V flags 1 class name jdk/javadoc/doclet/StandardDoclet header extends java/lang/Object implements jdk/javadoc/doclet/Doclet flags 21 diff --git a/make/data/symbols/jdk.jfr-B.sym.txt b/make/data/symbols/jdk.jfr-B.sym.txt index a42ce39defe..be19cab9578 100644 --- a/make/data/symbols/jdk.jfr-B.sym.txt +++ b/make/data/symbols/jdk.jfr-B.sym.txt @@ -1,5 +1,5 @@ # -# Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2018, 2021, 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 @@ -27,7 +27,7 @@ # ########################################################## # module name jdk.jfr -header exports jdk/jfr,jdk/jfr/consumer requires name\u0020;java.base\u0020;flags\u0020;8000 target linux-amd64 flags 8000 +header exports jdk/jfr,jdk/jfr/consumer extraModulePackages jdk/jfr/internal requires name\u0020;java.base\u0020;flags\u0020;8000 target linux-amd64 flags 8000 class name jdk/jfr/AnnotationElement header extends java/lang/Object flags 31 @@ -390,3 +390,12 @@ method name readEventTypes descriptor ()Ljava/util/List; thrownTypes java/io/IOE method name close descriptor ()V thrownTypes java/io/IOException flags 1 method name readAllEvents descriptor (Ljava/nio/file/Path;)Ljava/util/List; thrownTypes java/io/IOException flags 9 signature (Ljava/nio/file/Path;)Ljava/util/List; +class name jdk/jfr/internal/Control +header extends java/lang/Object flags 421 +method name descriptor (Ljava/security/AccessControlContext;)V flags 1 +method name descriptor (Ljava/lang/String;)V flags 1 +method name combine descriptor (Ljava/util/Set;)Ljava/lang/String; flags 401 signature (Ljava/util/Set;)Ljava/lang/String; +method name setValue descriptor (Ljava/lang/String;)V flags 401 +method name getValue descriptor ()Ljava/lang/String; flags 401 +method name clone descriptor ()Ljava/lang/Object; thrownTypes java/lang/CloneNotSupportedException flags 11 + diff --git a/make/data/symbols/jdk.jfr-G.sym.txt b/make/data/symbols/jdk.jfr-G.sym.txt index 397e082021a..ba5b7e3a743 100644 --- a/make/data/symbols/jdk.jfr-G.sym.txt +++ b/make/data/symbols/jdk.jfr-G.sym.txt @@ -1,5 +1,5 @@ # -# Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2020, 2021, 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 @@ -26,6 +26,9 @@ # ### THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### # ########################################################## # +module name jdk.jfr +header exports jdk/jfr,jdk/jfr/consumer requires name\u0020;java.base\u0020;flags\u0020;8000 target linux-amd64 flags 8000 + class name jdk/jfr/SettingControl header extends java/lang/Object flags 421 runtimeAnnotations @Ljdk/jfr/MetadataDefinition; @@ -48,3 +51,5 @@ class name jdk/jfr/consumer/RecordedObject class name jdk/jfr/consumer/RecordingStream method name onMetadata descriptor (Ljava/util/function/Consumer;)V flags 1 signature (Ljava/util/function/Consumer;)V +-class name jdk/jfr/internal/Control + diff --git a/make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java b/make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java index 1f439e1c29e..ea700f0b660 100644 --- a/make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java +++ b/make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java @@ -25,6 +25,7 @@ package build.tools.symbolgenerator; +import build.tools.symbolgenerator.CreateSymbols.ModuleHeaderDescription.ExportsDescription; import build.tools.symbolgenerator.CreateSymbols .ModuleHeaderDescription .ProvidesDescription; @@ -122,6 +123,7 @@ import com.sun.tools.classfile.Field; import com.sun.tools.classfile.InnerClasses_attribute; import com.sun.tools.classfile.InnerClasses_attribute.Info; import com.sun.tools.classfile.Method; +import com.sun.tools.classfile.ModulePackages_attribute; import com.sun.tools.classfile.MethodParameters_attribute; import com.sun.tools.classfile.ModuleMainClass_attribute; import com.sun.tools.classfile.ModuleResolution_attribute; @@ -244,7 +246,14 @@ public class CreateSymbols { md, mhd, versionsList); - mhd.exports.stream().forEach(pkg -> { + List packages = new ArrayList<>(); + mhd.exports.stream() + .map(ExportsDescription::packageName) + .forEach(packages::add); + if (mhd.extraModulePackages != null) { + packages.addAll(mhd.extraModulePackages); + } + packages.stream().forEach(pkg -> { for (char v : mhd.versions.toCharArray()) { package2Version2Module.computeIfAbsent(pkg, dummy -> new HashMap<>()).put(v, md.name); } @@ -974,13 +983,21 @@ public class CreateSymbols { return new RequiresEntry(idx, r.flags, r.version != null - ? addInt(cp, r.version) + ? addString(cp, r.version) : 0); } private static ExportsEntry createExportsEntry(List cp, - String e) { - return new ExportsEntry(addPackageName(cp, e), 0, new int[0]); + ExportsDescription export) { + int[] to; + if (export.isQualified()) { + to = export.to.stream() + .mapToInt(module -> addModuleName(cp, module)) + .toArray(); + } else { + to = new int[0]; + } + return new ExportsEntry(addPackageName(cp, export.packageName()), 0, to); } private static OpensEntry createOpensEntry(List cp, String e) { @@ -1405,7 +1422,7 @@ public class CreateSymbols { dumpDescriptions(classes, modules, platforms, Set.of(), descDest.resolve("symbols"), args); } //where: - private static final String DO_NO_MODIFY = + public static String DO_NOT_MODIFY = "#\n" + "# Copyright (c) {YEAR}, Oracle and/or its affiliates. All rights reserved.\n" + "# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.\n" + @@ -1477,14 +1494,19 @@ public class CreateSymbols { ExcludeIncludeList currentEIList = excludesIncludes; if (!currentVersionModules.isEmpty()) { + Set privateIncludes = + enhancedIncludesListBasedOnClassHeaders(classes, classData); Set includes = new HashSet<>(); for (ModuleDescription md : currentVersionModules.values()) { - md.header.get(0).exports.stream().map(e -> e + '/') + md.header.get(0).exports.stream() + .filter(e -> !e.isQualified()) + .map(e -> e.packageName + '/') .forEach(includes::add); } currentEIList = new ExcludeIncludeList(includes, + privateIncludes, Collections.emptySet()); } @@ -1507,7 +1529,9 @@ public class CreateSymbols { if (unsupported.header .get(0) .exports - .contains(cd.packge().replace('.', '/'))) { + .stream() + .map(ed -> ed.packageName) + .anyMatch(pack -> pack.equals(cd.packge().replace('.', '/')))) { ClassHeaderDescription ch = cd.header.get(0); if (ch.classAnnotations == null) { ch.classAnnotations = new ArrayList<>(); @@ -1529,7 +1553,7 @@ public class CreateSymbols { for (ClassDescription clazz : currentVersionClasses) { ClassHeaderDescription header = clazz.header.get(0); - if (includeEffectiveAccess(currentVersionClasses, clazz)) { + if (includeEffectiveAccess(currentVersionClasses, clazz) && currentEIList.accepts(clazz.name, false)) { modified |= include(includedClasses, currentVersionClasses, clazz.name); } @@ -1555,6 +1579,8 @@ public class CreateSymbols { } } while (modified); + Set allIncludedPackages = new HashSet<>(); + for (ClassDescription clazz : currentVersionClasses) { if (!includedClasses.contains(clazz.name)) { continue; @@ -1595,6 +1621,8 @@ public class CreateSymbols { } else { classes.add(clazz); } + + allIncludedPackages.add(clazz.packge().replace('.', '/')); } for (ModuleDescription module : currentVersionModules.values()) { @@ -1611,6 +1639,13 @@ public class CreateSymbols { } } + header.exports.removeIf(ed -> ed.isQualified() && + !allIncludedPackages.contains(ed.packageName())); + + if (header.extraModulePackages != null) { + header.extraModulePackages.retainAll(allIncludedPackages); + } + ModuleDescription existing = modules.get(module.name); if (existing != null) { @@ -1642,7 +1677,16 @@ public class CreateSymbols { md.header .stream() .filter(h -> h.versions.contains(v.version)) - .flatMap(h -> h.exports.stream()) + .flatMap(h -> { + List packages = new ArrayList<>(); + h.exports.stream() + .map(ExportsDescription::packageName) + .forEach(packages::add); + if (h.extraModulePackages != null) { + packages.addAll(h.extraModulePackages); + } + return packages.stream(); + }) .map(p -> p.replace('/', '.')) .forEach(p -> package2Modules.putIfAbsent(p, md.name)); } @@ -1718,11 +1762,11 @@ public class CreateSymbols { boolean hasChange = true; if (Files.isReadable(f)) { String oldContent = Files.readString(f, StandardCharsets.UTF_8); - int yearPos = DO_NO_MODIFY.indexOf("{YEAR}"); + int yearPos = DO_NOT_MODIFY.indexOf("{YEAR}"); String headerPattern = - Pattern.quote(DO_NO_MODIFY.substring(0, yearPos)) + + Pattern.quote(DO_NOT_MODIFY.substring(0, yearPos)) + "([0-9]+)(, [0-9]+)?" + - Pattern.quote(DO_NO_MODIFY.substring(yearPos + "{YEAR}".length())); + Pattern.quote(DO_NOT_MODIFY.substring(yearPos + "{YEAR}".length())); String pattern = headerPattern + Pattern.quote(dataString); Matcher m = Pattern.compile(pattern, Pattern.MULTILINE).matcher(oldContent); @@ -1739,7 +1783,7 @@ public class CreateSymbols { try (Writer out = Files.newBufferedWriter(f, StandardCharsets.UTF_8)) { String currentYear = String.valueOf(year); String yearSpec = (existingYear != null && !currentYear.equals(existingYear) ? existingYear + ", " : "") + currentYear; - out.append(DO_NO_MODIFY.replace("{YEAR}", yearSpec)); + out.append(DO_NOT_MODIFY.replace("{YEAR}", yearSpec)); out.write(dataString); } } @@ -1750,7 +1794,7 @@ public class CreateSymbols { outputFiles.put(desc, files); } - symbolsOut.append(DO_NO_MODIFY.replace("{YEAR}", "2015, " + year)); + symbolsOut.append(DO_NOT_MODIFY.replace("{YEAR}", "2015, " + year)); symbolsOut.append("#command used to generate this file:\n"); symbolsOut.append("#") .append(CreateSymbols.class.getName()) @@ -1923,7 +1967,7 @@ public class CreateSymbols { return ; } - if (!excludesIncludes.accepts(cf.getName())) { + if (!excludesIncludes.accepts(cf.getName(), true)) { return ; } @@ -2019,6 +2063,45 @@ public class CreateSymbols { addModuleHeader(moduleDesc, headerDesc, version); } + private Set enhancedIncludesListBasedOnClassHeaders(ClassList classes, + Iterable classData) { + Set additionalIncludes = new HashSet<>(); + + for (byte[] classFileData : classData) { + try (InputStream in = new ByteArrayInputStream(classFileData)) { + ClassFile cf = ClassFile.read(in); + + if (cf.access_flags.is(AccessFlags.ACC_MODULE)) { + continue; + } + + Set additionalClasses = new HashSet<>(); + + if (cf.super_class != 0) { + additionalClasses.add(cf.getSuperclassName()); + } + for (int i = 0; i < cf.interfaces.length; i++) { + additionalClasses.add(cf.getInterfaceName(i)); + } + + for (String additional : additionalClasses) { + int dollar; + + additionalIncludes.add(additional); + + while ((dollar = additional.lastIndexOf('$')) != (-1)) { + additional = additional.substring(0, dollar); + additionalIncludes.add(additional); + } + } + } catch (IOException | ConstantPoolException ex) { + throw new IllegalStateException(ex); + } + } + + return additionalIncludes; + } + private void addModuleHeader(ModuleDescription moduleDesc, ModuleHeaderDescription headerDesc, String version) { @@ -2204,9 +2287,11 @@ public class CreateSymbols { header.exports = Arrays.stream(mod.exports) - .filter(ee -> ee.exports_to_count == 0) - .map(ee -> getPackageName(cf, ee.exports_index)) + .map(ee -> ExportsDescription.create(cf, ee)) .collect(Collectors.toList()); + if (header.extraModulePackages != null) { + header.exports.forEach(ed -> header.extraModulePackages.remove(ed.packageName())); + } header.requires = Arrays.stream(mod.requires) .map(r -> RequiresDescription.create(cf, r)) @@ -2242,6 +2327,20 @@ public class CreateSymbols { break; } case Attribute.ModulePackages: + assert feature instanceof ModuleHeaderDescription; + ModuleHeaderDescription header = + (ModuleHeaderDescription) feature; + ModulePackages_attribute mod = + (ModulePackages_attribute) attr; + header.extraModulePackages = new ArrayList<>(); + for (int i = 0; i < mod.packages_count; i++) { + String packageName = getPackageName(cf, mod.packages_index[i]); + if (header.exports == null || + header.exports.stream().noneMatch(ed -> ed.packageName().equals(packageName))) { + header.extraModulePackages.add(packageName); + } + } + break; case Attribute.ModuleHashes: break; case Attribute.NestHost: { @@ -2352,11 +2451,16 @@ public class CreateSymbols { } } - private static Integer getVersion(ClassFile cf, int idx) { + public static String INJECTED_VERSION = null; + + private static String getVersion(ClassFile cf, int idx) { + if (INJECTED_VERSION != null) { + return INJECTED_VERSION; + } if (idx == 0) return null; try { - return ((CONSTANT_Integer_info) cf.constant_pool.get(idx)).value; + return ((CONSTANT_Utf8_info) cf.constant_pool.get(idx)).value; } catch (InvalidIndex ex) { throw new IllegalStateException(ex); } @@ -2470,9 +2574,15 @@ public class CreateSymbols { if (clazzName == null) return false; + ClassDescription desc = classes.find(clazzName, true); + + if (desc == null) { + return false; + } + boolean modified = includedClasses.add(clazzName); - for (ClassDescription outer : classes.enclosingClasses(classes.find(clazzName, true))) { + for (ClassDescription outer : classes.enclosingClasses(desc)) { modified |= includedClasses.add(outer.name); } @@ -2514,10 +2624,17 @@ public class CreateSymbols { public static class ExcludeIncludeList { public final Set includeList; + public final Set privateIncludeList; public final Set excludeList; protected ExcludeIncludeList(Set includeList, Set excludeList) { + this(includeList, Set.of(), excludeList); + } + + protected ExcludeIncludeList(Set includeList, Set privateIncludeList, + Set excludeList) { this.includeList = includeList; + this.privateIncludeList = privateIncludeList; this.excludeList = excludeList; } @@ -2537,8 +2654,10 @@ public class CreateSymbols { return new ExcludeIncludeList(includeList, excludeList); } - public boolean accepts(String className) { - return matches(includeList, className) && !matches(excludeList, className); + public boolean accepts(String className, boolean includePrivateClasses) { + return (matches(includeList, className) || + (includePrivateClasses && matches(privateIncludeList, className))) && + !matches(excludeList, className); } private static boolean matches(Set list, String className) { @@ -2738,8 +2857,9 @@ public class CreateSymbols { static class ModuleHeaderDescription extends HeaderDescription { String name; - List exports = new ArrayList<>(); + List exports = new ArrayList<>(); List opens = new ArrayList<>(); + List extraModulePackages = new ArrayList<>(); List requires = new ArrayList<>(); List uses = new ArrayList<>(); List provides = new ArrayList<>(); @@ -2753,6 +2873,7 @@ public class CreateSymbols { hash = 83 * hash + Objects.hashCode(this.name); hash = 83 * hash + Objects.hashCode(this.exports); hash = 83 * hash + Objects.hashCode(this.opens); + hash = 83 * hash + Objects.hashCode(this.extraModulePackages); hash = 83 * hash + Objects.hashCode(this.requires); hash = 83 * hash + Objects.hashCode(this.uses); hash = 83 * hash + Objects.hashCode(this.provides); @@ -2781,6 +2902,9 @@ public class CreateSymbols { if (!listEquals(this.opens, other.opens)) { return false; } + if (!listEquals(this.extraModulePackages, other.extraModulePackages)) { + return false; + } if (!listEquals(this.requires, other.requires)) { return false; } @@ -2812,10 +2936,17 @@ public class CreateSymbols { && versions.contains(version))) return ; output.append("header"); - if (exports != null && !exports.isEmpty()) - output.append(" exports " + serializeList(exports)); + if (exports != null && !exports.isEmpty()) { + List exportsList = + exports.stream() + .map(exp -> exp.serialize()) + .collect(Collectors.toList()); + output.append(" exports " + serializeList(exportsList)); + } if (opens != null && !opens.isEmpty()) output.append(" opens " + serializeList(opens)); + if (extraModulePackages != null && !extraModulePackages.isEmpty()) + output.append(" extraModulePackages " + serializeList(extraModulePackages)); if (requires != null && !requires.isEmpty()) { List requiresList = requires.stream() @@ -2862,8 +2993,12 @@ public class CreateSymbols { if (!"header".equals(reader.lineKey)) return false; - exports = deserializeList(reader.attributes.get("exports")); + List exportsList = deserializeList(reader.attributes.get("exports"), false); + exports = exportsList.stream() + .map(ExportsDescription::deserialize) + .collect(Collectors.toList()); opens = deserializeList(reader.attributes.get("opens")); + extraModulePackages = deserializeList(reader.attributes.get("extraModulePackages")); List requiresList = deserializeList(reader.attributes.get("requires")); requires = requiresList.stream() @@ -2893,13 +3028,53 @@ public class CreateSymbols { return true; } + record ExportsDescription(String packageName, List to) { + public String serialize() { + return packageName + + (isQualified() ? "[" + quote(serializeList(to), true, true) + "]" + : ""); + } + + public static ExportsDescription deserialize(String data) { + int bracket = data.indexOf("["); + String packageName; + List to; + if (bracket != (-1)) { + packageName = data.substring(0, bracket); + to = deserializeList(unquote(data.substring(bracket + 1, data.length() - 1))); + } else { + packageName = data; + to = null; + } + + return new ExportsDescription(packageName, to); + } + + public static ExportsDescription create(ClassFile cf, + ExportsEntry ee) { + String packageName = getPackageName(cf, ee.exports_index); + List to = null; + if (ee.exports_to_count > 0) { + to = new ArrayList<>(); + for (int moduleIndex : ee.exports_to_index) { + to.add(getModuleName(cf, moduleIndex)); + } + } + return new ExportsDescription(packageName, to); + } + + public boolean isQualified() { + return to != null && !to.isEmpty(); + } + } + static class RequiresDescription { final String moduleName; final int flags; - final Integer version; + final String version; public RequiresDescription(String moduleName, int flags, - Integer version) { + String version) { this.moduleName = moduleName; this.flags = flags; this.version = version; @@ -2907,7 +3082,7 @@ public class CreateSymbols { public String serialize() { String versionKeyValue = version != null - ? " version " + quote(String.valueOf(version), true) + ? " version " + quote(version, true) : ""; return "name " + quote(moduleName, true) + " flags " + quote(Integer.toHexString(flags), true) + @@ -2917,8 +3092,8 @@ public class CreateSymbols { public static RequiresDescription deserialize(String data) { Map attributes = splitAttributes(data); - Integer ver = attributes.containsKey("version") - ? Integer.parseInt(attributes.get("version")) + String ver = attributes.containsKey("version") + ? attributes.get("version") : null; int flags = Integer.parseInt(attributes.get("flags"), 16); return new RequiresDescription(attributes.get("name"), @@ -2929,7 +3104,7 @@ public class CreateSymbols { public static RequiresDescription create(ClassFile cf, RequiresEntry req) { String mod = getModuleName(cf, req.requires_index); - Integer ver = getVersion(cf, req.requires_version_index); + String ver = getVersion(cf, req.requires_version_index); return new RequiresDescription(mod, req.requires_flags, ver); @@ -3071,10 +3246,24 @@ public class CreateSymbols { header.write(output, baselineVersion, version); } for (FieldDescription field : fields) { - field.write(output, baselineVersion, version); + if (!field.versions.contains(version)) { + field.write(output, baselineVersion, version); + } + } + for (MethodDescription method : methods) { + if (!method.versions.contains(version)) { + method.write(output, baselineVersion, version); + } + } + for (FieldDescription field : fields) { + if (field.versions.contains(version)) { + field.write(output, baselineVersion, version); + } } for (MethodDescription method : methods) { - method.write(output, baselineVersion, version); + if (method.versions.contains(version)) { + method.write(output, baselineVersion, version); + } } output.append("\n"); } @@ -3157,6 +3346,12 @@ public class CreateSymbols { return pack; } + + @Override + public String toString() { + return name; + } + } static class ClassHeaderDescription extends HeaderDescription { @@ -3265,12 +3460,12 @@ public class CreateSymbols { readRecordComponents(reader); } readInnerClasses(reader); + isSealed = reader.attributes.containsKey("permittedSubclasses"); if (isSealed) { String subclassesList = reader.attributes.get("permittedSubclasses"); permittedSubclasses = deserializeList(subclassesList); } - return true; } @@ -4120,8 +4315,11 @@ public class CreateSymbols { } w.write("module:" + module.name); w.write("\n"); - for (String pack : header.get().exports) { - w.write(pack.replace('/', '.')); + for (ExportsDescription export : header.get().exports) { + if (export.isQualified()) { + continue; + } + w.write(export.packageName.replace('/', '.')); w.write("\n"); } } diff --git a/test/langtools/tools/javac/platform/NonExportedSuperTypes.java b/test/langtools/tools/javac/platform/NonExportedSuperTypes.java new file mode 100644 index 00000000000..b3f17fd6e3c --- /dev/null +++ b/test/langtools/tools/javac/platform/NonExportedSuperTypes.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2021, 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. + */ + +/* + * @test + * @bug 8277106 + * @summary Verify no error is when compiling a class whose supertype is not exported. + * @modules jdk.compiler + * jdk.jfr + * @compile --release 17 NonExportedSuperTypes.java + */ + +import jdk.jfr.Event; + +public class NonExportedSuperTypes { + + public void evt(Event evt) { + evt.toString(); + } + +} diff --git a/test/langtools/tools/javac/platform/createsymbols/CreateSymbolsTest.java b/test/langtools/tools/javac/platform/createsymbols/CreateSymbolsTest.java index 2f201fd0067..c54c21bfc0d 100644 --- a/test/langtools/tools/javac/platform/createsymbols/CreateSymbolsTest.java +++ b/test/langtools/tools/javac/platform/createsymbols/CreateSymbolsTest.java @@ -23,7 +23,7 @@ /** * @test - * @bug 8072480 + * @bug 8072480 8277106 * @summary Unit test for CreateSymbols * @modules java.compiler * jdk.compiler/com.sun.tools.javac.api diff --git a/test/langtools/tools/javac/platform/createsymbols/CreateSymbolsTestImpl.java b/test/langtools/tools/javac/platform/createsymbols/CreateSymbolsTestImpl.java index 42b9649311a..307c53135a7 100644 --- a/test/langtools/tools/javac/platform/createsymbols/CreateSymbolsTestImpl.java +++ b/test/langtools/tools/javac/platform/createsymbols/CreateSymbolsTestImpl.java @@ -28,8 +28,14 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.reflect.Method; import java.util.Arrays; +import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.io.IOException; +import java.io.OutputStream; +import java.nio.charset.StandardCharsets; +import java.nio.file.DirectoryStream; import java.nio.file.FileVisitResult; import java.nio.file.FileVisitor; import java.nio.file.Files; @@ -52,6 +58,14 @@ import build.tools.symbolgenerator.CreateSymbols.ClassDescription; import build.tools.symbolgenerator.CreateSymbols.ClassList; import build.tools.symbolgenerator.CreateSymbols.ExcludeIncludeList; import build.tools.symbolgenerator.CreateSymbols.VersionDescription; +import com.sun.tools.classfile.Attribute; +import com.sun.tools.classfile.Attributes; +import com.sun.tools.classfile.ClassFile; +import com.sun.tools.classfile.ClassWriter; +import com.sun.tools.classfile.ConstantPool; +import com.sun.tools.classfile.ConstantPool.CPInfo; +import com.sun.tools.classfile.ConstantPool.CONSTANT_Utf8_info; +import com.sun.tools.classfile.ModulePackages_attribute; public class CreateSymbolsTestImpl { @@ -641,6 +655,306 @@ public class CreateSymbolsTestImpl { """); } + @Test + void testNonExportedSuperclass() throws Exception { + doTestComplex("api.Api", + """ + package api; + + public class Api extends nonapi.Impl.Nested.Exp { + + public Api(); + } + """, + """ + import api.Api; + public class Test { + private void t(Api api) { + api.run(); + } + } + """, + """ + import api.Api; + public class Test { + private void t(Api api) { + fail + } + } + """, + """ + module m { + exports api; + } + """, + """ + package api; + import nonapi.Impl; + public class Api extends Impl.Nested.Exp { + } + """, + """ + package api; + public @interface Ann { + } + """, + """ + package nonapi; + import api.Ann; + public class Impl { + public static final String C = ""; + public void test() {} + @Ann + public static class Nested { + public static class Exp extends Nested implements Runnable { + public void run() {} + public OtherNested get() { return null; } + } + } + public static class OtherNested {} + } + """); + } + + void doTestComplex(String printClass, + String expected, + String depSuccess, + String depFailure, + String... code) throws Exception { + ToolBox tb = new ToolBox(); + String testClasses = System.getProperty("test.classes"); + Path output = Paths.get(testClasses, "test-data" + i++); + deleteRecursively(output); + Files.createDirectories(output); + Path ver9Jar = output.resolve("9.jar"); + compileAndPack(output, + ver9Jar, + code); + + + Path ctSym = output.resolve("ct.sym"); + + deleteRecursively(ctSym); + + CreateSymbols.ALLOW_NON_EXISTING_CLASSES = true; + CreateSymbols.EXTENSION = ".class"; + + deleteRecursively(ctSym); + + List versions = + Arrays.asList(new VersionDescription(ver9Jar.toAbsolutePath().toString(), "9", null)); + + ExcludeIncludeList acceptAll = new ExcludeIncludeList(null, null) { + @Override public boolean accepts(String className, boolean includePrivateClasses) { + return true; + } + }; + new CreateSymbols().createBaseLine(versions, acceptAll, ctSym, new String[0]); + Path symbolsDesc = ctSym.resolve("symbols"); + Path systemModules = ctSym.resolve("systemModules"); + + Files.newBufferedWriter(systemModules).close(); + + Path classesZip = output.resolve("classes.zip"); + Path classesDir = output.resolve("classes"); + + new CreateSymbols().createSymbols(null, symbolsDesc.toAbsolutePath().toString(), classesZip.toAbsolutePath().toString(), 0, "9", systemModules.toString()); + + try (JarFile jf = new JarFile(classesZip.toFile())) { + Enumeration en = jf.entries(); + + while (en.hasMoreElements()) { + JarEntry je = en.nextElement(); + if (je.isDirectory()) continue; + Path target = classesDir.resolve(je.getName()); + Files.createDirectories(target.getParent()); + Files.copy(jf.getInputStream(je), target); + } + } + + Path classes = classesDir; + Path scratch = output.resolve("scratch"); + + Files.createDirectories(scratch); + + String modulePath; + + try (Stream elements = Files.list(classes)) { + modulePath = elements.filter(el -> el.getFileName().toString().contains("9")) + .map(el -> el.resolve("m")) + .map(el -> el.toAbsolutePath().toString()) + .collect(Collectors.joining(File.pathSeparator)); + } + + { + String out = new JavacTask(tb, Task.Mode.CMDLINE) + .options("-d", scratch.toAbsolutePath().toString(), "--module-path", modulePath, + "--add-modules", "m", "-Xprint", "api.Api") + .run(Expect.SUCCESS) + .getOutput(Task.OutputKind.STDOUT) + .replaceAll("\\R", "\n"); + + if (!out.equals(expected)) { + throw new AssertionError("out=" + out + "; expected=" + expected); + } + } + + { + new JavacTask(tb) + .options("-d", scratch.toAbsolutePath().toString(), "--module-path", modulePath, + "--add-modules", "m") + .sources(depSuccess) + .run(Expect.SUCCESS) + .writeAll(); + } + + { + String expectedFailure = new JavacTask(tb) + .options("-d", scratch.toAbsolutePath().toString(), "--module-path", output.resolve("temp").toString(), + "--add-modules", "m", "-XDrawDiagnostics") + .sources(depFailure) + .run(Expect.FAIL) + .getOutput(Task.OutputKind.DIRECT) + .replaceAll("\\R", "\n"); + + String out = new JavacTask(tb) + .options("-d", scratch.toAbsolutePath().toString(), "--module-path", modulePath, + "--add-modules", "m", "-XDrawDiagnostics") + .sources(depFailure) + .run(Expect.FAIL) + .getOutput(Task.OutputKind.DIRECT) + .replaceAll("\\R", "\n"); + + if (!out.equals(expectedFailure)) { + throw new AssertionError("out=" + out + "; expected=" + expectedFailure); + } + } + } + + @Test + void testExtendsInternalData1() throws Exception { + doTestData(""" + module name m + header exports api,nonapi[java.base] requires name\\u0020;java.base\\u0020;flags\\u0020;8000\\u0020;version\\u0020;0 flags 8000 + + class name api/Ann + header extends java/lang/Object implements java/lang/annotation/Annotation flags 2601 + + class name api/Api + header extends nonapi/Impl$Nested$Exp flags 21 + innerclass innerClass nonapi/Impl$Nested outerClass nonapi/Impl innerClassName Nested flags 9 + innerclass innerClass nonapi/Impl$Nested$Exp outerClass nonapi/Impl$Nested innerClassName Exp flags 9 + method name descriptor ()V flags 1 + + class name nonapi/Impl + header extends java/lang/Object nestMembers nonapi/Impl$Nested,nonapi/Impl$Nested$Exp flags 21 + innerclass innerClass nonapi/Impl$Nested outerClass nonapi/Impl innerClassName Nested flags 9 + innerclass innerClass nonapi/Impl$Nested$Exp outerClass nonapi/Impl$Nested innerClassName Exp flags 9 + field name C descriptor Ljava/lang/String; constantValue flags 19 + method name descriptor ()V flags 1 + method name test descriptor ()V flags 1 + + class name nonapi/Impl$Nested + header extends java/lang/Object nestHost nonapi/Impl flags 21 classAnnotations @Lapi/Ann; + innerclass innerClass nonapi/Impl$Nested outerClass nonapi/Impl innerClassName Nested flags 9 + innerclass innerClass nonapi/Impl$Nested$Exp outerClass nonapi/Impl$Nested innerClassName Exp flags 9 + method name descriptor ()V flags 1 + + class name nonapi/Impl$Nested$Exp + header extends nonapi/Impl$Nested implements java/lang/Runnable nestHost nonapi/Impl flags 21 + innerclass innerClass nonapi/Impl$Nested outerClass nonapi/Impl innerClassName Nested flags 9 + innerclass innerClass nonapi/Impl$Nested$Exp outerClass nonapi/Impl$Nested innerClassName Exp flags 9 + method name descriptor ()V flags 1 + method name run descriptor ()V flags 1 + method name get descriptor ()Lnonapi/Impl$OtherNested; flags 1 + + """, + """ + module m { + exports api; + exports nonapi to java.base; + } + """, + """ + package api; + import nonapi.Impl; + public class Api extends Impl.Nested.Exp { + } + """, + """ + package api; + public @interface Ann { + } + """, + """ + package nonapi; + import api.Ann; + public class Impl { + public static final String C = ""; + public void test() {} + @Ann + public static class Nested { + public static class Exp extends Nested implements Runnable { + public void run() {} + public OtherNested get() { return null; } + } + } + public static class OtherNested {} + } + """); + } + + void doTestData(String data, + String... code) throws Exception { + String testClasses = System.getProperty("test.classes"); + Path output = Paths.get(testClasses, "test-data" + i++); + deleteRecursively(output); + Files.createDirectories(output); + Path ver9Jar = output.resolve("9.jar"); + compileAndPack(output, + ver9Jar, + code); + + Path ctSym = output.resolve("ct.sym"); + + deleteRecursively(ctSym); + + CreateSymbols.ALLOW_NON_EXISTING_CLASSES = true; + CreateSymbols.DO_NOT_MODIFY = ""; + CreateSymbols.EXTENSION = ".class"; + CreateSymbols.INJECTED_VERSION = "0"; + + deleteRecursively(ctSym); + + List versions = + Arrays.asList(new VersionDescription(ver9Jar.toAbsolutePath().toString(), "9", null)); + + ExcludeIncludeList acceptAll = new ExcludeIncludeList(null, null) { + @Override public boolean accepts(String className, boolean includePrivateClasses) { + return true; + } + }; + new CreateSymbols().createBaseLine(versions, acceptAll, ctSym, new String[0]); + + Path symFile = null; + + try (DirectoryStream ds = Files.newDirectoryStream(ctSym)) { + for (Path p : ds) { + if (p.toString().endsWith(".sym.txt")) { + if (symFile != null) { + throw new IllegalStateException("Multiple sym files!"); + } else { + symFile = p; + } + } + } + } + String acutalContent = new String(Files.readAllBytes(symFile), StandardCharsets.UTF_8); + if (!acutalContent.equals(data)) { + throw new AssertionError("out=" + acutalContent + "; expected=" + data); + } + } + void doTestIncluded(String code, String... includedClasses) throws Exception { boolean oldIncludeAll = includeAll; try { @@ -712,7 +1026,7 @@ public class CreateSymbolsTestImpl { new VersionDescription(jar8.toAbsolutePath().toString(), "8", "7")); ExcludeIncludeList acceptAll = new ExcludeIncludeList(null, null) { - @Override public boolean accepts(String className) { + @Override public boolean accepts(String className, boolean includePrivateClasses) { return true; } }; @@ -743,6 +1057,36 @@ public class CreateSymbolsTestImpl { System.err.println(Arrays.asList(code)); new JavacTask(tb).sources(code).options("-d", scratch.toAbsolutePath().toString()).run(Expect.SUCCESS); List classFiles = collectClassFile(scratch); + Path moduleInfo = scratch.resolve("module-info.class"); + if (Files.exists(moduleInfo)) { + Set packages = new HashSet<>(); + for (String cf : classFiles) { + int sep = cf.lastIndexOf(scratch.getFileSystem().getSeparator()); + if (sep != (-1)) { + packages.add(cf.substring(0, sep)); + } + } + ClassFile cf = ClassFile.read(moduleInfo); + List cp = new ArrayList<>(); + cp.add(null); + cf.constant_pool.entries().forEach(cp::add); + Map attrs = new HashMap<>(cf.attributes.map); + int[] encodedPackages = new int[packages.size()]; + int i = 0; + for (String p : packages) { + int nameIndex = cp.size(); + cp.add(new CONSTANT_Utf8_info(p)); + encodedPackages[i++] = cp.size(); + cp.add(new ConstantPool.CONSTANT_Package_info(null, nameIndex)); + } + int attrName = cp.size(); + cp.add(new CONSTANT_Utf8_info(Attribute.ModulePackages)); + attrs.put(Attribute.ModulePackages, new ModulePackages_attribute(attrName, encodedPackages)); + ClassFile newFile = new ClassFile(cf.magic, cf.minor_version, cf.major_version, new ConstantPool(cp.toArray(new CPInfo[0])), cf.access_flags, cf.this_class, cf.super_class, cf.interfaces, cf.fields, cf.methods, new Attributes(attrs)); + try (OutputStream out = Files.newOutputStream(moduleInfo)) { + new ClassWriter().write(newFile, out); + } + } try (Writer out = Files.newBufferedWriter(outputFile)) { for (String classFile : classFiles) { try (InputStream in = Files.newInputStream(scratch.resolve(classFile))) { -- GitLab From fb11d8faf21539a8dc08d371658d1835484c8344 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Wed, 8 Dec 2021 19:48:05 +0000 Subject: [PATCH 065/671] 8272945: Use snippets in java.compiler documentation Reviewed-by: erikj, alanb --- make/CompileInterimLangtools.gmk | 2 +- make/modules/java.compiler/Java.gmk | 2 + .../classes/javax/tools/JavaCompiler.java | 64 +++++++------------ .../classes/javax/tools/JavaFileManager.java | 26 +++++--- .../javax/tools/StandardJavaFileManager.java | 32 +++++----- .../classes/javax/tools/package-info.java | 14 ++-- .../snippet-files/JavaSourceFromString.java | 54 ++++++++++++++++ 7 files changed, 122 insertions(+), 72 deletions(-) create mode 100644 src/java.compiler/share/classes/javax/tools/snippet-files/JavaSourceFromString.java diff --git a/make/CompileInterimLangtools.gmk b/make/CompileInterimLangtools.gmk index a6a42f6a9cd..3fff64db1f8 100644 --- a/make/CompileInterimLangtools.gmk +++ b/make/CompileInterimLangtools.gmk @@ -71,7 +71,7 @@ define SetupInterimModule SRC := $(BUILDTOOLS_OUTPUTDIR)/gensrc/$1.interim \ $$(wildcard $(SUPPORT_OUTPUTDIR)/gensrc/$1) \ $(TOPDIR)/src/$1/share/classes, \ - EXCLUDES := sun, \ + EXCLUDES := sun javax/tools/snippet-files, \ EXCLUDE_FILES := $(TOPDIR)/src/$1/share/classes/module-info.java \ Standard.java, \ EXTRA_FILES := $(BUILDTOOLS_OUTPUTDIR)/gensrc/$1.interim/module-info.java, \ diff --git a/make/modules/java.compiler/Java.gmk b/make/modules/java.compiler/Java.gmk index e124e8844d3..e2d5ac264b8 100644 --- a/make/modules/java.compiler/Java.gmk +++ b/make/modules/java.compiler/Java.gmk @@ -25,3 +25,5 @@ DOCLINT += -Xdoclint:all/protected \ '-Xdoclint/package:java.*,javax.*' + +EXCLUDES += javax/tools/snippet-files diff --git a/src/java.compiler/share/classes/javax/tools/JavaCompiler.java b/src/java.compiler/share/classes/javax/tools/JavaCompiler.java index f7c1c61a41b..9039490524b 100644 --- a/src/java.compiler/share/classes/javax/tools/JavaCompiler.java +++ b/src/java.compiler/share/classes/javax/tools/JavaCompiler.java @@ -26,6 +26,7 @@ package javax.tools; import java.io.Writer; +import java.net.URI; import java.nio.charset.Charset; import java.util.Locale; import java.util.concurrent.Callable; @@ -106,42 +107,45 @@ import javax.annotation.processing.Processor; * work with multiple sequential compilations making the following * example a recommended coding pattern: * - *

- *       File[] files1 = ... ; // input for first compilation task
- *       File[] files2 = ... ; // input for second compilation task
+ *     {@snippet id="use-sjfm" lang=java :
+ *       File[] files1 = null ; // input for first compilation task     // @replace substring=null replacement="..."
+ *       File[] files2 = null ; // input for second compilation task    // @replace substring=null replacement="..."
  *
  *       JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
  *       StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
  *
- *       {@code Iterable} compilationUnits1 =
- *           fileManager.getJavaFileObjectsFromFiles({@linkplain java.util.Arrays#asList Arrays.asList}(files1));
+ *       Iterable compilationUnits1 =
+ *           fileManager.getJavaFileObjectsFromFiles(Arrays.asList(files1));  // @link substring=Arrays.asList target="java.util.Arrays#asList"
  *       compiler.getTask(null, fileManager, null, null, null, compilationUnits1).call();
  *
- *       {@code Iterable} compilationUnits2 =
+ *       Iterable compilationUnits2 =
  *           fileManager.getJavaFileObjects(files2); // use alternative method
  *       // reuse the same file manager to allow caching of jar files
  *       compiler.getTask(null, fileManager, null, null, null, compilationUnits2).call();
  *
- *       fileManager.close();
+ * fileManager.close(); + * } * * * *
{@link DiagnosticCollector}
*
* Used to collect diagnostics in a list, for example: - *
- *       {@code Iterable} compilationUnits = ...;
+ *     {@snippet id="use-diag-collector" lang=java :
+ *       Iterable compilationUnits = null;        // @replace substring=null replacement="..."
  *       JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
- *       {@code DiagnosticCollector diagnostics = new DiagnosticCollector();}
+ *       DiagnosticCollector diagnostics = new DiagnosticCollector();
  *       StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, null, null);
  *       compiler.getTask(null, fileManager, diagnostics, null, null, compilationUnits).call();
  *
- *       for ({@code Diagnostic} diagnostic : diagnostics.getDiagnostics())
+ *       for (Diagnostic diagnostic : diagnostics.getDiagnostics()) {
  *           System.out.format("Error on line %d in %s%n",
  *                             diagnostic.getLineNumber(),
  *                             diagnostic.getSource().toUri());
+ *       }
  *
- *       fileManager.close();
+ * fileManager.close(); + * } *
* *
@@ -158,9 +162,9 @@ import javax.annotation.processing.Processor; * allowing customizing behavior. For example, consider how to * log all calls to {@linkplain JavaFileManager#flush}: * - *
- *       final  Logger logger = ...;
- *       {@code Iterable} compilationUnits = ...;
+ *     {@snippet id="forward-fm" lang=java :
+ *       final  Logger logger = null;                                       // @replace substring=null replacement="..."
+ *       Iterable compilationUnits = null;        // @replace substring=null replacement="..."
  *       JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
  *       StandardJavaFileManager stdFileManager = compiler.getStandardFileManager(null, null, null);
  *       JavaFileManager fileManager = new ForwardingJavaFileManager(stdFileManager) {
@@ -170,7 +174,8 @@ import javax.annotation.processing.Processor;
  *               logger.exiting(StandardJavaFileManager.class.getName(), "flush");
  *           }
  *       };
- *       compiler.getTask(null, fileManager, null, null, null, compilationUnits).call();
+ * compiler.getTask(null, fileManager, null, null, null, compilationUnits).call(); + * } * * *
{@link SimpleJavaFileObject}
@@ -181,32 +186,7 @@ import javax.annotation.processing.Processor; * example, here is how to define a file object which represent * source code stored in a string: * - *
- *       /**
- *        * A file object used to represent source coming from a string.
- *        {@code *}/
- *       public class JavaSourceFromString extends SimpleJavaFileObject {
- *           /**
- *            * The source code of this "file".
- *            {@code *}/
- *           final String code;
- *
- *           /**
- *            * Constructs a new JavaSourceFromString.
- *            * {@code @}param name the name of the compilation unit represented by this file object
- *            * {@code @}param code the source code for the compilation unit represented by this file object
- *            {@code *}/
- *           JavaSourceFromString(String name, String code) {
- *               super({@linkplain java.net.URI#create URI.create}("string:///" + name.replace('.','/') + Kind.SOURCE.extension),
- *                     Kind.SOURCE);
- *               this.code = code;
- *           }
- *
- *           {@code @}Override
- *           public CharSequence getCharContent(boolean ignoreEncodingErrors) {
- *               return code;
- *           }
- *       }
+ * {@snippet id=fileObject class=JavaSourceFromString } * * * diff --git a/src/java.compiler/share/classes/javax/tools/JavaFileManager.java b/src/java.compiler/share/classes/javax/tools/JavaFileManager.java index af926147845..20178303b2f 100644 --- a/src/java.compiler/share/classes/javax/tools/JavaFileManager.java +++ b/src/java.compiler/share/classes/javax/tools/JavaFileManager.java @@ -28,6 +28,7 @@ package javax.tools; import java.io.Closeable; import java.io.Flushable; import java.io.IOException; +import java.net.URI; import java.util.Iterator; import java.util.ServiceLoader; import java.util.Set; @@ -80,8 +81,10 @@ import static javax.tools.JavaFileObject.Kind; * href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986, * section 3.3. Informally, this should be true: * - * - *
  URI.{@linkplain java.net.URI#create create}(relativeName).{@linkplain java.net.URI#normalize() normalize}().{@linkplain java.net.URI#getPath getPath}().equals(relativeName)
+ * {@snippet id="valid-relative-name" lang=java : + * // @link substring="create" target="URI#create" : @link substring=normalize target="URI#normalize" : @link substring=getPath target="URI#getPath" : + * URI.create(relativeName).normalize().getPath().equals(relativeName) + * } * *

All methods in this interface might throw a SecurityException. * @@ -403,7 +406,9 @@ public interface JavaFileManager extends Closeable, Flushable, OptionChecker { * StandardLocation#SOURCE_PATH SOURCE_PATH} location, this method * might be called like so: * - *

getFileForInput(SOURCE_PATH, "com.sun.tools.javac", "resources/compiler.properties");
+ * {@snippet id="call-getFileForInput" lang=java : + * getFileForInput(SOURCE_PATH, "com.sun.tools.javac", "resources/compiler.properties"); + * } * *

If the call was executed on Windows, with SOURCE_PATH set to * "C:\Documents and Settings\UncleBob\src\share\classes", @@ -666,16 +671,17 @@ public interface JavaFileManager extends Closeable, Flushable, OptionChecker { *

For a package-oriented location, a file object is contained in the location if there exist * values for packageName and relativeName such that either of the following * calls would return the {@link #isSameFile same} file object: - *

-     *     getFileForInput(location, packageName, relativeName)
-     *     getFileForOutput(location, packageName, relativeName, null)
-     * 
+ * {@snippet : + * // @highlight region substring=packageName type=italic @highlight region substring=relativeName type=italic : + * getFileForInput(location, packageName, relativeName) + * getFileForOutput(location, packageName, relativeName, null) // @end @end + * } * *

For a module-oriented location, a file object is contained in the location if there exists * a module that may be obtained by the call: - *

-     *     getLocationForModule(location, moduleName)
-     * 
+ * {@snippet id="call-getLocationForModule" lang=java : + * getLocationForModule(location, moduleName) // @highlight substring=moduleName type=italic + * } * such that the file object is contained in the (package-oriented) location for that module. * * @implSpec This implementation throws {@code UnsupportedOperationException}. diff --git a/src/java.compiler/share/classes/javax/tools/StandardJavaFileManager.java b/src/java.compiler/share/classes/javax/tools/StandardJavaFileManager.java index 5b6590bf926..936cb0aeacc 100644 --- a/src/java.compiler/share/classes/javax/tools/StandardJavaFileManager.java +++ b/src/java.compiler/share/classes/javax/tools/StandardJavaFileManager.java @@ -75,9 +75,10 @@ import java.util.List; * {@linkplain FileObject#openReader(boolean)} * must succeed if the following would succeed (ignoring * encoding issues): - *
- *
new {@linkplain java.io.FileInputStream#FileInputStream(File) FileInputStream}(new {@linkplain File#File(java.net.URI) File}({@linkplain FileObject fileObject}.{@linkplain FileObject#toUri() toUri}()))
- *
+ * {@snippet id="equiv-input" lang=java : + * // @link substring=FileInputStream target="java.io.FileInputStream#FileInputStream(File)" : @link regex="File\W" target="File#File(java.net.URI)" : @link substring=fileObject target=FileObject : @link substring=toURI target="FileObject#toUri()" : + * new FileInputStream(new File(fileObject.toURI())) + * } * *
  • * and the methods @@ -85,9 +86,10 @@ import java.util.List; * {@linkplain FileObject#openWriter()} must * succeed if the following would succeed (ignoring encoding * issues): - *
    - *
    new {@linkplain java.io.FileOutputStream#FileOutputStream(File) FileOutputStream}(new {@linkplain File#File(java.net.URI) File}({@linkplain FileObject fileObject}.{@linkplain FileObject#toUri() toUri}()))
    - *
    + * {@snippet id="equiv-output" lang=java : + * // @link substring=FileOutputStream target="java.io.FileOutputStream#FileOutputStream(File)" : @link regex="File\W" target="File#File(java.net.URI)" : @link substring=fileObject target=FileObject : @link substring=toURI target="FileObject#toUri()" : + * new FileOutputStream(new File(fileObject.toURI())) + * } *
  • * * @@ -241,9 +243,9 @@ public interface StandardJavaFileManager extends JavaFileManager { * Returns file objects representing the given files. * Convenience method equivalent to: * - *
    -     *     getJavaFileObjectsFromFiles({@linkplain java.util.Arrays#asList Arrays.asList}(files))
    -     * 
    + * {@snippet id="equiv-getJavaFileObjects" lang=java : + * getJavaFileObjectsFromFiles(Arrays.asList(files)) // @link substring="Arrays.asList" target="Arrays#asList" + * } * * @param files an array of files * @return a list of file objects @@ -259,9 +261,9 @@ public interface StandardJavaFileManager extends JavaFileManager { * Returns file objects representing the given paths. * Convenience method equivalent to: * - *
    -     *     getJavaFileObjectsFromPaths({@linkplain java.util.Arrays#asList Arrays.asList}(paths))
    -     * 
    + * {@snippet id="equiv-getJavaFileObjectsFromPaths" lang=java : + * getJavaFileObjectsFromPaths(Arrays.asList(paths)) // @link substring="Arrays.asList" target="Arrays#asList" + * } * * @implSpec * The default implementation will only throw {@code NullPointerException} @@ -296,9 +298,9 @@ public interface StandardJavaFileManager extends JavaFileManager { * Returns file objects representing the given file names. * Convenience method equivalent to: * - *
    -     *     getJavaFileObjectsFromStrings({@linkplain java.util.Arrays#asList Arrays.asList}(names))
    -     * 
    + * {@snippet id="equiv-getJavaFileObjectsFromStrings" lang=java : + * getJavaFileObjectsFromStrings(Arrays.asList(names)) // @link substring="Arrays.asList" target="Arrays#asList" + * } * * @param names a list of file names * @return a list of file objects diff --git a/src/java.compiler/share/classes/javax/tools/package-info.java b/src/java.compiler/share/classes/javax/tools/package-info.java index c5ec54e7871..963e6f2261c 100644 --- a/src/java.compiler/share/classes/javax/tools/package-info.java +++ b/src/java.compiler/share/classes/javax/tools/package-info.java @@ -52,7 +52,9 @@ * a default compiler is provided, it can be located using the * {@link javax.tools.ToolProvider}, for example: * - *

    {@code JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();} + * {@snippet id="show-getSystemJavaCompiler" lang=java : + * JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + * } * *

    It is possible to provide alternative compilers or tools * through the {@linkplain java.util.ServiceLoader service provider @@ -64,12 +66,16 @@ * META-INF/services/javax.tools.JavaCompiler}. This file would * contain the single line: * - *

    {@code com.vendor.VendorJavaCompiler} + * {@snippet id="show-service" : + * com.vendor.VendorJavaCompiler + * } * - *

    If the jar file is on the class path, VendorJavaCompiler can be + *

    If the jar file is on the class path, {@code VendorJavaCompiler} can be * located using code like this: * - *

    {@code JavaCompiler compiler = ServiceLoader.load(JavaCompiler.class).iterator().next();} + * {@snippet id="show-serviceLoader" lang=java : + * JavaCompiler compiler = ServiceLoader.load(JavaCompiler.class).iterator().next(); + * } * * @author Peter von der Ahé * @author Jonathan Gibbons diff --git a/src/java.compiler/share/classes/javax/tools/snippet-files/JavaSourceFromString.java b/src/java.compiler/share/classes/javax/tools/snippet-files/JavaSourceFromString.java new file mode 100644 index 00000000000..f0555a02e9e --- /dev/null +++ b/src/java.compiler/share/classes/javax/tools/snippet-files/JavaSourceFromString.java @@ -0,0 +1,54 @@ +// @replace region replacement="" +/* + * Copyright (c) 2021, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +import javax.tools.SimpleJavaFileObject; +import java.net.URI; +// @end +/** + * A file object used to represent source coming from a string. + */ +public class JavaSourceFromString extends SimpleJavaFileObject { + /** + * The source code of this "file". + */ + final String code; + + /** + * Constructs a new JavaSourceFromString. + * @param name the name of the compilation unit represented by this file object + * @param code the source code for the compilation unit represented by this file object + */ + JavaSourceFromString(String name, String code) { + super(URI.create("string:///" + name.replace('.','/') + Kind.SOURCE.extension), // @link substring="URI.create" target="URI#create(String)" + Kind.SOURCE); + this.code = code; + } + + @Override + public CharSequence getCharContent(boolean ignoreEncodingErrors) { + return code; + } +} -- GitLab From 5a80abf706dfde9342be53e78b942ff40f9624ea Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Wed, 8 Dec 2021 19:50:14 +0000 Subject: [PATCH 066/671] 8272944: Use snippets in jdk.javadoc documentation Reviewed-by: hannesw --- .../sun/tools/javac/model/JavacElements.java | 6 + .../jdk/javadoc/doclet/package-info.java | 255 ++++++++++-------- 2 files changed, 147 insertions(+), 114 deletions(-) diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/model/JavacElements.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/model/JavacElements.java index a1ae6c543a9..ed909c8b80f 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/model/JavacElements.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/model/JavacElements.java @@ -757,6 +757,12 @@ public class JavacElements implements Elements { */ private Pair getTreeAndTopLevel(Element e) { Symbol sym = cast(Symbol.class, e); + if (sym.kind == PCK) { + TypeSymbol pkgInfo = ((PackageSymbol) sym).package_info; + if (pkgInfo != null) { + pkgInfo.complete(); + } + } Env enterEnv = getEnterEnv(sym); if (enterEnv == null) return null; diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/doclet/package-info.java b/src/jdk.javadoc/share/classes/jdk/javadoc/doclet/package-info.java index 2e895024b93..3658ed74d85 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/doclet/package-info.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/doclet/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2021, 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 @@ -51,9 +51,9 @@ * The invocation is defined by the interface {@link jdk.javadoc.doclet.Doclet} * -- the {@link jdk.javadoc.doclet.Doclet#run(DocletEnvironment) run} interface * method, defines the entry point. - *

    - *    public boolean run(DocletEnvironment environment)
    - * 
    + * {@snippet id="entry-point" lang=java : + * public boolean run(DocletEnvironment environment) // @highlight substring="run" + * } * The {@link jdk.javadoc.doclet.DocletEnvironment} instance holds the * environment that the doclet will be initialized with. From this environment * all other information can be extracted, in the form of @@ -185,120 +185,147 @@ * * The following is an example doclet that displays information of a class * and its members, supporting an option. - *
    - * // note imports deleted for clarity
    + *
    + * {@snippet lang=java id="Example.java" :
    + * // @replace region=imports replacement=" // Note: imports deleted for clarity"
    + * import com.sun.source.doctree.DocCommentTree;
    + * import com.sun.source.util.DocTrees;
    + * import jdk.javadoc.doclet.Doclet;
    + * import jdk.javadoc.doclet.DocletEnvironment;
    + * import jdk.javadoc.doclet.Reporter;
    + *
    + * import javax.lang.model.SourceVersion;
    + * import javax.lang.model.element.Element;
    + * import javax.lang.model.element.TypeElement;
    + * import javax.lang.model.util.ElementFilter;
    + * import javax.tools.Diagnostic.Kind;
    + * import java.io.IOException;
    + * import java.io.PrintWriter;
    + * import java.util.List;
    + * import java.util.Locale;
    + * import java.util.Set;
    + * // @end
    + *
    + *
      * public class Example implements Doclet {
    - *    Reporter reporter;
    - *    @Override
    - *    public void init(Locale locale, Reporter reporter) {
    - *        reporter.print(Kind.NOTE, "Doclet using locale: " + locale);
    - *        this.reporter = reporter;
    - *    }
    - *
    - *    public void printElement(DocTrees trees, Element e) {
    - *        DocCommentTree docCommentTree = trees.getDocCommentTree(e);
    - *        if (docCommentTree != null) {
    - *            System.out.println("Element (" + e.getKind() + ": "
    - *                    + e + ") has the following comments:");
    - *            System.out.println("Entire body: " + docCommentTree.getFullBody());
    - *            System.out.println("Block tags: " + docCommentTree.getBlockTags());
    - *        }
    - *    }
    - *
    - *    @Override
    - *    public boolean run(DocletEnvironment docEnv) {
    - *        reporter.print(Kind.NOTE, "overviewfile: " + overviewfile);
    - *        // get the DocTrees utility class to access document comments
    - *        DocTrees docTrees = docEnv.getDocTrees();
    - *
    - *        // location of an element in the same directory as overview.html
    - *        try {
    - *            Element e = ElementFilter.typesIn(docEnv.getSpecifiedElements()).iterator().next();
    - *            DocCommentTree docCommentTree
    - *                    = docTrees.getDocCommentTree(e, overviewfile);
    - *            if (docCommentTree != null) {
    - *                System.out.println("Overview html: " + docCommentTree.getFullBody());
    - *            }
    - *        } catch (IOException missing) {
    - *            reporter.print(Kind.ERROR, "No overview.html found.");
    - *        }
    - *
    - *        for (TypeElement t : ElementFilter.typesIn(docEnv.getIncludedElements())) {
    - *            System.out.println(t.getKind() + ":" + t);
    - *            for (Element e : t.getEnclosedElements()) {
    - *                printElement(docTrees, e);
    - *            }
    - *        }
    - *        return true;
    - *    }
    - *
    - *    @Override
    - *    public String getName() {
    - *        return "Example";
    - *    }
    - *
    - *    private String overviewfile;
    - *
    - *    @Override
    - *    public Set<? extends Option> getSupportedOptions() {
    - *        Option[] options = {
    - *            new Option() {
    - *                private final List<String> someOption = Arrays.asList(
    - *                        "-overviewfile",
    - *                        "--overview-file",
    - *                        "-o"
    - *                );
    - *
    - *                @Override
    - *                public int getArgumentCount() {
    - *                    return 1;
    - *                }
    - *
    - *                @Override
    - *                public String getDescription() {
    - *                    return "an option with aliases";
    - *                }
    - *
    - *                @Override
    - *                public Option.Kind getKind() {
    - *                    return Option.Kind.STANDARD;
    - *                }
    - *
    - *                @Override
    - *                public List<String> getNames() {
    - *                    return someOption;
    - *                }
    - *
    - *                @Override
    - *                public String getParameters() {
    - *                    return "file";
    - *                }
    - *
    - *                @Override
    - *                public boolean process(String opt, List<String> arguments) {
    - *                    overviewfile = arguments.get(0);
    - *                    return true;
    - *                }
    - *            }
    - *        };
    - *        return new HashSet<>(Arrays.asList(options));
    - *    }
    - *
    - *    @Override
    - *    public SourceVersion getSupportedSourceVersion() {
    - *        // support the latest release
    - *        return SourceVersion.latest();
    - *    }
    + *     private Reporter reporter;
    + *     private PrintWriter stdout;
    + *
    + *     @Override
    + *     public void init(Locale locale, Reporter reporter) {
    + *         reporter.print(Kind.NOTE, "Doclet using locale: " + locale);
    + *         this.reporter = reporter;
    + *         stdout = reporter.getStandardWriter();
    + *     }
    + *
    + *     public void printElement(DocTrees trees, Element e) {
    + *         DocCommentTree docCommentTree = trees.getDocCommentTree(e);
    + *         if (docCommentTree != null) {
    + *             stdout.println("Element (" + e.getKind() + ": "
    + *                     + e + ") has the following comments:");
    + *             stdout.println("Entire body: " + docCommentTree.getFullBody());
    + *             stdout.println("Block tags: " + docCommentTree.getBlockTags());
    + *         }
    + *     }
    + *
    + *     @Override
    + *     public boolean run(DocletEnvironment docEnv) {
    + *         reporter.print(Kind.NOTE, "overviewFile: " + overviewFile);
    + *
    + *         // get the DocTrees utility class to access document comments
    + *         DocTrees docTrees = docEnv.getDocTrees();
    + *
    + *         // location of an element in the same directory as overview.html
    + *         try {
    + *             Element e = ElementFilter.typesIn(docEnv.getSpecifiedElements()).iterator().next();
    + *             DocCommentTree docCommentTree
    + *                     = docTrees.getDocCommentTree(e, overviewFile);
    + *             if (docCommentTree != null) {
    + *                 stdout.println("Overview html: " + docCommentTree.getFullBody());
    + *             }
    + *         } catch (IOException missing) {
    + *             reporter.print(Kind.ERROR, "No overview.html found.");
    + *         }
    + *
    + *         for (TypeElement t : ElementFilter.typesIn(docEnv.getIncludedElements())) {
    + *             stdout.println(t.getKind() + ":" + t);
    + *             for (Element e : t.getEnclosedElements()) {
    + *                 printElement(docTrees, e);
    + *             }
    + *         }
    + *         return true;
    + *     }
    + *
    + *     @Override
    + *     public String getName() {
    + *         return "Example";
    + *     }
    + *
    + *     private String overviewFile;
    + *
    + *     @Override
    + *     public Set getSupportedOptions() {
    + *         Option[] options = {
    + *             new Option() {
    + *                 private final List someOption = List.of(
    + *                         "--overview-file",
    + *                         "-overviewfile",
    + *                         "-o"
    + *                 );
    + *
    + *                 @Override
    + *                 public int getArgumentCount() {
    + *                     return 1;
    + *                 }
    + *
    + *                 @Override
    + *                 public String getDescription() {
    + *                     return "an option with aliases";
    + *                 }
    + *
    + *                 @Override
    + *                 public Option.Kind getKind() {
    + *                     return Option.Kind.STANDARD;
    + *                 }
    + *
    + *                 @Override
    + *                 public List getNames() {
    + *                     return someOption;
    + *                 }
    + *
    + *                 @Override
    + *                 public String getParameters() {
    + *                     return "file";
    + *                 }
    + *
    + *                 @Override
    + *                 public boolean process(String opt, List arguments) {
    + *                     overviewFile = arguments.get(0);
    + *                     return true;
    + *                 }
    + *             }
    + *         };
    + *
    + *         return Set.of(options);
    + *     }
    + *
    + *     @Override
    + *     public SourceVersion getSupportedSourceVersion() {
    + *         // support the latest release
    + *         return SourceVersion.latest();
    + *     }
    + * }
      * }
    - * 
    + * *

    * This doclet can be invoked with a command line, such as: - *

    - *     javadoc -doclet Example \
    - *       -overviewfile overview.html \
    - *       -sourcepath source-location \
    - *       source-location/Example.java
    - * 
    + * {@snippet id="run-doclet": + * javadoc -docletpath doclet-classes \ // @highlight substring="doclet-classes " type=italic + * -doclet Example \ + * --overview-file overview.html \ + * --source-path source-location \ // @highlight region substring="source-location" type=italic + * source-location/Example.java // @end + * } * *

    Migration Guide

    * -- GitLab From 8e8fadf2d4e45f53286dd8424d95f733a12cd1a0 Mon Sep 17 00:00:00 2001 From: Roger Riggs Date: Wed, 8 Dec 2021 20:37:41 +0000 Subject: [PATCH 067/671] 8278428: ObjectInputStream.readFully range check incorrect Reviewed-by: alanb --- .../classes/java/io/ObjectInputStream.java | 2 +- .../Serializable/oldTests/WritePrimitive.java | 67 ++++++++++++------- 2 files changed, 45 insertions(+), 24 deletions(-) diff --git a/src/java.base/share/classes/java/io/ObjectInputStream.java b/src/java.base/share/classes/java/io/ObjectInputStream.java index 5a0978ab382..1545db08385 100644 --- a/src/java.base/share/classes/java/io/ObjectInputStream.java +++ b/src/java.base/share/classes/java/io/ObjectInputStream.java @@ -1204,7 +1204,7 @@ public class ObjectInputStream * @throws IOException If other I/O error has occurred. */ public void readFully(byte[] buf, int off, int len) throws IOException { - Objects.checkFromToIndex(off, len, buf.length); + Objects.checkFromIndexSize(off, len, buf.length); bin.readFully(buf, off, len, false); } diff --git a/test/jdk/java/io/Serializable/oldTests/WritePrimitive.java b/test/jdk/java/io/Serializable/oldTests/WritePrimitive.java index f2bd28d75f7..2846e7c8f8d 100644 --- a/test/jdk/java/io/Serializable/oldTests/WritePrimitive.java +++ b/test/jdk/java/io/Serializable/oldTests/WritePrimitive.java @@ -32,28 +32,27 @@ */ import java.io.*; +import java.util.Arrays; public class WritePrimitive { public static void main (String argv[]) throws IOException { System.err.println("\nRegression test for testing of " + "serialization/deserialization of primitives \n"); + int i = 123456; + byte b = 12; + short s = 45; + char c = 'A'; + long l = 1234567890000L; + float f = 3.14159f; + double d = f * 2; + boolean z = true; + String string = "The String"; + PrimitivesTest prim = new PrimitivesTest(); + byte[] ba = {1, 2, 3, 4, 5, 6, 7}; // byte array to write - FileInputStream istream = null; - FileOutputStream ostream = null; - try { - int i = 123456; - byte b = 12; - short s = 45; - char c = 'A'; - long l = 1234567890000L; - float f = 3.14159f; - double d = f*2; - boolean z = true; - String string = "The String"; - PrimitivesTest prim = new PrimitivesTest(); - - ostream = new FileOutputStream("piotest1.tmp"); - ObjectOutputStream p = new ObjectOutputStream(ostream); + byte[] bytes; + try (ByteArrayOutputStream ostream = new ByteArrayOutputStream(); + ObjectOutputStream p = new ObjectOutputStream(ostream)) { p.writeInt(i); p.writeByte(b); @@ -63,14 +62,20 @@ public class WritePrimitive { p.writeFloat(f); p.writeDouble(d); p.writeBoolean(z); + p.write(ba); // for simple read(byte[]) + p.write(ba); // for readFully(byte[]) + p.write(ba, 0, ba.length - 2); // for readFully(byte[], 0, 7) p.writeUTF(string); p.writeObject(string); p.writeObject(prim); p.flush(); + bytes = ostream.toByteArray(); + + } - istream = new FileInputStream("piotest1.tmp"); - ObjectInputStream q = new ObjectInputStream(istream); + ByteArrayInputStream istream = new ByteArrayInputStream(bytes); + try (ObjectInputStream q = new ObjectInputStream(istream);) { int i_u = q.readInt(); byte b_u = q.readByte(); @@ -80,6 +85,12 @@ public class WritePrimitive { float f_u = q.readFloat(); double d_u = q.readDouble(); boolean z_u = q.readBoolean(); + byte[] ba_readBuf = new byte[ba.length]; + int ba_readLen = q.read(ba_readBuf); + byte[] ba_readFullyBuf = new byte[ba.length]; + int ba_readFullyLen = q.read(ba_readFullyBuf); + byte[] ba_readFullySizedBuf = new byte[ba.length]; + int ba_readFullySizedLen = q.read(ba_readFullySizedBuf, 0, ba.length - 1); String string_utf = q.readUTF(); String string_u = (String)q.readObject(); if (i != i_u) { @@ -120,6 +131,10 @@ public class WritePrimitive { z_u); throw new Error(); } + checkArray("read(byte[])", ba, ba.length, ba_readBuf, ba_readLen); + checkArray("readFully(byte[])", ba, ba.length, ba_readFullyBuf, ba_readFullyLen); + checkArray("readFully(byte[], off, len)", ba, ba.length - 2, ba_readFullySizedBuf, ba_readFullySizedLen); + if (!string.equals(string_utf)) { System.err.println("\nString: expected " + string + " actual " + string_utf); @@ -144,20 +159,26 @@ public class WritePrimitive { System.err.print("TEST FAILED: "); e.printStackTrace(); - System.err.println("\nInput remaining"); + System.err.println("\nBytes read: " + (bytes.length - istream.available()) + + ", Input remaining: " + istream.available()); int ch; try { while ((ch = istream.read()) != -1) { System.err.print("\n " + Integer.toString(ch, 16)+ " "); } System.out.println("\n "); - } catch (Exception f) { + } catch (Exception fex) { throw new Error(); } throw new Error(); - } finally { - if (istream != null) istream.close(); - if (ostream != null) ostream.close(); + } + } + + static void checkArray(String label, byte[] expected, int expectedLen, byte[] actual, int actualLen) { + int mismatch = Arrays.mismatch(expected, 0, expectedLen, actual, 0, actualLen); + if (actualLen != expectedLen || mismatch >= 0) { + System.err.println("\n" + label + ": expected " + expectedLen + " actual " + actualLen + ", mismatch: " + mismatch); + throw new Error(); } } } -- GitLab From c83b781b6002ca0f067a35e678ab5285d98d015d Mon Sep 17 00:00:00 2001 From: "Daniel D. Daugherty" Date: Wed, 8 Dec 2021 20:42:52 +0000 Subject: [PATCH 068/671] 8278459: ProblemList javax/swing/JTree/4908142/bug4908142.java on macosx-aarch64 Reviewed-by: lmesnik, bpb, prr --- test/jdk/ProblemList.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index a48fe6af429..2bdcb6708b4 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -748,6 +748,7 @@ javax/swing/JMenu/4515762/bug4515762.java 8276074 macosx-all sanity/client/SwingSet/src/ToolTipDemoTest.java 8225012 windows-all,macosx-all sanity/client/SwingSet/src/ScrollPaneDemoTest.java 8225013 linux-all sanity/client/SwingSet/src/ButtonDemoScreenshotTest.java 8265770 macosx-all +javax/swing/JTree/4908142/bug4908142.java 8278348 macosx-aarch64 ############################################################################ -- GitLab From 6e7b7f352e66c767b16e1e98a162e7fea79126c6 Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Wed, 8 Dec 2021 21:15:55 +0000 Subject: [PATCH 069/671] 8278251: Enable "missing-explicit-ctor" check in the jdk.unsupported.desktop module Reviewed-by: ihse, prr --- make/modules/jdk.unsupported.desktop/Java.gmk | 26 ------------------- 1 file changed, 26 deletions(-) delete mode 100644 make/modules/jdk.unsupported.desktop/Java.gmk diff --git a/make/modules/jdk.unsupported.desktop/Java.gmk b/make/modules/jdk.unsupported.desktop/Java.gmk deleted file mode 100644 index f892ebeb84c..00000000000 --- a/make/modules/jdk.unsupported.desktop/Java.gmk +++ /dev/null @@ -1,26 +0,0 @@ -# -# Copyright (c) 2020, 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. Oracle designates this -# particular file as subject to the "Classpath" exception as provided -# by Oracle in the LICENSE file that accompanied this code. -# -# 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. -# - -DISABLED_WARNINGS_java += missing-explicit-ctor -- GitLab From fe2ae8e38bd8660cc637f13f425ccea17a11aa4f Mon Sep 17 00:00:00 2001 From: Eamonn McManus Date: Wed, 8 Dec 2021 21:24:43 +0000 Subject: [PATCH 070/671] 8276904: Optional.toString() is unnecessarily expensive Reviewed-by: rriggs, smarks --- src/java.base/share/classes/java/util/Optional.java | 2 +- src/java.base/share/classes/java/util/OptionalDouble.java | 2 +- src/java.base/share/classes/java/util/OptionalInt.java | 2 +- src/java.base/share/classes/java/util/OptionalLong.java | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/java.base/share/classes/java/util/Optional.java b/src/java.base/share/classes/java/util/Optional.java index 64647ee49d5..cd8b2b6048f 100644 --- a/src/java.base/share/classes/java/util/Optional.java +++ b/src/java.base/share/classes/java/util/Optional.java @@ -454,7 +454,7 @@ public final class Optional { @Override public String toString() { return value != null - ? String.format("Optional[%s]", value) + ? ("Optional[" + value + "]") : "Optional.empty"; } } diff --git a/src/java.base/share/classes/java/util/OptionalDouble.java b/src/java.base/share/classes/java/util/OptionalDouble.java index 61e54cfec29..752aaac1e54 100644 --- a/src/java.base/share/classes/java/util/OptionalDouble.java +++ b/src/java.base/share/classes/java/util/OptionalDouble.java @@ -328,7 +328,7 @@ public final class OptionalDouble { @Override public String toString() { return isPresent - ? String.format("OptionalDouble[%s]", value) + ? ("OptionalDouble[" + value + "]") : "OptionalDouble.empty"; } } diff --git a/src/java.base/share/classes/java/util/OptionalInt.java b/src/java.base/share/classes/java/util/OptionalInt.java index d693a3ddba2..c1e62090c25 100644 --- a/src/java.base/share/classes/java/util/OptionalInt.java +++ b/src/java.base/share/classes/java/util/OptionalInt.java @@ -326,7 +326,7 @@ public final class OptionalInt { @Override public String toString() { return isPresent - ? String.format("OptionalInt[%s]", value) + ? ("OptionalInt[" + value + "]") : "OptionalInt.empty"; } } diff --git a/src/java.base/share/classes/java/util/OptionalLong.java b/src/java.base/share/classes/java/util/OptionalLong.java index f92c5bdff17..2c1171f86e9 100644 --- a/src/java.base/share/classes/java/util/OptionalLong.java +++ b/src/java.base/share/classes/java/util/OptionalLong.java @@ -326,7 +326,7 @@ public final class OptionalLong { @Override public String toString() { return isPresent - ? String.format("OptionalLong[%s]", value) + ? ("OptionalLong[" + value + "]") : "OptionalLong.empty"; } } -- GitLab From b3faecf73966ce0435644a89f8f43d85720e8328 Mon Sep 17 00:00:00 2001 From: Roland Westrelin Date: Wed, 8 Dec 2021 21:33:33 +0000 Subject: [PATCH 071/671] 8276116: C2: optimize long range checks in int counted loops Reviewed-by: kvn --- src/hotspot/cpu/x86/x86_32.ad | 18 ++ src/hotspot/share/opto/compile.cpp | 2 +- src/hotspot/share/opto/loopTransform.cpp | 63 ++-- src/hotspot/share/opto/loopnode.cpp | 257 ++++++++++++---- src/hotspot/share/opto/loopnode.hpp | 40 ++- src/hotspot/share/opto/loopopts.cpp | 2 +- .../c2/irTests/TestLongRangeChecks.java | 42 ++- .../rangechecks/TestLongRangeCheck.java | 286 +++++++++++++++++- 8 files changed, 610 insertions(+), 100 deletions(-) diff --git a/src/hotspot/cpu/x86/x86_32.ad b/src/hotspot/cpu/x86/x86_32.ad index 611206fa9fa..896064720ff 100644 --- a/src/hotspot/cpu/x86/x86_32.ad +++ b/src/hotspot/cpu/x86/x86_32.ad @@ -13130,6 +13130,24 @@ instruct cmovLL_mem_LTGE(cmpOp cmp, flagsReg_long_LTGE flags, eRegL dst, load_lo ins_pipe( pipe_cmov_reg_long ); %} +instruct cmovLL_reg_LTGE_U(cmpOpU cmp, flagsReg_ulong_LTGE flags, eRegL dst, eRegL src) %{ + match(Set dst (CMoveL (Binary cmp flags) (Binary dst src))); + predicate(VM_Version::supports_cmov() && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge )); + ins_cost(400); + expand %{ + cmovLL_reg_LTGE(cmp, flags, dst, src); + %} +%} + +instruct cmovLL_mem_LTGE_U(cmpOpU cmp, flagsReg_ulong_LTGE flags, eRegL dst, load_long_memory src) %{ + match(Set dst (CMoveL (Binary cmp flags) (Binary dst (LoadL src)))); + predicate(VM_Version::supports_cmov() && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge )); + ins_cost(500); + expand %{ + cmovLL_mem_LTGE(cmp, flags, dst, src); + %} +%} + // Compare 2 longs and CMOVE ints. instruct cmovII_reg_LTGE(cmpOp cmp, flagsReg_long_LTGE flags, rRegI dst, rRegI src) %{ predicate(VM_Version::supports_cmov() && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge )); diff --git a/src/hotspot/share/opto/compile.cpp b/src/hotspot/share/opto/compile.cpp index b2f5dd55788..f980fe6e06c 100644 --- a/src/hotspot/share/opto/compile.cpp +++ b/src/hotspot/share/opto/compile.cpp @@ -3463,7 +3463,7 @@ void Compile::final_graph_reshaping_main_switch(Node* n, Final_Reshape_Counts& f } break; case Op_Loop: - assert(!n->as_Loop()->is_transformed_long_inner_loop() || _loop_opts_cnt == 0, "should have been turned into a counted loop"); + assert(!n->as_Loop()->is_loop_nest_inner_loop() || _loop_opts_cnt == 0, "should have been turned into a counted loop"); case Op_CountedLoop: case Op_LongCountedLoop: case Op_OuterStripMinedLoop: diff --git a/src/hotspot/share/opto/loopTransform.cpp b/src/hotspot/share/opto/loopTransform.cpp index 0b2b58c50b8..30562826eac 100644 --- a/src/hotspot/share/opto/loopTransform.cpp +++ b/src/hotspot/share/opto/loopTransform.cpp @@ -1065,7 +1065,7 @@ void IdealLoopTree::policy_unroll_slp_analysis(CountedLoopNode *cl, PhaseIdealLo // When TRUE, the estimated node budget is also requested. // // We will actually perform iteration-splitting, a more powerful form of RCE. -bool IdealLoopTree::policy_range_check(PhaseIdealLoop* phase, bool provisional) const { +bool IdealLoopTree::policy_range_check(PhaseIdealLoop* phase, bool provisional, BasicType bt) const { if (!provisional && !RangeCheckElimination) return false; // If nodes are depleted, some transform has miscalculated its needs. @@ -1087,7 +1087,7 @@ bool IdealLoopTree::policy_range_check(PhaseIdealLoop* phase, bool provisional) BaseCountedLoopNode* cl = _head->as_BaseCountedLoop(); Node *trip_counter = cl->phi(); - BasicType bt = cl->bt(); + assert(!cl->is_LongCountedLoop() || bt == T_LONG, "only long range checks in long counted loops"); // Check loop body for tests of trip-counter plus loop-invariant vs // loop-invariant. @@ -1135,7 +1135,7 @@ bool IdealLoopTree::policy_range_check(PhaseIdealLoop* phase, bool provisional) } } - if (!phase->is_scaled_iv_plus_offset(rc_exp, trip_counter, NULL, NULL)) { + if (!phase->is_scaled_iv_plus_offset(rc_exp, trip_counter, NULL, NULL, bt)) { continue; } } @@ -1145,7 +1145,9 @@ bool IdealLoopTree::policy_range_check(PhaseIdealLoop* phase, bool provisional) if (is_loop_exit(iff)) { // Found valid reason to split iterations (if there is room). // NOTE: Usually a gross overestimate. - return provisional || phase->may_require_nodes(est_loop_clone_sz(2)); + // Long range checks cause the loop to be transformed in a loop nest which only causes a fixed number of nodes + // to be added + return provisional || bt == T_LONG || phase->may_require_nodes(est_loop_clone_sz(2)); } } // End of is IF } @@ -2508,34 +2510,52 @@ void PhaseIdealLoop::add_constraint(jlong stride_con, jlong scale_con, Node* off } } +bool PhaseIdealLoop::is_iv(Node* exp, Node* iv, BasicType bt) { + if (exp == iv) { + return true; + } + + if (bt == T_LONG && iv->bottom_type()->isa_int() && exp->Opcode() == Op_ConvI2L && exp->in(1) == iv) { + return true; + } + return false; +} + //------------------------------is_scaled_iv--------------------------------- // Return true if exp is a constant times an induction var -bool PhaseIdealLoop::is_scaled_iv(Node* exp, Node* iv, jlong* p_scale, BasicType bt) { +bool PhaseIdealLoop::is_scaled_iv(Node* exp, Node* iv, jlong* p_scale, BasicType bt, bool* converted) { exp = exp->uncast(); assert(bt == T_INT || bt == T_LONG, "unexpected int type"); - if (exp == iv) { + if (is_iv(exp, iv, bt)) { if (p_scale != NULL) { *p_scale = 1; } return true; } + if (bt == T_LONG && iv->bottom_type()->isa_int() && exp->Opcode() == Op_ConvI2L) { + exp = exp->in(1); + bt = T_INT; + if (converted != NULL) { + *converted = true; + } + } int opc = exp->Opcode(); // Can't use is_Mul() here as it's true for AndI and AndL if (opc == Op_Mul(bt)) { - if (exp->in(1)->uncast() == iv && exp->in(2)->is_Con()) { + if (is_iv(exp->in(1)->uncast(), iv, bt) && exp->in(2)->is_Con()) { if (p_scale != NULL) { *p_scale = exp->in(2)->get_integer_as_long(bt); } return true; } - if (exp->in(2)->uncast() == iv && exp->in(1)->is_Con()) { + if (is_iv(exp->in(2)->uncast(), iv, bt) && exp->in(1)->is_Con()) { if (p_scale != NULL) { *p_scale = exp->in(1)->get_integer_as_long(bt); } return true; } } else if (opc == Op_LShift(bt)) { - if (exp->in(1)->uncast() == iv && exp->in(2)->is_Con()) { + if (is_iv(exp->in(1)->uncast(), iv, bt) && exp->in(2)->is_Con()) { if (p_scale != NULL) { jint shift_amount = exp->in(2)->get_int(); if (bt == T_INT) { @@ -2552,9 +2572,9 @@ bool PhaseIdealLoop::is_scaled_iv(Node* exp, Node* iv, jlong* p_scale, BasicType //-----------------------------is_scaled_iv_plus_offset------------------------------ // Return true if exp is a simple induction variable expression: k1*iv + (invar + k2) -bool PhaseIdealLoop::is_scaled_iv_plus_offset(Node* exp, Node* iv, jlong* p_scale, Node** p_offset, BasicType bt, int depth) { +bool PhaseIdealLoop::is_scaled_iv_plus_offset(Node* exp, Node* iv, jlong* p_scale, Node** p_offset, BasicType bt, bool* converted, int depth) { assert(bt == T_INT || bt == T_LONG, "unexpected int type"); - if (is_scaled_iv(exp, iv, p_scale, bt)) { + if (is_scaled_iv(exp, iv, p_scale, bt, converted)) { if (p_offset != NULL) { Node *zero = _igvn.integercon(0, bt); set_ctrl(zero, C->root()); @@ -2565,13 +2585,13 @@ bool PhaseIdealLoop::is_scaled_iv_plus_offset(Node* exp, Node* iv, jlong* p_scal exp = exp->uncast(); int opc = exp->Opcode(); if (opc == Op_Add(bt)) { - if (is_scaled_iv(exp->in(1), iv, p_scale, bt)) { + if (is_scaled_iv(exp->in(1), iv, p_scale, bt, converted)) { if (p_offset != NULL) { *p_offset = exp->in(2); } return true; } - if (is_scaled_iv(exp->in(2), iv, p_scale, bt)) { + if (is_scaled_iv(exp->in(2), iv, p_scale, bt, converted)) { if (p_offset != NULL) { *p_offset = exp->in(1); } @@ -2581,7 +2601,7 @@ bool PhaseIdealLoop::is_scaled_iv_plus_offset(Node* exp, Node* iv, jlong* p_scal Node* offset2 = NULL; if (depth < 2 && is_scaled_iv_plus_offset(exp->in(1), iv, p_scale, - p_offset != NULL ? &offset2 : NULL, bt, depth+1)) { + p_offset != NULL ? &offset2 : NULL, bt, converted, depth+1)) { if (p_offset != NULL) { Node *ctrl_off2 = get_ctrl(offset2); Node* offset = AddNode::make(offset2, exp->in(2), bt); @@ -2592,7 +2612,7 @@ bool PhaseIdealLoop::is_scaled_iv_plus_offset(Node* exp, Node* iv, jlong* p_scal } } } else if (opc == Op_Sub(bt)) { - if (is_scaled_iv(exp->in(1), iv, p_scale, bt)) { + if (is_scaled_iv(exp->in(1), iv, p_scale, bt, converted)) { if (p_offset != NULL) { Node *zero = _igvn.integercon(0, bt); set_ctrl(zero, C->root()); @@ -2603,7 +2623,7 @@ bool PhaseIdealLoop::is_scaled_iv_plus_offset(Node* exp, Node* iv, jlong* p_scal } return true; } - if (is_scaled_iv(exp->in(2), iv, p_scale, bt)) { + if (is_scaled_iv(exp->in(2), iv, p_scale, bt, converted)) { if (p_offset != NULL) { // We can't handle a scale of min_jint (or min_jlong) here as -1 * min_jint = min_jint if (*p_scale == min_signed_integer(bt)) { @@ -3432,6 +3452,8 @@ bool IdealLoopTree::iteration_split_impl(PhaseIdealLoop *phase, Node_List &old_n } else if (policy_unswitching(phase)) { phase->do_unswitching(this, old_new); return false; // need to recalculate idom data + } else if (_head->is_LongCountedLoop()) { + phase->create_loop_nest(this, old_new); } return true; } @@ -3475,7 +3497,8 @@ bool IdealLoopTree::iteration_split_impl(PhaseIdealLoop *phase, Node_List &old_n // unrolling), plus any needed for RCE purposes. bool should_unroll = policy_unroll(phase); - bool should_rce = policy_range_check(phase, false); + bool should_rce = policy_range_check(phase, false, T_INT); + bool should_rce_long = policy_range_check(phase, false, T_LONG); // If not RCE'ing (iteration splitting), then we do not need a pre-loop. // We may still need to peel an initial iteration but we will not @@ -3490,6 +3513,9 @@ bool IdealLoopTree::iteration_split_impl(PhaseIdealLoop *phase, Node_List &old_n // peeling. if (should_rce || should_unroll) { if (cl->is_normal_loop()) { // Convert to 'pre/main/post' loops + if (should_rce_long && phase->create_loop_nest(this, old_new)) { + return true; + } uint estimate = est_loop_clone_sz(3); if (!phase->may_require_nodes(estimate)) { return false; @@ -3531,6 +3557,9 @@ bool IdealLoopTree::iteration_split_impl(PhaseIdealLoop *phase, Node_List &old_n phase->do_peeling(this, old_new); } } + if (should_rce_long) { + phase->create_loop_nest(this, old_new); + } } return true; } diff --git a/src/hotspot/share/opto/loopnode.cpp b/src/hotspot/share/opto/loopnode.cpp index 46e675ae239..c38e4829a23 100644 --- a/src/hotspot/share/opto/loopnode.cpp +++ b/src/hotspot/share/opto/loopnode.cpp @@ -525,10 +525,16 @@ static bool condition_stride_ok(BoolTest::mask bt, jlong stride_con) { return true; } -Node* PhaseIdealLoop::long_loop_replace_long_iv(Node* iv_to_replace, Node* inner_iv, Node* outer_phi, Node* inner_head) { - Node* iv_as_long = new ConvI2LNode(inner_iv, TypeLong::INT); - register_new_node(iv_as_long, inner_head); - Node* iv_replacement = new AddLNode(outer_phi, iv_as_long); +Node* PhaseIdealLoop::loop_nest_replace_iv(Node* iv_to_replace, Node* inner_iv, Node* outer_phi, Node* inner_head, + BasicType bt) { + Node* iv_as_long; + if (bt == T_LONG) { + iv_as_long = new ConvI2LNode(inner_iv, TypeLong::INT); + register_new_node(iv_as_long, inner_head); + } else { + iv_as_long = inner_iv; + } + Node* iv_replacement = AddNode::make(outer_phi, iv_as_long, bt); register_new_node(iv_replacement, inner_head); for (DUIterator_Last imin, i = iv_to_replace->last_outs(imin); i >= imin;) { Node* u = iv_to_replace->last_out(i); @@ -762,25 +768,36 @@ SafePointNode* PhaseIdealLoop::find_safepoint(Node* back_control, Node* x, Ideal // continue; // else break; // } -bool PhaseIdealLoop::transform_long_counted_loop(IdealLoopTree* loop, Node_List &old_new) { +// +// The same logic is used to transform an int counted loop that contains long range checks into a loop nest of 2 int +// loops with long range checks transformed to int range checks in the inner loop. +bool PhaseIdealLoop::create_loop_nest(IdealLoopTree* loop, Node_List &old_new) { Node* x = loop->_head; // Only for inner loops - if (loop->_child != NULL || !x->is_LongCountedLoop() || x->as_Loop()->is_transformed_long_outer_loop()) { + if (loop->_child != NULL || !x->is_BaseCountedLoop() || x->as_Loop()->is_loop_nest_outer_loop()) { return false; } - check_long_counted_loop(loop, x); + if (x->is_CountedLoop() && !x->as_CountedLoop()->is_main_loop() && !x->as_CountedLoop()->is_normal_loop()) { + return false; + } + + BaseCountedLoopNode* head = x->as_BaseCountedLoop(); + BasicType bt = x->as_BaseCountedLoop()->bt(); - LongCountedLoopNode* head = x->as_LongCountedLoop(); + check_counted_loop_shape(loop, x, bt); #ifndef PRODUCT - Atomic::inc(&_long_loop_candidates); + if (bt == T_LONG) { + Atomic::inc(&_long_loop_candidates); + } #endif jlong stride_con = head->stride_con(); assert(stride_con != 0, "missed some peephole opt"); // We can't iterate for more than max int at a time. if (stride_con != (jint)stride_con) { + assert(bt == T_LONG, "only for long loops"); return false; } // The number of iterations for the integer count loop: guarantee no @@ -788,7 +805,7 @@ bool PhaseIdealLoop::transform_long_counted_loop(IdealLoopTree* loop, Node_List // loop limit check if the exit test is <= or >=. int iters_limit = max_jint - ABS(stride_con) - 1; #ifdef ASSERT - if (StressLongCountedLoop > 0) { + if (bt == T_LONG && StressLongCountedLoop > 0) { iters_limit = iters_limit / StressLongCountedLoop; } #endif @@ -814,24 +831,38 @@ bool PhaseIdealLoop::transform_long_counted_loop(IdealLoopTree* loop, Node_List } // May not have gone thru igvn yet so don't use _igvn.type(phi) (PhaseIdealLoop::is_counted_loop() sets the iv phi's type) - const TypeLong* phi_t = phi->bottom_type()->is_long(); - assert(phi_t->_hi >= phi_t->_lo, "dead phi?"); - iters_limit = (int)MIN2((julong)iters_limit, (julong)(phi_t->_hi - phi_t->_lo)); + const TypeInteger* phi_t = phi->bottom_type()->is_integer(bt); + assert(phi_t->hi_as_long() >= phi_t->lo_as_long(), "dead phi?"); + iters_limit = checked_cast(MIN2((julong)iters_limit, (julong)(phi_t->hi_as_long() - phi_t->lo_as_long()))); - LongCountedLoopEndNode* exit_test = head->loopexit(); - BoolTest::mask bt = exit_test->test_trip(); - - // We need a safepoint to insert empty predicates for the inner loop. - SafePointNode* safepoint = find_safepoint(back_control, x, loop); + IfNode* exit_test = head->loopexit(); + BoolTest::mask mask = exit_test->as_BaseCountedLoopEnd()->test_trip(); + Node* cmp = exit_test->as_BaseCountedLoopEnd()->cmp_node(); assert(back_control->Opcode() == Op_IfTrue, "wrong projection for back edge"); - Node* exit_branch = exit_test->proj_out(false); - Node* entry_control = x->in(LoopNode::EntryControl); - Node* cmp = exit_test->cmp_node(); Node_List range_checks; iters_limit = extract_long_range_checks(loop, stride_con, iters_limit, phi, range_checks); + if (bt == T_INT) { + // The only purpose of creating a loop nest is to handle long range checks. If there are none, do not proceed further. + if (range_checks.size() == 0) { + return false; + } + } + + // We need a safepoint to insert empty predicates for the inner loop. + SafePointNode* safepoint; + if (bt == T_INT && head->as_CountedLoop()->is_strip_mined()) { + // Loop is strip mined: use the safepoint of the outer strip mined loop + strip_mined_nest_back_to_counted_loop(loop, head, back_control, exit_test, safepoint); + } else { + safepoint = find_safepoint(back_control, x, loop); + } + + Node* exit_branch = exit_test->proj_out(false); + Node* entry_control = head->in(LoopNode::EntryControl); + // Clone the control flow of the loop to build an outer loop Node* outer_back_branch = back_control->clone(); Node* outer_exit_test = new IfNode(exit_test->in(0), exit_test->in(1), exit_test->_prob, exit_test->_fcnt); @@ -867,19 +898,24 @@ bool PhaseIdealLoop::transform_long_counted_loop(IdealLoopTree* loop, Node_List Node* inner_iters_max = NULL; if (stride_con > 0) { - inner_iters_max = MaxNode::max_diff_with_zero(limit, outer_phi, TypeLong::LONG, _igvn); + inner_iters_max = MaxNode::max_diff_with_zero(limit, outer_phi, TypeInteger::bottom(bt), _igvn); } else { - inner_iters_max = MaxNode::max_diff_with_zero(outer_phi, limit, TypeLong::LONG, _igvn); + inner_iters_max = MaxNode::max_diff_with_zero(outer_phi, limit, TypeInteger::bottom(bt), _igvn); } - Node* inner_iters_limit = _igvn.longcon(iters_limit); + Node* inner_iters_limit = _igvn.integercon(iters_limit, bt); // inner_iters_max may not fit in a signed integer (iterating from // Long.MIN_VALUE to Long.MAX_VALUE for instance). Use an unsigned // min. - Node* inner_iters_actual = MaxNode::unsigned_min(inner_iters_max, inner_iters_limit, TypeLong::make(0, iters_limit, Type::WidenMin), _igvn); + Node* inner_iters_actual = MaxNode::unsigned_min(inner_iters_max, inner_iters_limit, TypeInteger::make(0, iters_limit, Type::WidenMin, bt), _igvn); - Node* inner_iters_actual_int = new ConvL2INode(inner_iters_actual); - _igvn.register_new_node_with_optimizer(inner_iters_actual_int); + Node* inner_iters_actual_int; + if (bt == T_LONG) { + inner_iters_actual_int = new ConvL2INode(inner_iters_actual); + _igvn.register_new_node_with_optimizer(inner_iters_actual_int); + } else { + inner_iters_actual_int = inner_iters_actual; + } Node* int_zero = _igvn.intcon(0); set_ctrl(int_zero, C->root()); @@ -919,11 +955,11 @@ bool PhaseIdealLoop::transform_long_counted_loop(IdealLoopTree* loop, Node_List // Replace inner loop long iv phi as inner loop int iv phi + outer // loop iv phi - Node* iv_add = long_loop_replace_long_iv(phi, inner_phi, outer_phi, head); + Node* iv_add = loop_nest_replace_iv(phi, inner_phi, outer_phi, head, bt); // Replace inner loop long iv incr with inner loop int incr + outer // loop iv phi - long_loop_replace_long_iv(incr, inner_incr, outer_phi, head); + loop_nest_replace_iv(incr, inner_incr, outer_phi, head, bt); set_subtree_ctrl(inner_iters_actual_int, body_populated); @@ -983,6 +1019,11 @@ bool PhaseIdealLoop::transform_long_counted_loop(IdealLoopTree* loop, Node_List // exit_branch: break; //in(0) := outer_exit_test // } + if (bt == T_INT) { + outer_phi = new ConvI2LNode(outer_phi); + register_new_node(outer_phi, outer_head); + } + transform_long_range_checks(checked_cast(stride_con), range_checks, outer_phi, inner_iters_actual_int, inner_phi, iv_add, inner_head); // Peel one iteration of the loop and use the safepoint at the end @@ -1009,15 +1050,79 @@ bool PhaseIdealLoop::transform_long_counted_loop(IdealLoopTree* loop, Node_List } #ifndef PRODUCT - Atomic::inc(&_long_loop_nests); + if (bt == T_LONG) { + Atomic::inc(&_long_loop_nests); + } #endif - inner_head->mark_transformed_long_inner_loop(); - outer_head->mark_transformed_long_outer_loop(); + inner_head->mark_loop_nest_inner_loop(); + outer_head->mark_loop_nest_outer_loop(); return true; } +// Convert the strip mined loop nest back to a single loop with the safepoint right before the loop exit test +void PhaseIdealLoop::strip_mined_nest_back_to_counted_loop(IdealLoopTree* loop, const BaseCountedLoopNode* head, + Node* back_control, IfNode*& exit_test, + SafePointNode*& safepoint) { + CountedLoopNode* cl = head->as_CountedLoop(); + cl->verify_strip_mined(1); + safepoint = cl->outer_safepoint(); + CountedLoopEndNode* cle = cl->loopexit(); + OuterStripMinedLoopNode* outer_head = cl->outer_loop(); + OuterStripMinedLoopEndNode* outer_end = cl->outer_loop_end(); + + cl->clear_strip_mined(); + + _igvn.replace_input_of(cl, LoopNode::EntryControl, outer_head->in(LoopNode::EntryControl)); + _igvn.replace_input_of(outer_head, LoopNode::EntryControl, C->top()); + set_idom(cl, cl->in(LoopNode::EntryControl), dom_depth(cl)); + + Node* exit_bol = cle->in(1); + Node *zero = _igvn.intcon(0); + set_ctrl(zero, C->root()); + _igvn.replace_input_of(cle, 1, zero); + + _igvn.replace_input_of(outer_end, 1, exit_bol); + + assert(outer_head->in(LoopNode::LoopBackControl)->in(0) == outer_end, ""); + _igvn.replace_input_of(outer_head->in(LoopNode::LoopBackControl), 0, C->top()); + _igvn.replace_input_of(back_control, 0, outer_end); + set_idom(back_control, outer_end, dom_depth(outer_end) + 1); + + Unique_Node_List wq; + wq.push(safepoint); + + IdealLoopTree* outer_loop_ilt = get_loop(outer_head); + + for (uint i = 0; i < wq.size(); i++) { + Node* n = wq.at(i); + for (uint j = 0; j < n->req(); ++j) { + Node* in = n->in(j); + if (in == NULL || in->is_CFG()) { + continue; + } + if (get_loop(get_ctrl(in)) != outer_loop_ilt) { + continue; + } + assert(!loop->_body.contains(in), ""); + loop->_body.push(in); + wq.push(in); + } + } + + set_loop(outer_end, loop); + loop->_body.push(outer_end); + set_loop(safepoint, loop); + loop->_body.push(safepoint); + set_loop(safepoint->in(0), loop); + loop->_body.push(safepoint->in(0)); + + exit_test = outer_end; + + outer_loop_ilt->_tail = C->top(); +} + int PhaseIdealLoop::extract_long_range_checks(const IdealLoopTree* loop, jlong stride_con, int iters_limit, PhiNode* phi, Node_List& range_checks) { if (stride_con < 0) { // only for stride_con > 0 && scale > 0 for now @@ -1164,7 +1269,8 @@ void PhaseIdealLoop::transform_long_range_checks(int stride_con, const Node_List // could be shared and have already been taken care of continue; } - bool ok = is_scaled_iv_plus_offset(rc_cmp->in(1), iv_add, &scale, &offset, T_LONG); + bool converted = false; + bool ok = is_scaled_iv_plus_offset(rc_cmp->in(1), iv_add, &scale, &offset, T_LONG, &converted); assert(ok, "inconsistent: was tested before"); Node* range = rc_cmp->in(2); Node* c = rc->in(0); @@ -1173,7 +1279,44 @@ void PhaseIdealLoop::transform_long_range_checks(int stride_con, const Node_List Node* R = range; Node* K = _igvn.longcon(scale); set_ctrl(K, this->C->root()); + Node* L = offset; + + if (converted) { + // This converts: + // i*K + L (long)max_jint and < R + // and so i*(long)K + L root()); + Node* max_range = new AddLNode(max_jint_plus_one_long, L); + register_new_node(max_range, entry_control); + R = MaxNode::unsigned_min(R, max_range, TypeLong::POS, _igvn); + set_subtree_ctrl(R, true); + } + Node* C = outer_phi; Node* Z_2 = new ConvI2LNode(inner_iters_actual_int, TypeLong::LONG); register_new_node(Z_2, entry_control); @@ -1251,8 +1394,8 @@ Node* PhaseIdealLoop::clamp(Node* R, Node* L, Node* H) { return max; } -LoopNode* PhaseIdealLoop::create_inner_head(IdealLoopTree* loop, LongCountedLoopNode* head, - LongCountedLoopEndNode* exit_test) { +LoopNode* PhaseIdealLoop::create_inner_head(IdealLoopTree* loop, BaseCountedLoopNode* head, + IfNode* exit_test) { LoopNode* new_inner_head = new LoopNode(head->in(1), head->in(2)); IfNode* new_inner_exit = new IfNode(exit_test->in(0), exit_test->in(1), exit_test->_prob, exit_test->_fcnt); _igvn.register_new_node_with_optimizer(new_inner_head); @@ -1272,21 +1415,21 @@ LoopNode* PhaseIdealLoop::create_inner_head(IdealLoopTree* loop, LongCountedLoop } #ifdef ASSERT -void PhaseIdealLoop::check_long_counted_loop(IdealLoopTree* loop, Node* x) { +void PhaseIdealLoop::check_counted_loop_shape(IdealLoopTree* loop, Node* x, BasicType bt) { Node* back_control = loop_exit_control(x, loop); assert(back_control != NULL, "no back control"); - BoolTest::mask bt = BoolTest::illegal; + BoolTest::mask mask = BoolTest::illegal; float cl_prob = 0; Node* incr = NULL; Node* limit = NULL; - Node* cmp = loop_exit_test(back_control, loop, incr, limit, bt, cl_prob); - assert(cmp != NULL && cmp->Opcode() == Op_CmpL, "no exit test"); + Node* cmp = loop_exit_test(back_control, loop, incr, limit, mask, cl_prob); + assert(cmp != NULL && cmp->Opcode() == Op_Cmp(bt), "no exit test"); Node* phi_incr = NULL; incr = loop_iv_incr(incr, x, loop, phi_incr); - assert(incr != NULL && incr->Opcode() == Op_AddL, "no incr"); + assert(incr != NULL && incr->Opcode() == Op_Add(bt), "no incr"); Node* xphi = NULL; Node* stride = loop_iv_stride(incr, loop, xphi); @@ -1297,11 +1440,11 @@ void PhaseIdealLoop::check_long_counted_loop(IdealLoopTree* loop, Node* x) { assert(phi != NULL && phi->in(LoopNode::LoopBackControl) == incr, "No phi"); - jlong stride_con = stride->get_long(); + jlong stride_con = stride->get_integer_as_long(bt); - assert(condition_stride_ok(bt, stride_con), "illegal condition"); + assert(condition_stride_ok(mask, stride_con), "illegal condition"); - assert(bt != BoolTest::ne, "unexpected condition"); + assert(mask != BoolTest::ne, "unexpected condition"); assert(phi_incr == NULL, "bad loop shape"); assert(cmp->in(1) == incr, "bad exit test shape"); @@ -1630,7 +1773,7 @@ bool PhaseIdealLoop::is_counted_loop(Node* x, IdealLoopTree*&loop, BasicType iv_ if (sov < 0) { return false; // Bailout: integer overflow is certain. } - assert(!x->as_Loop()->is_transformed_long_inner_loop(), "long loop was transformed"); + assert(!x->as_Loop()->is_loop_nest_inner_loop(), "loop was transformed"); // Generate loop's limit check. // Loop limit check predicate should be near the loop. ProjNode *limit_check_proj = find_predicate_insertion_point(init_control, Deoptimization::Reason_loop_limit_check); @@ -1720,7 +1863,7 @@ bool PhaseIdealLoop::is_counted_loop(Node* x, IdealLoopTree*&loop, BasicType iv_ #ifdef ASSERT if (iv_bt == T_INT && - !x->as_Loop()->is_transformed_long_inner_loop() && + !x->as_Loop()->is_loop_nest_inner_loop() && StressLongCountedLoop > 0 && trunc1 == NULL && convert_to_long_loop(cmp, phi, loop)) { @@ -1925,12 +2068,12 @@ bool PhaseIdealLoop::is_counted_loop(Node* x, IdealLoopTree*&loop, BasicType iv_ } #ifndef PRODUCT - if (x->as_Loop()->is_transformed_long_inner_loop()) { + if (x->as_Loop()->is_loop_nest_inner_loop() && iv_bt == T_LONG) { Atomic::inc(&_long_loop_counted_loops); } #endif - if (iv_bt == T_LONG && x->as_Loop()->is_transformed_long_outer_loop()) { - l->mark_transformed_long_outer_loop(); + if (iv_bt == T_LONG && x->as_Loop()->is_loop_nest_outer_loop()) { + l->mark_loop_nest_outer_loop(); } return true; @@ -2405,11 +2548,6 @@ int CountedLoopNode::stride_con() const { return cle != NULL ? cle->stride_con() : 0; } -jlong LongCountedLoopNode::stride_con() const { - LongCountedLoopEndNode* cle = loopexit_or_null(); - return cle != NULL ? cle->stride_con() : 0; -} - BaseCountedLoopNode* BaseCountedLoopNode::make(Node* entry, Node* backedge, BasicType bt) { if (bt == T_INT) { return new CountedLoopNode(entry, backedge); @@ -3542,7 +3680,7 @@ void IdealLoopTree::counted_loop( PhaseIdealLoop *phase ) { phase->is_counted_loop(_head, loop, T_LONG)) { remove_safepoints(phase, true); } else { - assert(!_head->is_Loop() || !_head->as_Loop()->is_transformed_long_inner_loop(), "transformation to counted loop should not fail"); + assert(!_head->is_Loop() || !_head->as_Loop()->is_loop_nest_inner_loop(), "transformation to counted loop should not fail"); if (_parent != NULL && !_irreducible) { // Not a counted loop. Keep one safepoint. bool keep_one_sfpt = true; @@ -4214,7 +4352,9 @@ void PhaseIdealLoop::build_and_optimize(LoopOptsMode mode) { // Because RCE opportunities can be masked by split_thru_phi, // look for RCE candidates and inhibit split_thru_phi // on just their loop-phi's for this pass of loop opts - if (SplitIfBlocks && do_split_ifs && lpt->policy_range_check(this, true)) { + if (SplitIfBlocks && do_split_ifs && + (lpt->policy_range_check(this, true, T_LONG) || + (head->is_CountedLoop() && lpt->policy_range_check(this, true, T_INT)))) { lpt->_rce_candidate = 1; // = true } } @@ -4266,13 +4406,6 @@ void PhaseIdealLoop::build_and_optimize(LoopOptsMode mode) { // Do verify graph edges in any case NOT_PRODUCT( C->verify_graph_edges(); ); - if (C->has_loops() && !C->major_progress()) { - for (LoopTreeIterator iter(_ltree_root); !iter.done(); iter.next()) { - IdealLoopTree *lpt = iter.current(); - transform_long_counted_loop(lpt, worklist); - } - } - if (!do_split_ifs) { // We saw major progress in Split-If to get here. We forced a // pass with unrolling and not split-if, however more split-if's diff --git a/src/hotspot/share/opto/loopnode.hpp b/src/hotspot/share/opto/loopnode.hpp index 4cca7ab45da..b156ceb95b4 100644 --- a/src/hotspot/share/opto/loopnode.hpp +++ b/src/hotspot/share/opto/loopnode.hpp @@ -77,8 +77,8 @@ protected: StripMined = 1<<15, SubwordLoop = 1<<16, ProfileTripFailed = 1<<17, - TransformedLongInnerLoop = 1<<18, - TransformedLongOuterLoop = 1<<19}; + LoopNestInnerLoop = 1 << 18, + LoopNestLongOuterLoop = 1 << 19}; char _unswitch_count; enum { _unswitch_max=3 }; char _postloop_flags; @@ -103,8 +103,8 @@ public: bool is_strip_mined() const { return _loop_flags & StripMined; } bool is_profile_trip_failed() const { return _loop_flags & ProfileTripFailed; } bool is_subword_loop() const { return _loop_flags & SubwordLoop; } - bool is_transformed_long_inner_loop() const { return _loop_flags & TransformedLongInnerLoop; } - bool is_transformed_long_outer_loop() const { return _loop_flags & TransformedLongOuterLoop; } + bool is_loop_nest_inner_loop() const { return _loop_flags & LoopNestInnerLoop; } + bool is_loop_nest_outer_loop() const { return _loop_flags & LoopNestLongOuterLoop; } void mark_partial_peel_failed() { _loop_flags |= PartialPeelFailed; } void mark_has_reductions() { _loop_flags |= HasReductions; } @@ -119,8 +119,8 @@ public: void clear_strip_mined() { _loop_flags &= ~StripMined; } void mark_profile_trip_failed() { _loop_flags |= ProfileTripFailed; } void mark_subword_loop() { _loop_flags |= SubwordLoop; } - void mark_transformed_long_inner_loop() { _loop_flags |= TransformedLongInnerLoop; } - void mark_transformed_long_outer_loop() { _loop_flags |= TransformedLongOuterLoop; } + void mark_loop_nest_inner_loop() { _loop_flags |= LoopNestInnerLoop; } + void mark_loop_nest_outer_loop() { _loop_flags |= LoopNestLongOuterLoop; } int unswitch_max() { return _unswitch_max; } int unswitch_count() { return _unswitch_count; } @@ -216,6 +216,8 @@ public: virtual BasicType bt() const = 0; + jlong stride_con() const; + static BaseCountedLoopNode* make(Node* entry, Node* backedge, BasicType bt); }; @@ -364,7 +366,6 @@ public: LongCountedLoopEndNode* loopexit_or_null() const { return (LongCountedLoopEndNode*) BaseCountedLoopNode::loopexit_or_null(); } LongCountedLoopEndNode* loopexit() const { return (LongCountedLoopEndNode*) BaseCountedLoopNode::loopexit(); } - jlong stride_con() const; }; @@ -512,6 +513,12 @@ inline Node* BaseCountedLoopNode::phi() const { return cle != NULL ? cle->phi() : NULL; } +inline jlong BaseCountedLoopNode::stride_con() const { + BaseCountedLoopEndNode* cle = loopexit_or_null(); + return cle != NULL ? cle->stride_con() : 0; +} + + //------------------------------LoopLimitNode----------------------------- // Counted Loop limit node which represents exact final iterator value: // trip_count = (limit - init_trip + stride - 1)/stride @@ -710,7 +717,7 @@ public: // Return TRUE or FALSE if the loop should be range-check-eliminated. // Gather a list of IF tests that are dominated by iteration splitting; // also gather the end of the first split and the start of the 2nd split. - bool policy_range_check(PhaseIdealLoop* phase, bool provisional) const; + bool policy_range_check(PhaseIdealLoop* phase, bool provisional, BasicType bt) const; // Return TRUE if "iff" is a range check. bool is_range_check_if(IfNode *iff, PhaseIdealLoop *phase, Invariance& invar DEBUG_ONLY(COMMA ProjNode *predicate_proj)) const; @@ -1146,8 +1153,8 @@ public: bool is_counted_loop(Node* x, IdealLoopTree*&loop, BasicType iv_bt); - Node* long_loop_replace_long_iv(Node* iv_to_replace, Node* inner_iv, Node* outer_phi, Node* inner_head); - bool transform_long_counted_loop(IdealLoopTree* loop, Node_List &old_new); + Node* loop_nest_replace_iv(Node* iv_to_replace, Node* inner_iv, Node* outer_phi, Node* inner_head, BasicType bt); + bool create_loop_nest(IdealLoopTree* loop, Node_List &old_new); #ifdef ASSERT bool convert_to_long_loop(Node* cmp, Node* phi, IdealLoopTree* loop); #endif @@ -1248,10 +1255,12 @@ public: void mark_reductions( IdealLoopTree *loop ); // Return true if exp is a constant times an induction var - bool is_scaled_iv(Node* exp, Node* iv, jlong* p_scale, BasicType bt); + bool is_scaled_iv(Node* exp, Node* iv, jlong* p_scale, BasicType bt, bool* converted); + + bool is_iv(Node* exp, Node* iv, BasicType bt); // Return true if exp is a scaled induction var plus (or minus) constant - bool is_scaled_iv_plus_offset(Node* exp, Node* iv, jlong* p_scale, Node** p_offset, BasicType bt, int depth = 0); + bool is_scaled_iv_plus_offset(Node* exp, Node* iv, jlong* p_scale, Node** p_offset, BasicType bt, bool* converted = NULL, int depth = 0); bool is_scaled_iv_plus_offset(Node* exp, Node* iv, int* p_scale, Node** p_offset) { jlong long_scale; if (is_scaled_iv_plus_offset(exp, iv, &long_scale, p_offset, T_INT)) { @@ -1610,9 +1619,9 @@ public: void rpo(Node* start, Node_Stack &stk, VectorSet &visited, Node_List &rpo_list) const; - void check_long_counted_loop(IdealLoopTree* loop, Node* x) NOT_DEBUG_RETURN; + void check_counted_loop_shape(IdealLoopTree* loop, Node* x, BasicType bt) NOT_DEBUG_RETURN; - LoopNode* create_inner_head(IdealLoopTree* loop, LongCountedLoopNode* head, LongCountedLoopEndNode* exit_test); + LoopNode* create_inner_head(IdealLoopTree* loop, BaseCountedLoopNode* head, IfNode* exit_test); int extract_long_range_checks(const IdealLoopTree* loop, jlong stride_con, int iters_limit, PhiNode* phi, @@ -1635,6 +1644,9 @@ public: Node* clamp(Node* R, Node* L, Node* H); bool safe_for_if_replacement(const Node* dom) const; + + void strip_mined_nest_back_to_counted_loop(IdealLoopTree* loop, const BaseCountedLoopNode* head, Node* back_control, + IfNode*&exit_test, SafePointNode*&safepoint); }; diff --git a/src/hotspot/share/opto/loopopts.cpp b/src/hotspot/share/opto/loopopts.cpp index f1cb053d87e..65bb4f663a8 100644 --- a/src/hotspot/share/opto/loopopts.cpp +++ b/src/hotspot/share/opto/loopopts.cpp @@ -1053,7 +1053,7 @@ Node *PhaseIdealLoop::split_if_with_blocks_pre( Node *n ) { // Do not clone the trip counter through on a CountedLoop // (messes up the canonical shape). - if (((n_blk->is_CountedLoop() || (n_blk->is_Loop() && n_blk->as_Loop()->is_transformed_long_inner_loop())) && n->Opcode() == Op_AddI) || + if (((n_blk->is_CountedLoop() || (n_blk->is_Loop() && n_blk->as_Loop()->is_loop_nest_inner_loop())) && n->Opcode() == Op_AddI) || (n_blk->is_LongCountedLoop() && n->Opcode() == Op_AddL)) { return n; } diff --git a/test/hotspot/jtreg/compiler/c2/irTests/TestLongRangeChecks.java b/test/hotspot/jtreg/compiler/c2/irTests/TestLongRangeChecks.java index 298f0094201..4fd677ab4c0 100644 --- a/test/hotspot/jtreg/compiler/c2/irTests/TestLongRangeChecks.java +++ b/test/hotspot/jtreg/compiler/c2/irTests/TestLongRangeChecks.java @@ -28,7 +28,7 @@ import java.util.Objects; /* * @test - * @bug 8259609 + * @bug 8259609 8276116 * @summary C2: optimize long range checks in long counted loops * @library /test/lib / * @run driver compiler.c2.irTests.TestLongRangeChecks @@ -41,8 +41,8 @@ public class TestLongRangeChecks { @Test - @IR(counts = { IRNode.LOOP, "1"}) - @IR(failOn = { IRNode.COUNTEDLOOP}) + @IR(counts = { IRNode.LOOP, "1" }) + @IR(failOn = { IRNode.COUNTEDLOOP }) public static void testStridePosScalePos(long start, long stop, long length, long offset) { final long scale = 1; final long stride = 1; @@ -60,4 +60,40 @@ public class TestLongRangeChecks { private void testStridePosScalePos_runner() { testStridePosScalePos(0, 100, 100, 0); } + + @Test + @IR(counts = { IRNode.LOOP, "1" }) + @IR(failOn = { IRNode.COUNTEDLOOP }) + public static void testStridePosScalePosInIntLoop1(int start, int stop, long length, long offset) { + final long scale = 2; + final int stride = 1; + + // Same but with int loop + for (int i = start; i < stop; i += stride) { + Objects.checkIndex(scale * i + offset, length); + } + } + + @Run(test = "testStridePosScalePosInIntLoop1") + private void testStridePosScalePosInIntLoop1_runner() { + testStridePosScalePosInIntLoop1(0, 100, 200, 0); + } + + @Test + @IR(counts = { IRNode.LOOP, "1" }) + @IR(failOn = { IRNode.COUNTEDLOOP }) + public static void testStridePosScalePosInIntLoop2(int start, int stop, long length, long offset) { + final int scale = 2; + final int stride = 1; + + // Same but with int loop + for (int i = start; i < stop; i += stride) { + Objects.checkIndex(scale * i + offset, length); + } + } + + @Run(test = "testStridePosScalePosInIntLoop2") + private void testStridePosScalePosInIntLoop2_runner() { + testStridePosScalePosInIntLoop2(0, 100, 200, 0); + } } diff --git a/test/hotspot/jtreg/compiler/rangechecks/TestLongRangeCheck.java b/test/hotspot/jtreg/compiler/rangechecks/TestLongRangeCheck.java index 63a649b886b..d56d19278cf 100644 --- a/test/hotspot/jtreg/compiler/rangechecks/TestLongRangeCheck.java +++ b/test/hotspot/jtreg/compiler/rangechecks/TestLongRangeCheck.java @@ -23,7 +23,7 @@ /** * @test - * @bug 8259609 + * @bug 8259609 8276116 * @summary C2: optimize long range checks in long counted loops * @requires vm.compiler2.enabled * @requires vm.compMode != "Xcomp" @@ -32,7 +32,7 @@ * @build sun.hotspot.WhiteBox * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox * - * @run main/othervm -ea -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:-BackgroundCompilation TestLongRangeCheck + * @run main/othervm -ea -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:-BackgroundCompilation -XX:-UseOnStackReplacement TestLongRangeCheck * */ @@ -193,6 +193,115 @@ public class TestLongRangeCheck { m.invoke(null, 0, 100, Long.MAX_VALUE, Long.MAX_VALUE - 50, 0, 50); assertIsCompiled(m); } + + test("testStridePosScalePosInIntLoop", 0, 100, 100, 0); + + test("testStrideNegScaleNegInIntLoop", 0, 100, 100, 100); + + test("testStrideNegScalePosInIntLoop", 0, 100, 100, 0); + + test("testStridePosScaleNegInIntLoop", 0, 100, 100, 99); + + test("testStridePosScalePosNotOneInIntLoop", 0, 100, 1090, 0); + + test("testStrideNegScaleNegNotOneInIntLoop", 0, 100, 1090, 1100); + + test("testStrideNegScalePosNotOneInIntLoop", 0, 100, 1090, 0); + + test("testStridePosScaleNegNotOneInIntLoop", 0, 100, 1090, 1089); + + v = ((long)Integer.MAX_VALUE / 10000) * 9999; + + test("testStridePosNotOneScalePosInIntLoop", -v, v, v * 4, 2 * v); + + test("testStrideNegNotOneScaleNegInIntLoop", -v, v, v * 4, 2 * v); + + test("testStrideNegNotOneScalePosInIntLoop", -v, v, v * 4, 2 * v); + + test("testStridePosNotOneScaleNegInIntLoop", -v, v, v * 4, 2 * v - 1); + + // offset causes overflow + { + Method m = newClassLoader().loadClass("TestLongRangeCheck").getDeclaredMethod("testStridePosScalePosInIntLoop", long.class, long.class, long.class, long.class); + m.invoke(null, 0, 100, 100, 0); + compile(m); + + m.invoke(null, 0, 100, 100, 0); + assertIsCompiled(m); + try { + m.invoke(null, 0, 100, 100, Long.MAX_VALUE - 50); + throw new RuntimeException("should have thrown"); + } catch(InvocationTargetException e) { + if (!(e.getCause() instanceof IndexOutOfBoundsException)) { + throw new RuntimeException("unexpected exception"); + } + } + assertIsNotCompiled(m); + } + // no spurious deopt if the range check doesn't fail because not executed + { + Method m = newClassLoader().loadClass("TestLongRangeCheck").getDeclaredMethod("testStridePosScalePosConditional", long.class, long.class, long.class, long.class, long.class, long.class); + m.invoke(null, 0, 100, 100, 0, 0, 100); + compile(m); + + m.invoke(null, 0, 100, 100, -50, 50, 100); + assertIsCompiled(m); + } + { + Method m = newClassLoader().loadClass("TestLongRangeCheck").getDeclaredMethod("testStridePosScalePosConditional", long.class, long.class, long.class, long.class, long.class, long.class); + m.invoke(null, 0, 100, 100, 0, 0, 100); + compile(m); + + m.invoke(null, 0, 100, Long.MAX_VALUE, Long.MAX_VALUE - 50, 0, 50); + assertIsCompiled(m); + } + + test("testStridePosScalePosNotOneInIntLoop2", 0, 100, 1090, 0); + + test("testStrideNegScaleNegNotOneInIntLoop2", 0, 100, 1090, 1100); + + test("testStrideNegScalePosNotOneInIntLoop2", 0, 100, 1090, 0); + + test("testStridePosScaleNegNotOneInIntLoop2", 0, 100, 1090, 1089); + + { + Method m = newClassLoader().loadClass("TestLongRangeCheck").getDeclaredMethod("testStridePosScalePosInIntLoopOverflow", long.class, long.class, long.class, long.class); + long stride = 1 << 14; + long scale = 1 << 15; + long offset = stride * scale * 4; + long length = offset + stride * scale * 3 + 1; + long stop = stride * 5; + + m.invoke(null, 0, stop, length, offset); + compile(m); + + m.invoke(null, 0, stop, length, offset); + // deoptimizes even though no range check fails + } + { + Method m = newClassLoader().loadClass("TestLongRangeCheck").getDeclaredMethod("testStridePosScalePosInIntLoopOverflow", long.class, long.class, long.class, long.class); + long stride = 1 << 14; + long scale = 1 << 15; + long offset = stride * scale * 4; + long length = offset + stride * scale * 3 + 1; + long stop = stride * 5; + + m.invoke(null, 0, stop, length, offset); + compile(m); + + offset = 0; + stop = stride * 5; + + try { + m.invoke(null, 0, stop, length, offset); + throw new RuntimeException("should have thrown"); + } catch(InvocationTargetException e) { + if (!(e.getCause() instanceof IndexOutOfBoundsException)) { + throw new RuntimeException("unexpected exception"); + } + } + assertIsNotCompiled(m); + } } public static void testStridePosScalePos(long start, long stop, long length, long offset) { @@ -301,4 +410,177 @@ public class TestLongRangeCheck { } } } + + private static void checkInputs(long... inputs) { + for (int i = 0; i < inputs.length; i++) { + if ((long)((int)inputs[i]) != inputs[i]) { + throw new RuntimeException("bad arguments"); + } + } + } + + public static void testStridePosScalePosInIntLoop(long start, long stop, long length, long offset) { + checkInputs(start, stop); + final long scale = 1; + final int stride = 1; + for (int i = (int)start; i < (int)stop; i += stride) { + Preconditions.checkIndex(scale * i + offset, length, null); + } + } + + public static void testStrideNegScaleNegInIntLoop(long start, long stop, long length, long offset) { + checkInputs(start, stop); + final long scale = -1; + final int stride = 1; + for (int i = (int)stop; i > (int)start; i -= stride) { + Preconditions.checkIndex(scale * i + offset, length, null); + } + } + + public static void testStrideNegScalePosInIntLoop(long start, long stop, long length, long offset) { + checkInputs(start, stop); + final long scale = 1; + final int stride = 1; + for (int i = (int)(stop-1); i >= (int)start; i -= stride) { + Preconditions.checkIndex(scale * i + offset, length, null); + } + } + + public static void testStridePosScaleNegInIntLoop(long start, long stop, long length, long offset) { + checkInputs(start, stop); + final long scale = -1; + final int stride = 1; + for (int i = (int)start; i < (int)stop; i += stride) { + Preconditions.checkIndex(scale * i + offset, length, null); + } + } + + public static void testStridePosScalePosNotOneInIntLoop(long start, long stop, long length, long offset) { + checkInputs(start, stop); + final long scale = 11; + final int stride = 1; + for (int i = (int)start; i < (int)stop; i += stride) { + Preconditions.checkIndex(scale * i + offset, length, null); + } + } + + public static void testStrideNegScaleNegNotOneInIntLoop(long start, long stop, long length, long offset) { + checkInputs(start, stop); + final long scale = -11; + final int stride = 1; + for (int i = (int)stop; i > (int)start; i -= stride) { + Preconditions.checkIndex(scale * i + offset, length, null); + } + } + + public static void testStrideNegScalePosNotOneInIntLoop(long start, long stop, long length, long offset) { + checkInputs(start, stop); + final long scale = 11; + final int stride = 1; + for (int i = (int)(stop-1); i >= (int)start; i -= stride) { + Preconditions.checkIndex(scale * i + offset, length, null); + } + } + + public static void testStridePosScaleNegNotOneInIntLoop(long start, long stop, long length, long offset) { + checkInputs(start, stop); + final long scale = -11; + final int stride = 1; + for (int i = (int)start; i < (int)stop; i += stride) { + Preconditions.checkIndex(scale * i + offset, length, null); + } + } + + public static void testStridePosNotOneScalePosInIntLoop(long start, long stop, long length, long offset) { + checkInputs(start, stop); + final long scale = 2; + final int stride = Integer.MAX_VALUE / 10000; + for (int i = (int)start; i < (int)stop; i += stride) { + Preconditions.checkIndex(scale * i + offset, length, null); + } + } + + public static void testStrideNegNotOneScaleNegInIntLoop(long start, long stop, long length, long offset) { + checkInputs(start, stop); + final long scale = -2; + final int stride = Integer.MAX_VALUE / 10000; + for (int i = (int)stop; i > (int)start; i -= stride) { + Preconditions.checkIndex(scale * i + offset, length, null); + } + } + + public static void testStrideNegNotOneScalePosInIntLoop(long start, long stop, long length, long offset) { + checkInputs(start, stop); + final long scale = 2; + final int stride = Integer.MAX_VALUE / 10000; + for (int i = (int)(stop-1); i >= (int)start; i -= stride) { + Preconditions.checkIndex(scale * i + offset, length, null); + } + } + + public static void testStridePosNotOneScaleNegInIntLoop(long start, long stop, long length, long offset) { + checkInputs(start, stop); + final long scale = -2; + final int stride = Integer.MAX_VALUE / 10000; + for (int i = (int)start; i < (int)stop; i += stride) { + Preconditions.checkIndex(scale * i + offset, length, null); + } + } + + public static void testStridePosScalePosConditionalInIntLoop(long start, long stop, long length, long offset, long start2, long stop2) { + checkInputs(start, stop, start2, stop2); + Preconditions.checkIndex(0, length, null); + final long scale = 1; + final int stride = 1; + for (int i = (int)start; i < (int)stop; i += stride) { + if (i >= (int)start2 && i < (int)stop2) { + Preconditions.checkIndex(scale * i + offset, length, null); + } + } + } + + public static void testStridePosScalePosNotOneInIntLoop2(long start, long stop, long length, long offset) { + checkInputs(start, stop); + final int scale = 11; + final int stride = 1; + for (int i = (int)start; i < (int)stop; i += stride) { + Preconditions.checkIndex(scale * i + offset, length, null); + } + } + + public static void testStrideNegScaleNegNotOneInIntLoop2(long start, long stop, long length, long offset) { + checkInputs(start, stop); + final int scale = -11; + final int stride = 1; + for (int i = (int)stop; i > (int)start; i -= stride) { + Preconditions.checkIndex(scale * i + offset, length, null); + } + } + + public static void testStrideNegScalePosNotOneInIntLoop2(long start, long stop, long length, long offset) { + checkInputs(start, stop); + final int scale = 11; + final int stride = 1; + for (int i = (int)(stop-1); i >= (int)start; i -= stride) { + Preconditions.checkIndex(scale * i + offset, length, null); + } + } + + public static void testStridePosScaleNegNotOneInIntLoop2(long start, long stop, long length, long offset) { + checkInputs(start, stop); + final int scale = -11; + final int stride = 1; + for (int i = (int)start; i < (int)stop; i += stride) { + Preconditions.checkIndex(scale * i + offset, length, null); + } + } + + public static void testStridePosScalePosInIntLoopOverflow(long start, long stop, long length, long offset) { + checkInputs(start, stop); + final int scale = 1 << 15; + final int stride = 1 << 14; + for (int i = (int)start; i < (int)stop; i += stride) { + Preconditions.checkIndex(scale * i + offset, length, null); + } + } } -- GitLab From 3893f4f70b5828ee8e673ce7b1422877efe5c292 Mon Sep 17 00:00:00 2001 From: Serguei Spitsyn Date: Wed, 8 Dec 2021 22:32:00 +0000 Subject: [PATCH 072/671] 8278330: dump stack trace if the jvmti test nsk/jvmti/GetThreadState/thrstat002 is failed with wrong thread state Reviewed-by: amenkov, lmesnik --- .../GetThreadState/thrstat002/thrstat002.cpp | 104 ++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetThreadState/thrstat002/thrstat002.cpp b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetThreadState/thrstat002/thrstat002.cpp index 4840af81f38..2b10a77c56c 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetThreadState/thrstat002/thrstat002.cpp +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetThreadState/thrstat002/thrstat002.cpp @@ -48,6 +48,107 @@ static jint state[] = { JVMTI_THREAD_STATE_IN_OBJECT_WAIT }; + +#if 1 // support for debug tracing + +#define LOG(...) \ + { \ + printf(__VA_ARGS__); \ + fflush(stdout); \ + } + +#define MAX_FRAME_COUNT_PRINT_STACK_TRACE 200 + +static void +check_jvmti_status(JNIEnv* jni, jvmtiError err, const char* msg) { + if (err != JVMTI_ERROR_NONE) { + LOG("check_jvmti_status: JVMTI function returned error: %s (%d)\n", TranslateError(err), err); + jni->FatalError(msg); + } +} + +static void +deallocate(jvmtiEnv *jvmti, JNIEnv* jni, void* ptr) { + jvmtiError err; + + err = jvmti->Deallocate((unsigned char*)ptr); + check_jvmti_status(jni, err, "deallocate: error in JVMTI Deallocate call"); +} + +static char* +get_method_class_name(jvmtiEnv *jvmti, JNIEnv* jni, jmethodID method) { + jclass klass = NULL; + char* cname = NULL; + char* result = NULL; + jvmtiError err; + + err = jvmti->GetMethodDeclaringClass(method, &klass); + check_jvmti_status(jni, err, "get_method_class_name: error in JVMTI GetMethodDeclaringClass"); + + err = jvmti->GetClassSignature(klass, &cname, NULL); + check_jvmti_status(jni, err, "get_method_class_name: error in JVMTI GetClassSignature"); + + size_t len = strlen(cname) - 2; // get rid of leading 'L' and trailing ';' + + err = jvmti->Allocate((jlong)(len + 1), (unsigned char**)&result); + check_jvmti_status(jni, err, "get_method_class_name: error in JVMTI Allocate"); + + strncpy(result, cname + 1, len); // skip leading 'L' + result[len] = '\0'; + deallocate(jvmti, jni, (void*)cname); + return result; +} + +static void +print_method(jvmtiEnv *jvmti, JNIEnv* jni, jmethodID method, jint depth) { + char* cname = NULL; + char* mname = NULL; + char* msign = NULL; + jvmtiError err; + + cname = get_method_class_name(jvmti, jni, method); + + err = jvmti->GetMethodName(method, &mname, &msign, NULL); + check_jvmti_status(jni, err, "print_method: error in JVMTI GetMethodName"); + + LOG("%2d: %s: %s%s\n", depth, cname, mname, msign); + fflush(0); + deallocate(jvmti, jni, (void*)cname); + deallocate(jvmti, jni, (void*)mname); + deallocate(jvmti, jni, (void*)msign); +} + +static char* +get_thread_name(jvmtiEnv *jvmti, JNIEnv* jni, jthread thread) { + jvmtiThreadInfo thr_info; + jvmtiError err; + + memset(&thr_info, 0, sizeof(thr_info)); + err = jvmti->GetThreadInfo(thread, &thr_info); + check_jvmti_status(jni, err, "get_thread_name: error in JVMTI GetThreadInfo call"); + + return thr_info.name == NULL ? (char*)"" : thr_info.name; +} + +static void +print_stack_trace(jvmtiEnv *jvmti, JNIEnv* jni, jthread thread) { + jvmtiFrameInfo frames[MAX_FRAME_COUNT_PRINT_STACK_TRACE]; + char* tname = get_thread_name(jvmti, jni, thread); + jint count = 0; + jvmtiError err; + + err = jvmti->GetStackTrace(thread, 0, MAX_FRAME_COUNT_PRINT_STACK_TRACE, frames, &count); + check_jvmti_status(jni, err, "print_stack_trace: error in JVMTI GetStackTrace"); + + LOG("JVMTI Stack Trace for thread %s: frame count: %d\n", tname, count); + for (int depth = 0; depth < count; depth++) { + print_method(jvmti, jni, frames[depth].method, depth); + } + deallocate(jvmti, jni, (void*)tname); + LOG("\n"); +} +#endif // support for debug tracing + void printStateFlags(jint flags) { if (flags & JVMTI_THREAD_STATE_SUSPENDED) printf(" JVMTI_THREAD_STATE_SUSPENDED"); @@ -337,6 +438,9 @@ Java_nsk_jvmti_GetThreadState_thrstat002_checkStatus(JNIEnv *env, jclass cls, TranslateState(state[statInd]), state[statInd]); printf(" actual: %s (%d)\n", TranslateState(thrState), thrState); +#ifdef DBG + print_stack_trace(jvmti, env, thr_ptr); +#endif result = STATUS_FAILED; } if (suspState != JVMTI_THREAD_STATE_SUSPENDED) { -- GitLab From 03bf55f62065f8f9c8ade1eff8ca6eaeabe51450 Mon Sep 17 00:00:00 2001 From: Vicente Romero Date: Wed, 8 Dec 2021 22:49:43 +0000 Subject: [PATCH 073/671] 8277980: ObjectMethods::bootstrap throws NPE when lookup is null Reviewed-by: jjg --- .../share/classes/java/lang/runtime/ObjectMethods.java | 6 +++--- test/jdk/java/lang/runtime/ObjectMethodsTest.java | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/java.base/share/classes/java/lang/runtime/ObjectMethods.java b/src/java.base/share/classes/java/lang/runtime/ObjectMethods.java index 5d092328f75..c2d388d01ba 100644 --- a/src/java.base/share/classes/java/lang/runtime/ObjectMethods.java +++ b/src/java.base/share/classes/java/lang/runtime/ObjectMethods.java @@ -396,15 +396,15 @@ public class ObjectMethods { * if invoked by a condy * @throws IllegalArgumentException if the bootstrap arguments are invalid * or inconsistent - * @throws NullPointerException if any argument but {@code lookup} is {@code null}, - * in the case of the {@code getters} argument, its - * contents cannot be {@code null} either + * @throws NullPointerException if any argument is {@code null} or if any element + * in the {@code getters} array is {@code null} * @throws Throwable if any exception is thrown during call site construction */ public static Object bootstrap(MethodHandles.Lookup lookup, String methodName, TypeDescriptor type, Class recordClass, String names, MethodHandle... getters) throws Throwable { + requireNonNull(lookup); requireNonNull(methodName); requireNonNull(type); requireNonNull(recordClass); diff --git a/test/jdk/java/lang/runtime/ObjectMethodsTest.java b/test/jdk/java/lang/runtime/ObjectMethodsTest.java index dba92eb32ff..0a7741c02e1 100644 --- a/test/jdk/java/lang/runtime/ObjectMethodsTest.java +++ b/test/jdk/java/lang/runtime/ObjectMethodsTest.java @@ -166,6 +166,7 @@ public class ObjectMethodsTest { assertThrows(NPE, () -> ObjectMethods.bootstrap(LOOKUP, npt.mn(), npt.mt(), null, "x;y", C.ACCESSORS)); assertThrows(NPE, () -> ObjectMethods.bootstrap(LOOKUP, npt.mn(), null, C.class, "x;y", C.ACCESSORS)); assertThrows(NPE, () -> ObjectMethods.bootstrap(LOOKUP, null, npt.mt(), C.class, "x;y", C.ACCESSORS)); + assertThrows(NPE, () -> ObjectMethods.bootstrap(null, npt.mn(), npt.mt(), C.class, "x;y", C.ACCESSORS)); } } -- GitLab From 3cec700a5caa2243772e4b01c40630cb044b76fc Mon Sep 17 00:00:00 2001 From: Roger Riggs Date: Wed, 8 Dec 2021 22:59:38 +0000 Subject: [PATCH 074/671] 8278463: [test] Serialization WritePrimitive test revised for readFully test fails Reviewed-by: darcy --- test/jdk/java/io/Serializable/oldTests/WritePrimitive.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/jdk/java/io/Serializable/oldTests/WritePrimitive.java b/test/jdk/java/io/Serializable/oldTests/WritePrimitive.java index 2846e7c8f8d..e6b841e7a49 100644 --- a/test/jdk/java/io/Serializable/oldTests/WritePrimitive.java +++ b/test/jdk/java/io/Serializable/oldTests/WritePrimitive.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2021, 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 @@ -22,6 +22,7 @@ */ /* @test + * @bug 8276806 8278463 * @summary it is a new version of an old test which was * /src/share/test/serialization/piotest.java * Test of serialization/deserialization of @@ -90,7 +91,7 @@ public class WritePrimitive { byte[] ba_readFullyBuf = new byte[ba.length]; int ba_readFullyLen = q.read(ba_readFullyBuf); byte[] ba_readFullySizedBuf = new byte[ba.length]; - int ba_readFullySizedLen = q.read(ba_readFullySizedBuf, 0, ba.length - 1); + int ba_readFullySizedLen = q.read(ba_readFullySizedBuf, 0, ba.length - 2); String string_utf = q.readUTF(); String string_u = (String)q.readObject(); if (i != i_u) { -- GitLab From 83e6a4c0e9e4a9474ae0c1252378b1a09d1d2df0 Mon Sep 17 00:00:00 2001 From: Valerie Peng Date: Wed, 8 Dec 2021 23:04:15 +0000 Subject: [PATCH 075/671] 8255409: Support the new C_GetInterfaceList, C_GetInterface, and C_SessionCancel APIs in PKCS#11 v3.0 Reviewed-by: ascarpino, weijun --- .../classes/sun/security/pkcs11/Config.java | 147 ++++++++------- .../sun/security/pkcs11/P11AEADCipher.java | 12 +- .../sun/security/pkcs11/P11Cipher.java | 14 +- .../sun/security/pkcs11/P11KeyWrapCipher.java | 19 +- .../classes/sun/security/pkcs11/P11Mac.java | 7 +- .../sun/security/pkcs11/P11PSSSignature.java | 17 +- .../sun/security/pkcs11/P11RSACipher.java | 19 +- .../sun/security/pkcs11/P11Signature.java | 14 +- .../classes/sun/security/pkcs11/P11Util.java | 21 +++ .../sun/security/pkcs11/SunPKCS11.java | 22 +-- .../sun/security/pkcs11/wrapper/PKCS11.java | 82 +++++++-- .../share/native/libj2pkcs11/p11_sessmgmt.c | 98 +++++++++- .../share/native/libj2pkcs11/p11_util.c | 14 ++ .../share/native/libj2pkcs11/pkcs11wrapper.h | 8 + .../unix/native/libj2pkcs11/p11_md.c | 172 ++++++++++++++---- .../unix/native/libj2pkcs11/p11_md.h | 5 +- .../windows/native/libj2pkcs11/p11_md.c | 164 +++++++++++++---- .../windows/native/libj2pkcs11/p11_md.h | 5 +- 18 files changed, 643 insertions(+), 197 deletions(-) diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/Config.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/Config.java index 6939c7be6f8..676c1fe50e3 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/Config.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/Config.java @@ -165,7 +165,7 @@ final class Config { // name of the C function that returns the PKCS#11 functionlist // This option primarily exists for the deprecated // Secmod.Module.getProvider() method. - private String functionList = "C_GetFunctionList"; + private String functionList = null; // whether to use NSS secmod mode. Implicitly set if nssLibraryDirectory, // nssSecmodDirectory, or nssModule is specified. @@ -311,6 +311,12 @@ final class Config { } String getFunctionList() { + if (functionList == null) { + // defaults to "C_GetFunctionList" for NSS secmod + if (nssUseSecmod || nssUseSecmodTrust) { + return "C_GetFunctionList"; + } + } return functionList; } @@ -408,67 +414,73 @@ final class Config { if (token != TT_WORD) { throw excToken("Unexpected token:"); } - String word = st.sval; - if (word.equals("name")) { - name = parseStringEntry(word); - } else if (word.equals("library")) { - library = parseLibrary(word); - } else if (word.equals("description")) { - parseDescription(word); - } else if (word.equals("slot")) { - parseSlotID(word); - } else if (word.equals("slotListIndex")) { - parseSlotListIndex(word); - } else if (word.equals("enabledMechanisms")) { - parseEnabledMechanisms(word); - } else if (word.equals("disabledMechanisms")) { - parseDisabledMechanisms(word); - } else if (word.equals("attributes")) { - parseAttributes(word); - } else if (word.equals("handleStartupErrors")) { - parseHandleStartupErrors(word); - } else if (word.endsWith("insertionCheckInterval")) { - insertionCheckInterval = parseIntegerEntry(word); + switch (st.sval) { + case "name"-> + name = parseStringEntry(st.sval); + case "library"-> + library = parseLibrary(st.sval); + case "description"-> + parseDescription(st.sval); + case "slot"-> + parseSlotID(st.sval); + case "slotListIndex"-> + parseSlotListIndex(st.sval); + case "enabledMechanisms"-> + parseEnabledMechanisms(st.sval); + case "disabledMechanisms"-> + parseDisabledMechanisms(st.sval); + case "attributes"-> + parseAttributes(st.sval); + case "handleStartupErrors"-> + parseHandleStartupErrors(st.sval); + case "insertionCheckInterval"-> { + insertionCheckInterval = parseIntegerEntry(st.sval); if (insertionCheckInterval < 100) { - throw excLine(word + " must be at least 100 ms"); + throw excLine(st.sval + " must be at least 100 ms"); } - } else if (word.equals("cleaner.shortInterval")) { - resourceCleanerShortInterval = parseIntegerEntry(word); + } + case "cleaner.shortInterval"-> { + resourceCleanerShortInterval = parseIntegerEntry(st.sval); if (resourceCleanerShortInterval < 1_000) { - throw excLine(word + " must be at least 1000 ms"); + throw excLine(st.sval + " must be at least 1000 ms"); } - } else if (word.equals("cleaner.longInterval")) { - resourceCleanerLongInterval = parseIntegerEntry(word); + } + case "cleaner.longInterval"-> { + resourceCleanerLongInterval = parseIntegerEntry(st.sval); if (resourceCleanerLongInterval < 1_000) { - throw excLine(word + " must be at least 1000 ms"); + throw excLine(st.sval + " must be at least 1000 ms"); } - } else if (word.equals("destroyTokenAfterLogout")) { - destroyTokenAfterLogout = parseBooleanEntry(word); - } else if (word.equals("showInfo")) { - showInfo = parseBooleanEntry(word); - } else if (word.equals("keyStoreCompatibilityMode")) { - keyStoreCompatibilityMode = parseBooleanEntry(word); - } else if (word.equals("explicitCancel")) { - explicitCancel = parseBooleanEntry(word); - } else if (word.equals("omitInitialize")) { - omitInitialize = parseBooleanEntry(word); - } else if (word.equals("allowSingleThreadedModules")) { - allowSingleThreadedModules = parseBooleanEntry(word); - } else if (word.equals("functionList")) { - functionList = parseStringEntry(word); - } else if (word.equals("nssUseSecmod")) { - nssUseSecmod = parseBooleanEntry(word); - } else if (word.equals("nssLibraryDirectory")) { - nssLibraryDirectory = parseLibrary(word); + } + case "destroyTokenAfterLogout"-> + destroyTokenAfterLogout = parseBooleanEntry(st.sval); + case "showInfo"-> + showInfo = parseBooleanEntry(st.sval); + case "keyStoreCompatibilityMode"-> + keyStoreCompatibilityMode = parseBooleanEntry(st.sval); + case "explicitCancel"-> + explicitCancel = parseBooleanEntry(st.sval); + case "omitInitialize"-> + omitInitialize = parseBooleanEntry(st.sval); + case "allowSingleThreadedModules"-> + allowSingleThreadedModules = parseBooleanEntry(st.sval); + case "functionList"-> + functionList = parseStringEntry(st.sval); + case "nssUseSecmod"-> + nssUseSecmod = parseBooleanEntry(st.sval); + case "nssLibraryDirectory"-> { + nssLibraryDirectory = parseLibrary(st.sval); nssUseSecmod = true; - } else if (word.equals("nssSecmodDirectory")) { - nssSecmodDirectory = expand(parseStringEntry(word)); + } + case "nssSecmodDirectory"-> { + nssSecmodDirectory = expand(parseStringEntry(st.sval)); nssUseSecmod = true; - } else if (word.equals("nssModule")) { - nssModule = parseStringEntry(word); + } + case "nssModule"-> { + nssModule = parseStringEntry(st.sval); nssUseSecmod = true; - } else if (word.equals("nssDbMode")) { - String mode = parseStringEntry(word); + } + case "nssDbMode"-> { + String mode = parseStringEntry(st.sval); if (mode.equals("readWrite")) { nssDbMode = Secmod.DbMode.READ_WRITE; } else if (mode.equals("readOnly")) { @@ -479,22 +491,25 @@ final class Config { throw excToken("nssDbMode must be one of readWrite, readOnly, and noDb:"); } nssUseSecmod = true; - } else if (word.equals("nssNetscapeDbWorkaround")) { - nssNetscapeDbWorkaround = parseBooleanEntry(word); + } + case "nssNetscapeDbWorkaround"-> { + nssNetscapeDbWorkaround = parseBooleanEntry(st.sval); nssUseSecmod = true; - } else if (word.equals("nssArgs")) { - parseNSSArgs(word); - } else if (word.equals("nssUseSecmodTrust")) { - nssUseSecmodTrust = parseBooleanEntry(word); - } else if (word.equals("useEcX963Encoding")) { - useEcX963Encoding = parseBooleanEntry(word); - } else if (word.equals("nssOptimizeSpace")) { - nssOptimizeSpace = parseBooleanEntry(word); - } else { + } + case "nssArgs"-> + parseNSSArgs(st.sval); + case "nssUseSecmodTrust"-> + nssUseSecmodTrust = parseBooleanEntry(st.sval); + case "useEcX963Encoding"-> + useEcX963Encoding = parseBooleanEntry(st.sval); + case "nssOptimizeSpace"-> + nssOptimizeSpace = parseBooleanEntry(st.sval); + default-> throw new ConfigurationException - ("Unknown keyword '" + word + "', line " + st.lineno()); + ("Unknown keyword '" + st.sval + "', line " + + st.lineno()); } - parsedKeywords.add(word); + parsedKeywords.add(st.sval); } reader.close(); reader = null; diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11AEADCipher.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11AEADCipher.java index 8a01705b76f..fbabbf2a36c 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11AEADCipher.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11AEADCipher.java @@ -401,7 +401,13 @@ final class P11AEADCipher extends CipherSpi { } private void cancelOperation() { - // cancel operation by finishing it; avoid killSession as some + token.ensureValid(); + if (P11Util.trySessionCancel(token, session, + (encrypt ? CKF_ENCRYPT : CKF_DECRYPT))) { + return; + } + + // cancel by finishing operations; avoid killSession as some // hardware vendors may require re-login int bufLen = doFinalLength(0); byte[] buffer = new byte[bufLen]; @@ -453,7 +459,7 @@ final class P11AEADCipher extends CipherSpi { token.ensureValid(); - byte[] aad = (aadBuffer.size() > 0? aadBuffer.toByteArray() : null); + byte[] aad = (aadBuffer.size() > 0 ? aadBuffer.toByteArray() : null); long p11KeyID = p11Key.getKeyID(); try { @@ -507,7 +513,7 @@ final class P11AEADCipher extends CipherSpi { result -= tagLen; } } - return (result > 0? result : 0); + return (result > 0 ? result : 0); } // reset the states to the pre-initialized values diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Cipher.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Cipher.java index 5934299e10c..367c9b84832 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Cipher.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Cipher.java @@ -445,8 +445,14 @@ final class P11Cipher extends CipherSpi { private void cancelOperation() { token.ensureValid(); - // cancel operation by finishing it; avoid killSession as some - // hardware vendors may require re-login + + if (P11Util.trySessionCancel(token, session, + (encrypt ? CKF_ENCRYPT : CKF_DECRYPT))) { + return; + } + + // cancel by finishing operations; avoid killSession as + // some hardware vendors may require re-login try { int bufLen = doFinalLength(0); byte[] buffer = new byte[bufLen]; @@ -458,7 +464,7 @@ final class P11Cipher extends CipherSpi { } catch (PKCS11Exception e) { if (e.match(CKR_OPERATION_NOT_INITIALIZED)) { // Cancel Operation may be invoked after an error on a PKCS#11 - // call. If the operation inside the token was already cancelled, + // call. If the operation inside the token is already cancelled, // do not fail here. This is part of a defensive mechanism for // PKCS#11 libraries that do not strictly follow the standard. return; @@ -488,7 +494,7 @@ final class P11Cipher extends CipherSpi { if (session == null) { session = token.getOpSession(); } - CK_MECHANISM mechParams = (blockMode == MODE_CTR? + CK_MECHANISM mechParams = (blockMode == MODE_CTR ? new CK_MECHANISM(mechanism, new CK_AES_CTR_PARAMS(iv)) : new CK_MECHANISM(mechanism, iv)); if (encrypt) { diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11KeyWrapCipher.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11KeyWrapCipher.java index 2385040d75c..caf0bd298fe 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11KeyWrapCipher.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11KeyWrapCipher.java @@ -126,7 +126,7 @@ final class P11KeyWrapCipher extends CipherSpi { String[] algoParts = algorithm.split("/"); if (algoParts[0].startsWith("AES")) { int index = algoParts[0].indexOf('_'); - fixedKeySize = (index == -1? -1 : + fixedKeySize = (index == -1 ? -1 : // should be well-formed since we specify what we support Integer.parseInt(algoParts[0].substring(index+1)) >> 3); try { @@ -180,7 +180,7 @@ final class P11KeyWrapCipher extends CipherSpi { protected AlgorithmParameters engineGetParameters() { // KW and KWP uses but not require parameters, return the default // IV when no IV is supplied by caller - byte[] iv = (this.iv == null? type.defIv : this.iv); + byte[] iv = (this.iv == null ? type.defIv : this.iv); AlgorithmParameterSpec spec = new IvParameterSpec(iv); try { @@ -213,7 +213,7 @@ final class P11KeyWrapCipher extends CipherSpi { ("Only IvParameterSpec is supported"); } - byte[] ivValue = (params == null? null : + byte[] ivValue = (params == null ? null : ((IvParameterSpec)params).getIV()); implInit(opmode, key, ivValue, sr); @@ -285,7 +285,14 @@ final class P11KeyWrapCipher extends CipherSpi { } private void cancelOperation() { - // cancel operation by finishing it; avoid killSession as some + token.ensureValid(); + + if (P11Util.trySessionCancel(token, session, + (opmode == Cipher.ENCRYPT_MODE ? CKF_ENCRYPT : CKF_DECRYPT))) { + return; + } + + // cancel by finishing operations; avoid killSession as some // hardware vendors may require re-login byte[] in = dataBuffer.toByteArray(); int inLen = in.length; @@ -379,7 +386,7 @@ final class P11KeyWrapCipher extends CipherSpi { } else { result -= BLK_SIZE; // minus the leading block including the ICV } - return (result > 0? result : 0); + return (result > 0 ? result : 0); } // reset the states to the pre-initialized values @@ -654,7 +661,7 @@ final class P11KeyWrapCipher extends CipherSpi { P11Key tbwP11Key = null; if (!(tbwKey instanceof P11Key)) { try { - tbwP11Key = (tbwKey instanceof SecretKey? + tbwP11Key = (tbwKey instanceof SecretKey ? P11SecretKeyFactory.convertKey(token, tbwKey, tbwKey.getAlgorithm()) : P11KeyFactory.convertKey(token, tbwKey, diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Mac.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Mac.java index 0e86528bb57..97082eae850 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Mac.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Mac.java @@ -147,7 +147,12 @@ final class P11Mac extends MacSpi { private void cancelOperation() { token.ensureValid(); - // cancel operation by finishing it; avoid killSession as some + + if (P11Util.trySessionCancel(token, session, CKF_SIGN)) { + return; + } + + // cancel by finishing operations; avoid killSession as some // hardware vendors may require re-login try { token.p11.C_SignFinal(session.id(), 0); diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11PSSSignature.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11PSSSignature.java index 88b7b9cd5e8..512bf521be7 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11PSSSignature.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11PSSSignature.java @@ -170,7 +170,7 @@ final class P11PSSSignature extends SignatureSpi { this.mechanism = new CK_MECHANISM(mechId); int idx = algorithm.indexOf("with"); // convert to stdName - this.mdAlg = (idx == -1? + this.mdAlg = (idx == -1 ? null : toStdName(algorithm.substring(0, idx))); switch ((int)mechId) { @@ -193,7 +193,7 @@ final class P11PSSSignature extends SignatureSpi { throw new NoSuchAlgorithmException("Unsupported algorithm: " + algorithm); } - this.md = (this.mdAlg == null? null : + this.md = (this.mdAlg == null ? null : MessageDigest.getInstance(this.mdAlg)); type = T_DIGEST; break; @@ -269,9 +269,16 @@ final class P11PSSSignature extends SignatureSpi { private void cancelOperation() { token.ensureValid(); + if (DEBUG) System.out.print("Cancelling operation"); - // cancel operation by finishing it; avoid killSession as some + if (P11Util.trySessionCancel(token, session, + (mode == M_SIGN ? CKF_SIGN : CKF_VERIFY))) { + if (DEBUG) System.out.println(" by C_SessionCancel"); + return; + } + + // cancel by finishing operations; avoid killSession call as some // hardware vendors may require re-login try { if (mode == M_SIGN) { @@ -280,7 +287,7 @@ final class P11PSSSignature extends SignatureSpi { token.p11.C_SignFinal(session.id(), 0); } else { byte[] digest = - (md == null? new byte[0] : md.digest()); + (md == null ? new byte[0] : md.digest()); if (DEBUG) System.out.println(" by C_Sign"); token.p11.C_Sign(session.id(), digest); } @@ -292,7 +299,7 @@ final class P11PSSSignature extends SignatureSpi { token.p11.C_VerifyFinal(session.id(), signature); } else { byte[] digest = - (md == null? new byte[0] : md.digest()); + (md == null ? new byte[0] : md.digest()); if (DEBUG) System.out.println(" by C_Verify"); token.p11.C_Verify(session.id(), digest, signature); } diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11RSACipher.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11RSACipher.java index 869b77d4a63..1506918da96 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11RSACipher.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11RSACipher.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,6 +37,7 @@ import javax.crypto.spec.*; import static sun.security.pkcs11.TemplateManager.*; import sun.security.pkcs11.wrapper.*; import static sun.security.pkcs11.wrapper.PKCS11Constants.*; +import static sun.security.pkcs11.wrapper.PKCS11Exception.RV.*; import sun.security.internal.spec.TlsRsaPremasterSecretParameterSpec; import sun.security.util.KeyUtil; @@ -266,7 +267,21 @@ final class P11RSACipher extends CipherSpi { // state variables such as "initialized" private void cancelOperation() { token.ensureValid(); - // cancel operation by finishing it; avoid killSession as some + + long flags = switch(mode) { + case MODE_ENCRYPT -> CKF_ENCRYPT; + case MODE_DECRYPT -> CKF_DECRYPT; + case MODE_SIGN -> CKF_SIGN; + case MODE_VERIFY -> CKF_VERIFY; + default -> { + throw new AssertionError("Unexpected value: " + mode); + } + }; + if (P11Util.trySessionCancel(token, session, flags)) { + return; + } + + // cancel by finishing operations; avoid killSession as some // hardware vendors may require re-login try { PKCS11 p11 = token.p11; diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Signature.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Signature.java index f18fc621d2e..c27a3f4f02e 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Signature.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Signature.java @@ -283,7 +283,13 @@ final class P11Signature extends SignatureSpi { private void cancelOperation() { token.ensureValid(); - // cancel operation by finishing it; avoid killSession as some + + if (P11Util.trySessionCancel(token, session, + (mode == M_SIGN ? CKF_SIGN : CKF_VERIFY))) { + return; + } + + // cancel by finishing operations; avoid killSession call as some // hardware vendors may require re-login try { if (mode == M_SIGN) { @@ -315,9 +321,9 @@ final class P11Signature extends SignatureSpi { } catch (PKCS11Exception e) { if (e.match(CKR_OPERATION_NOT_INITIALIZED)) { // Cancel Operation may be invoked after an error on a PKCS#11 - // call. If the operation inside the token was already cancelled, - // do not fail here. This is part of a defensive mechanism for - // PKCS#11 libraries that do not strictly follow the standard. + // call. If the operation was already cancelled, do not fail + // here. This is part of a defensive mechanism for PKCS#11 + // libraries that do not strictly follow the standard. return; } if (mode == M_VERIFY) { diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Util.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Util.java index 262cfc062ad..256c2f96568 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Util.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Util.java @@ -28,6 +28,9 @@ package sun.security.pkcs11; import java.math.BigInteger; import java.security.*; +import sun.security.pkcs11.wrapper.PKCS11Exception; +import static sun.security.pkcs11.wrapper.PKCS11Exception.RV.*; + /** * Collection of static utility methods. * @@ -187,4 +190,22 @@ public final class P11Util { return sb.toString(); } + // returns true if successfully cancelled + static boolean trySessionCancel(Token token, Session session, long flags) + throws ProviderException { + if (token.p11.getVersion().major == 3) { + try { + token.p11.C_SessionCancel(session.id(), flags); + return true; + } catch (PKCS11Exception e) { + // return false for CKR_OPERATION_CANCEL_FAILED, so callers + // can cancel in the pre v3.0 way, i.e. by finishing off the + // current operation + if (!e.match(CKR_OPERATION_CANCEL_FAILED)) { + throw new ProviderException("cancel failed", e); + } + } + } + return false; + } } diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SunPKCS11.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SunPKCS11.java index e86d54963d3..9cdbdfa9d6b 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SunPKCS11.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SunPKCS11.java @@ -150,7 +150,7 @@ public final class SunPKCS11 extends AuthProvider { this.config = c; if (debug != null) { - System.out.println("SunPKCS11 loading " + config.getFileName()); + debug.println("SunPKCS11 loading " + config.getFileName()); } String library = config.getLibrary(); @@ -176,7 +176,6 @@ public final class SunPKCS11 extends AuthProvider { // switch to using the NSS trust attributes for trusted certs // (KeyStore). // - if (useSecmod) { // note: Config ensures library/slot/slotListIndex not specified // in secmod mode. @@ -328,8 +327,7 @@ public final class SunPKCS11 extends AuthProvider { initArgs.flags = CKF_OS_LOCKING_OK; PKCS11 tmpPKCS11; try { - tmpPKCS11 = PKCS11.getInstance( - library, functionList, initArgs, + tmpPKCS11 = PKCS11.getInstance(library, functionList, initArgs, config.getOmitInitialize()); } catch (PKCS11Exception e) { if (debug != null) { @@ -345,18 +343,18 @@ public final class SunPKCS11 extends AuthProvider { } else { initArgs.flags = 0; } - tmpPKCS11 = PKCS11.getInstance(library, - functionList, initArgs, config.getOmitInitialize()); + tmpPKCS11 = PKCS11.getInstance(library, functionList, initArgs, + config.getOmitInitialize()); } p11 = tmpPKCS11; - CK_INFO p11Info = p11.C_GetInfo(); - if (p11Info.cryptokiVersion.major < 2) { + if (p11.getVersion().major < 2) { throw new ProviderException("Only PKCS#11 v2.0 and later " - + "supported, library version is v" + p11Info.cryptokiVersion); + + "supported, library version is v" + p11.getVersion()); } boolean showInfo = config.getShowInfo(); if (showInfo) { + CK_INFO p11Info = p11.C_GetInfo(); System.out.println("Information for provider " + getName()); System.out.println("Library info:"); System.out.println(p11Info); @@ -1482,12 +1480,10 @@ public final class SunPKCS11 extends AuthProvider { } // get the pin if necessary - char[] pin = null; if ((token.tokenInfo.flags & CKF_PROTECTED_AUTHENTICATION_PATH) == 0) { // get password - CallbackHandler myHandler = getCallbackHandler(handler); if (myHandler == null) { throw new LoginException @@ -1503,6 +1499,7 @@ public final class SunPKCS11 extends AuthProvider { PasswordCallback pcall = new PasswordCallback(form.format(source), false); Callback[] callbacks = { pcall }; + try { myHandler.handle(callbacks); } catch (Exception e) { @@ -1522,13 +1519,12 @@ public final class SunPKCS11 extends AuthProvider { } // perform token login - Session session = null; try { session = token.getOpSession(); - // pin is NULL if using CKF_PROTECTED_AUTHENTICATION_PATH p11.C_Login(session.id(), CKU_USER, pin); + if (debug != null) { debug.println("login succeeded"); } diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/PKCS11.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/PKCS11.java index a4c852f7abf..f87690bc24f 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/PKCS11.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/PKCS11.java @@ -110,7 +110,7 @@ public class PKCS11 { * e.g. pk2priv.dll. */ private final String pkcs11ModulePath; - + private final CK_VERSION version; private long pNativeData; /** @@ -141,13 +141,30 @@ public class PKCS11 { * path, if the driver is not in the system's search path. * * @param pkcs11ModulePath the PKCS#11 library path + * @param functionList the method name for retrieving the PKCS#11 + * function list; may be null if not set in config file * @preconditions (pkcs11ModulePath <> null) * @postconditions */ - PKCS11(String pkcs11ModulePath, String functionListName) + PKCS11(String pkcs11ModulePath, String functionList) throws IOException { - connect(pkcs11ModulePath, functionListName); + this.version = connect(pkcs11ModulePath, functionList); this.pkcs11ModulePath = pkcs11ModulePath; + // bug in native PKCS#11 lib; workaround it by calling C_GetInfo() + // and get cryptoki version from there + if (this.version.major != 2 && this.version.major != 3) { + try { + CK_INFO p11Info = C_GetInfo(); + this.version.major = p11Info.cryptokiVersion.major; + this.version.minor = p11Info.cryptokiVersion.minor; + } catch (PKCS11Exception e) { + // give up; just use what is returned by connect() + } + } + } + + public CK_VERSION getVersion() { + return version; } public static synchronized PKCS11 getInstance(String pkcs11ModulePath, @@ -186,11 +203,14 @@ public class PKCS11 { * native part. * * @param pkcs11ModulePath The PKCS#11 library path. + * @param functionList the method name for retrieving the PKCS#11 + * function list; may be null if not set in config file + * @return the actual PKCS11 interface version * @preconditions (pkcs11ModulePath <> null) * @postconditions */ - private native void connect(String pkcs11ModulePath, String functionListName) - throws IOException; + private native CK_VERSION connect(String pkcs11ModulePath, + String functionList) throws IOException; /** * Disconnects the PKCS#11 library from this object. After calling this @@ -463,6 +483,20 @@ public class PKCS11 { public native CK_SESSION_INFO C_GetSessionInfo(long hSession) throws PKCS11Exception; + /** + * C_SessionCancel terminates active session based operations. + * (Session management) (New in PKCS#11 v3.0) + * + * @param hSession the session's handle + * (PKCS#11 param: CK_SESSION_HANDLE hSession) + * @param flags indicates the operations to cancel. + * (PKCS#11 param: CK_FLAGS flags) + * @exception PKCS11Exception If function returns other value than CKR_OK. + * @preconditions + * @postconditions + */ + public native void C_SessionCancel(long hSession, long flags) + throws PKCS11Exception; /** * C_GetOperationState obtains the state of the cryptographic operation @@ -521,6 +555,24 @@ public class PKCS11 { public native void C_Login(long hSession, long userType, char[] pPin) throws PKCS11Exception; + ///** + // * C_LoginUser logs a user into a token. (New in PKCS#11 v3.0) + // * (Session management) + // * + // * @param hSession the session's handle + // * (PKCS#11 param: CK_SESSION_HANDLE hSession) + // * @param userType the user type + // * (PKCS#11 param: CK_USER_TYPE userType) + // * @param pPin the user's PIN and the length of the PIN + // * (PKCS#11 param: CK_CHAR_PTR pPin, CK_ULONG ulPinLen) + // * @param pUsername the user name and the length of the user name + // * (PKCS#11 param: CK_CHAR_PTR pUsername, CK_ULONG ulUsernameLen) + // * @exception PKCS11Exception If function returns other value than CKR_OK. + // * @preconditions + // * @postconditions + // */ + //public native void C_LoginUser(long hSession, long userType, char[] pPin, + // String pUsername) throws PKCS11Exception; /** * C_Logout logs a user out from a token. @@ -807,7 +859,6 @@ public class PKCS11 { public native int C_EncryptFinal(long hSession, long directOut, byte[] out, int outOfs, int outLen) throws PKCS11Exception; - /** * C_DecryptInit initializes a decryption operation. * (Encryption and decryption) @@ -902,8 +953,6 @@ public class PKCS11 { public native int C_DecryptFinal(long hSession, long directOut, byte[] out, int outOfs, int outLen) throws PKCS11Exception; - - /* ***************************************************************************** * Message digesting ******************************************************************************/ @@ -1624,9 +1673,9 @@ public class PKCS11 { // parent. Used for tokens that only support single threaded access static class SynchronizedPKCS11 extends PKCS11 { - SynchronizedPKCS11(String pkcs11ModulePath, String functionListName) + SynchronizedPKCS11(String pkcs11ModulePath, String functionList) throws IOException { - super(pkcs11ModulePath, functionListName); + super(pkcs11ModulePath, functionList); } synchronized void C_Initialize(Object pInitArgs) throws PKCS11Exception { @@ -1682,11 +1731,22 @@ static class SynchronizedPKCS11 extends PKCS11 { return super.C_GetSessionInfo(hSession); } - public synchronized void C_Login(long hSession, long userType, char[] pPin) + public synchronized void C_SessionCancel(long hSession, long flags) throws PKCS11Exception { + super.C_SessionCancel(hSession, flags); + } + + public synchronized void C_Login(long hSession, long userType, + char[] pPin) throws PKCS11Exception { super.C_Login(hSession, userType, pPin); } + //public synchronized void C_LoginUser(long hSession, long userType, + // char[] pPin, String pUsername) + // throws PKCS11Exception { + // super.C_LoginUser(hSession, userType, pPin, pUsername); + //} + public synchronized void C_Logout(long hSession) throws PKCS11Exception { super.C_Logout(hSession); } diff --git a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_sessmgmt.c b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_sessmgmt.c index b06d397b09e..5209c5bbf78 100644 --- a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_sessmgmt.c +++ b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_sessmgmt.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. */ /* Copyright (c) 2002 Graz University of Technology. All rights reserved. @@ -272,6 +272,33 @@ JNIEXPORT jobject JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1GetSessionI } #endif +#ifdef P11_ENABLE_C_SESSIONCANCEL +/* + * Class: sun_security_pkcs11_wrapper_PKCS11 + * Method: C_SessionCancel + * Signature: (JJ)V + * Parametermapping: *PKCS11* + * @param jlong jSessionHandle CK_SESSION_HANDLE hSession + * @param jlong jFlags CK_FLAGS flags + */ +JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1SessionCancel + (JNIEnv *env, jobject obj, jlong jSessionHandle, jlong jFlags) +{ + CK_SESSION_HANDLE ckSessionHandle; + CK_RV rv; + + CK_FUNCTION_LIST_3_0_PTR ckpFunctions30 = getFunctionList30(env, obj); + if (ckpFunctions30 == NULL) { return; } + + ckSessionHandle = jLongToCKULong(jSessionHandle); + + rv = (*ckpFunctions30->C_SessionCancel)(ckSessionHandle, + jLongToCKULong(jFlags)); + + ckAssertReturnValueOK(env, rv); +} +#endif + #ifdef P11_ENABLE_C_GETOPERATIONSTATE /* * Class: sun_security_pkcs11_wrapper_PKCS11 @@ -351,7 +378,7 @@ JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1SetOperationSt free(ckpState); - if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) { return; } + ckAssertReturnValueOK(env, rv); } #endif @@ -367,28 +394,83 @@ JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1SetOperationSt * CK_ULONG ulPinLen */ JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1Login - (JNIEnv *env, jobject obj, jlong jSessionHandle, jlong jUserType, jcharArray jPin) + (JNIEnv *env, jobject obj, jlong jSessionHandle, jlong jUserType, + jcharArray jPin) { CK_SESSION_HANDLE ckSessionHandle; CK_USER_TYPE ckUserType; CK_CHAR_PTR ckpPinArray = NULL_PTR; CK_ULONG ckPinLength; CK_RV rv; + CK_FUNCTION_LIST_PTR ckpFunctions; - CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj); - if (ckpFunctions == NULL) { return; } + ckpFunctions = getFunctionList(env, obj); + + if (ckpFunctions == NULL) { + return; + } ckSessionHandle = jLongToCKULong(jSessionHandle); ckUserType = jLongToCKULong(jUserType); jCharArrayToCKCharArray(env, jPin, &ckpPinArray, &ckPinLength); if ((*env)->ExceptionCheck(env)) { return; } - rv = (*ckpFunctions->C_Login)(ckSessionHandle, ckUserType, ckpPinArray, ckPinLength); + rv = (*ckpFunctions->C_Login)(ckSessionHandle, ckUserType, ckpPinArray, + ckPinLength); + free(ckpPinArray); + + ckAssertReturnValueOK(env, rv); +} +#endif + +#ifdef P11_ENABLE_C_LOGINUSER +/* + * Class: sun_security_pkcs11_wrapper_PKCS11 + * Method: C_LoginUser + * Signature: (JJ[C;Ljava/lang/String;)V + * Parametermapping: *PKCS11* + * @param jlong jSessionHandle CK_SESSION_HANDLE hSession + * @param jlong jUserType CK_USER_TYPE userType + * @param jcharArray jPin CK_CHAR_PTR pPin + * CK_ULONG ulPinLen + * @param jstring jUsername CK_CHAR_PTR pUsername + * CK_ULONG ulUsernameLen + */ +JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1LoginUser + (JNIEnv *env, jobject obj, jlong jSessionHandle, jlong jUserType, + jcharArray jPin, jstring jUsername) +{ + CK_SESSION_HANDLE ckSessionHandle; + CK_USER_TYPE ckUserType; + CK_CHAR_PTR ckpPinArray = NULL_PTR; + CK_ULONG ckPinLength; + CK_CHAR_PTR ckpUsername = NULL_PTR; + CK_ULONG ckUsernameLength; + CK_RV rv; + CK_FUNCTION_LIST_3_0_PTR ckpFunctions30; + + ckpFunctions30 = getFunctionList30(env, obj); + + ckSessionHandle = jLongToCKULong(jSessionHandle); + ckUserType = jLongToCKULong(jUserType); + jCharArrayToCKCharArray(env, jPin, &ckpPinArray, &ckPinLength); + if ((*env)->ExceptionCheck(env)) { return; } + jStringToCKUTF8CharArray(env, jUsername, &ckpUsername, + &ckUsernameLength); + if ((*env)->ExceptionCheck(env)) { return; } + + if (ckpFunctions30 == NULL) { + return; + } + rv = (*ckpFunctions30->C_LoginUser)(ckSessionHandle, ckUserType, + ckpPinArray, ckPinLength, ckpUsername, ckUsernameLength); free(ckpPinArray); + free(ckpUsername); - if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) { return; } + ckAssertReturnValueOK(env, rv); } + #endif #ifdef P11_ENABLE_C_LOGOUT @@ -411,7 +493,7 @@ JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1Logout ckSessionHandle = jLongToCKULong(jSessionHandle); rv = (*ckpFunctions->C_Logout)(ckSessionHandle); - if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) { return; } + ckAssertReturnValueOK(env, rv); } #endif diff --git a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_util.c b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_util.c index 520bd52a2cd..2920707a254 100644 --- a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_util.c +++ b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_util.c @@ -136,6 +136,20 @@ CK_FUNCTION_LIST_PTR getFunctionList(JNIEnv *env, jobject pkcs11Implementation) return ckpFunctions; } +CK_FUNCTION_LIST_3_0_PTR getFunctionList30(JNIEnv *env, jobject + pkcs11Implementation) { + ModuleData *moduleData; + CK_FUNCTION_LIST_3_0_PTR ckpFunctions30; + + moduleData = getModuleEntry(env, pkcs11Implementation); + if (moduleData == NULL) { + throwDisconnectedRuntimeException(env); + return NULL; + } + ckpFunctions30 = moduleData->ckFunctionList30Ptr; + return ckpFunctions30; +} + /* * Returns 1, if the given pkcs11Implementation is in the list. diff --git a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/pkcs11wrapper.h b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/pkcs11wrapper.h index eb6d01b9e47..c2b6f3d94b5 100644 --- a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/pkcs11wrapper.h +++ b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/pkcs11wrapper.h @@ -100,9 +100,11 @@ #define P11_ENABLE_C_CLOSESESSION #undef P11_ENABLE_C_CLOSEALLSESSIONS #define P11_ENABLE_C_GETSESSIONINFO +#define P11_ENABLE_C_SESSIONCANCEL #define P11_ENABLE_C_GETOPERATIONSTATE #define P11_ENABLE_C_SETOPERATIONSTATE #define P11_ENABLE_C_LOGIN +//#define P11_ENABLE_C_LOGINUSER #define P11_ENABLE_C_LOGOUT #define P11_ENABLE_C_CREATEOBJECT #define P11_ENABLE_C_COPYOBJECT @@ -209,17 +211,21 @@ //#define TRACE0d(s) { printf(s); fflush(stdout); } //#define TRACE1d(s, p1) { printf(s, p1); fflush(stdout); } //#define TRACE2d(s, p1, p2) { printf(s, p1, p2); fflush(stdout); } +//#define TRACE3d(s, p1, p2, p3) { printf(s, p1, p2, p3); fflush(stdout); } +//#define TRACE4d(s, p1, p2, p3, p4) { printf(s, p1, p2, p3, p4); fflush(stdout); } #ifdef P11_DEBUG #define TRACE0(s) { printf(s); fflush(stdout); } #define TRACE1(s, p1) { printf(s, p1); fflush(stdout); } #define TRACE2(s, p1, p2) { printf(s, p1, p2); fflush(stdout); } #define TRACE3(s, p1, p2, p3) { printf(s, p1, p2, p3); fflush(stdout); } +#define TRACE4(s, p1, p2, p3, p4) { printf(s, p1, p2, p3, p4); fflush(stdout); } #else #define TRACE0(s) #define TRACE1(s, p1) #define TRACE2(s, p1, p2) #define TRACE3(s, p1, p2, p3) +#define TRACE4(s, p1, p2, p3, p4) #define TRACE_INTEND #define TRACE_UNINTEND #endif @@ -412,6 +418,8 @@ CK_RV callJUnlockMutex(CK_VOID_PTR pMutex); void putModuleEntry(JNIEnv *env, jobject pkcs11Implementation, ModuleData *moduleData); ModuleData * removeModuleEntry(JNIEnv *env, jobject pkcs11Implementation); CK_FUNCTION_LIST_PTR getFunctionList(JNIEnv *env, jobject pkcs11Implementation); +CK_FUNCTION_LIST_3_0_PTR getFunctionList30(JNIEnv *env, jobject + pkcs11Implementation); /* A structure to encapsulate the required data for a Notify callback */ struct NotifyEncapsulation { diff --git a/src/jdk.crypto.cryptoki/unix/native/libj2pkcs11/p11_md.c b/src/jdk.crypto.cryptoki/unix/native/libj2pkcs11/p11_md.c index 0105a9873b5..6cae296e8d4 100644 --- a/src/jdk.crypto.cryptoki/unix/native/libj2pkcs11/p11_md.c +++ b/src/jdk.crypto.cryptoki/unix/native/libj2pkcs11/p11_md.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. */ /* Copyright (c) 2002 Graz University of Technology. All rights reserved. @@ -72,26 +72,34 @@ /* * Class: sun_security_pkcs11_wrapper_PKCS11 * Method: connect - * Signature: (Ljava/lang/String;)V + * Signature: (Ljava/lang/String;)Lsun/security/pkcs11/wrapper/CK_VERSION; */ -JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_connect - (JNIEnv *env, jobject obj, jstring jPkcs11ModulePath, jstring jGetFunctionList) -{ +JNIEXPORT jobject JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_connect + (JNIEnv *env, jobject obj, jstring jPkcs11ModulePath, + jstring jGetFunctionList) { + void *hModule; char *error; - CK_C_GetFunctionList C_GetFunctionList=NULL; + int i; + CK_ULONG ulCount = 0; + CK_C_GetInterfaceList C_GetInterfaceList = NULL; + CK_INTERFACE_PTR iList = NULL; + CK_C_GetInterface C_GetInterface = NULL; + CK_INTERFACE_PTR interface = NULL; + CK_C_GetFunctionList C_GetFunctionList = NULL; CK_RV rv; - ModuleData *moduleData; + ModuleData *moduleData = NULL; jobject globalPKCS11ImplementationReference; char *systemErrorMessage; char *exceptionMessage; - const char *getFunctionListStr; + const char *getFunctionListStr = NULL; - const char *libraryNameStr = (*env)->GetStringUTFChars(env, jPkcs11ModulePath, 0); + const char *libraryNameStr = (*env)->GetStringUTFChars(env, + jPkcs11ModulePath, 0); if (libraryNameStr == NULL) { - return; + return NULL; } - TRACE1("DEBUG: connect to PKCS#11 module: %s ... ", libraryNameStr); + TRACE1("Connect: connect to PKCS#11 module: %s ... ", libraryNameStr); /* * Load the PKCS #11 DLL @@ -108,39 +116,92 @@ JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_connect exceptionMessage = (char *) malloc(sizeof(char) * (strlen(systemErrorMessage) + strlen(libraryNameStr) + 1)); if (exceptionMessage == NULL) { throwOutOfMemoryError(env, 0); - (*env)->ReleaseStringUTFChars(env, jPkcs11ModulePath, libraryNameStr); - return; + goto cleanup; } strcpy(exceptionMessage, systemErrorMessage); strcat(exceptionMessage, libraryNameStr); throwIOException(env, exceptionMessage); - (*env)->ReleaseStringUTFChars(env, jPkcs11ModulePath, libraryNameStr); free(exceptionMessage); - return; + goto cleanup; } - (*env)->ReleaseStringUTFChars(env, jPkcs11ModulePath, libraryNameStr); - /* - * Get function pointer to C_GetFunctionList - */ - dlerror(); /* clear any old error message not fetched */ - // with the old JAR file jGetFunctionList is null, temporarily check for that + // clear any old error message not fetched + dlerror(); + +#ifdef DEBUG + C_GetInterfaceList = (CK_C_GetInterfaceList) dlsym(hModule, + "C_GetInterfaceList"); + if (C_GetInterfaceList != NULL) { + TRACE0("Connect: Found C_GetInterfaceList func\n"); + rv = (C_GetInterfaceList)(NULL, &ulCount); + if (rv == CKR_OK) { + TRACE1("Connect: interface list size %ld \n", ulCount); + // retrieve available interfaces and report their info + iList = (CK_INTERFACE_PTR) + malloc(ulCount*sizeof(CK_INTERFACE)); + rv = C_GetInterfaceList(iList, &ulCount); + if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) { + TRACE0("Connect: error polling interface list\n"); + goto cleanup; + } + for (i=0; i < (int)ulCount; i++) { + TRACE4("Connect: name %s, version %d.%d, flags 0x%lX\n", + iList[i].pInterfaceName, + ((CK_VERSION *)iList[i].pFunctionList)->major, + ((CK_VERSION *)iList[i].pFunctionList)->minor, + iList[i].flags); + } + } else { + TRACE0("Connect: error polling interface list size\n"); + } + } else { + TRACE0("Connect: No C_GetInterfaceList func\n"); + } +#endif + if (jGetFunctionList != NULL) { - getFunctionListStr = (*env)->GetStringUTFChars(env, jGetFunctionList, 0); + getFunctionListStr = (*env)->GetStringUTFChars(env, + jGetFunctionList, 0); if (getFunctionListStr == NULL) { - return; + goto cleanup; } - C_GetFunctionList = (CK_C_GetFunctionList) dlsym(hModule, getFunctionListStr); - (*env)->ReleaseStringUTFChars(env, jGetFunctionList, getFunctionListStr); - } - if (C_GetFunctionList == NULL) { - throwIOException(env, "ERROR: C_GetFunctionList == NULL"); - return; - } else if ( (systemErrorMessage = dlerror()) != NULL ){ - throwIOException(env, systemErrorMessage); - return; + C_GetFunctionList = (CK_C_GetFunctionList) dlsym(hModule, + getFunctionListStr); + if ((systemErrorMessage = dlerror()) != NULL){ + throwIOException(env, systemErrorMessage); + goto cleanup; + } + if (C_GetFunctionList == NULL) { + TRACE1("Connect: No %s func\n", getFunctionListStr); + throwIOException(env, "ERROR: C_GetFunctionList == NULL"); + goto cleanup; + } + TRACE1("Connect: Found %s func\n", getFunctionListStr); + } else { + // if none specified, then we try 3.0 API first before trying 2.40 + C_GetInterface = (CK_C_GetInterface) dlsym(hModule, "C_GetInterface"); + if ((C_GetInterface != NULL) && (dlerror() == NULL)) { + TRACE0("Connect: Found C_GetInterface func\n"); + rv = (C_GetInterface)(NULL, NULL, &interface, 0L); + if (ckAssertReturnValueOK(env, rv) == CK_ASSERT_OK) { + goto setModuleData; + } + } + C_GetFunctionList = (CK_C_GetFunctionList) dlsym(hModule, + "C_GetFunctionList"); + if ((systemErrorMessage = dlerror()) != NULL){ + throwIOException(env, systemErrorMessage); + goto cleanup; + } + if (C_GetFunctionList == NULL) { + TRACE0("Connect: No C_GetFunctionList func\n"); + throwIOException(env, "ERROR: C_GetFunctionList == NULL"); + goto cleanup; + } + TRACE0("Connect: Found C_GetFunctionList func\n"); } +setModuleData: /* * Get function pointers to all PKCS #11 functions */ @@ -148,19 +209,56 @@ JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_connect if (moduleData == NULL) { dlclose(hModule); throwOutOfMemoryError(env, 0); - return; + goto cleanup; } moduleData->hModule = hModule; moduleData->applicationMutexHandler = NULL; - rv = (C_GetFunctionList)(&(moduleData->ckFunctionListPtr)); + if (C_GetFunctionList != NULL) { + rv = (C_GetFunctionList)(&(moduleData->ckFunctionListPtr)); + if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) { + goto cleanup; + } + } else if (interface != NULL) { + moduleData->ckFunctionListPtr = interface->pFunctionList; + if (((CK_VERSION *)moduleData->ckFunctionListPtr)->major == 3) { + moduleData->ckFunctionList30Ptr = interface->pFunctionList; + } + } else { + // should never happen + throwIOException(env, "ERROR: No function list ptr found"); + goto cleanup; + } + if (((CK_VERSION *)moduleData->ckFunctionListPtr)->major == 3) { + moduleData->ckFunctionList30Ptr = interface->pFunctionList; + } else { + moduleData->ckFunctionList30Ptr = NULL; + } + + TRACE2("Connect: FunctionListPtr version = %d.%d\n", + ((CK_VERSION *)moduleData->ckFunctionListPtr)->major, + ((CK_VERSION *)moduleData->ckFunctionListPtr)->minor); + globalPKCS11ImplementationReference = (*env)->NewGlobalRef(env, obj); putModuleEntry(env, globalPKCS11ImplementationReference, moduleData); - TRACE0("FINISHED\n"); - - if(ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) { return; } +cleanup: + if (jPkcs11ModulePath != NULL && libraryNameStr != NULL) { + (*env)->ReleaseStringUTFChars(env, jPkcs11ModulePath, libraryNameStr); + } + if (jGetFunctionList != NULL && getFunctionListStr != NULL) { + (*env)->ReleaseStringUTFChars(env, jGetFunctionList, + getFunctionListStr); + } + TRACE0("Connect: FINISHED\n"); + if (moduleData != NULL) { + return ckVersionPtrToJVersion(env, + (CK_VERSION *)moduleData->ckFunctionListPtr); + } else { + return NULL; + } } + /* * Class: sun_security_pkcs11_wrapper_PKCS11 * Method: disconnect diff --git a/src/jdk.crypto.cryptoki/unix/native/libj2pkcs11/p11_md.h b/src/jdk.crypto.cryptoki/unix/native/libj2pkcs11/p11_md.h index 0d8cb363374..676e3ab5d4c 100644 --- a/src/jdk.crypto.cryptoki/unix/native/libj2pkcs11/p11_md.h +++ b/src/jdk.crypto.cryptoki/unix/native/libj2pkcs11/p11_md.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. */ /* @@ -83,8 +83,9 @@ struct ModuleData { /* the module (DLL or shared library) handle */ void *hModule; - /* The pointer to the PKCS#11 functions of this module. */ + /* The pointers to the PKCS#11 functions of this module. */ CK_FUNCTION_LIST_PTR ckFunctionListPtr; + CK_FUNCTION_LIST_3_0_PTR ckFunctionList30Ptr; /* Reference to the object to use for mutex handling. NULL, if not used. */ jobject applicationMutexHandler; diff --git a/src/jdk.crypto.cryptoki/windows/native/libj2pkcs11/p11_md.c b/src/jdk.crypto.cryptoki/windows/native/libj2pkcs11/p11_md.c index 145ad7f5693..ea005664dff 100644 --- a/src/jdk.crypto.cryptoki/windows/native/libj2pkcs11/p11_md.c +++ b/src/jdk.crypto.cryptoki/windows/native/libj2pkcs11/p11_md.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. */ /* Copyright (c) 2002 Graz University of Technology. All rights reserved. @@ -72,16 +72,22 @@ /* * Class: sun_security_pkcs11_wrapper_PKCS11 * Method: connect - * Signature: (Ljava/lang/String;)V + * Signature: (Ljava/lang/String;)Lsun/security/pkcs11/wrapper/CK_VERSION; */ -JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_connect +JNIEXPORT jobject JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_connect (JNIEnv *env, jobject obj, jstring jPkcs11ModulePath, - jstring jGetFunctionList) + jstring jGetFunctionList) { HINSTANCE hModule; - CK_C_GetFunctionList C_GetFunctionList; + int i = 0; + CK_ULONG ulCount = 0; + CK_C_GetInterfaceList C_GetInterfaceList = NULL; + CK_INTERFACE_PTR iList = NULL; + CK_C_GetInterface C_GetInterface = NULL; + CK_INTERFACE_PTR interface = NULL; + CK_C_GetFunctionList C_GetFunctionList = NULL; CK_RV rv = CK_ASSERT_OK; - ModuleData *moduleData; + ModuleData *moduleData = NULL; jobject globalPKCS11ImplementationReference; LPVOID lpMsgBuf = NULL; char *exceptionMessage = NULL; @@ -91,10 +97,9 @@ JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_connect jPkcs11ModulePath, 0); TRACE1("DEBUG: connect to PKCS#11 module: %s ... ", libraryNameStr); - - /* - * Load the PKCS #11 DLL - */ + /* + * Load the PKCS #11 DLL + */ hModule = LoadLibrary(libraryNameStr); if (hModule == NULL) { FormatMessage( @@ -120,29 +125,93 @@ JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_connect goto cleanup; } +#ifdef DEBUG /* - * Get function pointer to C_GetFunctionList + * Get function pointer to C_GetInterfaceList */ - getFunctionListStr = (*env)->GetStringUTFChars(env, jGetFunctionList, 0); - C_GetFunctionList = (CK_C_GetFunctionList) GetProcAddress(hModule, - getFunctionListStr); - (*env)->ReleaseStringUTFChars(env, jGetFunctionList, getFunctionListStr); - if (C_GetFunctionList == NULL) { - FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - GetLastError(), - 0, /* Default language */ - (LPTSTR) &lpMsgBuf, - 0, - NULL - ); - throwIOException(env, (LPTSTR) lpMsgBuf); - goto cleanup; + C_GetInterfaceList = (CK_C_GetInterfaceList) GetProcAddress(hModule, + "C_GetInterfaceList"); + if (C_GetInterfaceList != NULL) { + TRACE0("Found C_GetInterfaceList func\n"); + rv = (C_GetInterfaceList)(NULL, &ulCount); + if (rv == CKR_OK) { + /* get copy of interfaces */ + iList = (CK_INTERFACE_PTR) + malloc(ulCount*sizeof(CK_INTERFACE)); + rv = C_GetInterfaceList(iList, &ulCount); + for (i=0; i < (int)ulCount; i++) { + printf("interface %s version %d.%d funcs %p flags 0x%lu\n", + iList[i].pInterfaceName, + ((CK_VERSION *)iList[i].pFunctionList)->major, + ((CK_VERSION *)iList[i].pFunctionList)->minor, + iList[i].pFunctionList, iList[i].flags); + } + } else { + TRACE0("Connect: error polling interface list size\n"); + } + } else { + TRACE0("Connect: No C_GetInterfaceList func\n"); + } +#endif + + if (jGetFunctionList != NULL) { + getFunctionListStr = (*env)->GetStringUTFChars(env, + jGetFunctionList, 0); + if (getFunctionListStr == NULL) { + goto cleanup; + } + C_GetFunctionList = (CK_C_GetFunctionList) GetProcAddress(hModule, + getFunctionListStr); + if (C_GetFunctionList == NULL) { + TRACE1("Connect: No %s func\n", getFunctionListStr); + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + GetLastError(), + 0, /* Default language */ + (LPTSTR) &lpMsgBuf, + 0, + NULL + ); + throwIOException(env, (LPTSTR) lpMsgBuf); + goto cleanup; + } + TRACE1("Connect: Found %s func\n", getFunctionListStr); + } else { + // if none specified, then we try 3.0 API first before trying 2.40 + C_GetInterface = (CK_C_GetInterface) GetProcAddress(hModule, + "C_GetInterface"); + if (C_GetInterface != NULL) { + TRACE0("Connect: Found C_GetInterface func\n"); + rv = (C_GetInterface)(NULL, NULL, &interface, 0); + if (ckAssertReturnValueOK(env, rv) == CK_ASSERT_OK) { + goto setModuleData; + } + } + C_GetFunctionList = (CK_C_GetFunctionList) GetProcAddress(hModule, + "C_GetFunctionList"); + if (C_GetFunctionList == NULL) { + TRACE0("Connect: No C_GetFunctionList func\n"); + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + GetLastError(), + 0, /* Default language */ + (LPTSTR) &lpMsgBuf, + 0, + NULL + ); + throwIOException(env, (LPTSTR) lpMsgBuf); + goto cleanup; + } + TRACE0("Connect: Found C_GetFunctionList func\n"); } +setModuleData: /* * Get function pointers to all PKCS #11 functions */ @@ -153,12 +222,31 @@ JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_connect } moduleData->hModule = hModule; moduleData->applicationMutexHandler = NULL; - rv = (C_GetFunctionList)(&(moduleData->ckFunctionListPtr)); + if (C_GetFunctionList != NULL) { + rv = (C_GetFunctionList)(&(moduleData->ckFunctionListPtr)); + if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) { + goto cleanup; + } + } else if (interface != NULL) { + moduleData->ckFunctionListPtr = interface->pFunctionList; + } else { + // should never happen + throwIOException(env, "ERROR: No function list ptr found"); + goto cleanup; + } + if (((CK_VERSION *)moduleData->ckFunctionListPtr)->major == 3) { + moduleData->ckFunctionList30Ptr = interface->pFunctionList; + } else { + moduleData->ckFunctionList30Ptr = NULL; + } + + TRACE2("Connect: FunctionListPtr version = %d.%d\n", + ((CK_VERSION *)moduleData->ckFunctionListPtr)->major, + ((CK_VERSION *)moduleData->ckFunctionListPtr)->minor); + globalPKCS11ImplementationReference = (*env)->NewGlobalRef(env, obj); putModuleEntry(env, globalPKCS11ImplementationReference, moduleData); - TRACE0("FINISHED\n"); - cleanup: /* Free up allocated buffers we no longer need */ if (lpMsgBuf != NULL) { @@ -167,11 +255,21 @@ cleanup: if (libraryNameStr != NULL) { (*env)->ReleaseStringUTFChars(env, jPkcs11ModulePath, libraryNameStr); } + if (jGetFunctionList != NULL && getFunctionListStr != NULL) { + (*env)->ReleaseStringUTFChars(env, jGetFunctionList, + getFunctionListStr); + } if (exceptionMessage != NULL) { free(exceptionMessage); } + TRACE0("Connect: FINISHED\n"); + if (moduleData != NULL) { + return ckVersionPtrToJVersion(env, + (CK_VERSION *)moduleData->ckFunctionListPtr); + } else { + return NULL; + } - if(ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) { return; } } /* diff --git a/src/jdk.crypto.cryptoki/windows/native/libj2pkcs11/p11_md.h b/src/jdk.crypto.cryptoki/windows/native/libj2pkcs11/p11_md.h index 7cff0c7c249..0a069d5bc97 100644 --- a/src/jdk.crypto.cryptoki/windows/native/libj2pkcs11/p11_md.h +++ b/src/jdk.crypto.cryptoki/windows/native/libj2pkcs11/p11_md.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. */ /* @@ -93,8 +93,9 @@ struct ModuleData { HINSTANCE hModule; - /* The pointer to the PKCS#11 functions of this module. */ + /* The pointers to the PKCS#11 functions of this module. */ CK_FUNCTION_LIST_PTR ckFunctionListPtr; + CK_FUNCTION_LIST_3_0_PTR ckFunctionList30Ptr; /* Reference to the object to use for mutex handling. NULL, if not used. */ jobject applicationMutexHandler; -- GitLab From 352435581e4354741684d66df8a33b1fbdb96162 Mon Sep 17 00:00:00 2001 From: Zhiqiang Zang Date: Thu, 9 Dec 2021 00:18:59 +0000 Subject: [PATCH 076/671] 8277882: New subnode ideal optimization: converting "c0 - (x + c1)" into "(c0 - c1) - x" Reviewed-by: dlong, iveresov --- src/hotspot/share/opto/subnode.cpp | 44 ++++-- .../c2/TestSubIdealC0Minus_YPlusC1_.java | 133 ++++++++++++++++++ .../vm/compiler/SubIdealC0Minus_YPlusC1_.java | 110 +++++++++++++++ 3 files changed, 272 insertions(+), 15 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/c2/TestSubIdealC0Minus_YPlusC1_.java create mode 100644 test/micro/org/openjdk/bench/vm/compiler/SubIdealC0Minus_YPlusC1_.java diff --git a/src/hotspot/share/opto/subnode.cpp b/src/hotspot/share/opto/subnode.cpp index 5956b1738f1..48d9473f439 100644 --- a/src/hotspot/share/opto/subnode.cpp +++ b/src/hotspot/share/opto/subnode.cpp @@ -196,16 +196,23 @@ Node *SubINode::Ideal(PhaseGVN *phase, bool can_reshape){ } } - - // Convert "x - (y+c0)" into "(x-y) - c0" + // Convert "x - (y+c0)" into "(x-y) - c0" AND + // Convert "c1 - (y+c0)" into "(c1-c0) - y" // Need the same check as in above optimization but reversed. - if (op2 == Op_AddI && ok_to_convert(in2, in1)) { + if (op2 == Op_AddI + && ok_to_convert(in2, in1) + && in2->in(2)->Opcode() == Op_ConI) { + jint c0 = phase->type(in2->in(2))->isa_int()->get_con(); Node* in21 = in2->in(1); - Node* in22 = in2->in(2); - const TypeInt* tcon = phase->type(in22)->isa_int(); - if (tcon != NULL && tcon->is_con()) { - Node* sub2 = phase->transform( new SubINode(in1, in21) ); - Node* neg_c0 = phase->intcon(- tcon->get_con()); + if (in1->Opcode() == Op_ConI) { + // Match c1 + jint c1 = phase->type(in1)->isa_int()->get_con(); + Node* sub2 = phase->intcon(java_subtract(c1, c0)); + return new SubINode(sub2, in21); + } else { + // Match x + Node* sub2 = phase->transform(new SubINode(in1, in21)); + Node* neg_c0 = phase->intcon(-c0); return new AddINode(sub2, neg_c0); } } @@ -374,15 +381,22 @@ Node *SubLNode::Ideal(PhaseGVN *phase, bool can_reshape) { } } - // Convert "x - (y+c0)" into "(x-y) - c0" + // Convert "x - (y+c0)" into "(x-y) - c0" AND + // Convert "c1 - (y+c0)" into "(c1-c0) - y" // Need the same check as in above optimization but reversed. - if (op2 == Op_AddL && ok_to_convert(in2, in1)) { + if (op2 == Op_AddL + && ok_to_convert(in2, in1) + && in2->in(2)->Opcode() == Op_ConL) { + jlong c0 = phase->type(in2->in(2))->isa_long()->get_con(); Node* in21 = in2->in(1); - Node* in22 = in2->in(2); - const TypeLong* tcon = phase->type(in22)->isa_long(); - if (tcon != NULL && tcon->is_con()) { - Node* sub2 = phase->transform( new SubLNode(in1, in21) ); - Node* neg_c0 = phase->longcon(- tcon->get_con()); + if (in1->Opcode() == Op_ConL) { + // Match c1 + jlong c1 = phase->type(in1)->isa_long()->get_con(); + Node* sub2 = phase->longcon(java_subtract(c1, c0)); + return new SubLNode(sub2, in21); + } else { + Node* sub2 = phase->transform(new SubLNode(in1, in21)); + Node* neg_c0 = phase->longcon(-c0); return new AddLNode(sub2, neg_c0); } } diff --git a/test/hotspot/jtreg/compiler/c2/TestSubIdealC0Minus_YPlusC1_.java b/test/hotspot/jtreg/compiler/c2/TestSubIdealC0Minus_YPlusC1_.java new file mode 100644 index 00000000000..b623e1a2393 --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/TestSubIdealC0Minus_YPlusC1_.java @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2021, 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. + */ + +/* + * @test + * @bug 8277882 + * @summary New subnode ideal optimization: converting "c0 - (x + c1)" into "(c0 - c1) - x" + * @library /test/lib + * @run main/othervm -XX:-TieredCompilation -Xbatch + * -XX:CompileCommand=dontinline,compiler.c2.TestSubIdealC0Minus_YPlusC1_::test* + * -XX:CompileCommand=compileonly,compiler.c2.TestSubIdealC0Minus_YPlusC1_::test* + * compiler.c2.TestSubIdealC0Minus_YPlusC1_ + */ +package compiler.c2; + +import jdk.test.lib.Asserts; + +public class TestSubIdealC0Minus_YPlusC1_ { + + private static final int I_C0_0 = 1234; + private static final int I_C1 = 1234; + private static final int I_C0_1 = 4321; + + private static final long L_C0_0 = 123_456_789_123L; + private static final long L_C1 = 123_456_789_123L; + private static final long L_C0_1 = 654_321; + + public static int testIC0EqualsC1(int x) { + return I_C0_0 - (x + I_C1); + } + + public static long testLC0EqualsC1(long x) { + return L_C0_0 - (x + L_C1); + } + + public static int testIC0NotEqualsC1(int x) { + return I_C0_1 - (x + I_C1); + } + + public static long testLC0NotEqualsC1(long x) { + return L_C0_1 - (x + L_C1); + } + + public static int testIXPlusC1IsOverflow(int x) { + return Integer.MAX_VALUE - (x + Integer.MAX_VALUE); + } + + public static long testLXPlusC1IsOverflow(long x) { + return Long.MAX_VALUE - (x + Long.MAX_VALUE); + } + + public static int testIXPlusC1IsUnderflow(int x) { + return Integer.MIN_VALUE - (x + Integer.MIN_VALUE); + } + + public static long testLXPlusC1IsUnderflow(long x) { + return Long.MIN_VALUE - (x + Long.MIN_VALUE); + } + + public static int testIC0MinusC1IsOverflow(int x) { + return Integer.MAX_VALUE - (x + Integer.MIN_VALUE); + } + + public static long testLC0MinusC1IsOverflow(long x) { + return Long.MAX_VALUE - (x + Long.MIN_VALUE); + } + + public static int testIC0MinusC1IsUnderflow(int x) { + return Integer.MIN_VALUE - (x + Integer.MAX_VALUE); + } + + public static long testLC0MinusC1IsUnderflow(long x) { + return Long.MIN_VALUE - (x + Long.MAX_VALUE); + } + + public static int testIResultIsOverflow(int x) { + return 2147483637 - (x + 10); // Integer.MAX_VALUE == 2147483647 + } + + public static long testLResultIsOverflow(long x) { + return 9223372036854775797L - (x + 10); // Long.MAX_VALUE == 9223372036854775807 + } + + public static int testIResultIsUnderflow(int x) { + return -2147483637 - (x + 10); // Integer.MIN_VALUE == -2147483648 + } + + public static long testLResultIsUnderflow(long x) { + return -9223372036854775797L - (x + 10); // Long.MIN_VALUE == -9223372036854775808 + } + + public static void main(String... args) { + for (int i = 0; i < 50_000; i++) { + Asserts.assertTrue(testIC0EqualsC1(10) == -10); + Asserts.assertTrue(testIC0NotEqualsC1(100) == 2987); + Asserts.assertTrue(testIXPlusC1IsOverflow(10) == -10); + Asserts.assertTrue(testIXPlusC1IsUnderflow(-10) == 10); + Asserts.assertTrue(testIC0MinusC1IsOverflow(10) == -11); + Asserts.assertTrue(testIC0MinusC1IsUnderflow(10) == -9); + Asserts.assertTrue(testIResultIsOverflow(-21) == Integer.MIN_VALUE); + Asserts.assertTrue(testIResultIsUnderflow(2) == Integer.MAX_VALUE); + + Asserts.assertTrue(testLC0EqualsC1(10) == -10); + Asserts.assertTrue(testLC0NotEqualsC1(100) == -123456134902L); + Asserts.assertTrue(testLXPlusC1IsOverflow(10) == -10); + Asserts.assertTrue(testLXPlusC1IsUnderflow(-10) == 10); + Asserts.assertTrue(testLC0MinusC1IsOverflow(10) == -11); + Asserts.assertTrue(testLC0MinusC1IsUnderflow(10) == -9); + Asserts.assertTrue(testLResultIsOverflow(-21) == Long.MIN_VALUE); + Asserts.assertTrue(testLResultIsUnderflow(2) == Long.MAX_VALUE); + } + } +} diff --git a/test/micro/org/openjdk/bench/vm/compiler/SubIdealC0Minus_YPlusC1_.java b/test/micro/org/openjdk/bench/vm/compiler/SubIdealC0Minus_YPlusC1_.java new file mode 100644 index 00000000000..17728f6bc25 --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/compiler/SubIdealC0Minus_YPlusC1_.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2021, 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. + */ + +package org.openjdk.bench.vm.compiler; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.infra.Blackhole; + +import java.util.concurrent.TimeUnit; + +/** + * Tests transformation that converts "c0 - (x + c1)" into "(c0 - c1) + * - x" in SubINode::Ideal and SubLNode::Ideal. + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@State(Scope.Thread) +@Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS) +@Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS) +@Fork(value = 3 , jvmArgsAppend = {"-XX:-TieredCompilation", "-Xbatch", "-Xcomp"}) +public class SubIdealC0Minus_YPlusC1_ { + + private static final int I_C0 = 1234567; + + private static final int I_C1 = 1234567; + + private static final long L_C0 = 123_456_789_123_456L; + + private static final long L_C1 = 123_456_789_123_456L; + + private final int size = 100_000_000; + + private int[] ints_a; + + private long[] longs_a; + + @Setup + public void init() { + ints_a = new int[size]; + longs_a = new long[size]; + for (int i = 0; i < size; i++) { + ints_a[i] = i; + longs_a[i] = i * i; + } + } + + @Benchmark + public void baseline() { + for (int i = 0; i < size; i++) { + sink(ints_a[i]); + sink(longs_a[i]); + } + } + + @Benchmark + public void test() { + for (int i = 0; i < size; i++) { + sink(helper(ints_a[i])); + sink(helper(longs_a[i])); + } + } + + // Convert "c0 - (x + c1)" into "(c0 - c1) - x" for int. + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private static int helper(int x) { + return I_C0 - (x + I_C1); + } + + // Convert "c0 - (x + c1)" into "(c0 - c1) - x" for long. + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private static long helper(long x) { + return L_C0 - (x + L_C1); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private static void sink(int v) {} + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private static void sink(long v) {} +} -- GitLab From 8ef1a232b100dbac72356ca4844d01964f3d5287 Mon Sep 17 00:00:00 2001 From: Alexey Semenyuk Date: Thu, 9 Dec 2021 02:31:29 +0000 Subject: [PATCH 077/671] 8278311: Debian packaging doesn't work Reviewed-by: almatvee --- .../internal/OverridableResource.java | 32 +++++++++++++++++-- .../internal/OverridableResourceTest.java | 8 ++--- 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/OverridableResource.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/OverridableResource.java index 9680691bc5d..c455ef71500 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/OverridableResource.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/OverridableResource.java @@ -36,6 +36,8 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardCopyOption; import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -279,11 +281,35 @@ final class OverridableResource { private static Stream substitute(Stream lines, Map substitutionData) { + // Order substitution data by the length of keys. + // Longer keys go first. + // This is needed to properly handle cases when one key is + // a subtring of another and try the later first. + var orderedEntries = substitutionData.entrySet().stream() + .sorted(Map.Entry.comparingByKey( + Comparator.comparingInt(String::length)).reversed()) + .toList(); return lines.map(line -> { String result = line; - for (var entry : substitutionData.entrySet()) { - result = result.replace(entry.getKey(), Optional.ofNullable( - entry.getValue()).orElse("")); + var workEntries = orderedEntries; + var it = workEntries.listIterator(); + while (it.hasNext()) { + var entry = it.next(); + String newResult = result.replace(entry.getKey(), + Optional.ofNullable(entry.getValue()).orElse("")); + if (!newResult.equals(result)) { + // Substitution occured. + // Remove the matching substitution key from the list and + // go over the list of substitution entries again. + if (workEntries == orderedEntries) { + workEntries = new ArrayList<>(orderedEntries); + it = workEntries.listIterator(it.nextIndex() - 1); + it.next(); + } + it.remove(); + it = workEntries.listIterator(); + result = newResult; + } } return result; }); diff --git a/test/jdk/tools/jpackage/junit/jdk/jpackage/internal/OverridableResourceTest.java b/test/jdk/tools/jpackage/junit/jdk/jpackage/internal/OverridableResourceTest.java index 55a3c22dc9a..7b00a60acf0 100644 --- a/test/jdk/tools/jpackage/junit/jdk/jpackage/internal/OverridableResourceTest.java +++ b/test/jdk/tools/jpackage/junit/jdk/jpackage/internal/OverridableResourceTest.java @@ -136,16 +136,16 @@ public class OverridableResourceTest { } private void testCustomtWithSubstitution(String defaultName) throws IOException { - final List resourceData = List.of("A", "[BB]", "C", "Foo", - "GoodbyeHello"); + final List resourceData = List.of("A", "[BB]", "C", "Foo", "Foo", + "GoodbyeHello", "_B"); final Path customFile = createCustomFile("foo", resourceData); final Map substitutionData = new HashMap(Map.of("B", - "Bar", "Foo", "B")); + "Bar", "Foo", "B", "_B", "JJ")); substitutionData.put("Hello", null); final List expectedResourceData = List.of("A", "[BarBar]", "C", - "B", "Goodbye"); + "Bar", "Bar", "Goodbye", "JJ"); final List actualResourceData = convertToStringList(saveToFile( new OverridableResource(defaultName) -- GitLab From d1706828fb6a95ecad2bab4112b2e1a7d3319df8 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Thu, 9 Dec 2021 02:53:52 +0000 Subject: [PATCH 078/671] 8278466: "spurious markup" warnings in snippets when building `docs-reference` Reviewed-by: darcy --- .../share/classes/javax/tools/JavaFileManager.java | 2 +- .../share/classes/javax/tools/StandardJavaFileManager.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/java.compiler/share/classes/javax/tools/JavaFileManager.java b/src/java.compiler/share/classes/javax/tools/JavaFileManager.java index 20178303b2f..1fe510e809d 100644 --- a/src/java.compiler/share/classes/javax/tools/JavaFileManager.java +++ b/src/java.compiler/share/classes/javax/tools/JavaFileManager.java @@ -82,7 +82,7 @@ import static javax.tools.JavaFileObject.Kind; * section 3.3. Informally, this should be true: * * {@snippet id="valid-relative-name" lang=java : - * // @link substring="create" target="URI#create" : @link substring=normalize target="URI#normalize" : @link substring=getPath target="URI#getPath" : + * // @link substring="create" target="URI#create" @link substring=normalize target="URI#normalize" @link substring=getPath target="URI#getPath" : * URI.create(relativeName).normalize().getPath().equals(relativeName) * } * diff --git a/src/java.compiler/share/classes/javax/tools/StandardJavaFileManager.java b/src/java.compiler/share/classes/javax/tools/StandardJavaFileManager.java index 936cb0aeacc..be2b0cb4cd5 100644 --- a/src/java.compiler/share/classes/javax/tools/StandardJavaFileManager.java +++ b/src/java.compiler/share/classes/javax/tools/StandardJavaFileManager.java @@ -76,7 +76,7 @@ import java.util.List; * must succeed if the following would succeed (ignoring * encoding issues): * {@snippet id="equiv-input" lang=java : - * // @link substring=FileInputStream target="java.io.FileInputStream#FileInputStream(File)" : @link regex="File\W" target="File#File(java.net.URI)" : @link substring=fileObject target=FileObject : @link substring=toURI target="FileObject#toUri()" : + * // @link substring=FileInputStream target="java.io.FileInputStream#FileInputStream(File)" @link regex="File\b" target="File#File(java.net.URI)" @link substring=fileObject target=FileObject @link substring=toURI target="FileObject#toUri()" : * new FileInputStream(new File(fileObject.toURI())) * } * @@ -87,7 +87,7 @@ import java.util.List; * succeed if the following would succeed (ignoring encoding * issues): * {@snippet id="equiv-output" lang=java : - * // @link substring=FileOutputStream target="java.io.FileOutputStream#FileOutputStream(File)" : @link regex="File\W" target="File#File(java.net.URI)" : @link substring=fileObject target=FileObject : @link substring=toURI target="FileObject#toUri()" : + * // @link substring=FileOutputStream target="java.io.FileOutputStream#FileOutputStream(File)" @link regex="File\b" target="File#File(java.net.URI)" @link substring=fileObject target=FileObject @link substring=toURI target="FileObject#toUri()" : * new FileOutputStream(new File(fileObject.toURI())) * } * -- GitLab From 62a7f5d3236ab2248518a475b1d8b71cb4bf1313 Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Thu, 9 Dec 2021 06:50:56 +0000 Subject: [PATCH 079/671] 8254318: Remove .hgtags Reviewed-by: erikj, xliu --- .hgtags | 664 -------------------------------------------------------- 1 file changed, 664 deletions(-) delete mode 100644 .hgtags diff --git a/.hgtags b/.hgtags deleted file mode 100644 index ef4ec35e2f2..00000000000 --- a/.hgtags +++ /dev/null @@ -1,664 +0,0 @@ -3cc80be736f24704e505ad8ddaa598dec3fa2ed3 jdk-9+181 -e2b70be325bd10dae4c06f74c46d70d480854916 jdk-9+179 -5b16a1c3ccffff2a82c88bb7ea894c4ff1c9ebde jdk-9+180 -43bf6f30fcba031ecf0cc7e511efe3a8179d0f77 jdk-9+176 -d9f6bc6ba599d0487dc18b2fbdb6c34eedf6f958 jdk-9+177 -bc9df7dd63ec76f50fafeb4acc44465044662f0a jdk-9+178 -994036e74ab805bcc09afa0646be17a725bec42f jdk-9+175 -94680c6d60ecd9ed3ffd1847706efde7eb947afc jdk-9+174 -6dd7fda42bab7ecf648cafb0a4e9b4ca11b3094f jdk-9+173 -dad6746278facbbea57dd462cb56fb743dc0a5f0 jdk-9+172 -643b5f18c2656fe91b69fea85b07b98d5fad394d jdk-9+171 -898cbe31fbdae2d25d141384fac746cc244a730c jdk-9+170 -c7efde2b60fc1ec04630be769d9ad60efb39c39c jdk-9+169 -8fd0a4569191f33c98ee90c2709174a342fefb0d jdk-9+167 -fcabc74bd44e56c7419d111d59b95669ecb33c55 jdk-9+168 -d3e973f1809606c67412361041ad197e50fe8cec jdk-9+166 -3965b747cfe1e6cbd66b8739da5a1ea6ec6985e9 jdk-9+165 -d16aebbb56d37f12e0c0b0a4fb427db65e1fb1a8 jdk-9+162 -18c41483a082e097ac2f5f983c1226ed94aa4215 jdk-9+163 -32db52c675e7d5bc413605d2e89b68b608b19be0 jdk-9+164 -fd1497902bbe3aa24b21f270ecdcb8de5f7aa9ac jdk-9+159 -6aa8be0c4e054fe8b3ab016ae00d16d680f92145 jdk-9+160 -f6883b1a5a6478437cd4181c4bd45328ab24feaf jdk-9+161 -fa3e76b477829afc4476f0b725cfaa440a6fd917 jdk-9+157 -b5015f742ba648184bb7fc547197bd33ebfde30d jdk-9+158 -1cc8dd79fd1cd13d36b385196271a29632c67c3b jdk7-b24 -bf2517e15f0c0f950e5b3143c4ca11e2df73dcc1 jdk7-b25 -5ae7db536e3fcf6be78e45b240a9058095e0ed38 jdk7-b26 -67052ac87fc927d048e62ec54ff42adb230d3f7c jdk7-b27 -18dc4ba4739a537fd146f77da51db16efce28da2 jdk7-b28 -bfe4572fd301a6fcd120373cdb2eff5d2da0c72c jdk7-b29 -bee4731164a06ddece1297ae58db24aca6a1c626 jdk7-b30 -cd8b8f500face60d1566d850857a7fccadbd383a jdk7-b31 -a9f1805e3ba9ca520cad199d522c84af5433e85a jdk7-b32 -6838c1a3296aaa3572364d2ce7d70826cee96286 jdk7-b33 -90cf935adb353bb0af4b46fb0677e841fd24c000 jdk7-b34 -6d909d5803e3a22850e6c4e5a75b888742ee7e20 jdk7-b35 -d718a441936196b93d8bc9f084933af9a4c2a350 jdk7-b36 -c2036bf76829c03b99108fffab52e20910a9be4f jdk7-b37 -a2879b2837f5a4c87e9542efe69ef138194af8ff jdk7-b38 -126f365cec6c3c2c72de934fa1c64b5f082b55b5 jdk7-b39 -3c53424bbe3bb77e01b468b4b0140deec33e11fc jdk7-b40 -3cb2a607c347934f8e7e86f840a094c28b08d9ea jdk7-b41 -caf58ffa084568990cbb3441f9ae188e36b31770 jdk7-b42 -41bd0a702bc8ec6feebd725a63e7c3227f82ab11 jdk7-b43 -5843778bda89b1d5ac8e1aa05e26930ac90b3145 jdk7-b44 -54dffad0bf066791a2793305875250c395011d5f jdk7-b45 -04b2620edc72de93671646e4720c5992c74ac8b5 jdk7-b46 -0c4657194eec95c08ba478aee9cfc3c295e41657 jdk7-b47 -1bf51a4c2627c2f0e0cbcc2cf0421bdb37f1f2b2 jdk7-b48 -6b84b04a80afe23262377c60913eebfc898f14c4 jdk7-b49 -5da0e6b9f4f18ef483c977337214b12ee0e1fc8f jdk7-b50 -a25c5ec5e40e07733d1ff9898a0abe36159288ff jdk7-b51 -7a90e89e36d103038f8667f6a7daae34ecfa1ad8 jdk7-b52 -d52186ee770dac57950536cd00ccbfdef360b04c jdk7-b53 -15096652c4d48dfb9fc0b2cb135304db94c65ba0 jdk7-b54 -c8b275d62d6b0a980c510e839b70292245863e85 jdk7-b55 -a8134c4ee2cf451cf9b5e1609f39d83ecd53acc5 jdk7-b56 -b44f05654c26fcd1f995e712992f9b07ffd7c0c6 jdk7-b57 -d60a9ce3c3eabf28f5d50ae839d18be04a551bc2 jdk7-b58 -c33e7d38c9210741dbc285507403a4b20bd802a0 jdk7-b59 -5a10e4d0b14d7beac53a7b2213ae6864afe1fd3e jdk7-b60 -dbb955b1ee59b876dd1f133952b557b48b1d7732 jdk7-b61 -6107cbff3130c747d243c25a7874cd59db5744a8 jdk7-b62 -dfd8506f74c3731bb169ce93c72612d78ee0413b jdk7-b63 -d22867c5f1b295a0a2b3b4bc8999a2676f6e20c3 jdk7-b64 -7d3bf00f3cc4f8125de1842521e7567f37dc84b8 jdk7-b65 -62109d1b9e7310f29ab51ca6f1d71b899c0ce6b0 jdk7-b66 -eb24af1404aec8aa140c4cd4d13d2839b150dd41 jdk7-b67 -bca2225b66d78c4bf4d9801f54cac7715a598650 jdk7-b68 -1b662b1ed14eb4ae31d5138a36c433b13d941dc5 jdk7-b69 -207f694795c448c17753eff1a2f50363106960c2 jdk7-b70 -c5d39b6be65cba0effb5f466ea48fe43764d0e0c jdk7-b71 -df4bcd06e1d0ab306efa5a44f24a409dc0c0c742 jdk7-b72 -ce74bd35ce948d629a356e168797f44b593b1578 jdk7-b73 -4e7661eaa211e186674f6cbefec4aef1144ac2a0 jdk7-b74 -946518568340c4e511549318f19f47f06b7f5f9b jdk7-b75 -09e0b33177af2b98a03c9ca19eedf61440bd1cf6 jdk7-b76 -1d0121b741f029dc4b828e4b36ba6fda92907dd7 jdk7-b77 -4061c66ba1af1a2e27c2c839ba887407dd3ce050 jdk7-b78 -e9c98378f6b9256c0595ef2985ca5899f0c0e274 jdk7-b79 -e6abd38682d237306d6c147c17538ec9e7f8e3a7 jdk7-b80 -dcc938ac40cc45f1ef454d76020b5db5d943001c jdk7-b81 -a30062be6d9ca1d48579826f870f85974300004e jdk7-b82 -34c8199936a1682aa8587857f44cfaf37c2b6381 jdk7-b83 -b1e55627a6980b9508854ed0c0f21d4f981b4494 jdk7-b84 -b6f633a93ae0ec4555ff4bf756f5e2150c9bdede jdk7-b85 -c94d9cc81f495d97817eba9d71b84fc45f7661a5 jdk7-b86 -b7456c473862048fa70ed8092313a4ef0a55d403 jdk7-b87 -7077b95d42f6b3942a8751bba033801ff50e5889 jdk7-b88 -44158f6d3b94c0fa020e33632532473d92d1ea96 jdk7-b89 -1d1927f9ec097b62c913921e2dfa5dbaf5dc325b jdk7-b90 -308ad8f68b8dd68e22d73dd490e110059b732422 jdk7-b91 -ff9031a745d9cc52318f2148e43ca3b07ee08098 jdk7-b92 -b5dab6a313fdff4c043250e4d9c8f66fd624d27e jdk7-b93 -8bb281f0f91582104d65d032be22522bfd2d8110 jdk7-b94 -654298d26561b76dfe3cfcffbbd7078080837300 jdk7-b95 -d260f892491e040ae385a8e6df59557a7d721abf jdk7-b96 -7e406ebed9a5968b584f3c3e6b60893b5d6d9741 jdk7-b97 -db6e660120446c407e2d908d52ec046592b21726 jdk7-b98 -c4c8a5bc54f66abc68cd185d9294042121922154 jdk7-b99 -2d6ba7a221915bdf0311acc5641c7f3875cb793e jdk7-b100 -2548ac036b8fca3326d058d758e6df8355a42469 jdk7-b101 -88db80c8e49cea352c2900f689600dc410761c1f jdk7-b102 -64770970865839b0443066370e7d476ef47e90cd jdk7-b103 -10bc903a228d3a8efdf46fb8c3fcf82a59b88bc5 jdk7-b104 -1ce7938efb03224ccc8b3cdd7803eb39e889539c jdk7-b105 -6bdae472f77205046703b685eff2ac4f7a0ecf4e jdk7-b106 -439de530aac531a360beedba6e2fe51e17292cc0 jdk7-b107 -044d31b99ef5609389fc771c422e722e5e224228 jdk7-b108 -e02b4d709e177d08d56130a4bc68061e4bbacc7d jdk7-b109 -a6442d6bc38a44152e0662688213ce4d2701f42a jdk7-b110 -69f3edf083477955b5bd2f754252c7504167d8e1 jdk7-b111 -f960f117f1623629f64203e2b09a92a8f6f14ff5 jdk7-b112 -1fee41c7ed2b3388970a756a85aa693c0de8407a jdk7-b113 -750c1ccb2f2d1ddfa95ab6c7f897fdab2f87f7e9 jdk7-b114 -9cb24917216bc68997154f6e9566c3de62acb2f4 jdk7-b115 -a4e6aa1f45ad23a6f083ed98d970b5006ea4d292 jdk7-b116 -228e73f288c543a8c34e2a54227103ae5649e6af jdk7-b117 -2e876e59938a853934aa738c811b26c452bd9fe8 jdk7-b118 -4951967a61b4dbbf514828879f57bd1a0d4b420b jdk7-b119 -8c840d3ab24f8d0f422b991638acb44b6ab1d98c jdk7-b120 -0ce0a2c3a6926677dc507839a820ab6625541e5a jdk7-b121 -6f09ea1c034f087916d2a8cf0d22be768400118f jdk7-b122 -142129d8599d1f56b29387e7f9a5fad53b6d61df jdk7-b123 -aa894c225b1a517b665ac2a58295217ea2245134 jdk7-b124 -f658ec2730fa29323c36d23c27e54c7219ef5e16 jdk7-b125 -f1df068076986679ea1105532a65529d63a89060 jdk7-b126 -f83cd8bd35c678f94e526990e03dc838d0ec2717 jdk7-b127 -7da3f5f30855dec6bf3a86529e87dee883b90c72 jdk7-b128 -6823ea7eb8eb6fab405d7edb7a5c2f690887a2fa jdk7-b129 -a36beda9b9de91231d92a2c529f21cc218fcf8d5 jdk7-b130 -d8af56da89bc0fc02a6b6ad78f51157a46d665ab jdk7-b131 -d61280d36755d1941fb487f554e8b7a6d0bca6a1 jdk7-b132 -fd444c61e7ed3d92b2a730da7c737b02191b682f jdk7-b133 -def8e16dd237a47fc067d66d4c616d7baaec6001 jdk7-b134 -f75a1efb141210901aabe00a834e0fc32bb8b337 jdk7-b135 -46acf76a533954cfd594bb88fdea79938abfbe20 jdk7-b136 -d1cf7d4ee16c341f5b8c7e7f1d68a8c412b6c693 jdk7-b137 -62b8e328f8c8c66c14b0713222116f2add473f3f jdk7-b138 -955488f34ca418f6cdab843d61c20d2c615637d9 jdk7-b139 -f4298bc3f4b6baa315643be06966f09684290068 jdk7-b140 -5d86d0c7692e8f4a58d430d68c03594e2d3403b3 jdk7-b141 -92bf0655022d4187e9b49c1400f98fb3392a4630 jdk7-b142 -4a05062d8c4dfa3edec3faf1052af28baba5adff jdk7-b143 -07a8728ad49ef6dfa469c3a8bf5ab1e9c80bed5c jdk7-b144 -8294c99e685a1f6d1d37c45cd97854cf74be771e jdk7-b145 -dca1e8a87e8f756f95b99bac8fe795750d42e1b0 jdk7-b146 -a2a589fc29543ed32919c78a1810ad93a6fcf5bc jdk7-b147 -de9223c94f9c710b3eebb599cd3586f36c8b94a9 jdk8-b01 -1b9d19620eb4606a25b1e28f86d66c8bfa867e06 jdk8-b02 -6815e85bf96d6d3875954f9777660372cd70d065 jdk8-b03 -31f5c34d78081572ad9a2401c0bb0c6b9711dd65 jdk8-b04 -c4f9ea1ecb55ff44e0dd21d2888ead308c86a3aa jdk8-b05 -429da7734bf491bccde2a752fae97e9f225896dc jdk8-b06 -bc5710332b294676661103bb20d47d2ea3ba8def jdk8-b07 -24ee504f80412770c6874836cd9e55b536427b1d jdk8-b08 -fbf3cabc9e3bb1fcf710941d777cb0400505fbe6 jdk8-b09 -f651ce87127980c58e3599daba964eba2f3b4026 jdk8-b10 -cc1f5ce8e504d350e0b0c28c5f84333f8d540132 jdk8-b11 -86db042b3385c338e17f7664447fdc7d406dd19e jdk8-b12 -4cc0ef72c812943743ef4765f1100e2fbe2b1a08 jdk8-b13 -9ffaa48dbfb0f5936c2b789867d0785faec7071d jdk8-b14 -b5060eae3b32fd9f884a09774338cd8186d7fafa jdk8-b15 -736a63b854f321c7824b7e47890135f80aee05e3 jdk8-b16 -f0eccb2946986fb9626efde7d8ed9c8192623f5c jdk8-b17 -885050364691ac1ac978305c63f3368a197fb04d jdk8-b18 -0ff7113a0882ec82d642cb9f0297b4e497807ced jdk8-b19 -6561530ea757c3f3a6fb171c9cc7b3885cdeca85 jdk8-b20 -b3a426170188f52981cf4573a2f14d487fddab0d jdk8-b21 -e8f03541af27e38aafb619b96863e17f65ffe53b jdk8-b22 -498124337041ad53cbaa7eb110f3d7acd6d4eac4 jdk8-b23 -7d3720d8c595d1519c31e9ff7366203fc2c61350 jdk8-b24 -0071a6d64113a35ba345bb1580c256de5ce17d3e jdk8-b25 -6c805d8ed4e5449ea5e4d158c7bdbd7b0b70efd1 jdk8-b26 -c51754cddc037b9609e202b9ed38363d8683e7a8 jdk8-b27 -16ba58282d117247f480aae7a79b88141ade52a3 jdk8-b28 -e070119aa56ee4dc5506c19d2c4d2eecab8ad429 jdk8-b29 -23da7804aca0c9c4e6e86532a1453125a76d95ee jdk8-b30 -bac81e9f7d57b75fba5ab31b571f3fe0dc08af69 jdk8-b31 -2c5208ccb863db936eab523f49450b3fcd230348 jdk8-b32 -a6e6d42203e6d35f9e8b31eac25b0021b4dd58ad jdk8-b33 -0ae89825c75c9492e44efb3aca3d9ee3d8a209df jdk8-b34 -f151d5833912a82cd4f203944da0305c3be83ecc jdk8-b35 -98ce9816ae089c959ba1e70fba98423a31c4e9fa jdk8-b36 -b3a91113026c99b0da010d41055719ab0d8938f0 jdk8-b37 -4cc5610a6dd6227da766ebf9742eb11ff5ded6c0 jdk8-b38 -35a5397278779a2f8f3013f81586dc8f30cb149d jdk8-b39 -6e4e654931b976304bf6e7b4d0d6db8f75bac5d9 jdk8-b40 -c029c972396cea042a0dc67c0f7ccf2fe68007d4 jdk8-b41 -5c5a64ec0839df5affe9394b99ff338c363acbca jdk8-b42 -69d8a827cdf9236be9694a46d75c710d71dac7d7 jdk8-b43 -7e981cb0ad6a194f1fa859f9ad47586db461f269 jdk8-b44 -9b19b2302c28f4da6d4078f66234abecfed5688a jdk8-b45 -600c9a1feb01633cbcf2341a43d1d21e6497ecd0 jdk8-b46 -b820143a6f1ce993c6e6f31db4d64de990f42654 jdk8-b47 -086271e35b0a419b38e8bda9bebd70693811df0a jdk8-b48 -cecd7026f30cbd83b0601925a7a5e059aec98138 jdk8-b49 -38fe5ab028908cf64dd73a43336ba3211577bfc3 jdk8-b50 -382651d28f2502d371eca751962232c0e535e57a jdk8-b51 -b67041a6cb508da18d2f5c7687e6a31e08bea4fc jdk8-b52 -c7aa5cca1c01689a7b1a92411daf83684af05a33 jdk8-b53 -7c6aa31ff1b2ae48c1c686ebe1aadf0c3da5be15 jdk8-b54 -319f583f66db47395fa86127dd3ddb729eb7c64f jdk8-b55 -ffe6bce5a521be40146af2ac03c509b7bac30595 jdk8-b56 -2c21c080b11b93efb3851e39e1363e45da805943 jdk8-b57 -479d3302a26d7607ba271d66973e59ebf58825b6 jdk8-b58 -3bd874584fc01aae92fbc8827e2bd04d8b6ace04 jdk8-b59 -5e3adc681779037a2d33b7be6f75680619085492 jdk8-b60 -cdaa6122185f9bf512dcd6600f56bfccc4824e8c jdk8-b61 -8d9d430b4244b95f5cf1ebe719f834a1ac5d6cd5 jdk8-b62 -21ee1dd7b809639284900a128b9b656a592ebc7a jdk8-b63 -70fa4b11f26522e69b51fd652215f60ce350bac3 jdk8-b64 -a2cf4d4a484378caea2e827ed604b2bbae58bdba jdk8-b65 -17820b958ae84f7c1cc6719319c8e2232f7a4f1d jdk8-b66 -76cc9bd3ece407d3a15d3bea537b57927973c5e7 jdk8-b67 -cb33628d4e8f11e879c371959e5948b66a53376f jdk8-b68 -adb5171c554e14cd86f618b5584f6e3d693d5889 jdk8-b69 -0d625373c69e2ad6f546fd88ab50c6c9aad01271 jdk8-b70 -a41ada2ed4ef735449531c6ebe6cec593d890a1c jdk8-b71 -6725b3961f987cf40f446d1c11cd324a3bec545f jdk8-b72 -fe94b40ffd9390f6cffcdf51c0389b0e6dde0c13 jdk8-b73 -f627eff819628822a0777af8062244352f2a29cf jdk8-b74 -f1478a6d25fddd311a84dcbfac50824cc1858bdd jdk8-b75 -f407160c280d1c5b00d314c535441ac26f195fee jdk8-b76 -d17eb2e13e362085e866d46235314c50cc4661cc jdk8-b77 -6d3dcd34b5b962ea1ef9eed0dafdee9e812401bc jdk8-b78 -a1313a8d90d17d363a3b2a645dc4030ec204b168 jdk8-b79 -3fa21fbf9be7e6b482af43aacb6a09acfa30bdb6 jdk8-b80 -e41d716405b209d3eddef8bd4240cec2bd34dcca jdk8-b81 -5e8c55025644730385a6f8fa029ecdb2d2c98a07 jdk8-b82 -bcebd3fdefc91abb9d7fa0c5af6211b3f8720da6 jdk8-b83 -d7ad0dfaa41151bd3a9ae46725b0aec3730a9cd0 jdk8-b84 -1872c12529090e1c1dbf567f02ad7ae6231b8f0c jdk8-b85 -da9a4c9312816451884aa6db6f18be51a07bff13 jdk8-b86 -5ebf6c63714de2c9dcf831074086d31daec819df jdk8-b87 -e517701a4d0e25ae9c7945bca6e1762a8c5d8aa6 jdk8-b88 -4dec41b3c5e3bb616f0c6f15830d940905aa5d16 jdk8-b89 -f09ab0c416185e3cba371e81bcb6a16060c90f44 jdk8-b90 -80b6c3172dc2cfceb022411292d290a967f9c728 jdk8-b91 -2fd6acba737b01e705e1f7c33588c922a3787f13 jdk8-b92 -b72ae39e1329fefae50d4690db4fde43f3841a95 jdk8-b93 -0d804e3b955dce406af6a79ac1cc35c696aff7fb jdk8-b94 -49fe9c8049132647ad38837a877dd473e6c9b0e5 jdk8-b95 -ea73f01b9053e7165e7ba80f242bafecbc6af712 jdk8-b96 -0a85476a0b9cb876d5666d45097dac68bef3fce1 jdk8-b97 -711eb4aa87de68de78250e0549980936bab53d54 jdk8-b98 -2d3875b0d18b3ad1c2bebf385a697e309e4005a4 jdk8-b99 -3d34036aae4ea90b2ca59712d5a69db3221f0875 jdk8-b100 -edb01c460d4cab21ff0ff13512df7b746efaa0e7 jdk8-b101 -bbe43d712fe08e650808d774861b256ccb34e500 jdk8-b102 -30a1d677a20c6a95f98043d8f20ce570304e3818 jdk8-b103 -b5ed503c26ad38869c247c5e32debec217fd056b jdk8-b104 -589f4fdc584e373a47cde0162e9eceec9165c381 jdk8-b105 -514b0b69fb9683ef52062fd962a3e0644431f64d jdk8-b106 -892889f445755790ae90e61775bfb59ddc6182b5 jdk8-b107 -74049f7a28b48c14910106a75d9f2504169c352e jdk8-b108 -af9a674e12a16da1a4bd53e4990ddb1121a21ef1 jdk8-b109 -b5d2bf482a3ea1cca08c994512804ffbc73de0a1 jdk8-b110 -b9a0f6c693f347a6f4b9bb994957f4eaa05bdedd jdk8-b111 -ad67c34f79c28a8e755f4a49f313868619d6702c jdk8-b112 -4a4dbcf7cb7d3e1a81beaa3b11cd909f69ebc79a jdk8-b113 -dfa34ab293faad9b543a24646dbb381bc3ab5586 jdk8-b114 -3dd9732b17034f45d111996d1d50287b05a3998c jdk8-b115 -aaf663f591aba43ec942263b15ba62759ce26a1e jdk8-b116 -31b0e03fcad73d7886b306b4c2e57ad270780d0d jdk8-b117 -f5b521ade7a35cea18df78ee86322207729f5611 jdk8-b118 -87b743b2263cc53955266411b7797b365a0fb050 jdk8-b119 -a1ee9743f4ee165eae59389a020f2552f895dac8 jdk8-b120 -13b877757b0b1c0d5813298df85364f41d7ba6fe jdk9-b00 -f130ca87de6637acae7d99fcd7a8573eea1cbaed jdk9-b01 -b32e2219736e42baaf45daf0ad67ed34f6033799 jdk9-b02 -7f655f31f9bcee618cf832f08176ad8c1ed3fdd3 jdk9-b03 -099891b1d86f3719e116ac717ffdafc90d037fb7 jdk9-b04 -dd311791ad6895a3989020dd6c6c46db87972ab8 jdk9-b05 -85dbdc227c5e11429b4fc4a8ba763f50107edd6e jdk9-b06 -c826d05f1fb0773f6a28caa763307dd30d90d36e jdk9-b07 -b47e021195757f8f45582124ea7cad48ccf5f872 jdk9-b08 -efe7dbc6088691757404e0c8745f894e3ca9c022 jdk9-b09 -8c0bdeecd7c0f9ce3f3762a51991f755cb3a972c jdk9-b10 -0809c9a4d36e6291f1c4384604c4bbf29e975722 jdk9-b11 -0d1f816217dce5e72187f167cc1816080cbeb453 jdk9-b12 -1a30593dcb9802faec3b6edb24d86ca088594e4e jdk9-b13 -97932f6ad950ae5a73a9da5c96e6e58503ff646b jdk9-b14 -74eb0778e4f2dbff6628e718378449fba27c4265 jdk9-b15 -4a09f5d30be844ac6f714bdb0f63d8c3c08b9a98 jdk9-b16 -410bccbded9e9cce80f1e13ad221e37ae97a3986 jdk9-b17 -c5495e25c7258ab5f96a1ae14610887d76d2be63 jdk9-b18 -2dcf544eb7ed5ac6a3f7813a32e33acea7442405 jdk9-b19 -89731ae72a761afdf4262e8b9513f302f6563f89 jdk9-b20 -28dd0c7beb3cad9cf95f17b4b5ad87eb447a4084 jdk9-b21 -9678e0db8ff6ed845d4c2ee4a3baf7f386a777e5 jdk9-b22 -39cfdc2dcaf3f195c55398e4e677ab053b07e3d2 jdk9-b23 -d9ce05f36ffec3e5e8af62a92455c1c66a63c320 jdk9-b24 -13a5c76976fe48e55c9727c25fae2d2ce7c05da0 jdk9-b25 -cd6f4557e7fea5799ff3762ed7a80a743e75d5fd jdk9-b26 -d06a6d3c66c08293b2a9650f3cc01fd55c620e65 jdk9-b27 -f4269e8f454eb77763ecee228a88ae102a9aef6e jdk9-b28 -c36c0092693707a8255561433647e8c3cd724ccd jdk9-b29 -b2287cac7813c70ed7f679d9a46fe774bd4005f8 jdk9-b30 -9d0e6639a4d71b63507dd94b1a028e963b27e798 jdk9-b31 -1b1ec4291abc0ba6da7bf79b754f08dd759a4a0c jdk9-b32 -f0c5e4b732da823bdaa4184133675f384e7cd68d jdk9-b33 -9618201c5df28a460631577fad1f61e96f775c34 jdk9-b34 -a137992d750c72f6f944f341aa19b0d0d96afe0c jdk9-b35 -41df50e7303daf73c0d661ef601c4fe250915de5 jdk9-b36 -b409bc51bc23cfd51f2bd04ea919ec83535af9d0 jdk9-b37 -948cceef81ba4cb34bc233e7cc5952951ff04e88 jdk9-b38 -4e7c4d692e934cb9023af8201e7c2b510e9c4ee1 jdk9-b39 -82f4cb44b2d7af2352f48568a64b7b6a5ae960cd jdk9-b40 -9fffb959eb4197ff806e4ac12244761815b4deee jdk9-b41 -3107be2ba9c6e208a0b86bc7100a141abbc5b5fb jdk9-b42 -6494b13f88a867026ee316b444d9a4fa589dd6bd jdk9-b43 -abbfccd659b91a7bb815d5e36fed635dcdd40f31 jdk9-b44 -bfc24ae2b900187585079bb11e66e459d1e525fe jdk9-b45 -722378bc599e38d9a1dd484de30f10dfd7b21438 jdk9-b46 -8327024a99559982b848e9c2191da9c0bf8838fd jdk9-b47 -b2f9702efbe95527ea3a991474fda23987ff1c5c jdk9-b48 -5b8db585a33c3cc48e70e688ceee57dd9271dc5d jdk9-b49 -1550b2f6b63d1411fa84dc7bbc6f04809aedb43f jdk9-b50 -6efe265424e3f1ea596408a1f71baf2de316c772 jdk9-b51 -d6224d6021459ac8b3832e822f5acc849fa944af jdk9-b52 -874d76e4699dfcd61ae1826c9fe0ddc1610ad598 jdk9-b53 -82cd31c5d6ca8d4c1653f4eb1c09eb2d9a3b2813 jdk9-b54 -c97e2d1bad9708d379793ba2a4c848eda14c741e jdk9-b55 -47544495db2d3d2edf0f85862d8715592fdb919f jdk9-b56 -ddb95d8f169b09544cc17e72a6baaff2400092f5 jdk9-b57 -f40752db7773ca0c737f2ad88371e35c57fdfed7 jdk9-b58 -da950f343762a856d69751570a4c07cfa68a415b jdk9-b59 -38f98cb6b33562a926ec3b79c7b34128be37647d jdk9-b60 -ac3f5a39d4ff14d70c365e12cf5ec8f2abd52a04 jdk9-b61 -e7dbbef69d12b6a74dfad331b7188e7f893e8d29 jdk9-b62 -989253a902c34dcb7564695161c9200a5fbb7412 jdk9-b63 -8ffdeabc7c2b9a8280bf46cae026ac46b4d31c26 jdk9-b64 -4915246064b2f89d5f00c96e758686b7fdad36a6 jdk9-b65 -ff3fc75f3214ad7e03595be1b0d0f38d887b6f0e jdk9-b66 -56166ce66037952fa21e9f680b31bf8eb47312c0 jdk9-b67 -5b500c93ce4822d47061cd518ff3f72d9d8cb5b5 jdk9-b68 -d69c968463f0ae5d0b45de3fc14fe65171b23948 jdk9-b69 -43d0179ee9de3bfffae3417f09e07eb6d8efc963 jdk9-b70 -f66c185284727f6e6ffd27e9c45ed2dd9da0a691 jdk9-b71 -61d2d0629b6dbf4c091dc86151ade1b3ef34fffe jdk9-b72 -9b3a9d72f07b40c648de79961679f42283af1bb5 jdk9-b73 -7c577fda1855d03c04546694d514678f596508c9 jdk9-b74 -f55df5cfe11c97e4b58998b76f5bd00a73cde12d jdk9-b75 -eeea9adfd1e3d075ef82148c00a4847a1aab4d26 jdk9-b76 -c25e882cee9622ec75c4e9d60633539a2f0a8809 jdk9-b77 -c8753d0be1778944dc512ec86a459941ea1ad2c3 jdk9-b78 -3966bd3b8167419aa05c6718a4af1cf54b1e3c58 jdk9-b79 -3c9f5bd909ae7187f24622ee4b69f8a5756a9271 jdk9-b80 -2050b3a0aadcb0e024bf798197421d58e54ec8bf jdk9-b81 -6521875cb63e1d0121b30af56ebbc36db078c4c6 jdk9-b82 -f61a63b7d1e52e307abc0bfc751203155d362ec4 jdk9-b83 -51b2db2fa04c16d767b66113dbf08c5349ce382a jdk9-b84 -8392405ab038b22e69a3728e17dbdd9e3d3a22ed jdk9-b85 -7db0663a5e968059fa7c772172187ebd60b6492d jdk9-b86 -1a52a30674cd28c24d4d388150336121f2e9ddf9 jdk9-b87 -16b4968f9bb8f34371b42c0ba483d76e91ba84d8 jdk9-b88 -4a0312f2894bcbe1fd20266c8fda8d983bd2fcf6 jdk9-b89 -d131f4b8433a79408f935eff9bf92a0664229b60 jdk9-b90 -8077fd2f055d31e50b46fcf62d9c035bc385a215 jdk9-b91 -f242d4332f563648426a1b0fa02d8741beba19ef jdk9-b92 -09206c6513b300e1ac8541f3be012e1a49312104 jdk9-b93 -25a2cab05cfbe6034b71d9e72d64c65b0572ce63 jdk9-b94 -5ac6287ec71aafe021cc839d8bc828108d23aaba jdk-9+95 -139f19d70350238e15e107945cea75082b6380b3 jdk-9+96 -4edcff1b9a8875eb6380a2165dfec599e8e3f7c0 jdk-9+97 -d00ad2d9049ac60815f70bff445e95df85648bd2 jdk-9+98 -f9bcdce2df26678c3fe468130b535c0342c69b89 jdk-9+99 -4379223f8806626852c46c52d4e7a27a584b406e jdk-9+100 -80f67512daa15cf37b4825c1c62a675d524d7c49 jdk-9+101 -2dc4c11fe48831854916d53c3913bdb7d49023ea jdk-9+102 -4a652e4ca9523422149958673033e0ac740d5e1e jdk-9+103 -086c682bd8c5f195c324f61e2c61fbcd0226d63b jdk-9+104 -db483b34fa7148d257a429acddbde9c13687dcae jdk-9+105 -6c644cca3f3fc2763e2ff7d669849a75d34543ba jdk-9+106 -1c076468bf7dad5b8f2ee5dcf66e2279caa3e208 jdk-9+107 -257b579d813201682931d6b42f0445ffe5b4210d jdk-9+108 -c870cb782aca71093d2584376f27f0cfbfec0e3a jdk-9+109 -4a95f4b1bd8bfce85dc02a593896749feab96c34 jdk-9+110 -a6614ff7bf09da74be1d0ef3d9755090d244697a jdk-9+111 -7359994942f8d8e723b584d66a3a92c2e9e95e5c jdk-9+112 -6072af7a98be3922f26bdce71b53bb3646cb2ac9 jdk-9+113 -c84d0cce090e161d736de69e941830adf8c2f87a jdk-9+114 -8d78fb40648dd221ce4ef19f9d5aa41ee1a3a884 jdk-9+115 -84aba7335005a3a47751dcf1f37935f97df9f99a jdk-9+116 -82b8d12a553f5617737c238cec060281d52e351c jdk-9+117 -7c04fcb12bd4a31570a238e663fa846dfa5ec3b8 jdk-9+118 -caf97b37ebec84288c112d21d3a60cb628cba1e8 jdk-9+119 -9330543436402b8f3bd070524846a464d8143557 jdk-9+120 -18e5cdecb37a2f03ba74f6c8f022858bcbaacf56 jdk-9+121 -7693aa00e131493ceb42b93305e2f014c9922a3b jdk-9+122 -d53037a90c441cb528dc41c30827985de0e67c62 jdk-9+123 -2a5697a98620c4f40e4a1a71478464399b8878de jdk-9+124 -3aa52182b3ad7c5b3a61cf05a59dd07e4c5884e5 jdk-9+125 -03e7b2c5ae345be3caf981d76ceb3efe5ff447f8 jdk-9+126 -8e45018bde9de4ad15b972ae62874bba52dba2d5 jdk-9+127 -5bf88dce615f6804f9e101a96ffa7c9dfb4fbbbe jdk-9+128 -e8373543a3f0f60589b7d72b1f9b172721124caf jdk-9+129 -e613affb88d178dc7c589f1679db113d589bddb4 jdk-9+130 -4d2a15091124488080d65848b704e25599b2aaeb jdk-9+131 -2e83d21d78cd9c1d52e6cd2599e9c8aa36ea1f52 jdk-9+132 -e17429a7e843c4a4ed3651458d0f950970edcbcc jdk-9+133 -a71210c0d9800eb6925b61ecd6198abd554f90ee jdk-9+134 -e384420383a5b79fa0012ebcb25d8f83cff7f777 jdk-9+135 -1b4b5d01aa11edf24b6fadbe3d2f3e411e3b02cd jdk-9+136 -9cb87c88ed851c0575b8ead753ea238ed5b544e9 jdk-9+137 -d273dfe9a126d3bffe92072547fef2cd1361b0eb jdk-9+138 -65477538bec32963dc41153d89c4417eb46c45fc jdk-9+139 -0875007901f7d364a08220b052f0c81003e9c8c5 jdk-9+140 -9aadd2163b568d76f8969ad2fb404a63733da359 jdk-9+141 -df0e03e3ca0ed1307793017dfc1a054c8726131c jdk-9+142 -d62173b931bf5b6bffc6e80a9060bb2e8b8efc75 jdk-9+143 -31f5023200d42185b70c4c00ba5672391e4642d0 jdk-9+144 -3ee4e7827413fa5c5c4fca58597b0ad89e921bfb jdk-9+145 -581331db696a62dd411926ba7fd437252252a71d jdk-9+146 -f4e854a77aa38749bd90f722b06974a56e7233d5 jdk-9+147 -5c71ea43933b6c7e8a85eb1a4eb2213011b95d82 jdk-9+148 -cf139f925da04c8bd7efd33270a0315d72b338d3 jdk-9+149 -17469f16fbb406ec9f0dd262ce776ab6efbc38f1 jdk-9+150 -37b95df0042ae0687324e1f7dc4a2519e230e704 jdk-9+151 -ab2c8b03c3284fcbdd157551a66f807e3a182d9b jdk-9+152 -d7034ff7f8e257e81c9f95c7785dd4eaaa3c2afc jdk-9+153 -8c70d170e62c0c58b5bc3ba666bd140399b98c9c jdk-10+0 -45b751afd11e6c05991cf4913c5a0ac3304fcc4e jdk-9+154 -f4aff695ffe05cfdb69d8af25a4ddc6a029754ea jdk-9+155 -06bce0388880b5ff8e040e4a9d72a3ea11dac321 jdk-9+156 -74116beae88a8f17a80301aa6c83865c82f10ece jdk-10+1 -4a79ad46e578112fce68f1af9dd931025cc235cb jdk-10+2 -d1cab6c7e608479be4ebfad48a25b0ed48600f62 jdk-10+3 -02253db2ace1422f576f58502fc7831ead77424b jdk-10+4 -f113ce12fe24fbd24acf02711372d9f1e1c12426 jdk-10+5 -1407b19a2ddf6baae162f5a1a5b96af473f4d7d1 jdk-10+6 -30e75693ae99fd8e47fd2f5116527aff1b59aff9 jdk-10+7 -c42dc7b58b4d4301ea676a76326fd9bbd403d595 jdk-10+8 -aa5b01f5e5620438fd39efdb2e2f6365a2c7d898 jdk-10+9 -b0f2b8ff25a2209b2c807785d75f20e5086bbfc2 jdk-10+10 -036dbf8b381798e5d31065109714d04d97bf98a4 jdk-10+11 -e6d70017f5b9adbb2ec82d826973d0251800a3c3 jdk-10+12 -9927a9f16738e240ab7014f0118f41e314ef8f99 jdk-10+13 -9ef5029b247b4d940080417a287440bbdbab995b jdk-10+14 -878e216039322cb3f0ecbd0944642a2b4e2593f3 jdk-10+15 -4bbea012e5676e8025ade2bcfab4d6581e6e9f4b jdk-10+16 -7db699468b4f84abbcc01647e5a964409737411a jdk-10+17 -3739654290616e533fc6f51bf9ad69ed47a6abba jdk-10+18 -14df107500cc3b8ab238c3e4ad2c74e12bfe6067 jdk-10+19 -4586bc5d28d13d3147b993e6237eaf29a7073bbb jdk-10+20 -a85884d55ce32799f5c7382b7ea4839052b362a2 jdk-10+21 -e5357aa85dadacc6562175ff74714fecfb4470cf jdk-10+22 -22850b3a55240253841b9a425ad60a7fcdb22d47 jdk-10+23 -3b201865d5c1f244f555cad58da599c9261286d8 jdk-10+24 -8eb5e3ccee560c28ac9b1df2670adac2b3d36fad jdk-10+25 -1129253d3bc728a2963ba411ab9dd1adf358fb6b jdk-10+26 -b87d7b5d5dedc1185e5929470f945b7378cdb3ad jdk-10+27 -92f08900cb3c0d694e5c529a676c1c9e5909193f jdk-10+28 -a6e591e12f122768f675428e1e5a838fd0e9c7ec jdk-10+29 -8fee80b92e65149f7414250fd5e34b6f35d417b4 jdk-10+30 -e6278add9ff28fab70fe1cc4c1d65f7363dc9445 jdk-10+31 -a2008587c13fa05fa2dbfcb09fe987576fbedfd1 jdk-10+32 -bbd692ad4fa300ecca7939ffbe3b1d5e52a28cc6 jdk-10+33 -89deac44e51517841491ba86ff44aa82a5ca96b3 jdk-10+34 -d8c634b016c628622c9abbdc6bf50509e5dedbec jdk-10+35 -0ee20aad71c4f33c426372b4c8bcc1235ce2ec08 jdk-11+0 -959f2f7cbaa6d2ee45d50029744efb219721576c jdk-10+36 -4f830b447edf04fb4a52151a5ad44d9bb60723cd jdk-10+37 -e569e83139fdfbecfeb3cd9014d560917787f158 jdk-10+38 -5b834ec962366e00d4445352a999a3ac14e26f64 jdk-10+39 -860326263d1f6a83996d7da0f4c66806ae4aa1eb jdk-10+40 -3eae36c6baa5f916a3024cf1513e22357e00185d jdk-10+41 -4b62b815b4f49970b91a952929cf50115c263cb3 jdk-10+42 -107413b070b92c88bde6230ceb4a19b579781068 jdk-10+43 -dfa46cfe56346884a61efdc30dc50f7505d66761 jdk-11+1 -03ae177c26b016353e5ea1cab6ffd051dfa086ca jdk-11+2 -663f20fc51091bd7f95d18448850ba091207b7bd jdk-10+44 -4f96cf952e71cb8a127334494faf28880c26181b jdk-10+45 -1fd4d6068f54561cfc67d54fc9ca84af7212c4f8 jdk-11+3 -e59941f7247d451fa7df9eaef3fce0f492f8420c jdk-11+4 -d5c43e9f08fb9a7c74aae0d48daf17f2ad2afaef jdk-11+5 -3acb379b86725c47e7f33358cb22efa8752ae532 jdk-11+6 -f7363de371c9a1f668bd0a01b7df3d1ddb9cc58b jdk-11+7 -755e1b55a4dff510f9639cdb5c5e82549a7e09b3 jdk-11+8 -0c3e252cea44f06aef570ef464950ab97c669970 jdk-11+9 -6fa770f9f8ab296e1ce255ec17ccf6d4e1051886 jdk-10+46 -69d7398038c54774d9395b6810e0cca335edc02c jdk-11+10 -e1e60f75cd39312a7f59d2a4f91d624e5aecc95e jdk-11+11 -3ab6ba9f94a9045a526d645af26c933235371d6f jdk-11+12 -758deedaae8406ae60147486107a54e9864aa7b0 jdk-11+13 -3595bd343b65f8c37818ebe6a4c343ddeb1a5f88 jdk-11+14 -a11c1cb542bbd1671d25b85efe7d09b983c48525 jdk-11+15 -02934b0d661b82b7fe1052a04998d2091352e08d jdk-11+16 -64e4b1686141e57a681936a8283983341484676e jdk-11+17 -e1b3def126240d5433902f3cb0e91a4c27f6db50 jdk-11+18 -36ca515343e00b021dcfc902e986d26ec994a2e5 jdk-11+19 -95aad0c785e497f1bade3955c4e4a677b629fa9d jdk-12+0 -9816d7cc655e53ba081f938b656e31971b8f097a jdk-11+20 -14708e1acdc3974f4539027cbbcfa6d69f83cf51 jdk-11+21 -00b16d0457e43d23f6ca5ade6b243edce62750a0 jdk-12+1 -9937ef7499dcd7673714517fd5e450410c14ba4e jdk-11+22 -69b438908512d3dfef5852c6a843a5778333a309 jdk-12+2 -1edcf36fe15f79d6228d1a63eb680878e2386480 jdk-11+23 -990db216e7199b2ba9989d8fa20b657e0ca7d969 jdk-12+3 -ea900a7dc7d77dee30865c60eabd87fc24b1037c jdk-11+24 -499b873761d8e8a1cc4aa649daf04cbe98cbce77 jdk-12+4 -331888ea4a788df801b1edf8836646cd25fc758b jdk-11+25 -f8696e0ab9b795030429fc3374ec03e378fd9ed7 jdk-12+5 -945ba9278a272a5477ffb1b3ea1b04174fed8036 jdk-11+26 -7939b3c4e4088bf4f70ec5bbd8030393b653372f jdk-12+6 -9d7d74c6f2cbe522e39fa22dc557fdd3f79b32ad jdk-11+27 -ef57958c7c511162da8d9a75f0b977f0f7ac464e jdk-12+7 -76072a077ee1d815152d45d1692c4b36c53c5c49 jdk-11+28 -492b366f8e5784cc4927c2c98f9b8a3f16c067eb jdk-12+8 -31b159f30fb281016c5f0c103552809aeda84063 jdk-12+9 -8f594f75e0547d4ca16649cb3501659e3155e81b jdk-12+10 -f0f5d23449d31f1b3580c8a73313918cafeaefd7 jdk-12+11 -15094d12a632f452a2064318a4e416d0c7a9ce0c jdk-12+12 -511a9946f83e3e3c7b9dbe1840367063fb39b4e1 jdk-12+13 -8897e41b327c0a5601c6ba2bba5d07f15a3ffc91 jdk-12+14 -8897e41b327c0a5601c6ba2bba5d07f15a3ffc91 jdk-12+14 -6f04692c7d5137ee34a6bd94c0c8a6c9219cb127 jdk-12+14 -f8626bcc169813a4b2a15880386b952719d1d6d1 jdk-12+15 -199658d1ef860cdc17055b4fd3e94b057f292fe9 jdk-12+16 -eefa65e142af305923d2adcd596fab9c639723a1 jdk-12+17 -e38473506688e0995e701fc7f77d5a91b438ef93 jdk-12+18 -dc1f9dec2018a37fedba47d8a2aedef99faaec64 jdk-12+19 -40098289d5804c3b5e7074bc75501a81e70d9b0d jdk-12+20 -f8fb0c86f2b3d24294d39c5685a628e1beb14ba7 jdk-12+21 -732bec44c89e8b93a38296bf690f97b7230c5b6d jdk-12+22 -eef755718cb24813031a842bbfc716a6cea18e9a jdk-12+23 -cc4098b3bc10d1c390384289025fea7b0d4b9e93 jdk-13+0 -7d4397b43fa305806160785a4c7210600d59581a jdk-12+24 -11033c4ada542f9c9a873314b6ecf60af19e8256 jdk-13+1 -7496df94b3b79f3da53925d2d137317715f11d97 jdk-12+25 -50677f43ac3df9a8684222b8893543c60f3aa0bd jdk-13+2 -de9fd809bb475401aad188eab2264226788aad81 jdk-12+26 -642346a11059b9f283110dc301a24ed43b76a94e jdk-13+3 -f15d443f97318e9b40e6f451e327ff69ed4ec361 jdk-12+27 -a47b8125b7cc9ef59619745c163975fe935b57ed jdk-13+4 -659b004b6a1bd8c31e766cbdf328d8f8473fd4d7 jdk-12+28 -e3ed960609927b5fdfd0a797159835cd83a81a31 jdk-13+5 -44f41693631f9b5ac78ff4d2bfabd6734fe46df2 jdk-12+29 -b5f05fe4a6f8b3996a000c20078b356d991ca8ec jdk-13+6 -6c377af36a5c4203f16aed8a5e4c2ecc08fcd8bd jdk-12+30 -021917019cda1c0c5853255322274f37693a2431 jdk-13+7 -b5f7bb57de2f797be34f6c75d45c3245ad37ab97 jdk-12+31 -a535ba736cabc6886acdff36de3a096c46e5ddc5 jdk-13+8 -4ce47bc1fb92cf94c6e3d1f49d582f02dcb851ab jdk-12+32 -c081f3ea6b9300265a4a34e38f970b1e3ddaae9f jdk-13+9 -b67884871b5fff79c5ef3eb8ac74dd48d71ea9b1 jdk-12+33 -8e069f7b4fabfe05d9f500783e6d56cb0196d25c jdk-13+10 -21ea4076a275a0f498afa517e9ee1b94a9cf0255 jdk-13+11 -1d7aec80147a6d92b101a76aef92f3ddc88bedf4 jdk-13+12 -b67884871b5fff79c5ef3eb8ac74dd48d71ea9b1 jdk-12-ga -83cace4142c8563b6a921787db02388e1bc48d01 jdk-13+13 -46cf212cdccaf4fb064d913b12004007d3322b67 jdk-13+14 -f855ec13aa2501ae184c8b3e0626a8cec9966116 jdk-13+15 -9d0ae9508d5337b0dc7cc4684be42888c4023755 jdk-13+16 -93b702d2a0cb9e32160208f6700aede1f8492773 jdk-13+17 -bebb82ef3434a25f8142edafec20165f07ac562d jdk-13+18 -a43d6467317d8f1e160f67aadec37919c9d64443 jdk-13+19 -6ccc7cd7931e34129f6b7e04988fc9a63958dde0 jdk-13+20 -f2f11d7f7f4e7128f8aba6ffa576cfa76fbf7d1a jdk-13+21 -181986c5476468bc2dd4532af49599003ee8af37 jdk-13+22 -b034d2dee5fc93d42a81b65e58ce3f91e42586ff jdk-13+23 -7e2238451585029680f126ccbb46d01f2ff5607f jdk-13+24 -22b3b7983adab54e318f75aeb94471f7a4429c1e jdk-14+0 -22b3b7983adab54e318f75aeb94471f7a4429c1e jdk-13+25 -2f4e214781a1d597ed36bf5a36f20928c6c82996 jdk-14+1 -0692b67f54621991ba7afbf23e55b788f3555e69 jdk-13+26 -43627549a488b7d0b4df8fad436e36233df89877 jdk-14+2 -b7f68ddec66f996ae3aad03291d129ca9f02482d jdk-13+27 -e64383344f144217c36196c3c8a2df8f588a2af3 jdk-14+3 -1e95931e7d8fa7e3899340a9c7cb28dbea50c10c jdk-13+28 -19d0b382f0869f72d4381b54fa129f1c74b6e766 jdk-14+4 -3081f39a3d30d63b112098386ac2bb027c2b7223 jdk-13+29 -0f1e29c77e50c7da11d83df410026392c4d1a28c jdk-14+5 -2e63fb0a885fa908a97bbb0da8d7c3de11536aca jdk-13+30 -443f7359b34d60e7821216ffc60f88b6ffe0ccdd jdk-14+6 -6a159c6c23ccd0029140ab91653442e412305ce5 jdk-13+31 -28ab01c067551ef158abaef08e154e1051ca0893 jdk-14+7 -929f37a9c35d530d4e866f6e832001aeb4cfb371 jdk-13+32 -c0023e364b6f130cb1e93747b796d8718d544db1 jdk-14+8 -9c250a7600e12bdb1e611835250af3204d4aa152 jdk-13+33 -18f189e69b29f8215a3500b875127ed4fb2d977a jdk-14+9 -ececb6dae777e622abda42c705fd984a42f46b5a jdk-14+10 -bf4c808a4488025a415f867e54c8b088417e08a0 jdk-14+11 -8570f22b9b6ac6bec673899b582150865696e425 jdk-14+12 -fbbe6672ae15deaf350a9e935290a36f57ba9c25 jdk-14+13 -cddef3bde924f3ff4f17f3d369280cf69d0450e5 jdk-14+14 -9c250a7600e12bdb1e611835250af3204d4aa152 jdk-13-ga -778fc2dcbdaa8981e07e929a2cacef979c72261e jdk-14+15 -d29f0181ba424a95d881aba5eabf2e393abcc70f jdk-14+16 -5c83830390baafb76a1fbe33443c57620bd45fb9 jdk-14+17 -e84d8379815ba0d3e50fb096d28c25894cb50b8c jdk-14+18 -9b67dd88a9313e982ec5f710a7747161bc8f0c23 jdk-14+19 -54ffb15c48399dd59922ee22bb592d815307e77c jdk-14+20 -c16ac7a2eba4e73cb4f7ee9294dd647860eebff0 jdk-14+21 -83810b7d12e7ff761ad3dd91f323a22dad96f108 jdk-14+22 -15936b142f86731afa4b1a2c0fe4a01e806c4944 jdk-14+23 -438337c846fb071900ddb6922bddf8b3e895a514 jdk-14+24 -17d242844fc9e7d18b3eac97426490a9c246119e jdk-14+25 -288777cf0702914e5266bc1e5d380eed9032ca41 jdk-14+26 -2c724dba4c3cf9516b2152e151c9aea66b21b30b jdk-15+0 -91a3f092682fc715d991a87eb6ec6f28886d2035 jdk-14+27 -63e17cf29bed191ea21020b4648c9cdf893f80f5 jdk-15+1 -2069b4bfd23b56b6fc659fba8b75aaaa23debbe0 jdk-14+28 -f33197adda9ad82fdef46ac0f7dc0126204f35b2 jdk-15+2 -563fa900fa17c290ae516c7a3a69e8c069dde304 jdk-14+29 -d05fcdf25717d85e80a3a39a6b719458b22be5fe jdk-15+3 -d54ce919da90dab361995bb4d87be9851f00537a jdk-14+30 -bb0a7975b31ded63d594ee8dbfc4d4ead587f79b jdk-15+4 -decd3d2953b640f1043ee76953ff89238bff92e8 jdk-14+31 -b97c1773ccafae4a8c16cc6aedb10b2a4f9a07ed jdk-15+5 -2776da28515e087cc8849acf1e131a65ea7e77b6 jdk-14+32 -ef7d53b4fccd4a0501b17d974e84f37aa99fa813 jdk-15+6 -f728b6c7f4910d6bd6070cb4dde8393f4ba95113 jdk-14+33 -e2bc57500c1b785837982f7ce8af6751387ed73b jdk-15+7 -a96bc204e3b31ddbf909b20088964112f052927e jdk-14+34 -c7d4f2849dbfb755fc5860b362a4044ea0c9e082 jdk-15+8 -4a87bb7ebfd7f6a25ec59a5982fe3607242777f8 jdk-14+35 -62b5bfef8d618e08e6f3a56cf1fb0e67e89e9cc2 jdk-15+9 -bc54620a3848c26cff9766e5e2a6e5ddab98ed18 jdk-14+36 -1bee69801aeea1a34261c93f35bc9de072a98704 jdk-15+10 -b2dd4028a6de4e40dda8b76109e4b5c6b294f980 jdk-15+11 -2ec0ff3042630ddbd3587e340fe0dd40391cb6c4 jdk-15+12 -1c06a8ee8acad4d93c782626a233693a73de0add jdk-15+13 -1d6ceb13e142665ea833fca01c8c8598e0ddd211 jdk-15+14 -bc54620a3848c26cff9766e5e2a6e5ddab98ed18 jdk-14-ga -82b7c62cf4cc56828a8fb724f57087967232a2a7 jdk-15+15 -5c7ec21f5d13f6eb5cd32288c69b8be2f9cac256 jdk-15+16 -dd5198db2e5b1ebcafe065d987c03ba9fcb50fc3 jdk-15+17 -44aef192b488a48cce12422394691a6b1d16b98e jdk-15+18 -7cc27caabe6e342151e8baf549beb07a9c755ec2 jdk-15+19 -46bca5e5e6fb26efd07245d26fe96a9c3260f51e jdk-15+20 -12b55fad80f30d24b1f8fdb3b947ea6465ef9518 jdk-15+21 -7223c6d610343fd8323af9d07d501e01fa1a7696 jdk-15+22 -f143729ca00ec14a98ea5c7f73acba88da97746e jdk-15+23 -497fd9f9129c4928fd5a876dd55e0daf6298b511 jdk-15+24 -90b266a84c06f1b3dc0ed8767856793e8c1c357e jdk-15+25 -0a32396f7a690015d22ca3328ac441a358295d90 jdk-15+26 -93813843680bbe1b7efbca56c03fd137f20a2c31 jdk-16+0 -93813843680bbe1b7efbca56c03fd137f20a2c31 jdk-15+27 -4a485c89d5a08b495961835f5308a96038678aeb jdk-16+1 -06c9f89459daba98395fad726100feb44f89ba71 jdk-15+28 -bcbe7b8a77b8971bc221c0be1bd2abb6fb68c2d0 jdk-16+2 -b58fc60580550a4a587cab729d8fd87223ad6932 jdk-15+29 -76810b3a88c8c641ae3850a8dfd7c40c984aea9d jdk-16+3 -6909e4a1f25bfe9a2727026f5845fc1fc44a36aa jdk-15+30 -e2622818f0bd30e736252eba101fe7d2c27f400b jdk-16+4 -a32f58c6b8be81877411767de7ba9c4cf087c1b5 jdk-15+31 -143e258f64af490010eb7e0bacc1cfaeceff0993 jdk-16+5 -2dad000726b8d5db9f3df647fb4949d88f269dd4 jdk-15+32 -4a8fd81d64bafa523cddb45f82805536edace106 jdk-16+6 -6b65f4e7a975628df51ef755b02642075390041d jdk-15+33 -c3a4a7ea7c304cabdacdc31741eb94c51351668d jdk-16+7 -b0817631d2f4395508cb10e81c3858a94d9ae4de jdk-15+34 -0a73d6f3aab48ff6d7e61e47f0bc2d87a054f217 jdk-16+8 -fd60c3146a024037cdd9be34c645bb793995a7cc jdk-15+35 -c075a286cc7df767cce28e8057d6ec5051786490 jdk-16+9 -b01985b4f88f554f97901e53e1ba314681dd9c19 jdk-16+10 -e3f940bd3c8fcdf4ca704c6eb1ac745d155859d5 jdk-15+36 -5c18d696c7ce724ca36df13933aa53f50e12b9e0 jdk-16+11 -fc8e62b399bd93d06e8d13dc3b384c450e853dcd jdk-16+12 -fd07cdb26fc70243ef23d688b545514f4ddf1c2b jdk-16+13 -36b29df125dc88f11657ce93b4998aa9ff5f5d41 jdk-16+14 -- GitLab From 1ea766db5519f03e36fc5b0c446cf34b172bb349 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Gr=C3=B6nlund?= Date: Thu, 9 Dec 2021 09:23:39 +0000 Subject: [PATCH 080/671] 8278419: JFR jcmd option contract "This value cannot be changed once JFR has been initialized" is not enforced Reviewed-by: egahlin --- src/hotspot/share/jfr/dcmd/jfrDcmds.cpp | 62 ++++++++++--------- .../jfr/jcmd/TestJcmdConfigureReadOnly.java | 49 +++++++++++++++ 2 files changed, 81 insertions(+), 30 deletions(-) create mode 100644 test/jdk/jdk/jfr/jcmd/TestJcmdConfigureReadOnly.java diff --git a/src/hotspot/share/jfr/dcmd/jfrDcmds.cpp b/src/hotspot/share/jfr/dcmd/jfrDcmds.cpp index 9763ed62b76..319d1c1a4e8 100644 --- a/src/hotspot/share/jfr/dcmd/jfrDcmds.cpp +++ b/src/hotspot/share/jfr/dcmd/jfrDcmds.cpp @@ -388,12 +388,12 @@ void JfrConfigureFlightRecorderDCmd::print_help(const char* name) const { out->print_cr(" been initalized. (STRING, default determined by the value for"); out->print_cr(" memorysize)"); out->print_cr(""); - out->print_cr(" maxchunksize (Optional) Maximum size of an individual data chunk in bytes if"); + out->print_cr(" maxchunksize (Optional) Maximum size of an individual data chunk in bytes if"); out->print_cr(" one of the following suffixes is not used: 'm' or 'M' for"); out->print_cr(" megabytes OR 'g' or 'G' for gigabytes. This value cannot be"); out->print_cr(" changed once JFR has been initialized. (STRING, 12M)"); out->print_cr(""); - out->print_cr(" memorysize (Optional) Overall memory size, in bytes if one of the following"); + out->print_cr(" memorysize (Optional) Overall memory size, in bytes if one of the following"); out->print_cr(" suffixes is not used: 'm' or 'M' for megabytes OR 'g' or 'G' for"); out->print_cr(" gigabytes. This value cannot be changed once JFR has been"); out->print_cr(" initialized. (STRING, 10M)"); @@ -403,7 +403,11 @@ void JfrConfigureFlightRecorderDCmd::print_help(const char* name) const { out->print_cr(" location is the temporary directory for the operating system. On"); out->print_cr(" Linux operating systems, the temporary directory is /tmp. On"); out->print_cr(" Windows, the temporary directory is specified by the TMP"); - out->print_cr(" environment variable.)"); + out->print_cr(" environment variable)"); + out->print_cr(""); + out->print_cr(" dumppath (Optional) Path to the location where a recording file is written"); + out->print_cr(" in case the VM runs into a critical error, such as a system"); + out->print_cr(" crash. (STRING, The default location is the current directory)"); out->print_cr(""); out->print_cr(" stackdepth (Optional) Stack depth for stack traces. Setting this value"); out->print_cr(" greater than the default of 64 may cause a performance"); @@ -416,7 +420,8 @@ void JfrConfigureFlightRecorderDCmd::print_help(const char* name) const { out->print_cr(" performance and is not recommended. This value cannot be changed"); out->print_cr(" once JFR has been initialized. (STRING, 8k)"); out->print_cr(""); - out->print_cr(" samplethreads (Optional) Flag for activating thread sampling. (BOOLEAN, true)"); + out->print_cr(" samplethreads (Optional) Flag for activating thread sampling. This value cannot"); + out->print_cr(" be changed once JFR has been initialized. (BOOLEAN, true)"); out->print_cr(""); out->print_cr("Options must be specified using the or = syntax."); out->print_cr(""); @@ -467,38 +472,35 @@ void JfrConfigureFlightRecorderDCmd::execute(DCmdSource source, TRAPS) { } jobject stack_depth = NULL; - if (_stack_depth.is_set()) { - stack_depth = JfrJavaSupport::new_java_lang_Integer((jint)_stack_depth.value(), CHECK); - } - jobject global_buffer_count = NULL; - if (_global_buffer_count.is_set()) { - global_buffer_count = JfrJavaSupport::new_java_lang_Long(_global_buffer_count.value(), CHECK); - } - jobject global_buffer_size = NULL; - if (_global_buffer_size.is_set()) { - global_buffer_size = JfrJavaSupport::new_java_lang_Long(_global_buffer_size.value()._size, CHECK); - } - jobject thread_buffer_size = NULL; - if (_thread_buffer_size.is_set()) { - thread_buffer_size = JfrJavaSupport::new_java_lang_Long(_thread_buffer_size.value()._size, CHECK); - } - jobject max_chunk_size = NULL; - if (_max_chunk_size.is_set()) { - max_chunk_size = JfrJavaSupport::new_java_lang_Long(_max_chunk_size.value()._size, CHECK); - } - jobject memory_size = NULL; - if (_memory_size.is_set()) { - memory_size = JfrJavaSupport::new_java_lang_Long(_memory_size.value()._size, CHECK); - } - jobject sample_threads = NULL; - if (_sample_threads.is_set()) { - sample_threads = JfrJavaSupport::new_java_lang_Boolean(_sample_threads.value(), CHECK); + + if (!JfrRecorder::is_created()) { + if (_stack_depth.is_set()) { + stack_depth = JfrJavaSupport::new_java_lang_Integer((jint)_stack_depth.value(), CHECK); + } + if (_global_buffer_count.is_set()) { + global_buffer_count = JfrJavaSupport::new_java_lang_Long(_global_buffer_count.value(), CHECK); + } + if (_global_buffer_size.is_set()) { + global_buffer_size = JfrJavaSupport::new_java_lang_Long(_global_buffer_size.value()._size, CHECK); + } + if (_thread_buffer_size.is_set()) { + thread_buffer_size = JfrJavaSupport::new_java_lang_Long(_thread_buffer_size.value()._size, CHECK); + } + if (_max_chunk_size.is_set()) { + max_chunk_size = JfrJavaSupport::new_java_lang_Long(_max_chunk_size.value()._size, CHECK); + } + if (_memory_size.is_set()) { + memory_size = JfrJavaSupport::new_java_lang_Long(_memory_size.value()._size, CHECK); + } + if (_sample_threads.is_set()) { + sample_threads = JfrJavaSupport::new_java_lang_Boolean(_sample_threads.value(), CHECK); + } } static const char klass[] = "jdk/jfr/internal/dcmd/DCmdConfigure"; diff --git a/test/jdk/jdk/jfr/jcmd/TestJcmdConfigureReadOnly.java b/test/jdk/jdk/jfr/jcmd/TestJcmdConfigureReadOnly.java new file mode 100644 index 00000000000..6ddf3a75234 --- /dev/null +++ b/test/jdk/jdk/jfr/jcmd/TestJcmdConfigureReadOnly.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2021, 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. + */ + +package jdk.jfr.jcmd; + +import jdk.test.lib.process.OutputAnalyzer; + +/** + * @test + * @summary The test verifies JFR.configure command can only set certain options before JFR is started. + * @key jfr + * @requires vm.hasJFR + * @library /test/lib /test/jdk + * @run main/othervm jdk.jfr.jcmd.TestJcmdConfigureReadOnly + */ +public class TestJcmdConfigureReadOnly { + public static void main(String[] args) throws Exception { + // Set an option before initializing JFR. + OutputAnalyzer output = JcmdHelper.jcmd("JFR.configure", "stackdepth=" + 128); + output.shouldContain("Stack depth: 128"); + // JFR.start will initialize JFR. + output = JcmdHelper.jcmd("JFR.start"); + JcmdAsserts.assertRecordingHasStarted(output); + // Attempt to set a new value after JFR initialization. + output = JcmdHelper.jcmd("JFR.configure", "stackdepth=" + 256); + // After initialization, the option is considered read-only. + output.shouldContain("Stack depth: 128"); + } +} -- GitLab From 84baea753a01428d9dc5befa5f23d4ac853a7bbc Mon Sep 17 00:00:00 2001 From: Julia Boes Date: Thu, 9 Dec 2021 09:29:08 +0000 Subject: [PATCH 081/671] 8278433: Use snippets in jdk.incubator.foreign documentation Reviewed-by: mcimadamore --- .../jdk/incubator/foreign/CLinker.java | 6 +- .../jdk/incubator/foreign/MemoryAddress.java | 18 +-- .../jdk/incubator/foreign/MemoryHandles.java | 36 +++--- .../jdk/incubator/foreign/MemoryLayout.java | 114 +++++++++--------- .../jdk/incubator/foreign/MemorySegment.java | 110 ++++++++--------- .../jdk/incubator/foreign/ResourceScope.java | 38 +++--- .../incubator/foreign/SegmentAllocator.java | 36 +++--- .../jdk/incubator/foreign/SequenceLayout.java | 52 ++++---- .../jdk/incubator/foreign/ValueLayout.java | 56 ++++----- .../jdk/incubator/foreign/package-info.java | 113 +++++++++-------- 10 files changed, 289 insertions(+), 290 deletions(-) diff --git a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/CLinker.java b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/CLinker.java index f5f1a6dc313..745e27691dd 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/CLinker.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/CLinker.java @@ -181,9 +181,9 @@ public sealed interface CLinker extends SymbolLookup permits Windowsx64Linker, S * to allocate structs returned by-value. *

    * Calling this method is equivalent to the following code: -

    {@code
    -    linker.downcallHandle(function).bindTo(symbol);
    -}
    + * {@snippet lang=java : + * linker.downcallHandle(function).bindTo(symbol); + * } * * @param symbol downcall symbol. * @param function the function descriptor. diff --git a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemoryAddress.java b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemoryAddress.java index ce1a77c41b3..4856a66008d 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemoryAddress.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemoryAddress.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -46,17 +46,17 @@ import java.nio.ByteOrder; * Each dereference method takes a {@linkplain jdk.incubator.foreign.ValueLayout value layout}, which specifies the size, * alignment constraints, byte order as well as the Java type associated with the dereference operation, and an offset. * For instance, to read an int from a segment, using {@link ByteOrder#nativeOrder() default endianness}, the following code can be used: - *
    {@code
    -MemoryAddress address = ...
    -int value = address.get(ValueLayout.JAVA_INT, 0);
    - * }
    + * {@snippet lang=java : + * MemoryAddress address = ... + * int value = address.get(ValueLayout.JAVA_INT, 0); + * } * * If the value to be read is stored in memory using {@link ByteOrder#BIG_ENDIAN big-endian} encoding, the dereference operation * can be expressed as follows: - *
    {@code
    -MemoryAddress address = ...
    -int value = address.get(ValueLayout.JAVA_INT.withOrder(BIG_ENDIAN), 0);
    - * }
    + * {@snippet lang=java : + * MemoryAddress address = ... + * int value = address.get(ValueLayout.JAVA_INT.withOrder(BIG_ENDIAN), 0); + * } * * All the dereference methods in this class are restricted: since * a memory address does not feature temporal nor spatial bounds, the runtime has no way to check the correctness diff --git a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemoryHandles.java b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemoryHandles.java index f4489ecd601..f24f5c7bc6e 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemoryHandles.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemoryHandles.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -47,17 +47,17 @@ import java.util.Objects; * to the segment, at which dereference should occur. *

    * As an example, consider the memory layout expressed by a {@link GroupLayout} instance constructed as follows: - *

    {@code
    -GroupLayout seq = MemoryLayout.structLayout(
    -        MemoryLayout.paddingLayout(32),
    -        ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN).withName("value")
    -);
    - * }
    + * {@snippet lang=java : + * GroupLayout seq = MemoryLayout.structLayout( + * MemoryLayout.paddingLayout(32), + * ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN).withName("value") + * ); + * } * To access the member layout named {@code value}, we can construct a memory access var handle as follows: - *
    {@code
    -VarHandle handle = MemoryHandles.varHandle(ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN)); //(MemorySegment, long) -> int
    -handle = MemoryHandles.insertCoordinates(handle, 1, 4); //(MemorySegment) -> int
    - * }
    + * {@snippet lang=java : + * VarHandle handle = MemoryHandles.varHandle(ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN)); //(MemorySegment, long) -> int + * handle = MemoryHandles.insertCoordinates(handle, 1, 4); //(MemorySegment) -> int + * } * *

    Unless otherwise specified, passing a {@code null} argument, or an array argument containing one or more {@code null} * elements to a method in this class causes a {@link NullPointerException NullPointerException} to be thrown.

    @@ -177,13 +177,13 @@ public final class MemoryHandles { * example, it is often convenient to model an unsigned short as a * Java {@code int} to avoid dealing with negative values, which would be * the case if modeled as a Java {@code short}. This is illustrated in the following example: - *
    {@code
    -    MemorySegment segment = MemorySegment.allocateNative(2, ResourceScope.newImplicitScope());
    -    VarHandle SHORT_VH = ValueLayout.JAVA_SHORT.varHandle();
    -    VarHandle INT_VH = MemoryHandles.asUnsigned(SHORT_VH, int.class);
    -    SHORT_VH.set(segment, (short)-1);
    -    INT_VH.get(segment); // returns 65535
    -     * }
    + * {@snippet lang=java : + * MemorySegment segment = MemorySegment.allocateNative(2, ResourceScope.newImplicitScope()); + * VarHandle SHORT_VH = ValueLayout.JAVA_SHORT.varHandle(); + * VarHandle INT_VH = MemoryHandles.asUnsigned(SHORT_VH, int.class); + * SHORT_VH.set(segment, (short)-1); + * INT_VH.get(segment); // returns 65535 + * } *

    * When calling e.g. {@link VarHandle#set(Object...)} on the resulting var * handle, the incoming value (of type {@code adaptedType}) is converted by a diff --git a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemoryLayout.java b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemoryLayout.java index 8319f22c2ab..fe0fb4e93f9 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemoryLayout.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemoryLayout.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -58,24 +58,24 @@ import java.util.stream.Stream; *

    * For instance, consider the following struct declaration in C: * - *

    {@code
    - typedef struct {
    -     char kind;
    -     int value;
    - } TaggedValues[5];
    - * }
    + * {@snippet lang=c : + * typedef struct { + * char kind; + * int value; + * } TaggedValues[5]; + * } * * The above declaration can be modelled using a layout object, as follows: * - *
    {@code
    -SequenceLayout taggedValues = MemoryLayout.sequenceLayout(5,
    -    MemoryLayout.structLayout(
    -        ValueLayout.JAVA_BYTE.withName("kind"),
    -        MemoryLayout.paddingLayout(24),
    -        ValueLayout.JAVA_INT.withName("value")
    -    )
    -).withName("TaggedValues");
    - * }
    + * {@snippet lang=java : + * SequenceLayout taggedValues = MemoryLayout.sequenceLayout(5, + * MemoryLayout.structLayout( + * ValueLayout.JAVA_BYTE.withName("kind"), + * MemoryLayout.paddingLayout(24), + * ValueLayout.JAVA_INT.withName("value") + * ) + * ).withName("TaggedValues"); + * } *

    * All implementations of this interface must be value-based; * programmers should treat instances that are {@linkplain #equals(Object) equal} as interchangeable and should not @@ -129,42 +129,42 @@ SequenceLayout taggedValues = MemoryLayout.sequenceLayout(5, * Such layout paths can be constructed programmatically using the methods in this class. * For instance, given the {@code taggedValues} layout instance constructed as above, we can obtain the offset, * in bits, of the member layout named value in the first sequence element, as follows: - *

    {@code
    -long valueOffset = taggedValues.bitOffset(PathElement.sequenceElement(0),
    -                                          PathElement.groupElement("value")); // yields 32
    - * }
    + * {@snippet lang=java : + * long valueOffset = taggedValues.bitOffset(PathElement.sequenceElement(0), + * PathElement.groupElement("value")); // yields 32 + * } * * Similarly, we can select the member layout named {@code value}, as follows: - *
    {@code
    -MemoryLayout value = taggedValues.select(PathElement.sequenceElement(),
    -                                         PathElement.groupElement("value"));
    - * }
    + * {@snippet lang=java : + * MemoryLayout value = taggedValues.select(PathElement.sequenceElement(), + * PathElement.groupElement("value")); + * } * * And, we can also replace the layout named {@code value} with another layout, as follows: - *
    {@code
    -MemoryLayout taggedValuesWithHole = taggedValues.map(l -> MemoryLayout.paddingLayout(32),
    -                                            PathElement.sequenceElement(), PathElement.groupElement("value"));
    - * }
    + * {@snippet lang=java : + * MemoryLayout taggedValuesWithHole = taggedValues.map(l -> MemoryLayout.paddingLayout(32), + * PathElement.sequenceElement(), PathElement.groupElement("value")); + * } * * That is, the above declaration is identical to the following, more verbose one: - *
    {@code
    -MemoryLayout taggedValuesWithHole = MemoryLayout.sequenceLayout(5,
    -    MemoryLayout.structLayout(
    -        ValueLayout.JAVA_BYTE.withName("kind"),
    -        MemoryLayout.paddingLayout(32),
    -        MemoryLayout.paddingLayout(32)
    -));
    - * }
    + * {@snippet lang=java : + * MemoryLayout taggedValuesWithHole = MemoryLayout.sequenceLayout(5, + * MemoryLayout.structLayout( + * ValueLayout.JAVA_BYTE.withName("kind"), + * MemoryLayout.paddingLayout(32), + * MemoryLayout.paddingLayout(32) + * )); + * } * * Layout paths can feature one or more free dimensions. For instance, a layout path traversing * an unspecified sequence element (that is, where one of the path component was obtained with the * {@link PathElement#sequenceElement()} method) features an additional free dimension, which will have to be bound at runtime. * This is important when obtaining memory access var handle from layouts, as in the following code: * - *
    {@code
    -VarHandle valueHandle = taggedValues.varHandle(PathElement.sequenceElement(),
    -                                               PathElement.groupElement("value"));
    - * }
    + * {@snippet lang=java : + * VarHandle valueHandle = taggedValues.varHandle(PathElement.sequenceElement(), + * PathElement.groupElement("value")); + * } * * Since the layout path constructed in the above example features exactly one free dimension (as it doesn't specify * which member layout named {@code value} should be selected from the enclosing sequence layout), @@ -177,12 +177,12 @@ VarHandle valueHandle = taggedValues.varHandle(PathElement.sequenceElement(), * offsets of elements of a sequence at different indices, by supplying these indices when invoking the method handle. * For instance: * - *
    {@code
    -MethodHandle offsetHandle = taggedValues.byteOffsetHandle(PathElement.sequenceElement(),
    -                                                          PathElement.groupElement("kind"));
    -long offset1 = (long) offsetHandle.invokeExact(1L); // 8
    -long offset2 = (long) offsetHandle.invokeExact(2L); // 16
    - * }
    + * {@snippet lang=java : + * MethodHandle offsetHandle = taggedValues.byteOffsetHandle(PathElement.sequenceElement(), + * PathElement.groupElement("kind")); + * long offset1 = (long) offsetHandle.invokeExact(1L); // 8 + * long offset2 = (long) offsetHandle.invokeExact(2L); // 16 + * } * *

    Layout attributes

    * @@ -330,7 +330,7 @@ public sealed interface MemoryLayout extends Constable permits AbstractLayout, S *

    The final offset returned by the method handle is computed as follows: * *

    {@code
    -    offset = c_1 + c_2 + ... + c_m + (x_1 * s_1) + (x_2 * s_2) + ... + (x_n * s_n)
    +     * offset = c_1 + c_2 + ... + c_m + (x_1 * s_1) + (x_2 * s_2) + ... + (x_n * s_n)
          * }
    * * where {@code x_1}, {@code x_2}, ... {@code x_n} are dynamic values provided as {@code long} @@ -381,8 +381,8 @@ public sealed interface MemoryLayout extends Constable permits AbstractLayout, S *

    The final offset returned by the method handle is computed as follows: * *

    {@code
    -    bitOffset = c_1 + c_2 + ... + c_m + (x_1 * s_1) + (x_2 * s_2) + ... + (x_n * s_n)
    -    offset = bitOffset / 8
    +     * bitOffset = c_1 + c_2 + ... + c_m + (x_1 * s_1) + (x_2 * s_2) + ... + (x_n * s_n)
    +     * offset = bitOffset / 8
          * }
    * * where {@code x_1}, {@code x_2}, ... {@code x_n} are dynamic values provided as {@code long} @@ -413,7 +413,7 @@ public sealed interface MemoryLayout extends Constable permits AbstractLayout, S * The final memory location accessed by the returned memory access var handle can be computed as follows: * *
    {@code
    -    address = base + offset
    +     * address = base + offset
          * }
    * * where {@code base} denotes the base address expressed by the {@link MemorySegment} access coordinate @@ -421,7 +421,7 @@ public sealed interface MemoryLayout extends Constable permits AbstractLayout, S * can be expressed in the following form: * *
    {@code
    -    offset = c_1 + c_2 + ... + c_m + (x_1 * s_1) + (x_2 * s_2) + ... + (x_n * s_n)
    +     * offset = c_1 + c_2 + ... + c_m + (x_1 * s_1) + (x_2 * s_2) + ... + (x_n * s_n)
          * }
    * * where {@code x_1}, {@code x_2}, ... {@code x_n} are dynamic values provided as {@code long} @@ -458,8 +458,8 @@ public sealed interface MemoryLayout extends Constable permits AbstractLayout, S *

    The offset of the returned segment is computed as follows: * *

    {@code
    -    bitOffset = c_1 + c_2 + ... + c_m + (x_1 * s_1) + (x_2 * s_2) + ... + (x_n * s_n)
    -    offset = bitOffset / 8
    +     * bitOffset = c_1 + c_2 + ... + c_m + (x_1 * s_1) + (x_2 * s_2) + ... + (x_n * s_n)
    +     * offset = bitOffset / 8
          * }
    * * where {@code x_1}, {@code x_2}, ... {@code x_n} are dynamic values provided as {@code long} @@ -468,9 +468,9 @@ public sealed interface MemoryLayout extends Constable permits AbstractLayout, S * the layout path. * *

    After the offset is computed, the returned segment is created as if by calling: - *

    {@code
    -    segment.asSlice(offset, layout.byteSize());
    -     * }
    + * {@snippet lang=java : + * segment.asSlice(offset, layout.byteSize()); + * } * * where {@code segment} is the segment to be sliced, and where {@code layout} is the layout selected by the given * layout path, as per {@link MemoryLayout#select(PathElement...)}. @@ -599,7 +599,7 @@ public sealed interface MemoryLayout extends Constable permits AbstractLayout, S * with this path is bound by an index {@code I}, the resulting accessed offset can be obtained with the following * formula: *
    {@code
    -E * (S + I * F)
    +         * E * (S + I * F)
              * }
    * where {@code E} is the size (in bytes) of the sequence element layout. * diff --git a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemorySegment.java b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemorySegment.java index cd0f1181863..2a577cfc296 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemorySegment.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemorySegment.java @@ -119,17 +119,17 @@ import java.util.stream.Stream; * Each dereference method takes a {@linkplain jdk.incubator.foreign.ValueLayout value layout}, which specifies the size, * alignment constraints, byte order as well as the Java type associated with the dereference operation, and an offset. * For instance, to read an int from a segment, using {@link ByteOrder#nativeOrder() default endianness}, the following code can be used: - *
    {@code
    -MemorySegment segment = ...
    -int value = segment.get(ValueLayout.JAVA_INT, 0);
    - * }
    + * {@snippet lang=java : + * MemorySegment segment = ... + * int value = segment.get(ValueLayout.JAVA_INT, 0); + * } * * If the value to be read is stored in memory using {@link ByteOrder#BIG_ENDIAN big-endian} encoding, the dereference operation * can be expressed as follows: - *
    {@code
    -MemorySegment segment = ...
    -int value = segment.get(ValueLayout.JAVA_INT.withOrder(BIG_ENDIAN), 0);
    - * }
    + * {@snippet lang=java : + * MemorySegment segment = ... + * int value = segment.get(ValueLayout.JAVA_INT.withOrder(BIG_ENDIAN), 0); + * } * * For more complex dereference operations (e.g. structured memory access), clients can obtain a memory access var handle, * that is, a var handle that accepts a segment and, optionally, one or more additional {@code long} coordinates. Memory @@ -145,13 +145,13 @@ int value = segment.get(ValueLayout.JAVA_INT.withOrder(BIG_ENDIAN), 0); * the {@link #scope()} method. As for all resources associated with a resource scope, a segment cannot be * accessed after its corresponding scope has been closed. For instance, the following code will result in an * exception: - *
    {@code
    -MemorySegment segment = null;
    -try (ResourceScope scope = ResourceScope.newConfinedScope()) {
    -    segment = MemorySegment.allocateNative(8, scope);
    -}
    -segment.get(ValueLayout.JAVA_LONG, 0); // already closed!
    - * }
    + * {@snippet lang=java : + * MemorySegment segment = null; + * try (ResourceScope scope = ResourceScope.newConfinedScope()) { + * segment = MemorySegment.allocateNative(8, scope); + * } + * segment.get(ValueLayout.JAVA_LONG, 0); // already closed! + * } * Additionally, access to a memory segment is subject to the thread-confinement checks enforced by the owning scope; that is, * if the segment is associated with a shared scope, it can be accessed by multiple threads; if it is associated with a confined * scope, it can only be accessed by the thread which owns the scope. @@ -162,10 +162,10 @@ segment.get(ValueLayout.JAVA_LONG, 0); // already closed! *

    Memory segment views

    * * Memory segments support views. For instance, it is possible to create an immutable view of a memory segment, as follows: - *
    {@code
    -MemorySegment segment = ...
    -MemorySegment roSegment = segment.asReadOnly();
    - * }
    + * {@snippet lang=java : + * MemorySegment segment = ... + * MemorySegment roSegment = segment.asReadOnly(); + * } * It is also possible to create views whose spatial bounds are stricter than the ones of the original segment * (see {@link MemorySegment#asSlice(long, long)}). *

    @@ -184,15 +184,15 @@ MemorySegment roSegment = segment.asReadOnly(); * (to do this, the segment has to be associated with a shared scope). The following code can be used to sum all int * values in a memory segment in parallel: * - *

    {@code
    -try (ResourceScope scope = ResourceScope.newSharedScope()) {
    -    SequenceLayout SEQUENCE_LAYOUT = MemoryLayout.sequenceLayout(1024, ValueLayout.JAVA_INT);
    -    MemorySegment segment = MemorySegment.allocateNative(SEQUENCE_LAYOUT, scope);
    -    int sum = segment.elements(ValueLayout.JAVA_INT).parallel()
    -                           .mapToInt(s -> s.get(ValueLayout.JAVA_INT, 0))
    -                           .sum();
    -}
    - * }
    + * {@snippet lang=java : + * try (ResourceScope scope = ResourceScope.newSharedScope()) { + * SequenceLayout SEQUENCE_LAYOUT = MemoryLayout.sequenceLayout(1024, ValueLayout.JAVA_INT); + * MemorySegment segment = MemorySegment.allocateNative(SEQUENCE_LAYOUT, scope); + * int sum = segment.elements(ValueLayout.JAVA_INT).parallel() + * .mapToInt(s -> s.get(ValueLayout.JAVA_INT, 0)) + * .sum(); + * } + * } * * @implSpec * Implementations of this interface are immutable, thread-safe and value-based. @@ -233,9 +233,9 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory /** * Returns a sequential {@code Stream} over disjoint slices (whose size matches that of the specified layout) * in this segment. Calling this method is equivalent to the following code: - *
    {@code
    -    StreamSupport.stream(segment.spliterator(elementLayout), false);
    -     * }
    + * {@snippet lang=java : + * StreamSupport.stream(segment.spliterator(elementLayout), false); + * } * * @param elementLayout the layout to be used for splitting. * @return a sequential {@code Stream} over disjoint slices in this segment. @@ -274,9 +274,9 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory * and whose new size is computed by subtracting the specified offset from this segment size. *

    * Equivalent to the following code: - *

    {@code
    -    asSlice(offset, byteSize() - offset);
    -     * }
    + * {@snippet lang=java : + * asSlice(offset, byteSize() - offset); + * } * * @see #asSlice(long, long) * @@ -343,9 +343,9 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory * a negative or positive value. For instance, if both segments are native * segments, the resulting offset can be computed as follows: * - *
    {@code
    +     * {@snippet lang=java :
          * other.baseAddress().toRawLongValue() - segment.baseAddress().toRawLongValue()
    -     * }
    + * } * * If the segments share the same base address, {@code 0} is returned. If * {@code other} is a slice of this segment, the offset is always @@ -362,13 +362,13 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory * More specifically, the given value is filled into each address of this * segment. Equivalent to (but likely more efficient than) the following code: * - *
    {@code
    -byteHandle = MemoryLayout.ofSequence(ValueLayout.JAVA_BYTE)
    -         .varHandle(byte.class, MemoryLayout.PathElement.sequenceElement());
    -for (long l = 0; l < segment.byteSize(); l++) {
    -     byteHandle.set(segment.address(), l, value);
    -}
    -     * }
    + * {@snippet lang=java : + * byteHandle = MemoryLayout.ofSequence(ValueLayout.JAVA_BYTE) + * .varHandle(byte.class, MemoryLayout.PathElement.sequenceElement()); + * for (long l = 0; l < segment.byteSize(); l++) { + * byteHandle.set(segment.address(), l, value); + * } + * } * * without any regard or guarantees on the ordering of particular memory * elements being set. @@ -389,9 +389,9 @@ for (long l = 0; l < segment.byteSize(); l++) { * at offset {@code 0} through {@code src.byteSize() - 1}. *

    * Calling this method is equivalent to the following code: - *

    {@code
    -    MemorySegment.copy(src, 0, this, 0, src.byteSize);
    -     * }
    + * {@snippet lang=java : + * MemorySegment.copy(src, 0, this, 0, src.byteSize); + * } * @param src the source segment. * @throws IndexOutOfBoundsException if {@code src.byteSize() > this.byteSize()}. * @throws IllegalStateException if either the scope associated with the source segment or the scope associated @@ -801,9 +801,9 @@ for (long l = 0; l < segment.byteSize(); l++) { * when the segment is no longer in use. Failure to do so will result in off-heap memory leaks. *

    * This is equivalent to the following code: - *

    {@code
    -    allocateNative(layout.bytesSize(), layout.bytesAlignment(), scope);
    -     * }
    + * {@snippet lang=java : + * allocateNative(layout.bytesSize(), layout.bytesAlignment(), scope); + * } *

    * The block of off-heap memory associated with the returned native memory segment is initialized to zero. * @@ -826,9 +826,9 @@ for (long l = 0; l < segment.byteSize(); l++) { * when the segment is no longer in use. Failure to do so will result in off-heap memory leaks. *

    * This is equivalent to the following code: - *

    {@code
    -    allocateNative(bytesSize, 1, scope);
    -     * }
    + * {@snippet lang=java : + * allocateNative(bytesSize, 1, scope); + * } *

    * The block of off-heap memory associated with the returned native memory segment is initialized to zero. * @@ -935,9 +935,9 @@ for (long l = 0; l < segment.byteSize(); l++) { * For example, this may occur if the same file is {@linkplain MemorySegment#mapFile mapped} to two segments. *

    * Calling this method is equivalent to the following code: - *

    {@code
    -    MemorySegment.copy(srcSegment, ValueLayout.JAVA_BYTE, srcOffset, dstSegment, ValueLayout.JAVA_BYTE, dstOffset, bytes);
    -     * }
    + * {@snippet lang=java : + * MemorySegment.copy(srcSegment, ValueLayout.JAVA_BYTE, srcOffset, dstSegment, ValueLayout.JAVA_BYTE, dstOffset, bytes); + * } * @param srcSegment the source segment. * @param srcOffset the starting offset, in bytes, of the source segment. * @param dstSegment the destination segment. diff --git a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/ResourceScope.java b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/ResourceScope.java index f2fb32a0594..24665c7dfe9 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/ResourceScope.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/ResourceScope.java @@ -103,15 +103,15 @@ import java.util.Spliterator; * segment and allow multiple threads to work in parallel on disjoint segment slices. The following code can be used to sum * all int values in a memory segment in parallel: * - *
    {@code
    -try (ResourceScope scope = ResourceScope.newSharedScope()) {
    -    SequenceLayout SEQUENCE_LAYOUT = MemoryLayout.sequenceLayout(1024, ValueLayout.JAVA_INT);
    -    MemorySegment segment = MemorySegment.allocateNative(SEQUENCE_LAYOUT, scope);
    -    int sum = segment.elements(ValueLayout.JAVA_INT).parallel()
    -                        .mapToInt(s -> s.get(ValueLayout.JAVA_INT, 0))
    -                        .sum();
    -}
    - * }
    + * {@snippet lang=java : + * try (ResourceScope scope = ResourceScope.newSharedScope()) { + * SequenceLayout SEQUENCE_LAYOUT = MemoryLayout.sequenceLayout(1024, ValueLayout.JAVA_INT); + * MemorySegment segment = MemorySegment.allocateNative(SEQUENCE_LAYOUT, scope); + * int sum = segment.elements(ValueLayout.JAVA_INT).parallel() + * .mapToInt(s -> s.get(ValueLayout.JAVA_INT, 0)) + * .sum(); + * } + * } * *

    * Shared resource scopes, while powerful, must be used with caution: if one or more threads accesses @@ -131,13 +131,13 @@ try (ResourceScope scope = ResourceScope.newSharedScope()) { * This can be useful when clients need to perform a critical operation on a memory segment, during which they have * to ensure that the scope associated with that segment will not be closed; this can be done as follows: * - *

    {@code
    -MemorySegment segment = ...
    -try (ResourceScope criticalScope = ResourceScope.newConfinedScope()) {
    -    criticalScope.keepAlive(segment.scope());
    -    
    -}
    - * }
    + * {@snippet lang=java : + * MemorySegment segment = ... + * try (ResourceScope criticalScope = ResourceScope.newConfinedScope()) { + * criticalScope.keepAlive(segment.scope()); + * + * } + * } * * Note that a resource scope does not become unreachable * until all the scopes it depends on have been closed. @@ -239,9 +239,9 @@ public sealed interface ResourceScope extends AutoCloseable permits ResourceScop /** * Creates a new shared scope, managed by a private {@link Cleaner} instance. Equivalent to (but likely more efficient than) * the following code: - *
    {@code
    -    newSharedScope(Cleaner.create());
    -     * }
    + * {@snippet lang=java : + * newSharedScope(Cleaner.create()); + * } * @return a shared scope, managed by a private {@link Cleaner} instance. */ static ResourceScope newImplicitScope() { diff --git a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/SegmentAllocator.java b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/SegmentAllocator.java index 622308da088..d2f112c5d37 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/SegmentAllocator.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/SegmentAllocator.java @@ -339,9 +339,9 @@ public interface SegmentAllocator { /** * Returns a native unbounded arena-based allocator, with predefined block size and maximum arena size, * associated with the provided scope. Equivalent to the following code: - *
    {@code
    -    SegmentAllocator.newNativeArena(Long.MAX_VALUE, predefinedBlockSize, scope);
    -     * }
    + * {@snippet lang=java : + * SegmentAllocator.newNativeArena(Long.MAX_VALUE, predefinedBlockSize, scope); + * } * * @param scope the scope associated with the segments returned by the arena-based allocator. * @return a new unbounded arena-based allocator @@ -355,9 +355,9 @@ public interface SegmentAllocator { /** * Returns a native unbounded arena-based allocator, with block size set to the specified arena size, associated with * the provided scope, with given arena size. Equivalent to the following code: - *
    {@code
    -    SegmentAllocator.newNativeArena(arenaSize, arenaSize, scope);
    -     * }
    + * {@snippet lang=java : + * SegmentAllocator.newNativeArena(arenaSize, arenaSize, scope); + * } * * @param arenaSize the size (in bytes) of the allocation arena. * @param scope the scope associated with the segments returned by the arena-based allocator. @@ -416,10 +416,10 @@ public interface SegmentAllocator { * each new allocation request will return a new slice starting at the segment offset {@code 0} (alignment * constraints are ignored by this allocator), hence the name prefix allocator. * Equivalent to (but likely more efficient than) the following code: - *
    {@code
    -    MemorySegment segment = ...
    -    SegmentAllocator prefixAllocator = (size, align) -> segment.asSlice(0, size);
    -     * }
    + * {@snippet lang=java : + * MemorySegment segment = ... + * SegmentAllocator prefixAllocator = (size, align) -> segment.asSlice(0, size); + * } *

    * This allocator can be useful to limit allocation requests in case a client * knows that they have fully processed the contents of the allocated segment before the subsequent allocation request @@ -439,10 +439,10 @@ public interface SegmentAllocator { /** * Returns a native allocator, associated with the provided scope. Equivalent to (but likely more efficient than) * the following code: - *

    {@code
    -    ResourceScope scope = ...
    -    SegmentAllocator nativeAllocator = (size, align) -> MemorySegment.allocateNative(size, align, scope);
    -     * }
    + * {@snippet lang=java : + * ResourceScope scope = ... + * SegmentAllocator nativeAllocator = (size, align) -> MemorySegment.allocateNative(size, align, scope); + * } * * @param scope the scope associated with the returned allocator. * @return a native allocator, associated with the provided scope. @@ -455,10 +455,10 @@ public interface SegmentAllocator { /** * Returns a native allocator which allocates segments in independent {@linkplain ResourceScope#newImplicitScope() implicit scopes}. * Equivalent to (but likely more efficient than) the following code: - *
    {@code
    -    ResourceScope scope = ...
    -    SegmentAllocator implicitAllocator = (size, align) -> MemorySegment.allocateNative(size, align, ResourceScope.newImplicitScope());
    -     * }
    + * {@snippet lang=java : + * ResourceScope scope = ... + * SegmentAllocator implicitAllocator = (size, align) -> MemorySegment.allocateNative(size, align, ResourceScope.newImplicitScope()); + * } * * @return a native allocator which allocates segments in independent {@linkplain ResourceScope#newImplicitScope() implicit scopes}. */ diff --git a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/SequenceLayout.java b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/SequenceLayout.java index e751830313b..13ac7192728 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/SequenceLayout.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/SequenceLayout.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,18 +37,18 @@ import java.util.OptionalLong; * A finite sequence layout can be thought of as a group layout where the sequence layout's element layout is repeated a number of times * that is equal to the sequence layout's element count. In other words this layout: * - *
    {@code
    -MemoryLayout.sequenceLayout(3, ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN));
    - * }
    + * {@snippet lang=java : + * MemoryLayout.sequenceLayout(3, ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN)); + * } * * is equivalent to the following layout: * - *
    {@code
    -MemoryLayout.structLayout(
    -    ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN),
    -    ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN),
    -    ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN));
    - * }
    + * {@snippet lang=java : + * MemoryLayout.structLayout( + * ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN), + * ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN), + * ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN)); + * } * *

    * This is a value-based @@ -119,22 +119,22 @@ public final class SequenceLayout extends AbstractLayout implements MemoryLayout * as the flattened projection of this sequence layout. *

    * For instance, given a sequence layout of the kind: - *

    {@code
    -    var seq = MemoryLayout.sequenceLayout(4, MemoryLayout.sequenceLayout(3, ValueLayout.JAVA_INT));
    -     * }
    + * {@snippet lang=java : + * var seq = MemoryLayout.sequenceLayout(4, MemoryLayout.sequenceLayout(3, ValueLayout.JAVA_INT)); + * } * calling {@code seq.reshape(2, 6)} will yield the following sequence layout: - *
    {@code
    -    var reshapeSeq = MemoryLayout.sequenceLayout(2, MemoryLayout.sequenceLayout(6, ValueLayout.JAVA_INT));
    -     * }
    + * {@snippet lang=java : + * var reshapeSeq = MemoryLayout.sequenceLayout(2, MemoryLayout.sequenceLayout(6, ValueLayout.JAVA_INT)); + * } *

    * If one of the provided element count is the special value {@code -1}, then the element * count in that position will be inferred from the remaining element counts and the * element count of the flattened projection of this layout. For instance, a layout equivalent to * the above {@code reshapeSeq} can also be computed in the following ways: - *

    {@code
    -    var reshapeSeqImplicit1 = seq.reshape(-1, 6);
    -    var reshapeSeqImplicit2 = seq.reshape(2, -1);
    -     * }
    + * {@snippet lang=java : + * var reshapeSeqImplicit1 = seq.reshape(-1, 6); + * var reshapeSeqImplicit2 = seq.reshape(2, -1); + * } * @param elementCounts an array of element counts, of which at most one can be {@code -1}. * @return a new sequence layout where element layouts in the flattened projection of this * sequence layout (see {@link #flatten()}) are re-arranged into one or more nested sequence layouts. @@ -195,13 +195,13 @@ public final class SequenceLayout extends AbstractLayout implements MemoryLayout * This transformation preserves the layout size; nested sequence layout in this sequence layout will * be dropped and their element counts will be incorporated into that of the returned sequence layout. * For instance, given a sequence layout of the kind: - *
    {@code
    -    var seq = MemoryLayout.sequenceLayout(4, MemoryLayout.sequenceLayout(3, ValueLayout.JAVA_INT));
    -     * }
    + * {@snippet lang=java : + * var seq = MemoryLayout.sequenceLayout(4, MemoryLayout.sequenceLayout(3, ValueLayout.JAVA_INT)); + * } * calling {@code seq.flatten()} will yield the following sequence layout: - *
    {@code
    -    var flattenedSeq = MemoryLayout.sequenceLayout(12, ValueLayout.JAVA_INT);
    -     * }
    + * {@snippet lang=java : + * var flattenedSeq = MemoryLayout.sequenceLayout(12, ValueLayout.JAVA_INT); + * } * @return a new sequence layout with the same size as this layout (but, possibly, with different * element count), whose element layout is not a sequence layout. * @throws UnsupportedOperationException if this sequence layout, or one of the nested sequence layouts being diff --git a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/ValueLayout.java b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/ValueLayout.java index 36a3c6b5b9d..c6d63c3ca1c 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/ValueLayout.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/ValueLayout.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2021, 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 @@ -516,9 +516,9 @@ public sealed class ValueLayout extends AbstractLayout implements MemoryLayout { * A value layout constant whose size is the same as that of a machine address (e.g. {@code size_t}), * bit-alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}. * Equivalent to the following code: - *
    {@code
    -    MemoryLayout.valueLayout(MemoryAddress.class, ByteOrder.nativeOrder()).withBitAlignment(8);
    -     * }
    + * {@snippet lang=java : + * MemoryLayout.valueLayout(MemoryAddress.class, ByteOrder.nativeOrder()).withBitAlignment(8); + * } */ public static final OfAddress ADDRESS = new OfAddress(ByteOrder.nativeOrder()).withBitAlignment(8); @@ -526,9 +526,9 @@ public sealed class ValueLayout extends AbstractLayout implements MemoryLayout { * A value layout constant whose size is the same as that of a Java {@code byte}, * bit-alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}. * Equivalent to the following code: - *
    {@code
    -    MemoryLayout.valueLayout(byte.class, ByteOrder.nativeOrder()).withBitAlignment(8);
    -     * }
    + * {@snippet lang=java : + * MemoryLayout.valueLayout(byte.class, ByteOrder.nativeOrder()).withBitAlignment(8); + * } */ public static final OfByte JAVA_BYTE = new OfByte(ByteOrder.nativeOrder()).withBitAlignment(8); @@ -536,9 +536,9 @@ public sealed class ValueLayout extends AbstractLayout implements MemoryLayout { * A value layout constant whose size is the same as that of a Java {@code boolean}, * bit-alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}. * Equivalent to the following code: - *
    {@code
    -    MemoryLayout.valueLayout(boolean.class, ByteOrder.nativeOrder()).withBitAlignment(8);
    -     * }
    + * {@snippet lang=java : + * MemoryLayout.valueLayout(boolean.class, ByteOrder.nativeOrder()).withBitAlignment(8); + * } */ public static final OfBoolean JAVA_BOOLEAN = new OfBoolean(ByteOrder.nativeOrder()).withBitAlignment(8); @@ -546,9 +546,9 @@ public sealed class ValueLayout extends AbstractLayout implements MemoryLayout { * A value layout constant whose size is the same as that of a Java {@code char}, * bit-alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}. * Equivalent to the following code: - *
    {@code
    -    MemoryLayout.valueLayout(char.class, ByteOrder.nativeOrder()).withBitAlignment(8);
    -     * }
    + * {@snippet lang=java : + * MemoryLayout.valueLayout(char.class, ByteOrder.nativeOrder()).withBitAlignment(8); + * } */ public static final OfChar JAVA_CHAR = new OfChar(ByteOrder.nativeOrder()).withBitAlignment(8); @@ -556,9 +556,9 @@ public sealed class ValueLayout extends AbstractLayout implements MemoryLayout { * A value layout constant whose size is the same as that of a Java {@code short}, * bit-alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}. * Equivalent to the following code: - *
    {@code
    -    MemoryLayout.valueLayout(short.class, ByteOrder.nativeOrder()).withBitAlignment(8);
    -     * }
    + * {@snippet lang=java : + * MemoryLayout.valueLayout(short.class, ByteOrder.nativeOrder()).withBitAlignment(8); + * } */ public static final OfShort JAVA_SHORT = new OfShort(ByteOrder.nativeOrder()).withBitAlignment(8); @@ -566,9 +566,9 @@ public sealed class ValueLayout extends AbstractLayout implements MemoryLayout { * A value layout constant whose size is the same as that of a Java {@code int}, * bit-alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}. * Equivalent to the following code: - *
    {@code
    -    MemoryLayout.valueLayout(int.class, ByteOrder.nativeOrder()).withBitAlignment(8);
    -     * }
    + * {@snippet lang=java : + * MemoryLayout.valueLayout(int.class, ByteOrder.nativeOrder()).withBitAlignment(8); + * } */ public static final OfInt JAVA_INT = new OfInt(ByteOrder.nativeOrder()).withBitAlignment(8); @@ -576,9 +576,9 @@ public sealed class ValueLayout extends AbstractLayout implements MemoryLayout { * A value layout constant whose size is the same as that of a Java {@code long}, * bit-alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}. * Equivalent to the following code: - *
    {@code
    -    MemoryLayout.valueLayout(long.class, ByteOrder.nativeOrder()).withBitAlignment(8);
    -     * }
    + * {@snippet lang=java : + * MemoryLayout.valueLayout(long.class, ByteOrder.nativeOrder()).withBitAlignment(8); + * } */ public static final OfLong JAVA_LONG = new OfLong(ByteOrder.nativeOrder()) .withBitAlignment(8); @@ -587,9 +587,9 @@ public sealed class ValueLayout extends AbstractLayout implements MemoryLayout { * A value layout constant whose size is the same as that of a Java {@code float}, * bit-alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}. * Equivalent to the following code: - *
    {@code
    -    MemoryLayout.valueLayout(float.class, ByteOrder.nativeOrder()).withBitAlignment(8);
    -     * }
    + * {@snippet lang=java : + * MemoryLayout.valueLayout(float.class, ByteOrder.nativeOrder()).withBitAlignment(8); + * } */ public static final OfFloat JAVA_FLOAT = new OfFloat(ByteOrder.nativeOrder()).withBitAlignment(8); @@ -597,9 +597,9 @@ public sealed class ValueLayout extends AbstractLayout implements MemoryLayout { * A value layout constant whose size is the same as that of a Java {@code double}, * bit-alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}. * Equivalent to the following code: - *
    {@code
    -    MemoryLayout.valueLayout(double.class, ByteOrder.nativeOrder()).withBitAlignment(8);
    -     * }
    + * {@snippet lang=java : + * MemoryLayout.valueLayout(double.class, ByteOrder.nativeOrder()).withBitAlignment(8); + * } */ public static final OfDouble JAVA_DOUBLE = new OfDouble(ByteOrder.nativeOrder()).withBitAlignment(8); } diff --git a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/package-info.java b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/package-info.java index 82bc2f53d4b..a6d140e4266 100644 --- a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/package-info.java +++ b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/package-info.java @@ -43,12 +43,12 @@ * For example, to allocate an off-heap memory region big enough to hold 10 values of the primitive type {@code int}, and fill it with values * ranging from {@code 0} to {@code 9}, we can use the following code: * - *
    {@code
    -MemorySegment segment = MemorySegment.allocateNative(10 * 4, ResourceScope.newImplicitScope());
    -for (int i = 0 ; i < 10 ; i++) {
    -   segment.setAtIndex(ValueLayout.JAVA_INT, i, i);
    -}
    - * }
    + * {@snippet lang=java : + * MemorySegment segment = MemorySegment.allocateNative(10 * 4, ResourceScope.newImplicitScope()); + * for (int i = 0 ; i < 10 ; i++) { + * segment.setAtIndex(ValueLayout.JAVA_INT, i, i); + * } + * } * * This code creates a native memory segment, that is, a memory segment backed by * off-heap memory; the size of the segment is 40 bytes, enough to store 10 values of the primitive type {@code int}. @@ -69,14 +69,14 @@ for (int i = 0 ; i < 10 ; i++) { * Clients that operate under these assumptions might want to programmatically release the memory associated * with a memory segment. This can be done, using the {@link jdk.incubator.foreign.ResourceScope} abstraction, as shown below: * - *
    {@code
    -try (ResourceScope scope = ResourceScope.newConfinedScope()) {
    -    MemorySegment segment = MemorySegment.allocateNative(10 * 4, scope);
    -    for (int i = 0 ; i < 10 ; i++) {
    -        segment.setAtIndex(ValueLayout.JAVA_INT, i, i);
    -    }
    -}
    - * }
    + * {@snippet lang=java : + * try (ResourceScope scope = ResourceScope.newConfinedScope()) { + * MemorySegment segment = MemorySegment.allocateNative(10 * 4, scope); + * for (int i = 0 ; i < 10 ; i++) { + * segment.setAtIndex(ValueLayout.JAVA_INT, i, i); + * } + * } + * } * * This example is almost identical to the prior one; this time we first create a so called resource scope, * which is used to bind the life-cycle of the segment created immediately afterwards. Note the use of the @@ -107,19 +107,19 @@ try (ResourceScope scope = ResourceScope.newConfinedScope()) { * For example, to compute the length of a string using the C standard library function {@code strlen} on a Linux x64 platform, * we can use the following code: * - *
    {@code
    -      var linker = CLinker.systemCLinker();
    -      MethodHandle strlen = linker.downcallHandle(
    -        linker.lookup("strlen").get(),
    -        FunctionDescriptor.of(ValueLayout.JAVA_LONG, ValueLayout.ADDRESS)
    -      );
    -
    -      try (var scope = ResourceScope.newConfinedScope()) {
    -         var cString = MemorySegment.allocateNative(5 + 1, scope);
    -         cString.setUtf8String("Hello");
    -         long len = (long)strlen.invoke(cString); // 5
    -      }
    - * }
    + * {@snippet lang=java : + * var linker = CLinker.systemCLinker(); + * MethodHandle strlen = linker.downcallHandle( + * linker.lookup("strlen").get(), + * FunctionDescriptor.of(ValueLayout.JAVA_LONG, ValueLayout.ADDRESS) + * ); + * + * try (var scope = ResourceScope.newConfinedScope()) { + * var cString = MemorySegment.allocateNative(5 + 1, scope); + * cString.setUtf8String("Hello"); + * long len = (long)strlen.invoke(cString); // 5 + * } + * } * * Here, we obtain a {@linkplain jdk.incubator.foreign.CLinker#systemCLinker() linker instance} and we use it * to {@linkplain jdk.incubator.foreign.CLinker#lookup(java.lang.String) lookup} the {@code strlen} symbol in the @@ -148,11 +148,10 @@ try (ResourceScope scope = ResourceScope.newConfinedScope()) { * {@linkplain jdk.incubator.foreign.MemoryAddress#get(jdk.incubator.foreign.ValueLayout.OfInt, long) dereference methods} * provided: * - *
    {@code
    -...
    -MemoryAddress addr = ... //obtain address from native code
    -int x = addr.get(ValueLayout.JAVA_INT, 0);
    - * }
    + * {@snippet lang=java : + * MemoryAddress addr = ... //obtain address from native code + * int x = addr.get(ValueLayout.JAVA_INT, 0); + * } * * Alternatively, the client can * {@linkplain jdk.incubator.foreign.MemorySegment#ofAddress(jdk.incubator.foreign.MemoryAddress, long, jdk.incubator.foreign.ResourceScope) create} @@ -160,36 +159,36 @@ int x = addr.get(ValueLayout.JAVA_INT, 0); * for instance, be available in the documentation of the foreign function which produced the native address. * Here is how an unsafe segment can be created from a native address: * - *
    {@code
    -ResourceScope scope = ... // initialize a resource scope object
    -MemoryAddress addr = ... //obtain address from native code
    -MemorySegment segment = MemorySegment.ofAddress(addr, 4, scope); // segment is 4 bytes long
    -int x = segment.get(ValueLayout.JAVA_INT, 0);
    - * }
    + * {@snippet lang=java : + * ResourceScope scope = ... // initialize a resource scope object + * MemoryAddress addr = ... //obtain address from native code + * MemorySegment segment = MemorySegment.ofAddress(addr, 4, scope); // segment is 4 bytes long + * int x = segment.get(ValueLayout.JAVA_INT, 0); + * } * *

    Upcalls

    * The {@link jdk.incubator.foreign.CLinker} interface also allows to turn an existing method handle (which might point * to a Java method) into a memory address, so that Java code can effectively be passed to other foreign functions. * For instance, we can write a method that compares two integer values, as follows: * - *
    {@code
    -class IntComparator {
    -    static int intCompare(MemoryAddress addr1, MemoryAddress addr2) {
    -        return addr1.get(ValueLayout.JAVA_INT, 0) - addr2.get(ValueLayout.JAVA_INT, 0);
    -    }
    -}
    - * }
    + * {@snippet lang=java : + * class IntComparator { + * static int intCompare(MemoryAddress addr1, MemoryAddress addr2) { + * return addr1.get(ValueLayout.JAVA_INT, 0) - addr2.get(ValueLayout.JAVA_INT, 0); + * } + * } + * } * * The above method dereferences two memory addresses containing an integer value, and performs a simple comparison * by returning the difference between such values. We can then obtain a method handle which targets the above static * method, as follows: * - *
    {@code
    -FunctionDescriptor intCompareDescriptor = FunctionDescriptor.of(ValueLayout.JAVA_INT, ValueLayout.ADDRESS, ValueLayout.ADDRESS);
    -MethodHandle intCompareHandle = MethodHandles.lookup().findStatic(IntComparator.class,
    -                                                   "intCompare",
    -                                                   CLinker.upcallType(comparFunction));
    - * }
    + * {@snippet lang=java : + * FunctionDescriptor intCompareDescriptor = FunctionDescriptor.of(ValueLayout.JAVA_INT, ValueLayout.ADDRESS, ValueLayout.ADDRESS); + * MethodHandle intCompareHandle = MethodHandles.lookup().findStatic(IntComparator.class, + * "intCompare", + * CLinker.upcallType(comparFunction)); + * } * * As before, we need to create a {@link jdk.incubator.foreign.FunctionDescriptor} instance, this time describing the signature * of the function pointer we want to create. The descriptor can be used to @@ -199,12 +198,12 @@ MethodHandle intCompareHandle = MethodHandles.lookup().findStatic(IntComparator. * Now that we have a method handle instance, we can turn it into a fresh function pointer, * using the {@link jdk.incubator.foreign.CLinker} interface, as follows: * - *
    {@code
    -ResourceScope scope = ...
    -Addressable comparFunc = CLinker.systemCLinker().upcallStub(
    -     intCompareHandle, intCompareDescriptor, scope);
    -);
    - * }
    + * {@snippet lang=java : + * ResourceScope scope = ... + * Addressable comparFunc = CLinker.systemCLinker().upcallStub( + * intCompareHandle, intCompareDescriptor, scope); + * ); + * } * * The {@link jdk.incubator.foreign.FunctionDescriptor} instance created in the previous step is then used to * {@linkplain jdk.incubator.foreign.CLinker#upcallStub(java.lang.invoke.MethodHandle, jdk.incubator.foreign.FunctionDescriptor, jdk.incubator.foreign.ResourceScope) create} -- GitLab From 965ea8d9cd29aee41ba2b1b0b0c67bb67eca22dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Gr=C3=B6nlund?= Date: Thu, 9 Dec 2021 09:29:59 +0000 Subject: [PATCH 082/671] 8274298: JFR Thread Sampler thread must not acquire malloc lock after suspending a thread because of possible deadlock Reviewed-by: egahlin --- .../periodic/sampling/jfrThreadSampler.cpp | 30 +++++++++++- .../periodic/sampling/jfrThreadSampler.hpp | 1 + .../types/traceid/jfrTraceIdKlassQueue.cpp | 8 +++ .../types/traceid/jfrTraceIdKlassQueue.hpp | 6 ++- .../types/traceid/jfrTraceIdLoadBarrier.cpp | 8 +++ .../types/traceid/jfrTraceIdLoadBarrier.hpp | 5 ++ .../jfr/recorder/stacktrace/jfrStackTrace.cpp | 16 +++++- .../share/jfr/utilities/jfrEpochQueue.hpp | 14 +++--- .../jfr/utilities/jfrEpochQueue.inline.hpp | 49 ++++++++++++------- 9 files changed, 109 insertions(+), 28 deletions(-) diff --git a/src/hotspot/share/jfr/periodic/sampling/jfrThreadSampler.cpp b/src/hotspot/share/jfr/periodic/sampling/jfrThreadSampler.cpp index 35a3c8fb43b..c09c634e550 100644 --- a/src/hotspot/share/jfr/periodic/sampling/jfrThreadSampler.cpp +++ b/src/hotspot/share/jfr/periodic/sampling/jfrThreadSampler.cpp @@ -27,8 +27,10 @@ #include "jfr/recorder/jfrRecorder.hpp" #include "jfr/periodic/sampling/jfrCallTrace.hpp" #include "jfr/periodic/sampling/jfrThreadSampler.hpp" +#include "jfr/recorder/checkpoint/types/traceid/jfrTraceIdLoadBarrier.inline.hpp" #include "jfr/recorder/service/jfrOptionSet.hpp" #include "jfr/recorder/stacktrace/jfrStackTraceRepository.hpp" +#include "jfr/recorder/storage/jfrBuffer.hpp" #include "jfr/support/jfrThreadId.hpp" #include "jfr/support/jfrThreadLocal.hpp" #include "jfr/utilities/jfrTime.hpp" @@ -323,10 +325,15 @@ class JfrThreadSampler : public NonJavaThread { JavaThread* _last_thread_native; size_t _interval_java; size_t _interval_native; + const size_t _min_size; // for enqueue buffer monitoring + const size_t _renew_size; int _cur_index; const u4 _max_frames; volatile bool _disenrolled; + const JfrBuffer* get_enqueue_buffer(); + const JfrBuffer* renew_if_full(const JfrBuffer* enqueue_buffer); + JavaThread* next_thread(ThreadsList* t_list, JavaThread* first_sampled, JavaThread* current); void task_stacktrace(JfrSampleType type, JavaThread** last_thread); JfrThreadSampler(size_t interval_java, size_t interval_native, u4 max_frames); @@ -396,6 +403,8 @@ JfrThreadSampler::JfrThreadSampler(size_t interval_java, size_t interval_native, _last_thread_native(NULL), _interval_java(interval_java), _interval_native(interval_native), + _min_size(JfrOptionSet::stackdepth() * sizeof(intptr_t)), + _renew_size(_min_size * 2), _cur_index(-1), _max_frames(max_frames), _disenrolled(true) { @@ -520,6 +529,15 @@ void JfrThreadSampler::post_run() { delete this; } +const JfrBuffer* JfrThreadSampler::get_enqueue_buffer() { + const JfrBuffer* buffer = JfrTraceIdLoadBarrier::get_enqueue_buffer(this); + return buffer != nullptr ? renew_if_full(buffer) : JfrTraceIdLoadBarrier::renew_enqueue_buffer(_renew_size, this); +} + +const JfrBuffer* JfrThreadSampler::renew_if_full(const JfrBuffer* enqueue_buffer) { + assert(enqueue_buffer != nullptr, "invariant"); + return enqueue_buffer->free_size() < _min_size ? JfrTraceIdLoadBarrier::renew_enqueue_buffer(_renew_size, this) : enqueue_buffer; +} void JfrThreadSampler::task_stacktrace(JfrSampleType type, JavaThread** last_thread) { ResourceMark rm; @@ -530,7 +548,6 @@ void JfrThreadSampler::task_stacktrace(JfrSampleType type, JavaThread** last_thr const uint sample_limit = JAVA_SAMPLE == type ? MAX_NR_OF_JAVA_SAMPLES : MAX_NR_OF_NATIVE_SAMPLES; uint num_samples = 0; JavaThread* start = NULL; - { elapsedTimer sample_time; sample_time.start(); @@ -542,6 +559,15 @@ void JfrThreadSampler::task_stacktrace(JfrSampleType type, JavaThread** last_thr _cur_index = tlh.list()->find_index_of_JavaThread(*last_thread); JavaThread* current = _cur_index != -1 ? *last_thread : NULL; + // Explicitly monitor the available space of the thread-local buffer used by the load barrier + // for enqueuing klasses as part of tagging methods. We do this because if space becomes sparse, + // we cannot rely on the implicit allocation of a new buffer as part of the regular tag mechanism. + // If the free list is empty, a malloc could result, and the problem with that is that the thread + // we have suspended could be the holder of the malloc lock. Instead, the buffer is pre-emptively + // renewed before thread suspension. + const JfrBuffer* enqueue_buffer = get_enqueue_buffer(); + assert(enqueue_buffer != nullptr, "invariant"); + while (num_samples < sample_limit) { current = next_thread(tlh.list(), start, current); if (current == NULL) { @@ -553,9 +579,11 @@ void JfrThreadSampler::task_stacktrace(JfrSampleType type, JavaThread** last_thr if (current->is_Compiler_thread()) { continue; } + assert(enqueue_buffer->free_size() >= _min_size, "invariant"); if (sample_task.do_sample_thread(current, _frames, _max_frames, type)) { num_samples++; } + enqueue_buffer = renew_if_full(enqueue_buffer); } *last_thread = current; // remember the thread we last attempted to sample } diff --git a/src/hotspot/share/jfr/periodic/sampling/jfrThreadSampler.hpp b/src/hotspot/share/jfr/periodic/sampling/jfrThreadSampler.hpp index a036be65aee..709ebb42d61 100644 --- a/src/hotspot/share/jfr/periodic/sampling/jfrThreadSampler.hpp +++ b/src/hotspot/share/jfr/periodic/sampling/jfrThreadSampler.hpp @@ -28,6 +28,7 @@ #include "jfr/utilities/jfrAllocation.hpp" class JavaThread; +class JfrBuffer; class JfrStackFrame; class JfrThreadSampler; class Thread; diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdKlassQueue.cpp b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdKlassQueue.cpp index 7344e2aa6b4..fab51e0b92d 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdKlassQueue.cpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdKlassQueue.cpp @@ -247,6 +247,14 @@ void JfrTraceIdKlassQueue::enqueue(const Klass* klass) { _queue->enqueue(klass); } +JfrBuffer* JfrTraceIdKlassQueue::get_enqueue_buffer(Thread* thread) { + return _queue->thread_local_storage(thread); +} + +JfrBuffer* JfrTraceIdKlassQueue::renew_enqueue_buffer(size_t size, Thread* thread) { + return _queue->renew(size, thread); +} + void JfrTraceIdKlassQueue::iterate(klass_callback callback, bool previous_epoch) { assert_locked_or_safepoint(ClassLoaderDataGraph_lock); KlassFunctor functor(callback); diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdKlassQueue.hpp b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdKlassQueue.hpp index 1a3779c8b33..52a17ec750c 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdKlassQueue.hpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdKlassQueue.hpp @@ -28,6 +28,7 @@ #include "jfr/utilities/jfrAllocation.hpp" #include "jfr/utilities/jfrEpochQueue.hpp" +class JfrBuffer; class Klass; class Thread; @@ -47,7 +48,7 @@ class KlassFunctor { // It details how to store and process an enqueued Klass representation. See utilities/jfrEpochQueue.hpp. // template -class JfrEpochQueueKlassPolicy { +class JfrEpochQueueKlassPolicy : public JfrCHeapObj { public: typedef Buffer* BufferPtr; typedef Klass Type; @@ -64,8 +65,11 @@ class JfrEpochQueueKlassPolicy { }; class JfrTraceIdKlassQueue : public JfrCHeapObj { + friend class JfrTraceIdLoadBarrier; private: JfrEpochQueue* _queue; + JfrBuffer* get_enqueue_buffer(Thread* thread); + JfrBuffer* renew_enqueue_buffer(size_t size, Thread* thread); public: JfrTraceIdKlassQueue(); ~JfrTraceIdKlassQueue(); diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdLoadBarrier.cpp b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdLoadBarrier.cpp index b861b4142a2..f5e3612f254 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdLoadBarrier.cpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdLoadBarrier.cpp @@ -68,3 +68,11 @@ void JfrTraceIdLoadBarrier::do_klasses(klass_callback callback, bool previous_ep assert_locked_or_safepoint(ClassLoaderDataGraph_lock); klass_queue().iterate(callback, previous_epoch); } + +JfrBuffer* JfrTraceIdLoadBarrier::get_enqueue_buffer(Thread* thread) { + return klass_queue().get_enqueue_buffer(thread); +} + +JfrBuffer* JfrTraceIdLoadBarrier::renew_enqueue_buffer(size_t size, Thread* thread) { + return klass_queue().renew_enqueue_buffer(size, thread); +} diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdLoadBarrier.hpp b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdLoadBarrier.hpp index 18635bbd660..7113a65bd42 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdLoadBarrier.hpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdLoadBarrier.hpp @@ -29,6 +29,7 @@ #include "memory/allocation.hpp" class ClassLoaderData; +class JfrBuffer; class Klass; class Method; class ModuleEntry; @@ -69,12 +70,16 @@ class PackageEntry; class JfrTraceIdLoadBarrier : AllStatic { friend class Jfr; friend class JfrCheckpointManager; + friend class JfrStackTrace; + friend class JfrThreadSampler; private: static bool initialize(); static void clear(); static void destroy(); static void enqueue(const Klass* klass); static void load_barrier(const Klass* klass); + static JfrBuffer* get_enqueue_buffer(Thread* thread); + static JfrBuffer* renew_enqueue_buffer(size_t size, Thread* thread); public: static traceid load(const ClassLoaderData* cld); static traceid load(const Klass* klass); diff --git a/src/hotspot/share/jfr/recorder/stacktrace/jfrStackTrace.cpp b/src/hotspot/share/jfr/recorder/stacktrace/jfrStackTrace.cpp index ab5fa276c7b..925607cd6d5 100644 --- a/src/hotspot/share/jfr/recorder/stacktrace/jfrStackTrace.cpp +++ b/src/hotspot/share/jfr/recorder/stacktrace/jfrStackTrace.cpp @@ -27,6 +27,7 @@ #include "jfr/recorder/checkpoint/types/traceid/jfrTraceId.inline.hpp" #include "jfr/recorder/repository/jfrChunkWriter.hpp" #include "jfr/recorder/stacktrace/jfrStackTrace.hpp" +#include "jfr/recorder/storage/jfrBuffer.hpp" #include "jfr/support/jfrMethodLookup.hpp" #include "memory/allocation.inline.hpp" #include "oops/instanceKlass.inline.hpp" @@ -175,11 +176,22 @@ void vframeStreamSamples::samples_next() { } while (!fill_from_frame()); } +static const size_t min_valid_free_size_bytes = 16; + +static inline bool is_full(const JfrBuffer* enqueue_buffer) { + return enqueue_buffer->free_size() < min_valid_free_size_bytes; +} + bool JfrStackTrace::record_thread(JavaThread& thread, frame& frame) { + // Explicitly monitor the available space of the thread-local buffer used for enqueuing klasses as part of tagging methods. + // We do this because if space becomes sparse, we cannot rely on the implicit allocation of a new buffer as part of the + // regular tag mechanism. If the free list is empty, a malloc could result, and the problem with that is that the thread + // we have suspended could be the holder of the malloc lock. If there is no more available space, the attempt is aborted. + const JfrBuffer* const enqueue_buffer = JfrTraceIdLoadBarrier::get_enqueue_buffer(Thread::current()); + assert(enqueue_buffer != nullptr, "invariant"); vframeStreamSamples st(&thread, frame, false); u4 count = 0; _reached_root = true; - _hash = 1; while (!st.at_end()) { if (count >= _max_frames) { @@ -187,7 +199,7 @@ bool JfrStackTrace::record_thread(JavaThread& thread, frame& frame) { break; } const Method* method = st.method(); - if (!Method::is_valid_method(method)) { + if (!Method::is_valid_method(method) || is_full(enqueue_buffer)) { // we throw away everything we've gathered in this sample since // none of it is safe return false; diff --git a/src/hotspot/share/jfr/utilities/jfrEpochQueue.hpp b/src/hotspot/share/jfr/utilities/jfrEpochQueue.hpp index 89c314f424e..66b08ec7a66 100644 --- a/src/hotspot/share/jfr/utilities/jfrEpochQueue.hpp +++ b/src/hotspot/share/jfr/utilities/jfrEpochQueue.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -27,6 +27,8 @@ #include "jfr/recorder/storage/jfrEpochStorage.hpp" +class Thread; + /* * An ElmentPolicy template template argument provides the implementation for how elements * associated with the queue is encoded and managed by exposing the following members: @@ -43,7 +45,7 @@ * size_t operator()(const u1* next_element, Callback& callback, bool previous_epoch = false); */ template